diff --git a/bt5/erp5_accounting/WorkflowTemplateItem/portal_workflow/accounting_workflow/scripts/validateTransaction.xml b/bt5/erp5_accounting/WorkflowTemplateItem/portal_workflow/accounting_workflow/scripts/validateTransaction.xml index f643ca13f57c0e022f08b2d61df8cc2907bc0b45..f5c327f2a000cd42bdff500eb6ae228bb37ef014 100644 --- a/bt5/erp5_accounting/WorkflowTemplateItem/portal_workflow/accounting_workflow/scripts/validateTransaction.xml +++ b/bt5/erp5_accounting/WorkflowTemplateItem/portal_workflow/accounting_workflow/scripts/validateTransaction.xml @@ -74,11 +74,10 @@ """\n \n from Products.DCWorkflow.DCWorkflow import ValidationFailed\n +from Products.ERP5Type.Message import Message\n \n transaction = state_change[\'object\']\n -N_ = transaction.Base_translateString\n -def raiseError(msg) :\n - raise ValidationFailed(N_(msg))\n +N_ = lambda msg, **kw: Message(\'erp5_ui\', msg, **kw)\n \n # do we have to check transaction is in openned periods ?\n skip_period_validation = state_change[\'kwargs\'].get(\n @@ -98,7 +97,7 @@ if source_section is not None and \\\n source_section = source_section.getMappingRelatedValue(\n portal_type = \'Organisation\')\n if source_section is None:\n - raiseError(\'Source Section is not Defined.\')\n + raise ValidationFailed(\'Source Section is not Defined.\')\n \n destination_section = transaction.getDestinationSectionValue(\n portal_type = [\'Organisation\', \'Person\', \'Category\'])\n @@ -108,18 +107,18 @@ if destination_section is not None and \\\n portal_type = \'Organisation\')\n # if it\'s not an invoice, then we can validate without destination\n if destination_section is None and check_destination :\n - raiseError(\'Destination Section is not Defined.\')\n + raise ValidationFailed(\'Destination Section is not Defined.\')\n \n currency = transaction.getResource(portal_type = \'Currency\')\n if not currency :\n - raiseError(\'Currency is not Defined.\')\n + raise ValidationFailed(\'Currency is not Defined.\')\n \n # XXX manually default start date to stop date\n if not transaction.getStartDate() and transaction.getStopDate():\n transaction.setStartDate(transaction.getStopDate())\n \n if not transaction.getStartDate() :\n - raiseError(\'Date is not Defined\')\n + raise ValidationFailed(\'Date is not Defined\')\n else:\n if not skip_period_validation :\n valid_date = False\n @@ -142,8 +141,8 @@ else:\n if apd.getStartDate().Date() <= transaction_date.Date() <= apd.getStopDate().Date():\n valid_date = True\n if not valid_date :\n - raiseError("Date is not in an openned Accounting Period "\n - "for source section")\n + raise ValidationFailed("Date is not in an openned Accounting Period "\n + "for source section")\n # do the same for destination section \n if check_destination :\n valid_date = False\n @@ -162,8 +161,8 @@ else:\n if apd.getStartDate().Date() <= transaction_date.Date() <= apd.getStopDate().Date():\n valid_date = True\n if not valid_date :\n - raiseError("Date is not in an openned Accounting Period "+\n - "for destination section")\n + raise ValidationFailed("Date is not in an openned Accounting Period "\n + "for destination section")\n ]]></string> </value> @@ -235,11 +234,12 @@ else:\n <string>state_change</string> <string>Products.DCWorkflow.DCWorkflow</string> <string>ValidationFailed</string> + <string>Products.ERP5Type.Message</string> + <string>Message</string> <string>_getitem_</string> <string>transaction</string> - <string>_getattr_</string> <string>N_</string> - <string>raiseError</string> + <string>_getattr_</string> <string>skip_period_validation</string> <string>transition</string> <string>check_destination</string> diff --git a/bt5/erp5_accounting/WorkflowTemplateItem/portal_workflow/accounting_workflow/scripts/validateTransactionLines.xml b/bt5/erp5_accounting/WorkflowTemplateItem/portal_workflow/accounting_workflow/scripts/validateTransactionLines.xml index 2fac3eb5725c8bf223189faa8764a5d33413267a..cf4ed5a0a32d3aadb4ddd46be92a2a487a7286da 100644 --- a/bt5/erp5_accounting/WorkflowTemplateItem/portal_workflow/accounting_workflow/scripts/validateTransactionLines.xml +++ b/bt5/erp5_accounting/WorkflowTemplateItem/portal_workflow/accounting_workflow/scripts/validateTransactionLines.xml @@ -68,26 +68,36 @@ </item> <item> <key> <string>_body</string> </key> - <value> <string>"""\n - Validate Transaction Lines for source and destination section.\n + <value> <string>"""Validate Transaction Lines for source and destination section.\n """\n \n from Products.DCWorkflow.DCWorkflow import ValidationFailed\n +from Products.ERP5Type.Message import Message\n \n SOURCE, DESTINATION = (\'source\', \'destination\')\n -\n -error_message = \'\'\n transaction = state_change[\'object\']\n -N_ = transaction.Base_translateString\n +N_ = lambda msg, **kw: Message(\'erp5_ui\', msg, **kw)\n \n # first of all, validate the transaction itself\n container.validateTransaction(state_change)\n \n # Get sections.\n -source_section = transaction.getSourceSection( portal_type = [\'Person\', \'Organisation\',\'Category\'])\n -destination_section = transaction.getDestinationSection(portal_type = [\'Person\', \'Organisation\',\'Category\'])\n +source_section = transaction.getSourceSectionValue(\n + portal_type=[\'Person\', \'Organisation\'])\n +destination_section = transaction.getDestinationSectionValue(\n + portal_type=[\'Person\', \'Organisation\'])\n +\n +# do we want to check validity for destination as well?\n +check_for_destination = 0\n +if source_section is not None and destination_section is not None:\n + source_section_group = source_section.getGroup().lstrip(\'group/\').split(\'/\')\n + destination_section_group = destination_section\\\n + .getGroup().lstrip(\'group/\').split(\'/\')\n + if destination_section_group and source_section_group and \\\n + destination_section_group[0] == source_section_group[0]:\n + check_for_destination = 1\n \n -source_sum = 0\n +source_sum = 0\n destination_sum = 0\n \n # Check transaction lines\n @@ -96,10 +106,14 @@ if transaction.getPortalType() not in (\'Balance Transaction\',) :\n filter={ \'portal_type\':\n transaction.getPortalAccountingMovementTypeList()})\n for transaction_line in accounting_transaction_line_list:\n - if source_section != destination_section :\n - source_quantity = transaction_line.getSourceInventoriatedTotalAssetPrice() or 0\n - destination_quantity = transaction_line.getDestinationInventoriatedTotalAssetPrice() or 0\n - else :\n + # XXX would source_section != destination_section work here ?\n + if source_section is not None and destination_section is not None and\\\n + source_section.getUid() != destination_section.getUid():\n + source_quantity = transaction_line\\\n + .getSourceInventoriatedTotalAssetPrice() or 0\n + destination_quantity = transaction_line\\\n + .getDestinationInventoriatedTotalAssetPrice() or 0\n + else:\n destination_quantity = source_quantity = ((transaction_line\\\n .getSourceInventoriatedTotalAssetPrice() or 0) + \\\n (transaction_line.getDestinationInventoriatedTotalAssetPrice() or 0))\n @@ -110,72 +124,108 @@ if transaction.getPortalType() not in (\'Balance Transaction\',) :\n if transaction_line.getSource( portal_type = \'Account\') is None and \\\n transaction_line.getDestination(portal_type = \'Account\') is None and \\\n transaction_line.getQuantity() != 0:\n - raise ValidationFailed, N_("Action failed: no account defined for line \'${line_id}\'."\n - , mapping = {\'line_id\': transaction_line.getId()}\n - )\n + raise ValidationFailed, N_(\n + "Action failed: no account defined for line \'${line_id}\'.",\n + mapping = {\'line_id\': transaction_line.getId()} )\n \n for side in (SOURCE, DESTINATION) :\n if side == SOURCE:\n - account = transaction_line.getSourceValue(portal_type = \'Account\')\n + account = transaction_line.getSourceValue(portal_type=\'Account\')\n payment = transaction_line.getSourcePaymentValue()\n - third_party_path = transaction_line.getDestinationSection()\n third_party = transaction_line.getDestinationSectionValue()\n else:\n - account = transaction_line.getDestinationValue(portal_type = \'Account\')\n + account = transaction_line.getDestinationValue(portal_type=\'Account\')\n payment = transaction_line.getDestinationPaymentValue()\n - third_party_path = transaction_line.getSourceSection()\n third_party = transaction_line.getSourceSectionValue()\n \n if account is None:\n continue\n \n if account.getValidationState() != \'validated\':\n - raise ValidationFailed, N_("Action failed: account \'${account_title}\' is not opened."\n - , mapping = {\'account_title\': unicode(account.getTranslatedTitle(), \'utf8\')}\n - )\n -\n + raise ValidationFailed, N_(\n + "Action failed: account \'${account_title}\' is not opened.",\n + mapping = {\'account_title\':\n + unicode(account.getTranslatedTitle(), \'utf8\')})\n + \n # Test third party related-data\n if account.getAccountTypeId() in ("receivable", "payable"):\n # Test existence\n - if third_party_path in (None, \'\'):\n - raise ValidationFailed, N_("Action failed: no third party defined for line \'${line}\'."\n - , mapping = {\'line\': transaction_line.getId()}\n - )\n - if third_party not in (None, \'\') and third_party.getPortalType() in [\'Person\', \'Organisation\']:\n - # Test state\n + if third_party is None:\n + raise ValidationFailed, N_(\n + "Action failed: no third party defined for line \'${line}\'.",\n + mapping = {\'line\': transaction_line.getId()} )\n + if third_party is not None and third_party.getPortalType() \\\n + in [\'Person\', \'Organisation\']:\n + # Test state :(\n if third_party.getValidationState() != \'validated\':\n - raise ValidationFailed, N_("Action failed: third party \'${third_party_name}\' is not validated."\n - , mapping = {\'third_party_name\': unicode(third_party.getTranslatedTitle(), \'utf8\')}\n - )\n + raise ValidationFailed, N_(\n + "Action failed: third party \'${third_party_name}\' is not "\n + "validated.",\n + mapping = {\'third_party_name\':\n + unicode(third_party.getTranslatedTitle(), \'utf8\')} )\n # Test region\n - # Note: This test is normally handle by the entity workflow which don\'t allow validation of entity\n - # until region is set. So if the previous condition is not verified, the previous test\n - # catch it. We add this redundent test for easy upgrade of previous ERP5 accounting system.\n - if third_party.getRegion() in (None, \'\'):\n - raise ValidationFailed, N_("Action failed: third party \'${third_party_name}\' has no region."\n - , mapping = {\'third_party_name\': unicode(third_party.getTranslatedTitle(), \'utf8\')}\n - )\n -\n - if (side == SOURCE) and account.isMemberOf("account_type/asset/cash/bank"):\n - if payment in (None, ""):\n - raise ValidationFailed, N_("Action failed: no bank account defined for line \'${line}\'."\n - , mapping = {\'line\': transaction_line.getId()}\n - )\n - elif hasattr(payment, \'getPriceCurrency\') and \\\n - payment.getPriceCurrency() is not None and \\\n - payment.getPriceCurrency() != transaction_line.getResource():\n - raise ValidationFailed, N_("Action failed: bank account for line \'${line}\' "+\n - \'uses ${bank_account_currency} as default currency.\'\n - , mapping = { \'line\' : transaction_line.getId()\n - , \'bank_account_currency\': unicode(payment.getPriceCurrencyValue().getReference(), \'utf8\')\n - }\n - )\n + # Note: This test is normally handle by the entity workflow which\n + # don\'t allow validation of entity until region is set. So if the\n + # previous condition is not verified, the previous test catch it. We\n + # add this redundent test for easy upgrade of previous ERP5\n + # accounting system.\n + if not third_party.getRegion():\n + raise ValidationFailed, N_(\n + "Action failed: third party \'${third_party_name}\' has no "\n + "region.",\n + mapping = {\'third_party_name\':\n + unicode(third_party.getTranslatedTitle(), \'utf8\')})\n \n + if (side == SOURCE) and account.isMemberOf(\n + "account_type/asset/cash/bank"):\n + # XXX we must check for source only if we are intersted in the\n + # accounting for source. Today, payment transaction cannot be validated\n + # if they do not have a source, so this check is not needed yet.\n + if payment is None:\n + raise ValidationFailed, N_(\n + "Action failed: no source bank account defined for line \'${line}\'.",\n + mapping = {\'line\': transaction_line.getId()} )\n + else:\n + bank_account_currency = payment.getProperty(\'price_currency\')\n + if bank_account_currency is not None and \\\n + bank_account_currency != transaction_line.getResource():\n + raise ValidationFailed, N_(\n + "Action failed: source bank account for line \'${line}\' "\\\n + "uses ${bank_account_currency} as default currency.",\n + mapping = { \'line\' : transaction_line.getId(),\n + \'bank_account_currency\':\n + unicode(payment.getPriceCurrencyReference(), \'utf8\')})\n + \n + if (side == DESTINATION) and account.isMemberOf(\n + "account_type/asset/cash/bank"):\n + # we check account for destination section only if we are interested in\n + # the accounting for this entity.\n + if not check_for_destination:\n + continue\n + if payment is None:\n + raise ValidationFailed, N_(\n + "Action failed: no destination bank account defined for"\n + " line \'${line}\'.",\n + mapping = {\'line\': transaction_line.getId()} )\n + else:\n + bank_account_currency = payment.getProperty(\'price_currency\')\n + if bank_account_currency is not None and \\\n + bank_account_currency != transaction_line.getResource():\n + raise ValidationFailed, N_(\n + "Action failed: bank account for line \'${line}\' "\\\n + "uses ${bank_account_currency} as default currency.",\n + mapping = { \'line\' : transaction_line.getId(),\n + \'bank_account_currency\':\n + unicode(payment.getPriceCurrencyReference(), \'utf8\')})\n + \n + # TODO: should use currency precision instead of hardcoding 100 !\n if int(source_sum*100) != 0:\n - raise ValidationFailed, N_(\'Action failed: transaction is not balanced for source section.\')\n + raise ValidationFailed, N_(\n + \'Action failed: transaction is not balanced for source section.\')\n \n if int(destination_sum*100) != 0:\n - raise ValidationFailed, N_(\'Action failed: transaction is not balanced for destination section.\')\n + raise ValidationFailed, N_(\n + \'Action failed: transaction is not balanced for destination section.\')\n \n transaction.AccountingTransaction_deleteEmptyLines(redirect=0)\n </string> </value> @@ -247,31 +297,34 @@ transaction.AccountingTransaction_deleteEmptyLines(redirect=0)\n <string>state_change</string> <string>Products.DCWorkflow.DCWorkflow</string> <string>ValidationFailed</string> + <string>Products.ERP5Type.Message</string> + <string>Message</string> <string>_getiter_</string> <string>SOURCE</string> <string>DESTINATION</string> - <string>error_message</string> <string>_getitem_</string> <string>transaction</string> - <string>_getattr_</string> <string>N_</string> + <string>_getattr_</string> <string>container</string> <string>source_section</string> <string>destination_section</string> + <string>check_for_destination</string> + <string>None</string> + <string>source_section_group</string> + <string>destination_section_group</string> <string>source_sum</string> <string>destination_sum</string> <string>accounting_transaction_line_list</string> <string>transaction_line</string> <string>source_quantity</string> <string>destination_quantity</string> - <string>None</string> <string>side</string> <string>account</string> <string>payment</string> - <string>third_party_path</string> <string>third_party</string> <string>unicode</string> - <string>hasattr</string> + <string>bank_account_currency</string> <string>int</string> </tuple> </value> diff --git a/bt5/erp5_accounting/bt/revision b/bt5/erp5_accounting/bt/revision index dc7b54ad014355b948b93c4c6c5891da053d5fdd..aaa6442fe902e96a5233b136b973b96a4011fc18 100644 --- a/bt5/erp5_accounting/bt/revision +++ b/bt5/erp5_accounting/bt/revision @@ -1 +1 @@ -33 \ No newline at end of file +41 \ No newline at end of file