Commit 4140f969 authored by Jérome Perrin's avatar Jérome Perrin

rewrote for using Sequence class and increasing readability


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@3781 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 844fefc2
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# #
# Copyright (c) 2004 Nexedi SARL and Contributors. All Rights Reserved. # Copyright (c) 2004 Nexedi SARL and Contributors. All Rights Reserved.
# Sebastien Robin <seb@nexedi.com> # Sebastien Robin <seb@nexedi.com>
# Jrome Perrin <jerome@nexedi.com>
# #
# WARNING: This program as such is intended to be used by professional # WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential # programmers who take the whole responsability of assessing all potential
...@@ -25,218 +26,1059 @@ ...@@ -25,218 +26,1059 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# #
############################################################################## ##############################################################################
"""
Tests accounting simulation rules and delivery builder.
This tests also do basic checks for XMLMatrix and Predicate matching the
way it is used in the invoice related simulation.
"""
#
# Skeleton ZopeTestCase
# #
# TODO :
#from random import randint # * test match fr different predicate
# * test invoice with cells
# * test updateAppliedRule when modifying cell / lines
# * test payment rule & payment builder
# * test invoicing rule by connecting to order test.
#
import os, sys import os, sys
if __name__ == '__main__': if __name__ == '__main__':
execfile(os.path.join(sys.path[0], 'framework.py')) execfile(os.path.join(sys.path[0], 'framework.py'))
# Needed in order to have a log file inside the current folder # Needed in order to have a log file inside the current folder
import os
os.environ['EVENT_LOG_FILE'] = os.path.join(os.getcwd(), 'zLOG.log') os.environ['EVENT_LOG_FILE'] = os.path.join(os.getcwd(), 'zLOG.log')
os.environ['EVENT_LOG_SEVERITY'] = '-300' os.environ['EVENT_LOG_SEVERITY'] = '-300'
from Testing import ZopeTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from AccessControl.SecurityManagement import newSecurityManager from Products.ERP5Type.tests.Sequence import Sequence, SequenceList
#from DateTime import DateTime
#from Acquisition import aq_base, aq_inner
from zLOG import LOG
#from Products.ERP5Type.DateUtils import addToDate
#import time
#from Products.ERP5Type import product_path
#from DateTime import DateTime
from Testing import ZopeTestCase
from AccessControl.SecurityManagement import newSecurityManager
from zLOG import LOG, INFO
from DateTime import DateTime
class TestAccountingRules(ERP5TypeTestCase): class TestAccountingRules(ERP5TypeTestCase):
""" """
This should test these functions : This should test these functions :
- in InvoiceRule.py : - in InvoiceRule.py :
- expand - expand
- collectSimulationMovements
- in InvoiceTransactionRule.py : - in InvoiceTransactionRule.py and PaymentRule.py :
- test - test
- expand - expand
- newCellContent - newCellContent
- updateMatrix - updateMatrix
- getCellByPredicate - getCellByPredicate
"""
# Different variables used for this test """
run_all_test = 1
#source_company_id = 'Nexedi'
#destination_company_id = 'Coramy'
#component_id = 'brick'
#sales_order_id = '1'
#quantity = 10
#base_price = 0.7832
RUN_ALL_TESTS = 1
# define portal_types
account_module_portal_type = "Account Module"
accounting_module_portal_type = "Accounting Module"
product_module_portal_type = "Product Module"
currency_module_portal_type = "Currency Module"
organisation_portal_type = "Organisation"
account_portal_type = "Account"
product_portal_type = "Product"
currency_portal_type = "Currency"
predicate_portal_type = "Predicate"
applied_rule_portal_type = "Applied Rule"
simulation_movement_portal_type = "Simulation Movement"
accounting_rule_cell_portal_type = "Accounting Rule Cell"
sale_invoice_transaction_portal_type = "Sale Invoice Transaction"
sale_invoice_transaction_line_portal_type \
= "Sale Invoice Transaction Line"
sale_invoice_line_portal_type = "Sale Invoice Line"
purchase_invoice_transaction_portal_type \
= "Purchase Invoice Transaction"
payment_transaction_portal_type = "Payment Transaction"
def getTitle(self): def getTitle(self):
return "Accouting Rules" return "Test Accounting Rules"
def getBusinessTemplateList(self): def getBusinessTemplateList(self):
""" """ Return the list of business templates. """
Return the list of business templates. return ('erp5_pdm', 'erp5_trade', 'erp5_accounting')
"""
return ('erp5_accounting','erp5_trade', 'erp5_pdm')
def enableLightInstall(self):
"""
You can override this. Return if we should do a light install (1) or not (0)
"""
return 1
def enableActivityTool(self):
"""
You can override this. Return if we should create (1) or not (0) an activity tool
"""
return 1
def getActivityTool(self):
return getattr(self.getPortal(), 'portal_activities', None)
def getRuleTool(self):
return getattr(self.getPortal(), 'portal_rules', None)
def getWorkflowTool(self):
return getattr(self.getPortal(), 'portal_workflow', None)
def getAccountModule(self): def getAccountModule(self):
return getattr(self.getPortal(), 'account', None) return getattr(self.getPortal(), 'account',
getattr(self.getPortal(), 'account_module'))
def getAccountingModule(self): def getAccountingModule(self):
return getattr(self.getPortal(), 'accounting', None) return getattr(self.getPortal(), 'accounting',
getattr(self.getPortal(), 'accounting_module'))
def getOrganisationModule(self):
return getattr(self.getPortal(), 'organisation', None)
def getProductModule(self): def getProductModule(self):
return getattr(self.getPortal(), 'product', None) return getattr(self.getPortal(), 'product',
getattr(self.getPortal(), 'product_module'))
def getCurrencyModule(self) :
return getattr(self.getPortal(), 'currency', None) ## XXX move this to "Sequence class"
def playSequence(self, sequence_string) :
def login(self, quiet=0, run=run_all_test): sequence_list = SequenceList()
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def afterSetUp(self) :
self.login()
self.createCategories()
def login(self):
uf = self.getPortal().acl_users uf = self.getPortal().acl_users
uf._doAddUser('alex', '', ['Manager'], []) uf._doAddUser('alex', '', ['Manager', 'Owner', 'Assignor'], [])
user = uf.getUserById('alex').__of__(uf) user = uf.getUserById('alex').__of__(uf)
newSecurityManager(None, user) newSecurityManager(None, user)
def afterSetUp(self, quiet=1, run=1): def createCategories(self) :
self.login() """ create all categories that are needed for this test.
# Must add some accounts, accounting transactions, products, etc. It uses getCategoriesToCreate, so you should overload this method.
account_module = self.getAccountModule() """
self.accounting_module = self.getAccountingModule() # create base categories
self.currency_module = self.getCurrencyModule() for base_cat in self.getBaseCategoriesToCreate() :
self.organisation_module = self.getOrganisationModule() if not base_cat in self.getCategoryTool().objectIds() :
product_module = self.getProductModule() self.getCategoryTool().newContent(
self.activity_tool = self.getActivityTool() portal_type = 'Base Category',
self.catalog_tool = self.getCatalogTool() id = base_cat)
self.category_tool = self.getCategoryTool() # create categories
self.simulation_tool = self.getSimulationTool() for cat_string in self.getCategoriesToCreate() :
self.workflow_tool = self.getWorkflowTool() base_cat = cat_string.split("/")[0]
self.portal = self.getPortal() path = self.getPortal().portal_categories[base_cat]
# flush activities for cat in cat_string.split("/")[1:] :
get_transaction().commit() if not cat in path.objectIds() :
path = path.newContent(
portal_type = 'Category',
id = cat,
immediate_reindex = 1 )
# check categories have been created
for cat_string in self.getCategoriesToCreate() :
self.assertNotEquals(None,
self.getCategoryTool().restrictedTraverse(cat_string),
cat_string)
def getBaseCategoriesToCreate(self) :
return ("hd_size", "cpu_freq")
def getCategoriesToCreate(self):
return (
# regions for our organisations
"region/europe/west/france",
"region/africa",
# those are mandatory for account, and accounting rules depends on
# the account_type category. (ie payable, will create a Payment
# Transaction accordingly)
"account_type/asset/cash",
"account_type/asset/receivable/refundable_vat",
"account_type/equity",
"account_type/expense",
"account_type/income",
"account_type/liability/payable/collected_vat",
# some products lines for our products
"product_line/storever/notebook",
"product_line/storever/barebone",
"product_line/storever/openbrick",
"product_line/not_used/not_matched",
# some categories for variating our products
"cpu_freq/1Ghz",
"cpu_freq/2Ghz",
"hd_size/60Go",
"hd_size/120Go",
)
def rollbackTest(self) :
""" delete everything created by the test (for 'live debugin')"""
portal = self.getPortal()
from Products.ERP5.Document.AccountingTransaction \
import AccountingTransaction
self.tic() self.tic()
# When using light install, only base categories are created old_manage_beforeDelete = AccountingTransaction.manage_beforeDelete
if len(self.category_tool.region.contentValues()) == 0 : AccountingTransaction.manage_beforeDelete = lambda x, y, z: 1
self.category_tool.region.newContent(portal_type='Category', id='africa') self.getAccountModule().deleteContent(
o = self.category_tool.region.newContent(portal_type='Category', id='europe') list(self.getAccountModule().objectIds()))
o = o.newContent(portal_type='Category', id='west') self.getAccountingModule().deleteContent(
o.newContent(portal_type='Category', id='france') list(self.getAccountingModule().objectIds()))
self.getOrganisationModule().deleteContent(
self.category_tool.pcg.newContent(portal_type='Category', id='1') list(self.getOrganisationModule().objectIds()))
self.getCurrencyModule().deleteContent(
self.category_tool.product_line.newContent(portal_type='Category', id='erp5') list(self.getCurrencyModule().objectIds()))
o = self.category_tool.product_line.newContent(portal_type='Category', id='storever') self.getProductModule().deleteContent(
o.newContent(portal_type='Category', id='barebone') list(self.getProductModule().objectIds()))
o.newContent(portal_type='Category', id='notebook') self.getSimulationTool().deleteContent(
o.newContent(portal_type='Category', id='openbrick') list(self.getSimulationTool().objectIds()))
# If currency/EUR already exists, it means that the afterSetUp actions were already commited. Then, we just need to link to them. AccountingTransaction.manage_beforeDelete = old_manage_beforeDelete
old_euro = getattr( self.currency_module, 'EUR', None) self.tic()
if old_euro is not None :
self.invoice_transaction_rule = getattr(self.getRuleTool(), 'default_invoice_transaction_rule') def stepTic(self, **kw):
self.predicate_product1 = getattr(self.invoice_transaction_rule, 'product_1')
self.predicate_product2 = getattr(self.invoice_transaction_rule, 'product_2')
self.predicate_region1 = getattr(self.invoice_transaction_rule, 'region_1')
self.predicate_region2 = getattr(self.invoice_transaction_rule, 'region_2')
self.invoice = getattr(self.accounting_module, 'invoice1')
return
# Create some currencies
euro = self.currency_module.newContent(id='EUR', title='Euro', portal_type='Currency')
# Create some accounts
account_module.newContent(id='prestation_service', title='prestation_service', portal_type='Account')
account_module.newContent(id='creance_client', title='creance_client', portal_type='Account')
account_module.newContent(id='tva_collectee_196', title='tva_collectee_196', portal_type='Account')
account_module.newContent(id='account1', title='Account1', portal_type='Account')
account_module.newContent(id='account2', title='Account2', portal_type='Account')
account_module.newContent(id='account3', title='Account3', portal_type='Account')
account_module.newContent(id='account4', title='Account4', portal_type='Account')
# Create some organisations
self.organisation1 = self.organisation_module.newContent(id='nexedi', title='Nexedi', portal_type='Organisation')
self.organisation1.newContent(id='default_address', portal_type='Address', region='europe/west/france')
self.organisation2 = self.organisation_module.newContent(id='client1', title='Client1', portal_type='Organisation')
self.organisation2.newContent(id='default_address', portal_type='Address', region='europe/west/france')
# Create some products
self.product1 = product_module.newContent(id='product1', title='Product1', product_line='storever/notebook', base_price=3.0)
self.product2 = product_module.newContent(id='product2', title='Product2', product_line='storever/barebone', base_price=5.0)
# Create some predicates in the Invoice Transaction Rule
self.invoice_transaction_rule = getattr(self.getRuleTool(), 'default_invoice_transaction_rule')
self.invoice_transaction_rule.deleteContent(self.invoice_transaction_rule.contentIds()) # delete anything inside the rule first
self.predicate_product1 = self.invoice_transaction_rule.newContent(id='product_1', title='product_1', portal_type='Predicate Group', string_index='product', int_index='1', membership_criterion_base_category_list=['product_line',], membership_criterion_category_list=['product_line/storever/notebook'], immediate_reindex=1)
self.predicate_product2 = self.invoice_transaction_rule.newContent(id='product_2', title='product_2', portal_type='Predicate Group', string_index='product', int_index='2', membership_criterion_base_category_list=['product_line',], membership_criterion_category_list=['product_line/storever/barebone'], immediate_reindex=1)
self.predicate_region1 = self.invoice_transaction_rule.newContent(id='region_1', title='region_1', portal_type='Predicate Group', string_index='region', int_index='1', membership_criterion_base_category_list=['destination_region',], membership_criterion_category_list=['destination_region/region/europe/west/france'], immediate_reindex=1)
self.predicate_region2 = self.invoice_transaction_rule.newContent(id='region_2', title='region_2', portal_type='Predicate Group', string_index='region', int_index='2', membership_criterion_base_category_list=['destination_region',], membership_criterion_category_list=['destination_region/region/africa'], immediate_reindex=1)
# Create some invoices (now that there is nothing harmful inside the rule)
self.invoice = self.accounting_module.newContent(id='invoice1', portal_type='Sale Invoice Transaction', destination='organisation/client1', destination_section='organisation/client1', resource='currency/EUR')
invoice_line = self.invoice.newContent(id='1', portal_type='Invoice Line', resource='product/product1', quantity=7.0, price=11.0)
# flush activities
get_transaction().commit()
self.tic() self.tic()
def updateInvoiceTransactionRuleMatrix(self) : def stepCreateSaleInvoiceTransactionRule(self, sequence, **kw) :
"""
base_id = 'vat_per_region' Create some predicates in the Invoice Transaction Rule
"""
invoice_transaction_rule = getattr(self.getRuleTool(),
'default_invoice_transaction_rule')
# delete anything inside the rule first
# clear the message queue, so that it does not contains unexistant paths
self.tic()
invoice_transaction_rule.deleteContent(
[x for x in invoice_transaction_rule.objectIds()])
self.assertEquals(len(invoice_transaction_rule.objectValues()), 0)
# and add new content, predicate product_line
predicate_product_notebook = invoice_transaction_rule.newContent(
id = 'product_notebook',
title = 'Product Notebook',
portal_type = self.predicate_portal_type,
string_index = 'product',
int_index = '1',
membership_criterion_base_category_list = ['product_line',],
membership_criterion_category_list = ['product_line/storever/notebook'],
immediate_reindex = 1,
)
predicate_product_barebone = invoice_transaction_rule.newContent(
id = 'product_barebone',
title = 'Product Barebone',
portal_type = self.predicate_portal_type,
string_index = 'product',
int_index = '2',
membership_criterion_base_category_list = ['product_line',],
membership_criterion_category_list = ['product_line/storever/barebone'],
immediate_reindex = 1,
)
# ... and destination_region
predicate_region_france = invoice_transaction_rule.newContent(
id = 'region_france',
title = 'Region France',
portal_type = self.predicate_portal_type,
string_index = 'region',
int_index ='1',
membership_criterion_base_category_list = ['destination_region',],
membership_criterion_category_list =
['destination_region/region/europe/west/france'],
immediate_reindex = 1,
)
predicate_region_africa = invoice_transaction_rule.newContent(
id = 'region_africa',
title = 'region_africa',
portal_type = self.predicate_portal_type,
string_index = 'region',
int_index = '2',
membership_criterion_base_category_list = ['destination_region',],
membership_criterion_category_list = ['destination_region/region/africa'],
immediate_reindex = 1,
)
# sanity checks
self.failUnless(predicate_product_notebook != None)
self.failUnless(predicate_product_barebone != None)
self.failUnless(predicate_region_france != None)
self.failUnless(predicate_region_africa != None)
predicate_list = invoice_transaction_rule.contentValues(
filter = {'portal_type': self.predicate_portal_type})
self.assertEqual(len(predicate_list), 4)
sequence.edit(
invoice_transaction_rule = invoice_transaction_rule,
predicate_product_notebook = predicate_product_notebook,
predicate_product_barebone = predicate_product_barebone,
predicate_region_france = predicate_region_france,
predicate_region_africa = predicate_region_africa,
)
def stepUpdateSaleInvoiceTransactionRuleMatrix(self, sequence, **kw) :
""" creates/updates the matrix of the sale invoice transacction rule """
invoice_transaction_rule = sequence.get('invoice_transaction_rule')
base_id = 'movement'
kwd = {'base_id': base_id} kwd = {'base_id': base_id}
# update the matrix, generates the accounting rule cells # update the matrix, generates the accounting rule cells
self.invoice_transaction_rule.updateMatrix() invoice_transaction_rule.edit()
invoice_transaction_rule.updateMatrix()
self.tic()
# check the accounting rule cells inside the matrix # check the accounting rule cells inside the matrix
cell_list = self.invoice_transaction_rule.contentValues(filter={'portal_type':'Accounting Rule Cell'}) cell_list = invoice_transaction_rule.contentValues(
filter = {'portal_type':self.accounting_rule_cell_portal_type})
self.assertEqual(len(cell_list), 4) self.assertEqual(len(cell_list), 4)
self.product1_region1_cell = getattr(self.invoice_transaction_rule, 'vat_per_region_0_0', None) # In the matrix, cells are named on the scheme :
self.product1_region2_cell = getattr(self.invoice_transaction_rule, 'vat_per_region_0_1', None) # ${base_id} + '_'.join(predicate_dimension ordered by int_index)
self.product2_region1_cell = getattr(self.invoice_transaction_rule, 'vat_per_region_1_0', None) product_notebook_region_france_cell = getattr(invoice_transaction_rule,
self.product2_region2_cell = getattr(self.invoice_transaction_rule, 'vat_per_region_1_1', None) '%s_0_0'%base_id, None)
product_notebook_region_africa_cell = getattr(invoice_transaction_rule,
self.failUnless(self.product1_region1_cell != None) '%s_0_1'%base_id, None)
self.failUnless(self.product1_region2_cell != None) product_barebone_region_france_cell = getattr(invoice_transaction_rule,
self.failUnless(self.product2_region1_cell != None) '%s_1_0'%base_id, None)
self.failUnless(self.product2_region2_cell != None) product_barebone_region_africa_cell = getattr(invoice_transaction_rule,
'%s_1_1'%base_id, None)
self.product1_region1_line1 = getattr(self.product1_region1_cell, 'income', None)
self.failUnless(self.product1_region1_line1 != None) self.failUnless(product_notebook_region_france_cell != None)
self.product1_region1_line1.edit(title='income', source='account/account1', destination='account/account2', quantity=19.0) self.failUnless(product_notebook_region_africa_cell != None)
# flush activities self.failUnless(product_barebone_region_france_cell != None)
get_transaction().commit() self.failUnless(product_barebone_region_africa_cell != None)
sequence.edit(
product_notebook_region_france_cell = product_notebook_region_france_cell,
product_notebook_region_africa_cell = product_notebook_region_africa_cell,
product_barebone_region_france_cell = product_barebone_region_france_cell,
product_barebone_region_africa_cell = product_barebone_region_africa_cell,
)
def stepCreateNotebookFranceCell(self, sequence, **kw):
""" creates the content of product_notebook_region_france_cell """
# create content in the notebook / france cell
product_notebook_region_france_cell = sequence.get(
'product_notebook_region_france_cell')
product_notebook_region_france_cell_income = \
product_notebook_region_france_cell.newContent(
id = 'income',
source = sequence.get('income').getRelativeUrl(),
quantity = 1)
product_notebook_region_france_cell_receivable = \
product_notebook_region_france_cell.newContent(
id = 'receivable',
source = sequence.get('receivable').getRelativeUrl(),
quantity = -1.196)
product_notebook_region_france_cell_vat = \
product_notebook_region_france_cell.newContent(
id = 'collected_vat',
source = sequence.get('collected_vat').getRelativeUrl(),
quantity = 0.196)
sequence.edit(
invoice_transaction_rule_cell = product_notebook_region_france_cell,
product_notebook_region_france_cell_income =
product_notebook_region_france_cell_income,
product_notebook_region_france_cell_receivable =
product_notebook_region_france_cell_receivable,
product_notebook_region_france_cell_vat =
product_notebook_region_france_cell_vat,
)
def stepCreateBareboneFranceCell(self, sequence, **kw):
""" creates the content of product_barebone_region_france_cell,
the same as product_notebook_region_france_cell, but the income
account is differrent """
# create content in the notebook / france cell
product_barebone_region_france_cell = sequence.get(
'product_barebone_region_france_cell')
product_barebone_region_france_cell_income = \
product_barebone_region_france_cell.newContent(
id = 'income',
source = sequence.get('income_barebone').getRelativeUrl(),
quantity = 1)
product_barebone_region_france_cell_receivable = \
product_barebone_region_france_cell.newContent(
id = 'receivable',
source = sequence.get('receivable').getRelativeUrl(),
quantity = -1.196)
product_barebone_region_france_cell_vat = \
product_barebone_region_france_cell.newContent(
id = 'collected_vat',
source = sequence.get('collected_vat').getRelativeUrl(),
quantity = 0.196)
sequence.edit(
product_barebone_region_france_cell = product_barebone_region_france_cell,
product_barebone_region_france_cell_income =\
product_barebone_region_france_cell_income,
product_barebone_region_france_cell_vat =\
product_barebone_region_france_cell_vat,
product_barebone_region_france_cell_receivable =\
product_barebone_region_france_cell_receivable
)
def stepCreateAccounts(self, sequence, **kw):
"""
Create an income, an payable and a collected_vat account
"""
portal = self.getPortal()
account_module = self.getAccountModule()
if not hasattr(account_module, 'income') :
income = account_module.newContent(
id = "income",
portal_type = self.account_portal_type,
title = "Income Notebook",
account_type = "income",
immediate_reindex = 1,
)
income = account_module.newContent(
id = "income_barebone",
portal_type = self.account_portal_type,
title = "Income Barebone",
account_type = "income",
immediate_reindex = 1,
)
receivable = account_module.newContent(
id = "receivable",
portal_type=self.account_portal_type,
title = "Receivable",
account_type = "asset/receivable",
immediate_reindex = 1,
)
collected_vat = account_module.newContent(
id = "collected_vat",
portal_type=self.account_portal_type,
title = "Collected VAT",
account_type = "liability/payable/collected_vat",
immediate_reindex = 1,
)
# store accounts in sequence object
sequence.edit(
income = account_module.income,
income_barebone = account_module.income_barebone,
receivable = account_module.receivable,
collected_vat = account_module.collected_vat,
)
def stepCreateEntities(self, sequence, **kw) :
""" Create a vendor and a client organisation.
The region of the client is the same as the region
defined in the rule.
"""
organisation_module = self.getOrganisationModule()
if not hasattr(organisation_module, 'vendor') :
vendor = organisation_module.newContent(
portal_type = self.organisation_portal_type,
id = "vendor",
title = "Vendor",
region = "europe/west/france",
immediate_reindex = 1,
)
self.assertNotEquals(vendor.getDefaultRegionValue(), None)
client_fr = organisation_module.newContent(
portal_type = self.organisation_portal_type,
id = "client_fr",
title = "French Client",
region = "europe/west/france",
immediate_reindex = 1,
)
self.assertNotEquals(client_fr.getDefaultRegionValue(), None)
sequence.edit(
vendor = organisation_module.vendor,
client_fr = organisation_module.client_fr,
client = organisation_module.client_fr,
)
def stepCreateProducts(self, sequence, **kw) :
"""
Create 2 kind of products, a notebook (Varianted)
and a barebone not varianted.
"""
product_module = self.getProductModule()
if not hasattr(product_module, 'notebook') :
# Create some products
notebook = product_module.newContent(
id = 'notebook',
title = 'Notebook',
portal_type = self.product_portal_type,
product_line = 'storever/notebook',
base_price = 3.0,
immediate_reindex = 1,
)
# sets some variation categories on the notebook product
notebook.setVariationBaseCategoryList(["hd_size", "cpu_freq"])
notebook.setVariationCategoryList([
"cpu_freq/1Ghz",
"cpu_freq/2Ghz",
"hd_size/60Go",
"hd_size/120Go",])
barebone = product_module.newContent(
id = 'barebone',
title = 'Barebone',
portal_type = self.product_portal_type,
product_line = 'storever/barebone',
base_price = 5.0,
immediate_reindex = 1,
)
sequence.edit(
notebook = product_module.notebook,
barebone = product_module.barebone,
product_notebook = product_module.notebook,
product_barebone = product_module.barebone,
)
def stepCreateCurrencies(self, sequence, **kw) :
"""
Create EUR currency
"""
currency_module = self.getCurrencyModule()
if not hasattr(currency_module, 'EUR') :
currency_module.newContent(
id = 'EUR',
title = 'Euro',
portal_type = self.currency_portal_type,
)
sequence.edit(euro=currency_module.EUR, currency=currency_module.EUR)
def stepCreatePaymentRule(self, **kw) :
""" create a rule payment transaction generation """
# XXX: for now there are no cells in payment rule, so nothing to do here
# TODO
def stepCreateSimpleSaleInvoice(self, sequence, **kw) :
""" creates a simple sale invoice for non varianted notebook product.
The invoice is from `vendor` to `client_fr`, so the cell defined in
stepUpdateSaleInvoiceTransactionRuleMatrix should match.
This invoice containts one line, 10 notebook * 10 EUR, so total price
is 100
"""
vendor = sequence.get('vendor')
client = sequence.get('client')
product_notebook = sequence.get('product_notebook')
currency = sequence.get('currency')
simple_invoice = self.getAccountingModule().newContent(
id = 'simple_invoice',
portal_type = self.sale_invoice_transaction_portal_type,
resource = currency.getRelativeUrl(),
stop_date = DateTime(2004, 01, 01),
start_date = DateTime(2004, 01, 01),
source_section = vendor.getRelativeUrl(),
destination_section = client.getRelativeUrl(),
)
invoice_line = simple_invoice.newContent(
id = 'invoice_line',
resource = product_notebook.getRelativeUrl(),
quantity = 10,
price = 10)
self.assertEqual(invoice_line.getTotalPrice(), 100)
sequence.edit(
simple_invoice = simple_invoice,
invoice = simple_invoice,
invoice_line = invoice_line,
invoice_lines = [invoice_line]
)
def stepCreateSimpleSaleInvoiceTwoLines(self, sequence, **kw) :
"""
similar to stepCreateSimpleSaleInvoice, but replace
"10 notebook * 10 EUR, so total price is 100" by :
"5 notebook * 10 EUR + 5 notebook * 10 EUR , so total price is 100"
"""
vendor = sequence.get('vendor')
client = sequence.get('client')
product_notebook = sequence.get('product_notebook')
currency = sequence.get('currency')
simple_invoice = self.getAccountingModule().newContent(
id = 'simple_invoice_two_lines',
portal_type = self.sale_invoice_transaction_portal_type,
resource = currency.getRelativeUrl(),
stop_date = DateTime(2004, 01, 01),
start_date = DateTime(2004, 01, 01),
source_section = vendor.getRelativeUrl(),
destination_section = client.getRelativeUrl(),
)
invoice_line1 = simple_invoice.newContent(
id = 'invoice_line1',
resource = product_notebook.getRelativeUrl(),
quantity = 5,
price = 10)
invoice_line2 = simple_invoice.newContent(
id = 'invoice_line2',
resource = product_notebook.getRelativeUrl(),
quantity = 5,
price = 10)
self.assertEqual(invoice_line1.getTotalPrice()
+ invoice_line2.getTotalPrice(), 100)
sequence.edit(
simple_invoice = simple_invoice,
invoice = simple_invoice,
invoice_lines = [invoice_line1, invoice_line2]
)
def stepPlanInvoice(self, sequence, **kw) :
""" put the invoice in the `planned` state, which will
start the simulation process. """
invoice = sequence.get('invoice')
self.getPortal().portal_workflow.doActionFor(
invoice, 'plan_action',
wf_id = 'accounting_workflow'
)
self.assertEquals(invoice.getSimulationState(), 'planned')
def stepCreateMultiLineSaleInvoice(self, sequence, **kw) :
""" create an invoice with varianted products
The invoice is from `vendor` to `client_fr`, so the cell defined in
This invoice containts two lines :
10 notebook * 10 EUR, so total price is 100
(matched by product_notebook_region_france_cell)
10 barebone * 100 EUR, so total price is 1000
(matched by product_notebook_region_france_cell)
total price for the invoice is 100 + 1000
"""
vendor = sequence.get('vendor')
client = sequence.get('client')
product_notebook = sequence.get('product_notebook')
product_barebone = sequence.get('product_barebone')
currency = sequence.get('currency')
multi_line_invoice = self.getAccountingModule().newContent(
id = 'multi_line_invoice',
portal_type = self.sale_invoice_transaction_portal_type,
resource = currency.getRelativeUrl(),
price_currency = currency.getRelativeUrl(),
stop_date = DateTime(2004, 01, 01),
start_date = DateTime(2004, 01, 01),
source_section = vendor.getRelativeUrl(),
destination_section = client.getRelativeUrl(),
)
notebook_line = multi_line_invoice.newContent(
id = 'notebook_line',
resource = product_notebook.getRelativeUrl(),
quantity = 10,
price = 10)
barebone_line = multi_line_invoice.newContent(
id = 'barebone_line',
resource = product_barebone.getRelativeUrl(),
quantity = 10,
price = 100)
self.assertEqual( 10*10 + 10*100,
notebook_line.getTotalPrice() + barebone_line.getTotalPrice())
sequence.edit(
multi_line_invoice = multi_line_invoice,
invoice = multi_line_invoice,
invoice_lines = [notebook_line, barebone_line],
)
def stepCheckAddPredicate(self, sequence, **kw) :
invoice_transaction_rule = sequence.get('invoice_transaction_rule')
# next, we add a predicate to see if it is still okay (3x2 cells)
predicate_product3 = invoice_transaction_rule.newContent(
id = 'product_3',
title = 'product_3',
portal_type = self.predicate_portal_type,
string_index = 'product',
int_index = '3',
membership_criterion_base_category_list = ['product_line',],
membership_criterion_category_list = ['product_line/storever/openbrick'],
immediate_reindex = 1,
)
invoice_transaction_rule.updateMatrix()
self.tic() self.tic()
cell_list = invoice_transaction_rule.contentValues(
filter = {'portal_type': self.accounting_rule_cell_portal_type})
self.assertEqual(len(cell_list), 6)
def stepCheckRemovePredicate(self, sequence, **kw) :
invoice_transaction_rule = sequence.get('invoice_transaction_rule')
self.tic() # make sure message queue is empty
# then, we remove a predicate and check again (3x3 cells)
invoice_transaction_rule.deleteContent(id = 'region_africa')
invoice_transaction_rule.updateMatrix()
cell_list = invoice_transaction_rule.contentValues(
filter = {'portal_type':self.accounting_rule_cell_portal_type})
self.assertEqual(len(cell_list), 3)
def test_01_HasEverything(self, quiet=0, run=run_all_test): def stepCheckRestoreOriginalPredicates(self, sequence, **kw) :
if not run: return """ we put back the matrix in the original format (2x2 cells) """
invoice_transaction_rule = sequence.get("invoice_transaction_rule")
self.tic() # make sure message queue is empty
invoice_transaction_rule.deleteContent(id='product_3')
predicate_region_africa = invoice_transaction_rule.newContent(
id = 'region_africa', title = 'Region Africa',
portal_type = self.predicate_portal_type,
string_index = 'region', int_index = '2',
membership_criterion_base_category_list = ['destination_region',],
membership_criterion_category_list = ['destination_region/region/africa'],
immediate_reindex = 1,
)
invoice_transaction_rule.updateMatrix()
cell_list = invoice_transaction_rule.contentValues(
filter = {'portal_type':self.accounting_rule_cell_portal_type})
self.assertEqual(len(cell_list), 4)
def stepCreateDummyInvoice(self, sequence, **kw) :
""" Create a dummy invoice for temp movements """
invoice = self.getAccountingModule().newContent(
id = "dummy_invoice",
)
sequence.edit(invoice = invoice)
def stepCreateMatchableSaleInvoiceMovements(self, sequence, **kw) :
""" Create a temp movement that will be matched by the
default_invoice_transaction_rule """
from Products.ERP5Type.Document import newTempMovement
product_notebook_region_france_movement = newTempMovement(
sequence.get('invoice'),
'test1',
resource = sequence.get('notebook').getRelativeUrl(),
destination = sequence.get('client_fr').getRelativeUrl(),
)
product_barebone_region_france_movement = newTempMovement(
sequence.get('invoice'),
'test2',
resource = sequence.get('barebone').getRelativeUrl(),
destination = sequence.get('client_fr').getRelativeUrl(),
)
sequence.edit(
product_notebook_region_france_movement =
product_notebook_region_france_movement ,
product_barebone_region_france_movement =
product_barebone_region_france_movement ,
)
def stepCheckMatchableSaleInvoiceMovements(self, sequence, **kw) :
""" Check that we have a matching cell for the movement """
invoice_transaction_rule = sequence.get("invoice_transaction_rule")
product_barebone_region_france_movement = sequence.get(
'product_barebone_region_france_movement')
product_notebook_region_france_movement = sequence.get(
'product_notebook_region_france_movement')
# Make sure acquisition is working for destination_region
self.assertEqual(
product_barebone_region_france_movement.getDestinationRegion(),
'region/europe/west/france')
self.assertEqual(
product_notebook_region_france_movement.getDestinationRegion(),
'region/europe/west/france')
# Make sure category is working for resource
self.assertEqual(product_barebone_region_france_movement.getProductLine(),
'storever/barebone')
self.assertEqual(product_notebook_region_france_movement.getProductLine(),
'storever/notebook')
# check the predicates
predicate_product_notebook = sequence.get("predicate_product_notebook")
predicate_product_barebone = sequence.get("predicate_product_barebone")
predicate_region_france = sequence.get("predicate_region_france")
predicate_region_africa = sequence.get("predicate_region_africa")
self.assert_(not predicate_region_africa.test(
product_barebone_region_france_movement ))
self.assert_( predicate_region_france.test(
product_barebone_region_france_movement ))
self.assert_(not predicate_product_notebook.test(
product_barebone_region_france_movement ))
self.assert_( predicate_product_barebone.test(
product_barebone_region_france_movement ))
self.assert_(not predicate_region_africa.test(
product_notebook_region_france_movement ))
self.assert_( predicate_region_france.test(
product_notebook_region_france_movement ))
self.assert_(not predicate_product_barebone.test(
product_notebook_region_france_movement ))
self.assert_( predicate_product_notebook.test(
product_notebook_region_france_movement ))
# check the cells
product_notebook_region_france_cell = sequence.get(
'product_notebook_region_france_cell')
product_barebone_region_france_cell = sequence.get(
'product_barebone_region_france_cell')
product_notebook_region_africa_cell = sequence.get(
'product_notebook_region_africa_cell')
product_barebone_region_africa_cell = sequence.get(
'product_barebone_region_africa_cell')
self.assert_(not product_notebook_region_france_cell.test(
product_barebone_region_france_movement ))
self.assert_( product_barebone_region_france_cell.test(
product_barebone_region_france_movement ))
self.assert_(not product_notebook_region_africa_cell.test(
product_barebone_region_france_movement ))
self.assert_(not product_barebone_region_africa_cell.test(
product_barebone_region_france_movement ))
self.assert_( product_notebook_region_france_cell.test(
product_notebook_region_france_movement ))
self.assert_(not product_barebone_region_france_cell.test(
product_notebook_region_france_movement ))
self.assert_(not product_notebook_region_africa_cell.test(
product_notebook_region_france_movement ))
self.assert_(not product_barebone_region_africa_cell.test(
product_notebook_region_france_movement ))
# finally check the matching cell is the good one
self.assertEquals(product_notebook_region_france_cell,
invoice_transaction_rule._getMatchingCell(
product_notebook_region_france_movement ))
self.assertEqual(product_barebone_region_france_cell,
invoice_transaction_rule._getMatchingCell(
product_barebone_region_france_movement ))
def stepCreateNotMatchableSaleInvoiceMovements(self, sequence, **kw) :
""" create a temp movement that not any cell could match. """
from Products.ERP5Type.Document import newTempMovement
bad_movement1 = newTempMovement(
sequence.get("invoice"),
'test3',
product = None,
destination = sequence.get('client').getRelativeUrl(),
)
bad_movement2 = newTempMovement(
sequence.get("invoice"),
'test4',
gap = 'gap/1',
destination = sequence.get('client').getRelativeUrl(),
)
sequence.edit(
bad_movement1 = bad_movement1,
bad_movement2 = bad_movement2,
)
def stepCheckNotMatchableSaleInvoiceMovements(self, sequence, **kw) :
""" check that temp movement that cannot be matched is not matched. """
invoice_transaction_rule = sequence.get('invoice_transaction_rule')
self.assertEqual(None,
invoice_transaction_rule._getMatchingCell(
sequence.get('bad_movement1')))
self.assertEqual(None,
invoice_transaction_rule._getMatchingCell(
sequence.get('bad_movement2')))
def stepClearSimulation(self, sequence, **kw) :
""" clear the content of portal_simulation """
self.tic() # make sure message queue is empty
self.getSimulationTool().deleteContent(
list(self.getSimulationTool().objectIds()))
def stepClearAccountingModule(self, sequence, **kw) :
""" clear the content of accounting module """
self.tic() # make sure message queue is empty
# cancel accounting transaction to be able to delete them
for transaction in self.getAccountingModule().objectValues() :
self.getPortal().portal_workflow.doActionFor(
transaction, 'cancel_action', wf_id='accounting_workflow')
# delete
self.getAccountingModule().deleteContent(
list(self.getAccountingModule().objectIds()))
def stepCheckFirstRuleIsApplied(self, sequence, **kw) :
""" check every level of the simulation """
invoice = sequence.get('invoice')
invoice_line = sequence.get('invoice_line')
invoice_transaction_rule = sequence.get('invoice_transaction_rule')
vendor = sequence.get('vendor')
client = sequence.get('client')
currency = sequence.get('currency')
invoice_transaction_rule_cell = sequence.get(
'invoice_transaction_rule_cell')
# content of the simulation tool is a list of invoice rules
applied_rule_list = self.getSimulationTool().contentValues()
self.assertEqual(len(applied_rule_list), 1)
applied_rule = applied_rule_list[0]
self.assertEqual( applied_rule.getPortalType(),
self.applied_rule_portal_type)
self.assertEqual( applied_rule.getSpecialise(),
'portal_rules/default_invoice_rule')
self.assertEqual( applied_rule.getCausality(),
invoice.getRelativeUrl())
# inside the rule there are simulation movements
simulation_movement_list = applied_rule.contentValues()
# the first one is a mirror of the movement in the invoice line
self.assertEqual( len(simulation_movement_list), 1)
simulation_movement = simulation_movement_list[0]
self.assertEqual( simulation_movement.getPortalType(),
self.simulation_movement_portal_type)
self.assertEqual( invoice_line.getResource(),
simulation_movement.getResource())
self.assertEqual( invoice_line.getQuantity(),
simulation_movement.getQuantity())
self.assertEqual( invoice_line.getStopDate(),
simulation_movement.getStopDate())
self.assertEqual( invoice_line.getStartDate(),
simulation_movement.getStartDate())
self.assertEqual( invoice_line.getSourceSection(),
simulation_movement.getSourceSection())
self.assertEqual( invoice_line.getDestinationSection(),
simulation_movement.getDestinationSection())
self.assertEqual( invoice_line.getSource(),
simulation_movement.getSource())
self.assertEqual( invoice_line.getDestination(),
simulation_movement.getDestination())
# inside this movement there is an applied rule which
# specialize invoice_transaction_rule
applied_rule_list = simulation_movement.contentValues()
self.assertEquals( len(applied_rule_list), 1)
applied_rule = applied_rule_list[0]
self.assertEquals( applied_rule.getPortalType(),
self.applied_rule_portal_type)
self.assertEquals( applied_rule.getSpecialise(),
invoice_transaction_rule.getRelativeUrl())
# and in this applied rule, we got simulation movements,
# based on those inside product_notebook_region_france_cell
simulation_movement_list = applied_rule.contentValues()
self.assertEqual( len(simulation_movement_list), 3)
rule_movement_found = {}
for simulation_movement in simulation_movement_list :
self.assertEquals( simulation_movement.getSourceSection(),
vendor.getRelativeUrl())
self.assertEquals( simulation_movement.getDestinationSection(),
client.getRelativeUrl())
self.assertEquals( simulation_movement.getResource(),
currency.getRelativeUrl())
self.assertEquals( simulation_movement.getCausalityState(),
'expanded')
for rule_movement in invoice_transaction_rule_cell.contentValues() :
if simulation_movement.getSource() == rule_movement.getSource() :
rule_movement_found[rule_movement.getSource()] = 1
self.assertEquals(simulation_movement.getQuantity(),
rule_movement.getQuantity() * invoice_line.getTotalPrice())
self.assertEquals(simulation_movement.getSourceCredit(),
rule_movement.getSourceCredit() * invoice_line.getTotalPrice())
self.assertEquals(simulation_movement.getSourceDebit(),
rule_movement.getSourceDebit() * invoice_line.getTotalPrice())
self.assert_(len(rule_movement_found.keys()), 3)
sequence.edit( simulation_movement_list = simulation_movement_list )
def stepCheckPaymentRuleIsApplied(self, sequence, **kw) :
""" checks that a payment rule is applied for the total amount
of receivable """
# TODO
def stepConfirmInvoice(self, sequence, **kw) :
""" put the invoice in the `confirmed` state, which will
start the delivery builder """
invoice = sequence.get('invoice')
self.getPortal().portal_workflow.doActionFor(
invoice, 'confirm_action',
wf_id = 'accounting_workflow'
)
self.assertEquals(invoice.getSimulationState(), 'confirmed')
def stepCheckAccountingLinesCoherantWithSimulation(self, sequence, **kw) :
""" checks that accounting lines are created on the sale invoice
transaction """
invoice = sequence.get('invoice')
vendor = sequence.get('vendor')
client = sequence.get('client')
currency = sequence.get('currency')
invoice_line = sequence.get('invoice_line')
simulation_movement_list = sequence.get('simulation_movement_list')
invoice_transaction_rule_cell = sequence.get(
'invoice_transaction_rule_cell')
invoice_transaction_line_list = invoice.contentValues(
filter = {'portal_type':
self.sale_invoice_transaction_line_portal_type})
self.assertEquals( len(invoice_transaction_line_list),
len(simulation_movement_list))
simulation_movement_found = {}
for invoice_transaction_line in invoice_transaction_line_list :
self.assertEquals( invoice_transaction_line.getSourceSection(),
vendor.getRelativeUrl())
self.assertEquals( invoice_transaction_line.getDestinationSection(),
client.getRelativeUrl())
self.assertEquals( invoice_transaction_line.getResource(),
currency.getRelativeUrl())
for simulation_movement in simulation_movement_list :
if simulation_movement.getSource() == \
invoice_transaction_line.getSource() :
simulation_movement_found[simulation_movement.getSource()] = 1
self.assertEquals(simulation_movement.getQuantity(),
invoice_transaction_line.getQuantity())
self.assertEquals(simulation_movement.getSourceCredit(),
invoice_transaction_line.getSourceCredit())
self.assertEquals(simulation_movement.getSourceDebit(),
invoice_transaction_line.getSourceDebit())
self.assertEquals(simulation_movement.getDelivery(),
invoice_transaction_line.getRelativeUrl())
self.assert_(len(simulation_movement_found.keys()), 3)
def stepCheckAccountingLinesCreatedForSimpleInvoice(
self, sequence, **kw) :
""" Checks that accounting lines are created on the sale invoice
transaction and that all movement are correctly aggregated.
The price of the invoice was 100, it should result in the following
accounting layout :
=============== ======= =======
account Debit Credit
=============== ======= =======
income 100
collected_vat 19.60
receivable 119.60
=============== ======= =======
"""
invoice = sequence.get('invoice')
vendor = sequence.get('vendor')
client = sequence.get('client')
currency = sequence.get('currency')
invoice_lines = sequence.get('invoice_lines')
invoice_transaction_line_list = invoice.contentValues(
filter = {'portal_type': self.sale_invoice_transaction_line_portal_type})
self.assertEquals(len(invoice_transaction_line_list), 3)
accounting_lines_layout = {
'income' : (0, 100),
'collected_vat' : (0, 19.60),
'receivable' : (119.60, 0),
}
for invoice_transaction_line in invoice_transaction_line_list :
debit, credit = accounting_lines_layout[invoice_transaction_line.getSourceId()]
self.assertEquals(debit, invoice_transaction_line.getSourceDebit())
self.assertEquals(credit, invoice_transaction_line.getSourceCredit())
def stepCheckAccountingLinesCreatedForMultiLineInvoice(
self, sequence, **kw) :
""" Checks that accounting lines are created on the sale invoice
transaction and that all movement are correctly aggregated.
The price of the invoice was 1100, it should result in the following
accounting layout :
=============== ======= =======
account Debit Credit
=============== ======= =======
income 100
income_barebone 1000
collected_vat 215.60
receivable 1315.60
=============== ======= =======
"""
invoice = sequence.get('invoice')
vendor = sequence.get('vendor')
client = sequence.get('client')
currency = sequence.get('currency')
invoice_lines = sequence.get('invoice_lines')
invoice_transaction_line_list = invoice.contentValues(
filter = {'portal_type': self.sale_invoice_transaction_line_portal_type})
self.assertEquals(len(invoice_transaction_line_list), 4)
accounting_lines_layout = {
'income' : (0, 100),
'income_barebone' : (0, 1000),
'collected_vat' : (0, 215.60),
'receivable' : (1315.60, 0),
}
for invoice_transaction_line in invoice_transaction_line_list :
debit, credit = accounting_lines_layout[invoice_transaction_line.getSourceId()]
self.assertEquals(debit, invoice_transaction_line.getSourceDebit())
self.assertEquals(credit, invoice_transaction_line.getSourceCredit())
def test_01_HasEverything(self, quiet=0, run=RUN_ALL_TESTS):
""" check necessary tools and modules are present. """
if not run:
return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Has Everything ') ZopeTestCase._print('\nTest Has Everything ')
LOG('Testing... ',0,'testHasEverything') LOG('Testing... ', INFO, 'testHasEverything')
self.failUnless(self.getCategoryTool() != None) self.failUnless(self.getCategoryTool() != None)
self.failUnless(self.getSimulationTool() != None) self.failUnless(self.getSimulationTool() != None)
self.failUnless(self.getTypeTool() != None) self.failUnless(self.getTypeTool() != None)
...@@ -249,372 +1091,194 @@ class TestAccountingRules(ERP5TypeTestCase): ...@@ -249,372 +1091,194 @@ class TestAccountingRules(ERP5TypeTestCase):
self.failUnless(self.getProductModule() != None) self.failUnless(self.getProductModule() != None)
self.failUnless(self.getCurrencyModule() != None) self.failUnless(self.getCurrencyModule() != None)
def test_02_UpdateInvoiceTransactionRuleMatrix(self, quiet=0, run=run_all_test): def test_02_UpdateInvoiceTransactionRuleMatrix(self, quiet=0,
run=RUN_ALL_TESTS):
""" """
Try to update the matrix after adding some predicates, and check if all objects were created Try to update the matrix after adding some predicates,
and check if all objects were created
""" """
if not run: return if not run:
return
if not quiet: if not quiet:
message = 'Test Update Invoice Transaction Rule Matrix' message = 'Test Update Invoice Transaction Rule Matrix'
ZopeTestCase._print('\n%s ' % message) ZopeTestCase._print('\n%s ' % message)
LOG('Testing... ',0,message) LOG('Testing... ', INFO, message)
# before the tests, we need to be sure we have four predicates self.playSequence("""
self.failUnless(self.predicate_product1 != None) stepCreateSaleInvoiceTransactionRule
self.failUnless(self.predicate_product2 != None) stepUpdateSaleInvoiceTransactionRuleMatrix
self.failUnless(self.predicate_region1 != None) stepTic
self.failUnless(self.predicate_region2 != None) stepCheckAddPredicate
predicate_list = self.invoice_transaction_rule.contentValues(filter={'portal_type':'Predicate Group'}) stepTic
self.assertEqual(len(predicate_list), 4) stepCheckRemovePredicate
stepTic
# first, we check the matrix was initialized correctly (2x2 cells) stepCheckRestoreOriginalPredicates
self.updateInvoiceTransactionRuleMatrix() """)
cell_list = self.invoice_transaction_rule.contentValues(filter={'portal_type':'Accounting Rule Cell'})
self.assertEqual(len(cell_list), 4) def test_03_invoiceTransactionRule_getMatchingCell(self,
quiet=0, run=RUN_ALL_TESTS):
# next, we add a predicate to see if it is still okay (3x2 cells)
self.predicate_product3 = self.invoice_transaction_rule.newContent(id='product_3', title='product_3', portal_type='Predicate Group', string_index='product', int_index='3', membership_criterion_base_category_list=['product_line',], membership_criterion_category_list=['product_line/storever/openbrick'], immediate_reindex=1)
self.invoice_transaction_rule.updateMatrix()
cell_list = self.invoice_transaction_rule.contentValues(filter={'portal_type':'Accounting Rule Cell'})
self.assertEqual(len(cell_list), 6)
# then, we remove a predicate and check again (3x1 cells)
self.invoice_transaction_rule.deleteContent(id='region_2')
self.invoice_transaction_rule.updateMatrix()
cell_list = self.invoice_transaction_rule.contentValues(filter={'portal_type':'Accounting Rule Cell'})
self.assertEqual(len(cell_list), 3)
# finally, we put back the matrix in the original format (2x2 cells)
self.invoice_transaction_rule.deleteContent(id='product_3')
self.predicate_region2 = self.invoice_transaction_rule.newContent(id='region_2', title='region_2', portal_type='Predicate Group', string_index='region', int_index='2', membership_criterion_base_category_list=['region',], membership_criterion_category_list=['region/africa'], immediate_reindex=1)
self.invoice_transaction_rule.updateMatrix()
cell_list = self.invoice_transaction_rule.contentValues(filter={'portal_type':'Accounting Rule Cell'})
self.assertEqual(len(cell_list), 4)
def test_03_invoiceTransactionRule_getMatchingCell(self, quiet=0, run=run_all_test):
""" """
test InvoiceTransactionRule.getCellByPredicate() test predicates for the cells of invoice transaction rule
""" """
if not run: return if not run:
return
if not quiet: if not quiet:
message = 'Test Invoice Transaction Rule getCellByPredicate ' message = 'Test Invoice Transaction Rule getMatchingCell '
ZopeTestCase._print('\n%s ' % message) ZopeTestCase._print('\n%s ' % message)
LOG('Testing... ',0,message) LOG('Testing... ', INFO, message)
# before the tests, we must update the matrix
self.updateInvoiceTransactionRuleMatrix() self.playSequence("""
from Products.ERP5Type.Document import newTempMovement stepCreateAccounts
movement = newTempMovement(self.invoice, 'test1', resource = 'product/product1', stepCreateEntities
destination = 'organisation/nexedi') stepCreateCurrencies
# Make sure acquisition is working for destination_region stepTic
self.assertEqual(movement.getDestinationRegion(), 'region/europe/west/france') stepCreateSaleInvoiceTransactionRule
# Make sure category is working for destination_region stepUpdateSaleInvoiceTransactionRuleMatrix
self.assertEqual(movement.getProductLine(), 'storever/notebook') stepCreateProducts
# Test cell on movement stepTic
# correct cell stepCreateDummyInvoice
self.assertEqual(self.product1_region1_cell, self.invoice_transaction_rule._getMatchingCell(movement)) stepCreateMatchableSaleInvoiceMovements
# no predicate for this category stepCheckMatchableSaleInvoiceMovements
movement = newTempMovement(self.invoice, 'test2', resource = 'product/product2', stepCreateNotMatchableSaleInvoiceMovements
destination = 'organisation/nexedi') stepCheckNotMatchableSaleInvoiceMovements
self.assertEqual(self.product2_region1_cell, self.invoice_transaction_rule._getMatchingCell(movement)) """)
# incorrect category
movement = newTempMovement(self.invoice, 'test3', product = None, destination = 'organisation/nexedi') def test_04_SimpleInvoice(self, quiet=0, run=RUN_ALL_TESTS):
self.assertEqual(None, self.invoice_transaction_rule._getMatchingCell(movement))
# incorrect dimension
movement = newTempMovement(self.invoice, 'test4', pcg = 'pcg/1', destination = 'organisation/nexedi')
self.assertEqual(None, self.invoice_transaction_rule._getMatchingCell(movement))
def test_04_invoiceRule_expand(self, quiet=0, run=run_all_test):
""" """
Try to expand an invoice containing Invoice Lines Try to expand an invoice containing only one simple Invoice Line.
Check that the build is correct.
""" """
if not run: return if not run:
return
if not quiet: if not quiet:
message = 'Test Invoice Rule Expand ' message = 'Test Simple Invoice Rule'
ZopeTestCase._print('\n%s ' % message) ZopeTestCase._print('\n%s ' % message)
LOG('Testing... ',0,message) LOG('Testing... ', INFO, message)
# before the tests, we must update the matrix self.playSequence("""
self.updateInvoiceTransactionRuleMatrix() stepCreateAccounts
stepCreateEntities
#### stepCreateCurrencies
# TEST NO 1 : one Invoice Line (quantity * price) * tax == (7 * 11) * 19 stepCreateProducts
#### stepCreateSaleInvoiceTransactionRule
# the invoice is expanded by the invoice_edit_workflow when it is edited. stepUpdateSaleInvoiceTransactionRuleMatrix
self.invoice.edit(title='Invoice1') stepCreateNotebookFranceCell
stepTic
# flush activities stepClearSimulation
get_transaction().commit() stepClearAccountingModule
self.tic() stepCreateSimpleSaleInvoice
stepPlanInvoice
LOG('history', 0, repr(( self.workflow_tool.getHistoryOf('edit_workflow', self.invoice) ))) stepTic
stepCheckFirstRuleIsApplied
# check every level of the simulation stepCheckPaymentRuleIsApplied
applied_rule_list = self.simulation_tool.contentValues() # list of Invoice Rules stepConfirmInvoice
self.assertEqual(len(applied_rule_list), 1) stepTic
stepCheckAccountingLinesCoherantWithSimulation
applied_rule = applied_rule_list[0] """ )
self.assertEqual(applied_rule.getPortalType(), 'Applied Rule')
self.assertEqual(applied_rule.getSpecialise(), 'portal_rules/default_invoice_rule') def test_04b_SimpleInvoiceConfirm(self, quiet=0, run=RUN_ALL_TESTS):
self.assertEqual(applied_rule.getCausality(), 'accounting/invoice1') """
Same test as SimpleInvoice but directly confirm the invoice without planning it
movement_list = applied_rule.contentValues() # list of Invoice Lines """
self.assertEqual(len(movement_list), 1) if not run:
return
# Make sure the movement acquires all properties if not quiet:
movement = movement_list[0] message = 'Test Simple Invoice Rule (without plan)'
self.assertEqual(movement.getId(), '1') ZopeTestCase._print('\n%s ' % message)
self.assertEqual(movement.getPortalType(), 'Simulation Movement') LOG('Testing... ', INFO, message)
self.assertEqual(movement.getDelivery(), 'accounting/invoice1/1')
self.assertEqual(movement.getResource(), 'product/product1') self.playSequence("""
self.assertEqual(movement.getDestination(), 'organisation/client1') stepCreateAccounts
self.assertEqual(movement.getDestinationSection(), 'organisation/client1') stepCreateEntities
self.assertEqual(movement.getProductLine(), 'storever/notebook') stepCreateCurrencies
self.assertEqual(movement.getDestinationRegion(), 'region/europe/west/france') stepCreateProducts
stepCreateSaleInvoiceTransactionRule
# Make sure the invoice_transaction_rule applies to this movement stepUpdateSaleInvoiceTransactionRuleMatrix
self.assertEqual(self.invoice_transaction_rule.test(movement), True) stepCreateNotebookFranceCell
# And make sure the first cell applies stepTic
self.assertEqual(self.product1_region1_line1.test(movement), True) stepClearSimulation
stepClearAccountingModule
# Make sure expand succeeded stepCreateSimpleSaleInvoice
sub_applied_rule_list = movement.contentValues() # list of Invoice Transaction Rules stepConfirmInvoice
self.assertEqual(len(sub_applied_rule_list), 1) stepTic
stepCheckAccountingLinesCreatedForSimpleInvoice
sub_applied_rule = sub_applied_rule_list[0] """ )
self.assertEqual(sub_applied_rule.getId(), 'default_invoice_transaction_rule')
self.assertEqual(sub_applied_rule.getPortalType(), 'Applied Rule') def test_04c_SimpleInvoiceConfirm(self, quiet=0, run=RUN_ALL_TESTS):
self.assertEqual(sub_applied_rule.getSpecialise(), 'portal_rules/default_invoice_transaction_rule') """
Same test as SimpleInvoice but use 2 lines of quantity 5 instead of
sub_movement_list = sub_applied_rule.contentValues() # list of Sale Invoice Transaction Lines 1 line of quantity 10.
self.assertEqual(len(sub_movement_list), 3) # there should be 'income', 'receivable', 'collected_vat' """
if not run:
for sub_movement in sub_movement_list : return
if sub_movement.getId() not in ('income', 'receivable', 'collected_vat',) : if not quiet:
self.fail(msg='%s is not a normal Sale Invoice Transaction Line name' % sub_movement) message = 'Test Simple Invoice Rule (without plan)'
self.assertEqual(movement.getPortalType(), 'Simulation Movement') ZopeTestCase._print('\n%s ' % message)
if sub_movement.getId() == 'income' : LOG('Testing... ', INFO, message)
self.assertEqual(sub_movement.getSource(), 'account/account1')
self.assertEqual(sub_movement.getDestination(), 'account/account2') self.playSequence("""
self.assertEqual(sub_movement.getQuantity(), (7.0 * 11.0) * 19.0) stepCreateAccounts
stepCreateEntities
# check if invoice transaction lines are added and correct (outside simulation too) stepCreateCurrencies
invoice_transaction_line = getattr(self.invoice, 'income', None) stepCreateProducts
self.failIf(invoice_transaction_line is None) stepCreateSaleInvoiceTransactionRule
self.assertEqual(invoice_transaction_line.getPortalType(), 'Sale Invoice Transaction Line') stepUpdateSaleInvoiceTransactionRuleMatrix
self.assertEqual(invoice_transaction_line.getSource(), 'account/account1') stepCreateNotebookFranceCell
self.assertEqual(invoice_transaction_line.getDestination(), 'account/account2') stepTic
self.assertEqual(invoice_transaction_line.getQuantity(), (7.0 * 11.0) * 19.0) stepClearSimulation
stepClearAccountingModule
#### stepCreateSimpleSaleInvoiceTwoLines
# TEST NO 2 : one Invoice Line (quantity * price) * tax == (7 * 11) * 19 stepConfirmInvoice
# expand once again and check that everithing is still the same stepTic
#### stepCheckAccountingLinesCreatedForSimpleInvoice
# the invoice is expanded by the invoice_edit_workflow when it is edited. """ )
self.invoice.edit(title='Invoice1')
def test_05_MultiLineInvoice(self, quiet=0, run=RUN_ALL_TESTS):
# flush activities """
get_transaction().commit() Try to expand an invoice containing multiples Invoice Line.
self.tic() Check that the build is correct, ie the movement are aggregated.
"""
# check every level of the simulation if not run:
applied_rule_list = self.simulation_tool.contentValues() # list of Invoice Rules return
self.assertEqual(len(applied_rule_list), 1) if not quiet:
message = 'Test Multi Line Invoice Rule'
applied_rule = applied_rule_list[0] ZopeTestCase._print('\n%s ' % message)
self.assertEqual(applied_rule.getPortalType(), 'Applied Rule') LOG('Testing... ', INFO, message)
self.assertEqual(applied_rule.getSpecialise(), 'portal_rules/default_invoice_rule')
self.assertEqual(applied_rule.getCausality(), 'accounting/invoice1') self.playSequence("""
stepCreateAccounts
movement_list = applied_rule.contentValues() # list of Invoice Lines stepCreateEntities
self.assertEqual(len(movement_list), 1) stepCreateCurrencies
stepCreateProducts
movement = movement_list[0] stepCreateSaleInvoiceTransactionRule
self.assertEqual(movement.getId(), '1') stepTic
self.assertEqual(movement.getPortalType(), 'Simulation Movement') stepUpdateSaleInvoiceTransactionRuleMatrix
self.assertEqual(movement.getDelivery(), 'accounting/invoice1/1') stepTic
stepCreateNotebookFranceCell
sub_applied_rule_list = movement.contentValues() # list of Invoice Transaction Rules stepCreateBareboneFranceCell
self.assertEqual(len(sub_applied_rule_list), 1) stepTic
stepClearSimulation
sub_applied_rule = sub_applied_rule_list[0] stepClearAccountingModule
self.assertEqual(sub_applied_rule.getId(), 'default_invoice_transaction_rule') stepCreateMultiLineSaleInvoice
self.assertEqual(sub_applied_rule.getPortalType(), 'Applied Rule') stepPlanInvoice
self.assertEqual(sub_applied_rule.getSpecialise(), 'portal_rules/default_invoice_transaction_rule') stepConfirmInvoice
stepTic
sub_movement_list = sub_applied_rule.contentValues() # list of Sale Invoice Transaction Lines stepCheckAccountingLinesCreatedForMultiLineInvoice
self.assertEqual(len(sub_movement_list), 3) # there should be 'income', 'receivable', 'collected_vat' """ )
for sub_movement in sub_movement_list : def test_06_PaymentRuleForSaleInvoice(self, quiet=0, run=RUN_ALL_TESTS):
if sub_movement.getId() not in ('income', 'receivable', 'collected_vat',) : """ checks the payment rule is applied on sale invoice simulation
self.fail(msg='%s is not a normal Sale Invoice Transaction Line name' % sub_movement) movement. """
self.assertEqual(movement.getPortalType(), 'Simulation Movement') # checks :
if sub_movement.getId() == 'income' : # date from trade condition
self.assertEqual(sub_movement.getSource(), 'account/account1') # quantity from sum of receivable movement
self.assertEqual(sub_movement.getDestination(), 'account/account2') # link to sale invoice
self.assertEqual(sub_movement.getQuantity(), (7.0 * 11.0) * 19.0)
# check if invoice transaction lines are added and correct (outside simulation too)
#self.invoice.buildInvoiceTransactionList()
invoice_transaction_line = getattr(self.invoice, 'income', None)
self.failIf(invoice_transaction_line is None)
self.assertEqual(invoice_transaction_line.getPortalType(), 'Sale Invoice Transaction Line')
self.assertEqual(invoice_transaction_line.getSource(), 'account/account1')
self.assertEqual(invoice_transaction_line.getDestination(), 'account/account2')
self.assertEqual(invoice_transaction_line.getQuantity(), (7.0 * 11.0) * 19.0)
####
# TEST NO 3 : two Invoice Lines (quantity * price) * tax == (7 * 11) * 19 + (13 * 17) * 19
# add a line with same product_line and test again
####
invoice_line2 = self.invoice.newContent(id='2', portal_type='Invoice Line', resource='product/product1', quantity=13.0, price=17.0)
# the invoice is expanded by the invoice_edit_workflow when it is edited.
self.invoice.edit(title='Invoice1')
# flush activities
get_transaction().commit()
self.tic()
# check every level of the simulation
applied_rule_list = self.simulation_tool.contentValues() # list of Invoice Rules
self.assertEqual(len(applied_rule_list), 1)
applied_rule = applied_rule_list[0]
self.assertEqual(applied_rule.getPortalType(), 'Applied Rule')
self.assertEqual(applied_rule.getSpecialise(), 'portal_rules/default_invoice_rule')
self.assertEqual(applied_rule.getCausality(), 'accounting/invoice1')
movement_list = applied_rule.contentValues() # list of Invoice Lines
self.assertEqual(len(movement_list), 2)
for movement in movement_list :
movement_id = movement.getId()
if movement_id not in ('1', '2',) :
self.fail(msg='%s is not a normal Invoice Line name' % sub_movement)
self.assertEqual(movement.getPortalType(), 'Simulation Movement')
self.assertEqual(movement.getDelivery(), 'accounting/invoice1/%s' % movement_id)
sub_applied_rule_list = movement.contentValues() # list of Invoice Transaction Rules
self.assertEqual(len(sub_applied_rule_list), 1)
sub_applied_rule = sub_applied_rule_list[0]
self.assertEqual(sub_applied_rule.getId(), 'default_invoice_transaction_rule')
self.assertEqual(sub_applied_rule.getPortalType(), 'Applied Rule')
self.assertEqual(sub_applied_rule.getSpecialise(), 'portal_rules/default_invoice_transaction_rule')
sub_movement_list = sub_applied_rule.contentValues() # list of Sale Invoice Transaction Lines
self.assertEqual(len(sub_movement_list), 3) # there should be 'income', 'receivable', 'collected_vat'
for sub_movement in sub_movement_list :
if sub_movement.getId() not in ('income', 'receivable', 'collected_vat',) :
self.fail(msg='%s is not a normal Sale Invoice Transaction Line name' % sub_movement)
self.assertEqual(movement.getPortalType(), 'Simulation Movement')
if sub_movement.getId() == 'income' :
self.assertEqual(sub_movement.getSource(), 'account/account1')
self.assertEqual(sub_movement.getDestination(), 'account/account2')
if movement_id == '1' :
self.assertEqual(sub_movement.getQuantity(), (7.0 * 11.0) * 19.0)
elif movement_id == '2' :
self.assertEqual(sub_movement.getQuantity(), (13.0 * 17.0) * 19.0)
# check if invoice transaction lines are added and correct (outside simulation too)
invoice_transaction_line = getattr(self.invoice, 'income', None)
self.failIf(invoice_transaction_line is None)
self.assertEqual(invoice_transaction_line.getPortalType(), 'Sale Invoice Transaction Line')
self.assertEqual(invoice_transaction_line.getSource(), 'account/account1')
self.assertEqual(invoice_transaction_line.getDestination(), 'account/account2')
self.assertEqual(invoice_transaction_line.getQuantity(), (7.0 * 11.0 + 13.0 * 17.0) * 19.0)
####
# TEST NO 4 : three Invoice Lines (quantity * price) * tax == (7 * 11) * 19 + (13 * 17) * 19 + (23 * 29) * 31
####
# add a line with different product_line and test again (we first need a line for this one)
self.product2_region1_line1 = getattr(self.product2_region1_cell, 'income', None)
self.failUnless(self.product2_region1_line1 != None)
self.product2_region1_line1.edit(title='income', source='account/account3', destination='account/account4', quantity=31.0)
invoice_line3 = self.invoice.newContent(id='3', portal_type='Invoice Line', resource='product/product2', quantity=23.0, price=29.0)
# the invoice is expanded by the invoice_edit_workflow when it is edited.
self.invoice.edit(title='Invoice1')
# flush activities
get_transaction().commit()
self.tic()
# check every level of the simulation
applied_rule_list = self.simulation_tool.contentValues() # list of Invoice Rules
self.assertEqual(len(applied_rule_list), 1)
applied_rule = applied_rule_list[0]
self.assertEqual(applied_rule.getPortalType(), 'Applied Rule')
self.assertEqual(applied_rule.getSpecialise(), 'portal_rules/default_invoice_rule')
self.assertEqual(applied_rule.getCausality(), 'accounting/invoice1')
movement_list = applied_rule.contentValues() # list of Invoice Lines
self.assertEqual(len(movement_list), 3)
for movement in movement_list :
movement_id = movement.getId()
if movement_id not in ('1', '2', '3',) :
self.fail(msg='%s is not a normal Invoice Line name' % sub_movement)
self.assertEqual(movement.getPortalType(), 'Simulation Movement')
self.assertEqual(movement.getDelivery(), 'accounting/invoice1/%s' % movement_id)
sub_applied_rule_list = movement.contentValues() # list of Invoice Transaction Rules
self.assertEqual(len(sub_applied_rule_list), 1)
sub_applied_rule = sub_applied_rule_list[0]
self.assertEqual(sub_applied_rule.getId(), 'default_invoice_transaction_rule')
self.assertEqual(sub_applied_rule.getPortalType(), 'Applied Rule')
self.assertEqual(sub_applied_rule.getSpecialise(), 'portal_rules/default_invoice_transaction_rule')
sub_movement_list = sub_applied_rule.contentValues() # list of Sale Invoice Transaction Lines
self.assertEqual(len(sub_movement_list), 3) # there should be 'income', 'receivable', 'collected_vat'
for sub_movement in sub_movement_list :
if sub_movement.getId() not in ('income', 'receivable', 'collected_vat',) :
self.fail(msg='%s is not a normal Sale Invoice Transaction Line name' % sub_movement)
self.assertEqual(movement.getPortalType(), 'Simulation Movement')
if sub_movement.getId() == 'income' :
if movement_id == '1' :
self.assertEqual(sub_movement.getSource(), 'account/account1')
self.assertEqual(sub_movement.getDestination(), 'account/account2')
self.assertEqual(sub_movement.getQuantity(), (7.0 * 11.0) * 19.0)
elif movement_id == '2' :
self.assertEqual(sub_movement.getSource(), 'account/account1')
self.assertEqual(sub_movement.getDestination(), 'account/account2')
self.assertEqual(sub_movement.getQuantity(), (13.0 * 17.0) * 19.0)
elif movement_id == '3' :
self.assertEqual(sub_movement.getSource(), 'account/account3')
self.assertEqual(sub_movement.getDestination(), 'account/account4')
self.assertEqual(sub_movement.getQuantity(), (23.0 * 29.0) * 31.0)
# check if invoice transaction lines are added and correct (outside simulation too)
invoice_transaction_line = getattr(self.invoice, 'income', None)
if invoice_transaction_line.getSource() != 'account/account1':
other_invoice_transaction_line = invoice_transaction_line
invoice_transaction_line = getattr(self.invoice, 'income_1', None)
else:
other_invoice_transaction_line = getattr(self.invoice, 'income_1', None)
self.failIf(invoice_transaction_line is None)
self.assertEqual(invoice_transaction_line.getPortalType(), 'Sale Invoice Transaction Line')
self.assertEqual(invoice_transaction_line.getSource(), 'account/account1')
self.assertEqual(invoice_transaction_line.getDestination(), 'account/account2')
self.assertEqual(invoice_transaction_line.getQuantity(), (7.0 * 11.0 + 13.0 * 17.0) * 19.0)
invoice_transaction_line = other_invoice_transaction_line
self.failIf(invoice_transaction_line is None)
self.assertEqual(invoice_transaction_line.getPortalType(), 'Sale Invoice Transaction Line')
self.assertEqual(invoice_transaction_line.getSource(), 'account/account3')
self.assertEqual(invoice_transaction_line.getDestination(), 'account/account4')
self.assertEqual(invoice_transaction_line.getQuantity(), (23.0 * 29.0) * 31.0)
if __name__ == '__main__': if __name__ == '__main__':
framework() framework()
else: else:
import unittest import unittest
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestAccountingRules)) suite.addTest(unittest.makeSuite(TestAccountingRules))
return suite return suite
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment