diff --git a/account_banking_sepa_credit_transfer/tests/test_sct.py b/account_banking_sepa_credit_transfer/tests/test_sct.py index 9025dd092..76cb72aab 100644 --- a/account_banking_sepa_credit_transfer/tests/test_sct.py +++ b/account_banking_sepa_credit_transfer/tests/test_sct.py @@ -11,8 +11,8 @@ from lxml import etree class TestSCT(AccountingTestCase): - def test_sct(self): - self.company = self.env['res.company'] + def setUp(self): + super(TestSCT, self).setUp() self.account_model = self.env['account.account'] self.move_model = self.env['account.move'] self.journal_model = self.env['account.journal'] @@ -23,8 +23,9 @@ class TestSCT(AccountingTestCase): self.attachment_model = self.env['ir.attachment'] self.invoice_model = self.env['account.invoice'] self.invoice_line_model = self.env['account.invoice.line'] - company = self.env.ref('base.main_company') + self.main_company = self.env.ref('base.main_company') self.partner_agrolait = self.env.ref('base.res_partner_2') + self.partner_asus = self.env.ref('base.res_partner_1') self.partner_c2c = self.env.ref('base.res_partner_12') self.account_expense = self.account_model.search([( 'user_type_id', @@ -52,24 +53,31 @@ class TestSCT(AccountingTestCase): 'bank_account_link': 'fixed', 'fixed_journal_id': self.bank_journal.id, }) - eur_currency_id = self.env.ref('base.EUR').id - company.currency_id = eur_currency_id + self.eur_currency = self.env.ref('base.EUR') + self.usd_currency = self.env.ref('base.USD') + self.main_company.currency_id = self.eur_currency.id + + def test_eur_currency_sct(self): invoice1 = self.create_invoice( self.partner_agrolait.id, - 'account_payment_mode.res_partner_2_iban', 42.0, 'F1341') + 'account_payment_mode.res_partner_2_iban', self.eur_currency.id, + 42.0, 'F1341') invoice2 = self.create_invoice( self.partner_agrolait.id, - 'account_payment_mode.res_partner_2_iban', 12.0, 'F1342') + 'account_payment_mode.res_partner_2_iban', self.eur_currency.id, + 12.0, 'F1342') invoice3 = self.create_invoice( self.partner_agrolait.id, - 'account_payment_mode.res_partner_2_iban', 5.0, 'A1301', - 'in_refund') + 'account_payment_mode.res_partner_2_iban', self.eur_currency.id, + 5.0, 'A1301', 'in_refund') invoice4 = self.create_invoice( self.partner_c2c.id, - 'account_payment_mode.res_partner_12_iban', 11.0, 'I1642') + 'account_payment_mode.res_partner_12_iban', self.eur_currency.id, + 11.0, 'I1642') invoice5 = self.create_invoice( self.partner_c2c.id, - 'account_payment_mode.res_partner_12_iban', 41.0, 'I1643') + 'account_payment_mode.res_partner_12_iban', self.eur_currency.id, + 41.0, 'I1643') for inv in [invoice1, invoice2, invoice3, invoice4, invoice5]: action = inv.create_account_payment_line() self.assertEquals(action['res_model'], 'account.payment.order') @@ -86,7 +94,7 @@ class TestSCT(AccountingTestCase): self.assertEquals(len(pay_lines), 3) agrolait_pay_line1 = pay_lines[0] accpre = self.env['decimal.precision'].precision_get('Account') - self.assertEquals(agrolait_pay_line1.currency_id.id, eur_currency_id) + self.assertEquals(agrolait_pay_line1.currency_id, self.eur_currency) self.assertEquals( agrolait_pay_line1.partner_bank_id, invoice1.partner_bank_id) self.assertEquals(float_compare( @@ -101,7 +109,7 @@ class TestSCT(AccountingTestCase): ('partner_id', '=', self.partner_agrolait.id)]) self.assertEquals(len(bank_lines), 1) agrolait_bank_line = bank_lines[0] - self.assertEquals(agrolait_bank_line.currency_id.id, eur_currency_id) + self.assertEquals(agrolait_bank_line.currency_id, self.eur_currency) self.assertEquals(float_compare( agrolait_bank_line.amount_currency, 49.0, precision_digits=accpre), 0) @@ -139,14 +147,92 @@ class TestSCT(AccountingTestCase): self.assertEquals(inv.state, 'paid') return + def test_usd_currency_sct(self): + invoice1 = self.create_invoice( + self.partner_asus.id, + 'account_payment_mode.res_partner_2_iban', self.usd_currency.id, + 2042.0, 'Inv9032') + invoice2 = self.create_invoice( + self.partner_asus.id, + 'account_payment_mode.res_partner_2_iban', self.usd_currency.id, + 1012.0, 'Inv9033') + for inv in [invoice1, invoice2]: + action = inv.create_account_payment_line() + self.assertEquals(action['res_model'], 'account.payment.order') + self.payment_order = self.payment_order_model.browse(action['res_id']) + self.assertEquals( + self.payment_order.payment_type, 'outbound') + self.assertEquals( + self.payment_order.payment_mode_id, self.payment_mode) + self.assertEquals( + self.payment_order.journal_id, self.bank_journal) + pay_lines = self.payment_line_model.search([ + ('partner_id', '=', self.partner_asus.id), + ('order_id', '=', self.payment_order.id)]) + self.assertEquals(len(pay_lines), 2) + asus_pay_line1 = pay_lines[0] + accpre = self.env['decimal.precision'].precision_get('Account') + self.assertEquals(asus_pay_line1.currency_id, self.usd_currency) + self.assertEquals( + asus_pay_line1.partner_bank_id, invoice1.partner_bank_id) + self.assertEquals(float_compare( + asus_pay_line1.amount_currency, 2042, precision_digits=accpre), + 0) + self.assertEquals(asus_pay_line1.communication_type, 'normal') + self.assertEquals(asus_pay_line1.communication, 'Inv9032') + self.payment_order.draft2open() + self.assertEquals(self.payment_order.state, 'open') + self.assertEquals(self.payment_order.sepa, False) + bank_lines = self.bank_line_model.search([ + ('partner_id', '=', self.partner_asus.id)]) + self.assertEquals(len(bank_lines), 1) + asus_bank_line = bank_lines[0] + self.assertEquals(asus_bank_line.currency_id, self.usd_currency) + self.assertEquals(float_compare( + asus_bank_line.amount_currency, 3054.0, precision_digits=accpre), + 0) + self.assertEquals(asus_bank_line.communication_type, 'normal') + self.assertEquals( + asus_bank_line.communication, 'Inv9032-Inv9033') + self.assertEquals( + asus_bank_line.partner_bank_id, invoice1.partner_bank_id) + + action = self.payment_order.open2generated() + self.assertEquals(self.payment_order.state, 'generated') + self.assertEquals(action['res_model'], 'ir.attachment') + attachment = self.attachment_model.browse(action['res_id']) + self.assertEquals(attachment.datas_fname[-4:], '.xml') + xml_file = attachment.datas.decode('base64') + xml_root = etree.fromstring(xml_file) + # print "xml_file=", etree.tostring(xml_root, pretty_print=True) + namespaces = xml_root.nsmap + namespaces['p'] = xml_root.nsmap[None] + namespaces.pop(None) + pay_method_xpath = xml_root.xpath( + '//p:PmtInf/p:PmtMtd', namespaces=namespaces) + self.assertEquals(pay_method_xpath[0].text, 'TRF') + sepa_xpath = xml_root.xpath( + '//p:PmtInf/p:PmtTpInf/p:SvcLvl/p:Cd', namespaces=namespaces) + self.assertEquals(len(sepa_xpath), 0) + debtor_acc_xpath = xml_root.xpath( + '//p:PmtInf/p:DbtrAcct/p:Id/p:IBAN', namespaces=namespaces) + self.assertEquals( + debtor_acc_xpath[0].text, + self.payment_order.company_partner_bank_id.sanitized_acc_number) + self.payment_order.generated2uploaded() + self.assertEquals(self.payment_order.state, 'uploaded') + for inv in [invoice1, invoice2]: + self.assertEquals(inv.state, 'paid') + return + def create_invoice( - self, partner_id, partner_bank_xmlid, price_unit, reference, - type='in_invoice'): + self, partner_id, partner_bank_xmlid, currency_id, + price_unit, reference, type='in_invoice'): invoice = self.invoice_model.create({ 'partner_id': partner_id, 'reference_type': 'none', 'reference': reference, - 'currency_id': self.env.ref('base.EUR').id, + 'currency_id': currency_id, 'name': 'test', 'account_id': self.account_payable.id, 'type': type, diff --git a/account_payment_mode/__openerp__.py b/account_payment_mode/__openerp__.py index fc3acdf48..90c9e4378 100644 --- a/account_payment_mode/__openerp__.py +++ b/account_payment_mode/__openerp__.py @@ -16,6 +16,7 @@ 'views/account_payment_mode.xml', 'views/res_partner_bank.xml', 'views/res_partner.xml', + 'views/account_journal.xml', ], 'demo': ['demo/payment_demo.xml'], 'installable': True, diff --git a/account_payment_mode/models/account_journal.py b/account_payment_mode/models/account_journal.py index e9150c523..6ba0b3626 100644 --- a/account_payment_mode/models/account_journal.py +++ b/account_payment_mode/models/account_journal.py @@ -22,3 +22,6 @@ class AccountJournal(models.Model): default=_default_outbound_payment_methods) inbound_payment_method_ids = fields.Many2many( default=_default_inbound_payment_methods) + company_partner_id = fields.Many2one( + 'res.partner', related='company_id.partner_id', + readonly=True) # Used in domain of field bank_account_id diff --git a/account_payment_mode/views/account_journal.xml b/account_payment_mode/views/account_journal.xml new file mode 100644 index 000000000..b7873ba5d --- /dev/null +++ b/account_payment_mode/views/account_journal.xml @@ -0,0 +1,29 @@ + + + + + + + fix_bank_account_selection.account_journal.form + account.journal + + + + 1 + + + + + + + + 1 + + + + + + diff --git a/account_payment_order/models/account_payment_mode.py b/account_payment_order/models/account_payment_mode.py index 263117b96..9773ab8c0 100644 --- a/account_payment_order/models/account_payment_mode.py +++ b/account_payment_order/models/account_payment_mode.py @@ -41,16 +41,16 @@ class AccountPaymentMode(models.Model): ('move', 'Move'), ], default='due', string="Type of Date Filter") group_lines = fields.Boolean( - string="Group Lines in Payment Orders", default=True, - help="If this mark is checked, the payment order lines will be " - "grouped when validating the payment order before exporting the " - "bank file. The grouping will be done only if the following " + string="Group Transactions in Payment Orders", default=True, + help="If this mark is checked, the transaction lines of the " + "payment order will be grouped upon confirmation of the payment " + "order.The grouping will be done only if the following " "fields matches:\n" "* Partner\n" "* Currency\n" "* Destination Bank Account\n" - "* Communication Type (structured, free)\n" "* Payment Date\n" + "and if the 'Communication Type' is 'Free'\n" "(other modules can set additional fields to restrict the " "grouping.)") generate_move = fields.Boolean( diff --git a/account_payment_order/models/account_payment_order.py b/account_payment_order/models/account_payment_order.py index 93777b9f2..e1d95f68d 100644 --- a/account_payment_order/models/account_payment_order.py +++ b/account_payment_order/models/account_payment_order.py @@ -78,7 +78,13 @@ class AccountPaymentOrder(models.Model): # v8 field : line_ids bank_line_ids = fields.One2many( 'bank.payment.line', 'order_id', string="Bank Payment Lines", - readonly=True) + readonly=True, + help="The bank payment lines are used to generate the payment file. " + "They are automatically created from transaction lines upon " + "confirmation of the payment order: one bank payment line can " + "group several transaction lines if the option " + "'Group Transactions in Payment Orders' is active on the payment " + "mode.") total_company_currency = fields.Monetary( compute='_compute_total', store=True, readonly=True, currency_field='company_currency_id') @@ -343,12 +349,13 @@ class AccountPaymentOrder(models.Model): @api.multi def _prepare_move_line_offsetting_account( - self, amount, bank_payment_lines): + self, amount_company_currency, amount_payment_currency, + bank_lines): if self.payment_type == 'outbound': name = _('Payment order %s') % self.name else: name = _('Debit order %s') % self.name - date_maturity = bank_payment_lines[0].date + date_maturity = bank_lines[0].date if self.payment_mode_id.offsetting_account == 'bank_account': account_id = self.journal_id.default_debit_account_id.id elif self.payment_mode_id.offsetting_account == 'transfer_account': @@ -358,17 +365,21 @@ class AccountPaymentOrder(models.Model): 'partner_id': False, 'account_id': account_id, 'credit': (self.payment_type == 'outbound' and - amount or 0.0), + amount_company_currency or 0.0), 'debit': (self.payment_type == 'inbound' and - amount or 0.0), + amount_company_currency or 0.0), 'date_maturity': date_maturity, } + if bank_lines[0].currency_id != bank_lines[0].company_currency_id: + sign = self.payment_type == 'outbound' and -1 or 1 + vals.update({ + 'currency_id': bank_lines[0].currency_id.id, + 'amount_currency': amount_payment_currency * sign, + }) return vals @api.multi def _prepare_move_line_partner_account(self, bank_line): - # TODO : ALEXIS check don't group if move_line_id.account_id - # is not the same if bank_line.payment_line_ids[0].move_line_id: account_id =\ bank_line.payment_line_ids[0].move_line_id.account_id.id @@ -389,10 +400,16 @@ class AccountPaymentOrder(models.Model): 'partner_id': bank_line.partner_id.id, 'account_id': account_id, 'credit': (self.payment_type == 'inbound' and - bank_line.amount_currency or 0.0), + bank_line.amount_company_currency or 0.0), 'debit': (self.payment_type == 'outbound' and - bank_line.amount_currency or 0.0), + bank_line.amount_company_currency or 0.0), } + if bank_line.currency_id != bank_line.company_currency_id: + sign = self.payment_type == 'inbound' and -1 or 1 + vals.update({ + 'currency_id': bank_line.currency_id.id, + 'amount_currency': bank_line.amount_currency * sign, + }) return vals @api.multi @@ -415,25 +432,17 @@ class AccountPaymentOrder(models.Model): else: trfmoves[hashcode] = bline - company_currency = self.env.user.company_id.currency_id for hashcode, blines in trfmoves.iteritems(): mvals = self._prepare_move() - total_amount = 0 + total_company_currency = total_payment_currency = 0 for bline in blines: - total_amount += bline.amount_currency - if bline.currency_id != company_currency: - raise UserError(_( - "Cannot generate the account move when " - "the currency of the payment (%s) is not the " - "same as the currency of the company (%s). This " - "is not supported for the moment.") - % (bline.currency_id.name, company_currency.name)) - + total_company_currency += bline.amount_company_currency + total_payment_currency += bline.amount_currency partner_ml_vals = self._prepare_move_line_partner_account( bline) mvals['line_ids'].append((0, 0, partner_ml_vals)) trf_ml_vals = self._prepare_move_line_offsetting_account( - total_amount, blines) + total_company_currency, total_payment_currency, blines) mvals['line_ids'].append((0, 0, trf_ml_vals)) move = am_obj.create(mvals) blines.reconcile_payment_lines() diff --git a/account_payment_order/models/bank_payment_line.py b/account_payment_order/models/bank_payment_line.py index a1533f6ad..5e95e0667 100644 --- a/account_payment_order/models/bank_payment_line.py +++ b/account_payment_order/models/bank_payment_line.py @@ -34,6 +34,10 @@ class BankPaymentLine(models.Model): amount_currency = fields.Monetary( string='Amount', currency_field='currency_id', compute='_compute_amount', store=True, readonly=True) + amount_company_currency = fields.Monetary( + string='Amount in Company Currency', + currency_field='company_currency_id', + compute='_compute_amount', store=True, readonly=True) currency_id = fields.Many2one( 'res.currency', required=True, readonly=True, related='payment_line_ids.currency_id') # v8 field: currency @@ -50,6 +54,9 @@ class BankPaymentLine(models.Model): company_id = fields.Many2one( related='order_id.payment_mode_id.company_id', store=True, readonly=True) + company_currency_id = fields.Many2one( + related='order_id.payment_mode_id.company_id.currency_id', + readonly=True, store=True) @api.model def same_fields_payment_line_and_bank_payment_line(self): @@ -67,9 +74,14 @@ class BankPaymentLine(models.Model): @api.multi @api.depends('payment_line_ids', 'payment_line_ids.amount_currency') def _compute_amount(self): - for line in self: - line.amount_currency = sum( - line.mapped('payment_line_ids.amount_currency')) + for bline in self: + amount_currency = sum( + bline.mapped('payment_line_ids.amount_currency')) + amount_company_currency = bline.currency_id.with_context( + date=bline.date).compute( + amount_currency, bline.company_currency_id) + bline.amount_currency = amount_currency + bline.amount_company_currency = amount_company_currency @api.model @api.returns('self') diff --git a/account_payment_order/wizard/account_payment_line_create_view.xml b/account_payment_order/wizard/account_payment_line_create_view.xml index de7d836d0..b53cca822 100644 --- a/account_payment_order/wizard/account_payment_line_create_view.xml +++ b/account_payment_order/wizard/account_payment_line_create_view.xml @@ -33,14 +33,14 @@ - - - - - + + + + +