From a4307c65b96ad216d47b09f155209e04e479a3e6 Mon Sep 17 00:00:00 2001 From: Kevin Deldycke <kevin@nexedi.com> Date: Sun, 16 Oct 2005 00:26:44 +0000 Subject: [PATCH] First "as is" public release (Thanks to Mayoro, the author) git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@4042 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5/tests/testERP5Budget.py | 491 +++++++++++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100755 product/ERP5/tests/testERP5Budget.py diff --git a/product/ERP5/tests/testERP5Budget.py b/product/ERP5/tests/testERP5Budget.py new file mode 100755 index 0000000000..045fd1314b --- /dev/null +++ b/product/ERP5/tests/testERP5Budget.py @@ -0,0 +1,491 @@ +############################################################################## +# +# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved. +# +# 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. +# +############################################################################## + +# +# ZopeTestCase Skeleton +# + + +import os +from zLOG import LOG +from Testing import ZopeTestCase +from DateTime import DateTime +from Products.CMFCore.utils import getToolByName +from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase +from Products.ERP5Type.tests.Sequence import SequenceList +from AccessControl.SecurityManagement import newSecurityManager +from Products.ERP5Type.Utils import convertToUpperCase +from Products.CMFCore.utils import getToolByName + +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['EVENT_LOG_FILE'] = os.path.join(os.getcwd(), 'zLOG.log') +os.environ['EVENT_LOG_SEVERITY'] = '-300' + + +from Products.ERP5.Document.Person import Person +from Products.ERP5.Document.Organisation import Organisation + + + +class TestBudget(ERP5TypeTestCase): + """ + ERP5 Budget related tests. For the moment every assignment of budget related features are + in Budget module, as well as the predicates to test the accounting operations. These are + packaged in the erp5_budget business template. + """ + + # pseudo constants + RUN_ALL_TEST = 1 + QUIET = 0 + + + def getTitle(self): + """ + Return the title of the current test set. + """ + return "ERP5 Budget" + + + def getBusinessTemplateList(self): + """ + Return the list of required business templates. + """ + #return ( 'erp5_budget',) + #return ('erp5_accounting', 'erp5_budget') + return ('erp5_pdm', 'erp5_trade', 'erp5_accounting', 'erp5_budget') + + + def login(self, quiet=QUIET, run=RUN_ALL_TEST): + """ + Create a new manager user and login. + """ + user_name = 'maurice' + user_folder = self.getPortal().acl_users + user_folder._doAddUser(user_name, '', ['Manager', 'Owner', 'Assignor', 'Assignee', 'Author'], []) + user = user_folder.getUserById(user_name).__of__(user_folder) + newSecurityManager(None, user) + + def logMessage(self,message): + ZopeTestCase._print('\n%s ' % message) + LOG('Testing ... ',0,message) + + def stepCheckBudgetTransactionDrafted(self,budget_transaction, sequence=None, sequence_list=None, **kw): + self.assertEquals('draft', budget_transaction.getSimulationState()) + + + def stepCheckBudgetTransactionDelivered(self,budget_transaction, sequence=None, sequence_list=None, **kw): + self.assertEquals('delivered', budget_transaction.getSimulationState()) + + def stepDeliverBudgetTransaction(self,budget_transaction, sequence=None, sequence_list=None, **kw): + self.portal_workflow.doActionFor(budget_transaction,'deliver_action', \ + wf_id='budget_transaction_workflow') + + + def stepDeliverAccountingTransaction(self,accounting_transaction, sequence=None, sequence_list=None, **kw): + self.portal_workflow.doActionFor(accounting_transaction,'deliver_action', \ + wf_id='accounting_workflow') + + def stepCheckAccountingTransactionDelivered(self,accounting_transaction, sequence=None, sequence_list=None, **kw): + self.assertEquals('delivered', accounting_transaction.getSimulationState()) + + def stepPlanAccountingTransaction(self,accounting_transaction, sequence=None, sequence_list=None, **kw): + self.portal_workflow.doActionFor(accounting_transaction,'plan_action', \ + wf_id='accounting_workflow') + + def stepCheckAccountingTransactionPlanned(self,accounting_transaction, sequence=None, sequence_list=None, **kw): + self.assertEquals('planned', accounting_transaction.getSimulationState()) + + def stepStopAccountingTransaction(self,accounting_transaction, sequence=None, sequence_list=None, **kw): + self.portal_workflow.doActionFor(accounting_transaction,'stop_action', \ + wf_id='accounting_workflow') + + def stepCheckAccountingTransactionStopped(self,accounting_transaction, sequence=None, sequence_list=None, **kw): + self.assertEquals('stopped', accounting_transaction.getSimulationState()) + + def stepConfirmAccountingTransaction(self, accounting_transaction, sequence=None, sequence_list=None, **kw): + self.portal_workflow.doActionFor(accounting_transaction,'confirm_action', \ + wf_id='accounting_workflow') + + def stepCheckAccountingTransactionConfirmed(self,accounting_transaction, sequence=None, sequence_list=None, **kw): + self.assertEquals('confirmed', accounting_transaction.getSimulationState()) + + + def afterSetUp(self, quiet=QUIET, run=RUN_ALL_TEST): + """ + Initialize the ERP5 site. + """ + self.login() + self.portal = self.getPortal() + self.portal_catalog = self.getCatalogTool() + self.portal_categories = self.getCategoryTool() + self.portal_workflow = self.getWorkflowTool() + self.createCategories() + # Must add some accounts, accounting transactions, budget and budget transaction, etc. + account_module = self.getAccountModule() + accounting_module = self.getAccountingModule() + self.currency_module = self.getCurrencyModule() + self.organisation_module = self.getOrganisationModule() + budget_module = self.getBudgetModule() + budget_transaction_module = self.getBudgetTransactionModule() + self.portal = self.getPortal() + self.getAccountingModule().manage_addLocalRoles('maurice', ('Assignor','Assignee','Manager','Owner',)) + # flush activities + get_transaction().commit() + self.tic() + + # When using light install, only base categories are created + if len(self.portal_categories.region.contentValues()) == 0 : + o = self.portal_categories.region.newContent(portal_type='Category', id='europe') + o = o.newContent(portal_type='Category', id='west') + o.newContent(portal_type='Category', id='france') + + # If currency/XOF already exists, it means that the afterSetUp actions were already commited. Then, we just need to link to them. + old_eur = getattr( self.getCurrencyModule(), 'EUR', None) + # Create some currencies + if old_eur is None : + eur = self.getCurrencyModule().newContent(id='EUR', title='Euros', portal_type='Currency') + + # Create some organisations + old_organisation = getattr( self.organisation_module, 'world_company', None) + if old_organisation is None: + self.organisation0 = self.organisation_module.newContent(id='world_company', title='World Company Inc.', portal_type='Organisation') + self.organisation0.newContent(id='default_address', portal_type='Address', region='europe/west/france') + old_nexedi = getattr( self.organisation_module, 'nexedi', None) + if old_nexedi is None: + self.organisation1 = self.organisation_module.newContent(id='nexedi', title='Nexedi', portal_type='Organisation') + self.organisation1.newContent(id='default_address', portal_type='Address', region='europe/west/france') + old_client1 = getattr( self.organisation_module, 'client1', None) + if old_client1 is None: + self.organisation2 = self.organisation_module.newContent(id='client1', title='Client1', portal_type='Organisation') + self.organisation2.newContent(id='default_address', portal_type='Address', region='europe/west/france') + + # Create some accounts + old_accounts = getattr( account_module, 'prestation_service', None) + if old_accounts is None: + account_module.newContent(id='prestation_service', title='prestation_service', portal_type='Account', financial_section='actif/actif_circulant') + account_module.newContent(id='creance_client', title='creance_client', portal_type='Account', financial_section='actif/actif_circulant/caisse') + account_module.newContent(id='tva_collectee_196', title='tva_collectee_196', portal_type='Account', financial_section='actif/actif_circulant/caisse') + account_module.newContent(id='account1', title='Account1', portal_type='Account', financial_section='actif/actif_circulant/caisse') + account_module.newContent(id='account2', title='Account2', portal_type='Account', financial_section='actif/actif_immobilise/immobilisations_financieres') + account_module.newContent(id='account3', title='Account3', portal_type='Account', financial_section='actif/actif_immobilise/immobilisations_financieres') + account_module.newContent(id='account4', title='Account4', portal_type='Account', financial_section='actif/actif_immobilise/immobilisations_financieres') + + # Create some accounting transactions + self.accounting_transaction1 = accounting_module.newContent(portal_type='Accounting Transaction',title='Accounting 1 ', source_section='organisation/world_company', destination_section='organisation/client1', start_date='2005/08/22 18:06:26.388 GMT-4', resource='currency/EUR', source_function='function/hq') + self.accounting_transaction1.newContent(portal_type='Accounting Transaction Line', source_section='organisation/world_company', resource='currency/EUR', source_debit='2000.0', source_credit='0.0', source='account_module/account1') + self.accounting_transaction1.newContent(portal_type='Accounting Transaction Line', source_section='organisation/world_company', resource='currency/EUR', source_debit='0.0', source_credit='2000.0', source='account_module/account2') + + self.accounting_transaction2 = accounting_module.newContent(portal_type='Accounting Transaction',title='Accounting 2 ', source_section='organisation/world_company', destination_section='organisation/client1', start_date='2005/08/22 18:06:26.388 GMT-4', resource='currency/EUR', source_function='function/hq') + self.accounting_transaction2.newContent(portal_type='Accounting Transaction Line', source_section='organisation/world_company', resource='currency/EUR', source_debit='100000.0', source_credit='0.0', source='account_module/account1') + self.accounting_transaction2.newContent(portal_type='Accounting Transaction Line', source_section='organisation/world_company', resource='currency/EUR', source_debit='0.0', source_credit='100000.0', source='account_module/account4') + + id_list = [] + for objects in self.accounting_transaction1.getPortalObject().budget_module.objectValues(): + id_list.append(objects.getId()) + self.accounting_transaction1.budget_module.manage_delObjects(id_list) + + id_list = [] + for objects in self.accounting_transaction1.getPortalObject().budget_transaction_module.objectValues(): + id_list.append(objects.getId()) + self.accounting_transaction1.budget_transaction_module.manage_delObjects(id_list) + + + budget1 = budget_module.newContent(portal_type='Budget',title='Budget initial ', group='world_company', start_date='2005/01/01 18:06:26.388 GMT-4', stop_date='2005/12/31 18:06:26.388 GMT-4') + budget_line1 = budget1.newContent(portal_type='Budget Line', group='world_company', resource='currency/EUR',title = 'Line 1 of budget') + budget_cell1 = budget_line1.newContent( + id = 'cell_0_0_1', + portal_type = 'Budget Cell', + mapped_value_property_list = ('max_quantity'), + membership_criterion_category_list = ['financial_section/actif/actif_circulant/caisse', 'function/hq', 'group/world_company'], + membership_criterion_base_category_list = ['financial_section','function','group'] + ) + budget_cell1.setQuantity(3000.0) + + budget_cell2 = budget_line1.newContent( + id = 'cell_0_1_0', + portal_type = 'Budget Cell', + mapped_value_property_list = ('max_quantity'), + membership_criterion_category_list = [ 'financial_section/actif/actif_immobilise/immobilisations_financieres', 'function/hq', 'group/world_company'], + membership_criterion_base_category_list = ['financial_section','function','group'] + ) + budget_cell2.setQuantity(1000.0) + + budget_transfert1 = budget1.newContent(portal_type='Budget Transfert Line',source=budget_cell1.getRelativeUrl(), resource='currency/EUR',destination =budget_cell2.getRelativeUrl(),quantity=500.0) + + self.budget_transaction1 = budget_transaction_module.newContent(portal_type='Budget Transaction',source =budget_cell1.getRelativeUrl(), destination=budget_cell2.getRelativeUrl(), quantity=25.0,group='world_company', stop_date='2005/05/01 18:06:26.388 GMT-4') + + self.budget_transaction2 = budget_transaction_module.newContent(portal_type='Budget Transaction',source =budget_cell2.getRelativeUrl(), destination=budget_cell1.getRelativeUrl(), quantity=25.0,group='world_company', stop_date='2005/05/01 18:06:26.388 GMT-4') + + # flush activities + get_transaction().commit() + self.tic() + + + + + + def getAccountModule(self): + return getattr(self.getPortal(), 'account_module', None) + + def getAccountingModule(self): + return getattr(self.getPortal(), 'accounting_module', None) + + def getOrganisationModule(self): + return getattr(self.getPortal(), 'organisation', None) + + def getBudgetModule(self): + return getattr(self.getPortal(), 'budget_module', None) + + def getBudgetTransactionModule(self): + return getattr(self.getPortal(), 'budget_transaction_module', None) + + def getCurrencyModule(self) : + return getattr(self.getPortal(), 'currency', None) + + def createCategories(self): + """ + Create some categories for testing. + """ + self.category_list = [ + + # Function categories + {'path' : 'function/hq' + ,'title': 'HQ' + } + , {'path' : 'function/warehouse' + ,'title': 'Warehouse' + } + , {'path' : 'function/research_center' + ,'title': 'Research Center' + } + + # Group categories + , {'path' : 'group/nexedi' + ,'title': 'Nexedi' + } + , {'path' : 'group/world_company' + ,'title': 'World Company Inc.' + } + # some financial sections + , {'path' : 'financial_section/actif/actif_circulant' + ,'title': 'Actif Circulant' + } + , {'path' : 'financial_section/actif/actif_circulant/caisse' + ,'title': 'Caisse' + } + , {'path' : 'financial_section/actif/actif_immobilise/immobilisations_financieres' + ,'title': 'Immobilisations Financieres' + } + + ] + + # Create categories + # Note : this code was taken from the CategoryTool_importCategoryFile python + # script (packaged in erp5_core). + for category in self.category_list: + keys = category.keys() + if 'path' in keys: + base_path_obj = self.portal_categories + is_base_category = True + for category_id in category['path'].split('/'): + # The current category is not existing + if category_id not in base_path_obj.contentIds(): + # Create the category + if is_base_category: + category_type = 'Base Category' + else: + category_type = 'Category' + base_path_obj.newContent( portal_type = category_type + , id = category_id + , immediate_reindex = 1 + ) + base_path_obj = base_path_obj[category_id] + is_base_category = False + new_category = base_path_obj + + # Set the category properties + for key in keys: + if key != 'path': + method_id = "set" + convertToUpperCase(key) + value = category[key] + if value not in ('', None): + if hasattr(new_category, method_id): + method = getattr(new_category, method_id) + method(value.encode('UTF-8')) + + + + + ################################## + ## Basic steps + ################################## + +# def createOrganisation(self, sequence=None, sequence_list=None, **kw): +# """ +# Create an organisation +# """ +# portal_type = 'Organisation' +# organisation_module = self.portal.getDefaultModule(portal_type) +# self.organisation = organisation_module.newContent( portal_type = portal_type +# , group = 'group/world_company' +# , immediate_reindex = 1 +# ) + + ### TODO: write here basic steps + + + ################################## + ## Tests + ################################## + + def test_01_HasEverything(self, quiet=0, run=RUN_ALL_TEST): + if not run: return + if not quiet: + ZopeTestCase._print('\nTest Has Everything ') + LOG('Testing... ',0,'testHasEverything') + self.failUnless(self.getCategoryTool() != None) + self.failUnless(self.getAccountModule() != None) + self.failUnless(self.getAccountingModule() != None) + self.failUnless(self.getOrganisationModule() != None) + self.failUnless(self.getCurrencyModule() != None) + self.failUnless(self.getBudgetModule() != None) + self.failUnless(self.getBudgetTransactionModule() != None) + + def test_02_HasBudgetCells(self, quiet=0, run=RUN_ALL_TEST): + if not run: return + if not quiet: + ZopeTestCase._print('\nTest Has Budget Cells ') + LOG('Testing... ',0,'testHasBudgetCells') + message = "" + len_cells = 0 + self.afterSetUp() + for objects in self.getBudgetModule().budget_module.objectValues(): + if objects.getPortalType() == 'Budget': + for obj_line in objects.objectValues(): + if obj_line.getPortalType() == 'Budget Line': + for obj in obj_line.objectValues(): + len_cells += 1 + financial_section = obj.getMembershipCriterionCategoryList()[0] + function = obj.getMembershipCriterionCategoryList()[1] + group = obj.getMembershipCriterionCategoryList()[2] + quantity = obj.getQuantity() + message += str(obj.getId())+': '+str(financial_section)+', '+str(function)+', '+str(group)+', '+str(quantity)+'\n' + if len_cells == 0: + message = "could not create budget cells" + ZopeTestCase._print('\n%s ' % message) + LOG('Testing values... ',0,message) + self.failUnless(len_cells != 0) + + + def test_03_Enough_budget(self, quiet=0, run=RUN_ALL_TEST): + """ + Try to validate transactions of accountings if there is enough budget + """ + if not run: return + if not quiet: + message = 'Test if there is enough budget before validating an accounting transaction' + ZopeTestCase._print('\n%s ' % message) + LOG('Testing... ',0,message) + self.afterSetUp() + self.stepConfirmAccountingTransaction(self.accounting_transaction1) + message = str(self.accounting_transaction1.getSimulationState()) + ZopeTestCase._print('\n%s ' % message) + LOG('Testing simulation state accounting transaction 1... ',0,message) +# if self.stepCheckAccountingTransactionStopped(self.accounting_transaction1): +# message = 'There is enough budget, so this transaction will be validated' +# ZopeTestCase._print('\n%s ' % message) +# LOG('Testing accounting transaction 1... ',0,message) +# else: +# message = 'There is not enough budget, so this transaction will not be validated' +# ZopeTestCase._print('\n%s ' % message) +# LOG('Testing accounting transaction 1... ',0,message) + + self.stepConfirmAccountingTransaction(self.accounting_transaction2) + message = str(self.accounting_transaction2.getSimulationState()) + ZopeTestCase._print('\n%s ' % message) + LOG('Testing simulation state accounting transaction 2... ',0,message) +# if self.stepCheckAccountingTransactionStopped(self.accounting_transaction2): +# message = 'There is enough budget, so this transaction will be validated' +# ZopeTestCase._print('\n%s ' % message) +# LOG('Testing accounting transaction 2... ',0,message) +# else: +# message = 'There is not enough budget, so this transaction will not be validated' +# ZopeTestCase._print('\n%s ' % message) +# LOG('Testing accounting transaction 2... ',0,message) + + + + def test_04_Transaction_of_budget(self, quiet=0, run=RUN_ALL_TEST): + """ + Try to validate budget trasaction if the transfert is authorized + """ + if not run: return + if not quiet: + message = 'Test if the transaction of budget is authorized' + ZopeTestCase._print('\n%s ' % message) + LOG('Testing... ',0,message) + self.afterSetUp() + self.stepDeliverBudgetTransaction(self.budget_transaction1) + message = str(self.budget_transaction1.getSimulationState()) + ZopeTestCase._print('\n%s ' % message) + LOG('Testing simulation state budet 1... ',0,message) + if self.stepCheckBudgetTransactionDelivered(self.budget_transaction1): + message = 'This transaction is possible so we can validate it' + ZopeTestCase._print('\n%s ' % message) + LOG('Testing budget transaction 1... ',0,message) + else: + message = 'This transaction is not possible because it is not authorized' + ZopeTestCase._print('\n%s ' % message) + LOG('Testing budget transaction 1... ',0,message) + + self.stepDeliverBudgetTransaction(self.budget_transaction2) + message = str(self.budget_transaction2.getSimulationState()) + ZopeTestCase._print('\n%s ' % message) + LOG('Testing simulation state budet 2... ',0,message) + if self.stepCheckBudgetTransactionDrafted(self.budget_transaction2): + message = 'This transaction is possible so we can validate it' + ZopeTestCase._print('\n%s ' % message) + LOG('Testing budget transaction 2... ',0,message) + else: + message = 'This transaction is not possible because it is not authorized' + ZopeTestCase._print('\n%s ' % message) + LOG('Testing budget transaction 2... ',0,message) + + + + +if __name__ == '__main__': + framework() +else: + import unittest + def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestBudget)) + return suite -- 2.30.9