Commit c011f208 authored by Romain Courteaud's avatar Romain Courteaud

As Jerome rewrote Simulation part of Accounting, some methods can be removed.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@3480 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent d0b78a7d
...@@ -39,187 +39,8 @@ from Acquisition import Explicit, Implicit ...@@ -39,187 +39,8 @@ from Acquisition import Explicit, Implicit
from Products.PythonScripts.Utility import allow_class from Products.PythonScripts.Utility import allow_class
from DateTime import DateTime from DateTime import DateTime
# XXX FIXME: to be deleted
from Products.ERP5Type.XMLMatrix import TempXMLMatrix
from Products.ERP5.MovementGroup import OrderMovementGroup, PathMovementGroup
from Products.ERP5.MovementGroup import DateMovementGroup, ResourceMovementGroup
from Products.ERP5.MovementGroup import VariantMovementGroup, RootMovementGroup
from zLOG import LOG from zLOG import LOG
# XXX FIXME: to be deleted
class TempDeliveryCell(DeliveryCell):
def getPrice(self):
return self.price
def _setPrice(self, value):
self.price = value
def getQuantity(self):
return self.quantity
def _setQuantity(self, value):
self.quantity = value
def reindexObject(self, *args, **kw):
pass
def activate(self):
return self
# XXX FIXME: to be deleted
class XMLMatrix(TempXMLMatrix):
def newCellContent(self, id,**kw):
"""
If you delete this method, please check the code of the method
ERP5/Document/InventoryLine.newCellContent() and delete it.
If nothing has changed from the date I wrote this comment, the
behaviour of InventoryLine will be the same without
InventoryLine.newCellContent(), because Inventory line is a subclass
of Delivery which is a subclass of XMLMatrix (Kev).
"""
new_temp_object = TempDeliveryCell(id)
self._setObject(id, new_temp_object)
return self.get(id)
# XXX FIXME: to be deleted
class Group(Implicit):
"""
Hold movements which have the same resource and the same variation.
"""
# Declarative security
security = ClassSecurityInfo()
#security.declareObjectProtected(Permissions.View)
security.declareObjectPublic()
# These get methods are workarounds for the Zope security model.
security.declareProtected(Permissions.AccessContentsInformation, 'getMovementList')
def getMovementList(self):
return self.movement_list
security.declareProtected(Permissions.AccessContentsInformation, 'getResourceId')
def getResourceId(self):
return self.resource_id
security.declareProtected(Permissions.AccessContentsInformation, 'getResourceTitle')
def getResourceTitle(self):
return self.resource_title
security.declareProtected(Permissions.AccessContentsInformation, 'getVariationBaseCategoryList')
def getVariationBaseCategoryList(self):
return list(self.variation_base_category_list)
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalPrice')
def getTotalPrice(self):
return self.total_price
security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity')
def getTotalQuantity(self):
return self.total_quantity
security.declareProtected(Permissions.AccessContentsInformation, 'getMatrix')
def getMatrix(self):
return self.matrix
def __init__(self, movement):
self.movement_list = []
#self.quantity_unit = movement.getQuantityUnit() # This is likely an error JPSforYO
resource_value = movement.getResourceValue()
if resource_value is not None:
self.quantity_unit = resource_value.getDefaultQuantityUnit()
else:
self.quantity_unit = movement.getQuantityUnit() # Meaningless XXX ?
self.resource = movement.getResource()
self.resource_id = movement.getResourceId()
self.resource_title = movement.getResourceTitle()
self.variation_base_category_list = movement.getVariationBaseCategoryList()
self.variation_category_list = []
# self.total_price = movement.getTotalPrice() # This is likely an error JPSforYO
# self.total_quantity = movement.getTotalQuantity() # This is likely an error JPSforYO
self.total_price = 0.0 # No need to add twice since we add it in append
self.total_quantity = 0.0 # No need to add twice since we add it in append
self.matrix = XMLMatrix(None)
self.append(movement)
def test(self, movement):
# Use resource rather than resource_id JPSforYO
if movement.getResource() == self.resource and \
movement.getVariationBaseCategoryList() == self.variation_base_category_list:
return 1
else:
return 0
def append(self, movement):
if not movement in self.movement_list:
self.movement_list.append(movement)
price = movement.getTotalPrice()
if price is not None:
self.total_price += price # XXX Something should be done wrt to currency
# If one order has beed negociated in USD and anotehr in EUR, then there is no
# way to merge invoices. Multiple invoices must be produced
# This may require serious extensions to this code
# ie. N deliveries result in M invoices (1 invoice per currency)
#self.total_quantity += movement.getTotalQuantity() # This is likely an error JPSforYO
self.total_quantity += movement.getInventoriatedQuantity()
for category in movement.getVariationCategoryList():
if category not in self.variation_category_list:
self.variation_category_list.append(category)
def finish(self):
# Make up a list of cell ranges for setCellRange.
cell_range_list = []
for base_category in self.variation_base_category_list:
cell_range = []
for movement in self.movement_list:
for category in movement.getCategoryMembershipList(base_category, base=1):
if not category in cell_range:
cell_range.append(category)
cell_range_list.append(cell_range)
kw_list = {'base_id' : 'movement'}
apply(self.matrix._setCellRange, cell_range_list, kw_list)
# Add every movement into the matrix.
for movement in self.movement_list:
# Make sure that the order of the category lists is preserved.
point = []
for base_category in self.variation_base_category_list:
point += movement.getCategoryMembershipList(base_category, base=1)
cell = apply(self.matrix.getCell, point, kw_list)
if cell is None:
cell = apply(self.matrix.newCell, point, kw_list)
cell.setMappedValuePropertyList(['price', 'quantity'])
cell._setPrice(movement.getPrice())
cell._setQuantity(movement.getQuantity())
else:
quantity = movement.getQuantity()
if quantity:
cell._setPrice(movement.getPrice() * quantity + cell.getPrice()) # Accumulate total price
cell._setQuantity(quantity + cell.getQuantity()) # Accumulate quantity
# Normalize price to compute unit price
for cell in self.matrix.getCellValueList():
quantity = cell.getQuantity()
if quantity:
cell._setPrice(cell.getPrice() / float(quantity))
else:
cell._setPrice(0.0) # if quantity is zero, price is et to 0.0 as a convention
# Normalize self price also JPSforYO
quantity = self.total_quantity
if quantity:
self.price = self.total_price / float(quantity)
else:
self.price = 0.0
#LOG('Group', 0, repr(self.total_price), repr(self.total_quantity))
InitializeClass(Group)
#allow_class(Group)
class Delivery(XMLObject): class Delivery(XMLObject):
""" """
Each time delivery is modified, it MUST launch a reindexing of Each time delivery is modified, it MUST launch a reindexing of
...@@ -257,180 +78,6 @@ class Delivery(XMLObject): ...@@ -257,180 +78,6 @@ class Delivery(XMLObject):
""" """
return 1 return 1
# XXX FIXME: to be deleted
security.declareProtected(Permissions.ModifyPortalContent, 'buildInvoiceList')
def buildInvoiceList(self):
"""
Retrieve all invoices lines into the simulation
"""
reindexable_movement_list = []
parent_simulation_line_list = []
for o in self.objectValues():
parent_simulation_line_list += [x for x in o.getDeliveryRelatedValueList() \
if x.getPortalType()=='Simulation Movement']
invoice_rule_list = []
simulation_invoice_line_list = []
for o in parent_simulation_line_list:
for rule in o.objectValues():
invoice_rule_list.append(rule)
simulation_invoice_line_list += rule.objectValues()
#LOG('buildInvoiceList simulation_invoice_line_list',0,simulation_invoice_line_list)
from Products.ERP5.MovementGroup import OrderMovementGroup
from Products.ERP5.MovementGroup import PathMovementGroup
from Products.ERP5.MovementGroup import DateMovementGroup
from Products.ERP5.MovementGroup import ResourceMovementGroup
from Products.ERP5.MovementGroup import VariantMovementGroup
#class_list = [OrderMovementGroup,PathMovementGroup,DateMovementGroup,ResourceMovementGroup,VariantMovementGroup]
class_list = [OrderMovementGroup,PathMovementGroup,DateMovementGroup,ResourceMovementGroup]
root_group = self.portal_simulation.collectMovement(simulation_invoice_line_list,class_list=class_list)
invoice_list = []
#LOG('buildInvoiceList root_group',0,root_group)
if root_group is not None:
#LOG('buildInvoiceList root_group.group_list',0,root_group.group_list)
for order_group in root_group.group_list:
#LOG('buildInvoiceList order_group.order',0,order_group.order)
if order_group.order is not None:
# Only build if there is not order yet
#LOG('buildInvoiceList order_group.group_list',0,order_group.group_list)
for path_group in order_group.group_list :
invoice_module = self.accounting
invoice_type = 'Sale Invoice Transaction'
invoice_line_type = 'Invoice Line'
#LOG('buildInvoiceList path_group.group_list',0,path_group.group_list)
for date_group in path_group.group_list :
invoice = invoice_module.newContent(portal_type = invoice_type,
start_date = date_group.start_date,
stop_date = date_group.stop_date,
source = path_group.source,
destination = path_group.destination,
source_section = path_group.source_section,
destination_section = path_group.destination_section,
causality_value = self,
title = self.getTitle(),
description = 'Invoice related to the Delivery %s' % self.getTitle())
# the new invoice is added to the invoice_list
invoice_list.append(invoice)
#for rule in invoice_rule_list : rule.setDeliveryValue(invoice) # This looks strange. Is it okay to do this ?
for resource_group in date_group.group_list :
#LOG('buildInvoiceList resource_group.group_list',0,resource_group.group_list)
# Create a new Sale Invoice Transaction Line for each resource
invoice_line = invoice.newContent(
portal_type=invoice_line_type
, resource=resource_group.resource)
# line_variation_category_list = []
# line_variation_base_category_dict = {}
# compute line_variation_base_category_list and
# line_variation_category_list for new delivery_line
# for variant_group in resource_group.group_list :
# for variation_item in variant_group.category_list :
# if not variation_item in line_variation_category_list :
# line_variation_category_list.append(variation_item)
# variation_base_category_items = variation_item.split('/')
# if len(variation_base_category_items) > 0 :
# line_variation_base_category_dict[variation_base_category_items[0]] = 1
# update variation_base_category_list and line_variation_category_list for delivery_line
# line_variation_base_category_list = line_variation_base_category_dict.keys()
# invoice_line.setVariationBaseCategoryList(line_variation_base_category_list)
# invoice_line.setVariationCategoryList(line_variation_category_list)
# IMPORTANT : invoice cells are automatically created during setVariationCategoryList
#XXX for now, we quickly need this working, without the need of variant_group
object_to_update = invoice_line
# compute quantity and price for invoice_cell or invoice_line and
# build relation between simulation_movement and invoice_cell or invoice_line
if object_to_update is not None :
quantity = 0
total_price = 0
for movement in resource_group.movement_list :
quantity += movement.getConvertedQuantity()
try :
total_price += movement.getNetConvertedQuantity() * movement.getPrice() # XXX WARNING - ADD PRICED QUANTITY
except :
total_price = None
# What do we really need to update in the simulation movement ?
if movement.getPortalType() == 'Simulation Movement' :
movement._setDeliveryValue(object_to_update)
reindexable_movement_list.append(movement)
if quantity <> 0 and total_price is not None:
average_price = total_price/quantity
else :
average_price = 0
#LOG('buildInvoiceList edit', 0, repr(( object_to_update, quantity, average_price, )))
object_to_update.edit(quantity = quantity,
price = average_price)
# update quantity and price for each invoice_cell
#XXX for variant_group in resource_group.group_list :
if 0 :
#LOG('Variant_group examin',0,str(variant_group.category_list))
object_to_update = None
# if there is no variation of the resource, update invoice_line with quantities and price
if len(variant_group.category_list) == 0 :
object_to_update = invoice_line
# else find which invoice_cell is represented by variant_group
else :
categories_identity = 0
#LOG('Before Check cell',0,str(invoice_cell_type))
#LOG('Before Check cell',0,str(invoice_line.contentValues()))
for invoice_cell in invoice_line.contentValues(filter={'portal_type':'Invoice Cell'}) :
#LOG('Check cell',0,str(invoice_cell))
#LOG('Check cell',0,str(variant_group.category_list))
if len(variant_group.category_list) == len(invoice_cell.getVariationCategoryList()) :
#LOG('Parse category',0,str(invoice_cell.getVariationCategoryList()))
for category in invoice_cell.getVariationCategoryList() :
if not category in variant_group.category_list :
#LOG('Not found category',0,str(category))
break
else :
categories_identity = 1
if categories_identity :
object_to_update = invoice_cell
break
# compute quantity and price for invoice_cell or invoice_line and
# build relation between simulation_movement and invoice_cell or invoice_line
if object_to_update is not None :
cell_quantity = 0
cell_total_price = 0
for movement in variant_group.movement_list :
cell_quantity += movement.getConvertedQuantity()
try :
cell_total_price += movement.getNetConvertedQuantity() * movement.getPrice() # XXX WARNING - ADD PRICED QUANTITY
except :
cell_total_price = None
# What do we really need to update in the simulation movement ?
if movement.getPortalType() == 'Simulation Movement' :
movement._setDeliveryValue(object_to_update)
reindexable_movement_list.append(movement)
if cell_quantity <> 0 and cell_total_price is not None:
average_price = cell_total_price/cell_quantity
else :
average_price = 0
#LOG('buildInvoiceList edit', 0, repr(( object_to_update, cell_quantity, average_price, )))
object_to_update.edit(quantity = cell_quantity,
price = average_price)
# we now reindex the movements we modified
for movement in reindexable_movement_list :
movement.immediateReindexObject()
return invoice_list
# Pricing methods # Pricing methods
def _getTotalPrice(self, context): def _getTotalPrice(self, context):
return 2.0 return 2.0
...@@ -784,164 +431,6 @@ class Delivery(XMLObject): ...@@ -784,164 +431,6 @@ class Delivery(XMLObject):
kw['category'] = self._getMovementResourceList() kw['category'] = self._getMovementResourceList()
return self.portal_simulation.getMovementHistoryStat(**kw) return self.portal_simulation.getMovementHistoryStat(**kw)
# XXX FIXME: to be deleted
security.declareProtected(Permissions.AccessContentsInformation, 'collectMovement')
def collectMovement(self, movement_list):
"""
Collect all movements into a list of group objects.
"""
from Globals import InitializeClass
# Collect each delivery cell into a delivery line.
group_list = []
for movement in movement_list:
movement_in_group = 0
for group in group_list:
if group.test(movement):
group.append(movement)
movement_in_group = 1
break
if not movement_in_group:
group_list.append(Group(movement).__of__(self))
# This is required to build a matrix.
for group in group_list:
group.finish()
return group_list
# XXX FIXME: to be deleted
security.declareProtected(Permissions.AccessContentsInformation, 'buildInvoiceLineList')
def buildInvoiceLineList(self, movement_group):
"""
Build invoice lines from a list of movements.
"""
invoice_line_list = []
if movement_group is not None:
for group in movement_group:
# Create each invoice_line in the new invoice
# but only if quantity > 0
if group.total_quantity > 0 :
invoice_line = self.newContent(portal_type = 'Invoice Line',
resource = group.resource,
quantity_unit = group.quantity_unit) # FIXME: more args
invoice_line_list.append(invoice_line)
# Make sure that the order is always preserved.
variation_base_category_list = list(group.variation_base_category_list)
variation_base_category_list.sort()
invoice_line.setVariationBaseCategoryList(variation_base_category_list)
#LOG('buildInvoiceLineList', 0, "group.variation_base_category_list = %s" % str(group.variation_base_category_list))
variation_category_list = []
for cell_key in group.matrix.getCellKeyList(base_id='movement'):
for variation_category in cell_key:
if variation_category not in variation_category_list:
variation_category_list.append(variation_category)
invoice_line.setVariationCategoryList(variation_category_list)
# IMPORTANT : delivery cells are automatically created during setVariationCategoryList
#LOG('buildInvoiceLineList', 0, "invoice_line.contentValues() = %s" % str(invoice_line.contentValues()))
if len(variation_category_list) > 0:
for invoice_cell in invoice_line.contentValues(filter={'portal_type':'Invoice Cell'}):
category_list = invoice_cell.getVariationCategoryList()
# XXX getVariationCategoryList does not return the same order as setVariationBaseCategoryList
point = []
for base_category in group.variation_base_category_list:
for category in category_list:
if category.startswith(base_category + '/'):
point.append(category)
break
kw_list = {'base_id' : 'movement'}
cell = apply(group.matrix.getCell, point, kw_list)
#LOG('buildInvoiceLineList', 0,
# "point = %s, cell = %s" % (str(point), str(cell)))
if cell is not None:
#LOG('buildInvoiceLineList', 0,
# "quentity = %s, price = %s" % (str(cell.getQuantity()), str(cell.getPrice())))
invoice_cell.edit(quantity = cell.getQuantity(),
price = cell.getPrice(),
force_update = 1)
else:
# There is no variation category.
invoice_line.edit(quantity = group.total_quantity,
price = group.price,
force_update = 1) # Use unit price JPSforYO
return invoice_line_list
# XXX FIXME: to be deleted
# Simulation consistency propagation
security.declareProtected(Permissions.ModifyPortalContent, 'updateFromSimulation')
def updateFromSimulation(self, update_target = 0):
"""
Update all lines of this transaction based on movements in the simulation
related to this transaction.
"""
# XXX update_target no more used
transaction_type = self.getPortalType()
line_type = transaction_type + " Line"
to_aggregate_movement_list = []
to_reindex_list = []
source_section = self.getSourceSection()
destination_section = self.getDestinationSection()
resource = self.getResource()
start_date = self.getStartDate()
def updateLineOrCell(c):
quantity = 0
source = c.getSource()
destination = c.getDestination()
for m in c.getDeliveryRelatedValueList():
m_source_section = m.getSourceSection()
m_destination_section = m.getDestinationSection()
m_resource = m.getResource()
m_start_date = m.getStartDate()
m_source = m.getSource()
m_destination = m.getDestination()
m_quantity = m.getCorrectedQuantity()
if m_source_section == source_section and m_destination_section == destination_section \
and m_resource == resource and m_start_date == start_date:
if m_source == source and m_destination == destination:
# The path is the same, only the quantity may have changed
if m_quantity:
quantity += m_quantity
else:
# Source and/or destination have changed. The Simulation Movement has
# to be linked to a new TransactionLine
m.setDelivery('')
to_aggregate_movement_list.append(m)
to_reindex_list.append(m)
else:
# Source_section and/or destination_section and/or date and/or resource differ
# The Simulation Movement has to be linked to a new Transaction (or an existing one)
m.setDelivery('')
to_aggregate_movement_list.append(m)
to_reindex_list.append(m)
# Recalculate delivery ratios for the remaining movements in this line
c.setQuantity(quantity)
c.updateSimulationDeliveryProperties()
# Update the transaction from simulation
for l in self.contentValues(filter={'portal_type':self.getPortalDeliveryMovementTypeList()}):
if l.hasCellContent():
for c in l.contentValues(filter={'portal_type':self.getPortalDeliveryMovementTypeList()}):
updateLineOrCell(c)
else:
updateLineOrCell(l)
# Re-aggregate the disconnected movements
# XXX Dirty ; it should use DeliveryBuilder when it will be available
if len(to_aggregate_movement_list) > 0:
applied_rule_type = to_aggregate_movement_list[0].getRootAppliedRule().getSpecialiseId()
if applied_rule_type == "default_amortisation_rule":
self.portal_simulation.buildDeliveryList( self.portal_simulation.collectMovement(to_aggregate_movement_list,
[ResourceMovementGroup, DateMovementGroup, PathMovementGroup] ) )
# Touch the Transaction to make an automatic converge
self.edit()
# XXX FIXME: to be deleted # XXX FIXME: to be deleted
security.declareProtected(Permissions.ModifyPortalContent, 'propagateResourceToSimulation') security.declareProtected(Permissions.ModifyPortalContent, 'propagateResourceToSimulation')
def propagateResourceToSimulation(self): def propagateResourceToSimulation(self):
...@@ -1155,4 +644,3 @@ class Delivery(XMLObject): ...@@ -1155,4 +644,3 @@ class Delivery(XMLObject):
LOG("ERP5 Error:", 100, LOG("ERP5 Error:", 100,
"Could not expand applied rule %s for delivery %s" %\ "Could not expand applied rule %s for delivery %s" %\
(applied_rule_id, self.getId())) (applied_rule_id, self.getId()))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment