From 1d208b8a4dc4d2036d08f027c5007a39fdece98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com> Date: Tue, 23 Sep 2008 10:51:07 +0000 Subject: [PATCH] AccountingTransactionBalance was not handling correctly transactions where parties are defined at line level git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@23755 20353a03-c40f-0410-a6d1-a30d3c3de9de --- .../AccountingTransactionBalance.py | 57 +++++++++------- product/ERP5/tests/testAccounting.py | 68 +++++++++++++++++++ 2 files changed, 99 insertions(+), 26 deletions(-) diff --git a/product/ERP5/Constraint/AccountingTransactionBalance.py b/product/ERP5/Constraint/AccountingTransactionBalance.py index 1dba7639ba..b268c38fa5 100644 --- a/product/ERP5/Constraint/AccountingTransactionBalance.py +++ b/product/ERP5/Constraint/AccountingTransactionBalance.py @@ -46,36 +46,41 @@ class AccountingTransactionBalance(Constraint): """Implement here the consistency checker """ error_list = [] - source_sum = 0 - destination_sum = 0 + source_sum = dict() + destination_sum = dict() for line in obj.getMovementList( portal_type=obj.getPortalAccountingMovementTypeList()): if line.getSourceValue() is not None: - source_sum += line.getSourceInventoriatedTotalAssetPrice() or 0 + section = line.getSourceSectionValue() + source_sum[section] = source_sum.get(section, 0) + \ + (line.getSourceInventoriatedTotalAssetPrice() or 0) if line.getDestinationValue() is not None: - destination_sum += \ - line.getDestinationInventoriatedTotalAssetPrice() or 0 + section = line.getDestinationSectionValue() + destination_sum[section] = destination_sum.get(section, 0) + \ + (line.getDestinationInventoriatedTotalAssetPrice() or 0) - source_section = obj.getSourceSectionValue() - destination_section = obj.getDestinationSectionValue() - source_precision = destination_precision = 2 - - if source_section is not None and\ - source_section.getPortalType() == 'Organisation': - source_currency = source_section.getPriceCurrencyValue() - if source_currency is not None: - source_precision = source_currency.getQuantityPrecision() - if round(source_sum, source_precision) != 0: - error_list.append(self._generateError(obj, self._getMessage( - 'message_transaction_not_balanced_for_source'))) - - if destination_section is not None and\ - destination_section.getPortalType() == 'Organisation': - destination_currency = destination_section.getPriceCurrencyValue() - if destination_currency is not None: - destination_precision = destination_currency.getQuantityPrecision() - if round(destination_sum, destination_precision) != 0: - error_list.append(self._generateError(obj, self._getMessage( - 'message_transaction_not_balanced_for_destination'))) + for section, total in source_sum.items(): + precision = 2 + if section is not None and\ + section.getPortalType() == 'Organisation': + section_currency = section.getPriceCurrencyValue() + if section_currency is not None: + precision = section_currency.getQuantityPrecision() + if round(total, precision) != 0: + error_list.append(self._generateError(obj, self._getMessage( + 'message_transaction_not_balanced_for_source'))) + break + for section, total in destination_sum.items(): + precision = 2 + if section is not None and\ + section.getPortalType() == 'Organisation': + section_currency = section.getPriceCurrencyValue() + if section_currency is not None: + precision = section_currency.getQuantityPrecision() + if round(total, precision) != 0: + error_list.append(self._generateError(obj, self._getMessage( + 'message_transaction_not_balanced_for_source'))) + break + return error_list diff --git a/product/ERP5/tests/testAccounting.py b/product/ERP5/tests/testAccounting.py index 6f17682cc6..78f89e229d 100644 --- a/product/ERP5/tests/testAccounting.py +++ b/product/ERP5/tests/testAccounting.py @@ -514,6 +514,74 @@ class TestTransactionValidation(AccountingTestCase): # but if there are no accounts defined it's not a problem self.portal.portal_workflow.doActionFor(transaction, 'stop_action') + def test_NonBalancedAccountingTransactionSectionOnLines(self): + transaction = self._makeOne( + portal_type='Accounting Transaction', + start_date=DateTime('2007/01/02'), + resource='currency_module/yen', + lines=(dict(source_value=self.account_module.goods_sales, + destination_value=self.account_module.goods_purchase, + destination_section_value=self.organisation_module.client_1, + source_debit=500), + dict(source_value=self.account_module.goods_purchase, + source_credit=500))) + + # This is not balanced for client 1 + self.assertRaises(ValidationFailed, + self.portal.portal_workflow.doActionFor, + transaction, 'stop_action') + + for line in transaction.getMovementList(): + line.setDestinationSection(None) + self.assertEquals([], transaction.checkConsistency()) + self.portal.portal_workflow.doActionFor(transaction, 'stop_action') + + def test_NonBalancedAccountingTransactionDifferentSectionOnLines(self): + transaction = self._makeOne( + portal_type='Accounting Transaction', + start_date=DateTime('2007/01/02'), + resource='currency_module/yen', + lines=(dict(source_value=self.account_module.goods_sales, + destination_value=self.account_module.goods_purchase, + destination_section_value=self.organisation_module.client_1, + source_debit=500), + dict(source_value=self.account_module.goods_purchase, + destination_value=self.account_module.goods_sales, + destination_section_value=self.organisation_module.client_2, + source_credit=500))) + + # This is not balanced for client 1 and client 2, but if you look globally, + # it looks balanced. + self.assertRaises(ValidationFailed, + self.portal.portal_workflow.doActionFor, + transaction, 'stop_action') + self.assertEquals(1, len(transaction.checkConsistency()), + transaction.checkConsistency()) + + for line in transaction.getMovementList(): + line.setDestinationSectionValue( + self.organisation_module.client_2) + + self.assertEquals([], transaction.checkConsistency()) + self.portal.portal_workflow.doActionFor(transaction, 'stop_action') + + def test_NonBalancedAccountingTransactionSectionPersonOnLines(self): + transaction = self._makeOne( + portal_type='Accounting Transaction', + start_date=DateTime('2007/01/02'), + resource='currency_module/yen', + lines=(dict(source_value=self.account_module.goods_purchase, + destination_value=self.account_module.goods_purchase, + destination_section_value=self.person_module.john_smith, + source_debit=500), + dict(source_value=self.account_module.goods_purchase, + source_credit=500))) + + # This is not balanced for john smith, but as he is a person, it's not a + # problem + self.assertEquals([], transaction.checkConsistency()) + self.portal.portal_workflow.doActionFor(transaction, 'stop_action') + def test_AccountingTransactionValidationRefusedWithCategoriesAsSections(self): # Validating a transaction with categories as sections is refused. # See http://wiki.erp5.org/Discussion/AccountingProblems -- 2.30.9