Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Rafael Monnerat
erp5
Commits
4ee585d8
Commit
4ee585d8
authored
Apr 08, 2020
by
Arnaud Fontaine
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ERP5/Document: Fix pylint warnings.
parent
d672defe
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
792 additions
and
808 deletions
+792
-808
product/ERP5/Document/DeliveryCell.py
product/ERP5/Document/DeliveryCell.py
+170
-174
product/ERP5/Document/DeliveryLine.py
product/ERP5/Document/DeliveryLine.py
+398
-403
product/ERP5/Document/InventoryCell.py
product/ERP5/Document/InventoryCell.py
+52
-54
product/ERP5/Document/InventoryLine.py
product/ERP5/Document/InventoryLine.py
+104
-106
product/ERP5/Document/OrderCell.py
product/ERP5/Document/OrderCell.py
+47
-49
product/ERP5/Document/OrderLine.py
product/ERP5/Document/OrderLine.py
+21
-22
No files found.
product/ERP5/Document/DeliveryCell.py
View file @
4ee585d8
...
@@ -35,187 +35,183 @@ from AccessControl.PermissionRole import PermissionRole
...
@@ -35,187 +35,183 @@ from AccessControl.PermissionRole import PermissionRole
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
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.Movement
import
Movement
from
Products.ERP5.Document.MappedValue
import
MappedValue
from
Products.ERP5.Document.MappedValue
import
MappedValue
from
Products.ERP5.Document.ImmobilisationMovement
import
ImmobilisationMovement
from
Products.ERP5.Document.ImmobilisationMovement
import
ImmobilisationMovement
class
DeliveryCell
(
MappedValue
,
Movement
,
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.
"""
"""
A DeliveryCell allows to define specific quantities
return
False
for each variation of a resource in a delivery line.
"""
# MatrixBox methods
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
meta_type
=
'ERP5 Delivery Cell'
'hasCellContent'
)
portal_type
=
'Delivery Cell'
def
hasCellContent
(
self
,
base_id
=
'movement'
):
isCell
=
1
"""A cell cannot have cell content itself.
"""
# Declarative security
return
0
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isAccountable'
)
def
isAccountable
(
self
):
# Declarative properties
"""
property_sheets
=
(
PropertySheet
.
Base
Returns 1 if this needs to be accounted
,
PropertySheet
.
CategoryCore
Only account movements which are not associated to a delivery
,
PropertySheet
.
Arrow
Whenever delivery is there, delivery has priority
,
PropertySheet
.
Amount
"""
,
PropertySheet
.
Task
return
self
.
getParentValue
().
getParentValue
().
isAccountable
()
,
PropertySheet
.
Movement
,
PropertySheet
.
Price
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getPrice'
)
,
PropertySheet
.
Predicate
def
getPrice
(
self
,
*
args
,
**
kw
):
,
PropertySheet
.
MappedValue
"""
,
PropertySheet
.
ItemAggregation
call Movement.getPrice
)
"""
return
Movement
.
getPrice
(
self
,
*
args
,
**
kw
)
# Declarative interfaces
zope
.
interface
.
implements
(
interfaces
.
IDivergenceController
,)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getTotalPrice'
)
def
getTotalPrice
(
self
,
default
=
0.0
,
*
args
,
**
kw
):
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isPredicate'
)
"""
def
isPredicate
(
self
):
call Movement.getTotalPrice
"""Movements are not predicates.
"""
"""
return
Movement
.
getTotalPrice
(
self
,
default
=
default
,
*
args
,
**
kw
)
return
False
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
# MatrixBox methods
'getRootDeliveryValue'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
def
getRootDeliveryValue
(
self
):
'hasCellContent'
)
"""
def
hasCellContent
(
self
,
base_id
=
'movement'
):
Returns the root delivery responsible of this cell
"""A cell cannot have cell content itself.
"""
"""
return
self
.
getParentValue
().
getRootDeliveryValue
()
return
0
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isAccountable'
)
'notifyAfterUpdateRelatedContent'
)
def
isAccountable
(
self
):
def
notifyAfterUpdateRelatedContent
(
self
,
previous_category_url
,
new_category_url
):
"""
"""
Returns 1 if this needs to be accounted
Membership Crirerions and Category List are same in DeliveryCell
Only account movements which are not associated to a delivery
Must update it (or change implementation to remove data duplication)
Whenever delivery is there, delivery has priority
"""
"""
update_method
=
self
.
portal_categories
.
updateRelatedCategory
return
self
.
getParentValue
().
getParentValue
().
isAccountable
()
new_predicate_value
=
[
update_method
(
c
,
previous_category_url
,
new_category_url
)
for
c
in
self
.
getPredicateValueList
()]
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getPrice'
)
self
.
_setPredicateValueList
(
new_predicate_value
)
def
getPrice
(
self
,
*
args
,
**
kw
):
# No reindex needed since uid stable
"""
call Movement.getPrice
# XXX FIXME: option variation are today not well implemented
"""
# This little hack is needed to make the matrixbox working
return
Movement
.
getPrice
(
self
,
*
args
,
**
kw
)
# in DeliveryLine_viewIndustrialPhase
# Generic form (DeliveryLine_viewOption) is required
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getTotalPrice'
)
def
_edit
(
self
,
**
kw
):
def
getTotalPrice
(
self
,
default
=
0.0
,
*
args
,
**
kw
):
"""
"""
Store variation_category_list, in order to store new value of
call Movement.getTotalPrice
industrial_phase after.
"""
"""
return
Movement
.
getTotalPrice
(
self
,
default
=
default
,
*
args
,
**
kw
)
edit_order
=
[
'variation_category_list'
,
# edit this one first
'item_id_list'
]
# this one must be the last
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
edit_order
[
1
:
1
]
=
[
x
for
x
in
kw
.
pop
(
'edit_order'
,
())
'getRootDeliveryValue'
)
if
x
not
in
edit_order
]
def
getRootDeliveryValue
(
self
):
# Base._edit updates unordered properties first
"""
edit_order
[
1
:
1
]
=
[
x
for
x
in
kw
if
x
not
in
edit_order
]
Returns the root delivery responsible of this cell
MappedValue
.
_edit
(
self
,
edit_order
=
edit_order
,
**
kw
)
"""
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():
# if self.isSimulated():
# self.getRootDeliveryValue().activate().propagateResourceToSimulation()
# self.getRootDeliveryValue().activate().propagateResourceToSimulation()
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'updateSimulationDeliveryProperties'
)
'updateSimulationDeliveryProperties'
)
def
updateSimulationDeliveryProperties
(
self
,
movement_list
=
None
):
def
updateSimulationDeliveryProperties
(
self
,
movement_list
=
None
):
"""
"""
Set properties delivery_ratio and delivery_error for each
Set properties delivery_ratio and delivery_error for each
simulation movement in movement_list (all movements by default),
simulation movement in movement_list (all movements by default),
according to this delivery calculated quantity
according to this delivery calculated quantity
"""
"""
parent
=
self
.
getParentValue
()
parent
=
self
.
getParentValue
()
if
parent
is
not
None
:
parent
=
parent
.
getParentValue
()
if
parent
is
not
None
:
if
parent
is
not
None
:
parent
=
parent
.
getParentValue
()
parent
.
updateSimulationDeliveryProperties
(
movement_list
,
self
)
if
parent
is
not
None
:
parent
.
updateSimulationDeliveryProperties
(
movement_list
,
self
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isMovement'
)
def
isMovement
(
self
):
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isMovement'
)
return
1
def
isMovement
(
self
):
return
1
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isMovingItem'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
def
isMovingItem
(
self
,
item
):
'isMovingItem'
)
type_based_script
=
self
.
_getTypeBasedMethod
(
'isMovingItem'
)
def
isMovingItem
(
self
,
item
):
if
type_based_script
:
type_based_script
=
self
.
_getTypeBasedMethod
(
'isMovingItem'
)
return
type_based_script
(
item
)
if
type_based_script
:
return
self
.
isAccountable
()
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
# Override getQuantityUnitXXX to negate same methods defined in
# not from resource.
# Amount class. Because cell must acquire quantity unit from line
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
# not from resource.
'getQuantityUnitValue'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
def
getQuantityUnitValue
(
self
):
'getQuantityUnitValue'
)
return
self
.
getParentValue
().
getQuantityUnitValue
()
def
getQuantityUnitValue
(
self
):
return
self
.
getParentValue
().
getQuantityUnitValue
()
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getQuantityUnit'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
def
getQuantityUnit
(
self
,
checked_permission
=
None
):
'getQuantityUnit'
)
return
self
.
getParentValue
().
getQuantityUnit
(
checked_permission
=
checked_permission
)
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
# XXX: Dirty but required for erp5_banking_core
getBaobabSourceUid
=
lambda
x
:
x
.
getSourceUid
()
### Acquire Baobab source / destination uids from parent line
getBaobabSourceUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceUid
=
lambda
x
:
x
.
getSourceUid
()
getBaobabSourceUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationUid
=
lambda
x
:
x
.
getDestinationUid
()
getBaobabDestinationUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationUid
=
lambda
x
:
x
.
getDestinationUid
()
getBaobabDestinationUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceSectionUid
=
lambda
x
:
x
.
getSourceSectionUid
()
getBaobabSourceSectionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceSectionUid
=
lambda
x
:
x
.
getSourceSectionUid
()
getBaobabSourceSectionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationSectionUid
=
lambda
x
:
x
.
getDestinationSectionUid
()
getBaobabDestinationSectionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationSectionUid
=
lambda
x
:
x
.
getDestinationSectionUid
()
getBaobabDestinationSectionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourcePaymentUid
=
lambda
x
:
x
.
getSourcePaymentUid
()
getBaobabSourcePaymentUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourcePaymentUid
=
lambda
x
:
x
.
getSourcePaymentUid
()
getBaobabSourcePaymentUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationPaymentUid
=
lambda
x
:
x
.
getDestinationPaymentUid
()
getBaobabDestinationPaymentUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationPaymentUid
=
lambda
x
:
x
.
getDestinationPaymentUid
()
getBaobabDestinationPaymentUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceFunctionUid
=
lambda
x
:
x
.
getSourceFunctionUid
()
getBaobabSourceFunctionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceFunctionUid
=
lambda
x
:
x
.
getSourceFunctionUid
()
getBaobabSourceFunctionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationFunctionUid
=
lambda
x
:
x
.
getDestinationFunctionUid
()
getBaobabDestinationFunctionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationFunctionUid
=
lambda
x
:
x
.
getDestinationFunctionUid
()
getBaobabDestinationFunctionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceProjectUid
=
lambda
x
:
x
.
getSourceProjectUid
()
getBaobabSourceProjectUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceProjectUid
=
lambda
x
:
x
.
getSourceProjectUid
()
getBaobabSourceProjectUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationProjectUid
=
lambda
x
:
x
.
getDestinationProjectUid
()
getBaobabDestinationProjectUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationProjectUid
=
lambda
x
:
x
.
getDestinationProjectUid
()
\ No newline at end of file
getBaobabDestinationProjectUid__roles__
=
PermissionRole
(
Permissions
.
View
)
product/ERP5/Document/DeliveryLine.py
View file @
4ee585d8
...
@@ -41,240 +41,238 @@ from Products.ERP5Type.Base import Base
...
@@ -41,240 +41,238 @@ from Products.ERP5Type.Base import Base
edit_args_list
=
getargspec
(
Base
.
_edit
).
args
edit_args_list
=
getargspec
(
Base
.
_edit
).
args
class
DeliveryLine
(
Movement
,
XMLMatrix
,
ImmobilisationMovement
):
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
):
"""
"""
A DeliveryLine object allows to implement lines in
Returns the total price for this line, this line contains, or the cells it contains.
Deliveries (packing list, order, invoice, etc.)
It may include a price (for insurance, for customs, for invoices,
if hasLineContent: return sum of lines total price
for orders)
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
meta_type
=
'ERP5 Delivery Line'
if hasLineContent: return sum of lines total quantity
portal_type
=
'Delivery Line'
if hasCellContent: return sum of cells total quantity
else: return quantity
# Declarative security
if fast argument is true, inventory API will be used.
security
=
ClassSecurityInfo
()
"""
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
if
fast
:
kw
=
{}
# Declarative properties
kw
[
'section_uid'
]
=
self
.
getDestinationSectionUid
()
property_sheets
=
(
PropertySheet
.
Base
kw
[
'stock.explanation_uid'
]
=
self
.
getExplanationUid
()
,
PropertySheet
.
XMLObject
kw
[
'relative_url'
]
=
(
'%s/%%'
%
(
,
PropertySheet
.
CategoryCore
self
.
getRelativeUrl
().
replace
(
'_'
,
'
\
\
_'
)),
,
PropertySheet
.
Amount
self
.
getRelativeUrl
()
)
,
PropertySheet
.
Task
kw
[
'only_accountable'
]
=
False
,
PropertySheet
.
Arrow
return
self
.
getPortalObject
().
portal_simulation
.
getInventory
(
**
kw
)
,
PropertySheet
.
Movement
,
PropertySheet
.
Price
base_id
=
'movement'
,
PropertySheet
.
VariationRange
if
self
.
hasLineContent
():
,
PropertySheet
.
ItemAggregation
meta_type
=
self
.
meta_type
,
PropertySheet
.
SortIndex
return
sum
(
l
.
getTotalQuantity
()
for
l
in
)
self
.
objectValues
()
if
l
.
meta_type
==
meta_type
)
elif
self
.
hasCellContent
(
base_id
=
base_id
):
# Declarative interfaces
return
sum
([
cell
.
getQuantity
()
for
cell
in
self
.
getCellValueList
()])
zope
.
interface
.
implements
(
interfaces
.
IDivergenceController
,)
return
self
.
getQuantity
()
# Multiple inheritance definition
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
updateRelatedContent
=
XMLMatrix
.
updateRelatedContent
'hasLineContent'
)
def
hasLineContent
(
self
):
# Force in _edit to modify variation_base_category_list first
"""Return true if the object contains lines.
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
This method only checks the first sub line because all sub
lines should be same meta type in reality if we have line
lines should be same meta type in reality if we have line
inside line.
inside line.
"""
"""
return
len
(
self
)
!=
0
and
self
.
objectValues
()[
0
].
meta_type
==
self
.
meta_type
return
len
(
self
)
!=
0
and
self
.
objectValues
()[
0
].
meta_type
==
self
.
meta_type
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'hasCellContent'
)
'hasCellContent'
)
def
hasCellContent
(
self
,
base_id
=
'movement'
):
def
hasCellContent
(
self
,
base_id
=
'movement'
):
"""Return true if the object contains cells.
"""Return true if the object contains cells.
"""
"""
# Do not use XMLMatrix.hasCellContent, because it can generate
# Do not use XMLMatrix.hasCellContent, because it can generate
# inconsistency in catalog
# inconsistency in catalog
# Exemple: define a line and set the matrix cell range, but do not create
# Exemple: define a line and set the matrix cell range, but do not create
# cell.
# cell.
# Line was in this case consider like a movement, and was catalogued.
# Line was in this case consider like a movement, and was catalogued.
# But, getVariationText of the line was not empty.
# But, getVariationText of the line was not empty.
# So, in ZODB, resource as without variation, but in catalog, this was
# So, in ZODB, resource as without variation, but in catalog, this was
# the contrary...
# the contrary...
cell_range
=
XMLMatrix
.
getCellRange
(
self
,
base_id
=
base_id
)
cell_range
=
XMLMatrix
.
getCellRange
(
self
,
base_id
=
base_id
)
return
(
cell_range
is
not
None
and
len
(
cell_range
)
>
0
)
return
(
cell_range
is
not
None
and
len
(
cell_range
)
>
0
)
# DeliveryLine can be a movement when it does not content any cell and
# DeliveryLine can be a movement when it does not content any cell and
# matrix cell range is not empty.
# matrix cell range is not empty.
# Better implementation is needed.
# Better implementation is needed.
# We want to define a line without cell, defining a variated resource.
# 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
# If we modify the cell range, we need to move the quantity to a new
# cell, which define the same variated resource.
# cell, which define the same variated resource.
# return XMLMatrix.hasCellContent(self, base_id=base_id)
# return XMLMatrix.hasCellContent(self, base_id=base_id)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isMovement'
)
'isMovement'
)
def
isMovement
(
self
):
def
isMovement
(
self
):
"""
"""
returns true is the object contains no submovement (line or cell)
returns true is the object contains no submovement (line or cell)
"""
"""
object_list
=
self
.
objectValues
()
object_list
=
self
.
objectValues
()
if
object_list
:
if
object_list
:
portal_type
=
self
.
getPortalObject
().
getPortalMovementTypeList
()
portal_type
=
self
.
getPortalObject
().
getPortalMovementTypeList
()
for
ob
in
object_list
:
for
ob
in
object_list
:
if
ob
.
getPortalType
()
in
portal_type
:
if
ob
.
getPortalType
()
in
portal_type
:
return
False
return
False
return
True
return
True
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getMovedItemUidList'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getMovedItemUidList'
)
def
getMovedItemUidList
(
self
):
def
getMovedItemUidList
(
self
):
"""This method returns an uid list of items
"""This method returns an uid list of items
"""
"""
return
[
item
.
getUid
()
for
item
in
self
.
getAggregateValueList
()
\
return
[
item
.
getUid
()
for
item
in
self
.
getAggregateValueList
()
\
if
self
.
isMovingItem
(
item
)]
if
self
.
isMovingItem
(
item
)]
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getCellValueList'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getCellValueList'
)
def
getCellValueList
(
self
,
base_id
=
'movement'
):
def
getCellValueList
(
self
,
base_id
=
'movement'
):
"""
"""
This method can be overriden
This method can be overriden
"""
"""
return
XMLMatrix
.
getCellValueList
(
self
,
base_id
=
base_id
)
return
XMLMatrix
.
getCellValueList
(
self
,
base_id
=
base_id
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getCell'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getCell'
)
def
getCell
(
self
,
*
kw
,
**
kwd
):
def
getCell
(
self
,
*
kw
,
**
kwd
):
"""
"""
This method can be overriden
This method can be overriden
"""
"""
if
'base_id'
not
in
kwd
:
if
'base_id'
not
in
kwd
:
kwd
[
'base_id'
]
=
'movement'
kwd
[
'base_id'
]
=
'movement'
return
XMLMatrix
.
getCell
(
self
,
*
kw
,
**
kwd
)
return
XMLMatrix
.
getCell
(
self
,
*
kw
,
**
kwd
)
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'newCell'
)
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'newCell'
)
def
newCell
(
self
,
*
kw
,
**
kwd
):
def
newCell
(
self
,
*
kw
,
**
kwd
):
"""
"""
This method creates a new cell
This method creates a new cell
"""
"""
if
'base_id'
not
in
kwd
:
if
'base_id'
not
in
kwd
:
kwd
[
'base_id'
]
=
'movement'
kwd
[
'base_id'
]
=
'movement'
return
XMLMatrix
.
newCell
(
self
,
*
kw
,
**
kwd
)
return
XMLMatrix
.
newCell
(
self
,
*
kw
,
**
kwd
)
def
applyToDeliveryLineRelatedMovement
(
self
,
portal_type
=
'Simulation Movement'
,
method_id
=
'expand'
):
def
applyToDeliveryLineRelatedMovement
(
self
,
portal_type
=
'Simulation Movement'
,
method_id
=
'expand'
):
# Find related in simulation
# Find related in simulation
for
my_simulation_movement
in
self
.
getDeliveryRelatedValueList
(
for
my_simulation_movement
in
self
.
getDeliveryRelatedValueList
(
portal_type
=
'Simulation Movement'
):
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
# And apply
getattr
(
my_simulation_movement
.
getObject
(),
method_id
)()
getattr
(
my_simulation_movement
.
getObject
(),
method_id
)()
for
c
in
self
.
objectValues
(
portal_type
=
'Delivery Cell'
):
for
my_simulation_movement
in
c
.
getDeliveryRelatedValueList
(
def
reindexObject
(
self
,
*
k
,
**
kw
):
portal_type
=
'Simulation Movement'
):
"""Reindex children"""
# And apply
self
.
recursiveReindexObject
(
*
k
,
**
kw
)
getattr
(
my_simulation_movement
.
getObject
(),
method_id
)()
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getInventoriatedQuantity'
)
def
reindexObject
(
self
,
*
k
,
**
kw
):
def
getInventoriatedQuantity
(
self
):
"""Reindex children"""
"""
self
.
recursiveReindexObject
(
*
k
,
**
kw
)
"""
return
Movement
.
getInventoriatedQuantity
(
self
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getInventoriatedQuantity'
)
def
getInventoriatedQuantity
(
self
):
"""
"""
return
Movement
.
getInventoriatedQuantity
(
self
)
# security.declarePrivate('_checkConsistency')
# security.declarePrivate('_checkConsistency')
# def _checkConsistency(self, fixit=0, mapped_value_property_list = ('quantity', 'price')):
# def _checkConsistency(self, fixit=0, mapped_value_property_list = ('quantity', 'price')):
...
@@ -311,188 +309,185 @@ class DeliveryLine(Movement, XMLMatrix, ImmobilisationMovement):
...
@@ -311,188 +309,185 @@ class DeliveryLine(Movement, XMLMatrix, ImmobilisationMovement):
#
#
# return error_list
# return error_list
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getRootDeliveryValue'
)
'getRootDeliveryValue'
)
def
getRootDeliveryValue
(
self
):
def
getRootDeliveryValue
(
self
):
"""
"""
Returns the root delivery responsible of this line
Returns the root delivery responsible of this line
"""
"""
return
self
.
getParentValue
().
getRootDeliveryValue
()
return
self
.
getParentValue
().
getRootDeliveryValue
()
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'updateSimulationDeliveryProperties'
)
'updateSimulationDeliveryProperties'
)
def
updateSimulationDeliveryProperties
(
self
,
movement_list
=
None
):
def
updateSimulationDeliveryProperties
(
self
,
movement_list
=
None
):
"""
"""
Set properties delivery_ratio and delivery_error for each
Set properties delivery_ratio and delivery_error for each
simulation movement in movement_list (all movements by default),
simulation movement in movement_list (all movements by default),
according to this delivery calculated quantity
according to this delivery calculated quantity
"""
"""
parent
=
self
.
getParentValue
()
parent
=
self
.
getParentValue
()
if
parent
is
not
None
:
if
parent
is
not
None
:
parent
.
updateSimulationDeliveryProperties
(
movement_list
,
self
)
parent
.
updateSimulationDeliveryProperties
(
movement_list
,
self
)
security
.
declarePrivate
(
'manage_afterAdd'
)
security
.
declarePrivate
(
'manage_afterAdd'
)
def
manage_afterAdd
(
self
,
item
,
container
):
def
manage_afterAdd
(
self
,
item
,
container
):
"if the container is a line too, reindex it"
"if the container is a line too, reindex it"
if
self
.
meta_type
==
container
.
meta_type
:
if
self
.
meta_type
==
container
.
meta_type
:
container
.
reindexObject
()
container
.
reindexObject
()
return
Movement
.
manage_afterAdd
(
self
,
item
,
container
)
return
Movement
.
manage_afterAdd
(
self
,
item
,
container
)
security
.
declarePrivate
(
'manage_beforeDelete'
)
security
.
declarePrivate
(
'manage_beforeDelete'
)
def
manage_beforeDelete
(
self
,
item
,
container
):
def
manage_beforeDelete
(
self
,
item
,
container
):
"if the container is a line too, reindex it"
"if the container is a line too, reindex it"
if
self
.
meta_type
==
container
.
meta_type
:
if
self
.
meta_type
==
container
.
meta_type
:
container
.
reindexObject
()
container
.
reindexObject
()
return
Movement
.
manage_beforeDelete
(
self
,
item
,
container
)
return
Movement
.
manage_beforeDelete
(
self
,
item
,
container
)
# divergence support with solving
# divergence support with solving
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isDivergent'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isDivergent'
)
def
isDivergent
(
self
):
def
isDivergent
(
self
):
"""Returns true if the delivery line is divergent, or if any contained
"""Returns true if the delivery line is divergent, or if any contained
cell is divergent.
cell is divergent.
"""
"""
return
bool
(
self
.
getDivergenceList
())
return
bool
(
self
.
getDivergenceList
())
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getDivergenceList'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getDivergenceList'
)
def
getDivergenceList
(
self
):
def
getDivergenceList
(
self
):
"""Returns a list of messages that contains the divergences for that line
"""Returns a list of messages that contains the divergences for that line
and the cells it may contain.
and the cells it may contain.
"""
"""
if
self
.
hasCellContent
():
if
self
.
hasCellContent
():
divergence_list
=
[]
divergence_list
=
[]
for
cell
in
self
.
objectValues
(
portal_type
=
self
.
getPortalObject
()
for
cell
in
self
.
objectValues
(
portal_type
=
self
.
getPortalObject
()
.
getPortalDeliveryMovementTypeList
()):
.
getPortalDeliveryMovementTypeList
()):
divergence_list
+=
cell
.
getDivergenceList
()
divergence_list
+=
cell
.
getDivergenceList
()
return
divergence_list
return
divergence_list
else
:
else
:
return
Movement
.
getDivergenceList
(
self
)
return
Movement
.
getDivergenceList
(
self
)
def
_distributePropertyToSimulation
(
self
,
decision
):
def
_distributePropertyToSimulation
(
self
,
decision
):
"""Distributes property from self to all related simulation movements
"""Distributes property from self to all related simulation movements
AKA - accept decision"""
AKA - accept decision"""
for
simulation_movement
in
self
.
getDeliveryRelatedValueList
(
for
simulation_movement
in
self
.
getDeliveryRelatedValueList
(
portal_type
=
'Simulation Movement'
):
portal_type
=
'Simulation Movement'
):
simulation_movement
.
edit
(
**
{
simulation_movement
.
edit
(
**
{
decision
.
divergence
.
tested_property
:
decision
.
divergence
.
tested_property
:
self
.
getProperty
(
decision
.
divergence
.
tested_property
)
self
.
getProperty
(
decision
.
divergence
.
tested_property
)
})
})
def
_updatePropertyFromSimulation
(
self
,
decision_list
):
def
_updatePropertyFromSimulation
(
self
,
decision_list
):
"""Update property from simulation
"""Update property from simulation
'Stolen' from Products.ERP5.Document.DeliveryBuilder._solveDivergence
'Stolen' from Products.ERP5.Document.DeliveryBuilder._solveDivergence
Another possibility is to just simply copy properties or, in case of
Another possibility is to just simply copy properties or, in case of
quantity, add from all simulation movements.
quantity, add from all simulation movements.
"""
"""
simulation_movement_list
=
self
.
getDeliveryRelatedValueList
(
simulation_movement_list
=
self
.
getDeliveryRelatedValueList
(
portal_type
=
"Simulation Movement"
)
portal_type
=
"Simulation Movement"
)
business_link
=
simulation_movement_list
[
0
].
getCausalityValue
()
business_link
=
simulation_movement_list
[
0
].
getCausalityValue
()
delivery
=
self
.
getExplanationValue
()
delivery
=
self
.
getExplanationValue
()
delivery_portal_type
=
delivery
.
getPortalType
()
delivery_portal_type
=
delivery
.
getPortalType
()
delivery_line_portal_type
=
self
.
getPortalType
()
delivery_line_portal_type
=
self
.
getPortalType
()
# we need to find only one matching delivery builder
# we need to find only one matching delivery builder
for
delivery_builder
in
business_link
.
getDeliveryBuilderValueList
():
for
delivery_builder
in
business_link
.
getDeliveryBuilderValueList
():
if
delivery_builder
.
getDeliveryPortalType
()
==
\
if
delivery_builder
.
getDeliveryPortalType
()
==
\
delivery_portal_type
and
\
delivery_portal_type
and
\
delivery_builder
.
getDeliveryLinePortalType
()
==
\
delivery_builder
.
getDeliveryLinePortalType
()
==
\
delivery_line_portal_type
:
delivery_line_portal_type
:
break
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
:
else
:
raise
ValueError
(
'No builder found'
)
for
s_m
in
s_m_list_per_movement
:
delivery_ratio
=
1.0
/
len
(
s_m_list_per_movement
)
self
.
edit
(
quantity
=
0
)
# adoption have to 'rebuild' delivery line
s_m
.
edit
(
delivery_ratio
=
delivery_ratio
)
movement_type_list
=
(
delivery_builder
.
getDeliveryLinePortalType
(),
delivery_builder
.
getDeliveryCellPortalType
())
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'solve'
)
# Collect
def
solve
(
self
,
decision_list
):
root_group_node
=
delivery_builder
.
collectMovement
(
"""Solves line according to decision list
simulation_movement_list
)
"""
simulation_tool
=
self
.
getPortalObject
().
portal_simulation
divergence_list
=
[
decision
.
divergence
for
decision
in
decision_list
]
solveMovement
=
simulation_tool
.
solveMovement
# accept + split
# Build
for
decision
in
[
q
for
q
in
decision_list
if
q
.
decision
!=
'adopt'
]:
portal
=
self
.
getPortalObject
()
if
decision
.
decision
==
'accept'
:
delivery_module
=
getattr
(
portal
,
delivery_builder
.
getDeliveryModule
())
# accepting - in case of passed DeliverySolver use it, otherwise
delivery_to_update_list
=
[
delivery
]
# simply copy values to simulation
delivery_list
=
delivery_builder
.
_processDeliveryGroup
(
if
not
decision
.
delivery_solver_name
:
delivery_module
,
self
.
_distributePropertyToSimulation
(
decision
)
root_group_node
,
solveMovement
(
self
,
decision
.
delivery_solver_name
,
delivery_builder
.
getDeliveryMovementGroupList
(),
decision
.
target_solver_name
,
divergence_list
=
[
decision
.
divergence
])
delivery_to_update_list
=
delivery_to_update_list
,
elif
decision
.
decision
==
'split'
:
divergence_list
=
divergence_list
,
solveMovement
(
self
,
decision
.
delivery_solver_name
,
force_update
=
1
)
decision
.
target_solver_name
,
**
decision
.
split_kw
)
else
:
# aka - do nothing
new_delivery_list
=
[
x
for
x
in
delivery_list
if
x
!=
delivery
]
pass
if
new_delivery_list
:
# adopt
raise
ValueError
(
'No new deliveries shall be created'
)
adopt_decision_list
=
[
q
for
q
in
decision_list
\
if
q
.
decision
==
'adopt'
]
# Then, we should re-apply quantity divergence according to 'Do
if
adopt_decision_list
:
# nothing' quantity divergence list because all quantity are already
self
.
_updatePropertyFromSimulation
(
adopt_decision_list
)
# calculated in adopt prevision phase.
\ No newline at end of file
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
)
product/ERP5/Document/InventoryCell.py
View file @
4ee585d8
...
@@ -34,64 +34,62 @@ from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
...
@@ -34,64 +34,62 @@ from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
from
Products.ERP5.Document.DeliveryCell
import
DeliveryCell
from
Products.ERP5.Document.DeliveryCell
import
DeliveryCell
class
InventoryCell
(
DeliveryCell
):
class
InventoryCell
(
DeliveryCell
):
"""
"""
An InventoryCell allows to define specific inventory
An InventoryCell allows to define specific inventory
for each variation of a resource in an inventory line.
for each variation of a resource in an inventory line.
"""
"""
meta_type
=
'ERP5 Inventory Cell'
portal_type
=
'Inventory Cell'
add_permission
=
Permissions
.
AddPortalContent
isInventoryMovement
=
ConstantGetter
(
'isInventoryMovement'
,
value
=
True
)
meta_type
=
'ERP5 Inventory Cell'
# Declarative security
portal_type
=
'Inventory Cell'
security
=
ClassSecurityInfo
()
add_permission
=
Permissions
.
AddPortalContent
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
isInventoryMovement
=
ConstantGetter
(
'isInventoryMovement'
,
value
=
True
)
# Declarative security
# Declarative properties
security
=
ClassSecurityInfo
()
property_sheets
=
(
PropertySheet
.
Base
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
,
PropertySheet
.
CategoryCore
,
PropertySheet
.
Amount
,
PropertySheet
.
InventoryMovement
,
PropertySheet
.
Task
,
PropertySheet
.
Movement
,
PropertySheet
.
Price
,
PropertySheet
.
Predicate
,
PropertySheet
.
MappedValue
,
PropertySheet
.
ItemAggregation
)
# Declarative properties
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getTotalInventory'
)
property_sheets
=
(
PropertySheet
.
Base
def
getTotalInventory
(
self
):
,
PropertySheet
.
CategoryCore
"""
,
PropertySheet
.
Amount
Returns the inventory, as cells are not supposed to contain more cells.
,
PropertySheet
.
InventoryMovement
"""
,
PropertySheet
.
Task
return
self
.
getInventory
()
,
PropertySheet
.
Movement
,
PropertySheet
.
Price
,
PropertySheet
.
Predicate
,
PropertySheet
.
MappedValue
,
PropertySheet
.
ItemAggregation
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getTotalInventory'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getQuantity'
)
def
getTotalInventory
(
self
):
def
getQuantity
(
self
):
"""
"""
Returns the inventory, as cells are not supposed to contain more cells.
Computes a quantity which allows to reach inventory
"""
"""
if
not
self
.
hasCellContent
():
# First check if quantity already exists
quantity
=
self
.
_baseGetQuantity
()
if
quantity
not
in
(
0.0
,
0
,
None
):
return
quantity
# Make sure inventory is defined somewhere (here or parent)
if
getattr
(
aq_base
(
self
),
'inventory'
,
None
)
is
None
:
return
0.0
# No inventory defined, so no quantity
return
self
.
getInventory
()
return
self
.
getInventory
()
else
:
return
None
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getQuantity'
)
# Inventory cataloging
def
getQuantity
(
self
):
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getConvertedInventory'
)
"""
def
getConvertedInventory
(
self
):
Computes a quantity which allows to reach inventory
"""
"""
provides a default inventory value - None since
if
not
self
.
hasCellContent
():
no inventory was defined.
# First check if quantity already exists
"""
quantity
=
self
.
_baseGetQuantity
()
return
self
.
getInventory
()
# XXX quantity unit is missing
if
quantity
not
in
(
0.0
,
0
,
None
):
\ No newline at end of file
return
quantity
# Make sure inventory is defined somewhere (here or parent)
if
getattr
(
aq_base
(
self
),
'inventory'
,
None
)
is
None
:
return
0.0
# No inventory defined, so no quantity
return
self
.
getInventory
()
else
:
return
None
# Inventory cataloging
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getConvertedInventory'
)
def
getConvertedInventory
(
self
):
"""
provides a default inventory value - None since
no inventory was defined.
"""
return
self
.
getInventory
()
# XXX quantity unit is missing
product/ERP5/Document/InventoryLine.py
View file @
4ee585d8
...
@@ -36,112 +36,110 @@ from Products.ERP5.Document.Movement import Movement
...
@@ -36,112 +36,110 @@ from Products.ERP5.Document.Movement import Movement
from
Products.ERP5Type.Accessor.Constant
import
PropertyGetter
as
ConstantGetter
from
Products.ERP5Type.Accessor.Constant
import
PropertyGetter
as
ConstantGetter
class
InventoryLine
(
DeliveryLine
):
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
):
"""
"""
An Inventory Line describe the inventory of a resource, by variations.
Returns the inventory if no cell or the total inventory if cells
"""
"""
if
not
self
.
hasCellContent
():
meta_type
=
'ERP5 Inventory Line'
return
self
.
getInventory
()
portal_type
=
'Inventory Line'
else
:
add_permission
=
Permissions
.
AddPortalContent
total_quantity
=
0.0
isInventoryMovement
=
ConstantGetter
(
'isInventoryMovement'
,
value
=
True
)
for
cell
in
self
.
getCellValueList
(
base_id
=
'movement'
):
if
cell
.
getInventory
()
is
not
None
:
# Declarative security
total_quantity
+=
cell
.
getInventory
()
security
=
ClassSecurityInfo
()
return
total_quantity
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
# Declarative properties
'getQuantity'
)
property_sheets
=
(
PropertySheet
.
Base
def
getQuantity
(
self
):
,
PropertySheet
.
XMLObject
"""
,
PropertySheet
.
CategoryCore
Computes a quantity which allows to reach inventory
,
PropertySheet
.
Amount
"""
,
PropertySheet
.
InventoryMovement
if
not
self
.
hasCellContent
():
,
PropertySheet
.
Task
# First check if quantity already exists
,
PropertySheet
.
Arrow
quantity
=
self
.
_baseGetQuantity
()
,
PropertySheet
.
Movement
if
quantity
not
in
(
0.0
,
0
,
None
):
,
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
return
quantity
else
:
# Make sure inventory is defined somewhere (here or parent)
return
None
inventory
=
getattr
(
aq_base
(
self
),
'inventory'
,
None
)
if
inventory
is
not
None
:
# Inventory cataloging
return
inventory
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
return
quantity
'getConvertedInventory'
)
else
:
def
getConvertedInventory
(
self
):
return
None
"""
provides a default inventory value - None since
# Inventory cataloging
no inventory was defined.
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
"""
'getConvertedInventory'
)
return
self
.
getInventory
()
# XXX quantity unit is missing
def
getConvertedInventory
(
self
):
"""
# Required for indexing
provides a default inventory value - None since
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
no inventory was defined.
'getInventoriatedQuantity'
)
"""
def
getInventoriatedQuantity
(
self
):
return
self
.
getInventory
()
# XXX quantity unit is missing
"""
Take into account efficiency in converted target quantity
# Required for indexing
"""
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
return
Movement
.
getInventoriatedQuantity
(
self
)
'getInventoriatedQuantity'
)
def
getInventoriatedQuantity
(
self
):
# XXX: Dirty but required for erp5_banking_core
"""
getBaobabSourceUid
=
lambda
x
:
x
.
getSourceUid
()
Take into account efficiency in converted target quantity
getBaobabSourceUid__roles__
=
PermissionRole
(
Permissions
.
View
)
"""
return
Movement
.
getInventoriatedQuantity
(
self
)
getBaobabDestinationUid
=
lambda
x
:
x
.
getDestinationUid
()
getBaobabDestinationUid__roles__
=
PermissionRole
(
Permissions
.
View
)
# XXX: Dirty but required for erp5_banking_core
getBaobabSourceUid
=
lambda
x
:
x
.
getSourceUid
()
getBaobabSourceSectionUid
=
lambda
x
:
x
.
getSourceSectionUid
()
getBaobabSourceUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceSectionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationUid
=
lambda
x
:
x
.
getDestinationUid
()
getBaobabDestinationSectionUid
=
lambda
x
:
x
.
getDestinationSectionUid
()
getBaobabDestinationUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationSectionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceSectionUid
=
lambda
x
:
x
.
getSourceSectionUid
()
getBaobabSourcePaymentUid
=
lambda
x
:
x
.
getSourcePaymentUid
()
getBaobabSourceSectionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourcePaymentUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationSectionUid
=
lambda
x
:
x
.
getDestinationSectionUid
()
getBaobabDestinationPaymentUid
=
lambda
x
:
x
.
getDestinationPaymentUid
()
getBaobabDestinationSectionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationPaymentUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourcePaymentUid
=
lambda
x
:
x
.
getSourcePaymentUid
()
getBaobabSourceFunctionUid
=
lambda
x
:
x
.
getSourceFunctionUid
()
getBaobabSourcePaymentUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceFunctionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationPaymentUid
=
lambda
x
:
x
.
getDestinationPaymentUid
()
getBaobabDestinationFunctionUid
=
lambda
x
:
x
.
getDestinationFunctionUid
()
getBaobabDestinationPaymentUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationFunctionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceFunctionUid
=
lambda
x
:
x
.
getSourceFunctionUid
()
getBaobabSourceProjectUid
=
lambda
x
:
x
.
getSourceProjectUid
()
getBaobabSourceFunctionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabSourceProjectUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationFunctionUid
=
lambda
x
:
x
.
getDestinationFunctionUid
()
getBaobabDestinationProjectUid
=
lambda
x
:
x
.
getDestinationProjectUid
()
getBaobabDestinationFunctionUid__roles__
=
PermissionRole
(
Permissions
.
View
)
getBaobabDestinationProjectUid__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
product/ERP5/Document/OrderCell.py
View file @
4ee585d8
...
@@ -33,59 +33,57 @@ from Products.ERP5Type import Permissions, PropertySheet
...
@@ -33,59 +33,57 @@ from Products.ERP5Type import Permissions, PropertySheet
from
Products.ERP5.Document.DeliveryCell
import
DeliveryCell
from
Products.ERP5.Document.DeliveryCell
import
DeliveryCell
class
OrderCell
(
DeliveryCell
):
class
OrderCell
(
DeliveryCell
):
"""
"""
A OrderCell allows to define specific quantities
A OrderCell allows to define specific quantities
for each variation of a resource in a delivery line.
for each variation of a resource in a delivery line.
"""
"""
meta_type
=
'ERP5 Order Cell'
portal_type
=
'Order Cell'
isCell
=
1
meta_type
=
'ERP5 Order Cell'
# Declarative security
portal_type
=
'Order Cell'
security
=
ClassSecurityInfo
()
isCell
=
1
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
# Declarative security
# Declarative properties
security
=
ClassSecurityInfo
()
property_sheets
=
(
PropertySheet
.
Base
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
,
PropertySheet
.
CategoryCore
,
PropertySheet
.
Arrow
,
PropertySheet
.
Amount
,
PropertySheet
.
Task
,
PropertySheet
.
Movement
,
PropertySheet
.
Price
,
PropertySheet
.
Predicate
,
PropertySheet
.
MappedValue
,
PropertySheet
.
ItemAggregation
)
# Declarative properties
def
reindexObject
(
self
,
*
k
,
**
kw
):
property_sheets
=
(
PropertySheet
.
Base
"""
,
PropertySheet
.
CategoryCore
Reindex children and simulation
,
PropertySheet
.
Arrow
"""
,
PropertySheet
.
Amount
self
.
recursiveReindexObject
(
*
k
,
**
kw
)
,
PropertySheet
.
Task
,
PropertySheet
.
Movement
,
PropertySheet
.
Price
,
PropertySheet
.
Predicate
,
PropertySheet
.
MappedValue
,
PropertySheet
.
ItemAggregation
)
def
reindexObject
(
self
,
*
k
,
**
kw
):
"""
Reindex children and simulation
"""
self
.
recursiveReindexObject
(
*
k
,
**
kw
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'isMovement'
)
'isMovement'
)
def
isMovement
(
self
):
def
isMovement
(
self
):
"""
"""
should be considered as a movement if the parent does not have sub lines
should be considered as a movement if the parent does not have sub lines
"""
"""
return
not
self
.
getParentValue
().
hasLineContent
()
return
not
self
.
getParentValue
().
hasLineContent
()
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getTotalPrice'
)
'getTotalPrice'
)
def
getTotalPrice
(
self
,
default
=
0.0
,
*
args
,
**
kw
):
def
getTotalPrice
(
self
,
default
=
0.0
,
*
args
,
**
kw
):
"only return a value if self is a movement"
"only return a value if self is a movement"
if
not
self
.
isMovement
():
if
not
self
.
isMovement
():
return
default
return
default
return
DeliveryCell
.
getTotalPrice
(
self
,
default
=
default
,
*
args
,
**
kw
)
return
DeliveryCell
.
getTotalPrice
(
self
,
default
=
default
,
*
args
,
**
kw
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getTotalQuantity'
)
def
getTotalQuantity
(
self
,
default
=
0.0
,
*
args
,
**
kw
):
"only return a value if self is a movement"
if
not
self
.
isMovement
():
return
default
return
DeliveryCell
.
getTotalQuantity
(
self
,
default
=
default
,
*
args
,
**
kw
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getTotalQuantity'
)
def
getTotalQuantity
(
self
,
default
=
0.0
,
*
args
,
**
kw
):
"only return a value if self is a movement"
if
not
self
.
isMovement
():
return
default
return
DeliveryCell
.
getTotalQuantity
(
self
,
default
=
default
,
*
args
,
**
kw
)
\ No newline at end of file
product/ERP5/Document/OrderLine.py
View file @
4ee585d8
...
@@ -32,27 +32,26 @@ from Products.ERP5Type import Permissions, PropertySheet
...
@@ -32,27 +32,26 @@ from Products.ERP5Type import Permissions, PropertySheet
from
Products.ERP5.Document.DeliveryLine
import
DeliveryLine
from
Products.ERP5.Document.DeliveryLine
import
DeliveryLine
class
OrderLine
(
DeliveryLine
):
class
OrderLine
(
DeliveryLine
):
"""
"""
A order line defines quantity and price
A order line defines quantity and price
"""
"""
meta_type
=
'ERP5 Order Line'
portal_type
=
'Order Line'
meta_type
=
'ERP5 Order Line'
# Declarative security
portal_type
=
'Order Line'
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
# Declarative security
# Declarative properties
security
=
ClassSecurityInfo
()
property_sheets
=
(
PropertySheet
.
Base
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
,
PropertySheet
.
XMLObject
,
PropertySheet
.
CategoryCore
# Declarative properties
,
PropertySheet
.
Amount
property_sheets
=
(
PropertySheet
.
Base
,
PropertySheet
.
Task
,
PropertySheet
.
XMLObject
,
PropertySheet
.
DublinCore
,
PropertySheet
.
CategoryCore
,
PropertySheet
.
Arrow
,
PropertySheet
.
Amount
,
PropertySheet
.
Movement
,
PropertySheet
.
Task
,
PropertySheet
.
Price
,
PropertySheet
.
DublinCore
,
PropertySheet
.
VariationRange
,
PropertySheet
.
Arrow
,
PropertySheet
.
ItemAggregation
,
PropertySheet
.
Movement
)
,
PropertySheet
.
Price
\ No newline at end of file
,
PropertySheet
.
VariationRange
,
PropertySheet
.
ItemAggregation
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment