def __init__(self): self.paypal = PayPalClient(None)
def __init__(self): self.paypal = PayPalClient(None)
class PayoutEngine(object): def __init__(self): self.paypal = PayPalClient(None) def _get_reports(self): headers = { 'content-type': 'application/json', 'X-Nick-Name': settings.STORE_NAME, 'X-Roles': settings.ADMIN_ROLE, 'X-Email': settings.WSTOREMAIL } data = { 'aggregatorId': None, 'providerId': None, 'productClass': None, 'onlyPaid': "true" } # Make request url = settings.RSS if not url.endswith('/'): url += '/' url += 'rss/settlement/reports' response = requests.get(url, params=data, headers=headers) if response.status_code != 200: print("Error retrieving reports: {}".format(response.reason)) return [] return response.json() def _process_reports(self, reports): new_reports = defaultdict(lambda: defaultdict(list)) # Divide by currency for report in reports: if report['paid']: continue semipaid = None try: semipaid = ReportSemiPaid.objects.get(report=report['id']) except ObjectDoesNotExist: pass currency = report['currency'] usermail = User.objects.get( username=report['ownerProviderId']).email if semipaid is None or usermail not in semipaid.success: new_reports[currency][usermail].append( (report['ownerValue'], report['id'])) for stake in report['stakeholders']: stakemail = User.objects.get( username=stake['stakeholderId']).email if semipaid is None or stakemail not in semipaid.success: new_reports[currency][stakemail].append( (stake['modelValue'], report['id'])) return new_reports def _process_payouts(self, data): db = get_database_connection() reference = "__payout__engine__context__lock__" # Uses an atomic operation to get and set the _lock value in the purchase # document pre_value = db.wstore_payout.find_one_and_update( {'_id': reference}, {'$set': { '_lock': True }}) # If no reference exists, create it if pre_value is None: db.wstore_payout.insert_one({'_id': reference, '_lock': False}) pre_value = db.wstore_payout.find_one_and_update( {'_id': reference}, {'$set': { '_lock': True }}) # If the value of _lock before setting it to true was true, means # that the time out function has acquired it previously so the # view ends if '_lock' in pre_value and pre_value['_lock']: raise PayoutError('There is a payout running.') payments = [] context = Context.objects.all()[0] current_id = context.payouts_n for currency, users in data.items(): payments.append([]) for user, values in users.items(): for value, report in values: sender_id = '{}_{}'.format(report, current_id) payment = { 'recipient_type': 'EMAIL', 'amount': { 'value': "{0:.2f}".format(round(Decimal(value), 2)), 'currency': currency }, 'receiver': user, 'sender_item_id': sender_id } current_id += 1 payments[-1].append(payment) context.payouts_n = current_id context.save() # _lock is set to false db.wstore_payout.find_one_and_update({'_id': reference}, {'$set': { '_lock': False }}) return [self.paypal.batch_payout(paybatch) for paybatch in payments] def process_reports(self, reports): processed = self._process_reports(reports) payouts = self._process_payouts(processed) to_watch = [] for payout, created in payouts: if not created: # Full error, not even said the semipaid because it didn't failed some transaction print("Error, batch id: {}".format( payout['sender_batch_header']['sender_batch_id'])) # Log continue payout_id = payout['batch_header']['payout_batch_id'] status = payout['batch_header']['batch_status'] rpayout = ReportsPayout(reports=reports, payout_id=payout_id, status=status) rpayout.save() to_watch.append(payout) if len(to_watch) > 0: watcher = PayoutWatcher(to_watch, reports) watcher.start() def process_unpaid(self): reports = self._get_reports() self.process_reports(reports)
class PayoutEngine(object): def __init__(self): self.paypal = PayPalClient(None) def _get_reports(self): headers = { "content-type": "application/json", "X-Nick-Name": settings.STORE_NAME, "X-Roles": "provider", "X-Email": settings.WSTOREMAIL, } data = {"aggregatorId": None, "providerId": None, "productClass": None, "onlyPaid": "true"} # Make request url = settings.RSS if not url.endswith("/"): url += "/" url += "rss/settlement/reports" response = requests.get(url, params=data, headers=headers) if response.status_code != 200: print("Error retrieving reports: {}".format(response.reason)) return [] return response.json() def _process_reports(self, reports): new_reports = defaultdict(lambda: defaultdict(list)) # Divide by currency for report in reports: if report["paid"]: continue semipaid = None try: semipaid = ReportSemiPaid.objects.get(report=report["id"]) except ObjectDoesNotExist: pass currency = report["currency"] usermail = User.objects.get(username=report["ownerProviderId"]).email if semipaid is None or usermail not in semipaid.success: new_reports[currency][usermail].append((report["ownerValue"], report["id"])) for stake in report["stakeholders"]: stakemail = User.objects.get(username=stake["stakeholderId"]).email if semipaid is None or stakemail not in semipaid.success: new_reports[currency][stakemail].append((stake["modelValue"], report["id"])) return new_reports def _process_payouts(self, data): db = get_database_connection() reference = "__payout__engine__context__lock__" # Uses an atomic operation to get and set the _lock value in the purchase # document pre_value = db.wstore_payout.find_one_and_update({"_id": reference}, {"$set": {"_lock": True}}) # If no reference exists, create it if pre_value is None: db.wstore_payout.insert_one({"_id": reference, "_lock": False}) pre_value = db.wstore_payout.find_one_and_update({"_id": reference}, {"$set": {"_lock": True}}) # If the value of _lock before setting it to true was true, means # that the time out function has acquired it previously so the # view ends if "_lock" in pre_value and pre_value["_lock"]: raise PayoutError("There is a payout running.") payments = [] context = Context.objects.all()[0] current_id = context.payouts_n for currency, users in data.items(): payments.append([]) for user, values in users.items(): for value, report in values: sender_id = "{}_{}".format(report, current_id) payment = { "recipient_type": "EMAIL", "amount": {"value": "{0:.2f}".format(round(Decimal(value), 2)), "currency": currency}, "receiver": user, "sender_item_id": sender_id, } current_id += 1 payments[-1].append(payment) context.payouts_n = current_id context.save() # _lock is set to false db.wstore_payout.find_one_and_update({"_id": reference}, {"$set": {"_lock": False}}) return [self.paypal.batch_payout(paybatch) for paybatch in payments] def process_reports(self, reports): processed = self._process_reports(reports) payouts = self._process_payouts(processed) to_watch = [] for payout, created in payouts: if not created: # Full error, not even said the semipaid because it didn't failed some transaction print("Error, batch id: {}".format(payout["sender_batch_header"]["sender_batch_id"])) # Log continue payout_id = payout["batch_header"]["payout_batch_id"] status = payout["batch_header"]["batch_status"] rpayout = ReportsPayout(reports=reports, payout_id=payout_id, status=status) rpayout.save() to_watch.append(payout) if len(to_watch) > 0: watcher = PayoutWatcher(to_watch, reports) watcher.start() def process_unpaid(self): reports = self._get_reports() self.process_reports(reports)