Commit a5ebdf93 authored by Kevin Deldycke's avatar Kevin Deldycke

First commit


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@1481 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 2be48cec
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Kevin Deldycke <kevin@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.CMFCore.utils import getToolByName
from Acquisition import aq_base, aq_inner, aq_chain, aq_acquire
from xml.dom import implementation
from xml.dom.ext import PrettyPrint
from xml.dom import Node
import random
from cStringIO import StringIO
from zLOG import LOG
class ERP5ShopOrderConduit(ERP5Conduit):
"""
This conduit is used in the synchronisation process of Storever and ERP5 to convert
a Storever Shop Order to a ERP5 Sale Order.
"""
# TODO: tester ce script sur le serveur de backup (qui semble être different)
# Declarative security
security = ClassSecurityInfo()
# Initialize the random function
random.seed()
security.declareProtected(Permissions.ModifyPortalContent, 'constructContent')
def constructContent(self, object, object_id, docid, portal_type):
"""
This is a redefinition of the original ERP5Conduit.constructContent function to
allow the creation of a ERP5 Sale Order instead of a Storever Shop Order.
"""
portal_types = getToolByName(object, 'portal_types')
subobject = None
if portal_type == 'Shop Order':
# The random part of the id can be removed. It's only used for the developpement
new_object_id = 'storever-' + object_id + '-' + str(random.randint(1000, 9999))
object.newContent ( portal_type = 'Sale Order'
, id = new_object_id)
if portal_type == 'Order Line':
last_line_num = self.getLastOrderLineNumber(object)
new_object_id = "storever-" + str(last_line_num + 1) + "-" + object_id
object.newContent ( portal_type = 'Sale Order Line'
, id = new_object_id)
subobject = object._getOb(new_object_id)
return subobject
# # Not needed yet
# security.declareProtected(Permissions.ModifyPortalContent, 'addWorkflowNode')
# def addWorkflowNode(self, object, xml, simulate):
# """
# This is a redefinition of the original ERP5Conduit.addWorkflowNode function to
# allow the translation of a Storever Shop Order workflow to a ERP5 Sale Order one.
# """
# conflict_list = []
# status = self.getStatusFromXml(xml)
# # if status['action'] == 'ship':
# # status['time']
# return conflict_list
security.declarePrivate('dom2str')
def dom2str(self, xml_root=None):
"""
This function transform a DOM tree to string.
This function is only usefull for debugging.
"""
xml_str = StringIO()
PrettyPrint(xml_root, xml_str)
xml_string = xml_str.getvalue()
LOG('XML output: ', 0, xml_string)
return xml_string
security.declarePrivate('str2id')
def str2id(self, string=None):
"""
This function transform a string to a safe id.
It is also used here to create a safe category id from a string.
"""
out = ''
if string == None:
return None
string = string.lower()
# We ignore the discontinued information to allow the use of the same category
# even if the option is discontinued on the storever side
string = string.replace('discontinued', '')
string = string.strip()
# # TODO: manage accent
for char in string:
if char == '_' or char.isalnum():
pass
elif char.isspace() or char in ('+', '-'):
char = '_'
else:
char = None
if char != None:
out += char
# LOG('Category name output (using str2id) >>>>>>> ', 0, out)
return out
security.declarePrivate('countrySearch')
def countrySearch(self, site_root, category_path=None, country=None):
"""
This recursive function try to find the region category from the name of a country
"""
if category_path == None:
portal_categories = getToolByName(site_root, 'portal_categories')
categories_path = portal_categories.absolute_url(relative=1)
category_path = categories_path + '/region'
region_folder = site_root.restrictedTraverse(category_path)
for region_id in region_folder.objectIds():
region_path = category_path + '/' + region_id
splitted_path = region_path.split("/")
cat_region = "/".join(splitted_path[3:])
if region_id.lower() == country.lower():
return cat_region
find_path = self.countrySearch(site_root, region_path, country)
if find_path != None:
return find_path
return None
security.declarePrivate('createOrFindProduct')
def createOrFindProduct(self, erp5_site, erp5_product_id):
"""
This function try to find a previous product with the same id,
and create it if the search is unsuccessful
"""
erp5_site_path = erp5_site.absolute_url(relative=1)
product_path = erp5_site_path + '/product'
product_folder = erp5_site.restrictedTraverse(product_path)
# Try to find a previous product
for product_id in product_folder.objectIds():
if product_id == erp5_product_id:
return erp5_site.restrictedTraverse(erp5_site_path + '/product/' + erp5_product_id)
# We have to create a new product
product_folder.newContent ( portal_type = 'Product'
, id = erp5_product_id)
return product_folder._getOb(erp5_product_id)
security.declarePrivate('setProductWorkflow')
def setProductWorkflow(self, product_object, product_title):
"""
This function set the validation workflow to indicate if a product
is discontinued (workflow state = invalidate) or not (workflow state = validate)
"""
action = None
if hasattr(product_object, 'workflow_history'):
workflow_state = product_object.portal_workflow.getInfoFor(product_object, 'validation_state')
if product_title.lower().find('discontinued') != -1:
if workflow_state != 'invalidated':
action = 'invalidate_action'
elif workflow_state in ('draft', 'invalidated'):
action = 'validate_action'
if action != None:
product_object.portal_workflow.doActionFor( product_object
, action
, wf_id = 'validation_workflow')
security.declarePrivate('niceTitle')
def niceTitle(self, title):
"""
This function create a nice title without the discontinued information
"""
splitted_title = title.strip().split(" ")
nice_title = ''
for string in splitted_title:
if string.lower().find('discontinued') == -1:
nice_title += string + ' '
return nice_title.strip()
security.declarePrivate('getLastOrderLineNumber')
def getLastOrderLineNumber(self, order_object):
"""
This function give the number of the last Storever Shop Order Line processed
"""
# Scan existing order line id to get the last order line number
maximum_order_num = 0
for order_line_id in order_object.objectIds():
splitted_line_id = order_line_id.split("-")
current_line_num = int(splitted_line_id[1])
if current_line_num > maximum_order_num:
maximum_order_num = current_line_num
LOG('getLastOrderLineNumber return >>>>>>>> ', 0, repr(maximum_order_num))
return int(maximum_order_num)
# # Not needed yet because we prefer using my own owner_account_id property
# security.declareProtected(Permissions.ModifyPortalContent, 'addLocalRoleNode')
# def addLocalRoleNode(self, object, xml):
# """
# """
# conflict_list = []
# LOG('object >>>>>>>> ', 0, object)
# LOG('xml >>>>>>>> ', 0, self.dom2str(xml))
# return conflict_list
security.declareProtected(Permissions.ModifyPortalContent, 'editDocument')
def editDocument(self, object=None, **kw):
"""
This function use the properties of the object to convert a Storever ShopOrder to an ERP5 SaleOrder.
"""
if object == None:
return
LOG('KW >>>>>>>> ', 0, kw)
# Get the ERP5 root object
portal_types = getToolByName(object, 'portal_types')
erp5_site = portal_types.getPortalObject()
erp5_site_path = erp5_site.absolute_url(relative=1)
# The object is a ShopOrder
if kw.has_key('country'):
# Find the organisation and the person folder
person_path = erp5_site_path + '/person'
person_folder = erp5_site.restrictedTraverse(person_path)
organisation_path = erp5_site_path + '/organisation'
organisation_folder = erp5_site.restrictedTraverse(organisation_path)
# Find the service folder
service_path = erp5_site_path + '/service'
service_folder = erp5_site.restrictedTraverse(service_path)
# # TODO : if storever-id exist dans ERP5 --> prendre en charge l'update de la facture
# Get the id of the owner account in storever
owner_account_id = kw['owner_account_id']
# Set the id of the owner in ERP5 (the owner could be an Organisation or a Person)
owner_id = "storever-" + owner_account_id
# Try to find the identity created for a previous ShopOrder of the same Storever member account
person_object = None
organisation_object = None
for person_id in person_folder.objectIds():
if person_id == owner_id:
person_object = erp5_site.restrictedTraverse(erp5_site_path + '/person/' + person_id)
LOG("Previous person found ! >>>>>>>>",0,repr(person_object))
break
for organisation_id in organisation_folder.objectIds():
if organisation_id == owner_id:
organisation_object = erp5_site.restrictedTraverse(erp5_site_path + '/organisation/' + organisation_id)
LOG("Previous organisation found ! >>>>>>>>",0,repr(organisation_object))
break
# Define the previous customer structure
previous_owner_type = ''
if person_object != None:
previous_owner_type += 'p'
if organisation_object != None:
previous_owner_type += 'o'
if len(previous_owner_type) == 0:
previous_owner_type = None
LOG("Previous customer structure >>>>>>>>",0,repr(previous_owner_type))
# Try to know the type of the current storever customer
owner_type = ''
if kw.has_key('name') and kw['name'] not in (None, ''):
owner_type += 'p'
if kw.has_key('organisation') and kw['organisation'] not in (None, '', 'none'):
owner_type += 'o'
if kw.has_key('eu_vat') and kw['eu_vat'] not in (None, '') and owner_type.find('o') == -1:
owner_type += 'o'
if len(owner_type) == 0:
owner_type = None
LOG("Current customer structure >>>>>>>>",0,repr(owner_type))
# # TODO : in this part of the script, add the possibility to find an existing
# # ERP5 person/organisation according to the name of that person/organisation
# Compare the current representation of the member account with the previous one
if previous_owner_type != owner_type:
# There is difference between the two (previous and current) representation of the customer
# We have to manage the differences to create a unique customer representation
LOG("There is difference between previous and current >>>>>>>>",0,None)
if previous_owner_type == None:
# No previous customer found, create one
if owner_type.find('o') != -1:
organisation_folder.newContent ( portal_type = 'Organisation'
, id = owner_id)
organisation_object = organisation_folder._getOb(owner_id)
LOG("new organisation created >>>>>>>>",0,repr(organisation_object))
if owner_type.find('p') != -1:
person_folder.newContent ( portal_type = 'Person'
, id = owner_id)
person_object = person_folder._getOb(owner_id)
LOG("new person created >>>>>>>>",0,repr(person_object))
else:
if owner_type == None:
# Use the previous Structure
owner_type = previous_owner_type
LOG("Use the previous Structure >>>>>>>>",0,None)
else:
LOG("We have to convert the structure >>>>>>>>",0,None)
# # XXX Be aware of that problem: the invoice for a sale order must be the same
# Case to process :
# previous current
# o --> p
# o --> op
# p --> o
# op --> o
# op --> p
# p --> op - in progress
# The previous customer was detected as a person only
if previous_owner_type.find('p') != -1 and previous_owner_type.find('o') == -1:
# Case to process :
# previous current
# p --> o
# p --> op - in progress
# The customer has now an organisation, we have to create this organisation and link the person to
if owner_type.find('p') != -1 and owner_type.find('o') != -1:
# Create a new organisation
# # TODO : factorise this code with the same above
organisation_folder.newContent ( portal_type = 'Organisation'
, id = owner_id)
organisation_object = organisation_folder._getOb(owner_id)
else:
# # TODO : Transform a person to an organisation ? Is it a good idea ?
pass
# The previous customer was detected as an organisation only
elif previous_owner_type.find('p') == -1 and previous_owner_type.find('o') != -1:
# Case to process :
# previous current
# o --> p
# o --> op
pass
# The previous customer was detected as a person in an organisation
else:
# Case to process :
# previous current
# op --> o
# op --> p
pass
else:
if previous_owner_type == None or owner_type == None:
# There is not enough informations to know if the customer is an organisation or
# a person and there is no previous record
# By default, we consider the customer as a person, so we have to force to create one
owner_type = 'p'
person_folder.newContent ( portal_type = 'Person'
, id = owner_id)
person_object = person_folder._getOb(owner_id)
LOG("Create a person by default >>>>>>>>",0,repr(person_object))
else:
# The structure is the same
# We only need to be aware of data fusion between the previous and the current representation
# So we don't need to do something because the information fusion process take place below
LOG("The structure is the same. don't do anything >>>>>>>>",0,None)
pass
LOG("Person object >>>>>>>>",0,repr(person_object))
LOG("Organisation object >>>>>>>>",0,repr(organisation_object))
# Copy informations related to the customer in the ERP5 representation of the customer
# Be carefull because all informations from the storever ShopOrder are optionnals
if owner_type.find('p') != -1:
# Link the customer with the Sale Order
object.setDestination("person/" + owner_id)
object.setDestinationDecision("person/" + owner_id)
# # TODO : do the same things for each single information
# # TODO : before doing something working well in every case, copy the previou value in the comment field to traceback the modification and let me evaluate the solidity of my algorithm
# # TODO : perhaps it's possible to factorize the code using a generic function
# Synchronise the street address
if kw.has_key('address'):
previous_address = person_object.getDefaultAddressStreetAddress()
if len(previous_address) == 0:
person_object.setDefaultAddressStreetAddress(kw['address'].title())
elif previous_address.strip().lower() != kw['address'].strip().lower():
LOG('We have to make the fusion of previous address with the current one >>>>>>>', 0, None)
person_object.setDefaultAddressCity(kw['city'].title())
person_object.setDefaultAddressZipCode(kw['zipcode'])
# # TODO : set the person products interest (storever, etc)
# Search the country in the region category
if kw['country'] != None:
region_path = self.countrySearch(erp5_site, None, kw['country'])
if region_path != None:
person_object.setDefaultAddressRegion(region_path)
# else:
# # TODO : Ask the user to select an appropriate region
person_object.setDefaultEmailText(kw['email'])
person_object.setDefaultTelephoneText(kw['phone'])
# # TODO : Don't work
# person_object.setDefaultCareerRole("client")
# Split the name to give at least a required LastName
# Then the title will be automaticaly created by the Person object from this data
if kw.has_key('name') and kw['name'] != None:
splitted_name = kw['name'].strip().split(" ")
person_object.setLastName((splitted_name[-1]).title())
if len(splitted_name) > 1:
person_object.setFirstName((" ".join(splitted_name[:-1])).title())
else:
# We have to find a title to have something to show in the RelationField of the SaleOrderForm
person_object.setTitle(owner_account_id.title())
# The Person is subordinated to an Organisation ?
if owner_type.find('o') != -1:
# # TODO : fix this
# person_object.setSubordination("organisation/" + owner_id)
organisation_object.setTitle(kw['organisation'].title())
organisation_object.setCorporateName(kw['organisation'].title())
organisation_object.setRole("client")
if kw.has_key('eu_vat'):
organisation_object.setEuVatCode(kw['eu_vat'])
# The customer is not a person or a person of an organisation, so the customer is an organisation...
else:
# Link the customer with the Sale Order
object.setDestination("organisation/" + owner_id)
object.setDestinationDecision("organisation/" + owner_id)
# All informations describe the organisation
organisation_object.setTitle(kw['organisation'].title())
organisation_object.setCorporateName(kw['organisation'].title())
organisation_object.setRole("client")
organisation_object.setEuVatCode(kw['eu_vat'])
organisation_object.setDefaultAddressStreetAddress(kw['address'].title())
organisation_object.setDefaultAddressCity(kw['city'].title())
organisation_object.setDefaultAddressZipCode(kw['zipcode'])
# Search the country in the region category
if kw['country'] != None:
region_path = self.countrySearch(erp5_site, None, kw['country'])
if region_path != None:
organisation_object.setDefaultAddressRegion(region_path)
# else:
# # TODO : Ask the user to select an appropriate region
organisation_object.setDefaultEmailText(kw['email'])
organisation_object.setDefaultTelephoneText(kw['phone'])
# Save the billing address in the description, because there is no dedicated place for it
if kw.has_key('billing_address') and len(kw['billing_address']) > 0:
object.setDescription("Send the bill to : " + kw['billing_address'])
# Set the Title because its required
object.setTitle("Storever Order " + kw['order_id'])
# # ONLY for information (will be used in the future)
object.setDescription(str(object.getDescription()) + "\n\nTotal Price (with transport fees) :" + str(kw['total_price']))
# Add a new orderLine for the shipment
stor_ship_title = kw['send_fee_title'].strip()
erp5_ship_title = stor_ship_title + ' Shipment'
my_shipment_id = 'storever-' + self.str2id(stor_ship_title)
# Try to find an existing shipment service using several methods
shipment_id = None
for service_id in service_folder.objectIds():
service_object = erp5_site.restrictedTraverse(erp5_site_path + '/service/' + service_id)
# First method: compare the id with my standard layout
if service_id.strip() == my_shipment_id:
shipment_id = my_shipment_id
LOG("Service found with method 1 ! >>>>>>>>", 0, repr(shipment_id))
break
# Second method: use a standard title layout
if service_object.getTitle().lower().strip() == erp5_ship_title.lower().strip():
shipment_id = service_id
LOG("Service found with method 2 ! >>>>>>>>", 0, repr(shipment_id))
break
# Third method: compare words
erp5_ship_id_word_list = self.str2id(service_id).split("_")
stor_ship_id_word_list = self.str2id(stor_ship_title).split("_")
erp5_ship_title_word_list = self.str2id(erp5_ship_title).split("_")
erp5_ship_id_word_list.sort(lambda x, y: cmp(str(x), str(y)))
stor_ship_id_word_list.sort(lambda x, y: cmp(str(x), str(y)))
erp5_ship_title_word_list.sort(lambda x, y: cmp(str(x), str(y)))
if stor_ship_id_word_list in (erp5_ship_id_word_list, erp5_ship_title_word_list):
shipment_id = service_id
LOG("Service found with method 3 ! >>>>>>>>", 0, repr(shipment_id))
break
# No previous shipment service found, so create a new one
if shipment_id == None:
# TODO : implement the code here to follow the comment in the LOG below
LOG("We have to create the shipping service with this id >>>>>>>>", 0, repr(my_shipment_id))
# Create a new shipment service
shipment_id = my_shipment_id
# Get the object of the shipment service
# shipment_path = erp5_site_path + '/service/' + shipment_id
# shipment_object = erp5_site.restrictedTraverse(shipment_path)
# Create a new order line in this order to represent the shipment service
ship_order_line_id = "storever-" + shipment_id
object.newContent( portal_type = 'Sale Order Line'
, id = ship_order_line_id)
ship_order_object = object._getOb(ship_order_line_id)
ship_order_object.setQuantity(1.0)
ship_order_object.setPrice(kw['send_fee'])
ship_order_object.setQuantityUnit('Unit')
ship_order_object.setResource("service/" + shipment_id)
# The object is an OrderLine
else:
# Find the product folder
product_path = erp5_site_path + '/product'
product_folder = erp5_site.restrictedTraverse(product_path)
# Find the parent order object
parent_order_object = object.aq_parent
# Get the id of the product in storever
storever_product_id = kw['product_id']
# Set the id of the product in ERP5
erp5_product_id = "storever-" + storever_product_id
# Try to find a previous product or create a new one
product_object = self.createOrFindProduct(erp5_site, erp5_product_id)
# Create a nice title (without discontinued) from the product title
product_title = self.niceTitle(kw['product_title'])
# Synchronise every data
product_object.setDescription(kw['product_description'])
product_object.setTitle(product_title)
# # TODO : I don't know where to put this value,
# # because there is no "delivery days"-like property for a product
# product_object.setDeliveryDays(kw['product_delivery_days'])
if kw['product_expiration_date'] != None:
product_object.setSourceBasePriceValidity(kw['product_expiration_date'])
product_object.setBasePrice(kw['product_price'])
product_object.setQuantityUnit('Unit')
# Set the worflow status
self.setProductWorkflow(product_object, kw['product_title'])
# In storever, every option are set as string in the title of the OrderLine
# This part of code create a list of all options choosen by the customer for this product
splitted_title = kw['title'].strip().split(":")
option_list = (":".join(splitted_title[1:])).split("/")
LOG('Customer option list: ', 0, repr(option_list))
# Now, we will find the price of each option
option_classes = [ kw['product_disk_price']
, kw['product_memory_price']
, kw['product_option_price']
, kw['product_processor_price']
]
priced_list = {}
for option_item in option_list:
option = option_item.strip()
for option_class in option_classes:
for option_key in option_class.keys():
if option == option_key.strip():
priced_list[option] = option_class[option_key]
# # TODO : there is no default options in the final priced_list. Is the option 'default' important ?
LOG('Customer option priced list: ', 0, repr(priced_list))
# In ERP5, we have decided to represent some options as variation of a product
# and some options as new order line of product
# Now we will update or create the variation categories related to the initial product
# Don't forget to add this base categories in portal_category :
# 'hd_size', 'memory_size', 'optical_drive', 'keyboad_layout', 'cpu_type'
portal_cat = product_object.portal_categories
# Get all keyboard related options and all optical drive related options
keyboard_options = {}
optical_options = {}
options_prices = kw['product_option_price']
for option_key in options_prices.keys():
if option_key.lower().find("keyboard") != -1:
keyboard_options[option_key] = options_prices[option_key]
elif option_key.lower().find("cd") != -1 or option_key.lower().find("dvd") != -1:
optical_options[option_key] = options_prices[option_key]
LOG('Product keyboard layout priced list: ', 0, repr(keyboard_options))
LOG('Product optical drive priced list: ', 0, repr(optical_options))
# Create a data structure containing all allowed variations
variant_category_list = [ ('hd_size', kw['product_disk_price'])
, ('memory_size', kw['product_memory_price'])
, ('cpu_type', kw['product_processor_price'])
, ('optical_drive', optical_options)
, ('keyboad_layout', keyboard_options)]
# Create or update every category representing all variantions
base_cat_list = []
cat_list = []
for (cat_base, cat_data) in variant_category_list:
if len(cat_data) > 0 and portal_cat.resolveCategory(cat_base) != None:
base_cat_list.append(cat_base)
for disk_variant_key in cat_data.keys():
cat_id = self.str2id(disk_variant_key)
cat_path = cat_base + '/' + cat_id
cat_list.append(cat_path)
if portal_cat.resolveCategory(cat_path) == None:
cat_base_object = portal_cat._getOb(cat_base)
cat_base_object.newContent ( portal_type = 'Category'
, id = cat_id)
LOG("New category '", 0, cat_path + "' created")
# Set the base variation of the product
product_object.setVariationBaseCategoryList(base_cat_list)
# Set the variation range of the product
product_object.setVariationCategoryList(cat_list)
LOG("cat_list >>>>>>>>>>", 0, repr(cat_list))
# Now we seperate options and variations of the initial product ordered by the customer
customer_product_option_list = {}
customer_product_variation_list = {}
customer_product_base_variation_list = []
for option in priced_list:
option_is_variant = None
for (cat_base, cat_data) in variant_category_list:
base_cat_object = portal_cat.resolveCategory(cat_base)
cat_list = base_cat_object.getCategoryChildIdItemList()
for (category, category_bis) in cat_list:
if self.str2id(option) == category:
customer_product_variation_list[category] = cat_base + '/' + category
if cat_base not in customer_product_base_variation_list:
customer_product_base_variation_list.append(cat_base)
option_is_variant = 1
break
if option_is_variant == 1:
break
if option_is_variant == None:
customer_product_option_list[option] = priced_list[option]
if len(customer_product_option_list) + len(customer_product_variation_list) != len(priced_list):
LOG('Wrong repartition of the customer priced list', 200)
LOG('>>>>>> Customer product option priced list: ', 0, repr(customer_product_option_list))
LOG('>>>>>> Customer product variation priced list: ', 0, repr(customer_product_variation_list))
LOG('>>>>>> Customer product base variation list: ', 0, repr(customer_product_base_variation_list))
# This variable repesent the sum of every option prices
options_price_sum = 0.0
# We have to create a new product for every option not included in the variation system
for opt_prod_key in customer_product_option_list.keys():
opt_prod_price = customer_product_option_list[opt_prod_key]
# Set the id of the optionnal product
opt_prod_key = self.str2id(opt_prod_key)
opt_prod_id = "storever-" + opt_prod_key
# Create the optionnal product or get it if it already exist
opt_prod_object = self.createOrFindProduct(erp5_site, opt_prod_id)
# Remove the "discontinued" string in the title
opt_prod_title = self.niceTitle(opt_prod_key)
# Set some properties of the optionnal product
opt_prod_object.setTitle(opt_prod_title.title())
opt_prod_object.setBasePrice(opt_prod_price)
opt_prod_object.setQuantityUnit('Unit')
# Set the workflow state of the optionnal product
self.setProductWorkflow(opt_prod_object, opt_prod_key)
# Get the last number of order lines
# This process is needed to distinguish the same option created for two different product
# and avoid problem when a new Order line is created for a option product already used
# inside the same Sale Order
last_line_num = self.getLastOrderLineNumber(parent_order_object)
opt_prod_line_id = "storever-" + str(last_line_num) + "-" + opt_prod_key
# Create an order line for the product
parent_order_object.newContent ( portal_type = 'Sale Order Line'
, id = opt_prod_line_id)
opt_order_line_object = parent_order_object._getOb(opt_prod_line_id)
# Set several properties of the new orderLine
opt_order_line_object.setQuantityUnit('Unit')
opt_order_line_object.setPrice(opt_prod_price)
# There is the same quantity of the base product
opt_order_line_object.setQuantity(kw['quantity'])
# Link the Order Line with the product
opt_order_line_object.setResource("product/" + opt_prod_id)
# Calcul the sum of option prices
options_price_sum += float(opt_prod_price)
# # TODO: don't forget to manage the VAT values
# TODO: # Try to find a previous OrderLine to update
# line_object = None
# for product_id in product_folder.objectIds():
# if product_id == erp5_product_id:
# product_object = erp5_site.restrictedTraverse(erp5_site_path + '/product/' + erp5_product_id)
# break
# Migrate the line informations
object.setQuantity(kw['quantity'])
object.setDescription(kw['title'])
object.setQuantityUnit('Unit')
# Substract to the product price the sum of options prices
initial_prod_price = float(kw['price']) - options_price_sum
object.setPrice(initial_prod_price)
# Link the Order Line with the product
object.setResource("product/" + erp5_product_id)
# Set variations of the order line product choosen by the customer
category_list = []
for variation_key in customer_product_variation_list.keys():
category_list.append(customer_product_variation_list[variation_key])
object.setVariationBaseCategoryList(customer_product_base_variation_list)
# # TODO : fix this
# object.setVariationCategoryList(category_list)
return
\ No newline at end of file
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