Commit df217a68 authored by Jean-Paul Smets's avatar Jean-Paul Smets

Moved rules to ERP5 product

git-svn-id: https://svn.erp5.org/repos/public/erp5/sandbox/amount_generator@37484 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent d6f02509
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
"""
XXX This file is experimental for new simulation implementation, and
will replace DeliveryRule.
"""
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.mixin.rule import RuleMixin, MovementGeneratorMixin
from Products.ERP5.mixin.movement_collection_updater import \
MovementCollectionUpdaterMixin
class DeliveryRootSimulationRule(RuleMixin, MovementCollectionUpdaterMixin, Predicate):
"""
Delivery Rule object make sure an Delivery in the simulation
is consistent with the real delivery
WARNING: what to do with movement split ?
"""
# CMF Type Definition
meta_type = 'ERP5 Delivery Root Simulation Rule'
portal_type = 'Delivery Root Simulation Rule'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IRule,
interfaces.IDivergenceController,
interfaces.IMovementCollectionUpdater,)
# Default Properties
property_sheets = (
PropertySheet.Base,
PropertySheet.XMLObject,
PropertySheet.CategoryCore,
PropertySheet.DublinCore,
PropertySheet.Task,
PropertySheet.Predicate,
PropertySheet.Reference,
PropertySheet.Version,
PropertySheet.Rule
)
def _getMovementGenerator(self, context):
"""
Return the movement generator to use in the expand process
"""
return DeliveryRuleMovementGenerator(applied_rule=context, rule=self)
def _getMovementGeneratorContext(self, context):
"""
Return the movement generator context to use for expand
"""
return context
def _getMovementGeneratorMovementList(self, context):
"""
Return the movement lists to provide to the movement generator
"""
return []
def _isProfitAndLossMovement(self, movement):
# For a kind of trade rule, a profit and loss movement lacks source
# or destination.
return (movement.getSource() is None or movement.getDestination() is None)
class DeliveryRuleMovementGenerator(MovementGeneratorMixin):
def _getInputMovementList(self, movement_list=None, rounding=None):
"""Input movement list comes from delivery"""
delivery = self._applied_rule.getDefaultCausalityValue()
if delivery is None:
return []
else:
result = []
existing_movement_list = self._applied_rule.objectValues()
for movement in delivery.getMovementList(
portal_type=delivery.getPortalDeliveryMovementTypeList()):
simulation_movement = self._getDeliveryRelatedSimulationMovement(movement)
if simulation_movement is None or \
simulation_movement in existing_movement_list:
result.append(movement)
return result
def _getDeliveryRelatedSimulationMovement(self, delivery_movement):
"""Helper method to get the delivery related simulation movement.
This method is more robust than simply calling getDeliveryRelatedValue
which will not work if simulation movements are not indexed.
"""
simulation_movement = delivery_movement.getDeliveryRelatedValue()
if simulation_movement is not None:
return simulation_movement
# simulation movement was not found, maybe simply because it's not indexed
# yet. We'll look in the simulation tree and try to find it anyway before
# creating another simulation movement.
# Try to find the one from trade model rule, which is the most common case
# where we may expand again before indexation of simulation movements is
# finished.
delivery = delivery_movement.getExplanationValue()
for movement in delivery.getMovementList():
related_simulation_movement = movement.getDeliveryRelatedValue()
if related_simulation_movement is not None:
for applied_rule in related_simulation_movement.contentValues():
for simulation_movement in applied_rule.contentValues():
if simulation_movement.getDeliveryValue() == delivery_movement:
return simulation_movement
return None
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
"""
XXX This file is experimental for new simulation implementation, and
will replace DeliveryRule.
"""
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.mixin.rule import RuleMixin, MovementGeneratorMixin
from Products.ERP5.mixin.movement_collection_updater import \
MovementCollectionUpdaterMixin
class DeliverySimulationRule(RuleMixin, MovementCollectionUpdaterMixin, Predicate):
"""
Delivery Rule object make sure an Delivery in the simulation
is consistent with the real delivery
WARNING: what to do with movement split ?
"""
# CMF Type Definition
meta_type = 'ERP5 Delivery Simulation Rule'
portal_type = 'Delivery Simulation Rule'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IRule,
interfaces.IDivergenceController,
interfaces.IMovementCollectionUpdater,)
# Default Properties
property_sheets = (
PropertySheet.Base,
PropertySheet.XMLObject,
PropertySheet.CategoryCore,
PropertySheet.DublinCore,
PropertySheet.Task,
PropertySheet.Predicate,
PropertySheet.Reference,
PropertySheet.Version,
PropertySheet.Rule
)
def _getMovementGenerator(self, context):
"""
Return the movement generator to use in the expand process
"""
return DeliveryRuleMovementGenerator(applied_rule=context, rule=self)
def _getMovementGeneratorContext(self, context):
"""
Return the movement generator context to use for expand
"""
return context
def _getMovementGeneratorMovementList(self, context):
"""
Return the movement lists to provide to the movement generator
"""
return []
def _isProfitAndLossMovement(self, movement):
# For a kind of trade rule, a profit and loss movement lacks source
# or destination.
return (movement.getSource() is None or movement.getDestination() is None)
class DeliveryRuleMovementGenerator(MovementGeneratorMixin):
def _getUpdatePropertyDict(self, input_movement):
# Override default mixin implementation
return {'order': None,
'delivery': None,}
def _getInputMovementList(self, movement_list=None, rounding=None):
return [self._applied_rule.getParentValue(),]
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
"""
XXX This file is experimental for new simulation implementation, and
will replace InvoiceRule.
"""
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.mixin.rule import RuleMixin, MovementGeneratorMixin
from Products.ERP5.mixin.movement_collection_updater import \
MovementCollectionUpdaterMixin
class InvoiceRootSimulationRule(RuleMixin, MovementCollectionUpdaterMixin, Predicate):
"""
InvoiceRule and DeliveryRule seems to be identical. Keep it for
compatibility only.
"""
# CMF Type Definition
meta_type = 'ERP5 Invoice Root Simulation Rule'
portal_type = 'Invoice Root Simulation Rule'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IRule,
interfaces.IDivergenceController,
interfaces.IMovementCollectionUpdater,)
# Default Properties
property_sheets = (
PropertySheet.Base,
PropertySheet.XMLObject,
PropertySheet.CategoryCore,
PropertySheet.DublinCore,
PropertySheet.Task,
PropertySheet.Predicate,
PropertySheet.Reference,
PropertySheet.Version,
PropertySheet.Rule
)
def _getMovementGenerator(self, context):
"""
Return the movement generator to use in the expand process
"""
return InvoiceRuleMovementGenerator(applied_rule=context, rule=self)
def _getMovementGeneratorContext(self, context):
"""
Return the movement generator context to use for expand
"""
return context
def _getMovementGeneratorMovementList(self, context):
"""
Return the movement lists to provide to the movement generator
"""
return []
def _isProfitAndLossMovement(self, movement):
# For a kind of trade rule, a profit and loss movement lacks source
# or destination.
return (movement.getSource() is None or movement.getDestination() is None)
class InvoiceRuleMovementGenerator(MovementGeneratorMixin):
def _getInputMovementList(self, movement_list=None, rounding=None):
"""Input movement list comes from delivery"""
delivery = self._applied_rule.getDefaultCausalityValue()
if delivery is None:
return []
else:
ret = []
existing_movement_list = self._applied_rule.objectValues()
for movement in delivery.getMovementList(
portal_type=(delivery.getPortalInvoiceMovementTypeList() + \
delivery.getPortalTaxMovementTypeList())): # This is bad XXX-JPS - use use
simulation_movement = self._getDeliveryRelatedSimulationMovement(movement)
if simulation_movement is None or \
simulation_movement in existing_movement_list:
ret.append(movement)
return ret
def _getDeliveryRelatedSimulationMovement(self, delivery_movement):
"""Helper method to get the delivery related simulation movement.
This method is more robust than simply calling getDeliveryRelatedValue
which will not work if simulation movements are not indexed.
"""
simulation_movement = delivery_movement.getDeliveryRelatedValue()
if simulation_movement is not None:
return simulation_movement
# simulation movement was not found, maybe simply because it's not indexed
# yet. We'll look in the simulation tree and try to find it anyway before
# creating another simulation movement.
# Try to find the one from trade model rule, which is the most common case
# where we may expand again before indexation of simulation movements is
# finished.
delivery = delivery_movement.getExplanationValue()
for movement in delivery.getMovementList():
related_simulation_movement = movement.getDeliveryRelatedValue()
if related_simulation_movement is not None:
for applied_rule in related_simulation_movement.contentValues():
for simulation_movement in applied_rule.contentValues():
if simulation_movement.getDeliveryValue() == delivery_movement:
return simulation_movement
return None
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2009 Nexedi SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
"""
XXX This file is experimental for new simulation implementation, and
will replace InvoicingRule.
"""
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.mixin.rule import RuleMixin, MovementGeneratorMixin
from Products.ERP5.mixin.movement_collection_updater import \
MovementCollectionUpdaterMixin
class InvoiceSimulationRule(RuleMixin, MovementCollectionUpdaterMixin, Predicate):
"""
Invoicing Rule expand simulation created by a order or delivery rule.
"""
# CMF Type Definition
meta_type = 'ERP5 Invoice Simulation Rule'
portal_type = 'Invoice Simulation Rule'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IRule,
interfaces.IDivergenceController,
interfaces.IMovementCollectionUpdater,)
# Default Properties
property_sheets = (
PropertySheet.Base,
PropertySheet.XMLObject,
PropertySheet.CategoryCore,
PropertySheet.DublinCore,
PropertySheet.Task,
PropertySheet.Predicate,
PropertySheet.Reference,
PropertySheet.Version,
PropertySheet.Rule
)
def _getMovementGenerator(self, context):
"""
Return the movement generator to use in the expand process
"""
return InvoicingRuleMovementGenerator(applied_rule=context, rule=self)
def _getMovementGeneratorContext(self, context):
"""
Return the movement generator context to use for expand
"""
return context
def _getMovementGeneratorMovementList(self, context, movement_list=None, rounding=None):
"""
Return the movement lists to provide to the movement generator
"""
return []
def _isProfitAndLossMovement(self, movement):
# For a kind of trade rule, a profit and loss movement lacks source
# or destination.
return (movement.getSource() is None or movement.getDestination() is None)
class InvoicingRuleMovementGenerator(MovementGeneratorMixin):
def _getInputMovementList(self, movement_list=None, rounding=None):
return [self._applied_rule.getParentValue(),]
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2009 Nexedi SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
"""
XXX This file is experimental for new simulation implementation, and
will replace InvoicingRule.
"""
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.mixin.rule import RuleMixin, MovementGeneratorMixin
from Products.ERP5.mixin.movement_collection_updater import \
MovementCollectionUpdaterMixin
from Products.ERP5.Document.PredicateMatrix import PredicateMatrix
class InvoiceTransactionSimulationRule(RuleMixin, MovementCollectionUpdaterMixin, Predicate, PredicateMatrix):
"""
Invoice Transaction Rule object generates accounting movements for
each invoice movement based on category membership and other
predicated. Template accounting movements are stored in cells inside
an instance of the InvoiceTransactionRule.
"""
# CMF Type Definition
meta_type = 'ERP5 Invoice Transaction Simulation Rule'
portal_type = 'Invoice Transaction Simulation Rule'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IRule,
interfaces.IDivergenceController,
interfaces.IMovementCollectionUpdater,)
# Default Properties
property_sheets = (
PropertySheet.Base,
PropertySheet.XMLObject,
PropertySheet.CategoryCore,
PropertySheet.DublinCore,
PropertySheet.Task,
PropertySheet.Predicate,
PropertySheet.Reference,
PropertySheet.Version,
PropertySheet.Rule
)
def _getMovementGenerator(self, context):
"""
Return the movement generator to use in the expand process
"""
return InvoiceTransactionRuleMovementGenerator(applied_rule=context, rule=self)
def _getMovementGeneratorContext(self, context):
"""
Return the movement generator context to use for expand
"""
return context
def _getMovementGeneratorMovementList(self, context):
"""
Return the movement lists to provide to the movement generator
"""
return []
def _isProfitAndLossMovement(self, movement):
# For a kind of trade rule, a profit and loss movement lacks source
# or destination.
return (movement.getSource() is None or movement.getDestination() is None)
class InvoiceTransactionRuleMovementGenerator(MovementGeneratorMixin):
def getGeneratedMovementList(self, movement_list=None, rounding=False):
"""
Input movement list comes from order
XXX This implementation is very primitive, and does not support BPM,
i.e. business paths are not taken into account.
"""
ret = []
rule = self._rule
# input_movement, business_path = rule._getInputMovementAndPathTupleList(
# applied_rule)[0]
input_movement = self._applied_rule.getParentValue()
parent_movement = self._applied_rule.getParentValue()
# Find a matching cell
cell = rule._getMatchingCell(input_movement)
if cell is not None:
for accounting_rule_cell_line in cell.objectValues():
# get the resource (in that order):
# * resource from the invoice (using deliveryValue)
# * price_currency from the invoice
# * price_currency from the parents simulation movement's
# deliveryValue
# * price_currency from the top level simulation movement's
# orderValue
resource = None
invoice_line = input_movement.getDeliveryValue()
if invoice_line is not None :
invoice = invoice_line.getExplanationValue()
resource = invoice.getProperty('resource',
invoice.getProperty('price_currency', None))
if resource is None :
# search the resource on parents simulation movement's deliveries
simulation_movement = parent_movement
portal_simulation = self._applied_rule.getPortalObject().portal_simulation
while resource is None and \
simulation_movement != portal_simulation :
delivery = simulation_movement.getDeliveryValue()
if delivery is not None:
resource = delivery.getProperty('price_currency', None)
if (resource is None) and \
(simulation_movement.getParentValue().getParentValue() \
== portal_simulation) :
# we are on the first simulation movement, we'll try
# to get the resource from it's order price currency.
order = simulation_movement.getOrderValue()
if order is not None:
resource = order.getProperty('price_currency', None)
simulation_movement = simulation_movement\
.getParentValue().getParentValue()
if resource is None :
# last resort : get the resource from the rule
resource = accounting_rule_cell_line.getResource() \
or cell.getResource()
# XXX we need business path here?
kw = self._getPropertyAndCategoryList(input_movement, None, rule)
kw.update(
delivery=None,
source=[accounting_rule_cell_line.getSource()],
destination=[accounting_rule_cell_line.getDestination()],
quantity=(input_movement.getCorrectedQuantity() *
input_movement.getPrice(0.0)) *
accounting_rule_cell_line.getQuantity(),
resource=[resource],
price=1,
)
if resource is not None:
#set asset_price on movement when resource is different from price
#currency of the source/destination section
destination_exchange_ratio, precision = self \
._getCurrencyRatioAndPrecisionByArrow(
rule, 'destination_section', kw)
if destination_exchange_ratio is not None:
kw.update(destination_total_asset_price=round(
(destination_exchange_ratio*
parent_movement.getTotalPrice()),precision))
source_exchange_ratio, precision = self \
._getCurrencyRatioAndPrecisionByArrow(
rule, 'source_section', kw)
if source_exchange_ratio is not None:
kw.update(source_total_asset_price=round(
(source_exchange_ratio*
parent_movement.getTotalPrice()),precision))
if accounting_rule_cell_line.hasProperty(
'generate_prevision_script_id'):
generate_prevision_script_id = \
accounting_rule_cell_line.getGeneratePrevisionScriptId()
kw.update(getattr(input_movement,
generate_prevision_script_id)(kw))
simulation_movement = self._applied_rule.newContent(
portal_type=RuleMixin.movement_type,
temp_object=True,
**kw)
ret.append(simulation_movement)
return ret
def _getCurrencyRatioAndPrecisionByArrow(self, rule, arrow, prevision_line):
from Products.ERP5Type.Document import newTempSimulationMovement
try:
prevision_currency = prevision_line['resource'][0]
except IndexError:
prevision_currency = None
exchange_ratio = None
precision = None
try:
section = prevision_line.get(arrow, [])[0]
except IndexError:
section = None
if section is not None:
currency_url = rule.restrictedTraverse(section).getProperty(
'price_currency', None)
else:
currency_url = None
if currency_url is not None and prevision_currency != currency_url:
precision = section.getPriceCurrencyValue() \
.getQuantityPrecision()
temporary_movement = newTempSimulationMovement(rule.getPortalObject(),
'1', **prevision_line)
exchange_ratio = rule.restrictedTraverse(currency_url).getPrice(
context=temporary_movement.asContext(
categories=['price_currency/%s' % currency_url,
'resource/%s' % prevision_currency],
start_date=temporary_movement.getStartDate()))
return exchange_ratio, precision
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
"""
XXX This file is experimental for new simulation implementation, and
will replace OrderRule.
"""
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.mixin.rule import RuleMixin, MovementGeneratorMixin
from Products.ERP5.mixin.movement_collection_updater import \
MovementCollectionUpdaterMixin
class OrderRootSimulationRule(RuleMixin, MovementCollectionUpdaterMixin, Predicate):
"""
Order Rule object make sure an Order in the simulation
is consistent with the real order
WARNING: what to do with movement split ?
"""
# CMF Type Definition
meta_type = 'ERP5 Order Root Simulation Rule'
portal_type = 'Order Root Simulation Rule'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IRule,
interfaces.IDivergenceController,
interfaces.IMovementCollectionUpdater,)
# Default Properties
property_sheets = (
PropertySheet.Base,
PropertySheet.XMLObject,
PropertySheet.CategoryCore,
PropertySheet.DublinCore,
PropertySheet.Task,
PropertySheet.Predicate,
PropertySheet.Reference,
PropertySheet.Version,
PropertySheet.Rule
)
def _getMovementGenerator(self, context):
"""
Return the movement generator to use in the expand process
"""
return OrderRuleMovementGenerator(applied_rule=context, rule=self)
def _getMovementGeneratorContext(self, context):
"""
Return the movement generator context to use for expand
"""
return context
def _getMovementGeneratorMovementList(self, context):
"""
Return the movement lists to provide to the movement generator
"""
return []
def _isProfitAndLossMovement(self, movement):
# For a kind of trade rule, a profit and loss movement lacks source
# or destination.
return (movement.getSource() is None or movement.getDestination() is None)
class OrderRuleMovementGenerator(MovementGeneratorMixin):
def _getInputMovementList(self, movement_list=None, rounding=None):
"""Input movement list comes from order"""
order = self._applied_rule.getDefaultCausalityValue()
if order is None:
return []
else:
return order.getMovementList(
portal_type=order.getPortalOrderMovementTypeList())
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
"""
XXX This file is experimental for new simulation implementation, and
will replace PaymentRule.
"""
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.mixin.rule import RuleMixin, MovementGeneratorMixin
from Products.ERP5.mixin.movement_collection_updater import \
MovementCollectionUpdaterMixin
class PaymentSimulationRule(RuleMixin, MovementCollectionUpdaterMixin, Predicate):
"""
Payment Rule generates payment simulation movement from invoice
transaction simulation movements.
"""
# CMF Type Definition
meta_type = 'ERP5 Payment Simulation Rule'
portal_type = 'Payment Simulation Rule'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IRule,
interfaces.IDivergenceController,
interfaces.IMovementCollectionUpdater,)
# Default Properties
property_sheets = (
PropertySheet.Base,
PropertySheet.XMLObject,
PropertySheet.CategoryCore,
PropertySheet.DublinCore,
PropertySheet.Task,
PropertySheet.Predicate,
PropertySheet.Reference,
PropertySheet.Version,
PropertySheet.Rule
)
def _getMovementGenerator(self, context):
"""
Return the movement generator to use in the expand process
"""
return PaymentRuleMovementGenerator(applied_rule=context, rule=self)
def _getMovementGeneratorContext(self, context):
"""
Return the movement generator context to use for expand
"""
return context
def _getMovementGeneratorMovementList(self, context):
"""
Return the movement lists to provide to the movement generator
"""
return []
def _isProfitAndLossMovement(self, movement):
# For a kind of trade rule, a profit and loss movement lacks source
# or destination.
return (movement.getSource() is None or movement.getDestination() is None)
class PaymentRuleMovementGenerator(MovementGeneratorMixin):
def getGeneratedMovementList(self, movement_list=None, rounding=False):
"""
Input movement list comes from parent.
XXX This implementation using Business Path, not Payment Condition.
"""
ret = []
rule = self._rule
for input_movement, business_path in self \
._getInputMovementAndPathTupleList(movement_list=movement_list, rounding=rounding):
# Payment Rule does not work with Business Path
if business_path is None:
continue
# Since we need to consider business_path only for bank movement,
# not for payable movement, we pass None as business_path here.
kw = self._getPropertyAndCategoryList(input_movement, None, rule)
kw.update({'order':None, 'delivery':None})
quantity = kw.pop('quantity', 0)
efficiency = business_path.getEfficiency()
if efficiency:
quantity *= efficiency
start_date = business_path.getExpectedStartDate(input_movement)
if start_date is not None:
kw.update({'start_date':start_date})
stop_date = business_path.getExpectedStopDate(input_movement)
if stop_date is not None:
kw.update({'stop_date':stop_date})
# one for payable
simulation_movement = self._applied_rule.newContent(
portal_type=RuleMixin.movement_type,
temp_object=True,
quantity=-quantity,
**kw)
ret.append(simulation_movement)
# one for bank
kw.update({'source':business_path.getSource(),
'destination':business_path.getDestination(),})
simulation_movement = self._applied_rule.newContent(
portal_type=RuleMixin.movement_type,
temp_object=True,
quantity=quantity,
**kw)
ret.append(simulation_movement)
return ret
def _getInputMovementList(self, movement_list=None, rounding=None):
return [self._applied_rule.getParentValue(),]
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
#from Products.ERP5Type.Globals import InitializeClass, PersistentMapping
#from Products.CMFCore.utils import getToolByName
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.Document.Invoice import Invoice
class AccountingRuleCell(Predicate, Invoice):
"""
An AccountingRuleCell object allows to add SaleInvoiceTransactionLines into a Matrix
"""
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
, PropertySheet.Delivery
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Amount
, PropertySheet.Reference
, PropertySheet.PaymentCondition
, PropertySheet.Predicate
, PropertySheet.MappedValue
)
# CMF Type Definition
meta_type = 'ERP5 Accounting Rule Cell'
portal_type = 'Accounting Rule Cell'
add_permission = Permissions.AddPortalContent
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
##############################################################################
#
# Copyright (c) 2010 Nexedi SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5.Document.DeliveryRootSimulationRule \
import DeliveryRootSimulationRule
class AccountingTransactionRootSimulationRule(DeliveryRootSimulationRule):
"""
Accounting Transaction Root Simulation Rule is a root level rule for
Accounting Transaction.
"""
# CMF Type Definition
meta_type = 'ERP5 Accounting Transaction Root Simulation Rule'
portal_type = 'Accounting Transaction Root Simulation Rule'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
def _getInputMovementList(self, applied_rule):
"""Return list of movements from delivery"""
delivery = applied_rule.getDefaultCausalityValue()
movement_list = []
delivery_movement_type_list = self.getPortalAccountingMovementTypeList()
if delivery is not None:
existing_movement_list = applied_rule.objectValues()
for movement in delivery.getMovementList(
portal_type=delivery_movement_type_list):
simulation_movement = self._getDeliveryRelatedSimulationMovement(
movement)
if simulation_movement is None or \
simulation_movement in existing_movement_list:
movement_list.append(movement)
return movement_list
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