############################################################################## # -*- coding: utf-8 -*- # # Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved. # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsibility of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # guarantees and support are strongly adviced to contract a Free Software # Service Company # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## import unittest from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.Sequence import SequenceList from Products.ERP5Type.tests.utils import createZODBPythonScript from Products.ERP5.tests.testInvoice import TestSaleInvoiceMixin class TestNestedLineMixin(TestSaleInvoiceMixin): """ NestedLineMovementGroup is a mark only for controlling multiple lines in DeliveryBuilder. We need this feature to make multi-level "Invoice Line"s. """ DEFAULT_SEQUENCE = TestSaleInvoiceMixin.PACKING_LIST_DEFAULT_SEQUENCE + \ """ stepSetReadyPackingList stepTic stepUpdateBuilderForMultipleLineList stepSetPythonScriptForDeliveryBuilder stepStartPackingList stepCheckInvoicingRule stepTic stepGetRelatedInvoiceFromPackingList """ delivery_builder_id = 'sale_invoice_builder' default_quantity = TestSaleInvoiceMixin.default_quantity new_order_quantity = TestSaleInvoiceMixin.default_quantity * 3 new_packing_list_quantity = TestSaleInvoiceMixin.default_quantity * 5 new_invoice_quantity = TestSaleInvoiceMixin.default_quantity * 2 def afterSetUp(self): TestSaleInvoiceMixin.afterSetUp(self) # Necessary to allow Invoice Line to be included in Invoice Line. self.allowInvoiceLineContentTypeInInvoiceLine() def allowInvoiceLineContentTypeInInvoiceLine(self): return UnrestrictedMethod(self._allowInvoiceLineContentTypeInInvoiceLine)() def _allowInvoiceLineContentTypeInInvoiceLine(self): invoice_line_type = self.portal.portal_types['Invoice Line'] if 'Invoice Line' not in invoice_line_type.allowed_content_types: invoice_line_type.allowed_content_types += ('Invoice Line',) def stepGetRelatedInvoiceFromPackingList(self, sequence, **kw): packing_list = sequence.get('packing_list') related_invoice_list = packing_list \ .getCausalityRelatedValueList(portal_type=self.invoice_portal_type) invoice = related_invoice_list[0].getObject() sequence.edit(invoice=invoice) def stepUpdateBuilderForMultipleLineList(self, **kw): self.updateBuilderForMultipleLineList() def updateBuilderForMultipleLineList(self): return UnrestrictedMethod(self._updateBuilderForMultipleLineList)() def _updateBuilderForMultipleLineList(self): delivery_builder = getattr(self.portal.portal_deliveries, self.delivery_builder_id) delivery_builder.deleteContent(delivery_builder.contentIds()) delivery_builder.newContent( portal_type='Property Movement Group', collect_order_group='delivery', divergence_scope='property', tested_property_list=('start_date', 'stop_date'), int_index=1) delivery_builder.newContent( portal_type='Category Movement Group', collect_order_group='delivery', divergence_scope='category', tested_property_list=('delivery_mode', 'incoterm', 'source', 'destination', 'source_section', 'destination_section', 'destination_function', 'source_function', 'source_decision', 'destination_decision', 'source_administration', 'destination_administration', 'source_project', 'destination_project', 'price_currency'), int_index=2) delivery_builder.newContent( portal_type='Delivery Causality Assignment Movement Group', collect_order_group='delivery', int_index=3) delivery_builder.newContent( portal_type='Property Movement Group', collect_order_group='line', divergence_scope='property', tested_property_list=('start_date', 'stop_date'), int_index=1) # *** test this *** delivery_builder.newContent( portal_type='Nested Line Movement Group', collect_order_group='line', int_index=2) delivery_builder.newContent( portal_type='Category Movement Group', collect_order_group='line', divergence_scope='category', tested_property_list=('resource', 'aggregate', 'base_contribution'), int_index=3) delivery_builder.newContent( portal_type='Base Variant Movement Group', collect_order_group='line', int_index=4) delivery_builder.newContent( portal_type='Property Movement Group', collect_order_group='line', divergence_scope='property', tested_property_list=('description'), int_index=5) delivery_builder.newContent( portal_type='Variant Movement Group', collect_order_group='cell', divergence_scope='category', int_index=1) def stepSetExistDeliveriesToSequence(self, sequence=None, **kw): order = self.portal.sale_order_module.contentValues(portal_type='Sale Order')[0] packing_list = self.portal.sale_packing_list_module \ .contentValues(portal_type='Sale Packing List')[0] invoice = self.portal.accounting_module \ .contentValues(portal_type='Sale Invoice Transaction')[0] sequence.edit(order=order, packing_list=packing_list, invoice=invoice) def stepUpdateOrder(self, sequence=None, **kw): movement = sequence.get('order').getMovementList(portal_type='Sale Order Line')[0] movement.edit(quantity=self.new_order_quantity, price=self.default_price) def stepUpdatePackingList(self, sequence=None, **kw): movement = sequence.get('packing_list') \ .getMovementList(portal_type='Sale Packing List Line')[0] movement.edit(quantity=self.new_packing_list_quantity) def stepSetFillContainerLine(self, sequence=None, **kw): movement = sequence.get('container_line') movement.edit(quantity=self.new_order_quantity) def stepUpdateInvoice(self, sequence=None, **kw): movement = sequence.get('invoice') \ .getMovementList(portal_type='Invoice Line')[0] movement.edit(quantity=self.new_invoice_quantity) def stepSetPythonScriptForDeliveryBuilder(self, **kw): """ Make a script which returns existing Sale Invoice Transactions, so that all movements are merged into existing ones. """ delivery_select_method_id = 'Test_selectDelivery' createZODBPythonScript( self.portal.portal_skins.custom, delivery_select_method_id, 'movement_list=None', """ return context.getPortalObject().portal_catalog(portal_type='Sale Invoice Transaction') """) delivery_builder = getattr(self.portal.portal_deliveries, self.delivery_builder_id) delivery_builder.delivery_select_method_id = delivery_select_method_id def stepSetSeparateMethodToDeliveryBuilder(self, **kw): """ Merge multiple simulation movements into one movement. """ delivery_builder = getattr(self.portal.portal_deliveries, self.delivery_builder_id) delivery_builder.delivery_cell_separate_order = ('calculateAddQuantity',) def stepAdoptPrevisionPackingListQuantity(self,sequence=None, sequence_list=None): document = sequence.get('packing_list') self._solveDivergence(document, 'quantity', 'adopt') def stepAcceptDecisionPackingListQuantity(self,sequence=None, sequence_list=None): document = sequence.get('packing_list') self._solveDivergence(document, 'quantity', 'accept') def stepAdoptPrevisionInvoiceQuantity(self,sequence=None, sequence_list=None): document = sequence.get('invoice') self._solveDivergence(document, 'quantity', 'adopt') def stepAcceptDecisionInvoiceQuantity(self,sequence=None, sequence_list=None): document = sequence.get('invoice') self._solveDivergence(document, 'quantity', 'accept') class TestNestedLine(TestNestedLineMixin, ERP5TypeTestCase): quiet = 0 def test_01_IfNested(self, quiet=quiet): sequence_list = SequenceList() sequence = sequence_list.addSequenceString(self.DEFAULT_SEQUENCE) sequence_list.play(self, quiet=quiet) # order = sequence.get('order') # packing_list = sequence.get('packing_list') document = sequence.get('invoice') self.assertEquals('Sale Invoice Transaction', document.getPortalType()) self.assertEquals(1, len(document)) line = document.objectValues()[0] self.assertEquals('Invoice Line', line.getPortalType()) self.assertEquals(None, line.getQuantity(None)) self.assertEquals(1, len(line)) line_line = line.objectValues()[0] self.assertEquals('Invoice Line', line_line.getPortalType()) self.assertEquals(self.default_price * self.default_quantity, document.getTotalPrice()) self.assertEquals(self.default_quantity, document.getTotalQuantity()) self.assertEquals(self.default_price, line_line.getPrice()) self.assertEquals(self.default_quantity, line_line.getQuantity()) def test_02_AdoptingPrevision(self, quiet=quiet): sequence_list = SequenceList() sequence = sequence_list.addSequenceString(self.DEFAULT_SEQUENCE + \ """ stepUpdatePackingList stepTic stepAcceptDecisionPackingListQuantity stepTic stepCheckInvoiceIsDivergent stepCheckInvoiceIsDiverged stepAdoptPrevisionInvoiceQuantity stepTic """ ) sequence_list.play(self, quiet=quiet) document = sequence.get('invoice') self.assertEquals('solved', document.getCausalityState()) self.assertEquals(1, len(document)) line = document.objectValues()[0] self.assertEquals('Invoice Line', line.getPortalType()) self.assertEquals(None, line.getQuantity(None)) self.assertEquals(1, len(line)) line_line = line.objectValues()[0] self.assertEquals('Invoice Line', line_line.getPortalType()) self.assertEquals(self.default_price * self.new_packing_list_quantity, document.getTotalPrice()) self.assertEquals(self.new_packing_list_quantity, document.getTotalQuantity()) self.assertEquals(self.new_packing_list_quantity, line_line.getQuantity()) def test_03_AcceptingDecision(self, quiet=quiet): sequence_list = SequenceList() sequence = sequence_list.addSequenceString(self.DEFAULT_SEQUENCE + \ """ stepUpdateInvoice stepTic stepCheckInvoiceIsDivergent stepAcceptDecisionInvoiceQuantity stepTic stepCheckInvoiceIsNotDivergent stepCheckPackingListIsDivergent stepAdoptPrevisionPackingListQuantity stepTic """ ) sequence_list.play(self, quiet=quiet) document = sequence.get('invoice') self.assertEquals('solved', document.getCausalityState()) self.assertEquals(1, len(document)) line = document.objectValues()[0] self.assertEquals('Invoice Line', line.getPortalType()) self.assertEquals(None, line.getQuantity(None)) self.assertEquals(1, len(line)) line_line = line.objectValues()[0] self.assertEquals('Invoice Line', line_line.getPortalType()) self.assertEquals(self.default_price * self.new_invoice_quantity, document.getTotalPrice()) self.assertEquals(self.new_invoice_quantity, document.getTotalQuantity()) self.assertEquals(self.new_invoice_quantity, line_line.getQuantity()) def test_04_MergingMultipleSaleOrders(self, quiet=quiet): sequence_list = SequenceList() sequence = sequence_list.addSequenceString(self.DEFAULT_SEQUENCE + \ """ stepCreateOrder stepSetOrderProfile stepSetOrderPriceCurrency stepTic stepCreateOrderLine stepSetOrderLineResource stepUpdateOrder stepOrderOrder stepTic stepCheckDeliveryBuilding stepConfirmOrder stepTic stepCheckOrderRule stepCheckOrderSimulation stepCheckDeliveryBuilding stepAddPackingListContainer stepAddPackingListContainerLine stepSetFillContainerLine stepTic stepSetReadyPackingList stepTic stepStartPackingList stepCheckInvoicingRule stepTic stepCheckInvoiceIsDivergent stepAdoptPrevisionInvoiceQuantity stepTic """ ) sequence_list.play(self, quiet=quiet) self.assertEquals(1, len(self.portal.accounting_module)) document = self.portal.accounting_module.objectValues()[0] self.assertEquals('solved', document.getCausalityState()) self.assertEquals(1, len(document)) line = document.objectValues()[0] self.assertEquals('Invoice Line', line.getPortalType()) self.assertEquals(None, line.getQuantity(None)) self.assertEquals(1, len(line)) line_line = line.objectValues()[0] self.assertEquals('Invoice Line', line_line.getPortalType()) # The sale invoice summed up from two sale orders. # The quantity of a sale order is self.default_quantity, and # that of the other one is self.new_order_quantity. self.assertEquals(self.default_price * (self.default_quantity + self.new_order_quantity), document.getTotalPrice()) self.assertEquals(self.default_quantity + self.new_order_quantity, document.getTotalQuantity()) self.assertEquals(self.default_quantity + self.new_order_quantity, line_line.getQuantity()) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestNestedLine)) return suite