[Erp5-report] r7717 - in /erp5/trunk/products: ERP5/tests/ ERP5Type/tests/
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed Jun 14 14:38:00 CEST 2006
Author: jerome
Date: Wed Jun 14 14:37:57 2006
New Revision: 7717
URL: http://svn.erp5.org?rev=7717&view=rev
Log:
New test for VAT and invoices.
Added:
erp5/trunk/products/ERP5/tests/testInvoiceVAT.py
Modified:
erp5/trunk/products/ERP5Type/tests/run_unit_test
Added: erp5/trunk/products/ERP5/tests/testInvoiceVAT.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/tests/testInvoiceVAT.py?rev=7717&view=auto
==============================================================================
--- erp5/trunk/products/ERP5/tests/testInvoiceVAT.py (added)
+++ erp5/trunk/products/ERP5/tests/testInvoiceVAT.py Wed Jun 14 14:37:57 2006
@@ -1,0 +1,519 @@
+##############################################################################
+#
+# Copyright (c) 2004 Nexedi SARL and Contributors. All Rights Reserved.
+# Jerome Perrin <jerome at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+"""
+ Tests VAT for invoices.
+"""
+
+import os, sys
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+# Needed in order to have a log file inside the current folder
+os.environ.setdefault('EVENT_LOG_FILE', 'zLOG.log')
+os.environ.setdefault('EVENT_LOG_SEVERITY', '-300')
+
+from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
+from AccessControl.SecurityManagement import newSecurityManager
+from DateTime import DateTime
+
+class TestInvoiceVAT(ERP5TypeTestCase):
+ """Test VAT for invoices.
+
+ """
+
+ RUN_ALL_TESTS = 1
+
+ default_region = "europe/west/france"
+ invoice_portal_type = 'Sale Invoice Transaction'
+ invoice_line_portal_type = 'Invoice Line'
+ invoice_cell_portal_type = 'Invoice Cell'
+ invoice_transaction_line_portal_type = 'Sale Invoice Transaction Line'
+
+ def getTitle(self):
+ return "Invoices and VAT"
+
+ def afterSetUp(self):
+ """set up """
+ self.createCategories()
+ self.login()
+
+ def _safeTic(self):
+ """Like tic, but swallowing errors, usefull for teardown"""
+ try:
+ get_transaction().commit()
+ self.tic()
+ except RuntimeError:
+ pass
+
+ def beforeTearDown(self):
+ """Clear everything for next test."""
+ self._safeTic()
+ for module in [ 'sale_packing_list_module',
+ 'organisation_module',
+ 'person_module',
+ 'currency_module',
+ 'product_module',
+ 'portal_simulation' ]:
+ folder = getattr(self.getPortal(), module, None)
+ if folder:
+ [x.unindexObject() for x in folder.objectValues()]
+ self._safeTic()
+ folder.manage_delObjects([x.getId() for x in folder.objectValues()])
+ accounting_module = self.getPortal().accounting_module
+ [x.cancel() for x in accounting_module.objectValues()]
+ accounting_module.manage_delObjects([x.getId() for x in
+ accounting_module.objectValues()])
+ self._safeTic()
+ # cancel remaining messages
+ activity_tool = self.getPortal().portal_activities
+ for message in activity_tool.getMessageList():
+ activity_tool.manageCancel(message.object_path, message.method_id)
+ ZopeTestCase._print('\nCancelling active message %s.%s()\n'
+ % (message.object_path, message.method_id) )
+ get_transaction().commit()
+
+ def login(self, quiet=0, run=1):
+ uf = self.getPortal().acl_users
+ uf._doAddUser('alex', '', ['Manager', 'Assignee', 'Assignor',
+ 'Associate', 'Auditor', 'Author'], [])
+ user = uf.getUserById('alex').__of__(uf)
+ newSecurityManager(None, user)
+
+ def createCategories(self):
+ """Create the categories for our test. """
+ # create categories
+ for cat_string in self.getNeededCategoryList() :
+ base_cat = cat_string.split("/")[0]
+ path = self.getPortal().portal_categories[base_cat]
+ for cat in cat_string.split("/")[1:] :
+ if not cat in path.objectIds() :
+ path = path.newContent(
+ portal_type='Category',
+ id=cat,
+ immediate_reindex=1 )
+ else:
+ path = path[cat]
+ # check categories have been created
+ for cat_string in self.getNeededCategoryList() :
+ self.assertNotEquals(None,
+ self.getCategoryTool().restrictedTraverse(cat_string),
+ cat_string)
+
+ def getNeededCategoryList(self):
+ """return a list of categories that should be created."""
+ return ( 'account_type/asset'
+ 'account_type/asset/cash',
+ 'account_type/asset/cash/bank',
+ 'account_type/asset/receivable',
+ 'account_type/asset/receivable/refundable_vat',
+ 'account_type/equity',
+ 'account_type/expense',
+ 'account_type/income',
+ 'account_type/liability',
+ 'account_type/liability/payable',
+ 'account_type/liability/payable/collected_vat',
+ 'region/%s' % self.default_region,
+ )
+
+ def getBusinessTemplateList(self):
+ """ """
+ return ('erp5_base', 'erp5_pdm', 'erp5_trade', 'erp5_accounting',)
+
+ def _makeAccount(self, **kw):
+ """Creates an Account."""
+ account = self.getPortal().account_module.newContent(
+ portal_type='Account',
+ **kw)
+ get_transaction().commit()
+ self.tic()
+ return account
+
+ def _makeOrganisation(self, **kw):
+ """Creates an organisation."""
+ org = self.getPortal().organisation_module.newContent(
+ portal_type='Organisation',
+ **kw)
+ get_transaction().commit()
+ self.tic()
+ return org
+
+ def _makeSalePackingList(self, **kw):
+ """Creates a sale packing list."""
+ spl = self.getPortal().sale_packing_list_module.newContent(
+ portal_type='Sale Packing List',)
+ spl.edit(**kw)
+ get_transaction().commit()
+ self.tic()
+ return spl
+
+ def _makeSaleInvoice(self, created_by_builder=0, **kw):
+ """Creates a sale invoice."""
+ sit = self.getPortal().accounting_module.newContent(
+ portal_type='Sale Invoice Transaction',
+ created_by_builder=created_by_builder)
+ sit.edit(**kw)
+ get_transaction().commit()
+ self.tic()
+ return sit
+
+ def _makeCurrency(self, **kw):
+ """Creates a currency."""
+ currency = self.getCurrencyModule().newContent(
+ portal_type = 'Currency', **kw)
+ get_transaction().commit()
+ self.tic()
+ return currency
+
+ def _makeResource(self, **kw):
+ """Creates a resource."""
+ resource = self.getPortal().product_module.newContent(
+ portal_type='Product', **kw)
+ get_transaction().commit()
+ self.tic()
+ return resource
+
+ def _makeSimpleInvoiceTransactionRule(self, resource, receivable_account,
+ vat_account, income_account):
+ """A simple invoice transaction rule, with only one accounting cell,
+
+ Debit Credit
+ receivable account 1.1
+ vat account 0.1
+ income account 1
+
+ """
+ itr = self.getPortal().portal_rules.default_invoice_transaction_rule
+ itr.manage_delObjects([x for x in itr.objectIds()])
+ pred = itr.newContent(portal_type='Predicate')
+ pred.setStringIndex('product')
+ pred.setIntIndex(1) # XXX is it usefull ?
+ pred.setMembershipCriterionBaseCategoryList('resource')
+ pred.setMembershipCriterionCategoryList(['resource/%s' %
+ resource.getRelativeUrl()])
+ get_transaction().commit()
+ self.tic()
+ itr.updateMatrix()
+
+ cell_list = itr.getCellValueList(base_id='movement')
+ self.assertEquals(len(cell_list), 1)
+ cell = cell_list[0]
+ cell.newContent(
+ portal_type = 'Accounting Transaction Line',
+ source_value = receivable_account,
+ quantity=-1.1 )
+ cell.newContent(
+ portal_type = 'Accounting Transaction Line',
+ source_value = vat_account,
+ quantity=.1 )
+ cell.newContent(
+ portal_type = 'Accounting Transaction Line',
+ source_value = income_account,
+ quantity=1 )
+
+ def _stopPackingList(self, packing_list):
+ """Stop a packing list, this will trigger invoice generation with
+ the builder.
+ """
+ packing_list.confirm()
+ packing_list.setReady()
+ packing_list.start()
+ get_transaction().commit()
+ self.tic()
+ packing_list.stop()
+ self.assertEquals(packing_list.getSimulationState(), 'stopped')
+ get_transaction().commit()
+ self.tic()
+
+ def _makeOnePackingList(self):
+ """Returns currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section and packing_list.
+
+ The packing list is ready to test.
+ """
+ currency = self._makeCurrency()
+ resource = self._makeResource()
+ receivable_account = self._makeAccount(
+ account_type='asset/receivable')
+ self.assertNotEquals(receivable_account.getAccountTypeValue(), None)
+ vat_account = self._makeAccount(
+ account_type='liability/payable/collected_vat')
+ self.assertNotEquals(vat_account.getAccountTypeValue(), None)
+ income_account = self._makeAccount(account_type='income')
+ self.assertNotEquals(income_account.getAccountTypeValue(), None)
+
+ self._makeSimpleInvoiceTransactionRule(
+ resource=resource,
+ receivable_account=receivable_account,
+ vat_account=vat_account,
+ income_account=income_account )
+
+ section = self._makeOrganisation(title='Section')
+ mirror_section = self._makeOrganisation(title='Mirror Section')
+ packing_list = self._makeSalePackingList(
+ source_value=section,
+ source_section_value=section,
+ destination_value=mirror_section,
+ destination_section_value=mirror_section,
+ price_currency_value=currency,
+ start_date=DateTime())
+ return (currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section, packing_list)
+
+ def _makeOneInvoice(self):
+ """Returns currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section and invoice
+
+ The invoice is ready to test.
+ """
+ currency = self._makeCurrency()
+ resource = self._makeResource()
+ receivable_account = self._makeAccount(
+ account_type='asset/receivable')
+ self.assertNotEquals(receivable_account.getAccountTypeValue(), None)
+ vat_account = self._makeAccount(
+ account_type='liability/payable/collected_vat')
+ self.assertNotEquals(vat_account.getAccountTypeValue(), None)
+ income_account = self._makeAccount(account_type='income')
+ self.assertNotEquals(income_account.getAccountTypeValue(), None)
+
+ self._makeSimpleInvoiceTransactionRule(
+ resource=resource,
+ receivable_account=receivable_account,
+ vat_account=vat_account,
+ income_account=income_account )
+
+ section = self._makeOrganisation(title='Section')
+ mirror_section = self._makeOrganisation(title='Mirror Section')
+ sale_invoice = self._makeSaleInvoice(
+ source_value=section,
+ source_section_value=section,
+ destination_value=mirror_section,
+ destination_section_value=mirror_section,
+ price_currency_value=currency,
+ created_by_builder=1, # XXX this prevent
+ # init scripts from
+ # creating lines
+ start_date=DateTime())
+ return (currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section, sale_invoice)
+
+ def _checkInvoiceVAT(self, invoice, total_price, vat_ratio,
+ total_vat_amount):
+ """Check the VAT for this invoice.
+ This check will first check VAT on the invoice, then confirm the
+ invoice, so that transaction lines are generated, and make sure
+ values are still correct when read on the accounting lines rather
+ than on the simulation.
+
+ o invoice: The Invoice object
+ o total_price: The total price that this invoice is supposed to
+ have (ie. the receivable quantity)
+ o vat_ratio: The VAT ratio.
+ o total_vat_amount: The value for the VAT.
+ """
+ # check vat informations
+ vat_info = invoice.SaleInvoiceTransaction_getVAT()
+ self.assertEquals(total_price, sum([line.getTotalPrice() for line in
+ invoice.getMovementList()]))
+ self.assertEquals(vat_info['total'], total_vat_amount)
+ self.assertEquals(vat_info['ratio'], vat_ratio)
+
+ # confirm the invoice,
+ invoice.confirm()
+ get_transaction().commit()
+ self.tic()
+ # this will generate accounting lines
+ self.assertNotEquals(len(invoice.getMovementList(
+ portal_type=self.getPortal().getPortalAccountingMovementTypeList())), 0)
+ # and vat information will still be OK
+ vat_info = invoice.SaleInvoiceTransaction_getVAT()
+ self.assertEquals(total_price, sum([line.getTotalPrice() for line in
+ invoice.getMovementList()]))
+ self.assertEquals(vat_info['total'], total_vat_amount)
+ self.assertEquals(vat_info['ratio'], vat_ratio)
+
+
+ # invoice without packing list related
+
+ def test_SimpleInvoice(self, quiet=0, run=RUN_ALL_TESTS):
+ """Test VAT for a simple invoice created directly. """
+ ( currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section, invoice
+ ) = self._makeOneInvoice()
+
+ # add lines in the invoice
+ for i in (1, 2):
+ line = invoice.newContent(
+ portal_type='Invoice Line',)
+ line.edit(quantity=10,
+ price=100,
+ resource_value=resource )
+ invoice.plan()
+ get_transaction().commit();
+ self.tic()
+
+ # actual values on invoice line should be:
+ total_price = 2 * 10 * 100
+ vat_ratio = .1
+ total_vat_amount = total_price * vat_ratio
+ self._checkInvoiceVAT(invoice, total_price, vat_ratio,
+ total_vat_amount)
+
+ def test_SimpleInvoiceEmptyLines(self, quiet=0, run=RUN_ALL_TESTS):
+ """Test VAT for a simple invoice created directly; empty lines should not
+ be a problem."""
+ ( currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section, invoice
+ ) = self._makeOneInvoice()
+
+ # add lines in the invoice
+ for i in (1, 2):
+ line = invoice.newContent(
+ portal_type='Invoice Line',)
+ line.edit(quantity=10,
+ price=100,
+ resource_value=resource )
+ invoice.plan()
+ get_transaction().commit();
+ self.tic()
+
+ # actual values on invoice line should be:
+ total_price = 2 * 10 * 100
+ vat_ratio = .1
+ total_vat_amount = total_price * vat_ratio
+ self._checkInvoiceVAT(invoice, total_price, vat_ratio,
+ total_vat_amount)
+
+ # same if we add an empty invoice line
+ invoice.newContent(portal_type='Invoice Line')
+ self._checkInvoiceVAT(invoice, total_price, vat_ratio,
+ total_vat_amount)
+ # ... or an empty accouting line
+ invoice.newContent(portal_type='Accounting Transaction Line')
+ self._checkInvoiceVAT(invoice, total_price, vat_ratio,
+ total_vat_amount)
+
+ def TODOtest_SimpleInvoiceTwoResources(self, quiet=0, run=RUN_ALL_TESTS):
+ """Test VAT, for two resources, where only one requires VAT """
+ ( currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section, invoice
+ ) = self._makeOneInvoice()
+
+ another_resource = self._makeResource(title='Another resource')
+
+ # add lines in the invoice
+ for res in (resource, another_resource):
+ line = invoice.newContent(
+ portal_type='Invoice Line',)
+ line.edit(quantity=10,
+ price=100,
+ resource_value=res )
+ invoice.plan()
+ get_transaction().commit();
+ self.tic()
+
+ # actual values on invoice line should be:
+ total_price = 2 * 10 * 100
+ vat_ratio = .1
+ total_vat_amount = 10 * 100 * vat_ratio # only one line with VAT
+ self._checkInvoiceVAT(invoice, total_price, vat_ratio,
+ total_vat_amount)
+
+ # invoice from a packing list
+
+ def test_InvoiceTwoLinesWithSameResource(self, quiet=0,
+ run=RUN_ALL_TESTS):
+ """Test VAT for an invoice that cames from a packing list with two
+ lines of the same resource.
+ """
+ ( currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section, packing_list
+ ) = self._makeOnePackingList()
+
+ # add lines in the packing list
+ for i in (1, 2):
+ line = packing_list.newContent(
+ portal_type='Sale Packing List Line',)
+ line.edit(quantity=10,
+ price=100,
+ resource_value=resource )
+
+ self._stopPackingList(packing_list)
+ invoice = packing_list.getCausalityRelatedValue(
+ portal_type='Sale Invoice Transaction')
+ self.assertNotEquals(invoice, None)
+
+ # actual values on invoice line should be:
+ total_price = 2 * 10 * 100
+ vat_ratio = .1
+ total_vat_amount = total_price * vat_ratio
+
+ self._checkInvoiceVAT(invoice, total_price, vat_ratio,
+ total_vat_amount)
+
+ def test_InvoiceTwoLinesWithSameResourceDifferentDate(self, quiet=0,
+ run=RUN_ALL_TESTS):
+ """Test VAT for an invoice that cames from a packing list with two
+ lines of the same resource, with different dates.
+ """
+ ( currency, resource, receivable_account, vat_account,
+ income_account, section, mirror_section, packing_list
+ ) = self._makeOnePackingList()
+
+ date = DateTime()
+ # add lines in the packing list
+ for i in (1, 2):
+ line = packing_list.newContent(
+ portal_type='Sale Packing List Line',)
+ line.edit(quantity=10,
+ price=100,
+ date=date + i,
+ resource_value=resource )
+
+ self._stopPackingList(packing_list)
+ invoice = packing_list.getCausalityRelatedValue(
+ portal_type='Sale Invoice Transaction')
+ self.assertNotEquals(invoice, None)
+
+ # actual values on invoice line should be:
+ total_price = 2 * 10 * 100
+ vat_ratio = .1
+ total_vat_amount = total_price * vat_ratio
+
+ self._checkInvoiceVAT(invoice, total_price, vat_ratio,
+ total_vat_amount)
+
+if __name__ == '__main__':
+ framework()
+else:
+ import unittest
+ def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestInvoiceVAT))
+ return suite
+
Modified: erp5/trunk/products/ERP5Type/tests/run_unit_test
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/run_unit_test?rev=7717&r1=7716&r2=7717&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/run_unit_test (original)
+++ erp5/trunk/products/ERP5Type/tests/run_unit_test Wed Jun 14 14:37:57 2006
@@ -13,6 +13,7 @@
$DIRECTORY/ERP5Type/tests/runUnitTest.py testAccountingRules >> $DIRECTORY/test_full_output 2>&1
$DIRECTORY/ERP5Type/tests/runUnitTest.py testAccounting >> $DIRECTORY/test_full_output 2>&1
$DIRECTORY/ERP5Type/tests/runUnitTest.py testInvoice >> $DIRECTORY/test_full_output 2>&1
+$DIRECTORY/ERP5Type/tests/runUnitTest.py testInvoiceVAT >> $DIRECTORY/test_full_output 2>&1
$DIRECTORY/ERP5Type/tests/runUnitTest.py testResource >> $DIRECTORY/test_full_output 2>&1
$DIRECTORY/ERP5Type/tests/runUnitTest.py testInteractionWorkflow >> $DIRECTORY/test_full_output 2>&1
$DIRECTORY/ERP5Type/tests/runUnitTest.py testImmobilisation >> $DIRECTORY/test_full_output 2>&1
More information about the Erp5-report
mailing list