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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
amrani
erp5
Commits
256bbd86
Commit
256bbd86
authored
Jan 24, 2014
by
Julien Muchembled
Committed by
Sebastien Robin
Mar 06, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP: mrp
parent
76811dba
Changes
29
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1118 additions
and
582 deletions
+1118
-582
bt5/erp5_mrp/ActionTemplateItem/portal_types/Transformation%20Simulation%20Rule/view.xml
.../portal_types/Transformation%20Simulation%20Rule/view.xml
+79
-0
bt5/erp5_mrp/ActionTemplateItem/portal_types/Transformation%20Sourcing%20Simulation%20Rule/view.xml
...es/Transformation%20Sourcing%20Simulation%20Rule/view.xml
+79
-0
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_packing_list_builder.xml
...tem/portal_deliveries/production_packing_list_builder.xml
+1
-1
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_packing_list_builder/category_movement_group_on_delivery.xml
...king_list_builder/category_movement_group_on_delivery.xml
+5
-0
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_packing_list_builder/category_movement_group_on_line.xml
..._packing_list_builder/category_movement_group_on_line.xml
+8
-0
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_report_builder.xml
...plateItem/portal_deliveries/production_report_builder.xml
+1
-1
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_report_builder/category_movement_group_on_delivery.xml
...on_report_builder/category_movement_group_on_delivery.xml
+5
-0
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_report_builder/category_movement_group_on_line.xml
...uction_report_builder/category_movement_group_on_line.xml
+8
-0
bt5/erp5_mrp/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml
...eAllowedContentTypeTemplateItem/allowed_content_types.xml
+24
-0
bt5/erp5_mrp/PortalTypeTemplateItem/portal_types/Transformation%20Simulation%20Rule.xml
...eItem/portal_types/Transformation%20Simulation%20Rule.xml
+141
-0
bt5/erp5_mrp/PortalTypeTemplateItem/portal_types/Transformation%20Sourcing%20Simulation%20Rule.xml
...l_types/Transformation%20Sourcing%20Simulation%20Rule.xml
+141
-0
bt5/erp5_mrp/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
...rtalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
+8
-0
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/OrderLine_getResourceTransformationItemList.xml
.../erp5_mrp/OrderLine_getResourceTransformationItemList.xml
+12
-15
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/ProductionDelivery_copyOrderProperties.xml
...skins/erp5_mrp/ProductionDelivery_copyOrderProperties.xml
+7
-18
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/ProductionPackingList_selectMovement.xml
...l_skins/erp5_mrp/ProductionPackingList_selectMovement.xml
+11
-35
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/ProductionReport_selectMovement.xml
...portal_skins/erp5_mrp/ProductionReport_selectMovement.xml
+14
-11
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/SimulationMovement_testTransformationSimulationRule.xml
...p/SimulationMovement_testTransformationSimulationRule.xml
+10
-41
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/SimulationMovement_testTransformationSourcingSimulationRule.xml
...tionMovement_testTransformationSourcingSimulationRule.xml
+5
-3
bt5/erp5_mrp/bt/template_action_path_list
bt5/erp5_mrp/bt/template_action_path_list
+3
-1
bt5/erp5_mrp/bt/template_portal_type_allowed_content_type_list
...rp5_mrp/bt/template_portal_type_allowed_content_type_list
+19
-1
bt5/erp5_mrp/bt/template_portal_type_id_list
bt5/erp5_mrp/bt/template_portal_type_id_list
+3
-1
bt5/erp5_mrp/bt/template_portal_type_workflow_chain_list
bt5/erp5_mrp/bt/template_portal_type_workflow_chain_list
+5
-1
product/ERP5/Document/Amount.py
product/ERP5/Document/Amount.py
+29
-44
product/ERP5/Document/BusinessProcess.py
product/ERP5/Document/BusinessProcess.py
+39
-0
product/ERP5/Document/TradeModelSimulationRule.py
product/ERP5/Document/TradeModelSimulationRule.py
+3
-6
product/ERP5/Document/TransformationSimulationRule.py
product/ERP5/Document/TransformationSimulationRule.py
+159
-0
product/ERP5/Document/TransformationSourcingSimulationRule.py
...uct/ERP5/Document/TransformationSourcingSimulationRule.py
+94
-0
product/ERP5/ERP5Site.py
product/ERP5/ERP5Site.py
+14
-0
product/ERP5/tests/testMRP.py
product/ERP5/tests/testMRP.py
+191
-403
No files found.
bt5/erp5_mrp/ActionTemplateItem/portal_types/Transformation%20Simulation%20Rule/view.xml
0 → 100644
View file @
256bbd86
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"ActionInformation"
module=
"Products.CMFCore.ActionInformation"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
categories
</string>
</key>
<value>
<tuple>
<string>
action_type/object_view
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
category
</string>
</key>
<value>
<string>
object_view
</string>
</value>
</item>
<item>
<key>
<string>
condition
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
icon
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
view
</string>
</value>
</item>
<item>
<key>
<string>
permissions
</string>
</key>
<value>
<tuple>
<string>
View
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
priority
</string>
</key>
<value>
<float>
1.0
</float>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string>
View
</string>
</value>
</item>
<item>
<key>
<string>
visible
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<global
name=
"Expression"
module=
"Products.CMFCore.Expression"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
text
</string>
</key>
<value>
<string>
string:${object_url}/Rule_view
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_mrp/ActionTemplateItem/portal_types/Transformation%20Sourcing%20Simulation%20Rule/view.xml
0 → 100644
View file @
256bbd86
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"ActionInformation"
module=
"Products.CMFCore.ActionInformation"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
categories
</string>
</key>
<value>
<tuple>
<string>
action_type/object_view
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
category
</string>
</key>
<value>
<string>
object_view
</string>
</value>
</item>
<item>
<key>
<string>
condition
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
icon
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
view
</string>
</value>
</item>
<item>
<key>
<string>
permissions
</string>
</key>
<value>
<tuple>
<string>
View
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
priority
</string>
</key>
<value>
<float>
1.0
</float>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string>
View
</string>
</value>
</item>
<item>
<key>
<string>
visible
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<global
name=
"Expression"
module=
"Products.CMFCore.Expression"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
text
</string>
</key>
<value>
<string>
string:${object_url}/Rule_view
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_packing_list_builder.xml
View file @
256bbd86
...
...
@@ -96,7 +96,7 @@
</item>
<item>
<key>
<string>
simulation_select_method_id
</string>
</key>
<value>
<string>
TransformationSourcingRule
_selectMovement
</string>
</value>
<value>
<string>
ProductionPackingList
_selectMovement
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
...
...
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_packing_list_builder/category_movement_group_on_delivery.xml
View file @
256bbd86
...
...
@@ -45,6 +45,7 @@
<string>
destination_project
</string>
<string>
source_payment
</string>
<string>
destination_payment
</string>
<string>
specialise
</string>
</tuple>
</value>
</item>
...
...
@@ -52,6 +53,10 @@
<key>
<string>
title
</string>
</key>
<value>
<string>
category_movement_group_on_delivery
</string>
</value>
</item>
<item>
<key>
<string>
update_always
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
</dictionary>
</pickle>
</record>
...
...
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_packing_list_builder/category_movement_group_on_line.xml
View file @
256bbd86
...
...
@@ -38,6 +38,10 @@
<value>
<tuple>
<string>
resource
</string>
<string>
base_contribution
</string>
<string>
base_application
</string>
<string>
industrial_phase
</string>
<string>
quantity_unit
</string>
</tuple>
</value>
</item>
...
...
@@ -45,6 +49,10 @@
<key>
<string>
title
</string>
</key>
<value>
<string>
category_movement_group_on_line
</string>
</value>
</item>
<item>
<key>
<string>
update_always
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
</dictionary>
</pickle>
</record>
...
...
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_report_builder.xml
View file @
256bbd86
...
...
@@ -96,7 +96,7 @@
</item>
<item>
<key>
<string>
simulation_select_method_id
</string>
</key>
<value>
<string>
TransformationRule
_selectMovement
</string>
</value>
<value>
<string>
ProductionReport
_selectMovement
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
...
...
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_report_builder/category_movement_group_on_delivery.xml
View file @
256bbd86
...
...
@@ -45,6 +45,7 @@
<string>
destination_project
</string>
<string>
source_payment
</string>
<string>
destination_payment
</string>
<string>
specialise
</string>
</tuple>
</value>
</item>
...
...
@@ -52,6 +53,10 @@
<key>
<string>
title
</string>
</key>
<value>
<string>
category_movement_group_on_delivery
</string>
</value>
</item>
<item>
<key>
<string>
update_always
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
</dictionary>
</pickle>
</record>
...
...
bt5/erp5_mrp/PathTemplateItem/portal_deliveries/production_report_builder/category_movement_group_on_line.xml
View file @
256bbd86
...
...
@@ -38,6 +38,10 @@
<value>
<tuple>
<string>
resource
</string>
<string>
base_contribution
</string>
<string>
base_application
</string>
<string>
industrial_phase
</string>
<string>
quantity_unit
</string>
</tuple>
</value>
</item>
...
...
@@ -45,6 +49,10 @@
<key>
<string>
title
</string>
</key>
<value>
<string>
category_movement_group_on_line
</string>
</value>
</item>
<item>
<key>
<string>
update_always
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
</dictionary>
</pickle>
</record>
...
...
bt5/erp5_mrp/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml
View file @
256bbd86
...
...
@@ -27,6 +27,10 @@
<portal_type
id=
"Production Report Module"
>
<item>
Production Report
</item>
</portal_type>
<portal_type
id=
"Rule Tool"
>
<item>
Transformation Simulation Rule
</item>
<item>
Transformation Sourcing Simulation Rule
</item>
</portal_type>
<portal_type
id=
"Supply Chain"
>
<item>
Supply Link
</item>
<item>
Supply Node
</item>
...
...
@@ -34,4 +38,24 @@
<portal_type
id=
"Supply Chain Module"
>
<item>
Supply Chain
</item>
</portal_type>
<portal_type
id=
"Transformation Simulation Rule"
>
<item>
Category Membership Divergence Tester
</item>
<item>
DateTime Divergence Tester
</item>
<item>
Float Divergence Tester
</item>
<item>
Mapped Property
</item>
<item>
Net Converted Quantity Divergence Tester
</item>
<item>
Specialise Divergence Tester
</item>
<item>
String Divergence Tester
</item>
<item>
Variation Divergence Tester
</item>
</portal_type>
<portal_type
id=
"Transformation Sourcing Simulation Rule"
>
<item>
Category Membership Divergence Tester
</item>
<item>
DateTime Divergence Tester
</item>
<item>
Float Divergence Tester
</item>
<item>
Mapped Property
</item>
<item>
Net Converted Quantity Divergence Tester
</item>
<item>
Specialise Divergence Tester
</item>
<item>
String Divergence Tester
</item>
<item>
Variation Divergence Tester
</item>
</portal_type>
</allowed_content_type_list>
\ No newline at end of file
bt5/erp5_mrp/PortalTypeTemplateItem/portal_types/Transformation%20Simulation%20Rule.xml
0 → 100644
View file @
256bbd86
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Base Type"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_property_domain_dict
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
short_title
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</string>
</persistent>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key>
<string>
acquire_local_roles
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
<item>
<key>
<string>
content_icon
</string>
</key>
<value>
<string>
rule_icon.gif
</string>
</value>
</item>
<item>
<key>
<string>
content_meta_type
</string>
</key>
<value>
<string>
ERP5 Transformation Simulation Rule
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
filter_content_types
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
<item>
<key>
<string>
group_list
</string>
</key>
<value>
<tuple>
<string>
rule
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Transformation Simulation Rule
</string>
</value>
</item>
<item>
<key>
<string>
init_script
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
permission
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
type_class
</string>
</key>
<value>
<string>
TransformationSimulationRule
</string>
</value>
</item>
<item>
<key>
<string>
type_interface
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
type_mixin
</string>
</key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<tuple>
<global
name=
"TranslationInformation"
module=
"Products.ERP5Type.TranslationProviderBase"
/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
domain_name
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
property_name
</string>
</key>
<value>
<string>
short_title
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"3"
aka=
"AAAAAAAAAAM="
>
<pickle>
<tuple>
<global
name=
"TranslationInformation"
module=
"Products.ERP5Type.TranslationProviderBase"
/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
domain_name
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
property_name
</string>
</key>
<value>
<string>
title
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_mrp/PortalTypeTemplateItem/portal_types/Transformation%20Sourcing%20Simulation%20Rule.xml
0 → 100644
View file @
256bbd86
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Base Type"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_property_domain_dict
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
short_title
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</string>
</persistent>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key>
<string>
acquire_local_roles
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
<item>
<key>
<string>
content_icon
</string>
</key>
<value>
<string>
rule_icon.gif
</string>
</value>
</item>
<item>
<key>
<string>
content_meta_type
</string>
</key>
<value>
<string>
ERP5 Transformation Sourcing Simulation Rule
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
filter_content_types
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
<item>
<key>
<string>
group_list
</string>
</key>
<value>
<tuple>
<string>
rule
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Transformation Sourcing Simulation Rule
</string>
</value>
</item>
<item>
<key>
<string>
init_script
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
permission
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
type_class
</string>
</key>
<value>
<string>
TransformationSourcingSimulationRule
</string>
</value>
</item>
<item>
<key>
<string>
type_interface
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
type_mixin
</string>
</key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<tuple>
<global
name=
"TranslationInformation"
module=
"Products.ERP5Type.TranslationProviderBase"
/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
domain_name
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
property_name
</string>
</key>
<value>
<string>
short_title
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"3"
aka=
"AAAAAAAAAAM="
>
<pickle>
<tuple>
<global
name=
"TranslationInformation"
module=
"Products.ERP5Type.TranslationProviderBase"
/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
domain_name
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
property_name
</string>
</key>
<value>
<string>
title
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_mrp/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
View file @
256bbd86
...
...
@@ -47,4 +47,12 @@
<type>
Supply Node
</type>
<workflow>
edit_workflow
</workflow>
</chain>
<chain>
<type>
Transformation Simulation Rule
</type>
<workflow>
edit_workflow, rule_validation_workflow
</workflow>
</chain>
<chain>
<type>
Transformation Sourcing Simulation Rule
</type>
<workflow>
edit_workflow, rule_validation_workflow
</workflow>
</chain>
</workflow_chain>
\ No newline at end of file
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/OrderLine_getResourceTransformationItemList.xml
View file @
256bbd86
...
...
@@ -50,26 +50,23 @@
</item>
<item>
<key>
<string>
_body
</string>
</key>
<value>
<string>
portal = context.getPortalObject()\n
from ZTUtils import LazyFilter\n
resource = context.getResourceValue()\n
<value>
<string>
resource = context.getResourceValue()\n
\n
result = []\n
\n
if include_empty:\n
result.append([\'\',\'\'])\n
if resource is None:\n
return result\n
result.append((\'\',\'\'))\n
\n
# XXX: Is it possible to use cache? Hook it on resource?\n
for transformation in LazyFilter(\n
resource.getResourceRelatedValueList(portal_type=portal.getPortalTransformationTypeList()),\n
skip=\'View\'\n
):\n
if not skip_invalidated or transformation.getProperty(\'validation_state\',\'default\') != \'invalidated\':\n
result.append( (transformation.getTitle(),transformation.getRelativeUrl()) )\n
if resource is not None:\n
portal = context.getPortalObject()\n
kw = {\'validation_state\': \'!=invalidated\'} if skip_invalidated else {}\n
result.extend((transformation.title, transformation.relative_url)\n
for transformation in portal.portal_catalog(\n
select_list=(\'title\', \'relative_url\'),\n
portal_type=portal.getPortalTransformationTypeList(),\n
strict_resource_uid=resource.getUid(),\n
sort_on=(\'title\', \'relative_url\'),\n
**kw))\n
\n
result.sort(key=lambda x: x[0])\n
return result\n
</string>
</value>
</item>
...
...
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/ProductionDelivery_copyOrderProperties.xml
View file @
256bbd86
...
...
@@ -50,25 +50,14 @@
</item>
<item>
<key>
<string>
_body
</string>
</key>
<value>
<string>
packing_list = context\n
<value>
<string>
if context.getSimulationState() == \'draft\':\n
order = context.getCausalityValue()\n
context.edit(\n
comment=order.getComment(),\n
title=order.getTitle(),\n
)\n
\n
tag = packing_list.getPath() + \'_confirm\'\n
\n
# First, copy Order properties\n
related_order = packing_list.getCausalityValue()\n
packing_list.edit(\n
comment=related_order.getComment(),\n
delivery_mode=related_order.getDeliveryMode(),\n
incoterm=related_order.getIncoterm(),\n
destination_administration_value=\\\n
related_order.getDestinationAdministrationValue(),\n
activate_kw={\'tag\':tag},\n
)\n
\n
packing_list.startBuilding()\n
packing_list.activate(after_tag=tag).updateCausalityState()\n
\n
packing_list.activate(after_tag=tag).ProductionDelivery_confirm()\n
context.Delivery_confirm()\n
</string>
</value>
</item>
<item>
...
...
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/
TransformationRule
_selectMovement.xml
→
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/
ProductionPackingList
_selectMovement.xml
View file @
256bbd86
...
...
@@ -50,48 +50,24 @@
</item>
<item>
<key>
<string>
_body
</string>
</key>
<value>
<string>
kw[\'explanation_portal_type\'] = \'Production Order\'\n
kw[\'parent_specialise_portal_type\'] = \'Transformation Rule\'\n
kw[\'grand_parent_simulation_state\'] = \'confirmed\'\n
\n
kw[\'delivery_uid\'] = None\n
kw[\'left_join_list\'] = [\'delivery_uid\']\n
kw[\'select_dict\'] = dict(delivery_uid=None)\n
kw[\'group_by\'] = (\'uid\',)\n
\n
kw[\'src__\'] = src__ \n
result = context.portal_catalog(**kw)\n
if src__:\n
result\n
\n
movement_list = []\n
for movement in result:\n
movement = movement.getObject()\n
root_movement = movement.getRootSimulationMovement()\n
root_rule = root_movement.getParentValue().getSpecialiseValue()\n
if root_rule.getPortalType() in ("Production Order Rule",\n
"Production Order Root Simulation Rule") \\\n
and root_movement.getSimulationState() == "confirmed":\n
movement_list.append(movement)\n
\n
return movement_list\n
<value>
<string>
return context.portal_catalog(\n
explanation_portal_type="Production Order",\n
parent_specialise_portal_type=("Delivery Simulation Rule",\n
"Transformation Sourcing Simulation Rule"),\n
delivery_uid=None,\n
left_join_list=("delivery_uid",),\n
select_list=("delivery_uid",),\n
group_by=("uid",),\n
**kw)\n
</string>
</value>
</item>
<item>
<key>
<string>
_params
</string>
</key>
<value>
<string>
src__=0, **kw
</string>
</value>
</item>
<item>
<key>
<string>
_proxy_roles
</string>
</key>
<value>
<tuple>
<string>
Manager
</string>
</tuple>
</value>
<value>
<string>
**kw
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
TransformationRule
_selectMovement
</string>
</value>
<value>
<string>
ProductionPackingList
_selectMovement
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
...
...
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/Production
Delivery_confirm
.xml
→
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/Production
Report_selectMovement
.xml
View file @
256bbd86
...
...
@@ -50,24 +50,27 @@
</item>
<item>
<key>
<string>
_body
</string>
</key>
<value>
<string>
from Products.ERP5Type.Message import Message\n
packing_list = context\n
\n
packing_list_state = packing_list.getSimulationState()\n
if packing_list_state == "draft":\n
packing_list.portal_workflow.doActionFor(\n
packing_list,\n
\'confirm_action\',\n
comment=Message(\'erp5_ui\', \'Initialised by Delivery Builder\'))\n
<value>
<string>
return context.portal_catalog(\n
explanation_portal_type="Production Order",\n
parent_specialise_portal_type="Transformation Simulation Rule",\n
delivery_uid=None,\n
left_join_list=("delivery_uid",),\n
select_list=("delivery_uid",),\n
group_by=("uid",),\n
**kw)\n
</string>
</value>
</item>
<item>
<key>
<string>
_params
</string>
</key>
<value>
<string></string>
</value>
<value>
<string>
**kw
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
ProductionDelivery_confirm
</string>
</value>
<value>
<string>
ProductionReport_selectMovement
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string></string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/
TransformationSourcingRule_selectMovement
.xml
→
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/
SimulationMovement_testTransformationSimulationRule
.xml
View file @
256bbd86
...
...
@@ -50,55 +50,24 @@
</item>
<item>
<key>
<string>
_body
</string>
</key>
<value>
<string>
kw[\'explanation_portal_type\'] = \'Production Order\'\n
<value>
<string>
specialise_list = context.getSpecialiseValueList(portal_type="Transformation")\n
if (len(specialise_list) == 1 and\n
context.getResource() == specialise_list[0].getResource()):\n
parent = context.getParentValue()\n
if parent.getSpecialiseValue().getPortalType() == "Delivery Simulation Rule":\n
movement = context.getParentValue().getDeliveryValue()\n
\n
kw[\'delivery_uid\'] = None\n
kw[\'left_join_list\'] = [\'delivery_uid\']\n
kw[\'select_dict\'] = dict(delivery_uid=None)\n
kw[\'group_by\'] = (\'uid\',)\n
\n
kw[\'src__\'] = src__ \n
result = context.portal_catalog(**kw)\n
if src__:\n
result\n
\n
movement_list = []\n
for movement in result:\n
movement = movement.getObject()\n
root_movement = movement.getRootSimulationMovement()\n
root_type = root_movement.getParentValue().getSpecialiseValue().getPortalType()\n
parent_type = movement.getParentValue().getSpecialiseValue().getPortalType()\n
if (root_type == "Production Order Rule" and\n
parent_type in ("Transformation Sourcing Rule",\n
"Production Order Rule") or\n
root_type == "Production Order Root Simulation Rule" and\n
parent_type in ("Transformation Sourcing Rule",\n
"Delivery Simulation Rule")) \\\n
and root_movement.getSimulationState() == "confirmed":\n
movement_list.append(movement)\n
\n
return movement_list\n
return movement is not None and movement.getPortalType() in (\n
"Production Order Line", "Production Order Cell")\n
</string>
</value>
</item>
<item>
<key>
<string>
_params
</string>
</key>
<value>
<string>
src__=0, **kw
</string>
</value>
</item>
<item>
<key>
<string>
_proxy_roles
</string>
</key>
<value>
<tuple>
<string>
Manager
</string>
</tuple>
</value>
<value>
<string>
rule
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
TransformationSourcingRule_selectMovement
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string></string>
</value>
<value>
<string>
SimulationMovement_testTransformationSimulationRule
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/
ProductionOrder_getRuleReferenc
e.xml
→
bt5/erp5_mrp/SkinTemplateItem/portal_skins/erp5_mrp/
SimulationMovement_testTransformationSourcingSimulationRul
e.xml
View file @
256bbd86
...
...
@@ -50,16 +50,18 @@
</item>
<item>
<key>
<string>
_body
</string>
</key>
<value>
<string>
return \'default_production_order_rule\'\n
<value>
<string>
rule = context.getParentValue().getSpecialiseValue()\n
return rule.getPortalType() == "Transformation Simulation Rule" \\\n
and rule.testTransformationSourcing(context)\n
</string>
</value>
</item>
<item>
<key>
<string>
_params
</string>
</key>
<value>
<string></string>
</value>
<value>
<string>
rule
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
ProductionOrder_getRuleReferenc
e
</string>
</value>
<value>
<string>
SimulationMovement_testTransformationSourcingSimulationRul
e
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_mrp/bt/template_action_path_list
View file @
256bbd86
...
...
@@ -37,3 +37,5 @@ Supply Chain | view
Supply Chain | view_supply_node
Supply Link | view
Supply Node | view
Transformation Simulation Rule | view
Transformation Sourcing Simulation Rule | view
\ No newline at end of file
bt5/erp5_mrp/bt/template_portal_type_allowed_content_type_list
View file @
256bbd86
...
...
@@ -8,6 +8,24 @@ Production Packing List | Production Packing List Line
Production Report Line | Production Report Cell
Production Report Module | Production Report
Production Report | Production Report Line
Rule Tool | Transformation Simulation Rule
Rule Tool | Transformation Sourcing Simulation Rule
Supply Chain Module | Supply Chain
Supply Chain | Supply Link
Supply Chain | Supply Node
Transformation Simulation Rule | Category Membership Divergence Tester
Transformation Simulation Rule | DateTime Divergence Tester
Transformation Simulation Rule | Float Divergence Tester
Transformation Simulation Rule | Mapped Property
Transformation Simulation Rule | Net Converted Quantity Divergence Tester
Transformation Simulation Rule | Specialise Divergence Tester
Transformation Simulation Rule | String Divergence Tester
Transformation Simulation Rule | Variation Divergence Tester
Transformation Sourcing Simulation Rule | Category Membership Divergence Tester
Transformation Sourcing Simulation Rule | DateTime Divergence Tester
Transformation Sourcing Simulation Rule | Float Divergence Tester
Transformation Sourcing Simulation Rule | Mapped Property
Transformation Sourcing Simulation Rule | Net Converted Quantity Divergence Tester
Transformation Sourcing Simulation Rule | Specialise Divergence Tester
Transformation Sourcing Simulation Rule | String Divergence Tester
Transformation Sourcing Simulation Rule | Variation Divergence Tester
\ No newline at end of file
bt5/erp5_mrp/bt/template_portal_type_id_list
View file @
256bbd86
...
...
@@ -14,3 +14,5 @@ Supply Chain
Supply Chain Module
Supply Link
Supply Node
Transformation Simulation Rule
Transformation Sourcing Simulation Rule
\ No newline at end of file
bt5/erp5_mrp/bt/template_portal_type_workflow_chain_list
View file @
256bbd86
...
...
@@ -37,3 +37,7 @@ Supply Chain | edit_workflow
Supply Chain | validation_workflow
Supply Link | edit_workflow
Supply Node | edit_workflow
Transformation Simulation Rule | edit_workflow
Transformation Simulation Rule | rule_validation_workflow
Transformation Sourcing Simulation Rule | edit_workflow
Transformation Sourcing Simulation Rule | rule_validation_workflow
\ No newline at end of file
product/ERP5/Document/Amount.py
View file @
256bbd86
...
...
@@ -28,6 +28,7 @@
##############################################################################
import
zope.interface
from
collections
import
defaultdict
from
math
import
log
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5.mixin.variated
import
VariatedMixin
...
...
@@ -85,19 +86,15 @@ class Amount(Base, VariatedMixin):
" omit_option_base_category."
,
DeprecationWarning
)
omit_optional_variation
=
omit_option_base_category
result
=
[]
resource
=
self
.
getDefaultResourceValue
()
if
resource
is
not
None
:
resource_variation_list
=
resource
.
getVariationBaseCategoryList
(
if
resource
is
None
:
return
[]
variation_list
=
resource
.
getVariationBaseCategoryList
(
omit_optional_variation
=
omit_optional_variation
)
if
len
(
base_category_list
)
>
0
:
variation_list
=
filter
(
lambda
x
:
x
in
base_category_list
,
resource_variation_list
)
else
:
variation_list
=
resource_variation_list
if
len
(
variation_list
)
>
0
:
result
=
self
.
getAcquiredCategoryMembershipList
(
variation_list
,
base
=
1
)
return
result
variation_list
.
append
(
'industrial_phase'
)
if
base_category_list
:
variation_list
=
filter
(
base_category_list
.
__contains__
,
variation_list
)
return
self
.
getAcquiredCategoryMembershipList
(
variation_list
,
base
=
1
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getVariationCategoryItemList'
)
...
...
@@ -110,43 +107,32 @@ class Amount(Base, VariatedMixin):
Result is left display.
"""
variation_category_item_list
=
[]
if
base_category_list
==
():
base_category_list
=
self
.
getVariationRangeBaseCategoryList
()
for
base_category
in
base_category_list
:
variation_category_list
=
self
.
getVariationCategoryList
(
base_category_list
=
[
base_category
])
resource_list
=
[
self
.
portal_categories
.
resolveCategory
(
x
)
for
x
in
\
variation_category_list
]
category_list
=
[
x
for
x
in
resource_list
\
if
x
.
getPortalType
()
==
'Category'
]
variation_category_item_list
.
extend
(
Renderer
(
is_right_display
=
0
,
display_none_category
=
0
,
base
=
base
,
current_category
=
current_category
,
display_id
=
display_id
,
**
kw
).
\
render
(
category_list
))
object_list
=
[
x
for
x
in
resource_list
\
if
x
.
getPortalType
()
!=
'Category'
]
variation_category_item_list
.
extend
(
Renderer
(
is_right_display
=
0
,
base_category
=
base_category
,
display_none_category
=
0
,
base
=
base
,
current_category
=
current_category
,
display_id
=
'title'
,
**
kw
).
\
render
(
object_list
))
category_list
=
self
.
getVariationCategoryList
()
if
category_list
:
variation_dict
=
defaultdict
(
lambda
:
([],
[]))
resolveCategory
=
self
.
getPortalObject
().
portal_categories
.
resolveCategory
for
category
in
category_list
:
resource
=
resolveCategory
(
category
)
variation_dict
[
category
.
split
(
'/'
,
1
)[
0
]]
\
[
resource
.
getPortalType
()
==
'Category'
].
append
(
resource
)
kw
=
dict
(
is_right_display
=
0
,
display_none_category
=
0
,
base
=
base
,
current_category
=
current_category
,
**
kw
)
render_category_list
=
Renderer
(
display_id
=
display_id
,
**
kw
).
render
kw
[
'display_id'
]
=
'title'
for
base_category
,
(
object_list
,
category_list
)
in
variation_dict
.
iteritems
():
variation_category_item_list
+=
render_category_list
(
category_list
)
variation_category_item_list
+=
Renderer
(
base_category
=
base_category
,
**
kw
).
render
(
object_list
)
return
variation_category_item_list
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'_setVariationCategoryList'
)
def
_setVariationCategoryList
(
self
,
value
):
result
=
[]
resource
=
self
.
getDefaultResourceValue
()
if
resource
is
not
None
:
variation_list
=
resource
.
getVariationBaseCategoryList
()
if
len
(
variation_list
)
>
0
:
self
.
_setCategoryMembership
(
variation_list
,
value
,
base
=
1
)
variation_list
.
append
(
'industrial_phase'
)
self
.
_setCategoryMembership
(
variation_list
,
value
,
base
=
1
)
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'setVariationCategoryList'
)
...
...
@@ -209,7 +195,6 @@ class Amount(Base, VariatedMixin):
"""
return
VariationValue
(
context
=
self
)
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'_setVariationValue'
)
def
_setVariationValue
(
self
,
variation_value
):
return
variation_value
.
setVariationValue
(
self
)
...
...
product/ERP5/Document/BusinessProcess.py
View file @
256bbd86
...
...
@@ -28,6 +28,7 @@
#
##############################################################################
from
collections
import
defaultdict
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5Type.TransactionalVariable
import
getTransactionalVariable
...
...
@@ -845,3 +846,41 @@ class BusinessProcess(Path, XMLObject):
"""
for
business_link
in
self
.
getBuildableBusinessLinkValueList
(
explanation
):
business_link
.
build
(
explanation
=
explanation
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getPreviousTradePhaseDict'
)
def
getPreviousTradePhaseDict
(
self
,
trade_phase_list
=
None
):
"""Return a dict mapping each phase to a set of previous ones
If trade_phase_list is given, the return graph is reduced to only keep
phases in this list.
"""
state_dict
=
defaultdict
(
set
)
phase_list
=
[]
for
link
in
self
.
getBusinessLinkValueList
(
sort_on
=
None
):
phase
,
=
link
.
getTradePhaseList
()
# BL must have exactly 1 TP
phase_list
.
append
((
phase
,
link
.
getPredecessor
()))
state_dict
[
link
.
getSuccessor
()].
add
(
phase
)
result
=
dict
((
phase
,
state_dict
[
state
])
for
phase
,
state
in
phase_list
)
if
trade_phase_list
:
# reduce graph
next_dict
=
defaultdict
(
set
)
# build {phase: next_set} (i.e. reverse result)
for
next
,
phase_set
in
result
.
iteritems
():
for
phase
in
phase_set
:
next_dict
[
phase
].
add
(
next
)
# for each phase to remove
for
phase
in
set
(
result
).
difference
(
trade_phase_list
):
# edit the graph like we would do for a doubly linked list
previous_set
=
result
.
pop
(
phase
)
next_set
=
next_dict
[
phase
]
# i.e. edit next phases to replace current phase by previous ones
for
next
in
next_set
:
phase_set
=
result
[
next
]
phase_set
.
remove
(
phase
)
phase_set
|=
previous_set
# and previous phases to replace current by next ones
for
previous
in
previous_set
:
phase_set
=
next_dict
[
previous
]
phase_set
.
remove
(
phase
)
phase_set
|=
next_set
return
result
product/ERP5/Document/TradeModelSimulationRule.py
View file @
256bbd86
...
...
@@ -86,13 +86,10 @@ class TradeModelRuleMovementGenerator(MovementGeneratorMixin):
def
_getInputMovementList
(
self
,
movement_list
=
None
,
rounding
=
False
):
simulation_movement
=
self
.
_applied_rule
.
getParentValue
()
portal
=
self
.
_applied_rule
.
getPortalObject
()
# List of types passed to simulation_movemet.asComposedDocument()
# it needs to include portal types of all 'amount_generator*' groups:
composition_type_list
=
(
portal
.
getPortalAmountGeneratorTypeList
()
+
portal
.
getPortalAmountGeneratorLineTypeList
()
+
portal
.
getPortalAmountGeneratorCellTypeList
())
amount_list
=
simulation_movement
.
getAggregatedAmountList
(
amount_generator_type_list
=
composition_type_list
)
# List of types passed to simulation_movement.asComposedDocument()
# it needs to include portal types of all 'amount_generator*' groups:
amount_generator_type_list
=
portal
.
getPortalAmountGeneratorAllTypeList
(
0
))
input_movement
=
aq_base
(
simulation_movement
).
__of__
(
self
.
_applied_rule
)
for
amount
in
amount_list
:
# Do not ignore amount with price = 0 (such behaviour can be obtained by
...
...
product/ERP5/Document/TransformationSimulationRule.py
0 → 100644
View file @
256bbd86
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2014 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Acquisition
import
aq_base
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5Type.TransactionalVariable
import
getTransactionalVariable
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
class
TransformationSimulationRule
(
RuleMixin
,
MovementCollectionUpdaterMixin
):
"""
"""
# CMF Type Definition
meta_type
=
'ERP5 Transformation Simulation Rule'
portal_type
=
'Transformation Simulation Rule'
# Declarative security
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
# Default Properties
property_sheets
=
(
PropertySheet
.
Base
,
PropertySheet
.
XMLObject
,
PropertySheet
.
CategoryCore
,
PropertySheet
.
DublinCore
,
PropertySheet
.
Task
,
PropertySheet
.
Predicate
,
PropertySheet
.
Reference
,
PropertySheet
.
Version
,
PropertySheet
.
Rule
)
def
_getMovementGenerator
(
self
,
context
):
"""
Return the movement generator to use in the expand process
"""
return
TransformationRuleMovementGenerator
(
applied_rule
=
context
,
rule
=
self
)
def
testTransformationSourcing
(
self
,
context
):
if
context
.
getReference
().
split
(
'/'
,
1
)[
0
]
==
'pr'
:
return
False
# context consumes a resource: maybe sourcing is required.
# Let's see if the business process defines any trade phase that:
# - is not yet expanded (well, we only checks parents and siblings)
# - and precedes a phase of the current transformation
phase
=
context
.
getTradePhase
()
parent
=
context
.
getParentValue
()
tv
=
getTransactionalVariable
()
key
=
'isSourcingNeeded'
,
parent
.
getUid
()
try
:
needed_set
=
tv
[
key
]
except
KeyError
:
phase_set
=
set
(
x
.
getTradePhase
()
for
x
in
parent
.
objectValues
())
phase_list
=
phase_set
.
copy
()
movement
=
parent
.
getParentValue
()
while
movement
.
getPortalType
()
==
'Simulation Movement'
:
phase_set
.
add
(
movement
.
getTradePhase
())
movement
=
movement
.
getParentValue
().
getParentValue
()
previous_dict
=
context
.
asComposedDocument
().
getPreviousTradePhaseDict
()
needed_set
=
tv
[
key
]
=
frozenset
(
x
for
x
in
phase_list
if
previous_dict
[
x
]
-
phase_set
)
return
phase
in
needed_set
class
TransformationRuleMovementGenerator
(
MovementGeneratorMixin
):
def
_getUpdatePropertyDict
(
self
,
input_movement
):
return
{}
def
_getInputMovementList
(
self
,
movement_list
=
None
,
rounding
=
None
):
parent_movement
=
self
.
_applied_rule
.
getParentValue
()
portal
=
self
.
_applied_rule
.
getPortalObject
()
amount_list
=
parent_movement
.
getAggregatedAmountList
(
amount_generator_type_list
=
portal
.
getPortalAmountGeneratorAllTypeList
(
1
))
arrow_list
=
[
'destination'
+
x
[
6
:]
for
x
in
parent_movement
.
getCategoryMembershipList
(
(
'source'
,
'source_section'
),
base
=
True
)]
def
newMovement
(
reference
,
kw
=
{}):
movement
=
aq_base
(
parent_movement
.
asContext
(
**
kw
)).
__of__
(
self
.
_applied_rule
)
movement
.
_setReference
(
reference
)
movement
.
_setCategoryMembership
((
'destination'
,
'source_section'
,
'destination_section'
,
'source'
),
arrow_list
,
base
=
True
)
return
movement
phase_set
=
set
()
for
amount
in
amount_list
:
# Do not ignore amount with price = 0 (such behaviour can be obtained by
# specifying a predicate on the amount generator line/cell).
if
amount
.
getResource
():
phase_set
.
add
(
amount
.
getTradePhase
())
# FIXME: Is it the right way to have source/destination and other
# non-Amount properties set on the generated movement ?
movement
=
newMovement
(
amount
.
getCausality
(),
dict
((
k
,
v
)
for
k
,
v
in
amount
.
__dict__
.
iteritems
()
if
k
[
0
]
!=
'_'
and
k
!=
'categories'
))
base_category_set
=
set
(
amount
.
getBaseCategoryList
())
base_category_set
.
remove
(
'price_currency'
)
# XXX
movement
.
_setCategoryMembership
(
base_category_set
,
amount
.
getCategoryList
(),
base
=
True
)
movement
.
quantity
=
-
movement
.
quantity
yield
movement
phase_dict
=
parent_movement
.
asComposedDocument
()
\
.
getPreviousTradePhaseDict
(
phase_set
)
final_set
=
phase_set
.
copy
()
previous_set
=
final_set
.
copy
()
while
previous_set
:
phase_list
=
phase_dict
[
previous_set
.
pop
()]
final_set
.
difference_update
(
phase_list
)
previous_set
.
update
(
phase_list
)
# We should not need an option not to generate movements for intermediate
# resources. This can be configured on Trade Model Paths by filtering out
# movement with an industrial_phase (other properties like reference
# starting with "pr/" is possible). The drawback with such filter is that
# Same Total Quantity check must be disabled.
if
1
:
cr_quantity
=
-
parent_movement
.
getQuantity
()
def
newIntermediateMovement
(
reference_prefix
,
industrial_phase
,
**
kw
):
movement
=
newMovement
(
reference_prefix
+
phase
,
kw
)
movement
.
_setTradePhase
(
phase
)
movement
.
_setIndustrialPhase
(
'trade_phase/'
+
industrial_phase
)
return
movement
for
phase
in
phase_set
:
for
previous
in
phase_dict
[
phase
]:
yield
newIntermediateMovement
(
'cr/'
,
previous
,
quantity
=
cr_quantity
)
if
phase
not
in
final_set
:
yield
newIntermediateMovement
(
'pr/'
,
phase
)
movement
=
newMovement
(
'pr'
)
movement
.
_setTradePhaseList
(
final_set
)
yield
movement
product/ERP5/Document/TransformationSourcingSimulationRule.py
0 → 100644
View file @
256bbd86
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2014 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Acquisition
import
aq_base
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
class
TransformationSourcingSimulationRule
(
RuleMixin
,
MovementCollectionUpdaterMixin
):
"""
Transformation Sourcing Rule makes sure
items required in a Transformation are sourced.
"""
# CMF Type Definition
meta_type
=
'ERP5 Transformation Sourcing Simulation Rule'
portal_type
=
'Transformation Sourcing Simulation Rule'
# Declarative security
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
# Default Properties
property_sheets
=
(
PropertySheet
.
Base
,
PropertySheet
.
XMLObject
,
PropertySheet
.
CategoryCore
,
PropertySheet
.
DublinCore
,
PropertySheet
.
Task
,
PropertySheet
.
Predicate
,
PropertySheet
.
Reference
,
PropertySheet
.
Version
,
PropertySheet
.
Rule
)
def
_getMovementGenerator
(
self
,
context
):
"""
Return the movement generator to use in the expand process
"""
return
TransformationSourcingRuleMovementGenerator
(
applied_rule
=
context
,
rule
=
self
)
class
TransformationSourcingRuleMovementGenerator
(
MovementGeneratorMixin
):
def
_getUpdatePropertyDict
(
self
,
input_movement
):
return
{}
def
_getInputMovementList
(
self
,
movement_list
=
None
,
rounding
=
None
):
parent_movement
=
self
.
_applied_rule
.
getParentValue
()
phase_dict
=
parent_movement
.
asComposedDocument
()
\
.
getPreviousTradePhaseDict
()
movement
=
aq_base
(
parent_movement
).
__of__
(
self
.
_applied_rule
)
movement
=
movement
.
asContext
(
quantity
=-
movement
.
getQuantity
())
movement
.
_setReference
(
None
)
movement
.
_setTradePhaseList
(
phase_dict
[
parent_movement
.
getTradePhase
()])
if
parent_movement
.
getReference
().
startswith
(
'cr/'
):
# For partially produced resources, automatically guess source from other
# movements of the transformation. This avoids duplicate information
# on Trade Model Paths.
# 'here/getSource' condition can be used to match such movements.
# The opposite condition can be used to match raw materials.
reference
=
'pr'
+
parent_movement
.
getIndustrialPhase
()[
11
:]
for
pr
in
parent_movement
.
getParentValue
().
objectValues
():
if
pr
.
getReference
()
==
reference
:
movement
.
_setSource
(
pr
.
getDestination
())
movement
.
_setSourceSection
(
pr
.
getDestinationSection
())
break
return
movement
,
product/ERP5/ERP5Site.py
View file @
256bbd86
...
...
@@ -1419,6 +1419,20 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
"""
return
self
.
_getPortalGroupedTypeList
(
'amount_generator_cell'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getPortalAmountGeneratorAllTypeList'
)
def
getPortalAmountGeneratorAllTypeList
(
self
,
transformation
):
"""
Return amount generator types, including lines & cells,
but only or without those related to transformations.
"""
result
=
list
(
self
.
getPortalAmountGeneratorTypeList
())
result
+=
self
.
getPortalAmountGeneratorLineTypeList
()
result
+=
self
.
getPortalAmountGeneratorCellTypeList
()
if
transformation
:
return
tuple
(
x
for
x
in
result
if
x
.
startswith
(
'Transformation'
))
return
tuple
(
x
for
x
in
result
if
not
x
.
startswith
(
'Transformation'
))
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getPortalBusinessProcessTypeList'
)
def
getPortalBusinessProcessTypeList
(
self
):
...
...
product/ERP5/tests/testMRP.py
View file @
256bbd86
...
...
@@ -27,90 +27,102 @@
##############################################################################
import
unittest
from
Products.ERP5Type.tests.ERP5TypeTestCase
import
ERP5TypeTestCase
from
DateTime
import
DateTime
from
Products.CMFCore.utils
import
getToolByName
from
Products.ERP5Type.tests.utils
import
reindex
from
Products.ERP5Type.tests.ERP5TypeTestCase
import
ERP5TypeTestCase
from
Products.ERP5.tests.testBPMCore
import
TestBPMMixin
from
Products.ERP5Type.tests.backportUnittest
import
skip
from
Products.ERP5.tests.utils
import
newSimulationExpectedFailure
class
TestMRPMixin
(
TestBPMMixin
):
transformation_portal_type
=
'Transformation'
transformed_resource_portal_type
=
'Transformation Transformed Resource'
product_portal_type
=
'Product'
organisation_portal_type
=
'Organisation'
order_portal_type
=
'Production Order'
order_line_portal_type
=
'Production Order Line'
def
afterSetUp
(
self
):
super
(
TestMRPMixin
,
self
).
afterSetUp
()
self
.
_createRule
(
"Transformation Simulation Rule"
)
rule
=
self
.
_createRule
(
"Transformation Sourcing Simulation Rule"
)
rule
.
_setSameTotalQuantity
(
False
)
def
getBusinessTemplateList
(
self
):
return
TestBPMMixin
.
getBusinessTemplateList
(
self
)
+
(
'erp5_mrp'
,
)
def
invalidateRules
(
self
):
"""
do reversely of validateRules
"""
rule_tool
=
self
.
getRuleTool
()
for
rule
in
rule_tool
.
contentValues
(
portal_type
=
rule_tool
.
getPortalRuleTypeList
()):
if
rule
.
getValidationState
()
==
'validated'
:
rule
.
invalidate
()
def
_createRule
(
self
,
portal_type
):
x
=
portal_type
.
replace
(
' Simulation '
,
' '
).
replace
(
' '
,
'_'
).
lower
()
reference
=
"default_"
+
x
id
=
"testMRP_"
+
x
rule_tool
=
self
.
portal
.
portal_rules
try
:
rule
=
self
.
getRule
(
reference
=
reference
)
self
.
assertEqual
(
rule
.
getId
(),
id
)
except
IndexError
:
rule
=
rule_tool
.
newContent
(
id
,
portal_type
,
reference
=
reference
,
test_method_id
=
"SimulationMovement_test"
+
portal_type
.
replace
(
' '
,
''
))
def
newTester
(
p
,
t
,
**
kw
):
kw
.
setdefault
(
"tested_property"
,
(
p
,))
return
rule
.
newContent
(
p
+
"_tester"
,
t
+
" Divergence Tester"
,
title
=
p
+
" divergence tester"
,
**
kw
)
for
x
in
(
"aggregate"
,
"base_application"
,
"base_contribution"
,
"destination_section"
,
"destination"
,
"price_currency"
,
"resource"
,
"source_section"
,
"source"
,
"use"
):
newTester
(
x
,
"Category Membership"
)
for
x
in
(
"start_date"
,
"stop_date"
):
newTester
(
x
,
"DateTime"
)
newTester
(
"price"
,
"Float"
)
newTester
(
"quantity"
,
"Net Converted Quantity"
,
tested_property
=
(
"quantity"
,
"quantity_unit"
))
newTester
(
"specialise"
,
"Specialise"
)
newTester
(
"variation"
,
"Variation"
,
tested_property
=
(
"variation_category_list"
,
"variation_property_dict"
))
newTester
(
"reference"
,
"String"
,
matching_provider
=
1
,
divergence_provider
=
0
)
if
rule
.
getValidationState
()
!=
'validated'
:
rule
.
validate
()
return
rule
def
_createDocument
(
self
,
portal_type
,
**
kw
):
module
=
self
.
portal
.
getDefaultModule
(
portal_type
=
portal_type
)
return
self
.
_createObject
(
module
,
portal_type
,
**
kw
)
def
_createObject
(
self
,
parent
,
portal_type
,
id
=
None
,
**
kw
):
o
=
None
if
id
is
not
None
:
o
=
parent
.
get
(
str
(
id
),
None
)
if
o
is
None
:
o
=
parent
.
newContent
(
portal_type
=
portal_type
)
o
.
edit
(
**
kw
)
return
o
return
self
.
portal
.
getDefaultModule
(
portal_type
=
portal_type
).
newContent
(
portal_type
=
portal_type
,
**
kw
)
def
createTransformation
(
self
,
**
kw
):
return
self
.
_createDocument
(
self
.
transformation_portal_type
,
**
kw
)
return
self
.
_createDocument
(
'Transformation'
,
**
kw
)
def
createProduct
(
self
,
**
kw
):
return
self
.
_createDocument
(
self
.
product_portal_type
,
**
kw
)
return
self
.
_createDocument
(
'Product'
,
**
kw
)
def
create
Organisation
(
self
,
**
kw
):
return
self
.
_createDocument
(
self
.
organisation_portal_type
,
**
kw
)
def
create
Node
(
self
,
**
kw
):
return
self
.
_createDocument
(
'Organisation'
,
**
kw
)
def
createOrder
(
self
,
**
kw
):
return
self
.
_createDocument
(
self
.
order_portal_type
,
**
kw
)
return
self
.
_createDocument
(
'Production Order'
,
**
kw
)
def
createOrderLine
(
self
,
order
,
**
kw
):
return
self
.
_createObject
(
order
,
self
.
order_line_portal_type
,
**
kw
)
return
order
.
newContent
(
portal_type
=
order
.
getPortalType
()
+
' Line'
,
**
kw
)
def
createTransformedResource
(
self
,
transformation
,
**
kw
):
return
self
.
_createObject
(
transformation
,
self
.
transformed_resource_portal_type
,
**
kw
)
return
transformation
.
newContent
(
portal_type
=
'Transformation Transformed Resource'
,
**
kw
)
@
reindex
def
createCategories
(
self
):
category_tool
=
getToolByName
(
self
.
portal
,
'portal_categories'
)
self
.
createCategoriesInCategory
(
category_tool
.
base_amoun
t
,
[
'weight'
])
self
.
createCategoriesInCategory
(
category_tool
.
base_amoun
t
.
weight
,
[
'kg'
])
category_tool
=
self
.
portal
.
portal_categories
self
.
createCategoriesInCategory
(
category_tool
.
quantity_uni
t
,
[
'weight'
])
self
.
createCategoriesInCategory
(
category_tool
.
quantity_uni
t
.
weight
,
[
'kg'
])
self
.
createCategoriesInCategory
(
category_tool
.
trade_phase
,
[
'mrp'
,])
self
.
createCategoriesInCategory
(
category_tool
.
trade_phase
.
mrp
,
[
'p'
+
str
(
i
)
for
i
in
range
(
5
)])
# phase0 ~ 4
(
'p'
+
str
(
i
)
for
i
in
xrange
(
2
)))
self
.
createCategoriesInCategory
(
category_tool
.
trade_phase
.
mrp
,
(
's'
+
str
(
i
)
for
i
in
xrange
(
1
)))
self
.
createCategoriesInCategory
(
category_tool
.
trade_state
,
(
'ready'
,
'partial'
,
'done'
))
(
's'
+
str
(
i
)
for
i
in
xrange
(
5
)
))
@
reindex
def
createDefaultOrder
(
self
,
transformation
=
None
,
business_process
=
None
):
def
createDefaultOrder
(
self
,
business_process
,
transformation
=
None
):
if
transformation
is
None
:
transformation
=
self
.
createDefaultTransformation
()
if
business_process
is
None
:
business_process
=
self
.
createSimpleBusinessProcess
()
base_date
=
DateTime
()
order
=
self
.
createOrder
(
specialise_value
=
business_process
,
start_date
=
base_date
,
stop_date
=
base_date
+
3
)
...
...
@@ -118,390 +130,166 @@ class TestMRPMixin(TestBPMMixin):
quantity
=
10
,
resource
=
transformation
.
getResource
(),
specialise_value
=
transformation
)
# XXX in some case, specialise_value is not related to order_line by edit,
# but by setSpecialise() is ok, Why?
order_line
.
setSpecialiseValue
(
transformation
)
return
order
@
reindex
def
createDefaultTransformation
(
self
):
resource1
=
self
.
createProduct
(
id
=
'1'
,
quantity_unit_list
=
[
'weight/kg'
])
resource2
=
self
.
createProduct
(
id
=
'2'
,
quantity_unit_list
=
[
'weight/kg'
])
resource3
=
self
.
createProduct
(
id
=
'3'
,
quantity_unit_list
=
[
'weight/kg'
])
resource4
=
self
.
createProduct
(
id
=
'4'
,
quantity_unit_list
=
[
'weight/kg'
])
resource5
=
self
.
createProduct
(
id
=
'5'
,
quantity_unit_list
=
[
'weight/kg'
])
transformation
=
self
.
createTransformation
(
resource_value
=
resource5
)
resource
=
lambda
:
self
.
createProduct
(
quantity_unit_list
=
[
'weight/kg'
])
transformation
=
self
.
createTransformation
(
resource_value
=
resource
())
self
.
createTransformedResource
(
transformation
=
transformation
,
resource_value
=
resource
1
,
resource_value
=
resource
()
,
quantity
=
3
,
quantity_unit_list
=
[
'weight/kg'
],
trade_phase
=
'mrp/p
2
'
)
trade_phase
=
'mrp/p
0
'
)
self
.
createTransformedResource
(
transformation
=
transformation
,
resource_value
=
resource
2
,
resource_value
=
resource
()
,
quantity
=
1
,
quantity_unit_list
=
[
'weight/kg'
],
trade_phase
=
'mrp/p
2
'
)
trade_phase
=
'mrp/p
0
'
)
self
.
createTransformedResource
(
transformation
=
transformation
,
resource_value
=
resource
3
,
resource_value
=
resource
()
,
quantity
=
4
,
quantity_unit_list
=
[
'weight/kg'
],
trade_phase
=
'mrp/p
3
'
)
trade_phase
=
'mrp/p
1
'
)
self
.
createTransformedResource
(
transformation
=
transformation
,
resource_value
=
resource
4
,
resource_value
=
resource
()
,
quantity
=
1
,
quantity_unit_list
=
[
'weight/kg'
],
trade_phase
=
'mrp/p
3
'
)
trade_phase
=
'mrp/p
1
'
)
return
transformation
@
reindex
def
createSimpleBusinessProcess
(
self
):
""" mrp/p2 mrp/3
ready -------- partial_produced ------- done
"""
# organisations
source_section
=
self
.
createOrganisation
(
title
=
'source_section'
)
source
=
self
.
createOrganisation
(
title
=
'source'
)
destination_section
=
self
.
createOrganisation
(
title
=
'destination_section'
)
destination
=
self
.
createOrganisation
(
title
=
'destination'
)
business_process
=
self
.
createBusinessProcess
(
referential_date
=
'stop_date'
)
self
.
createBusinessLink
(
business_process
,
id
=
'p2'
,
predecessor
=
'trade_state/ready'
,
successor
=
'trade_state/partial'
,
quantity
=
1
,
trade_phase
=
[
'mrp/p2'
],
source_section_value
=
source_section
,
source_value
=
source
,
destination_section_value
=
destination_section
,
destination_value
=
destination
)
self
.
createBusinessLink
(
business_process
,
id
=
'p3'
,
predecessor
=
'trade_state/partial'
,
successor
=
'trade_state/done'
,
quantity
=
1
,
deliverable
=
1
,
# root explanation
trade_phase
=
[
'mrp/p3'
],
source_section_value
=
source_section
,
source_value
=
source
,
destination_section_value
=
destination_section
,
destination_value
=
destination
)
return
business_process
@
reindex
def
createConcurrentBusinessProcess
(
self
):
""" mrp/p2
ready ======== partial_produced
mrp/p3
def
createBusinessProcess1
(
self
,
node_p0
=
None
):
""" order p0 s0 p1 deliver
------- S0 ---- S1 ---- S2 ---- S3 ------- S4
PO PR PPL PR PPL
"""
# organisations
source_section
=
self
.
createOrganisation
(
title
=
'source_section'
)
source
=
self
.
createOrganisation
(
title
=
'source'
)
destination_section
=
self
.
createOrganisation
(
title
=
'destination_section'
)
destination
=
self
.
createOrganisation
(
title
=
'destination'
)
business_process
=
self
.
createBusinessProcess
(
referential_date
=
'stop_date'
)
business_process
=
self
.
_createDocument
(
"Business Process"
)
builder
=
'portal_deliveries/production_packing_list_builder'
completed
=
'delivered'
,
'started'
,
'stopped'
phase_list
=
[(
'default/order'
,
None
,
(
'confirmed'
,)),
(
'default/delivery'
,
builder
,
completed
)]
phase_list
[
1
:
1
]
=
[(
'mrp/p'
+
str
(
i
),
'portal_deliveries/production_report_builder'
,
completed
)
for
i
in
xrange
(
2
)]
if
node_p0
is
not
None
:
phase_list
.
insert
(
2
,
(
'mrp/s0'
,
builder
,
completed
))
predecessor
=
None
for
i
,
(
phase
,
builder
,
completed
)
in
enumerate
(
phase_list
):
successor
=
'trade_state/s'
+
str
(
i
)
self
.
createBusinessLink
(
business_process
,
id
=
'p2'
,
predecessor
=
'trade_state/ready'
,
successor
=
'trade_state/partial'
,
quantity
=
1
,
trade_phase
=
[
'mrp/p2'
],
source_section_value
=
source_section
,
source_value
=
source
,
destination_section_value
=
destination_section
,
destination_value
=
destination
)
self
.
createBusinessLink
(
business_process
,
id
=
'p3'
,
predecessor
=
'trade_state/ready'
,
successor
=
'trade_state/partial'
,
quantity
=
1
,
deliverable
=
1
,
# root explanation
trade_phase
=
[
'mrp/p3'
],
source_section_value
=
source_section
,
source_value
=
source
,
destination_section_value
=
destination_section
,
destination_value
=
destination
)
completed_state
=
completed
,
predecessor
=
predecessor
,
successor
=
successor
,
trade_phase
=
phase
,
delivery_builder
=
builder
)
predecessor
=
successor
phase_list
=
[
x
[
0
]
for
x
in
phase_list
]
if
node_p0
is
not
None
:
self
.
createTradeModelPath
(
business_process
,
destination_value
=
node_p0
,
trade_phase
=
phase_list
.
pop
(
1
))
self
.
createTradeModelPath
(
business_process
,
test_tales_expression
=
"here/getSource"
,
trade_phase
=
phase_list
.
pop
(
1
))
self
.
createTradeModelPath
(
business_process
,
trade_phase_list
=
phase_list
)
return
business_process
def
checkStock
(
self
,
resource
,
*
node_variation_quantity
):
if
isinstance
(
resource
,
str
):
resource
=
self
.
portal
.
unrestrictedTraverse
(
resource
)
expected_dict
=
dict
(((
x
[
0
].
getUid
(),
x
[
1
]),
x
[
2
])
for
x
in
node_variation_quantity
)
for
r
in
resource
.
getCurrentInventoryList
(
group_by_node
=
1
,
group_by_variation
=
1
):
self
.
assertEqual
(
expected_dict
.
pop
((
r
.
node_uid
,
r
.
variation_text
),
0
),
r
.
inventory
)
self
.
assertFalse
(
any
(
expected_dict
.
itervalues
()),
expected_dict
)
class
TestMRPImplementation
(
TestMRPMixin
):
"""the test for implementation"""
@
skip
(
'Unfinished experimental feature'
)
def
test_TransformationRule_getHeadProductionPathList
(
self
):
rule
=
self
.
getRule
(
reference
=
'default_transformation_model_rule'
)
transformation
=
self
.
createDefaultTransformation
()
business_process
=
self
.
createSimpleBusinessProcess
()
self
.
assertEqual
([
business_process
.
p2
],
rule
.
getHeadProductionPathList
(
transformation
,
business_process
))
business_process
=
self
.
createConcurrentBusinessProcess
()
self
.
assertEqual
(
set
([
business_process
.
p2
,
business_process
.
p3
]),
set
(
rule
.
getHeadProductionPathList
(
transformation
,
business_process
)))
@
newSimulationExpectedFailure
def
test_TransformationRule_expand
(
self
):
# mock order
order
=
self
.
createDefaultOrder
()
order_line
=
order
.
objectValues
()[
0
]
business_process
=
order
.
getSpecialiseValue
()
# paths
path_p2
=
'%s/p2'
%
business_process
.
getRelativeUrl
()
path_p3
=
'%s/p3'
%
business_process
.
getRelativeUrl
()
# organisations
path
=
business_process
.
p2
source_section
=
path
.
getSourceSection
()
source
=
path
.
getSource
()
destination_section
=
path
.
getDestinationSection
()
destination
=
path
.
getDestination
()
consumed_organisations
=
(
source_section
,
source
,
destination_section
,
None
)
produced_organisations
=
(
source_section
,
None
,
destination_section
,
destination
)
# don't need another rules, just need TransformationRule for test
self
.
invalidateRules
()
def
test
(
self
):
workshop
=
self
.
createNode
(
title
=
'workshop'
)
workshop2
=
self
.
createNode
(
title
=
'workshop2'
)
destination
=
self
.
createNode
(
title
=
'destination'
)
business_process
=
self
.
createBusinessProcess1
(
workshop2
)
order
=
self
.
createDefaultOrder
(
business_process
)
order_line
,
=
order
.
objectValues
()
order
.
_edit
(
source_value
=
workshop
,
destination_value
=
destination
)
self
.
tic
()
# alter simulations of the order
# root
applied_rule
=
self
.
portal
.
portal_simulation
.
newContent
(
portal_type
=
'Applied Rule'
)
movement
=
applied_rule
.
newContent
(
portal_type
=
'Simulation Movement'
)
applied_rule
.
edit
(
causality_value
=
order
)
movement
.
edit
(
order_value
=
order_line
,
quantity
=
order_line
.
getQuantity
(),
resource
=
order_line
.
getResource
())
# test mock
applied_rule
=
movement
.
newContent
(
potal_type
=
'Applied Rule'
)
rule
=
self
.
getRule
(
reference
=
'default_transformation_model_rule'
)
rule
.
expand
(
applied_rule
)
# assertion
expected_value_set
=
set
([
((
path_p2
,),
'product_module/5'
,
produced_organisations
,
'mrp/p3'
,
-
10
),
((
path_p2
,),
'product_module/1'
,
consumed_organisations
,
'mrp/p2'
,
30
),
((
path_p2
,),
'product_module/2'
,
consumed_organisations
,
'mrp/p2'
,
10
),
((
path_p3
,),
'product_module/5'
,
consumed_organisations
,
'mrp/p3'
,
10
),
((
path_p3
,),
'product_module/3'
,
consumed_organisations
,
'mrp/p3'
,
40
),
((
path_p3
,),
'product_module/4'
,
consumed_organisations
,
'mrp/p3'
,
10
),
((
path_p3
,),
'product_module/5'
,
produced_organisations
,
None
,
-
10
)])
movement_list
=
applied_rule
.
objectValues
()
self
.
assertEqual
(
len
(
expected_value_set
),
len
(
movement_list
))
movement_value_set
=
set
([])
for
movement
in
movement_list
:
movement_value_set
|=
set
([(
tuple
(
movement
.
getCausalityList
()),
movement
.
getResource
(),
(
movement
.
getSourceSection
(),
movement
.
getSource
(),
movement
.
getDestinationSection
(),
movement
.
getDestination
(),),
# organisations
movement
.
getTradePhase
(),
movement
.
getQuantity
())])
self
.
assertEqual
(
expected_value_set
,
movement_value_set
)
@
skip
(
'Unfinished experimental feature'
)
def
test_TransformationRule_expand_concurrent
(
self
):
business_process
=
self
.
createConcurrentBusinessProcess
()
# mock order
order
=
self
.
createDefaultOrder
(
business_process
=
business_process
)
order_line
=
order
.
objectValues
()[
0
]
# phases
phase_p2
=
'%s/p2'
%
business_process
.
getRelativeUrl
()
phase_p3
=
'%s/p3'
%
business_process
.
getRelativeUrl
()
# organisations
path
=
business_process
.
p2
source_section
=
path
.
getSourceSection
()
source
=
path
.
getSource
()
destination_section
=
path
.
getDestinationSection
()
destination
=
path
.
getDestination
()
organisations
=
(
source_section
,
source
,
destination_section
,
destination
)
consumed_organisations
=
(
source_section
,
source
,
destination_section
,
None
)
produced_organisations
=
(
source_section
,
None
,
destination_section
,
destination
)
# don't need another rules, just need TransformationRule for test
self
.
invalidateRules
()
order
.
plan
()
self
.
tic
()
# alter simulations of the order
# root
applied_rule
=
self
.
portal
.
portal_simulation
.
newContent
(
portal_type
=
'Applied Rule'
)
movement
=
applied_rule
.
newContent
(
portal_type
=
'Simulation Movement'
)
applied_rule
.
edit
(
causality_value
=
order
)
movement
.
edit
(
order_value
=
order_line
,
quantity
=
order_line
.
getQuantity
(),
resource
=
order_line
.
getResource
())
# test mock
applied_rule
=
movement
.
newContent
(
potal_type
=
'Applied Rule'
)
rule
=
self
.
getRule
(
reference
=
'default_transformation_model_rule'
)
rule
.
expand
(
applied_rule
)
# assertion
expected_value_set
=
set
([
((
phase_p2
,),
'product_module/1'
,
consumed_organisations
,
'mrp/p2'
,
30
),
((
phase_p2
,),
'product_module/2'
,
consumed_organisations
,
'mrp/p2'
,
10
),
((
phase_p3
,),
'product_module/3'
,
consumed_organisations
,
'mrp/p3'
,
40
),
((
phase_p3
,),
'product_module/4'
,
consumed_organisations
,
'mrp/p3'
,
10
),
((
phase_p2
,
phase_p3
),
'product_module/5'
,
produced_organisations
,
None
,
-
10
)])
movement_list
=
applied_rule
.
objectValues
()
self
.
assertEqual
(
len
(
expected_value_set
),
len
(
movement_list
))
movement_value_set
=
set
([])
for
movement
in
movement_list
:
movement_value_set
|=
set
([(
tuple
(
movement
.
getCausalityList
()),
movement
.
getResource
(),
(
movement
.
getSourceSection
(),
movement
.
getSource
(),
movement
.
getDestinationSection
(),
movement
.
getDestination
(),),
# organisations
movement
.
getTradePhase
(),
movement
.
getQuantity
())])
self
.
assertEqual
(
expected_value_set
,
movement_value_set
)
@
skip
(
'Unfinished experimental feature'
)
def
test_TransformationRule_expand_reexpand
(
self
):
"""
test case of difference when any movement are frozen
by using above result
"""
self
.
test_TransformationRule_expand_concurrent
()
ar
,
=
order
.
getCausalityRelatedValueList
(
portal_type
=
"Applied Rule"
)
sm
,
=
ar
.
objectValues
()
# order
ar
,
=
sm
.
objectValues
()
sm
,
=
ar
.
objectValues
()
# deliver
ar
,
=
sm
.
objectValues
()
movement_list
=
[]
resource
=
order_line
.
getResource
()
for
sm
in
ar
.
objectValues
():
self
.
assertEqual
(
sm
.
getSource
(),
None
)
self
.
assertTrue
(
sm
.
getDestination
())
# Reference is used to match movements when reexpanding.
reference
=
sm
.
getReference
()
if
reference
.
split
(
'/'
,
1
)[
0
]
in
(
'pr'
,
'cr'
):
self
.
assertEqual
(
sm
.
getResource
(),
resource
)
else
:
cr
=
self
.
portal
.
unrestrictedTraverse
(
reference
).
getResource
()
self
.
assertTrue
(
None
!=
sm
.
getResource
()
==
cr
!=
resource
)
reference
=
None
movement_list
.
append
((
sm
.
getTradePhase
(),
sm
.
getQuantity
(),
reference
,
sm
.
getIndustrialPhaseList
()))
movement_list
.
sort
()
self
.
assertEqual
(
movement_list
,
sorted
((
(
'mrp/p0'
,
-
10
,
None
,
[]),
(
'mrp/p0'
,
-
30
,
None
,
[]),
(
'mrp/p0'
,
10
,
'pr/mrp/p0'
,
[
'trade_phase/mrp/p0'
]),
(
'mrp/p1'
,
-
10
,
'cr/mrp/p1'
,
[
'trade_phase/mrp/p0'
]),
(
'mrp/p1'
,
-
10
,
None
,
[]),
(
'mrp/p1'
,
-
40
,
None
,
[]),
(
'mrp/p1'
,
10
,
'pr'
,
[]),
)))
order
.
confirm
()
order
.
localBuild
()
self
.
tic
()
self
.
checkStock
(
resource
)
applied_rule
=
self
.
portal
.
portal_simulation
.
objectValues
()[
0
]
business_process
=
applied_rule
.
getCausalityValue
().
getSpecialiseValue
()
# phases
phase_p2
=
'%s/p2'
%
business_process
.
getRelativeUrl
()
phase_p3
=
'%s/p3'
%
business_process
.
getRelativeUrl
()
# organisations
path
=
business_process
.
p2
source_section
=
path
.
getSourceSection
()
source
=
path
.
getSource
()
destination_section
=
path
.
getDestinationSection
()
destination
=
path
.
getDestination
()
consumed_organisations
=
(
source_section
,
source
,
destination_section
,
None
)
produced_organisations
=
(
source_section
,
None
,
destination_section
,
destination
)
movement
=
applied_rule
.
objectValues
()[
0
]
applied_rule
=
movement
.
objectValues
()[
0
]
# these movements are made by transformation
for
movement
in
applied_rule
.
objectValues
():
movement
.
edit
(
quantity
=
1
)
# set the state value of isFrozen to 1,
movement
.
_baseSetFrozen
(
1
)
# re-expand
rule
=
self
.
getRule
(
reference
=
'default_transformation_model_rule'
)
rule
.
expand
(
applied_rule
)
# assertion
expected_value_set
=
set
([
((
phase_p2
,),
'product_module/1'
,
consumed_organisations
,
'mrp/p2'
,
1
),
# Frozen
((
phase_p2
,),
'product_module/1'
,
consumed_organisations
,
'mrp/p2'
,
29
),
((
phase_p2
,),
'product_module/2'
,
consumed_organisations
,
'mrp/p2'
,
1
),
# Frozen
((
phase_p2
,),
'product_module/2'
,
consumed_organisations
,
'mrp/p2'
,
9
),
((
phase_p3
,),
'product_module/3'
,
consumed_organisations
,
'mrp/p3'
,
1
),
# Frozen
((
phase_p3
,),
'product_module/3'
,
consumed_organisations
,
'mrp/p3'
,
39
),
((
phase_p3
,),
'product_module/4'
,
consumed_organisations
,
'mrp/p3'
,
1
),
# Frozen
((
phase_p3
,),
'product_module/4'
,
consumed_organisations
,
'mrp/p3'
,
9
),
((
phase_p2
,
phase_p3
),
'product_module/5'
,
produced_organisations
,
None
,
1
),
# Frozen
((
phase_p2
,
phase_p3
),
'product_module/5'
,
produced_organisations
,
None
,
-
11
)])
movement_list
=
applied_rule
.
objectValues
()
self
.
assertEqual
(
len
(
expected_value_set
),
len
(
movement_list
))
movement_value_set
=
set
([])
for
movement
in
movement_list
:
movement_value_set
|=
set
([(
tuple
(
movement
.
getCausalityList
()),
movement
.
getResource
(),
(
movement
.
getSourceSection
(),
movement
.
getSource
(),
movement
.
getDestinationSection
(),
movement
.
getDestination
(),),
# organisations
movement
.
getTradePhase
(),
movement
.
getQuantity
())])
self
.
assertEqual
(
expected_value_set
,
movement_value_set
)
@
skip
(
'Unfinished experimental feature'
)
def
test_TransformationSourcingRule_expand
(
self
):
# mock order
order
=
self
.
createDefaultOrder
()
order_line
=
order
.
objectValues
()[
0
]
# don't need another rules, just need TransformationSourcingRule for test
self
.
invalidateRules
()
def
getRelatedDeliveryList
(
portal_type
):
return
order
.
getCausalityRelatedValueList
(
portal_type
=
portal_type
)
pr1
,
=
getRelatedDeliveryList
(
"Production Report"
)
pr1
.
start
()
pr1
.
deliver
()
order
.
localBuild
()
self
.
tic
()
variation
=
'industrial_phase/trade_phase/mrp/p0'
self
.
checkStock
(
resource
,
(
workshop2
,
variation
,
10
))
business_process
=
order
.
getSpecialiseValue
()
# get last path of a business process
# in simple business path, the last is between "partial_produced" and "done"
causality_path
=
None
for
state
in
business_process
.
objectValues
(
portal_type
=
self
.
portal
.
getPortalBusinessStateTypeList
()):
if
len
(
state
.
getRemainingTradePhaseList
(
self
.
portal
))
==
0
:
causality_path
=
state
.
getSuccessorRelatedValue
()
# phases
phase_p2
=
'%s/p2'
%
business_process
.
getRelativeUrl
()
# organisations
source_section
=
causality_path
.
getSourceSection
()
source
=
causality_path
.
getSource
()
destination_section
=
causality_path
.
getDestinationSection
()
destination
=
causality_path
.
getDestination
()
organisations
=
(
source_section
,
source
,
destination_section
,
destination
)
# sourcing resource
sourcing_resource
=
order_line
.
getResource
()
# alter simulations of the order
# root
applied_rule
=
self
.
portal
.
portal_simulation
.
newContent
(
portal_type
=
'Applied Rule'
)
movement
=
applied_rule
.
newContent
(
portal_type
=
'Simulation Movement'
)
applied_rule
.
edit
(
causality_value
=
order
)
movement
.
edit
(
order_value
=
order_line
,
causality_value
=
causality_path
,
quantity
=
order_line
.
getQuantity
(),
resource
=
sourcing_resource
,
)
ppl1
,
=
getRelatedDeliveryList
(
"Production Packing List"
)
ppl1
.
start
()
ppl1
.
deliver
()
order
.
localBuild
()
self
.
tic
()
self
.
checkStock
(
resource
,
(
workshop
,
variation
,
10
))
# test mock
applied_rule
=
movement
.
newContent
(
potal_type
=
'Applied Rule'
)
rule
=
self
.
getRule
(
reference
=
'default_transformation_sourcing_model_rule'
)
rule
.
expand
(
applied_rule
)
pr2
,
=
(
x
for
x
in
getRelatedDeliveryList
(
"Production Report"
)
if
x
.
aq_base
is
not
pr1
.
aq_base
)
pr2
.
start
()
pr2
.
deliver
()
order
.
localBuild
()
self
.
tic
()
self
.
checkStock
(
resource
,
(
workshop
,
''
,
10
))
# assertion
expected_value_set
=
set
([
((
phase_p2
,),
sourcing_resource
,
organisations
,
10
)])
movement_list
=
applied_rule
.
objectValues
()
self
.
assertEqual
(
len
(
expected_value_set
),
len
(
movement_list
))
movement_value_set
=
set
([])
for
movement
in
movement_list
:
movement_value_set
|=
set
([(
tuple
(
movement
.
getCausalityList
()),
movement
.
getResource
(),
(
movement
.
getSourceSection
(),
movement
.
getSource
(),
movement
.
getDestinationSection
(),
movement
.
getDestination
(),),
# organisations
movement
.
getQuantity
())])
self
.
assertEqual
(
expected_value_set
,
movement_value_set
)
ppl2
,
=
(
x
for
x
in
getRelatedDeliveryList
(
"Production Packing List"
)
if
x
.
aq_base
is
not
ppl1
.
aq_base
)
ppl2
.
start
()
ppl2
.
deliver
()
self
.
tic
()
self
.
checkStock
(
resource
,
(
destination
,
''
,
10
))
def
test_suite
():
...
...
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