1# -*- coding: utf-8 -*- 2# Part of Odoo. See LICENSE file for full copyright and licensing details. 3 4from datetime import datetime 5from pytz import UTC 6 7from odoo import api, fields, models 8from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT 9 10 11class AdyenTransaction(models.Model): 12 _name = 'adyen.transaction' 13 _description = 'Adyen for Platforms Transaction' 14 _order = 'date desc' 15 16 adyen_account_id = fields.Many2one('adyen.account') 17 reference = fields.Char('Reference') 18 amount = fields.Float('Amount') 19 currency_id = fields.Many2one('res.currency', string='Currency') 20 date = fields.Datetime('Date') 21 description = fields.Char('Description') 22 status = fields.Selection(string='Type', selection=[ 23 ('PendingCredit', 'Pending Credit'), 24 ('CreditFailed', 'Credit Failed'), 25 ('Credited', 'Credited'), 26 ('Converted', 'Converted'), 27 ('PendingDebit', 'Pending Debit'), 28 ('DebitFailed', 'Debit Failed'), 29 ('Debited', 'Debited'), 30 ('DebitReversedReceived', 'Debit Reversed Received'), 31 ('DebitedReversed', 'Debit Reversed'), 32 ('ChargebackReceived', 'Chargeback Received'), 33 ('Chargeback', 'Chargeback'), 34 ('ChargebackReversedReceived', 'Chargeback Reversed Received'), 35 ('ChargebackReversed', 'Chargeback Reversed'), 36 ('Payout', 'Payout'), 37 ('PayoutReversed', 'Payout Reversed'), 38 ('FundTransfer', 'Fund Transfer'), 39 ('PendingFundTransfer', 'Pending Fund Transfer'), 40 ('ManualCorrected', 'Manual Corrected'), 41 ]) 42 adyen_payout_id = fields.Many2one('adyen.payout') 43 44 @api.model 45 def sync_adyen_transactions(self): 46 ''' Method called by cron to sync transactions from Adyen. 47 Updates the status of pending transactions and create missing ones. 48 ''' 49 for payout_id in self.env['adyen.payout'].search([]): 50 page = 1 51 has_next_page = True 52 new_transactions = True 53 pending_statuses = ['PendingCredit', 'PendingDebit', 'DebitReversedReceived', 'ChargebackReceived', 'ChargebackReversedReceived', 'PendingFundTransfer'] 54 pending_transaction_ids = payout_id.transaction_ids.filtered(lambda tr: tr.status in pending_statuses) 55 56 while has_next_page and (new_transactions or pending_transaction_ids): 57 # Fetch next transaction page 58 transactions, has_next_page = payout_id._fetch_transactions(page) 59 for transaction in transactions: 60 transaction_reference = transaction.get('paymentPspReference') or transaction.get('pspReference') 61 transaction_id = payout_id.transaction_ids.filtered(lambda tr: tr.reference == transaction_reference) 62 if transaction_id: 63 new_transactions = False 64 if transaction_id in pending_transaction_ids: 65 # Update transaction status 66 transaction_id.sudo().write({ 67 'status': transaction['transactionStatus'], 68 }) 69 pending_transaction_ids -= transaction_id 70 else: 71 currency_id = self.env['res.currency'].search([('name', '=', transaction['amount']['currency'])]) 72 # New transaction 73 self.env['adyen.transaction'].sudo().create({ 74 'adyen_account_id': payout_id.adyen_account_id.id, 75 'reference': transaction_reference, 76 'amount': transaction['amount']['value'] / (10 ** currency_id.decimal_places), 77 'currency_id': currency_id.id, 78 'date': datetime.strptime(transaction['creationDate'], '%Y-%m-%dT%H:%M:%S%z').astimezone(UTC).strftime(DEFAULT_SERVER_DATETIME_FORMAT), 79 'description': transaction.get('description'), 80 'status': transaction['transactionStatus'], 81 'adyen_payout_id': payout_id.id, 82 }) 83 page += 1 84