...
 
Commits (214)
Showing 1000 changed files with 3403 additions and 369 deletions

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

[submodule "bt5/erp5_notebook"]
path = bt5/erp5_notebook
url = https://lab.nexedi.com/tiwariayush/bt5-erp5_notebook
Changes
=======
0.4.58 (2019-03-05)
-------------------
* erp5.util
- testnode: Give more time to supervisord to kill subprocess [Sebastien Robin]
0.4.57 (2019-02-25)
-------------------
* erp5.util
- testnode: Allow to pass max_quantity to runComputerPartition [Lukasz Nowak]
- testnode: use CPUs a bit less agressively [Jerome Perrin]
- testnode: avoid to rebuild testnode dependencies (firefox) all the time [Sebastien Robin]
- testnode: try much more agressively to kill remaining processes [Sebastien Robin]
0.4.56 (2018-09-28)
-------------------
......
......@@ -77,8 +77,6 @@ Once the period is closed (i.e. the Accounting Period Delimiter is in delivered
<string>title</string>
<string>short_title</string>
<string>description</string>
<string>start_date</string>
<string>stop_date</string>
</tuple>
</value>
</item>
......
......@@ -82,10 +82,6 @@
<string>reference</string>
<string>source_reference</string>
<string>destination_reference</string>
<string>source_section_title</string>
<string>destination_section_title</string>
<string>start_date</string>
<string>stop_date</string>
</tuple>
</value>
</item>
......
......@@ -85,10 +85,6 @@
<string>reference</string>
<string>source_reference</string>
<string>destination_reference</string>
<string>source_section_title</string>
<string>destination_section_title</string>
<string>start_date</string>
<string>stop_date</string>
</tuple>
</value>
</item>
......
......@@ -83,10 +83,6 @@
<string>reference</string>
<string>source_reference</string>
<string>destination_reference</string>
<string>source_section_title</string>
<string>destination_section_title</string>
<string>start_date</string>
<string>stop_date</string>
</tuple>
</value>
</item>
......
......@@ -82,10 +82,6 @@
<string>reference</string>
<string>source_reference</string>
<string>destination_reference</string>
<string>source_section_title</string>
<string>destination_section_title</string>
<string>start_date</string>
<string>stop_date</string>
</tuple>
</value>
</item>
......
......@@ -84,10 +84,6 @@
<string>reference</string>
<string>source_reference</string>
<string>destination_reference</string>
<string>source_section_title</string>
<string>destination_section_title</string>
<string>start_date</string>
<string>stop_date</string>
</tuple>
</value>
</item>
......
......@@ -88,10 +88,6 @@
<string>reference</string>
<string>source_reference</string>
<string>destination_reference</string>
<string>source_section_title</string>
<string>destination_section_title</string>
<string>start_date</string>
<string>stop_date</string>
</tuple>
</value>
</item>
......
......@@ -88,6 +88,7 @@
<string>my_source_function</string>
<string>my_source_funding</string>
<string>my_source_project_title</string>
<string>my_source_payment_request_title</string>
<string>my_source_payment</string>
<string>my_payment_mode</string>
<string>my_aggregate_title_list</string>
......
......@@ -88,6 +88,7 @@
<string>my_destination_function</string>
<string>my_destination_funding</string>
<string>my_destination_project_title</string>
<string>my_destination_payment_request_title</string>
<string>my_destination_payment</string>
<string>my_payment_mode</string>
<string>my_aggregate_title_list</string>
......
......@@ -89,7 +89,7 @@ if len(payment_request_set) > 1:
min_project_count = 1
if context.getSourceProject() or context.getDestinationProject():
min_project_count = 2
if len(project_set) > min_project_count:
if force_project or len(project_set) > min_project_count:
if source:
a(('getSourceProjectTitle', 'Project'))
else:
......
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>source=0</string> </value>
<value> <string>source=0, force_project=False</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -80,6 +80,7 @@
<string>my_destination_project_title</string>
<string>my_destination_reference</string>
<string>my_destination_carrier_title</string>
<string>my_destination_payment_request_title</string>
</list>
</value>
</item>
......@@ -95,6 +96,7 @@
<string>my_source_project_title</string>
<string>my_source_reference</string>
<string>my_source_carrier_title</string>
<string>my_source_payment_request_title</string>
</list>
</value>
</item>
......
......@@ -80,6 +80,7 @@
<string>my_source_project_title</string>
<string>my_source_reference</string>
<string>my_source_carrier_title</string>
<string>my_source_payment_request_title</string>
</list>
</value>
</item>
......@@ -95,6 +96,7 @@
<string>my_destination_project_title</string>
<string>my_destination_reference</string>
<string>my_destination_carrier_title</string>
<string>my_destination_payment_request_title</string>
</list>
</value>
</item>
......
......@@ -65,7 +65,7 @@
<key> <string>roles</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
</tuple>
</value>
</item>
......
<tal:block tal:define='site_root python: here.getWebSiteValue() or here.getPortalObject();
portal_url python: site_root.absolute_url();
portal_type python: here.getPortalType();
div_id string:${id}_ace;
mode python: here.Base_getAceEditorMode();
container_div_id string:${div_id}_container;
......@@ -150,6 +151,7 @@
ace_editor_container_div = null;
ace_editor = null;
var mode = '${mode}';
var portal_type = '${portal_type}';
var params = '${params}';
function maximizeFullscreenRemoveSaveMessage() {
......@@ -394,6 +396,7 @@
ace.require('ace/ext/language_tools');
ace_editor.setOptions({ enableBasicAutocompletion: true, enableSnippets: true });
var data_options = {};
data_options.portal_type = portal_type;
if (params !== 'None') {
data_options.bound_names = ['context','container','script','traverse_subpath','printed','same_type','string','sequence','random','DateTime','whrandom','reorder','sets','test','math'],
data_options.params = params;
......
......@@ -200,7 +200,7 @@ def checkPythonSourceCodeAsJSON(self, data, REQUEST=None):
else:
body = data['code']
message_list = checkPythonSourceCode(body.encode('utf8'))
message_list = checkPythonSourceCode(body.encode('utf8'), data.get('portal_type'))
for message_dict in message_list:
if is_python_script:
message_dict['row'] = message_dict['row'] - 2
......
......@@ -33,7 +33,7 @@ def checkPythonScript(script_instance, script_path):
{'bound_names': extra_builtins +
script_instance.getBindingAssignments().getAssignedNamesInOrder(),
'params': script_instance.params(),
'code': unicode(script_instance.read(), 'utf8')
'code': unicode(script_instance.body(), 'utf8')
}))['annotations']:
annotation["script_path"] = script_path
line_list.append(
......
......@@ -94,7 +94,6 @@
<string>short_title</string>
<string>subject_list</string>
<string>filename</string>
<string>source_project_title</string>
</tuple>
</value>
</item>
......
##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Yoshinori Okuji <yo@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5.mixin.variated import VariatedMixin
class Budget(Predicate, VariatedMixin):
"""
Budget means a kind of budget stock.
"""
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.SimpleItem
, PropertySheet.CategoryCore
, PropertySheet.Folder
, PropertySheet.Predicate
, PropertySheet.SortIndex
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Budget
, PropertySheet.Path
, PropertySheet.VariationRange
, PropertySheet.Reference
, PropertySheet.Version
)
# CMF Type Definition
meta_type='ERP5 Budget'
portal_type='Budget'
add_permission = Permissions.AddPortalContent
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>Budget</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.Budget</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.Budget</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
##############################################################################
#
# Copyright (c) 2005, 2006 Nexedi SARL and Contributors. All Rights Reserved.
# Yoshinori Okuji <yo@nexedi.com>
# Romain Courteaud <romain@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5.Document.MetaNode import MetaNode
from Products.ERP5.Document.Movement import Movement
class BudgetCell(Predicate, MetaNode, Movement):
""" Budget Cell defines a cell of budget.
XXX This is not a Movement, but we need getDestinationCredit
XXX This is not a MetaNode
"""
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.SimpleItem
, PropertySheet.Folder
, PropertySheet.Predicate
, PropertySheet.SortIndex
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Amount
, PropertySheet.Budget
, PropertySheet.MappedValue
, PropertySheet.VariationRange
)
# CMF Type Definition
meta_type='ERP5 Budget Cell'
portal_type='Budget Cell'
add_permission = Permissions.AddPortalContent
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
security.declareProtected(Permissions.AccessContentsInformation, 'getTitle')
def getTitle(self):
"""
Return a calculated title.
"""
script = self._getTypeBasedMethod('asTitle')
if script is not None:
return script()
raise UnboundLocalError(
"Did not find title script for portal type: %r" %
self.getPortalType())
security.declareProtected(Permissions.AccessContentsInformation, 'getCurrentInventory')
def getCurrentInventory(self, at_date=None, **kw):
""" Returns current inventory.
at_date parameter can be used to take into account budget transactions
before that date.
"""
kw['node_uid'] = self.getUid()
resource = self.getResourceValue()
if resource is not None:
kw['resource_uid'] = resource.getUid()
if at_date:
kw['at_date'] = at_date
sign = self.getParentValue().BudgetLine_getConsumptionSign()
return sign * self.portal_simulation.getCurrentInventory(**kw)
security.declareProtected(Permissions.AccessContentsInformation, 'getCurrentBalance')
def getCurrentBalance(self, at_date=None):
"""
Returns current balance
"""
sign = self.getParentValue().BudgetLine_getConsumptionSign()
return sign * self.getQuantity(0.0) + self.getCurrentInventory(at_date=at_date)
security.declareProtected(Permissions.AccessContentsInformation, 'getConsumedBudget')
def getConsumedBudget(self, src__=0):
"""
Return consumed budget.
"""
script = self._getTypeBasedMethod('getConsumedBudget')
if script is not None:
return script(src__=src__)
raise UnboundLocalError(
"Did not find consumed budget script for portal type: %r" %
self.getPortalType())
security.declareProtected(Permissions.AccessContentsInformation, 'getAvailableBudget')
def getAvailableBudget(self, at_date=None):
"""
Return available budget.
"""
return self.getCurrentBalance(at_date=at_date) - self.getEngagedBudget()
security.declareProtected(Permissions.AccessContentsInformation, 'getEngagedBudget')
def getEngagedBudget(self, src__=0):
"""
Return Engaged budget.
"""
script = self._getTypeBasedMethod('getEngagedBudget')
if script is not None:
return script(src__=src__)
raise UnboundLocalError(
"Did not find engaged budget script for portal type: %r" %
self.getPortalType())
security.declareProtected(Permissions.AccessContentsInformation,
'getExplanationValue')
def getExplanationValue(self):
"""Explanation has no meaning for a budget cell"""
return None
security.declareProtected(Permissions.ModifyPortalContent,
'setSourceCredit')
def setSourceCredit(self, source_credit):
"""Set the quantity.
Overloaded from movement, we always set the quantity, even if not passed
"""
try:
source_credit = float(source_credit)
except TypeError:
source_credit = 0.0
Movement.setSourceCredit(self, source_credit)
def setSourceDebit(self, source_debit):
"""Set the quantity.
Overloaded from movement, we always set the quantity, even if not passed
"""
try:
source_debit = float(source_debit)
except TypeError:
source_debit = 0.0
Movement.setSourceDebit(self, source_debit)
security.declareProtected(Permissions.ModifyPortalContent,
'setDestinationDebit', 'setDestinationCredit' )
setDestinationDebit = setSourceCredit
setDestinationCredit = setSourceDebit
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>BudgetCell</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.BudgetCell</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.BudgetCell</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
##############################################################################
#
# Copyright (c) 2005, 2006 Nexedi SARL and Contributors. All Rights Reserved.
# Yoshinori Okuji <yo@nexedi.com>
# Romain Courteaud <romain@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5.mixin.variated import VariatedMixin
from Products.ERP5Type.Cache import transactional_cached
from ZTUtils import make_query
class TempBudgetCell(object):
__allow_access_to_unprotected_subobjects__ = 1
__slots__ = ('amount', 'cell_index', 'url', 'engaged_budget')
def __init__(self, amount, cell_index, url, engaged_budget):
self.amount = amount
self.cell_index = cell_index
self.url = url
self.engaged_budget = engaged_budget
def getConsumedBudget(self):
return self.amount
def getAvailableBudget(self):
return self.amount
def getEngagedBudget(self):
return self.amount
def getExplanationUrl(self, *args, **w):
return '%s/BudgetLine_viewConsumedBudgetMovementList?%s' % (
self.url,
make_query(dict(cell_index=list(self.cell_index), engaged_budget=self.engaged_budget)))
class BudgetLine(Predicate, XMLMatrix, VariatedMixin):
""" A Line of budget, variated in budget cells.
"""
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.SimpleItem
, PropertySheet.CategoryCore
, PropertySheet.Folder
, PropertySheet.Predicate
, PropertySheet.SortIndex
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Budget
, PropertySheet.Amount
, PropertySheet.VariationRange
)
# CMF Type Definition
meta_type='ERP5 Budget Line'
portal_type='Budget Line'
add_permission = Permissions.AddPortalContent
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
security.declareProtected(Permissions.AccessContentsInformation,
'getConsumedBudgetDict')
def getConsumedBudgetDict(self, **kw):
"""Returns all the consumptions in a dict where the keys are the cells, and
the value is the consumed budget.
"""
return self._getBudgetDict(**kw)
security.declareProtected(Permissions.AccessContentsInformation,
'getEngagedBudgetDict')
def getEngagedBudgetDict(self, **kw):
"""Returns all the engagements in a dict where the keys are the cells, and
the value is the engaged budget.
"""
kw.setdefault('stock_explanation_simulation_state',
self.getPortalReservedInventoryStateList() +
self.getPortalCurrentInventoryStateList() +
self.getPortalTransitInventoryStateList())
kw['simulation_period'] = ''
return self._getBudgetDict(**kw)
security.declareProtected(Permissions.AccessContentsInformation,
'getAvailableBudgetDict')
def getAvailableBudgetDict(self, **kw):
"""Returns all the engagements in a dict where the keys are the cells, and
the value is the engaged budget.
"""
budget_dict = {k: v * -1
for k, v in self.getEngagedBudgetDict(**kw).iteritems()}
cell_key_list = self.getCellKeyList()
for cell_key in cell_key_list:
cell_key = tuple(cell_key)
cell = self.getCell(*cell_key)
if cell is not None:
engaged = budget_dict.get(cell_key, 0)
budget_dict[cell_key] = cell.getCurrentBalance() + engaged
return budget_dict
@transactional_cached(key_method=lambda self, **kw:
(self.getRelativeUrl(), tuple(kw.items())))
def _getBudgetDict(self, simulation_period='Current', **kw):
"""Use getCurrentInventoryList to compute all budget cell consumptions at
once, and returns them in a dict.
"""
budget = self.getParentValue()
budget_model = budget.getSpecialiseValue(portal_type='Budget Model')
if budget_model is None:
return {}
query_dict = budget_model.getInventoryListQueryDict(self)
query_dict.update(kw)
query_dict.setdefault('ignore_group_by', True)
sign = self.BudgetLine_getConsumptionSign()
cell_key_cache = {}
budget_dict = {}
portal = self.getPortalObject()
getInventoryList = portal.portal_simulation.getInventoryList
if simulation_period == 'Current':
getInventoryList = portal.portal_simulation.getCurrentInventoryList
for brain in getInventoryList(**query_dict):
cell_key = budget_model._getCellKeyFromInventoryListBrain(brain, self,
cell_key_cache=cell_key_cache)
# XXX total_quantity or total_price ??
previous_value = budget_dict.get(cell_key, 0)
budget_dict[cell_key] = previous_value + brain.total_price * sign
return budget_dict
security.declareProtected(Permissions.AccessContentsInformation,
'getConsumedBudgetCell')
def getConsumedBudgetCell(self, *cell_index, **kw):
consumed_budget_dict = self.getConsumedBudgetDict()
return TempBudgetCell(consumed_budget_dict.get(cell_index),
cell_index, self.absolute_url(), False)
security.declareProtected(Permissions.AccessContentsInformation,
'getAvailableBudgetCell')
def getAvailableBudgetCell(self, *cell_index, **kw):
available_budget_dict = self.getAvailableBudgetDict()
return TempBudgetCell(available_budget_dict.get(cell_index),
cell_index, self.absolute_url(), True)
security.declareProtected(Permissions.AccessContentsInformation,
'getEngagedBudgetCell')
def getEngagedBudgetCell(self, *cell_index, **kw):
engaged_budget_dict = self.getEngagedBudgetDict()
return TempBudgetCell(engaged_budget_dict.get(cell_index),
cell_index, self.absolute_url(), True)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>BudgetLine</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5.Document.BudgetLine</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.BudgetLine</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
##############################################################################
#
# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Core.Predicate import Predicate
class BudgetModel(Predicate):
"""A model of budget, with all budget variation
"""
# Default Properties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.SimpleItem
, PropertySheet.CategoryCore
, PropertySheet.Folder
, PropertySheet.Predicate
, PropertySheet.SortIndex
, PropertySheet.Task
, PropertySheet.Arrow
, PropertySheet.Budget
, PropertySheet.Path
)
# CMF Type Definition
meta_type = 'ERP5 Budget Model'
portal_type = 'Budget Model'
add_permission = Permissions.AddPortalContent
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
security.declareProtected(Permissions.AccessContentsInformation,
'getCellRangeForBudgetLine')
def getCellRangeForBudgetLine(self, budget_line, matrixbox=0):
"""Return the cell range to use for the budget.
"""
cell_range = []
for budget_variation in sorted(self.contentValues(
portal_type=self.getPortalBudgetVariationTypeList(),),
key=lambda x:x.getIntIndex()):
if not budget_variation.isMemberOf('budget_variation/budget_cell'):
continue
variation_cell_range = budget_variation.getCellRangeForBudgetLine(
budget_line, matrixbox=matrixbox)
if variation_cell_range \
and variation_cell_range != [[]] \
and variation_cell_range not in cell_range:
cell_range.extend(variation_cell_range)
return cell_range
security.declareProtected(Permissions.AccessContentsInformation,
'getConsumptionCellRangeForBudgetLine')
def getConsumptionCellRangeForBudgetLine(self, budget_line, matrixbox=0, engaged_budget=False):
"""Return the cell range to use for the budget consumption.
It can be different from the cell range for definition when using full
consumption detail on budget variations.
"""
cell_range = []
for budget_variation in sorted(self.contentValues(
portal_type=self.getPortalBudgetVariationTypeList(),),
key=lambda x:x.getIntIndex()):
if not budget_variation.isMemberOf('budget_variation/budget_cell'):
continue
variation_cell_range = budget_variation.getConsumptionCellRangeForBudgetLine(
budget_line, matrixbox=matrixbox, engaged_budget=engaged_budget)
if variation_cell_range \
and variation_cell_range != [[]] \
and variation_cell_range not in cell_range:
cell_range.extend(variation_cell_range)
return cell_range
security.declareProtected(Permissions.AccessContentsInformation,
'getInventoryQueryDict')
def getInventoryQueryDict(self, budget_cell):
"""Returns the query dict to pass to simulation query for a budget cell
"""
query_dict = {}
for budget_variation in sorted(self.contentValues(
portal_type=self.getPortalBudgetVariationTypeList()),
key=lambda x:x.getIntIndex()):
query_dict.update(
budget_variation.getInventoryQueryDict(budget_cell))
# include dates from the budget
budget = budget_cell.getParentValue().getParentValue()
query_dict.setdefault('from_date', budget.getStartDateRangeMin())
start_date_range_max = budget.getStartDateRangeMax()
if start_date_range_max:
query_dict.setdefault('at_date', start_date_range_max.latestTime())
return query_dict
security.declareProtected(Permissions.AccessContentsInformation,
'getInventoryListQueryDict')
def getInventoryListQueryDict(self, budget_line):
"""Returns the query dict to pass to simulation query for a budget line
"""
query_dict = {}
for budget_variation in sorted(self.contentValues(
portal_type=self.getPortalBudgetVariationTypeList()),
key=lambda x:x.getIntIndex()):
variation_query_dict = budget_variation.getInventoryListQueryDict(
budget_line)
# Merge group_by and select_list arguments.
# Other arguments should not conflict
if 'group_by' in query_dict and 'group_by' in variation_query_dict:
variation_query_dict['group_by'].extend(query_dict['group_by'])
if 'select_list' in query_dict \
and 'select_list' in variation_query_dict:
variation_query_dict['select_list'].extend(
query_dict['select_list'])
query_dict.update(variation_query_dict)
# include dates from the budget
budget = budget_line.getParentValue()
query_dict.setdefault('from_date', budget.getStartDateRangeMin())
start_date_range_max = budget.getStartDateRangeMax()
if start_date_range_max:
query_dict.setdefault('at_date', start_date_range_max.latestTime())
return query_dict
def _getCellKeyFromInventoryListBrain(self, brain, budget_line,
cell_key_cache=None):
"""Compute the cell key from an inventory brain, the cell key can be used
to retrieve the budget cell in the corresponding budget line.
"""
cell_key = ()
for budget_variation in sorted