diff --git a/product/ERP5/Document/Inventory.py b/product/ERP5/Document/Inventory.py index 724022491898e633dbf76cc4e38a906d7eaf84a2..6049ad001b479d5bf6d27181d49e35fbb24611ff 100644 --- a/product/ERP5/Document/Inventory.py +++ b/product/ERP5/Document/Inventory.py @@ -72,76 +72,147 @@ class Inventory(Delivery): def immediateReindexObject(self,temp_constructor=None,**kw): """ Rewrite reindexObject so that we can insert lines in stock table - to make sure all stock values for resources in this inventory - is equal to null before the date of this inventory + which will be equal to the difference between stock values for + resource in the inventory and the one before the date of this inventory temp_constructor is used in some particular cases where we want to have our own temp object constructor, this is usefull if we want to use some classes with some particular methods """ + sql_catalog_id = kw.pop("sql_catalog_id", None) + disable_archive = kw.pop("disable_archive", 0) + connection_id = None + if sql_catalog_id is not None: + # try to get connection used in the catalog + catalog = self.portal_catalog[sql_catalog_id] + for method in catalog.objectValues(): + if method.meta_type == "Z SQL Method": + if 'deferred' not in method.connection_id \ + and 'transactionless' not in method.connection_id: + connection_id = method.connection_id + break + resource_and_variation_dict = {} stock_object_list = [] + stock_append = stock_object_list.append if temp_constructor is None: from Products.ERP5Type.Document import newTempDeliveryLine temp_constructor = newTempDeliveryLine start_date = self.getStartDate() node = self.getDestination() - portal_simulation = self.getPortalObject().portal_simulation - current_inventory_list = portal_simulation.getInventoryList( \ + # build a dict containing all inventory for this node group by resource/variation + # and then subvariation + current_inventory_list = self.getPortalObject().portal_simulation.getInventoryList( \ to_date = start_date - , node = node - , simulation_state = self.getPortalCurrentInventoryStateList() - , group_by_sub_variation = 1 - , group_by_variation = 1 - , group_by_resource = 1 - ) + , node = node + , simulation_state = self.getPortalCurrentInventoryStateList() + , group_by_sub_variation = 1 + , group_by_variation = 1 + , group_by_resource = 1 + , group_by_payment = 1 + , connection_id = connection_id + ) current_inventory_dict = {} current_inventory_key_id_list = ('resource_relative_url', 'variation_text') for line in current_inventory_list: current_inventory_key = tuple([line[x] for x in current_inventory_key_id_list]) + if current_inventory_key[1] == None: + # To be consistent + current_inventory_key = (current_inventory_key[0], "") try: current_inventory_by_sub_variation = current_inventory_dict[current_inventory_key] except KeyError: current_inventory_by_sub_variation = current_inventory_dict[current_inventory_key] = {} current_inventory_by_sub_variation[line['sub_variation_text']] = line['total_quantity'] + def getCurrentInventoryBySubVariation(**criterion_dict): current_inventory_key = tuple([criterion_dict[x] for x in current_inventory_key_id_list]) return current_inventory_dict.get(current_inventory_key, {}) + # Browse all movements on inventory and create diff line when necessary + not_used_inventory_dict = {} + inventory_uid = self.getUid() + inventory_id = self.getId() for movement in self.getMovementList(): if movement.getResourceValue() is not None and movement.getQuantity() not in (None,''): resource_path = movement.getResource() variation_text = movement.getVariationText() + movement_quantity = movement.getQuantity() + destination_payment_path = movement.getDestinationPayment() resource_and_variation_key = (resource_path, variation_text) - if resource_and_variation_key not in resource_and_variation_dict: - resource_and_variation_dict[resource_and_variation_key] = None - kwd = {'uid':self.getUid(), - 'start_date': start_date} - variation_list = variation_text.split('\n') - inventory_by_subvariation_dict = getCurrentInventoryBySubVariation( + inventory_by_subvariation_dict = getCurrentInventoryBySubVariation( resource_relative_url=resource_path, variation_text=variation_text) - for sub_variation_text, total_quantity in inventory_by_subvariation_dict.iteritems(): + movement_sub_variation_text = movement.getSubVariationText() + # Check wath is the quantity difference + if movement_sub_variation_text in inventory_by_subvariation_dict.keys(): + total_quantity = inventory_by_subvariation_dict.pop(movement_sub_variation_text) + # Put remaining subvariation in a dict to know which one to removed at end + not_used_inventory_dict[resource_and_variation_key] = inventory_by_subvariation_dict + diff_quantity = movement_quantity - total_quantity + else: + # Inventory for new resource/variation/sub_variation + diff_quantity = movement_quantity + # Put remaining subvariation in a dict to know which one to removed at end + not_used_inventory_dict[resource_and_variation_key] = inventory_by_subvariation_dict + + # Create tmp movement with only diff between inventory + # and previous stock values + if diff_quantity != 0: + kwd = {'uid':inventory_uid, + 'start_date': start_date} + if variation_text is not None: + variation_list = variation_text.split('\n') + else: + variation_list = [] + category_list = self.getCategoryList() sub_variation_list = [] - if sub_variation_text is not None: + if movement_sub_variation_text is not None: + sub_variation_list = movement_sub_variation_text.split('\n') + temp_delivery_line = temp_constructor(self, + inventory_id) + kwd['quantity'] = diff_quantity + category_list.append('resource/%s' % resource_path) + category_list.append('destination_payment/%s' % destination_payment_path) + category_list.extend(variation_list) + category_list.extend(sub_variation_list) + kwd['category_list'] = category_list + temp_delivery_line.edit(**kwd) + stock_append(temp_delivery_line) + + # Now create line to remove some subvariation text not present in new inventory + for resource_and_variation_key in not_used_inventory_dict.keys(): + inventory_by_subvariation_dict = not_used_inventory_dict[resource_and_variation_key] + for sub_variation_text in inventory_by_subvariation_dict.keys(): + if sub_variation_text not in (None, ""): # XXX maybe also need to removed those one + category_list = self.getCategoryList() + quantity = inventory_by_subvariation_dict[sub_variation_text] + resource_path, variation_text = resource_and_variation_key + kwd = {'uid':inventory_uid, + 'start_date': start_date} + if variation_text is not None: + variation_list = variation_text.split('\n') + else: + variation_list = [] sub_variation_list = sub_variation_text.split('\n') - category_list = self.getCategoryList() - if total_quantity != 0: + diff_quantity = - quantity temp_delivery_line = temp_constructor(self, - self.getId()) - kwd['quantity'] = - total_quantity + inventory_id) + kwd['quantity'] = diff_quantity category_list.append('resource/%s' % resource_path) category_list.extend(variation_list) category_list.extend(sub_variation_list) kwd['category_list'] = category_list temp_delivery_line.edit(**kwd) - stock_object_list.append(temp_delivery_line) + stock_append(temp_delivery_line) + + # Reindex objects object_list = [self] - self.portal_catalog.catalogObjectList(object_list) + self.portal_catalog.catalogObjectList(object_list, disable_archive=disable_archive) if len(stock_object_list)==0: # Make sure to remove all lines from Products.ERP5Type.Document import newTempBase - stock_object_list.append(temp_constructor(self,self.getId(), - uid=self.getUid())) + stock_append(temp_constructor(self,inventory_id, + uid=inventory_uid)) self.portal_catalog.catalogObjectList(stock_object_list, method_id_list=('z_catalog_stock_list',), - disable_cache=1,check_uid=0) + disable_cache=1,check_uid=0, disable_archive=disable_archive) diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_stock_list.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_stock_list.xml index fc11b1bc52315aa42b9085baf7a274286edb860c..8fb6b9194a91bbda80cc0efffc7801556009634d 100644 --- a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_stock_list.xml +++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_stock_list.xml @@ -3,11 +3,8 @@ <record id="1" aka="AAAAAAAAAAE="> <pickle> <tuple> - <tuple> - <string>Products.ZSQLMethods.SQL</string> - <string>SQL</string> - </tuple> - <none/> + <global name="SQL" module="Products.ZSQLMethods.SQL"/> + <tuple/> </tuple> </pickle> <pickle> @@ -158,6 +155,12 @@ <dictionary/> </value> </item> + <item> + <key> <string>isInventoryMovement</string> </key> + <value> + <dictionary/> + </value> + </item> <item> <key> <string>isMovement</string> </key> <value> @@ -177,29 +180,30 @@ <key> <string>_keys</string> </key> <value> <list> - <string>uid</string> - <string>getResourceUid</string> - <string>getInventoriatedQuantity</string> - <string>getSourceUid</string> - <string>getDestinationUid</string> - <string>getSourceSectionUid</string> - <string>getDestinationSectionUid</string> - <string>isMovement</string> - <string>getSourcePaymentUid</string> - <string>getDestinationPaymentUid</string> - <string>getSourceFunctionUid</string> - <string>getDestinationFunctionUid</string> - <string>getSourceProjectUid</string> - <string>getDestinationProjectUid</string> - <string>getSimulationState</string> - <string>getSourceInventoriatedTotalAssetPrice</string> - <string>getDestinationInventoriatedTotalAssetPrice</string> - <string>getStartDate</string> - <string>getStopDate</string> - <string>isAccountable</string> - <string>getPortalType</string> - <string>getVariationText</string> - <string>getSubVariationText</string> +<string>uid</string> +<string>getResourceUid</string> +<string>getInventoriatedQuantity</string> +<string>getSourceUid</string> +<string>getDestinationUid</string> +<string>getSourceSectionUid</string> +<string>getDestinationSectionUid</string> +<string>isMovement</string> +<string>isInventoryMovement</string> +<string>getSourcePaymentUid</string> +<string>getDestinationPaymentUid</string> +<string>getSourceFunctionUid</string> +<string>getDestinationFunctionUid</string> +<string>getSourceProjectUid</string> +<string>getDestinationProjectUid</string> +<string>getSimulationState</string> +<string>getSourceInventoriatedTotalAssetPrice</string> +<string>getDestinationInventoriatedTotalAssetPrice</string> +<string>getStartDate</string> +<string>getStopDate</string> +<string>isAccountable</string> +<string>getPortalType</string> +<string>getVariationText</string> +<string>getSubVariationText</string> </list> </value> </item> @@ -224,6 +228,7 @@ getDestinationUid\r\n getSourceSectionUid\r\n getDestinationSectionUid\r\n isMovement\r\n +isInventoryMovement\r\n getSourcePaymentUid\r\n getDestinationPaymentUid\r\n getSourceFunctionUid\r\n @@ -291,6 +296,7 @@ WHERE\n <dtml-let row_list="[]">\n <dtml-in prefix="loop" expr="_.range(_.len(uid))">\n <dtml-if "isMovement[loop_item]">\n + <dtml-if "not isInventoryMovement[loop_item]">\n <dtml-if "isAccountable[loop_item]">\n <dtml-if "getResourceUid[loop_item]">\n <dtml-if "getDestinationUid[loop_item]">\n @@ -336,6 +342,7 @@ WHERE\n </dtml-if>\n </dtml-if>\n </dtml-if>\n + </dtml-if>\n </dtml-in> \n \n <dtml-if "row_list">\n @@ -375,9 +382,11 @@ VALUES\n <value> <object> <klass> - <global name="SQL" module="Shared.DC.ZRDB.DA"/> + <global name="__newobj__" module="copy_reg"/> </klass> - <none/> + <tuple> + <global name="SQL" module="Shared.DC.ZRDB.DA"/> + </tuple> <state> <dictionary> <item> @@ -417,6 +426,7 @@ WHERE\n <dtml-let row_list="[]">\n <dtml-in prefix="loop" expr="_.range(_.len(uid))">\n <dtml-if "isMovement[loop_item]">\n + <dtml-if "not isInventoryMovement[loop_item]">\n <dtml-if "isAccountable[loop_item]">\n <dtml-if "getResourceUid[loop_item]">\n <dtml-if "getDestinationUid[loop_item]">\n @@ -462,6 +472,7 @@ WHERE\n </dtml-if>\n </dtml-if>\n </dtml-if>\n + </dtml-if>\n </dtml-in> \n \n <dtml-if "row_list">\n diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/revision b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/revision index d15a2cc44e31b14c65264271b81072e5ba0e1634..d30c290ffcf10673ccdaaa233c29109552860aa4 100644 --- a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/revision +++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/revision @@ -1 +1,2 @@ -80 +85 +