############################################################################## # # Copyright (c) 2009-2010 Nexedi SA and Contributors. All Rights Reserved. # Fabien Morin <fabien.morin@gmail.com> # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsibility 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 # guarantees 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. # ############################################################################## from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5ReportTestCase from Products.ERP5.tests.testTradeModelLine import TestTradeModelLineMixin from AccessControl.SecurityManagement import newSecurityManager from Products.ERP5Type.tests.Sequence import SequenceList from Products.ERP5Type.tests.utils import reindex from Products.CMFCore.utils import getToolByName from DateTime import DateTime import transaction class TestPayrollMixin(ERP5ReportTestCase, TestTradeModelLineMixin): normal_resource_use_category_list = ['payroll/base_salary'] invoicing_resource_use_category_list = ['payroll/tax'] BUSINESS_PATH_CREATION_SEQUENCE_STRING = """ CreateBusinessProcess CreateBusinessPath CreateUrssafRoubaixOrganisation ModifyBusinessPathTradePhase ModelSpecialiseBusinessProcess Tic """ COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING = """ CreateUrssafService CreateLabourService CreateEmployer CreateEmployee CreatePriceCurrency CreateBasicModel Tic ModelCreateUrssafModelLine UrssafModelLineCreateMovements CreateBasicPaysheet PaysheetCreateLabourPaySheetLine Tic """ + BUSINESS_PATH_CREATION_SEQUENCE_STRING def getTitle(self): return "Payroll" def afterSetUp(self): """Prepare the test.""" self.createCategories() self.setSystemPreference() @reindex def beforeTearDown(self): transaction.abort() for module in ( self.portal.organisation_module, self.portal.person_module, self.portal.paysheet_model_module, self.portal.accounting_module, self.portal.business_process_module, self.portal.service_module, self.portal.portal_simulation,): module.manage_delObjects(list(module.objectIds())) def login(self): uf = self.getPortal().acl_users uf._doAddUser('admin', '', ['Manager', 'Assignee', 'Assignor', 'Associate', 'Auditor', 'Author'], []) user = uf.getUserById('admin').__of__(uf) newSecurityManager(None, user) @reindex def setSystemPreference(self): preference_tool = getToolByName(self.portal, 'portal_preferences') system_preference_list = preference_tool.contentValues( portal_type='System Preference') if len(system_preference_list) > 1: raise AttributeError('More than one System Preference, cannot test') if len(system_preference_list) == 0: system_preference = preference_tool.newContent( portal_type='System Preference') else: system_preference = system_preference_list[0] system_preference.edit( preferred_invoicing_resource_use_category_list = \ self.invoicing_resource_use_category_list, preferred_normal_resource_use_category_list = \ self.normal_resource_use_category_list, preferred_payroll_resource_use_category_list = \ ['use/payroll'], priority = 1, ) if system_preference.getPreferenceState() == 'disabled': system_preference.enable() @reindex def createCategories(self): """Create the categories for our test. """ # create categories for cat_string in self.getNeededCategoryList() : base_cat = cat_string.split("/")[0] # if base_cat not exist, create it if getattr(self.getPortal().portal_categories, base_cat, None) == None: self.getPortal().portal_categories.newContent(\ portal_type='Base Category', id=base_cat) 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, title=cat.replace('_', ' ').title(),) 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 ('tax_category/employer_share', 'tax_category/employee_share', 'base_amount/deductible_tax', 'base_amount/base_salary', 'base_amount/net_salary', 'grade/worker', 'grade/engineer', 'quantity_unit/time/month', 'product_line/labour', 'product_line/state_insurance', 'use/payroll/tax', 'use/payroll/base_salary', 'use/payroll/output', 'trade_phase/payroll/france/urssaf', 'trade_phase/payroll/france/labour', 'time/hours', 'salary_range/france', 'salary_range/france/slice_a', 'salary_range/france/slice_b', 'salary_range/france/slice_c', 'salary_range/france/forfait', 'salary_range/france/slice_0_to_200', 'salary_range/france/slice_200_to_400', 'salary_range/france/slice_400_to_5000', 'salary_range/france/slice_600_to_800', 'marital_status/married', 'marital_status/single', 'group/demo_group', ) def getBusinessTemplateList(self): return TestTradeModelLineMixin.getBusinessTemplateList(self) + ('erp5_payroll', ) def createService(self): module = self.portal.getDefaultModule(portal_type='Service') return module.newContent(portal_type='Service') def stepCreateUrssafService(self, sequence=None, **kw): node = self.createService() node.edit(title='Urssaf', product_line='state_insurance', quantity_unit='time/month', variation_base_category_list=['tax_category', 'salary_range'], use='payroll/tax') node.setVariationCategoryList(['tax_category/employee_share', 'tax_category/employer_share', 'salary_range/france/slice_0_to_200', 'salary_range/france/slice_200_to_400', 'salary_range/france/slice_400_to_5000', 'salary_range/france/slice_600_to_800', ]) sequence.edit(urssaf_service = node) def stepCreateLabourService(self, sequence=None, **kw): node = self.createService() node.edit(title='Labour', quantity_unit='time/month', product_line='labour', use='payroll/base_salary') sequence.edit(labour_service = node) def stepCreateLabourOutputService(self, sequence=None, **kw): '''In case we want to have the labour line in the model, the use category should not be base_salary (=input) because in this case the line will be added on each calculation''' node = self.createService() node.edit(title='Labour', quantity_unit='time/month', product_line='labour', use='payroll/output') sequence.edit(labour_service = node) def stepCreateBonusService(self, sequence=None, **kw): node = self.createService() node.edit(title='Bonus', quantity_unit='time/month', variation_base_category_list=['tax_category'], product_line='labour', use='payroll/base_salary') node.setVariationCategoryList(['tax_category/employee_share', 'tax_category/employer_share']) sequence.edit(bonus_service = node) def stepCreateOldAgeInsuranaceService(self, sequence=None, **kw): node = self.createService() node.edit(title='Old Age Insurance', quantity_unit='time/month', variation_base_category_list=['tax_category', 'salary_range'], product_line='state_insurance', use='payroll/tax') node.setVariationCategoryList(['tax_category/employee_share', 'tax_category/employer_share']) sequence.edit(old_age_insurance_service = node) def stepCreateSicknessInsuranceService(self, sequence=None, **kw): node = self.createService() node.edit(title='Sickness Insurance', quantity_unit='time/month', variation_base_category_list=['tax_category', 'salary_range'], product_line='state_insurance', use='payroll/tax') node.setVariationCategoryList(['tax_category/employee_share', 'tax_category/employer_share']) sequence.edit(sickness_insurance_service = node) def createModel(self): module = self.portal.getDefaultModule(portal_type='Pay Sheet Model') return module.newContent(portal_type='Pay Sheet Model') def createPerson(self): module = self.portal.getDefaultModule(portal_type='Person') return module.newContent(portal_type='Person') def createOrganisation(self): module = self.portal.getDefaultModule(portal_type='Organisation') return module.newContent(portal_type='Organisation') def stepCreateEmployee(self, sequence=None, **kw): employer = sequence.get('employer') node = self.createPerson() node.edit(title='Employee', career_subordination_value=employer) sequence.edit(employee = node) def stepCreateEmployer(self, sequence=None, **kw): node = self.createOrganisation() node.edit(title='Employer') sequence.edit(employer = node) def stepCreateBasicModel(self, sequence=None, **kw): model = self.createModel() employer = sequence.get('employer') employee = sequence.get('employee') model.edit(destination_section_value=employer, source_section_value=employee, effective_date=DateTime(2009,01,01), expiration_date=DateTime(2009,12,31), version='001', reference='basic_model', ) sequence.edit(model = model) def addSlice(self, model, slice, min_value, max_value, base_id='cell'): '''add a new slice in the model''' slice_value = model.newCell(slice, portal_type='Pay Sheet Model Slice', base_id=base_id) slice_value.setQuantityRangeMax(max_value) slice_value.setQuantityRangeMin(min_value) return slice_value def stepSetCurrencyOnModel(self, sequence=None, **kw): model = sequence.get('model') currency = sequence.get('price_currency') model.setPriceCurrencyValue(currency) def stepCreateModelWithSlices(self, sequence=None, **kw): model = self.createModel() employer = sequence.get('employer') employee = sequence.get('employee') model.edit(destination_section_value=employer, source_section_value=employee) model.setVariationSettingsCategoryList(\ ['salary_range/france']) self.addSlice(model, 'salary_range/france/slice_0_to_200', 0, 200) self.addSlice(model, 'salary_range/france/slice_200_to_400', 200, 400) self.addSlice(model, 'salary_range/france/slice_400_to_5000', 400, 5000) self.addSlice(model, 'salary_range/france/slice_600_to_800', 600, 800) sequence.edit(model = model) def createModelLine(self, document, **kw): return document.newContent(portal_type='Pay Sheet Model Line', **kw) def stepModelCreateUrssafModelLine(self, sequence=None, **kw): model = sequence.get('model') model_line = self.createModelLine(model) model_line.edit(title='Urssaf', reference='urssaf_model_line', trade_phase='payroll/france/urssaf', resource_value=sequence.get('urssaf_service'), variation_category_list=['tax_category/employee_share', 'tax_category/employer_share'], base_application_list=[ 'base_amount/base_salary'], base_contribution_list=['base_amount/deductible_tax']) sequence.edit(urssaf_model_line = model_line) def stepModelCreateUrssafModelLineWithSlices(self, sequence=None, **kw): model = sequence.get('model') model_line = self.createModelLine(model) model_line.edit(title='Urssaf', reference='urssaf_model_line_2', trade_phase='payroll/france/urssaf', resource_value=sequence.get('urssaf_service'), variation_category_list=['tax_category/employee_share', 'tax_category/employer_share', 'salary_range/france/slice_0_to_200', 'salary_range/france/slice_200_to_400', 'salary_range/france/slice_400_to_5000'], base_application_list=[ 'base_amount/base_salary'], base_contribution_list=['base_amount/deductible_tax']) sequence.edit(urssaf_model_line_with_slices = model_line) def stepModelCreateUrssafModelLineWithComplexSlices(self, sequence=None, **kw): model = sequence.get('model') model_line = self.createModelLine(model) model_line.edit(title='Urssaf', reference='urssaf_model_line_3', trade_phase='payroll/france/urssaf', resource_value=sequence.get('urssaf_service'), variation_category_list=['tax_category/employee_share', 'tax_category/employer_share', 'salary_range/france/slice_200_to_400', 'salary_range/france/slice_600_to_800'], base_application_list=[ 'base_amount/base_salary'], base_contribution_list=['base_amount/deductible_tax']) sequence.edit(urssaf_model_line_with_slices = model_line) def stepPaysheetCreateUrssafModelLine(self, sequence=None, **kw): '''The model line created here have the same reference than the model line created in stepModelCreateUrssafModelLine. This is used for line overloading tests''' paysheet = sequence.get('paysheet') model_line = self.createModelLine(paysheet) model_line.edit(title='Urssaf', reference='urssaf_model_line', trade_phase='payroll/france/urssaf', resource_value=sequence.get('urssaf_service'), variation_category_list=['tax_category/employee_share', 'tax_category/employer_share'], base_application_list=[ 'base_amount/base_salary'], base_contribution_list=['base_amount/deductible_tax']) sequence.edit(urssaf_model_line = model_line) def stepUrssafModelLineCreateMovements(self, sequence=None, **kw): model_line = sequence.get('urssaf_model_line') cell1 = model_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.1, tax_category='employee_share') cell2 = model_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.5, tax_category='employer_share') def stepUrssafModelLineCreateMovementsWithQuantityOnly(self, sequence=None, **kw): model_line = sequence.get('urssaf_model_line') cell1 = model_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(quantity=-100, tax_category='employee_share') cell2 = model_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(quantity=-200, tax_category='employer_share') def stepUrssafModelLineWithSlicesCreateMovements(self, sequence=None, **kw): model_line = sequence.get('urssaf_model_line_with_slices') cell1 = model_line.newCell('salary_range/france/slice_0_to_200', 'tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.1, tax_category='employee_share', salary_range='france/slice_0_to_200') cell2 = model_line.newCell('salary_range/france/slice_0_to_200', 'tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.2, tax_category='employer_share', salary_range='france/slice_0_to_200') cell3 = model_line.newCell('salary_range/france/slice_200_to_400', 'tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell3.edit(price=0.3, tax_category='employee_share', salary_range='france/slice_200_to_400') cell4 = model_line.newCell('salary_range/france/slice_200_to_400', 'tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell4.edit(price=0.4, tax_category='employer_share', salary_range='france/slice_200_to_400') cell5 = model_line.newCell('salary_range/france/slice_400_to_5000', 'tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell5.edit(price=0.5, tax_category='employee_share', salary_range='france/slice_400_to_5000') cell6 = model_line.newCell('salary_range/france/slice_400_to_5000', 'tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell6.edit(price=0.6, tax_category='employer_share', salary_range='france/slice_400_to_5000') def stepUrssafModelLineWithComplexSlicesCreateMovements(self, sequence=None, **kw): model_line = sequence.get('urssaf_model_line_with_slices') cell1 = model_line.newCell('salary_range/france/slice_200_to_400', 'tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.1, tax_category='employee_share', salary_range='france/slice_200_to_400') cell2 = model_line.newCell('salary_range/france/slice_200_to_400', 'tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.2, tax_category='employer_share', salary_range='france/slice_200_to_400') cell3 = model_line.newCell('salary_range/france/slice_600_to_800', 'tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell3.edit(price=0.3, tax_category='employee_share', salary_range='france/slice_600_to_800') cell4 = model_line.newCell('salary_range/france/slice_600_to_800', 'tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell4.edit(price=0.4, tax_category='employer_share', salary_range='france/slice_600_to_800') def stepPaysheetUrssafModelLineCreateMovements(self, sequence=None, **kw): model_line = sequence.get('urssaf_model_line') cell1 = model_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.3, tax_category='employee_share') cell2 = model_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.7, tax_category='employer_share') def createPaysheet(self, sequence=None, **kw): module = self.portal.getDefaultModule(portal_type='Pay Sheet Transaction') return module.newContent(portal_type='Pay Sheet Transaction') def stepCreateBasicPaysheet(self, sequence=None, **kw): paysheet = self.createPaysheet() paysheet.edit(title='test 1', specialise_value=sequence.get('model'), source_section_value=sequence.get('employee'), destination_section_value=sequence.get('employer'), resource_value=sequence.get('price_currency'), start_date=DateTime(2009,06,01), stop_date=DateTime(2009,06,30)) sequence.edit(paysheet = paysheet) def createPaysheetLine(self, document, **kw): return document.newContent(portal_type='Pay Sheet Line', **kw) def stepPaysheetCreateLabourPaySheetLine(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line = self.createPaysheetLine(paysheet) paysheet_line.edit(title='Labour', price=20, quantity=150, resource_value=sequence.get('labour_service'), base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary']) sequence.edit(labour_paysheet_line = paysheet_line) def stepPaysheetCreateBonusPaySheetLine(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line = self.createPaysheetLine(paysheet) paysheet_line.edit(title='Bonus', resource_value=sequence.get('bonus_service'), variation_category_list=['tax_category/employee_share', 'tax_category/employer_share'], base_contribution_list=[ 'base_amount/base_salary']) sequence.edit(bonus_paysheet_line = paysheet_line) def stepPaysheetCreateBonusPaySheetLineMovements(self, sequence=None, **kw): paysheet_line = sequence.get('bonus_paysheet_line') cell1 = paysheet_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(quantity=1000, price=1, tax_category='employee_share') cell2 = paysheet_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(quantity=1000, price=1, tax_category='employer_share') def checkUpdateAggregatedAmountListReturn(self, model, paysheet, expected_movement_to_delete_count, expected_movement_to_add_count): movement_dict = model.updateAggregatedAmountList(context=paysheet) movement_to_delete = movement_dict['movement_to_delete_list'] movement_to_add = movement_dict['movement_to_add_list'] self.assertEquals(len(movement_to_delete), expected_movement_to_delete_count) self.assertEquals(len(movement_to_add), expected_movement_to_add_count) def stepCheckUpdateAggregatedAmountListReturn(self, sequence=None, **kw): model = sequence.get('model') paysheet = sequence.get('paysheet') self.checkUpdateAggregatedAmountListReturn(model, paysheet, 0, 2) def stepCheckUpdateAggregatedAmountListReturnUsingSlices(self, sequence=None, **kw): model = sequence.get('model') paysheet = sequence.get('paysheet') self.checkUpdateAggregatedAmountListReturn(model, paysheet, 0, 6) def stepCheckUpdateAggregatedAmountListReturnUsingComplexSlices(self, sequence=None, **kw): model = sequence.get('model') paysheet = sequence.get('paysheet') self.checkUpdateAggregatedAmountListReturn(model, paysheet, 0, 4) def stepCheckUpdateAggregatedAmountListReturnUsingPredicate(self, sequence=None, **kw): model = sequence.get('model') paysheet = sequence.get('paysheet') self.checkUpdateAggregatedAmountListReturn(model, paysheet, 0, 4) def stepCheckUpdateAggregatedAmountListReturnAfterChangePredicate(self, sequence=None, **kw): # the marital status of the employe is change in the way that sickness # insurance model_line will not be applied but old age insurance yes. # So two movements will be deleted (from sickness insurance) and two should # be added (from old age insurance) model = sequence.get('model') paysheet = sequence.get('paysheet') self.checkUpdateAggregatedAmountListReturn(model, paysheet, 2, 2) def stepCheckUpdateAggregatedAmountListReturnAfterRemoveLine(self, sequence=None, **kw): model = sequence.get('model') paysheet = sequence.get('paysheet') self.checkUpdateAggregatedAmountListReturn(model, paysheet, 2, 0) def stepPaysheetApplyTransformation(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet.applyTransformation() def stepCheckPaysheetLineAreCreated(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 2) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 2) # 2 because labour line contain no movement def stepCheckNoPaysheetLineAreCreated(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 0) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 0) # 2 because labour line contain no movement def stepCheckPaysheetLineAreCreatedUsingBonus(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 3) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 4) # 4 because labour line contain no movement # 2 for bonus, and 2 for urssaf def stepCheckThereIsOnlyOnePaysheetLine(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 1) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 0) # 0 because labour line contain no movement def stepCheckPaysheetLineAreCreatedUsingSlices(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 2) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 6) # 6 because labour line contain no movement and # because of the 3 slice and 2 tax_categories def stepCheckPaysheetLineAreCreatedUsingComplexSlices(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 2) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 4) # 4 because labour line contain no movement and # because of the 2 slice and 2 tax_categories def stepCheckPaysheetLineAreCreatedUsingWith3Lines(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 3) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 4) # 4 because labour line contain no movement and # because of the two lines and 2 tax_categories # (urssaf and sickness insurance. old age # insurance does not match predicate) def stepCheckPaysheetLineAreCreatedAfterUpdateWithLinesWithSameResource(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 3) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 8) # 8 because labour line contain no movement and # because of the 3 slice and 2 tax_categories # + the first model line with 2 tax_categories def stepCheckPaysheetLineAmounts(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.5) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetLineWithBonusAmounts(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 4000) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 4000) self.assertEquals(cell2.getPrice(), 0.5) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) elif service == 'Bonus': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getTotalPrice(), 1000) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getTotalPrice(), 1000) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetLineAmountsWithQuantityOnly(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), -100) self.assertEquals(cell1.getPrice(), 1) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), -200) self.assertEquals(cell2.getPrice(), 1) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetLineAmountsUsingSlices(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share', 'salary_range/france/slice_0_to_200') self.assertEquals(cell1.getQuantity(), 200) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share', 'salary_range/france/slice_0_to_200') self.assertEquals(cell2.getQuantity(), 200) self.assertEquals(cell2.getPrice(), 0.2) cell3 = paysheet_line.getCell('tax_category/employee_share', 'salary_range/france/slice_200_to_400') self.assertEquals(cell3.getQuantity(), 200) self.assertEquals(cell3.getPrice(), 0.3) cell4 = paysheet_line.getCell('tax_category/employer_share', 'salary_range/france/slice_200_to_400') self.assertEquals(cell4.getQuantity(), 200) self.assertEquals(cell4.getPrice(), 0.4) cell5 = paysheet_line.getCell('tax_category/employee_share', 'salary_range/france/slice_400_to_5000') self.assertEquals(cell5.getQuantity(), 2600) self.assertEquals(cell5.getPrice(), 0.5) cell6 = paysheet_line.getCell('tax_category/employer_share', 'salary_range/france/slice_400_to_5000') self.assertEquals(cell6.getQuantity(), 2600) self.assertEquals(cell6.getPrice(), 0.6) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetLineAmountsUsingComplexSlices(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share', 'salary_range/france/slice_200_to_400') self.assertEquals(cell1.getQuantity(), 200) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share', 'salary_range/france/slice_200_to_400') self.assertEquals(cell2.getQuantity(), 200) self.assertEquals(cell2.getPrice(), 0.2) cell3 = paysheet_line.getCell('tax_category/employee_share', 'salary_range/france/slice_600_to_800') self.assertEquals(cell3.getQuantity(), 200) self.assertEquals(cell3.getPrice(), 0.3) cell4 = paysheet_line.getCell('tax_category/employer_share', 'salary_range/france/slice_600_to_800') self.assertEquals(cell4.getQuantity(), 200) self.assertEquals(cell4.getPrice(), 0.4) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetLineAmountsAfterUpdateWithLinesWithSameResource(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': if len(paysheet_line.contentValues(portal_type='Pay Sheet Cell')) == 6: # there is two lines with the same resource, one with slice and one # without cell1 = paysheet_line.getCell('tax_category/employee_share', 'salary_range/france/slice_0_to_200') self.assertEquals(cell1.getQuantity(), 200) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share', 'salary_range/france/slice_0_to_200') self.assertEquals(cell2.getQuantity(), 200) self.assertEquals(cell2.getPrice(), 0.2) cell3 = paysheet_line.getCell('tax_category/employee_share', 'salary_range/france/slice_200_to_400') self.assertEquals(cell3.getQuantity(), 200) self.assertEquals(cell3.getPrice(), 0.3) cell4 = paysheet_line.getCell('tax_category/employer_share', 'salary_range/france/slice_200_to_400') self.assertEquals(cell4.getQuantity(), 200) self.assertEquals(cell4.getPrice(), 0.4) cell5 = paysheet_line.getCell('tax_category/employee_share', 'salary_range/france/slice_400_to_5000') self.assertEquals(cell5.getQuantity(), 2600) self.assertEquals(cell5.getPrice(), 0.5) cell6 = paysheet_line.getCell('tax_category/employer_share', 'salary_range/france/slice_400_to_5000') self.assertEquals(cell6.getQuantity(), 2600) self.assertEquals(cell6.getPrice(), 0.6) else: cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.5) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetLineAmountsWithSicknessInsuranceAndUrssaf(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.5) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) elif service == 'Sickness Insurance': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.4) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.3) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetLineAmountsWithOldAgeInsuranceAndUrssaf(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.5) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) elif service == 'Old Age Insurance': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.5) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.8) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckUpdateAggregatedAmountListReturnNothing(self, sequence=None, **kw): paysheet = sequence.get('paysheet') model = sequence.get('model') movement_dict = model.updateAggregatedAmountList(context=paysheet) movement_to_delete = movement_dict['movement_to_delete_list'] movement_to_add = movement_dict['movement_to_add_list'] self.assertEquals(len(movement_to_delete), 0) self.assertEquals(len(movement_to_add), 0) def stepCreateUrssafRoubaixOrganisation(self, sequence=None, **kw): node = self.createOrganisation() node.edit(title='Urssaf de Roubaix Tourcoing') sequence.edit(urssaf_roubaix = node) def stepModifyBusinessPathTradePhase(self, sequence=None, **kw): business_path = sequence.get('business_path') business_path.setTradePhaseList(['payroll/france/urssaf', 'payroll/france/labour']) business_path.setSourceValue(sequence.get('urssaf_roubaix')) business_path.setSourceSectionValue(sequence.get('urssaf_roubaix')) business_path.setDeliveryBuilderList(('portal_deliveries/pay_sheet_builder',)) sequence.edit(business_path=business_path) def stepModelSpecialiseBusinessProcess(self, sequence=None, **kw): model = sequence.get('model') business_process = sequence.get('business_process') model.setSpecialiseValueList(business_process) def stepCheckSourceSectionOnMovements(self, sequence=None, **kw): '''Check that the cell contain urssaf_roubaix as source section. This should be the case if getAggregatedAmountList from PaySheetModelLine is able to use Business Process to find the good source_section''' paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') urssaf_roubaix = sequence.get('urssaf_roubaix') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getSourceSectionValue(), urssaf_roubaix) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getSourceSectionValue(), urssaf_roubaix) elif service == 'Labour': pass else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepModelSetCategories(self, sequence=None, **kw): model = sequence.get('model') currency = sequence.get('price_currency') employer = sequence.get('employer') employee = sequence.get('employee') model.edit(\ price_currency_value=currency, default_payment_condition_trade_date='custom', default_payment_condition_payment_date=DateTime(2009,05,25), work_time_annotation_line_quantity=151.67, work_time_annotation_line_quantity_unit='time/hours', ) def stepPaysheetSetModelAndApplyIt(self, sequence=None, **kw): paysheet = sequence.get('paysheet') model = sequence.get('model') paysheet.setSpecialiseValue(model) paysheet.PaySheetTransaction_applyModel(force=1) def stepCheckCategoriesOnPaySheet(self, sequence=None, **kw): paysheet = sequence.get('paysheet') employer = sequence.get('employer') employee = sequence.get('employee') currency = sequence.get('price_currency') self.assertEquals(paysheet.getSourceSectionValue(), employee) self.assertEquals(paysheet.getDestinationSectionValue(), employer) self.assertEquals(paysheet.getPriceCurrencyValue(), currency) self.assertEquals(paysheet.getDefaultPaymentConditionTradeDate(), 'custom') self.assertEquals(paysheet.getDefaultPaymentConditionPaymentDate(), DateTime(2009,05,25)) self.assertEquals(paysheet.getWorkTimeAnnotationLineQuantity(), 151.67) self.assertEquals(paysheet.getWorkTimeAnnotationLineQuantityUnit(), 'time/hours') def stepCheckPaysheetContainNoAnnotationLine(self, sequence=None, **kw): paysheet = sequence.get('paysheet') self.assertEquals(len(paysheet.contentValues(portal_type=\ 'Annotation Line')), 0) def stepCheckPaysheetContainOneAnnotationLine(self, sequence=None, **kw): paysheet = sequence.get('paysheet') self.assertEquals(len(paysheet.contentValues(portal_type=\ 'Annotation Line')), 1) def stepCheckPaysheetContainNoPaymentCondition(self, sequence=None, **kw): paysheet = sequence.get('paysheet') self.assertEquals(len(paysheet.contentValues(portal_type=\ 'Payment Condition')), 0) def stepCheckPaysheetContainOnePaymentCondition(self, sequence=None, **kw): paysheet = sequence.get('paysheet') self.assertEquals(len(paysheet.contentValues(portal_type=\ 'Payment Condition')), 1) def stepCreateModelTree(self, sequence=None, **kw): ''' Create three models inheriting from each other. Set slices values on a model. the inheritance tree look like this : Employee Model / \ / \ / \ Company Model Second Company Alt / / / Country Model ''' model_employee = self.createModel() model_employee.edit(title='Employee Model', reference='model_employee', variation_settings_category_list='salary_range/france') model_company = self.createModel() model_company.edit(title='Company Model', reference='model_company', variation_settings_category_list='salary_range/france') model_company_alt = self.createModel() model_company_alt.edit(title='Second Company Model', reference='model_company_alt', variation_settings_category_list='salary_range/france') model_country = self.createModel() model_country.edit(title='Country Model', reference='model_country', variation_settings_category_list='salary_range/france') # add some cells in the models slice1 = model_employee.newCell('salary_range/france/slice_a', portal_type='Pay Sheet Model Slice', base_id='cell') slice1.setQuantityRangeMin(0) slice1.setQuantityRangeMax(1) slice2 = model_company.newCell('salary_range/france/slice_b', portal_type='Pay Sheet Model Slice', base_id='cell') slice2.setQuantityRangeMin(2) slice2.setQuantityRangeMax(3) slice3 = model_company_alt.newCell('salary_range/france/forfait', portal_type='Pay Sheet Model Slice', base_id='cell') slice3.setQuantityRangeMin(20) slice3.setQuantityRangeMax(30) slice4 = model_country.newCell('salary_range/france/slice_c', portal_type='Pay Sheet Model Slice', base_id='cell') slice4.setQuantityRangeMin(4) slice4.setQuantityRangeMax(5) # inherite from each other model_employee.setSpecialiseValueList((model_company, model_company_alt)) model_company.setSpecialiseValue(model_country) sequence.edit(model_employee = model_employee, model_company = model_company, model_company_alt = model_company_alt, model_country = model_country) def assertCell(self, model, salary_range, range_min, range_max): cell = model.getCell(salary_range) self.assertNotEqual(cell, None) self.assertEqual(cell.getQuantityRangeMin(), range_min) self.assertEqual(cell.getQuantityRangeMax(), range_max) def assertCellIsNone(self, model, salary_range): cell = model.getCell(salary_range) self.assertEqual(cell, None) def stepCheckgetCellResults(self, sequence=None, **kw): model_employee = sequence.get('model_employee') model_company = sequence.get('model_company') model_company_alt = sequence.get('model_company_alt') model_country = sequence.get('model_country') # check model_employee could access all cells self.assertCell(model_employee, 'salary_range/france/slice_a', 0, 1) self.assertCell(model_employee, 'salary_range/france/slice_b', 2, 3) self.assertCell(model_employee, 'salary_range/france/forfait', 20, 30) self.assertCell(model_employee, 'salary_range/france/slice_c', 4, 5) # check model_company could access just it's own cell # and this of the country model self.assertCellIsNone(model_company, 'salary_range/france/slice_a') self.assertCell(model_company, 'salary_range/france/slice_b', 2, 3) self.assertCellIsNone(model_company, 'salary_range/france/forfait') self.assertCell(model_company, 'salary_range/france/slice_c', 4, 5) # model_company_alt could access just it's own cell self.assertCellIsNone(model_company_alt, 'salary_range/france/slice_a') self.assertCellIsNone(model_company_alt, 'salary_range/france/slice_b') self.assertCell(model_company_alt, 'salary_range/france/forfait', 20, 30) self.assertCellIsNone(model_company_alt, 'salary_range/france/slice_c') # check model_country could access just it's own cell self.assertCellIsNone(model_country, 'salary_range/france/slice_a') self.assertCellIsNone(model_country, 'salary_range/france/slice_b') self.assertCellIsNone(model_country, 'salary_range/france/forfait') self.assertCell(model_country, 'salary_range/france/slice_c', 4, 5) def stepModelCreateIntermediateModelLine(self, sequence=None, **kw): ''' create an intermediate_line wich contribute to tax and applied to base_salary ''' model = sequence.get('model') model_line = self.createModelLine(model) model_line.edit(title='intermediate line', trade_phase='payroll/france/urssaf', resource_value=sequence.get('urssaf_service'), reference='intermediate_line', variation_category_list=['tax_category/employee_share', 'tax_category/employer_share'], base_contribution_list=['base_amount/deductible_tax'], base_application_list=['base_amount/base_salary'], create_line=False,) sequence.edit(intermediate_model_line = model_line) def stepModelCreateAppliedOnTaxModelLine(self, sequence=None, **kw): ''' create a model line applied on tax ''' model = sequence.get('model') model_line = self.createModelLine(model) model_line.edit(title='line applied on intermediate line', trade_phase='payroll/france/urssaf', resource_value=sequence.get('urssaf_service'), reference='line_applied_on_intermediate_line', variation_category_list=['tax_category/employee_share', 'tax_category/employer_share'], base_contribution_list=['base_amount/net_salary'], base_application_list=['base_amount/deductible_tax']) sequence.edit(model_line_applied_on_tax = model_line) def stepIntermediateModelLineCreateMovements(self, sequence=None, **kw): model_line = sequence.get('intermediate_model_line') cell1 = model_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.2, tax_category='employee_share') cell2 = model_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.2, tax_category='employer_share') def stepAppliedOnTaxModelLineCreateMovements(self, sequence=None, **kw): model_line = sequence.get('model_line_applied_on_tax') cell1 = model_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.1, tax_category='employee_share') cell2 = model_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.5, tax_category='employer_share') def stepModelCreateOldAgeInsuranceModelLine(self, sequence=None, **kw): model = sequence.get('model') model_line = self.createModelLine(model) model_line.edit(title='Old Age Insurance', trade_phase='payroll/france/urssaf', resource_value=sequence.get('old_age_insurance_service'), reference='old_age_insurance', variation_category_list=['tax_category/employee_share', 'tax_category/employer_share'], base_application_list=[ 'base_amount/base_salary'], base_contribution_list=['base_amount/deductible_tax']) sequence.edit(old_age_insurance = model_line) def stepOldAgeInsuranceModelLineCreateMovements(self, sequence=None, **kw): model_line = sequence.get('old_age_insurance') cell1 = model_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.5, tax_category='employee_share') cell2 = model_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.8, tax_category='employer_share') def stepModelCreateSicknessInsuranceModelLine(self, sequence=None, **kw): model = sequence.get('model') model_line = self.createModelLine(model) model_line.edit(title='Sickness Insurance', trade_phase='payroll/france/urssaf', resource_value=sequence.get('sickness_insurance_service'), reference='sickness_insurance', variation_category_list=['tax_category/employee_share', 'tax_category/employer_share'], base_application_list=[ 'base_amount/base_salary'], base_contribution_list=['base_amount/deductible_tax']) sequence.edit(sickness_insurance = model_line) def stepSicknessInsuranceModelLineCreateMovements(self, sequence=None, **kw): model_line = sequence.get('sickness_insurance') cell1 = model_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.4, tax_category='employee_share') cell2 = model_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.3, tax_category='employer_share') def stepCheckPaysheetIntermediateLines(self, sequence=None, **kw): paysheet = sequence.get('paysheet') # paysheet should contain only two lines (labour and urssaf, but not # intermediate urssaf self.assertEquals(len(paysheet.contentValues(portal_type=\ 'Pay Sheet Line')), 2) # check amounts paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 600) # here it's 600 of tax # because of the intermediate line (3000*0.2) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 600) # here it's 600 of tax # because of the intermediate line (3000*0.2) self.assertEquals(cell2.getPrice(), 0.5) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepPaysheetCreateModelLine(self, sequence=None, **kw): paysheet = sequence.get('paysheet') model_line = self.createModelLine(paysheet) model_line.edit(title='model line in the paysheet', trade_phase='payroll/france/urssaf', resource_value=sequence.get('old_age_insurance_service'), reference='model_line_in_the_payesheet', variation_category_list=['tax_category/employee_share', 'tax_category/employer_share'], base_application_list=[ 'base_amount/base_salary'], base_contribution_list=['base_amount/deductible_tax']) sequence.edit(model_line_on_paysheet = model_line) def stepPaysheetModelLineCreateMovements(self, sequence=None, **kw): model_line = sequence.get('model_line_on_paysheet') cell1 = model_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell1.edit(price=0.5, tax_category='employee_share') cell2 = model_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Model Cell', base_id='movement', mapped_value_property_list=('quantity', 'price')) cell2.edit(price=0.8, tax_category='employer_share') def stepCheckUpdateAggregatedAmountListReturnWithModelLineOnPaysheet(self, sequence=None, **kw): model = sequence.get('model') paysheet = sequence.get('paysheet') self.checkUpdateAggregatedAmountListReturn(model, paysheet, 0, 4) def stepCheckPaysheetLineAreCreatedWithModelLineOnPaysheet(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') self.assertEqual(len(paysheet_line_list), 3) self.assertEqual(len(paysheet.getMovementList(portal_type=\ 'Pay Sheet Cell')), 4) # 2 from the urssaf paysheet line # 2 from the line create with the paysheet model # line self.assertEqual(len(paysheet.contentValues(portal_type=\ 'Pay Sheet Model Line')), 1) def stepCheckPaysheetLineFromModelLineAmounts(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.1) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.5) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) elif service == 'Old Age Insurance': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.5) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.8) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepModelModifyUrssafModelLine(self, sequence=None, **kw): model_line = sequence.get('urssaf_model_line') # modify price on movements : cell_1 = model_line.getCell('tax_category/employee_share', base_id='movement') self.assertNotEquals(cell_1, None) cell_1.edit(price=0.2) cell_2 = model_line.getCell('tax_category/employer_share', base_id='movement') self.assertNotEquals(cell_2, None) cell_2.edit(price=0.6) def stepModelDelUrssafModelLine(self, sequence=None, **kw): model_line = sequence.get('urssaf_model_line') model = sequence.get('model') model.manage_delObjects(model_line.getId()) def stepCheckPaysheetLineNewAmountsAfterUpdate(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.2) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.6) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetLineLabourAmountOnly(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetModelLineOverLoadAmounts(self, sequence=None, **kw): paysheet = sequence.get('paysheet') paysheet_line_list = paysheet.contentValues(portal_type='Pay Sheet Line') for paysheet_line in paysheet_line_list: service = paysheet_line.getResourceTitle() if service == 'Urssaf': cell1 = paysheet_line.getCell('tax_category/employee_share') self.assertEquals(cell1.getQuantity(), 3000) self.assertEquals(cell1.getPrice(), 0.3) cell2 = paysheet_line.getCell('tax_category/employer_share') self.assertEquals(cell2.getQuantity(), 3000) self.assertEquals(cell2.getPrice(), 0.7) elif service == 'Labour': self.assertEqual(paysheet_line.getTotalPrice(), 3000.0) else: self.fail("Unknown service for line %s" % paysheet_line.getTitle()) def stepCheckPaysheetConsistency(self, sequence=None, **kw): paysheet = sequence.get('paysheet') self.assertEquals([], paysheet.checkConsistency()) def stepCheckModelConsistency(self, sequence=None, **kw): model = sequence.get('model') self.assertEquals([], model.checkConsistency()) def stepCheckServiceConsistency(self, sequence=None, **kw): service = sequence.get('urssaf_service') self.assertEquals([], service.checkConsistency()) def stepAddPredicateOnOldAgeInsuranceModelLineForSinglePerson(self, sequence=None, **kw): model_line = sequence.get('old_age_insurance') model_line.setMembershipCriterionBaseCategoryList(\ ['source_marital_status']) model_line.setMembershipCriterionCategoryList(\ ['source_marital_status/marital_status/single']) def stepAddPredicateOnSicknessInsuranceModelLineForMarriedPerson(self, sequence=None, **kw): model_line = sequence.get('sickness_insurance') model_line.setMembershipCriterionBaseCategoryList(\ ['source_marital_status']) model_line.setMembershipCriterionCategoryList(\ ['source_marital_status/marital_status/married']) def stepSetMaritalStatusMarriedOnEmployee(self, sequence=None, **kw): employee = sequence.get('employee') employee.setMaritalStatus('married') def stepSetMaritalStatusSingleOnEmployee(self, sequence=None, **kw): employee = sequence.get('employee') employee.setMaritalStatus('single') def stepModelTreeAddAnnotationLines(self, sequence=None, **kw): model_employee = sequence.get('model_employee') model_employee.newContent(id='over_time_duration', title='Over time duration', portal_type='Annotation Line', reference='over_time_duration', quantity=1) model_company = sequence.get('model_company') model_company.newContent(id='worked_time_duration', title='Worked time duration', portal_type='Annotation Line', reference='worked_time_duration', quantity=2) model_company_alt = sequence.get('model_company_alt') model_company_alt.newContent(id='social_insurance', title='Social insurance', portal_type='Annotation Line', reference='social_insurance', quantity=3) model_country = sequence.get('model_country') model_country.newContent(id='social_insurance', title='Social insurance', portal_type='Annotation Line', reference='social_insurance', quantity=4) def stepCheckInheritanceModelReferenceDict(self, sequence=None, **kw): model_employee = sequence.get('model_employee') model_employee_url = model_employee.getRelativeUrl() model_company_url = sequence.get('model_company').getRelativeUrl() model_company_alt_url = sequence.get('model_company_alt').getRelativeUrl() model_country_url = sequence.get('model_country').getRelativeUrl() model_reference_dict = model_employee.getInheritanceReferenceDict(\ portal_type_list=('Annotation Line',)) self.assertEquals(len(model_reference_dict), 3) # there is 4 model but two # models have the same # reference. self.assertEquals(model_reference_dict.has_key(model_employee_url), True) self.assertEquals(model_reference_dict[model_employee_url], ['over_time_duration']) self.assertEquals(model_reference_dict.has_key(model_company_url), True) self.assertEquals(model_reference_dict[model_company_url], ['worked_time_duration']) self.assertEquals(model_reference_dict.has_key(model_company_alt_url), True) self.assertEquals(model_reference_dict[model_company_alt_url], ['social_insurance']) self.assertNotEquals(model_reference_dict.has_key(model_country_url), True) # check the object list : paysheet = self.createPaysheet() paysheet.setSpecialiseValue(model_employee) object_list = paysheet.getInheritedObjectValueList(portal_type_list=\ ('Annotation Line',)) self.assertEquals(len(object_list), 3) # one line have the same reference # than another, so each reference # should be prensent only one time # in the list over_time_duration = paysheet.getAnnotationLineFromReference(\ 'over_time_duration') self.assertNotEquals(over_time_duration, None) over_time_duration.getQuantity(1) worked_time_duration = paysheet.getAnnotationLineFromReference(\ 'worked_time_duration') self.assertNotEquals(worked_time_duration, None) worked_time_duration.getQuantity(2) social_insurance = paysheet.getAnnotationLineFromReference(\ 'social_insurance') self.assertNotEquals(social_insurance, None) social_insurance.getQuantity(3) def stepCheckPaySheetTransaction_getMovementListReturn(self, sequence=None, **kw): paysheet = sequence.get('paysheet') # when pay sheet has no line, the script returns an empty list self.assertEquals(len(paysheet.PaySheetTransaction_getMovementList()), 0) # we add a line, then it is returned in the list line = self.createPaysheetLine(paysheet) self.assertEquals(len(paysheet.PaySheetTransaction_getMovementList()), 1) # if the line has cells with different tax categories, new properties are # added to this line. urssaf_service = sequence.get('urssaf_service') line.setResourceValue(urssaf_service) line.setVariationCategoryList(['tax_category/employee_share', 'tax_category/employer_share']) cell0 = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement') cell0.setMappedValuePropertyList(['quantity', 'price']) cell0.setVariationCategoryList(('tax_category/employee_share',)) cell0.setPrice(2) cell0.setQuantity(3) cell1 = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement') cell1.setMappedValuePropertyList(['quantity', 'price']) cell1.setVariationCategoryList(('tax_category/employer_share',)) cell1.setPrice(4) cell1.setQuantity(5) movement_list = paysheet.PaySheetTransaction_getMovementList() self.assertEquals(1, len(movement_list)) movement = movement_list[0] self.assertEquals(2, movement.employee_share_price) self.assertEquals(3, movement.employee_share_quantity) self.assertEquals(2*3, movement.employee_share_total_price) self.assertEquals(4, movement.employer_share_price) self.assertEquals(5, movement.employer_share_quantity) self.assertEquals(4*5, movement.employer_share_total_price) def stepCheckModelWithoutRefValidity(self, sequence=None, **kw): ''' If no reference are defined on a model, the behavior is that this model is always valid. So check a Pay Sheet Transaction Line is created after calling the calculation script ''' eur = sequence.get('currency') labour = sequence.get('labour_service_output') model_without_ref = self.getPortalObject().paysheet_model_module.newContent( \ specialise_value=sequence.get('business_process'), portal_type='Pay Sheet Model', variation_settings_category_list=['salary_range/france',], effective_date=DateTime(2009, 1, 1), expiration_date=DateTime(2009, 12, 31)) model_without_ref.setPriceCurrencyValue(eur) model_line_1 = self.createModelLine(model_without_ref) model_line_1.edit( trade_phase='payroll/france/labour', reference='model_without_ref', resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=10000) # create the paysheet paysheet = self.createPaysheet() paysheet.edit(specialise_value=model_without_ref, start_date=DateTime(2009, 1, 1), stop_date=DateTime(2009, 1, 31), price_currency_value=eur) paysheet.PaySheetTransaction_applyModel() self.stepTic() portal_type_list = ['Pay Sheet Model Line',] # if no reference, we don't care about dates sub_object_list = paysheet.getInheritedObjectValueList(portal_type_list) self.assertEquals(len(paysheet.contentValues(\ portal_type='Pay Sheet Line')), 0) # calculate the pay sheet paysheet.applyTransformation() self.stepTic() self.assertEquals(len(paysheet.contentValues( portal_type='Pay Sheet Line')), 1) # check values on the paysheet self.assertEquals(paysheet.contentValues()[0].getTotalPrice(), 10000) def stepCheckModelWithoutDateValidity(self, sequence=None, **kw): ''' If no date are defined on a model, the behavior is that this model is always valid. ''' eur = sequence.get('currency') labour = sequence.get('labour_service_output') model_without_date = self.getPortalObject().paysheet_model_module.newContent( \ specialise_value=sequence.get('business_process'), portal_type='Pay Sheet Model', variation_settings_category_list=['salary_range/france',], reference='fabien_model_without_date') model_line_2 = self.createModelLine(model_without_date) model_line_2.edit( trade_phase='payroll/france/labour', reference='model_without_date', resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=10000) # create a paysheet without date paysheet_without_date = self.createPaysheet() paysheet_without_date.edit(specialise_value=model_without_date, price_currency_value=eur) paysheet_without_date.PaySheetTransaction_applyModel() self.stepTic() portal_type_list = ['Pay Sheet Model Line',] # check the paysheet contail no lines before calculation self.assertEquals(len(paysheet_without_date.contentValues(\ portal_type='Pay Sheet Line')), 0) # calculate the pay sheet paysheet_without_date.applyTransformation() self.stepTic() self.assertEquals(len(paysheet_without_date.contentValues(\ portal_type='Pay Sheet Line')), 1) # check values on the paysheet_without_date self.assertEquals(paysheet_without_date.contentValues()[0].getTotalPrice(), 10000) # create a paysheet with dates paysheet_with_date = self.createPaysheet() paysheet_with_date.edit(specialise_value=model_without_date, start_date=DateTime(2009, 1, 1), stop_date=DateTime(2009, 1, 31), price_currency_value=eur) paysheet_with_date.PaySheetTransaction_applyModel() self.stepTic() portal_type_list = ['Pay Sheet Model Line',] # check the paysheet contains no lines before calculation self.assertEquals(len(paysheet_with_date.contentValues(\ portal_type='Pay Sheet Line')), 0) # calculate the pay sheet paysheet_with_date.applyTransformation() self.stepTic() # after calculation, paysheet contains one line, because the model applies. self.assertEquals(len(paysheet_with_date.contentValues(\ portal_type='Pay Sheet Line')), 1) self.assertEquals(paysheet_without_date.contentValues()[0].getTotalPrice(), 10000) def stepCheckModelDateValidity(self, sequence=None, **kw): ''' check that model effective_date and expiration_date are take into account. ''' eur = sequence.get('currency') labour = sequence.get('labour_service_output') model_1 = self.getPortalObject().paysheet_model_module.newContent( \ specialise_value=sequence.get('business_process'), portal_type='Pay Sheet Model', variation_settings_category_list=['salary_range/france',], reference='fabien_model_2009', effective_date=DateTime(2009, 1, 1), expiration_date=DateTime(2009, 06, 30)) model_2 = self.getPortalObject().paysheet_model_module.newContent( \ specialise_value=sequence.get('business_process'), portal_type='Pay Sheet Model', variation_settings_category_list=['salary_range/france',], reference='fabien_model_2009', effective_date=DateTime(2009, 07, 1), expiration_date=DateTime(2009, 12, 31)) model_line_3 = self.createModelLine(model_1) model_line_3.edit( trade_phase='payroll/france/labour', reference='check_model_date_validity_1', resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=20000, price=1) model_line_4 = self.createModelLine(model_2) model_line_4.edit( trade_phase='payroll/france/labour', reference='check_model_date_validity_2', resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=30000, price=1) self.stepTic() # create the paysheet paysheet = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', specialise_value=model_1, start_date=DateTime(2009, 07, 1), stop_date=DateTime(2009, 07, 31), price_currency_value=eur) paysheet.PaySheetTransaction_applyModel() self.stepTic() self.assertEquals(len(paysheet.contentValues(\ portal_type='Pay Sheet Line')), 0) # calculate the pay sheet paysheet.applyTransformation() self.stepTic() self.assertEquals(len(paysheet.contentValues(\ portal_type='Pay Sheet Line')), 1) # check values on the paysheet, if it's model_2, the total_price # should be 30000. self.assertEquals(paysheet.contentValues()[0].getTotalPrice(), 30000) def stepCheckModelVersioning(self, sequence=None, **kw): ''' check that latest version is used in case of more thant one model is matching using dates ''' eur = sequence.get('currency') # define a non effective model model_1 = self.getPortalObject().paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', variation_settings_category_list=['salary_range/france',], reference='fabien_model_2009', effective_date=DateTime(2009, 01, 1), expiration_date=DateTime(2009, 02, 28), specialise_value=sequence.get('business_process')) # define two models with same references and same dates # but different version number model_2 = self.getPortalObject().paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', variation_settings_category_list=['salary_range/france',], reference='fabien_model_2009', effective_date=DateTime(2009, 07, 1), expiration_date=DateTime(2009, 12, 31), version='002', specialise_value=sequence.get('business_process')) model_3 = self.getPortalObject().paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', variation_settings_category_list=['salary_range/france',], reference='fabien_model_2009', effective_date=DateTime(2009, 07, 1), expiration_date=DateTime(2009, 12, 31), version='001', specialise_value=sequence.get('business_process')) self.stepTic() # create the paysheet paysheet = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', specialise_value=model_1, start_date=DateTime(2009, 07, 1), stop_date=DateTime(2009, 07, 31), price_currency_value=eur) paysheet.PaySheetTransaction_applyModel() self.stepTic() # the effective model should be model_2 because of the effective date and # version number specialise_value = paysheet.getSpecialiseValue() effective_model = specialise_value.getEffectiveModel(\ start_date=paysheet.getStartDate(), stop_date=paysheet.getStopDate()) self.assertEquals(effective_model, model_2) # check the effective model tree list effective_value_list = specialise_value.findEffectiveSpecialiseValueList(\ context=specialise_value, start_date=paysheet.getStartDate(), stop_date=paysheet.getStopDate()) self.assertEquals(effective_value_list, [model_2]) def stepCreateModelLineZeroPrice(self, sequence=None, **kw): '''Test the creation of lines when the price is set to zero: the line should not be created.''' model = sequence.get('model') labour = sequence.get('labour_service_output') line = model.newContent( id='line', portal_type='Pay Sheet Model Line', resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=5, price=0) def stepComplexModelInheritanceScheme(self, sequence=None, **kw): ''' check inheritance and effective model with a more complex inheritance tree # the inheritance tree look like this : model_employee (model_1, 01/01/09, 28/02/09) ; (model_2, 01/07/09, 31/12/09) ; (model_3, 01/07/09, 31/12/09) | | | model_company (model_4, 01/07/09, 31/12/09), (model_5, 01/07/09, 31/12/09) | | | model_company (model_6, 01/07/09, 31/12/09), (model_7, 01/07/09, 31/12/09) ''' eur = sequence.get('currency') labour = sequence.get('labour_service_output') paysheet_model_module = self.getPortalObject().paysheet_model_module # define a non effective model model_1 = paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', specialise_value=sequence.get('business_process'), reference='fabien_model_2009', effective_date=DateTime(2009, 01, 1), expiration_date=DateTime(2009, 02, 28)) model_line_1 = self.createModelLine(model_1) model_line_1.edit( resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=10000) # define two models with same references and same dates # but different version number model_2 = paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', specialise_value=sequence.get('business_process'), reference='fabien_model_2009', effective_date=DateTime(2009, 07, 1), expiration_date=DateTime(2009, 12, 31), version='002') model_line_2 = self.createModelLine(model_2) model_line_2.edit( resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=20000) model_3 = paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', specialise_value=sequence.get('business_process'), reference='fabien_model_2009', effective_date=DateTime(2009, 07, 1), expiration_date=DateTime(2009, 12, 31), version='001') model_line_3 = self.createModelLine(model_3) model_line_3.edit( resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=30000) # define two models with same references and same dates # but different version number model_4 = paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', specialise_value=sequence.get('business_process'), reference='fabien_model_level_2_2009', effective_date=DateTime(2009, 01, 1), expiration_date=DateTime(2009, 06, 30), version='002') model_line_4 = self.createModelLine(model_4) model_line_4.edit( resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=40000) model_5 = paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', specialise_value=sequence.get('business_process'), reference='fabien_model_level_2_2009', effective_date=DateTime(2009, 07, 1), expiration_date=DateTime(2009, 12, 31), version='001') model_line_5 = self.createModelLine(model_5) model_line_5.edit( resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=50000) # third level : define two models with same references and same dates # but different version number model_6 = paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', specialise_value=sequence.get('business_process'), reference='fabien_model_level_3_2009', effective_date=DateTime(2009, 01, 1), expiration_date=DateTime(2009, 06, 30), version='002') model_line_6 = self.createModelLine(model_6) model_line_6.edit( resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=60000) model_7 = paysheet_model_module.newContent( \ portal_type='Pay Sheet Model', specialise_value=sequence.get('business_process'), reference='fabien_model_level_3_2009', effective_date=DateTime(2009, 07, 1), expiration_date=DateTime(2009, 12, 31), version='001') model_line_7 = self.createModelLine(model_7) model_line_7.edit( resource_value=labour, base_contribution_list=['base_amount/base_salary', 'base_amount/gross_salary'], quantity=70000) self.stepTic() # create the paysheet paysheet = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', specialise_value=model_1, start_date=DateTime(2009, 07, 1), stop_date=DateTime(2009, 07, 31), price_currency_value=eur) specialise_value = paysheet.getSpecialiseValue() # design some heritance trees, and check them: model_1.setSpecialiseValue(model_4) model_4.setSpecialiseValue(model_6) paysheet.PaySheetTransaction_applyModel() self.assertEquals(specialise_value.findSpecialiseValueList(context=paysheet), [model_1, model_4, model_6]) self.assertEquals(specialise_value.findEffectiveSpecialiseValueList(\ context=paysheet, start_date=paysheet.getStartDate(), stop_date=paysheet.getStopDate()), [model_2,]) model_1.setSpecialiseValue(None) model_2.setSpecialiseValue(model_5) model_5.setSpecialiseValue(model_6) paysheet.PaySheetTransaction_applyModel() self.assertEquals(specialise_value.findSpecialiseValueList(context=paysheet), [model_1,]) self.assertEquals(specialise_value.findEffectiveSpecialiseValueList(\ context=paysheet, start_date=paysheet.getStartDate(), stop_date=paysheet.getStopDate()), [model_2, model_5, model_7]) model_3.setSpecialiseValue(model_5) model_5.setSpecialiseValue(model_6) paysheet.PaySheetTransaction_applyModel() self.assertEquals(specialise_value.findSpecialiseValueList(context=paysheet), [model_1,]) self.assertEquals(specialise_value.findEffectiveSpecialiseValueList(\ context=paysheet, start_date=paysheet.getStartDate(), stop_date=paysheet.getStopDate()), [model_2, model_5, model_7]) def stepCheckPropertiesAreCopiedFromModelLineToPaySheetLine(self, sequence=None, **kw): model = sequence.get('model') paysheet = sequence.get('paysheet') property_list = ('title', 'description', 'int_index') for model_line in model.contentValues(portal_type='Pay Sheet Model Line'): model_line_resource = model_line.getResource() line_found = False for paysheet_line in paysheet.contentValues(portal_type='Pay Sheet Line'): if paysheet_line.getResource() == model_line_resource: line_found = True for prop in property_list: prop_from_model_line = getattr(model_line, prop, None) # check a value is set on the model line self.assertNotEquals(prop_from_model_line, None) prop_from_paysheet_line = getattr(paysheet_line, prop, None) # check the property is the same on model_line and paysheet_line self.assertEquals(prop_from_model_line, prop_from_paysheet_line) break # check that for each model line, we foud a corresponding paysheet_line self.assertEquals(line_found, True) def stepSetProperiesOnModelLines(self, sequence=None, **kw): model = sequence.get('model') index = 0 for model_line in model.contentValues(portal_type='Pay Sheet Model Line'): model_line.setTitle('Model line title %s' % index) model_line.setDescription('Model line description %s' % index) model_line.setIntIndex(index) index += 1 class TestPayroll(TestPayrollMixin): def test_modelGetCell(self): ''' Model objects have a overload method called getCell. This method first call the XMLMatrix.getCell and if the cell is not found, call getCell method in all it's inherited model until the cell is found or the cell have been searched on all inherited models. TODO : Currently, the method use a Depth-First Search algorithm, it will be better to use Breadth-First Search one. more about this on : - http://en.wikipedia.org/wiki/Breadth-first_search - http://en.wikipedia.org/wiki/Depth-first_search ''' sequence_list = SequenceList() sequence_string = """ CreateModelTree Tic CheckgetCellResults """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_applyModelSetCategories(self): ''' check that when the model is set on the Pay Sheet Transaction, properties like source, destination, currency, ... and sub-object like annotation_line are copied from the model to the Pay Sheet Transaction ''' sequence_list = SequenceList() sequence_string = """ CreateUrssafService CreateLabourService CreateEmployer CreateEmployee CreateBasicModel Tic CreatePriceCurrency ModelSetCategories CreateBasicPaysheet PaysheetSetModelAndApplyIt CheckCategoriesOnPaySheet """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_applyModelTwice(self): ''' apply model twice does not copy subdocument twice ''' sequence_list = SequenceList() sequence_string = """ CreateUrssafService CreateLabourService CreateEmployer CreateEmployee CreateBasicModel Tic CreatePriceCurrency ModelSetCategories CreateBasicPaysheet CheckPaysheetContainNoAnnotationLine CheckPaysheetContainNoPaymentCondition PaysheetSetModelAndApplyIt CheckPaysheetContainOneAnnotationLine CheckPaysheetContainOnePaymentCondition PaysheetSetModelAndApplyIt CheckPaysheetContainOneAnnotationLine CheckPaysheetContainOnePaymentCondition """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_checkConsistency(self): ''' minimal test for checkConsistency on a Pay Sheet Transaction and it's subdocuments (may have to be updated when we'll add more constraints). ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CheckPaysheetConsistency CheckModelConsistency CheckServiceConsistency """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_basicPaySheetCalculation(self): ''' test applyTransformation method. It should create new movements ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetLineAmounts CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineAmounts """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_intermediateLines(self): ''' Intermediate lines are paysheet model lines usefull to calcul, but we don't want to have on paysheet. So a checkbox on paysheet model lines permit to create it or not (created by default) ''' sequence_list = SequenceList() sequence_string = """ CreateUrssafService CreateLabourService CreateEmployer CreateEmployee CreateBasicModel Tic ModelCreateIntermediateModelLine ModelCreateAppliedOnTaxModelLine IntermediateModelLineCreateMovements AppliedOnTaxModelLineCreateMovements CreateBasicPaysheet PaysheetCreateLabourPaySheetLine """ + self.BUSINESS_PATH_CREATION_SEQUENCE_STRING + """ PaysheetApplyTransformation Tic CheckPaysheetIntermediateLines """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelLineInPaysheet(self): ''' Put a Pay Sheet Model Line in Pay Sheet Transaction. This line will be like editable line ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CreateOldAgeInsuranaceService PaysheetCreateModelLine PaysheetModelLineCreateMovements CheckUpdateAggregatedAmountListReturnWithModelLineOnPaysheet PaysheetApplyTransformation Tic CheckPaysheetLineAreCreatedWithModelLineOnPaysheet CheckPaysheetLineFromModelLineAmounts CheckUpdateAggregatedAmountListReturnNothing """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_updateModifyMovements(self): ''' Calculate the paySheet using a model, modify one value in the model and check that updateAggregatedAmount return nothing but modifed movements that need to be modified ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetLineAmounts CheckUpdateAggregatedAmountListReturnNothing ModelModifyUrssafModelLine CheckUpdateAggregatedAmountListReturnNothing PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetLineNewAmountsAfterUpdate CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineNewAmountsAfterUpdate """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_updateAddMovements(self): ''' Calculate the paySheet using a model, add a model line in the model and check that updateAggregatedAmount add the movements corresponding to this model_line ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetLineAmounts CheckUpdateAggregatedAmountListReturnNothing CreateSicknessInsuranceService ModelCreateSicknessInsuranceModelLine SicknessInsuranceModelLineCreateMovements CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreatedUsingWith3Lines CheckPaysheetLineAmountsWithSicknessInsuranceAndUrssaf CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineAmountsWithSicknessInsuranceAndUrssaf """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_updateRemoveMovements(self): ''' Calculate the paySheet using a model, delete a model line in the model and check that updateAggregatedAmount remove the movements corresponding to this model_line ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetLineAmounts CheckUpdateAggregatedAmountListReturnNothing ModelDelUrssafModelLine CheckUpdateAggregatedAmountListReturnAfterRemoveLine PaysheetApplyTransformation Tic CheckThereIsOnlyOnePaysheetLine CheckPaysheetLineLabourAmountOnly CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineLabourAmountOnly """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelLineOverLoad(self): ''' Check it's possible to overload a model line from the model tree by having a model line with the same reference in the paysheet. ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ PaysheetCreateUrssafModelLine PaysheetUrssafModelLineCreateMovements CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetModelLineOverLoadAmounts CheckUpdateAggregatedAmountListReturnNothing """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_sourceSectionIsSetOnMovements(self): ''' check that after apply transformation, source section is set on movment (using Business Process) ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ PaysheetApplyTransformation Tic CheckSourceSectionOnMovements """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_sliceOnModelLine(self): ''' It's possible to define some slices on model, and use it on model lines. Check that works and that after appy transformation, amounts are goods ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CreateUrssafService CreateLabourService CreateEmployer CreateEmployee CreateModelWithSlices Tic ModelCreateUrssafModelLineWithSlices Tic UrssafModelLineWithSlicesCreateMovements CreateBasicPaysheet PaysheetCreateLabourPaySheetLine """ + self.BUSINESS_PATH_CREATION_SEQUENCE_STRING + """ CheckUpdateAggregatedAmountListReturnUsingSlices PaysheetApplyTransformation Tic CheckPaysheetLineAreCreatedUsingSlices CheckPaysheetLineAmountsUsingSlices CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineAmountsUsingSlices """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_complexSliceOnModelLine(self): ''' Check if there is only slice_200_to_400 (without previous slice_0_to_200), amount paid for this tax are correct. ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CreateUrssafService CreateLabourService CreateEmployer CreateEmployee CreateModelWithSlices Tic ModelCreateUrssafModelLineWithComplexSlices Tic UrssafModelLineWithComplexSlicesCreateMovements CreateBasicPaysheet PaysheetCreateLabourPaySheetLine """ + self.BUSINESS_PATH_CREATION_SEQUENCE_STRING + """ CheckUpdateAggregatedAmountListReturnUsingComplexSlices PaysheetApplyTransformation Tic CheckPaysheetLineAreCreatedUsingComplexSlices CheckPaysheetLineAmountsUsingComplexSlices CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineAmountsUsingComplexSlices """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelLineWithNonePrice(self): ''' test the creation of lines when the price is not set, but only the quantity. This means that no ratio is applied on this line. ''' sequence_list = SequenceList() sequence_string = """ CreateUrssafService CreateLabourService CreateEmployer CreateEmployee CreatePriceCurrency CreateBasicModel Tic ModelCreateUrssafModelLine UrssafModelLineCreateMovementsWithQuantityOnly CreateBasicPaysheet PaysheetCreateLabourPaySheetLine """ + self.BUSINESS_PATH_CREATION_SEQUENCE_STRING + """ CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetLineAmountsWithQuantityOnly CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineAmountsWithQuantityOnly """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelLineWithZeroPrice(self): '''Test the creation of lines when the price is set to zero: the line should not be created.''' sequence_list = SequenceList() sequence_string = """ CreateLabourOutputService CreateEmployer CreateEmployee CreatePriceCurrency CreateBasicModel Tic CreateModelLineZeroPrice CreateBasicPaysheet """ + self.BUSINESS_PATH_CREATION_SEQUENCE_STRING + """ PaysheetApplyTransformation Tic CheckNoPaysheetLineAreCreated """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_predicateOnModelLine(self): ''' Check predicates can be used on model lines to select a line or not. 1 - employee have married marital status so Sickness Insurance tax should be applied, and Old age insurance should not be 2 - employee marital status is changed to single. So after re-apply the transformation, Sickness Insurance tax sould not be applied (and it's movements should be removed) but Old age insurance should be applied (and two movements should be created). ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CreateOldAgeInsuranaceService ModelCreateOldAgeInsuranceModelLine OldAgeInsuranceModelLineCreateMovements AddPredicateOnOldAgeInsuranceModelLineForSinglePerson CreateSicknessInsuranceService ModelCreateSicknessInsuranceModelLine SicknessInsuranceModelLineCreateMovements AddPredicateOnSicknessInsuranceModelLineForMarriedPerson SetMaritalStatusMarriedOnEmployee CheckUpdateAggregatedAmountListReturnUsingPredicate PaysheetApplyTransformation Tic CheckPaysheetLineAreCreatedUsingWith3Lines CheckPaysheetLineAmountsWithSicknessInsuranceAndUrssaf CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineAmountsWithSicknessInsuranceAndUrssaf SetMaritalStatusSingleOnEmployee CheckUpdateAggregatedAmountListReturnAfterChangePredicate PaysheetApplyTransformation Tic CheckPaysheetLineAreCreatedUsingWith3Lines CheckPaysheetLineAmountsWithOldAgeInsuranceAndUrssaf CheckUpdateAggregatedAmountListReturnNothing """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_paySheetCalculationWithBonus(self): ''' add one more line in the paysheet that will not be hour count and rate (like the salary) but just a normal amount. Check applyTransformation method result. It should create new movements applied on the slary + the bonnus ''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ CreateBonusService PaysheetCreateBonusPaySheetLine PaysheetCreateBonusPaySheetLineMovements CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreatedUsingBonus CheckPaysheetLineWithBonusAmounts CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineWithBonusAmounts """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelSubObjectInheritance(self): ''' check that a model can inherite some datas from another the ineritance rules are the following : - a DATA could be a model_line, annotation_line, ratio_line - a model_line, annotation_line and a ratio_line have a REFERENCE - a model can have some DATA's - a model can inherite from another, that's mean : o At the calculation step, each DATA of the parent model will be checked : the DATA with a REFERENCE that's already in the child model will not entered in the calcul. The other will. o This will be repeated on each parent model and on each parent of the parent model,... until there is no parent model to inherite ''' sequence_list = SequenceList() sequence_string = """ CreateModelTree ModelTreeAddAnnotationLines CheckInheritanceModelReferenceDict """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_PaySheetTransaction_getMovementList(self): ''' PaySheetTransaction_getMovementList is a script used by the listbox to display information about lines in the Paysheet. Just test the return of it. ''' sequence_list = SequenceList() sequence_string = """ CreateUrssafService CreateBasicPaysheet CheckPaySheetTransaction_getMovementListReturn """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_PayrollTaxesReport(self): currency_module = self.getCurrencyModule() if not hasattr(currency_module, 'EUR'): currency_module.newContent( portal_type = 'Currency', reference = "EUR", id = "EUR", base_unit_quantity=0.001 ) eur = self.portal.currency_module.EUR service = self.portal.service_module.newContent( portal_type='Service', title='PS1', variation_base_category_list=('tax_category',), variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) employer = self.portal.organisation_module.newContent( portal_type='Organisation', title='Employer', price_currency_value=eur, group_value=self.portal.portal_categories.group.demo_group) employee1 = self.portal.person_module.newContent( portal_type='Person', title='Employee One', career_reference='E1', career_subordination_value=employer) employee2 = self.portal.person_module.newContent( portal_type='Person', title='Employee Two', career_reference='E2', career_subordination_value=employer) provider = self.portal.organisation_module.newContent( portal_type='Organisation', title='Service Provider') other_provider = self.portal.organisation_module.newContent( portal_type='Organisation', title='Another Service Provider') ps1 = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', title='Employee 1', destination_section_value=employer, source_section_value=employee1, start_date=DateTime(2006, 1, 1),) line = ps1.newContent(portal_type='Pay Sheet Line', resource_value=service, source_section_value=provider, # (destination is set by PaySheetTransaction.createPaySheetLine) destination_value=employee1, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=-.50, quantity=2000, tax_category='employee_share') cell_employer = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=-.40, quantity=2000, tax_category='employer_share') ps1.plan() ps2 = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', title='Employee 2', destination_section_value=employer, source_section_value=employee2, start_date=DateTime(2006, 1, 1),) line = ps2.newContent(portal_type='Pay Sheet Line', resource_value=service, source_section_value=provider, destination_value=employee2, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=-.50, quantity=3000, tax_category='employee_share') cell_employer = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=-.40, quantity=3000, tax_category='employer_share') other_line = ps2.newContent(portal_type='Pay Sheet Line', resource_value=service, destination_value=employee2, source_section_value=other_provider, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = other_line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=-.46, quantity=2998, tax_category='employee_share') cell_employer = other_line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=-.42, quantity=2998, tax_category='employer_share') self.stepTic() # AccountingTransactionModule_getPaySheetMovementMirrorSectionItemList is # used in the report dialog to display possible organisations. self.assertEquals( [('', ''), (other_provider.getTitle(), other_provider.getRelativeUrl()), (provider.getTitle(), provider.getRelativeUrl())], self.portal.accounting_module\ .AccountingTransactionModule_getPaySheetMovementMirrorSectionItemList()) # set request variables and render request_form = self.portal.REQUEST request_form['at_date'] = DateTime(2006, 2, 2) request_form['section_category'] = 'group/demo_group' request_form['simulation_state'] = ['draft', 'planned'] request_form['resource'] = service.getRelativeUrl() request_form['mirror_section'] = provider.getRelativeUrl() report_section_list = self.getReportSectionList( self.portal.accounting_module, 'AccountingTransactionModule_viewPaySheetLineReport') self.assertEquals(1, len(report_section_list)) line_list = self.getListBoxLineList(report_section_list[0]) data_line_list = [l for l in line_list if l.isDataLine()] self.assertEquals(2, len(data_line_list)) # base_unit_quantity for EUR is set to 0.001 in the created currencies, so the # precision is 3. Editable Fields will reuse this precision. precision = self.portal.REQUEST.get('precision') self.assertEquals(3, precision) self.checkLineProperties(data_line_list[0], id=1, employee_career_reference='E1', employee_title='Employee One', base=2000, employee_share=2000 * .50, employer_share=2000 * .40, total=(2000 * .50 + 2000 * .40)) self.checkLineProperties(data_line_list[1], id=2, employee_career_reference='E2', employee_title='Employee Two', base=3000, employee_share=3000 * .50, employer_share=3000 * .40, total=(3000 * .50 + 3000 * .40)) # stat line self.checkLineProperties(line_list[-1], base=3000 + 2000, employee_share=(3000 + 2000) * .50, employer_share=(3000 + 2000) * .40, total=((3000 + 2000) * .50 + (3000 + 2000) * .40)) def test_PayrollTaxesReportDifferentSalaryRange(self): currency_module = self.getCurrencyModule() if not hasattr(currency_module, 'EUR'): currency_module.newContent( portal_type = 'Currency', reference = "EUR", id = "EUR", base_unit_quantity=0.001 ) eur = self.portal.currency_module.EUR service = self.portal.service_module.newContent( portal_type='Service', title='PS1', variation_base_category_list=('tax_category', 'salary_range'), variation_category_list=('tax_category/employee_share', 'tax_category/employer_share', 'salary_range/france/slice_a', 'salary_range/france/slice_b')) employer = self.portal.organisation_module.newContent( portal_type='Organisation', title='Employer', price_currency_value=eur, group_value=self.portal.portal_categories.group.demo_group) employee1 = self.portal.person_module.newContent( portal_type='Person', title='Employee One', career_reference='E1', career_subordination_value=employer) employee2 = self.portal.person_module.newContent( portal_type='Person', title='Employee Two', career_reference='E2', career_subordination_value=employer) provider = self.portal.organisation_module.newContent( portal_type='Organisation', title='Service Provider') other_provider = self.portal.organisation_module.newContent( portal_type='Organisation', title='Another Service Provider') ps1 = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', title='Employee 1', destination_section_value=employer, source_section_value=employee1, start_date=DateTime(2006, 1, 1),) line = ps1.newContent(portal_type='Pay Sheet Line', resource_value=service, source_section_value=provider, # (destination is set by PaySheetTransaction.createPaySheetLine) destination_value=employee1, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share', 'salary_range/france/slice_a', 'salary_range/france/slice_b')) cell_employee_a = line.newCell('tax_category/employee_share', 'salary_range/france/slice_a', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee_a.edit(price=-.50, quantity=1000, tax_category='employee_share', salary_range='france/slice_a') cell_employee_b = line.newCell('tax_category/employee_share', 'salary_range/france/slice_b', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee_b.edit(price=-.20, quantity=500, tax_category='employee_share', salary_range='france/slice_b') cell_employer_a = line.newCell('tax_category/employer_share', 'salary_range/france/slice_a', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer_a.edit(price=-.40, quantity=1000, tax_category='employer_share', salary_range='france/slice_a') cell_employer_b = line.newCell('tax_category/employer_share', 'salary_range/france/slice_b', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer_b.edit(price=-.32, quantity=500, tax_category='employer_share', salary_range='france/slice_b') ps1.plan() ps2 = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', title='Employee 2', destination_section_value=employer, source_section_value=employee2, start_date=DateTime(2006, 1, 1),) line = ps2.newContent(portal_type='Pay Sheet Line', resource_value=service, source_section_value=provider, destination_value=employee2, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share', 'salary_range/france/slice_a', 'salary_range/france/slice_b')) cell_employee_a = line.newCell('tax_category/employee_share', 'salary_range/france/slice_a', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee_a.edit(price=-.50, quantity=1000, salary_range='france/slice_a', tax_category='employee_share') cell_employee_b = line.newCell('tax_category/employee_share', 'salary_range/france/slice_b', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee_b.edit(price=-.20, quantity=3000, salary_range='france/slice_b', tax_category='employee_share') cell_employer_a = line.newCell('tax_category/employer_share', 'salary_range/france/slice_a', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer_a.edit(price=-.40, quantity=1000, salary_range='france/slice_a', tax_category='employer_share') cell_employer_b = line.newCell('tax_category/employer_share', 'salary_range/france/slice_b', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer_b.edit(price=-.32, quantity=3000, salary_range='france/slice_b', tax_category='employer_share') self.stepTic() # set request variables and render request_form = self.portal.REQUEST request_form['at_date'] = DateTime(2006, 2, 2) request_form['section_category'] = 'group/demo_group' request_form['simulation_state'] = ['draft', 'planned'] request_form['resource'] = service.getRelativeUrl() request_form['mirror_section'] = provider.getRelativeUrl() report_section_list = self.getReportSectionList( self.portal.accounting_module, 'AccountingTransactionModule_viewPaySheetLineReport') self.assertEquals(1, len(report_section_list)) line_list = self.getListBoxLineList(report_section_list[0]) data_line_list = [l for l in line_list if l.isDataLine()] self.assertEquals(6, len(data_line_list)) self.checkLineProperties(data_line_list[0], id=1, employee_career_reference='E1', employee_title='Employee One', base=1000, employee_share=1000 * .50, employer_share=1000 * .40, total=(1000 * .50 + 1000 * .40)) self.checkLineProperties(data_line_list[1], id=2, employee_career_reference='E2', employee_title='Employee Two', base=1000, employee_share=1000 * .50, employer_share=1000 * .40, total=(1000 * .50 + 1000 * .40)) self.checkLineProperties(data_line_list[2], employee_title='Total Slice A', base=2000, employee_share=2000 * .50, employer_share=2000 * .40, #total=(2000 * .50 + 2000 * .40) ) self.checkLineProperties(data_line_list[3], id=3, employee_career_reference='E1', employee_title='Employee One', base=500, employee_share=500 * .20, employer_share=500 * .32, total=(500 * .20 + 500 * .32)) self.checkLineProperties(data_line_list[4], id=4, employee_career_reference='E2', employee_title='Employee Two', base=3000, employee_share=3000 * .20, employer_share=3000 * .32, total=(3000 * .20 + 3000 * .32)) self.checkLineProperties(data_line_list[5], employee_title='Total Slice B', base=3500, employee_share=3500 * .20, employer_share=3500 * .32, #total=(3500 * .20 + 3500 * .32), ) # stat line self.checkLineProperties(line_list[-1], base=2000 + 3500, employee_share=(2000 * .50 + 3500 * .20), employer_share=(2000 * .40 + 3500 * .32), total=((2000 * .50 + 3500 * .20) + (2000 * .40 + 3500 * .32))) def test_NetSalaryReport(self): currency_module = self.getCurrencyModule() if not hasattr(currency_module, 'EUR'): currency_module.newContent( portal_type = 'Currency', reference = "EUR", id = "EUR", base_unit_quantity=0.001 ) eur = self.portal.currency_module.EUR salary_service = self.portal.service_module.newContent( portal_type='Service', title='Gross Salary', variation_base_category_list=('tax_category',), variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) service = self.portal.service_module.newContent( portal_type='Service', title='PS1', variation_base_category_list=('tax_category',), variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) employer = self.portal.organisation_module.newContent( portal_type='Organisation', title='Employer', price_currency_value=eur, group_value=self.portal.portal_categories.group.demo_group) employee1 = self.portal.person_module.newContent( portal_type='Person', title='Employee One', career_reference='E1', career_subordination_value=employer) employee1_ba = employee1.newContent(portal_type='Bank Account', title='Bank 1') employee2 = self.portal.person_module.newContent( portal_type='Person', title='Employee Two', career_reference='E2', career_subordination_value=employer) employee2_ba = employee2.newContent(portal_type='Bank Account', title='Bank 2') provider = self.portal.organisation_module.newContent( portal_type='Organisation', title='Service Provider') other_provider = self.portal.organisation_module.newContent( portal_type='Organisation', title='Another Service Provider') ps1 = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', title='Employee 1', destination_section_value=employer, source_section_value=employee1, payment_condition_source_payment_value=employee1_ba, start_date=DateTime(2006, 1, 1),) line = ps1.newContent(portal_type='Pay Sheet Line', resource_value=salary_service, destination_value=employee1, base_contribution_list=['base_amount/net_salary',], variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=1, quantity=2000, tax_category='employee_share') line = ps1.newContent(portal_type='Pay Sheet Line', resource_value=service, source_section_value=provider, destination_value=employee1, base_contribution_list=['base_amount/net_salary',], variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=-.50, quantity=2000, tax_category='employee_share') cell_employer = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=-.40, quantity=2000, tax_category='employer_share') ps1.plan() ps2 = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', title='Employee 2', destination_section_value=employer, source_section_value=employee2, payment_condition_source_payment_value=employee2_ba, start_date=DateTime(2006, 1, 1),) line = ps2.newContent(portal_type='Pay Sheet Line', resource_value=salary_service, destination_value=employee2, base_contribution_list=['base_amount/net_salary',], variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=1, quantity=3000, tax_category='employee_share') line = ps2.newContent(portal_type='Pay Sheet Line', resource_value=service, source_section_value=provider, destination_value=employee2, base_contribution_list=['base_amount/net_salary',], variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=-.50, quantity=3000, tax_category='employee_share') cell_employer = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=-.40, quantity=3000, tax_category='employer_share') self.stepTic() # set request variables and render request_form = self.portal.REQUEST request_form['at_date'] = DateTime(2006, 2, 2) request_form['section_category'] = 'group/demo_group' request_form['simulation_state'] = ['draft', 'planned'] report_section_list = self.getReportSectionList( self.portal.accounting_module, 'AccountingTransactionModule_viewNetSalaryReport') self.assertEquals(1, len(report_section_list)) line_list = self.getListBoxLineList(report_section_list[0]) data_line_list = [l for l in line_list if l.isDataLine()] self.assertEquals(2, len(data_line_list)) # base_unit_quantity for EUR is set to 0.001 in the created currencies, so the # precision is 3. Editable Fields will reuse this precision. precision = self.portal.REQUEST.get('precision') self.assertEquals(3, precision) self.checkLineProperties(data_line_list[0], employee_career_reference='E1', employee_title='Employee One', employee_bank_account='Bank 1', total_price=2000 - (2000 * .5),) self.checkLineProperties(data_line_list[1], employee_career_reference='E2', employee_title='Employee Two', employee_bank_account='Bank 2', total_price=3000 - (3000 * .5),) # stat line self.checkLineProperties( line_list[-1], total_price=3000 + 2000 - (2000 * .5) - (3000 * .5)) def test_AccountingLineGeneration(self): currency_module = self.getCurrencyModule() if not hasattr(currency_module, 'EUR'): currency_module.newContent( portal_type = 'Currency', reference = "EUR", id = "EUR", base_unit_quantity=0.001 ) # create services base_salary = self.portal.service_module.newContent( portal_type='Service', title='Base Salary', product_line='base_salary', variation_base_category_list=('tax_category',), variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) bonus = self.portal.service_module.newContent( portal_type='Service', title='Bonus', product_line='base_salary', variation_base_category_list=('tax_category',), variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) deductions = self.portal.service_module.newContent( portal_type='Service', title='Deductions', product_line='base_salary', variation_base_category_list=('tax_category',), variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) tax1 = self.portal.service_module.newContent( portal_type='Service', title='Tax1', product_line='payroll_tax_1', variation_base_category_list=('tax_category',), variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) # create accounts account_payroll_wages_expense = self.portal.account_module.newContent( portal_type='Account', title='Payroll Wages (expense)', account_type='expense',) account_payroll_taxes_expense = self.portal.account_module.newContent( portal_type='Account', title='Payroll Taxes (expense)', account_type='expense',) account_net_wages = self.portal.account_module.newContent( portal_type='Account', title='Net Wages', account_type='liability/payable',) account_payroll_taxes = self.portal.account_module.newContent( portal_type='Account', title='Payroll Taxes', account_type='liability/payable',) # create an invoice transaction rule for pay sheets. rule = self.portal.portal_rules.newContent( portal_type='Invoice Transaction Rule', title='Rule for PaySheet Accounting', reference='paysheet_transaction_rule', test_method_id='SimulationMovement_testInvoiceTransactionRule') rule.newContent(portal_type='Predicate', title='Employee Share', string_index='tax_category', int_index=1, membership_criterion_base_category_list=('tax_category',), membership_criterion_category_list=('tax_category/employee_share',)) rule.newContent(portal_type='Predicate', title='Employer Share', string_index='tax_category', int_index=2, membership_criterion_base_category_list=('tax_category',), membership_criterion_category_list=('tax_category/employer_share',)) rule.newContent(portal_type='Predicate', title='Base Salary', string_index='service', int_index=1, membership_criterion_base_category_list=('product_line',), membership_criterion_category_list=('product_line/base_salary',)) rule.newContent(portal_type='Predicate', title='Payroll Tax 1', string_index='service', int_index=2, membership_criterion_base_category_list=('product_line',), membership_criterion_category_list=('product_line/payroll_tax_1',)) self.stepTic() cell_list = rule.contentValues(portal_type='Accounting Rule Cell') self.assertEquals(4, len(cell_list)) employee_base_salary = rule._getOb('movement_0_0') self.assertEquals('Employee Share * Base Salary', employee_base_salary.getTitle()) employee_base_salary.newContent( portal_type='Accounting Rule Cell Line', destination_debit=1, destination_value=account_payroll_wages_expense) employee_base_salary.newContent( portal_type='Accounting Rule Cell Line', destination_credit=1, destination_value=account_net_wages) employer_tax = rule._getOb('movement_1_1') self.assertEquals('Employer Share * Payroll Tax 1', employer_tax.getTitle()) employer_tax.newContent( portal_type='Accounting Rule Cell Line', destination_debit=1, destination_value=account_payroll_taxes) employer_tax.newContent( portal_type='Accounting Rule Cell Line', destination_credit=1, destination_value=account_payroll_taxes_expense) employee_tax = rule._getOb('movement_0_1') self.assertEquals('Employee Share * Payroll Tax 1', employee_tax.getTitle()) employee_tax.newContent( portal_type='Accounting Rule Cell Line', destination_debit=1, destination_value=account_payroll_taxes) employee_tax.newContent( portal_type='Accounting Rule Cell Line', destination_credit=1, generate_prevision_script_id=\ 'SimulationMovement_generatePrevisionForEmployeeSharePaySheetMovement', destination_value=account_net_wages) rule.validate() # create a pay sheet eur = self.portal.currency_module.EUR employer = self.portal.organisation_module.newContent( portal_type='Organisation', title='Employer', price_currency_value=eur, group_value=self.portal.portal_categories.group.demo_group) employee = self.portal.person_module.newContent( portal_type='Person', title='Employee', career_reference='E1', career_subordination_value=employer) provider = self.portal.organisation_module.newContent( portal_type='Organisation', title='Service Provider') ps = self.portal.accounting_module.newContent( portal_type='Pay Sheet Transaction', price_currency_value=eur, resource_value=eur, title='Employee 1', destination_section_value=employer, source_section_value=employee, start_date=DateTime(2006, 1, 1),) # base salary = 2000 line = ps.newContent(portal_type='Pay Sheet Line', title='Base salary', resource_value=base_salary, destination_value=employee, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=1, quantity=2000, tax_category='employee_share') cell_employer = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=1, quantity=2000, tax_category='employer_share') # base_salary += 100 (bonus) line = ps.newContent(portal_type='Pay Sheet Line', title='Bonus', resource_value=bonus, destination_value=employee, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=1, quantity=100, tax_category='employee_share') cell_employer = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=1, quantity=100, tax_category='employer_share') # base_salary -= 50 (deductions) => base_salary == 2050 line = ps.newContent(portal_type='Pay Sheet Line', title='Deduction', resource_value=deductions, destination_value=employee, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=-1, quantity=50, tax_category='employee_share') cell_employer = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=-1, quantity=50, tax_category='employer_share') # tax1 = 10% for employee ( 205 ) # 20% for employer ( 410 ) line = ps.newContent(portal_type='Pay Sheet Line', title='Tax 1', resource_value=tax1, source_section_value=provider, destination_value=employee, variation_category_list=('tax_category/employee_share', 'tax_category/employer_share')) cell_employee = line.newCell('tax_category/employee_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employee.edit(price=-.1, quantity=2050, tax_category='employee_share') cell_employer = line.newCell('tax_category/employer_share', portal_type='Pay Sheet Cell', base_id='movement', mapped_value_property_list=('price', 'quantity'),) cell_employer.edit(price=-.2, quantity=2050, tax_category='employer_share') ps.plan() self.stepTic() related_applied_rule = ps.getCausalityRelatedValue( portal_type='Applied Rule') self.assertNotEquals(related_applied_rule, None) # build accounting lines ps.confirm() ps.start() self.stepTic() accounting_line_list = ps.contentValues( portal_type='Pay Sheet Transaction Line') self.assertEquals(len(accounting_line_list), 4) line = [l for l in accounting_line_list if l.getDestinationValue() == account_payroll_wages_expense][0] self.assertEquals(2050, line.getDestinationDebit()) self.assertEquals(employer, line.getDestinationSectionValue()) line = [l for l in accounting_line_list if l.getDestinationValue() == account_net_wages][0] self.assertEquals(2050 - 205, line.getDestinationCredit()) self.assertEquals(employer, line.getDestinationSectionValue()) self.assertEquals(employee, line.getSourceSectionValue()) line = [l for l in accounting_line_list if l.getDestinationValue() == account_payroll_taxes_expense][0] self.assertEquals(410, line.getDestinationDebit()) self.assertEquals(employer, line.getDestinationSectionValue()) line = [l for l in accounting_line_list if l.getDestinationValue() == account_payroll_taxes][0] self.assertEquals(410 + 205, line.getDestinationCredit()) self.assertEquals(employer, line.getDestinationSectionValue()) self.assertEquals(provider, line.getSourceSectionValue()) def test_modelWithoutReferenceValidity(self): ''' Check that if no REFERENCE are defined on a model, the behavior is that this model is always valid. So check a Pay Sheet Transaction Line is created after calling the calculation script ''' sequence_list = SequenceList() sequence_string = """ CreatePriceCurrency CreateLabourOutputService CreateBusinessProcess CreateBusinessPath CreateUrssafRoubaixOrganisation ModifyBusinessPathTradePhase Tic CheckModelWithoutRefValidity """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelWithoutDateValidity(self): ''' Check that if no DATE are defined on a model, the behavior is that this model is always valid. (XXX check if it's what we want) So check that a line is created after calling calculation script, even if there is no start_date or stop_date ''' sequence_list = SequenceList() sequence_string = """ CreatePriceCurrency CreateLabourOutputService CreateBusinessProcess CreateBusinessPath CreateUrssafRoubaixOrganisation ModifyBusinessPathTradePhase Tic CheckModelWithoutDateValidity """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelDateValidity(self): ''' check that model effective_date and expiration_date are take into account. ''' sequence_list = SequenceList() sequence_string = """ CreatePriceCurrency CreateLabourOutputService CreateBusinessProcess CreateBusinessPath CreateUrssafRoubaixOrganisation ModifyBusinessPathTradePhase Tic CheckModelDateValidity """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelVersioning(self): '''check that latest version is used in case of more thant one model is matching using dates ''' sequence_list = SequenceList() sequence_string = """ CreatePriceCurrency CreateBusinessProcess CreateBusinessPath CreateUrssafRoubaixOrganisation ModifyBusinessPathTradePhase Tic CheckModelVersioning """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_modelSliceInheritance(self): '''Check the slice inheritance''' base_id = 'cell' paysheet_model_module = self.getPortalObject().paysheet_model_module model_1 = paysheet_model_module.newContent( portal_type='Pay Sheet Model', variation_settings_category_list= ('salary_range/france',)) model_2 = paysheet_model_module.newContent( portal_type='Pay Sheet Model', specialise_value=model_1,) cell = model_1.newCell('salary_range/france/slice_a', portal_type='Pay Sheet Model Slice', base_id='cell') cell.setQuantityRangeMin(1) cell.setQuantityRangeMax(2) # model 2 gets cell values from model 1 (see test_07_model_getCell) self.assertEquals(1, model_2.getCell('salary_range/france/slice_a').getQuantityRangeMin()) self.assertEquals(2, model_2.getCell('salary_range/france/slice_a').getQuantityRangeMax()) # model 2 can override values model_2.edit(variation_settings_category_list=('salary_range/france',)) cell = model_2.newCell('salary_range/france/slice_a', portal_type='Pay Sheet Model Slice', base_id='cell') cell.setQuantityRangeMin(3) cell.setQuantityRangeMax(4) self.assertEquals(3, model_2.getCell('salary_range/france/slice_a').getQuantityRangeMin()) self.assertEquals(4, model_2.getCell('salary_range/france/slice_a').getQuantityRangeMax()) # when unsetting variation settings category on this model will acquire # again values from specialised model model_2.edit(variation_settings_category_list=()) self.assertEquals(1, model_2.getCell('salary_range/france/slice_a').getQuantityRangeMin()) self.assertEquals(2, model_2.getCell('salary_range/france/slice_a').getQuantityRangeMax()) def test_complexModelInheritanceScheme(self): '''check inheritance and effective model with a more complex inheritance tree''' sequence_list = SequenceList() sequence_string = """ CreatePriceCurrency CreateLabourOutputService Tic ComplexModelInheritanceScheme """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_updatePaysheetAfterModelModification(self): '''generate a paysheet using a model, modify the model by adding a new model line with the same resource as the first one and update the paysheet. Check the paysheet values have been updated (new line created) ''' sequence_list = SequenceList() sequence_string = ''' CreateUrssafService CreateLabourService CreateEmployer CreateEmployee CreatePriceCurrency CreateModelWithSlices Tic ModelCreateUrssafModelLine UrssafModelLineCreateMovements CreateBasicPaysheet PaysheetCreateLabourPaySheetLine Tic ''' + self.BUSINESS_PATH_CREATION_SEQUENCE_STRING +''' CheckUpdateAggregatedAmountListReturn PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetLineAmounts CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineAmounts ModelCreateUrssafModelLineWithSlices Tic UrssafModelLineWithSlicesCreateMovements Tic PaysheetApplyTransformation Tic CheckPaysheetLineAreCreatedAfterUpdateWithLinesWithSameResource CheckPaysheetLineAmountsAfterUpdateWithLinesWithSameResource CheckUpdateAggregatedAmountListReturnNothing CheckPaysheetLineAmountsAfterUpdateWithLinesWithSameResource ''' sequence_list.addSequenceString(sequence_string) sequence_list.play(self) def test_propertiesAreSetOnPaysheetLines(self): '''check porperties from model line (like description, int_index, title, ...) are copied on the paysheet lines''' sequence_list = SequenceList() sequence_string = self.COMMON_BASIC_DOCUMENT_CREATION_SEQUENCE_STRING + """ SetProperiesOnModelLines Tic PaysheetApplyTransformation Tic CheckPaysheetLineAreCreated CheckPaysheetLineAmounts CheckPropertiesAreCopiedFromModelLineToPaySheetLine """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self) import unittest def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestPayroll)) return suite