diff --git a/product/ERP5/tests/testInvoice.py b/product/ERP5/tests/testInvoice.py index a9bd755fff67abd97fc1a74e0d9f800aa6566a97..6d517ec49bac9e36afa579ad6879d161094e2c11 100644 --- a/product/ERP5/tests/testInvoice.py +++ b/product/ERP5/tests/testInvoice.py @@ -351,1015 +351,951 @@ class TestInvoiceMixin(TestPackingListMixin, self.assertEquals(movement.getStopDate(), parent_movement.getStopDate()) + def modifyPackingListState(self, transition_name, + sequence,packing_list=None): + """ calls the workflow for the packing list """ + if packing_list is None: + packing_list = sequence.get('packing_list') + packing_list.portal_workflow.doActionFor(packing_list, transition_name) + def stepSetReadyPackingList(self, sequence=None, sequence_list=None, **kw): + """ set the Packing List as Ready. This must build the invoice. """ + self.modifyPackingListState('set_ready_action', sequence=sequence) + packing_list = sequence.get('packing_list') + self.assertEquals(packing_list.getSimulationState(), 'ready') -class TestInvoice(TestInvoiceMixin): - """Test methods for sale and purchase invoice. - Subclasses must defines portal types to use. - """ - quiet = 1 - def test_invoice_transaction_line_resource(self): - """ - tests that simulation movements corresponding to accounting line have a - good resource in the simulation - """ - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource', - product_line='apparel') - currency = self.portal.currency_module.newContent( - portal_type='Currency', - title='Currency', - base_unit_quantity=0.01) - self.createInvoiceTransactionRule(currency) + def stepSetReadyNewPackingList(self, sequence=None, + sequence_list=None, **kw): + """ set the Packing List as Ready. This must build the invoice. """ + packing_list = sequence.get('new_packing_list') + self.modifyPackingListState('set_ready_action', sequence=sequence, + packing_list=packing_list) + self.assertEquals(packing_list.getSimulationState(), 'ready') - client = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Client', - price_currency= currency.getRelativeUrl(), - default_address_region=self.default_region) - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Vendor', - price_currency= currency.getRelativeUrl(), - default_address_region=self.default_region) - order = self.portal.getDefaultModule(self.order_portal_type).newContent( - portal_type=self.order_portal_type, - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client, - start_date=DateTime(2008, 1, 1), - price_currency_value=currency, - title='Order') - order_line = order.newContent(portal_type=self.order_line_portal_type, - resource_value=resource, - quantity=1, - price=2) + def stepStartPackingList(self, sequence=None, sequence_list=None, **kw): + self.modifyPackingListState('start_action', sequence=sequence) + packing_list = sequence.get('packing_list') + self.assertEquals(packing_list.getSimulationState(), 'started') - order.confirm() - transaction.commit() - self.tic() + def stepStartNewPackingList(self, sequence=None, sequence_list=None, **kw): + packing_list = sequence.get('new_packing_list') + self.modifyPackingListState('start_action', sequence=sequence, + packing_list=packing_list) + self.assertEquals(packing_list.getSimulationState(), 'started') - related_applied_rule = order.getCausalityRelatedValue( - portal_type='Applied Rule') - order_movement = related_applied_rule.contentValues()[0] - delivery_applied_rule = order_movement.contentValues()[0] - delivery_movement = delivery_applied_rule.contentValues()[0] - invoice_applied_rule = delivery_movement.contentValues()[0] - invoice_movement = invoice_applied_rule.contentValues()[0] - invoice_transaction_applied_rule = invoice_movement.contentValues()[0] - invoice_transaction_movement =\ - invoice_transaction_applied_rule.contentValues()[0] - self.assertEquals(currency, - invoice_transaction_movement.getResourceValue()) - self.assertEquals(currency, - delivery_movement.getPriceCurrencyValue()) + def stepStopPackingList(self, sequence=None, sequence_list=None, **kw): + self.modifyPackingListState('stop_action', sequence=sequence) + packing_list = sequence.get('packing_list') + self.assertEquals(packing_list.getSimulationState(), 'stopped') - - def test_modify_planned_order_invoicing_rule(self): - """ - tests that modifying a planned order affects movements from invoicing - rule - """ - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource', - product_line='apparel') - currency = self.portal.currency_module.newContent( - portal_type='Currency', - title='Currency', - base_unit_quantity=0.01) + def stepDeliverPackingList(self, sequence=None, sequence_list=None, **kw): + self.modifyPackingListState('deliver_action', sequence=sequence) + packing_list = sequence.get('packing_list') + self.assertEquals(packing_list.getSimulationState(), 'delivered') - client = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Client', - price_currency= currency.getRelativeUrl()) - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Vendor', - price_currency= currency.getRelativeUrl()) - order = self.portal.getDefaultModule(self.order_portal_type).newContent( - portal_type=self.order_portal_type, - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client, - start_date=DateTime(2008, 1, 1), - price_currency_value=currency, - title='Order') - order_line = order.newContent(portal_type=self.order_line_portal_type, - resource_value=resource, - quantity=1, - price=2) + def stepCancelPackingList(self, sequence=None, sequence_list=None, **kw): + self.modifyPackingListState('cancel_action', sequence=sequence) + packing_list = sequence.get('packing_list') + self.assertEquals(packing_list.getSimulationState(), 'cancelled') - other_entity = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Other Entity', - price_currency=currency.getRelativeUrl()) - other_project = self.portal.project_module.newContent( - portal_type='Project', - title='Other Project') - order.plan() - transaction.commit() - self.tic() - self.assertEquals('planned', order.getSimulationState()) + def modifyInvoiceState(self, transition_name, + sequence,invoice=None): + """ calls the workflow for the invoice """ + if invoice is None: + invoice = sequence.get('invoice') + invoice.portal_workflow.doActionFor(invoice, transition_name) - related_applied_rule = order.getCausalityRelatedValue( - portal_type='Applied Rule') - delivery_movement = related_applied_rule.contentValues()[0] - invoice_applied_rule = delivery_movement.contentValues()[0] - invoice_movement = invoice_applied_rule.contentValues()[0] + def stepStartInvoice(self, sequence=None, sequence_list=None, **kw): + self.modifyInvoiceState('start_action', sequence=sequence) + invoice = sequence.get('invoice') + self.assertEquals(invoice.getSimulationState(), 'started') - order_line.setSourceValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getSourceValue()) + def stepStartNewInvoice(self, sequence=None, sequence_list=None, **kw): + invoice = sequence.get('new_invoice') + self.modifyInvoiceState('start_action', sequence=sequence, + invoice=invoice) + self.assertEquals(invoice.getSimulationState(), 'started') - order_line.setDestinationValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getDestinationValue()) + def stepStopInvoice(self, sequence=None, sequence_list=None, **kw): + self.modifyInvoiceState('stop_action', sequence=sequence) + invoice = sequence.get('invoice') + self.assertEquals(invoice.getSimulationState(), 'stopped') - order_line.setSourceSectionValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getSourceSectionValue()) + def stepDeliverInvoice(self, sequence=None, sequence_list=None, **kw): + self.modifyInvoiceState('deliver_action', sequence=sequence) + invoice = sequence.get('invoice') + self.assertEquals(invoice.getSimulationState(), 'delivered') - # make sure destination_section != source_section, this might be needed by - # some rules - order_line.setSourceSectionValue(order_line.getDestinationSectionValue()) + def stepCancelInvoice(self, sequence=None, sequence_list=None, **kw): + self.modifyInvoiceState('cancel_action', sequence=sequence) + invoice = sequence.get('invoice') + self.assertEquals(invoice.getSimulationState(), 'cancelled') - order_line.setDestinationSectionValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getDestinationSectionValue()) - order_line.setSourceAdministrationValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getSourceAdministrationValue()) + def stepSwitchPackingLists(self, sequence=None, sequence_list=None, **kw): + packing_list = sequence.get('packing_list') + new_packing_list = sequence.get('new_packing_list') + #invoice = new_packing_list.getDefaultCausalityRelatedValue( + #portal_type=self.invoice_portal_type) + sequence.edit(packing_list=new_packing_list, + new_packing_list=packing_list)#, invoice=invoice) - order_line.setDestinationAdministrationValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getDestinationAdministrationValue()) + def stepSwitchInvoices(self, sequence=None, sequence_list=None, **kw): + invoice = sequence.get('invoice') + new_invoice = sequence.get('new_invoice') + sequence.edit(invoice=new_invoice, new_invoice=invoice) - order_line.setSourceDecisionValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getSourceDecisionValue()) + def stepCheckPackingListSimulation(self, sequence=None, sequence_list=None, **kw): + """ checks that simulation movements related to the packing list are OK """ + packing_list = sequence.get('packing_list') + order = sequence.get('order') + order_root_applied_rule = order.getCausalityRelatedValueList( + portal_type = 'Applied Rule')[0] + # check simulation movements from this packing list + for movement in packing_list.getMovementList() : + simulation_movement_list = movement.getOrderRelatedValueList() + self.assertNotEquals(len(simulation_movement_list), 0) + total_quantity = 0 + for simulation_movement in simulation_movement_list : + total_quantity += simulation_movement.getQuantity() + # check that those movements come from the same root applied + # rule than the order. + self.assertEquals( simulation_movement.getRootAppliedRule(), + order_root_applied_rule) + self.assertEquals(total_quantity, movement.getQuantity()) - order_line.setDestinationDecisionValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getDestinationDecisionValue()) - - order_line.setSourceProjectValue(other_project) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_project, - invoice_movement.getSourceProjectValue()) - - order_line.setDestinationProjectValue(other_project) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_project, - invoice_movement.getDestinationProjectValue()) + def stepCheckInvoiceBuilding(self, sequence=None, sequence_list=None, **kw): + """ + checks that the invoice is built with the default_invoice_builder + """ + packing_list = sequence.get('packing_list') + related_invoice_list = packing_list.getCausalityRelatedValueList( + portal_type=self.invoice_portal_type) - order_line.setSourcePaymentValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getSourcePaymentValue()) + packing_list_building_state = 'started' + packing_list_state = packing_list.getSimulationState() + if packing_list_state != packing_list_building_state : + self.assertEquals(0, len(related_invoice_list)) + else: + self.assertEquals(1, len(related_invoice_list)) - order_line.setDestinationPaymentValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getDestinationPaymentValue()) + invoice = related_invoice_list[0].getObject() + self.failUnless(invoice is not None) + # Invoices created by Delivery Builder are in confirmed state + self.assertEquals(invoice.getSimulationState(), 'confirmed') - order_line.setSourceFunctionValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getSourceFunctionValue()) + # Get the list of simulation movements of packing list ... + packing_list_simulation_movement_list = [] + for packing_list_movement in packing_list.getMovementList(): + packing_list_simulation_movement_list.extend( + packing_list_movement.getDeliveryRelatedValueList()) + # ... invoice simulation movement are their childrens. + simulation_movement_list = [] + for p_l_simulation_movement in packing_list_simulation_movement_list : + for applied_rule in p_l_simulation_movement.objectValues() : + simulation_movement_list.extend(applied_rule.objectValues()) - order_line.setDestinationFunctionValue(other_entity) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_entity, - invoice_movement.getDestinationFunctionValue()) + # First, test if each Simulation Movement is related to an + # Invoice Movement + invoice_relative_url = invoice.getRelativeUrl() + for simulation_movement in simulation_movement_list: + invoice_movement_list = simulation_movement.getDeliveryValueList() + self.assertEquals(len(invoice_movement_list), 1) + invoice_movement = invoice_movement_list[0] + self.failUnless(invoice_movement is not None) + self.assert_(invoice_movement.getRelativeUrl().\ + startswith(invoice_relative_url)) - self.assertNotEquals(123, order_line.getPrice()) - order_line.setPrice(123) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(123, - invoice_movement.getPrice()) + # Then, test if each Invoice movement is equals to the sum of somes + # Simulation Movements + for invoice_movement in invoice.getMovementList(portal_type = [ + self.invoice_cell_portal_type, + self.invoice_line_portal_type]) : + related_simulation_movement_list = invoice_movement.\ + getDeliveryRelatedValueList(portal_type='Simulation Movement') + quantity = 0 + total_price = 0 + invoice_movement_quantity = invoice_movement.getQuantity() + for related_simulation_movement in related_simulation_movement_list: + quantity += related_simulation_movement.getQuantity() + total_price += related_simulation_movement.getPrice() *\ + related_simulation_movement.getQuantity() + # Test resource + self.assertEquals(invoice_movement.getResource(), \ + related_simulation_movement.getResource()) + # Test resource variation + self.assertEquals(invoice_movement.getVariationText(), \ + related_simulation_movement.getVariationText()) + self.assertEquals(invoice_movement.getVariationCategoryList(), \ + related_simulation_movement.getVariationCategoryList()) + # Test acquisition + self.checkAcquisition(invoice_movement, + related_simulation_movement) + # Test delivery ratio + self.assertEquals(related_simulation_movement.getQuantity() /\ + invoice_movement_quantity, \ + related_simulation_movement.getDeliveryRatio()) - self.assertNotEquals(456, order_line.getQuantity()) - order_line.setQuantity(456) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(456, - invoice_movement.getQuantity()) + self.assertEquals(quantity, invoice_movement.getQuantity()) + # Test price + self.assertEquals(total_price / quantity, invoice_movement.getPrice()) - other_resource = self.portal.product_module.newContent( - portal_type='Product', - title='Other Resource') - order_line.setResourceValue(other_resource) - transaction.commit() - self.tic() - # after changing 'resource', related simulation movement will be - # replaced with another id, and we need to find the appropriate one - # here. - delivery_movement = related_applied_rule.contentValues()[0] - invoice_applied_rule = delivery_movement.contentValues()[0] - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(other_resource, - invoice_movement.getResourceValue()) + sequence.edit(invoice = invoice) - order_line.setStartDate(DateTime(2001, 02, 03)) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(DateTime(2001, 02, 03), - invoice_movement.getStartDate()) + # Test causality + self.assertEquals(len(invoice.getCausalityValueList( + portal_type = self.packing_list_portal_type)), 1) + self.assertEquals(invoice.getCausalityValue(), packing_list) - order_line.setStopDate(DateTime(2002, 03, 04)) - transaction.commit() - self.tic() - invoice_movement = invoice_applied_rule.contentValues()[0] - self.assertEquals(DateTime(2002, 03, 04), - invoice_movement.getStopDate()) + # Finally, test getTotalQuantity and getTotalPrice on Invoice + self.assertEquals(packing_list.getTotalQuantity(), + invoice.getTotalQuantity()) + self.assertEquals(packing_list.getTotalPrice(), + invoice.getTotalPrice()) - def test_modify_planned_order_invoice_transaction_rule(self): + def stepCheckPaymentBuilding(self, sequence=None, sequence_list=None, **kw): """ - tests that modifying a planned order affects movements from invoice - transaction rule + checks that the payment is built with the default_payment_builder """ - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource', - product_line='apparel') - currency = self.portal.currency_module.newContent( - portal_type='Currency', - title='Currency', - base_unit_quantity=0.01) - self.createInvoiceTransactionRule(currency) - - client = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Client', - default_address_region=self.default_region) - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Vendor', - default_address_region=self.default_region) - order = self.portal.getDefaultModule(self.order_portal_type).newContent( - portal_type=self.order_portal_type, - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client, - start_date=DateTime(2008, 1, 1), - price_currency_value=currency, - title='Order') - order_line = order.newContent(portal_type=self.order_line_portal_type, - resource_value=resource, - quantity=1, - price=2) - other_entity = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Other Entity', - default_address_region=self.default_region) - other_project = self.portal.project_module.newContent( - portal_type='Project', - title='Other Project') - order.plan() - transaction.commit() - self.tic() - self.assertEquals('planned', order.getSimulationState()) - - related_applied_rule = order.getCausalityRelatedValue( - portal_type='Applied Rule') - order_movement = related_applied_rule.contentValues()[0] - delivery_applied_rule = order_movement.contentValues()[0] - delivery_movement = delivery_applied_rule.contentValues()[0] - invoice_applied_rule = delivery_movement.contentValues()[0] - invoice_movement = invoice_applied_rule.contentValues()[0] - invoice_transaction_applied_rule = invoice_movement.contentValues()[0] + invoice = sequence.get('invoice') + related_payment_list = invoice.getCausalityRelatedValueList( + portal_type=self.payment_portal_type) - # utility function to return the simulation movement that should be used - # for "income" line - def getIncomeSimulationMovement(applied_rule): - for movement in applied_rule.contentValues(): - if movement.getDestination() == 'account_module/purchase'\ - and movement.getSource() == 'account_module/sale': - return movement - self.fail('Income movement not found') + invoice_building_state = 'started' + invoice_state = invoice.getSimulationState() + if invoice_state != invoice_building_state : + self.assertEquals(0, len(related_payment_list)) + else: + self.assertEquals(1, len(related_payment_list)) - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) + payment = related_payment_list[0].getObject() + self.failUnless(payment is not None) + # Payments created by Delivery Builder are in planned state + self.assertEquals(payment.getSimulationState(), 'planned') - order_line.setSourceSectionValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(other_entity, - invoice_transaction_movement.getSourceSectionValue()) + # Get the list of simulation movements of packing list ... + invoice_simulation_movement_list = [] + for invoice_movement in invoice.getMovementList( + portal_type=self.portal.getPortalAccountingMovementTypeList()): + invoice_simulation_movement_list.extend( + invoice_movement.getDeliveryRelatedValueList()) + # ... payment simulation movement are their childrens. + simulation_movement_list = [] + for p_l_simulation_movement in invoice_simulation_movement_list : + for applied_rule in p_l_simulation_movement.objectValues() : + simulation_movement_list.extend(applied_rule.objectValues()) - # make sure destination_section != source_section, this might be needed by - # some rules - order_line.setSourceSectionValue(order_line.getDestinationSectionValue()) + # First, test if each Simulation Movement is related to an + # Payment Movement + payment_relative_url = payment.getRelativeUrl() + for simulation_movement in simulation_movement_list: + payment_movement_list = simulation_movement.getDeliveryValueList() + self.assertEquals(len(payment_movement_list), 1) + payment_movement = payment_movement_list[0] + self.failUnless(payment_movement is not None) + self.assert_(payment_movement.getRelativeUrl().\ + startswith(payment_relative_url)) - order_line.setDestinationSectionValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getDestinationSectionValue()) + # Then, test if each Payment movement is equals to the sum of somes + # Simulation Movements + for payment_movement in payment.getMovementList(): + related_simulation_movement_list = payment_movement.\ + getDeliveryRelatedValueList(portal_type='Simulation Movement') + quantity = 0 + total_price = 0 + payment_movement_quantity = payment_movement.getQuantity() + for related_simulation_movement in related_simulation_movement_list: + quantity += related_simulation_movement.getQuantity() + total_price += related_simulation_movement.getPrice() *\ + related_simulation_movement.getQuantity() + # Test resource + self.assertEquals(payment_movement.getResource(), \ + related_simulation_movement.getResource()) + # Test resource variation + self.assertEquals(payment_movement.getVariationText(), \ + related_simulation_movement.getVariationText()) + self.assertEquals(payment_movement.getVariationCategoryList(), \ + related_simulation_movement.getVariationCategoryList()) + # Test acquisition + self.checkAcquisition(payment_movement, + related_simulation_movement) + # Test delivery ratio + self.assertEquals(related_simulation_movement.getQuantity() /\ + payment_movement_quantity, \ + related_simulation_movement.getDeliveryRatio()) - order_line.setSourceAdministrationValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getSourceAdministrationValue()) + self.assertEquals(quantity, payment_movement.getQuantity()) + # Test price + self.assertEquals(total_price / quantity, payment_movement.getPrice()) - order_line.setDestinationAdministrationValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getDestinationAdministrationValue()) + sequence.edit(payment = payment) - order_line.setSourceDecisionValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getSourceDecisionValue()) + # Test causality + self.assertEquals(len(payment.getCausalityValueList( + portal_type = self.invoice_portal_type)), 1) + self.assertEquals(payment.getCausalityValue(), invoice) - order_line.setDestinationDecisionValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getDestinationDecisionValue()) + # Finally, test getTotalQuantity and getTotalPrice on Payment + self.assertEquals(0, payment.getTotalQuantity()) + self.assertEquals(0, payment.getTotalPrice()) - order_line.setSourceProjectValue(other_project) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_project, - invoice_transaction_movement.getSourceProjectValue()) + def stepCheckInvoicesConsistency(self, sequence=None, sequence_list=None, + **kw): + """ + Checks that all invoices are consistent: + - transaction lines match invoice lines + - no movement is divergent + """ + invoice_list = self.getPortal()['accounting_module'].objectValues() + for invoice in invoice_list: + accounting_state_list = \ + list(self.getPortal().getPortalCurrentInventoryStateList()) + accounting_state_list.append('cancelled') + if invoice.getSimulationState() in accounting_state_list: + invoice_line_list = invoice.contentValues( + portal_type=self.invoice_line_portal_type) + invoice_transaction_line_list = invoice.contentValues( + portal_type=self.invoice_transaction_line_portal_type) + self.assertEquals(3, len(invoice_transaction_line_list)) + expected_price = 0.0 + for line in invoice_line_list: + expected_price += line.getTotalPrice() + for line_id, line_source, line_dest, line_ratio in \ + self.transaction_line_definition_list: + for line in invoice.contentValues( + portal_type=self.invoice_transaction_line_portal_type): + if line.getSource() == 'account_module/%s' % line_source and \ + line.getDestination() == 'account_module/%s' % line_dest: + break + else: + self.fail('No line found that matches %s' % line_id) + resource_precision = line.getResourceValue().getQuantityPrecision() + self.assertEquals(round(line.getQuantity(), resource_precision), + round(expected_price * line_ratio, resource_precision)) - order_line.setDestinationProjectValue(other_project) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_project, - invoice_transaction_movement.getDestinationProjectValue()) + def stepCheckInvoiceLineHasReferenceAndIntIndex(self, sequence=None, **kw): + """Check that the unique invoice line in the invoice has reference and int + index. + """ + invoice = sequence.get('invoice') + invoice_line_list = invoice.contentValues( + portal_type=self.invoice_line_portal_type) + self.assertEquals(1, len(invoice_line_list)) + invoice_line = invoice_line_list[0] + self.assertEquals(1, invoice_line.getIntIndex()) + self.assertEquals('1', invoice_line.getReference()) - order_line.setSourceFunctionValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getSourceFunctionValue()) + def stepCheckPackingListInvoice( + self, sequence=None, sequence_list=None, **kw): + """ Checks if the delivery builder is working as expected, + coping the atributes from packing list to invoice.""" + packing_list = sequence.get('packing_list') + related_invoice_list = packing_list.getCausalityRelatedValueList( + portal_type=self.invoice_portal_type) + self.assertEquals(len(related_invoice_list), 1) + invoice = related_invoice_list[0] + self.assertEquals(packing_list.getSource(), invoice.getSource()) + self.assertEquals(packing_list.getDestination(), invoice.getDestination()) + self.assertEquals(packing_list.getDestinationSection(), \ + invoice.getDestinationSection()) + self.assertEquals(packing_list.getSourceSection(), \ + invoice.getSourceSection()) + self.assertEquals(packing_list.getDestinationDecision(), \ + invoice.getDestinationDecision()) + self.assertEquals(packing_list.getSourceDecision(), \ + invoice.getSourceDecision()) + self.assertEquals(packing_list.getDestinationAdministration(), \ + invoice.getDestinationAdministration()) + self.assertEquals(packing_list.getSourceAdministration(), \ + invoice.getSourceAdministration()) + self.assertEquals(packing_list.getDestinationProject(), \ + invoice.getDestinationProject()) + self.assertEquals(packing_list.getSourceProject(), \ + invoice.getSourceProject()) + self.assertEquals(packing_list.getPriceCurrency(), \ + invoice.getPriceCurrency()) - order_line.setDestinationFunctionValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getDestinationFunctionValue()) - order_line.setSourcePaymentValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getSourcePaymentValue()) - order_line.setDestinationPaymentValue(other_entity) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(other_entity, - invoice_transaction_movement.getDestinationPaymentValue()) + def stepCheckDeliveryRuleForDeferred( + self, sequence=None, sequence_list=None, **kw): + """ Checks that a delivery rule has been created when we took 'split + and defer' decision on the divergeant Packing List. """ + # TODO - order_line.setQuantity(1) - order_line.setPrice(123) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(123, - invoice_transaction_movement.getQuantity()) + def stepCheckDeliveryRuleIsEmpty( + self, sequence=None, sequence_list=None, **kw): + """ Checks that an empty delivery rule is created for the + convergeant Packing List""" + packing_list = sequence.get('packing_list') + self.failUnless(packing_list is not None) + simulation_tool = self.getSimulationTool() + # Check that there is an applied rule for our packing list + rule_list = [x for x in simulation_tool.objectValues() + if x.getCausalityValue()==packing_list] + self.assertEquals(len(rule_list),1) + packing_list_rule = rule_list[0] + sequence.edit(packing_list_rule=packing_list_rule) + rule_line_list = packing_list_rule.objectValues() + packing_list_line_list = packing_list.objectValues() + self.assertEquals(len(packing_list_line_list), + len(rule_line_list)) + self.assertEquals(1, len(rule_line_list)) + rule_line = rule_line_list[0] + packing_list_line = packing_list_line_list[0] + self.assertEquals(rule_line.getQuantity(), 10) + self.assertEquals(rule_line.getPrice(), 100) + self.assertEquals(rule_line.getDeliveryValue(), + packing_list_line) + self.assertEquals(rule_line.getStartDate(), + packing_list_line.getStartDate()) + self.assertEquals(rule_line.getStopDate(), + packing_list_line.getStopDate()) + self.assertEquals(rule_line.getPortalType(), + 'Simulation Movement') - order_line.setQuantity(456) - order_line.setPrice(1) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(456, - invoice_transaction_movement.getQuantity()) - - order_line.setStartDate(DateTime(2001, 02, 03)) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(DateTime(2001, 02, 03), - invoice_transaction_movement.getStartDate()) - - order_line.setStopDate(DateTime(2002, 03, 04)) - transaction.commit() - self.tic() - self.assertEquals(3, len(invoice_transaction_applied_rule)) - invoice_transaction_movement = getIncomeSimulationMovement( - invoice_transaction_applied_rule) - self.assertEquals(DateTime(2002, 03, 04), - invoice_transaction_movement.getStopDate()) - - - def test_Invoice_viewAsODT(self): - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource',) - client = self.portal.organisation_module.newContent( - portal_type='Organisation', title='Client') - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', title='Vendor') - invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent( - portal_type=self.invoice_portal_type, - start_date=DateTime(2008, 12, 31), - title='Invoice', - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client) - line = invoice.newContent(portal_type=self.invoice_line_portal_type, - resource_value=resource, - quantity=10, - price=3) - invoice.confirm() - transaction.commit() - self.tic() - - odt = invoice.Invoice_viewAsODT() - from Products.ERP5OOo.tests.utils import Validator - odf_validator = Validator() - err_list = odf_validator.validate(odt) - if err_list: - self.fail(''.join(err_list)) - - def test_Invoice_viewAsODT_empty_image(self): - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource',) - client = self.portal.organisation_module.newContent( - portal_type='Organisation', title='Client') - client_logo = client.newContent(portal_type='Image', - id='default_image') - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', title='Vendor') - vendor_logo = vendor.newContent(portal_type='Image', - id='default_image') - self.assertEquals(0, vendor_logo.getSize()) - self.assertEquals(0, vendor.getDefaultImageWidth()) - self.assertEquals(0, vendor.getDefaultImageHeight()) - invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent( - portal_type=self.invoice_portal_type, - start_date=DateTime(2008, 12, 31), - title='Invoice', - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client) - line = invoice.newContent(portal_type=self.invoice_line_portal_type, - resource_value=resource, - quantity=10, - price=3) - invoice.confirm() - transaction.commit() - self.tic() - - odt = invoice.Invoice_viewAsODT() - from Products.ERP5OOo.tests.utils import Validator - odf_validator = Validator() - err_list = odf_validator.validate(odt) - if err_list: - self.fail(''.join(err_list)) - - # the <draw:image> should not be present, because there's no logo - parser = OOoParser() - parser.openFromString(odt) - style_xml = parser.oo_files['styles.xml'] - self.assert_('<draw:image' not in style_xml) - - def test_Invoice_viewAsODT_invalid_image(self): - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource',) - file_data = FileUpload(__file__, 'rb') - client = self.portal.organisation_module.newContent( - portal_type='Organisation', title='Client') - client_logo = client.newContent(portal_type='Image', - id='default_image', - file=file_data) - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', title='Vendor') - vendor_logo = vendor.newContent(portal_type='Image', - id='default_image', - file=file_data) - - # width and height of an invalid image are -1 according to - # OFS.Image.getImageInfo maybe this is not what we want here ? - self.assertEquals(-1, vendor.getDefaultImageWidth()) - self.assertEquals(-1, vendor.getDefaultImageHeight()) - - invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent( - portal_type=self.invoice_portal_type, - start_date=DateTime(2008, 12, 31), - title='Invoice', - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client) - line = invoice.newContent(portal_type=self.invoice_line_portal_type, - resource_value=resource, - quantity=10, - price=3) - invoice.confirm() - transaction.commit() - self.tic() - - odt = invoice.Invoice_viewAsODT() - from Products.ERP5OOo.tests.utils import Validator - odf_validator = Validator() - err_list = odf_validator.validate(odt) - if err_list: - self.fail(''.join(err_list)) - def test_invoice_building_with_cells(self): - # if the order has cells, the invoice built from that order must have - # cells too - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource', - variation_base_category_list=['size']) - currency = self.portal.currency_module.newContent( - portal_type='Currency', - title='Currency') - - client = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Client') - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Vendor') - order = self.portal.getDefaultModule(self.order_portal_type).newContent( - portal_type=self.order_portal_type, - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client, - start_date=DateTime(2008, 1, 1), - price_currency_value=currency, - title='Order') - - order_line = order.newContent(portal_type=self.order_line_portal_type, - resource_value=resource,) - order_line.setVariationBaseCategoryList(('size', )) - order_line.setVariationCategoryList(['size/Baby', 'size/Child/32']) - order_line.updateCellRange() - - cell_baby = order_line.newCell('size/Baby', base_id='movement', - portal_type=self.order_cell_portal_type) - cell_baby.edit(quantity=10, - price=4, - variation_category_list=['size/Baby'], - mapped_value_property_list=['quantity', 'price'],) - - cell_child_32 = order_line.newCell('size/Child/32', base_id='movement', - portal_type=self.order_cell_portal_type) - cell_child_32.edit(quantity=20, - price=5, - variation_category_list=['size/Child/32'], - mapped_value_property_list=['quantity', 'price'],) - order.confirm() - transaction.commit() - self.tic() - - related_packing_list = order.getCausalityRelatedValue( - portal_type=self.packing_list_portal_type) - self.assertNotEquals(related_packing_list, None) - - related_packing_list.start() - related_packing_list.stop() - transaction.commit() - self.tic() + def stepCheckPackingList(self,sequence=None, sequence_list=None,**kw): + """ """ + packing_list_module = self.getSalePackingListModule() + order_rule = sequence.get('order_rule') + order = sequence.get('order') + sale_packing_list_list = [] + for o in packing_list_module.objectValues(): + if o.getCausalityValue() == order: + sale_packing_list_list.append(o) + self.assertEquals(len(sale_packing_list_list), 1) + sale_packing_list = sale_packing_list_list[0] + sale_packing_list_line_list = sale_packing_list.objectValues() + self.assertEquals(len(sale_packing_list_line_list),1) + sale_packing_list_line = sale_packing_list_line_list[0] + product = sequence.get('resource') + self.assertEquals(sale_packing_list_line.getResourceValue(), + product) + self.assertEquals(sale_packing_list_line.getPrice(), + self.price1) + LOG('sale_packing_list_line.showDict()',0, + sale_packing_list_line.showDict()) + self.assertEquals(sale_packing_list_line.getQuantity(), + self.quantity1) + self.assertEquals(sale_packing_list_line.getTotalPrice(), + self.total_price1) + sequence.edit(packing_list = sale_packing_list) - related_invoice = related_packing_list.getCausalityRelatedValue( - portal_type=self.invoice_portal_type) - self.assertNotEquals(related_invoice, None) + def stepCheckTwoInvoices(self,sequence=None, sequence_list=None, **kw): + """ checks invoice properties are well set. """ + # Now we will check that we have two invoices created + packing_list = sequence.get('packing_list') + invoice_list = packing_list.getCausalityRelatedValueList( + portal_type=self.invoice_portal_type) + self.assertEquals(len(invoice_list),1) + invoice = invoice_list[0] + self.assertEquals(invoice.getSimulationState(), 'confirmed') + sequence.edit(invoice=invoice) + new_packing_list = sequence.get('new_packing_list') + new_invoice_list = new_packing_list.getCausalityRelatedValueList( + portal_type=self.invoice_portal_type) + self.assertEquals(len(new_invoice_list),1) + new_invoice = new_invoice_list[0] + self.assertEquals(new_invoice.getSimulationState(), 'confirmed') + sequence.edit(new_invoice=new_invoice) - line_list = related_invoice.contentValues( - portal_type=self.invoice_line_portal_type) - self.assertEquals(1, len(line_list)) - invoice_line = line_list[0] + def stepStartTwoInvoices(self,sequence=None, sequence_list=None, **kw): + """ start both invoices. """ + portal = self.getPortal() + invoice = sequence.get('invoice') + new_invoice = sequence.get('new_invoice') + portal.portal_workflow.doActionFor(invoice, 'start_action') + portal.portal_workflow.doActionFor(new_invoice, 'start_action') - self.assertEquals(resource, invoice_line.getResourceValue()) - self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList()) - self.assertEquals(2, - len(invoice_line.getCellValueList(base_id='movement'))) + def stepCheckTwoInvoicesTransactionLines(self,sequence=None, + sequence_list=None, **kw): + """ checks invoice properties are well set. """ + invoice = sequence.get('invoice') + new_invoice = sequence.get('new_invoice') + self.assertEquals(3,len(invoice.objectValues( + portal_type=self.invoice_transaction_line_portal_type))) + self.assertEquals(3,len(new_invoice.objectValues( + portal_type=self.invoice_transaction_line_portal_type))) + account_module = self.getAccountModule() + found_dict = {} + for line in invoice.objectValues( + portal_type=self.invoice_transaction_line_portal_type): + source_id = line.getSourceId() + found_dict[source_id] = line.getQuantity() + total_price = (self.default_quantity-1) * self.default_price + expected_dict = { + 'sale' : total_price, + 'receivable_vat' : total_price * self.vat_rate, + 'customer' : - (total_price + total_price * self.vat_rate) + } + self.failIfDifferentSet(expected_dict.keys(),found_dict.keys()) + for key in found_dict.keys(): + self.assertAlmostEquals(expected_dict[key],found_dict[key],places=2) + found_dict = {} + for line in new_invoice.objectValues( + portal_type=self.invoice_transaction_line_portal_type): + source_id = line.getSourceId() + found_dict[source_id] = line.getQuantity() + total_price = 1 * self.default_price + expected_dict = { + 'sale' : total_price, + 'receivable_vat' : total_price * self.vat_rate, + 'customer' : - (total_price + total_price * self.vat_rate) + } + self.failIfDifferentSet(expected_dict.keys(), found_dict.keys()) + for key in found_dict.keys(): + self.assertAlmostEquals(expected_dict[key], found_dict[key], places=2) - cell_baby = invoice_line.getCell('size/Baby', base_id='movement') - self.assertNotEquals(cell_baby, None) - self.assertEquals(resource, cell_baby.getResourceValue()) - self.assertEquals(10, cell_baby.getQuantity()) - self.assertEquals(4, cell_baby.getPrice()) - self.assertTrue('size/Baby' in - cell_baby.getVariationCategoryList()) - self.assertTrue(cell_baby.isMemberOf('size/Baby')) + def stepRebuildAndCheckNothingIsCreated(self, sequence=None, + sequence_list=None, **kw): + """Rebuilds with sale_invoice_builder and checks nothing more is + created. """ + accounting_module = self.getAccountingModule() + portal_type_list = ('Sale Invoice Transaction', 'Purchase Invoice Transaction') + sale_invoice_transaction_count = len(accounting_module.objectValues( + portal_type=portal_type_list)) + for builder in self.getPortal().portal_deliveries.objectValues(): + builder.build() + self.assertEquals(sale_invoice_transaction_count, + len(accounting_module.objectValues( + portal_type=portal_type_list))) - cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement') - self.assertNotEquals(cell_child_32, None) - self.assertEquals(resource, cell_child_32.getResourceValue()) - self.assertEquals(20, cell_child_32.getQuantity()) - self.assertEquals(5, cell_child_32.getPrice()) - self.assertTrue('size/Child/32' in - cell_child_32.getVariationCategoryList()) - self.assertTrue(cell_child_32.isMemberOf('size/Child/32')) - - - - def test_invoice_created_from_packing_list_with_no_order(self): - # if the order has cells and an aggregate, the invoice built - #from that order must have - # cells too - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource', - variation_base_category_list=['size']) - currency = self.portal.currency_module.newContent( - portal_type='Currency', - title='Currency') + def stepModifyInvoicesDate(self, sequence=None, + sequence_list=None, **kw): + """Change invoice date""" + invoice = sequence.get('invoice') + new_invoice = sequence.get('new_invoice') + invoice.edit(start_date=self.datetime, + stop_date=self.datetime+1) + new_invoice.edit(start_date=self.datetime, + stop_date=self.datetime+1) - client = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Client') - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Vendor') - no_order_packing_list = \ -self.portal.getDefaultModule(self.packing_list_portal_type).newContent( - portal_type=self.packing_list_portal_type, - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client, - start_date=DateTime(2008, 1, 1), - price_currency_value=currency, - title='Order') + def stepRemoveDateMovementGroupForTransactionBuilder(self, sequence=None, + sequence_list=None, **kw): + """ + Remove DateMovementGroup + """ + portal = self.getPortal() + builder = portal.portal_deliveries.sale_invoice_transaction_builder + delivery_movement_group_list = builder.getDeliveryMovementGroupList() + uf = self.getPortal().acl_users + uf._doAddUser('admin', '', ['Manager'], []) + user = uf.getUserById('admin').__of__(uf) + newSecurityManager(None, user) + for movement_group in delivery_movement_group_list: + if movement_group.getPortalType() == 'Property Movement Group': + # it contains 'start_date' and 'stop_date' only, so we remove + # movement group itself. + builder.deleteContent(movement_group.getId()) + builder.newContent( + portal_type = 'Parent Explanation Movement Group', + collect_order_group='delivery', + int_index=len(delivery_movement_group_list)+1 + ) + user = uf.getUserById('test_invoice_user').__of__(uf) + newSecurityManager(None, user) - packing_list_line = no_order_packing_list.newContent( - portal_type=self.packing_list_line_portal_type, - resource_value=resource,) - packing_list_line.setVariationBaseCategoryList(('size', )) - packing_list_line.setVariationCategoryList(['size/Baby', 'size/Child/32']) - packing_list_line.updateCellRange() + def stepEditInvoice(self, sequence=None, sequence_list=None, **kw): + """Edit the current invoice, to trigger updateAppliedRule.""" + invoice = sequence.get('invoice') + invoice.edit() - cell_baby = packing_list_line.newCell('size/Baby', base_id='movement', - portal_type=self.packing_list_cell_portal_type) - cell_baby.edit(quantity=10, - price=4, - variation_category_list=['size/Baby'], - mapped_value_property_list=['quantity', 'price'],) + # call updateAppliedRule directly, don't rely on edit interactions + rule_reference = 'default_invoice_rule' + self.assertNotEquals(0, + len(self.portal.portal_rules.searchFolder(reference=rule_reference))) + invoice.updateAppliedRule(rule_reference=rule_reference) - cell_child_32 = packing_list_line.newCell( - 'size/Child/32',base_id='movement', - portal_type=self.packing_list_cell_portal_type) - cell_child_32.edit(quantity=20, - price=5, - variation_category_list=['size/Child/32'], - mapped_value_property_list=['quantity', 'price'],) - no_order_packing_list.confirm() - transaction.commit() - self.tic() - self.assertNotEquals(no_order_packing_list, None) + def stepCheckInvoiceRuleNotAppliedOnInvoiceEdit(self, + sequence=None, sequence_list=None, **kw): + """If we call edit on the invoice, invoice rule should not be + applied on lines created by delivery builder.""" + invoice = sequence.get('invoice') + # FIXME: empty applied rule should not be created + #self.assertEquals(len(invoice.getCausalityRelatedValueList( + # portal_type=self.applied_rule_portal_type)), 0) + for invoice_mvt in invoice.getMovementList(): + self.assertEquals(len(invoice_mvt.getOrderRelatedValueList( + portal_type=self.simulation_movement_portal_type)), 0) - no_order_packing_list.start() - no_order_packing_list.stop() - transaction.commit() - self.tic() + def stepEditPackingList(self, sequence=None, sequence_list=None, **kw): + """Edit the current packing list, to trigger updateAppliedRule.""" + packing_list = sequence.get('packing_list') + packing_list.edit() - related_invoice = no_order_packing_list.getCausalityRelatedValue( - portal_type=self.invoice_portal_type) - self.assertNotEquals(related_invoice, None) + # call updateAppliedRule directly, don't rely on edit interactions + rule_reference = 'default_delivery_rule' + self.assertNotEquals(0, + len(self.portal.portal_rules.searchFolder(reference=rule_reference))) + packing_list.updateAppliedRule(rule_reference=rule_reference) - line_list = related_invoice.contentValues( - portal_type=self.invoice_line_portal_type) - self.assertEquals(1, len(line_list)) - invoice_line = line_list[0] + def stepCheckDeliveryRuleNotAppliedOnPackingListEdit(self, + sequence=None, sequence_list=None, **kw): + """If we call edit on the packing list, delivery rule should not be + applied on lines created by delivery builder.""" + packing_list = sequence.get('packing_list') + # FIXME: empty applied rule should not be created + #self.assertEquals(len(packing_list.getCausalityRelatedValueList( + # portal_type=self.applied_rule_portal_type)), 0) + for delivery_mvt in packing_list.getMovementList(): + self.assertEquals(len(delivery_mvt.getOrderRelatedValueList( + portal_type=self.simulation_movement_portal_type)), 0) - self.assertEquals(resource, invoice_line.getResourceValue()) - self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList()) - self.assertEquals(2, - len(invoice_line.getCellValueList(base_id='movement'))) + def stepDecreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None, + **kw): + """ + Set a decreased quantity on invoice lines + """ + invoice = sequence.get('invoice') + quantity = sequence.get('line_quantity',default=self.default_quantity) + quantity = quantity - 1 + sequence.edit(line_quantity=quantity) + for invoice_line in invoice.objectValues( + portal_type=self.invoice_line_portal_type): + invoice_line.edit(quantity=quantity) + sequence.edit(last_delta = sequence.get('last_delta', 0.0) - 1.0) - cell_baby = invoice_line.getCell('size/Baby', base_id='movement') - self.assertNotEquals(cell_baby, None) - self.assertEquals(resource, cell_baby.getResourceValue()) - self.assertEquals(10, cell_baby.getQuantity()) - self.assertEquals(4, cell_baby.getPrice()) - self.assertTrue('size/Baby' in - cell_baby.getVariationCategoryList()) - self.assertTrue(cell_baby.isMemberOf('size/Baby')) + def stepIncreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None, + **kw): + """ + Set a Increased quantity on invoice lines + """ + invoice = sequence.get('invoice') + quantity = sequence.get('line_quantity',default=self.default_quantity) + quantity = quantity + 1 + sequence.edit(line_quantity=quantity) + for invoice_line in invoice.objectValues( + portal_type=self.invoice_line_portal_type): + invoice_line.edit(quantity=quantity) + sequence.edit(last_delta = sequence.get('last_delta', 0.0) + 1.0) - cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement') - self.assertNotEquals(cell_child_32, None) - self.assertEquals(resource, cell_child_32.getResourceValue()) - self.assertEquals(20, cell_child_32.getQuantity()) - self.assertEquals(5, cell_child_32.getPrice()) - self.assertTrue('size/Child/32' in - cell_child_32.getVariationCategoryList()) - self.assertTrue(cell_child_32.isMemberOf('size/Child/32')) - - def test_invoice_building_with_cells_and_aggregate(self): - # if the order has cells and an aggregate, the invoice built - #from that order must have - # cells too - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource', - variation_base_category_list=['size']) - currency = self.portal.currency_module.newContent( - portal_type='Currency', - title='Currency') + def stepSetInvoiceLineQuantityToZero(self, sequence=None, sequence_list=None, + **kw): + """ + Set the quantity on invoice lines to zero + """ + invoice = sequence.get('invoice') + #default_quantity = sequence.get('line_quantity',default_quantity) + quantity = 0.0 + sequence.edit(line_quantity=quantity) + for invoice_line in invoice.objectValues( + portal_type=self.invoice_line_portal_type): + invoice_line.edit(quantity=quantity) + sequence.edit(last_delta = - self.default_quantity) - client = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Client') - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Vendor') - order = self.portal.getDefaultModule(self.order_portal_type).newContent( - portal_type=self.order_portal_type, - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client, - start_date=DateTime(2008, 1, 1), - price_currency_value=currency, - title='Order') + def stepChangeInvoiceStartDate(self, sequence=None, sequence_list=None, **kw): + """ + Change the start_date of the invoice. + """ + invoice = sequence.get('invoice') + invoice.edit(start_date=self.datetime + 15) - order_line = order.newContent(portal_type=self.order_line_portal_type, - resource_value=resource,) - order_line.setVariationBaseCategoryList(('size', )) - order_line.setVariationCategoryList(['size/Baby', 'size/Child/32']) - order_line.updateCellRange() + def stepCheckInvoiceIsCalculating(self, sequence=None, sequence_list=None, + **kw): + """ + Test if invoice is calculating + """ + invoice = sequence.get('invoice') + self.assertEquals('calculating',invoice.getCausalityState()) - cell_baby = order_line.newCell('size/Baby', base_id='movement', - portal_type=self.order_cell_portal_type) - cell_baby.edit(quantity=10, - price=4, - variation_category_list=['size/Baby'], - mapped_value_property_list=['quantity', 'price'],) + def stepCheckInvoiceIsDiverged(self, sequence=None, sequence_list=None, + **kw): + """ + Test if invoice is diverged + """ + invoice = sequence.get('invoice') + self.assertEquals('diverged',invoice.getCausalityState()) - cell_child_32 = order_line.newCell('size/Child/32', base_id='movement', - portal_type=self.order_cell_portal_type) - cell_child_32.edit(quantity=20, - price=5, - variation_category_list=['size/Child/32'], - mapped_value_property_list=['quantity', 'price'],) - order.confirm() - transaction.commit() - self.tic() + def stepCheckInvoiceIsSolved(self, sequence=None, sequence_list=None, + **kw): + """ + Test if invoice is solved + """ + invoice = sequence.get('invoice') + self.assertEquals('solved', invoice.getCausalityState(), + invoice.getDivergenceList()) - related_packing_list = order.getCausalityRelatedValue( - portal_type=self.packing_list_portal_type) - self.assertNotEquals(related_packing_list, None) + def stepCheckInvoiceIsDivergent(self, sequence=None, sequence_list=None, + **kw): + """ + Test if invoice is divergent + """ + invoice = sequence.get('invoice') + self.assertTrue(invoice.isDivergent()) - related_packing_list.start() - related_packing_list.stop() - transaction.commit() - self.tic() + def stepCheckInvoiceIsNotDivergent(self, sequence=None, sequence_list=None, + **kw): + """ + Test if invoice is not divergent + """ + invoice = sequence.get('invoice') + if invoice.isDivergent(): + self.fail(invoice.getDivergenceList()) - related_invoice = related_packing_list.getCausalityRelatedValue( - portal_type=self.invoice_portal_type) - self.assertNotEquals(related_invoice, None) + def stepSplitAndDeferInvoice(self, sequence=None, sequence_list=None, + **kw): + """ + split and defer at the invoice level + """ + invoice = sequence.get('invoice') + kw = {'listbox':[ + {'listbox_key':line.getRelativeUrl(), + 'choice':'SplitAndDefer'} for line in invoice.getMovementList()]} + self.portal.portal_workflow.doActionFor( + invoice, + 'split_and_defer_action', + start_date=self.datetime + 15, + stop_date=self.datetime + 25, + **kw) + pass - line_list = related_invoice.contentValues( - portal_type=self.invoice_line_portal_type) - self.assertEquals(1, len(line_list)) - invoice_line = line_list[0] + def stepUnifyStartDateWithDecisionInvoice(self, sequence=None, + sequence_list=None): + invoice = sequence.get('invoice') + self._solveDeliveryGroupDivergence(invoice, 'start_date', + invoice.getRelativeUrl()) - self.assertEquals(resource, invoice_line.getResourceValue()) - self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList()) - self.assertEquals(2, - len(invoice_line.getCellValueList(base_id='movement'))) + def stepAcceptDecisionQuantityInvoice(self,sequence=None, sequence_list=None): + invoice = sequence.get('invoice') + self._solveDivergence(invoice, 'quantity', 'accept') - cell_baby = invoice_line.getCell('size/Baby', base_id='movement') - self.assertNotEquals(cell_baby, None) - self.assertEquals(resource, cell_baby.getResourceValue()) - self.assertEquals(10, cell_baby.getQuantity()) - self.assertEquals(4, cell_baby.getPrice()) - self.assertTrue('size/Baby' in - cell_baby.getVariationCategoryList()) - self.assertTrue(cell_baby.isMemberOf('size/Baby')) + def stepAcceptDecisionInvoice(self, sequence=None, sequence_list=None, + **kw): + """ + accept decision at the invoice level + """ + invoice = sequence.get('invoice') + invoice.portal_workflow.doActionFor(invoice,'accept_decision_action') - cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement') - self.assertNotEquals(cell_child_32, None) - self.assertEquals(resource, cell_child_32.getResourceValue()) - self.assertEquals(20, cell_child_32.getQuantity()) - self.assertEquals(5, cell_child_32.getPrice()) - self.assertTrue('size/Child/32' in - cell_child_32.getVariationCategoryList()) - self.assertTrue(cell_child_32.isMemberOf('size/Child/32')) - - - def test_description_copied_on_lines(self): - # if the order lines have different descriptions, description must be - # copied in the simulation and on created movements - resource = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource',) - resource2 = self.portal.getDefaultModule( - self.resource_portal_type).newContent( - portal_type=self.resource_portal_type, - title='Resource2',) - currency = self.portal.currency_module.newContent( - portal_type='Currency', - title='Currency') + def stepCheckInvoiceSplitted(self, sequence=None, sequence_list=None, **kw): + """ + Test if invoice was splitted + """ + packing_list = sequence.get('packing_list') + invoice_list = packing_list.getCausalityRelatedValueList( + portal_type=self.invoice_portal_type) + self.assertEquals(2,len(invoice_list)) + invoice1 = None + invoice2 = None + for invoice in invoice_list: + if invoice.getUid() == sequence.get('invoice').getUid(): + invoice1 = invoice + else: + invoice2 = invoice + sequence.edit(new_invoice=invoice2) + for line in invoice1.objectValues( + portal_type=self.invoice_line_portal_type): + self.assertEquals(self.default_quantity-1,line.getQuantity()) + for line in invoice2.objectValues( + portal_type=self.invoice_line_portal_type): + self.assertEquals(1,line.getQuantity()) - client = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Client') - vendor = self.portal.organisation_module.newContent( - portal_type='Organisation', - title='Vendor') - order = self.portal.getDefaultModule(self.order_portal_type).newContent( - portal_type=self.order_portal_type, - source_value=vendor, - source_section_value=vendor, - destination_value=client, - destination_section_value=client, - start_date=DateTime(2008, 1, 1), - price_currency_value=currency, - title='Order') + def stepCheckInvoiceNotSplitted(self, sequence=None, sequence_list=None, **kw): + """ + Test if invoice was not splitted + """ + packing_list = sequence.get('packing_list') + invoice_list = packing_list.getCausalityRelatedValueList( + portal_type=self.invoice_portal_type) + self.assertEquals(1,len(invoice_list)) + invoice1 = None + for invoice in invoice_list: + if invoice.getUid() == sequence.get('invoice').getUid(): + invoice1 = invoice + last_delta = sequence.get('last_delta', 0.0) + for line in invoice1.objectValues( + portal_type=self.invoice_line_portal_type): + self.assertEquals(self.default_quantity + last_delta, + line.getQuantity()) - order.newContent(portal_type=self.order_line_portal_type, - quantity=3, - price=10, - description='The first line', - resource_value=resource,) - order.newContent(portal_type=self.order_line_portal_type, - quantity=5, - price=10, - description='The second line', - resource_value=resource2,) + def stepAddInvoiceLines(self, sequence=None, sequence_list=[]): + """ + add some invoice and accounting lines to the invoice + """ + invoice = sequence.get('invoice') + invoice.newContent(portal_type='Invoice Line', + resource_value=sequence.get('resource'), quantity=3, price=555) + invoice.newContent(portal_type='Sale Invoice Transaction Line', + id ='receivable', source='account_module/customer', + destination='account_module/supplier', quantity=-1665) + invoice.newContent(portal_type='Sale Invoice Transaction Line', + id='income', source='account_module/sale', + destination='account_module/purchase', quantity=1665) - order.confirm() - transaction.commit() - self.tic() + def stepAddWrongInvoiceLines(self, sequence=None, sequence_list=[]): + """ + add some wrong invoice and accounting lines to the invoice + """ + invoice = sequence.get('invoice') + invoice.newContent(portal_type='Sale Invoice Transaction Line', + id='bad_movement', source='account_module/sale', + destination='account_module/purchase', quantity=2, price=4) + invoice.newContent(portal_type='Sale Invoice Transaction Line', + id='counter_bad_movement', source='account_module/sale', + destination='account_module/purchase', quantity=-2, price=4) + for movement in invoice.getMovementList(): + movement.edit(resource_value=sequence.get('resource')) - related_packing_list = order.getCausalityRelatedValue( - portal_type=self.packing_list_portal_type) - self.assertNotEquals(related_packing_list, None) - - movement_list = related_packing_list.getMovementList() - self.assertEquals(2, len(movement_list)) - self.assertEquals(['The first line'], - [m.getDescription() for m in movement_list if m.getQuantity() == 3]) - self.assertEquals(['The second line'], - [m.getDescription() for m in movement_list if m.getQuantity() == 5]) + def stepCheckStartInvoiceFail(self, sequence=None, sequence_list=[]): + """ + checks that it's not possible to start an invoice with really wrong + lines + """ + try: + self.tic() + except RuntimeError, exc: + invoice = sequence.get('invoice') + it_builder = self.portal.portal_deliveries.sale_invoice_transaction_builder + # check which activities are failing + self.assertTrue(str(exc).startswith('tic is looping forever.'), + '%s does not start with "tic is looping forever."' % str(exc)) + msg_list = ['/'.join(x.object_path) for x in + self.getActivityTool().getMessageList()] + self.assertTrue(it_builder.getPath() in msg_list, '%s in %s' % + (it_builder.getPath(), msg_list)) + # flush failing activities + activity_tool = self.getActivityTool() + activity_tool.manageClearActivities(keep=0) + else: + self.fail("Error: stepStartInvoice didn't fail, the builder script" + + " InvoiceTransaction_postTransactionLineGeneration should have" + + " complained that accounting movements use multiple resources") - related_packing_list.start() - related_packing_list.stop() - transaction.commit() - self.tic() + def stepCheckSimulationTrees(self, sequence=None, sequence_list=[]): + """ + check that rules are created in the order we expect them + """ + applied_rule_set = set() + invoice = sequence.get('invoice') + for movement in invoice.getMovementList(): + for sm in movement.getDeliveryRelatedValueList(): + applied_rule_set.add(sm.getRootAppliedRule()) - related_invoice = related_packing_list.getCausalityRelatedValue( - portal_type=self.invoice_portal_type) - self.assertNotEquals(related_invoice, None) + rule_dict = { + 'Order Rule': { + 'movement_type_list': ['Sale Order Line', 'Sale Order Cell'], + 'next_rule_list': ['Delivering Rule', ], + }, + 'Delivering Rule': { + 'movement_type_list': ['Sale Packing List Line', 'Sale Packing List Cell'], + 'next_rule_list': ['Invoicing Rule', ], + }, + 'Invoicing Rule': { + 'movement_type_list': invoice.getPortalInvoiceMovementTypeList(), + 'next_rule_list': ['Invoice Transaction Rule', 'Trade Model Rule'], + }, + 'Trade Model Rule': { + 'next_rule_list': ['Invoice Transaction Rule'], + }, + 'Invoice Rule': { + 'movement_type_list': invoice.getPortalInvoiceMovementTypeList() \ + + invoice.getPortalAccountingMovementTypeList(), + 'next_rule_list': ['Invoice Transaction Rule', 'Payment Rule', + 'Trade Model Rule'], + }, + 'Invoice Transaction Rule': { + 'parent_movement_type_list': invoice.getPortalInvoiceMovementTypeList(), + 'movement_type_list': invoice.getPortalAccountingMovementTypeList(), + 'next_rule_list': ['Payment Rule'], + }, + 'Payment Rule': { + 'parent_movement_type_list': invoice.getPortalAccountingMovementTypeList(), + 'next_rule_list': [], + }, + } - movement_list = related_invoice.getMovementList( - portal_type=self.invoice_line_portal_type) - self.assertEquals(2, len(movement_list)) - self.assertEquals(['The first line'], - [m.getDescription() for m in movement_list if m.getQuantity() == 3]) - self.assertEquals(['The second line'], - [m.getDescription() for m in movement_list if m.getQuantity() == 5]) + def checkTree(rule): + """ + checks the tree recursively + """ + rule_type = rule.getSpecialiseValue().getPortalType() + rule_def = rule_dict.get(rule_type, {}) + for k, v in rule_def.iteritems(): + if k == 'movement_type_list': + for movement in rule.objectValues(): + if movement.getDeliveryValue() is not None: + self.assertTrue(movement.getDeliveryValue().getPortalType() in v, + 'looking for %s in %s on %s' % ( + movement.getDeliveryValue().getPortalType(), v, + movement.getPath())) + elif k == 'next_rule_list': + for movement in rule.objectValues(): + found_rule_dict = {} + for next_rule in movement.objectValues(): + next_rule_type = next_rule.getSpecialiseValue().getPortalType() + self.assertTrue(next_rule_type in v, + 'looking for %s in %s on %s' % ( + next_rule_type, v, next_rule.getPath())) + n = found_rule_dict.get(next_rule_type, 0) + found_rule_dict[next_rule_type] = n + 1 + # for each movement, we want to make sure that each rule is not + # instanciated more than once + if len(found_rule_dict): + self.assertEquals(set(found_rule_dict.itervalues()), set([1])) + elif k == 'parent_movement_type_list': + if rule.getParentValue().getDeliveryValue() is not None: + parent_type = rule.getParentValue().getDeliveryValue().getPortalType() + self.assertTrue(parent_type in v, 'looking for %s in %s on %s' % ( + parent_type, v, rule.getParentValue().getPath())) + elif k == 'parent_id_list': + self.assertTrue(rule.getParentId() in v, 'looking for %s in %s on %s' + % (rule.getParentId(), v, rule.getPath())) + for movement in rule.objectValues(): + for next_rule in movement.objectValues(): + checkTree(next_rule) + for applied_rule in applied_rule_set: + checkTree(applied_rule) - def test_CopyAndPaste(self): - """Test copy on paste on Invoice. - When an invoice is copy/pasted, references should be resetted. + def stepAddInvoiceLinesManyTransactions(self, sequence=None, sequence_list=[]): """ - accounting_module = self.portal.accounting_module - invoice = accounting_module.newContent( - portal_type=self.invoice_portal_type) - invoice.edit(reference='reference', - source_reference='source_reference', - destination_reference='destination_reference',) - cb_data = accounting_module.manage_copyObjects([invoice.getId()]) - copied, = accounting_module.manage_pasteObjects(cb_data) - new_invoice = accounting_module[copied['new_id']] - self.assertNotEquals(invoice.getReference(), - new_invoice.getReference()) - self.assertNotEquals(invoice.getSourceReference(), - new_invoice.getSourceReference()) - self.assertNotEquals(invoice.getDestinationReference(), - new_invoice.getDestinationReference()) + add some invoice and accounting lines to the invoice + """ + invoice = sequence.get('invoice') + invoice_line = invoice.newContent(portal_type='Invoice Line') + transaction_line_1 = invoice.newContent(portal_type='Sale Invoice Transaction Line') + transaction_line_2 = invoice.newContent(portal_type='Sale Invoice Transaction Line') + transaction.commit() + self.tic() + invoice_line.edit(resource_value=sequence.get('resource'), quantity=3, + price=555) + transaction_line_1.edit(id ='receivable', source='account_module/customer', + destination='account_module/supplier', quantity=-1665) + transaction_line_2.edit( + id='income', source='account_module/sale', + destination='account_module/purchase', quantity=1665) - def test_delivery_mode_and_incoterm_on_invoice(self): +class TestInvoice(TestInvoiceMixin): + """Test methods for sale and purchase invoice. + Subclasses must defines portal types to use. + """ + quiet = 1 + def test_invoice_transaction_line_resource(self): """ - test that categories delivery_mode and incoterm are copied on - the invoice by the delivery builder - """ - resource = self.portal.product_module.newContent( - portal_type='Product', + tests that simulation movements corresponding to accounting line have a + good resource in the simulation + """ + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, title='Resource', product_line='apparel') currency = self.portal.currency_module.newContent( portal_type='Currency', - title='euro') - currency.setBaseUnitQuantity(0.01) + title='Currency', + base_unit_quantity=0.01) self.createInvoiceTransactionRule(currency) - transaction.commit() - self.tic()#execute transaction + client = self.portal.organisation_module.newContent( portal_type='Organisation', title='Client', + price_currency= currency.getRelativeUrl(), default_address_region=self.default_region) vendor = self.portal.organisation_module.newContent( portal_type='Organisation', title='Vendor', + price_currency= currency.getRelativeUrl(), default_address_region=self.default_region) order = self.portal.getDefaultModule(self.order_portal_type).newContent( portal_type=self.order_portal_type, @@ -1367,1272 +1303,1351 @@ self.portal.getDefaultModule(self.packing_list_portal_type).newContent( source_section_value=vendor, destination_value=client, destination_section_value=client, - start_date=DateTime(2008,10, 21), - price_currency_value=currency, - delivery_mode=self.mail_delivery_mode, - incoterm=self.cpt_incoterm, - title='Order') - order_line = order.newContent(portal_type=self.order_line_portal_type, - resource_value=resource, - quantity=5, - price=2) - order.confirm() - transaction.commit() - self.tic() - related_packing_list = order.getCausalityRelatedValue( - portal_type=self.packing_list_portal_type) - self.assertNotEquals(related_packing_list, None) - self.assertEquals(related_packing_list.getDeliveryMode(), - order.getDeliveryMode()) - self.assertEquals(related_packing_list.getIncoterm(), - order.getIncoterm()) - related_packing_list.start() - related_packing_list.stop() + start_date=DateTime(2008, 1, 1), + price_currency_value=currency, + title='Order') + order_line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=resource, + quantity=1, + price=2) + + order.confirm() transaction.commit() self.tic() - related_invoice = related_packing_list.getCausalityRelatedValue( - portal_type=self.invoice_portal_type) - self.assertNotEquals(related_invoice, None) - self.assertEquals(related_invoice.getDeliveryMode(), - order.getDeliveryMode()) - self.assertEquals(related_invoice.getIncoterm(), - order.getIncoterm()) - - - def test_01_quantity_unit_copied(self): + + related_applied_rule = order.getCausalityRelatedValue( + portal_type='Applied Rule') + order_movement = related_applied_rule.contentValues()[0] + delivery_applied_rule = order_movement.contentValues()[0] + delivery_movement = delivery_applied_rule.contentValues()[0] + invoice_applied_rule = delivery_movement.contentValues()[0] + invoice_movement = invoice_applied_rule.contentValues()[0] + invoice_transaction_applied_rule = invoice_movement.contentValues()[0] + invoice_transaction_movement =\ + invoice_transaction_applied_rule.contentValues()[0] + self.assertEquals(currency, + invoice_transaction_movement.getResourceValue()) + self.assertEquals(currency, + delivery_movement.getPriceCurrencyValue()) + + + def test_modify_planned_order_invoicing_rule(self): """ - tests that when a resource uses different quantity unit that the - quantity units are copied on the packing list line and then the invoice - line using the delivery builers - """ - resource = self.portal.product_module.newContent( - portal_type='Product', + tests that modifying a planned order affects movements from invoicing + rule + """ + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, title='Resource', product_line='apparel') - resource.setQuantityUnitList([self.unit_piece_quantity_unit, - self.mass_quantity_unit]) currency = self.portal.currency_module.newContent( portal_type='Currency', - title='euro') - currency.setBaseUnitQuantity(0.01) - transaction.commit() - self.tic()#execute transaction + title='Currency', + base_unit_quantity=0.01) + client = self.portal.organisation_module.newContent( portal_type='Organisation', title='Client', - default_address_region=self.default_region) + price_currency= currency.getRelativeUrl()) vendor = self.portal.organisation_module.newContent( portal_type='Organisation', title='Vendor', - default_address_region=self.default_region) + price_currency= currency.getRelativeUrl()) order = self.portal.getDefaultModule(self.order_portal_type).newContent( portal_type=self.order_portal_type, source_value=vendor, source_section_value=vendor, destination_value=client, destination_section_value=client, - start_date=DateTime(2008,10, 21), + start_date=DateTime(2008, 1, 1), price_currency_value=currency, - delivery_mode=self.mail_delivery_mode, - incoterm=self.cpt_incoterm, title='Order') - first_order_line = order.newContent( - portal_type=self.order_line_portal_type, - resource_value=resource, - quantity_unit = self.unit_piece_quantity_unit, - quantity=5, - price=3) - second_order_line = order.newContent( - portal_type=self.order_line_portal_type, + order_line = order.newContent(portal_type=self.order_line_portal_type, resource_value=resource, - quantity_unit=self.mass_quantity_unit, - quantity=1.5, + quantity=1, price=2) - self.assertEquals(first_order_line.getQuantityUnit(), - self.unit_piece_quantity_unit) - self.assertEquals(second_order_line.getQuantityUnit(), - self.mass_quantity_unit) - order.confirm() + other_entity = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Other Entity', + price_currency=currency.getRelativeUrl()) + other_project = self.portal.project_module.newContent( + portal_type='Project', + title='Other Project') + order.plan() transaction.commit() self.tic() - related_packing_list = order.getCausalityRelatedValue( - portal_type=self.packing_list_portal_type) - self.assertNotEquals(related_packing_list, None) - movement_list = related_packing_list.getMovementList() - self.assertEquals(len(movement_list),2) - movement_list = sorted(movement_list, key=lambda x: x.getQuantity()) - self.assertEquals(movement_list[0].getQuantityUnit(), - self.mass_quantity_unit) - self.assertEquals(movement_list[0].getQuantity(), 1.5) - self.assertEquals(movement_list[1].getQuantityUnit(), - self.unit_piece_quantity_unit) - self.assertEquals(movement_list[1].getQuantity(), 5) + self.assertEquals('planned', order.getSimulationState()) - related_packing_list.start() - related_packing_list.stop() - related_packing_list.deliver() + related_applied_rule = order.getCausalityRelatedValue( + portal_type='Applied Rule') + delivery_movement = related_applied_rule.contentValues()[0] + invoice_applied_rule = delivery_movement.contentValues()[0] + invoice_movement = invoice_applied_rule.contentValues()[0] + + order_line.setSourceValue(other_entity) transaction.commit() self.tic() - related_invoice = related_packing_list.getCausalityRelatedValue( - portal_type=self.invoice_portal_type) - self.assertNotEquals(related_invoice, None) - movement_list = related_invoice.getMovementList() - self.assertEquals(len(movement_list),2) - movement_list = sorted(movement_list, key=lambda x: x.getQuantity()) - self.assertEquals(movement_list[0].getQuantityUnit(), - self.mass_quantity_unit) - self.assertEquals(movement_list[0].getQuantity(), 1.5) - self.assertEquals(movement_list[1].getQuantityUnit(), - self.unit_piece_quantity_unit) - self.assertEquals(movement_list[1].getQuantity(), 5) + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getSourceValue()) - + order_line.setDestinationValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getDestinationValue()) - def _acceptDivergenceOnInvoice(self, invoice, divergence_list): - builder_list = invoice.getBuilderList() - self.assertEquals(2, len(builder_list)) - for builder in builder_list: - builder.solveDivergence(invoice.getRelativeUrl(), - divergence_to_accept_list=divergence_list) + order_line.setSourceSectionValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getSourceSectionValue()) - def test_accept_quantity_divergence_on_invoice_with_stopped_packing_list( - self, quiet=quiet): - sequence_list = SequenceList() - sequence = sequence_list.addSequenceString(self.PACKING_LIST_DEFAULT_SEQUENCE) - sequence_list.play(self, quiet=quiet) + # make sure destination_section != source_section, this might be needed by + # some rules + order_line.setSourceSectionValue(order_line.getDestinationSectionValue()) - packing_list = sequence.get('packing_list') - packing_list_line = packing_list.getMovementList()[0] - previous_quantity = packing_list_line.getQuantity() - - packing_list.setReady() - packing_list.start() - packing_list.stop() - self.assertEquals('stopped', packing_list.getSimulationState()) + order_line.setDestinationSectionValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getDestinationSectionValue()) + + order_line.setSourceAdministrationValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getSourceAdministrationValue()) + + order_line.setDestinationAdministrationValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getDestinationAdministrationValue()) + + order_line.setSourceDecisionValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getSourceDecisionValue()) + + order_line.setDestinationDecisionValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getDestinationDecisionValue()) + + order_line.setSourceProjectValue(other_project) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_project, + invoice_movement.getSourceProjectValue()) + + order_line.setDestinationProjectValue(other_project) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_project, + invoice_movement.getDestinationProjectValue()) + + order_line.setSourcePaymentValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getSourcePaymentValue()) + + order_line.setDestinationPaymentValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getDestinationPaymentValue()) + + order_line.setSourceFunctionValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getSourceFunctionValue()) + + order_line.setDestinationFunctionValue(other_entity) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_entity, + invoice_movement.getDestinationFunctionValue()) + + self.assertNotEquals(123, order_line.getPrice()) + order_line.setPrice(123) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(123, + invoice_movement.getPrice()) + + self.assertNotEquals(456, order_line.getQuantity()) + order_line.setQuantity(456) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(456, + invoice_movement.getQuantity()) + + other_resource = self.portal.product_module.newContent( + portal_type='Product', + title='Other Resource') + order_line.setResourceValue(other_resource) transaction.commit() self.tic() + # after changing 'resource', related simulation movement will be + # replaced with another id, and we need to find the appropriate one + # here. + delivery_movement = related_applied_rule.contentValues()[0] + invoice_applied_rule = delivery_movement.contentValues()[0] + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(other_resource, + invoice_movement.getResourceValue()) - invoice = packing_list.getCausalityRelatedValue( - portal_type=self.invoice_portal_type) - self.assertNotEquals(invoice, None) - invoice_line_list = invoice.getMovementList() - self.assertEquals(1, len(invoice_line_list)) - invoice_line = invoice_line_list[0] - - new_quantity = invoice_line.getQuantity() * 2 - invoice_line.setQuantity(new_quantity) - + order_line.setStartDate(DateTime(2001, 02, 03)) transaction.commit() self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(DateTime(2001, 02, 03), + invoice_movement.getStartDate()) - self.assertTrue(invoice.isDivergent()) - divergence_list = invoice.getDivergenceList() - self.assertEquals(1, len(divergence_list)) - - divergence = divergence_list[0] - self.assertEquals('quantity', divergence.tested_property) + order_line.setStopDate(DateTime(2002, 03, 04)) + transaction.commit() + self.tic() + invoice_movement = invoice_applied_rule.contentValues()[0] + self.assertEquals(DateTime(2002, 03, 04), + invoice_movement.getStopDate()) - # accept decision - self._acceptDivergenceOnInvoice(invoice, divergence_list) + def test_modify_planned_order_invoice_transaction_rule(self): + """ + tests that modifying a planned order affects movements from invoice + transaction rule + """ + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource', + product_line='apparel') + currency = self.portal.currency_module.newContent( + portal_type='Currency', + title='Currency', + base_unit_quantity=0.01) + self.createInvoiceTransactionRule(currency) + client = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Client', + default_address_region=self.default_region) + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Vendor', + default_address_region=self.default_region) + order = self.portal.getDefaultModule(self.order_portal_type).newContent( + portal_type=self.order_portal_type, + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client, + start_date=DateTime(2008, 1, 1), + price_currency_value=currency, + title='Order') + order_line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=resource, + quantity=1, + price=2) + other_entity = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Other Entity', + default_address_region=self.default_region) + other_project = self.portal.project_module.newContent( + portal_type='Project', + title='Other Project') + order.plan() transaction.commit() self.tic() - self.assertEquals('solved', invoice.getCausalityState()) + self.assertEquals('planned', order.getSimulationState()) - self.assertEquals([], invoice.getDivergenceList()) - self.assertEquals(new_quantity, invoice_line.getQuantity()) - self.assertEquals(new_quantity, - invoice_line.getDeliveryRelatedValue(portal_type='Simulation Movement' - ).getQuantity()) + related_applied_rule = order.getCausalityRelatedValue( + portal_type='Applied Rule') + order_movement = related_applied_rule.contentValues()[0] + delivery_applied_rule = order_movement.contentValues()[0] + delivery_movement = delivery_applied_rule.contentValues()[0] + invoice_applied_rule = delivery_movement.contentValues()[0] + invoice_movement = invoice_applied_rule.contentValues()[0] + invoice_transaction_applied_rule = invoice_movement.contentValues()[0] - self.assertEquals([], packing_list.getDivergenceList()) - self.assertEquals('solved', packing_list.getCausalityState()) - - def _adoptDivergenceOnInvoice(self, invoice, divergence_list): - builder_list = invoice.getBuilderList() - self.assertEquals(2, len(builder_list)) - for builder in builder_list: - builder.solveDivergence(invoice.getRelativeUrl(), - divergence_to_adopt_list=divergence_list) + # utility function to return the simulation movement that should be used + # for "income" line + def getIncomeSimulationMovement(applied_rule): + for movement in applied_rule.contentValues(): + if movement.getDestination() == 'account_module/purchase'\ + and movement.getSource() == 'account_module/sale': + return movement + self.fail('Income movement not found') - def test_adopt_quantity_divergence_on_invoice_line_with_stopped_packing_list( - self, quiet=quiet): - # #1053 - sequence_list = SequenceList() - sequence = sequence_list.addSequenceString(self.PACKING_LIST_DEFAULT_SEQUENCE) - sequence_list.play(self, quiet=quiet) + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) - packing_list = sequence.get('packing_list') - packing_list_line = packing_list.getMovementList()[0] - previous_quantity = packing_list_line.getQuantity() - previous_resource = packing_list_line.getResource() - previous_price = packing_list_line.getPrice() - - packing_list.setReady() - packing_list.start() - packing_list.stop() - self.assertEquals('stopped', packing_list.getSimulationState()) + order_line.setSourceSectionValue(other_entity) transaction.commit() self.tic() + self.assertEquals(other_entity, + invoice_transaction_movement.getSourceSectionValue()) - invoice = packing_list.getCausalityRelatedValue( - portal_type=self.invoice_portal_type) - self.assertNotEquals(invoice, None) - invoice_line_list = invoice.getMovementList() - self.assertEquals(1, len(invoice_line_list)) - invoice_line = invoice_line_list[0] + # make sure destination_section != source_section, this might be needed by + # some rules + order_line.setSourceSectionValue(order_line.getDestinationSectionValue()) - new_quantity = invoice_line.getQuantity() * 2 - invoice_line.setQuantity(new_quantity) - + order_line.setDestinationSectionValue(other_entity) transaction.commit() self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getDestinationSectionValue()) - self.assertTrue(invoice.isDivergent()) - divergence_list = invoice.getDivergenceList() - self.assertEquals(1, len(divergence_list)) - - divergence = divergence_list[0] - self.assertEquals('quantity', divergence.tested_property) + order_line.setSourceAdministrationValue(other_entity) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getSourceAdministrationValue()) - # adopt prevision - self._adoptDivergenceOnInvoice(invoice, divergence_list) + order_line.setDestinationAdministrationValue(other_entity) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getDestinationAdministrationValue()) + order_line.setSourceDecisionValue(other_entity) transaction.commit() self.tic() - self.assertEquals([], invoice.getDivergenceList()) - self.assertEquals('solved', invoice.getCausalityState()) + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getSourceDecisionValue()) - self.assertEquals(1, - len(invoice.getMovementList(portal_type=self.invoice_line_portal_type))) - self.assertEquals(0, - len(invoice.getMovementList(portal_type=self.invoice_transaction_line_portal_type))) + order_line.setDestinationDecisionValue(other_entity) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getDestinationDecisionValue()) - self.assertEquals(previous_resource, invoice_line.getResource()) - self.assertEquals(previous_quantity, invoice_line.getQuantity()) - self.assertEquals(previous_price, invoice_line.getPrice()) - self.assertEquals(previous_quantity, - invoice_line.getDeliveryRelatedValue(portal_type='Simulation Movement' - ).getQuantity()) + order_line.setSourceProjectValue(other_project) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_project, + invoice_transaction_movement.getSourceProjectValue()) - self.assertEquals([], packing_list.getDivergenceList()) - self.assertEquals('solved', packing_list.getCausalityState()) - + order_line.setDestinationProjectValue(other_project) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_project, + invoice_transaction_movement.getDestinationProjectValue()) + order_line.setSourceFunctionValue(other_entity) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getSourceFunctionValue()) -class TestSaleInvoiceMixin(TestInvoiceMixin, - ERP5TypeTestCase): - """Test sale invoice are created from orders then packing lists. + order_line.setDestinationFunctionValue(other_entity) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getDestinationFunctionValue()) - Those tests methods only work for sale, because sale and purchase invoice - are not built at the same time on packing list workflow. - """ - quiet = 0 - invoice_portal_type = 'Sale Invoice Transaction' - invoice_line_portal_type = 'Invoice Line' - invoice_cell_portal_type = 'Invoice Cell' - invoice_transaction_line_portal_type = 'Sale Invoice Transaction Line' - payment_portal_type = 'Payment Transaction' + order_line.setSourcePaymentValue(other_entity) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getSourcePaymentValue()) - # default sequence for one line of not varianted resource. - PACKING_LIST_DEFAULT_SEQUENCE = """ - stepCreateEntities - stepCreateCurrency - stepCreateSaleInvoiceTransactionRule - stepCreateOrder - stepSetOrderProfile - stepSetOrderPriceCurrency - stepCreateNotVariatedResource - stepTic - stepCreateOrderLine - stepSetOrderLineResource - stepSetOrderLineDefaultValues - stepOrderOrder - stepTic - stepCheckDeliveryBuilding - stepConfirmOrder - stepTic - stepCheckOrderRule - stepCheckOrderSimulation - stepCheckDeliveryBuilding - stepAddPackingListContainer - stepAddPackingListContainerLine - stepSetContainerLineFullQuantity - stepTic - stepCheckPackingListIsPacked - """ + order_line.setDestinationPaymentValue(other_entity) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(other_entity, + invoice_transaction_movement.getDestinationPaymentValue()) - # default sequence for two lines of not varianted resource. - PACKING_LIST_TWO_LINES_DEFAULT_SEQUENCE = """ - stepCreateEntities - stepCreateCurrency - stepCreateSaleInvoiceTransactionRule - stepCreateOrder - stepSetOrderProfile - stepSetOrderPriceCurrency - stepCreateNotVariatedResource - stepTic - stepCreateOrderLine - stepSetOrderLineResource - stepSetOrderLineDefaultValues - stepCreateNotVariatedResource - stepTic - stepCreateOrderLine - stepSetOrderLineResource - stepSetOrderLineDefaultValues - stepOrderOrder - stepTic - stepCheckDeliveryBuilding - stepConfirmOrder - stepTic - stepCheckOrderRule - stepCheckOrderSimulation - stepCheckDeliveryBuilding - stepAddPackingListContainer - stepAddPackingListContainerLine - stepTic - stepSetContainerFullQuantity - stepTic - stepCheckPackingListIsPacked - """ + order_line.setQuantity(1) + order_line.setPrice(123) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(123, + invoice_transaction_movement.getQuantity()) - # default sequence for one line of not varianted resource. - TWO_PACKING_LIST_DEFAULT_SEQUENCE = """ - stepCreateEntities - stepCreateCurrency - stepCreateSaleInvoiceTransactionRule - stepCreateOrder - stepSetOrderProfile - stepSetOrderPriceCurrency - stepCreateNotVariatedResource - stepTic - stepCreateOrderLine - stepSetOrderLineResource - stepSetOrderLineDefaultValues - stepOrderOrder - stepTic - stepCheckDeliveryBuilding - stepConfirmOrder - stepTic - stepCheckOrderRule - stepCheckOrderSimulation - stepCheckDeliveryBuilding - stepDecreasePackingListLineQuantity - stepCheckPackingListIsCalculating - stepTic - stepCheckPackingListIsDiverged - stepSplitAndDeferPackingList - stepTic - stepCheckPackingListIsSolved - stepCheckPackingListSplitted - stepAddPackingListContainer - stepAddPackingListContainerLine - stepSetContainerLineFullQuantity - stepTic - stepCheckPackingListIsPacked - stepDefineNewPackingListContainer - stepTic - stepCheckNewPackingListIsPacked - """ + order_line.setQuantity(456) + order_line.setPrice(1) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(456, + invoice_transaction_movement.getQuantity()) - def modifyPackingListState(self, transition_name, - sequence,packing_list=None): - """ calls the workflow for the packing list """ - if packing_list is None: - packing_list = sequence.get('packing_list') - packing_list.portal_workflow.doActionFor(packing_list, transition_name) + order_line.setStartDate(DateTime(2001, 02, 03)) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(DateTime(2001, 02, 03), + invoice_transaction_movement.getStartDate()) - def stepSetReadyPackingList(self, sequence=None, sequence_list=None, **kw): - """ set the Packing List as Ready. This must build the invoice. """ - self.modifyPackingListState('set_ready_action', sequence=sequence) - packing_list = sequence.get('packing_list') - self.assertEquals(packing_list.getSimulationState(), 'ready') + order_line.setStopDate(DateTime(2002, 03, 04)) + transaction.commit() + self.tic() + self.assertEquals(3, len(invoice_transaction_applied_rule)) + invoice_transaction_movement = getIncomeSimulationMovement( + invoice_transaction_applied_rule) + self.assertEquals(DateTime(2002, 03, 04), + invoice_transaction_movement.getStopDate()) - def stepSetReadyNewPackingList(self, sequence=None, - sequence_list=None, **kw): - """ set the Packing List as Ready. This must build the invoice. """ - packing_list = sequence.get('new_packing_list') - self.modifyPackingListState('set_ready_action', sequence=sequence, - packing_list=packing_list) - self.assertEquals(packing_list.getSimulationState(), 'ready') - def stepStartPackingList(self, sequence=None, sequence_list=None, **kw): - self.modifyPackingListState('start_action', sequence=sequence) - packing_list = sequence.get('packing_list') - self.assertEquals(packing_list.getSimulationState(), 'started') + def test_Invoice_viewAsODT(self): + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource',) + client = self.portal.organisation_module.newContent( + portal_type='Organisation', title='Client') + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', title='Vendor') + invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent( + portal_type=self.invoice_portal_type, + start_date=DateTime(2008, 12, 31), + title='Invoice', + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client) + line = invoice.newContent(portal_type=self.invoice_line_portal_type, + resource_value=resource, + quantity=10, + price=3) + invoice.confirm() + transaction.commit() + self.tic() - def stepStartNewPackingList(self, sequence=None, sequence_list=None, **kw): - packing_list = sequence.get('new_packing_list') - self.modifyPackingListState('start_action', sequence=sequence, - packing_list=packing_list) - self.assertEquals(packing_list.getSimulationState(), 'started') + odt = invoice.Invoice_viewAsODT() + from Products.ERP5OOo.tests.utils import Validator + odf_validator = Validator() + err_list = odf_validator.validate(odt) + if err_list: + self.fail(''.join(err_list)) - def stepStopPackingList(self, sequence=None, sequence_list=None, **kw): - self.modifyPackingListState('stop_action', sequence=sequence) - packing_list = sequence.get('packing_list') - self.assertEquals(packing_list.getSimulationState(), 'stopped') + def test_Invoice_viewAsODT_empty_image(self): + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource',) + client = self.portal.organisation_module.newContent( + portal_type='Organisation', title='Client') + client_logo = client.newContent(portal_type='Image', + id='default_image') + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', title='Vendor') + vendor_logo = vendor.newContent(portal_type='Image', + id='default_image') + self.assertEquals(0, vendor_logo.getSize()) + self.assertEquals(0, vendor.getDefaultImageWidth()) + self.assertEquals(0, vendor.getDefaultImageHeight()) + invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent( + portal_type=self.invoice_portal_type, + start_date=DateTime(2008, 12, 31), + title='Invoice', + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client) + line = invoice.newContent(portal_type=self.invoice_line_portal_type, + resource_value=resource, + quantity=10, + price=3) + invoice.confirm() + transaction.commit() + self.tic() - def stepDeliverPackingList(self, sequence=None, sequence_list=None, **kw): - self.modifyPackingListState('deliver_action', sequence=sequence) - packing_list = sequence.get('packing_list') - self.assertEquals(packing_list.getSimulationState(), 'delivered') + odt = invoice.Invoice_viewAsODT() + from Products.ERP5OOo.tests.utils import Validator + odf_validator = Validator() + err_list = odf_validator.validate(odt) + if err_list: + self.fail(''.join(err_list)) - def stepCancelPackingList(self, sequence=None, sequence_list=None, **kw): - self.modifyPackingListState('cancel_action', sequence=sequence) - packing_list = sequence.get('packing_list') - self.assertEquals(packing_list.getSimulationState(), 'cancelled') + # the <draw:image> should not be present, because there's no logo + parser = OOoParser() + parser.openFromString(odt) + style_xml = parser.oo_files['styles.xml'] + self.assert_('<draw:image' not in style_xml) - def modifyInvoiceState(self, transition_name, - sequence,invoice=None): - """ calls the workflow for the invoice """ - if invoice is None: - invoice = sequence.get('invoice') - invoice.portal_workflow.doActionFor(invoice, transition_name) + def test_Invoice_viewAsODT_invalid_image(self): + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource',) + file_data = FileUpload(__file__, 'rb') + client = self.portal.organisation_module.newContent( + portal_type='Organisation', title='Client') + client_logo = client.newContent(portal_type='Image', + id='default_image', + file=file_data) + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', title='Vendor') + vendor_logo = vendor.newContent(portal_type='Image', + id='default_image', + file=file_data) - def stepStartInvoice(self, sequence=None, sequence_list=None, **kw): - self.modifyInvoiceState('start_action', sequence=sequence) - invoice = sequence.get('invoice') - self.assertEquals(invoice.getSimulationState(), 'started') + # width and height of an invalid image are -1 according to + # OFS.Image.getImageInfo maybe this is not what we want here ? + self.assertEquals(-1, vendor.getDefaultImageWidth()) + self.assertEquals(-1, vendor.getDefaultImageHeight()) - def stepStartNewInvoice(self, sequence=None, sequence_list=None, **kw): - invoice = sequence.get('new_invoice') - self.modifyInvoiceState('start_action', sequence=sequence, - invoice=invoice) - self.assertEquals(invoice.getSimulationState(), 'started') + invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent( + portal_type=self.invoice_portal_type, + start_date=DateTime(2008, 12, 31), + title='Invoice', + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client) + line = invoice.newContent(portal_type=self.invoice_line_portal_type, + resource_value=resource, + quantity=10, + price=3) + invoice.confirm() + transaction.commit() + self.tic() - def stepStopInvoice(self, sequence=None, sequence_list=None, **kw): - self.modifyInvoiceState('stop_action', sequence=sequence) - invoice = sequence.get('invoice') - self.assertEquals(invoice.getSimulationState(), 'stopped') + odt = invoice.Invoice_viewAsODT() + from Products.ERP5OOo.tests.utils import Validator + odf_validator = Validator() + err_list = odf_validator.validate(odt) + if err_list: + self.fail(''.join(err_list)) - def stepDeliverInvoice(self, sequence=None, sequence_list=None, **kw): - self.modifyInvoiceState('deliver_action', sequence=sequence) - invoice = sequence.get('invoice') - self.assertEquals(invoice.getSimulationState(), 'delivered') + def test_invoice_building_with_cells(self): + # if the order has cells, the invoice built from that order must have + # cells too + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource', + variation_base_category_list=['size']) + currency = self.portal.currency_module.newContent( + portal_type='Currency', + title='Currency') - def stepCancelInvoice(self, sequence=None, sequence_list=None, **kw): - self.modifyInvoiceState('cancel_action', sequence=sequence) - invoice = sequence.get('invoice') - self.assertEquals(invoice.getSimulationState(), 'cancelled') + client = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Client') + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Vendor') + order = self.portal.getDefaultModule(self.order_portal_type).newContent( + portal_type=self.order_portal_type, + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client, + start_date=DateTime(2008, 1, 1), + price_currency_value=currency, + title='Order') + order_line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=resource,) + order_line.setVariationBaseCategoryList(('size', )) + order_line.setVariationCategoryList(['size/Baby', 'size/Child/32']) + order_line.updateCellRange() - def stepSwitchPackingLists(self, sequence=None, sequence_list=None, **kw): - packing_list = sequence.get('packing_list') - new_packing_list = sequence.get('new_packing_list') - #invoice = new_packing_list.getDefaultCausalityRelatedValue( - #portal_type=self.invoice_portal_type) - sequence.edit(packing_list=new_packing_list, - new_packing_list=packing_list)#, invoice=invoice) + cell_baby = order_line.newCell('size/Baby', base_id='movement', + portal_type=self.order_cell_portal_type) + cell_baby.edit(quantity=10, + price=4, + variation_category_list=['size/Baby'], + mapped_value_property_list=['quantity', 'price'],) - def stepSwitchInvoices(self, sequence=None, sequence_list=None, **kw): - invoice = sequence.get('invoice') - new_invoice = sequence.get('new_invoice') - sequence.edit(invoice=new_invoice, new_invoice=invoice) + cell_child_32 = order_line.newCell('size/Child/32', base_id='movement', + portal_type=self.order_cell_portal_type) + cell_child_32.edit(quantity=20, + price=5, + variation_category_list=['size/Child/32'], + mapped_value_property_list=['quantity', 'price'],) + order.confirm() + transaction.commit() + self.tic() - def stepCheckPackingListSimulation(self, sequence=None, sequence_list=None, **kw): - """ checks that simulation movements related to the packing list are OK """ - packing_list = sequence.get('packing_list') - order = sequence.get('order') - order_root_applied_rule = order.getCausalityRelatedValueList( - portal_type = 'Applied Rule')[0] - # check simulation movements from this packing list - for movement in packing_list.getMovementList() : - simulation_movement_list = movement.getOrderRelatedValueList() - self.assertNotEquals(len(simulation_movement_list), 0) - total_quantity = 0 - for simulation_movement in simulation_movement_list : - total_quantity += simulation_movement.getQuantity() - # check that those movements come from the same root applied - # rule than the order. - self.assertEquals( simulation_movement.getRootAppliedRule(), - order_root_applied_rule) - self.assertEquals(total_quantity, movement.getQuantity()) + related_packing_list = order.getCausalityRelatedValue( + portal_type=self.packing_list_portal_type) + self.assertNotEquals(related_packing_list, None) - def stepCheckInvoiceBuilding(self, sequence=None, sequence_list=None, **kw): - """ - checks that the invoice is built with the default_invoice_builder - """ - packing_list = sequence.get('packing_list') - related_invoice_list = packing_list.getCausalityRelatedValueList( - portal_type=self.invoice_portal_type) + related_packing_list.start() + related_packing_list.stop() + transaction.commit() + self.tic() - packing_list_building_state = 'started' - packing_list_state = packing_list.getSimulationState() - if packing_list_state != packing_list_building_state : - self.assertEquals(0, len(related_invoice_list)) - else: - self.assertEquals(1, len(related_invoice_list)) + related_invoice = related_packing_list.getCausalityRelatedValue( + portal_type=self.invoice_portal_type) + self.assertNotEquals(related_invoice, None) - invoice = related_invoice_list[0].getObject() - self.failUnless(invoice is not None) - # Invoices created by Delivery Builder are in confirmed state - self.assertEquals(invoice.getSimulationState(), 'confirmed') + line_list = related_invoice.contentValues( + portal_type=self.invoice_line_portal_type) + self.assertEquals(1, len(line_list)) + invoice_line = line_list[0] - # Get the list of simulation movements of packing list ... - packing_list_simulation_movement_list = [] - for packing_list_movement in packing_list.getMovementList(): - packing_list_simulation_movement_list.extend( - packing_list_movement.getDeliveryRelatedValueList()) - # ... invoice simulation movement are their childrens. - simulation_movement_list = [] - for p_l_simulation_movement in packing_list_simulation_movement_list : - for applied_rule in p_l_simulation_movement.objectValues() : - simulation_movement_list.extend(applied_rule.objectValues()) + self.assertEquals(resource, invoice_line.getResourceValue()) + self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList()) + self.assertEquals(2, + len(invoice_line.getCellValueList(base_id='movement'))) - # First, test if each Simulation Movement is related to an - # Invoice Movement - invoice_relative_url = invoice.getRelativeUrl() - for simulation_movement in simulation_movement_list: - invoice_movement_list = simulation_movement.getDeliveryValueList() - self.assertEquals(len(invoice_movement_list), 1) - invoice_movement = invoice_movement_list[0] - self.failUnless(invoice_movement is not None) - self.assert_(invoice_movement.getRelativeUrl().\ - startswith(invoice_relative_url)) + cell_baby = invoice_line.getCell('size/Baby', base_id='movement') + self.assertNotEquals(cell_baby, None) + self.assertEquals(resource, cell_baby.getResourceValue()) + self.assertEquals(10, cell_baby.getQuantity()) + self.assertEquals(4, cell_baby.getPrice()) + self.assertTrue('size/Baby' in + cell_baby.getVariationCategoryList()) + self.assertTrue(cell_baby.isMemberOf('size/Baby')) - # Then, test if each Invoice movement is equals to the sum of somes - # Simulation Movements - for invoice_movement in invoice.getMovementList(portal_type = [ - self.invoice_cell_portal_type, - self.invoice_line_portal_type]) : - related_simulation_movement_list = invoice_movement.\ - getDeliveryRelatedValueList(portal_type='Simulation Movement') - quantity = 0 - total_price = 0 - invoice_movement_quantity = invoice_movement.getQuantity() - for related_simulation_movement in related_simulation_movement_list: - quantity += related_simulation_movement.getQuantity() - total_price += related_simulation_movement.getPrice() *\ - related_simulation_movement.getQuantity() - # Test resource - self.assertEquals(invoice_movement.getResource(), \ - related_simulation_movement.getResource()) - # Test resource variation - self.assertEquals(invoice_movement.getVariationText(), \ - related_simulation_movement.getVariationText()) - self.assertEquals(invoice_movement.getVariationCategoryList(), \ - related_simulation_movement.getVariationCategoryList()) - # Test acquisition - self.checkAcquisition(invoice_movement, - related_simulation_movement) - # Test delivery ratio - self.assertEquals(related_simulation_movement.getQuantity() /\ - invoice_movement_quantity, \ - related_simulation_movement.getDeliveryRatio()) + cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement') + self.assertNotEquals(cell_child_32, None) + self.assertEquals(resource, cell_child_32.getResourceValue()) + self.assertEquals(20, cell_child_32.getQuantity()) + self.assertEquals(5, cell_child_32.getPrice()) + self.assertTrue('size/Child/32' in + cell_child_32.getVariationCategoryList()) + self.assertTrue(cell_child_32.isMemberOf('size/Child/32')) + + + + def test_invoice_created_from_packing_list_with_no_order(self): + # if the order has cells and an aggregate, the invoice built + #from that order must have + # cells too + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource', + variation_base_category_list=['size']) + currency = self.portal.currency_module.newContent( + portal_type='Currency', + title='Currency') - self.assertEquals(quantity, invoice_movement.getQuantity()) - # Test price - self.assertEquals(total_price / quantity, invoice_movement.getPrice()) + client = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Client') + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Vendor') + no_order_packing_list = \ +self.portal.getDefaultModule(self.packing_list_portal_type).newContent( + portal_type=self.packing_list_portal_type, + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client, + start_date=DateTime(2008, 1, 1), + price_currency_value=currency, + title='Order') - sequence.edit(invoice = invoice) + packing_list_line = no_order_packing_list.newContent( + portal_type=self.packing_list_line_portal_type, + resource_value=resource,) + packing_list_line.setVariationBaseCategoryList(('size', )) + packing_list_line.setVariationCategoryList(['size/Baby', 'size/Child/32']) + packing_list_line.updateCellRange() - # Test causality - self.assertEquals(len(invoice.getCausalityValueList( - portal_type = self.packing_list_portal_type)), 1) - self.assertEquals(invoice.getCausalityValue(), packing_list) + cell_baby = packing_list_line.newCell('size/Baby', base_id='movement', + portal_type=self.packing_list_cell_portal_type) + cell_baby.edit(quantity=10, + price=4, + variation_category_list=['size/Baby'], + mapped_value_property_list=['quantity', 'price'],) - # Finally, test getTotalQuantity and getTotalPrice on Invoice - self.assertEquals(packing_list.getTotalQuantity(), - invoice.getTotalQuantity()) - self.assertEquals(packing_list.getTotalPrice(), - invoice.getTotalPrice()) + cell_child_32 = packing_list_line.newCell( + 'size/Child/32',base_id='movement', + portal_type=self.packing_list_cell_portal_type) + cell_child_32.edit(quantity=20, + price=5, + variation_category_list=['size/Child/32'], + mapped_value_property_list=['quantity', 'price'],) + no_order_packing_list.confirm() + transaction.commit() + self.tic() + self.assertNotEquals(no_order_packing_list, None) - def stepCheckPaymentBuilding(self, sequence=None, sequence_list=None, **kw): - """ - checks that the payment is built with the default_payment_builder - """ - invoice = sequence.get('invoice') - related_payment_list = invoice.getCausalityRelatedValueList( - portal_type=self.payment_portal_type) + no_order_packing_list.start() + no_order_packing_list.stop() + transaction.commit() + self.tic() - invoice_building_state = 'started' - invoice_state = invoice.getSimulationState() - if invoice_state != invoice_building_state : - self.assertEquals(0, len(related_payment_list)) - else: - self.assertEquals(1, len(related_payment_list)) + related_invoice = no_order_packing_list.getCausalityRelatedValue( + portal_type=self.invoice_portal_type) + self.assertNotEquals(related_invoice, None) - payment = related_payment_list[0].getObject() - self.failUnless(payment is not None) - # Payments created by Delivery Builder are in planned state - self.assertEquals(payment.getSimulationState(), 'planned') + line_list = related_invoice.contentValues( + portal_type=self.invoice_line_portal_type) + self.assertEquals(1, len(line_list)) + invoice_line = line_list[0] - # Get the list of simulation movements of packing list ... - invoice_simulation_movement_list = [] - for invoice_movement in invoice.getMovementList( - portal_type=self.portal.getPortalAccountingMovementTypeList()): - invoice_simulation_movement_list.extend( - invoice_movement.getDeliveryRelatedValueList()) - # ... payment simulation movement are their childrens. - simulation_movement_list = [] - for p_l_simulation_movement in invoice_simulation_movement_list : - for applied_rule in p_l_simulation_movement.objectValues() : - simulation_movement_list.extend(applied_rule.objectValues()) + self.assertEquals(resource, invoice_line.getResourceValue()) + self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList()) + self.assertEquals(2, + len(invoice_line.getCellValueList(base_id='movement'))) - # First, test if each Simulation Movement is related to an - # Payment Movement - payment_relative_url = payment.getRelativeUrl() - for simulation_movement in simulation_movement_list: - payment_movement_list = simulation_movement.getDeliveryValueList() - self.assertEquals(len(payment_movement_list), 1) - payment_movement = payment_movement_list[0] - self.failUnless(payment_movement is not None) - self.assert_(payment_movement.getRelativeUrl().\ - startswith(payment_relative_url)) + cell_baby = invoice_line.getCell('size/Baby', base_id='movement') + self.assertNotEquals(cell_baby, None) + self.assertEquals(resource, cell_baby.getResourceValue()) + self.assertEquals(10, cell_baby.getQuantity()) + self.assertEquals(4, cell_baby.getPrice()) + self.assertTrue('size/Baby' in + cell_baby.getVariationCategoryList()) + self.assertTrue(cell_baby.isMemberOf('size/Baby')) - # Then, test if each Payment movement is equals to the sum of somes - # Simulation Movements - for payment_movement in payment.getMovementList(): - related_simulation_movement_list = payment_movement.\ - getDeliveryRelatedValueList(portal_type='Simulation Movement') - quantity = 0 - total_price = 0 - payment_movement_quantity = payment_movement.getQuantity() - for related_simulation_movement in related_simulation_movement_list: - quantity += related_simulation_movement.getQuantity() - total_price += related_simulation_movement.getPrice() *\ - related_simulation_movement.getQuantity() - # Test resource - self.assertEquals(payment_movement.getResource(), \ - related_simulation_movement.getResource()) - # Test resource variation - self.assertEquals(payment_movement.getVariationText(), \ - related_simulation_movement.getVariationText()) - self.assertEquals(payment_movement.getVariationCategoryList(), \ - related_simulation_movement.getVariationCategoryList()) - # Test acquisition - self.checkAcquisition(payment_movement, - related_simulation_movement) - # Test delivery ratio - self.assertEquals(related_simulation_movement.getQuantity() /\ - payment_movement_quantity, \ - related_simulation_movement.getDeliveryRatio()) + cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement') + self.assertNotEquals(cell_child_32, None) + self.assertEquals(resource, cell_child_32.getResourceValue()) + self.assertEquals(20, cell_child_32.getQuantity()) + self.assertEquals(5, cell_child_32.getPrice()) + self.assertTrue('size/Child/32' in + cell_child_32.getVariationCategoryList()) + self.assertTrue(cell_child_32.isMemberOf('size/Child/32')) + + def test_invoice_building_with_cells_and_aggregate(self): + # if the order has cells and an aggregate, the invoice built + #from that order must have + # cells too + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource', + variation_base_category_list=['size']) + currency = self.portal.currency_module.newContent( + portal_type='Currency', + title='Currency') - self.assertEquals(quantity, payment_movement.getQuantity()) - # Test price - self.assertEquals(total_price / quantity, payment_movement.getPrice()) + client = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Client') + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Vendor') + order = self.portal.getDefaultModule(self.order_portal_type).newContent( + portal_type=self.order_portal_type, + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client, + start_date=DateTime(2008, 1, 1), + price_currency_value=currency, + title='Order') - sequence.edit(payment = payment) + order_line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=resource,) + order_line.setVariationBaseCategoryList(('size', )) + order_line.setVariationCategoryList(['size/Baby', 'size/Child/32']) + order_line.updateCellRange() - # Test causality - self.assertEquals(len(payment.getCausalityValueList( - portal_type = self.invoice_portal_type)), 1) - self.assertEquals(payment.getCausalityValue(), invoice) + cell_baby = order_line.newCell('size/Baby', base_id='movement', + portal_type=self.order_cell_portal_type) + cell_baby.edit(quantity=10, + price=4, + variation_category_list=['size/Baby'], + mapped_value_property_list=['quantity', 'price'],) - # Finally, test getTotalQuantity and getTotalPrice on Payment - self.assertEquals(0, payment.getTotalQuantity()) - self.assertEquals(0, payment.getTotalPrice()) + cell_child_32 = order_line.newCell('size/Child/32', base_id='movement', + portal_type=self.order_cell_portal_type) + cell_child_32.edit(quantity=20, + price=5, + variation_category_list=['size/Child/32'], + mapped_value_property_list=['quantity', 'price'],) + order.confirm() + transaction.commit() + self.tic() - def stepCheckInvoicesConsistency(self, sequence=None, sequence_list=None, - **kw): - """ - Checks that all invoices are consistent: - - transaction lines match invoice lines - - no movement is divergent - """ - invoice_list = self.getPortal()['accounting_module'].objectValues() - for invoice in invoice_list: - accounting_state_list = \ - list(self.getPortal().getPortalCurrentInventoryStateList()) - accounting_state_list.append('cancelled') - if invoice.getSimulationState() in accounting_state_list: - invoice_line_list = invoice.contentValues( - portal_type=self.invoice_line_portal_type) - invoice_transaction_line_list = invoice.contentValues( - portal_type=self.invoice_transaction_line_portal_type) - self.assertEquals(3, len(invoice_transaction_line_list)) - expected_price = 0.0 - for line in invoice_line_list: - expected_price += line.getTotalPrice() - for line_id, line_source, line_dest, line_ratio in \ - self.transaction_line_definition_list: - for line in invoice.contentValues( - portal_type=self.invoice_transaction_line_portal_type): - if line.getSource() == 'account_module/%s' % line_source and \ - line.getDestination() == 'account_module/%s' % line_dest: - break - else: - self.fail('No line found that matches %s' % line_id) - resource_precision = line.getResourceValue().getQuantityPrecision() - self.assertEquals(round(line.getQuantity(), resource_precision), - round(expected_price * line_ratio, resource_precision)) + related_packing_list = order.getCausalityRelatedValue( + portal_type=self.packing_list_portal_type) + self.assertNotEquals(related_packing_list, None) - def stepCheckInvoiceLineHasReferenceAndIntIndex(self, sequence=None, **kw): - """Check that the unique invoice line in the invoice has reference and int - index. - """ - invoice = sequence.get('invoice') - invoice_line_list = invoice.contentValues( - portal_type=self.invoice_line_portal_type) - self.assertEquals(1, len(invoice_line_list)) - invoice_line = invoice_line_list[0] - self.assertEquals(1, invoice_line.getIntIndex()) - self.assertEquals('1', invoice_line.getReference()) + related_packing_list.start() + related_packing_list.stop() + transaction.commit() + self.tic() - def stepCheckPackingListInvoice( - self, sequence=None, sequence_list=None, **kw): - """ Checks if the delivery builder is working as expected, - coping the atributes from packing list to invoice.""" - packing_list = sequence.get('packing_list') - related_invoice_list = packing_list.getCausalityRelatedValueList( - portal_type=self.invoice_portal_type) - self.assertEquals(len(related_invoice_list), 1) - invoice = related_invoice_list[0] - self.assertEquals(packing_list.getSource(), invoice.getSource()) - self.assertEquals(packing_list.getDestination(), invoice.getDestination()) - self.assertEquals(packing_list.getDestinationSection(), \ - invoice.getDestinationSection()) - self.assertEquals(packing_list.getSourceSection(), \ - invoice.getSourceSection()) - self.assertEquals(packing_list.getDestinationDecision(), \ - invoice.getDestinationDecision()) - self.assertEquals(packing_list.getSourceDecision(), \ - invoice.getSourceDecision()) - self.assertEquals(packing_list.getDestinationAdministration(), \ - invoice.getDestinationAdministration()) - self.assertEquals(packing_list.getSourceAdministration(), \ - invoice.getSourceAdministration()) - self.assertEquals(packing_list.getDestinationProject(), \ - invoice.getDestinationProject()) - self.assertEquals(packing_list.getSourceProject(), \ - invoice.getSourceProject()) - self.assertEquals(packing_list.getPriceCurrency(), \ - invoice.getPriceCurrency()) + related_invoice = related_packing_list.getCausalityRelatedValue( + portal_type=self.invoice_portal_type) + self.assertNotEquals(related_invoice, None) + line_list = related_invoice.contentValues( + portal_type=self.invoice_line_portal_type) + self.assertEquals(1, len(line_list)) + invoice_line = line_list[0] + self.assertEquals(resource, invoice_line.getResourceValue()) + self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList()) + self.assertEquals(2, + len(invoice_line.getCellValueList(base_id='movement'))) - def stepCheckDeliveryRuleForDeferred( - self, sequence=None, sequence_list=None, **kw): - """ Checks that a delivery rule has been created when we took 'split - and defer' decision on the divergeant Packing List. """ - # TODO + cell_baby = invoice_line.getCell('size/Baby', base_id='movement') + self.assertNotEquals(cell_baby, None) + self.assertEquals(resource, cell_baby.getResourceValue()) + self.assertEquals(10, cell_baby.getQuantity()) + self.assertEquals(4, cell_baby.getPrice()) + self.assertTrue('size/Baby' in + cell_baby.getVariationCategoryList()) + self.assertTrue(cell_baby.isMemberOf('size/Baby')) - def stepCheckDeliveryRuleIsEmpty( - self, sequence=None, sequence_list=None, **kw): - """ Checks that an empty delivery rule is created for the - convergeant Packing List""" - packing_list = sequence.get('packing_list') - self.failUnless(packing_list is not None) - simulation_tool = self.getSimulationTool() - # Check that there is an applied rule for our packing list - rule_list = [x for x in simulation_tool.objectValues() - if x.getCausalityValue()==packing_list] - self.assertEquals(len(rule_list),1) - packing_list_rule = rule_list[0] - sequence.edit(packing_list_rule=packing_list_rule) - rule_line_list = packing_list_rule.objectValues() - packing_list_line_list = packing_list.objectValues() - self.assertEquals(len(packing_list_line_list), - len(rule_line_list)) - self.assertEquals(1, len(rule_line_list)) - rule_line = rule_line_list[0] - packing_list_line = packing_list_line_list[0] - self.assertEquals(rule_line.getQuantity(), 10) - self.assertEquals(rule_line.getPrice(), 100) - self.assertEquals(rule_line.getDeliveryValue(), - packing_list_line) - self.assertEquals(rule_line.getStartDate(), - packing_list_line.getStartDate()) - self.assertEquals(rule_line.getStopDate(), - packing_list_line.getStopDate()) - self.assertEquals(rule_line.getPortalType(), - 'Simulation Movement') + cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement') + self.assertNotEquals(cell_child_32, None) + self.assertEquals(resource, cell_child_32.getResourceValue()) + self.assertEquals(20, cell_child_32.getQuantity()) + self.assertEquals(5, cell_child_32.getPrice()) + self.assertTrue('size/Child/32' in + cell_child_32.getVariationCategoryList()) + self.assertTrue(cell_child_32.isMemberOf('size/Child/32')) + + + def test_description_copied_on_lines(self): + # if the order lines have different descriptions, description must be + # copied in the simulation and on created movements + resource = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource',) + resource2 = self.portal.getDefaultModule( + self.resource_portal_type).newContent( + portal_type=self.resource_portal_type, + title='Resource2',) + currency = self.portal.currency_module.newContent( + portal_type='Currency', + title='Currency') + client = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Client') + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Vendor') + order = self.portal.getDefaultModule(self.order_portal_type).newContent( + portal_type=self.order_portal_type, + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client, + start_date=DateTime(2008, 1, 1), + price_currency_value=currency, + title='Order') - def stepCheckPackingList(self,sequence=None, sequence_list=None,**kw): - """ """ - packing_list_module = self.getSalePackingListModule() - order_rule = sequence.get('order_rule') - order = sequence.get('order') - sale_packing_list_list = [] - for o in packing_list_module.objectValues(): - if o.getCausalityValue() == order: - sale_packing_list_list.append(o) - self.assertEquals(len(sale_packing_list_list), 1) - sale_packing_list = sale_packing_list_list[0] - sale_packing_list_line_list = sale_packing_list.objectValues() - self.assertEquals(len(sale_packing_list_line_list),1) - sale_packing_list_line = sale_packing_list_line_list[0] - product = sequence.get('resource') - self.assertEquals(sale_packing_list_line.getResourceValue(), - product) - self.assertEquals(sale_packing_list_line.getPrice(), - self.price1) - LOG('sale_packing_list_line.showDict()',0, - sale_packing_list_line.showDict()) - self.assertEquals(sale_packing_list_line.getQuantity(), - self.quantity1) - self.assertEquals(sale_packing_list_line.getTotalPrice(), - self.total_price1) - sequence.edit(packing_list = sale_packing_list) + order.newContent(portal_type=self.order_line_portal_type, + quantity=3, + price=10, + description='The first line', + resource_value=resource,) + order.newContent(portal_type=self.order_line_portal_type, + quantity=5, + price=10, + description='The second line', + resource_value=resource2,) - def stepCheckTwoInvoices(self,sequence=None, sequence_list=None, **kw): - """ checks invoice properties are well set. """ - # Now we will check that we have two invoices created - packing_list = sequence.get('packing_list') - invoice_list = packing_list.getCausalityRelatedValueList( - portal_type=self.invoice_portal_type) - self.assertEquals(len(invoice_list),1) - invoice = invoice_list[0] - self.assertEquals(invoice.getSimulationState(), 'confirmed') - sequence.edit(invoice=invoice) - new_packing_list = sequence.get('new_packing_list') - new_invoice_list = new_packing_list.getCausalityRelatedValueList( - portal_type=self.invoice_portal_type) - self.assertEquals(len(new_invoice_list),1) - new_invoice = new_invoice_list[0] - self.assertEquals(new_invoice.getSimulationState(), 'confirmed') - sequence.edit(new_invoice=new_invoice) + order.confirm() + transaction.commit() + self.tic() - def stepStartTwoInvoices(self,sequence=None, sequence_list=None, **kw): - """ start both invoices. """ - portal = self.getPortal() - invoice = sequence.get('invoice') - new_invoice = sequence.get('new_invoice') - portal.portal_workflow.doActionFor(invoice, 'start_action') - portal.portal_workflow.doActionFor(new_invoice, 'start_action') + related_packing_list = order.getCausalityRelatedValue( + portal_type=self.packing_list_portal_type) + self.assertNotEquals(related_packing_list, None) + + movement_list = related_packing_list.getMovementList() + self.assertEquals(2, len(movement_list)) + self.assertEquals(['The first line'], + [m.getDescription() for m in movement_list if m.getQuantity() == 3]) + self.assertEquals(['The second line'], + [m.getDescription() for m in movement_list if m.getQuantity() == 5]) - def stepCheckTwoInvoicesTransactionLines(self,sequence=None, - sequence_list=None, **kw): - """ checks invoice properties are well set. """ - invoice = sequence.get('invoice') - new_invoice = sequence.get('new_invoice') - self.assertEquals(3,len(invoice.objectValues( - portal_type=self.invoice_transaction_line_portal_type))) - self.assertEquals(3,len(new_invoice.objectValues( - portal_type=self.invoice_transaction_line_portal_type))) - account_module = self.getAccountModule() - found_dict = {} - for line in invoice.objectValues( - portal_type=self.invoice_transaction_line_portal_type): - source_id = line.getSourceId() - found_dict[source_id] = line.getQuantity() - total_price = (self.default_quantity-1) * self.default_price - expected_dict = { - 'sale' : total_price, - 'receivable_vat' : total_price * self.vat_rate, - 'customer' : - (total_price + total_price * self.vat_rate) - } - self.failIfDifferentSet(expected_dict.keys(),found_dict.keys()) - for key in found_dict.keys(): - self.assertAlmostEquals(expected_dict[key],found_dict[key],places=2) - found_dict = {} - for line in new_invoice.objectValues( - portal_type=self.invoice_transaction_line_portal_type): - source_id = line.getSourceId() - found_dict[source_id] = line.getQuantity() - total_price = 1 * self.default_price - expected_dict = { - 'sale' : total_price, - 'receivable_vat' : total_price * self.vat_rate, - 'customer' : - (total_price + total_price * self.vat_rate) - } - self.failIfDifferentSet(expected_dict.keys(), found_dict.keys()) - for key in found_dict.keys(): - self.assertAlmostEquals(expected_dict[key], found_dict[key], places=2) + related_packing_list.start() + related_packing_list.stop() + transaction.commit() + self.tic() - def stepRebuildAndCheckNothingIsCreated(self, sequence=None, - sequence_list=None, **kw): - """Rebuilds with sale_invoice_builder and checks nothing more is - created. """ - accounting_module = self.getAccountingModule() - portal_type_list = ('Sale Invoice Transaction', 'Purchase Invoice Transaction') - sale_invoice_transaction_count = len(accounting_module.objectValues( - portal_type=portal_type_list)) - for builder in self.getPortal().portal_deliveries.objectValues(): - builder.build() - self.assertEquals(sale_invoice_transaction_count, - len(accounting_module.objectValues( - portal_type=portal_type_list))) + related_invoice = related_packing_list.getCausalityRelatedValue( + portal_type=self.invoice_portal_type) + self.assertNotEquals(related_invoice, None) - def stepModifyInvoicesDate(self, sequence=None, - sequence_list=None, **kw): - """Change invoice date""" - invoice = sequence.get('invoice') - new_invoice = sequence.get('new_invoice') - invoice.edit(start_date=self.datetime, - stop_date=self.datetime+1) - new_invoice.edit(start_date=self.datetime, - stop_date=self.datetime+1) + movement_list = related_invoice.getMovementList( + portal_type=self.invoice_line_portal_type) + self.assertEquals(2, len(movement_list)) + self.assertEquals(['The first line'], + [m.getDescription() for m in movement_list if m.getQuantity() == 3]) + self.assertEquals(['The second line'], + [m.getDescription() for m in movement_list if m.getQuantity() == 5]) - def stepRemoveDateMovementGroupForTransactionBuilder(self, sequence=None, - sequence_list=None, **kw): + + def test_CopyAndPaste(self): + """Test copy on paste on Invoice. + When an invoice is copy/pasted, references should be resetted. """ - Remove DateMovementGroup + accounting_module = self.portal.accounting_module + invoice = accounting_module.newContent( + portal_type=self.invoice_portal_type) + invoice.edit(reference='reference', + source_reference='source_reference', + destination_reference='destination_reference',) + cb_data = accounting_module.manage_copyObjects([invoice.getId()]) + copied, = accounting_module.manage_pasteObjects(cb_data) + new_invoice = accounting_module[copied['new_id']] + self.assertNotEquals(invoice.getReference(), + new_invoice.getReference()) + self.assertNotEquals(invoice.getSourceReference(), + new_invoice.getSourceReference()) + self.assertNotEquals(invoice.getDestinationReference(), + new_invoice.getDestinationReference()) + + def test_delivery_mode_and_incoterm_on_invoice(self): """ - portal = self.getPortal() - builder = portal.portal_deliveries.sale_invoice_transaction_builder - delivery_movement_group_list = builder.getDeliveryMovementGroupList() - uf = self.getPortal().acl_users - uf._doAddUser('admin', '', ['Manager'], []) - user = uf.getUserById('admin').__of__(uf) - newSecurityManager(None, user) - for movement_group in delivery_movement_group_list: - if movement_group.getPortalType() == 'Property Movement Group': - # it contains 'start_date' and 'stop_date' only, so we remove - # movement group itself. - builder.deleteContent(movement_group.getId()) - builder.newContent( - portal_type = 'Parent Explanation Movement Group', - collect_order_group='delivery', - int_index=len(delivery_movement_group_list)+1 - ) - user = uf.getUserById('test_invoice_user').__of__(uf) - newSecurityManager(None, user) + test that categories delivery_mode and incoterm are copied on + the invoice by the delivery builder + """ + resource = self.portal.product_module.newContent( + portal_type='Product', + title='Resource', + product_line='apparel') + currency = self.portal.currency_module.newContent( + portal_type='Currency', + title='euro') + currency.setBaseUnitQuantity(0.01) + self.createInvoiceTransactionRule(currency) + transaction.commit() + self.tic()#execute transaction + client = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Client', + default_address_region=self.default_region) + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Vendor', + default_address_region=self.default_region) + order = self.portal.getDefaultModule(self.order_portal_type).newContent( + portal_type=self.order_portal_type, + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client, + start_date=DateTime(2008,10, 21), + price_currency_value=currency, + delivery_mode=self.mail_delivery_mode, + incoterm=self.cpt_incoterm, + title='Order') + order_line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=resource, + quantity=5, + price=2) + order.confirm() + transaction.commit() + self.tic() + related_packing_list = order.getCausalityRelatedValue( + portal_type=self.packing_list_portal_type) + self.assertNotEquals(related_packing_list, None) + self.assertEquals(related_packing_list.getDeliveryMode(), + order.getDeliveryMode()) + self.assertEquals(related_packing_list.getIncoterm(), + order.getIncoterm()) + related_packing_list.start() + related_packing_list.stop() + transaction.commit() + self.tic() + related_invoice = related_packing_list.getCausalityRelatedValue( + portal_type=self.invoice_portal_type) + self.assertNotEquals(related_invoice, None) + self.assertEquals(related_invoice.getDeliveryMode(), + order.getDeliveryMode()) + self.assertEquals(related_invoice.getIncoterm(), + order.getIncoterm()) + + + def test_01_quantity_unit_copied(self): + """ + tests that when a resource uses different quantity unit that the + quantity units are copied on the packing list line and then the invoice + line using the delivery builers + """ + resource = self.portal.product_module.newContent( + portal_type='Product', + title='Resource', + product_line='apparel') + resource.setQuantityUnitList([self.unit_piece_quantity_unit, + self.mass_quantity_unit]) + currency = self.portal.currency_module.newContent( + portal_type='Currency', + title='euro') + currency.setBaseUnitQuantity(0.01) + transaction.commit() + self.tic()#execute transaction + client = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Client', + default_address_region=self.default_region) + vendor = self.portal.organisation_module.newContent( + portal_type='Organisation', + title='Vendor', + default_address_region=self.default_region) + order = self.portal.getDefaultModule(self.order_portal_type).newContent( + portal_type=self.order_portal_type, + source_value=vendor, + source_section_value=vendor, + destination_value=client, + destination_section_value=client, + start_date=DateTime(2008,10, 21), + price_currency_value=currency, + delivery_mode=self.mail_delivery_mode, + incoterm=self.cpt_incoterm, + title='Order') + first_order_line = order.newContent( + portal_type=self.order_line_portal_type, + resource_value=resource, + quantity_unit = self.unit_piece_quantity_unit, + quantity=5, + price=3) + second_order_line = order.newContent( + portal_type=self.order_line_portal_type, + resource_value=resource, + quantity_unit=self.mass_quantity_unit, + quantity=1.5, + price=2) + self.assertEquals(first_order_line.getQuantityUnit(), + self.unit_piece_quantity_unit) + self.assertEquals(second_order_line.getQuantityUnit(), + self.mass_quantity_unit) - def stepEditInvoice(self, sequence=None, sequence_list=None, **kw): - """Edit the current invoice, to trigger updateAppliedRule.""" - invoice = sequence.get('invoice') - invoice.edit() + order.confirm() + transaction.commit() + self.tic() + related_packing_list = order.getCausalityRelatedValue( + portal_type=self.packing_list_portal_type) + self.assertNotEquals(related_packing_list, None) + movement_list = related_packing_list.getMovementList() + self.assertEquals(len(movement_list),2) + movement_list = sorted(movement_list, key=lambda x: x.getQuantity()) + self.assertEquals(movement_list[0].getQuantityUnit(), + self.mass_quantity_unit) + self.assertEquals(movement_list[0].getQuantity(), 1.5) + self.assertEquals(movement_list[1].getQuantityUnit(), + self.unit_piece_quantity_unit) + self.assertEquals(movement_list[1].getQuantity(), 5) - # call updateAppliedRule directly, don't rely on edit interactions - rule_reference = 'default_invoice_rule' - self.assertNotEquals(0, - len(self.portal.portal_rules.searchFolder(reference=rule_reference))) - invoice.updateAppliedRule(rule_reference=rule_reference) + related_packing_list.start() + related_packing_list.stop() + related_packing_list.deliver() + transaction.commit() + self.tic() + related_invoice = related_packing_list.getCausalityRelatedValue( + portal_type=self.invoice_portal_type) + self.assertNotEquals(related_invoice, None) + movement_list = related_invoice.getMovementList() + self.assertEquals(len(movement_list),2) + movement_list = sorted(movement_list, key=lambda x: x.getQuantity()) + self.assertEquals(movement_list[0].getQuantityUnit(), + self.mass_quantity_unit) + self.assertEquals(movement_list[0].getQuantity(), 1.5) + self.assertEquals(movement_list[1].getQuantityUnit(), + self.unit_piece_quantity_unit) + self.assertEquals(movement_list[1].getQuantity(), 5) - def stepCheckInvoiceRuleNotAppliedOnInvoiceEdit(self, - sequence=None, sequence_list=None, **kw): - """If we call edit on the invoice, invoice rule should not be - applied on lines created by delivery builder.""" - invoice = sequence.get('invoice') - # FIXME: empty applied rule should not be created - #self.assertEquals(len(invoice.getCausalityRelatedValueList( - # portal_type=self.applied_rule_portal_type)), 0) - for invoice_mvt in invoice.getMovementList(): - self.assertEquals(len(invoice_mvt.getOrderRelatedValueList( - portal_type=self.simulation_movement_portal_type)), 0) + + + def _acceptDivergenceOnInvoice(self, invoice, divergence_list): + builder_list = invoice.getBuilderList() + self.assertEquals(2, len(builder_list)) + for builder in builder_list: + builder.solveDivergence(invoice.getRelativeUrl(), + divergence_to_accept_list=divergence_list) + + def test_accept_quantity_divergence_on_invoice_with_stopped_packing_list( + self, quiet=quiet): + sequence_list = SequenceList() + sequence = sequence_list.addSequenceString(self.PACKING_LIST_DEFAULT_SEQUENCE) + sequence_list.play(self, quiet=quiet) - def stepEditPackingList(self, sequence=None, sequence_list=None, **kw): - """Edit the current packing list, to trigger updateAppliedRule.""" packing_list = sequence.get('packing_list') - packing_list.edit() + packing_list_line = packing_list.getMovementList()[0] + previous_quantity = packing_list_line.getQuantity() + + packing_list.setReady() + packing_list.start() + packing_list.stop() + self.assertEquals('stopped', packing_list.getSimulationState()) + transaction.commit() + self.tic() - # call updateAppliedRule directly, don't rely on edit interactions - rule_reference = 'default_delivery_rule' - self.assertNotEquals(0, - len(self.portal.portal_rules.searchFolder(reference=rule_reference))) - packing_list.updateAppliedRule(rule_reference=rule_reference) + invoice = packing_list.getCausalityRelatedValue( + portal_type=self.invoice_portal_type) + self.assertNotEquals(invoice, None) + invoice_line_list = invoice.getMovementList() + self.assertEquals(1, len(invoice_line_list)) + invoice_line = invoice_line_list[0] - def stepCheckDeliveryRuleNotAppliedOnPackingListEdit(self, - sequence=None, sequence_list=None, **kw): - """If we call edit on the packing list, delivery rule should not be - applied on lines created by delivery builder.""" - packing_list = sequence.get('packing_list') - # FIXME: empty applied rule should not be created - #self.assertEquals(len(packing_list.getCausalityRelatedValueList( - # portal_type=self.applied_rule_portal_type)), 0) - for delivery_mvt in packing_list.getMovementList(): - self.assertEquals(len(delivery_mvt.getOrderRelatedValueList( - portal_type=self.simulation_movement_portal_type)), 0) + new_quantity = invoice_line.getQuantity() * 2 + invoice_line.setQuantity(new_quantity) + + transaction.commit() + self.tic() - def stepDecreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None, - **kw): - """ - Set a decreased quantity on invoice lines - """ - invoice = sequence.get('invoice') - quantity = sequence.get('line_quantity',default=self.default_quantity) - quantity = quantity - 1 - sequence.edit(line_quantity=quantity) - for invoice_line in invoice.objectValues( - portal_type=self.invoice_line_portal_type): - invoice_line.edit(quantity=quantity) - sequence.edit(last_delta = sequence.get('last_delta', 0.0) - 1.0) + self.assertTrue(invoice.isDivergent()) + divergence_list = invoice.getDivergenceList() + self.assertEquals(1, len(divergence_list)) - def stepIncreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None, - **kw): - """ - Set a Increased quantity on invoice lines - """ - invoice = sequence.get('invoice') - quantity = sequence.get('line_quantity',default=self.default_quantity) - quantity = quantity + 1 - sequence.edit(line_quantity=quantity) - for invoice_line in invoice.objectValues( - portal_type=self.invoice_line_portal_type): - invoice_line.edit(quantity=quantity) - sequence.edit(last_delta = sequence.get('last_delta', 0.0) + 1.0) + divergence = divergence_list[0] + self.assertEquals('quantity', divergence.tested_property) - def stepSetInvoiceLineQuantityToZero(self, sequence=None, sequence_list=None, - **kw): - """ - Set the quantity on invoice lines to zero - """ - invoice = sequence.get('invoice') - #default_quantity = sequence.get('line_quantity',default_quantity) - quantity = 0.0 - sequence.edit(line_quantity=quantity) - for invoice_line in invoice.objectValues( - portal_type=self.invoice_line_portal_type): - invoice_line.edit(quantity=quantity) - sequence.edit(last_delta = - self.default_quantity) + # accept decision + self._acceptDivergenceOnInvoice(invoice, divergence_list) - def stepChangeInvoiceStartDate(self, sequence=None, sequence_list=None, **kw): - """ - Change the start_date of the invoice. - """ - invoice = sequence.get('invoice') - invoice.edit(start_date=self.datetime + 15) + transaction.commit() + self.tic() + self.assertEquals('solved', invoice.getCausalityState()) - def stepCheckInvoiceIsCalculating(self, sequence=None, sequence_list=None, - **kw): - """ - Test if invoice is calculating - """ - invoice = sequence.get('invoice') - self.assertEquals('calculating',invoice.getCausalityState()) + self.assertEquals([], invoice.getDivergenceList()) + self.assertEquals(new_quantity, invoice_line.getQuantity()) + self.assertEquals(new_quantity, + invoice_line.getDeliveryRelatedValue(portal_type='Simulation Movement' + ).getQuantity()) - def stepCheckInvoiceIsDiverged(self, sequence=None, sequence_list=None, - **kw): - """ - Test if invoice is diverged - """ - invoice = sequence.get('invoice') - self.assertEquals('diverged',invoice.getCausalityState()) + self.assertEquals([], packing_list.getDivergenceList()) + self.assertEquals('solved', packing_list.getCausalityState()) + + def _adoptDivergenceOnInvoice(self, invoice, divergence_list): + builder_list = invoice.getBuilderList() + self.assertEquals(2, len(builder_list)) + for builder in builder_list: + builder.solveDivergence(invoice.getRelativeUrl(), + divergence_to_adopt_list=divergence_list) - def stepCheckInvoiceIsSolved(self, sequence=None, sequence_list=None, - **kw): - """ - Test if invoice is solved - """ - invoice = sequence.get('invoice') - self.assertEquals('solved', invoice.getCausalityState(), - invoice.getDivergenceList()) + def test_adopt_quantity_divergence_on_invoice_line_with_stopped_packing_list( + self, quiet=quiet): + # #1053 + sequence_list = SequenceList() + sequence = sequence_list.addSequenceString(self.PACKING_LIST_DEFAULT_SEQUENCE) + sequence_list.play(self, quiet=quiet) - def stepCheckInvoiceIsDivergent(self, sequence=None, sequence_list=None, - **kw): - """ - Test if invoice is divergent - """ - invoice = sequence.get('invoice') - self.assertTrue(invoice.isDivergent()) + packing_list = sequence.get('packing_list') + packing_list_line = packing_list.getMovementList()[0] + previous_quantity = packing_list_line.getQuantity() + previous_resource = packing_list_line.getResource() + previous_price = packing_list_line.getPrice() + + packing_list.setReady() + packing_list.start() + packing_list.stop() + self.assertEquals('stopped', packing_list.getSimulationState()) + transaction.commit() + self.tic() - def stepCheckInvoiceIsNotDivergent(self, sequence=None, sequence_list=None, - **kw): - """ - Test if invoice is not divergent - """ - invoice = sequence.get('invoice') - if invoice.isDivergent(): - self.fail(invoice.getDivergenceList()) + invoice = packing_list.getCausalityRelatedValue( + portal_type=self.invoice_portal_type) + self.assertNotEquals(invoice, None) + invoice_line_list = invoice.getMovementList() + self.assertEquals(1, len(invoice_line_list)) + invoice_line = invoice_line_list[0] - def stepSplitAndDeferInvoice(self, sequence=None, sequence_list=None, - **kw): - """ - split and defer at the invoice level - """ - invoice = sequence.get('invoice') - kw = {'listbox':[ - {'listbox_key':line.getRelativeUrl(), - 'choice':'SplitAndDefer'} for line in invoice.getMovementList()]} - self.portal.portal_workflow.doActionFor( - invoice, - 'split_and_defer_action', - start_date=self.datetime + 15, - stop_date=self.datetime + 25, - **kw) - pass + new_quantity = invoice_line.getQuantity() * 2 + invoice_line.setQuantity(new_quantity) + + transaction.commit() + self.tic() - def stepUnifyStartDateWithDecisionInvoice(self, sequence=None, - sequence_list=None): - invoice = sequence.get('invoice') - self._solveDeliveryGroupDivergence(invoice, 'start_date', - invoice.getRelativeUrl()) + self.assertTrue(invoice.isDivergent()) + divergence_list = invoice.getDivergenceList() + self.assertEquals(1, len(divergence_list)) - def stepAcceptDecisionQuantityInvoice(self,sequence=None, sequence_list=None): - invoice = sequence.get('invoice') - self._solveDivergence(invoice, 'quantity', 'accept') + divergence = divergence_list[0] + self.assertEquals('quantity', divergence.tested_property) - def stepAcceptDecisionInvoice(self, sequence=None, sequence_list=None, - **kw): - """ - accept decision at the invoice level - """ - invoice = sequence.get('invoice') - invoice.portal_workflow.doActionFor(invoice,'accept_decision_action') + # adopt prevision + self._adoptDivergenceOnInvoice(invoice, divergence_list) - def stepCheckInvoiceSplitted(self, sequence=None, sequence_list=None, **kw): - """ - Test if invoice was splitted - """ - packing_list = sequence.get('packing_list') - invoice_list = packing_list.getCausalityRelatedValueList( - portal_type=self.invoice_portal_type) - self.assertEquals(2,len(invoice_list)) - invoice1 = None - invoice2 = None - for invoice in invoice_list: - if invoice.getUid() == sequence.get('invoice').getUid(): - invoice1 = invoice - else: - invoice2 = invoice - sequence.edit(new_invoice=invoice2) - for line in invoice1.objectValues( - portal_type=self.invoice_line_portal_type): - self.assertEquals(self.default_quantity-1,line.getQuantity()) - for line in invoice2.objectValues( - portal_type=self.invoice_line_portal_type): - self.assertEquals(1,line.getQuantity()) + transaction.commit() + self.tic() + self.assertEquals([], invoice.getDivergenceList()) + self.assertEquals('solved', invoice.getCausalityState()) - def stepCheckInvoiceNotSplitted(self, sequence=None, sequence_list=None, **kw): - """ - Test if invoice was not splitted - """ - packing_list = sequence.get('packing_list') - invoice_list = packing_list.getCausalityRelatedValueList( - portal_type=self.invoice_portal_type) - self.assertEquals(1,len(invoice_list)) - invoice1 = None - for invoice in invoice_list: - if invoice.getUid() == sequence.get('invoice').getUid(): - invoice1 = invoice - last_delta = sequence.get('last_delta', 0.0) - for line in invoice1.objectValues( - portal_type=self.invoice_line_portal_type): - self.assertEquals(self.default_quantity + last_delta, - line.getQuantity()) + self.assertEquals(1, + len(invoice.getMovementList(portal_type=self.invoice_line_portal_type))) + self.assertEquals(0, + len(invoice.getMovementList(portal_type=self.invoice_transaction_line_portal_type))) - def stepAddInvoiceLines(self, sequence=None, sequence_list=[]): - """ - add some invoice and accounting lines to the invoice - """ - invoice = sequence.get('invoice') - invoice.newContent(portal_type='Invoice Line', - resource_value=sequence.get('resource'), quantity=3, price=555) - invoice.newContent(portal_type='Sale Invoice Transaction Line', - id ='receivable', source='account_module/customer', - destination='account_module/supplier', quantity=-1665) - invoice.newContent(portal_type='Sale Invoice Transaction Line', - id='income', source='account_module/sale', - destination='account_module/purchase', quantity=1665) + self.assertEquals(previous_resource, invoice_line.getResource()) + self.assertEquals(previous_quantity, invoice_line.getQuantity()) + self.assertEquals(previous_price, invoice_line.getPrice()) + self.assertEquals(previous_quantity, + invoice_line.getDeliveryRelatedValue(portal_type='Simulation Movement' + ).getQuantity()) - def stepAddWrongInvoiceLines(self, sequence=None, sequence_list=[]): - """ - add some wrong invoice and accounting lines to the invoice - """ - invoice = sequence.get('invoice') - invoice.newContent(portal_type='Sale Invoice Transaction Line', - id='bad_movement', source='account_module/sale', - destination='account_module/purchase', quantity=2, price=4) - invoice.newContent(portal_type='Sale Invoice Transaction Line', - id='counter_bad_movement', source='account_module/sale', - destination='account_module/purchase', quantity=-2, price=4) - for movement in invoice.getMovementList(): - movement.edit(resource_value=sequence.get('resource')) + self.assertEquals([], packing_list.getDivergenceList()) + self.assertEquals('solved', packing_list.getCausalityState()) + - def stepCheckStartInvoiceFail(self, sequence=None, sequence_list=[]): - """ - checks that it's not possible to start an invoice with really wrong - lines - """ - try: - self.tic() - except RuntimeError, exc: - invoice = sequence.get('invoice') - it_builder = self.portal.portal_deliveries.sale_invoice_transaction_builder - # check which activities are failing - self.assertTrue(str(exc).startswith('tic is looping forever.'), - '%s does not start with "tic is looping forever."' % str(exc)) - msg_list = ['/'.join(x.object_path) for x in - self.getActivityTool().getMessageList()] - self.assertTrue(it_builder.getPath() in msg_list, '%s in %s' % - (it_builder.getPath(), msg_list)) - # flush failing activities - activity_tool = self.getActivityTool() - activity_tool.manageClearActivities(keep=0) - else: - self.fail("Error: stepStartInvoice didn't fail, the builder script" - + " InvoiceTransaction_postTransactionLineGeneration should have" - + " complained that accounting movements use multiple resources") - def stepCheckSimulationTrees(self, sequence=None, sequence_list=[]): - """ - check that rules are created in the order we expect them - """ - applied_rule_set = set() - invoice = sequence.get('invoice') - for movement in invoice.getMovementList(): - for sm in movement.getDeliveryRelatedValueList(): - applied_rule_set.add(sm.getRootAppliedRule()) +class TestSaleInvoiceMixin(TestInvoiceMixin, + ERP5TypeTestCase): + """Test sale invoice are created from orders then packing lists. - rule_dict = { - 'Order Rule': { - 'movement_type_list': ['Sale Order Line', 'Sale Order Cell'], - 'next_rule_list': ['Delivering Rule', ], - }, - 'Delivering Rule': { - 'movement_type_list': ['Sale Packing List Line', 'Sale Packing List Cell'], - 'next_rule_list': ['Invoicing Rule', ], - }, - 'Invoicing Rule': { - 'movement_type_list': invoice.getPortalInvoiceMovementTypeList(), - 'next_rule_list': ['Invoice Transaction Rule', 'Trade Model Rule'], - }, - 'Trade Model Rule': { - 'next_rule_list': ['Invoice Transaction Rule'], - }, - 'Invoice Rule': { - 'movement_type_list': invoice.getPortalInvoiceMovementTypeList() \ - + invoice.getPortalAccountingMovementTypeList(), - 'next_rule_list': ['Invoice Transaction Rule', 'Payment Rule', - 'Trade Model Rule'], - }, - 'Invoice Transaction Rule': { - 'parent_movement_type_list': invoice.getPortalInvoiceMovementTypeList(), - 'movement_type_list': invoice.getPortalAccountingMovementTypeList(), - 'next_rule_list': ['Payment Rule'], - }, - 'Payment Rule': { - 'parent_movement_type_list': invoice.getPortalAccountingMovementTypeList(), - 'next_rule_list': [], - }, - } + Those tests methods only work for sale, because sale and purchase invoice + are not built at the same time on packing list workflow. + """ + quiet = 0 + invoice_portal_type = 'Sale Invoice Transaction' + invoice_line_portal_type = 'Invoice Line' + invoice_cell_portal_type = 'Invoice Cell' + invoice_transaction_line_portal_type = 'Sale Invoice Transaction Line' + payment_portal_type = 'Payment Transaction' - def checkTree(rule): - """ - checks the tree recursively - """ - rule_type = rule.getSpecialiseValue().getPortalType() - rule_def = rule_dict.get(rule_type, {}) - for k, v in rule_def.iteritems(): - if k == 'movement_type_list': - for movement in rule.objectValues(): - if movement.getDeliveryValue() is not None: - self.assertTrue(movement.getDeliveryValue().getPortalType() in v, - 'looking for %s in %s on %s' % ( - movement.getDeliveryValue().getPortalType(), v, - movement.getPath())) - elif k == 'next_rule_list': - for movement in rule.objectValues(): - found_rule_dict = {} - for next_rule in movement.objectValues(): - next_rule_type = next_rule.getSpecialiseValue().getPortalType() - self.assertTrue(next_rule_type in v, - 'looking for %s in %s on %s' % ( - next_rule_type, v, next_rule.getPath())) - n = found_rule_dict.get(next_rule_type, 0) - found_rule_dict[next_rule_type] = n + 1 - # for each movement, we want to make sure that each rule is not - # instanciated more than once - if len(found_rule_dict): - self.assertEquals(set(found_rule_dict.itervalues()), set([1])) - elif k == 'parent_movement_type_list': - if rule.getParentValue().getDeliveryValue() is not None: - parent_type = rule.getParentValue().getDeliveryValue().getPortalType() - self.assertTrue(parent_type in v, 'looking for %s in %s on %s' % ( - parent_type, v, rule.getParentValue().getPath())) - elif k == 'parent_id_list': - self.assertTrue(rule.getParentId() in v, 'looking for %s in %s on %s' - % (rule.getParentId(), v, rule.getPath())) - for movement in rule.objectValues(): - for next_rule in movement.objectValues(): - checkTree(next_rule) + # default sequence for one line of not varianted resource. + PACKING_LIST_DEFAULT_SEQUENCE = """ + stepCreateEntities + stepCreateCurrency + stepCreateSaleInvoiceTransactionRule + stepCreateOrder + stepSetOrderProfile + stepSetOrderPriceCurrency + stepCreateNotVariatedResource + stepTic + stepCreateOrderLine + stepSetOrderLineResource + stepSetOrderLineDefaultValues + stepOrderOrder + stepTic + stepCheckDeliveryBuilding + stepConfirmOrder + stepTic + stepCheckOrderRule + stepCheckOrderSimulation + stepCheckDeliveryBuilding + stepAddPackingListContainer + stepAddPackingListContainerLine + stepSetContainerLineFullQuantity + stepTic + stepCheckPackingListIsPacked + """ - for applied_rule in applied_rule_set: - checkTree(applied_rule) + # default sequence for two lines of not varianted resource. + PACKING_LIST_TWO_LINES_DEFAULT_SEQUENCE = """ + stepCreateEntities + stepCreateCurrency + stepCreateSaleInvoiceTransactionRule + stepCreateOrder + stepSetOrderProfile + stepSetOrderPriceCurrency + stepCreateNotVariatedResource + stepTic + stepCreateOrderLine + stepSetOrderLineResource + stepSetOrderLineDefaultValues + stepCreateNotVariatedResource + stepTic + stepCreateOrderLine + stepSetOrderLineResource + stepSetOrderLineDefaultValues + stepOrderOrder + stepTic + stepCheckDeliveryBuilding + stepConfirmOrder + stepTic + stepCheckOrderRule + stepCheckOrderSimulation + stepCheckDeliveryBuilding + stepAddPackingListContainer + stepAddPackingListContainerLine + stepTic + stepSetContainerFullQuantity + stepTic + stepCheckPackingListIsPacked + """ + # default sequence for one line of not varianted resource. + TWO_PACKING_LIST_DEFAULT_SEQUENCE = """ + stepCreateEntities + stepCreateCurrency + stepCreateSaleInvoiceTransactionRule + stepCreateOrder + stepSetOrderProfile + stepSetOrderPriceCurrency + stepCreateNotVariatedResource + stepTic + stepCreateOrderLine + stepSetOrderLineResource + stepSetOrderLineDefaultValues + stepOrderOrder + stepTic + stepCheckDeliveryBuilding + stepConfirmOrder + stepTic + stepCheckOrderRule + stepCheckOrderSimulation + stepCheckDeliveryBuilding + stepDecreasePackingListLineQuantity + stepCheckPackingListIsCalculating + stepTic + stepCheckPackingListIsDiverged + stepSplitAndDeferPackingList + stepTic + stepCheckPackingListIsSolved + stepCheckPackingListSplitted + stepAddPackingListContainer + stepAddPackingListContainerLine + stepSetContainerLineFullQuantity + stepTic + stepCheckPackingListIsPacked + stepDefineNewPackingListContainer + stepTic + stepCheckNewPackingListIsPacked + """ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase): """Tests for sale invoice. @@ -3012,25 +3027,6 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase): sequence_list.addSequenceString(sequence) sequence_list.play(self, quiet=quiet) - def stepAddInvoiceLinesManyTransactions(self, sequence=None, sequence_list=[]): - """ - add some invoice and accounting lines to the invoice - """ - invoice = sequence.get('invoice') - invoice_line = invoice.newContent(portal_type='Invoice Line') - transaction_line_1 = invoice.newContent(portal_type='Sale Invoice Transaction Line') - transaction_line_2 = invoice.newContent(portal_type='Sale Invoice Transaction Line') - transaction.commit() - self.tic() - invoice_line.edit(resource_value=sequence.get('resource'), quantity=3, - price=555) - transaction_line_1.edit(id ='receivable', source='account_module/customer', - destination='account_module/supplier', quantity=-1665) - transaction_line_2.edit( - id='income', source='account_module/sale', - destination='account_module/purchase', quantity=1665) - - def test_16a_ManuallyAddedMovementsManyTransactions(self, quiet=quiet): """ Checks that adding invoice lines and accounting lines to one invoice