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 @@
from AccessControl import ClassSecurityInfo
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
......
......@@ -27,7 +27,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5.Document.DeliveryRootSimulationRule \
from erp5.component.document.DeliveryRootSimulationRule \
import DeliveryRootSimulationRule, DeliveryRuleMovementGenerator
class AccountingTransactionRootSimulationRule(DeliveryRootSimulationRule):
......
......@@ -30,7 +30,7 @@ from UserDict import UserDict
from AccessControl import ClassSecurityInfo
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 Products.ZSQLCatalog.SQLCatalog import Query
import types
......
......@@ -32,7 +32,7 @@ from Products.ERP5Type import Permissions
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
from erp5.component.document.AccountingTransactionLine import \
AccountingTransactionLine
from Products.ERP5.Document.InventoryLine import InventoryLine
from erp5.component.document.InventoryLine import InventoryLine
class BalanceTransactionLine(AccountingTransactionLine, InventoryLine):
......
......@@ -30,7 +30,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5.Document.DeliveryRootSimulationRule \
from erp5.component.document.DeliveryRootSimulationRule \
import DeliveryRootSimulationRule, DeliveryRuleMovementGenerator
class InvoiceRootSimulationRule(DeliveryRootSimulationRule):
......
......@@ -32,7 +32,7 @@ import unittest
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from erp5.component.test.testProductionOrderApparel import TestProductionOrderApparelMixin
from Products.ERP5.tests.testProductionPackingList import TestProductionDelivery
from erp5.component.test.testProductionPackingList import TestProductionDelivery
class TestProductionDeliveryApparel(TestProductionOrderApparelMixin,
TestProductionDelivery, ERP5TypeTestCase):
......
erp5_core
\ No newline at end of file
erp5_core
erp5_trade
\ No newline at end of file
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
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
class CashContainer(BaobabMixin, Container):
......
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
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 zope.interface import implements
......
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
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 zope.interface import implements
......
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
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
......
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
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 zope.interface import implements
......
......@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
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
class CashInventoryLine(InventoryLine, CashDeliveryLine):
......
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
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 zope.interface import implements
......
......@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine
from erp5.component.document.DeliveryLine import DeliveryLine
class BudgetTransaction(DeliveryLine):
"""
......
erp5_base
\ No newline at end of file
erp5_base
erp5_trade
\ No newline at end of file
......@@ -33,7 +33,7 @@ from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5.Document.Movement import Movement
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):
"""
......
......@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell
from erp5.component.document.DeliveryCell import DeliveryCell
class InvoiceCell(DeliveryCell):
"""
......
......@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine
from erp5.component.document.DeliveryLine import DeliveryLine
class InvoiceLine(DeliveryLine):
"""
......
......@@ -5,7 +5,7 @@
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5.Document.DeliveryLine import DeliveryLine
from erp5.component.document.DeliveryLine import DeliveryLine
class ImplicitItemMovement(DeliveryLine):
......
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell
from erp5.component.document.DeliveryCell import DeliveryCell
class ManufacturingExecutionCell(DeliveryCell):
"""
......
......@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine
from erp5.component.document.DeliveryLine import 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
class ProductionSimulationRule(DeliverySimulationRule):
......
......@@ -30,7 +30,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell
from erp5.component.document.DeliveryCell import DeliveryCell
class ProductionReportCell(DeliveryCell):
"""
......
......@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine
from erp5.component.document.DeliveryLine import DeliveryLine
class ProductionReportLine(DeliveryLine):
"""
......
......@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo
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
class PaySheetModel(TradeCondition, XMLMatrix):
......
......@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo
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
class PaySheetModelCell(TradeModelCell):
......
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.TradeModelLine import TradeModelLine
from erp5.component.document.TradeModelLine import TradeModelLine
class PaySheetModelLine(TradeModelLine):
"""
......
......@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell
from erp5.component.document.DeliveryCell import DeliveryCell
class PaySheetModelSlice(DeliveryCell):
"""
......
erp5_trade
\ No newline at end of file
......@@ -26,7 +26,7 @@
#
##############################################################################
from Products.ERP5.Document.InvoiceTransactionSimulationRule import (InvoiceTransactionSimulationRule,
from erp5.component.document.InvoiceTransactionSimulationRule import (InvoiceTransactionSimulationRule,
InvoiceTransactionRuleMovementGenerator)
class InventoryAssetPriceAccountingRuleMovementGenerator(InvoiceTransactionRuleMovementGenerator):
......
......@@ -35,6 +35,7 @@ from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Path import Path
from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5.ExplanationCache import _getExplanationCache
from erp5.component.interface.IBusinessLink import IBusinessLink
import zope.interface
......@@ -93,7 +94,7 @@ class BusinessLink(Path, Predicate):
)
# Declarative interfaces
zope.interface.implements(interfaces.IBusinessLink,
zope.interface.implements(IBusinessLink,
interfaces.IPredicate,
)
......
......@@ -36,6 +36,7 @@ from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5.Document.Path import Path
from Products.ERP5.ExplanationCache import _getExplanationCache, _getBusinessLinkClosure
from Products.ERP5.MovementCollectionDiff import _getPropertyAndCategoryList
from erp5.component.interface.IBusinessProcess import IBusinessProcess
import zope.interface
......@@ -116,7 +117,7 @@ class BusinessProcess(Path, XMLObject):
)
# Declarative interfaces
zope.interface.implements(interfaces.IBusinessProcess,
zope.interface.implements(IBusinessProcess,
interfaces.IArrowBase)
# 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
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell
from erp5.component.document.DeliveryCell import DeliveryCell
class ContainerCell(DeliveryCell):
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
meta_type = 'ERP5 Container Cell'
portal_type = 'Container Cell'
isCell = 1
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
meta_type = 'ERP5 Container Cell'
portal_type = 'Container Cell'
isCell = 1
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# 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 properties
property_sheets = ( PropertySheet.Base
, PropertySheet.CategoryCore
, PropertySheet.Arrow
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
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
"""
# Never accountable
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
"""
# Never accountable
return 0
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self):
"""Return True if this movement diverges from the its simulation.
Container Cells are never divergent.
"""
return False
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self):
"""Return True if this movement diverges from the its simulation.
Container Cells are never divergent.
"""
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
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine
from erp5.component.document.DeliveryLine import DeliveryLine
class ContainerLine(DeliveryLine):
"""
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)
"""
"""
A DeliveryLine object allows to implement lines in
Deliveries (packing list, order, invoice, etc.)
meta_type = 'ERP5 Container Line'
portal_type = 'Container Line'
It may include a price (for insurance, for customs, for invoices,
for orders)
"""
meta_type = 'ERP5 Container Line'
portal_type = 'Container Line'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# 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
)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
)
# Cell Related
security.declareProtected( Permissions.ModifyPortalContent, 'newCellContent' )
def newCellContent(self, id, portal_type='Container Cell', **kw):
"""Overriden to specify default portal type
"""
return self.newContent(id=id, portal_type=portal_type, **kw)
# Cell Related
security.declareProtected( Permissions.ModifyPortalContent, 'newCellContent' )
def newCellContent(self, id, portal_type='Container Cell', **kw): # pylint: disable=redefined-builtin
"""Overriden to specify default portal type
"""
return self.newContent(id=id, portal_type=portal_type, **kw)
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
"""
# Never accountable
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
"""
# Never accountable
return 0
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self):
"""Return True if this movement diverges from the its simulation.
Container Lines are never divergent.
"""
return False
security.declareProtected(Permissions.AccessContentsInformation, 'isDivergent')
def isDivergent(self):
"""Return True if this movement diverges from the its simulation.
Container Lines are never divergent.
"""
return False
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity')
def getTotalQuantity(self):
"""
Returns the quantity if no cell or the total quantity if cells
"""
base_id = 'movement'
if not self.hasCellContent(base_id=base_id):
return self.getQuantity()
return sum(cell.getQuantity() for cell in
self.getCellValueList(base_id=base_id))
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity')
def getTotalQuantity(self, *args, **kw):
"""
Returns the quantity if no cell or the total quantity if cells
"""
base_id = 'movement'
if not self.hasCellContent(base_id=base_id):
return self.getQuantity()
return sum(cell.getQuantity() for cell in
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):
if temp_constructor is None:
def temp_constructor(self, id, *args, **kw):
return self.newContent(temp_object=True, portal_type='Movement',
id=id, *args, **kw)
temp_constructor = lambda self, id, *args, **kw: self.newContent(
temp_object=True, portal_type='Movement',
id=id, *args, **kw)
stop_date = self.getStopDate()
stock_object_list = []
......@@ -199,8 +199,8 @@ class Inventory(Delivery):
__order_id_counter_list = [0]
def getOrderIdCounter():
value = __order_id_counter_list[0]
__order_id_counter_list[0] = value + 1
value = __order_id_counter_list[0] # pylint: disable=cell-var-from-loop
__order_id_counter_list[0] = value + 1 # pylint: disable=cell-var-from-loop
return value
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
from Products.ERP5Type import Permissions, PropertySheet
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):
"""
An InventoryCell allows to define specific inventory
for each variation of a resource in an inventory line.
"""
"""
An InventoryCell allows to define specific inventory
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'
portal_type = 'Inventory Cell'
add_permission = Permissions.AddPortalContent
isInventoryMovement = ConstantGetter('isInventoryMovement', value=True)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.InventoryMovement
, PropertySheet.Task
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.InventoryMovement
, PropertySheet.Task
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalInventory')
def getTotalInventory(self):
"""
Returns the inventory, as cells are not supposed to contain more cells.
"""
return self.getInventory()
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalInventory')
def getTotalInventory(self):
"""
Returns the inventory, as cells are not supposed to contain more cells.
"""
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)
if getattr(aq_base(self), 'inventory', None) is None:
return 0.0 # No inventory defined, so no quantity
return self.getInventory()
else:
return None
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)
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
# 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
\ 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>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 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryCell import DeliveryCell
from erp5.component.document.DeliveryCell import DeliveryCell
class OrderCell(DeliveryCell):
"""
A OrderCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
"""
A OrderCell allows to define specific quantities
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'
portal_type = 'Order Cell'
isCell = 1
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# 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 properties
property_sheets = ( PropertySheet.Base
, PropertySheet.CategoryCore
, PropertySheet.Arrow
, PropertySheet.Amount
, 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)
def reindexObject(self, *k, **kw):
"""
Reindex children and simulation
"""
self.recursiveReindexObject(*k,**kw)
security.declareProtected(Permissions.AccessContentsInformation,
'isMovement')
def isMovement(self):
"""
should be considered as a movement if the parent does not have sub lines
"""
return not self.getParentValue().hasLineContent()
security.declareProtected(Permissions.AccessContentsInformation,
'isMovement')
def isMovement(self):
"""
should be considered as a movement if the parent does not have sub lines
"""
return not self.getParentValue().hasLineContent()
security.declareProtected(Permissions.AccessContentsInformation,
security.declareProtected(Permissions.AccessContentsInformation,
'getTotalPrice')
def getTotalPrice(self, default=0.0, *args, **kw):
"only return a value if self is a movement"
if not self.isMovement():
return default
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)
def getTotalPrice(self, default=0.0, *args, **kw):
"only return a value if self is a movement"
if not self.isMovement():
return default
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)
\ 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 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.DeliveryLine import DeliveryLine
from erp5.component.document.DeliveryLine import 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'
portal_type = 'Order Line'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.DublinCore
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Task
, PropertySheet.DublinCore
, PropertySheet.Arrow
, PropertySheet.Movement
, PropertySheet.Price
, PropertySheet.VariationRange
, PropertySheet.ItemAggregation
)
\ 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>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
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.Delivery import Delivery
from warnings import warn
class PackingList(Delivery):
"""
"""
Delivery/PackingList is the main document
which allows to control causality in the simulation
......@@ -58,67 +57,66 @@ class PackingList(Delivery):
- postpone delivery
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
containers.
FIXME: this method does not support packing list with 2 movements of
same resource.
"""
# build a mapping of
# (resource, variation_text) -> quantity
container_dict = defaultdict(int)
for container in self.contentValues(
portal_type=self.getPortalContainerTypeList()):
for container_line in container.contentValues(
portal_type=self.getPortalContainerLineTypeList(),):
if container_line.hasCellContent(base_id='movement'):
for container_cell in container_line.contentValues(
portal_type=self.getPortalContainerLineTypeList(),):
key = (container_cell.getResource(),
container_cell.getVariationText())
container_dict[key] += container_cell.getQuantity()
else:
key = (container_line.getResource(),
container_line.getVariationText())
container_dict[key] += container_line.getQuantity()
if not container_dict:
"""
# build a mapping of
# (resource, variation_text) -> quantity
container_dict = defaultdict(int)
for container in self.contentValues(
portal_type=self.getPortalContainerTypeList()):
for container_line in container.contentValues(
portal_type=self.getPortalContainerLineTypeList(),):
if container_line.hasCellContent(base_id='movement'):
for container_cell in container_line.contentValues(
portal_type=self.getPortalContainerLineTypeList(),):
key = (container_cell.getResource(),
container_cell.getVariationText())
container_dict[key] += container_cell.getQuantity()
else:
key = (container_line.getResource(),
container_line.getVariationText())
container_dict[key] += container_line.getQuantity()
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
# 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 True
return True
\ 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>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 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.TradeModelLine import TradeModelLine
from erp5.component.document.TradeModelLine import 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
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.Utils import deprecated
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.mixin.amount_generator import AmountGeneratorMixin
from Products.ERP5.mixin.variated import VariatedMixin
class TradeCondition(MappedValue, AmountGeneratorMixin, VariatedMixin):
"""
Trade Conditions are used to store the conditions (payment, logistic,...)
which should be applied (and used in the orders) when two companies make
business together
"""
meta_type = 'ERP5 Trade Condition'
portal_type = 'Trade Condition'
model_line_portal_type_list = ('Trade Model Line',)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
"""
Trade Conditions are used to store the conditions (payment, logistic,...)
which should be applied (and used in the orders) when two companies make
business together
"""
meta_type = 'ERP5 Trade Condition'
portal_type = 'Trade Condition'
model_line_portal_type_list = ('Trade Model Line',)
# Declarative properties
property_sheets = ( PropertySheet.Base
, 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.
)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
zope.interface.implements(interfaces.IAmountGenerator,
interfaces.IMovementGenerator,
interfaces.IMovementCollectionUpdater,)
# Declarative properties
property_sheets = ( PropertySheet.Base
, 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):
return ()
# Mapped Value implementation
# Transformation itself provides no properties or categories
def getMappedValuePropertyList(self):
return ()
security.declareProtected(Permissions.AccessContentsInformation,
'findEffectiveSpecialiseValueList')
#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.
def getMappedValueBaseCategoryList(self): # pylint: disable=arguments-differ
return ()
This algorithm uses Breadth First Search.
"""
portal_type_set = set(portal_type_list or
self.getPortalAmountGeneratorTypeList())
return [x for x in context._findEffectiveSpecialiseValueList()
if x.getPortalType() in portal_type_set]
security.declareProtected(Permissions.AccessContentsInformation,
'findEffectiveSpecialiseValueList')
#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.
security.declareProtected(Permissions.AccessContentsInformation,
'getAggregatedAmountList')
def getAggregatedAmountList(self, *args, **kw):
"""
"""
# 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)
This algorithm uses Breadth First Search.
"""
portal_type_set = set(portal_type_list or
self.getPortalAmountGeneratorTypeList())
return [x for x in context._findEffectiveSpecialiseValueList()
if x.getPortalType() in portal_type_set]
#deprecated # XXX
security.declareProtected(Permissions.AccessContentsInformation,
'getEffectiveModel')
def getEffectiveModel(self, start_date=None, stop_date=None):
return _getEffectiveModel(self, start_date, stop_date)
security.declareProtected(Permissions.AccessContentsInformation,
'getAggregatedAmountList')
def getAggregatedAmountList(self, *args, **kw):
"""
"""
# 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 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.TradeModelLine import TradeModelLine
from erp5.component.document.TradeModelLine import TradeModelLine
import zope.interface
class TradeModelCell(TradeModelLine):
"""Trade Model Line
"""
meta_type = 'ERP5 Trade Model Cell'
portal_type = 'Trade Model Cell'
isCell = 1
"""Trade Model Line
"""
meta_type = 'ERP5 Trade Model Cell'
portal_type = 'Trade Model Cell'
isCell = 1
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
# interfaces.IVariated as soon as interfaces.IVariated will be zope3
zope.interface.implements(
interfaces.IAmountGenerator
)
# Declarative interfaces
# interfaces.IVariated as soon as interfaces.IVariated will be zope3
zope.interface.implements(
interfaces.IAmountGenerator
)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.SimpleItem
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Price
, PropertySheet.TradeModelLine
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.SimpleItem
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Price
, PropertySheet.TradeModelLine
, PropertySheet.Predicate
, PropertySheet.MappedValue
, PropertySheet.ItemAggregation
)
security.declareProtected( Permissions.AccessContentsInformation,
'hasCellContent' )
def hasCellContent(self, base_id='movement'):
"""A cell cannot have cell content itself.
"""
return 0
security.declareProtected( Permissions.AccessContentsInformation,
'hasCellContent' )
def hasCellContent(self, base_id='movement'):
"""A cell cannot have cell content itself.
"""
return 0
security.declareProtected(Permissions.AccessContentsInformation,
'getQuantity')
def getQuantity(self):
"""Overridden getter to return None instead 0 if undefined"""
return self._baseGetQuantity(None)
security.declareProtected(Permissions.AccessContentsInformation,
'getQuantity')
def getQuantity(self):
"""Overridden getter to return None instead 0 if undefined"""
return self._baseGetQuantity(None)
security.declareProtected(Permissions.AccessContentsInformation,
'getTotalPrice')
def getTotalPrice(self):
"""
Returns the totals price for this line
"""
quantity = self.getQuantity() or 0.0
price = self.getPrice() or 0.0
return quantity * price
security.declareProtected(Permissions.AccessContentsInformation,
'getTotalPrice')
def getTotalPrice(self):
"""
Returns the totals price for this line
"""
quantity = self.getQuantity() or 0.0
price = self.getPrice() or 0.0
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):
# Else tax provides only a ratio on amount
return ('price',)
def getMappedValueBaseCategoryList(self):
def getMappedValueBaseCategoryList(self): # pylint: disable=arguments-differ
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):
_message_id_tuple = ('message_cell_inexistance',)
@staticmethod
def _convertFromFilesystemDefinition(base_id):
def _convertFromFilesystemDefinition(base_id, *args, **kw):
"""
@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
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Path import Path
from Products.ERP5.ExplanationCache import _getExplanationCache
from erp5.component.interface.ITradeModelPath import ITradeModelPath
import zope.interface
......@@ -94,7 +95,7 @@ class TradeModelPath(Path):
# Declarative interfaces
zope.interface.implements(interfaces.ICategoryAccessProvider,
interfaces.IArrowBase,
interfaces.ITradeModelPath,
ITradeModelPath,
interfaces.IPredicate,
)
......
......@@ -27,7 +27,7 @@
#
##############################################################################
"""
Products.ERP5.interfaces.business_link
erp5.component.interface.IBusinessLink
"""
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 @@
#
##############################################################################
"""
Products.ERP5.interfaces.trade_model_path
erp5.component.interface.ITradeModelPath
"""
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.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.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
\ 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 = (
'Pay Sheet Cell',
)
portal_tax_movement_type_list = ( 'Tax Line', 'Discount Line',
'Pay Sheet Line', )
portal_tax_movement_type_list = ( 'Pay Sheet Line', )
portal_order_movement_type_list = (
'Purchase Order Line',
......
......@@ -34,9 +34,9 @@ class InventoryInteractor(Interactor):
subdocuments are modified.
"""
def install(self):
from Products.ERP5.Document.InventoryLine import InventoryLine
from erp5.component.document.InventoryLine import InventoryLine
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)
def reindexInventory(self, method_call_object, *args, **kw):
......
......@@ -27,7 +27,7 @@
#
##############################################################################
"""
Products.ERP5.interfaces.business_process
erp5.component.interface.IBusinessProcess
"""
from zope.interface import Interface
......
......@@ -37,11 +37,11 @@ implements_tuple_list = [
(('erp5.component.document.RoleDefinition', 'RoleDefinition'), 'ILocalRoleGenerator'),
(('erp5.component.document.BusinessLink','BusinessLink'), 'IBusinessLink'),
(('erp5.component.document.BusinessLink','BusinessLink'), 'ICategoryAccessProvider'),
(('Products.ERP5.Document.TradeCondition','TradeCondition'), 'IAmountGenerator'),
(('Products.ERP5.Document.TradeModelCell','TradeModelCell'), 'IAmountGenerator'),
(('Products.ERP5.Document.TradeModelCell','TradeModelCell'), 'IVariated'),
(('Products.ERP5.Document.TradeModelLine','TradeModelLine'), 'IAmountGenerator'),
(('Products.ERP5.Document.TradeModelLine','TradeModelLine'), 'IVariated'),
(('erp5.component.document.TradeCondition','TradeCondition'), 'IAmountGenerator'),
(('erp5.component.document.TradeModelCell','TradeModelCell'), 'IAmountGenerator'),
(('erp5.component.document.TradeModelCell','TradeModelCell'), 'IVariated'),
(('erp5.component.document.TradeModelLine','TradeModelLine'), 'IAmountGenerator'),
(('erp5.component.document.TradeModelLine','TradeModelLine'), 'IVariated'),
(('erp5.component.document.TradeModelPath','TradeModelPath'), 'IArrowBase'),
(('Products.ERP5.Document.Transformation','Transformation'), 'IAmountGenerator'),
(('Products.ERP5.Document.Transformation','Transformation'), 'IVariated'),
......
......@@ -2903,13 +2903,6 @@ class TestOrder(TestOrderMixin, ERP5TypeTestCase):
resource_value=resource,
quantity=10,
price=3)
# see TODO above
#tax_line = order.newContent(portal_type='Tax Line',
# resource_value=tax,
# quantity=30,
# price=.26)
order.confirm()
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