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
Labels
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Romain Courteaud
erp5
Commits
be5c52af
Commit
be5c52af
authored
Feb 11, 2020
by
Romain Courteaud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "ZODB Components: Preparation of erp5_base migration from FS: One Mixin per source file."
This reverts commit
66f30ebb
.
parent
36ee1f08
Changes
29
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
434 additions
and
629 deletions
+434
-629
bt5/erp5_mrp/DocumentTemplateItem/portal_components/document.erp5.ProductionSimulationRule.py
...rtal_components/document.erp5.ProductionSimulationRule.py
+1
-1
bt5/erp5_web/DocumentTemplateItem/portal_components/document.erp5.StaticWebSection.py
...eItem/portal_components/document.erp5.StaticWebSection.py
+1
-1
product/ERP5/Document/AcceptSolver.py
product/ERP5/Document/AcceptSolver.py
+1
-1
product/ERP5/Document/AdoptSolver.py
product/ERP5/Document/AdoptSolver.py
+1
-1
product/ERP5/Document/Delivery.py
product/ERP5/Document/Delivery.py
+1
-1
product/ERP5/Document/DeliveryRootSimulationRule.py
product/ERP5/Document/DeliveryRootSimulationRule.py
+1
-2
product/ERP5/Document/DeliverySimulationRule.py
product/ERP5/Document/DeliverySimulationRule.py
+1
-2
product/ERP5/Document/Document.py
product/ERP5/Document/Document.py
+1
-1
product/ERP5/Document/InvoiceSimulationRule.py
product/ERP5/Document/InvoiceSimulationRule.py
+1
-2
product/ERP5/Document/InvoiceTransactionSimulationRule.py
product/ERP5/Document/InvoiceTransactionSimulationRule.py
+1
-2
product/ERP5/Document/OrderRootSimulationRule.py
product/ERP5/Document/OrderRootSimulationRule.py
+1
-2
product/ERP5/Document/PaymentSimulationRule.py
product/ERP5/Document/PaymentSimulationRule.py
+1
-2
product/ERP5/Document/SubscriptionItem.py
product/ERP5/Document/SubscriptionItem.py
+1
-2
product/ERP5/Document/TradeModelSimulationRule.py
product/ERP5/Document/TradeModelSimulationRule.py
+1
-2
product/ERP5/Document/TransformationSimulationRule.py
product/ERP5/Document/TransformationSimulationRule.py
+1
-2
product/ERP5/Document/TransformationSourcingSimulationRule.py
...uct/ERP5/Document/TransformationSourcingSimulationRule.py
+1
-2
product/ERP5/Document/WebSection.py
product/ERP5/Document/WebSection.py
+1
-1
product/ERP5/mixin/configurable_property_solver.py
product/ERP5/mixin/configurable_property_solver.py
+0
-86
product/ERP5/mixin/document_extensible_traversable.py
product/ERP5/mixin/document_extensible_traversable.py
+0
-63
product/ERP5/mixin/extensible_traversable.py
product/ERP5/mixin/extensible_traversable.py
+70
-8
product/ERP5/mixin/movement_generator.py
product/ERP5/mixin/movement_generator.py
+0
-119
product/ERP5/mixin/ooo_document_extensible_traversable.py
product/ERP5/mixin/ooo_document_extensible_traversable.py
+0
-67
product/ERP5/mixin/rule.py
product/ERP5/mixin/rule.py
+240
-0
product/ERP5/mixin/simulable.py
product/ERP5/mixin/simulable.py
+0
-175
product/ERP5/mixin/solver.py
product/ERP5/mixin/solver.py
+53
-1
product/ERP5Configurator/Document/SecurityCategoryMappingConfiguratorItem.py
...rator/Document/SecurityCategoryMappingConfiguratorItem.py
+1
-1
product/ERP5Configurator/mixin/configurator_item.py
product/ERP5Configurator/mixin/configurator_item.py
+52
-0
product/ERP5Configurator/mixin/skin_configurator_item.py
product/ERP5Configurator/mixin/skin_configurator_item.py
+0
-81
product/ERP5OOo/Document/OOoDocument.py
product/ERP5OOo/Document/OOoDocument.py
+1
-1
No files found.
bt5/erp5_mrp/DocumentTemplateItem/portal_components/document.erp5.ProductionSimulationRule.py
View file @
be5c52af
from
Products.ERP5.Document.DeliverySimulationRule
import
DeliverySimulationRule
from
Products.ERP5.mixin.
movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.
rule
import
MovementGeneratorMixin
class
ProductionSimulationRule
(
DeliverySimulationRule
):
"""
...
...
bt5/erp5_web/DocumentTemplateItem/portal_components/document.erp5.StaticWebSection.py
View file @
be5c52af
...
...
@@ -31,7 +31,7 @@ from AccessControl import ClassSecurityInfo
from
Acquisition
import
aq_base
from
OFS.Traversable
import
NotFound
from
Products.ERP5.mixin.
document_
extensible_traversable
import
DocumentExtensibleTraversableMixin
from
Products.ERP5.mixin.extensible_traversable
import
DocumentExtensibleTraversableMixin
from
Products.ERP5.Document.WebSection
import
WebSection
from
Products.ERP5Type
import
Permissions
...
...
product/ERP5/Document/AcceptSolver.py
View file @
be5c52af
...
...
@@ -29,7 +29,7 @@
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
from
Products.ERP5.mixin.
configurable_property_
solver
import
ConfigurablePropertySolverMixin
from
Products.ERP5.mixin.solver
import
ConfigurablePropertySolverMixin
class
AcceptSolver
(
ConfigurablePropertySolverMixin
):
"""Target solver that accepts the values from the decision on the prevision.
...
...
product/ERP5/Document/AdoptSolver.py
View file @
be5c52af
...
...
@@ -29,7 +29,7 @@
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
from
Products.ERP5.mixin.
configurable_property_
solver
import
ConfigurablePropertySolverMixin
from
Products.ERP5.mixin.solver
import
ConfigurablePropertySolverMixin
class
AdoptSolver
(
ConfigurablePropertySolverMixin
):
"""Target solver that adopts the values from the prevision on the decision.
...
...
product/ERP5/Document/Delivery.py
View file @
be5c52af
...
...
@@ -41,7 +41,7 @@ from Products.ERP5Type.XMLObject import XMLObject
from
Products.ERP5.Document.ImmobilisationDelivery
import
ImmobilisationDelivery
from
Products.ERP5.mixin.amount_generator
import
AmountGeneratorMixin
from
Products.ERP5.mixin.composition
import
CompositionMixin
from
Products.ERP5.mixin.
simulab
le
import
SimulableMixin
from
Products.ERP5.mixin.
ru
le
import
SimulableMixin
from
Products.ERP5Type.UnrestrictedMethod
import
UnrestrictedMethod
,
\
unrestricted_apply
from
zLOG
import
LOG
,
PROBLEM
...
...
product/ERP5/Document/DeliveryRootSimulationRule.py
View file @
be5c52af
...
...
@@ -29,8 +29,7 @@
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5.mixin.rule
import
RuleMixin
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
...
...
product/ERP5/Document/DeliverySimulationRule.py
View file @
be5c52af
...
...
@@ -29,8 +29,7 @@
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5.mixin.rule
import
RuleMixin
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
...
...
product/ERP5/Document/Document.py
View file @
be5c52af
...
...
@@ -206,7 +206,7 @@ class DocumentConversionServerProxy():
def
__getattr__
(
self
,
attr
):
return
partial
(
self
.
_proxy_function
,
attr
)
from
Products.ERP5.mixin.
document_
extensible_traversable
import
DocumentExtensibleTraversableMixin
from
Products.ERP5.mixin.extensible_traversable
import
DocumentExtensibleTraversableMixin
class
Document
(
DocumentExtensibleTraversableMixin
,
XMLObject
,
UrlMixin
,
CachedConvertableMixin
,
CrawlableMixin
,
TextConvertableMixin
,
...
...
product/ERP5/Document/InvoiceSimulationRule.py
View file @
be5c52af
...
...
@@ -29,8 +29,7 @@
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5.mixin.rule
import
RuleMixin
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
...
...
product/ERP5/Document/InvoiceTransactionSimulationRule.py
View file @
be5c52af
...
...
@@ -29,8 +29,7 @@
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5.mixin.rule
import
RuleMixin
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
from
Products.ERP5.Document.PredicateMatrix
import
PredicateMatrix
...
...
product/ERP5/Document/OrderRootSimulationRule.py
View file @
be5c52af
...
...
@@ -29,8 +29,7 @@
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5.mixin.rule
import
RuleMixin
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
...
...
product/ERP5/Document/PaymentSimulationRule.py
View file @
be5c52af
...
...
@@ -29,8 +29,7 @@
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5.mixin.rule
import
RuleMixin
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
...
...
product/ERP5/Document/SubscriptionItem.py
View file @
be5c52af
...
...
@@ -33,8 +33,7 @@ from AccessControl import ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5.Document.Item
import
Item
from
Products.ERP5.mixin.composition
import
CompositionMixin
from
Products.ERP5.mixin.simulable
import
SimulableMixin
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
MovementGeneratorMixin
,
SimulableMixin
from
Products.ERP5.mixin.periodicity
import
PeriodicityMixin
from
Products.ERP5Type.UnrestrictedMethod
import
UnrestrictedMethod
from
Products.ERP5Type.Base
import
Base
...
...
product/ERP5/Document/TradeModelSimulationRule.py
View file @
be5c52af
...
...
@@ -30,8 +30,7 @@ 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
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
...
...
product/ERP5/Document/TransformationSimulationRule.py
View file @
be5c52af
...
...
@@ -31,8 +31,7 @@ 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
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
...
...
product/ERP5/Document/TransformationSourcingSimulationRule.py
View file @
be5c52af
...
...
@@ -30,8 +30,7 @@ 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
from
Products.ERP5.mixin.movement_generator
import
MovementGeneratorMixin
from
Products.ERP5.mixin.rule
import
RuleMixin
,
MovementGeneratorMixin
from
Products.ERP5.mixin.movement_collection_updater
import
\
MovementCollectionUpdaterMixin
...
...
product/ERP5/Document/WebSection.py
View file @
be5c52af
...
...
@@ -30,7 +30,7 @@
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5.Document.Domain
import
Domain
from
Products.ERP5.mixin.
document_
extensible_traversable
import
DocumentExtensibleTraversableMixin
from
Products.ERP5.mixin.extensible_traversable
import
DocumentExtensibleTraversableMixin
from
Acquisition
import
aq_base
,
aq_inner
from
Products.ERP5Type.UnrestrictedMethod
import
unrestricted_apply
from
AccessControl
import
Unauthorized
...
...
product/ERP5/mixin/configurable_property_solver.py
deleted
100644 → 0
View file @
36ee1f08
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type.Globals
import
InitializeClass
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5.mixin.solver
import
SolverMixin
from
Products.ERP5.mixin.configurable
import
ConfigurableMixin
class
ConfigurablePropertySolverMixin
(
SolverMixin
,
ConfigurableMixin
,
XMLObject
):
"""
Base class for Target Solvers that can be applied to many
solver-decisions of a solver process, and need to accumulate the
tested_property_list configuration among all solver-decisions
"""
add_permission
=
Permissions
.
AddPortalContent
isIndexable
=
0
# We do not want to fill the catalog with objects on which we need no reporting
# Declarative security
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
zope
.
interface
.
implements
(
interfaces
.
ISolver
,
interfaces
.
IConfigurable
,)
# Default Properties
property_sheets
=
(
PropertySheet
.
Base
,
PropertySheet
.
XMLObject
,
PropertySheet
.
CategoryCore
,
PropertySheet
.
DublinCore
,
PropertySheet
.
TargetSolver
)
def
updateConfiguration
(
self
,
**
kw
):
# This method is called once for each 'Solver Decision' of a
# 'Solver Process' that maps into this solver for the same
# Simulation Movement, so we need to take care not to lose
# information by overwriting.
configuration
=
self
.
_getConfigurationPropertyDict
()
tested_property_list
=
configuration
.
get
(
'tested_property_list'
)
if
tested_property_list
is
not
None
:
tested_property_set
=
set
(
tested_property_list
)
tested_property_set
.
update
(
kw
.
get
(
'tested_property_list'
,
()))
kw
[
'tested_property_list'
]
=
list
(
tested_property_set
)
super
(
ConfigurablePropertySolverMixin
,
self
).
updateConfiguration
(
**
kw
)
def
getTestedPropertyList
(
self
):
configuration_dict
=
self
.
getConfigurationPropertyDict
()
tested_property_list
=
configuration_dict
.
get
(
'tested_property_list'
)
if
tested_property_list
is
None
:
portal_type
=
self
.
getPortalObject
().
portal_types
.
getTypeInfo
(
self
)
tested_property_list
=
portal_type
.
getTestedPropertyList
()
return
tested_property_list
InitializeClass
(
ConfigurablePropertySolverMixin
)
product/ERP5/mixin/document_extensible_traversable.py
deleted
100644 → 0
View file @
36ee1f08
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
# Ivan Tyagov <ivan@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
Acquisition
import
aq_base
from
AccessControl
import
Unauthorized
from
AccessControl.SecurityManagement
import
setSecurityManager
from
Products.ERP5.mixin.base_extensible_traversable
import
BaseExtensibleTraversableMixin
from
Products.ERP5Type.UnrestrictedMethod
import
unrestricted_apply
class
DocumentExtensibleTraversableMixin
(
BaseExtensibleTraversableMixin
):
"""
This class provides a implementation of IExtensibleTraversable for Document classed based documents.
"""
def
getExtensibleContent
(
self
,
request
,
name
):
old_manager
,
user
=
self
.
_forceIdentification
(
request
)
# Next get the document per name
portal
=
self
.
getPortalObject
()
document
=
self
.
getDocumentValue
(
name
=
name
,
portal
=
portal
)
# restore original security context if there's a logged in user
if
user
is
not
None
:
setSecurityManager
(
old_manager
)
if
document
is
not
None
:
document
=
aq_base
(
document
.
asContext
(
id
=
name
,
# Hide some properties to permit locating the original
original_container
=
document
.
getParentValue
(),
original_id
=
document
.
getId
(),
editable_absolute_url
=
document
.
absolute_url
()))
return
document
.
__of__
(
self
)
# no document found for current user, still such document may exists
# in some cases user (like Anonymous) can not view document according to portal catalog
# but we may ask him to login if such a document exists
isAuthorizationForced
=
getattr
(
self
,
'isAuthorizationForced'
,
None
)
if
isAuthorizationForced
is
not
None
and
isAuthorizationForced
():
if
unrestricted_apply
(
self
.
getDocumentValue
,
(
name
,
portal
))
is
not
None
:
# force user to login as specified in Web Section
raise
Unauthorized
product/ERP5/mixin/
base_
extensible_traversable.py
→
product/ERP5/mixin/extensible_traversable.py
View file @
be5c52af
...
...
@@ -27,22 +27,26 @@
#
##############################################################################
from
warnings
import
warn
from
base64
import
decodestring
from
zLOG
import
LOG
from
AccessControl
import
ClassSecurityInfo
,
getSecurityManager
from
AccessControl.SecurityManagement
import
newSecurityManager
,
setSecurityManager
from
Products.CMFCore.utils
import
getToolByName
from
Acquisition
import
aq_base
from
Products.ERP5Type.Globals
import
get_request
from
AccessControl
import
Unauthorized
from
Products.ERP5Type.ExtensibleTraversable
import
ExtensibleTraversableMixIn
from
Products.ERP5Type.Cache
import
getReadOnlyTransactionCache
from
AccessControl
import
ClassSecurityInfo
,
getSecurityManager
from
AccessControl.SecurityManagement
import
newSecurityManager
,
setSecurityManager
from
Products.ERP5Type.Globals
import
InitializeClass
from
Products.ERP5Type
import
Permissions
from
Products.ERP5Type.Globals
import
get_request
from
Products.CMFCore.utils
import
getToolByName
,
_checkConditionalGET
,
_setCacheHeaders
,
_ViewEmulator
from
OFS.Image
import
File
as
OFSFile
from
warnings
import
warn
from
base64
import
decodestring
from
Products.ERP5Type.UnrestrictedMethod
import
unrestricted_apply
from
Products.ERP5.Document.Document
import
ConversionError
,
NotConvertedError
# XXX: these duplicate ones in ERP5.Document
_MARKER
=
[]
EMBEDDED_FORMAT
=
'_embedded'
class
BaseExtensibleTraversableMixin
(
ExtensibleTraversableMixIn
):
"""
...
...
@@ -166,3 +170,61 @@ class BaseExtensibleTraversableMixin(ExtensibleTraversableMixIn):
return
document
.
__of__
(
self
)
InitializeClass
(
BaseExtensibleTraversableMixin
)
class
DocumentExtensibleTraversableMixin
(
BaseExtensibleTraversableMixin
):
"""
This class provides a implementation of IExtensibleTraversable for Document classed based documents.
"""
def
getExtensibleContent
(
self
,
request
,
name
):
old_manager
,
user
=
self
.
_forceIdentification
(
request
)
# Next get the document per name
portal
=
self
.
getPortalObject
()
document
=
self
.
getDocumentValue
(
name
=
name
,
portal
=
portal
)
# restore original security context if there's a logged in user
if
user
is
not
None
:
setSecurityManager
(
old_manager
)
if
document
is
not
None
:
document
=
aq_base
(
document
.
asContext
(
id
=
name
,
# Hide some properties to permit locating the original
original_container
=
document
.
getParentValue
(),
original_id
=
document
.
getId
(),
editable_absolute_url
=
document
.
absolute_url
()))
return
document
.
__of__
(
self
)
# no document found for current user, still such document may exists
# in some cases user (like Anonymous) can not view document according to portal catalog
# but we may ask him to login if such a document exists
isAuthorizationForced
=
getattr
(
self
,
'isAuthorizationForced'
,
None
)
if
isAuthorizationForced
is
not
None
and
isAuthorizationForced
():
if
unrestricted_apply
(
self
.
getDocumentValue
,
(
name
,
portal
))
is
not
None
:
# force user to login as specified in Web Section
raise
Unauthorized
class
OOoDocumentExtensibleTraversableMixin
(
BaseExtensibleTraversableMixin
):
"""
This class provides a implementation of IExtensibleTraversable for OOoDocument classed based documents.
"""
def
getExtensibleContent
(
self
,
request
,
name
):
# Be sure that html conversion is done,
# as it is required to extract extensible content
old_manager
,
user
=
self
.
_forceIdentification
(
request
)
web_cache_kw
=
{
'name'
:
name
,
'format'
:
EMBEDDED_FORMAT
}
try
:
self
.
_convert
(
format
=
'html'
)
view
=
_ViewEmulator
().
__of__
(
self
)
# If we have a conditional get, set status 304 and return
# no content
if
_checkConditionalGET
(
view
,
web_cache_kw
):
return
''
# call caching policy manager.
_setCacheHeaders
(
view
,
web_cache_kw
)
mime
,
data
=
self
.
getConversion
(
format
=
EMBEDDED_FORMAT
,
filename
=
name
)
document
=
OFSFile
(
name
,
name
,
data
,
content_type
=
mime
).
__of__
(
self
.
aq_parent
)
except
(
NotConvertedError
,
ConversionError
,
KeyError
):
document
=
DocumentExtensibleTraversableMixin
.
getExtensibleContent
(
self
,
request
,
name
)
# restore original security context if there's a logged in user
if
user
is
not
None
:
setSecurityManager
(
old_manager
)
return
document
product/ERP5/mixin/movement_generator.py
deleted
100644 → 0
View file @
36ee1f08
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
class
MovementGeneratorMixin
(
object
):
"""
This class provides a generic implementation of IMovementGenerator
which can be used together the Rule mixin class bellow. It does not
have any pretention to provide more than that.
TODO:
- _getInputMovementList is still not well defined. Should input
be an amount (_getInputAmountList) or a movement? This
requires careful thiking.
"""
# Default values
_applied_rule
=
None
_rule
=
None
_trade_phase_list
=
None
_explanation
=
None
def
__init__
(
self
,
applied_rule
,
explanation
=
None
,
rule
=
None
,
trade_phase_list
=
None
):
self
.
_trade_phase_list
=
trade_phase_list
# XXX-JPS Why a list ?
self
.
_applied_rule
=
applied_rule
if
rule
is
None
and
applied_rule
is
not
None
:
self
.
_rule
=
applied_rule
.
getSpecialiseValue
()
else
:
self
.
_rule
=
rule
# for rule specific stuff
if
explanation
is
None
:
self
.
_explanation
=
applied_rule
else
:
# A good example of explicit explanation can be getRootExplanationLineValue
# since different lines could have different dates
# such an explicit root explanation only works if
# indexing of simulation has already happened
self
.
_explanation
=
explanation
# XXX-JPS handle delay_mode
# Implementation of IMovementGenerator
def
getGeneratedMovementList
(
self
,
movement_list
=
None
,
rounding
=
False
):
"""
Returns a list of movements generated by that rule.
movement_list - optional IMovementList which can be passed explicitely
rounding - boolean argument, which controls if rounding shall be applied on
generated movements or not
NOTE:
- implement rounding appropriately (True or False seems
simplistic)
"""
# Default implementation below can be overriden by subclasses
# however it should be generic enough not to be overriden
# by most classes
# Results will be appended to result
result
=
[]
# Build a list of movement and business path
input_movement_list
=
self
.
_getInputMovementList
(
movement_list
=
movement_list
,
rounding
=
rounding
)
for
input_movement
in
input_movement_list
:
# Merge movement and business path properties (core implementation)
# Lookup Business Process through composition (NOT UNION)
business_process
=
input_movement
.
asComposedDocument
()
explanation
=
self
.
_applied_rule
# We use applied rule as local explanation
trade_phase
=
self
.
_getTradePhaseList
(
input_movement
,
business_process
)
# XXX-JPS not convenient to handle
update_property_dict
=
self
.
_getUpdatePropertyDict
(
input_movement
)
result
.
extend
(
business_process
.
getTradePhaseMovementList
(
explanation
,
input_movement
,
trade_phase
=
trade_phase
,
delay_mode
=
None
,
update_property_dict
=
update_property_dict
))
# And return list of generated movements
return
result
def
_getUpdatePropertyDict
(
self
,
input_movement
):
# XXX Wouldn't it better to return {} or {'delivery': None} ?
# Below code is mainly for root applied rules.
# Other movement generators usually want to reset delivery.
return
{
'delivery'
:
input_movement
.
getRelativeUrl
()}
def
_getTradePhaseList
(
self
,
input_movement
,
business_process
):
# XXX-JPS WEIRD
if
self
.
_trade_phase_list
:
return
self
.
_trade_phase_list
if
self
.
_rule
is
not
None
:
trade_phase_list
=
self
.
_rule
.
getTradePhaseList
()
if
trade_phase_list
:
return
trade_phase_list
return
input_movement
.
getTradePhaseList
()
or
\
business_process
.
getTradePhaseList
()
def
_getInputMovementList
(
self
,
movement_list
=
None
,
rounding
=
None
):
#XXX-JPS should it be amount or movement ?
raise
NotImplementedError
# Default implementation takes amounts ?
# Use TradeModelRuleMovementGenerator._getInputMovementList as default implementation
# and potentially use trade phase for that.... as a way to filter out
product/ERP5/mixin/ooo_document_extensible_traversable.py
deleted
100644 → 0
View file @
36ee1f08
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
# Ivan Tyagov <ivan@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
AccessControl.SecurityManagement
import
setSecurityManager
from
Products.CMFCore.utils
import
_checkConditionalGET
,
_setCacheHeaders
,
_ViewEmulator
from
OFS.Image
import
File
as
OFSFile
from
Products.ERP5.Document.Document
import
ConversionError
,
NotConvertedError
from
Products.ERP5.mixin.base_extensible_traversable
import
BaseExtensibleTraversableMixin
from
Products.ERP5.mixin.document_extensible_traversable
import
DocumentExtensibleTraversableMixin
# XXX: these duplicate ones in ERP5.Document
EMBEDDED_FORMAT
=
'_embedded'
class
OOoDocumentExtensibleTraversableMixin
(
BaseExtensibleTraversableMixin
):
"""
This class provides a implementation of IExtensibleTraversable for OOoDocument classed based documents.
"""
def
getExtensibleContent
(
self
,
request
,
name
):
# Be sure that html conversion is done,
# as it is required to extract extensible content
old_manager
,
user
=
self
.
_forceIdentification
(
request
)
web_cache_kw
=
{
'name'
:
name
,
'format'
:
EMBEDDED_FORMAT
}
try
:
self
.
_convert
(
format
=
'html'
)
view
=
_ViewEmulator
().
__of__
(
self
)
# If we have a conditional get, set status 304 and return
# no content
if
_checkConditionalGET
(
view
,
web_cache_kw
):
return
''
# call caching policy manager.
_setCacheHeaders
(
view
,
web_cache_kw
)
mime
,
data
=
self
.
getConversion
(
format
=
EMBEDDED_FORMAT
,
filename
=
name
)
document
=
OFSFile
(
name
,
name
,
data
,
content_type
=
mime
).
__of__
(
self
.
aq_parent
)
except
(
NotConvertedError
,
ConversionError
,
KeyError
):
document
=
DocumentExtensibleTraversableMixin
.
getExtensibleContent
(
self
,
request
,
name
)
# restore original security context if there's a logged in user
if
user
is
not
None
:
setSecurityManager
(
old_manager
)
return
document
product/ERP5/mixin/rule.py
View file @
be5c52af
...
...
@@ -26,12 +26,20 @@
#
##############################################################################
import
transaction
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type.Globals
import
InitializeClass
from
Acquisition
import
aq_base
from
Products.ERP5Type
import
Permissions
,
interfaces
from
Products.ERP5Type.Base
import
Base
from
Products.ERP5Type.Core.Predicate
import
Predicate
from
Products.ERP5Type.Errors
import
SimulationError
from
Products.ERP5Type.TransactionalVariable
import
getTransactionalVariable
from
Products.ERP5.ExpandPolicy
import
policy_dict
from
Products.ERP5.MovementCollectionDiff
import
_getPropertyAndCategoryList
from
zLOG
import
LOG
def
_compare
(
tester_list
,
prevision_movement
,
decision_movement
):
for
tester
in
tester_list
:
...
...
@@ -39,6 +47,99 @@ def _compare(tester_list, prevision_movement, decision_movement):
return
False
return
True
class
MovementGeneratorMixin
(
object
):
"""
This class provides a generic implementation of IMovementGenerator
which can be used together the Rule mixin class bellow. It does not
have any pretention to provide more than that.
TODO:
- _getInputMovementList is still not well defined. Should input
be an amount (_getInputAmountList) or a movement? This
requires careful thiking.
"""
# Default values
_applied_rule
=
None
_rule
=
None
_trade_phase_list
=
None
_explanation
=
None
def
__init__
(
self
,
applied_rule
,
explanation
=
None
,
rule
=
None
,
trade_phase_list
=
None
):
self
.
_trade_phase_list
=
trade_phase_list
# XXX-JPS Why a list ?
self
.
_applied_rule
=
applied_rule
if
rule
is
None
and
applied_rule
is
not
None
:
self
.
_rule
=
applied_rule
.
getSpecialiseValue
()
else
:
self
.
_rule
=
rule
# for rule specific stuff
if
explanation
is
None
:
self
.
_explanation
=
applied_rule
else
:
# A good example of explicit explanation can be getRootExplanationLineValue
# since different lines could have different dates
# such an explicit root explanation only works if
# indexing of simulation has already happened
self
.
_explanation
=
explanation
# XXX-JPS handle delay_mode
# Implementation of IMovementGenerator
def
getGeneratedMovementList
(
self
,
movement_list
=
None
,
rounding
=
False
):
"""
Returns a list of movements generated by that rule.
movement_list - optional IMovementList which can be passed explicitely
rounding - boolean argument, which controls if rounding shall be applied on
generated movements or not
NOTE:
- implement rounding appropriately (True or False seems
simplistic)
"""
# Default implementation below can be overriden by subclasses
# however it should be generic enough not to be overriden
# by most classes
# Results will be appended to result
result
=
[]
# Build a list of movement and business path
input_movement_list
=
self
.
_getInputMovementList
(
movement_list
=
movement_list
,
rounding
=
rounding
)
for
input_movement
in
input_movement_list
:
# Merge movement and business path properties (core implementation)
# Lookup Business Process through composition (NOT UNION)
business_process
=
input_movement
.
asComposedDocument
()
explanation
=
self
.
_applied_rule
# We use applied rule as local explanation
trade_phase
=
self
.
_getTradePhaseList
(
input_movement
,
business_process
)
# XXX-JPS not convenient to handle
update_property_dict
=
self
.
_getUpdatePropertyDict
(
input_movement
)
result
.
extend
(
business_process
.
getTradePhaseMovementList
(
explanation
,
input_movement
,
trade_phase
=
trade_phase
,
delay_mode
=
None
,
update_property_dict
=
update_property_dict
))
# And return list of generated movements
return
result
def
_getUpdatePropertyDict
(
self
,
input_movement
):
# XXX Wouldn't it better to return {} or {'delivery': None} ?
# Below code is mainly for root applied rules.
# Other movement generators usually want to reset delivery.
return
{
'delivery'
:
input_movement
.
getRelativeUrl
()}
def
_getTradePhaseList
(
self
,
input_movement
,
business_process
):
# XXX-JPS WEIRD
if
self
.
_trade_phase_list
:
return
self
.
_trade_phase_list
if
self
.
_rule
is
not
None
:
trade_phase_list
=
self
.
_rule
.
getTradePhaseList
()
if
trade_phase_list
:
return
trade_phase_list
return
input_movement
.
getTradePhaseList
()
or
\
business_process
.
getTradePhaseList
()
def
_getInputMovementList
(
self
,
movement_list
=
None
,
rounding
=
None
):
#XXX-JPS should it be amount or movement ?
raise
NotImplementedError
# Default implementation takes amounts ?
# Use TradeModelRuleMovementGenerator._getInputMovementList as default implementation
# and potentially use trade phase for that.... as a way to filter out
class
RuleMixin
(
Predicate
):
"""
Provides generic methods and helper methods to implement
...
...
@@ -378,3 +479,142 @@ class RuleMixin(Predicate):
movement_collection_diff
.
addNewMovement
(
new_movement
)
InitializeClass
(
RuleMixin
)
class
SimulableMixin
(
Base
):
security
=
ClassSecurityInfo
()
def
updateSimulation
(
self
,
**
kw
):
"""Create/update related simulation trees by activity
This method is used to maintain related objects in simulation trees:
- hiding complexity of activity dependencies
- avoiding duplicate work
Repeated calls of this method for the same delivery will result in a single
call to _updateSimulation. Grouping may happen at the end of the transaction
or by the grouping method.
See _updateSimulation for accepted parameters.
"""
tv
=
getTransactionalVariable
()
key
=
'SimulableMixin.updateSimulation'
,
self
.
getUid
()
item_list
=
kw
.
items
()
try
:
kw
,
ignore
=
tv
[
key
]
kw
.
update
(
item_list
)
except
KeyError
:
ignore_key
=
key
+
(
'ignore'
,)
ignore
=
tv
.
pop
(
ignore_key
,
set
())
tv
[
key
]
=
kw
,
ignore
def
before_commit
():
if
kw
:
path
=
self
.
getPath
()
if
aq_base
(
self
.
unrestrictedTraverse
(
path
,
None
))
is
aq_base
(
self
):
self
.
activate
(
activity
=
'SQLQueue'
,
group_method_id
=
'portal_rules/updateSimulation'
,
tag
=
'build:'
+
path
,
priority
=
3
,
).
_updateSimulation
(
**
kw
)
del
tv
[
key
]
ignore
.
update
(
kw
)
tv
[
ignore_key
]
=
ignore
transaction
.
get
().
addBeforeCommitHook
(
before_commit
)
for
k
,
v
in
item_list
:
if
not
v
:
ignore
.
add
(
k
)
elif
k
not
in
ignore
:
continue
del
kw
[
k
]
def
_updateSimulation
(
self
,
create_root
=
0
,
expand_root
=
0
,
expand_related
=
0
,
index_related
=
0
):
"""
Depending on set parameters, this method will:
create_root -- if a root applied rule is missing, create and expand it
expand_root -- expand related root applied rule,
create it before if missing
expand_related -- expand related simulation movements
index_related -- reindex related simulation movements (recursively)
"""
if
create_root
or
expand_root
:
applied_rule
=
self
.
_getRootAppliedRule
()
if
applied_rule
is
None
:
applied_rule
=
self
.
_createRootAppliedRule
()
expand_root
=
applied_rule
is
not
None
activate_kw
=
{
'tag'
:
'build:'
+
self
.
getPath
()}
if
expand_root
:
applied_rule
.
expand
(
activate_kw
=
activate_kw
)
else
:
applied_rule
=
None
if
expand_related
:
for
movement
in
self
.
_getAllRelatedSimulationMovementList
():
movement
=
movement
.
getObject
()
if
not
movement
.
aq_inContextOf
(
applied_rule
):
# XXX: make sure this will also reindex of all sub-objects recursively
movement
.
expand
(
activate_kw
=
activate_kw
)
elif
index_related
:
for
movement
in
self
.
_getAllRelatedSimulationMovementList
():
movement
=
movement
.
getObject
()
if
not
movement
.
aq_inContextOf
(
applied_rule
):
movement
.
recursiveReindexObject
(
activate_kw
=
activate_kw
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getRuleReference'
)
def
getRuleReference
(
self
):
"""Returns an appropriate rule reference
XXX: Using reference to select a rule (for a root applied rule) is wrong
and should be replaced by predicate and workflow state.
"""
method
=
self
.
_getTypeBasedMethod
(
'getRuleReference'
)
if
method
is
None
:
raise
SimulationError
(
"Missing type-based 'getRuleReference' script for "
+
repr
(
self
))
return
method
()
def
_getRootAppliedRule
(
self
):
"""Get related root applied rule if it exists"""
applied_rule_list
=
self
.
getCausalityRelatedValueList
(
portal_type
=
'Applied Rule'
)
if
len
(
applied_rule_list
)
==
1
:
return
applied_rule_list
[
0
]
elif
applied_rule_list
:
raise
SimulationError
(
'%r has more than one applied rule.'
%
self
)
def
_createRootAppliedRule
(
self
):
"""Create a root applied rule"""
# XXX: Consider moving this first test to Delivery
if
self
.
isSimulated
():
# No need to have a root applied rule
# if we are already in the simulation process
return
rule_reference
=
self
.
getRuleReference
()
if
rule_reference
:
portal
=
self
.
getPortalObject
()
rule_list
=
portal
.
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
portal
.
getPortalRuleTypeList
(),
validation_state
=
"validated"
,
reference
=
rule_reference
,
sort_on
=
'version'
,
sort_order
=
'descending'
)
if
rule_list
:
applied_rule
=
rule_list
[
0
].
constructNewAppliedRule
(
portal
.
portal_simulation
,
is_indexable
=
False
)
applied_rule
.
_setCausalityValue
(
self
)
del
applied_rule
.
isIndexable
# To prevent duplicate root Applied Rule, we reindex immediately and
# lock ZODB, and we rely on the fact that ZODB is committed after
# catalog. This way, we guarantee the catalog is up-to-date as soon as
# ZODB is unlocked.
applied_rule
.
immediateReindexObject
()
self
.
serialize
()
# prevent duplicate root Applied Rule
return
applied_rule
raise
SimulationError
(
"No such rule as %r is found"
%
rule_reference
)
security
.
declarePrivate
(
'manage_beforeDelete'
)
def
manage_beforeDelete
(
self
,
item
,
container
):
"""Delete related Applied Rule"""
for
o
in
self
.
getCausalityRelatedValueList
(
portal_type
=
'Applied Rule'
):
o
.
getParentValue
().
deleteContent
(
o
.
getId
())
super
(
SimulableMixin
,
self
).
manage_beforeDelete
(
item
,
container
)
InitializeClass
(
SimulableMixin
)
product/ERP5/mixin/simulable.py
deleted
100644 → 0
View file @
36ee1f08
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
import
transaction
from
Acquisition
import
aq_base
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
from
Products.ERP5Type.Globals
import
InitializeClass
from
Products.ERP5Type.Base
import
Base
from
Products.ERP5Type.TransactionalVariable
import
getTransactionalVariable
from
Products.ERP5Type.Errors
import
SimulationError
class
SimulableMixin
(
Base
):
security
=
ClassSecurityInfo
()
def
updateSimulation
(
self
,
**
kw
):
"""Create/update related simulation trees by activity
This method is used to maintain related objects in simulation trees:
- hiding complexity of activity dependencies
- avoiding duplicate work
Repeated calls of this method for the same delivery will result in a single
call to _updateSimulation. Grouping may happen at the end of the transaction
or by the grouping method.
See _updateSimulation for accepted parameters.
"""
tv
=
getTransactionalVariable
()
key
=
'SimulableMixin.updateSimulation'
,
self
.
getUid
()
item_list
=
kw
.
items
()
try
:
kw
,
ignore
=
tv
[
key
]
kw
.
update
(
item_list
)
except
KeyError
:
ignore_key
=
key
+
(
'ignore'
,)
ignore
=
tv
.
pop
(
ignore_key
,
set
())
tv
[
key
]
=
kw
,
ignore
def
before_commit
():
if
kw
:
path
=
self
.
getPath
()
if
aq_base
(
self
.
unrestrictedTraverse
(
path
,
None
))
is
aq_base
(
self
):
self
.
activate
(
activity
=
'SQLQueue'
,
group_method_id
=
'portal_rules/updateSimulation'
,
tag
=
'build:'
+
path
,
priority
=
3
,
).
_updateSimulation
(
**
kw
)
del
tv
[
key
]
ignore
.
update
(
kw
)
tv
[
ignore_key
]
=
ignore
transaction
.
get
().
addBeforeCommitHook
(
before_commit
)
for
k
,
v
in
item_list
:
if
not
v
:
ignore
.
add
(
k
)
elif
k
not
in
ignore
:
continue
del
kw
[
k
]
def
_updateSimulation
(
self
,
create_root
=
0
,
expand_root
=
0
,
expand_related
=
0
,
index_related
=
0
):
"""
Depending on set parameters, this method will:
create_root -- if a root applied rule is missing, create and expand it
expand_root -- expand related root applied rule,
create it before if missing
expand_related -- expand related simulation movements
index_related -- reindex related simulation movements (recursively)
"""
if
create_root
or
expand_root
:
applied_rule
=
self
.
_getRootAppliedRule
()
if
applied_rule
is
None
:
applied_rule
=
self
.
_createRootAppliedRule
()
expand_root
=
applied_rule
is
not
None
activate_kw
=
{
'tag'
:
'build:'
+
self
.
getPath
()}
if
expand_root
:
applied_rule
.
expand
(
activate_kw
=
activate_kw
)
else
:
applied_rule
=
None
if
expand_related
:
for
movement
in
self
.
_getAllRelatedSimulationMovementList
():
movement
=
movement
.
getObject
()
if
not
movement
.
aq_inContextOf
(
applied_rule
):
# XXX: make sure this will also reindex of all sub-objects recursively
movement
.
expand
(
activate_kw
=
activate_kw
)
elif
index_related
:
for
movement
in
self
.
_getAllRelatedSimulationMovementList
():
movement
=
movement
.
getObject
()
if
not
movement
.
aq_inContextOf
(
applied_rule
):
movement
.
recursiveReindexObject
(
activate_kw
=
activate_kw
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getRuleReference'
)
def
getRuleReference
(
self
):
"""Returns an appropriate rule reference
XXX: Using reference to select a rule (for a root applied rule) is wrong
and should be replaced by predicate and workflow state.
"""
method
=
self
.
_getTypeBasedMethod
(
'getRuleReference'
)
if
method
is
None
:
raise
SimulationError
(
"Missing type-based 'getRuleReference' script for "
+
repr
(
self
))
return
method
()
def
_getRootAppliedRule
(
self
):
"""Get related root applied rule if it exists"""
applied_rule_list
=
self
.
getCausalityRelatedValueList
(
portal_type
=
'Applied Rule'
)
if
len
(
applied_rule_list
)
==
1
:
return
applied_rule_list
[
0
]
elif
applied_rule_list
:
raise
SimulationError
(
'%r has more than one applied rule.'
%
self
)
def
_createRootAppliedRule
(
self
):
"""Create a root applied rule"""
# XXX: Consider moving this first test to Delivery
if
self
.
isSimulated
():
# No need to have a root applied rule
# if we are already in the simulation process
return
rule_reference
=
self
.
getRuleReference
()
if
rule_reference
:
portal
=
self
.
getPortalObject
()
rule_list
=
portal
.
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
portal
.
getPortalRuleTypeList
(),
validation_state
=
"validated"
,
reference
=
rule_reference
,
sort_on
=
'version'
,
sort_order
=
'descending'
)
if
rule_list
:
applied_rule
=
rule_list
[
0
].
constructNewAppliedRule
(
portal
.
portal_simulation
,
is_indexable
=
False
)
applied_rule
.
_setCausalityValue
(
self
)
del
applied_rule
.
isIndexable
# To prevent duplicate root Applied Rule, we reindex immediately and
# lock ZODB, and we rely on the fact that ZODB is committed after
# catalog. This way, we guarantee the catalog is up-to-date as soon as
# ZODB is unlocked.
applied_rule
.
immediateReindexObject
()
self
.
serialize
()
# prevent duplicate root Applied Rule
return
applied_rule
raise
SimulationError
(
"No such rule as %r is found"
%
rule_reference
)
security
.
declarePrivate
(
'manage_beforeDelete'
)
def
manage_beforeDelete
(
self
,
item
,
container
):
"""Delete related Applied Rule"""
for
o
in
self
.
getCausalityRelatedValueList
(
portal_type
=
'Applied Rule'
):
o
.
getParentValue
().
deleteContent
(
o
.
getId
())
super
(
SimulableMixin
,
self
).
manage_beforeDelete
(
item
,
container
)
InitializeClass
(
SimulableMixin
)
product/ERP5/mixin/solver.py
View file @
be5c52af
...
...
@@ -30,8 +30,10 @@
import
zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type.Globals
import
InitializeClass
from
Products.ERP5Type
import
Permissions
,
interfaces
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5Type.UnrestrictedMethod
import
super_user
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5.mixin.configurable
import
ConfigurableMixin
class
SolverMixin
(
object
):
"""
...
...
@@ -71,3 +73,53 @@ class SolverMixin(object):
return
solver_list
InitializeClass
(
SolverMixin
)
class
ConfigurablePropertySolverMixin
(
SolverMixin
,
ConfigurableMixin
,
XMLObject
):
"""
Base class for Target Solvers that can be applied to many
solver-decisions of a solver process, and need to accumulate the
tested_property_list configuration among all solver-decisions
"""
add_permission
=
Permissions
.
AddPortalContent
isIndexable
=
0
# We do not want to fill the catalog with objects on which we need no reporting
# Declarative security
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
zope
.
interface
.
implements
(
interfaces
.
ISolver
,
interfaces
.
IConfigurable
,)
# Default Properties
property_sheets
=
(
PropertySheet
.
Base
,
PropertySheet
.
XMLObject
,
PropertySheet
.
CategoryCore
,
PropertySheet
.
DublinCore
,
PropertySheet
.
TargetSolver
)
def
updateConfiguration
(
self
,
**
kw
):
# This method is called once for each 'Solver Decision' of a
# 'Solver Process' that maps into this solver for the same
# Simulation Movement, so we need to take care not to lose
# information by overwriting.
configuration
=
self
.
_getConfigurationPropertyDict
()
tested_property_list
=
configuration
.
get
(
'tested_property_list'
)
if
tested_property_list
is
not
None
:
tested_property_set
=
set
(
tested_property_list
)
tested_property_set
.
update
(
kw
.
get
(
'tested_property_list'
,
()))
kw
[
'tested_property_list'
]
=
list
(
tested_property_set
)
super
(
ConfigurablePropertySolverMixin
,
self
).
updateConfiguration
(
**
kw
)
def
getTestedPropertyList
(
self
):
configuration_dict
=
self
.
getConfigurationPropertyDict
()
tested_property_list
=
configuration_dict
.
get
(
'tested_property_list'
)
if
tested_property_list
is
None
:
portal_type
=
self
.
getPortalObject
().
portal_types
.
getTypeInfo
(
self
)
tested_property_list
=
portal_type
.
getTestedPropertyList
()
return
tested_property_list
InitializeClass
(
ConfigurablePropertySolverMixin
)
product/ERP5Configurator/Document/SecurityCategoryMappingConfiguratorItem.py
View file @
be5c52af
...
...
@@ -30,7 +30,7 @@ import zope.interface
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
interfaces
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5Configurator.mixin.
skin_
configurator_item
import
\
from
Products.ERP5Configurator.mixin.configurator_item
import
\
SkinConfiguratorItemMixin
class
SecurityCategoryMappingConfiguratorItem
(
SkinConfiguratorItemMixin
,
...
...
product/ERP5Configurator/mixin/configurator_item.py
View file @
be5c52af
...
...
@@ -29,7 +29,9 @@
##############################################################################
from
Products.ERP5Type.ConsistencyMessage
import
ConsistencyMessage
from
Products.ERP5Type.Base
import
Base
from
zLOG
import
LOG
,
INFO
import
time
class
ConfiguratorItemMixin
:
""" This is the base class for all configurator item. """
...
...
@@ -62,3 +64,53 @@ class ConfiguratorItemMixin:
current_template_path_list
=
list
(
bt5_obj
.
getTemplatePathList
())
current_template_path_list
.
extend
(
template_path_list
)
bt5_obj
.
edit
(
template_path_list
=
current_template_path_list
)
class
SkinConfiguratorItemMixin
(
ConfiguratorItemMixin
):
""" Mixin which allows to create python scripts and/or skin
elements during the configuration.
"""
def
install
(
self
,
skinfolder
,
business_configuration
):
"""
"""
bt5_obj
=
business_configuration
.
getSpecialiseValue
()
if
bt5_obj
is
None
:
LOG
(
'ConfiguratorItem'
,
INFO
,
'Unable to find related business template to %s'
%
\
business_configuration
.
getRelativeUrl
())
return
template_skin_id_list
=
list
(
bt5_obj
.
getTemplateSkinIdList
())
if
skinfolder
.
getId
()
not
in
template_skin_id_list
:
template_skin_id_list
.
append
(
skinfolder
.
getId
())
bt5_obj
.
edit
(
template_skin_id_list
=
template_skin_id_list
)
def
_createSkinFolder
(
self
,
folder_id
=
"custom"
):
""" Creates a new skin folder id if it do not exists and
update Skin information """
folder
=
getattr
(
self
.
portal_skins
,
folder_id
,
None
)
if
folder
is
not
None
:
return
folder
folder
=
self
.
portal_skins
.
manage_addProduct
[
'OFSP'
].
manage_addFolder
(
folder_id
)
# Register on all skin selections.
raise
NotImplementedError
def
_createZODBPythonScript
(
self
,
container
,
script_id
,
script_params
,
script_content
):
"""Creates a Python script `script_id` in the given `container`, with
`script_params` and `script_content`.
If the container already contains an object with id `script_id`, this
object is removed first.
"""
if
script_id
in
container
.
objectIds
():
container
.
manage_delObjects
([
script_id
])
container
.
manage_addProduct
[
'PythonScripts'
]
\
.
manage_addPythonScript
(
id
=
script_id
)
script
=
container
.
_getOb
(
script_id
)
script
.
ZPythonScript_edit
(
script_params
,
script_content
)
container
.
portal_url
.
getPortalObject
().
changeSkin
(
None
)
return
script
product/ERP5Configurator/mixin/skin_configurator_item.py
deleted
100644 → 0
View file @
36ee1f08
##############################################################################
#
# Copyright (c) 2006-2012 Nexedi SARL and Contributors. All Rights Reserved.
# Romain Courteaud <romain@nexedi.com>
# Ivan Tyagov <ivan@nexedi.com>
# Rafael Monnerat <rafael@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
zLOG
import
LOG
,
INFO
from
Products.ERP5Configurator.mixin.configurator_item
import
ConfiguratorItemMixin
class
SkinConfiguratorItemMixin
(
ConfiguratorItemMixin
):
""" Mixin which allows to create python scripts and/or skin
elements during the configuration.
"""
def
install
(
self
,
skinfolder
,
business_configuration
):
"""
"""
bt5_obj
=
business_configuration
.
getSpecialiseValue
()
if
bt5_obj
is
None
:
LOG
(
'ConfiguratorItem'
,
INFO
,
'Unable to find related business template to %s'
%
\
business_configuration
.
getRelativeUrl
())
return
template_skin_id_list
=
list
(
bt5_obj
.
getTemplateSkinIdList
())
if
skinfolder
.
getId
()
not
in
template_skin_id_list
:
template_skin_id_list
.
append
(
skinfolder
.
getId
())
bt5_obj
.
edit
(
template_skin_id_list
=
template_skin_id_list
)
def
_createSkinFolder
(
self
,
folder_id
=
"custom"
):
""" Creates a new skin folder id if it do not exists and
update Skin information """
folder
=
getattr
(
self
.
portal_skins
,
folder_id
,
None
)
if
folder
is
not
None
:
return
folder
folder
=
self
.
portal_skins
.
manage_addProduct
[
'OFSP'
].
manage_addFolder
(
folder_id
)
# Register on all skin selections.
raise
NotImplementedError
def
_createZODBPythonScript
(
self
,
container
,
script_id
,
script_params
,
script_content
):
"""Creates a Python script `script_id` in the given `container`, with
`script_params` and `script_content`.
If the container already contains an object with id `script_id`, this
object is removed first.
"""
if
script_id
in
container
.
objectIds
():
container
.
manage_delObjects
([
script_id
])
container
.
manage_addProduct
[
'PythonScripts'
]
\
.
manage_addPythonScript
(
id
=
script_id
)
script
=
container
.
_getOb
(
script_id
)
script
.
ZPythonScript_edit
(
script_params
,
script_content
)
container
.
portal_url
.
getPortalObject
().
changeSkin
(
None
)
return
script
product/ERP5OOo/Document/OOoDocument.py
View file @
be5c52af
...
...
@@ -43,7 +43,7 @@ from Products.ERP5Type.Utils import fill_args_from_request
# Mixin Import
from
Products.ERP5.mixin.base_convertable
import
BaseConvertableFileMixin
from
Products.ERP5.mixin.text_convertable
import
TextConvertableMixin
from
Products.ERP5.mixin.
ooo_document_
extensible_traversable
import
OOoDocumentExtensibleTraversableMixin
from
Products.ERP5.mixin.extensible_traversable
import
OOoDocumentExtensibleTraversableMixin
EMBEDDED_FORMAT
=
'_embedded'
...
...
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