Commit be3df2e3 authored by Sebastien Robin's avatar Sebastien Robin

added one way synchronization


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@1860 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent ea38db70
...@@ -97,7 +97,8 @@ class ERP5Conduit(XMLSyncUtilsMixin): ...@@ -97,7 +97,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
""" """
return the string corresponding to the local encoding return the string corresponding to the local encoding
""" """
return "iso-8859-1" #return "iso-8859-1"
return "utf-8"
security.declareProtected(Permissions.ModifyPortalContent, '__init__') security.declareProtected(Permissions.ModifyPortalContent, '__init__')
def __init__(self): def __init__(self):
......
...@@ -47,6 +47,8 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -47,6 +47,8 @@ class ERP5ShopOrderConduit(ERP5Conduit):
""" """
This conduit is used in the synchronisation process of Storever and ERP5 to convert This conduit is used in the synchronisation process of Storever and ERP5 to convert
a Storever Shop Order to a ERP5 Sale Order. a Storever Shop Order to a ERP5 Sale Order.
Don't forget to add this base categories in portal_category :
'hd_size', 'memory_size', 'optical_drive', 'keyboad_layout', 'cpu_type'
""" """
...@@ -72,17 +74,17 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -72,17 +74,17 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if portal_type == 'Shop Order': if portal_type == 'Shop Order':
# The random part of the id can be removed. It's only used for the developpement # 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)) new_object_id = 'storever-' + object_id + '-' + str(random.randint(1000, 9999))
object.newContent ( portal_type = 'Sale Order' subobject = object.newContent( portal_type = 'Sale Order'
, id = new_object_id) , id = new_object_id)
if portal_type == 'Order Line': if portal_type == 'Order Line':
last_line_num = self.getLastOrderLineNumber(object) last_line_num = self.getLastOrderLineNumber(object)
new_object_id = "storever-" + str(last_line_num + 1) + "-" + object_id new_object_id = "storever-" + str(last_line_num + 1) + "-" + object_id
object.newContent ( portal_type = 'Sale Order Line' subobject = object.newContent( portal_type = 'Sale Order Line'
, id = new_object_id) , id = new_object_id)
subobject = object._getOb(new_object_id)
return subobject return subobject
# # Not needed yet # # Not needed yet
# security.declareProtected(Permissions.ModifyPortalContent, 'addWorkflowNode') # security.declareProtected(Permissions.ModifyPortalContent, 'addWorkflowNode')
# def addWorkflowNode(self, object, xml, simulate): # def addWorkflowNode(self, object, xml, simulate):
...@@ -178,9 +180,8 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -178,9 +180,8 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if product_id == erp5_product_id: if product_id == erp5_product_id:
return erp5_site.restrictedTraverse(erp5_site_path + '/product/' + erp5_product_id) return erp5_site.restrictedTraverse(erp5_site_path + '/product/' + erp5_product_id)
# We have to create a new product # We have to create a new product
product_folder.newContent ( portal_type = 'Product' return product_folder.newContent( portal_type = 'Product'
, id = erp5_product_id) , id = erp5_product_id)
return product_folder._getOb(erp5_product_id)
...@@ -190,18 +191,25 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -190,18 +191,25 @@ class ERP5ShopOrderConduit(ERP5Conduit):
This function set the validation workflow to indicate if a product This function set the validation workflow to indicate if a product
is discontinued (workflow state = invalidate) or not (workflow state = validate) is discontinued (workflow state = invalidate) or not (workflow state = validate)
""" """
#!!!!!!!!!!!!!!!!!!!!!!!!!!
# return
#!!!!!!!!!!!!!!!!!!!!!!!!!!
action = None action = None
if hasattr(product_object, 'workflow_history'): if hasattr(product_object, 'workflow_history'):
LOG('Info needed from portal_workflow >>>>>>>>> ', 0, '')
workflow_state = product_object.portal_workflow.getInfoFor(product_object, 'validation_state') workflow_state = product_object.portal_workflow.getInfoFor(product_object, 'validation_state')
LOG('workflow_state is >>>>>>>>> ', 0, repr(workflow_state))
if product_title.lower().find('discontinued') != -1: if product_title.lower().find('discontinued') != -1:
if workflow_state != 'invalidated': if workflow_state != 'invalidated':
action = 'invalidate_action' action = 'invalidate_action'
elif workflow_state in ('draft', 'invalidated'): elif workflow_state in ('draft', 'invalidated'):
action = 'validate_action' action = 'validate_action'
LOG('action is >>>>>>>>> ', 0, repr(action))
if action != None: if action != None:
product_object.portal_workflow.doActionFor( product_object product_object.portal_workflow.doActionFor( product_object
, action , action
, wf_id = 'validation_workflow') , wf_id = 'validation_workflow')
LOG('end of workflow action >>>>>>>>> ', 0, repr(action))
...@@ -248,6 +256,43 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -248,6 +256,43 @@ class ERP5ShopOrderConduit(ERP5Conduit):
security.declarePrivate('updateObjProperty')
def updateObjProperty(self, object, property, kw, key):
"""
This function update the property of an object with a given value stored in a dictionnary. This function help the Conduit to make decision about the synchronisation of values.
Example of call : self.updateObjProperty(person_object, 'DefaultAddressStreetAddress', kw, 'address')
Solution (d'apres seb) :
* machin = getattr (object, methos)
* machin()
"""
if kw.has_key(key):
new_value = kw[key]
if new_value != None:
if type(new_value) is type('s'):
new_value = new_value.title()
current_value = eval('object.get' + property + '()')
LOG("I have to run this >>>>>>>> ", 0, 'object.get' + property + '()')
LOG("current_value >>>>>>>> ", 0, repr(current_value))
# The current property value is not consistent
if current_value == None or len(current_value) == 0:
# Erase the current value with the new one
LOG("I have to run this to set the property >>>>>>>> " + 'object.set' + str(property) + '(' + str(new_value) + ')' + str(current_value), 0, '')
# A previous consistent value exist
elif current_value.strip().lower() != new_value.strip().lower():
# TODO : We need to choose if we replace it or not, or mix the current with the new one
LOG('We have to make the fusion of previous address with the current one >>>>>>>', 0, '')
return False
return True
return False
security.declareProtected(Permissions.ModifyPortalContent, 'editDocument') security.declareProtected(Permissions.ModifyPortalContent, 'editDocument')
def editDocument(self, object=None, **kw): def editDocument(self, object=None, **kw):
""" """
...@@ -258,6 +303,10 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -258,6 +303,10 @@ class ERP5ShopOrderConduit(ERP5Conduit):
LOG('KW >>>>>>>> ', 0, kw) LOG('KW >>>>>>>> ', 0, kw)
# This list contain a list of object to check to know if their workflow need to be mofified
# We store these objects into a list and we will apply modification at the end to avoid mysql lock problem
workflow_joblist = []
# Get the ERP5 root object # Get the ERP5 root object
portal_types = getToolByName(object, 'portal_types') portal_types = getToolByName(object, 'portal_types')
erp5_site = portal_types.getPortalObject() erp5_site = portal_types.getPortalObject()
...@@ -265,12 +314,11 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -265,12 +314,11 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# The object is a ShopOrder # The object is a ShopOrder
if kw.has_key('country'): if kw.has_key('country'):
# Find the organisation and the person folder # Find the organisation and the person folder
person_path = erp5_site_path + '/person' person_path = erp5_site_path + '/person'
person_folder = erp5_site.restrictedTraverse(person_path) person_folder = erp5_site.restrictedTraverse(person_path)
organisation_path = erp5_site_path + '/organisation' organisation_path = erp5_site_path + '/organisation'
organisation_folder = erp5_site.restrictedTraverse(organisation_path) org_folder = erp5_site.restrictedTraverse(organisation_path)
# Find the service folder # Find the service folder
service_path = erp5_site_path + '/service' service_path = erp5_site_path + '/service'
service_folder = erp5_site.restrictedTraverse(service_path) service_folder = erp5_site.restrictedTraverse(service_path)
...@@ -284,23 +332,23 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -284,23 +332,23 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# Try to find the identity created for a previous ShopOrder of the same Storever member account # Try to find the identity created for a previous ShopOrder of the same Storever member account
person_object = None person_object = None
organisation_object = None org_object = None
for person_id in person_folder.objectIds(): for person_id in person_folder.objectIds():
if person_id == owner_id: if person_id == owner_id:
person_object = erp5_site.restrictedTraverse(erp5_site_path + '/person/' + person_id) person_object = erp5_site.restrictedTraverse(erp5_site_path + '/person/' + person_id)
LOG("Previous person found ! >>>>>>>>",0,repr(person_object)) LOG("Previous person found ! >>>>>>>>",0,repr(person_object))
break break
for organisation_id in organisation_folder.objectIds(): for organisation_id in org_folder.objectIds():
if organisation_id == owner_id: if organisation_id == owner_id:
organisation_object = erp5_site.restrictedTraverse(erp5_site_path + '/organisation/' + organisation_id) org_object = erp5_site.restrictedTraverse(erp5_site_path + '/organisation/' + organisation_id)
LOG("Previous organisation found ! >>>>>>>>",0,repr(organisation_object)) LOG("Previous organisation found ! >>>>>>>>",0,repr(org_object))
break break
# Define the previous customer structure # Define the previous customer structure
previous_owner_type = '' previous_owner_type = ''
if person_object != None: if person_object != None:
previous_owner_type += 'p' previous_owner_type += 'p'
if organisation_object != None: if org_object != None:
previous_owner_type += 'o' previous_owner_type += 'o'
if len(previous_owner_type) == 0: if len(previous_owner_type) == 0:
previous_owner_type = None previous_owner_type = None
...@@ -324,27 +372,25 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -324,27 +372,25 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if previous_owner_type != owner_type: if previous_owner_type != owner_type:
# There is difference between the two (previous and current) representation of the customer # 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 # We have to manage the differences to create a unique customer representation
LOG("There is difference between previous and current >>>>>>>>",0,None) LOG("There is difference between previous and current >>>>>>>>",0,'')
if previous_owner_type == None: if previous_owner_type == None:
# No previous customer found, create one # No previous customer found, create one
if owner_type.find('o') != -1: if owner_type.find('o') != -1:
organisation_folder.newContent ( portal_type = 'Organisation' org_object = org_folder.newContent( portal_type = 'Organisation'
, id = owner_id) , id = owner_id)
organisation_object = organisation_folder._getOb(owner_id) LOG("new organisation created >>>>>>>>",0,repr(org_object))
LOG("new organisation created >>>>>>>>",0,repr(organisation_object))
if owner_type.find('p') != -1: if owner_type.find('p') != -1:
person_folder.newContent ( portal_type = 'Person' person_object = person_folder.newContent( portal_type = 'Person'
, id = owner_id) , id = owner_id)
person_object = person_folder._getOb(owner_id)
LOG("new person created >>>>>>>>",0,repr(person_object)) LOG("new person created >>>>>>>>",0,repr(person_object))
else: else:
if owner_type == None: if owner_type == None:
# Use the previous Structure # Use the previous Structure
owner_type = previous_owner_type owner_type = previous_owner_type
LOG("Use the previous Structure >>>>>>>>",0,None) LOG("Use the previous Structure >>>>>>>>",0,'')
else: else:
LOG("We have to convert the structure >>>>>>>>",0,None) LOG("We have to convert the structure >>>>>>>>",0,'')
# # XXX Be aware of that problem: the invoice for a sale order must be the same # # XXX Be aware of that problem: the invoice for a sale order must look the same (I mean when we generate the pdf version)
# Case to process : # Case to process :
# previous current # previous current
# o --> p # o --> p
...@@ -364,9 +410,8 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -364,9 +410,8 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if owner_type.find('p') != -1 and owner_type.find('o') != -1: if owner_type.find('p') != -1 and owner_type.find('o') != -1:
# Create a new organisation # Create a new organisation
# # TODO : factorise this code with the same above # # TODO : factorise this code with the same above
organisation_folder.newContent ( portal_type = 'Organisation' org_object = org_folder.newContent( portal_type = 'Organisation'
, id = owner_id) , id = owner_id)
organisation_object = organisation_folder._getOb(owner_id)
else: else:
# # TODO : Transform a person to an organisation ? Is it a good idea ? # # TODO : Transform a person to an organisation ? Is it a good idea ?
pass pass
...@@ -390,19 +435,18 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -390,19 +435,18 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# a person and there is no previous record # 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 # By default, we consider the customer as a person, so we have to force to create one
owner_type = 'p' owner_type = 'p'
person_folder.newContent ( portal_type = 'Person' person_object = person_folder.newContent( portal_type = 'Person'
, id = owner_id) , id = owner_id)
person_object = person_folder._getOb(owner_id)
LOG("Create a person by default >>>>>>>>",0,repr(person_object)) LOG("Create a person by default >>>>>>>>",0,repr(person_object))
else: else:
# The structure is the same # The structure is the same
# We only need to be aware of data fusion between the previous and the current representation # 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 # 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) LOG("The structure is the same. don't do anything >>>>>>>>",0,'')
pass pass
LOG("Person object >>>>>>>>",0,repr(person_object)) LOG("Person object >>>>>>>>",0,repr(person_object))
LOG("Organisation object >>>>>>>>",0,repr(organisation_object)) LOG("Organisation object >>>>>>>>",0,repr(org_object))
# Copy informations related to the customer in the ERP5 representation of the customer # Copy informations related to the customer in the ERP5 representation of the customer
# Be carefull because all informations from the storever ShopOrder are optionnals # Be carefull because all informations from the storever ShopOrder are optionnals
...@@ -415,12 +459,20 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -415,12 +459,20 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# # 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 : 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 # # TODO : perhaps it's possible to factorize the code using a generic function
# Synchronise the street address # Synchronise the street address
if kw.has_key('address'):
previous_address = person_object.getDefaultAddressStreetAddress() # Solution (d'apres seb)
if len(previous_address) == 0: # machin = getattr (object, methos)
person_object.setDefaultAddressStreetAddress(kw['address'].title()) # method(machin)
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) machin = self.updateObjProperty(person_object, 'DefaultAddressStreetAddress', kw, 'address')
LOG("My new updateObjProperty() return >>>>>>>>",0,repr(machin))
# if kw.has_key('address') and kw['address'] != None:
# 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, '')
person_object.setDefaultAddressCity(kw['city'].title()) person_object.setDefaultAddressCity(kw['city'].title())
person_object.setDefaultAddressZipCode(kw['zipcode']) person_object.setDefaultAddressZipCode(kw['zipcode'])
...@@ -432,7 +484,9 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -432,7 +484,9 @@ class ERP5ShopOrderConduit(ERP5Conduit):
person_object.setDefaultAddressRegion(region_path) person_object.setDefaultAddressRegion(region_path)
# else: # else:
# # TODO : Ask the user to select an appropriate region # # TODO : Ask the user to select an appropriate region
if kw.has_key('email') and kw['email'] != None:
person_object.setDefaultEmailText(kw['email']) person_object.setDefaultEmailText(kw['email'])
if kw.has_key('phone') and kw['phone'] != None:
person_object.setDefaultTelephoneText(kw['phone']) person_object.setDefaultTelephoneText(kw['phone'])
# # TODO : Don't work # # TODO : Don't work
# person_object.setDefaultCareerRole("client") # person_object.setDefaultCareerRole("client")
...@@ -450,39 +504,44 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -450,39 +504,44 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if owner_type.find('o') != -1: if owner_type.find('o') != -1:
# # TODO : fix this # # TODO : fix this
# person_object.setSubordination("organisation/" + owner_id) # person_object.setSubordination("organisation/" + owner_id)
organisation_object.setTitle(kw['organisation'].title()) if kw.has_key('organisation') and kw['organisation'] != None:
organisation_object.setCorporateName(kw['organisation'].title()) org_object.setTitle(kw['organisation'].title())
organisation_object.setRole("client") if kw.has_key('eu_vat') and kw['eu_vat'] != None:
if kw.has_key('eu_vat'): org_object.setEuVatCode(kw['eu_vat'])
organisation_object.setEuVatCode(kw['eu_vat']) # Test for debug
if (not (kw.has_key('organisation')) or (kw.has_key('organisation') and kw['organisation'] != None)) and (not (kw.has_key('eu_vat')) or (kw.has_key('eu_vat') and kw['eu_vat'] != None)):
LOG("AARRGG ! Big conflict detected : this organisation has no title or eu_vat. These properties are primary key to deduced that the storever member account was an organisation >>>>>>>>>>", 0, '')
org_object.setCorporateName(kw['organisation'].title())
org_object.setRole("client")
# The customer is not a person or a person of an organisation, so the customer is an organisation... # The customer is not a person or a person of an organisation, so the customer is an organisation...
else: else:
# Link the customer with the Sale Order # Link the customer with the Sale Order
object.setDestination("organisation/" + owner_id) object.setDestination("organisation/" + owner_id)
object.setDestinationDecision("organisation/" + owner_id) object.setDestinationDecision("organisation/" + owner_id)
# All informations describe the organisation # All informations describe the organisation
organisation_object.setTitle(kw['organisation'].title()) org_object.setTitle(kw['organisation'].title())
organisation_object.setCorporateName(kw['organisation'].title()) org_object.setCorporateName(kw['organisation'].title())
organisation_object.setRole("client") org_object.setRole("client")
organisation_object.setEuVatCode(kw['eu_vat']) org_object.setEuVatCode(kw['eu_vat'])
organisation_object.setDefaultAddressStreetAddress(kw['address'].title()) org_object.setDefaultAddressStreetAddress(kw['address'].title())
organisation_object.setDefaultAddressCity(kw['city'].title()) org_object.setDefaultAddressCity(kw['city'].title())
organisation_object.setDefaultAddressZipCode(kw['zipcode']) org_object.setDefaultAddressZipCode(kw['zipcode'])
# Search the country in the region category # Search the country in the region category
if kw['country'] != None: if kw['country'] != None:
region_path = self.countrySearch(erp5_site, None, kw['country']) region_path = self.countrySearch(erp5_site, None, kw['country'])
if region_path != None: if region_path != None:
organisation_object.setDefaultAddressRegion(region_path) org_object.setDefaultAddressRegion(region_path)
# else: # else:
# # TODO : Ask the user to select an appropriate region # # TODO : Ask the user to select an appropriate region
organisation_object.setDefaultEmailText(kw['email']) org_object.setDefaultEmailText(kw['email'])
organisation_object.setDefaultTelephoneText(kw['phone']) org_object.setDefaultTelephoneText(kw['phone'])
# Save the billing address in the description, because there is no dedicated place for it # 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: if kw.has_key('billing_address') and len(kw['billing_address']) > 0:
object.setDescription("Send the bill to : " + kw['billing_address']) object.setDescription("Send the bill to : " + kw['billing_address'])
# Set the Title because its required # Set the Title because its required
object.setTitle("Storever Order " + kw['order_id']) object.setTitle("Storever Order " + str(kw['order_id']))
# # ONLY for information (will be used in the future) # # ONLY for information (will be used in the future)
object.setDescription(str(object.getDescription()) + "\n\nTotal Price (with transport fees) :" + str(kw['total_price'])) object.setDescription(str(object.getDescription()) + "\n\nTotal Price (with transport fees) :" + str(kw['total_price']))
...@@ -531,9 +590,8 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -531,9 +590,8 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# Create a new order line in this order to represent the shipment service # Create a new order line in this order to represent the shipment service
ship_order_line_id = "storever-" + shipment_id ship_order_line_id = "storever-" + shipment_id
object.newContent( portal_type = 'Sale Order Line' ship_order_object = object.newContent( portal_type = 'Sale Order Line'
, id = ship_order_line_id) , id = ship_order_line_id)
ship_order_object = object._getOb(ship_order_line_id)
ship_order_object.setQuantity(1.0) ship_order_object.setQuantity(1.0)
ship_order_object.setPrice(kw['send_fee']) ship_order_object.setPrice(kw['send_fee'])
ship_order_object.setQuantityUnit('Unit') ship_order_object.setQuantityUnit('Unit')
...@@ -579,15 +637,13 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -579,15 +637,13 @@ class ERP5ShopOrderConduit(ERP5Conduit):
product_object.setSourceBasePriceValidity(kw['product_expiration_date']) product_object.setSourceBasePriceValidity(kw['product_expiration_date'])
product_object.setBasePrice(kw['product_price']) product_object.setBasePrice(kw['product_price'])
product_object.setQuantityUnit('Unit') product_object.setQuantityUnit('Unit')
# Save the worflow status for later modification
# Set the worflow status workflow_joblist.append((product_object, kw['product_title']))
self.setProductWorkflow(product_object, kw['product_title'])
# In storever, every option are set as string in the title of the OrderLine # 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 # This part of code create a list of all options choosen by the customer for this product
splitted_title = kw['title'].strip().split(":") splitted_title = kw['title'].strip().split(":")
option_list = (":".join(splitted_title[1:])).split("/") option_list = (":".join(splitted_title[1:])).split("/")
LOG('Customer option list: ', 0, repr(option_list)) LOG('Customer option list >>>>>> ', 0, repr(option_list))
# Now, we will find the price of each option # Now, we will find the price of each option
option_classes = [ kw['product_disk_price'] option_classes = [ kw['product_disk_price']
...@@ -603,7 +659,7 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -603,7 +659,7 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if option == option_key.strip(): if option == option_key.strip():
priced_list[option] = option_class[option_key] priced_list[option] = option_class[option_key]
# # TODO : there is no default options in the final priced_list. Is the option 'default' important ? # # 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)) LOG('Customer option priced list >>>>>>>>> ', 0, repr(priced_list))
# In ERP5, we have decided to represent some options as variation of a product # In ERP5, we have decided to represent some options as variation of a product
# and some options as new order line of product # and some options as new order line of product
...@@ -621,8 +677,8 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -621,8 +677,8 @@ class ERP5ShopOrderConduit(ERP5Conduit):
keyboard_options[option_key] = options_prices[option_key] keyboard_options[option_key] = options_prices[option_key]
elif option_key.lower().find("cd") != -1 or option_key.lower().find("dvd") != -1: elif option_key.lower().find("cd") != -1 or option_key.lower().find("dvd") != -1:
optical_options[option_key] = options_prices[option_key] optical_options[option_key] = options_prices[option_key]
LOG('Product keyboard layout priced list: ', 0, repr(keyboard_options)) LOG('Product keyboard layout priced list >>>>>>>>> ', 0, repr(keyboard_options))
LOG('Product optical drive priced list: ', 0, repr(optical_options)) LOG('Product optical drive priced list >>>>>>>>> ', 0, repr(optical_options))
# Create a data structure containing all allowed variations # Create a data structure containing all allowed variations
variant_category_list = [ ('hd_size', kw['product_disk_price']) variant_category_list = [ ('hd_size', kw['product_disk_price'])
...@@ -644,7 +700,7 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -644,7 +700,7 @@ class ERP5ShopOrderConduit(ERP5Conduit):
cat_base_object = portal_cat._getOb(cat_base) cat_base_object = portal_cat._getOb(cat_base)
cat_base_object.newContent ( portal_type = 'Category' cat_base_object.newContent ( portal_type = 'Category'
, id = cat_id) , id = cat_id)
LOG("New category '", 0, cat_path + "' created") LOG("New created category >>>>>>>>>>> ", 0, cat_path)
# Set the base variation of the product # Set the base variation of the product
product_object.setVariationBaseCategoryList(base_cat_list) product_object.setVariationBaseCategoryList(base_cat_list)
...@@ -661,6 +717,7 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -661,6 +717,7 @@ class ERP5ShopOrderConduit(ERP5Conduit):
for option in priced_list: for option in priced_list:
option_is_variant = None option_is_variant = None
for (cat_base, cat_data) in variant_category_list: for (cat_base, cat_data) in variant_category_list:
LOG('editDocument, cat_base',0,cat_base)
base_cat_object = portal_cat.resolveCategory(cat_base) base_cat_object = portal_cat.resolveCategory(cat_base)
cat_list = base_cat_object.getCategoryChildIdItemList() cat_list = base_cat_object.getCategoryChildIdItemList()
for (category, category_bis) in cat_list: for (category, category_bis) in cat_list:
...@@ -675,7 +732,7 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -675,7 +732,7 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if option_is_variant == None: if option_is_variant == None:
customer_product_option_list[option] = priced_list[option] customer_product_option_list[option] = priced_list[option]
if len(customer_product_option_list) + len(customer_product_variation_list) != len(priced_list): if len(customer_product_option_list) + len(customer_product_variation_list) != len(priced_list):
LOG('Wrong repartition of the customer priced list', 200) LOG('>>>>>>> Wrong repartition of the customer priced list', 200)
LOG('>>>>>> Customer product option priced list: ', 0, repr(customer_product_option_list)) 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 variation priced list: ', 0, repr(customer_product_variation_list))
LOG('>>>>>> Customer product base variation list: ', 0, repr(customer_product_base_variation_list)) LOG('>>>>>> Customer product base variation list: ', 0, repr(customer_product_base_variation_list))
...@@ -700,20 +757,18 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -700,20 +757,18 @@ class ERP5ShopOrderConduit(ERP5Conduit):
opt_prod_object.setTitle(opt_prod_title.title()) opt_prod_object.setTitle(opt_prod_title.title())
opt_prod_object.setBasePrice(opt_prod_price) opt_prod_object.setBasePrice(opt_prod_price)
opt_prod_object.setQuantityUnit('Unit') opt_prod_object.setQuantityUnit('Unit')
# Set the workflow state of the optionnal product # Save the workflow state changing for later modification
self.setProductWorkflow(opt_prod_object, opt_prod_key) workflow_joblist.append((opt_prod_object, opt_prod_key))
# Get the last number of order lines # Get the last number of order lines
# This process is needed to distinguish the same option created for two different product # 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 # and avoid problem when a new Order line is created for an option product already used
# inside the same Sale Order # inside the same Sale Order
last_line_num = self.getLastOrderLineNumber(parent_order_object) last_line_num = self.getLastOrderLineNumber(parent_order_object)
opt_prod_line_id = "storever-" + str(last_line_num) + "-" + opt_prod_key opt_prod_line_id = "storever-" + str(last_line_num) + "-" + opt_prod_key
# Create an order line for the product # Create an order line for the product
parent_order_object.newContent ( portal_type = 'Sale Order Line' opt_order_line_object = parent_order_object.newContent( portal_type = 'Sale Order Line'
, id = opt_prod_line_id) , id = opt_prod_line_id)
opt_order_line_object = parent_order_object._getOb(opt_prod_line_id)
# Set several properties of the new orderLine # Set several properties of the new orderLine
opt_order_line_object.setQuantityUnit('Unit') opt_order_line_object.setQuantityUnit('Unit')
opt_order_line_object.setPrice(opt_prod_price) opt_order_line_object.setPrice(opt_prod_price)
...@@ -725,13 +780,6 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -725,13 +780,6 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# Calcul the sum of option prices # Calcul the sum of option prices
options_price_sum += float(opt_prod_price) options_price_sum += float(opt_prod_price)
# # TODO: don't forget to manage the VAT values # # TODO: don't forget to manage the VAT values
# TODO: # Try to find a previous OrderLine to update # TODO: # Try to find a previous OrderLine to update
...@@ -761,4 +809,10 @@ class ERP5ShopOrderConduit(ERP5Conduit): ...@@ -761,4 +809,10 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# # TODO : fix this # # TODO : fix this
# object.setVariationCategoryList(category_list) # object.setVariationCategoryList(category_list)
# Do all workflow change at the end
LOG("enter workflow loop >>>>>>>>",0,repr(workflow_joblist))
for (object, object_title) in workflow_joblist:
LOG("Workflow to change :: >>>>>>>>",0,repr(object, object_title))
self.setProductWorkflow(object, object_title)
return return
...@@ -33,6 +33,7 @@ from Products.ERP5Type import Permissions ...@@ -33,6 +33,7 @@ from Products.ERP5Type import Permissions
from Products.ERP5Type.Document.Folder import Folder from Products.ERP5Type.Document.Folder import Folder
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import PropertySheet from Products.ERP5Type import PropertySheet
from zLOG import LOG
def addSubscriber( self, id, title='', REQUEST=None ): def addSubscriber( self, id, title='', REQUEST=None ):
""" """
...@@ -83,6 +84,16 @@ class Subscriber(Subscription): ...@@ -83,6 +84,16 @@ class Subscriber(Subscription):
Send ACK for a group of documents Send ACK for a group of documents
""" """
def getConduit(self):
"""
Return the conduit of the publication
"""
#LOG('Subscriber.getConduit, self.getPhysicalPath()',0,self.getPhysicalPath())
#LOG('Subscriber.getConduit, self.getParent().getPhysicalPath()',0,self.aq_parent.getPhysicalPath())
#LOG('Subscriber.getConduit, self.getParent()',0,self.getParent())
return self.aq_parent.getConduit()
#return self.conduit
def SendDocuments(self): def SendDocuments(self):
""" """
We send all the updated documents (ie. documents not marked We send all the updated documents (ie. documents not marked
...@@ -142,7 +153,7 @@ class Publication(Subscription): ...@@ -142,7 +153,7 @@ class Publication(Subscription):
constructors = (addPublication,) constructors = (addPublication,)
# Constructor # Constructor
def __init__(self, id, title, publication_url, destination_path, query, xml_mapping, gpg_key): def __init__(self, id, title, publication_url, destination_path, query, xml_mapping, conduit, gpg_key):
""" """
constructor constructor
""" """
...@@ -156,6 +167,7 @@ class Publication(Subscription): ...@@ -156,6 +167,7 @@ class Publication(Subscription):
self.gpg_key = gpg_key self.gpg_key = gpg_key
self.setGidGenerator(None) self.setGidGenerator(None)
self.setIdGenerator(None) self.setIdGenerator(None)
self.setConduit(conduit)
Folder.__init__(self, id) Folder.__init__(self, id)
self.title = title self.title = title
......
...@@ -342,7 +342,10 @@ class Signature(Folder,SyncCode): ...@@ -342,7 +342,10 @@ class Signature(Folder,SyncCode):
""" """
set the XML corresponding to the object set the XML corresponding to the object
""" """
return self.xml xml = getattr(self,'xml',None)
if xml == '':
xml = None
return xml
def setTempXML(self, xml): def setTempXML(self, xml):
""" """
...@@ -610,7 +613,7 @@ class Subscription(Folder, SyncCode): ...@@ -610,7 +613,7 @@ class Subscription(Folder, SyncCode):
) )
# Constructor # Constructor
def __init__(self, id, title, publication_url, subscription_url, destination_path, query, xml_mapping, gpg_key): def __init__(self, id, title, publication_url, subscription_url, destination_path, query, xml_mapping, conduit, gpg_key):
""" """
We need to create a dictionnary of We need to create a dictionnary of
signatures of documents which belong to the synchronisation signatures of documents which belong to the synchronisation
...@@ -621,7 +624,7 @@ class Subscription(Folder, SyncCode): ...@@ -621,7 +624,7 @@ class Subscription(Folder, SyncCode):
self.subscription_url = str(subscription_url) self.subscription_url = str(subscription_url)
self.destination_path = str(destination_path) self.destination_path = str(destination_path)
self.setQuery(query) self.setQuery(query)
self.xml_mapping = xml_mapping self.setXMLMapping(xml_mapping)
self.anchor = None self.anchor = None
self.session_id = 0 self.session_id = 0
#self.signatures = PersistentMapping() #self.signatures = PersistentMapping()
...@@ -631,6 +634,7 @@ class Subscription(Folder, SyncCode): ...@@ -631,6 +634,7 @@ class Subscription(Folder, SyncCode):
self.gpg_key = gpg_key self.gpg_key = gpg_key
self.setGidGenerator(None) self.setGidGenerator(None)
self.setIdGenerator(None) self.setIdGenerator(None)
self.setConduit(conduit)
Folder.__init__(self, id) Folder.__init__(self, id)
self.title = title self.title = title
...@@ -675,6 +679,14 @@ class Subscription(Folder, SyncCode): ...@@ -675,6 +679,14 @@ class Subscription(Folder, SyncCode):
LOG('Subscription',0,'getSynchronizationType: %s' % code) LOG('Subscription',0,'getSynchronizationType: %s' % code)
return code return code
def setXMLMapping(self, value):
"""
this the name of the method used in order to get the xml
"""
if value == '':
value = None
self.xml_mapping = value
def checkCorrectRemoteSessionId(self, session_id): def checkCorrectRemoteSessionId(self, session_id):
""" """
We will see if the last session id was the same We will see if the last session id was the same
...@@ -726,6 +738,19 @@ class Subscription(Folder, SyncCode): ...@@ -726,6 +738,19 @@ class Subscription(Folder, SyncCode):
""" """
self.id = id self.id = id
def setConduit(self, value):
"""
set the Conduit
"""
self.conduit = value
def getConduit(self):
"""
get the Conduit
"""
return getattr(self,'conduit',None)
def getQuery(self): def getQuery(self):
""" """
return the query return the query
...@@ -748,8 +773,8 @@ class Subscription(Folder, SyncCode): ...@@ -748,8 +773,8 @@ class Subscription(Folder, SyncCode):
""" """
set the query set the query
""" """
if query in (None,''): if query == '':
query = 'objectValues' query = None
self.query = query self.query = query
def getPublicationUrl(self): def getPublicationUrl(self):
...@@ -777,11 +802,17 @@ class Subscription(Folder, SyncCode): ...@@ -777,11 +802,17 @@ class Subscription(Folder, SyncCode):
xml_mapping = getattr(self,'xml_mapping','asXML') xml_mapping = getattr(self,'xml_mapping','asXML')
return xml_mapping return xml_mapping
def setXMLMapping(self, xml_mapping): def getXMLFromObject(self,object):
""" """
return the xml mapping return the xml mapping
""" """
self.xml_mapping = xml_mapping xml_mapping = self.getXMLMapping()
xml = ''
if xml_mapping is not None:
func = getattr(object,xml_mapping,None)
if func is not None:
xml = func()
return xml
def setGidGenerator(self, method): def setGidGenerator(self, method):
""" """
...@@ -843,6 +874,15 @@ class Subscription(Folder, SyncCode): ...@@ -843,6 +874,15 @@ class Subscription(Folder, SyncCode):
LOG('getObjectFromGid',0,'returning None') LOG('getObjectFromGid',0,'returning None')
return None return None
# def setOneWaySyncFromServer(self,value):
# """
# If this option is enabled, then we will not
# send our own modifications
# """
# self.one_way_sync_from_server = value
#
def getObjectList(self): def getObjectList(self):
""" """
This returns the list of sub-object corresponding This returns the list of sub-object corresponding
...@@ -851,6 +891,8 @@ class Subscription(Folder, SyncCode): ...@@ -851,6 +891,8 @@ class Subscription(Folder, SyncCode):
destination = self.getDestination() destination = self.getDestination()
query = self.getQuery() query = self.getQuery()
query_list = [] query_list = []
if query is None:
return query_list
if type(query) is type('a'): if type(query) is type('a'):
query_method = getattr(destination,query,None) query_method = getattr(destination,query,None)
if query_method is not None: if query_method is not None:
......
...@@ -36,6 +36,7 @@ from Globals import InitializeClass, DTMLFile, PersistentMapping, Persistent ...@@ -36,6 +36,7 @@ from Globals import InitializeClass, DTMLFile, PersistentMapping, Persistent
from AccessControl import ClassSecurityInfo, getSecurityManager from AccessControl import ClassSecurityInfo, getSecurityManager
from Products.CMFCore import CMFCorePermissions from Products.CMFCore import CMFCorePermissions
from Products.ERP5SyncML import _dtmldir from Products.ERP5SyncML import _dtmldir
from Products.ERP5SyncML import Conduit
from Publication import Publication,Subscriber from Publication import Publication,Subscriber
from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2 from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2
from Subscription import Subscription,Signature from Subscription import Subscription,Signature
...@@ -158,7 +159,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -158,7 +159,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
security.declareProtected(Permissions.ModifyPortalContent, 'manage_addPublication') security.declareProtected(Permissions.ModifyPortalContent, 'manage_addPublication')
def manage_addPublication(self, title, publication_url, destination_path, def manage_addPublication(self, title, publication_url, destination_path,
query, xml_mapping, gpg_key, RESPONSE=None): query, xml_mapping, conduit, gpg_key, RESPONSE=None):
""" """
create a new publication create a new publication
""" """
...@@ -168,7 +169,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -168,7 +169,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
folder = self.getObjectContainer() folder = self.getObjectContainer()
new_id = self.getPublicationIdFromTitle(title) new_id = self.getPublicationIdFromTitle(title)
pub = Publication(new_id, title, publication_url, destination_path, pub = Publication(new_id, title, publication_url, destination_path,
query, xml_mapping, gpg_key) query, xml_mapping, conduit, gpg_key)
folder._setObject( new_id, pub ) folder._setObject( new_id, pub )
#if len(self.list_publications) == 0: #if len(self.list_publications) == 0:
# self.list_publications = PersistentMapping() # self.list_publications = PersistentMapping()
...@@ -178,7 +179,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -178,7 +179,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
security.declareProtected(Permissions.ModifyPortalContent, 'manage_addSubscription') security.declareProtected(Permissions.ModifyPortalContent, 'manage_addSubscription')
def manage_addSubscription(self, title, publication_url, subscription_url, def manage_addSubscription(self, title, publication_url, subscription_url,
destination_path, query, xml_mapping, gpg_key, RESPONSE=None): destination_path, query, xml_mapping, conduit, gpg_key, RESPONSE=None):
""" """
XXX should be renamed as addSubscription XXX should be renamed as addSubscription
create a new subscription create a new subscription
...@@ -189,7 +190,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -189,7 +190,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
folder = self.getObjectContainer() folder = self.getObjectContainer()
new_id = self.getSubscriptionIdFromTitle(title) new_id = self.getSubscriptionIdFromTitle(title)
sub = Subscription(new_id, title, publication_url, subscription_url, sub = Subscription(new_id, title, publication_url, subscription_url,
destination_path, query, xml_mapping, gpg_key) destination_path, query, xml_mapping, conduit, gpg_key)
folder._setObject( new_id, sub ) folder._setObject( new_id, sub )
#if len(self.list_subscriptions) == 0: #if len(self.list_subscriptions) == 0:
# self.list_subscriptions = PersistentMapping() # self.list_subscriptions = PersistentMapping()
...@@ -199,7 +200,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -199,7 +200,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
security.declareProtected(Permissions.ModifyPortalContent, 'manage_editPublication') security.declareProtected(Permissions.ModifyPortalContent, 'manage_editPublication')
def manage_editPublication(self, title, publication_url, destination_path, def manage_editPublication(self, title, publication_url, destination_path,
query, xml_mapping, gpg_key, RESPONSE=None): query, xml_mapping, conduit, gpg_key, RESPONSE=None):
""" """
modify a publication modify a publication
""" """
...@@ -208,6 +209,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -208,6 +209,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
pub.setPublicationUrl(publication_url) pub.setPublicationUrl(publication_url)
pub.setDestinationPath(destination_path) pub.setDestinationPath(destination_path)
pub.setQuery(query) pub.setQuery(query)
pub.setConduit(conduit)
pub.setXMLMapping(xml_mapping) pub.setXMLMapping(xml_mapping)
pub.setGPGKey(gpg_key) pub.setGPGKey(gpg_key)
if RESPONSE is not None: if RESPONSE is not None:
...@@ -215,7 +217,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -215,7 +217,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
security.declareProtected(Permissions.ModifyPortalContent, 'manage_editSubscription') security.declareProtected(Permissions.ModifyPortalContent, 'manage_editSubscription')
def manage_editSubscription(self, title, publication_url, subscription_url, def manage_editSubscription(self, title, publication_url, subscription_url,
destination_path, query, xml_mapping, gpg_key, RESPONSE=None): destination_path, query, xml_mapping, conduit, gpg_key, RESPONSE=None):
""" """
modify a subscription modify a subscription
""" """
...@@ -224,6 +226,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -224,6 +226,7 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
sub.setPublicationUrl(publication_url) sub.setPublicationUrl(publication_url)
sub.setDestinationPath(destination_path) sub.setDestinationPath(destination_path)
sub.setQuery(query) sub.setQuery(query)
sub.setConduit(conduit)
sub.setXMLMapping(xml_mapping) sub.setXMLMapping(xml_mapping)
sub.setGPGKey(gpg_key) sub.setGPGKey(gpg_key)
sub.setSubscriptionUrl(subscription_url) sub.setSubscriptionUrl(subscription_url)
...@@ -370,20 +373,22 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -370,20 +373,22 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
#conflict.setDomain('Publication') #conflict.setDomain('Publication')
conflict.setSubscriber(subscriber) conflict.setSubscriber(subscriber)
#conflict.setDomainId(subscriber.getId()) #conflict.setDomainId(subscriber.getId())
conflict_list += [conflict.__of__(self)] if path is None or conflict.getObjectPath() == path:
conflict_list += [conflict.__of__(subscriber)]
for subscription in self.getSubscriptionList(): for subscription in self.getSubscriptionList():
sub_conflict_list = subscription.getConflictList() sub_conflict_list = subscription.getConflictList()
for conflict in sub_conflict_list: for conflict in sub_conflict_list:
#conflict.setDomain('Subscription') #conflict.setDomain('Subscription')
conflict.setSubscriber(subscription) conflict.setSubscriber(subscription)
#conflict.setDomainId(subscription.getId()) #conflict.setDomainId(subscription.getId())
conflict_list += [conflict.__of__(self)] if path is None or conflict.getObjectPath() == path:
if path is not None: # Retrieve only conflicts for a given path conflict_list += [conflict.__of__(subscription)]
new_list = [] #if path is not None: # Retrieve only conflicts for a given path
for conflict in conflict_list: # new_list = []
if conflict.getObjectPath() == path: # for conflict in conflict_list:
new_list += [conflict.__of__(self)] # if conflict.getObjectPath() == path:
return new_list # new_list += [conflict.__of__(self)]
# return new_list
return conflict_list return conflict_list
security.declareProtected(Permissions.AccessContentsInformation,'getDocumentConflictList') security.declareProtected(Permissions.AccessContentsInformation,'getDocumentConflictList')
...@@ -530,7 +535,9 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -530,7 +535,9 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
object_id = docid object_id = docid
if object_id in directory.objectIds(): if object_id in directory.objectIds():
directory._delObject(object_id) directory._delObject(object_id)
conduit = ERP5Conduit() #conduit = ERP5Conduit()
conduit_name = subscriber.getConduit()
conduit = getattr(getattr(Conduit,conduit_name),conduit_name)()
conduit.addNode(xml=publisher_xml,object=directory,object_id=object_id) conduit.addNode(xml=publisher_xml,object=directory,object_id=object_id)
subscriber_document = directory._getOb(object_id) subscriber_document = directory._getOb(object_id)
for c in self.getConflictList(conflict.getObjectPath()): for c in self.getConflictList(conflict.getObjectPath()):
...@@ -565,7 +572,9 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -565,7 +572,9 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
publisher_xml = self.getXMLObject(object=publisher_object,xml_mapping = subscriber.getXMLMapping()) publisher_xml = self.getXMLObject(object=publisher_object,xml_mapping = subscriber.getXMLMapping())
directory = publisher_object.aq_inner.aq_parent directory = publisher_object.aq_inner.aq_parent
object_id = self._getCopyId(publisher_object) object_id = self._getCopyId(publisher_object)
conduit = ERP5Conduit() #conduit = ERP5Conduit()
conduit_name = subscriber.getConduit()
conduit = getattr(getattr(Conduit,conduit_name),conduit_name)()
conduit.addNode(xml=publisher_xml,object=directory,object_id=object_id) conduit.addNode(xml=publisher_xml,object=directory,object_id=object_id)
subscriber_document = directory._getOb(object_id) subscriber_document = directory._getOb(object_id)
subscriber_document._conflict_resolution = 1 subscriber_document._conflict_resolution = 1
...@@ -576,7 +585,6 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -576,7 +585,6 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
conflict.setCopyPath(copy_path) conflict.setCopyPath(copy_path)
return copy_path return copy_path
security.declareProtected(Permissions.AccessContentsInformation, 'getSubscriberDocument') security.declareProtected(Permissions.AccessContentsInformation, 'getSubscriberDocument')
def getSubscriberDocument(self, conflict): def getSubscriberDocument(self, conflict):
""" """
...@@ -613,7 +621,9 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -613,7 +621,9 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
# get the signature: # get the signature:
LOG('p_sync.setRemoteObject, subscriber: ',0,subscriber) LOG('p_sync.setRemoteObject, subscriber: ',0,subscriber)
signature = subscriber.getSignature(object.getId()) # XXX may be change for rid signature = subscriber.getSignature(object.getId()) # XXX may be change for rid
conduit = ERP5Conduit() #conduit = ERP5Conduit()
conduit_name = subscriber.getConduit()
conduit = getattr(getattr(Conduit,conduit_name),conduit_name)()
for xupdate in conflict.getXupdateList(): for xupdate in conflict.getXupdateList():
conduit.updateNode(xml=xupdate,object=object,force=1) conduit.updateNode(xml=xupdate,object=object,force=1)
if solve_conflict: if solve_conflict:
...@@ -632,7 +642,6 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati ...@@ -632,7 +642,6 @@ class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronizati
directory._delObject(copy_id) directory._delObject(copy_id)
signature.setStatus(self.PUB_CONFLICT_MERGE) signature.setStatus(self.PUB_CONFLICT_MERGE)
security.declareProtected(Permissions.ModifyPortalContent, 'manageLocalValue') security.declareProtected(Permissions.ModifyPortalContent, 'manageLocalValue')
def managePublisherValue(self, subscription_url, property_id, object_path, RESPONSE=None): def managePublisherValue(self, subscription_url, property_id, object_path, RESPONSE=None):
""" """
......
...@@ -218,6 +218,7 @@ class XMLSyncUtilsMixin(SyncCode): ...@@ -218,6 +218,7 @@ class XMLSyncUtilsMixin(SyncCode):
""" """
xml_method = None xml_method = None
xml = "" xml = ""
if xml_mapping is not None:
if hasattr(object,xml_mapping): if hasattr(object,xml_mapping):
xml_method = getattr(object,xml_mapping) xml_method = getattr(object,xml_mapping)
elif hasattr(object,'manage_FTPget'): elif hasattr(object,'manage_FTPget'):
...@@ -601,23 +602,12 @@ class XMLSyncUtilsMixin(SyncCode): ...@@ -601,23 +602,12 @@ class XMLSyncUtilsMixin(SyncCode):
# Here we first check if the object was modified or not by looking at dates # Here we first check if the object was modified or not by looking at dates
if signature is not None: if signature is not None:
signature.checkSynchronizationNeeded(object) signature.checkSynchronizationNeeded(object)
# LOG('getSyncMLData',0,'signature.status: %s' % str(signature.getStatus()))
# LOG('getSyncMLData',0,'signature.action: %s' % str(signature.getAction()))
# last_modification = DateTime(object.ModificationDate())
# LOG('getSyncMLData object.ModificationDate()',0,object.ModificationDate())
# last_synchronization = signature.getLastSynchronizationDate()
# parent = object.aq_parent
# # XXX CPS Specific
# #if parent.id == 'portal_repository':
# if 1:
# if last_synchronization is not None and last_modification is not None:
# if last_synchronization > last_modification:
# LOG('getSyncMLData, no modification on: ',0,object.id)
# signature.setStatus(self.SYNCHRONIZED)
status = self.SENT status = self.SENT
more_data=0 more_data=0
# For the case it was never synchronized, we have to send everything # For the case it was never synchronized, we have to send everything
if signature==None or (signature.getXML()==None and signature.getStatus()!=self.PARTIAL) or \ if signature is not None and signature.getXMLMapping()==None:
pass
elif signature==None or (signature.getXML()==None and signature.getStatus()!=self.PARTIAL) or \
self.getAlertCode(remote_xml)==self.SLOW_SYNC: self.getAlertCode(remote_xml)==self.SLOW_SYNC:
#LOG('PubSyncModif',0,'Current object.getPath: %s' % object.getPath()) #LOG('PubSyncModif',0,'Current object.getPath: %s' % object.getPath())
LOG('getSyncMLData',0,'no signature for gid: %s' % object_gid) LOG('getSyncMLData',0,'no signature for gid: %s' % object_gid)
...@@ -781,10 +771,10 @@ class XMLSyncUtilsMixin(SyncCode): ...@@ -781,10 +771,10 @@ class XMLSyncUtilsMixin(SyncCode):
LOG('applyActionList',0,'object after add: %s' % repr(object)) LOG('applyActionList',0,'object after add: %s' % repr(object))
if object is not None: if object is not None:
LOG('SyncModif',0,'addNode, found the object') LOG('SyncModif',0,'addNode, found the object')
mapping = getattr(object,domain.getXMLMapping(),None) #mapping = getattr(object,domain.getXMLMapping(),None)
xml_object = '' xml_object = domain.getXMLFromObject(object)
if mapping is not None: #if mapping is not None:
xml_object = mapping() # xml_object = mapping()
signature.setStatus(self.SYNCHRONIZED) signature.setStatus(self.SYNCHRONIZED)
signature.setId(object.getId()) signature.setId(object.getId())
signature.setXML(xml_object) signature.setXML(xml_object)
...@@ -798,14 +788,14 @@ class XMLSyncUtilsMixin(SyncCode): ...@@ -798,14 +788,14 @@ class XMLSyncUtilsMixin(SyncCode):
signature = subscriber.getSignature(object_gid) signature = subscriber.getSignature(object_gid)
LOG('SyncModif',0,'previous signature: %s' % str(signature)) LOG('SyncModif',0,'previous signature: %s' % str(signature))
previous_xml = signature.getXML() previous_xml = signature.getXML()
LOG('SyncModif',0,'previous signature: %i' % len(previous_xml)) #LOG('SyncModif',0,'previous signature: %i' % len(previous_xml))
conflict_list += conduit.updateNode(xml=data_subnode, object=object, conflict_list += conduit.updateNode(xml=data_subnode, object=object,
previous_xml=signature.getXML(),force=force, previous_xml=signature.getXML(),force=force,
simulate=simulate) simulate=simulate)
mapping = getattr(object,domain.getXMLMapping(),None) #mapping = getattr(object,domain.getXMLMapping(),None)
xml_object = '' xml_object = domain.getXMLFromObject(object)
if mapping is not None: #if mapping is not None:
xml_object = mapping() # xml_object = mapping()
signature.setTempXML(xml_object) signature.setTempXML(xml_object)
if conflict_list != []: if conflict_list != []:
status_code = self.CONFLICT status_code = self.CONFLICT
...@@ -922,7 +912,8 @@ class XMLSyncUtils(XMLSyncUtilsMixin): ...@@ -922,7 +912,8 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
Send the server modification, this happens after the Synchronization Send the server modification, this happens after the Synchronization
initialization initialization
""" """
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit #from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from Products.ERP5SyncML import Conduit
has_response = 0 #check if syncmodif replies to this messages has_response = 0 #check if syncmodif replies to this messages
cmd_id = 1 # specifies a SyncML message-unique command identifier cmd_id = 1 # specifies a SyncML message-unique command identifier
LOG('SyncModif',0,'Starting... domain: %s' % str(domain)) LOG('SyncModif',0,'Starting... domain: %s' % str(domain))
...@@ -968,7 +959,9 @@ class XMLSyncUtils(XMLSyncUtilsMixin): ...@@ -968,7 +959,9 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
remote_xml=remote_xml) remote_xml=remote_xml)
alert_code = self.getAlertCode(remote_xml) alert_code = self.getAlertCode(remote_xml)
conduit = ERP5Conduit() #conduit = ERP5Conduit()
conduit_name = subscriber.getConduit()
conduit = getattr(getattr(Conduit,conduit_name),conduit_name)()
LOG('SyncModif, subscriber: ',0,subscriber) LOG('SyncModif, subscriber: ',0,subscriber)
# Then apply the list of actions # Then apply the list of actions
(xml_confirmation,has_next_action,cmd_id) = self.applyActionList(cmd_id=cmd_id, (xml_confirmation,has_next_action,cmd_id) = self.applyActionList(cmd_id=cmd_id,
......
...@@ -87,6 +87,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -87,6 +87,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="xml_mapping" value="<dtml-var getXMLMapping>" size="40" /> <input type="text" name="xml_mapping" value="<dtml-var getXMLMapping>" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Conduit
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="conduit" value="<dtml-var getConduit>" size="40" />
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
......
...@@ -97,6 +97,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -97,6 +97,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="xml_mapping" value="<dtml-var getXMLMapping>" size="40" /> <input type="text" name="xml_mapping" value="<dtml-var getXMLMapping>" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Conduit
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="conduit" value="<dtml-var getConduit>" size="40" />
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
......
...@@ -83,6 +83,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -83,6 +83,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="xml_mapping" size="40" /> <input type="text" name="xml_mapping" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Conduit
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="conduit" size="40" />
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
......
...@@ -93,6 +93,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -93,6 +93,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="xml_mapping" size="40" /> <input type="text" name="xml_mapping" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Conduit
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="conduit" size="40" />
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
......
...@@ -107,7 +107,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -107,7 +107,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
/person_client2 : empty /person_client2 : empty
""" """
#return ('sync_crm',) #return ('sync_crm',)
return ('erp5_core',) return ()
def getSynchronizationTool(self): def getSynchronizationTool(self):
return getattr(self.getPortal(), 'portal_synchronizations', None) return getattr(self.getPortal(), 'portal_synchronizations', None)
...@@ -124,57 +124,57 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -124,57 +124,57 @@ class TestERP5SyncML(ERP5TypeTestCase):
def getPortalId(self): def getPortalId(self):
return self.getPortal().getId() return self.getPortal().getId()
def testHasEverything(self, quiet=0, run=run_all_test): def test_01_HasEverything(self, quiet=0, run=run_all_test):
# Test if portal_synchronizations was created # Test if portal_synchronizations was created
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Has Everything ') ZopeTestCase._print('\nTest Has Everything ')
LOG('Testing... ',0,'testHasEverything') LOG('Testing... ',0,'test_01_HasEverything')
self.failUnless(self.getSynchronizationTool()!=None) self.failUnless(self.getSynchronizationTool()!=None)
#self.failUnless(self.getPersonServer()!=None) #self.failUnless(self.getPersonServer()!=None)
#self.failUnless(self.getPersonClient1()!=None) #self.failUnless(self.getPersonClient1()!=None)
#self.failUnless(self.getPersonClient2()!=None) #self.failUnless(self.getPersonClient2()!=None)
def testAddPublication(self, quiet=0, run=run_all_test): def test_02_AddPublication(self, quiet=0, run=run_all_test):
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Add a Publication ') ZopeTestCase._print('\nTest Add a Publication ')
LOG('Testing... ',0,'testAddPublication') LOG('Testing... ',0,'test_02_AddPublication')
portal_id = self.getPortalName() portal_id = self.getPortalName()
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
portal_sync.manage_addPublication(self.pub_id,self.publication_url, portal_sync.manage_addPublication(self.pub_id,self.publication_url,
'/%s/person_server' % portal_id,'', '/%s/person_server' % portal_id,'objectValues',
self.xml_mapping,'') self.xml_mapping,'ERP5Conduit','')
pub = portal_sync.getPublication(self.pub_id) pub = portal_sync.getPublication(self.pub_id)
self.failUnless(pub is not None) self.failUnless(pub is not None)
def testAddSubscription1(self, quiet=0, run=run_all_test): def test_03_AddSubscription1(self, quiet=0, run=run_all_test):
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Add First Subscription ') ZopeTestCase._print('\nTest Add First Subscription ')
LOG('Testing... ',0,'testAddSubscription1') LOG('Testing... ',0,'test_03_AddSubscription1')
portal_id = self.getPortalId() portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
portal_sync.manage_addSubscription(self.sub_id1,self.publication_url, portal_sync.manage_addSubscription(self.sub_id1,self.publication_url,
self.subscription_url1,'/%s/person_client1' % portal_id,'', self.subscription_url1,'/%s/person_client1' % portal_id,'objectValues',
self.xml_mapping,'') self.xml_mapping,'ERP5Conduit','')
sub = portal_sync.getSubscription(self.sub_id1) sub = portal_sync.getSubscription(self.sub_id1)
self.failUnless(sub is not None) self.failUnless(sub is not None)
def testAddSubscription2(self, quiet=0, run=run_all_test): def test_04_AddSubscription2(self, quiet=0, run=run_all_test):
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Add Second Subscription ') ZopeTestCase._print('\nTest Add Second Subscription ')
LOG('Testing... ',0,'testAddSubscription2') LOG('Testing... ',0,'test_04_AddSubscription2')
portal_id = self.getPortalId() portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
portal_sync.manage_addSubscription(self.sub_id2,self.publication_url, portal_sync.manage_addSubscription(self.sub_id2,self.publication_url,
self.subscription_url2,'/%s/person_client2' % portal_id,'', self.subscription_url2,'/%s/person_client2' % portal_id,'objectValues',
self.xml_mapping,'') self.xml_mapping,'ERP5Conduit','')
sub = portal_sync.getSubscription(self.sub_id2) sub = portal_sync.getSubscription(self.sub_id2)
self.failUnless(sub is not None) self.failUnless(sub is not None)
def login(self, quiet=0, run=run_all_test): def login(self, quiet=0):
uf = self.getPortal().acl_users uf = self.getPortal().acl_users
uf._doAddUser('seb', '', ['Manager'], []) uf._doAddUser('seb', '', ['Manager'], [])
user = uf.getUserById('seb').__of__(uf) user = uf.getUserById('seb').__of__(uf)
...@@ -213,12 +213,12 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -213,12 +213,12 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(nb_person==2) self.failUnless(nb_person==2)
return nb_person return nb_person
def setupPublicationAndSubscription(self, quiet=0, run=run_all_test): def setupPublicationAndSubscription(self, quiet=0, run=1):
self.testAddPublication(quiet=1,run=1) self.test_02_AddPublication(quiet=1,run=1)
self.testAddSubscription1(quiet=1,run=1) self.test_03_AddSubscription1(quiet=1,run=1)
self.testAddSubscription2(quiet=1,run=1) self.test_04_AddSubscription2(quiet=1,run=1)
def setupPublicationAndSubscriptionAndGid(self, quiet=0, run=run_all_test): def setupPublicationAndSubscriptionAndGid(self, quiet=0, run=1):
self.setupPublicationAndSubscription(quiet=1,run=1) self.setupPublicationAndSubscription(quiet=1,run=1)
def getGid(object): def getGid(object):
return object.getTitle() return object.getTitle()
...@@ -233,20 +233,20 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -233,20 +233,20 @@ class TestERP5SyncML(ERP5TypeTestCase):
sub1.setIdGenerator('generateNewId') sub1.setIdGenerator('generateNewId')
sub2.setIdGenerator('generateNewId') sub2.setIdGenerator('generateNewId')
def testGetSynchronizationList(self, quiet=0, run=run_all_test): def test_05_GetSynchronizationList(self, quiet=0, run=run_all_test):
# This test the getSynchronizationList, ie, # This test the getSynchronizationList, ie,
# We want to see if we retrieve both the subscription # We want to see if we retrieve both the subscription
# and the publication # and the publication
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest getSynchronizationList ') ZopeTestCase._print('\nTest getSynchronizationList ')
LOG('Testing... ',0,'testGetSynchronizationList') LOG('Testing... ',0,'test_05_GetSynchronizationList')
self.setupPublicationAndSubscription(quiet=1,run=1) self.setupPublicationAndSubscription(quiet=1,run=1)
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
synchronization_list = portal_sync.getSynchronizationList() synchronization_list = portal_sync.getSynchronizationList()
self.failUnless(len(synchronization_list)==self.nb_synchronization) self.failUnless(len(synchronization_list)==self.nb_synchronization)
def testGetObjectList(self, quiet=0, run=run_all_test): def test_06_GetObjectList(self, quiet=0, run=run_all_test):
""" """
This test the default getObjectList, ie, when the This test the default getObjectList, ie, when the
query is 'objectValues', and this also test if we enter query is 'objectValues', and this also test if we enter
...@@ -255,7 +255,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -255,7 +255,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest getObjectList ') ZopeTestCase._print('\nTest getObjectList ')
LOG('Testing... ',0,'testGetObjectList') LOG('Testing... ',0,'test_06_GetObjectList')
self.login() self.login()
self.setupPublicationAndSubscription(quiet=1,run=1) self.setupPublicationAndSubscription(quiet=1,run=1)
nb_person = self.populatePersonServer(quiet=1,run=1) nb_person = self.populatePersonServer(quiet=1,run=1)
...@@ -276,7 +276,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -276,7 +276,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
object_list = publication.getObjectList() object_list = publication.getObjectList()
self.failUnless(len(object_list)==1) self.failUnless(len(object_list)==1)
def testExportImport(self, quiet=0, run=run_all_test): def test_07_ExportImport(self, quiet=0, run=run_all_test):
""" """
We will try to export a person with asXML We will try to export a person with asXML
And then try to add it to another folder with a conduit And then try to add it to another folder with a conduit
...@@ -284,7 +284,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -284,7 +284,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Export and Import ') ZopeTestCase._print('\nTest Export and Import ')
LOG('Testing... ',0,'testExportImport') LOG('Testing... ',0,'test_07_ExportImport')
self.login() self.login()
self.populatePersonServer(quiet=1,run=1) self.populatePersonServer(quiet=1,run=1)
person_server = self.getPersonServer() person_server = self.getPersonServer()
...@@ -303,7 +303,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -303,7 +303,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
c_local_role = person_client1.get_local_roles() c_local_role = person_client1.get_local_roles()
self.assertEqual(s_local_role,c_local_role) self.assertEqual(s_local_role,c_local_role)
def synchronize(self, id, run=run_all_test): def synchronize(self, id, run=1):
""" """
This just define how we synchronize, we have This just define how we synchronize, we have
to define it here because it is specific to the unit testing to define it here because it is specific to the unit testing
...@@ -334,7 +334,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -334,7 +334,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
nb_message += 1 + result['has_response'] nb_message += 1 + result['has_response']
return nb_message return nb_message
def synchronizeWithBrokenMessage(self, id, run=run_all_test): def synchronizeWithBrokenMessage(self, id, run=1):
""" """
This just define how we synchronize, we have This just define how we synchronize, we have
to define it here because it is specific to the unit testing to define it here because it is specific to the unit testing
...@@ -371,13 +371,13 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -371,13 +371,13 @@ class TestERP5SyncML(ERP5TypeTestCase):
nb_message += 1 + result['has_response'] nb_message += 1 + result['has_response']
return nb_message return nb_message
def testFirstSynchronization(self, quiet=0, run=run_all_test): def test_08_FirstSynchronization(self, quiet=0, run=run_all_test):
# We will try to populate the folder person_client1 # We will try to populate the folder person_client1
# with the data form person_server # with the data form person_server
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest First Synchronization ') ZopeTestCase._print('\nTest First Synchronization ')
LOG('Testing... ',0,'testFirstSynchronization') LOG('Testing... ',0,'test_08_FirstSynchronization')
self.login() self.login()
self.setupPublicationAndSubscription(quiet=1,run=1) self.setupPublicationAndSubscription(quiet=1,run=1)
nb_person = self.populatePersonServer(quiet=1,run=1) nb_person = self.populatePersonServer(quiet=1,run=1)
...@@ -418,13 +418,13 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -418,13 +418,13 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(person2_c.getFirstName()==self.first_name1) self.failUnless(person2_c.getFirstName()==self.first_name1)
self.failUnless(person2_c.getLastName()==self.last_name1) self.failUnless(person2_c.getLastName()==self.last_name1)
def testFirstSynchronizationWithLongLines(self, quiet=0, run=run_all_test): def test_09_FirstSynchronizationWithLongLines(self, quiet=0, run=run_all_test):
# We will try to populate the folder person_client1 # We will try to populate the folder person_client1
# with the data form person_server # with the data form person_server
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest First Synchronization With Long Lines ') ZopeTestCase._print('\nTest First Synchronization With Long Lines ')
LOG('Testing... ',0,'testFirstSynchronizationWithLongLines') LOG('Testing... ',0,'test_09_FirstSynchronizationWithLongLines')
self.login() self.login()
self.setupPublicationAndSubscription(quiet=1,run=1) self.setupPublicationAndSubscription(quiet=1,run=1)
nb_person = self.populatePersonServer(quiet=1,run=1) nb_person = self.populatePersonServer(quiet=1,run=1)
...@@ -448,13 +448,13 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -448,13 +448,13 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(person1_c.getFirstName()==long_line) self.failUnless(person1_c.getFirstName()==long_line)
self.failUnless(person1_c.getLastName()==self.last_name1) self.failUnless(person1_c.getLastName()==self.last_name1)
def testGetObjectFromGid(self, quiet=0, run=run_all_test): def test_10_GetObjectFromGid(self, quiet=0, run=run_all_test):
# We will try to get an object from a publication # We will try to get an object from a publication
# just by givin the gid # just by givin the gid
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest getObjectFromGid ') ZopeTestCase._print('\nTest getObjectFromGid ')
LOG('Testing... ',0,'testGetObjectFromGid') LOG('Testing... ',0,'test_10_GetObjectFromGid')
self.login() self.login()
self.setupPublicationAndSubscription(quiet=1,run=1) self.setupPublicationAndSubscription(quiet=1,run=1)
self.populatePersonServer(quiet=1,run=1) self.populatePersonServer(quiet=1,run=1)
...@@ -465,14 +465,14 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -465,14 +465,14 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(object is not None) self.failUnless(object is not None)
self.failUnless(object.getId()==self.id1) self.failUnless(object.getId()==self.id1)
def testGetSynchronizationState(self, quiet=0, run=run_all_test): def test_11_GetSynchronizationState(self, quiet=0, run=run_all_test):
# We will try to get the state of objects # We will try to get the state of objects
# that are just synchronized, # that are just synchronized,
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest getSynchronizationState ') ZopeTestCase._print('\nTest getSynchronizationState ')
LOG('Testing... ',0,'testGetSynchronizationState') LOG('Testing... ',0,'test_11_GetSynchronizationState')
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
person_server = self.getPersonServer() person_server = self.getPersonServer()
person1_s = person_server._getOb(self.id1) person1_s = person_server._getOb(self.id1)
...@@ -486,7 +486,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -486,7 +486,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
# for each subscriber # for each subscriber
self.checkSynchronizationStateIsSynchronized() self.checkSynchronizationStateIsSynchronized()
def checkSynchronizationStateIsSynchronized(self, quiet=0, run=run_all_test): def checkSynchronizationStateIsSynchronized(self, quiet=0, run=1):
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
person_server = self.getPersonServer() person_server = self.getPersonServer()
for person in person_server.objectValues(): for person in person_server.objectValues():
...@@ -513,7 +513,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -513,7 +513,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
for m in sub.getSignatureList(): for m in sub.getSignatureList():
self.assertEquals(m.getPartialXML(),None) self.assertEquals(m.getPartialXML(),None)
def checkSynchronizationStateIsConflict(self, quiet=0, run=run_all_test): def checkSynchronizationStateIsConflict(self, quiet=0, run=1):
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
person_server = self.getPersonServer() person_server = self.getPersonServer()
for person in person_server.objectValues(): for person in person_server.objectValues():
...@@ -540,12 +540,12 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -540,12 +540,12 @@ class TestERP5SyncML(ERP5TypeTestCase):
for state in state_list: for state in state_list:
self.failUnless(state[1]==state[0].CONFLICT) self.failUnless(state[1]==state[0].CONFLICT)
def testUpdateSimpleData(self, quiet=0, run=run_all_test): def test_12_UpdateSimpleData(self, quiet=0, run=run_all_test):
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Update Simple Data ') ZopeTestCase._print('\nTest Update Simple Data ')
LOG('Testing... ',0,'testUpdateSimpleData') LOG('Testing... ',0,'test_12_UpdateSimpleData')
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
# First we do only modification on server # First we do only modification on server
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
person_server = self.getPersonServer() person_server = self.getPersonServer()
...@@ -585,14 +585,14 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -585,14 +585,14 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(person1_c.getFirstName()==self.first_name3) self.failUnless(person1_c.getFirstName()==self.first_name3)
self.failUnless(person1_c.getDescription()==self.description3) self.failUnless(person1_c.getDescription()==self.description3)
def testGetConflictList(self, quiet=0, run=run_all_test): def test_13_GetConflictList(self, quiet=0, run=run_all_test):
# We will try to generate a conflict and then to get it # We will try to generate a conflict and then to get it
# We will also make sure it contains what we want # We will also make sure it contains what we want
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Get Conflict List ') ZopeTestCase._print('\nTest Get Conflict List ')
LOG('Testing... ',0,'testGetConflictList') LOG('Testing... ',0,'test_13_GetConflictList')
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
# First we do only modification on server # First we do only modification on server
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
person_server = self.getPersonServer() person_server = self.getPersonServer()
...@@ -613,14 +613,14 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -613,14 +613,14 @@ class TestERP5SyncML(ERP5TypeTestCase):
subscriber = conflict.getSubscriber() subscriber = conflict.getSubscriber()
self.failUnless(subscriber.getSubscriptionUrl()==self.subscription_url1) self.failUnless(subscriber.getSubscriptionUrl()==self.subscription_url1)
def testGetPublisherAndSubscriberDocument(self, quiet=0, run=run_all_test): def test_14_GetPublisherAndSubscriberDocument(self, quiet=0, run=run_all_test):
# We will try to generate a conflict and then to get it # We will try to generate a conflict and then to get it
# We will also make sure it contains what we want # We will also make sure it contains what we want
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Get Publisher And Subscriber Document ') ZopeTestCase._print('\nTest Get Publisher And Subscriber Document ')
LOG('Testing... ',0,'testGetPublisherAndSubscriberDocument') LOG('Testing... ',0,'test_14_GetPublisherAndSubscriberDocument')
self.testGetConflictList(quiet=1,run=1) self.test_13_GetConflictList(quiet=1,run=1)
# First we do only modification on server # First we do only modification on server
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
person_server = self.getPersonServer() person_server = self.getPersonServer()
...@@ -634,14 +634,14 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -634,14 +634,14 @@ class TestERP5SyncML(ERP5TypeTestCase):
subscriber_document = conflict.getSubscriberDocument() subscriber_document = conflict.getSubscriberDocument()
self.failUnless(subscriber_document.getDescription()==self.description3) self.failUnless(subscriber_document.getDescription()==self.description3)
def testApplyPublisherValue(self, quiet=0, run=run_all_test): def test_15_ApplyPublisherValue(self, quiet=0, run=run_all_test):
# We will try to generate a conflict and then to get it # We will try to generate a conflict and then to get it
# We will also make sure it contains what we want # We will also make sure it contains what we want
if not run: return if not run: return
self.testGetConflictList(quiet=1,run=1) self.test_13_GetConflictList(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Apply Publisher Value ') ZopeTestCase._print('\nTest Apply Publisher Value ')
LOG('Testing... ',0,'testApplyPublisherValue') LOG('Testing... ',0,'test_15_ApplyPublisherValue')
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
conflict_list = portal_sync.getConflictList() conflict_list = portal_sync.getConflictList()
conflict = conflict_list[0] conflict = conflict_list[0]
...@@ -657,16 +657,16 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -657,16 +657,16 @@ class TestERP5SyncML(ERP5TypeTestCase):
conflict_list = portal_sync.getConflictList() conflict_list = portal_sync.getConflictList()
self.failUnless(len(conflict_list)==0) self.failUnless(len(conflict_list)==0)
def testApplySubscriberValue(self, quiet=0, run=run_all_test): def test_16_ApplySubscriberValue(self, quiet=0, run=run_all_test):
# We will try to generate a conflict and then to get it # We will try to generate a conflict and then to get it
# We will also make sure it contains what we want # We will also make sure it contains what we want
if not run: return if not run: return
self.testGetConflictList(quiet=1,run=1) self.test_13_GetConflictList(quiet=1,run=1)
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
conflict_list = portal_sync.getConflictList() conflict_list = portal_sync.getConflictList()
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Apply Subscriber Value ') ZopeTestCase._print('\nTest Apply Subscriber Value ')
LOG('Testing... ',0,'testApplySubscriberValue') LOG('Testing... ',0,'test_16_ApplySubscriberValue')
conflict = conflict_list[0] conflict = conflict_list[0]
person_server = self.getPersonServer() person_server = self.getPersonServer()
person1_s = person_server._getOb(self.id1) person1_s = person_server._getOb(self.id1)
...@@ -715,17 +715,17 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -715,17 +715,17 @@ class TestERP5SyncML(ERP5TypeTestCase):
len_path = len(sub_sub_person2.getPhysicalPath()) - 3 len_path = len(sub_sub_person2.getPhysicalPath()) - 3
self.failUnless(len_path==3) self.failUnless(len_path==3)
def testAddSubObject(self, quiet=0, run=run_all_test): def test_17_AddSubObject(self, quiet=0, run=run_all_test):
""" """
In this test, we synchronize, then add sub object on the In this test, we synchronize, then add sub object on the
server and then see if the next synchronization will also server and then see if the next synchronization will also
create sub-objects on the client create sub-objects on the client
""" """
if not run: return if not run: return
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Add Sub Object ') ZopeTestCase._print('\nTest Add Sub Object ')
LOG('Testing... ',0,'testAddSubObject') LOG('Testing... ',0,'test_17_AddSubObject')
self.populatePersonServerWithSubObject(quiet=1,run=1) self.populatePersonServerWithSubObject(quiet=1,run=1)
self.synchronize(self.sub_id1) self.synchronize(self.sub_id1)
self.synchronize(self.sub_id2) self.synchronize(self.sub_id2)
...@@ -747,7 +747,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -747,7 +747,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(sub_sub_person2.getFirstName()==self.first_name2) self.failUnless(sub_sub_person2.getFirstName()==self.first_name2)
self.failUnless(sub_sub_person2.getLastName()==self.last_name2) self.failUnless(sub_sub_person2.getLastName()==self.last_name2)
def testUpdateSubObject(self, quiet=0, run=run_all_test): def test_18_UpdateSubObject(self, quiet=0, run=run_all_test):
""" """
In this test, we start with a tree of object already In this test, we start with a tree of object already
synchronized, then we update a subobject, and we will see synchronized, then we update a subobject, and we will see
...@@ -756,10 +756,10 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -756,10 +756,10 @@ class TestERP5SyncML(ERP5TypeTestCase):
the client and the server by the same time the client and the server by the same time
""" """
if not run: return if not run: return
self.testAddSubObject(quiet=1,run=1) self.test_17_AddSubObject(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Update Sub Object ') ZopeTestCase._print('\nTest Update Sub Object ')
LOG('Testing... ',0,'testUpdateSubObject') LOG('Testing... ',0,'test_18_UpdateSubObject')
person_client1 = self.getPersonClient1() person_client1 = self.getPersonClient1()
person1_c = person_client1._getOb(self.id1) person1_c = person_client1._getOb(self.id1)
sub_person1_c = person1_c._getOb(self.id1) sub_person1_c = person1_c._getOb(self.id1)
...@@ -777,17 +777,17 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -777,17 +777,17 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(sub_sub_person_s.getDescription()==self.description3) self.failUnless(sub_sub_person_s.getDescription()==self.description3)
self.failUnless(sub_sub_person_s.getFirstName()==self.first_name3) self.failUnless(sub_sub_person_s.getFirstName()==self.first_name3)
def testDeleteObject(self, quiet=0, run=run_all_test): def test_19_DeleteObject(self, quiet=0, run=run_all_test):
""" """
We will do a first synchronization, then delete an object on both We will do a first synchronization, then delete an object on both
sides, and we will see if nothing is left on the server and also sides, and we will see if nothing is left on the server and also
on the two clients on the two clients
""" """
if not run: return if not run: return
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Delete Object ') ZopeTestCase._print('\nTest Delete Object ')
LOG('Testing... ',0,'testDeleteObject') LOG('Testing... ',0,'test_19_DeleteObject')
person_server = self.getPersonServer() person_server = self.getPersonServer()
person_server.manage_delObjects(self.id1) person_server.manage_delObjects(self.id1)
person_client1 = self.getPersonClient1() person_client1 = self.getPersonClient1()
...@@ -803,7 +803,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -803,7 +803,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(len(subscription1.getObjectList())==0) self.failUnless(len(subscription1.getObjectList())==0)
self.failUnless(len(subscription2.getObjectList())==0) self.failUnless(len(subscription2.getObjectList())==0)
def testDeleteSubObject(self, quiet=0, run=run_all_test): def test_20_DeleteSubObject(self, quiet=0, run=run_all_test):
""" """
We will do a first synchronization, then delete a sub-object on both We will do a first synchronization, then delete a sub-object on both
sides, and we will see if nothing is left on the server and also sides, and we will see if nothing is left on the server and also
...@@ -816,10 +816,10 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -816,10 +816,10 @@ class TestERP5SyncML(ERP5TypeTestCase):
- id2 - id2
""" """
if not run: return if not run: return
self.testAddSubObject(quiet=1,run=1) self.test_17_AddSubObject(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Delete Sub Object ') ZopeTestCase._print('\nTest Delete Sub Object ')
LOG('Testing... ',0,'testDeleteSubObject') LOG('Testing... ',0,'test_20_DeleteSubObject')
person_server = self.getPersonServer() person_server = self.getPersonServer()
sub_object_s = person_server._getOb(self.id1)._getOb(self.id1) sub_object_s = person_server._getOb(self.id1)._getOb(self.id1)
sub_object_s.manage_delObjects(self.id1) sub_object_s.manage_delObjects(self.id1)
...@@ -836,16 +836,16 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -836,16 +836,16 @@ class TestERP5SyncML(ERP5TypeTestCase):
len_c2 = len(sub_object_c2.objectValues()) len_c2 = len(sub_object_c2.objectValues())
self.failUnless(len_s==len_c1==len_c2==0) self.failUnless(len_s==len_c1==len_c2==0)
def testGetConflictListOnSubObject(self, quiet=0, run=run_all_test): def test_21_GetConflictListOnSubObject(self, quiet=0, run=run_all_test):
""" """
We will change several attributes on a sub object on both the server We will change several attributes on a sub object on both the server
and a client, then we will see if we have correctly the conflict list and a client, then we will see if we have correctly the conflict list
""" """
if not run: return if not run: return
self.testAddSubObject(quiet=1,run=1) self.test_17_AddSubObject(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Get Conflict List On Sub Object ') ZopeTestCase._print('\nTest Get Conflict List On Sub Object ')
LOG('Testing... ',0,'testGetConflictListOnSubObject') LOG('Testing... ',0,'test_21_GetConflictListOnSubObject')
person_server = self.getPersonServer() person_server = self.getPersonServer()
object_s = person_server._getOb(self.id1) object_s = person_server._getOb(self.id1)
sub_object_s = object_s._getOb(self.id1) sub_object_s = object_s._getOb(self.id1)
...@@ -869,16 +869,16 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -869,16 +869,16 @@ class TestERP5SyncML(ERP5TypeTestCase):
conflict_list = portal_sync.getConflictList(sub_object_s) conflict_list = portal_sync.getConflictList(sub_object_s)
self.failUnless(len(conflict_list)==2) self.failUnless(len(conflict_list)==2)
def testApplyPublisherDocumentOnSubObject(self, quiet=0, run=run_all_test): def test_22_ApplyPublisherDocumentOnSubObject(self, quiet=0, run=run_all_test):
""" """
there's several conflict on a sub object, we will see if we can there's several conflict on a sub object, we will see if we can
correctly have the publisher version of this document correctly have the publisher version of this document
""" """
if not run: return if not run: return
self.testGetConflictListOnSubObject(quiet=1,run=1) self.test_21_GetConflictListOnSubObject(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Apply Publisher Document On Sub Object ') ZopeTestCase._print('\nTest Apply Publisher Document On Sub Object ')
LOG('Testing... ',0,'testApplyPublisherDocumentOnSubObject') LOG('Testing... ',0,'test_22_ApplyPublisherDocumentOnSubObject')
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
conflict_list = portal_sync.getConflictList() conflict_list = portal_sync.getConflictList()
conflict = conflict_list[0] conflict = conflict_list[0]
...@@ -899,16 +899,16 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -899,16 +899,16 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(sub_object_c2.getDescription()==self.description2) self.failUnless(sub_object_c2.getDescription()==self.description2)
self.failUnless(sub_object_c2.getLanguage()==self.lang2) self.failUnless(sub_object_c2.getLanguage()==self.lang2)
def testApplySubscriberDocumentOnSubObject(self, quiet=0, run=run_all_test): def test_23_ApplySubscriberDocumentOnSubObject(self, quiet=0, run=run_all_test):
""" """
there's several conflict on a sub object, we will see if we can there's several conflict on a sub object, we will see if we can
correctly have the subscriber version of this document correctly have the subscriber version of this document
""" """
if not run: return if not run: return
self.testGetConflictListOnSubObject(quiet=1,run=1) self.test_21_GetConflictListOnSubObject(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Apply Subscriber Document On Sub Object ') ZopeTestCase._print('\nTest Apply Subscriber Document On Sub Object ')
LOG('Testing... ',0,'testApplySubscriberDocumentOnSubObject') LOG('Testing... ',0,'test_23_ApplySubscriberDocumentOnSubObject')
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
conflict_list = portal_sync.getConflictList() conflict_list = portal_sync.getConflictList()
conflict = conflict_list[0] conflict = conflict_list[0]
...@@ -929,7 +929,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -929,7 +929,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(sub_object_c2.getDescription()==self.description3) self.failUnless(sub_object_c2.getDescription()==self.description3)
self.failUnless(sub_object_c2.getLanguage()==self.lang3) self.failUnless(sub_object_c2.getLanguage()==self.lang3)
def testSynchronizeWithStrangeGid(self, quiet=0, run=run_all_test): def test_24_SynchronizeWithStrangeGid(self, quiet=0, run=run_all_test):
""" """
By default, the synchronization process use the id in order to By default, the synchronization process use the id in order to
recognize objects (because by default, getGid==getId. Here, we will see recognize objects (because by default, getGid==getId. Here, we will see
...@@ -938,7 +938,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -938,7 +938,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Synchronize With Strange Gid ') ZopeTestCase._print('\nTest Synchronize With Strange Gid ')
LOG('Testing... ',0,'testSynchronizeWithStrangeGid') LOG('Testing... ',0,'test_24_SynchronizeWithStrangeGid')
self.login() self.login()
self.setupPublicationAndSubscriptionAndGid(quiet=1,run=1) self.setupPublicationAndSubscriptionAndGid(quiet=1,run=1)
nb_person = self.populatePersonServer(quiet=1,run=1) nb_person = self.populatePersonServer(quiet=1,run=1)
...@@ -976,16 +976,16 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -976,16 +976,16 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(person_s.getDescription()==self.description3) self.failUnless(person_s.getDescription()==self.description3)
self.failUnless(person_c1.getDescription()==self.description3) self.failUnless(person_c1.getDescription()==self.description3)
def testMultiNodeConflict(self, quiet=0, run=run_all_test): def test_25_MultiNodeConflict(self, quiet=0, run=run_all_test):
""" """
We will create conflicts with 3 differents nodes, and we will We will create conflicts with 3 differents nodes, and we will
solve it by taking one full version of documents. solve it by taking one full version of documents.
""" """
if not run: return if not run: return
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Multi Node Conflict ') ZopeTestCase._print('\nTest Multi Node Conflict ')
LOG('Testing... ',0,'testMultiNodeConflict') LOG('Testing... ',0,'test_25_MultiNodeConflict')
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
person_server = self.getPersonServer() person_server = self.getPersonServer()
person1_s = person_server._getOb(self.id1) person1_s = person_server._getOb(self.id1)
...@@ -1041,17 +1041,17 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -1041,17 +1041,17 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(person1_c2.getFormat()==self.format4) self.failUnless(person1_c2.getFormat()==self.format4)
def testSynchronizeWorkflowHistory(self, quiet=0, run=run_all_test): def test_26_SynchronizeWorkflowHistory(self, quiet=0, run=run_all_test):
""" """
We will do a synchronization, then we will edit two times We will do a synchronization, then we will edit two times
the object on the server, then two times the object on the the object on the server, then two times the object on the
client, and see if the global history as 4 more actions. client, and see if the global history as 4 more actions.
""" """
if not run: return if not run: return
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Synchronize WorkflowHistory ') ZopeTestCase._print('\nTest Synchronize WorkflowHistory ')
LOG('Testing... ',0,'testSynchronizeWorkflowHistory') LOG('Testing... ',0,'test_26_SynchronizeWorkflowHistory')
person_server = self.getPersonServer() person_server = self.getPersonServer()
person1_s = person_server._getOb(self.id1) person1_s = person_server._getOb(self.id1)
person_client1 = self.getPersonClient1() person_client1 = self.getPersonClient1()
...@@ -1068,16 +1068,16 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -1068,16 +1068,16 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(len(person1_s.workflow_history[self.workflow_id])==len_wf+4) self.failUnless(len(person1_s.workflow_history[self.workflow_id])==len_wf+4)
self.failUnless(len(person1_c.workflow_history[self.workflow_id])==len_wf+4) self.failUnless(len(person1_c.workflow_history[self.workflow_id])==len_wf+4)
def testUpdateLocalRole(self, quiet=0, run=run_all_test): def test_27_UpdateLocalRole(self, quiet=0, run=run_all_test):
""" """
We will do a first synchronization, then modify, add and delete We will do a first synchronization, then modify, add and delete
an user role and see if it is correctly synchronized an user role and see if it is correctly synchronized
""" """
if not run: return if not run: return
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Update Local Role ') ZopeTestCase._print('\nTest Update Local Role ')
LOG('Testing... ',0,'testUpdateLocalRole') LOG('Testing... ',0,'test_27_UpdateLocalRole')
# First, Create a new user # First, Create a new user
uf = self.getPortal().acl_users uf = self.getPortal().acl_users
uf._doAddUser('jp', '', ['Manager'], []) uf._doAddUser('jp', '', ['Manager'], [])
...@@ -1101,17 +1101,17 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -1101,17 +1101,17 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.assertEqual(role_1_s,role_1_c) self.assertEqual(role_1_s,role_1_c)
self.assertEqual(role_2_s,role_2_c) self.assertEqual(role_2_s,role_2_c)
def testPartialData(self, quiet=0, run=run_all_test): def test_28_PartialData(self, quiet=0, run=run_all_test):
""" """
We will do a first synchronization, then we will do a change, then We will do a first synchronization, then we will do a change, then
we will modify the SyncCode max_line value so it we will modify the SyncCode max_line value so it
it will generate many messages it will generate many messages
""" """
if not run: return if not run: return
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Partial Data ') ZopeTestCase._print('\nTest Partial Data ')
LOG('Testing... ',0,'testPartialData') LOG('Testing... ',0,'test_28_PartialData')
previous_max_lines = SyncCode.MAX_LINES previous_max_lines = SyncCode.MAX_LINES
SyncCode.MAX_LINES = 10 SyncCode.MAX_LINES = 10
self.populatePersonServerWithSubObject(quiet=1,run=1) self.populatePersonServerWithSubObject(quiet=1,run=1)
...@@ -1136,7 +1136,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -1136,7 +1136,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.assertEquals(sub_sub_person2.getLastName(),self.last_name2) self.assertEquals(sub_sub_person2.getLastName(),self.last_name2)
SyncCode.MAX_LINES = previous_max_lines SyncCode.MAX_LINES = previous_max_lines
def testBrokenMessage(self, quiet=0, run=run_all_test): def test_29_BrokenMessage(self, quiet=0, run=run_all_test):
""" """
With http synchronization, when a message is not well With http synchronization, when a message is not well
received, then we send message again, we want to received, then we send message again, we want to
...@@ -1148,7 +1148,7 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -1148,7 +1148,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Broken Message ') ZopeTestCase._print('\nTest Broken Message ')
LOG('Testing... ',0,'testBrokenMessage') LOG('Testing... ',0,'test_29_BrokenMessage')
previous_max_lines = SyncCode.MAX_LINES previous_max_lines = SyncCode.MAX_LINES
SyncCode.MAX_LINES = 10 SyncCode.MAX_LINES = 10
self.setupPublicationAndSubscription(quiet=1,run=1) self.setupPublicationAndSubscription(quiet=1,run=1)
...@@ -1172,14 +1172,14 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -1172,14 +1172,14 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.failUnless(person1_c.getLastName()==self.last_name1) self.failUnless(person1_c.getLastName()==self.last_name1)
SyncCode.MAX_LINES = previous_max_lines SyncCode.MAX_LINES = previous_max_lines
def testGetSynchronizationType(self, quiet=0, run=run_all_test): def test_30_GetSynchronizationType(self, quiet=0, run=run_all_test):
# We will try to update some simple data, first # We will try to update some simple data, first
# we change on the server side, the on the client side # we change on the server side, the on the client side
if not run: return if not run: return
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Get Synchronization Type ') ZopeTestCase._print('\nTest Get Synchronization Type ')
LOG('Testing... ',0,'testGetSynchronizationType') LOG('Testing... ',0,'test_30_GetSynchronizationType')
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
# First we do only modification on server # First we do only modification on server
# Check for each subsription that the synchronization type # Check for each subsription that the synchronization type
# is TWO WAY # is TWO WAY
...@@ -1209,16 +1209,16 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -1209,16 +1209,16 @@ class TestERP5SyncML(ERP5TypeTestCase):
for sub in portal_sync.getSubscriptionList(): for sub in portal_sync.getSubscriptionList():
self.assertEquals(sub.getSynchronizationType(),SyncCode.TWO_WAY) self.assertEquals(sub.getSynchronizationType(),SyncCode.TWO_WAY)
def testUpdateLocalPermission(self, quiet=0, run=run_all_test): def test_31_UpdateLocalPermission(self, quiet=0, run=run_all_test):
""" """
We will do a first synchronization, then modify, add and delete We will do a first synchronization, then modify, add and delete
an user role and see if it is correctly synchronized an user role and see if it is correctly synchronized
""" """
if not run: return if not run: return
self.testFirstSynchronization(quiet=1,run=1) self.test_08_FirstSynchronization(quiet=1,run=1)
if not quiet: if not quiet:
ZopeTestCase._print('\nTest Update Local Permission ') ZopeTestCase._print('\nTest Update Local Permission ')
LOG('Testing... ',0,'testUpdateLocalPermission') LOG('Testing... ',0,'test_31_UpdateLocalPermission')
# then create roles # then create roles
person_server = self.getPersonServer() person_server = self.getPersonServer()
person1_s = person_server._getOb(self.id1) person1_s = person_server._getOb(self.id1)
...@@ -1249,9 +1249,64 @@ class TestERP5SyncML(ERP5TypeTestCase): ...@@ -1249,9 +1249,64 @@ class TestERP5SyncML(ERP5TypeTestCase):
self.assertEqual(role_1_s,role_1_c) self.assertEqual(role_1_s,role_1_c)
self.assertEqual(role_2_s,role_2_c) self.assertEqual(role_2_s,role_2_c)
# We may add a test in order to check if the slow_sync mode works fine, ie def test_32_AddOneWaySubscription(self, quiet=0, run=1):
# if we do have both object on the client and server side, we must make sure if not run: return
# that the server first sends is own data if not quiet:
ZopeTestCase._print('\nTest Add One Way Subscription ')
LOG('Testing... ',0,'test_32_AddOneWaySubscription')
portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool()
portal_sync.manage_addSubscription(self.sub_id1,self.publication_url,
self.subscription_url1,'/%s/person_client1' % portal_id,'objectValues',
'','ERP5Conduit','')
sub = portal_sync.getSubscription(self.sub_id1)
#sub.setOneWaySyncFromServer(1)
self.failUnless(sub is not None)
def test_33_OneWaySync(self, quiet=0, run=1):
"""
We will test if we can synchronize only from to server to the client.
We want to make sure in this case that all modifications on the client
will not be taken into account.
"""
if not run: return
if not quiet:
ZopeTestCase._print('\nTest One Way Sync ')
LOG('Testing... ',0,'test_33_OneWaySync')
self.test_02_AddPublication(quiet=1,run=1)
self.test_32_AddOneWaySubscription(quiet=1,run=1)
nb_person = self.populatePersonServer(quiet=1,run=1)
portal_sync = self.getSynchronizationTool()
for sub in portal_sync.getSubscriptionList():
self.assertEquals(sub.getSynchronizationType(),SyncCode.SLOW_SYNC)
# First do the sync from the server to the client
nb_message1 = self.synchronize(self.sub_id1)
for sub in portal_sync.getSubscriptionList():
self.assertEquals(sub.getSynchronizationType(),SyncCode.TWO_WAY)
self.assertEquals(nb_message1,self.nb_message_first_synchronization)
subscription1 = portal_sync.getSubscription(self.sub_id1)
self.assertEquals(len(subscription1.getObjectList()),nb_person)
person_server = self.getPersonServer() # We also check we don't
# modify initial ob
person1_s = person_server._getOb(self.id1)
self.failUnless(person1_s.getId()==self.id1)
self.failUnless(person1_s.getFirstName()==self.first_name1)
self.failUnless(person1_s.getLastName()==self.last_name1)
person_client1 = self.getPersonClient1()
person1_c = person_client1._getOb(self.id1)
self.failUnless(person1_c.getId()==self.id1)
self.failUnless(person1_c.getFirstName()==self.first_name1)
self.failUnless(person1_c.getLastName()==self.last_name1)
# Then we change things on both sides and we look if there
# is synchronization from only one way
person1_c.setFirstName(self.first_name2)
person1_s.setLastName(self.last_name2)
nb_message1 = self.synchronize(self.sub_id1)
self.assertEquals(person1_c.getLastName(),self.last_name2)
self.assertEquals(person1_s.getFirstName(),self.first_name1)
if __name__ == '__main__': if __name__ == '__main__':
framework() framework()
......
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