Commit 3d2ac188 authored by Arnaud Fontaine's avatar Arnaud Fontaine

ZODB Components: erp5_trade: Migrate Documents, Interfaces and Mixins from filesystem.

This removes TaxLine Document which was replaced by Trade Model Line a while ago.
parent 8c66c72a
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
from Products.ERP5.Document.Amount import Amount from Products.ERP5.Document.Amount import Amount
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5.Document.DeliveryRootSimulationRule \ from erp5.component.document.DeliveryRootSimulationRule \
import DeliveryRootSimulationRule, DeliveryRuleMovementGenerator import DeliveryRootSimulationRule, DeliveryRuleMovementGenerator
class AccountingTransactionRootSimulationRule(DeliveryRootSimulationRule): class AccountingTransactionRootSimulationRule(DeliveryRootSimulationRule):
......
...@@ -30,7 +30,7 @@ from UserDict import UserDict ...@@ -30,7 +30,7 @@ from UserDict import UserDict
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.Inventory import Inventory from erp5.component.document.Inventory import Inventory
from erp5.component.document.AccountingTransaction import AccountingTransaction from erp5.component.document.AccountingTransaction import AccountingTransaction
from Products.ZSQLCatalog.SQLCatalog import Query from Products.ZSQLCatalog.SQLCatalog import Query
import types import types
......
...@@ -32,7 +32,7 @@ from Products.ERP5Type import Permissions ...@@ -32,7 +32,7 @@ from Products.ERP5Type import Permissions
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
from erp5.component.document.AccountingTransactionLine import \ from erp5.component.document.AccountingTransactionLine import \
AccountingTransactionLine AccountingTransactionLine
from Products.ERP5.Document.InventoryLine import InventoryLine from erp5.component.document.InventoryLine import InventoryLine
class BalanceTransactionLine(AccountingTransactionLine, InventoryLine): class BalanceTransactionLine(AccountingTransactionLine, InventoryLine):
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5.Document.DeliveryRootSimulationRule \ from erp5.component.document.DeliveryRootSimulationRule \
import DeliveryRootSimulationRule, DeliveryRuleMovementGenerator import DeliveryRootSimulationRule, DeliveryRuleMovementGenerator
class InvoiceRootSimulationRule(DeliveryRootSimulationRule): class InvoiceRootSimulationRule(DeliveryRootSimulationRule):
......
...@@ -32,7 +32,7 @@ import unittest ...@@ -32,7 +32,7 @@ import unittest
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from erp5.component.test.testProductionOrderApparel import TestProductionOrderApparelMixin from erp5.component.test.testProductionOrderApparel import TestProductionOrderApparelMixin
from Products.ERP5.tests.testProductionPackingList import TestProductionDelivery from erp5.component.test.testProductionPackingList import TestProductionDelivery
class TestProductionDeliveryApparel(TestProductionOrderApparelMixin, class TestProductionDeliveryApparel(TestProductionOrderApparelMixin,
TestProductionDelivery, ERP5TypeTestCase): TestProductionDelivery, ERP5TypeTestCase):
......
erp5_core erp5_core
\ No newline at end of file erp5_trade
\ No newline at end of file
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.Container import Container from erp5.component.document.Container import Container
from erp5.component.module.BaobabMixin import BaobabMixin from erp5.component.module.BaobabMixin import BaobabMixin
class CashContainer(BaobabMixin, Container): class CashContainer(BaobabMixin, Container):
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.DeliveryCell import DeliveryCell from erp5.component.document.DeliveryCell import DeliveryCell
from erp5.component.module.BaobabMixin import BaobabMixin from erp5.component.module.BaobabMixin import BaobabMixin
from zope.interface import implements from zope.interface import implements
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
from erp5.component.module.BaobabMixin import BaobabMixin from erp5.component.module.BaobabMixin import BaobabMixin
from zope.interface import implements from zope.interface import implements
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.Inventory import Inventory from erp5.component.document.Inventory import Inventory
from erp5.component.document.BankingOperation import BankingOperation from erp5.component.document.BankingOperation import BankingOperation
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.InventoryCell import InventoryCell from erp5.component.document.InventoryCell import InventoryCell
from erp5.component.document.CashDeliveryCell import CashDeliveryCell from erp5.component.document.CashDeliveryCell import CashDeliveryCell
from zope.interface import implements from zope.interface import implements
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from erp5.component.document.CashDeliveryLine import CashDeliveryLine from erp5.component.document.CashDeliveryLine import CashDeliveryLine
from Products.ERP5.Document.InventoryLine import InventoryLine from erp5.component.document.InventoryLine import InventoryLine
from zope.interface import implements from zope.interface import implements
class CashInventoryLine(InventoryLine, CashDeliveryLine): class CashInventoryLine(InventoryLine, CashDeliveryLine):
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
from erp5.component.module.BaobabMixin import BaobabMixin from erp5.component.module.BaobabMixin import BaobabMixin
from zope.interface import implements from zope.interface import implements
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
class BudgetTransaction(DeliveryLine): class BudgetTransaction(DeliveryLine):
""" """
......
erp5_base erp5_base
\ No newline at end of file erp5_trade
\ No newline at end of file
...@@ -33,7 +33,7 @@ from Products.ERP5Type import Permissions, PropertySheet ...@@ -33,7 +33,7 @@ from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5.Document.Movement import Movement from Products.ERP5.Document.Movement import Movement
from Products.ERP5.Document.ImmobilisationMovement import ImmobilisationMovement from Products.ERP5.Document.ImmobilisationMovement import ImmobilisationMovement
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
class ImmobilisationLine(Movement, XMLObject, ImmobilisationMovement, DeliveryLine): class ImmobilisationLine(Movement, XMLObject, ImmobilisationMovement, DeliveryLine):
""" """
......
...@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo ...@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell from erp5.component.document.DeliveryCell import DeliveryCell
class InvoiceCell(DeliveryCell): class InvoiceCell(DeliveryCell):
""" """
......
...@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo ...@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
class InvoiceLine(DeliveryLine): class InvoiceLine(DeliveryLine):
""" """
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
############################################################################## ##############################################################################
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
class ImplicitItemMovement(DeliveryLine): class ImplicitItemMovement(DeliveryLine):
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell from erp5.component.document.DeliveryCell import DeliveryCell
class ManufacturingExecutionCell(DeliveryCell): class ManufacturingExecutionCell(DeliveryCell):
""" """
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
class ManufacturingExecutionLine(DeliveryLine): class ManufacturingExecutionLine(DeliveryLine):
""" """
......
from Products.ERP5.Document.DeliverySimulationRule import DeliverySimulationRule from erp5.component.document.DeliverySimulationRule import DeliverySimulationRule
from Products.ERP5.mixin.movement_generator import MovementGeneratorMixin from Products.ERP5.mixin.movement_generator import MovementGeneratorMixin
class ProductionSimulationRule(DeliverySimulationRule): class ProductionSimulationRule(DeliverySimulationRule):
......
...@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo ...@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell from erp5.component.document.DeliveryCell import DeliveryCell
class ProductionReportCell(DeliveryCell): class ProductionReportCell(DeliveryCell):
""" """
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
class ProductionReportLine(DeliveryLine): class ProductionReportLine(DeliveryLine):
""" """
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.TradeCondition import TradeCondition from erp5.component.document.TradeCondition import TradeCondition
from Products.ERP5Type.XMLMatrix import XMLMatrix from Products.ERP5Type.XMLMatrix import XMLMatrix
class PaySheetModel(TradeCondition, XMLMatrix): class PaySheetModel(TradeCondition, XMLMatrix):
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5.Document.TradeModelCell import TradeModelCell from erp5.component.document.TradeModelCell import TradeModelCell
from Products.ERP5Type.Core.Predicate import Predicate from Products.ERP5Type.Core.Predicate import Predicate
class PaySheetModelCell(TradeModelCell): class PaySheetModelCell(TradeModelCell):
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.TradeModelLine import TradeModelLine from erp5.component.document.TradeModelLine import TradeModelLine
class PaySheetModelLine(TradeModelLine): class PaySheetModelLine(TradeModelLine):
""" """
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell from erp5.component.document.DeliveryCell import DeliveryCell
class PaySheetModelSlice(DeliveryCell): class PaySheetModelSlice(DeliveryCell):
""" """
......
erp5_trade
\ No newline at end of file
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
# #
############################################################################## ##############################################################################
from Products.ERP5.Document.InvoiceTransactionSimulationRule import (InvoiceTransactionSimulationRule, from erp5.component.document.InvoiceTransactionSimulationRule import (InvoiceTransactionSimulationRule,
InvoiceTransactionRuleMovementGenerator) InvoiceTransactionRuleMovementGenerator)
class InventoryAssetPriceAccountingRuleMovementGenerator(InvoiceTransactionRuleMovementGenerator): class InventoryAssetPriceAccountingRuleMovementGenerator(InvoiceTransactionRuleMovementGenerator):
......
...@@ -35,6 +35,7 @@ from Products.ERP5Type import Permissions, PropertySheet, interfaces ...@@ -35,6 +35,7 @@ from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Path import Path from Products.ERP5.Document.Path import Path
from Products.ERP5Type.Core.Predicate import Predicate from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5.ExplanationCache import _getExplanationCache from Products.ERP5.ExplanationCache import _getExplanationCache
from erp5.component.interface.IBusinessLink import IBusinessLink
import zope.interface import zope.interface
...@@ -93,7 +94,7 @@ class BusinessLink(Path, Predicate): ...@@ -93,7 +94,7 @@ class BusinessLink(Path, Predicate):
) )
# Declarative interfaces # Declarative interfaces
zope.interface.implements(interfaces.IBusinessLink, zope.interface.implements(IBusinessLink,
interfaces.IPredicate, interfaces.IPredicate,
) )
......
...@@ -36,6 +36,7 @@ from Products.ERP5Type.XMLObject import XMLObject ...@@ -36,6 +36,7 @@ from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5.Document.Path import Path from Products.ERP5.Document.Path import Path
from Products.ERP5.ExplanationCache import _getExplanationCache, _getBusinessLinkClosure from Products.ERP5.ExplanationCache import _getExplanationCache, _getBusinessLinkClosure
from Products.ERP5.MovementCollectionDiff import _getPropertyAndCategoryList from Products.ERP5.MovementCollectionDiff import _getPropertyAndCategoryList
from erp5.component.interface.IBusinessProcess import IBusinessProcess
import zope.interface import zope.interface
...@@ -116,7 +117,7 @@ class BusinessProcess(Path, XMLObject): ...@@ -116,7 +117,7 @@ class BusinessProcess(Path, XMLObject):
) )
# Declarative interfaces # Declarative interfaces
zope.interface.implements(interfaces.IBusinessProcess, zope.interface.implements(IBusinessProcess,
interfaces.IArrowBase) interfaces.IArrowBase)
# ITradeModelPathProcess implementation # ITradeModelPathProcess implementation
......
##############################################################################
#
# Copyright (c) 2002, 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
# Romain Courteaud <romain@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 AccessControl import ClassSecurityInfo
from AccessControl.PermissionRole import PermissionRole
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5.Document.Movement import Movement
class Container(Movement, XMLObject):
"""
Container is equivalent to a movement with qty 1.0 and resource =
to the kind of packaging Container may point to item (ex.
Container serial No or Parcel Serial No if tracing required)
Container may eventually usa optional property sheet to store
parcel No information (we use Item property sheet for that). Some
acquisition may be required...
A Container which does not point to an Item can act itself as an Item
for traceability.
Container Line / Container Cell is used to store quantities (never
accounted)
Container Line / Countainer Cell may point to Item
"""
meta_type = 'ERP5 Container'
portal_type = 'Container'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
, PropertySheet.Item
, PropertySheet.Container
, PropertySheet.SortIndex
)
security.declareProtected(Permissions.AccessContentsInformation,
'getQuantity')
def getQuantity(self, default=1.0):
"""
Returns 1 because only one container is shipped
"""
return 1.0
security.declareProtected(Permissions.AccessContentsInformation,
'isAccountable')
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
# Always accountable - to account the containers which we use
return 1
security.declareProtected( Permissions.ModifyPortalContent,
'hasCellContent' )
def hasCellContent(self, base_id='movement'):
"""
This method can be overriden
"""
return 0
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self):
"""Return True if this movement diverges from the its simulation.
Containers are never divergent.
"""
return False
security.declareProtected(Permissions.AccessContentsInformation,
'getContainerText')
def getContainerText(self):
"""
Creates a unique string which allows to compare/hash two containers
"""
result = ""
container_line_list = list(self.objectValues())
container_line_list.sort(key=lambda x: x.getResource())
for container_line in container_line_list:
if container_line.hasCellContent():
container_cell_list = list(container_line.objectValues())
container_cell_list.sort(key=lambda x: x.getVariationText())
for container_cell in container_cell_list:
result += "%s %s %s\n" % (container_cell.getResource(),
container_cell.getQuantity(),
'|'.join(container_cell.getVariationText().split('\n')))
else:
result += "%s %s\n" % (container_line.getResource(), container_line.getQuantity())
container_list = list(self.objectValues(spec = self.meta_type))
container_list.sort(key=lambda x: x.getContainerText())
more_result = ""
for container in container_list:
more_result += container.getContainerText()
result = result + '\n'.join([" %s" % x for x in more_result.split('\n')])
return result
# Used for optimization - requires reindexing using container_uid
security.declareProtected(Permissions.AccessContentsInformation,
'getContainerUid')
def getContainerUid(self):
return self.getUid()
security.declareProtected(Permissions.AccessContentsInformation,
'getContainerValue')
def getContainerValue(self):
return self
security.declareProtected(Permissions.AccessContentsInformation,
'getContainer')
def getContainer(self):
return self.getRelativeUrl()
# Quantity methods
security.declareProtected(Permissions.AccessContentsInformation,
'getContainedTotalQuantity')
def getContainedTotalQuantity(self, recursive = 0):
"""
The sum of quantities of contained lines
"""
result = 0.0
for o in self.contentValues(filter =
{'portal_type': self.getPortalContainerLineTypeList()}):
result += o.getTotalQuantity()
if recursive:
for o in self.contentValues(filter =
{'portal_type': self.getPortalContainerTypeList()}):
result += o.getContainedTotalQuantity()
return result
security.declareProtected(Permissions.AccessContentsInformation,
'getContainedTotalPrice')
def getContainedTotalPrice(self, recursive = 0):
"""
The sum of price of contained lines
"""
result = 0.0
for o in self.contentValues(filter =
{'portal_type': self.getPortalContainerLineTypeList()}):
result += o.getTotalPrice()
if recursive:
for o in self.contentValues(filter =
{'portal_type': self.getPortalContainerTypeList()}):
result += o.getContainedTotalPrice()
return result
# Item Access
security.declareProtected(Permissions.AccessContentsInformation,
'getTrackedItemUidList')
def getTrackedItemUidList(self):
"""
Return a list of uid for related items.
If this container is related to no item, it is treated as an Item
"""
### XXX We should filter by portal type here
item_uid_list = self.getAggregateUidList()
if len(item_uid_list): return item_uid_list
return (self.getUid(),)
# XXX: Dirty but required for erp5_banking_core
getBaobabSourceUid = lambda x: x.getSourceUid()
getBaobabSourceUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationUid = lambda x: x.getDestinationUid()
getBaobabDestinationUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceSectionUid = lambda x: x.getSourceSectionUid()
getBaobabSourceSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationSectionUid = lambda x: x.getDestinationSectionUid()
getBaobabDestinationSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourcePaymentUid = lambda x: x.getSourcePaymentUid()
getBaobabSourcePaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationPaymentUid = lambda x: x.getDestinationPaymentUid()
getBaobabDestinationPaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceFunctionUid = lambda x: x.getSourceFunctionUid()
getBaobabSourceFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationFunctionUid = lambda x: x.getDestinationFunctionUid()
getBaobabDestinationFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceProjectUid = lambda x: x.getSourceProjectUid()
getBaobabSourceProjectUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationProjectUid = lambda x: x.getDestinationProjectUid()
getBaobabDestinationProjectUid__roles__ = PermissionRole(Permissions.View)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>Container</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.Container</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.Container</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -31,48 +31,48 @@ from AccessControl import ClassSecurityInfo ...@@ -31,48 +31,48 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell from erp5.component.document.DeliveryCell import DeliveryCell
class ContainerCell(DeliveryCell): class ContainerCell(DeliveryCell):
""" """
A DeliveryCell allows to define specific quantities A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line. for each variation of a resource in a delivery line.
""" """
meta_type = 'ERP5 Container Cell' meta_type = 'ERP5 Container Cell'
portal_type = 'Container Cell' portal_type = 'Container Cell'
isCell = 1 isCell = 1
# Declarative security # Declarative security
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties # Declarative properties
property_sheets = ( PropertySheet.Base property_sheets = ( PropertySheet.Base
, PropertySheet.CategoryCore , PropertySheet.CategoryCore
, PropertySheet.Arrow , PropertySheet.Arrow
, PropertySheet.Amount , PropertySheet.Amount
, PropertySheet.Task , PropertySheet.Task
, PropertySheet.Movement , PropertySheet.Movement
, PropertySheet.Price , PropertySheet.Price
, PropertySheet.Predicate , PropertySheet.Predicate
, PropertySheet.MappedValue , PropertySheet.MappedValue
, PropertySheet.ItemAggregation , PropertySheet.ItemAggregation
) )
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'isAccountable') 'isAccountable')
def isAccountable(self): def isAccountable(self):
""" """
Returns 1 if this needs to be accounted Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority Whenever delivery is there, delivery has priority
""" """
# Never accountable # Never accountable
return 0 return 0
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent') security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self): def isDivergent(self):
"""Return True if this movement diverges from the its simulation. """Return True if this movement diverges from the its simulation.
Container Cells are never divergent. Container Cells are never divergent.
""" """
return False return False
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ContainerCell</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.ContainerCell</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.ContainerCell</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -31,68 +31,67 @@ from AccessControl import ClassSecurityInfo ...@@ -31,68 +31,67 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
class ContainerLine(DeliveryLine): class ContainerLine(DeliveryLine):
""" """
A DeliveryLine object allows to implement lines in A DeliveryLine object allows to implement lines in
Deliveries (packing list, order, invoice, etc.) Deliveries (packing list, order, invoice, etc.)
It may include a price (for insurance, for customs, for invoices,
for orders)
"""
meta_type = 'ERP5 Container Line' It may include a price (for insurance, for customs, for invoices,
portal_type = 'Container Line' for orders)
"""
meta_type = 'ERP5 Container Line'
portal_type = 'Container Line'
# Declarative security # Declarative security
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties # Declarative properties
property_sheets = ( PropertySheet.Base property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject , PropertySheet.XMLObject
, PropertySheet.CategoryCore , PropertySheet.CategoryCore
, PropertySheet.Amount , PropertySheet.Amount
, PropertySheet.Task , PropertySheet.Task
, PropertySheet.Arrow , PropertySheet.Arrow
, PropertySheet.Movement , PropertySheet.Movement
, PropertySheet.Price , PropertySheet.Price
, PropertySheet.VariationRange , PropertySheet.VariationRange
, PropertySheet.ItemAggregation , PropertySheet.ItemAggregation
) )
# Cell Related # Cell Related
security.declareProtected( Permissions.ModifyPortalContent, 'newCellContent' ) security.declareProtected( Permissions.ModifyPortalContent, 'newCellContent' )
def newCellContent(self, id, portal_type='Container Cell', **kw): def newCellContent(self, id, portal_type='Container Cell', **kw): # pylint: disable=redefined-builtin
"""Overriden to specify default portal type """Overriden to specify default portal type
""" """
return self.newContent(id=id, portal_type=portal_type, **kw) return self.newContent(id=id, portal_type=portal_type, **kw)
security.declareProtected(Permissions.AccessContentsInformation, 'isAccountable') security.declareProtected(Permissions.AccessContentsInformation, 'isAccountable')
def isAccountable(self): def isAccountable(self):
""" """
Returns 1 if this needs to be accounted Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority Whenever delivery is there, delivery has priority
""" """
# Never accountable # Never accountable
return 0 return 0
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent') security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self): def isDivergent(self):
"""Return True if this movement diverges from the its simulation. """Return True if this movement diverges from the its simulation.
Container Lines are never divergent. Container Lines are never divergent.
""" """
return False return False
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity') security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity')
def getTotalQuantity(self): def getTotalQuantity(self, *args, **kw):
""" """
Returns the quantity if no cell or the total quantity if cells Returns the quantity if no cell or the total quantity if cells
""" """
base_id = 'movement' base_id = 'movement'
if not self.hasCellContent(base_id=base_id): if not self.hasCellContent(base_id=base_id):
return self.getQuantity() return self.getQuantity()
return sum(cell.getQuantity() for cell in return sum(cell.getQuantity() for cell in
self.getCellValueList(base_id=base_id)) self.getCellValueList(base_id=base_id))
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ContainerLine</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.ContainerLine</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.ContainerLine</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2002, 2004 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
# Romain Courteaud <romain@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.
#
##############################################################################
import zope.interface
from AccessControl import ClassSecurityInfo
from AccessControl.PermissionRole import PermissionRole
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Movement import Movement
from Products.ERP5.Document.MappedValue import MappedValue
from Products.ERP5.Document.ImmobilisationMovement import ImmobilisationMovement
class DeliveryCell(MappedValue, Movement, ImmobilisationMovement):
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
meta_type = 'ERP5 Delivery Cell'
portal_type = 'Delivery Cell'
isCell = 1
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.CategoryCore
, PropertySheet.Arrow
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
# Declarative interfaces
zope.interface.implements(interfaces.IDivergenceController,)
security.declareProtected(Permissions.AccessContentsInformation, 'isPredicate')
def isPredicate(self):
"""Movements are not predicates.
"""
return False
# MatrixBox methods
security.declareProtected( Permissions.AccessContentsInformation,
'hasCellContent' )
def hasCellContent(self, base_id='movement'):
"""A cell cannot have cell content itself.
"""
return 0
security.declareProtected(Permissions.AccessContentsInformation, 'isAccountable')
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
return self.getParentValue().getParentValue().isAccountable()
security.declareProtected(Permissions.AccessContentsInformation, 'getPrice')
def getPrice(self, *args, **kw):
"""
call Movement.getPrice
"""
return Movement.getPrice(self, *args, **kw)
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalPrice')
def getTotalPrice(self, default=0.0, *args, **kw):
"""
call Movement.getTotalPrice
"""
return Movement.getTotalPrice(self, default=default, *args, **kw)
security.declareProtected(Permissions.AccessContentsInformation,
'getRootDeliveryValue')
def getRootDeliveryValue(self):
"""
Returns the root delivery responsible of this cell
"""
return self.getParentValue().getRootDeliveryValue()
security.declareProtected( Permissions.ModifyPortalContent,
'notifyAfterUpdateRelatedContent' )
def notifyAfterUpdateRelatedContent(self, previous_category_url, new_category_url):
"""
Membership Crirerions and Category List are same in DeliveryCell
Must update it (or change implementation to remove data duplication)
"""
update_method = self.portal_categories.updateRelatedCategory
new_predicate_value = [update_method(c, previous_category_url, new_category_url)
for c in self.getPredicateValueList()]
self._setPredicateValueList(new_predicate_value)
# No reindex needed since uid stable
# XXX FIXME: option variation are today not well implemented
# This little hack is needed to make the matrixbox working
# in DeliveryLine_viewIndustrialPhase
# Generic form (DeliveryLine_viewOption) is required
def _edit(self, **kw):
"""
Store variation_category_list, in order to store new value of
industrial_phase after.
"""
edit_order = ['variation_category_list', # edit this one first
'item_id_list'] # this one must be the last
edit_order[1:1] = [x for x in kw.pop('edit_order', ())
if x not in edit_order]
# Base._edit updates unordered properties first
edit_order[1:1] = [x for x in kw if x not in edit_order]
MappedValue._edit(self, edit_order=edit_order, **kw)
# if self.isSimulated():
# self.getRootDeliveryValue().activate().propagateResourceToSimulation()
security.declareProtected(Permissions.ModifyPortalContent,
'updateSimulationDeliveryProperties')
def updateSimulationDeliveryProperties(self, movement_list = None):
"""
Set properties delivery_ratio and delivery_error for each
simulation movement in movement_list (all movements by default),
according to this delivery calculated quantity
"""
parent = self.getParentValue()
if parent is not None:
parent = parent.getParentValue()
if parent is not None:
parent.updateSimulationDeliveryProperties(movement_list, self)
security.declareProtected(Permissions.AccessContentsInformation, 'isMovement')
def isMovement(self):
return 1
security.declareProtected(Permissions.AccessContentsInformation,
'isMovingItem')
def isMovingItem(self, item):
type_based_script = self._getTypeBasedMethod('isMovingItem')
if type_based_script:
return type_based_script(item)
return self.isAccountable()
# Override getQuantityUnitXXX to negate same methods defined in
# Amount class. Because cell must acquire quantity unit from line
# not from resource.
security.declareProtected( Permissions.AccessContentsInformation,
'getQuantityUnitValue')
def getQuantityUnitValue(self):
return self.getParentValue().getQuantityUnitValue()
security.declareProtected( Permissions.AccessContentsInformation,
'getQuantityUnit')
def getQuantityUnit(self, checked_permission=None):
return self.getParentValue().getQuantityUnit(checked_permission=checked_permission)
# XXX: Dirty but required for erp5_banking_core
### Acquire Baobab source / destination uids from parent line
getBaobabSourceUid = lambda x: x.getSourceUid()
getBaobabSourceUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationUid = lambda x: x.getDestinationUid()
getBaobabDestinationUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceSectionUid = lambda x: x.getSourceSectionUid()
getBaobabSourceSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationSectionUid = lambda x: x.getDestinationSectionUid()
getBaobabDestinationSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourcePaymentUid = lambda x: x.getSourcePaymentUid()
getBaobabSourcePaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationPaymentUid = lambda x: x.getDestinationPaymentUid()
getBaobabDestinationPaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceFunctionUid = lambda x: x.getSourceFunctionUid()
getBaobabSourceFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationFunctionUid = lambda x: x.getDestinationFunctionUid()
getBaobabDestinationFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceProjectUid = lambda x: x.getSourceProjectUid()
getBaobabSourceProjectUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationProjectUid = lambda x: x.getDestinationProjectUid()
getBaobabDestinationProjectUid__roles__ = PermissionRole(Permissions.View)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>DeliveryCell</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.DeliveryCell</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.DeliveryCell</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# -*- coding: utf-8 -*-
##############################################################################
#
# 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.
#
##############################################################################
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5.Document.Movement import Movement
from Products.ERP5.Document.ImmobilisationMovement import ImmobilisationMovement
from inspect import getargspec
from Products.ERP5Type.Base import Base
edit_args_list = getargspec(Base._edit).args
class DeliveryLine(Movement, XMLMatrix, ImmobilisationMovement):
"""
A DeliveryLine object allows to implement lines in
Deliveries (packing list, order, invoice, etc.)
It may include a price (for insurance, for customs, for invoices,
for orders)
"""
meta_type = 'ERP5 Delivery Line'
portal_type = 'Delivery Line'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
, PropertySheet.SortIndex
)
# Declarative interfaces
zope.interface.implements(interfaces.IDivergenceController,)
# Multiple inheritance definition
updateRelatedContent = XMLMatrix.updateRelatedContent
# Force in _edit to modify variation_base_category_list first
def _edit(self, edit_order=(), **kw):
# XXX FIXME For now, special cases are handled in _edit methods in many
# documents : DeliveryLine, DeliveryCell ... Ideally, to prevent code
# duplication, it should be handled in a _edit method present only in
# Amount.py
# If variations and resources are set at the same time, resource must be
# set before any variation.
before_order = ('resource', 'resource_value',
'variation_base_category_list',
'variation_category_list')
before_kw = {k: kw.pop(k) for k in before_order if k in kw}
if before_kw:
before_kw.update((k, kw[k]) for k in edit_args_list if k in kw)
Base._edit(self, edit_order=before_order, **before_kw)
if kw:
Movement._edit(self, edit_order=edit_order, **kw)
# We must check if the user has changed the resource of particular line
security.declareProtected( Permissions.ModifyPortalContent, 'edit' )
def edit(self, REQUEST=None, force_update = 0, reindex_object=1, **kw):
return self._edit(REQUEST=REQUEST, force_update=force_update, reindex_object=reindex_object, **kw)
security.declareProtected(Permissions.AccessContentsInformation,
'isAccountable')
def isAccountable(self):
"""To avoid duplicate docstring. Please read movement interface."""
return self.getParentValue().isAccountable() and (not self.hasCellContent())
security.declareProtected(Permissions.AccessContentsInformation,
'isMovingItem')
def isMovingItem(self, item):
type_based_script = self._getTypeBasedMethod('isMovingItem')
if type_based_script:
return type_based_script(item)
return self.isAccountable()
def _getTotalPrice(self, default=0.0, context=None, fast=0):
"""
Returns the total price for this line, this line contains, or the cells it contains.
if hasLineContent: return sum of lines total price
if hasCellContent: return sum of cells total price
else: return quantity * price
if fast argument is true, inventory API will be used.
"""
if fast:
kw = {}
kw['section_uid'] = self.getDestinationSectionUid()
kw['stock.explanation_uid'] = self.getExplanationUid()
kw['relative_url'] = ( '%s/%%' % (
self.getRelativeUrl().replace('_', '\\_')),
self.getRelativeUrl() )
kw['only_accountable'] = False
return self.getPortalObject().portal_simulation.getInventoryAssetPrice(**kw)
if self.hasLineContent():
meta_type = self.meta_type
return sum(l.getTotalPrice(context=context)
for l in self.objectValues() if l.meta_type==meta_type)
elif not self.hasCellContent(base_id='movement'):
return Movement._getTotalPrice(self, default=default, context=context)
return sum(cell.getTotalPrice(default=0.0, context=context)
for cell in self.getCellValueList())
security.declareProtected( Permissions.AccessContentsInformation,
'getTotalQuantity')
def getTotalQuantity(self, fast=0):
"""
Returns the quantity if no cell or the total quantity if cells
if hasLineContent: return sum of lines total quantity
if hasCellContent: return sum of cells total quantity
else: return quantity
if fast argument is true, inventory API will be used.
"""
if fast:
kw = {}
kw['section_uid'] = self.getDestinationSectionUid()
kw['stock.explanation_uid'] = self.getExplanationUid()
kw['relative_url'] = ( '%s/%%' % (
self.getRelativeUrl().replace('_', '\\_')),
self.getRelativeUrl() )
kw['only_accountable'] = False
return self.getPortalObject().portal_simulation.getInventory(**kw)
base_id = 'movement'
if self.hasLineContent():
meta_type = self.meta_type
return sum(l.getTotalQuantity() for l in
self.objectValues() if l.meta_type==meta_type)
elif self.hasCellContent(base_id=base_id):
return sum([cell.getQuantity() for cell in self.getCellValueList()])
return self.getQuantity()
security.declareProtected(Permissions.AccessContentsInformation,
'hasLineContent')
def hasLineContent(self):
"""Return true if the object contains lines.
This method only checks the first sub line because all sub
lines should be same meta type in reality if we have line
inside line.
"""
return len(self) != 0 and self.objectValues()[0].meta_type == self.meta_type
security.declareProtected(Permissions.AccessContentsInformation,
'hasCellContent')
def hasCellContent(self, base_id='movement'):
"""Return true if the object contains cells.
"""
# Do not use XMLMatrix.hasCellContent, because it can generate
# inconsistency in catalog
# Exemple: define a line and set the matrix cell range, but do not create
# cell.
# Line was in this case consider like a movement, and was catalogued.
# But, getVariationText of the line was not empty.
# So, in ZODB, resource as without variation, but in catalog, this was
# the contrary...
cell_range = XMLMatrix.getCellRange(self, base_id=base_id)
return (cell_range is not None and len(cell_range) > 0)
# DeliveryLine can be a movement when it does not content any cell and
# matrix cell range is not empty.
# Better implementation is needed.
# We want to define a line without cell, defining a variated resource.
# If we modify the cell range, we need to move the quantity to a new
# cell, which define the same variated resource.
# return XMLMatrix.hasCellContent(self, base_id=base_id)
security.declareProtected( Permissions.AccessContentsInformation,
'isMovement' )
def isMovement(self):
"""
returns true is the object contains no submovement (line or cell)
"""
object_list = self.objectValues()
if object_list:
portal_type = self.getPortalObject().getPortalMovementTypeList()
for ob in object_list:
if ob.getPortalType() in portal_type:
return False
return True
security.declareProtected(Permissions.AccessContentsInformation, 'getMovedItemUidList')
def getMovedItemUidList(self):
"""This method returns an uid list of items
"""
return [item.getUid() for item in self.getAggregateValueList() \
if self.isMovingItem(item)]
security.declareProtected( Permissions.AccessContentsInformation, 'getCellValueList' )
def getCellValueList(self, base_id='movement'):
"""
This method can be overriden
"""
return XMLMatrix.getCellValueList(self, base_id=base_id)
security.declareProtected( Permissions.AccessContentsInformation, 'getCell' )
def getCell(self, *kw , **kwd):
"""
This method can be overriden
"""
if 'base_id' not in kwd:
kwd['base_id'] = 'movement'
return XMLMatrix.getCell(self, *kw, **kwd)
security.declareProtected( Permissions.ModifyPortalContent, 'newCell' )
def newCell(self, *kw, **kwd):
"""
This method creates a new cell
"""
if 'base_id' not in kwd:
kwd['base_id'] = 'movement'
return XMLMatrix.newCell(self, *kw, **kwd)
def applyToDeliveryLineRelatedMovement(self, portal_type='Simulation Movement', method_id = 'expand'):
# Find related in simulation
for my_simulation_movement in self.getDeliveryRelatedValueList(
portal_type = 'Simulation Movement'):
# And apply
getattr(my_simulation_movement.getObject(), method_id)()
for c in self.objectValues(portal_type='Delivery Cell'):
for my_simulation_movement in c.getDeliveryRelatedValueList(
portal_type = 'Simulation Movement'):
# And apply
getattr(my_simulation_movement.getObject(), method_id)()
def reindexObject(self, *k, **kw):
"""Reindex children"""
self.recursiveReindexObject(*k, **kw)
security.declareProtected(Permissions.AccessContentsInformation, 'getInventoriatedQuantity')
def getInventoriatedQuantity(self):
"""
"""
return Movement.getInventoriatedQuantity(self)
# security.declarePrivate('_checkConsistency')
# def _checkConsistency(self, fixit=0, mapped_value_property_list = ('quantity', 'price')):
# """
# Check the constitency of transformation elements
# """
# error_list = XMLMatrix._checkConsistency(self, fixit=fixit)
#
# # First quantity
# # We build an attribute equality and look at all cells
# q_constraint = Constraint.AttributeEquality(
# domain_base_category_list = self.getVariationBaseCategoryList(),
# predicate_operator = 'SUPERSET_OF',
# mapped_value_property_list = mapped_value_property_list )
# for k in self.getCellKeys(base_id = 'movement'):
# kw={}
# kw['base_id'] = 'movement'
# c = self.getCell(*k, **kw)
# if c is not None:
# predicate_value = []
# for p in k:
# if p is not None: predicate_value += [p]
# q_constraint.edit(predicate_value_list = predicate_value)
# if fixit:
# error_list += q_constraint.fixConsistency(c)
# else:
# error_list += q_constraint.checkConsistency(c)
# if list(c.getVariationCategoryList()) != predicate_value:
# error_message = "Variation %s but sould be %s" % (c.getVariationCategoryList(),predicate_value)
# if fixit:
# c.setVariationCategoryList(predicate_value)
# error_message += " (Fixed)"
# error_list += [(c.getRelativeUrl(), 'VariationCategoryList inconsistency', 100, error_message)]
#
# return error_list
security.declareProtected(Permissions.AccessContentsInformation,
'getRootDeliveryValue')
def getRootDeliveryValue(self):
"""
Returns the root delivery responsible of this line
"""
return self.getParentValue().getRootDeliveryValue()
security.declareProtected(Permissions.ModifyPortalContent,
'updateSimulationDeliveryProperties')
def updateSimulationDeliveryProperties(self, movement_list = None):
"""
Set properties delivery_ratio and delivery_error for each
simulation movement in movement_list (all movements by default),
according to this delivery calculated quantity
"""
parent = self.getParentValue()
if parent is not None:
parent.updateSimulationDeliveryProperties(movement_list, self)
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self, item, container):
"if the container is a line too, reindex it"
if self.meta_type == container.meta_type:
container.reindexObject()
return Movement.manage_afterAdd(self, item, container)
security.declarePrivate('manage_beforeDelete')
def manage_beforeDelete(self, item, container):
"if the container is a line too, reindex it"
if self.meta_type == container.meta_type:
container.reindexObject()
return Movement.manage_beforeDelete(self, item, container)
# divergence support with solving
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self):
"""Returns true if the delivery line is divergent, or if any contained
cell is divergent.
"""
return bool(self.getDivergenceList())
security.declareProtected(Permissions.AccessContentsInformation, 'getDivergenceList')
def getDivergenceList(self):
"""Returns a list of messages that contains the divergences for that line
and the cells it may contain.
"""
if self.hasCellContent():
divergence_list = []
for cell in self.objectValues(portal_type=self.getPortalObject()
.getPortalDeliveryMovementTypeList()):
divergence_list += cell.getDivergenceList()
return divergence_list
else:
return Movement.getDivergenceList(self)
def _distributePropertyToSimulation(self, decision):
"""Distributes property from self to all related simulation movements
AKA - accept decision"""
for simulation_movement in self.getDeliveryRelatedValueList(
portal_type='Simulation Movement'):
simulation_movement.edit(**{
decision.divergence.tested_property:
self.getProperty(decision.divergence.tested_property)
})
def _updatePropertyFromSimulation(self, decision_list):
"""Update property from simulation
'Stolen' from Products.ERP5.Document.DeliveryBuilder._solveDivergence
Another possibility is to just simply copy properties or, in case of
quantity, add from all simulation movements.
"""
simulation_movement_list = self.getDeliveryRelatedValueList(
portal_type="Simulation Movement")
business_link = simulation_movement_list[0].getCausalityValue()
delivery = self.getExplanationValue()
delivery_portal_type = delivery.getPortalType()
delivery_line_portal_type = self.getPortalType()
# we need to find only one matching delivery builder
for delivery_builder in business_link.getDeliveryBuilderValueList():
if delivery_builder.getDeliveryPortalType() == \
delivery_portal_type and \
delivery_builder.getDeliveryLinePortalType() == \
delivery_line_portal_type:
break
else:
raise ValueError('No builder found')
self.edit(quantity=0) # adoption have to 'rebuild' delivery line
# Collect
root_group_node = delivery_builder.collectMovement(
simulation_movement_list)
divergence_list = [decision.divergence for decision in decision_list]
# Build
portal = self.getPortalObject()
delivery_module = getattr(portal, delivery_builder.getDeliveryModule())
delivery_to_update_list = [delivery]
delivery_list = delivery_builder._processDeliveryGroup(
delivery_module,
root_group_node,
delivery_builder.getDeliveryMovementGroupList(),
delivery_to_update_list=delivery_to_update_list,
divergence_list=divergence_list,
force_update=1)
new_delivery_list = [x for x in delivery_list if x != delivery]
if new_delivery_list:
raise ValueError('No new deliveries shall be created')
# Then, we should re-apply quantity divergence according to 'Do
# nothing' quantity divergence list because all quantity are already
# calculated in adopt prevision phase.
quantity_dict = {}
for divergence in self.getDivergenceList():
if divergence.getProperty('divergence_scope') != 'quantity' or \
divergence in divergence_list:
continue
s_m = divergence.getProperty('simulation_movement')
delivery_movement = s_m.getDeliveryValue()
assert delivery_movement == self
quantity_gap = divergence.getProperty('decision_value') - \
divergence.getProperty('prevision_value')
delivery_movement.setQuantity(delivery_movement.getQuantity() + \
quantity_gap)
quantity_dict[s_m] = \
divergence.getProperty('decision_value')
# Finally, recalculate delivery_ratio
#
# Here, created/updated movements are not indexed yet. So we try to
# gather delivery relations from simulation movements.
delivery_dict = {}
for s_m in simulation_movement_list:
delivery_path = s_m.getDelivery()
delivery_dict[delivery_path] = \
delivery_dict.get(delivery_path, []) + \
[s_m]
for s_m_list_per_movement in delivery_dict.values():
total_quantity = sum([quantity_dict.get(s_m, s_m.getQuantity()) \
for s_m in s_m_list_per_movement])
if total_quantity != 0.0:
for s_m in s_m_list_per_movement:
delivery_ratio = quantity_dict.get(s_m, s_m.getQuantity()) \
/ total_quantity
s_m.edit(delivery_ratio=delivery_ratio)
else:
for s_m in s_m_list_per_movement:
delivery_ratio = 1.0 / len(s_m_list_per_movement)
s_m.edit(delivery_ratio=delivery_ratio)
security.declareProtected(Permissions.ModifyPortalContent, 'solve')
def solve(self, decision_list):
"""Solves line according to decision list
"""
simulation_tool = self.getPortalObject().portal_simulation
solveMovement = simulation_tool.solveMovement
# accept + split
for decision in [q for q in decision_list if q.decision != 'adopt']:
if decision.decision == 'accept':
# accepting - in case of passed DeliverySolver use it, otherwise
# simply copy values to simulation
if not decision.delivery_solver_name:
self._distributePropertyToSimulation(decision)
solveMovement(self, decision.delivery_solver_name,
decision.target_solver_name, divergence_list = [decision.divergence])
elif decision.decision == 'split':
solveMovement(self, decision.delivery_solver_name,
decision.target_solver_name, **decision.split_kw)
else: # aka - do nothing
pass
# adopt
adopt_decision_list = [q for q in decision_list \
if q.decision == 'adopt']
if adopt_decision_list:
self._updatePropertyFromSimulation(adopt_decision_list)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>DeliveryLine</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.DeliveryLine</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.DeliveryLine</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>DeliveryRootSimulationRule</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.DeliveryRootSimulationRule</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.DeliveryRootSimulationRule</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>DeliverySimulationRule</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.DeliverySimulationRule</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.DeliverySimulationRule</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -144,9 +144,9 @@ class Inventory(Delivery): ...@@ -144,9 +144,9 @@ class Inventory(Delivery):
if temp_constructor is None: if temp_constructor is None:
def temp_constructor(self, id, *args, **kw): temp_constructor = lambda self, id, *args, **kw: self.newContent(
return self.newContent(temp_object=True, portal_type='Movement', temp_object=True, portal_type='Movement',
id=id, *args, **kw) id=id, *args, **kw)
stop_date = self.getStopDate() stop_date = self.getStopDate()
stock_object_list = [] stock_object_list = []
...@@ -199,8 +199,8 @@ class Inventory(Delivery): ...@@ -199,8 +199,8 @@ class Inventory(Delivery):
__order_id_counter_list = [0] __order_id_counter_list = [0]
def getOrderIdCounter(): def getOrderIdCounter():
value = __order_id_counter_list[0] value = __order_id_counter_list[0] # pylint: disable=cell-var-from-loop
__order_id_counter_list[0] = value + 1 __order_id_counter_list[0] = value + 1 # pylint: disable=cell-var-from-loop
return value return value
for movement in method(): for movement in method():
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>Inventory</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.Inventory</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.Inventory</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -32,66 +32,64 @@ from AccessControl import ClassSecurityInfo ...@@ -32,66 +32,64 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
from Products.ERP5.Document.DeliveryCell import DeliveryCell from erp5.component.document.DeliveryCell import DeliveryCell
class InventoryCell(DeliveryCell): class InventoryCell(DeliveryCell):
""" """
An InventoryCell allows to define specific inventory An InventoryCell allows to define specific inventory
for each variation of a resource in an inventory line. for each variation of a resource in an inventory line.
""" """
meta_type = 'ERP5 Inventory Cell'
portal_type = 'Inventory Cell'
add_permission = Permissions.AddPortalContent
isInventoryMovement = ConstantGetter('isInventoryMovement', value=True)
meta_type = 'ERP5 Inventory Cell' # Declarative security
portal_type = 'Inventory Cell' security = ClassSecurityInfo()
add_permission = Permissions.AddPortalContent security.declareObjectProtected(Permissions.AccessContentsInformation)
isInventoryMovement = ConstantGetter('isInventoryMovement', value=True)
# Declarative security # Declarative properties
security = ClassSecurityInfo() property_sheets = ( PropertySheet.Base
security.declareObjectProtected(Permissions.AccessContentsInformation) , PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.InventoryMovement
, PropertySheet.Task
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
# Declarative properties security.declareProtected(Permissions.AccessContentsInformation, 'getTotalInventory')
property_sheets = ( PropertySheet.Base def getTotalInventory(self):
, PropertySheet.CategoryCore """
, PropertySheet.Amount Returns the inventory, as cells are not supposed to contain more cells.
, PropertySheet.InventoryMovement """
, PropertySheet.Task return self.getInventory()
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalInventory') security.declareProtected(Permissions.AccessContentsInformation, 'getQuantity')
def getTotalInventory(self): def getQuantity(self):
""" """
Returns the inventory, as cells are not supposed to contain more cells. Computes a quantity which allows to reach inventory
""" """
if not self.hasCellContent():
# First check if quantity already exists
quantity = self._baseGetQuantity()
if quantity not in (0.0, 0, None):
return quantity
# Make sure inventory is defined somewhere (here or parent)
if getattr(aq_base(self), 'inventory', None) is None:
return 0.0 # No inventory defined, so no quantity
return self.getInventory() return self.getInventory()
else:
return None
security.declareProtected(Permissions.AccessContentsInformation, 'getQuantity') # Inventory cataloging
def getQuantity(self): security.declareProtected(Permissions.AccessContentsInformation, 'getConvertedInventory')
""" def getConvertedInventory(self):
Computes a quantity which allows to reach inventory """
""" provides a default inventory value - None since
if not self.hasCellContent(): no inventory was defined.
# First check if quantity already exists """
quantity = self._baseGetQuantity() return self.getInventory() # XXX quantity unit is missing
if quantity not in (0.0, 0, None): \ No newline at end of file
return quantity
# Make sure inventory is defined somewhere (here or parent)
if getattr(aq_base(self), 'inventory', None) is None:
return 0.0 # No inventory defined, so no quantity
return self.getInventory()
else:
return None
# Inventory cataloging
security.declareProtected(Permissions.AccessContentsInformation, 'getConvertedInventory')
def getConvertedInventory(self):
"""
provides a default inventory value - None since
no inventory was defined.
"""
return self.getInventory() # XXX quantity unit is missing
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>InventoryCell</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.InventoryCell</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.InventoryCell</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
##############################################################################
#
# Copyright (c) 2002-2005 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 AccessControl import ClassSecurityInfo
from AccessControl.PermissionRole import PermissionRole
from Acquisition import aq_base
from Products.ERP5Type import Permissions, PropertySheet
from erp5.component.document.DeliveryLine import DeliveryLine
from Products.ERP5.Document.Movement import Movement
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
class InventoryLine(DeliveryLine):
"""
An Inventory Line describe the inventory of a resource, by variations.
"""
meta_type = 'ERP5 Inventory Line'
portal_type = 'Inventory Line'
add_permission = Permissions.AddPortalContent
isInventoryMovement = ConstantGetter('isInventoryMovement', value=True)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.InventoryMovement
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
)
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalInventory')
def getTotalInventory(self):
"""
Returns the inventory if no cell or the total inventory if cells
"""
if not self.hasCellContent():
return self.getInventory()
else:
total_quantity = 0.0
for cell in self.getCellValueList(base_id='movement'):
if cell.getInventory() is not None:
total_quantity += cell.getInventory()
return total_quantity
security.declareProtected(Permissions.AccessContentsInformation,
'getQuantity')
def getQuantity(self):
"""
Computes a quantity which allows to reach inventory
"""
if not self.hasCellContent():
# First check if quantity already exists
quantity = self._baseGetQuantity()
if quantity not in (0.0,0,None):
return quantity
# Make sure inventory is defined somewhere (here or parent)
inventory = getattr(aq_base(self), 'inventory', None)
if inventory is not None:
return inventory
return quantity
else:
return None
# Inventory cataloging
security.declareProtected(Permissions.AccessContentsInformation,
'getConvertedInventory')
def getConvertedInventory(self):
"""
provides a default inventory value - None since
no inventory was defined.
"""
return self.getInventory() # XXX quantity unit is missing
# Required for indexing
security.declareProtected(Permissions.AccessContentsInformation,
'getInventoriatedQuantity')
def getInventoriatedQuantity(self):
"""
Take into account efficiency in converted target quantity
"""
return Movement.getInventoriatedQuantity(self)
# XXX: Dirty but required for erp5_banking_core
getBaobabSourceUid = lambda x: x.getSourceUid()
getBaobabSourceUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationUid = lambda x: x.getDestinationUid()
getBaobabDestinationUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceSectionUid = lambda x: x.getSourceSectionUid()
getBaobabSourceSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationSectionUid = lambda x: x.getDestinationSectionUid()
getBaobabDestinationSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourcePaymentUid = lambda x: x.getSourcePaymentUid()
getBaobabSourcePaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationPaymentUid = lambda x: x.getDestinationPaymentUid()
getBaobabDestinationPaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceFunctionUid = lambda x: x.getSourceFunctionUid()
getBaobabSourceFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationFunctionUid = lambda x: x.getDestinationFunctionUid()
getBaobabDestinationFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceProjectUid = lambda x: x.getSourceProjectUid()
getBaobabSourceProjectUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationProjectUid = lambda x: x.getDestinationProjectUid()
getBaobabDestinationProjectUid__roles__ = PermissionRole(Permissions.View)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>InventoryLine</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.InventoryLine</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.InventoryLine</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
##############################################################################
#
# Copyright (c) 2002, 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
# Romain Courteaud <romain@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 AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Utils import deprecated
from Products.ERP5.Document.Delivery import Delivery
class Order(Delivery):
# CMF Type Definition
meta_type = 'ERP5 Order'
portal_type = 'Order'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Reference
, PropertySheet.TradeCondition
, PropertySheet.Comment
, PropertySheet.Order
)
security.declareProtected(Permissions.AccessContentsInformation, \
'isAccountable')
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
return 0
def getTotalPrice(self, **kw) :
"""Returns the total price for this Order.
If base_contribution is passed, the trade model lines will be used to
include movements that will be generated.
"""
if kw.get('fast'):
kw['only_accountable'] = False
if kw.get('base_contribution') is None:
kw.setdefault('portal_type', self.getPortalOrderMovementTypeList())
return Delivery.getTotalPrice(self, **kw)
else:
# Find amounts from the result of getAggregatedAmountList.
# Call getAggregatedAmountList and sum all the amounts which
# base_contribution category is matched with.
raise NotImplementedError
"""
rounding = kw.get('rounding')
from Products.ERP5.PropertySheet.TradeModelLine import TARGET_LEVEL_MOVEMENT
trade_condition = self.getSpecialiseValue()
if trade_condition is None:
# We cannot find any amount so that the result is 0.
return 0
base_contribution = kw.get('base_contribution')
if isinstance(base_contribution, (tuple, list)):
base_contribution_list = base_contribution
else:
base_contribution_list = (base_contribution,)
base_contribution_value_list = []
portal_categories = self.portal_categories
for relative_url in base_contribution_list:
base_contribution_value = portal_categories.getCategoryValue(relative_url)
if base_contribution_value is not None:
base_contribution_value_list.append(base_contribution_value)
if not base_contribution_value_list:
# We cannot find any amount so that the result is 0.
return 0
current_aggregated_amount_list = trade_condition.getAggregatedAmountList(self, rounding=rounding, force_create_line=True)
trade_model_line = self.newContent(temp_object=True,
portal_type='Trade Model Line',
id='_temp_' + self.getId(), notify_workflow=False)
# prevent invoking interaction workflows.
trade_model_line.portal_type = ''
trade_model_line.edit(target_level=TARGET_LEVEL_MOVEMENT, price=1,
efficiency=1, quantity=None,
base_application_value_list=base_contribution_value_list)
aggregated_amount_list = trade_model_line._getAggregatedAmountList(
self,
movement_list=self.getMovementList(),
current_aggregated_amount_list=current_aggregated_amount_list,
rounding=rounding)
return aggregated_amount_list.getTotalPrice()
"""
def getTotalQuantity(self, **kw) :
"""Returns the total quantity for this Order. """
if 'portal_type' not in kw:
kw['portal_type'] = self.getPortalObject() \
.getPortalOrderMovementTypeList()
if kw.get('fast'):
kw['only_accountable'] = False
return Delivery.getTotalQuantity(self, **kw)
@deprecated
def applyToOrderRelatedMovement(self, method_id='expand', **kw):
# WARNING: does not work if it was not catalogued immediately
# 'order' category is deprecated. it is kept for compatibility.
for m in self.getMovementList():
for my_simulation_movement in m.getDeliveryRelatedValueList(
portal_type='Simulation Movement') or \
m.getOrderRelatedValueList(
portal_type='Simulation Movement'):
getattr(my_simulation_movement, method_id)(**kw)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>Order</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.Order</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.Order</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -30,62 +30,60 @@ ...@@ -30,62 +30,60 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell from erp5.component.document.DeliveryCell import DeliveryCell
class OrderCell(DeliveryCell): class OrderCell(DeliveryCell):
""" """
A OrderCell allows to define specific quantities A OrderCell allows to define specific quantities
for each variation of a resource in a delivery line. for each variation of a resource in a delivery line.
""" """
meta_type = 'ERP5 Order Cell'
portal_type = 'Order Cell'
isCell = 1
meta_type = 'ERP5 Order Cell' # Declarative security
portal_type = 'Order Cell' security = ClassSecurityInfo()
isCell = 1 security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative security # Declarative properties
security = ClassSecurityInfo() property_sheets = ( PropertySheet.Base
security.declareObjectProtected(Permissions.AccessContentsInformation) , PropertySheet.CategoryCore
, PropertySheet.Arrow
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
# Declarative properties def reindexObject(self, *k, **kw):
property_sheets = ( PropertySheet.Base """
, PropertySheet.CategoryCore Reindex children and simulation
, PropertySheet.Arrow """
, PropertySheet.Amount self.recursiveReindexObject(*k,**kw)
, PropertySheet.Task
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
def reindexObject(self, *k, **kw):
"""
Reindex children and simulation
"""
self.recursiveReindexObject(*k,**kw)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'isMovement') 'isMovement')
def isMovement(self): def isMovement(self):
""" """
should be considered as a movement if the parent does not have sub lines should be considered as a movement if the parent does not have sub lines
""" """
return not self.getParentValue().hasLineContent() return not self.getParentValue().hasLineContent()
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getTotalPrice') 'getTotalPrice')
def getTotalPrice(self, default=0.0, *args, **kw): def getTotalPrice(self, default=0.0, *args, **kw):
"only return a value if self is a movement" "only return a value if self is a movement"
if not self.isMovement(): if not self.isMovement():
return default return default
return DeliveryCell.getTotalPrice(self, default=default, *args, **kw) return DeliveryCell.getTotalPrice(self, default=default, *args, **kw)
security.declareProtected(Permissions.AccessContentsInformation,
'getTotalQuantity')
def getTotalQuantity(self, default=0.0, *args, **kw):
"only return a value if self is a movement"
if not self.isMovement():
return default
return DeliveryCell.getTotalQuantity(self, default=default, *args, **kw)
security.declareProtected(Permissions.AccessContentsInformation,
'getTotalQuantity')
def getTotalQuantity(self, default=0.0, *args, **kw):
"only return a value if self is a movement"
if not self.isMovement():
return default
return DeliveryCell.getTotalQuantity(self, default=default, *args, **kw)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>OrderCell</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.OrderCell</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.OrderCell</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -29,30 +29,29 @@ ...@@ -29,30 +29,29 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine from erp5.component.document.DeliveryLine import DeliveryLine
class OrderLine(DeliveryLine): class OrderLine(DeliveryLine):
""" """
A order line defines quantity and price A order line defines quantity and price
""" """
meta_type = 'ERP5 Order Line'
portal_type = 'Order Line'
meta_type = 'ERP5 Order Line' # Declarative security
portal_type = 'Order Line' security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative security # Declarative properties
security = ClassSecurityInfo() property_sheets = ( PropertySheet.Base
security.declareObjectProtected(Permissions.AccessContentsInformation) , PropertySheet.XMLObject
, PropertySheet.CategoryCore
# Declarative properties , PropertySheet.Amount
property_sheets = ( PropertySheet.Base , PropertySheet.Task
, PropertySheet.XMLObject , PropertySheet.DublinCore
, PropertySheet.CategoryCore , PropertySheet.Arrow
, PropertySheet.Amount , PropertySheet.Movement
, PropertySheet.Task , PropertySheet.Price
, PropertySheet.DublinCore , PropertySheet.VariationRange
, PropertySheet.Arrow , PropertySheet.ItemAggregation
, PropertySheet.Movement )
, PropertySheet.Price \ No newline at end of file
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>OrderLine</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.OrderLine</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.OrderLine</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>OrderRootSimulationRule</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.OrderRootSimulationRule</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.OrderRootSimulationRule</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -32,10 +32,9 @@ from AccessControl import ClassSecurityInfo ...@@ -32,10 +32,9 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.Delivery import Delivery from Products.ERP5.Document.Delivery import Delivery
from warnings import warn
class PackingList(Delivery): class PackingList(Delivery):
""" """
Delivery/PackingList is the main document Delivery/PackingList is the main document
which allows to control causality in the simulation which allows to control causality in the simulation
...@@ -58,67 +57,66 @@ class PackingList(Delivery): ...@@ -58,67 +57,66 @@ class PackingList(Delivery):
- postpone delivery - postpone delivery
solutions are implemented as solvers solutions are implemented as solvers
"""
# CMF Type Definition
meta_type = 'ERP5 Packing List'
portal_type = 'Packing List'
add_permission = Permissions.AddPortalContent
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Comment
, PropertySheet.Movement
, PropertySheet.TradeCondition
, PropertySheet.Order
)
#######################################################
# Container computation
security.declareProtected(Permissions.AccessContentsInformation,
'isPacked')
def isPacked(self):
""" """
# CMF Type Definition
meta_type = 'ERP5 Packing List'
portal_type = 'Packing List'
add_permission = Permissions.AddPortalContent
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Comment
, PropertySheet.Movement
, PropertySheet.TradeCondition
, PropertySheet.Order
)
#######################################################
# Container computation
security.declareProtected(Permissions.AccessContentsInformation,
'isPacked')
def isPacked(self):
"""
Returns true if all quantities for all variations of resources are in Returns true if all quantities for all variations of resources are in
containers. containers.
FIXME: this method does not support packing list with 2 movements of FIXME: this method does not support packing list with 2 movements of
same resource. same resource.
""" """
# build a mapping of # build a mapping of
# (resource, variation_text) -> quantity # (resource, variation_text) -> quantity
container_dict = defaultdict(int) container_dict = defaultdict(int)
for container in self.contentValues( for container in self.contentValues(
portal_type=self.getPortalContainerTypeList()): portal_type=self.getPortalContainerTypeList()):
for container_line in container.contentValues( for container_line in container.contentValues(
portal_type=self.getPortalContainerLineTypeList(),): portal_type=self.getPortalContainerLineTypeList(),):
if container_line.hasCellContent(base_id='movement'): if container_line.hasCellContent(base_id='movement'):
for container_cell in container_line.contentValues( for container_cell in container_line.contentValues(
portal_type=self.getPortalContainerLineTypeList(),): portal_type=self.getPortalContainerLineTypeList(),):
key = (container_cell.getResource(), key = (container_cell.getResource(),
container_cell.getVariationText()) container_cell.getVariationText())
container_dict[key] += container_cell.getQuantity() container_dict[key] += container_cell.getQuantity()
else: else:
key = (container_line.getResource(), key = (container_line.getResource(),
container_line.getVariationText()) container_line.getVariationText())
container_dict[key] += container_line.getQuantity() container_dict[key] += container_line.getQuantity()
if not container_dict: if not container_dict:
return False
# Check that all movements are packed.
for movement in self.getMovementList():
key = (movement.getResource(),
movement.getVariationText())
if container_dict.get(key) != movement.getQuantity():
return False return False
return True
# Check that all movements are packed. \ No newline at end of file
for movement in self.getMovementList():
key = (movement.getResource(),
movement.getVariationText())
if container_dict.get(key) != movement.getQuantity():
return False
return True
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>PackingList</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.PackingList</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.PackingList</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.TradeModelLine import TradeModelLine from erp5.component.document.TradeModelLine import TradeModelLine
class PaymentCondition(TradeModelLine): class PaymentCondition(TradeModelLine):
""" """
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>PaymentCondition</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.PaymentCondition</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.PaymentCondition</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -36,100 +36,96 @@ import zope.interface ...@@ -36,100 +36,96 @@ import zope.interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.Utils import deprecated
from Products.ERP5.mixin.composition import _getEffectiveModel from Products.ERP5.mixin.composition import _getEffectiveModel
from Products.ERP5.Document.Transformation import Transformation
from Products.ERP5.GeneratedAmountList import GeneratedAmountList
from Products.ERP5.Document.MappedValue import MappedValue from Products.ERP5.Document.MappedValue import MappedValue
from Products.ERP5.mixin.amount_generator import AmountGeneratorMixin from Products.ERP5.mixin.amount_generator import AmountGeneratorMixin
from Products.ERP5.mixin.variated import VariatedMixin from Products.ERP5.mixin.variated import VariatedMixin
class TradeCondition(MappedValue, AmountGeneratorMixin, VariatedMixin): class TradeCondition(MappedValue, AmountGeneratorMixin, VariatedMixin):
""" """
Trade Conditions are used to store the conditions (payment, logistic,...) Trade Conditions are used to store the conditions (payment, logistic,...)
which should be applied (and used in the orders) when two companies make which should be applied (and used in the orders) when two companies make
business together business together
""" """
meta_type = 'ERP5 Trade Condition' meta_type = 'ERP5 Trade Condition'
portal_type = 'Trade Condition' portal_type = 'Trade Condition'
model_line_portal_type_list = ('Trade Model Line',) model_line_portal_type_list = ('Trade Model Line',)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties # Declarative security
property_sheets = ( PropertySheet.Base security = ClassSecurityInfo()
, PropertySheet.XMLObject security.declareObjectProtected(Permissions.AccessContentsInformation)
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
, PropertySheet.Folder
, PropertySheet.Comment
, PropertySheet.Reference
, PropertySheet.Version
, PropertySheet.Arrow
, PropertySheet.TradeCondition
, PropertySheet.Order
, PropertySheet.Task # XXX It is probably wrong to have
# Task propertysheet, however many tests fails
# if not present. Cleaning required.
)
zope.interface.implements(interfaces.IAmountGenerator, # Declarative properties
interfaces.IMovementGenerator, property_sheets = ( PropertySheet.Base
interfaces.IMovementCollectionUpdater,) , PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
, PropertySheet.Folder
, PropertySheet.Comment
, PropertySheet.Reference
, PropertySheet.Version
, PropertySheet.Arrow
, PropertySheet.TradeCondition
, PropertySheet.Order
, PropertySheet.Task # XXX It is probably wrong to have
# Task propertysheet, however many tests fails
# if not present. Cleaning required.
)
zope.interface.implements(interfaces.IAmountGenerator,
interfaces.IMovementGenerator,
interfaces.IMovementCollectionUpdater,)
# Mapped Value implementation
# Transformation itself provides no properties or categories
def getMappedValuePropertyList(self):
return ()
def getMappedValueBaseCategoryList(self): # Mapped Value implementation
return () # Transformation itself provides no properties or categories
def getMappedValuePropertyList(self):
return ()
security.declareProtected(Permissions.AccessContentsInformation, def getMappedValueBaseCategoryList(self): # pylint: disable=arguments-differ
'findEffectiveSpecialiseValueList') return ()
#deprecated # XXX
def findEffectiveSpecialiseValueList(self, context, portal_type_list=None):
"""Return a list of effective specialised objects that is the
inheritance tree.
An effective object is an object which have start_date and stop_date
included to the range of the given parameters start_date and stop_date.
This algorithm uses Breadth First Search. security.declareProtected(Permissions.AccessContentsInformation,
""" 'findEffectiveSpecialiseValueList')
portal_type_set = set(portal_type_list or #deprecated # XXX
self.getPortalAmountGeneratorTypeList()) def findEffectiveSpecialiseValueList(self, context, portal_type_list=None):
return [x for x in context._findEffectiveSpecialiseValueList() """Return a list of effective specialised objects that is the
if x.getPortalType() in portal_type_set] inheritance tree.
An effective object is an object which have start_date and stop_date
included to the range of the given parameters start_date and stop_date.
security.declareProtected(Permissions.AccessContentsInformation, This algorithm uses Breadth First Search.
'getAggregatedAmountList') """
def getAggregatedAmountList(self, *args, **kw): portal_type_set = set(portal_type_list or
""" self.getPortalAmountGeneratorTypeList())
""" return [x for x in context._findEffectiveSpecialiseValueList()
# Detect old use of getAggregatedAmountList if x.getPortalType() in portal_type_set]
if 'context' in kw:
context = kw.pop('context')
else:
if 'force_create_line' in kw:
del kw['force_create_line']
elif not args or isinstance(args[0], (list, tuple)):
return AmountGeneratorMixin.getAggregatedAmountList(self, *args, **kw)
context, args = args[0], args[1:]
warnings.warn("The API of getAggregatedAmountList has changed:"
" it must be called on the context instead of passing"
" the context as first parameter", DeprecationWarning)
# XXX add a 'trade_amount_generator' group type
kw['amount_generator_type_list'] = ('Purchase Trade Condition',
'Sale Trade Condition',
'Trade Model Line')
return context.getAggregatedAmountList(*args, **kw)
#deprecated # XXX security.declareProtected(Permissions.AccessContentsInformation,
security.declareProtected(Permissions.AccessContentsInformation, 'getAggregatedAmountList')
'getEffectiveModel') def getAggregatedAmountList(self, *args, **kw):
def getEffectiveModel(self, start_date=None, stop_date=None): """
return _getEffectiveModel(self, start_date, stop_date) """
# Detect old use of getAggregatedAmountList
if 'context' in kw:
context = kw.pop('context')
else:
if 'force_create_line' in kw:
del kw['force_create_line']
elif not args or isinstance(args[0], (list, tuple)):
return AmountGeneratorMixin.getAggregatedAmountList(self, *args, **kw)
context, args = args[0], args[1:]
warnings.warn("The API of getAggregatedAmountList has changed:"
" it must be called on the context instead of passing"
" the context as first parameter", DeprecationWarning)
# XXX add a 'trade_amount_generator' group type
kw['amount_generator_type_list'] = ('Purchase Trade Condition',
'Sale Trade Condition',
'Trade Model Line')
return context.getAggregatedAmountList(*args, **kw)
#deprecated # XXX
security.declareProtected(Permissions.AccessContentsInformation,
'getEffectiveModel')
def getEffectiveModel(self, start_date=None, stop_date=None):
return _getEffectiveModel(self, start_date, stop_date)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>TradeCondition</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.TradeCondition</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.TradeCondition</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -29,57 +29,57 @@ ...@@ -29,57 +29,57 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.TradeModelLine import TradeModelLine from erp5.component.document.TradeModelLine import TradeModelLine
import zope.interface import zope.interface
class TradeModelCell(TradeModelLine): class TradeModelCell(TradeModelLine):
"""Trade Model Line """Trade Model Line
""" """
meta_type = 'ERP5 Trade Model Cell' meta_type = 'ERP5 Trade Model Cell'
portal_type = 'Trade Model Cell' portal_type = 'Trade Model Cell'
isCell = 1 isCell = 1
# Declarative security # Declarative security
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces # Declarative interfaces
# interfaces.IVariated as soon as interfaces.IVariated will be zope3 # interfaces.IVariated as soon as interfaces.IVariated will be zope3
zope.interface.implements( zope.interface.implements(
interfaces.IAmountGenerator interfaces.IAmountGenerator
) )
# Declarative properties # Declarative properties
property_sheets = ( PropertySheet.Base property_sheets = ( PropertySheet.Base
, PropertySheet.SimpleItem , PropertySheet.SimpleItem
, PropertySheet.CategoryCore , PropertySheet.CategoryCore
, PropertySheet.Amount , PropertySheet.Amount
, PropertySheet.Price , PropertySheet.Price
, PropertySheet.TradeModelLine , PropertySheet.TradeModelLine
, PropertySheet.Predicate , PropertySheet.Predicate
, PropertySheet.MappedValue , PropertySheet.MappedValue
, PropertySheet.ItemAggregation , PropertySheet.ItemAggregation
) )
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'hasCellContent' ) 'hasCellContent' )
def hasCellContent(self, base_id='movement'): def hasCellContent(self, base_id='movement'):
"""A cell cannot have cell content itself. """A cell cannot have cell content itself.
""" """
return 0 return 0
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getQuantity') 'getQuantity')
def getQuantity(self): def getQuantity(self):
"""Overridden getter to return None instead 0 if undefined""" """Overridden getter to return None instead 0 if undefined"""
return self._baseGetQuantity(None) return self._baseGetQuantity(None)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getTotalPrice') 'getTotalPrice')
def getTotalPrice(self): def getTotalPrice(self):
""" """
Returns the totals price for this line Returns the totals price for this line
""" """
quantity = self.getQuantity() or 0.0 quantity = self.getQuantity() or 0.0
price = self.getPrice() or 0.0 price = self.getPrice() or 0.0
return quantity * price return quantity * price
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>TradeModelCell</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.TradeModelCell</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.TradeModelCell</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -65,5 +65,5 @@ class TradeModelLine(AmountGeneratorLine): ...@@ -65,5 +65,5 @@ class TradeModelLine(AmountGeneratorLine):
# Else tax provides only a ratio on amount # Else tax provides only a ratio on amount
return ('price',) return ('price',)
def getMappedValueBaseCategoryList(self): def getMappedValueBaseCategoryList(self): # pylint: disable=arguments-differ
return self._baseGetMappedValueBaseCategoryList() or ('trade_phase', 'use',) return self._baseGetMappedValueBaseCategoryList() or ('trade_phase', 'use',)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>TradeModelLine</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.TradeModelLine</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.TradeModelLine</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -61,7 +61,7 @@ class TradeModelLineCellConsistencyConstraint(ConstraintMixin): ...@@ -61,7 +61,7 @@ class TradeModelLineCellConsistencyConstraint(ConstraintMixin):
_message_id_tuple = ('message_cell_inexistance',) _message_id_tuple = ('message_cell_inexistance',)
@staticmethod @staticmethod
def _convertFromFilesystemDefinition(base_id): def _convertFromFilesystemDefinition(base_id, *args, **kw):
""" """
@see ERP5Type.mixin.constraint.ConstraintMixin._convertFromFilesystemDefinition @see ERP5Type.mixin.constraint.ConstraintMixin._convertFromFilesystemDefinition
""" """
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>TradeModelLineCellConsistencyConstraint</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.TradeModelLineCellConsistencyConstraint</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.TradeModelLineCellConsistencyConstraint</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -34,6 +34,7 @@ from AccessControl import ClassSecurityInfo ...@@ -34,6 +34,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Path import Path from Products.ERP5.Document.Path import Path
from Products.ERP5.ExplanationCache import _getExplanationCache from Products.ERP5.ExplanationCache import _getExplanationCache
from erp5.component.interface.ITradeModelPath import ITradeModelPath
import zope.interface import zope.interface
...@@ -94,7 +95,7 @@ class TradeModelPath(Path): ...@@ -94,7 +95,7 @@ class TradeModelPath(Path):
# Declarative interfaces # Declarative interfaces
zope.interface.implements(interfaces.ICategoryAccessProvider, zope.interface.implements(interfaces.ICategoryAccessProvider,
interfaces.IArrowBase, interfaces.IArrowBase,
interfaces.ITradeModelPath, ITradeModelPath,
interfaces.IPredicate, interfaces.IPredicate,
) )
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
# #
############################################################################## ##############################################################################
""" """
Products.ERP5.interfaces.business_link erp5.component.interface.IBusinessLink
""" """
from zope.interface import Interface from zope.interface import Interface
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interface Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>IBusinessLink</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.interfaces.business_link</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interface.erp5.IBusinessLink</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Interface Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interface Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>IBusinessProcess</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.interfaces.business_process</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interface.erp5.IBusinessProcess</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Interface Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
# #
############################################################################## ##############################################################################
""" """
Products.ERP5.interfaces.trade_model_path erp5.component.interface.ITradeModelPath
""" """
from zope.interface import Interface from zope.interface import Interface
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interface Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ITradeModelPath</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.interfaces.trade_model_path</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interface.erp5.ITradeModelPath</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Interface Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
document.erp5.BusinessLink document.erp5.BusinessLink
document.erp5.BusinessProcess document.erp5.BusinessProcess
document.erp5.Container
document.erp5.ContainerCell
document.erp5.ContainerLine
document.erp5.DeliveryCell
document.erp5.DeliveryLine
document.erp5.DeliveryRootSimulationRule
document.erp5.DeliverySimulationRule
document.erp5.DuplicateInventoryConstraint document.erp5.DuplicateInventoryConstraint
document.erp5.Inventory
document.erp5.InventoryCell
document.erp5.InventoryLine
document.erp5.Order
document.erp5.OrderCell
document.erp5.OrderLine
document.erp5.OrderRootSimulationRule
document.erp5.PackingList
document.erp5.PaymentCondition
document.erp5.TradeCondition
document.erp5.TradeModelCell
document.erp5.TradeModelLine
document.erp5.TradeModelLineCellConsistencyConstraint
document.erp5.TradeModelPath document.erp5.TradeModelPath
\ No newline at end of file
interface.erp5.IBusinessLink
interface.erp5.IBusinessProcess
interface.erp5.ITradeModelPath
\ No newline at end of file
##############################################################################
#
# Copyright (c) 2002, 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
# Romain Courteaud <romain@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 AccessControl import ClassSecurityInfo
from AccessControl.PermissionRole import PermissionRole
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5.Document.Movement import Movement
class Container(Movement, XMLObject):
"""
Container is equivalent to a movement with qty 1.0 and resource =
to the kind of packaging Container may point to item (ex.
Container serial No or Parcel Serial No if tracing required)
Container may eventually usa optional property sheet to store
parcel No information (we use Item property sheet for that). Some
acquisition may be required...
A Container which does not point to an Item can act itself as an Item
for traceability.
Container Line / Container Cell is used to store quantities (never
accounted)
Container Line / Countainer Cell may point to Item
"""
meta_type = 'ERP5 Container'
portal_type = 'Container'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
, PropertySheet.Item
, PropertySheet.Container
, PropertySheet.SortIndex
)
security.declareProtected(Permissions.AccessContentsInformation,
'getQuantity')
def getQuantity(self, default=1.0):
"""
Returns 1 because only one container is shipped
"""
return 1.0
security.declareProtected(Permissions.AccessContentsInformation,
'isAccountable')
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
# Always accountable - to account the containers which we use
return 1
security.declareProtected( Permissions.ModifyPortalContent,
'hasCellContent' )
def hasCellContent(self, base_id='movement'):
"""
This method can be overriden
"""
return 0
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self):
"""Return True if this movement diverges from the its simulation.
Containers are never divergent.
"""
return False
security.declareProtected(Permissions.AccessContentsInformation,
'getContainerText')
def getContainerText(self):
"""
Creates a unique string which allows to compare/hash two containers
"""
result = ""
container_line_list = list(self.objectValues())
container_line_list.sort(key=lambda x: x.getResource())
for container_line in container_line_list:
if container_line.hasCellContent():
container_cell_list = list(container_line.objectValues())
container_cell_list.sort(key=lambda x: x.getVariationText())
for container_cell in container_cell_list:
result += "%s %s %s\n" % (container_cell.getResource(),
container_cell.getQuantity(),
'|'.join(container_cell.getVariationText().split('\n')))
else:
result += "%s %s\n" % (container_line.getResource(), container_line.getQuantity())
container_list = list(self.objectValues(spec = self.meta_type))
container_list.sort(key=lambda x: x.getContainerText())
more_result = ""
for container in container_list:
more_result += container.getContainerText()
result = result + '\n'.join(map(lambda x: " %s" % x, more_result.split('\n')))
return result
# Used for optimization - requires reindexing using container_uid
security.declareProtected(Permissions.AccessContentsInformation,
'getContainerUid')
def getContainerUid(self):
return self.getUid()
security.declareProtected(Permissions.AccessContentsInformation,
'getContainerValue')
def getContainerValue(self):
return self
security.declareProtected(Permissions.AccessContentsInformation,
'getContainer')
def getContainer(self):
return self.getRelativeUrl()
# Quantity methods
security.declareProtected(Permissions.AccessContentsInformation,
'getContainedTotalQuantity')
def getContainedTotalQuantity(self, recursive = 0):
"""
The sum of quantities of contained lines
"""
result = 0.0
for o in self.contentValues(filter =
{'portal_type': self.getPortalContainerLineTypeList()}):
result += o.getTotalQuantity()
if recursive:
for o in self.contentValues(filter =
{'portal_type': self.getPortalContainerTypeList()}):
result += o.getContainedTotalQuantity()
return result
security.declareProtected(Permissions.AccessContentsInformation,
'getContainedTotalPrice')
def getContainedTotalPrice(self, recursive = 0):
"""
The sum of price of contained lines
"""
result = 0.0
for o in self.contentValues(filter =
{'portal_type': self.getPortalContainerLineTypeList()}):
result += o.getTotalPrice()
if recursive:
for o in self.contentValues(filter =
{'portal_type': self.getPortalContainerTypeList()}):
result += o.getContainedTotalPrice()
return result
# Item Access
security.declareProtected(Permissions.AccessContentsInformation,
'getTrackedItemUidList')
def getTrackedItemUidList(self):
"""
Return a list of uid for related items.
If this container is related to no item, it is treated as an Item
"""
### XXX We should filter by portal type here
item_uid_list = self.getAggregateUidList()
if len(item_uid_list): return item_uid_list
return (self.getUid(),)
# XXX: Dirty but required for erp5_banking_core
getBaobabSourceUid = lambda x: x.getSourceUid()
getBaobabSourceUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationUid = lambda x: x.getDestinationUid()
getBaobabDestinationUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceSectionUid = lambda x: x.getSourceSectionUid()
getBaobabSourceSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationSectionUid = lambda x: x.getDestinationSectionUid()
getBaobabDestinationSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourcePaymentUid = lambda x: x.getSourcePaymentUid()
getBaobabSourcePaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationPaymentUid = lambda x: x.getDestinationPaymentUid()
getBaobabDestinationPaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceFunctionUid = lambda x: x.getSourceFunctionUid()
getBaobabSourceFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationFunctionUid = lambda x: x.getDestinationFunctionUid()
getBaobabDestinationFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceProjectUid = lambda x: x.getSourceProjectUid()
getBaobabSourceProjectUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationProjectUid = lambda x: x.getDestinationProjectUid()
getBaobabDestinationProjectUid__roles__ = PermissionRole(Permissions.View)
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2002, 2004 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
# Romain Courteaud <romain@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.
#
##############################################################################
import zope.interface
from AccessControl import ClassSecurityInfo
from AccessControl.PermissionRole import PermissionRole
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.OrderLine import OrderLine
from Products.ERP5.Document.Movement import Movement
from Products.ERP5.Document.MappedValue import MappedValue
from Products.ERP5.Document.ImmobilisationMovement import ImmobilisationMovement
class DeliveryCell(MappedValue, Movement, ImmobilisationMovement):
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
meta_type = 'ERP5 Delivery Cell'
portal_type = 'Delivery Cell'
isCell = 1
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.CategoryCore
, PropertySheet.Arrow
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
# Declarative interfaces
zope.interface.implements(interfaces.IDivergenceController,)
security.declareProtected(Permissions.AccessContentsInformation, 'isPredicate')
def isPredicate(self):
"""Movements are not predicates.
"""
return False
# MatrixBox methods
security.declareProtected( Permissions.AccessContentsInformation,
'hasCellContent' )
def hasCellContent(self, base_id='movement'):
"""A cell cannot have cell content itself.
"""
return 0
security.declareProtected(Permissions.AccessContentsInformation, 'isAccountable')
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
return self.getParentValue().getParentValue().isAccountable()
security.declareProtected(Permissions.AccessContentsInformation, 'getPrice')
def getPrice(self, *args, **kw):
"""
call Movement.getPrice
"""
return Movement.getPrice(self, *args, **kw)
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalPrice')
def getTotalPrice(self, default=0.0, *args, **kw):
"""
call Movement.getTotalPrice
"""
return Movement.getTotalPrice(self, default=default, *args, **kw)
security.declareProtected(Permissions.AccessContentsInformation,
'getRootDeliveryValue')
def getRootDeliveryValue(self):
"""
Returns the root delivery responsible of this cell
"""
return self.getParentValue().getRootDeliveryValue()
security.declareProtected( Permissions.ModifyPortalContent,
'notifyAfterUpdateRelatedContent' )
def notifyAfterUpdateRelatedContent(self, previous_category_url,
new_category_url):
"""
Membership Crirerions and Category List are same in DeliveryCell
Must update it (or change implementation to remove data duplication)
"""
update_method = self.portal_categories.updateRelatedCategory
predicate_value = self.getPredicateValueList()
new_predicate_value = map(lambda c: update_method(c,
previous_category_url, new_category_url), predicate_value)
self._setPredicateValueList(new_predicate_value)
# No reindex needed since uid stable
# XXX FIXME: option variation are today not well implemented
# This little hack is needed to make the matrixbox working
# in DeliveryLine_viewIndustrialPhase
# Generic form (DeliveryLine_viewOption) is required
def _edit(self, **kw):
"""
Store variation_category_list, in order to store new value of
industrial_phase after.
"""
edit_order = ['variation_category_list', # edit this one first
'item_id_list'] # this one must be the last
edit_order[1:1] = [x for x in kw.pop('edit_order', ())
if x not in edit_order]
# Base._edit updates unordered properties first
edit_order[1:1] = [x for x in kw if x not in edit_order]
MappedValue._edit(self, edit_order=edit_order, **kw)
# if self.isSimulated():
# self.getRootDeliveryValue().activate().propagateResourceToSimulation()
security.declareProtected(Permissions.ModifyPortalContent,
'updateSimulationDeliveryProperties')
def updateSimulationDeliveryProperties(self, movement_list = None):
"""
Set properties delivery_ratio and delivery_error for each
simulation movement in movement_list (all movements by default),
according to this delivery calculated quantity
"""
parent = self.getParentValue()
if parent is not None:
parent = parent.getParentValue()
if parent is not None:
parent.updateSimulationDeliveryProperties(movement_list, self)
security.declareProtected(Permissions.AccessContentsInformation, 'isMovement')
def isMovement(self):
return 1
security.declareProtected(Permissions.AccessContentsInformation,
'isMovingItem')
def isMovingItem(self, item):
type_based_script = self._getTypeBasedMethod('isMovingItem')
if type_based_script:
return type_based_script(item)
return self.isAccountable()
# Override getQuantityUnitXXX to negate same methods defined in
# Amount class. Because cell must acquire quantity unit from line
# not from resource.
security.declareProtected( Permissions.AccessContentsInformation,
'getQuantityUnitValue')
def getQuantityUnitValue(self):
return self.getParentValue().getQuantityUnitValue()
security.declareProtected( Permissions.AccessContentsInformation,
'getQuantityUnit')
def getQuantityUnit(self, checked_permission=None):
return self.getParentValue().getQuantityUnit(checked_permission=checked_permission)
# XXX: Dirty but required for erp5_banking_core
### Acquire Baobab source / destination uids from parent line
getBaobabSourceUid = lambda x: x.getSourceUid()
getBaobabSourceUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationUid = lambda x: x.getDestinationUid()
getBaobabDestinationUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceSectionUid = lambda x: x.getSourceSectionUid()
getBaobabSourceSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationSectionUid = lambda x: x.getDestinationSectionUid()
getBaobabDestinationSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourcePaymentUid = lambda x: x.getSourcePaymentUid()
getBaobabSourcePaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationPaymentUid = lambda x: x.getDestinationPaymentUid()
getBaobabDestinationPaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceFunctionUid = lambda x: x.getSourceFunctionUid()
getBaobabSourceFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationFunctionUid = lambda x: x.getDestinationFunctionUid()
getBaobabDestinationFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceProjectUid = lambda x: x.getSourceProjectUid()
getBaobabSourceProjectUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationProjectUid = lambda x: x.getDestinationProjectUid()
getBaobabDestinationProjectUid__roles__ = PermissionRole(Permissions.View)
# -*- coding: utf-8 -*-
##############################################################################
#
# 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.
#
##############################################################################
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5.Document.Movement import Movement
from Products.ERP5.Document.ImmobilisationMovement import ImmobilisationMovement
from inspect import getargspec
from Products.ERP5Type.Base import Base
edit_args_list = getargspec(Base._edit).args
class DeliveryLine(Movement, XMLMatrix, ImmobilisationMovement):
"""
A DeliveryLine object allows to implement lines in
Deliveries (packing list, order, invoice, etc.)
It may include a price (for insurance, for customs, for invoices,
for orders)
"""
meta_type = 'ERP5 Delivery Line'
portal_type = 'Delivery Line'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
, PropertySheet.SortIndex
)
# Declarative interfaces
zope.interface.implements(interfaces.IDivergenceController,)
# Multiple inheritance definition
updateRelatedContent = XMLMatrix.updateRelatedContent
# Force in _edit to modify variation_base_category_list first
def _edit(self, edit_order=(), **kw):
# XXX FIXME For now, special cases are handled in _edit methods in many
# documents : DeliveryLine, DeliveryCell ... Ideally, to prevent code
# duplication, it should be handled in a _edit method present only in
# Amount.py
# If variations and resources are set at the same time, resource must be
# set before any variation.
before_order = ('resource', 'resource_value',
'variation_base_category_list',
'variation_category_list')
before_kw = {k: kw.pop(k) for k in before_order if k in kw}
if before_kw:
before_kw.update((k, kw[k]) for k in edit_args_list if k in kw)
Base._edit(self, edit_order=before_order, **before_kw)
if kw:
Movement._edit(self, edit_order=edit_order, **kw)
# We must check if the user has changed the resource of particular line
security.declareProtected( Permissions.ModifyPortalContent, 'edit' )
def edit(self, REQUEST=None, force_update = 0, reindex_object=1, **kw):
return self._edit(REQUEST=REQUEST, force_update=force_update, reindex_object=reindex_object, **kw)
security.declareProtected(Permissions.AccessContentsInformation,
'isAccountable')
def isAccountable(self):
"""To avoid duplicate docstring. Please read movement interface."""
return self.getParentValue().isAccountable() and (not self.hasCellContent())
security.declareProtected(Permissions.AccessContentsInformation,
'isMovingItem')
def isMovingItem(self, item):
type_based_script = self._getTypeBasedMethod('isMovingItem')
if type_based_script:
return type_based_script(item)
return self.isAccountable()
def _getTotalPrice(self, default=0.0, context=None, fast=0):
"""
Returns the total price for this line, this line contains, or the cells it contains.
if hasLineContent: return sum of lines total price
if hasCellContent: return sum of cells total price
else: return quantity * price
if fast argument is true, inventory API will be used.
"""
if fast:
kw = {}
kw['section_uid'] = self.getDestinationSectionUid()
kw['stock.explanation_uid'] = self.getExplanationUid()
kw['relative_url'] = ( '%s/%%' % (
self.getRelativeUrl().replace('_', '\\_')),
self.getRelativeUrl() )
kw['only_accountable'] = False
return self.getPortalObject().portal_simulation.getInventoryAssetPrice(**kw)
if self.hasLineContent():
meta_type = self.meta_type
return sum(l.getTotalPrice(context=context)
for l in self.objectValues() if l.meta_type==meta_type)
elif not self.hasCellContent(base_id='movement'):
return Movement._getTotalPrice(self, default=default, context=context)
return sum(cell.getTotalPrice(default=0.0, context=context)
for cell in self.getCellValueList())
security.declareProtected( Permissions.AccessContentsInformation,
'getTotalQuantity')
def getTotalQuantity(self, fast=0):
"""
Returns the quantity if no cell or the total quantity if cells
if hasLineContent: return sum of lines total quantity
if hasCellContent: return sum of cells total quantity
else: return quantity
if fast argument is true, inventory API will be used.
"""
if fast:
kw = {}
kw['section_uid'] = self.getDestinationSectionUid()
kw['stock.explanation_uid'] = self.getExplanationUid()
kw['relative_url'] = ( '%s/%%' % (
self.getRelativeUrl().replace('_', '\\_')),
self.getRelativeUrl() )
kw['only_accountable'] = False
return self.getPortalObject().portal_simulation.getInventory(**kw)
base_id = 'movement'
if self.hasLineContent():
meta_type = self.meta_type
return sum(l.getTotalQuantity() for l in
self.objectValues() if l.meta_type==meta_type)
elif self.hasCellContent(base_id=base_id):
return sum([cell.getQuantity() for cell in self.getCellValueList()])
return self.getQuantity()
security.declareProtected(Permissions.AccessContentsInformation,
'hasLineContent')
def hasLineContent(self):
"""Return true if the object contains lines.
This method only checks the first sub line because all sub
lines should be same meta type in reality if we have line
inside line.
"""
return len(self) != 0 and self.objectValues()[0].meta_type == self.meta_type
security.declareProtected(Permissions.AccessContentsInformation,
'hasCellContent')
def hasCellContent(self, base_id='movement'):
"""Return true if the object contains cells.
"""
# Do not use XMLMatrix.hasCellContent, because it can generate
# inconsistency in catalog
# Exemple: define a line and set the matrix cell range, but do not create
# cell.
# Line was in this case consider like a movement, and was catalogued.
# But, getVariationText of the line was not empty.
# So, in ZODB, resource as without variation, but in catalog, this was
# the contrary...
cell_range = XMLMatrix.getCellRange(self, base_id=base_id)
return (cell_range is not None and len(cell_range) > 0)
# DeliveryLine can be a movement when it does not content any cell and
# matrix cell range is not empty.
# Better implementation is needed.
# We want to define a line without cell, defining a variated resource.
# If we modify the cell range, we need to move the quantity to a new
# cell, which define the same variated resource.
# return XMLMatrix.hasCellContent(self, base_id=base_id)
security.declareProtected( Permissions.AccessContentsInformation,
'isMovement' )
def isMovement(self):
"""
returns true is the object contains no submovement (line or cell)
"""
object_list = self.objectValues()
if object_list:
portal_type = self.getPortalObject().getPortalMovementTypeList()
for ob in object_list:
if ob.getPortalType() in portal_type:
return False
return True
security.declareProtected(Permissions.AccessContentsInformation, 'getMovedItemUidList')
def getMovedItemUidList(self):
"""This method returns an uid list of items
"""
return [item.getUid() for item in self.getAggregateValueList() \
if self.isMovingItem(item)]
security.declareProtected( Permissions.AccessContentsInformation, 'getCellValueList' )
def getCellValueList(self, base_id='movement'):
"""
This method can be overriden
"""
return XMLMatrix.getCellValueList(self, base_id=base_id)
security.declareProtected( Permissions.AccessContentsInformation, 'getCell' )
def getCell(self, *kw , **kwd):
"""
This method can be overriden
"""
if 'base_id' not in kwd:
kwd['base_id'] = 'movement'
return XMLMatrix.getCell(self, *kw, **kwd)
security.declareProtected( Permissions.ModifyPortalContent, 'newCell' )
def newCell(self, *kw, **kwd):
"""
This method creates a new cell
"""
if 'base_id' not in kwd:
kwd['base_id'] = 'movement'
return XMLMatrix.newCell(self, *kw, **kwd)
def applyToDeliveryLineRelatedMovement(self, portal_type='Simulation Movement', method_id = 'expand'):
# Find related in simulation
for my_simulation_movement in self.getDeliveryRelatedValueList(
portal_type = 'Simulation Movement'):
# And apply
getattr(my_simulation_movement.getObject(), method_id)()
for c in self.objectValues(portal_type='Delivery Cell'):
for my_simulation_movement in c.getDeliveryRelatedValueList(
portal_type = 'Simulation Movement'):
# And apply
getattr(my_simulation_movement.getObject(), method_id)()
def reindexObject(self, *k, **kw):
"""Reindex children"""
self.recursiveReindexObject(*k, **kw)
security.declareProtected(Permissions.AccessContentsInformation, 'getInventoriatedQuantity')
def getInventoriatedQuantity(self):
"""
"""
return Movement.getInventoriatedQuantity(self)
# security.declarePrivate('_checkConsistency')
# def _checkConsistency(self, fixit=0, mapped_value_property_list = ('quantity', 'price')):
# """
# Check the constitency of transformation elements
# """
# error_list = XMLMatrix._checkConsistency(self, fixit=fixit)
#
# # First quantity
# # We build an attribute equality and look at all cells
# q_constraint = Constraint.AttributeEquality(
# domain_base_category_list = self.getVariationBaseCategoryList(),
# predicate_operator = 'SUPERSET_OF',
# mapped_value_property_list = mapped_value_property_list )
# for k in self.getCellKeys(base_id = 'movement'):
# kw={}
# kw['base_id'] = 'movement'
# c = self.getCell(*k, **kw)
# if c is not None:
# predicate_value = []
# for p in k:
# if p is not None: predicate_value += [p]
# q_constraint.edit(predicate_value_list = predicate_value)
# if fixit:
# error_list += q_constraint.fixConsistency(c)
# else:
# error_list += q_constraint.checkConsistency(c)
# if list(c.getVariationCategoryList()) != predicate_value:
# error_message = "Variation %s but sould be %s" % (c.getVariationCategoryList(),predicate_value)
# if fixit:
# c.setVariationCategoryList(predicate_value)
# error_message += " (Fixed)"
# error_list += [(c.getRelativeUrl(), 'VariationCategoryList inconsistency', 100, error_message)]
#
# return error_list
security.declareProtected(Permissions.AccessContentsInformation,
'getRootDeliveryValue')
def getRootDeliveryValue(self):
"""
Returns the root delivery responsible of this line
"""
return self.getParentValue().getRootDeliveryValue()
security.declareProtected(Permissions.ModifyPortalContent,
'updateSimulationDeliveryProperties')
def updateSimulationDeliveryProperties(self, movement_list = None):
"""
Set properties delivery_ratio and delivery_error for each
simulation movement in movement_list (all movements by default),
according to this delivery calculated quantity
"""
parent = self.getParentValue()
if parent is not None:
parent.updateSimulationDeliveryProperties(movement_list, self)
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self, item, container):
"if the container is a line too, reindex it"
if self.meta_type == container.meta_type:
container.reindexObject()
return Movement.manage_afterAdd(self, item, container)
security.declarePrivate('manage_beforeDelete')
def manage_beforeDelete(self, item, container):
"if the container is a line too, reindex it"
if self.meta_type == container.meta_type:
container.reindexObject()
return Movement.manage_beforeDelete(self, item, container)
# divergence support with solving
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self):
"""Returns true if the delivery line is divergent, or if any contained
cell is divergent.
"""
return bool(self.getDivergenceList())
security.declareProtected(Permissions.AccessContentsInformation, 'getDivergenceList')
def getDivergenceList(self):
"""Returns a list of messages that contains the divergences for that line
and the cells it may contain.
"""
if self.hasCellContent():
divergence_list = []
for cell in self.objectValues(portal_type=self.getPortalObject()
.getPortalDeliveryMovementTypeList()):
divergence_list += cell.getDivergenceList()
return divergence_list
else:
return Movement.getDivergenceList(self)
def _distributePropertyToSimulation(self, decision):
"""Distributes property from self to all related simulation movements
AKA - accept decision"""
for simulation_movement in self.getDeliveryRelatedValueList(
portal_type='Simulation Movement'):
simulation_movement.edit(**{
decision.divergence.tested_property:
self.getProperty(decision.divergence.tested_property)
})
def _updatePropertyFromSimulation(self, decision_list):
"""Update property from simulation
'Stolen' from Products.ERP5.Document.DeliveryBuilder._solveDivergence
Another possibility is to just simply copy properties or, in case of
quantity, add from all simulation movements.
"""
simulation_movement_list = self.getDeliveryRelatedValueList(
portal_type="Simulation Movement")
business_link = simulation_movement_list[0].getCausalityValue()
delivery = self.getExplanationValue()
delivery_portal_type = delivery.getPortalType()
delivery_line_portal_type = self.getPortalType()
# we need to find only one matching delivery builder
for delivery_builder in business_link.getDeliveryBuilderValueList():
if delivery_builder.getDeliveryPortalType() == \
delivery_portal_type and \
delivery_builder.getDeliveryLinePortalType() == \
delivery_line_portal_type:
break
else:
raise ValueError('No builder found')
self.edit(quantity=0) # adoption have to 'rebuild' delivery line
movement_type_list = (delivery_builder.getDeliveryLinePortalType(),
delivery_builder.getDeliveryCellPortalType())
# Collect
root_group_node = delivery_builder.collectMovement(
simulation_movement_list)
divergence_list = [decision.divergence for decision in decision_list]
# Build
portal = self.getPortalObject()
delivery_module = getattr(portal, delivery_builder.getDeliveryModule())
delivery_to_update_list = [delivery]
delivery_list = delivery_builder._processDeliveryGroup(
delivery_module,
root_group_node,
delivery_builder.getDeliveryMovementGroupList(),
delivery_to_update_list=delivery_to_update_list,
divergence_list=divergence_list,
force_update=1)
new_delivery_list = [x for x in delivery_list if x != delivery]
if new_delivery_list:
raise ValueError('No new deliveries shall be created')
# Then, we should re-apply quantity divergence according to 'Do
# nothing' quantity divergence list because all quantity are already
# calculated in adopt prevision phase.
quantity_dict = {}
for divergence in self.getDivergenceList():
if divergence.getProperty('divergence_scope') != 'quantity' or \
divergence in divergence_list:
continue
s_m = divergence.getProperty('simulation_movement')
delivery_movement = s_m.getDeliveryValue()
assert delivery_movement == self
quantity_gap = divergence.getProperty('decision_value') - \
divergence.getProperty('prevision_value')
delivery_movement.setQuantity(delivery_movement.getQuantity() + \
quantity_gap)
quantity_dict[s_m] = \
divergence.getProperty('decision_value')
# Finally, recalculate delivery_ratio
#
# Here, created/updated movements are not indexed yet. So we try to
# gather delivery relations from simulation movements.
delivery_dict = {}
for s_m in simulation_movement_list:
delivery_path = s_m.getDelivery()
delivery_dict[delivery_path] = \
delivery_dict.get(delivery_path, []) + \
[s_m]
for s_m_list_per_movement in delivery_dict.values():
total_quantity = sum([quantity_dict.get(s_m, s_m.getQuantity()) \
for s_m in s_m_list_per_movement])
if total_quantity != 0.0:
for s_m in s_m_list_per_movement:
delivery_ratio = quantity_dict.get(s_m, s_m.getQuantity()) \
/ total_quantity
s_m.edit(delivery_ratio=delivery_ratio)
else:
for s_m in s_m_list_per_movement:
delivery_ratio = 1.0 / len(s_m_list_per_movement)
s_m.edit(delivery_ratio=delivery_ratio)
security.declareProtected(Permissions.ModifyPortalContent, 'solve')
def solve(self, decision_list):
"""Solves line according to decision list
"""
simulation_tool = self.getPortalObject().portal_simulation
solveMovement = simulation_tool.solveMovement
solve_result_list = []
# accept + split
for decision in [q for q in decision_list if q.decision != 'adopt']:
if decision.decision == 'accept':
# accepting - in case of passed DeliverySolver use it, otherwise
# simply copy values to simulation
if not decision.delivery_solver_name:
self._distributePropertyToSimulation(decision)
solveMovement(self, decision.delivery_solver_name,
decision.target_solver_name, divergence_list = [decision.divergence])
elif decision.decision == 'split':
solveMovement(self, decision.delivery_solver_name,
decision.target_solver_name, **decision.split_kw)
else: # aka - do nothing
pass
# adopt
adopt_decision_list = [q for q in decision_list \
if q.decision == 'adopt']
if adopt_decision_list:
self._updatePropertyFromSimulation(adopt_decision_list)
##############################################################################
#
# Copyright (c) 2002-2005 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 AccessControl import ClassSecurityInfo
from AccessControl.PermissionRole import PermissionRole
from Acquisition import aq_base
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine
from Products.ERP5.Document.Movement import Movement
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
class InventoryLine(DeliveryLine):
"""
An Inventory Line describe the inventory of a resource, by variations.
"""
meta_type = 'ERP5 Inventory Line'
portal_type = 'Inventory Line'
add_permission = Permissions.AddPortalContent
isInventoryMovement = ConstantGetter('isInventoryMovement', value=True)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.InventoryMovement
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
)
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalInventory')
def getTotalInventory(self):
"""
Returns the inventory if no cell or the total inventory if cells
"""
if not self.hasCellContent():
return self.getInventory()
else:
total_quantity = 0.0
for cell in self.getCellValueList(base_id='movement'):
if cell.getInventory() is not None:
total_quantity += cell.getInventory()
return total_quantity
security.declareProtected(Permissions.AccessContentsInformation,
'getQuantity')
def getQuantity(self):
"""
Computes a quantity which allows to reach inventory
"""
if not self.hasCellContent():
# First check if quantity already exists
quantity = self._baseGetQuantity()
if quantity not in (0.0,0,None):
return quantity
# Make sure inventory is defined somewhere (here or parent)
inventory = getattr(aq_base(self), 'inventory', None)
if inventory is not None:
return inventory
return quantity
else:
return None
# Inventory cataloging
security.declareProtected(Permissions.AccessContentsInformation,
'getConvertedInventory')
def getConvertedInventory(self):
"""
provides a default inventory value - None since
no inventory was defined.
"""
return self.getInventory() # XXX quantity unit is missing
# Required for indexing
security.declareProtected(Permissions.AccessContentsInformation,
'getInventoriatedQuantity')
def getInventoriatedQuantity(self):
"""
Take into account efficiency in converted target quantity
"""
return Movement.getInventoriatedQuantity(self)
# XXX: Dirty but required for erp5_banking_core
getBaobabSourceUid = lambda x: x.getSourceUid()
getBaobabSourceUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationUid = lambda x: x.getDestinationUid()
getBaobabDestinationUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceSectionUid = lambda x: x.getSourceSectionUid()
getBaobabSourceSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationSectionUid = lambda x: x.getDestinationSectionUid()
getBaobabDestinationSectionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourcePaymentUid = lambda x: x.getSourcePaymentUid()
getBaobabSourcePaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationPaymentUid = lambda x: x.getDestinationPaymentUid()
getBaobabDestinationPaymentUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceFunctionUid = lambda x: x.getSourceFunctionUid()
getBaobabSourceFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationFunctionUid = lambda x: x.getDestinationFunctionUid()
getBaobabDestinationFunctionUid__roles__ = PermissionRole(Permissions.View)
getBaobabSourceProjectUid = lambda x: x.getSourceProjectUid()
getBaobabSourceProjectUid__roles__ = PermissionRole(Permissions.View)
getBaobabDestinationProjectUid = lambda x: x.getDestinationProjectUid()
getBaobabDestinationProjectUid__roles__ = PermissionRole(Permissions.View)
##############################################################################
#
# Copyright (c) 2002, 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
# Romain Courteaud <romain@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 AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Utils import deprecated
from Products.ERP5.Document.Delivery import Delivery
from warnings import warn
class Order(Delivery):
# CMF Type Definition
meta_type = 'ERP5 Order'
portal_type = 'Order'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Reference
, PropertySheet.TradeCondition
, PropertySheet.Comment
, PropertySheet.Order
)
security.declareProtected(Permissions.AccessContentsInformation, \
'isAccountable')
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
return 0
def getTotalPrice(self, **kw) :
"""Returns the total price for this Order.
If base_contribution is passed, the trade model lines will be used to
include movements that will be generated.
"""
if kw.get('fast'):
kw['only_accountable'] = False
rounding = kw.get('rounding')
if kw.get('base_contribution') is None:
kw.setdefault('portal_type', self.getPortalOrderMovementTypeList())
return Delivery.getTotalPrice(self, **kw)
else:
# Find amounts from the result of getAggregatedAmountList.
# Call getAggregatedAmountList and sum all the amounts which
# base_contribution category is matched with.
from Products.ERP5.PropertySheet.TradeModelLine import TARGET_LEVEL_MOVEMENT
trade_condition = self.getSpecialiseValue()
if trade_condition is None:
# We cannot find any amount so that the result is 0.
return 0
base_contribution = kw.get('base_contribution')
if isinstance(base_contribution, (tuple, list)):
base_contribution_list = base_contribution
else:
base_contribution_list = (base_contribution,)
base_contribution_value_list = []
portal_categories = self.portal_categories
for relative_url in base_contribution_list:
base_contribution_value = portal_categories.getCategoryValue(relative_url)
if base_contribution_value is not None:
base_contribution_value_list.append(base_contribution_value)
if not base_contribution_value_list:
# We cannot find any amount so that the result is 0.
return 0
current_aggregated_amount_list = trade_condition.getAggregatedAmountList(self, rounding=rounding, force_create_line=True)
trade_model_line = self.newContent(temp_object=True,
portal_type='Trade Model Line',
id='_temp_' + self.getId(), notify_workflow=False)
# prevent invoking interaction workflows.
trade_model_line.portal_type = ''
trade_model_line.edit(target_level=TARGET_LEVEL_MOVEMENT, price=1,
efficiency=1, quantity=None,
base_application_value_list=base_contribution_value_list)
aggregated_amount_list = trade_model_line._getAggregatedAmountList(
self,
movement_list=self.getMovementList(),
current_aggregated_amount_list=current_aggregated_amount_list,
rounding=rounding)
return aggregated_amount_list.getTotalPrice()
def getTotalQuantity(self, **kw) :
"""Returns the total quantity for this Order. """
if 'portal_type' not in kw:
kw['portal_type'] = self.getPortalObject() \
.getPortalOrderMovementTypeList()
if kw.get('fast'):
kw['only_accountable'] = False
return Delivery.getTotalQuantity(self, **kw)
@deprecated
def applyToOrderRelatedMovement(self, method_id='expand', **kw):
# WARNING: does not work if it was not catalogued immediately
# 'order' category is deprecated. it is kept for compatibility.
for m in self.getMovementList():
for my_simulation_movement in m.getDeliveryRelatedValueList(
portal_type='Simulation Movement') or \
m.getOrderRelatedValueList(
portal_type='Simulation Movement'):
getattr(my_simulation_movement, method_id)(**kw)
##############################################################################
#
# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
# Jerome Perrin <jerome@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 AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine
class TaxLine(DeliveryLine):
""" Tax Line
"""
meta_type = 'ERP5 Tax Line'
portal_type = 'Tax Line'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
, PropertySheet.Reference
, PropertySheet.SortIndex
)
security.declareProtected(Permissions.AccessContentsInformation,
'isAccountable')
def isAccountable(self):
"""Return true if the parent is accountable and
not an accounting transaction.
NOTE: this is because, if the parent is an accounting transaction,
the accounting is done with another accounting transaction line,
so making tax lines accountable would duplicate the accounting.
"""
delivery = self.getParentValue()
if delivery.isAccountable():
portal = delivery.getPortalObject()
type_list = portal.getPortalAccountingTransactionTypeList()
return delivery.getPortalType() not in type_list
return 0
security.declareProtected(Permissions.AccessContentsInformation,
'hasCellContent')
def hasCellContent(self, base_id='movement'):
"""Tax line does not contain cell
"""
return 0
security.declareProtected(Permissions.AccessContentsInformation,
'isMovement' )
def isMovement(self):
"""Tax lines are movements
"""
return 1
...@@ -99,8 +99,7 @@ portal_invoice_movement_type_list = ( ...@@ -99,8 +99,7 @@ portal_invoice_movement_type_list = (
'Pay Sheet Cell', 'Pay Sheet Cell',
) )
portal_tax_movement_type_list = ( 'Tax Line', 'Discount Line', portal_tax_movement_type_list = ( 'Pay Sheet Line', )
'Pay Sheet Line', )
portal_order_movement_type_list = ( portal_order_movement_type_list = (
'Purchase Order Line', 'Purchase Order Line',
......
...@@ -34,9 +34,9 @@ class InventoryInteractor(Interactor): ...@@ -34,9 +34,9 @@ class InventoryInteractor(Interactor):
subdocuments are modified. subdocuments are modified.
""" """
def install(self): def install(self):
from Products.ERP5.Document.InventoryLine import InventoryLine from erp5.component.document.InventoryLine import InventoryLine
self.on(InventoryLine.reindexObject).doAfter(self.reindexInventory) self.on(InventoryLine.reindexObject).doAfter(self.reindexInventory)
from Products.ERP5.Document.InventoryCell import InventoryCell from erp5.component.document.InventoryCell import InventoryCell
self.on(InventoryCell.reindexObject).doAfter(self.reindexInventory) self.on(InventoryCell.reindexObject).doAfter(self.reindexInventory)
def reindexInventory(self, method_call_object, *args, **kw): def reindexInventory(self, method_call_object, *args, **kw):
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
# #
############################################################################## ##############################################################################
""" """
Products.ERP5.interfaces.business_process erp5.component.interface.IBusinessProcess
""" """
from zope.interface import Interface from zope.interface import Interface
......
...@@ -37,11 +37,11 @@ implements_tuple_list = [ ...@@ -37,11 +37,11 @@ implements_tuple_list = [
(('erp5.component.document.RoleDefinition', 'RoleDefinition'), 'ILocalRoleGenerator'), (('erp5.component.document.RoleDefinition', 'RoleDefinition'), 'ILocalRoleGenerator'),
(('erp5.component.document.BusinessLink','BusinessLink'), 'IBusinessLink'), (('erp5.component.document.BusinessLink','BusinessLink'), 'IBusinessLink'),
(('erp5.component.document.BusinessLink','BusinessLink'), 'ICategoryAccessProvider'), (('erp5.component.document.BusinessLink','BusinessLink'), 'ICategoryAccessProvider'),
(('Products.ERP5.Document.TradeCondition','TradeCondition'), 'IAmountGenerator'), (('erp5.component.document.TradeCondition','TradeCondition'), 'IAmountGenerator'),
(('Products.ERP5.Document.TradeModelCell','TradeModelCell'), 'IAmountGenerator'), (('erp5.component.document.TradeModelCell','TradeModelCell'), 'IAmountGenerator'),
(('Products.ERP5.Document.TradeModelCell','TradeModelCell'), 'IVariated'), (('erp5.component.document.TradeModelCell','TradeModelCell'), 'IVariated'),
(('Products.ERP5.Document.TradeModelLine','TradeModelLine'), 'IAmountGenerator'), (('erp5.component.document.TradeModelLine','TradeModelLine'), 'IAmountGenerator'),
(('Products.ERP5.Document.TradeModelLine','TradeModelLine'), 'IVariated'), (('erp5.component.document.TradeModelLine','TradeModelLine'), 'IVariated'),
(('erp5.component.document.TradeModelPath','TradeModelPath'), 'IArrowBase'), (('erp5.component.document.TradeModelPath','TradeModelPath'), 'IArrowBase'),
(('Products.ERP5.Document.Transformation','Transformation'), 'IAmountGenerator'), (('Products.ERP5.Document.Transformation','Transformation'), 'IAmountGenerator'),
(('Products.ERP5.Document.Transformation','Transformation'), 'IVariated'), (('Products.ERP5.Document.Transformation','Transformation'), 'IVariated'),
......
...@@ -2903,13 +2903,6 @@ class TestOrder(TestOrderMixin, ERP5TypeTestCase): ...@@ -2903,13 +2903,6 @@ class TestOrder(TestOrderMixin, ERP5TypeTestCase):
resource_value=resource, resource_value=resource,
quantity=10, quantity=10,
price=3) price=3)
# see TODO above
#tax_line = order.newContent(portal_type='Tax Line',
# resource_value=tax,
# quantity=30,
# price=.26)
order.confirm() order.confirm()
self.tic() self.tic()
......
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