Commit 1c49a1ac authored by Nicolas Wavrant's avatar Nicolas Wavrant

erp5_accounting: closing an Accounting Period generates one Balance...

erp5_accounting: closing an Accounting Period generates one Balance Transaction per accounting ledger

BalanceTransaction.py updated to correctly index Balance Transactions with their ledgers.
_computeStockDifferenceList also now returns a correct result
parent 880248d8
"""Creates a balance transaction to open the next period. """Creates a balance transaction to open the next period.
""" """
from Products.ZSQLCatalog.SQLCatalog import Query
portal = context.getPortalObject() portal = context.getPortalObject()
Base_translateString = portal.Base_translateString Base_translateString = portal.Base_translateString
...@@ -61,7 +63,9 @@ section_list = [section] ...@@ -61,7 +63,9 @@ section_list = [section]
if group_value is not None: if group_value is not None:
section_list.extend(getDependantSectionList(group_value, section)) section_list.extend(getDependantSectionList(group_value, section))
def createBalanceTransaction(section): ledger_list = portal.portal_categories.ledger.getCategoryChildValueList(is_self_excluded=1) + [None,]
def createBalanceTransaction(section, ledger=None):
balance_date = at_date + 1 balance_date = at_date + 1
# We discard hours, minutes and seconds and at the same time, make sure the date # We discard hours, minutes and seconds and at the same time, make sure the date
# is in its "normal timezone". For example, when at_date is the day of a dailight saving # is in its "normal timezone". For example, when at_date is the day of a dailight saving
...@@ -69,220 +73,247 @@ def createBalanceTransaction(section): ...@@ -69,220 +73,247 @@ def createBalanceTransaction(section):
balance_date = DateTime(balance_date.year(), balance_date.month(), balance_date.day()) balance_date = DateTime(balance_date.year(), balance_date.month(), balance_date.day())
return portal.accounting_module.newContent( return portal.accounting_module.newContent(
portal_type='Balance Transaction', portal_type='Balance Transaction',
ledger=ledger,
start_date=balance_date, start_date=balance_date,
title=context.getTitle() or Base_translateString('Balance Transaction'), title=context.getTitle() or Base_translateString('Balance Transaction'),
destination_section_value=section, destination_section_value=section,
resource=section_currency, resource=section_currency,
causality_value=context) causality_value=context)
getInventoryList = portal.portal_simulation.getInventoryList
with context.defaultActivateParameterDict({'tag': activity_tag}, placeless=True): with context.defaultActivateParameterDict({'tag': activity_tag}, placeless=True):
for section in section_list: # List ledgers on which there are movements
section_uid = section.getUid() inventory_ledger_uid_list = [inventory.ledger_uid for inventory \
balance_transaction = None in getInventoryList(at_date=at_date.latestTime(),
portal_type=portal.getPortalAccountingMovementTypeList(),
group_by_ledger=True)]
group_by_node_node_category_list = [] for ledger in ledger_list:
group_by_mirror_section_node_category_list = []
group_by_payment_node_category_list = []
profit_and_loss_node_category_list = []
node_category_list = portal.portal_categories\ # If there are no movements within this ledger, we can
.account_type.getCategoryChildValueList() # directly go to another
for node_category in node_category_list: if ledger is None and None not in inventory_ledger_uid_list:
node_category_url = node_category.getRelativeUrl() continue
if node_category_url in ( elif ledger is not None and ledger.getUid() not in inventory_ledger_uid_list:
'account_type/asset/cash/bank',): continue
group_by_payment_node_category_list.append(node_category_url)
elif node_category_url in (
'account_type/asset/receivable',
'account_type/liability/payable'):
group_by_mirror_section_node_category_list.append(node_category_url)
elif node_category.isMemberOf('account_type/income') or \
node_category.isMemberOf('account_type/expense'):
profit_and_loss_node_category_list.append(node_category_url)
else:
group_by_node_node_category_list.append(node_category_url)
getInventoryList = portal.portal_simulation.getInventoryList if ledger is not None:
ledger_uid = ledger.getUid()
ledger_url = ledger.getCategoryRelativeUrl()
else:
ledger_uid = Query(ledger_uid=None)
ledger_url = ''
inventory_param_dict = dict(section_uid=section_uid, for section in section_list:
simulation_state=('delivered',), section_uid = section.getUid()
precision=section_currency_precision, balance_transaction = None
portal_type=portal.getPortalAccountingMovementTypeList(),
at_date=at_date.latestTime(),)
# Calculate the sum of profit and loss accounts balances for that period. group_by_node_node_category_list = []
# This must match the difference between assets, liability and equity accounts. group_by_mirror_section_node_category_list = []
profit_and_loss_accounts_balance = portal.portal_simulation.getInventoryAssetPrice( group_by_payment_node_category_list = []
from_date=context.getStartDate(), profit_and_loss_node_category_list = []
node_category_strict_membership=profit_and_loss_node_category_list,
**inventory_param_dict) node_category_list = portal.portal_categories\
selected_profit_and_loss_account_balance = portal.portal_simulation.getInventoryAssetPrice( .account_type.getCategoryChildValueList()
node=profit_and_loss_account, for node_category in node_category_list:
resource=section_currency, node_category_url = node_category.getRelativeUrl()
**inventory_param_dict) if node_category_url in (
'account_type/asset/cash/bank',):
section_currency_uid = context.getParentValue().getPriceCurrencyUid() group_by_payment_node_category_list.append(node_category_url)
elif node_category_url in (
profit_and_loss_quantity = 0 'account_type/asset/receivable',
line_count = 0 'account_type/liability/payable'):
group_by_mirror_section_node_category_list.append(node_category_url)
for inventory in getInventoryList( elif node_category.isMemberOf('account_type/income') or \
node_category_strict_membership=group_by_node_node_category_list, node_category.isMemberOf('account_type/expense'):
group_by_node=1, profit_and_loss_node_category_list.append(node_category_url)
group_by_resource=1, else:
**inventory_param_dict): group_by_node_node_category_list.append(node_category_url)
total_price = roundCurrency(inventory.total_price or 0, section_currency) inventory_param_dict = dict(section_uid=section_uid,
quantity = roundCurrency(inventory.total_quantity or 0, simulation_state=('delivered',),
inventory.resource_relative_url) precision=section_currency_precision,
portal_type=portal.getPortalAccountingMovementTypeList(),
if not total_price and not quantity: at_date=at_date.latestTime(),
continue ledger_uid=ledger_uid)
line_count += 1 # Calculate the sum of profit and loss accounts balances for that period.
if inventory.resource_uid != section_currency_uid: # This must match the difference between assets, liability and equity accounts.
profit_and_loss_accounts_balance = portal.portal_simulation.getInventoryAssetPrice(
from_date=context.getStartDate(),
node_category_strict_membership=profit_and_loss_node_category_list,
**inventory_param_dict)
selected_profit_and_loss_account_balance = portal.portal_simulation.getInventoryAssetPrice(
node=profit_and_loss_account,
resource=section_currency,
**inventory_param_dict)
section_currency_uid = context.getParentValue().getPriceCurrencyUid()
profit_and_loss_quantity = 0
line_count = 0
for inventory in getInventoryList(
node_category_strict_membership=group_by_node_node_category_list,
group_by_node=1,
group_by_resource=1,
**inventory_param_dict):
total_price = roundCurrency(inventory.total_price or 0, section_currency)
quantity = roundCurrency(inventory.total_quantity or 0,
inventory.resource_relative_url)
if not total_price and not quantity:
continue
line_count += 1
if inventory.resource_uid != section_currency_uid:
profit_and_loss_quantity += total_price
if balance_transaction is None:
balance_transaction = createBalanceTransaction(section, ledger_url)
balance_transaction.newContent(
id='%03d' % line_count,
portal_type='Balance Transaction Line',
destination=inventory.node_relative_url,
resource=inventory.resource_relative_url,
quantity=quantity,
destination_total_asset_price=total_price)
else:
if total_price != quantity:
# If this fail for you, your accounting doesn't use currencies with
# consistency
raise ValueError('Different price: %s != %s ' % (
total_price, quantity))
if inventory.node_relative_url != profit_and_loss_account:
profit_and_loss_quantity += total_price
if balance_transaction is None:
balance_transaction = createBalanceTransaction(section, ledger_url)
balance_transaction.newContent(
id='%03d' % line_count,
portal_type='Balance Transaction Line',
destination=inventory.node_relative_url,
quantity=total_price)
for inventory in getInventoryList(
node_category_strict_membership=group_by_mirror_section_node_category_list,
group_by_node=1,
group_by_mirror_section=1,
group_by_resource=1,
**inventory_param_dict):
total_price = roundCurrency(inventory.total_price or 0, section_currency)
quantity = roundCurrency(inventory.total_quantity or 0,
inventory.resource_relative_url)
if not total_price and not quantity:
continue
profit_and_loss_quantity += total_price profit_and_loss_quantity += total_price
line_count += 1
if balance_transaction is None:
balance_transaction = createBalanceTransaction(section) if inventory.resource_uid != section_currency_uid:
balance_transaction.newContent( if balance_transaction is None:
balance_transaction = createBalanceTransaction(section, ledger_url)
balance_transaction.newContent(
id='%03d' % line_count, id='%03d' % line_count,
portal_type='Balance Transaction Line', portal_type='Balance Transaction Line',
destination=inventory.node_relative_url, destination=inventory.node_relative_url,
source_section_uid=inventory.mirror_section_uid,
resource=inventory.resource_relative_url, resource=inventory.resource_relative_url,
quantity=quantity, quantity=quantity,
destination_total_asset_price=total_price) destination_total_asset_price=total_price)
else: else:
if total_price != quantity: if total_price != quantity:
# If this fail for you, your accounting doesn't use currencies with raise ValueError('Different price: %s != %s ' % (
# consistency total_price, quantity))
raise ValueError('Different price: %s != %s ' % (
total_price, quantity))
if inventory.node_relative_url != profit_and_loss_account:
profit_and_loss_quantity += total_price
if balance_transaction is None: if balance_transaction is None:
balance_transaction = createBalanceTransaction(section) balance_transaction = createBalanceTransaction(section, ledger_url)
balance_transaction.newContent( balance_transaction.newContent(
id='%03d' % line_count, id='%03d' % line_count,
portal_type='Balance Transaction Line', portal_type='Balance Transaction Line',
destination=inventory.node_relative_url, destination=inventory.node_relative_url,
source_section_uid=inventory.mirror_section_uid,
quantity=total_price) quantity=total_price)
for inventory in getInventoryList( for inventory in getInventoryList(
node_category_strict_membership=group_by_mirror_section_node_category_list, node_category_strict_membership=group_by_payment_node_category_list,
group_by_node=1, group_by_node=1,
group_by_mirror_section=1, group_by_payment=1,
group_by_resource=1, group_by_resource=1,
**inventory_param_dict): **inventory_param_dict):
total_price = roundCurrency(inventory.total_price or 0, section_currency) total_price = roundCurrency(inventory.total_price or 0, section_currency)
quantity = roundCurrency(inventory.total_quantity or 0, quantity = roundCurrency(inventory.total_quantity or 0,
inventory.resource_relative_url) inventory.resource_relative_url)
if not total_price and not quantity: if not total_price and not quantity:
continue continue
profit_and_loss_quantity += total_price profit_and_loss_quantity += total_price
line_count += 1
line_count += 1
if inventory.resource_uid != section_currency_uid:
if balance_transaction is None: if inventory.resource_uid != section_currency_uid:
balance_transaction = createBalanceTransaction(section) if balance_transaction is None:
balance_transaction.newContent( balance_transaction = createBalanceTransaction(section, ledger_url)
id='%03d' % line_count, balance_transaction.newContent(
portal_type='Balance Transaction Line', id='%03d' % line_count,
destination=inventory.node_relative_url, portal_type='Balance Transaction Line',
source_section_uid=inventory.mirror_section_uid, destination=inventory.node_relative_url,
resource=inventory.resource_relative_url, resource=inventory.resource_relative_url,
quantity=quantity, quantity=quantity,
destination_total_asset_price=total_price) destination_payment_uid=inventory.payment_uid,
else: destination_total_asset_price=total_price)
if total_price != quantity: else:
raise ValueError('Different price: %s != %s ' % ( if total_price != quantity:
total_price, quantity)) raise ValueError('Different price: %s != %s ' % (
if balance_transaction is None: total_price, quantity))
balance_transaction = createBalanceTransaction(section) if balance_transaction is None:
balance_transaction.newContent( balance_transaction = createBalanceTransaction(section, ledger_url)
id='%03d' % line_count, balance_transaction.newContent(
portal_type='Balance Transaction Line', id='%03d' % line_count,
destination=inventory.node_relative_url, portal_type='Balance Transaction Line',
source_section_uid=inventory.mirror_section_uid, destination=inventory.node_relative_url,
quantity=total_price) destination_payment_uid=inventory.payment_uid,
quantity=total_price)
for inventory in getInventoryList( if balance_transaction is None:
node_category_strict_membership=group_by_payment_node_category_list, # we did not have any transaction for this section
group_by_node=1,
group_by_payment=1, # One possible corner case is that we have only transactions that brings
group_by_resource=1, # the balance of all balance sheets accounts to 0. In this case we want to
**inventory_param_dict): # create a balance transaction that notes that the current balance of profit
# and loss account is 0, so that the delta gets indexed.
total_price = roundCurrency(inventory.total_price or 0, section_currency) if profit_and_loss_accounts_balance:
quantity = roundCurrency(inventory.total_quantity or 0, balance_transaction = createBalanceTransaction(section, ledger_url)
inventory.resource_relative_url) balance_transaction.newContent(
portal_type='Balance Transaction Line',
if not total_price and not quantity: destination=profit_and_loss_account,
quantity=0)
balance_transaction.stop()
balance_transaction.deliver()
continue continue
profit_and_loss_quantity += total_price
assert roundCurrency(profit_and_loss_accounts_balance, section_currency) == roundCurrency(
line_count += 1 - roundCurrency(selected_profit_and_loss_account_balance, section_currency)
- roundCurrency(profit_and_loss_quantity, section_currency), section_currency)
if inventory.resource_uid != section_currency_uid:
if balance_transaction is None: # If profit_and_loss_quantity equals 0 then we are on a
balance_transaction = createBalanceTransaction(section) # ledger which no accounting transactions are member of
balance_transaction.newContent( if profit_and_loss_quantity != 0.:
id='%03d' % line_count, # add a final line for p&l
portal_type='Balance Transaction Line',
destination=inventory.node_relative_url,
resource=inventory.resource_relative_url,
quantity=quantity,
destination_payment_uid=inventory.payment_uid,
destination_total_asset_price=total_price)
else:
if total_price != quantity:
raise ValueError('Different price: %s != %s ' % (
total_price, quantity))
if balance_transaction is None:
balance_transaction = createBalanceTransaction(section)
balance_transaction.newContent(
id='%03d' % line_count,
portal_type='Balance Transaction Line',
destination=inventory.node_relative_url,
destination_payment_uid=inventory.payment_uid,
quantity=total_price)
if balance_transaction is None:
# we did not have any transaction for this section
# One possible corner case is that we have only transactions that brings
# the balance of all balance sheets accounts to 0. In this case we want to
# create a balance transaction that notes that the current balance of profit
# and loss account is 0, so that the delta gets indexed.
if profit_and_loss_accounts_balance:
balance_transaction = createBalanceTransaction(section)
balance_transaction.newContent( balance_transaction.newContent(
portal_type='Balance Transaction Line', id='%03d' % (line_count + 1),
destination=profit_and_loss_account, portal_type='Balance Transaction Line',
quantity=0) destination=profit_and_loss_account,
quantity=-profit_and_loss_quantity)
# and go to delivered state directly (the user is not supposed to edit this document)
balance_transaction.stop() balance_transaction.stop()
balance_transaction.deliver() balance_transaction.deliver()
continue
assert roundCurrency(profit_and_loss_accounts_balance, section_currency) == roundCurrency(
- roundCurrency(selected_profit_and_loss_account_balance, section_currency)
- roundCurrency(profit_and_loss_quantity, section_currency), section_currency)
# add a final line for p&l
balance_transaction.newContent(
id='%03d' % (line_count + 1),
portal_type='Balance Transaction Line',
destination=profit_and_loss_account,
quantity=-profit_and_loss_quantity)
# and go to delivered state directly (the user is not supposed to edit this document)
balance_transaction.stop()
balance_transaction.deliver()
# make sure this Accounting Period has an activity pending during the indexing # make sure this Accounting Period has an activity pending during the indexing
# of the balance transaction. # of the balance transaction.
......
...@@ -32,6 +32,7 @@ from AccessControl import ClassSecurityInfo ...@@ -32,6 +32,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.Inventory import Inventory from Products.ERP5.Document.Inventory import Inventory
from Products.ERP5.Document.AccountingTransaction import AccountingTransaction from Products.ERP5.Document.AccountingTransaction import AccountingTransaction
from Products.ZSQLCatalog.SQLCatalog import Query
import types import types
...@@ -136,6 +137,10 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -136,6 +137,10 @@ class BalanceTransaction(AccountingTransaction, Inventory):
getInventoryList = self.getPortalObject()\ getInventoryList = self.getPortalObject()\
.portal_simulation.getInventoryList .portal_simulation.getInventoryList
section_uid = self.getDestinationSectionUid() section_uid = self.getDestinationSectionUid()
ledger_uid = self.getLedgerUid()
if ledger_uid is None:
ledger_uid = Query(ledger_uid=None)
precision = 2 precision = 2
if section_uid is not None: if section_uid is not None:
accounting_currency = \ accounting_currency = \
...@@ -150,7 +155,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -150,7 +155,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
section_uid=section_uid, section_uid=section_uid,
precision=precision, precision=precision,
portal_type=self.getPortalAccountingMovementTypeList(), portal_type=self.getPortalAccountingMovementTypeList(),
simulation_state=('delivered', )) simulation_state=('delivered', ),
ledger_uid=ledger_uid)
# node # node
for movement in self._getGroupByNodeMovementList(): for movement in self._getGroupByNodeMovementList():
...@@ -267,7 +273,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -267,7 +273,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
relative_url=movement.getRelativeUrl(), relative_url=movement.getRelativeUrl(),
quantity=movement.getQuantity(), quantity=movement.getQuantity(),
total_price=movement\ total_price=movement\
.getDestinationInventoriatedTotalAssetPrice(), )) .getDestinationInventoriatedTotalAssetPrice(),
ledger_uid=movement.getLedgerUid(), ))
# mirror section # mirror section
for movement in self._getGroupByMirrorSectionMovementList(): for movement in self._getGroupByMirrorSectionMovementList():
...@@ -291,7 +298,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -291,7 +298,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
relative_url=movement.getRelativeUrl(), relative_url=movement.getRelativeUrl(),
quantity=movement.getQuantity(), quantity=movement.getQuantity(),
total_price=movement\ total_price=movement\
.getDestinationInventoriatedTotalAssetPrice(), )) .getDestinationInventoriatedTotalAssetPrice(),
ledger_uid=movement.getLedgerUid(), ))
# payment # payment
for movement in self._getGroupByPaymentMovementList(): for movement in self._getGroupByPaymentMovementList():
...@@ -315,7 +323,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -315,7 +323,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
relative_url=movement.getRelativeUrl(), relative_url=movement.getRelativeUrl(),
quantity=movement.getQuantity(), quantity=movement.getQuantity(),
total_price=movement\ total_price=movement\
.getDestinationInventoriatedTotalAssetPrice(), )) .getDestinationInventoriatedTotalAssetPrice(),
ledger_uid=movement.getLedgerUid(), ))
return new_stock return new_stock
......
...@@ -42,6 +42,8 @@ from AccessControl.SecurityManagement import newSecurityManager ...@@ -42,6 +42,8 @@ from AccessControl.SecurityManagement import newSecurityManager
from Products.ERP5Type.tests.Sequence import SequenceList from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Form.PreferenceTool import Priority from Products.ERP5Form.PreferenceTool import Priority
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
SOURCE = 'source' SOURCE = 'source'
DESTINATION = 'destination' DESTINATION = 'destination'
RUN_ALL_TESTS = 1 RUN_ALL_TESTS = 1
...@@ -1167,6 +1169,356 @@ class TestClosingPeriod(AccountingTestCase): ...@@ -1167,6 +1169,356 @@ class TestClosingPeriod(AccountingTestCase):
self.assertEqual(None, pl_movement.getSourceTotalAssetPrice()) self.assertEqual(None, pl_movement.getSourceTotalAssetPrice())
self.assertEqual(200., pl_movement.getDestinationCredit()) self.assertEqual(200., pl_movement.getDestinationCredit())
@UnrestrictedMethod
def setUpLedger(self):
# Create Ledger Categories
ledger_category = self.portal.portal_categories.ledger
ledger_accounting_category = ledger_category.get('accounting', None)
if ledger_accounting_category is None:
ledger_accounting_category = ledger_category.newContent(portal_type='Category', id='accounting')
if ledger_accounting_category.get('general', None) is None:
ledger_accounting_category.newContent(portal_type='Category', id='general')
if ledger_accounting_category.get('detailed', None) is None:
ledger_accounting_category.newContent(portal_type='Category', id='detailed')
if ledger_accounting_category.get('other', None) is None:
ledger_accounting_category.newContent(portal_type='Category', id='other')
# Allow some ledgers on the 'Sale Invoice Transaction' portal type
self.portal.portal_types['Sale Invoice Transaction'].edit(
ledger=['accounting/general', 'accounting/detailed'])
def test_createBalanceOnLedgerWithTransactionsWithNoLedger(self):
self.setUpLedger()
organisation_module = self.organisation_module
period = self.section.newContent(portal_type='Accounting Period')
period.setStartDate(DateTime(2006, 1, 1))
period.setStopDate(DateTime(2006, 12, 31))
pl = self.portal.account_module.newContent(
portal_type='Account',
account_type='equity')
# 2 Transactions for clients 1 and 2 on ledger accounting/general
transaction1 = self._makeOne(
start_date=DateTime(2006, 1, 1),
portal_type='Sale Invoice Transaction',
ledger='accounting/general',
destination_section_value=organisation_module.client_1,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=100),
dict(source_value=self.account_module.receivable,
source_credit=100)))
transaction2 = self._makeOne(
start_date=DateTime(2006, 1, 2),
portal_type='Sale Invoice Transaction',
ledger='accounting/general',
destination_section_value=organisation_module.client_2,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=200),
dict(source_value=self.account_module.receivable,
source_credit=200)))
# 2 Transactions for clients 1 and 2 on ledger accounting/detailed
transaction3 = self._makeOne(
start_date=DateTime(2006, 1, 1),
portal_type='Sale Invoice Transaction',
ledger='accounting/detailed',
destination_section_value=organisation_module.client_1,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=400),
dict(source_value=self.account_module.receivable,
source_credit=400)))
transaction4 = self._makeOne(
start_date=DateTime(2006, 1, 2),
portal_type='Sale Invoice Transaction',
ledger='accounting/detailed',
destination_section_value=organisation_module.client_2,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=800),
dict(source_value=self.account_module.receivable,
source_credit=800)))
# 2 Transactions for clients 1 and 2 with no ledger
transaction5 = self._makeOne(
start_date=DateTime(2006, 1, 1),
portal_type='Sale Invoice Transaction',
ledger='',
destination_section_value=organisation_module.client_1,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=1600),
dict(source_value=self.account_module.receivable,
source_credit=1600)))
transaction6 = self._makeOne(
start_date=DateTime(2006, 1, 2),
portal_type='Sale Invoice Transaction',
ledger='',
destination_section_value=organisation_module.client_2,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=3200),
dict(source_value=self.account_module.receivable,
source_credit=3200)))
period.AccountingPeriod_createBalanceTransaction(
profit_and_loss_account=pl.getRelativeUrl())
accounting_transaction_list = self.accounting_module.contentValues()
self.assertEqual(9, len(accounting_transaction_list))
balance_transaction_list = self.accounting_module.contentValues(
portal_type='Balance Transaction')
self.assertEqual(3, len(balance_transaction_list))
# 1st balance has 3 lines : # 2nd balance has 3 lines :
# on ledger/accounting/general # on ledger/accounting/detailed
# pl = 300 D # pl = 1200 D
# receivable/client1 = 200 C # receivable/client1 = 800 C
# receivable/client2 = 100 C # receivable/client2 = 400 C
# 3rd balance has 3 lines :
# on no ledger
# pl = 4800 D
# receivable/client1 = 3200 C
# receivable/client2 = 1600 C
result_mapping = {}
result_mapping['accounting/general'] = {'client1': 100., 'client2': 200., 'pl': 300.}
result_mapping['accounting/detailed'] = {'client1': 400., 'client2': 800., 'pl': 1200.}
result_mapping[None] = {'client1': 1600., 'client2': 3200., 'pl': 4800.}
for balance_transaction in balance_transaction_list:
self.assertEqual(self.section,
balance_transaction.getDestinationSectionValue())
self.assertEqual(None, balance_transaction.getSourceSection())
self.assertEqual(DateTime(2007, 1, 1),
balance_transaction.getStartDate())
self.assertEqual('currency_module/euro',
balance_transaction.getResource())
self.assertEqual('delivered', balance_transaction.getSimulationState())
movement_list = balance_transaction.getMovementList()
self.assertEqual(3, len(movement_list))
current_ledger = balance_transaction.getLedger()
assert current_ledger in (None, 'accounting/general', 'accounting/detailed')
result = result_mapping[current_ledger]
client1_movement_list = [m for m in movement_list
if m.getSourceSectionValue() == organisation_module.client_1]
self.assertEqual(1, len(client1_movement_list))
client1_movement = client1_movement_list[0]
self.assertEqual([], client1_movement.getValueList('resource'))
self.assertEqual([], client1_movement.getValueList('destination_section'))
self.assertEqual(None, client1_movement.getSource())
self.assertEqual(self.account_module.receivable,
client1_movement.getDestinationValue())
self.assertEqual(organisation_module.client_1,
client1_movement.getSourceSectionValue())
self.assertEqual(None, client1_movement.getDestinationTotalAssetPrice())
self.assertEqual(None, client1_movement.getSourceTotalAssetPrice())
self.assertEqual(result['client1'], client1_movement.getDestinationCredit())
client2_movement_list = [m for m in movement_list
if m.getSourceSectionValue() == organisation_module.client_2]
self.assertEqual(1, len(client2_movement_list))
client2_movement = client2_movement_list[0]
self.assertEqual([], client2_movement.getValueList('resource'))
self.assertEqual([], client2_movement.getValueList('destination_section'))
self.assertEqual(None, client2_movement.getSource())
self.assertEqual(self.account_module.receivable,
client2_movement.getDestinationValue())
self.assertEqual(organisation_module.client_2,
client2_movement.getSourceSectionValue())
self.assertEqual(None, client2_movement.getDestinationTotalAssetPrice())
self.assertEqual(None, client2_movement.getSourceTotalAssetPrice())
self.assertEqual(result['client2'], client2_movement.getDestinationCredit())
pl_movement_list = [m for m in movement_list
if m.getDestinationValue() == pl]
self.assertEqual(1, len(pl_movement_list))
pl_movement = pl_movement_list[0]
self.assertEqual([], pl_movement.getValueList('resource'))
self.assertEqual(None, pl_movement.getSource())
self.assertEqual(pl,
pl_movement.getDestinationValue())
self.assertEqual(None,
pl_movement.getSourceSection())
self.assertEqual(None, pl_movement.getDestinationTotalAssetPrice())
self.assertEqual(None, pl_movement.getSourceTotalAssetPrice())
self.assertEqual(result['pl'], pl_movement.getDestinationDebit())
self.tic()
def test_createBalanceOnLedgerWithAllTransactionsWithLedger(self):
self.setUpLedger()
organisation_module = self.organisation_module
period = self.section.newContent(portal_type='Accounting Period')
period.setStartDate(DateTime(2006, 1, 1))
period.setStopDate(DateTime(2006, 12, 31))
pl = self.portal.account_module.newContent(
portal_type='Account',
account_type='equity')
# 2 Transactions for clients 1 and 2 on ledger accounting/general
transaction1 = self._makeOne(
start_date=DateTime(2006, 1, 1),
portal_type='Sale Invoice Transaction',
ledger='accounting/general',
destination_section_value=organisation_module.client_1,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=100),
dict(source_value=self.account_module.receivable,
source_credit=100)))
transaction2 = self._makeOne(
start_date=DateTime(2006, 1, 2),
portal_type='Sale Invoice Transaction',
ledger='accounting/general',
destination_section_value=organisation_module.client_2,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=200),
dict(source_value=self.account_module.receivable,
source_credit=200)))
# 2 Transactions for clients 1 and 2 on ledger accounting/detailed
transaction3 = self._makeOne(
start_date=DateTime(2006, 1, 1),
portal_type='Sale Invoice Transaction',
ledger='accounting/detailed',
destination_section_value=organisation_module.client_1,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=400),
dict(source_value=self.account_module.receivable,
source_credit=400)))
transaction4 = self._makeOne(
start_date=DateTime(2006, 1, 2),
portal_type='Sale Invoice Transaction',
ledger='accounting/detailed',
destination_section_value=organisation_module.client_2,
simulation_state='delivered',
lines=(dict(source_value=self.account_module.goods_sales,
source_debit=800),
dict(source_value=self.account_module.receivable,
source_credit=800)))
period.AccountingPeriod_createBalanceTransaction(
profit_and_loss_account=pl.getRelativeUrl())
accounting_transaction_list = self.accounting_module.contentValues()
self.assertEqual(6, len(accounting_transaction_list))
balance_transaction_list = self.accounting_module.contentValues(
portal_type='Balance Transaction')
self.assertEqual(2, len(balance_transaction_list))
# 1st balance has 3 lines : # 2nd balance has 3 lines :
# on ledger/accounting/general # on ledger/accounting/detailed
# pl = 300 D # pl = 1200 D
# receivable/client1 = 200 C # receivable/client1 = 800 C
# receivable/client2 = 100 C # receivable/client2 = 400 C
result_mapping = {}
result_mapping['accounting/general'] = {'client1': 100., 'client2': 200., 'pl': 300.}
result_mapping['accounting/detailed'] = {'client1': 400., 'client2': 800., 'pl': 1200.}
for balance_transaction in balance_transaction_list:
self.assertEqual(self.section,
balance_transaction.getDestinationSectionValue())
self.assertEqual(None, balance_transaction.getSourceSection())
self.assertEqual(DateTime(2007, 1, 1),
balance_transaction.getStartDate())
self.assertEqual('currency_module/euro',
balance_transaction.getResource())
self.assertEqual('delivered', balance_transaction.getSimulationState())
movement_list = balance_transaction.getMovementList()
self.assertEqual(3, len(movement_list))
current_ledger = balance_transaction.getLedger()
assert current_ledger in ('accounting/general', 'accounting/detailed')
result = result_mapping[current_ledger]
client1_movement_list = [m for m in movement_list
if m.getSourceSectionValue() == organisation_module.client_1]
self.assertEqual(1, len(client1_movement_list))
client1_movement = client1_movement_list[0]
self.assertEqual([], client1_movement.getValueList('resource'))
self.assertEqual([], client1_movement.getValueList('destination_section'))
self.assertEqual(None, client1_movement.getSource())
self.assertEqual(self.account_module.receivable,
client1_movement.getDestinationValue())
self.assertEqual(organisation_module.client_1,
client1_movement.getSourceSectionValue())
self.assertEqual(None, client1_movement.getDestinationTotalAssetPrice())
self.assertEqual(None, client1_movement.getSourceTotalAssetPrice())
self.assertEqual(result['client1'], client1_movement.getDestinationCredit())
client2_movement_list = [m for m in movement_list
if m.getSourceSectionValue() == organisation_module.client_2]
self.assertEqual(1, len(client2_movement_list))
client2_movement = client2_movement_list[0]
self.assertEqual([], client2_movement.getValueList('resource'))
self.assertEqual([], client2_movement.getValueList('destination_section'))
self.assertEqual(None, client2_movement.getSource())
self.assertEqual(self.account_module.receivable,
client2_movement.getDestinationValue())
self.assertEqual(organisation_module.client_2,
client2_movement.getSourceSectionValue())
self.assertEqual(None, client2_movement.getDestinationTotalAssetPrice())
self.assertEqual(None, client2_movement.getSourceTotalAssetPrice())
self.assertEqual(result['client2'], client2_movement.getDestinationCredit())
pl_movement_list = [m for m in movement_list
if m.getDestinationValue() == pl]
self.assertEqual(1, len(pl_movement_list))
pl_movement = pl_movement_list[0]
self.assertEqual([], pl_movement.getValueList('resource'))
self.assertEqual(None, pl_movement.getSource())
self.assertEqual(pl,
pl_movement.getDestinationValue())
self.assertEqual(None,
pl_movement.getSourceSection())
self.assertEqual(None, pl_movement.getDestinationTotalAssetPrice())
self.assertEqual(None, pl_movement.getSourceTotalAssetPrice())
self.assertEqual(result['pl'], pl_movement.getDestinationDebit())
self.tic()
def testStockTableContent():
q = self.portal.erp5_sql_connection.manage_test
self.assertEqual(2, q(
"SELECT count(*) FROM stock WHERE portal_type="
"'Balance Transaction Line'")[0][0])
self.assertEqual(300, q(
"SELECT sum(total_price) FROM stock WHERE portal_type="
"'Balance Transaction Line' AND ledger_uid="
"%s GROUP BY ledger_uid" %
self.portal.portal_categories.ledger.accounting.general.getUid())[0][0])
self.assertEqual(300, q(
"SELECT sum(quantity) FROM stock WHERE portal_type="
"'Balance Transaction Line' AND ledger_uid="
"%s GROUP BY ledger_uid" %
self.portal.portal_categories.ledger.accounting.general.getUid())[0][0])
self.assertEqual(1200, q(
"SELECT sum(total_price) FROM stock WHERE portal_type="
"'Balance Transaction Line' AND ledger_uid="
"%s GROUP BY ledger_uid" % self.portal.portal_categories.ledger.accounting.detailed.getUid())[0][0])
self.assertEqual(1200, q(
"SELECT sum(quantity) FROM stock WHERE portal_type="
"'Balance Transaction Line' AND ledger_uid="
"%s GROUP BY ledger_uid" % self.portal.portal_categories.ledger.accounting.detailed.getUid())[0][0])
# now check content of stock table
testStockTableContent()
balance_transaction.immediateReindexObject()
self.tic()
testStockTableContent()
def test_createBalanceOnMirrorSectionMultiCurrency(self): def test_createBalanceOnMirrorSectionMultiCurrency(self):
pl = self.portal.account_module.newContent( pl = self.portal.account_module.newContent(
......
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