<html><body>
<ul style="list-style:none">
<li style="color: red">CMFActivity/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">CMFCategory/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaySheetTransaction.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaySheetTransaction(Invoice):
"""
A paysheet will store data about the salary of an employee
"""
def getRatioQuantityFromReference(self, ratio_reference=None):
"""
return the ratio value correponding to the ratio_reference,
None if ratio_reference not found
"""
def getRatioQuantityList(self, ratio_reference_list):
"""
Return a list of reference_ratio_list correponding values.
reference_ratio_list is a list of references to the ratio lines
we want to get.
"""
def getAnnotationLineFromReference(self, reference=None):
"""
return the annotation line correponding to the reference,
None if reference not found
"""
def getAnnotationLineListList(self, reference_list):
"""
Return a annotation line list corresponding to the reference_list
reference_list is a list of references to the Annotation Line we want
to get.
"""
def createPaySheetLine(self, cell_list, title='', res='', desc='',
def getEditableModelLineAsDict(self, listbox, paysheet):
def getNotEditableModelLineAsDict(self, paysheet):
def sortByIntIndex(a, b):
def createPaySheetLineList(self, listbox=None, batch_mode=0, **kw):
def sortByIntIndex(a, b):
def getModifiedCell(cell, slice_dict, tax_category):
def getInheritedObjectValueList(self, portal_type_list):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ContainerLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ContainerLine(DeliveryLine):
"""
A DeliveryLine object allows to implement lines in
Deliveries (packing list, order, invoice, etc.)
It may include a price (for insurance, for customs, for invoices,
for orders)
"""
def newCellContent(self, id,**kw):
"""
This method can be overriden
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
def isDivergent(self):
"""
Returns 1 if the target is not met according to the current information
After and edit, the isOutOfTarget will be checked. If it is 1,
a message is emitted
emit targetUnreachable !
"""
def getTotalQuantity(self):
"""
Returns the quantity if no cell or the total quantity if cells
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Account.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Account(XMLObject):
"""
An account is an abstract metanode which holds
currencies. Accounting is implemented through
categories. For example, a sales movement may be
written:
Resource: EUR
Amount: 200
source/compte/produit
destination/compte/client
client/auchan
section/coramy
A purchase movement is written:
Resource: EUR
Amount: 200
source/compte/charge
destination/compte/fournisseur
fournisseur/coramy
section/auchan
Sections allow to implement simple analytical accounting.
(at the present stage, category membership is boolean logics.
at some point, category membership should become fuzzy logics)
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Invoice.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Invoice(AccountingTransaction):
def getTotalPrice(self, **kw):
""" Returns the total price for this invoice """
def getTotalQuantity(self, **kw):
""" Returns the total quantity for this invoice """
def getTotalNetPrice(self):
""" Returns the total net price for this invoice """
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Inventory.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Inventory(Delivery):
"""
Inventory
"""
def alternateReindexObject(self, **kw):
"""
This method is called when an inventory object is included in a
group of catalogged objects.
"""
def appendToCategoryListFromUid(self, category_list, uid, base_category):
def appendToCategoryList(self, category_list, value, base_category):
def splitAndExtendToCategoryList(self, category_list, value, *args, **kw):
def immediateReindexObject(self, temp_constructor=None, **kw):
"""
Rewrite reindexObject so that we can insert lines in stock table
which will be equal to the difference between stock values for
resource in the inventory and the one before the date of this inventory
temp_constructor is used in some particular cases where we want
to have our own temp object constructor, this is usefull if we
want to use some classes with some particular methods
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/OrderRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class OrderRule(DeliveryRule):
"""
Order Rule object make sure an Order in the similation
is consistent with the real order
WARNING: what to do with movement split ?
"""
def expand(self, applied_rule, force=0, **kw):
"""
Expands the Order to a new simulation tree.
expand is only allowed to modify a simulation movement if it doesn't
have a delivery relation yet.
If the movement is in ordered or planned state, has no delivered
child, and is not in order, it can be deleted.
Else, if the movement is in ordered or planned state, has no
delivered child, and is in order, it can be modified.
Else, it cannot be modified.
"""
def isStable(self, applied_rule):
"""
Checks that the applied_rule is stable
"""
def isDivergent(self, movement):
"""
Checks that the movement is divergent
"""
def _getExpandablePropertyDict(self, applied_rule, movement,
"""
Return a Dictionary with the Properties used to edit
the simulation movement
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/MappedValue.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class MappedValue(Predicate, Amount):
"""
A MappedValue allows to associate a value to a domain
Although MappedValue are supposed to be independent of any
design choice, we have to implement them as subclasses of
Amount in order to make sure they provide a complete
variation interface. In particular, we want to be able
to call getVariationValue / setVariationValue on a
MappedValue.
XXX - Amount should be remove from here
Interesting Idea: properties and categories of the mapped value
(not of the predicate) could be handled through additional matrix
dimensions rather than through ad-hoc definition.
"""
def _edit(self, REQUEST=None, force_update = 0, **kw):
def getProperty(self, key, d=None, evaluate=1):
"""
Generic accessor. First we check if the value
exists. Else we call the real accessor
"""
# def _setProperty(self, key, value, type='string', **kw):
# """
# Generic accessor. Calls the real accessor
#
# **kw allows to call setProperty as a generic setter (ex. setProperty(value_uid, portal_type=))
# """
def getMappedValuePropertyList(self, *args):
"""
Return property list managed by this mapped value
Coramy Compatibility Layer - XXX not for Standard Version
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Binder.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Binder(Folder, Document):
"""
A Binder is a Folder wich can be considered as a document.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Machine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Machine(XMLObject):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/InventoryLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class InventoryLine(DeliveryLine):
"""
An Inventory Line describe the inventory of a resource, by variations.
"""
def _edit(self, REQUEST=None, force_update = 0, **kw):
def getTotalInventory(self):
"""
Returns the inventory if no cell or the total inventory if cells
"""
def getQuantity(self):
"""
Computes a quantity which allows to reach inventory
"""
def getConvertedInventory(self):
"""
provides a default inventory value - None since
no inventory was defined.
"""
def getInventoriatedQuantity(self):
"""
Take into account efficiency in converted target quantity
"""
def reindexObject(self, *args, **kw):
"""
Make sure to reindex the inventory
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/BaseCategory.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class BaseCategory(CMFBaseCategory, XMLObject):
"""
Base Categories allow to implement virtual categories
through acquisition
"""
def experimental_listDAVObjects(self):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ProductionOrderRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ProductionOrderRule(OrderRule):
"""
Prouction Order Rule object use a Supply Chain to expand a
Production Order.
"""
def _getExpandablePropertyDict(self, applied_rule, movement,
"""
Return a Dictionary with the Properties used to edit
the simulation movement.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PredicateGroup.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PredicateGroup(Predicate):
"""
aaaa
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Category.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Category(CMFCategory, Predicate, MetaNode, MetaResource):
"""
Category objects allow to define classification categories
in an ERP5 portal. For example, a document may be assigned a color
attribute (red, blue, green). Rather than assigning an attribute
with a pop-up menu (which is still a possibility), we can prefer
in certain cases to associate to the object a category. In this
example, the category will be named color/red, color/blue or color/green
Categories can include subcategories. For example, a region category can
define
region/europe
region/europe/west/
region/europe/west/france
region/europe/west/germany
region/europe/south/spain
region/americas
region/americas/north
region/americas/north/us
region/americas/south
region/asia
In this example the base category is 'region'.
Categories are meant to be indexed with the ZSQLCatalog (and thus
a unique UID will be automatically generated each time a category is
indexed).
Categories allow define sets and subsets of objects and can be used
for many applications :
- association of a document to a URL
- description of organisations (geographical, professional)
Through acquisition, it is possible to create 'virtual' classifications based
on existing documents or categories. For example, if there is a document at
the URL
organisation/nexedi
and there exists a base category 'client', then the portal_categories tool
will allow to create a virtual category
client/organisation/nexedi
Virtual categories allow not to duplicate information while providing
a representation power equivalent to RDF or relational databases.
Categories are implemented as a subclass of BTreeFolders
NEW: categories should also be able to act as a domain. We should add
a Domain interface to categories so that we do not need to regenerate
report trees for categories.
"""
def _experimental_aq_dynamic(self, name):
def experimental_listDAVObjects(self):
"""
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Bug.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Bug(XMLObject, Folder):
"""
Bug means a bug report, a feature request or an issue.
"""
def SearchableText(self):
""" Used by the catalog for basic full text indexing """
return """ %s %s %s """ % ( self.getTitle(),
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/File.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
def _unpackData(data):
"""
Unpack Pdata into string
"""
class File(Document, CMFFile, ConversionCacheMixin):
"""
A File can contain raw data which can be uploaded and downloaded.
It is the root class of Image, OOoDocument (ERP5OOo product),
etc. The main purpose of the File class is to handle efficiently
large files. It uses Pdata from OFS.File for this purpose.
File inherits from XMLObject and can be synchronized
accross multiple sites.
Subcontent: File can only contain role information.
TODO:
* make sure ZODB BLOBS are supported to prevent
feeding the ZODB cache with unnecessary large data
"""
def _edit(self, set_filename__=1, **kw):
"""\
This is used to edit files
"""
def manage_afterClone(self, item):
def manage_afterAdd(self, item, container):
def manage_beforeDelete(self, item, container):
def get_size(self):
"""
has to be overwritten here, otherwise WebDAV fails
"""
def _setFile(self, data, precondition=None):
def setFile(self, data, precondition=None):
def hasFile(self):
"""
Checks whether a file was uploaded into the document.
"""
def hasBaseData(self):
"""
By default, a File instance does not require conversion
to a base format. Therefore, hasBaseData must be overriden.
"""
def guessMimeType(self, fname=''):
"""
get mime type from file name
"""
def PUT(self, REQUEST, RESPONSE):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Event.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Event(EmailDocument, Movement):
"""
Event is the base class for all events in ERP5.
Event objects include emails, phone calls,
The purpose of an Event object is to keep track
of the interface between the ERP and third parties.
Events have a start and stop date.
Events may contain files and local role definitions.
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
def getQuantity(self):
"""
Quantity is set automatically on Events.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/OrderBuilder.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class CollectError(Exception): pass
class MatrixError(Exception): pass
class OrderBuilder(XMLObject, Amount, Predicate):
"""
Order Builder objects allow to gather multiple Simulation Movements
into a single Delivery.
The initial quantity property of the Delivery Line is calculated by
summing quantities of related Simulation Movements.
Order Builder objects are provided with a set a parameters to achieve
their goal:
A path definition: source, destination, etc. which defines the general
kind of movements it applies.
simulation_select_method which defines how to query all Simulation
Movements which meet certain criteria (including the above path path
definition).
collect_order_list which defines how to group selected movements
according to gathering rules.
delivery_select_method which defines how to select existing Delivery
which may eventually be updated with selected simulation movements.
delivery_module, delivery_type and delivery_line_type which define the
module and portal types for newly built Deliveries and Delivery Lines.
Order Builders can also be provided with optional parameters to
restrict selection to a given root Applied Rule caused by a single Order
or to Simulation Movements related to a limited set of existing
Deliveries.
"""
def build(self, applied_rule_uid=None, movement_relative_url_list=None,
"""
Build deliveries from a list of movements
Delivery Builders can also be provided with optional parameters to
restrict selection to a given root Applied Rule caused by a single Order
or to Simulation Movements related to a limited set of existing
"""
def callBeforeBuildingScript(self):
"""
Call a script on the module, for example, to remove some
auto_planned Order.
This part can only be done with a script, because user may want
to keep existing auto_planned Order, and only update lines in
them.
No activities are used when deleting a object, so, current
implementation should be OK.
"""
def searchMovementList(self, applied_rule_uid=None,**kw):
"""
Defines how to query all Simulation Movements which meet certain
criteria (including the above path path definition).
First, select movement matching to criteria define on
DeliveryBuilder.
Then, call script simulation_select_method to restrict
movement_list.
"""
def getCollectOrderList(self):
"""
Simply method to get the 3 collect order lists define on a
DeliveryBuilder
"""
def collectMovement(self, movement_list):
"""
group movements in the way we want. Thanks to this method, we are able
to retrieve movement classed by order, resource, criterion,....
movement_list : the list of movement wich we want to group
check_list : the list of classes used to group movements. The order
of the list is important and determines by what we will
group movement first
Typically, check_list is :
[DateMovementGroup,PathMovementGroup,...]
"""
def testObjectProperties(self, instance, property_dict):
"""
Test instance properties.
"""
def buildDeliveryList(self, movement_group, delivery_relative_url_list=None,
"""
Build deliveries from a list of movements
"""
def _deliveryGroupProcessing(self, delivery_module, movement_group,
"""
Build empty delivery from a list of movement
"""
def _deliveryLineGroupProcessing(self, delivery, movement_group,
"""
Build delivery line from a list of movement on a delivery
"""
def _deliveryCellGroupProcessing(self, delivery_line, movement_group,
"""
Build delivery cell from a list of movement on a delivery line
or complete delivery line
"""
def _setDeliveryMovementProperties(self, delivery_movement,
"""
Initialize or update delivery movement properties.
Set delivery ratio on simulation movement.
"""
def callAfterBuildingScript(self, delivery_list,**kw):
"""
Call script on each delivery built
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Image.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Image(File, OFSImage):
"""
An Image is a File which contains image data. It supports
various conversions of format, size, resolution through
imagemagick. imagemagick was preferred due to its ability
to support PDF files (incl. Adobe Illustrator) which make
it very useful in the context of a graphic design shop.
Image inherits from XMLObject and can be synchronized
accross multiple sites.
Subcontent: Image can only contain role information.
TODO:
* extend Image to support more image file formats,
including Xara Xtreme (http://www.xaraxtreme.org/)
* include upgrade methods so that previous images
in ERP5 get upgraded automatically to new class
"""
def _update_image_info(self):
"""
This method tries to determine the content type of an image and
its geometry. It uses currently OFS.Image for this purpose.
However, this method is known to be too simplistic.
TODO:
- use image magick or PIL
"""
def _upradeImage(self):
"""
This method upgrades internal data structures is required
"""
def getWidth(self):
"""
Tries to get the width from the image data.
"""
def getHeight(self):
"""
Tries to get the height from the image data.
"""
def getContentType(self, format=''):
"""Original photo content_type."""
def tag(self, display=None, height=None, width=None, cookie=0,
"""Return HTML img tag."""
def __str__(self):
def displayIds(self, exclude=('thumbnail',)):
"""Return list of display Ids."""
def displayLinks(self, exclude=('thumbnail',)):
"""Return list of HTML <a> tags for displays."""
def displayMap(self, exclude=None, format='', quality=75, resolution=None):
"""Return list of displays with size info."""
def convert(self, format, display=None, quality=75, resolution=None, frame=None):
"""
Implementation of conversion for PDF files
"""
def index_html(self, REQUEST, RESPONSE, display=None, format='', quality=75,
"""Return the image data."""
def _resize(self, display, width, height, quality=75, format='',
"""Resize and resample photo."""
def writeData(stream, data):
def _getDisplayData(self, display, format='', quality=75, resolution=None, frame=None):
"""Return raw photo data for given display."""
def _getDisplayPhoto(self, display, format='', quality=75, resolution=None, frame=None):
"""Return photo object for given display."""
def _makeDisplayPhoto(self, display, format='', quality=75, resolution=None, frame=None):
"""Create given display."""
def _getAspectRatioSize(self, width, height):
"""Return proportional dimensions within desired size."""
def _validImage(self):
"""At least see if it *might* be valid."""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/EmailDocument.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
"""
A dummy exception class which is used when MimetypesRegistry product is
not installed yet.
"""
class EmailDocument(File, TextDocument):
"""
EmailDocument is a File which stores its metadata in a form which
is similar to a TextDocument.
A Text Document which stores raw HTML and can
convert it to various formats.
"""
def _getMessage(self):
def getContentInformation(self):
"""
Returns the content information from the header information.
This is used by the metadata discovery system.
Header information is converted in UTF-8 since this is the standard
way of representing strings in ERP5.
"""
def getAttachmentInformationList(self, **kw):
"""
Returns a list of dictionnaries for every attachment. Each dictionnary
represents the metadata of the attachment.
**kw - support for listbox (TODO: improve it)
"""
def getAttachmentData(self, index, REQUEST=None):
"""
Returns the decoded data of an attachment.
"""
def getTitle(self, default=_MARKER):
"""
Returns the title
"""
def getStartDate(self, default=_MARKER):
"""
Returns the title
"""
def getTextContent(self, default=_MARKER):
"""
Returns the content of the email as text. This is useful
to display the content of an email.
TODO: add support for legacy objects
"""
def getTextFormat(self, default=_MARKER):
"""
Returns the format of the email (text or html).
TODO: add support for legacy objects
"""
def _convertToBaseFormat(self):
"""
Build a structure which can be later used
to extract content information from this mail
message.
"""
def convert(self, format, **kw):
"""
Convert text using portal_transforms
"""
def hasBaseData(self):
"""
Since there is no need to convert to a base format, we consider that
we always have the base format data if and only is we have
some text defined or a file.
"""
def getReplyBody(self):
"""
This is used in order to respond to a mail,
this put a '> ' before each line of the body
"""
def getReplySubject(self):
"""
This is used in order to respond to a mail,
this put a 'Re: ' before the orignal subject
"""
def getReplyTo(self):
"""
Returns the send of this message based on getContentInformation
"""
def send(self, from_url=None, to_url=None, reply_url=None, subject=None,
"""
Sends the current event content by email. If documents are
attached through the aggregate category, enclose them.
from_url - the sender of this email. If not provided
we will use source to find a valid
email address
to_url - the recipients of this email. If not provided
we will use destination category to
find a list of valid email addresses
reply_url - the email address to reply to. If nothing
is provided, use the email defined in
preferences.
subject - a custom title. If not provided, we will use
getTitle
body - a body message If not provided, we will
use the text representation of the event
as body (UTF-8)
attachment_format - defines an option format
to convet attachments to (ex. application/pdf)
download - if set to True returns, the message online
rather than sending it.
This method is based on the examples provided by
http://docs.python.org/lib/node162.html
TODO: support conversion to base format and use
base format rather than original format
TODO2: consider turning this method into a general method for
any ERP5 document.
"""
def sendMailHostMessage(self, message):
"""
Send one by one
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaySheetLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaySheetLine(InvoiceLine):
"""
A PaySheetLine object allows to implement lines in
PaySheetTransactions.
It may include a price (for employer or employee share, etc.)
"""
def newCellContent(self, id,**kw):
"""
This method can be overriden
"""
def isAccountable(self):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/MetaNode.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class MetaNode(Node):
"""
A Node
"""
def immediateUpdateCapacity(self):
"""
Lookup for capacities children of self and update capacity attributes
by calling portal simulation (deferred)
"""
def updateCapacity(self):
"""
Lookup for capacities children of self and update capacity attributes
by calling portal simulation (deferred)
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AmortisationRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AmortisationRule(Rule):
"""
Amortisation Rule object plans an item amortisation
"""
def expand(self, applied_rule, force=0, **kw):
"""
Expands the current movement downward.
-> new status -> expanded
An applied rule can be expanded only if its parent movement
is expanded.
"""
def updateSimulationMovementProperties(simulation_movement, calculated_movement, set_ratio=0):
"""
Update the properties of the given simulation movement according
to the given calculated_movement.
WARNING : This method does not check if the state of the Amortisation
Transaction corresponding to the Simulation Movement makes it uneditable
set_ratio is used to force the delivery_ratio property update
Return a list of the properties which have been modified
"""
def updateSimulationMovement(aggregated_movement, calculated_movement,
"""
Update the Simulation Movement corresponding to aggregated_movement.
Modify it to respect calculated_movement values.
If the corresponding Amortisation Transaction is already validated,
create a corrective Simulation Movement, since a validated Transaction
must not be modified.
If a correction movement already exists, the new movement takes care of it.
correction_number is the id number for new movements.
Return the number of new Simulation Movements created
"""
def createMovement(property_dict, correction_number):
def updateSimulationMovementToZero(aggregated_movement,
"""
Set the quantity value of the given aggregated movement to 0.
This method takes care of the validated aggregated movements
Return the number of new movements created
"""
def setRemainingAggregatedMovementsToZero(aggregated_movement_dict,
"""
The remaining aggregation movements in aggregated_movement_dict
are set to quantity 0, taking care of their validation state and
the already made correction
"""
def _getCorrectionMovementData(self, aggregated_movement_dict):
"""
Return a dictionary containing the first id number for a new correction movement,
and a re-handled structure containing the correction movements, in order to make
easier their search
It is needed to reduce the number of correction movements. If we can notice that
an aggregated movement is already corrected by a correction movement, we do not
have to correct it again
"""
def _matchAmortisationPeriods(self, calculated_period_dict, aggregated_period_dict):
"""
Try to match each period in calculated_period_dict with a period in
aggregated_period_dict.
It is done by using a "matching ratio" : when two movements of both dictionaries
have a identical property (source, destination, quantity, resource, ...), the
matching ratio is incremented for the correspondance between the both corresponding
periods.
Then, periods are matched in order of priority of the matching ratio.
"""
def calculateMovementMatch(movement_a, movement_b, parameter_list = ['source_section_value',
def _placeMovementInStructure(self, structure, movement_dict, period_number, name):
"""
Used to sort aggregated and calculated movements in a structure
to make easier the correspondance work
"""
def _getAccountingMovement(self, immo_period, previous_period, next_period, period_number=0, item=None, **kw):
"""
Calculates the value of accounting movements during the given period
between the two given immobilisation movements.
"""
def buildImmobilisationCalculatedMovementList(date, period, source_section, destination_section,
def buildUnimmobilisationCalculatedMovementList(date, period, source_section, destination_section,
def buildTransferCalculatedMovementList(date, period, source_section, destination_section,
def buildAnnuityCalculatedMovementList(date, period, annuity, source_section, destination_section,
def buildSpecificCalculatedMovementList(date, period, annuity, source_section, destination_section,
def buildCalculatedMovementList(date, period, annuity, source_section,
def buildAnnuity(from_date, to_date, depr_account, amo_account, precision, depr_name, amo_name):
def isOrderable(self, m):
def isDeliverable(self, m):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ProjectReport.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ProjectReport(Delivery):
"""
A project report allows to report times and expenses related to a project in
a consulting firm. This project report has a starting and and finishing date,
which is mainly used for information and classification.
The time sheet and the expense sheet are both composed of billiable and non-
billiable time and expense to the invoiced client.
The amount of time on a particular project relates to a client.
A expense relates to a project.
OUTPHASED BY TASK REPORT
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Project.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Project(Order):
"""
Project is a class which describes a typical project in consulting firm.
A project has a client, an invoiced client. A project has also a start
date and a stop date. It is composed of several tasks.
Each task has a person to perform it, a certain amount of time, a date,
a place, a description. For each person and each task, there is dedicated
time rate.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PresencePeriod.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PresencePeriod(Movement, PeriodicityMixin):
"""
Presence Period is used to add available time of the user in a
period of Time
"""
def isAccountable(self):
"""
For now, consider that it's always accountable
"""
def getDestinationUid(self, *args, **kw):
"""
Return the destination uid
"""
def getInventoriatedQuantity(self, default=None, *args, **kw):
"""
Surcharged accessor to calculate the Quantity in second
from stop date and start date values.
"""
def asMovementList(self):
"""
Generate multiple movement from a single one.
It is used for cataloging a movement multiple time in
the movement/stock tables.
Ex: a movement have multiple destinations.
asMovementList returns a list a movement context with different
single destination.
"""
def _getDatePeriodList(self):
"""
Get all periods between periodicity start date
and periodicity stop date
"""
def getNextPeriodicalDate(self, current_date, next_start_date=None):
"""
Get the next date where this periodic event should start.
XXX It completely reimplements the PeriodictyMixin method because
the minimal duration between dates is day, and not minute
Better way would be to improve the API of getNextPeriodicalDate,
and optimize addToDate method.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Domain.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Domain(Predicate, MetaNode, MetaResource):
"""
Domain can be used as MetaNodes or MetaResources. For example,
a Domain viewed as a MetaNode can search for all emerging movements
and compare it with its capacity.
Structure is:
- base domain (like base category)
- sub domain (like category)
Allows to define ranges:
- price between X and Y
- portal_type in (a, b, c)
- price between X and Y and region in (a, b, c)
Reports:
- listbox allows to produce reports
- output to html, pdf or ooffice
- definition through the web (ie. which field in which column, which statistics)
- definition of selection (to list)
- ability for use to "save" favourite report (user reports)
- library of favourite reports (global reports)
- matrixbox allows to produce reports
- output to html, pdf or ooffice
- definition through the web (ie. which base_category or base_domain in which axis)
- definition of selection (to map to matrix)
- ability for use to "save" favourite report (user reports)
- library of favourite reports (global reports)
Domain and Domain Generators are now unified. Any domain may act
as a domain generator or as a simple predicate.
A Domain Generator uses a method (SQL, Python) to select objects
which are then wrapped as Virtual Domains. This can be used for
example to provide the list the 10 best selling shops to
a report tree.
"""
def getRelativeUrl(self):
"""
We must eliminate portal_categories in the RelativeUrl
since it is never present in the category list
"""
def getDomainGeneratorList(self, depth=0):
"""
We call a script which builds for us a list DomainGenerator instances
We need a way to know how deep we are in the domain generation
to prevent infinite recursion XXX not implemented
"""
def generateTempDomain(self, id):
"""
We generate temp domain here because we must set an aquisition wrapper
"""
def getChildDomainValueList(self, parent = None, **kw):
"""
Return child domain objects already present or me may generate
dynamically childs.
"""
def experimental_listDAVObjects(self):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PackingList.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PackingList(Delivery):
"""
Delivery/PackingList is the main document
which allows to control causality in the simulation
PackingList have 2 different states:
- solved: this happens when quantities and target
quantities are the same
- diverged: this happens when quantities and target
quantities are different
Resolution of diverged PackingList is achieved by workflow
methods. Such workflow methods eventually change
movements in the simulation. Typical solution include:
- reduce quantity
- split delivery
- postpone delivery
solutions are implemented as solvers
"""
def isDivergent(self,**kw):
"""
Returns 1 if not simulated or inconsistent target and values
"""
def isPacked(self):
"""
Returns 0 if all quantity resource on packing list line
are not in container.
It works only if a Resource is not on 2 PackingListLine.
"""
def updateAppliedRule(self, rule_id=None, rule_reference=None, **kw):
"""XXX FIXME: Kept for compatibility.
updateAppliedRule must be called with a rule_reference in a workflow
script.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Calendar.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Calendar(Path, XMLObject):
"""
Calendar contains Calendar Lines.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/RoleDefinition.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class RoleDefinition(XMLObject):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/BankAccount.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class BankAccount(Folder, Coordinate, MetaNode):
"""
A bank account number holds a collection of numbers and codes
(ex. SWIFT, RIB, etc.) which may be used to identify a bank account.
A Bank Account is owned by a Person or an Organisation. A Bank Account
contain Agents with Agent Privileges used by the owner to delegate the
management of the bank account to trusted third-party Persons.
BankAccount inherits from Base and from the mix-in Coordinate.
"""
def getReference(self, *args, **kw):
"""reference depends on the site configuration.
"""
# def getBankCode(self, **kw):
# """
# Never return None.
# """
# def getBranch(self, **kw):
# """
# Never return None.
# """
# def getBankAccountNumber(self, **kw):
# """
# Never return None.
# """
# def getBankCountryCode(self, **kw):
# """
# Never return None.
# """
# def getIbanTextFormat(self):
# """
# Returns the standard IBAN text format
# """
# def getIban(self):
# """
# The International Bank Account Number of this bank account.
# IBAN is an international standard for identifying bank accounts worldwide.
# """
# def getIbanKey(self):
# """
# The IBAN key ensure the integry of the IBAN code.
# It's calculated with the ISO 7064 method (known as "97-10 modulo").
# """
# def getBban(self):
# """
# The Basic Bank Account Number (BBAN) is the last part of the IBAN.
# Usualy it correspond to the national bank account number.
# """
# def getBbanTextFormat(self, sep=' '):
# """
# Returns a BBAN text format
# """
# def getBbanKey(self):
# """
# The BBAN key ensure the integry of the BBAN code.
# This is the french BBAN key algorithm.
# """
# def transcode(string):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ProductionReportLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ProductionReportLine(DeliveryLine):
"""
Production Report Lines allow to ...
"""
def newCellContent(self, id,**kw):
"""
This method can be overriden
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Variation.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Variation(XMLObject):
"""
A Variation
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/TransformationRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class TransformationRuleError(Exception): pass
class TransformationRule(Rule):
"""
Order Rule object make sure an Order in the similation
is consistent with the real order
"""
def expand(self, applied_rule, **kw):
"""
Expands the current movement downward.
-> new status -> expanded
An applied rule can be expanded only if its parent movement
is expanded.
"""
def _expandProducedResource(self, applied_rule, production,
"""
Produced resource.
Create a movement for the resource produced by the transformation.
Only one produced movement can be created.
"""
def _expandConsumedResource(self, applied_rule, production,
"""
Consumed resource.
Create a movement for each resource consumed by the transformation,
and for the previous variation of the produced resource.
"""
def _expandConsumedPreviousVariation(self, applied_rule, production,
"""
Create a movement for the previous variation of the produced resource.
"""
def _expandConsumedRawMaterials(self, applied_rule, production,
"""
Create a movement for each resource consumed by the transformation,
"""
def solve(self, applied_rule, solution_list):
"""
Solve inconsistency according to a certain number of solutions
templates. This updates the
-> new status -> solved
This applies a solution to an applied rule. Once
the solution is applied, the parent movement is checked.
If it does not diverge, the rule is reexpanded. If not,
diverge is called on the parent movement.
"""
def diverge(self, applied_rule):
"""
-> new status -> diverged
This basically sets the rule to "diverged"
and blocks expansion process
"""
# def isDivergent(self, applied_rule):
# """
# Returns 1 if divergent rule
# """
# def getDivergenceList(self, applied_rule):
# """
# Returns a list Divergence descriptors
# """
# def getSolverList(self, applied_rule):
# """
# Returns a list Divergence solvers
# """
def isDeliverable(self, m):
def isOrderable(self, m):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/MetaResource.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class MetaResource(Resource):
"""
A Resource
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Agent.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Agent(Folder, Image):
"""
An Agent is a Person who is permitted to perform some actions on the bank
account according to Privileges.
"""
def __init__(self, *args, **kw):
def importSignature(self, import_file=None, form_id=None, REQUEST=None, **kw):
"""
Imports a scan of a signature.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Amount.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Amount(Base, Variated):
"""
A mix-in class which provides some utilities
(variations, conversions, etc.)
Utilities include
- getVariation accesors (allows to access variations of whatever)
-
"""
def getVariationCategoryList(self, default=[], base_category_list=(),
"""
Returns the possible discrete variations
(as a list of relative urls to categories)
"""
def getVariationCategoryItemList(self, base_category_list=(), base=1,
"""
Returns the list of possible variations
XXX Copied and modified from Variated
Result is left display.
"""
def _setVariationCategoryList(self, value):
def setVariationCategoryList(self, value):
def getVariationBaseCategoryList(self, default=[],
"""
Return the list of base_category from all variation related to
amount.
It is maybe a nonsense, but useful for correcting user errors.
"""
def getVariationBaseCategoryItemList(self,display_id='title_or_id',**kw):
"""
Returns a list of base_category tuples.
"""
def getVariationValue(self):
"""
New Method for dicrete and countinuous variations
using a VariantValue instance
A new instance of VariationValue is created with categories
and attributes set to what they should be.
A this point, we only implement discrete variations
"""
def _setVariationValue(self, variation_value):
def setVariationValue(self, variation_value):
def getVariationRangeCategoryItemList(self, **kw):
"""
Returns possible variation category values for the
order line according to the default resource.
Possible category values is provided as a list of
tuples (id, title). This is mostly
useful in ERP5Form instances to generate selection
menus.
"""
def getVariationRangeCategoryList(self, default=[], base_category_list=(),
"""
Returns possible variation category values for the
order line according to the default resource.
"""
def getVariationRangeBaseCategoryList(self, default=[], omit_option_base_category=0):
"""
Returns possible variations base categories for this amount ie.
the variation base category of the resource (not the
variation range).
Should be a range because we shall variate the amount
into cells (ie. the line into cells) on part of the
getVariationRangeBaseCategoryList -> notion of
getVariationBaseCategoryList is different
"""
def getVariationRangeBaseCategoryItemList(self, omit_option_base_category=0,
"""
Returns possible variations base categories for this amount ie.
the variation base category of the resource (not the
variation range).
"""
def getVariationPropertyDict(self):
"""
Return a dictionary of:
{property_id: property_value,}
Each property is a variation of the resource.
The variation property list is defined on resource,
with setVariationPropertyList.
"""
def setVariationPropertyDict(self, property_dict):
"""
Take a parameter a property dict like:
{property_id: property_value,}
Each property is a variation of the resource.
If one of the property_id is not a variation, a exception
KeyError is raised.
"""
def getQuantityUnitRangeItemList(self, base_category_list=()):
def getResourceDefaultQuantityUnit(self):
"""
Return default quantity unit of the resource
"""
def getResourcePrice(self):
"""
Return price of the resource in the current context
The price is expressed in the standard unit of the resource (?)
"""
def getDuration(self):
"""
Return duration in minute
"""
def getPrice(self):
def getTotalPrice(self, **kw):
"""
Return total price for the number of items
Price is defined on
"""
def getConvertedQuantity(self):
"""
Converts quantity to default unit
"""
def setConvertedQuantity(self, value):
def getNetQuantity(self):
"""
Take into account efficiency in quantity
"""
def getNetTargetQuantity(self):
"""
Take into account efficiency in target quantity
"""
def getNetConvertedQuantity(self):
"""
Take into account efficiency in converted quantity
"""
def setNetConvertedQuantity(self, value):
"""
Take into account efficiency in converted quantity
"""
def getNetConvertedTargetQuantity(self):
"""
Take into account efficiency in converted target quantity
"""
def setNetConvertedTargetQuantity(self, value):
"""
Take into account efficiency in converted quantity
"""
def getInventoriatedQuantity(self):
"""
Take into account efficiency in converted target quantity
"""
def getProductionQuantity(self,quantity=None):
"""
Return the produced quantity
"""
def getConsumptionQuantity(self,quantity=None):
"""
Return the consumption quantity
"""
def setProductionQuantity(self, value):
"""
Return the produced quantity
"""
def setConsumptionQuantity(self, value):
"""
Return the produced quantity
"""
def getConvertedInventory(self):
"""
provides a default inventory value - None since
no inventory was defined.
"""
# def getStandardInventoriatedQuantity(self):
# """
# The inventoriated quantity converted in a default unit
#
# For assortments, returns the inventoriated quantity in terms of number of items
# in the assortemnt.
#
# For accounting, returns the quantity converted in a default unit
# """
def getLostQuantity(self):
def setLostQuantity(self, value):
def _setLostQuantity(self, value):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/SetPricing.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SetPricing(MappedValue, XMLMatrix):
"""
Un element de tarif est un prix pour un ensemble de conditions d'application...
"""
def _setQuantityRangeList(self, category_list):
"""
Defines the possible base categories which Quantity value (Q)
variate on
"""
def setQuantityRangeList(self, category_list):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AccountingTransactionLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AccountingTransactionLine(DeliveryLine):
"""
Accounting Transaction Lines allow to move some quantity of money from
a source to a destination
"""
def getInventoriatedQuantity(self):
"""
Redefine this method here, because AccountingTransactionLine does
not have target values.
"""
def getInventoriatedStartDate(self):
"""
Get the start date.
"""
def getInventoriatedStopDate(self):
"""
Get the stop date.
"""
def getPrice(self, context=None):
"""
On accounting transaction lines, the price is always set to 1.
We use the `quantity` property for the default quantity, and the
converted value for source in getSourceInventoriatedTotalAssetPrice
and getDestinationInventoriatedTotalAssetPrice for destination.
"""
def getSourceAssetPrice(self):
"""
The price is set to 1.0 because we do not want to implement
automatic currency conversion in accounting. Users must define the
conversion manually in accounting. This is required by accounting
law. One can not account USD (in a EUR based company) without
defining the equivalent in EUR.
"""
def getDestinationAssetPrice(self):
"""
The price is set to 1.0 because we do not want to implement
automatic currency conversion in accounting. Users must define the
conversion manually in accounting. This is required by accounting
law. One can not account USD (in a EUR based company) without
defining the equivalent in EUR.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AmountFilter.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AmountFilter(MappedValue, Amount):
"""
An AmountFilter allows to define last minute
changes in a transformation. For example: different
quantity, different efficiency, different resource.
They are used mainly to customize production orders
and are parsed by TransformationRule.
It follows the mapped value API and is defined
as an amount (resource, variation, quantity, efficiency)
Definition is based on target values and values. For example,
- quantity: 20
- target_quantity: 25
Means that we will actualy use 25 instead of theoretical 20.
"""
def update(self, amount_line):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/OrderCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class OrderCell(DeliveryCell):
"""
A OrderCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
def reindexObject(self, *k, **kw):
"""
Reindex children and simulation
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Delivery.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Delivery(XMLObject, ImmobilisationDelivery):
"""
Each time delivery is modified, it MUST launch a reindexing of
inventories which are related to the resources contained in the Delivery
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
def _getTotalPrice(self, context):
def _getDefaultTotalPrice(self, context):
def _getSourceTotalPrice(self, context):
def _getDestinationTotalPrice(self, context):
def getDefaultTotalPrice(self, context=None, REQUEST=None, **kw):
"""
"""
def getSourceTotalPrice(self, context=None, REQUEST=None, **kw):
"""
"""
def getDestinationTotalPrice(self, context=None, REQUEST=None, **kw):
"""
"""
def updatePrice(self):
def getTotalPrice(self, fast=1, src__=0, **kw):
""" Returns the total price for this order
if the `fast` argument is set to a true value, then it use
SQLCatalog to compute the price, otherwise it sums the total
price of objects one by one.
So if the order is not in the catalog, getTotalPrice(fast=1)
will return 0, this is not a bug.
"""
def getTotalQuantity(self, fast=1, src__=0, **kw):
""" Returns the total quantity of this order.
if the `fast` argument is set to a true value, then it use
SQLCatalog to compute the quantity, otherwise it sums the total
quantity of objects one by one.
So if the order is not in the catalog, getTotalQuantity(fast=1)
will return 0, this is not a bug.
"""
def getDeliveryUid(self):
def getDeliveryValue(self):
"""
Deprecated, we should use getRootDeliveryValue instead
"""
def getRootDeliveryValue(self):
"""
This method returns the delivery, it is usefull to retrieve the delivery
from a line or a cell
"""
def getDelivery(self):
def getMovementList(self, portal_type=None, **kw):
"""
Return a list of movements.
"""
def getSimulatedMovementList(self):
"""
Return a list of simulated movements.
This does not contain Container Line or Container Cell.
"""
def getInvoiceMovementList(self):
"""
Return a list of simulated movements.
This does not contain Container Line or Container Cell.
"""
def getContainerList(self):
"""
Return a list of root containers.
This does not contain sub-containers.
"""
def applyToDeliveryRelatedMovement(self, portal_type='Simulation Movement',
def isConvergent(self,**kw):
"""
Returns 0 if the target is not met
"""
def isSimulated(self):
"""
Returns 1 if all movements have a delivery or order counterpart
in the simulation
"""
def isDivergent(self, fast=0, **kw):
"""
Returns 1 if the target is not met according to the current information
After and edit, the isOutOfTarget will be checked. If it is 1,
a message is emitted
emit targetUnreachable !
"""
def getDivergenceList(self, **kw):
"""
Return a list of messages that contains the divergences
"""
def updateCausalityState(self, **kw):
"""
This is often called as an activity, it will check if the
deliver is convergent, and if so it will put the delivery
in a solved state, if not convergent in a diverged state
"""
def _updateCausalityState(self, **kw):
def splitAndDeferMovementList(self, start_date=None, stop_date=None,
"""
this method will unlink and delete movements in movement_uid_list and
rebuild a new Packing List with them.
1/ change date in simulation, call TargetSolver and expand
2/ detach simulation movements from to-be-deleted movements
3/ delete movements
XXX make sure that all detached movements are deleted at the same
time, else the interaction workflow would reattach them to a delivery
rule.
4/ call builder
"""
def reindexObject(self, *k, **kw):
"""
Reindex children and simulation
"""
def _getMovementResourceList(self):
def getInventory(self, **kw):
"""
Returns inventory
"""
def getCurrentInventory(self, **kw):
"""
Returns current inventory
"""
def getAvailableInventory(self, **kw):
"""
Returns available inventory
(current inventory - deliverable)
"""
def getFutureInventory(self, **kw):
"""
Returns inventory at infinite
"""
def getInventoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getCurrentInventoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getFutureInventoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getInventoryStat(self, **kw):
"""
Returns statistics of inventory grouped by section or site
"""
def getCurrentInventoryStat(self, **kw):
"""
Returns statistics of inventory grouped by section or site
"""
def getFutureInventoryStat(self, **kw):
"""
Returns statistics of inventory grouped by section or site
"""
def getInventoryChart(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getCurrentInventoryChart(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getFutureInventoryChart(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getInventoryHistoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getInventoryHistoryChart(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getMovementHistoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getMovementHistoryStat(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
# def getInventoryAssetPrice(self, **kw):
# """
# Returns asset at infinite
# """
# def getFutureInventoryAssetPrice(self, **kw):
# """
# Returns asset at infinite
# """
# def getCurrentInventoryAssetPrice(self, **kw):
# """
# Returns asset at infinite
# """
# def getAvailableInventoryAssetPrice(self, **kw):
# """
# Returns asset at infinite
# """
def _edit(self, REQUEST=None, force_update = 0, **kw):
"""
call propagateArrowToSimulation
"""
def notifySimulationChange(self):
"""
WorkflowMethod used to notify the causality workflow that the simulation
has changed, so we have to check if the delivery is divergent or not
"""
def updateAppliedRule(self, *args, **kw):
"""
Create a new Applied Rule if none is related, or call expand
on the existing one.
The chosen applied rule will be the validated rule with reference ==
rule_reference, and the higher version number.
If no rule is found, simply pass rule_reference to _createAppliedRule,
to keep compatibility vith the previous behaviour
"""
def _updateAppliedRule(self, rule_reference=None, rule_id=None, force=0,
def _createAppliedRule(self, rule_id, force=0, activate_kw=None, **kw):
"""
Create a new Applied Rule is none is related, or call expand
on the existing one.
"""
def expand(self, *args,**kw):
"""
Reexpand applied rule
Also reexpand all rules related to movements
"""
def _expand(self, applied_rule_id=None, force=0, activate_kw=None,**kw):
def expandRuleRelatedToMovement(self,excluded_rule_path_list=None,
"""
Some delivery movement may be related to another applied rule than
the one related to the delivery. Delivery movements may be related
to many simulation movements from many different root applied rules,
so it is required to expand the applied rule parent to related
simulation movements.
exclude_rule_path : do not expand this applied rule (or children
applied rule)
"""
def getRootCausalityValueList(self):
"""
Returns the initial causality value for this movement.
This method will look at the causality and check if the
causality has already a causality
"""
def setRootCausalityValueList(self,value):
"""
This is a hack
"""
def getParentExplanationValue(self):
"""
This method should be removed as soon as movement groups
will be rewritten. It is a temp hack
"""
def setParentExplanationValue(self,value):
"""
This is a hack
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/InvoicingRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class InvoicingRule(Rule):
"""
Invoicing Rule expand simulation created by a order or delivery rule.
"""
def isAccountable(self, movement):
"""
Tells wether generated movement needs to be accounted or not.
Invoice movement are never accountable, so simulation movement for
invoice movements should not be accountable either.
"""
def _generatePrevisionList(self, applied_rule, **kw):
"""
Generate a list of movements, that should be children of this rule,
based on its context (parent movement, delivery, configuration ...)
These previsions are acrually returned as dictionaries.
"""
def expand(self, applied_rule, force=0, **kw):
"""
Expands the rule:
- generate a list of previsions
- compare the prevision with existing children
- get the list of existing movements (immutable, mutable, deletable)
- compute the difference between prevision and existing (add,
modify, remove)
- add/modify/remove child movements to match prevision
"""
def isDeliverable(self, movement):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ContainerCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ContainerCell(DeliveryCell):
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
def isDivergent(self):
"""
Returns 1 if the target is not met according to the current information
After and edit, the isOutOfTarget will be checked. If it is 1,
a message is emitted
emit targetUnreachable !
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ImmobilisationDelivery.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ImmobilisationDelivery(XMLObject):
"""
An Immobilisation Delivery is an object whose role is to
contain delivery movements which can immobilise items.
"""
def updateImmobilisationState(self, **kw):
"""
This is often called as an activity, it will check if the
delivery is valid as an immobilisation movement, and if so
it will put the delivery in a valid state, if not valid in
an invalid state
"""
def getImmobilisationMovementList(self, **kw):
"""
Return regular movements + immobilisation movements like
Immobilisation Line and Immobilisation Cell
"""
def checkImmobilisationConsistency(self, *args, **kw):
"""
Check the consistency about immobilisation values
"""
def isValidImmobilisationMovement(self, *args, **kw):
"""
Return true if all submovements are valid in terms of immobilisation
"""
def isInvalidImmobilisationMovement(self, *args, **kw):
"""
Return false if all submovements are valid in terms of immobilisation
"""
def getAggregatedItemsNextImmobilisationMovementValueList(self, **kw):
"""
Return the list of each next immobilisation movement for each aggregated item
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/MailMessage.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class MailMessage(Event, CMFMailInMessage):
"""
LEGACY
The MailMessage class is deprecated. It is superceded by
the Event class (for CRM events) and by the EmailDocument class
(to store raw email messages).
TODO: compatibility layer is required so that old MailMessage
instance can mimic Event instances based on legacy data. This
is required for example for old CRM implementations of ERP5.
"""
def getReplyBody(self):
"""
This is used in order to respond to a mail,
this put a '> ' before each line of the body
"""
def getReplySubject(self):
"""
This is used in order to respond to a mail,
this put a 'Re: ' before the orignal subject
"""
def send(self, from_url=None, to_url=None, msg=None, subject=None):
"""
Sends a reply to this mail message.
"""
def getTextContent(self, default=_MARKER):
"""
Overload EmailDocument method to add backward compatibility layer
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Currency.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Currency(Resource):
"""
Currency
"""
def convertQuantity(self, quantity, from_unit, to_unit):
def convertCurrency(self, quantity, to_currency):
def asNumericCode(self):
"""Return a numeric code defined in ISO 4217."""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/BalanceTransaction.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class InventoryKey(UserDict):
"""Class to use as a key when defining inventory dicts.
"""
def __init__(self, **kw):
def clear(self):
def pop(self, keys, *args):
def update(self, dict=None, **kwargs):
def __delitem__(self, key):
def __setitem__(self, key, item):
def setdefault(self, key, failobj=None):
def __hash__(self):
def __cmp__(self, other):
class BalanceTransaction(AccountingTransaction, Inventory):
"""Balance Transaction
"""
def _getGroupByNodeMovementList(self):
"""Returns movements that implies only grouping by node."""
def _getGroupByPaymentMovementList(self):
"""Returns movements that implies grouping by node and payment"""
def _getGroupByMirrorSectionMovementList(self):
"""Returns movements that implies only grouping by node and mirror section"""
def _getCurrentStockDict(self):
"""Looks the current stock by calling getInventoryList, and building a
dictionnary of InventoryKey
"""
def _getNewStockDict(self):
"""Looks the new stock on lines in this inventory, and building a
dictionnary of InventoryKey
"""
def _computeStockDifferenceList(self, current_stock_dict, new_stock_dict):
"""Compute the difference between the result of _getCurrentStockDict and
_getNewStockDict. Returns a list of dictionnaries with similar keys that
the ones on inventory brains (node, section, mirror_section ...)
"""
def computeStockDifference(current_stock_list, new_stock_list):
def negateStock(stock):
def _getTempObjectFactory(self):
"""Returns the factory method that will create temp object.
This method must return a function that accepts properties keywords
arguments and returns a temp object edited with those properties.
"""
def factory(*args, **kw):
def URLGetter(url):
def getRelativeUrl():
def PathGetter(path):
def getPath():
def alternateReindexObject(self, **kw):
"""This method is called when an inventory object is included in a
group of catalogged objects.
"""
def immediateReindexObject(self, **kw):
"""Reindexes the object.
This is different indexing that the default Inventory indexing, because
we want to take into account that lines in this balance transaction to
represent the balance of an account (node) with different parameters,
based on the account_type of those accounts:
- on standards accounts: it's simply the balance for node, section
(and maybe resource, like all of thoses)
- on payable / receivable accounts: for node, section and mirror
section
- on bank accounts: for node, section and payment
Also this uses total_price (and quantity), and ignores variations and
subvariations as it does not exist in accounting.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/DeliveryLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class DeliveryLine(Movement, XMLObject, XMLMatrix, Variated,
"""
A DeliveryLine object allows to implement lines in
Deliveries (packing list, order, invoice, etc.)
It may include a price (for insurance, for customs, for invoices,
for orders)
"""
def getSimulationState(self):
"""
Explicitly acquire simulation_state from parent
"""
def _edit(self, REQUEST=None, force_update = 0, **kw):
def edit(self, REQUEST=None, force_update = 0, reindex_object=1, **kw):
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
def _getTotalPrice(self, context, fast=1):
""" Returns the total price for this line or the cells it contains. """
def getTotalQuantity(self, fast=1):
"""
Returns the quantity if no cell or the total quantity if cells
If fast is equal to 0, we returns the right quantity even
if there is nothing into the catalog or the catalog is not
up to date
"""
def hasCellContent(self, base_id='movement'):
"""Return true if the object contains cells.
"""
def getCellValueList(self, base_id='movement'):
"""
This method can be overriden
"""
def getCell(self, *kw , **kwd):
"""
This method can be overriden
"""
def newCell(self, *kw, **kwd):
"""
This method creates a new cell
"""
def isDivergent(self):
"""
Returns 1 if the target is not met according to the current information
After and edit, the isOutOfTarget will be checked. If it is 1,
a message is emitted
emit targetUnreachable !
"""
def getDivergenceList(self):
"""
Return a list of messages that contains the divergences
"""
def applyToDeliveryLineRelatedMovement(self, portal_type='Simulation Movement', method_id = 'expand'):
def reindexObject(self, *k, **kw):
"""Reindex children"""
def getInventoriatedQuantity(self):
"""
"""
def getInventoriatedStartDate(self):
"""
"""
def getInventoriatedStopDate(self):
"""
"""
# def _checkConsistency(self, fixit=0, mapped_value_property_list = ('quantity', 'price')):
# """
# Check the constitency of transformation elements
# """
def getSimulationQuantity(self):
"""
Computes the quantities in the simulation
"""
def getSimulationSourceList(self):
"""
Computes the sources in the simulation
"""
def getSimulationDestinationList(self):
"""
Computes the destinations in the simulation
"""
def getSimulationSourceSectionList(self):
"""
Computes the source sections in the simulation
"""
def getSimulationDestinationSectionList(self):
"""
Computes the destination sections in the simulation
"""
def getRootDeliveryValue(self):
"""
Returns the root delivery responsible of this line
"""
def updateSimulationDeliveryProperties(self, movement_list = None):
"""
Set properties delivery_ratio and delivery_error for each
simulation movement in movement_list (all movements by default),
according to this delivery calculated quantity
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ExtFolder.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Deletion(TM):
"""Remove the directory at the end of a transaction.
"""
def __init__(self, path):
def _finish(self):
def _abort(self):
class ExtFolder( XMLObject ):
"""
ExtFolder stores sub-objects as ExtFile or ExtImage.
"""
def PUT_factory( self, name, typ, body ):
"""Return an ExtFile or ExtImage object.
"""
def _getRepositoryPath(self):
"""Return the path in the filesystem.
"""
def generateRpmHeaderList(self):
"""Run genhdlist on the directory behind this object.
"""
def generateBt5HeaderList(self):
"""Run genbt5list on the directory behind this object.
"""
def manage_beforeDelete(self, item, container):
"""Called before deleting this object.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/InventoryCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class InventoryCell(DeliveryCell):
"""
An InventoryCell allows to define specific inventory
for each variation of a resource in an inventory line.
"""
def _edit(self, REQUEST=None, force_update = 0, **kw):
def getTotalInventory(self):
"""
Returns the inventory if no cell or the total inventory if cells
"""
def getQuantity(self):
"""
Computes a quantity which allows to reach inventory
"""
def getConvertedInventory(self):
"""
provides a default inventory value - None since
no inventory was defined.
"""
def reindexObject(self, *args, **kw):
"""
Make sure to reindex the inventory
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/CategoryDivergenceTester.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class CategoryDivergenceTester(PropertyDivergenceTester):
"""
The purpose of this divergence tester is to check the
consistency between delivery movement and simulation movement
for some specific categories.
"""
def explain(self, simulation_movement):
"""
This method returns a list of messages that contains
the divergence of the Delivery Line.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/QuantityDivergenceTester.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class QuantityDivergenceTester(PropertyDivergenceTester):
"""
The purpose of this divergence tester is to check the
consistency between delivery movement and simulation movement
for the property quantity.
"""
def explain(self, simulation_movement):
"""
This method returns a list of messages that contains
the divergence of the Delivery Line.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/BaseDomain.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class BaseDomain(Domain):
"""
Base Domain is the root of a tree of domains which can be used
as nodes in a report tree of ListBox
Domain can be used as MetaNodes or MetaResources. For example,
a Domain viewed as a MetaNode can search for all emerging movements
and compare it with its capacity.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Url.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class UrlMixIn:
def asURL(self):
"""
Returns a text representation of the Url if defined
or None else.
"""
def fromURL(self, url):
"""
Analyses a URL and splits it into two parts. URLs
normally follow RFC 1738. However, we accept URLs
without the protocol a.k.a. scheme part (http, mailto, etc.). In this
case only the url_string a.k.a. scheme-specific-part is taken
into account. asURL will then generate the full URL.
"""
class Url(Coordinate, Base, UrlMixIn):
"""
A Url is allows to represent in a standard way coordinates
such as web sites, emails, ftp sites, etc.
"""
def asText(self):
"""
Returns a text representation of the url_string a.k.a. scheme-specific-part
This method is useful to handled emails, web pages of companies, etc.
in the same way as for other coordinates (ex. telephones). Most
users just enter www.erp5.com or info@erp5.com rather than
http://www.erp5.com or mailto:info@erp5.com
"""
def fromText(self, text):
"""
Sets url_string a.k.a. scheme-specific-part of a URL
"""
def standardTextFormat(self):
"""
Returns the standard text formats for urls. The purpose
of this method is unknown.
"""
def send(self, from_url=None, to_url=None, msg=None,
"""
This method was previously named 'SendMail' and is used to send email
* attachment_list is a list of dictionnaries with those keys:
- name : name of the attachment,
- content: data of the attachment
- mime_type: mime-type corresponding to the attachment
* extra_headers is a dictionnary of custom headers to add to the email.
"X-" prefix is automatically added to those headers.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/BalanceTransactionLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class BalanceTransactionLine(AccountingTransactionLine, InventoryLine):
"""A balance transaction line inherits price handling from accounting
transaction line, and indexing from inventory line.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/SupplyLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SupplyLine(DeliveryLine, Path):
"""A Supply Line is a path to define price
"""
def getPrice(self):
def getTotalPrice(self):
"""
Returns the totals price for this line
"""
def _getPrice(self, context):
def _getDefaultPrice(self, context):
def _getTotalPrice(self, context):
def _getDefaultTotalPrice(self, context):
def isAccountable(self):
"""Supply Line are not accounted.
"""
def getDefaultPrice(self, context=None, REQUEST=None, **kw):
"""
"""
def getDefaultTotalPrice(self, context=None, REQUEST=None, **kw):
"""
"""
def hasCellContent(self, base_id='path'):
"""
This method can be overriden
"""
def getCellValueList(self, base_id='path'):
"""
This method can be overriden
"""
def getCell(self, *kw , **kwd):
"""
This method can be overriden
"""
def newCell(self, *kw, **kwd):
"""
This method creates a new cell
"""
def getQuantityPredicateIdList(self, price_parameter):
"""
Return predicate id related to a price parameter.
"""
def getQuantityPredicateValueList(self, price_parameter):
"""
Return predicate related to a price parameter.
"""
def getQuantityStepList(self, *args, **kw):
"""
Return predicate step related to a price_parameter
"""
def updateQuantityPredicate(self, price_parameter):
"""
Update the quantity predicate for this price parameter
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/TransformationSourcingRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ProductionOrderError(Exception): pass
class TransformationSourcingRuleError(Exception): pass
class TransformationSourcingRuleMixin(ExtensionClass.Base):
"""
Mixin class used by TransformationSourcingRule and TransformationRule
"""
def getSupplyChain(self, applied_rule):
"""
Get the SupplyChain.
"""
def getCurrentSupplyLink(self, movement):
"""
Get the current SupplyLink
"""
def _buildMovementList(self, applied_rule, movement_dict,activate_kw=None,**kw):
"""
For each movement in the dictionnary, test if the movement already
exists.
If not, create it.
Then, update the movement attributes.
"""
def getTransformation(self, movement):
"""
Get transformation related to used by the applied rule.
"""
class TransformationSourcingRule(Rule):
"""
Transformation Sourcing Rule object make sure
items required in a Transformation are sourced
"""
def expand(self, applied_rule, activate_kw=None,**kw):
"""
Expands the current movement downward.
-> new status -> expanded
An applied rule can be expanded only if its parent movement
is expanded.
"""
def solve(self, applied_rule, solution_list):
"""
Solve inconsistency according to a certain number of solutions
templates. This updates the
-> new status -> solved
This applies a solution to an applied rule. Once
the solution is applied, the parent movement is checked.
If it does not diverge, the rule is reexpanded. If not,
diverge is called on the parent movement.
"""
def diverge(self, applied_rule):
"""
-> new status -> diverged
This basically sets the rule to "diverged"
and blocks expansion process
"""
# def isDivergent(self, applied_rule):
# """
# Returns 1 if divergent rule
# """
# def getDivergenceList(self, applied_rule):
# """
# Returns a list Divergence descriptors
# """
# def getSolverList(self, applied_rule):
# """
# Returns a list Divergence solvers
# """
def isDeliverable(self, m):
def isOrderable(self, m):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/DeliveryRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class DeliveryRule(Rule):
"""
Delivery Rule object make sure orphaned movements in a Delivery
(ie. movements which have no explanation in terms of order)
are part of the simulation process
"""
def expand(self, applied_rule, **kw):
"""
Expands the additional Delivery movements to a new simulation tree.
Expand is only allowed to create or modify simulation movements for
delivery lines which are not already linked to another simulation
movement.
If the movement is not in current state, has no delivered child, and not
in delivery movements, it can be deleted.
Else if the movement is not in current state, it can be modified.
Else, it cannot be modified.
"""
def solve(self, applied_rule, solution_list):
"""
Solve inconsistency according to a certain number of solutions
templates. This updates the
-> new status -> solved
This applies a solution to an applied rule. Once
the solution is applied, the parent movement is checked.
If it does not diverge, the rule is reexpanded. If not,
diverge is called on the parent movement.
"""
def diverge(self, applied_rule):
"""
-> new status -> diverged
This basically sets the rule to "diverged"
and blocks expansion process
"""
def isStable(self, applied_rule):
"""
Checks that the applied_rule is stable
"""
def getSolverList(self, applied_rule):
"""
Returns a list Divergence solvers
"""
def isOrderable(self, movement):
def isDeliverable(self, movement):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/IndependentCapacity.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class IndependentCapacity(Capacity):
"""
Independent Capacity allows to select a set of resources
and attach a quantity to each resource
"""
def asCapacityItemList(self):
"""
Returns an association list of points and capacity values
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Document.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
def makeSortedTuple(kw):
class SnapshotMixin:
"""
This class provides a generic API to store in the ZODB
PDF snapshots of objects and documents with the
goal to keep a facsimile copy of documents as they
were at a given date.
"""
def createSnapshot(self):
"""
Create a snapshot (PDF). This is the normal way to modifiy
snapshot_data. Once a snapshot is taken, a new snapshot
can not be taken.
NOTE: use getSnapshotData and hasSnapshotData accessors
to access a snapshot.
NOTE2: implementation of createSnapshot should probably
be delegated to a types base method since this it
is configuration dependent.
"""
def deleteSnapshot(self):
"""
Deletes the snapshot - in theory this should never be done.
It is there for programmers and system administrators.
"""
class ConversionError(Exception):pass
class NotConvertedError(Exception):pass
class ConversionCacheMixin:
"""
This class provides a generic API to store in the ZODB
various converted versions of a file or of a string.
Versions are stored in dictionaries; the class stores also
generation time of every format and its mime-type string.
Format can be a string or a tuple (e.g. format, resolution).
TODO:
* Implement ZODB BLOB
"""
def clearConversionCache(self):
"""
Clear cache (invoked by interaction workflow upon file upload
needed here to overwrite class attribute with instance attrs
"""
def updateConversionCache(self):
def hasConversion(self, **format):
"""
Checks whether we have a version in this format
"""
def getCacheTime(self, **format):
"""
Checks when if ever was the file produced
"""
def updateConversion(self, **format):
def setConversion(self, data, mime=None, **format):
"""
Saves a version of the document in a given format; records mime type
and conversion time (which is right now).
"""
def getConversion(self, **format):
"""
Returns version of the document in a given format, if it has it; otherwise
returns empty string (the caller should check hasConversion before calling
this function.
(we could be much cooler here - pass testing and updating methods to this function
so that it does it all by itself; this'd eliminate the need for setConversion public method)
XXX-BG: I'm not sure now what I meant by this...
"""
def getConversionCacheInfo(self):
"""
Get cache details as string (for debugging)
"""
class Document(XMLObject, UrlMixIn, ConversionCacheMixin, SnapshotMixin):
"""
Document is an abstract class with all methods
related to document management in ERP5. This includes
searchable text, explicit relations, implicit relations,
metadata, versions, languages, etc.
Documents may either store their content directly or
cache content which is retrieved from a specified URL.
The second case if often referred as "External Document".
Standalone "External Documents" may be created by specifying
a URL to the contribution tool which is in charge of initiating
the download process and selecting the appropriate document type.
Groups of "External Documents" may also be generated from
so-called "External Source" (refer to ExternalSource class
for more information).
External Documents may be downloaded once or updated at
regular interval. The later can be useful to update the content
of an external source. Previous versions may be stored
in place or kept in a separate file. This feature
is known as the crawling API. It is mostly implemented
in ContributionTool with wrappers in the Document class.
It can be useful for create a small search engine.
There are currently two types of Document subclasses:
* File for binary file based documents. File
has subclasses such as Image, OOoDocument,
PDFDocument, etc. to implement specific conversion
methods.
* TextDocument for text based documents. TextDocument
has subclasses such as Wiki to implement specific
methods. TextDocument itself has a subclass
(XSLTDocument) which provides XSLT based analysis
and transformation of XML content based on XSLT
templates.
Document classes which implement conversion should use
the ConversionCacheMixin class so that converted values are
stored inside ZODB and do not need to be recalculated.
More generally, conversion should be achieved through
the convert method and other methods of the conversion
API (convertToBaseFormat, etc.). Moreover, any Document
subclass must ne able to convert documents to text
(asText method) and HTML (asHTML method). Text is required
for full text indexing. HTML is required for crawling.
Instances can be created directly, or via portal_contributions tool
which manages document ingestion process whereby a file can be uploaded
by http or sent in by email or dropped in by webdav or in some other
way as yet unknown. The ingestion process has the following steps:
(1) portal type detection
(2) object creation and upload of data
(3) metadata discovery (optionally with conversion of data to another format)
(4) other possible actions to finalise the ingestion (ex. by assigning
a reference)
This class handles (3) and calls a ZMI script to do (4).
Metadata can be drawn from various sources:
input - data supplied with http request or set on the object during (2) (e.g.
discovered from email text)
file_name - data which might be encoded in file name
user_login - information about user who is contributing the file
content - data which might be derived from document content
If a certain property is defined in more than one source, it is set according to
preference order returned by a script
Document_getPreferredDocumentMetadataDiscoveryOrderList
(or any type-based version since discovery is type dependent)
Methods for discovering metadata are:
getPropertyDictFromInput
getPropertyDictFromFileName
getPropertyDictFromUserLogin
getPropertyDictFromContent
Methods for processing content are implemented either in
Document class or in Base class:
getSearchableReferenceList (Base)
getSearchableText (Base)
index_html (overriden in Document subclasses)
Methods for handling relations are implemented either in
Document class or in Base class:
getImplicitSuccessorValueList (Base)
getImplicitPredecessorValueList (Base)
getImplicitSimilarValueList (Base)
getSimilarCloudValueList (Document)
Implicit relations consist in finding document references inside
searchable text (ex. INV-23456) and deducting relations from that.
Two customisable methods required. One to find a list of implicit references
inside the content (getSearchableReferenceList) and one to convert a given
document reference into a list of reference strings which could
be present in other content (asSearchableReferenceList).
document.getSearchableReferenceList() returns
[
{'reference':' INV-12367'},
{'reference': 'INV-1112', 'version':'012}',
{'reference': 'AB-CC-DRK', 'version':'011', 'language': 'en'}
]
The Document class behaviour can be extended / customized through scripts
(which are type-based so can be adjusted per portal type).
* Document_getPropertyDictFromUserLogin - finds a user (by user_login or from session)
and returns properties which should be set on the document
* Document_getPropertyDictFromContent - analyzes document content and returns
properties which should be set on the document
* Base_getImplicitSuccessorValueList - finds appropriate all documents
referenced in the current content
* Base_getImplicitPredecessorValueList - finds document predecessors based on
the document coordinates (can use only complete coordinates, or also partial)
* Document_getPreferredDocumentMetadataDiscoveryOrderList - returns an order
in which metadata should be set/overwritten
* Document_finishIngestion - called by portal_activities after all the ingestion
is completed (and after document has been converted, so text_content
is available if the document has it)
* Document_getNewRevision - calculates revision number which should be set
on this document. Implementation depends on revision numbering policy which
can be very different. Interaction workflow should call setNewRevision method.
* Document_populateContent - analyses the document content and produces
subcontent based on it (ex. images, news, etc.). This scripts can
involve for example an XSLT transformation to process XML.
Subcontent: documents may include subcontent (files, images, etc.)
so that publication of rich content can be path independent. Subcontent
can also be used to help the rendering in HTML of complex documents
such as ODF documents.
Consistency checking:
Default implementation uses DocumentReferenceConstraint to check if the
reference/language/version triplet is unique. Additional constraints
can be added if necessary.
NOTE: Document.py supports a notion of revision which is very specific.
The underlying concept is that, as soon as a document has a reference,
the association of (reference, version, language) must be unique
accross the whole system. This means that a given document in a given
version in a given language is unique. The underlying idea is similar
to the one in a Wiki system in which each page is unique and acts
the the atom of collaboration. In the case of ERP5, if a team collaborates
on a Text document written with an offline word processor, all
updates should be placed inside the same object. A Contribution
will thus modify an existing document, if allowed from security
point of view, and increase the revision number. Same goes for
properties (title). Each change generates a new revision.
"""
def index_html(self, REQUEST, RESPONSE, format=None, **kw):
"""
We follow here the standard Zope API for files and images
and extend it to support format conversion. The idea
is that an image which ID is "something.jpg" should
ne directly accessible through the URL
/a/b/something.jpg. The same is true for a file and
for any document type which primary purpose is to
be used by a helper application rather than displayed
as HTML in a web browser. Exceptions to this approach
include Web Pages which are intended to be primarily rendered
withing the layout of a Web Site or withing a standard ERP5 page.
Please refer to the index_html of TextDocument.
Should return appropriate format (calling convert
if necessary) and set headers.
format -- the format specied in the form of an extension
string (ex. jpeg, html, text, txt, etc.)
**kw -- can be various things - e.g. resolution
TODO:
- implement guards API so that conversion to certain
formats require certain permission
"""
def getSearchableText(self, md=None):
"""
Used by the catalog for basic full text indexing.
Uses searchable_property_list attribute to put together various properties
of the document into one searchable text string.
XXX-JPS - This method is nice. It should probably be moved to Base class
searchable_property_list could become a standard class attribute.
TODO (future): Make this property a per portal type property.
"""
def getPropertyListOrValue(property):
"""
we try to get a list, else we get value and convert to list
"""
def isExternalDocument(self):
"""
Return true if this document was obtained from an external source
"""
def getSearchableReferenceList(self):
"""
This method returns a list of dictionaries which can
be used to find objects by reference. It uses for
that a regular expression defined at system level
preferences.
"""
def getImplicitSuccessorValueList(self):
"""
Find objects which we are referencing (if our text_content contains
references of other documents). The whole implementation is delegated to
Base_getImplicitSuccessorValueList script.
The implementation goes in 2 steps:
- Step 1: extract with a regular expression
a list of distionaries with various parameters such as
reference, portal_type, language, version, user, etc. This
part is configured through a portal preference.
- Step 2: read the list of dictionaries
and build a list of values by calling portal_catalog
with appropriate parameters (and if possible build
a complex query whenever this becomes available in
portal catalog)
The script is reponsible for calling getSearchableReferenceList
so that it can use another approach if needed.
NOTE: passing a group_by parameter may be useful at a
later stage of the implementation.
"""
def getImplicitPredecessorValueList(self):
"""
This function tries to find document which are referencing us - by reference only, or
by reference/language etc. Implementation is passed to
Base_getImplicitPredecessorValueList
The script should proceed in two steps:
Step 1: build a list of references out of the context
(ex. INV-123456, 123456, etc.)
Step 2: search using the portal_catalog and use
priorities (ex. INV-123456 before 123456)
( if possible build a complex query whenever
this becomes available in portal catalog )
NOTE: passing a group_by parameter may be useful at a
later stage of the implementation.
"""
def getImplicitSimilarValueList(self):
"""
Analyses content of documents to find out by the content which documents
are similar. Not implemented yet.
No cloud needed because transitive process
"""
def getSimilarCloudValueList(self, depth=0):
"""
Returns all documents which are similar to us, directly or indirectly, and
in both directions. In other words, it is a transitive closure of similar
relation. Every document is returned in the latest version available.
"""
def getRelatedList(ob, level=0):
def getLatestVersionValue(self, language=None):
"""
Tries to find the latest version with the latest revision
of self which the current user is allowed to access.
If language is provided, return the latest document
in the language.
If language is not provided, return the latest version
in original language or in the user language if the version is
the same.
"""
def getVersionValueList(self, version=None, language=None):
"""
Returns a list of documents with same reference, same portal_type
but different version and given language or any language if not given.
"""
def isVersionUnique(self):
"""
Returns true if no other document exists with the same
reference, version and language, or if the current
document has no reference.
"""
def setUniqueReference(self, suffix='auto'):
"""
Create a unique reference for the current document
based on a suffix
"""
def getRevision(self):
"""
Returns the current revision by analysing the change log
of the current object. The return value is a string
in order to be consistent with the property sheet
definition.
NOTE: for now, workflow choice is hardcoded. This is
an optimisation hack. If a document does neither use
edit_workflow or processing_status_workflow, the
first workflow in the chain has prioriot. Better
implementation would require to be able to define
which workflow in a chain is the default one for
revision tracking (and for modification date).
"""
def getRevisionList(self):
"""
Returns the list of revision numbers of the current document
by by analysing the change log of the current object.
"""
def mergeRevision(self):
"""
Merge the current document with any previous revision
or change its version to make sure it is still unique.
NOTE: revision support is implemented in the Document
class rather than within the ContributionTool
because the ingestion process requires to analyse the content
of the document first. Hence, it is not possible to
do any kind of update operation until the whole ingestion
process is completed, since update requires to know
reference, version, language, etc. In addition,
we have chosen to try to merge revisions after each
metadata discovery as a way to make sure that any
content added in the system through the ContributionTool
(ex. through webdav) will be merged if necessary.
It may be posssible though to split disoverMetadata and
finishIngestion.
"""
def getLanguageList(self, version=None):
"""
Returns a list of languages which this document is available in
for the current user.
"""
def getOriginalLanguage(self):
"""
Returns the original language of this document.
XXX-JPS not implemented yet ?
"""
def getPropertyDictFromUserLogin(self, user_login=None):
"""
Based on the user_login, find out as many properties as needed.
returns properties which should be set on the document
"""
def getPropertyDictFromContent(self):
"""
Based on the document content, find out as many properties as needed.
returns properties which should be set on the document
"""
def getPropertyDictFromFileName(self, file_name):
"""
Based on the file name, find out as many properties as needed.
returns properties which should be set on the document
"""
def getPropertyDictFromInput(self):
"""
Get properties which were supplied explicitly to the ingestion method
(discovered or supplied before the document was created).
The implementation consists in saving document properties
into _backup_input by supposing that original input parameters were
set on the document by ContributionTool.newContent as soon
as the document was created.
"""
def getStandardFileName(self):
"""
Returns the document coordinates as a standard file name. This
method is the reverse of getPropertyDictFromFileName.
"""
def discoverMetadata(self, file_name=None, user_login=None):
"""
This is the main metadata discovery function - controls the process
of discovering data from various sources. The discovery itself is
delegated to scripts or uses preference-configurable regexps. The
method returns either self or the document which has been
merged in the discovery process.
file_name - this parameter is a file name of the form "AA-BBB-CCC-223-en"
user_login - this is a login string of a person; can be None if the user is
currently logged in, then we'll get him from session
"""
def finishIngestion(self):
"""
Finish the ingestion process by calling the appropriate script. This
script can for example allocate a reference number automatically if
no reference was defined.
"""
def convert(self, format, **kw):
"""
Main content conversion function, returns result which should
be returned and stored in cache.
format - the format specied in the form of an extension
string (ex. jpeg, html, text, txt, etc.)
**kw can be various things - e.g. resolution
Default implementation returns an empty string (html, text)
or raises an error.
TODO:
- implement guards API so that conversion to certain
formats require certain permission
"""
def asText(self):
"""
Converts the content of the document to a textual representation.
"""
def asEntireHTML(self):
"""
Returns a complete HTML representation of the document
(with body tags, etc.). Adds if necessary a base
tag so that the document can be displayed in an iframe
or standalone.
Actual conversion is delegated to _asHTML
"""
def _asHTML(self):
"""
A private method which converts to HTML. This method
is the one to override in subclasses.
"""
def asStrippedHTML(self):
"""
Returns a stripped HTML representation of the document
(without html and body tags, etc.) which can be used to inline
a preview of the document.
"""
def getContentInformation(self):
"""
Returns the content information from the HTML conversion.
The default implementation tries to build a dictionnary
from the HTML conversion of the document and extract
the document title.
"""
def convertToBaseFormat(self):
"""
Converts the content of the document to a base format
which is later used for all conversions. This method
is common to all kinds of documents and handles
exceptions in a unified way.
Implementation is delegated to _convertToBaseFormat which
must be overloaded by subclasses of Document which
need a base format.
convertToBaseFormat is called upon file upload, document
ingestion by the processing_status_workflow.
NOTE: the data of the base format conversion should be stored
using the base_data property. Refer to Document.py propertysheet.
Use accessors (getBaseData, setBaseData, hasBaseData, etc.)
"""
def _convertToBaseFormat(self):
"""
Placeholder method. Must be subclassed by classes
which need a base format. Refer to OOoDocument
for an example of ODF base format which is used
as a way to convert about any file format into
about any file format.
Other possible applications: conversion of HTML
text to tiddy HTML such as described here:
http://www.xml.com/pub/a/2004/09/08/pyxml.html
so that resulting text can be processed more
easily by XSLT parsers. Conversion of internal
links to images of an HTML document to local
links (in combindation with populate).
"""
def isSupportBaseDataConversion(self):
"""
This is a public interface to check a document that is support conversion
to base format and can be overridden in subclasses.
"""
def convertFile(self, **kw):
"""
Workflow transition invoked when conversion occurs.
"""
def updateBaseMetadata(self, **kw):
"""
Update the base format data with the latest properties entered
by the user. For example, if title is changed in ERP5 interface,
the base format file should be updated accordingly.
Default implementation does nothing. Refer to OOoDocument class
for an example of implementation.
"""
def populateContent(self):
"""
Populates the Document with subcontent based on the
document base data.
This can be used for example to transform the XML
of an RSS feed into a single piece per news or
to transform an XML export from a database into
individual records. Other application: populate
an HTML text document with its images, used in
conversion with convertToBaseFormat.
"""
def getContentURLList(self):
"""
Returns a list of URLs referenced by the content of this document.
Default implementation consists in analysing the document
converted to HTML. Subclasses may overload this method
if necessary. However, it is better to extend the conversion
methods in order to produce valid HTML, which is useful to
many people, rather than overload this method which is only
useful for crawling.
"""
def updateContentFromURL(self, repeat=MAX_REPEAT, crawling_depth=0):
"""
Download and update content of this document from its source URL.
Implementation is handled by ContributionTool.
"""
def crawlContent(self):
"""
Initialises the crawling process on the current document.
"""
def isIndexContent(self, container=None):
"""
Ask container if we are and index, or a content.
In the vast majority of cases we are content.
This method is required in a crawling process to make
a difference between URLs which return an index (ex. the
list of files in remote server which is accessed through HTTP)
and the files themselves.
"""
def getContentBaseURL(self):
"""
Returns the content base URL based on the actual content or
on its URL.
"""
def getFrequencyIndex(self):
"""
Returns the document update frequency as an integer
which is used by alamrs to decide which documents
must be updates at which time. The index represents
a time slot (ex. all days in a month, all hours in a week).
"""
def getCreationDateIndex(self, at_date = None):
"""
Returns the document Creation Date Index which is the creation
date converted into hours modulo the Frequency Index.
"""
def isUpdatable(self):
"""
This method is used to decide which document can be updated
in the crawling process. This can depend for example on
workflow states (publication state,
validation state) or on roles on the document.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaySheetCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaySheetCell(InvoiceCell):
"""
A PaySheetCell allows to define specific quantities
for each variation of a resource in a pay sheet line.
"""
def getNetConvertedQuantity(self):
"""
We do not need conversion here
"""
def isAccountable(self):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Container.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Container(Movement, XMLObject):
"""
Container is equivalent to a movement with qty 1.0 and resource =
to the kind of packaging Container may point to item (ex.
Container serial No or Parcel Serial No if tracing required)
Container may eventually usa optional property sheet to store
parcel No information (we use Item property sheet for that). Some
acquisition may be required...
A Container which does not point to an Item can act itself as an Item
for traceability.
Container Line / Container Cell is used to store quantities (never
accounted)
Container Line / Countainer Cell may point to Item
"""
def getQuantity(self):
"""
Returns 1 because only one container is shipped
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
def hasCellContent(self, base_id='movement'):
"""
This method can be overriden
"""
def isDivergent(self):
"""
Returns 1 if the target is not met according to the current information
After and edit, the isOutOfTarget will be checked. If it is 1,
a message is emitted
emit targetUnreachable !
"""
def getContainerText(self):
"""
Creates a unique string which allows to compare/hash two containers
"""
def getContainerUid(self):
def getContainerValue(self):
def getContainer(self):
def getContainedTotalQuantity(self, recursive = 0):
"""
The sum of quantities of contained lines
"""
def getContainedTotalPrice(self, recursive = 0):
"""
The sum of price of contained lines
"""
def getTrackedItemUidList(self):
"""
Return a list of uid for related items.
If this container is related to no item, it is treated as an Item
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/SupplyRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SupplyRule(MappedValue, XMLMatrix):
"""
Supply rule contains mapped values (if required) for each possible
variation of a resource. Structure should be similar to
transformed resource (domain / category membership)
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Resource.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Resource(XMLMatrix, Variated):
"""
A Resource
"""
def getVariationRangeCategoryItemList(self, base_category_list=(), base=1,
"""
Returns possible variations
resource.getVariationRangeCategoryItemList
=> [(display, value)]
## Variation API (exemple) ##
Base categories defined:
- colour
- morphology
- size
Categories defined:
- colour/blue
- colour/red
- size/Man
- size/Woman
Resource 'resource' created with variation_base_category_list:
(colour, morphology, size)
resource.getVariationRangeCategoryList
variation | individual variation | result
____________________________________________________________________________________
| | (colour/blue, colour/red, size/Man, size/Woman)
size/Man | | (colour/blue, colour/red, size/Man, size/Woman)
colour/blue | | (colour/blue, colour/red, size/Man, size/Woman)
| colour/1 | (colour/1, size/Man, size/Woman)
| morphology/2 | (colour/blue, colour/red, size/Man, size/Woman, morphology/2)
"""
def getVariationCategoryItemList(self, base_category_list=(),
"""
Returns variations of the resource.
If omit_individual_variation==1, does not return individual
variation.
Else, returns them.
Display is on left.
=> [(display, value)]
*old parameters: base=1, current_category=None,
display_id='getTitle' (default value getTitleOrId)
"""
def getVariationCategoryList(self, default=[], base_category_list=(),
"""
Returns variations of the resource.
If omit_individual_variation==1, does not return individual
variation.
Else, returns them.
## Variation API (exemple) ##
Base categories defined:
- colour
- morphology
- size
Categories defined:
- colour/blue
- colour/red
- size/Man
- size/Woman
Resource 'resource' created with variation_base_category_list:
(colour, morphology, size)
resource.getVariationCategoryList
variation | individual variation | result
_____________________________________________________
| | ()
size/Man | | (size/Man, )
colour/blue | | (colour/blue, )
| colour/1 | (colour/1, )
| morphology/2 | (morphology/2, )
"""
def convertQuantity(self, quantity, from_unit, to_unit):
def getDefaultDestinationAmountBis(self, unit=None, variation=None, REQUEST=None):
def getDefaultSourceAmountBis(self, unit=None, variation=None, REQUEST=None):
def getDefaultResourceValue(self):
def getInventory(self, **kw):
"""
Returns inventory
"""
def getCurrentInventory(self, **kw):
"""
Returns current inventory
"""
def getAvailableInventory(self, **kw):
"""
Returns available inventory
(current inventory - deliverable)
"""
def getFutureInventory(self, **kw):
"""
Returns inventory at infinite
"""
def getInventoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getCurrentInventoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getAvailableInventoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getFutureInventoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getInventoryStat(self, **kw):
"""
Returns statistics of inventory grouped by section or site
"""
def getCurrentInventoryStat(self, **kw):
"""
Returns statistics of inventory grouped by section or site
"""
def getAvailableInventoryStat(self, **kw):
"""
Returns statistics of inventory grouped by section or site
"""
def getFutureInventoryStat(self, **kw):
"""
Returns statistics of inventory grouped by section or site
"""
def getInventoryChart(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getCurrentInventoryChart(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getFutureInventoryChart(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getInventoryHistoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getInventoryHistoryChart(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getMovementHistoryList(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getMovementHistoryStat(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getNextNegativeInventoryDate(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getInventoryAssetPrice(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getCurrentInventoryAssetPrice(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getAvailableInventoryAssetPrice(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getFutureInventoryAssetPrice(self, **kw):
"""
Returns list of inventory grouped by section or site
"""
def getIndustrialPrice(self, context=None, REQUEST=None, **kw):
"""
Returns industrial price
"""
def _getIndustrialPrice(self, context):
def asPredicate(self):
"""
Returns a temporary Predicate based on the Resource properties
"""
def _pricingSortMethod(self, a, b):
def getPriceParameterDict(self, context=None, REQUEST=None, **kw):
"""
Get all pricing parameters from Predicate.
"""
def getPricingVariable(self, context=None):
"""
Return the value of the property used to calculate variable pricing
This basically calls a script like Product_getPricingVariable
"""
def getPriceCalculationOperandDict(self, default=None, context=None,
"""Return a dictionary which contains operands for price calculation.
Consult the doc string in Movement.getPriceCalculationOperandDict
for more details.
"""
def getPrice(self, default=None, context=None, REQUEST=None, **kw):
"""
Return the unit price of a resource in a specific context.
"""
def getQuantityPrecision(self):
"""Return the floating point precision of a quantity.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/BusinessTemplate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
def _getCatalog(acquisition_context):
"""
Return the id of the SQLCatalog which correspond to the current BT.
"""
def _getCatalogValue(acquisition_context):
"""
Returns the catalog object which correspond to the ZSQLMethods
stored/to store in the business template.
NB: acquisition_context must make possible to reach portal object
and getTemplateCatalogMethodIdList.
"""
def _recursiveRemoveUid(obj):
"""Recusivly set uid to None, to prevent (un)indexing.
This is used to prevent unindexing real objects when we delete subobjects on
a copy of this object.
"""
def removeAll(entry):
def getChainByType(context):
"""
This is used in order to construct the full list
of mapping between type and list of workflow associated
This is only useful in order to use
portal_workflow.manage_changeWorkflows
"""
def fixZSQLMethod(portal, method):
"""Make sure the ZSQLMethod uses a valid connection.
"""
class BusinessTemplateArchive:
"""
This is the base class for all Business Template archives
"""
def __init__(self, creation=0, importing=0, file=None, path=None, **kw):
def addFolder(self, **kw):
def addObject(self, *kw):
def finishCreation(self, **kw):
class BusinessTemplateFolder(BusinessTemplateArchive):
"""
Class archiving business template into a folder tree
"""
def _initCreation(self, path):
def addFolder(self, name=''):
def addObject(self, obj, name, path=None, ext='.xml'):
def _initImport(self, file=None, path=None, **kw):
def importFiles(self, item, **kw):
"""
Import file from a local folder
"""
class BusinessTemplateTarball(BusinessTemplateArchive):
"""
Class archiving businnes template into a tarball file
"""
def _initCreation(self, path):
def addFolder(self, name=''):
def addObject(self, obj, name, path=None, ext='.xml'):
def finishCreation(self):
def _initImport(self, file=None, **kw):
def importFiles(self, item, **kw):
"""
Import all file from the archive to the site
"""
class TemplateConditionError(Exception): pass
class TemplateConflictError(Exception): pass
class BusinessTemplateMissingDependency(Exception): pass
class BaseTemplateItem(Implicit, Persistent):
"""
This class is the base class for all template items.
"""
def __init__(self, id_list, **kw):
def build(self, context, **kw):
def preinstall(self, context, installed_bt, **kw):
"""
Build a list of added/removed/changed files between the BusinessTemplate
being installed (self) and the installed one (installed_bt).
Note : we compare files between BTs, *not* between the installed BT and
the objects in the DataFS.
XXX: -12 used here is -len('TemplateItem')
"""
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def remove(self, context, **kw):
"""
If 'remove' is chosen on an object containing subobjects, all the
subobjects will be removed too, even if 'backup' or 'keep' was chosen for
the subobjects.
Likewise, for 'save_and_remove' : subobjects will get saved too.
"""
def trash(self, context, new_item, **kw):
def export(self, context, bta, **kw):
def getKeys(self):
def importFile(self, bta, **kw):
def removeProperties(self, obj):
"""
Remove unneeded properties for export
"""
class ObjectTemplateItem(BaseTemplateItem):
"""
This class is used for generic objects and as a subclass.
"""
def __init__(self, id_list, tool_id=None, **kw):
def export(self, context, bta, **kw):
"""
Export the business template : fill the BusinessTemplateArchive with
objects exported as XML, hierarchicaly organised.
"""
def build_sub_objects(self, context, id_list, url, **kw):
def build(self, context, **kw):
def _compileXML(self, file):
def _importFile(self, file_name, file_obj):
def preinstall(self, context, installed_bt, **kw):
def _backupObject(self, action, trashbin, container_path, object_id, **kw):
"""
Backup the object in portal trash if necessery and return its subobjects
"""
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
class PathTemplateItem(ObjectTemplateItem):
"""
This class is used to store objects with wildcards supported.
"""
def __init__(self, id_list, tool_id=None, **kw):
def uninstall(self, context, **kw):
def _resolvePath(self, folder, relative_url_list, id_list):
"""
This method calls itself recursively.
The folder is the current object which contains sub-objects.
The list of ids are path components. If the list is empty,
the current folder is valid.
"""
def build(self, context, **kw):
class ToolTemplateItem(PathTemplateItem):
"""This class is used only for making a distinction between other objects
and tools, because tools may not be backed up."""
def _backupObject(self, action, trashbin, container_path, object_id, **kw):
"""Fake as if a trashbin is not available."""
class PreferenceTemplateItem(PathTemplateItem):
"""
This class is used to store preference objects
"""
def _resolvePath(self, folder, relative_url_list, id_list):
"""
This method calls itself recursively.
The folder is the current object which contains sub-objects.
The list of ids are path components. If the list is empty,
the current folder is valid.
"""
def install(self, context, trashbin, **kw):
"""
Enable Preference
"""
class CategoryTemplateItem(ObjectTemplateItem):
def __init__(self, id_list, tool_id='portal_categories', **kw):
def build_sub_objects(self, context, id_list, url, **kw):
def build(self, context, **kw):
def install(self, context, trashbin, **kw):
class SkinTemplateItem(ObjectTemplateItem):
def __init__(self, id_list, tool_id='portal_skins', **kw):
def preinstall(self, context, installed_bt, **kw):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
class WorkflowTemplateItem(ObjectTemplateItem):
def __init__(self, id_list, tool_id='portal_workflow', **kw):
def preinstall(self, context, installed_bt, **kw):
def install(self, context, trashbin, **kw):
class PortalTypeTemplateItem(ObjectTemplateItem):
def __init__(self, id_list, tool_id='portal_types', **kw):
def build(self, context, **kw):
def install(self, context, trashbin, **kw):
def _importFile(self, file_name, file):
class PortalTypeWorkflowChainTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def preinstall(self, context, installed_bt, **kw):
def _importFile(self, file_name, file):
class PortalTypeAllowedContentTypeTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
def preinstall(self, context, installed_bt, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
class PortalTypeHiddenContentTypeTemplateItem(PortalTypeAllowedContentTypeTemplateItem):
class PortalTypePropertySheetTemplateItem(PortalTypeAllowedContentTypeTemplateItem):
class PortalTypeBaseCategoryTemplateItem(PortalTypeAllowedContentTypeTemplateItem):
class CatalogMethodTemplateItem(ObjectTemplateItem):
"""Template Item for catalog methods.
This template item stores catalog method and install them in the
default catalog.
The use Catalog makes for methods is saved as well and recreated on
installation.
"""
def __init__(self, id_list, tool_id='portal_catalog', **kw):
def _extractMethodProperties(self, catalog, method_id):
"""Extracts properties for a given method in the catalog.
Returns a mapping of property name -> boolean """
def build(self, context, **kw):
def export(self, context, bta, **kw):
def generateXml(self, path=None):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def _importFile(self, file_name, file):
class ActionTemplateItem(ObjectTemplateItem):
def __init__(self, id_list, **kw):
def _splitPath(self, path):
"""
Split path tries to split a complexe path such as:
"foo/bar[id=zoo]"
into
"foo/bar", "id", "zoo"
This is used mostly for generic objects
"""
def build(self, context, **kw):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
class PortalTypeRolesTemplateItem(BaseTemplateItem):
def __init__(self, id_list, **kw):
def build(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
class SitePropertyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class ModuleTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
def install(self, context, trashbin, **kw):
def _importFile(self, file_name, file):
def uninstall(self, context, **kw):
def trash(self, context, new_item, **kw):
class DocumentTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def preinstall(self, context, installed_bt, **kw):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def export(self, context, bta, **kw):
def _importFile(self, file_name, file):
class PropertySheetTemplateItem(DocumentTemplateItem):
class ConstraintTemplateItem(DocumentTemplateItem):
class ExtensionTemplateItem(DocumentTemplateItem):
class TestTemplateItem(DocumentTemplateItem):
class ProductTemplateItem(BaseTemplateItem):
class RoleTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def preinstall(self, context, installed_bt, **kw):
def install(self, context, trashbin, **kw):
def _importFile(self, file_name, file):
def uninstall(self, context, **kw):
def trash(self, context, new_item, **kw):
def generateXml(self, path):
def export(self, context, bta, **kw):
class CatalogResultKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogRelatedKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogResultTableTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogKeywordKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogDateTimeKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogFullTextKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogRequestKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogMultivalueKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogTopicKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class CatalogScriptableKeyTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
class MessageTranslationTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
def preinstall(self, context, installed_bt, **kw):
def install(self, context, trashbin, **kw):
def export(self, context, bta, **kw):
def _importFile(self, file_name, file):
class LocalRolesTemplateItem(BaseTemplateItem):
def __init__(self, id_list, **kw):
def build(self, context, **kw):
def generateXml(self, path=None):
def export(self, context, bta, **kw):
def _importFile(self, file_name, file):
def install(self, context, trashbin, **kw):
def uninstall(self, context, **kw):
class BusinessTemplate(XMLObject):
"""
A business template allows to construct ERP5 modules
in part or completely. Each object is separated from its
subobjects and exported in xml format.
It may include:
- catalog definition
- SQL method objects
- SQL methods including:
- purpose (catalog, uncatalog, etc.)
- filter definition
- portal_types definition
- object without optimal actions
- list of relation between portal type and workflow
- module definition
- id
- title
- portal type
- roles/security
- site property definition
- id
- type
- value
- document/propertysheet/extension/test definition
- copy of the local file
- message transalation definition
- .po file
The Business Template properties are exported to the bt folder with
one property per file
Technology:
- download a gzip file or folder tree (from the web, from a CVS repository,
from local file system) (import/donwload)
- install files to the right location (install)
Use case:
- install core ERP5 (the minimum)
- go to "BT" menu. Import BT. Select imported BT. Click install.
- go to "BT" menu. Create new BT.
Define BT elements (workflow, methods, attributes, etc.).
Build BT and export or save it
Done.
"""
, 'description' : """\
Business Template is a set of definitions, such as skins, portal types and categories. This is used to set up a new ERP5 site very efficiently."""
def __init__(self, *args, **kw):
def getTemplateFormatVersion(self, **kw):
"""This is a workaround, because template_format_version was not set even for the new format.
"""
def manage_afterAdd(self, item, container):
"""
This is called when a new business template is added or imported.
"""
def getRevision(self):
"""returns the revision property.
This is a workaround for #461.
"""
def updateRevisionNumber(self):
"""Increment bt revision number.
"""
def build(self, no_action=0):
"""
Copy existing portal objects to self
"""
def publish(self, url, username=None, password=None):
"""
Publish in a format or another
"""
def update(self):
"""
Update template: download new template definition
"""
def isCatalogUpdatable(self):
"""
Return if catalog will be updated or not by business template installation
"""
def preinstall(self, check_dependencies=1, **kw):
"""
Return the list of modified/new/removed object between a Business Template
and the one installed if exists
"""
def _install(self, force=1, object_to_update=None, **kw):
"""
Install a new Business Template, if force, all will be upgraded or installed
otherwise depends of dict object_to_update
"""
def install(self, **kw):
"""
For install based on paramaters provided in **kw
"""
def reinstall(self, **kw):
"""Reinstall Business Template.
"""
def trash(self, new_bt, **kw):
"""
Trash unnecessary items before upgrading to a new business
template.
This is similar to uninstall, but different in that this does
not remove all items.
"""
def uninstall(self, **kw):
"""
For uninstall based on paramaters provided in **kw
"""
def _clean(self):
"""
Clean built information.
"""
def getBuildingState(self, default=None, id_only=1):
"""
Returns the current state in building
"""
def getInstallationState(self, default=None, id_only=1):
"""
Returns the current state in installation
"""
def toxml(self):
"""
Return this Business Template in XML
"""
def _getOrderedList(self, id):
"""
We have to set this method because we want an
ordered list
"""
def getTemplateCatalogMethodIdList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplateBaseCategoryList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplateWorkflowIdList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePortalTypeIdList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePortalTypeWorkflowChainList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePathList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePreferenceList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePortalTypeAllowedContentTypeList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePortalTypeHiddenContentTypeList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePortalTypePropertySheetList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePortalTypeBaseCategoryList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplateActionPathList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplatePortalTypeRolesList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplateSkinIdList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplateModuleIdList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplateMessageTranslationList(self):
"""
We have to set this method because we want an
ordered list
"""
def getTemplateToolIdList(self):
"""
We have to set this method because we want an
ordered list
"""
def export(self, path=None, local=0, **kw):
"""
Export this Business Template
"""
def importFile(self, dir = 0, file=None, root_path=None):
"""
Import all xml files in Business Template
"""
def getItemsList(self):
"""Return list of items in business template
"""
def checkDependencies(self):
"""
Check if all the dependencies of the business template
are installed. Raise an exception with the list of
missing dependencies if some are missing
"""
def diffObject(self, REQUEST, **kw):
"""
Make a diff between an object in the Business Template
and the same in the Business Template installed in the site
"""
def getPortalTypesProperties(self, **kw):
"""
Fill field about properties for each portal type
"""
def guessPortalTypes(self, **kw):
"""
This method guesses portal types based on modules define in the Business Template
"""
def getChildPortalType(type_id):
def clearPortalTypes(self, **kw):
"""
clear id list register for portal types
"""
# def __init__(self, ):
# def register(self, update=0, gen=None, site=None):
# def tpc_prepare(self, *d, **kw):
# def _finish(self, **kw):
# def _abort(self, **kw):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Discount.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Discount(XMLObject):
"""
Discounts are used in orders, trade condition,...
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/DeliveryBuilder.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SelectMethodError(Exception): pass
class SelectMovementError(Exception): pass
class DeliveryBuilder(OrderBuilder):
"""
Delivery Builder objects allow to gather multiple Simulation Movements
into a single Delivery.
The initial quantity property of the Delivery Line is calculated by
summing quantities of related Simulation Movements.
Delivery Builders are called for example whenever an order is confirmed.
They are also called globaly in order to gather any confirmed or above
Simulation Movement which was not associated to any Delivery Line.
Such movements are called orphaned Simulation Movements.
Delivery Builder objects are provided with a set a parameters to achieve
their goal:
A path definition: source, destination, etc. which defines the general
kind of movements it applies.
simulation_select_method which defines how to query all Simulation
Movements which meet certain criteria (including the above path path
definition).
collect_order_list which defines how to group selected movements
according to gathering rules.
delivery_select_method which defines how to select existing Delivery
which may eventually be updated with selected simulation movements.
delivery_module, delivery_type and delivery_line_type which define the
module and portal types for newly built Deliveries and Delivery Lines.
Delivery Builders can also be provided with optional parameters to
restrict selection to a given root Applied Rule caused by a single Order
or to Simulation Movements related to a limited set of existing
Deliveries.
"""
def callBeforeBuildingScript(self):
"""
Redefine this method, because it seems nothing interesting can be
done before building Delivery.
"""
def searchMovementList(self, applied_rule_uid=None,**kw):
"""
defines how to query all Simulation Movements which meet certain criteria
(including the above path path definition).
First, select movement matching to criteria define on DeliveryBuilder
Then, call script simulation_select_method to restrict movement_list
"""
def _setDeliveryMovementProperties(self, delivery_movement,
"""
Initialize or update delivery movement properties.
Set delivery ratio on simulation movement.
Create the relation between simulation movement
and delivery movement.
"""
def updateFromSimulation(self, delivery_relative_url, create_new_delivery=1):
"""
Update all lines of this transaction based on movements in the
simulation related to this transaction.
"""
def _deliveryUpdateGroupProcessing(self, delivery, movement_group):
"""
Update delivery movement
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AssortedResource.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AssortedResource(TransformedResource):
"""
This code was copied from TransformedResource very stupidly.
Therefore it is necessaery to review all the code. -yo
AssortedResource defines which
resource is being assorted
- variation
- quantity
Maybe defined by mapped values inside the transformed resource
WARNING: the notion of category range is quite complex in this case.
getVariationRangeCategoryList -> possible variations of the transformed
resource ie. getVariationCategoryList
of the resource
getVariationCategoryList -> variation value of the transformed
resource (ie. default variation)
getVariationRangeBaseCategoryList -> possible variation base categories
of the transformed resource
(ie. getVariationBaseCategoryList
of the resource)
getVariationBaseCategoryList -> choice of variation base categories
defined by the transformed resource
(should be the same as getVariationRangeBaseCategoryList)
getTransformationVariationRangeBaseCategoryList OK
-> possible variation base categories
which can be used the the
transformation matrix
(based on resource)
getTransformationVariationBaseCategoryList OK
-> choice of variation base categories
which can be used the the
transformation matrix
(based on resource)
getTransformationVariationRangeCategoryList OK
-> possible category values
which can be used in the
transformation matrix
(based on resource)
getTransformationVariationCategoryList OK
-> choice of category values
which can be used in the
transformation matrix
XXX WE HAVE an issue here:
- the variation range of the transformation
defines both the variation range of the main resource
and the variation range for matrices
- where do we define default variation value
for the resource produced by the transformation ?
(probably in the domain fields)
- where do we define selection parameters ?
getResourceVariationCategoryList
getResourceVariationRangeCategoryList
setValueUids could be overriden to provide quick and dirty
behaviour of range update
"""
def getAssortedVariationCategoryList(self, cell_index):
"""
Nice for A
"""
def getAssortedVariationBaseCategoryList(self):
"""
Nice for A
"""
def getAssortmentVariationCategoryList(self, cell_index):
"""
Nice for C
"""
def getAssortmentVariationBaseCategoryList(self):
"""
Nice for C
"""
def _getSortedBaseCategoryList(self, base_category_list):
def _updateCellRange(self, base=1, current_category=None):
def _setQVariationBaseCategoryList(self, value):
"""
Defines the possible base categories which Quantity value (Q)
variate on
"""
def setQVariationBaseCategoryList(self, value):
"""
Defines the possible base categories which Quantity value (Q)
variate on and reindex the object
"""
def _setVVariationBaseCategoryList(self, value):
"""
Defines the possible base categories which Variation value (V)
variate on
"""
def setVVariationBaseCategoryList(self, value):
"""
Defines the possible base categories which Variation value (V)
variate on and reindex the object
"""
def getQLineItemList(self, display_id='getTitle', base=1, current_category=None):
"""
"""
def getQColumnItemList(self, display_id='getTitle', base=1, current_category=None):
"""
"""
def getQTabItemList(self, display_id='getTitle', base=1, current_category=None):
"""
Returns a list of items which can be used as index for
each tab of a matrix or to define a cell range.
"""
def getVLineItemList(self):
def getVColumnItemList(self):
def getVTabItemList(self):
def newCell(self, *kw, **kwd):
def newCellContent(self, id,**kw):
"""
This method can be overriden
"""
def _checkConsistency(self, fixit=0):
"""
Check the constitency of transformation elements
"""
def getAggregatedAmountList(self, REQUEST):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/TransformedResource.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class TransformedResource(Predicate, XMLObject, XMLMatrix, Amount):
"""
TransformedResource defines which
resource is being transformed
- variation
- quantity
Maybe defined by mapped values inside the transformed resource
XXX Transformation works only for a miximum of 3 variation base category...
Matrixbox must be rewrite for a clean implementation of n base category
"""
def updateVariationCategoryList(self):
"""
Check if variation category list of the resource changed and
update transformed resource by doing a set cell range
"""
def _updateQMatrixCellRange(self):
def _setQVariationBaseCategoryList(self, value):
"""
Defines the possible base categories which Quantity value (Q)
variate on
"""
def setQVariationBaseCategoryList(self, value):
"""
Defines the possible base categories which Quantity value (Q)
variate on and reindex the object
"""
def _updateVMatrixCellRange(self):
def _setVVariationBaseCategoryList(self, value):
"""
Defines the possible base categories which Variation value (V)
variate on
"""
def setVVariationBaseCategoryList(self, value):
"""
Defines the possible base categories which Variation value (V)
variate on and reindex the object
"""
def getAggregatedAmountList(self, context=None, REQUEST=None, **kw):
"""
Get all interesting amount value and return AggregatedAmountList
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaySheetTransactionLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaySheetTransactionLine(AccountingTransactionLine):
"""
Pay Sheet Transaction Lines allow to move some quantity of money from a source to a destination like
an Accounting Transaction Line with more informative content
A paysheet transaction line contain details of the paysheet calculation for accounting(ex: insurances, pension, helps...).
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaySheetModel.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaySheetModel(TradeCondition, XMLMatrix):
"""
PaySheetModel are used to define calculating rules specific to a
date, a convention, a enmployees group...
This permit to applied a whole of calculating rules on a whole of
pay sheets
"""
def getCell(self, *kw , **kwd):
def getReferenceDict(self, portal_type_list, get_none_reference=0):
def getInheritanceModelReferenceDict(self, portal_type_list):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/InvoiceLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class InvoiceLine(DeliveryLine):
"""
A DeliveryLine object allows to implement lines in
Deliveries (packing list, order, invoice, etc.)
It may include a price (for insurance, for customs, for invoices,
for orders)
"""
def newCellContent(self, id,**kw):
"""
This method can be overriden
"""
def isAccountable(self):
"""
Invoice movements are never accountable, because they have no
impact on stock calculations.
"""
# def isDivergent(self):
# """
# Returns 1 if the target is not met according to the current information
# After and edit, the isOutOfTarget will be checked. If it is 1,
# a message is emitted
#
# emit targetUnreachable !
# """
def getGroupCriterion(self):
"""
Return the criterion for grouping. This should be overriden by each class.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/VariatedProperty.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class VariatedProperty(XMLObject, XMLMatrix):
"""
VariatedReference defines a reference which
can take multiples values depending of the variations of a resource
Maybe defined by mapped values inside the resource
"""
def newCellContent(self, id, **kw):
"""
This method can be overriden
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/TradeCondition.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class TradeCondition(Path):
"""
Trade Conditions are used to store the conditions (payment, logistic,...)
which should be applied (and used in the orders) when two companies make
business together
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Person.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Person(XMLObject):
"""
An Person object holds the information about
an person (ex. you, me, someone in the company,
someone outside of the company, a member of the portal,
etc.).
Person objects can contain Coordinate objects
(ex. Telephone, Url) as well a documents of various types.
Person objects can be synchronized accross multiple
sites.
Person objects inherit from the Node base class
(one of the 5 base classes in the ERP5 universal business model)
"""
def _setTitle(self, value):
"""
Here we see that we must define a notion
of priority in the way fields are updated
"""
def getTitle(self, **kw):
"""
Returns the title if it exists or a combination of
first name and last name
"""
def title_or_id(self):
def setTitle(self, value):
"""
Updates the title if necessary
"""
def _setFirstName(self, value):
"""
Update Title if first_name is modified
"""
def setFirstName(self, value):
"""
Updates the first_name if necessary
"""
def _setLastName(self, value):
"""
Update Title if last_name is modified
"""
def setLastName(self, value):
"""
Updates the last_name if necessary
"""
def setReference(self, value):
"""
Set the user id. This method is defined explicitly, because:
- we want to apply a different permission
- we want to prevent duplicated user ids, but only when
PAS _AND_ ERP5UserManager are used
"""
def checkPassword(self, value) :
"""
Check the password, usefull when changing password
"""
def setPassword(self, value) :
"""
Set the password, only if the password is not empty.
"""
def getAvailableTime(self, *args, **kw):
"""
Calculate available time for a person
XXX What are the parameters - documentation needed
What is the result ?
"""
def getAvailableTimeSequence(self, *args, **kw):
"""
Calculate available time for a person in a sequence
XXX What are the parameters - documentation needed
What is the result ?
"""
def notifyMessage(self, message):
"""
This method can only be called with proxy roles.
A per user preference allows for deciding how to be notified.
- by email
- by SMS (if meaningful)
- daily
- weekly
- instantly
notification is handled as an activity
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PDFDocument.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PDFDocument(Image, ConversionCacheMixin):
"""
PDFDocument is a subclass of Image which is able to
extract text content from a PDF file either as text
or as HTML.
"""
def index_html(self, REQUEST, RESPONSE, display=None, format='', quality=75,
"""
Returns data in the appropriate format (graphical)
it is always a zip because multi-page pdfs are converted into a zip
file of many images
"""
def convert(self, format, **kw):
"""
Implementation of conversion for PDF files
"""
def populateContent(self):
"""
Convert each page to an Image and populate the
PDF directory with converted images. May be useful
to provide online PDF reader
"""
def _convertToText(self):
"""
Convert the PDF text content to text with pdftotext
"""
def _convertToHTML(self):
"""
Convert the PDF text content to HTML with pdftohtml
NOTE: XXX check that command exists and was executed
successfully
"""
def getContentInformation(self):
"""
Returns the information about the PDF document with
pdfinfo.
NOTE: XXX check that command exists and was executed
successfully
"""
def _setFile(self, data, precondition=None):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaySheetModelLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaySheetModelLine(PaySheetLine, Predicate):
"""
A PaySheetModelLine object allows to implement lines in
PaySheetModel.
A PaySheetModelLine contain all parameters witch make it possible to
calculate a service contribution.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Consumption.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Consumption(XMLObject, XMLMatrix, Variated):
"""
A matrix which provides default quantities
for a given quantity
"""
def _setVariationCategoryList(self,value):
"""
Set consumption variation category list.
Set matrix cell range.
"""
def setVariationCategoryList(self,value):
"""
Set consumption variation category list.
Reindex Object.
"""
def getVariationRangeBaseCategoryItemList(self):
"""
Return range of base variation item
Left display
"""
def getQuantityRatio(self, variation_category_line,
"""
Return quantity ratio for a virtual cell.
Return None if not result can be return.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/GeographicAddress.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class GeographicAddress(Coordinate, Base):
"""
A geographic address holds a complete set of
geographic coordinates including street, number,
city, zip code, region.
Geographic address is a terminating leaf
in the OFS. It can not contain anything.
Geographic address inherits from Base and
from the mix-in Coordinate
"""
def asText(self):
"""
Returns the address as a complete formatted string
with street address, zip, city and region
"""
def fromText(self, coordinate_text):
"""
Tries to recognize the coordinate_text to update
this address
"""
def standardTextFormat(self):
"""
Returns the standard text format for geographic addresses
"""
return ("""\
c/o Jean-Paul Sartre
43, avenue Kleber
75118 Paris Cedex 5
""",
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Career.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Career(Path):
"""
Contains information about abilities, salary, grade, role... of a
Person at a certain career step.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Immobilisation.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Immobilisation(XMLObject, Delivery):
"""
An Immobilisation object holds the information about
an accounting immobilisation (in order to amortise an object)
It is an instant movement without source or destination, but which
implies a state change and a source_decision and a destination_decision
Do not index in stock table
"""
def isMovement(self, **kw):
"""
An Immobilisation must not be indexed in stock table, so it is not a Movement
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ProductionReportCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ProductionReportCell(DeliveryCell):
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
def hasCellContent(self, base_id='movement'):
"""A cell cannot have cell content itself.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AnnotationLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AnnotationLine(PaySheetLine):
"""
A AnnotationLine object allows to add annotation on
PaySheetTransaction. This could be accrued leave or worked duration
or anything else.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaySheetModelSlice.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaySheetModelSlice(DeliveryCell):
"""
A PaySheetModelSlice allows to define max and min values
for each slice
"""
def reindexObject(self, *k, **kw):
"""
Reindex children and simulation
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/InvoiceRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class InvoiceRule(DeliveryRule):
"""
InvoiceRule and DeliveryRule seems to be identical.
Keep it for compatibility only.
"""
def isAccountable(self, movement):
"""Tells wether generated movement needs to be accounted or not.
Invoice movement are never accountable, so simulation movement for
invoice movements should not be accountable either.
"""
def expand(self, applied_rule,
"""
Call expand defined on DeliveryRule.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Coordinate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Coordinate(Base):
"""
Coordinates is a mix-in class which is used to store elementary
coordinates of an Entity (ex. Person, Organisation)
UNKNOWN Coordinates are treated as a document
with a subject (to find a given type of coordinate).
Coordinates use a URL approach. Any coordinate can
be rendered in a URL style. For example::
- tel:+33(0)662057614
- fax:+33(0)153010929
- mailto:jp@nexedi.com
- naf:722Z
- smail://Nexedi/Jean-Paul Smets/943, av de la Republique/59700
Marcq-en-Baroeul/France
Coordinates are stored as content within an Entity. Coordinate ids
are generated as a combination of a so-called role (ex. shipping,
billing, etc.) and a class string. This way, coordinates can
be accessed as attributes of the containing Entity::
- default_phone
- default_fax
- billing_address
- shipping_address
In order to be able to list all coordinates of an Entity,
a list of Coordinate metatypes has to be defined and
stored somewhere. (TODO)
"""
def getRegularExpressionFindAll(self, regular_expression, string):
"""
allows call of re.findall in a python script used for Coordinate
"""
def getRegularExpressionGroups(self, regular_expression, string):
"""
allows call of re.search.groups in a python script used for Coordinate
"""
def view(self):
"""
Return the default view even if index_html is overridden.
"""
def getSearchableText(self):
"""
text for indexing
"""
def asText(self):
"""
returns the coordinate as a text string
"""
def getText(self):
"""
calls asText
"""
def fromText(self, coordinate_text):
"""
modifies the coordinate according to the input text
must be implemented by subclasses
"""
def _setText(self, value):
"""
calls fromText
"""
def standardTextFormat(self):
"""
Returns the standard text formats for telephone numbers
"""
def _writeFromPUT( self, body ):
def PUT(self, REQUEST, RESPONSE):
"""
Handle HTTP / WebDAV / FTP PUT requests.
"""
def manage_FTPget(self):
"""
Get the coordinate as text for WebDAV src / FTP download.
"""
def get_size( self ):
"""
Used for FTP and apparently the ZMI now too
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ImmobilisationLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ImmobilisationLine(Movement, XMLObject, ImmobilisationMovement, DeliveryLine):
"""
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/WebSite.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class WebSiteTraversalHook(Persistent):
"""
This is used by WebSite to rewrite URLs in such way
that once a user gets into a Web Site object, all
documents referenced by the web site are accessed
through the web site rather than directly.
We inherit for persistent, so that pickle mechanism ignores _v_request .
"""
def _physicalPathToVirtualPath(self, path):
"""
Remove the path to the VirtualRoot from a physical path
and add the path to the WebSite if any
"""
def __call__(self, container, request):
"""
Each time we are traversed, we patch the request instance with our
rewritted version of physicalPathToVirtualPath
"""
class WebSite(WebSection):
"""
The Web Site root class is specialises WebSection
by defining a global webmaster user.
"""
def getWebSiteValue(self):
"""
Returns the current web site (ie. self) though containment acquisition
"""
def manage_beforeDelete(self, item, container):
def manage_afterAdd(self, item, container):
def getPermanentURLList(self, document):
"""
Return a list of URLs which exist in the site for
a given document. This could be implemented either
by keep a history of documents which have been
accessed or by parsing all WebSections and listing
all documents in each of them to build a reverse
mapping of getPermanentURL
"""
def getWebSectionValueList(self, document):
"""
Returns a list of sections which a given document is
part of.
This could be implemented either by testing all sections
and building a cache or by using the predicate API
to find which sections apply.
"""
def getWebSectionUidList(section):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Transformation.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Transformation(XMLObject, Predicate, Variated):
"""
Build of material - contains a list of transformed resources
Use of default_resource... (to define the variation range,
to ...)
XXX Transformation works only for a miximum of 3 variation base category...
Matrixbox must be rewrite for a clean implementation of n base category
"""
def updateVariationCategoryList(self):
"""
Check if variation category list of the resource changed and update transformation
and transformation line
"""
def getVariationRangeBaseCategoryList(self):
"""
Returns possible variation base_category ids of the
default resource which can be used a variation axis
in the transformation.
"""
def getVariationRangeBaseCategoryItemList(self,display_id='title_or_id',**kw):
"""
Returns possible variations of the transformation
as a list of tuples (id, title). This is mostly
useful in ERP5Form instances to generate selection
menus.
"""
def getVariationRangeCategoryItemList(self, base_category_list=(),
"""
Returns possible variation category values for the
transformation according to the default resource.
Possible category values is provided as a list of
tuples (id, title). This is mostly
useful in ERP5Form instances to generate selection
menus.
User may want to define generic transformation without
any resource define.
"""
def _setVariationBaseCategoryList(self, value):
"""
Define the possible base categories
"""
def setVariationBaseCategoryList(self, value):
"""
Define the possible base categories and reindex object
"""
def getVariationCategoryItemList(self, base_category_list=(), base=1,
"""
Returns the list of possible variations
XXX Copied and modified from Variated
Result is left display.
"""
def getAggregatedAmountList(self, context=None, REQUEST=None,
"""
getAggregatedAmountList returns a AggregatedAmountList which
can be used either to do some calculation (ex. price, BOM)
or to display a detailed view of a transformation.
context_quantity : if set to one, multiply all quantities
with the quantity of the context
"""
class AggregatedAmountList(UserList):
"""
Temporary object needed to aggregate Amount value
And to calculate some report or total value
"""
def getTotalPrice(self):
"""
Return total bas price of the transformation
"""
def getTotalDuration(self):
"""
Return total duration of the transformation
"""
def multiplyQuantity(self,context=None):
"""
Take into account the quantity of the
context. Change the quantity of each element.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AppliedRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AppliedRule(XMLObject):
"""
An applied rule holds a list of simulation movements.
An applied rule points to an instance of Rule (which defines the actual
rule to apply with its parameters) through the specialise relation.
An applied rule can expand itself (look at its direct parent and take
conclusions on what should be inside).
An applied rule can tell if it is stable (if its children are consistent
with what would be expanded from its direct parent).
An applied rule can tell if any of his direct children is divergent (not
consistent with the delivery).
All algorithms are implemented by the rule.
"""
def tpValues(self) :
""" show the content in the left pane of the ZMI """
def isAccountable(self, movement):
"""Tells whether generated movement needs to be accounted or not."""
def expand(self, **kw):
"""
Expands the current movement downward.
-> new status -> expanded
An applied rule can be expanded only if its parent movement
is expanded.
"""
def _expand(self, **kw):
def solve(self, solution_list):
"""
Solve inconsistency according to a certain number of solutions
templates. This updates the
-> new status -> solved
This applies a solution to an applied rule. Once
the solution is applied, the parent movement is checked.
If it does not diverge, the rule is reexpanded. If not,
diverge is called on the parent movement.
"""
def diverge(self):
"""
-> new status -> diverged
This basically sets the rule to "diverged"
and blocks expansion process
"""
def isStable(self):
"""
Tells whether the rule is stable or not.
"""
def isDivergent(self, sim_mvt):
"""
Tells whether generated sim_mvt is divergent or not.
"""
def getDivergenceList(self, sim_mvt):
"""
Returns a list Divergence descriptors
"""
def getSolverList(self, movement):
"""
Returns a list Divergence solvers
"""
def isRootAppliedRule(self):
"""
Returns 1 is this is a root applied rule
"""
def getRootAppliedRule(self):
"""Return the root applied rule.
useful if some reindexing is needed from inside
"""
def notifySimulationChange(self, notify_dict):
def _isTreeDelivered(self):
"""
Checks if submovements of this applied rule (going down the complete
simulation tree) have a delivery relation.
Returns True if at least one is delivered, False if none of them are.
see SimulationMovement._isTreeDelivered
"""
def getTreeDelivered(applied_rule):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Rule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Rule(Predicate, XMLObject):
"""
Rule objects implement the simulation algorithm
(expand, solve)
Example of rules
- Stock rule (checks stocks)
- Order rule (copies movements from an order)
- Capacity rule (makes sure stocks / sources are possible)
- Transformation rule (expands transformations)
- Template rule (creates submovements with a template system)
used in Invoice rule, Paysheet rule, etc.
Rules are called one by one at the global level (the rules folder)
and at the local level (applied rules in the simulation folder)
The simulation_tool includes rules which are parametrized by the sysadmin
The simulation_tool does the logics of checking, calling, etc.
simulation_tool is a subclass of Folder & Tool
"""
def isAccountable(self, movement):
"""Tells wether generated movement needs to be accounted or not.
Only account movements which are not associated to a delivery;
Whenever delivery is there, delivery has priority
"""
def constructNewAppliedRule(self, context, id=None,
"""
Creates a new applied rule which points to self
"""
def test(self, *args, **kw):
"""
If no test method is defined, return False, to prevent infinite loop
"""
def expand(self, applied_rule, **kw):
"""
Expands the current movement downward.
An applied rule can be expanded only if its parent movement
is expanded.
"""
def solve(self, applied_rule, solution_list):
"""
Solve inconsistency according to a certain number of solutions
templates. This updates the
-> new status -> solved
This applies a solution to an applied rule. Once
the solution is applied, the parent movement is checked.
If it does not diverge, the rule is reexpanded. If not,
diverge is called on the parent movement.
"""
def diverge(self, applied_rule):
"""
-> new status -> diverged
This basically sets the rule to "diverged"
and blocks expansion process
"""
def isDivergent(self, sim_mvt, ignore_list=[]):
"""
Returns true if the Simulation Movement is divergent comparing to
the delivery value
"""
def getDivergenceList(self, sim_mvt):
"""
Return a list of messages that contains the divergences.
"""
# def getSolverList(self, applied_rule):
# """
# Returns a list Divergence solvers
# """
def isOrderable(self, movement):
def isDeliverable(self, movement):
def isStable(self, applied_rule, **kw):
"""
- generate a list of previsions
- compare the prevision with existing children
- return 1 if they match, 0 else
"""
def _getCurrentMovementList(self, applied_rule, **kw):
"""
Returns the list of current children of the applied rule, sorted in 3
groups : immutables/mutables/deletable
If a movement is not frozen, and has no delivered child, it can be
deleted.
Else, if a movement is not frozen, and has some delivered child, it can
be modified.
Else, it cannot be modified.
- is delivered
- has delivered childs (including self)
- is in reserved or current state
- is frozen
a movement is deletable if it has no delivered child, is not in current
state, and not in delivery movements.
a movement
"""
def _getCompensatedMovementList(self, applied_rule,
"""
Compute the difference between prevision and existing movements
immutable movements need compensation, mutables needs to be modified
XXX For now, this implementation is too simple. It could be improved by
using MovementGroups
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/SupplyLink.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SupplyLink(Path, XMLObject):
"""
A DeliveryLine object allows to implement lines in
Deliveries (packing list, order, invoice, etc.)
It may include a price (for insurance, for customs, for invoices,
for orders)
"""
def isProductionSupplyLink(self):
"""
Return 1 if the SupplyLink represents a production.
"""
def isPackingListSupplyLink(self):
"""
Return 1 if the SupplyLink represents a packing list.
"""
def getCurrentNodeValue(self):
"""
Return the node used to find the previous SupplyLink
"""
def getNextNodeValue(self):
"""
Return the node used to find the next SupplyLink
"""
def test(self, movement, concurrent_supply_link_list):
"""
Test if the current link can expand this movement.
Futur implementation have to return properties value
(like quantity) calculated.
This method is called only on packing list supply link.
"""
def calculateStartDate(self, stop_date):
"""
Calculate the start date, depending on the delay.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/DomainGenerator.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class DomainGenerator(XMLObject):
"""
This class defines a predicate as well as all necessary
information to generate subdomains.
Instances are stored in RAM as temp objects
Generator API - DRAFT
"""
def getDomainGeneratorList(self, depth=0, klass=None, script='', parent=None):
"""
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/SaleOpportunity.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SaleOpportunity(Ticket):
"""
LEGACY
This class is superceded by the Ticket class. Legacy
sale opportunity data should still be usable.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ProductionReport.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ProductionReport(Delivery):
"""
A Transaction object allows to add
elementary accounting transactions in the general ledger
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/TextDocument.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class TextDocument(Document, TextContent):
"""
A Document contains text which can be formatted using
*Structured Text* or *HTML*. Text can be automatically translated
through the use of 'message catalogs'.
Document inherits from XMLObject and can
be synchronized accross multiple sites.
Version Management: the notion of version depends on the
type of application. For example, in the case (1) of Transformation
(BOM), all versions are considered as equal and may be kept
indefinitely for both archive and usage purpose. In the case (2)
of Person data, the new version replaces the previous one
in place and is not needed for archive. In the case (3) of
a web page, the new version replaces the previous one,
the previous one being kept in place for archive.
Subcontent: documents may include subcontent (files, images, etc.)
so that publication of rich content can be path independent.
"""
def _edit(self, **kw):
"""\
This is used to edit files which contain HTML content.
"""
def index_html(self, REQUEST, RESPONSE, format=None, **kw):
"""
Unlike for images and files, we want to provide
in the case of HTML a nice standard display with
all the layout of a Web Site. If no format is provided,
the default rendering will use the standard ERP5 machinery.
By providing a format parameter, it is possible to
convert the text content into various formats.
"""
def convert(self, format, **kw):
"""
Convert text using portal_transforms
"""
def __call__(self):
def getContentBaseURL(self):
"""
Returns the content base URL based on the actual content
(in HTML)
"""
def hasBaseData(self):
"""
A TextDocument store its data in the "text_content" property. Since
there is no such thing as base_data in TextDocument, having base_data
is equivalent to having some text_content.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Telephone.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Telephone(Coordinate, Base):
"""
A telephone is a coordinate which stores a telephone number
The telephone class may be used by multiple content types (ex. Fax,
Mobile Phone, Fax, Remote Access, etc.).
A telephone is a terminating leaf
in the OFS. It can not contain anything.
Telephone inherits from Base and
from the mix-in Coordinate
A list of I18N telephone codes can be found here::
http://kropla.com/dialcode.htm
"""
def fromText(self, coordinate_text):
""" See ICoordinate.fromText """
def asText(self):
"""
Returns the telephone number in standard format
"""
def asURL(self):
"""Returns a text representation of the Url if defined
or None else.
"""
def standardTextFormat(self):
"""
Returns the standard text formats for telephone numbers
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/DeliveryCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class DeliveryCell(MappedValue, Movement, ImmobilisationMovement):
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
def getSimulationState(self):
"""
Explicitly acquire simulation_state from parent
"""
def hasCellContent(self, base_id='movement'):
"""A cell cannot have cell content itself.
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
def getProperty(self, key, d=None):
"""
Generic accessor. First we check if the value
exists. Else we call the real accessor
"""
def updatePrice(self):
def getPrice(self, context=None, REQUEST=None, **kw):
"""
Returns the price if defined on the cell
or acquire it
"""
def getQuantity(self):
"""
Returns the quantity if defined on the cell
or acquire it
"""
def getInventoriatedQuantity(self):
"""
"""
def getStartDate(self):
"""
"""
def getStopDate(self):
"""
"""
def getRootDeliveryValue(self):
"""
Returns the root delivery responsible of this cell
"""
def getSimulationQuantity(self):
"""
Computes the quantities in the simulation
"""
def notifyAfterUpdateRelatedContent(self, previous_category_url,
"""
Membership Crirerions and Category List are same in DeliveryCell
Must update it (or change implementation to remove data duplication)
"""
def _edit(self, REQUEST=None, force_update=0, reindex_object=0, **kw):
"""
Store variation_category_list, in order to store new value of
industrial_phase after.
"""
def updateSimulationDeliveryProperties(self, movement_list = None):
"""
Set properties delivery_ratio and delivery_error for each
simulation movement in movement_list (all movements by default),
according to this delivery calculated quantity
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PredicateMatrix.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PredicateMatrix(XMLMatrix):
"""
PredicateMatrix implements a matrix of predicates, and
allows to get cell that match predicates.
"""
def _getMatchingCell(self, movement):
"""
Browse all cells and test them until match found
"""
def updateMatrix(self) :
"""
This methods updates the matrix so that cells are consistent
with the predicates.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ImmobilisableItem.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ImmobilisableItem(XMLObject, Amount):
"""
An Immobilisable Item is an Item which can be immobilised
and amortised in accounting
"""
def getImmobilisationRelatedMovementList(self,
"""
Returns a dictionary of lists containing movements related to amortisation system
from_date is included, to_date is excluded
filter_valid eliminates all invalid immobilisation movements in immobilisation movement list.
Also, only movements in current_inventory state are returned if filter_valid is set.
If filter_valid is set and some movements are in state 'calculating', a ImmobilisationValidityError is launch
immobilisation_movement and owner_change specify which lists to return
immobilisation_movement_list is the list of movements to use instead of looking in SQL. Warning : in the case of
movement_list is provided, no filter is applied on it (unless looking at each movement validity)
and movement_list is supposed to be well sorted.
The search is based on catalog so you can use related keys
"""
def _ownerChange(self, first_section, second_section):
"""
Tests if section 1 and section 2 are the same owner or not
It is done by looking at the mapped organisations
If a mapped organisation exists, and the social capital currency is not None,
it is considered as an independant organisation
"""
def _getFirstIndependantOrganisation(self, section):
"""
Returns the first found independant organisation, looking at
the group tree upward. An independant organisation is found when the
category has a mapping related value, and this value has a social capital currency
"""
def getImmobilisationMovementValueList(self,
"""
Returns a list of immobilisation movements applied to current item from date to date
Argument filter_valid allows to select only the valid immobilisation movements
"""
def getUnfilteredImmobilisationMovementValueList(self, from_date=None, to_date=None, **kw):
"""
Returns a list of immobilisation applied to the current item from date to date
All of the movements are returned, not even those which are valid
"""
def getPastImmobilisationMovementValueList(self, from_date=None, at_date=None, **kw):
"""
Returns a list of immobilisation movements applied to current item before the given date, or now
"""
def getFutureImmobilisationMovementValueList(self, to_date=None, at_date=None, from_movement=None, **kw):
"""
Returns a list of immobilisation movements applied to current item after the given date (excluded), or now
If from_movement is set and the given movement is found, remove it from the list
"""
def getLastImmobilisationMovementValue(self, at_date=None, **kw):
"""
Returns the last immobilisation movement before the given date, or now
"""
def getNextImmobilisationMovementValue(self, at_date=None, from_movement=None, **kw):
"""
Returns the first immobilisation movement after the given date, or now
If from_movement is set and the given movement is the next one, returns
the second next movement
"""
def getImmobilisationPeriodList(self, from_date=None, to_date=None, **kw):
"""
Returns a list of dictionaries representing immobilisation periods for the object
from_date is included, to_date is excluded
"""
def setPreviousPeriodParameters(period_list,
def getLastImmobilisationPeriod(self, to_date=None, **kw):
"""
Returns the current immobilisation period, or the last one if the
item is not currently immobilised, at the given at_date (excluded)
"""
def isCurrentlyImmobilised(self, **kw):
""" Returns true if the item is immobilised at this time """
def isNotCurrentlyImmobilised(self, **kw):
""" Returns true if the item is not immobilised at this time """
def isImmobilised(self, at_date=None, **kw):
"""
Returns true if the item is immobilised at the given date.
If at_date = None, returns true if the item has ever been immobilised.
"""
def getCurrentRemainingAmortisationDuration(self, **kw):
""" Returns the calculated remaining amortisation duration for this item at the current time. """
def getRemainingAmortisationDuration(self, at_date=None, **kw):
"""
Returns the calculated remaining amortisation duration for the item.
It is based on the latest immobilisation period at given date, or now.
"""
def getRemainingDurability(self, at_date=None, **kw):
"""
Returns the durability of the item at the given date, or now.
The durability is quantity of something which corresponds to the 'life' of the item
(ex : km for a car, or time for anything)
Each Immobilisation Movement stores the durability at a given time, so it is possible
to approximate the durability between two Immobilisation Movements by using a simple
linear calculation.
Note that durability has no sense for items which are immobilisated but not
amortised (like grounds, etc...). Calculation is based on duration, so an item
immobilised without amortisation duration will not decrease its durability.
"""
def getCurrentRemainingDurability(self, **kw):
"""
Returns the remaining durability at the current date
"""
def getAmortisationPrice(self, at_date=None, with_currency=0, **kw):
"""
Returns the deprecated value of item at given date, or now.
If with_currency is set, returns a string containing the value and the corresponding currency.
"""
def getCurrentAmortisationPrice(self, with_currency=0, **kw):
""" Returns the deprecated value of item at current time """
def _createAmortisationRule(self):
"""
Build or update the amortisation rule related to this item, then expand the rule
SHOULD BE RUN AS MANAGER
"""
def expandAmortisation(self,**kw):
"""
Calculate the amortisation annuities for the item
in an activity
SHOULD BE RUN AS MANAGER
"""
def immediateExpandAmortisation(self):
"""
Calculate the amortisation annuities for the item
SHOULD BE RUN AS MANAGER
"""
def getSectionMovementValueList(self,
"""
Return the list of successive movements affecting
owners of the item. If at_date is None, return the result all the time
Only the movements in current_inventory_state are taken into account
"""
def getSectionChangeList(self, at_date=None, **kw):
"""
Return the list of successive owners of the item with
the corresponding ownership change dates
If at_date is None, return the result all the time
"""
def getSectionValue(self, at_date=None, **kw):
"""
Return the owner of the item at the given date
If at_date is None, return the last owner without time limit
"""
def getCurrentSectionValue(self, **kw):
"""
Return the current owner of the item
"""
def getCleanSqlDict(self, kw):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/CalendarException.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class CalendarException(XMLObject):
"""
Exception of Calendar Period
"""
def reindexObject(self, *args, **kw):
"""
Make sure to reindex the parent period
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Movement.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Movement(XMLObject, Amount):
"""
The Movement class allows to implement ERP5 universal accounting model.
Movement instances are used in different situations:
- Orders: Movement instances are use as a documentary object
to define quantities in orders
- Deliveries: movements track the actual transfer of resources
in the past (accounting) or in the future (planning / budgetting)
For example, the following objects are Orders:
- a purchase order (the document we send to a supplier
when we need some goods)
- a sales order (the document we ask our customer
to sign to confirm a sale)
- a production order (the document we send to the workshop
to confirm we need some operation / service to be achieved)
Orders allow to describe a target, but can not be used to account
the reality of actual transfered quantities.
This is not the case for Deliveries:
- an invoice (a delivery of money between abstract accounts)
- a packing list (ie. a delivery of goods shipped)
- a delivery report (ie. a delivery of goods received)
- a production report (ie. a delivery of service)
- a T/T report (a delivery of money between reals accounts)
For planning, the following approach is used:
1- Movements from an order are never modified once the order
is confirmed. This is a rule. An Order is like a contract.
It can only be amended, if all parties agree.
2- Movements in a delivery may exist on their own
(ex. an accounting transaction). Past movements
can not be modified. Future movements may or may
not be modified
When an order is confirmed, the list of "order" movements
it contains is copied into "delivery" movements. Each delivery
movement contains a "causality" reference to the order
it. This allows delivery to be completely different from order
(ex. different resource, different date, different quantity)
and allows to keep track of the causal relation between
a delivery and an order.
A delivery document (actually a delivery line) then points to one or more of
the "delivery" movements in the simulation. It is possible to know
which items have been delivered by making sure each movement in the simulation
is associated to a "delivery document".
By looking at all "simulation"
Delivery movements can be applied the following transformations:
- split : one movement is cut into 2 or more movements
- submovements : one movement "generates" many other movements.
For example, a delivery of goods from the workshop to the stock,
will result in a "pull" calculation which generates operations
and sourcing based on a BOM document. The causality of each
delivery is the "applied rule" which was used to generate submovements
One should note that
- movements are never joined (because it would break causality and
tracability)
- movements acquire some context information from their causality
Some submovements need no order to be "confirmed". Some submovements
need an order to be "confirmed". For example
- a submovement which allows to compute the CO2 emissions
of a production facility needs no order confirmation
(this kind of movement is mostly ised for reporting)
- a submovement which takes some goods in a stock and
brings them to a workshop needs some "stock movement"
order to be "confirmed"
- a submovement which requires someone to take his time
for some operation nees a "service order" to be confirmed
This means that the simulation process must make a distinction
between different workflows applicable to a movement. For
movements which require an order to be confirmed, the workflow
involves the following steps:
- an order is automaticaly generated, with "order movements"
which become "causalities" for delivery movements (XXX
this sound strange...)
- each order movement is associated to one of the delivery
As a result, a delivery movement which requires an order may
have 2 causalities
- one causality (ie. application of a rule)
- another causality (ie. confirmation in an order)
Each causality may define its own context. One context
may be related for example to a customer request, another context
may be related to an "internal customer" request (eg. the production manager).
Context may eventually conflict each other.
In a customer oriented company, movements should probably
always be stored within the customer order and acquire
from the order all context information.
In a mass production facility, context may be defined in more
than one location. This is an incentive for putting
all movements in a simulation "box".
The second approach is chosen for documentary consistency approach :
in ERP5, documents rules, can be synchronized. Simulation can not be
synchronized
"""
def _getPrice(self, context):
def _getTotalPrice(self, default=None, context=None):
def getPriceCalculationOperandDict(self, default=None, context=None, **kw):
"""Return a dict object which contains operands used for price
calculation. The returned items depend on a site configuration,
because this will invoke a custom script at the end. The only
assumption is that the dict must contain a key 'price'
which represents the final result of the price calculation.
The purpose is to obtain descriptive information to notify the user
of how a price is calculated in details, in particular, for invoices
and quotations. So a script which is eventually called should provide
all values required for generating such reports (e.g. a price,
a price without a discount, and a discount).
"""
def getPrice(self, default=None, evaluate=1, **kw):
"""
Get the Price in the context.
If price is not stored locally, lookup a price and store it.
"""
def getTotalPrice(self, default=None, context=None, REQUEST=None, **kw):
"""
Get the Total Price in the context.
"""
def getTotalQuantity(self):
"""
Returns the quantity if no cell or the total quantity if cells
"""
def getIndustrialPrice(self):
"""
Calculates industrial price in context of this movement
"""
def getSourceInventoriatedTotalAssetPrice(self):
"""
Returns a price which can be used to calculate stock value (asset)
Asset price is used for calculation of inventory asset value
and for accounting
If the asset price is specified (as in accounting for multi-currency),
then it is returned. If no asset price is specified, then we use
the price as defined on the line, but only for incoming quantities
(purchase price, industrial price, etc.).
For outgoing quantities, it is the responsability of database
to calculate asset prices based on calculation rules (FIFO,
FILO, AVERAGE, etc.).
"""
def getSourceInventoriatedTotalAssetDebit(self) :
"""
Returns the debit part of inventoriated source total asset price.
"""
def getSourceInventoriatedTotalAssetCredit(self) :
"""
Returns the credit part of inventoriated source total asset price.
"""
def getDestinationInventoriatedTotalAssetPrice(self):
"""
Returns a price which can be used to calculate stock value (asset)
Asset price is used for calculation of inventory asset value
and for accounting
"""
def getDestinationInventoriatedTotalAssetDebit(self) :
"""
Returns the debit part of inventoriated destination total asset price.
"""
def getDestinationInventoriatedTotalAssetCredit(self) :
"""
Returns the credit part of inventoriated destination total asset price.
"""
def getSourceAssetPrice(self):
"""
Returns the price converted to the currency of the source section
This will be implemeted by calling currency conversion on currency resources
"""
def getDestinationAssetPrice(self):
"""
Returns the price converted to the currency of the destination section
"""
def isConvergent(self):
"""
Returns 0 if the target is not met
"""
def isDivergent(self):
"""
XXX documentation out of sync with actual use
Returns 1 if the target is not met according to the current information
After and edit, the isOutOfTarget will be checked. If it is 1,
a message is emitted
emit targetUnreachable !
"""
def getDivergenceList(self):
"""
Return a list of messages that contains the divergences
"""
def isFrozen(self):
"""
Returns the frozen status of this movemnt.
a movement in started, stopped, delivered is automatically frozen.
If frozen is locally set to '0', we must check for a parent set to '1', in
which case, we want the children to be frozen as well.
"""
def getExplanation(self):
"""
Returns the relative_url of the explanation of this movement.
"""
def getExplanationUid(self):
"""
Returns the uid of the explanation of this movement.
"""
def getExplanationValue(self):
"""
Returns the object explanation of this movement.
"""
def getExplanationTitle(self, default=''):
"""
Returns the title of the explanation of this movement.
"""
def getExplanationReference(self, default=''):
"""
Returns the reference of the explanation of this movement.
"""
def getRootCausalityValueList(self):
"""
Returns the initial causality value for this movement.
This method will look at the causality and check if the
causality has already a causality
"""
def isSimulated(self):
def getOrderQuantity(self):
"""
Returns the quantity of related order(s)
"""
def getDeliveryQuantity(self):
"""
Returns the quantity of related delivery(s)
"""
def getSimulationQuantity(self):
"""
Returns the sum of quantities in related simulation movements
"""
def getOrderStartDateList(self):
"""
Returns the list of start date of related order(s)
"""
def getDeliveryStartDateList(self):
"""
Returns the list of start date of related delivery(s)
"""
def getSimulationStartDateList(self):
"""
Returns the list of start date related simulation movements
"""
def getOrderStopDateList(self):
"""
Returns the list of stop date of related order(s)
"""
def getDeliveryStopDateList(self):
"""
Returns the list of stop date of related delivery(s)
"""
def getSimulationStopDateList(self):
"""
Returns the list of stop date related simulation movements
"""
def getOrderSourceList(self):
"""
Returns the source of related orders
"""
def getDeliverySourceList(self):
"""
Returns the source of related deliveries
"""
def getSimulationSourceList(self):
"""
Returns the source of related simulation movements
"""
def getOrderDestinationList(self):
"""
Returns the destination of related orders
"""
def getDeliveryDestinationList(self):
"""
Returns the destination of related deliveries
"""
def getSimulationDestinationList(self):
"""
Returns the destination of related simulation movements
"""
def getOrderSourceSectionList(self):
"""
Returns the source_section of related orders
"""
def getDeliverySourceSectionList(self):
"""
Returns the source_section of related deliveries
"""
def getSimulationSourceSectionList(self):
"""
Returns the source_section of related simulation movements
"""
def getOrderDestinationSectionList(self):
"""
Returns the destination_section of related orders
"""
def getDeliveryDestinationSectionList(self):
"""
Returns the destination_section of related deliveries
"""
def getSimulationDestinationSectionList(self):
"""
Returns the destination_section of related simulation movements
"""
def getSourceDebit(self):
"""
Return the quantity
"""
def getSourceCredit(self):
"""
Return the quantity
"""
def setSourceDebit(self, source_debit):
"""
Set the quantity
"""
def setSourceCredit(self, source_credit):
"""
Set the quantity
"""
def _edit(self, **kw):
"""Overloaded _edit to support setting debit and credit at the same time,
which is required for the GUI.
"""
def getSourceAssetDebit(self):
"""
Return the debit part of the source total asset price.
This is the same as getSourceDebit where quantity is replaced
by source_total_asset_price.
This method returns 0 if the total asset price is not set.
"""
def getSourceAssetCredit(self):
"""
Return the credit part of the source total asset price.
This is the same as getSourceCredit where quantity is replaced
by source_total_asset_price.
This method returns 0 if the total asset price is not set.
"""
def getDestinationAssetDebit(self):
"""
Return the debit part of the destination total asset price.
This is the same as getDestinationDebit where quantity is replaced
by destination_total_asset_price.
This method returns 0 if the total asset price is not set.
"""
def getDestinationAssetCredit(self):
"""
Return the credit part of the destination total asset price.
This is the same as getDestinationCredit where quantity is replaced
by destination_total_asset_price.
This method returns 0 if the total asset price is not set.
"""
def setSourceAssetDebit(self, source_debit):
"""
Set the source total asset price
"""
def setSourceAssetCredit(self, source_credit):
"""
Set the source total asset price
"""
def setDestinationAssetDebit(self, destination_debit):
"""
Set the destination total asset price
"""
def setDestinationAssetCredit(self, destination_credit):
"""
Set the destination total asset price
"""
def getTrackedItemUidList(self):
"""
Return a list of uid for related items
"""
def getProductionTotalQuantity(self):
"""
Return the produced quantity
"""
def getConsumptionTotalQuantity(self):
"""
Return the produced quantity
"""
def getSubVariationText(self,**kw):
"""
Provide a string representation of XXX
"""
def getParentExplanationValue(self):
"""
This method should be removed as soon as movement groups
will be rewritten. It is a temp hack
"""
# def getSourceStandardInventoriatedQuantity(self):
# """
# The inventoriated quantity converted in a default unit
#
# For assortments, returns the inventoriated quantity in terms of number of items
# in the assortemnt.
#
# For accounting, returns the quantity converted in a default unit
# """
# def getDestinationStandardInventoriatedQuantity(self):
# """
# The inventoriated quantity converted in a default unit
#
# For assortments, returns the inventoriated quantity in terms of number of items
# in the assortemnt.
#
# For accounting, returns the quantity converted in a default unit
# """
def asMovementList(self):
"""
Placeholder method called when indexing a movement.
It can be overloaded to generate multiple movements
from a single one.
It is used for cataloging a movement multiple time in
the movement/stock tables.
Ex: a movement have multiple destinations.
asMovementList returns a list a movement context with different
single destination.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/InvoiceTransactionRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class InvoiceTransactionRule(Rule, PredicateMatrix):
"""
Invoice Transaction Rule object generates accounting movements
for each invoice movement based on category membership and
other predicated. Template accounting movements are stored
in cells inside an instance of the InvoiceTransactionRule.
"""
def _generatePrevisionList(self, applied_rule, **kw):
"""
Generate a list of movements, that should be children of this rule,
based on its context (parent movement, delivery, configuration ...)
These previsions are acrually returned as dictionaries.
"""
def expand(self, applied_rule, force=0, **kw):
"""
Expands the rule:
- generate a list of previsions
- compare the prevision with existing children
- get the list of existing movements (immutable, mutable, deletable)
- compute the difference between prevision and existing (add,
modify, remove)
- add/modify/remove child movements to match prevision
"""
def newCellContent(self, id, **kw):
"""
Creates a new Cell.
"""
def solve(self, applied_rule, solution_list):
"""
Solve inconsistency according to a certain number of solutions
templates. This updates the
-> new status -> solved
This applies a solution to an applied rule. Once
the solution is applied, the parent movement is checked.
If it does not diverge, the rule is reexpanded. If not,
diverge is called on the parent movement.
"""
def diverge(self, applied_rule):
"""
-> new status -> diverged
This basically sets the rule to "diverged"
and blocks expansion process
"""
# def isDivergent(self, applied_rule):
# """
# Returns 1 if divergent rule
# """
# def getDivergenceList(self, applied_rule):
# """
# Returns a list Divergence descriptors
# """
# def getSolverList(self, applied_rule):
# """
# Returns a list Divergence solvers
# """
def isOrderable(self, m):
def isDeliverable(self, m):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ImmobilisationMovement.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ImmobilisationMovement(Movement, XMLObject):
"""
An ImmobilisationMovement is a generic object representing an immobilisation
and optional amortisation decision for any item. It holds information about
an accounting immobilisation (in order to amortise an object)
"""
def _checkImmobilisationConsistency(self, fixit=0, mapped_value_property_list=(), to_translate=1):
"""
If to_translate is set, the method may return a dictionary {'msg':'...', 'mapping':{} }
"""
def checkValuesAreNotNone(property_list):
def checkValue(variable,
def checkPreviousMovementForItem(movement, item):
def checkImmobilisationConsistency(self, *args, **kw):
"""
Checks the consistency about immobilisation values
"""
def getAmortisationMethodParameter(self, parameter_list, **kw):
"""
Returns a dictionary containing the value of each parameter
whose name is given in parameter_list.
Warning : can only be used on a movement whose amortisation_method
is not in (None, NO_CHANGE_METHOD)
"""
def getAmortisationMethodParameterForItem(self, item, parameter_list, split_char=None, split_qty=3, **kw):
"""
Returns a dictionary containing the value of each parameter
whose name is given in parameter_list.
The value is get from the amortisation method parameter folder
(e.g. portal_skins/erp5_accounting_eu/linear)
This folder has specifical parameters needed for calculation
'item' can be None to access parameters on a movement whose method is not NO_CHANGE_METHOD nor None
"""
def getActualAmortisationMethodForItem(self, item, **kw):
"""
Returns the actual amortisation method by getting the previous
movement method if the current one is NO_CHANGE_METHOD
"""
def getNeededSpecificParameterListForItem(self, item, **kw):
"""
Returns the list of specific parameters which are
needed for the amortisation calculation for the given item
"""
def getUncontinuousNeededSpecificParameterListForItem(self, item, **kw):
"""
Returns the list of specific parameters which are
needed for the amortisation calculation for the given item
when the amortisation is not continuing the previous period
"""
def getFacultativeSpecificParameterListForItem(self, item, **kw):
"""
Returns the list of specific parameters which are
facultative for the amortisation calculation for the given item
"""
def isUsingAmortisationMethod(self, method):
"""
Return true if this item is using the given method
"""
def getImmobilisationState(self, id_only=1):
"""
Return root delivery immobilisation state
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Pricing.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Pricing(MappedValue, XMLMatrix):
"""
Un element de tarif est un prix pour un ensemble de conditions d'application...
"""
def _setQuantityRangeList(self, category_list):
"""
Defines the possible base categories which Quantity value (Q)
variate on
"""
def setQuantityRangeList(self, category_list):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/SupplyCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SupplyCell(Predicate, DeliveryCell, Path):
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
(PATH)
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Path.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Path(MappedValue):
"""
A Path defines a planning element. A path is the combination of
- a MappedValue (Paths can hold an undetermined number of properties
associated to extra conditions)
- an Arrow (a path is associated to a source and destination)
- a Path (which defines the resource involved)
- a FlowCapacity (which defines the capacities on the Path)
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Organisation.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Organisation(XMLObject):
"""
An Organisation object holds the information about
an organisation (ex. a division in a company, a company,
a service in a public administration).
Organisation objects can contain Coordinate objects
(ex. Telephone, Url) as well a documents of various types.
Organisation objects can be synchronized accross multiple
sites.
Organisation objects inherit from the MetaNode base class
(one of the 5 base classes in the ERP5 universal business model)
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Capacity.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Capacity(XMLObject):
"""
Mix-in
"""
def asCapacityItemList(self):
"""
Returns an association list of points and capacity values
"""
def reindexObject(self):
"""
Overload reindexing in order to forward any modifications of capacity
to simulation tool
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Item.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Item(XMLObject, Amount, ImmobilisableItem):
"""
Items in ERP5 are intended to provide a way to track objects
"""
def generateNewId(self, id_group='item_id_group', default=None, method=None):
"""
We want a different id for all Item
"""
def getPrice(self,context=None,**kw):
"""
Get the Price in the context.
If price is not stored locally, lookup a price
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Device.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Device(Item):
"""
Devices represent equipments with one network interface
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AccountingTransaction.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AccountingTransaction(Delivery):
"""
A Transaction object allows to add
elementary accounting transactions in the general ledger
"""
def hasSourceSectionAccounting(self):
"""Return true if we should take into account accounting for source
section.
"""
def hasDestinationSectionAccounting(self):
"""Return true if we should take into account accounting for destination
section.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/WebSection.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class WebSection(Domain):
"""
A Web Section is a Domain with an extended API intended to
support the creation of Web front ends to
server ERP5 contents through a pretty and configurable
user interface.
WebSection uses the following scripts for customisation:
- WebSection_getBreadcrumbItemList
- WebSection_getDocumentValueList
- WebSection_getPermanentURL
- WebSection_getDocumentValue
- WebSection_getDefaultDocumentValue
- WebSection_getSectionValue
- WebSection_getWebSiteValue
It defines the following REQUEST global variables:
- current_web_section
- current_web_document
- is_web_section_default_document
"""
def _aq_dynamic(self, name):
"""
Try to find a suitable document based on the
web site local naming policies as defined by
the getDocumentValue method
"""
def getWebSectionValue(self):
"""
Returns the current web section (ie. self) though containment acquisition.
To understand the misteries of acquisition and how the rule
containment vs. acquisition works, please look at
XXXX (Zope web site)
"""
def __call__(self):
"""
If a Web Section has a default document, we render
the default document instead of rendering the Web Section
itself.
The implementation is based on the presence of specific
variables in the REQUEST (besides editable_mode and
ignore_layout).
current_web_section -- defines the Web Section which is
used to display the current document.
current_web_document -- defines the Document (ex. Web Page)
which is being displayed within current_web_section.
is_web_section_default_document -- a boolean which is
set each time we display a default document as a section.
We use REQUEST parameters so that they are reset for every
Web transaction and can be accessed from widgets.
"""
def getApplicableLayout(self):
"""
The applicable layout on a section is the container layout.
"""
def getDocumentValue(self, name=None, portal=None, **kw):
"""
Return the default document with the given
name. The name parameter may represent anything
such as a document reference, an identifier,
etc.
If name is not provided, the method defaults
to returning the default document by calling
getDefaultDocumentValue.
kw parameters can be useful to filter content
(ex. force a given validation state)
This method must be implemented through a
portal type dependent script:
WebSection_getDocumentValue
"""
def getDefaultDocumentValue(self):
"""
Return the default document of the current
section.
This method must be implemented through a
portal type dependent script:
WebSection_getDefaultDocumentValue
"""
def getDocumentValueList(self, **kw):
"""
Return the list of documents which belong to the
current section. The API is designed to
support additional parameters so that it is possible
to group documents by reference, version, language, etc.
or to implement filtering of documents.
This method must be implemented through a
portal type dependent script:
WebSection_getDocumentValueList
"""
def getPermanentURL(self, document):
"""
Return a permanent URL of document in the context
of the current section.
This method must be implemented through a
portal type dependent script:
WebSection_getPermanentURL
"""
def getBreadcrumbItemList(self, document):
"""
Return a section dependent breadcrumb in the form
of a list of (title, document) tuples.
This method must be implemented through a
portal type dependent script:
WebSection_getBreadcrumbItemList
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaymentRule.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaymentRule(Rule):
"""
Payment Rule generates payment simulation movement from invoice transaction simulation movements.
This one is a very s(imple|tupid) one : if the parent movement is a 'receivable' one,
we just create two submovements : 'receivable' (as credit)
and 'bank' (as debit) with the same quantity as the parent.
"""
def expand(self, applied_rule, **kw):
"""
Expands the current movement downward.
-> new status -> expanded
An applied rule can be expanded only if its parent movement
is expanded.
"""
def isDeliverable(self, m):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AgentPrivilege.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AgentPrivilege(XMLObject):
"""
An Agent Privilege allow the Bank Account owner to give permissions to an Agent for a given period of time, for a maximum amount of money.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Assignment.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Assignment(Path):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/AccountingRuleCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class AccountingRuleCell(Predicate, Invoice):
"""
An AccountingRuleCell object allows to add SaleInvoiceTransactionLines into a Matrix
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Supply.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Supply(Path, XMLObject):
"""A Supply defines precise pricing and shipping conditions between
two trade parties for a limited selection of traded products,
components, services, etc. It can be used to represent price
catalogs, product referencing, pricing policy, etc.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Alarm.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PeriodicityMixin:
"""
Periodicity is a Mixin Class used to calculate date periodicity.
"""
def _validateMinute(self, date, previous_date):
"""
Validate if date's minute matches the periodicity definition
"""
def _validateHour(self, date):
"""
Validate if date's hour matches the periodicity definition
"""
def _validateDay(self, date):
"""
Validate if date's day matches the periodicity definition
"""
def _validateWeek(self, date):
"""
Validate if date's week matches the periodicity definition
"""
def _validateMonth(self, date):
"""
Validate if date's month matches the periodicity definition
"""
def getNextPeriodicalDate(self, current_date, next_start_date=None):
"""
Get the next date where this periodic event should start.
We have to take into account the start date, because
sometimes an event may be started by hand. We must be
sure to never forget to start an event, even with some
delays.
Here are some rules :
- if the periodicity start date is in the past and we never starts
this periodic event, then return the periodicity start date.
- if the periodicity start date is in the past but we already
have started the periodic event, then see
XXX Better API is needed. It may defined which minimal time duration has to
be added in order to calculate next date.
Ex: here, we use minute as smaller duration.
On CalendarPeriod, day is the smaller duration.
"""
def getWeekDayList(self):
"""
returns something like ['Sunday','Monday',...]
"""
def getWeekDayItemList(self):
"""
returns something like [('Sunday', 'Sunday'), ('Monday', 'Monday'),...]
"""
def getMonthItemList(self):
"""
returns something like [('January', 1), ('February', 2),...]
"""
def getPeriodicityWeekDayList(self):
"""
Make sure that the list of days is ordered
"""
class Alarm(XMLObject, PeriodicityMixin):
"""
An Alarm is in charge of checking anything (quantity of a certain
resource on the stock, consistency of some order,....) periodically.
This check can span over multiple activities through an active
process.
An Alarm is capable of displaying the last result of the check
process which was run in background. The result can be provided
either as a boolean value (alarm was raised or not) or
in the form of an HTML report which is intended to be
displayed in a control center. Moreover, user may be notified
automatically of alarm failures.
Alarm may also provide a solution if something wrong happens. This
solution takes the form of a script which can be invoked
by the administrator or by the user by clicking on a button
displayed in the Alarm control center.
"""
def isActive(self):
"""
This method returns only True or False.
It simply tells if this alarm is currently
active or not. An Alarm is said to be active whenever
some calculation is undergoing either as part
of the sensing process (activeSense) or as part
of the problem resolution process (solve).
"""
def activeSense(self, fixit=0):
"""
This method launches the sensing process as activities.
It is intended to launch a very long process made
of many activities. It returns nothing since the results
are collected in an active process.
The result of the sensing process can be obtained by invoking
the sense method or by requesting a report.
"""
def sense(self, process=None):
"""
This method returns True or False. False for no problem, True for problem.
This method should respond very quickly.
Complex alarms should use activity based calculations through
the activeSense method.
The process parameter can be used to retrive sense values for
past processes.
"""
def report(self, reset=0, process=None):
"""
This methods produces a report (HTML) to display
the results of the sensing process.
The report is intended to provide a nice visualisation
of the sensing process, of problems which may occur or
of the fact that there was no problem. No calculation
should be made normally at this time (or very fast calculation).
Complex alarms should implement calculation through
the invocation of activeSense.
Report implementation is normally made using an
ERP5 Form.
"""
def solve(self):
"""
This method tries resolve a problems detected by an Alarm
within the sensing process. Problem resolution is
implemented by an external script.
If no external script is dehfined, activeSense is invoked
with fixit=1
"""
def notify(self):
"""
This method is called to notify people that some alarm has
been sensed. Notification consists of sending an email
to the system address if nothing was defined or to
notify all agents defined on the alarm if specified.
"""
message="""
Alarm Title: %s
Alarm Description:
%s
Alarm URL: %s
""" % (self.getTitle(), self.getDescription(), self.absolute_url()))
def getLastActiveProcess(self):
"""
This returns the last active process finished. So it will
not returns the current one
"""
def sort_date(a, b):
def newActiveProcess(self):
"""
We will create a new active process in order to store
new results, then this process will be added to the list
of processes
"""
def setNextAlarmDate(self, current_date=None):
"""
Save the next alarm date
"""
def getAlarmDate(self):
"""
returns something like ['Sunday','Monday',...]
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/InvoiceCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class InvoiceCell(DeliveryCell):
"""
A DeliveryCell allows to define specific quantities
for each variation of a resource in a delivery line.
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
# def isDivergent(self):
# """
# Returns 1 if the target is not met according to the current information
# After and edit, the isOutOfTarget will be checked. If it is 1,
# a message is emitted
#
# emit targetUnreachable !
# """
def getGroupCriterion(self):
"""
Return the criterion for grouping. This should be overriden by each class.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Predicate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Predicate(XMLObject, Folder):
"""
A Predicate object defines a list of criterions
which can be applied to test a document or to search for documents.
Predicates are defined by a combination of PropertySheet values
(ex. membership_criterion_list) and criterion list (ex. quantity
is between 0 and 10). An additional script can be associated to
extend the standard Predicate semantic with any additional
script based test.
The idea between Predicate in ERP5 is to have a simple
way of defining simple predicates which can be later
searched through a simplistic rule based engine and which can
still provide complete expressivity through additional scripting.
The approach is intended to provide the expressivity of a rule
based system without the burden of building a fully expressive
rule engine.
"""
def test(self, context, tested_base_category_list=None, **kw):
"""
A Predicate can be tested on a given context.
Parameters can passed in order to ignore some conditions.
- tested_base_category_list: this is the list of category that we do
want to test. For example, we might want to test only the
destination or the source of a predicate.
"""
def buildSQLQuery(self, strict_membership=0, table='category',
"""
A Predicate can be rendered as an SQL expression. This
can be used to generate SQL requests in reports or in
catalog search queries.
XXX - This method is not implemented yet
"""
def asSQLExpression(self, strict_membership=0, table='category'):
"""
A Predicate can be rendered as an SQL expression. This
can be used to generate SQL requests in reports or in
catalog search queries.
"""
def asSQLJoinExpression(self, strict_membership=0, table='category', join_table='catalog', join_column='uid'):
"""
"""
def searchResults(self, **kw):
"""
"""
def countResults(self, REQUEST=None, used=None, **kw):
"""
"""
def getCriterionList(self, **kw):
"""
Returns the list of criteria which are defined by the Predicate.
Each criterion is returned in a TempBase instance intended to be
displayed in a ListBox.
XXX - It would be better to return criteria in a Criterion class
instance
"""
def setCriterion(self, property, identity=None, min=None, max=None, **kw):
"""
This methods sets parameters of a criterion. There is at most one
criterion per property. Defined parameters are
identity -- if not None, allows for testing identity of the property
with the provided value
min -- if not None, allows for testing that the property
is greater than min
max -- if not None, allows for testing that the property
is greater than max
"""
def edit(self, **kwd):
"""
The edit method is overriden so that any time a
criterion_property_list property is defined, a list of criteria
is created to match the provided criterion_property_list.
"""
def setPredicateCategoryList(self, category_list):
"""
This method updates a Predicate by implementing an
AND operation on all predicates (or categories)
provided in category_list. Categories behave as a
special kind of predicate which only acts on category
membership.
WARNING: this method does not take into account scripts at
this point.
"""
def generatePredicate(self, multimembership_criterion_base_category_list=(),
"""
This method generates a new temporary predicate based on an ad-hoc
interpretation of local properties of an object. For example,
a start_range_min property will be interpreted as a way to define
a min criterion on start_date.
The purpose of this method is to be called from
a script called PortalType_asPredicate to ease the generation of
Predicates based on range properties. It should be considered mostly
as a trick to simplify the development of Predicates and forms.
"""
def asPredicate(self, script_id=None):
"""
This method tries to convert the current Document into a predicate
looking up methods named ${PortalType}_asPredicate,
${MetaType}_asPredicate, ${Class}_asPredicate
"""
def searchPredicate(self, **kw):
"""
Returns a list of documents matching the predicate
TO BE IMPLEMENTED using portal_catalog(**kw)
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/SupplyChain.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SupplyChainError(Exception): pass
class SupplyChain(Path, XMLObject):
"""
SupplyChain defines the route used to produced a resource.
"""
def getLastLink(self):
"""
Return the SupplyLink representing the last ridge of the
SupplyChain (if this one is correctly defined...).
"""
def getNextSupplyLinkList(self, current_supply_link):
"""
Return the previous SupplyLink list.
"""
def getNextProductionSupplyLinkList(self, current_supply_link):
"""
Return the next SupplyLink which represents a production,
if there is one.
No recursion is done.
"""
def getNextProductionIndustrialPhaseList(self, current_supply_link):
"""
Return all next industrial phase representing a production.
"""
def getPreviousSupplyLinkList(self, current_supply_link):
"""
Return the previous SupplyLink list.
"""
def getPreviousProductionSupplyLinkList(self, current_supply_link,
"""
Return the previous SupplyLink which represents a production.
If recursive=1, browse the SupplyChain until a valid link is found.
checked_link_list is used to prevent infinite loop.
"""
def getPreviousPackingListSupplyLinkList(self, current_supply_link,
"""
Return the previous SupplyLink which represents a production.
If recursive=1, browse the SupplyChain until a valid link is found.
checked_link_list is used to prevent infinite loop.
"""
def getPreviousIndustrialPhaseList(self, current_supply_link, method_id,
"""
Return recursively all previous industrial phase.
"""
def getPreviousProductionIndustrialPhaseList(self, current_supply_link,
"""
Return recursively all previous industrial phase representing
a production.
"""
def getPreviousPackingListIndustrialPhaseList(self, current_supply_link):
"""
Return recursively all previous industrial phase representing
a packing list.
"""
def test(self, current_supply_link, movement):
"""
Test if the resource on the movement can be delivered by
the previous supply link of the current one.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/SimulationMovement.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class SimulationMovement(Movement):
"""
Simulation movements belong to a simulation workflow which includes
the following steps
- planned
- ordered
- confirmed (the movement is now confirmed in qty or date)
- started (the movement has started)
- stopped (the movement is now finished)
- delivered (the movement is now archived in a delivery)
The simulation worklow uses some variables, which are
set by the template
- is_order_required
- is_delivery_required
XX
- is_problem_checking_required ?
Other flag
(forzen flag)
NEW: we do not use DCWorklow so that the simulation process
can be as much as possible independent of a Zope / CMF implementation.
"""
def tpValues(self) :
""" show the content in the left pane of the ZMI """
def getPrice(self, default=None, context=None, REQUEST=None, **kw):
"""
"""
def getCausalityState(self):
"""
Returns the current state in causality
"""
def setCausalityState(self, value):
"""
Change causality state
"""
def getSimulationState(self, id_only=1):
"""
Returns the current state in simulation
Inherit from order or delivery or parent (but use a conversion
table to make orders planned when parent is confirmed)
XXX: movements in zero stock rule can not acquire simulation state
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Some Simulation movement corresponds to non accountable movements,
the parent applied rule decide wether this movement is accountable
or not.
"""
def requiresOrder(self):
"""
Returns 1 if this needs to be ordered
"""
def requiresDelivery(self):
"""
Returns 1 if this needs to be accounted
"""
def expand(self, force=0, **kw):
"""
Checks all existing applied rules and make sure they still apply.
Checks for other possible rules and starts expansion process (instanciates
applied rules and calls expand on them).
First get all applicable rules,
then, delete all applied rules that no longer match and are not linked to
a delivery,
finally, apply new rules if no rule with the same type is already applied.
"""
def diverge(self):
"""
-> new status -> diverged
Movements which diverge can not be expanded
"""
def getExplanation(self):
"""Returns the delivery's relative_url if any or the order's
relative_url related to the root applied rule if any.
"""
def getExplanationUid(self):
"""Returns the delivery's uid if any or the order's uid related to
the root applied rule if any.
"""
def getExplanationValue(self):
"""Returns the delivery if any or the order related to the root
applied rule if any.
"""
def isOrderable(self):
def isDeliverable(self):
def getOrderStartDate(self):
def getOrderStopDate(self):
def getDeliveryStartDateList(self):
"""
Returns the stop date of related delivery
"""
def getDeliveryStopDateList(self):
"""
Returns the stop date of related delivery
"""
def getDeliveryQuantity(self):
"""
Returns the quantity of related delivery
"""
def isConvergent(self):
"""
Returns true if the Simulation Movement is convergent with the
the delivery value
"""
def isDivergent(self):
"""
Returns true if the Simulation Movement is divergent from the
the delivery value
"""
def getDivergenceList(self):
"""
Returns detailed information about the divergence
"""
def getSolverList(self):
"""
Returns solvers that can fix the current divergence
"""
def setDefaultDeliveryProperties(self):
"""
Sets the delivery_ratio and delivery_error properties to the
calculated value
"""
def getCorrectedQuantity(self):
"""
Returns the quantity property deducted by the possible profit_quantity
"""
def getRootSimulationMovement(self):
"""
Return the root simulation movement in the simulation tree.
FIXME : this method should be called getRootSimulationMovementValue
"""
def getRootSimulationMovementUid(self):
"""
Return the uid of the root simulation movement in the simulation tree.
"""
def getRootCausalityValueList(self):
"""
Returns the initial causality value for this movement.
This method will look at the causality and check if the
causality has already a causality
"""
def _isTreeDelivered(self, ignore_first=0):
"""
checks if subapplied rules of this movement (going down the complete
simulation tree) have a child with a delivery relation.
Returns True if at least one is delivered, False if none of them are.
see AppliedRule._isTreeDelivered
"""
def getTreeDelivered(movement, ignore_first=0):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/LeavePeriod.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class LeavePeriod(PresencePeriod):
"""
Leave Period is used to remove available time of the user in a
period of Time
"""
def getInventoriatedQuantity(self, default=None, *args, **kw):
"""
Surcharged accessor to calculate the Quantity in second.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/VariationImage.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class VariationImage(Image, Variation):
"""
A Variation combinated with a image
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PortalTest.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PortalTest(MappedValue, XMLMatrix):
"""
Container for test descriptions (funtionnal test scenarii,...).
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ExternalSource.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ExternalSource(XMLObject, UrlMixIn):
"""
An External Source consists of single URL which defines the
root of a collection of documents, each of which can be accessed
individually. The URL can be an http site, an ftp site, a local repository,
a samba server, etc.
The main purpose of External Sources is to group related documents
and define shared security policies, shared updated policies, etc.
For example, all pages of
a wiki with restricted access rights share the same security policy
(ex. team, project, etc.). Another purpose of the External Source class is
to make it easy to manage external sources of knowledge (adding them,
removing them, etc.).
The second purpose of an external source is to provide a way to search
contents stored externally in a system which is not compatible with
ERP5 Catalog.
Example of external sources:
- a Web Site
- a SAMBA share
- an FTP server
- a backup server
- a mail directory
- a mailing list archive
ExternalSource may be subclassed to provide more automation
features. This is useful for example to manage the creation
of a mailing list, the deletion of mailing list and the
definition of the members of a mailing list in a centralised way.
NOTE: RSS feeds are not external sources but standard Text
documents with transformation and update policy. They use
the populateContent method to create subcontent from
a root content. This is different with crawling.
NOTE2: access to filesystems through URL requires to extend
urllib2 so that directories are handled as if they were web
pages OR RSS feed with a list of files (and associated URL).
Complete implemetation of external sources will require
major extensions to urllib2 (or equivalent).
NOTE3: it is possible to make external search sources persistent
by triggering an activity with newContent for every displayed
result. This can be done by wrapping the results in a generator
(yield). The interest of this approach is to make it possible to
search already searched contents without having to go through the
external source search (ie. with the front page search).
"""
def crawlContent(self):
"""
Creates the initial content from the URL by crawling the root
"""
def getContentURLList(self):
"""
Returns the root of the crawling process
"""
def getContentBaseURL(self):
"""
Returns None to force crawler to ignore this parameter
"""
def isIndexContent(self, content=None):
"""
This method is able to answer a content object if it is an index or a
"real" content. Sometimes (though not often) we want to define a content
as index (e.g. if it is only a list of mailing list messages), so that we
do not index it for searching etc). Default implementation returns
False.
"""
def searchResults(self, **kw):
"""
Search results. There is no notion of security here since
the source is external.
NOTE: implementation is delegated to a script so that different
kinds of sources may be implemented using different portal
types.
NOTE2: a typical implementation consists in creating
a specific SQL method with a dedicated connector then
force the SQL catalog to use that method instead of the standard
ones, yet delegate the SQL generation to the catalog.
"""
def countResults(self, **kw):
"""
Count results. There is no notion of security here since
the source is external.
NOTE: implementation is delegated to a script so that different
kinds of sources may be implemented using different portal
types.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Wiki.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Wiki( Document ):
"""
A simple Wiki document. A Wiki page may contain
subobjects (File, Image, etc.) just like any text
based Document.
"""
def _getTopLevelUrl(self):
def _render_text(self, text):
"""
Render a piece of text.
"""
def _render_tales(self, expr):
"""
Evaluate the expression.
FIXME
"""
def _render_table_row(self, text):
"""
Render a row of a table.
"""
def render(self, content=None, format=None):
"""
Render the contents and generate HTML.
FIXME: Very dirty. Better to rewrite this with a state machine.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PropertyDivergenceTester.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PropertyDivergenceTester(XMLObject):
"""
The purpose of this divergence tester is to check the
consistency between delivery movement and simulation movement
for some specific properties.
"""
def test(self, simulation_movement):
"""
This is the fast method to test, return True or False.
It depends if the simulation_movement is divergent or not.
"""
def explain(self, simulation_movement):
"""
This method returns a list of messages that contains
the divergence of the Delivery Line.
"""
def _splitStringList(self, string_list):
"""
Convert a list of string with a pipe (ex: ["azert | qsdfg", ] )
to a list of tuple (ex: [("azert", "qsdfg"), ] )
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Order.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Order(Delivery):
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
def getTotalPrice(self, **kw) :
"""Returns the total price for this Order. """
def getTotalQuantity(self, **kw) :
"""Returns the total quantity for this Order. """
def applyToOrderRelatedMovement(self, portal_type='Simulation Movement', \
"""
Warning: does not work if it was not catalogued immediately
"""
def applyToOrderRelatedAppliedRule(self, method_id='expand',**kw):
def getOrderRelatedMovementList(self):
"""
Returns simulation movements related to a cell or line
of this order
"""
def manage_beforeDelete(self, item, container):
"""
Delete related Applied Rule
"""
def updateAppliedRule(self, rule_id=None, rule_reference=None, **kw):
"""XXX FIXME: Kept for compatibility.
updateAppliedRule must be called with a rule_reference in a workflow
script.
"""
def expandAppliedRuleRelatedToOrder(self, activate_kw=None,**kw):
"""
Expand the applied rule related
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/ImmobilisationCell.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class ImmobilisationCell(Movement, XMLObject, ImmobilisationMovement):
"""
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/Ticket.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Ticket(Movement, Project):
"""
A Ticket allows to track a sales process involving
multilple Person and Organisations. It is a placeholder for
documents, events, etc.
Tickets behave both a movements and as projects:
- as movements because they relate to an amount
of resource exchanged between multiple parties
- as a project because it acts as a reporting
node for other movements (ex. accounting,
task reports)
Ticket are a good example of documents which may require
synchronisation process accross multiple sites and
for which acquisition properties such as source_title
may be useful to provide a simple way to synchronise
data with relations.
"""
def isAccountable(self):
"""
Returns 1 if this needs to be accounted
Only account movements which are not associated to a delivery
Whenever delivery is there, delivery has priority
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/OrderLine.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class OrderLine(DeliveryLine):
"""
A order line defines quantity and price
"""
def hasLineContent(self):
"""Return true if the object contains lines.
We cache results in a volatile variable.
"""
def applyToOrderLineRelatedMovement(self, portal_type='Simulation Movement',
"""
Warning: does not work if it was not catalogued immediately
"""
def getSimulationQuantity(self):
"""
Computes the target quantities in the simulation
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/PaymentCondition.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class PaymentCondition(XMLObject):
"""
Payment Conditions are used to define all the parameters of a payment
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5/Document/DependentCapacity.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class DependentCapacity(Capacity):
"""
Dependent Capacity allows to select a group of resources
and attach a quantity to it
"""
def asCapacityItemList(self):
"""
Returns an association list of points and capacity values
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Catalog/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Catalog/Document/Archive.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Archive(Predicate):
"""
A Catalog Archive object
It defines the date of the archive and the catalog to use
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Form/Document/Preference.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class Priority:
""" names for priorities """
class Preference( Folder ):
"""
A system or user preference
TODO:
- migrate to ERP5Type the whole preference system
"""
def _clearCache(self):
"""Clear caches used by methods of this preference
# TODO: clear different caches according to the preference priority
# TODO: (XXX) currently, if one use enables / disables a cache, caches
for all other users are reset. This is not good for a system
in which users do a lot of preference validation. A better solution
is needed for this. But it is not easy because the concept of
"per user cache" has been proven to be ambiguous or useless.
In theory, a solution could consist in using more keys to
select caches or to delete "manually" certain cache keys.
"""
def _edit(self, **kw):
"""edit and clear all caches"""
def enable(self):
"""Workflow method"""
def disable(self):
"""Workflow method"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Form/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Modeling/Document/ModelingTemplate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
"""
Description
"""
class ModelingTemplate(Folder):
def addClassesFromDict(self, dict):
""" Create Class Modeling from dictionary """
def addWorkflowsFromDict(self, dict):
""" Create Workflow Template from dictionary """
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Modeling/Document/StateTemplate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
"""
Description
"""
class StateTemplate(Folder):
# def addStateFromDict(self,dict):
# """ Create State from dictionary """
# def addClassMethodFromDict(self,dict):
# """ Create Attribute from dictionary """
# initial_code = """\"\"\" ERP5Gen Genereted \"\"\"
# pass """
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Modeling/Document/AttributeTemplate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
"""
Description
"""
class AttributeTemplate(XMLObject):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Modeling/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Modeling/Document/ClassTemplate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
"""
Description
"""
class ClassTemplate(Folder):
def addAttributeFromDict(self,dict):
""" Create Attribute from dictionary """
def addClassMethodFromDict(self,dict):
""" Create Attribute from dictionary """
initial_code = """\"\"\" ERP5Gen Genereted \"\"\"
pass """
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Modeling/Document/ClassMethodTemplate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
"""
Description
"""
class ClassMethodTemplate(XMLObject):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Modeling/Document/TransitionTemplate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
"""
Description
"""
class TransitionTemplate(Folder):
# def addStateFromDict(self,dict):
# """ Create State from dictionary """
# def addClassMethodFromDict(self,dict):
# """ Create Attribute from dictionary """
# initial_code = """\"\"\" ERP5Gen Genereted \"\"\"
# pass """
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Modeling/Document/WorkflowTemplate.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
"""
Description
"""
class WorkflowTemplate(Folder):
def addStateFromDict(self,dict):
"""
Create State from dictionary
"""
# def addClassMethodFromDict(self,dict):
# """ Create Attribute from dictionary """
# initial_code = """\"\"\" ERP5Gen Genereted \"\"\"
# pass """
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5OOo/Document/OOoDocument.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
class TimeoutTransport(SafeTransport):
"""A xmlrpc transport with configurable timeout.
"""
def __init__(self, timeout=None, scheme='http'):
def send_content(self, connection, request_body):
def make_connection(self, h):
class OOoDocument(File, ConversionCacheMixin):
"""
A file document able to convert OOo compatible files to
any OOo supported format, to capture metadata and to
update metadata in OOo documents.
This class can be used:
- to create an OOo document database with powerful indexing (r/o)
and metadata handling (r/w) features (ex. change title in ERP5 ->
title is changed in OOo document)
- to massively convert MS Office documents to OOo format
- to easily keep snapshots (in PDF and/or OOo format) of OOo documents
generated from OOo templates
This class may be used in the future:
- to create editable OOo templates (ex. by adding tags in WYSIWYG mode
and using tags to make document dynamic - ask kevin for more info)
- to automatically sign / encrypt OOo documents based on user
- to automatically sign / encrypt PDF generated from OOo documents based on user
This class should not be used:
- to store files in formats not supported by OOo
- to stored pure images (use Image for that)
- as a general file conversion system (use portal_transforms for that)
TODO:
- better permissions
"""
def isSupportBaseDataConversion(self):
"""
OOoDocument is needed to conversion to base format.
"""
def _setFile(self, data, precondition=None):
def index_html(self, REQUEST, RESPONSE, format=None, display=None, **kw):
"""
Default renderer with conversion support. Format is
a string. The list of available formats can be obtained
by calling getTargetFormatItemList.
"""
def _getServerCoordinate(self):
"""
Returns the oood conversion server coordinates
as defined in preferences.
"""
def _mkProxy(self):
"""
Create an XML-RPC proxy to access the conversion server.
"""
def getTargetFormatItemList(self):
"""
Returns a list of acceptable formats for conversion
in the form of tuples (for listfield in ERP5Form)
NOTE: it is the responsability of the conversion server
to provide an extensive list of conversion formats.
"""
def cached_getTargetFormatItemList(content_type):
def getTargetFormatTitleList(self):
"""
Returns a list of acceptable formats for conversion
"""
def getTargetFormatList(self):
"""
Returns a list of acceptable formats for conversion
"""
def isTargetFormatAllowed(self, format):
"""
Checks if the current document can be converted
into the specified target format.
"""
def _convert(self, format):
"""
Communicates with server to convert a file
"""
def convert(self, format, display=None, **kw):
"""Convert the document to the given format.
If a conversion is already stored for this format, it is returned
directly, otherwise the conversion is stored for the next time.
"""
def asTextContent(self):
"""
Extract plain text from ooo docs by stripping the XML file.
This is the simplest way, the most universal and it is compatible
will all formats.
"""
def populateContent(self, zip_file=None):
"""
Extract content from the ODF zip file and populate the document.
Optional parameter zip_file prevents from converting content twice.
"""
def hasBaseData(self):
"""
OOo instances implement conversion to a base format. We should therefore
use the default accessor.
"""
def _convertToBaseFormat(self):
"""
Converts the original document into ODF
by invoking the conversion server. Store the result
on the object. Update metadata information.
"""
def getContentInformation(self):
"""
Returns the metadata extracted by the conversion
server.
"""
def updateBaseMetadata(self, **kw):
"""
Updates metadata information in the converted OOo document
based on the values provided by the user. This is implemented
through the invocation of the conversion server.
"""
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5OOo/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Subversion/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5SyncML/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red">ERP5Type/Document/__init__.py</li>
<ul style="list-style:none"> <li style="color: blue"><pre>
def newTempBase(folder, id, REQUEST=None, **kw):
</pre></li></ul></li></ul>
<ul style="list-style:none">
<li style="color: red"></li>
<ul style="list-style:none"> <li style="color: blue"><pre>
<html><body>