From 9b2c1763a47672544588b6ba937a425b31396c8f Mon Sep 17 00:00:00 2001 From: Jean-Paul Smets <jp@nexedi.com> Date: Sun, 8 Feb 2004 19:30:40 +0000 Subject: [PATCH] Global Udate to Latest Coramy Optimizations git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@441 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/Coramy/Document/Invoice.py | 2 + product/Coramy/Document/Item.py | 22 +- product/Coramy/Document/Modele.py | 8 +- .../Coramy/skins/coramy_custom/seb_test.py | 18 +- .../Coramy/skins/coramy_custom/test_jps.py | 35 +- .../PortalSimulation_zGetResourceList.zsql | 17 +- .../SQLDict_createMessageTable.zsql | 16 +- .../skins/coramy_erp5/SQLDict_delMessage.zsql | 10 +- .../coramy_erp5/SQLDict_processMessage.zsql | 14 +- .../coramy_erp5/SQLDict_readMessage.zsql | 14 +- .../coramy_erp5/SQLDict_readMessageList.zsql | 16 +- .../coramy_erp5/SQLDict_writeMessage.zsql | 12 +- .../folder_workflow_status_modify.py | 1 + .../Delivery_zSearchResource.zsql | 2 +- .../PieceTissu_searchConsumedList.zsql | 6 +- .../PieceTissu_zGetAvailableItemList.zsql | 27 +- .../Resource_zGetAggregateList.zsql | 10 +- ...roductionOrder_getDeliveryCellPrintList.py | 50 ++- .../coramy_mrp/InventoryMP_fastAddLine.py | 2 +- .../skins/coramy_mrp/PieceTissu_fastInput.py | 4 + .../coramy_mrp/PieceTissu_fastInputRetour.py | 8 +- .../PieceTissu_searchByResource.form | 4 +- ...ortalSimulation_activateRequirementList.py | 46 +- .../PortalSimulation_buildRequirementOrder.py | 15 +- .../PortalSimulation_updateAssetPrice.py | 12 - .../Resource_zGetInventoryList.zsql | 4 +- ...ionTool_zGetCoramyFutureInventoryList.zsql | 8 +- .../coramy_mrp/ZeroStock_buildOrderList.py | 24 +- .../skins/coramy_mrp/item_tissu_list.form | 7 +- .../skins/coramy_mrp/item_tissu_view.form | 24 + ...nsformedComponent_getCorrespondanceList.py | 19 +- .../transformation_correspondances_print.pt | 2 +- .../Container_printExtandLabel.py | 2 + .../coramy_trade/Container_printMetoLabel.py | 2 + .../coramy_trade/Container_sendExtandEdi.py | 2 +- .../DeliveryLine_getTargetQuantityList.py | 25 +- .../Delivery_exportContainerList.py | 5 +- .../coramy_trade/default_pdf_template.pt | 417 +++++++++++++----- .../purchase_packing_list_view.form | 4 +- .../coramy_trade/sales_invoice_list.form | 6 +- .../coramy_trade/sales_packing_list_print.pt | 5 +- product/ERP5/Document/Amount.py | 18 +- product/ERP5/Document/Container.py | 14 + product/ERP5/Document/DeliveryCell.py | 39 +- product/ERP5/Document/InventoryCell.py | 80 +++- product/ERP5/Document/InventoryLine.py | 95 +++- product/ERP5/Document/Invoice.py | 36 +- product/ERP5/Document/Movement.py | 78 ++-- product/ERP5/Document/Order.py | 39 ++ product/ERP5/Document/PackingList.py | 1 + product/ERP5/Document/Resource.py | 25 +- product/ERP5/Document/Transformation.py | 2 +- product/ERP5/Document/ZeroStockRule.py | 2 +- product/ERP5/ERP5Globals.py | 3 +- product/ERP5/Extensions/InventoryBrain.py | 100 ++--- product/ERP5/Interface/__init__.py | 2 +- product/ERP5/TargetSolver/SplitAndDefer.py | 1 + product/ERP5/Variated.py | 17 +- .../sale_invoice_transaction_view.form | 4 +- product/ERP5/skins/erp5_core/base_edit.py | 5 +- .../skins/erp5_core/base_update_relation.py | 4 +- product/ERP5/skins/erp5_core/doFavorite.py | 19 +- .../skins/erp5_core/workflow_status_modify.py | 1 + .../skins/erp5_html_style/list_menu_box.pt | 4 +- .../sale_invoice_transaction_view.form | 4 +- product/ERP5Form/ListBox.py | 3 +- product/ERP5Form/PDFTemplate.py | 4 +- product/ERP5Form/SelectionTool.py | 8 + product/ERP5Type/ZopePatch.py | 2 + product/ZSQLCatalog/SQLCatalog.py | 2 +- product/ZSQLCatalog/zsqlbrain.py | 18 +- 71 files changed, 1123 insertions(+), 434 deletions(-) diff --git a/product/Coramy/Document/Invoice.py b/product/Coramy/Document/Invoice.py index 08e30b3bd8..4ce28ca855 100755 --- a/product/Coramy/Document/Invoice.py +++ b/product/Coramy/Document/Invoice.py @@ -60,7 +60,9 @@ class Invoice(ERP5Invoice): , PropertySheet.Movement , PropertySheet.Amount , PropertySheet.Reference + , PropertySheet.TradeCondition , PropertySheet.PaymentCondition + , PropertySheet.Comment ) # Factory Type Information diff --git a/product/Coramy/Document/Item.py b/product/Coramy/Document/Item.py index 108b1211c3..e15c08c7f8 100755 --- a/product/Coramy/Document/Item.py +++ b/product/Coramy/Document/Item.py @@ -155,4 +155,24 @@ Un item sert a assurer la tracabilite des choses dans ERP5.""" sub_quantity = 0 for sub_item in sub_item_list : sub_quantity += sub_item.getQuantity() - return self.getQuantity() - sub_quantity \ No newline at end of file + return self.getQuantity() - sub_quantity + + security.declareProtected(Permissions.ModifyPortalContent, 'getLastLocationTitle') + def getLastLocationTitle(self): + """ + Returns the last location of this item or empty string + """ + related_movement_list = self.PieceTissu_zGetAggregateRelatedMovementList() + if len(related_movement_list) > 0 : + last_movement = related_movement_list[0] + quantity = last_movement.quantity + inventory = last_movement.inventory + if inventory is not None : + last_location_title = last_movement.destination_title + elif quantity >= 0 : + last_location_title = last_movement.destination_title + else : + last_location_title = '' + return last_location_title + else : + return '' diff --git a/product/Coramy/Document/Modele.py b/product/Coramy/Document/Modele.py index feb37a5c10..9e225269ab 100755 --- a/product/Coramy/Document/Modele.py +++ b/product/Coramy/Document/Modele.py @@ -168,8 +168,14 @@ un modele...""" """ return PRI for Modèle """ - for pri in self.contentValues({'portal_type': 'Set Mapped Value'}): + for pri in self.contentValues(filter={'portal_type': 'Set Mapped Value'}): if 'pri' in pri.getMappedValuePropertyList(): if pri.test(context): return pri.getProperty('pri') return None + + def _updateIndustrialPrice(self): + pass + #self.modele_compute_pri(batch_mode=1) + + diff --git a/product/Coramy/skins/coramy_custom/seb_test.py b/product/Coramy/skins/coramy_custom/seb_test.py index 7a0378af61..b6d812d34c 100755 --- a/product/Coramy/skins/coramy_custom/seb_test.py +++ b/product/Coramy/skins/coramy_custom/seb_test.py @@ -7,4 +7,20 @@ ##parameters= ##title= ## -return context +organisation_list = context.object_action_list(selection_name='organisations_selection') + +request = context.REQUEST +tab = '\t' +cr = '\n' +export = '' +del_list = [] + +for modele_item in organisation_list : + ligne_modele = '' + modele=modele_item.getObject() + + if int(modele.getId()) >= 726 : + del_list.append(modele.getId()) + +context.getPortalObject().organisation.deleteContent(del_list) +return len(del_list) diff --git a/product/Coramy/skins/coramy_custom/test_jps.py b/product/Coramy/skins/coramy_custom/test_jps.py index 16dcd1a079..21c2334f5e 100755 --- a/product/Coramy/skins/coramy_custom/test_jps.py +++ b/product/Coramy/skins/coramy_custom/test_jps.py @@ -7,22 +7,25 @@ ##parameters= ##title= ## -selection = context.portal_selections.getSelectionFor('purchase_packing_list_selection',REQUEST=context.REQUEST) -delivery_list = selection(context=context) -request = context.REQUEST +# Collect movements in Zero Stock applied rule +zs_movement_list = [context.portal_simulation.zero_stock['modele-137H401_coloris-modele-137H401-1_taille-adulte-52']] -for delivery_item in delivery_list: - delivery = delivery_item.getObject() +# keep only movements with a Modele resource +movement_list = [] +for movement in zs_movement_list : + try : + if movement.getResourceValue().getPortalType() == 'Modele' : + movement_list.append(movement) + except : + pass - if delivery is not None : - order_list = delivery.getCausalityValueList() - if len(order_list) > 0 : - order = order_list[0] - # what's the gestionaire of this order - user_name = '' - # are we on a sales order or puchase order ? - if order.getPortalType() == 'Purchase Order' : - user_name = order.getDestinationAdministrationPersonTitle().replace(' ','_') - delivery.assign_gestionaire_designe_roles(user_name = user_name) +# Parse movements into a root group +root_group = context.portal_simulation.collectMovement(movement_list) +order_list = context.portal_simulation.buildOrderList(root_group) -return 'fait' +# update produced orders +for order in order_list: + order.autoPlan() + order.purchase_order_apply_condition() + +return "fait" diff --git a/product/Coramy/skins/coramy_erp5/PortalSimulation_zGetResourceList.zsql b/product/Coramy/skins/coramy_erp5/PortalSimulation_zGetResourceList.zsql index d5c8a69176..59d5d4579b 100755 --- a/product/Coramy/skins/coramy_erp5/PortalSimulation_zGetResourceList.zsql +++ b/product/Coramy/skins/coramy_erp5/PortalSimulation_zGetResourceList.zsql @@ -1,23 +1,16 @@ <dtml-comment> title: connection_id:MySQL -max_rows:1000 -max_cache:100 +max_rows:100000 +max_cache:0 cache_time:0 class_name: class_file: </dtml-comment> -<params>section -strict_membership</params> +<params></params> SELECT DISTINCT movement.resource_uid, + catalog.relative_url AS resource_relative_url, movement.variation_text FROM - movement, stock, catalog as section, category -WHERE - stock.uid = movement.uid -AND stock.section_uid = section.uid -AND section.uid = category.category_uid -AND category.base_category_uid = <dtml-sqlvar "portal_categories.group.getUid()" type="int"> -AND section.relative_url = <dtml-sqlvar section type="string"> -<dtml-if strict_membership>AND category.strict_membership=1</dtml-if> \ No newline at end of file + movement LEFT JOIN catalog ON (catalog.uid = movement.resource_uid) \ No newline at end of file diff --git a/product/Coramy/skins/coramy_erp5/SQLDict_createMessageTable.zsql b/product/Coramy/skins/coramy_erp5/SQLDict_createMessageTable.zsql index 79b7a07c29..890ab6a159 100755 --- a/product/Coramy/skins/coramy_erp5/SQLDict_createMessageTable.zsql +++ b/product/Coramy/skins/coramy_erp5/SQLDict_createMessageTable.zsql @@ -8,16 +8,18 @@ class_name: class_file: </dtml-comment> <params></params> -# Host: -# Database: test -# Table: 'stock' -# CREATE TABLE `message` ( + `uid` int(11) NOT NULL auto_increment, `path` VARCHAR(255), `method_id` VARCHAR(40), + `processing_node` INT DEFAULT -1, + `processing` INT DEFAULT 0, + `priority` INT DEFAULT 0, `message` BLOB, - `processing_node` INT DEFAULT NULL, + PRIMARY KEY (`uid`), KEY `path` (`path`), - KEY `processing_node` (`processing_node`), KEY `method_id` (`method_id`), -) TYPE = InnoDB; \ No newline at end of file + KEY `processing_node` (`processing_node`), + KEY `processing` (`processing`), + KEY `priority` (`priority`), +) TYPE = InnoDB; diff --git a/product/Coramy/skins/coramy_erp5/SQLDict_delMessage.zsql b/product/Coramy/skins/coramy_erp5/SQLDict_delMessage.zsql index b75a63d246..bfefd52843 100755 --- a/product/Coramy/skins/coramy_erp5/SQLDict_delMessage.zsql +++ b/product/Coramy/skins/coramy_erp5/SQLDict_delMessage.zsql @@ -7,11 +7,9 @@ cache_time:0 class_name: class_file: </dtml-comment> -<params>path -method_id</params> +<params>uid:list</params> DELETE FROM - message + message WHERE - path = <dtml-sqlvar path type="string"> -<dtml-if method_id>AND method_id = <dtml-sqlvar method_id type="string"></dtml-if> - \ No newline at end of file +<dtml-in uid>uid = <dtml-sqlvar sequence-item type="int"><dtml-if sequence-end><dtml-else> OR </dtml-if> +</dtml-in> \ No newline at end of file diff --git a/product/Coramy/skins/coramy_erp5/SQLDict_processMessage.zsql b/product/Coramy/skins/coramy_erp5/SQLDict_processMessage.zsql index 25a0c3422c..fa0e19ecd6 100755 --- a/product/Coramy/skins/coramy_erp5/SQLDict_processMessage.zsql +++ b/product/Coramy/skins/coramy_erp5/SQLDict_processMessage.zsql @@ -1,17 +1,15 @@ <dtml-comment> title: connection_id:MySQL -max_rows:1000 -max_cache:100 +max_rows:1 +max_cache:0 cache_time:0 class_name: class_file: </dtml-comment> -<params>path -method_id -processing_node</params> +<params>uid</params> UPDATE message -SET processing_node=<dtml-sqlvar processing_node type="int"> +SET processing=1 WHERE - path = <dtml-sqlvar path type="string"> -<dtml-if method_id>AND method_id = <dtml-sqlvar method_id type="string"></dtml-if> \ No newline at end of file +<dtml-in uid>uid = <dtml-sqlvar sequence-item type="int"><dtml-if sequence-end><dtml-else> + OR </dtml-if></dtml-in> \ No newline at end of file diff --git a/product/Coramy/skins/coramy_erp5/SQLDict_readMessage.zsql b/product/Coramy/skins/coramy_erp5/SQLDict_readMessage.zsql index 85d687f7a7..dcc09df313 100755 --- a/product/Coramy/skins/coramy_erp5/SQLDict_readMessage.zsql +++ b/product/Coramy/skins/coramy_erp5/SQLDict_readMessage.zsql @@ -7,8 +7,14 @@ cache_time:0 class_name: class_file: </dtml-comment> -<params></params> +<params>processing_node +priority</params> SELECT * FROM - message -WHERE - processing_node is NULL \ No newline at end of file + message +WHERE + processing <> 1 +<dtml-if processing_node> AND processing_node = <dtml-sqlvar processing_node type="int"></dtml-if> +<dtml-if priority> AND priority = <dtml-sqlvar priority type="int"> </dtml-if> + +ORDER BY + priority \ No newline at end of file diff --git a/product/Coramy/skins/coramy_erp5/SQLDict_readMessageList.zsql b/product/Coramy/skins/coramy_erp5/SQLDict_readMessageList.zsql index 8ba47984dc..b584c64a23 100755 --- a/product/Coramy/skins/coramy_erp5/SQLDict_readMessageList.zsql +++ b/product/Coramy/skins/coramy_erp5/SQLDict_readMessageList.zsql @@ -8,12 +8,16 @@ class_name: class_file: </dtml-comment> <params>path -method_id</params> +method_id +processing_node +priority</params> SELECT * FROM - message -<dtml-if "path or method_id"> + message WHERE -<dtml-if path> path = <dtml-sqlvar path type="string"></dtml-if> + processing <> 1 +<dtml-if processing_node>AND processing_node = <dtml-sqlvar processing_node type="int"> </dtml-if> +<dtml-if priority>AND priority = <dtml-sqlvar priority type="int"> </dtml-if> +<dtml-if path>AND path = <dtml-sqlvar path type="string"></dtml-if> <dtml-if method_id>AND method_id = <dtml-sqlvar method_id type="string"></dtml-if> -</dtml-if> - \ No newline at end of file +GROUP BY + path, method_id, processing_node, processing \ No newline at end of file diff --git a/product/Coramy/skins/coramy_erp5/SQLDict_writeMessage.zsql b/product/Coramy/skins/coramy_erp5/SQLDict_writeMessage.zsql index c0b07320f1..a7a9511202 100755 --- a/product/Coramy/skins/coramy_erp5/SQLDict_writeMessage.zsql +++ b/product/Coramy/skins/coramy_erp5/SQLDict_writeMessage.zsql @@ -9,7 +9,13 @@ class_file: </dtml-comment> <params>path method_id -message</params> +message +priority</params> INSERT INTO message -VALUES - (<dtml-sqlvar path type="string">,<dtml-sqlvar method_id type="string">,<dtml-sqlvar message type="string">,NULL); \ No newline at end of file +SET + path = <dtml-sqlvar path type="string">, + method_id = <dtml-sqlvar method_id type="string">, + processing_node = -1, + processing = -1, + priority = <dtml-sqlvar priority type="int">, + message = <dtml-sqlvar message type="string"> \ No newline at end of file diff --git a/product/Coramy/skins/coramy_erp5/folder_workflow_status_modify.py b/product/Coramy/skins/coramy_erp5/folder_workflow_status_modify.py index 7d3a65eb85..3cce15d2b3 100755 --- a/product/Coramy/skins/coramy_erp5/folder_workflow_status_modify.py +++ b/product/Coramy/skins/coramy_erp5/folder_workflow_status_modify.py @@ -30,6 +30,7 @@ try: action_list = o.portal_workflow.getActionsFor(o) action_list = filter(lambda x:x.has_key('id'), action_list ) action_id_list = map(lambda x:x['id'], action_list) + # If the user is not allowed to do this transition, it will not be in action_list if workflow_action in action_id_list: o.portal_workflow.doActionFor( o, diff --git a/product/Coramy/skins/coramy_list_method/Delivery_zSearchResource.zsql b/product/Coramy/skins/coramy_list_method/Delivery_zSearchResource.zsql index e32a1d7f86..0657b61692 100755 --- a/product/Coramy/skins/coramy_list_method/Delivery_zSearchResource.zsql +++ b/product/Coramy/skins/coramy_list_method/Delivery_zSearchResource.zsql @@ -11,7 +11,7 @@ class_file:zsqlbrain.py variante_id_list="" sort_on portal_type</params> -SELECT DISTINCT catalog.id, catalog.relative_url, catalog.path, catalog.Description, catalog.simulation_state, catalog.default_destination_title +SELECT DISTINCT catalog.id, catalog.uid, catalog.relative_url, catalog.path, catalog.Description, catalog.simulation_state, catalog.default_destination_title FROM catalog, catalog AS line <dtml-if expr="_.len(resource_id_list)>0"> , catalog AS resource diff --git a/product/Coramy/skins/coramy_list_method/PieceTissu_searchConsumedList.zsql b/product/Coramy/skins/coramy_list_method/PieceTissu_searchConsumedList.zsql index c6cb7d4d2b..f68a928652 100755 --- a/product/Coramy/skins/coramy_list_method/PieceTissu_searchConsumedList.zsql +++ b/product/Coramy/skins/coramy_list_method/PieceTissu_searchConsumedList.zsql @@ -20,6 +20,10 @@ AND category.base_category_uid = <dtml-var "portal_categories.aggregate.getUid() LEFT JOIN stock ON (stock.uid = category.uid) +LEFT JOIN movement +ON (movement.uid = category.uid) + WHERE item.portal_type = "Piece Tissu" AND stock.node_uid = <dtml-var "portal_categories.site.Stock_MP.Gravelines.getUid()"> -AND stock.quantity < 0 \ No newline at end of file +AND stock.quantity < 0 +AND movement.inventory IS NULL \ No newline at end of file diff --git a/product/Coramy/skins/coramy_list_method/PieceTissu_zGetAvailableItemList.zsql b/product/Coramy/skins/coramy_list_method/PieceTissu_zGetAvailableItemList.zsql index 6b29340792..ba56364ea9 100755 --- a/product/Coramy/skins/coramy_list_method/PieceTissu_zGetAvailableItemList.zsql +++ b/product/Coramy/skins/coramy_list_method/PieceTissu_zGetAvailableItemList.zsql @@ -17,6 +17,23 @@ SELECT DISTINCT item.uid, item.id, item.path, item.Description, item.simulation_state, item.default_destination_title FROM catalog AS item + +LEFT JOIN category +ON (category.category_uid=item.uid +AND category.base_category_uid = <dtml-var "portal_categories.aggregate.getUid()">) + +LEFT JOIN stock +ON (stock.uid = category.uid) + +LEFT JOIN movement +ON (movement.uid = category.uid) + +LEFT JOIN movement AS next_movement +ON (next_movement.resource_uid = movement.resource_uid +AND next_movement.variation_text = movement.variation_text +AND next_movement.start_date > movement.start_date +AND not (next_movement.inventory is NULL)) + <dtml-if expr="_.len(resource_id_list)>0"> , catalog AS resource , category AS cat1 @@ -26,9 +43,15 @@ FROM , category AS cat2 </dtml-if> -WHERE item.portal_type = "Piece Tissu" -<dtml-in PieceTissu_searchConsumedList>AND item.uid <> <dtml-sqlvar uid type="int"> +WHERE + item.portal_type = "Piece Tissu" +AND stock.node_uid = <dtml-var "portal_categories.site.Stock_MP.Gravelines.getUid()"> +AND ( stock.quantity >= 0 +OR (stock.quantity < 0 +AND not (movement.inventory is NULL) ) ) +<dtml-in PieceTissu_searchConsumedList>AND item.uid <> <dtml-sqlvar uid type="int"> </dtml-in> +AND next_movement.uid is NULL <dtml-if expr="_.len(resource_id_list)>0"> AND ( resource.id LIKE "<dtml-var expr="resource_id_list[0]">" diff --git a/product/Coramy/skins/coramy_list_method/Resource_zGetAggregateList.zsql b/product/Coramy/skins/coramy_list_method/Resource_zGetAggregateList.zsql index 3c02864110..bed12eb8ac 100755 --- a/product/Coramy/skins/coramy_list_method/Resource_zGetAggregateList.zsql +++ b/product/Coramy/skins/coramy_list_method/Resource_zGetAggregateList.zsql @@ -1,7 +1,7 @@ <dtml-comment> title: connection_id:MySQL -max_rows:1000 +max_rows:750 max_cache:100 cache_time:0 class_name:ZSQLBrain @@ -15,17 +15,15 @@ resource_uid</params> SELECT catalog.* FROM - catalog, movement, category, stock, catalog as movement_c + catalog, movement, category, stock WHERE movement.uid = category.uid +AND category.category_uid = catalog.uid +AND category.base_category_uid = <dtml-var "portal_categories.aggregate.getUid()"> AND stock.uid = movement.uid AND movement.is_accountable = 1 AND movement.resource_uid = <dtml-sqlvar resource_uid type="int"> -AND movement_c.uid = category.uid -AND category.category_uid = catalog.uid -AND category.base_category_uid = <dtml-var "portal_categories.aggregate.getUid()"> AND movement.delivery_uid = <dtml-sqlvar explanation_uid type="int"> AND movement.variation_text = <dtml-sqlvar variation_text type="string"> AND stock.node_uid = <dtml-sqlvar node_uid type="int"> AND stock.section_uid = <dtml-sqlvar section_uid type="int"> -AND movement.variation_text = <dtml-sqlvar variation_text type="string"> \ No newline at end of file diff --git a/product/Coramy/skins/coramy_manufacturing/ProductionOrder_getDeliveryCellPrintList.py b/product/Coramy/skins/coramy_manufacturing/ProductionOrder_getDeliveryCellPrintList.py index 0bc81ab581..d94be0ac36 100755 --- a/product/Coramy/skins/coramy_manufacturing/ProductionOrder_getDeliveryCellPrintList.py +++ b/product/Coramy/skins/coramy_manufacturing/ProductionOrder_getDeliveryCellPrintList.py @@ -60,15 +60,16 @@ if resource <> None : corresp_variation_list = [movement.getTaille()]+['value'] # find taille_client - line_taille_client = ' ' - correspondance_list = resource.getSpecialiseValueList(portal_type='Correspondance Tailles') - if len(correspondance_list) == 1 : - my_correspondance = correspondance_list[0] - mapped_value_list = my_correspondance.objectValues() - for mapped_value in mapped_value_list : - if mapped_value.test(my_correspondance.asContext(categories=corresp_variation_list)) : - line_taille_client = mapped_value.getProperty(key='taille_client') - break + line_taille_client = movement.Amount_getTailleClient() + +# correspondance_list = resource.getSpecialiseValueList(portal_type='Correspondance Tailles') +# if len(correspondance_list) == 1 : +# my_correspondance = correspondance_list[0] +# mapped_value_list = my_correspondance.objectValues() +# for mapped_value in mapped_value_list : +# if mapped_value.test(my_correspondance.asContext(categories=corresp_variation_list)) : +# line_taille_client = mapped_value.getProperty(key='taille_client') +# break try : line_quantity = float(movement.getProperty(key='quantity')) @@ -78,21 +79,22 @@ if resource <> None : line_date = order_line.aq_parent.getStopDate() # find code_article - line_code_article = '' - variated_reference_list = resource.contentValues(filter={'portal_type':'Variated Reference'}) - # we search a variated_reference wich define 'code_article' - my_variated_reference = None - for variated_reference in variated_reference_list : - if len(variated_reference.getMappedValuePropertyList()) <> 0 : - if variated_reference.getMappedValuePropertyList()[0] == 'code_article' : - my_variated_reference = variated_reference - break - if my_variated_reference is not None : - mapped_value_list = my_variated_reference.objectValues() - for mapped_value in mapped_value_list : - if mapped_value.test(my_variated_reference.asContext(categories=variation_list)) : - line_code_article = mapped_value.getProperty(key='code_article') - break + line_code_article = movement.Amount_getCodeArticleClient() + +# variated_reference_list = resource.contentValues(filter={'portal_type':'Variated Reference'}) +# # we search a variated_reference wich define 'code_article' +# my_variated_reference = None +# for variated_reference in variated_reference_list : +# if len(variated_reference.getMappedValuePropertyList()) <> 0 : +# if variated_reference.getMappedValuePropertyList()[0] == 'code_article' : +# my_variated_reference = variated_reference +# break +# if my_variated_reference is not None : +# mapped_value_list = my_variated_reference.objectValues() +# for mapped_value in mapped_value_list : +# if mapped_value.test(my_variated_reference.asContext(categories=variation_list)) : +# line_code_article = mapped_value.getProperty(key='code_article') +# break line_items = [line_resource,line_coloris,line_morphologie,line_taille, line_taille_client,line_quantity,line_date,line_code_article] diff --git a/product/Coramy/skins/coramy_mrp/InventoryMP_fastAddLine.py b/product/Coramy/skins/coramy_mrp/InventoryMP_fastAddLine.py index b0b658495c..4185e70362 100755 --- a/product/Coramy/skins/coramy_mrp/InventoryMP_fastAddLine.py +++ b/product/Coramy/skins/coramy_mrp/InventoryMP_fastAddLine.py @@ -18,7 +18,7 @@ try: if product_reference_list <> '' : product_list += product_reference_list - if len(supplier_list) > 0 : + elif len(supplier_list) > 0 : product_raw_list = context.Resource_sqlResourceSupplierSearch(supplier_title_list=supplier_list) for product_item in product_raw_list : product_list.append(product_item.title) diff --git a/product/Coramy/skins/coramy_mrp/PieceTissu_fastInput.py b/product/Coramy/skins/coramy_mrp/PieceTissu_fastInput.py index 70a823d1b8..1ded3b86b4 100755 --- a/product/Coramy/skins/coramy_mrp/PieceTissu_fastInput.py +++ b/product/Coramy/skins/coramy_mrp/PieceTissu_fastInput.py @@ -28,6 +28,10 @@ try : if line.find(text_list[0]) <> (-1) : # quantity # create previous item + # first check if needed if quantity compatible with parent_item + if my_quantity is not None and my_container.getPortalType() == 'Piece Tissu' : + if my_quantity >= my_container.getRemainingQuantity() : + my_quantity = None if my_quantity is not None : compteur += 1 new_id = str(my_container.generateNewId(default = 40000)) diff --git a/product/Coramy/skins/coramy_mrp/PieceTissu_fastInputRetour.py b/product/Coramy/skins/coramy_mrp/PieceTissu_fastInputRetour.py index c3d470c24e..9ca4f74bbc 100755 --- a/product/Coramy/skins/coramy_mrp/PieceTissu_fastInputRetour.py +++ b/product/Coramy/skins/coramy_mrp/PieceTissu_fastInputRetour.py @@ -58,7 +58,9 @@ try : except : quantity = 0 - if not quantity in (0, 0.0, '0') : + if quantity < 0 : + error_item_list.append(id_and_weight_list[i*2]+'(quantité trop importante)') + elif not quantity in (0, 0.0, '0') : # create the new item new_id = str(item.generateNewId(default = 40000)) item.portal_types.constructContent(type_name = 'Piece Tissu', @@ -81,11 +83,11 @@ try : movement_list[0].setItemIdList(new_aggregated_item_id_list) compteur += 1 else : - error_item_list.append(id_and_weight_list[i*2]+'(conversion)') + error_item_list.append(id_and_weight_list[i*2]+'(conversion kg mètre impossible)') else : error_item_list.append(id_and_weight_list[i*2]+'(non sortie ou plusieurs sorties)') else : - error_item_list.append(id_and_weight_list[i*2]+'(quantité)') + error_item_list.append(id_and_weight_list[i*2]+'(quantité mal définie)') else : error_item_list.append(id_and_weight_list[i*2]+'(inconnue)') diff --git a/product/Coramy/skins/coramy_mrp/PieceTissu_searchByResource.form b/product/Coramy/skins/coramy_mrp/PieceTissu_searchByResource.form index fd8c7870e3..ff90a74274 100755 --- a/product/Coramy/skins/coramy_mrp/PieceTissu_searchByResource.form +++ b/product/Coramy/skins/coramy_mrp/PieceTissu_searchByResource.form @@ -86,7 +86,7 @@ <values> <alternate_name></alternate_name> <css_class></css_class> - <default>Delivery_zSearchResource</default> + <default>PieceTissu_zGetAvailableItemList</default> <description></description> <display_maxwidth></display_maxwidth> <display_width type="int">20</display_width> @@ -95,7 +95,7 @@ <hidden type="int">1</hidden> <max_length></max_length> <required type="int">0</required> - <title></title> + <title>x</title> <truncate type="int">0</truncate> </values> <tales> diff --git a/product/Coramy/skins/coramy_mrp/PortalSimulation_activateRequirementList.py b/product/Coramy/skins/coramy_mrp/PortalSimulation_activateRequirementList.py index 4d70a0ce24..a1f0c2187c 100755 --- a/product/Coramy/skins/coramy_mrp/PortalSimulation_activateRequirementList.py +++ b/product/Coramy/skins/coramy_mrp/PortalSimulation_activateRequirementList.py @@ -1,19 +1,31 @@ -# Erase existing auto_planned -order_list = context.portal_catalog(simulation_state="auto_planned", parent_uid=[context.ordre_fabrication.getUid()]) -order_id_list = map(lambda x:x.id,order_list) -object_id_list = context.ordre_fabrication.objectIds() -order_id_list = filter(lambda x: x in object_id_list, order_id_list) -context.ordre_fabrication.deleteContent(order_id_list) +## Script (Python) "PortalSimulation_activateRequirementList" +##bind container=container +##bind context=context +##bind namespace= +##bind script=script +##bind subpath=traverse_subpath +##parameters= +##title= +## +if 1: + # Erase existing auto_planned + order_list = context.portal_catalog(simulation_state="auto_planned", parent_uid=[context.ordre_fabrication.getUid()]) + order_id_list = map(lambda x:x.id,order_list) + object_id_list = context.ordre_fabrication.objectIds() + order_id_list = filter(lambda x: x in object_id_list, order_id_list) + context.ordre_fabrication.deleteContent(order_id_list) -order_list = context.portal_catalog(simulation_state="auto_planned", parent_uid=[context.commande_achat.getUid()]) -order_id_list = map(lambda x:x.id,order_list) -object_id_list = context.commande_achat.objectIds() -order_id_list = filter(lambda x: x in object_id_list, order_id_list) -context.commande_achat.deleteContent(order_id_list) + order_list = context.portal_catalog(simulation_state="auto_planned", parent_uid=[context.commande_achat.getUid()]) + order_id_list = map(lambda x:x.id,order_list) + object_id_list = context.commande_achat.objectIds() + order_id_list = filter(lambda x: x in object_id_list, order_id_list) + context.commande_achat.deleteContent(order_id_list) + +#return "Done" # Stock sourcing states -#source_state_list = ('auto_planned', 'planned', 'ordered', 'confirmed', 'getting_ready', 'ready', 'delivered', 'started', 'stopped', 'invoiced') -source_state_list = None +source_state_list = ('auto_planned', 'planned', 'ordered', 'confirmed', 'getting_ready', 'ready', 'started', 'stopped', 'delivered', 'invoiced') +#source_state_list = None # Get inventory list inventory_list = context.SimulationTool_getGroupFutureInventoryList(simulation_state=source_state_list) @@ -28,9 +40,9 @@ for inventory_item in inventory_list: if movement is not None: resource = movement.getResourceValue() if resource is not None: - # Only source negative stock - print "Activate Build Order for %s for missing quantity %s" % (inventory_item.resource_relative_url, inventory_item.inventory) - resource.activate(priority=2).PortalSimulation_buildRequirementOrder(resource=inventory_item.resource_relative_url) + if resource.getPortalType() != "Assortiment": + # Only source negative stock + print "Activate Build Order for %s for missing quantity %s" % (inventory_item.resource_relative_url, inventory_item.inventory) + resource.activate(priority=2).PortalSimulation_buildRequirementOrder(resource=inventory_item.resource_relative_url) return printed - diff --git a/product/Coramy/skins/coramy_mrp/PortalSimulation_buildRequirementOrder.py b/product/Coramy/skins/coramy_mrp/PortalSimulation_buildRequirementOrder.py index 66968d13a2..050d304273 100755 --- a/product/Coramy/skins/coramy_mrp/PortalSimulation_buildRequirementOrder.py +++ b/product/Coramy/skins/coramy_mrp/PortalSimulation_buildRequirementOrder.py @@ -7,21 +7,20 @@ ##parameters=resource=None ##title= ## - -from Products.ERP5Type.Document import newTempMovement +from Products.ERP5.Document import newTempMovement from DateTime import DateTime # Stock sourcing states -#source_state_list = ('auto_planned', 'planned', 'ordered', 'confirmed', 'getting_ready', 'ready', 'delivered', 'started', 'stopped', 'invoiced') -source_state_list = None +source_state_list = ('auto_planned', 'planned', 'ordered', 'confirmed', 'getting_ready', 'ready', 'delivered', 'started', 'stopped', 'invoiced') +#source_state_list = None # Default date -now_date = DateTime() +now_date = DateTime(DateTime().Date()) # Get inventory list inventory_list = context.SimulationTool_getGroupFutureInventoryList(resource=resource, simulation_state=source_state_list) # Commit SQL -# context.portal_simulation.commitTransaction() +context.portal_simulation.commitTransaction() # First, find out which resources are missing # and build a dictionnary of quantity, variation @@ -40,7 +39,7 @@ for inventory_item in inventory_list: #LOG('ZeroStockRule WARNING',0,'None movement found') # Commit SQL -# context.portal_simulation.commitTransaction() +context.portal_simulation.commitTransaction() # A list of resources to create to_create = quantity_dict.keys() @@ -93,4 +92,4 @@ for order in order_list: order.autoPlan() order.purchase_order_apply_condition() -return printed \ No newline at end of file +return printed diff --git a/product/Coramy/skins/coramy_mrp/PortalSimulation_updateAssetPrice.py b/product/Coramy/skins/coramy_mrp/PortalSimulation_updateAssetPrice.py index 778e7288c0..f58476bad8 100755 --- a/product/Coramy/skins/coramy_mrp/PortalSimulation_updateAssetPrice.py +++ b/product/Coramy/skins/coramy_mrp/PortalSimulation_updateAssetPrice.py @@ -7,24 +7,12 @@ ##parameters= ##title= ## -mlist = context.Resource_zGetMovementHistoryList(resource = ["modele/417P401"], - variation_text = """coloris/modele/417P401/1_espace_stuc -taille/enfant/10 ans""", - section_category = "group/Coramy", - node_category= "site/Stock_PF", - strict_membership = 0, - simulation_state = ('delivered', 'started', 'stopped', 'invoiced')) - -print map(lambda x:x.relative_url, mlist) -print "next" - result = context.portal_simulation.updateAssetPrice( "modele/417P401", """coloris/modele/417P401/1_espace_stuc taille/enfant/10 ans""", "group/Coramy", "site/Stock_PF" - ) for i in result: diff --git a/product/Coramy/skins/coramy_mrp/Resource_zGetInventoryList.zsql b/product/Coramy/skins/coramy_mrp/Resource_zGetInventoryList.zsql index a1dbbdfb3e..3bf2e4096b 100755 --- a/product/Coramy/skins/coramy_mrp/Resource_zGetInventoryList.zsql +++ b/product/Coramy/skins/coramy_mrp/Resource_zGetInventoryList.zsql @@ -23,9 +23,11 @@ omit_simulation omit_input omit_output simulation_state -query</params> +query +calculate_asset:int=0</params> SELECT SUM(stock.quantity) AS inventory, + <dtml-if "calculate_asset != 0"> SUM(stock.total_asset_price) AS asset_price, </dtml-if> node.title AS node_title, node.relative_url AS node_relative_url, section.title AS section_title, diff --git a/product/Coramy/skins/coramy_mrp/SimulationTool_zGetCoramyFutureInventoryList.zsql b/product/Coramy/skins/coramy_mrp/SimulationTool_zGetCoramyFutureInventoryList.zsql index 3a208af4e8..7bfb60a0ca 100755 --- a/product/Coramy/skins/coramy_mrp/SimulationTool_zGetCoramyFutureInventoryList.zsql +++ b/product/Coramy/skins/coramy_mrp/SimulationTool_zGetCoramyFutureInventoryList.zsql @@ -7,7 +7,9 @@ cache_time:0 class_name:ZSQLBrain class_file:zsqlbrain.py </dtml-comment> -<params>to_date</params> +<params>to_date +resource +simulation_state:list</params> SELECT SUM(stock.quantity) as inventory, section.title AS section_title, @@ -29,7 +31,9 @@ AND stock.section_uid = section_category.uid AND (node_category.category_uid=<dtml-var "portal_categories.site.Stock_MP.getUid()"> OR node_category.category_uid=<dtml-var "portal_categories.site.Stock_PF.getUid()">) AND stock.node_uid = node_category.uid -<dtml-if to_date>AND movement.stop_date < <dtml-sqlvar to_date type="string"> +<dtml-if resource>AND resource.relative_url = <dtml-sqlvar resource type="string"> +</dtml-if><dtml-if to_date> AND movement.stop_date < <dtml-sqlvar to_date type="string"> +</dtml-if><dtml-if simulation_state> AND (<dtml-in simulation_state> catalog.simulation_state = <dtml-sqlvar sequence-item type="string"><dtml-if sequence-end><dtml-else> OR </dtml-if></dtml-in>) </dtml-if> GROUP BY resource.uid, movement.variation_text diff --git a/product/Coramy/skins/coramy_mrp/ZeroStock_buildOrderList.py b/product/Coramy/skins/coramy_mrp/ZeroStock_buildOrderList.py index 27ed12f097..4022508e06 100755 --- a/product/Coramy/skins/coramy_mrp/ZeroStock_buildOrderList.py +++ b/product/Coramy/skins/coramy_mrp/ZeroStock_buildOrderList.py @@ -7,28 +7,35 @@ ##parameters= ##title= ## -if 1: +return context.portal_simulation.zero_stock.deleteContent(context.portal_simulation.zero_stock.contentIds()) + +if 0: # Delete all proposed orders - for o in context.portal_catalog(simulation_state="auto_planned", parent_uid=[context.ordre_fabrication.getUid()]) : - realo = o.getObject() - realo.aq_parent.deleteContent(realo.getId()) + #production_list = context.portal_catalog(simulation_state="auto_planned", parent_uid=[context.ordre_fabrication.getUid()]) + #context.ordre_fabrication.deleteContent(map(lambda b:b.id, production_list)) + buy_list = context.portal_catalog(simulation_state="auto_planned", parent_uid=[context.commande_achat.getUid()]) + #return map(lambda b:b.id, buy_list) + #context.commande_achat.deleteContent(map(lambda b:b.id, buy_list)) # Empty Zero Stock context.portal_simulation.zero_stock.deleteContent(context.portal_simulation.zero_stock.contentIds()) + context.portal_simulation.commitTransaction() # Release any SQL locks + # Expand Zero Stock as many times as needed (1 or 2 for the Coramy case) # for i in range(0,1): - context.portal_simulation.zero_stock.expand() + context.portal_simulation.portal_simulation.zero_stock.expand() # Collect movements in Zero Stock applied rule zs_movement_list = context.portal_simulation.zero_stock.contentValues() +#return len(zs_movement_list ) +#context.portal_simulation.commitTransaction() # Release any SQL locks # keep only movements with a Modele resource movement_list = [] -for movement in zs_movement_list[0:100] : +for movement in zs_movement_list: resource_value = movement.getResourceValue() if resource_value is not None: - #if resource_value.getPortalType() == 'Modele' : movement_list.append(movement) # Parse movements into a root group @@ -40,6 +47,9 @@ for order in order_list: order.autoPlan() order.purchase_order_apply_condition() +context.portal_simulation.commitTransaction() # Release any SQL locks +return "Done" + # reEmpty Zero Stock because we don't want to see the zero_stock quantities in the columns future_stock context.portal_simulation.zero_stock.deleteContent(context.portal_simulation.zero_stock.contentIds()) diff --git a/product/Coramy/skins/coramy_mrp/item_tissu_list.form b/product/Coramy/skins/coramy_mrp/item_tissu_list.form index c7732d3e14..2da60ef698 100755 --- a/product/Coramy/skins/coramy_mrp/item_tissu_list.form +++ b/product/Coramy/skins/coramy_mrp/item_tissu_list.form @@ -15,10 +15,10 @@ <field><id>listbox</id> <type>ListBox</type> <values> - <all_columns type="list">[('id', 'N\xb0 pi\xe8ce'), ('default_resource_title', 'Tissu'), ('getColoris', 'Coloris'), ('getRemainingQuantity', 'Quantit\xe9'), ('default_source_title', 'Fournisseur'), ('default_source_reference', 'R\xe9f\xe9rence Fournisseur'), ('bain_teinture', 'Bain de teinture'), ('getLaizeUtile', 'Laize utile'), ('getLocation', 'Emplacement')]</all_columns> + <all_columns type="list">[('id', 'N\xb0 pi\xe8ce'), ('default_resource_title', 'Tissu'), ('getColoris', 'Coloris'), ('getRemainingQuantity', 'Quantit\xe9'), ('default_source_title', 'Fournisseur'), ('default_source_reference', 'R\xe9f\xe9rence Fournisseur'), ('bain_teinture', 'Bain de teinture'), ('getLaizeUtile', 'Laize utile'), ('getLastLocationTitle', 'Localisation'), ('getLocation', 'Emplacement')]</all_columns> <all_editable_columns type="list">[]</all_editable_columns> <alternate_name></alternate_name> - <columns type="list">[('id', 'N\xb0 pi\xe8ce'), ('default_resource_title', 'Tissu'), ('getColoris', 'Coloris'), ('getRemainingQuantity', 'Quantit\xe9'), ('default_source_title', 'Fournisseur'), ('default_source_reference', 'R\xe9f\xe9rence Fournisseur'), ('bain_teinture', 'Bain de teinture'), ('getLaizeUtile', 'Laize utile'), ('getLocation', 'Emplacement')]</columns> + <columns type="list">[('id', 'N\xb0 pi\xe8ce'), ('default_resource_title', 'Tissu'), ('getColoris', 'Coloris'), ('getRemainingQuantity', 'Quantit\xe9'), ('default_source_title', 'Fournisseur'), ('default_source_reference', 'R\xe9f\xe9rence Fournisseur'), ('bain_teinture', 'Bain de teinture'), ('getLaizeUtile', 'Laize utile'), ('getLastLocationTitle', 'Localisation'), ('getLocation', 'Emplacement')]</columns> <css_class></css_class> <default></default> <default_params type="list">[('id', "''")]</default_params> @@ -31,7 +31,7 @@ <hidden type="int">0</hidden> <lines type="int">30</lines> <list_action>list</list_action> - <list_method type="method">PieceTissu_zGetAvailableItemList</list_method> + <list_method type="method">portal_catalog</list_method> <meta_types type="list">[]</meta_types> <portal_types type="list">[('Piece Tissu', 'Piece Tissu')]</portal_types> <report_root_list type="list">[]</report_root_list> @@ -45,6 +45,7 @@ <title>Pièces de tissu</title> </values> <tales> + <list_method>python:here.getPortalObject().portal_skins.local_list_method[here.REQUEST.list_method_id]</list_method> </tales> <messages> <message name="external_validator_failed">The input failed the external validator.</message> diff --git a/product/Coramy/skins/coramy_mrp/item_tissu_view.form b/product/Coramy/skins/coramy_mrp/item_tissu_view.form index f0c93e9b59..9b1b1ef999 100755 --- a/product/Coramy/skins/coramy_mrp/item_tissu_view.form +++ b/product/Coramy/skins/coramy_mrp/item_tissu_view.form @@ -114,6 +114,30 @@ <message name="not_float">You did not enter a floating point number.</message> </messages> </field> + <field><id>my_last_location_title</id> <type>StringField</type> + <values> + <alternate_name></alternate_name> + <css_class></css_class> + <default></default> + <description></description> + <display_maxwidth></display_maxwidth> + <display_width type="int">20</display_width> + <external_validator></external_validator> + <extra></extra> + <hidden type="int">0</hidden> + <max_length></max_length> + <required type="int">0</required> + <title>Localisation</title> + <truncate type="int">0</truncate> + </values> + <tales> + </tales> + <messages> + <message name="external_validator_failed">The input failed the external validator.</message> + <message name="required_not_found">Input is required but no input given.</message> + <message name="too_long">Too much input was given.</message> + </messages> + </field> <field><id>my_location</id> <type>StringField</type> <values> <alternate_name></alternate_name> diff --git a/product/Coramy/skins/coramy_pdm/TransformedComponent_getCorrespondanceList.py b/product/Coramy/skins/coramy_pdm/TransformedComponent_getCorrespondanceList.py index 9bf9d16efd..f395c3bf04 100755 --- a/product/Coramy/skins/coramy_pdm/TransformedComponent_getCorrespondanceList.py +++ b/product/Coramy/skins/coramy_pdm/TransformedComponent_getCorrespondanceList.py @@ -4,7 +4,7 @@ ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath -##parameters=transformation=None, quantities=1 +##parameters= ##title= ## transformed_component = context @@ -14,9 +14,8 @@ variation_base_category_list = [] q_variation_base_category_list = transformed_component.getQVariationBaseCategoryList() v_variation_base_category_list = transformed_component.getVVariationBaseCategoryList() -if quantities : - for base_category in q_variation_base_category_list : - variation_base_category_list.append(base_category) +for base_category in q_variation_base_category_list : + variation_base_category_list.append(base_category) for base_category in v_variation_base_category_list : if not base_category in variation_base_category_list : @@ -26,7 +25,7 @@ variation_base_category_list.sort() variation_list_list = [] for base_category in variation_base_category_list : - variation_list = transformation.getVariationCategoryList(base_category_list = base_category) + variation_list = context.aq_parent.getVariationCategoryList(base_category_list = base_category) variation_list_list.append(variation_list) cartesian_variation_list = context.cartesianProduct(variation_list_list) @@ -55,14 +54,6 @@ for variation_list in cartesian_variation_list : pretty_variation_2 = '- ' for my_variation in variation : pretty_variation_2 += my_variation+' - ' - if pretty_variation_2 == '- ' : - try : - pretty_variation_2 += transformed_component.getVariationCategoryList()[0] - except : - pass - if quantities : - correspondance_list.append([pretty_variation_1, quantity, pretty_variation_2]) - else : - correspondance_list.append([pretty_variation_1, '', pretty_variation_2]) + correspondance_list.append([pretty_variation_1, quantity, pretty_variation_2]) return correspondance_list diff --git a/product/Coramy/skins/coramy_pdm/transformation_correspondances_print.pt b/product/Coramy/skins/coramy_pdm/transformation_correspondances_print.pt index 0e53f6df8f..10897cfcd4 100755 --- a/product/Coramy/skins/coramy_pdm/transformation_correspondances_print.pt +++ b/product/Coramy/skins/coramy_pdm/transformation_correspondances_print.pt @@ -90,7 +90,7 @@ <tr> <td colspan="3" > <table class="border" border="0" width="100%" - tal:define="correspondances_list python:transformed_resource.TransformedComponent_getCorrespondanceList(transformation,quantities=0)"> + tal:define="correspondances_list python:transformed_resource.TransformedComponent_getCorrespondanceList()"> <tr tal:condition="python:len(correspondances_list)==0"> <td> <span tal:repeat="variation_item python:transformed_resource.getVariationCategoryList()"> diff --git a/product/Coramy/skins/coramy_trade/Container_printExtandLabel.py b/product/Coramy/skins/coramy_trade/Container_printExtandLabel.py index c1031316f4..fa22ab7109 100755 --- a/product/Coramy/skins/coramy_trade/Container_printExtandLabel.py +++ b/product/Coramy/skins/coramy_trade/Container_printExtandLabel.py @@ -47,6 +47,8 @@ elif local_user == 'Jocelyne_Olejarz' : printer_name = 'Meto_XS40_4' elif local_user == 'Nathalie_Wadoux' : printer_name = 'Meto_XS40_5' +elif local_user == 'Chantal_Hannequin' : + printer_name = 'Meto_XS40_6' else : printer_name = 'Meto_XS40_2' diff --git a/product/Coramy/skins/coramy_trade/Container_printMetoLabel.py b/product/Coramy/skins/coramy_trade/Container_printMetoLabel.py index 4b8427c527..e899b5decc 100755 --- a/product/Coramy/skins/coramy_trade/Container_printMetoLabel.py +++ b/product/Coramy/skins/coramy_trade/Container_printMetoLabel.py @@ -22,6 +22,8 @@ elif local_user == 'Jocelyne_Olejarz' : printer_name = 'Meto_XS40_4' elif local_user == 'Nathalie_Wadoux' : printer_name = 'Meto_XS40_5' +elif local_user == 'Chantal_Hannequin' : + printer_name = 'Meto_XS40_6' else : printer_name = 'Meto_XS40_2' diff --git a/product/Coramy/skins/coramy_trade/Container_sendExtandEdi.py b/product/Coramy/skins/coramy_trade/Container_sendExtandEdi.py index 5e87bd7e8b..927e851e85 100755 --- a/product/Coramy/skins/coramy_trade/Container_sendExtandEdi.py +++ b/product/Coramy/skins/coramy_trade/Container_sendExtandEdi.py @@ -21,7 +21,7 @@ def decoupe(s,width): result = s[-width:] else: #result = string.ljust(s,width) - result = (' ' * (width-len(s))) + s + result = s + (' ' * (width-len(s))) #return ' '+s return result diff --git a/product/Coramy/skins/coramy_trade/DeliveryLine_getTargetQuantityList.py b/product/Coramy/skins/coramy_trade/DeliveryLine_getTargetQuantityList.py index d703d0e305..99c62c1209 100755 --- a/product/Coramy/skins/coramy_trade/DeliveryLine_getTargetQuantityList.py +++ b/product/Coramy/skins/coramy_trade/DeliveryLine_getTargetQuantityList.py @@ -20,8 +20,8 @@ def category_property(category, property): else : return " " -for taille in taille_list : - my_taille = 'taille/'+taille +if len(taille_list) == 0 : + my_taille = None if coloris is not None and morphologie is not None : my_coloris = 'coloris/'+coloris my_morphologie = 'morphologie/'+morphologie @@ -40,5 +40,26 @@ for taille in taille_list : target_quantity_list.append(delivery_line.getCell(None, my_taille, base_id='movement').getProperty(key="target_quantity")) else : target_quantity_list.append(0) +else : + for taille in taille_list : + my_taille = 'taille/'+taille + if coloris is not None and morphologie is not None : + my_coloris = 'coloris/'+coloris + my_morphologie = 'morphologie/'+morphologie + if delivery_line.getCell(my_coloris, my_taille, my_morphologie, base_id='movement') <> None : + target_quantity_list.append(delivery_line.getCell(my_coloris, my_taille, my_morphologie, base_id='movement').getProperty(key="target_quantity")) + else : + target_quantity_list.append(0) + elif coloris is not None : + my_coloris = 'coloris/'+coloris + if delivery_line.getCell(my_coloris, my_taille, base_id='movement') <> None : + target_quantity_list.append(delivery_line.getCell(my_coloris, my_taille, base_id='movement').getProperty(key="target_quantity")) + else : + target_quantity_list.append(0) + else : # coloris is None : + if delivery_line.getCell(None, my_taille, base_id='movement') <> None : + target_quantity_list.append(delivery_line.getCell(None, my_taille, base_id='movement').getProperty(key="target_quantity")) + else : + target_quantity_list.append(0) return target_quantity_list diff --git a/product/Coramy/skins/coramy_trade/Delivery_exportContainerList.py b/product/Coramy/skins/coramy_trade/Delivery_exportContainerList.py index 2b92fe4d4b..3172747499 100755 --- a/product/Coramy/skins/coramy_trade/Delivery_exportContainerList.py +++ b/product/Coramy/skins/coramy_trade/Delivery_exportContainerList.py @@ -31,7 +31,10 @@ for container_item in container_list : ligne_container += str(container.getGrossWeight())+tab ligne_container += first_line.getResourceValue().getId()+tab ligne_container += delivery.getDestinationSectionTitle()+tab - ligne_container += first_line.getColorisValue().getId()+tab + if first_line.getColorisValue() is not None : + ligne_container += first_line.getColorisValue().getId()+tab + else : + ligne_container += ''+tab ligne_container += first_line.Amount_getTailleClient()+tab ligne_container += "Maillot de bain"+tab ligne_container += first_line.Amount_getCodeArticleClient()+tab diff --git a/product/Coramy/skins/coramy_trade/default_pdf_template.pt b/product/Coramy/skins/coramy_trade/default_pdf_template.pt index 9a173a0156..9ae10f1a2e 100755 --- a/product/Coramy/skins/coramy_trade/default_pdf_template.pt +++ b/product/Coramy/skins/coramy_trade/default_pdf_template.pt @@ -10,16 +10,34 @@ allowsplitting="1" tal:define="packing_list python:here.getCausalityValueList(portal_type=['Sale Packing List','Sales Packing List'])[0]; invoice_id python:here.getId(); + invoice_reference python: here.getReference(0); resource_title python:here.getResourceTitle() or 'Euros'; resource_id python:here.getResourceId() or 'EUR'; - income python: here.income; - vat python: here.vat; - payable python: here.payable;"> + income python: here.Invoice_zGetTotalNetPrice(); + vat python: here.Invoice_zGetTotalVat(); + payable python: here.getDefaultTotalPrice(); + payable python: income + vat; + vad_recoverable python: here.getValueAddedTaxRecoverable(); + vad_ratio python: here.getValueAddedTaxRatio(); + source_decision_title python: here.getSourceDecisionTitle(); + payment_mode python: here.getPaymentMode(); + payment_term python: here.getPaymentTerm(30); + incoterm python: packing_list.getIncotermId(); + delivery_mode python: packing_list.getDeliveryModeTitle().split('/')[-1]; + escompte_value python: here.Invoice_zGetEscompteDescription(); + container_number python: len(packing_list.contentValues(filter={'portal_type':'Container'})); + total_price python:here.getDefaultTotalPrice();"> + + <!-- due_date python: DateTime.getNextMonth(start_date.month(), start_date.year()) ; --> <tal:block - tal:define="destination python: packing_list.getDestinationValue(); - destination_administration python: packing_list.getDestinationAdministrationValue() or packing_list.getDestinationSectionValue(); - start_date python:packing_list.getStartDate(); + tal:define="destination python: here.getDestinationValue(); + destination_administration python: here.getDestinationAdministrationValue() or here.getDestinationSectionValue(); + DateTime python: modules['DateTime'].DateTime; + start_date python:here.getStartDate( packing_list.getTargetStopDate() ) ; + due_date python: here.Invoice_zGetDueDate(); packing_list_id python:packing_list.getId(); + code_comptable python: destination_administration.getCodeComptable(); + eu_vat_code python: destination_administration.getEuVatCode(); order python:packing_list.getCausalityValueList(portal_type=['Sale Order','Sales Order'])[0];"> <stylesheet> @@ -78,7 +96,8 @@ <stylecmd expr="('RIGHTPADDING', (0,0), (-1,-1), 5)"/> <stylecmd expr="('TOPPADDING', (0,0), (-1,-1), 1)"/> <stylecmd expr="('BOTTOMPADDING', (0,0), (-1,-1), 1)"/> - <stylecmd expr="('ALIGN', (0,0), (-1,-1), 'LEFT')"/> + <stylecmd expr="('ALIGN', (0,0), (1,0), 'LEFT')"/> + <stylecmd expr="('ALIGN', (2,0), (-1,-1), 'RIGHT')"/> <stylecmd expr="('GRID', (0,0), (-1,-1), 0, colors.white)"/> <stylecmd expr="('BOX', (0,0), (-1,-1), 0, colors.white)"/> <stylecmd expr="('FONT', (0,0), (-1,-1), 'Helvetica', 8)"/> @@ -132,7 +151,7 @@ </stylesheet> - <pagetemplate id="FirstPage" nextid="Page" startframe="content"> + <pagetemplate id="FirstPage" nextid="SecondPage" startframe="content"> <static> <!-- Entete CORAMY --> @@ -159,21 +178,21 @@ <!-- Titre du document (Facture n°) --> <infostring align="left" x="6.8cm" y="26cm" size="16" - font="Helvetica-Bold" color="(0,0,0)" tal:content="python: 'Facture n° %s' % invoice_id"> - Facture n° 105 915 + font="Helvetica-Bold" color="(0,0,0)" tal:content="python: 'Facture n° %s' % invoice_reference"> + Facture n° XXX </infostring> <infostring align="left" x="14cm" y="26cm" size="8" font="Helvetica" color="(0,0,0)" tal:content="python: start_date.strftime('Gravelines, le %e/%m/%y')"> - Gravelines, le 9/07/03 + Gravelines, le XXX </infostring> <infostring align="left" x="18.5cm" y="26cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - Folio 1 + Folio %(page)s </infostring> - <!-- Grand cadre de la fature --> + <!-- Grand cadre de la facture --> <line x1="1cm" x2="20.5cm" y1="25cm" y2="25cm" width="1"/> <line x1="1cm" x2="1cm" y1="25cm" y2="4cm" width="1"/> <line x1="20.5cm" x2="20.5cm" y1="25cm" y2="4cm" width="1"/> @@ -195,7 +214,7 @@ </infostring> <infostring align="center" x="2.5cm" y="24.2cm" size="8" font="Helvetica-Bold" color="(0,0,0)" tal:content="python: order.getDestinationReference()"> - 7286007 + DestinationReference XXX </infostring> <infostring align="left" x="1.7cm" y="23.8cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> @@ -206,7 +225,7 @@ </infostring> <infostring align="center" x="2.5cm" y="23.3cm" size="8" font="Helvetica-Bold" color="(0,0,0)" tal:content="python: order.getId()"> - 119 022 + Order.id XXX </infostring> <infostring align="left" x="1.1cm" y="22.9cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> @@ -217,33 +236,23 @@ </infostring> <infostring align="center" x="2.5cm" y="22.4cm" size="8" font="Helvetica-Bold" color="(0,0,0)" tal:content="python: packing_list_id"> - 108 301 + PackingListId XXX </infostring> - <infostring align="left" x="1.1cm" y="21.9cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="1.7cm" y="21.9cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Nombre de colis </infostring> - <infostring align="left" x="1.3cm" y="21.7cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="1.9cm" y="21.7cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Kolli anzahl </infostring> - <infostring align="left" x="1.2cm" y="21.5cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="1.8cm" y="21.5cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Nb of parcels </infostring> - <infostring align="left" x="3.5cm" y="21.7cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - 32 - </infostring> - - <infostring align="left" x="1.1cm" y="21cm" size="6" font="Helvetica" color="(0,0,0)"> - Poids brut (kg) - </infostring> - <infostring align="left" x="1.2cm" y="20.8cm" size="6" font="Helvetica" color="(0,0,0)"> - Brutto-gewicht - </infostring> - <infostring align="left" x="1.3cm" y="20.6cm" size="6" font="Helvetica" color="(0,0,0)"> - Gross weight + <infostring align="center" x="2.5cm" y="21.1cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: container_number"> + NbrColis XXX </infostring> - <infostring align="left" x="6cm" y="24.7cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Livraison / Versand / Delivery </infostring> @@ -279,36 +288,30 @@ </tal:block> - <infostring align="left" x="4.5cm" y="22cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="4.5cm" y="21.7cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Commercial </infostring> - <infostring align="left" x="4.4cm" y="21.5cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="6cm" y="21.7cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: source_decision_title "> + Commercial XXX + </infostring> + <infostring align="left" x="4.4cm" y="21.1cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Paiement </infostring> - <infostring align="left" x="4.6cm" y="21.3cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="4.6cm" y="20.9cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Zahlung </infostring> - <infostring align="left" x="4.5cm" y="21.1cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="4.5cm" y="20.7cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Payment </infostring> - <infostring align="left" x="4.3cm" y="20.7cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> - Device / Currency / Wahrung - </infostring> - <infostring align="left" x="5.8cm" y="21.4cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - Cheque - </infostring> - <infostring align="left" x="5.8cm" y="21.1cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - 20 jours Net + <infostring align="left" x="5.8cm" y="21cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: payment_mode "> + payment_modeXXX </infostring> - <infostring align="left" x="8.5cm" y="20.6cm" size="8" font="Helvetica-Bold" color="(0,0,0)" - tal:content="python: resource_title"> - Euros + <infostring align="left" x="5.8cm" y="20.7cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: '%i jours Net' % payment_term"> + payment_termXXX </infostring> - <infostring align="left" x="10.2cm" y="20.6cm" size="8" font="Helvetica-Bold" color="(0,0,0)" - tal:content="python: resource_id"> - EUR - </infostring> - <infostring align="left" x="11.6cm" y="22cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Code comptable @@ -319,47 +322,50 @@ <infostring align="left" x="11.6cm" y="20.9cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Conditions d'escompte / Diskont / Discount. </infostring> - <infostring align="left" x="14cm" y="22cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - 41REDOU + <infostring align="left" x="14cm" y="22cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: code_comptable"> + CodeComptable XXX </infostring> - <infostring align="left" x="11.6cm" y="20.6cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - 2,75 sous 20 jours + <infostring align="left" x="14cm" y="21.4cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: eu_vat_code"> + NoTVAXXX + </infostring> + <infostring align="left" x="11.6cm" y="20.6cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: escompte_value"> + Escompte XXX </infostring> - <infostring align="left" x="18.9cm" y="24.6cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> - Port / Porto - </infostring> - <infostring align="left" x="19.1cm" y="24.4cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> - Freight - </infostring> - <infostring align="left" x="19cm" y="24cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - Franco - </infostring> - <infostring align="left" x="18.9cm" y="23.4cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + + <infostring align="left" x="18.9cm" y="24.2cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Transporteur </infostring> - <infostring align="left" x="18.6cm" y="23.2cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="18.6cm" y="24cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Carrier / Spediteur </infostring> - <infostring align="left" x="18.8cm" y="22.8cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - CORAMY + <infostring align="center" x="19.5cm" y="23.6cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: delivery_mode"> + delivery_modeXXX </infostring> - <infostring align="left" x="18.6cm" y="22cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="18.6cm" y="23cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Transport </infostring> - <infostring align="left" x="20cm" y="22cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> + <infostring align="left" x="20cm" y="23cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> 3 </infostring> - <infostring align="left" x="18.6cm" y="21.4cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="18.6cm" y="22.1cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Transaction </infostring> - <infostring align="left" x="19.9cm" y="21.4cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> + <infostring align="left" x="19.9cm" y="22.1cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> 11 </infostring> - <infostring align="left" x="18.6cm" y="20.8cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> + <infostring align="left" x="18.6cm" y="21.2cm" size="6" font="Helvetica-Oblique" color="(0,0,0)"> Livraison </infostring> + <infostring align="left" x="19.9cm" y="21.2cm" size="8" font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: incoterm"> + incotermXXX + </infostring> <!-- Détail de la facture --> <rectangle x="1cm" y="19.9cm" width="19.5cm" height="0.4cm" @@ -368,15 +374,15 @@ <infostring align="left" x="2.8cm" y="20cm" size="9" font="Helvetica-Oblique" color="(0,0,0)"> - Denomination des produits + Dénomination des produits </infostring> <infostring align="left" x="10cm" y="20cm" size="9" font="Helvetica-Oblique" color="(0,0,0)"> - Repartition par tailles + Répartition par tailles </infostring> <infostring align="left" x="15.4cm" y="20cm" size="9" font="Helvetica-Oblique" color="(0,0,0)"> - Quantite + Quantité </infostring> <infostring align="left" x="17.1cm" y="20cm" size="9" font="Helvetica-Oblique" color="(0,0,0)"> @@ -409,10 +415,12 @@ font="Helvetica-Oblique" color="(0,0,0)"> T.V.A. </infostring> - <infostring align="left" x="9.3cm" y="5.1cm" size="9" - font="Helvetica" color="(0,0,0)"> - 19,6%% - </infostring> + <tal:block tal:condition="python: vad_recoverable"> + <infostring align="left" x="9.3cm" y="5.1cm" size="9" + font="Helvetica" color="(0,0,0)" tal:content="python: '%.1f' % (vad_ratio * 100) + '%%'"> + 19,6%% + </infostring> + </tal:block> <infostring align="left" x="11.2cm" y="5.5cm" size="9" font="Helvetica-Oblique" color="(0,0,0)"> Port @@ -440,48 +448,249 @@ <infostring align="center" x="2.2cm" y="4.5cm" size="9" font="Helvetica" color="(0,0,0)" - tal:content="python: '%.2f' % income.getSourceCredit()"> - 14 408,46 + tal:content="python: '%.2f' % income"> + income XXX </infostring> - <infostring align="left" x="6.5cm" y="4.5cm" size="9" + <infostring align="center" x="3.8cm" y="4.5cm" size="9" font="Helvetica" color="(0,0,0)"> - 14 408,46 + </infostring> - <infostring align="center" x="9.7cm" y="4.5cm" size="9" + <infostring align="left" x="6.5cm" y="4.5cm" size="9" font="Helvetica" color="(0,0,0)" - tal:content="python: '%.2f' % vat.getSourceCredit()"> - 2 824,06 + tal:content="python: '%.2f' % income"> + + </infostring> + <tal:block tal:condition="python: vad_recoverable"> + <infostring align="center" x="9.7cm" y="4.5cm" size="9" + font="Helvetica" color="(0,0,0)" + tal:content="python: '%.2f' % vat"> + vat XXX + </infostring> + </tal:block> + <infostring align="left" x="10.7cm" y="4.5cm" size="9" + font="Helvetica" color="(0,0,0)"> + </infostring> <infostring align="center" x="13.8cm" y="4.5cm" size="10" font="Helvetica-Bold" color="(0,0,0)" - tal:content="python: '%.2f' % payable.getSourceDebit()"> - 17 232,52 + tal:content="python: '%.2f' % payable"> + payable XXX </infostring> <infostring align="center" x="16cm" y="4.5cm" size="10" font="Helvetica-Bold" color="(0,0,0)" tal:content="python: resource_id"> - EUR + resource_id XXX </infostring> <infostring align="left" x="18cm" y="4.5cm" size="10" - font="Helvetica-Bold" color="(0,0,0)"> - 31/07/03 + font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: due_date.strftime('%e/%m/%y')"> + due_date XXX </infostring> <infostring align="left" x="1.1cm" y="3.8cm" size="5" font="Helvetica" color="(0,0,0)"> - En application de la loi du 31/12/1992, nous vous precisons que la presente facture devra etre reglee a la date indiquee ci-dessous. En cas de reglement comptant sous 10 jours, date de facture, l'escompte ci-dessus mentionne purra etre deduit du + En application de la loi du 31/12/1992, nous vous précisons que la presente facture devra être réglée à la date indiquée ci-dessus. En cas de règlement comptant sous 10 jours, date de facture, l'escompte ci-dessus mentionné pourra être déduit du </infostring> <infostring align="left" x="1.1cm" y="3.5cm" size="5" font="Helvetica" color="(0,0,0)"> - montant H.T. de la facture, auquel cas le montant de TVA deductible par vous devra etre diminue du montant de celle afférente a l'escompte. Son règlement donnera lieu au versement d'un intérêt moratoire, calcule sur les sommes restant + montant H.T. de la facture, auquel cas le montant de TVA déductible par vous devra être diminué du montant de celle afférente à l'escompte. Son règlement donnera lieu au versement d'un intérêt moratoire, calculé sur les sommes restant </infostring> <infostring align="left" x="1.1cm" y="3.2cm" size="5" font="Helvetica" color="(0,0,0)"> - dues a cette date de reglement en principal, frais et taxes inclus, et au taux de l'interet legal majore de 5 points, sans que cette penalite puisse etre en toute hypothese inferieure a 1,5 fois le taux de l'interet legal. + dues à cette date de règlement en principal, frais et taxes inclus, et au taux de l'intérêt légal majoré de 5 points, sans que cette pénalité puisse être en toute hypothèse inférieure à 1,5 fois le taux de l'intérêt légal. + </infostring> + + </static> + + <frame id="content" + nextid="content" + x="1cm" + y="5.8cm" + width="19.5cm" + height="14.1cm" + leftpadding="0.1cm" + rightpadding="0.1cm" + toppadding="0.2cm" + bottompadding="0.5cm" + showBoundary="1"/> + </pagetemplate> + + + + + <pagetemplate id="SecondPage" nextid="SecondPage" startframe="content"> + <static> + + <!-- Entete CORAMY --> + <infostring align="left" x="1.4cm" y="28cm" size="40" + font="Times-Bold" color="(0,0,0)">Coramy</infostring> + + <rectangle x="1cm" y="28cm" width="0.3cm" height="0.4cm" + linewidth="0.0" stroke="(1,1,1)" fill="(0.5,0.5,0.5)"/> + <rectangle x="6.5cm" y="28cm" width="13.5cm" height="0.4cm" + linewidth="0.0" stroke="(1,1,1)" fill="(0.5,0.5,0.5)"/> + + <infostring align="left" x="7cm" y="28.5cm" size="8" + font="Helvetica" color="(0,0,0)"> + 5 bis, rue Denis Cordonnier - F.59820 GRAVELINES - Tel. 33(0)3 28 51 91 51 - Fax 33(0)3 28 23 34 96 + </infostring> + <infostring align="left" x="10cm" y="28.1cm" size="8" + font="Helvetica" color="(1,1,1)"> + MAILLOTS DE BAIN - GYM - SWIMSUITS - FITNESS + </infostring> + <infostring align="left" x="6.8cm" y="27.7cm" size="6" + font="Helvetica" color="(0,0,0)"> + SAS capital de 435.200 EUR - T.V.A. FR 67 611 750 274 - R.C. Dunkerque 611 750 274 - SIRET 611 750 274 00023 - CNUF 15971 + </infostring> + + <!-- Titre du document (Facture n°) --> + <infostring align="left" x="6.8cm" y="26cm" size="16" + font="Helvetica-Bold" color="(0,0,0)" tal:content="python: 'Facture n° %s' % invoice_reference"> + Facture n° XXX + </infostring> + + <infostring align="left" x="14cm" y="26cm" size="8" + font="Helvetica" color="(0,0,0)" tal:content="python: start_date.strftime('Gravelines, le %e/%m/%y')"> + Gravelines, le XXX + </infostring> + + <infostring align="left" x="18.5cm" y="26cm" size="8" + font="Helvetica-Bold" color="(0,0,0)"> + Folio %(page)s + </infostring> + + <!-- Grand cadre de la facture --> + <line x1="1cm" x2="20.5cm" y1="25cm" y2="25cm" width="1"/> + <line x1="1cm" x2="1cm" y1="25cm" y2="4cm" width="1"/> + <line x1="20.5cm" x2="20.5cm" y1="25cm" y2="4cm" width="1"/> + <line x1="1cm" x2="20.5cm" y1="4cm" y2="4cm" width="1"/> + + + <!-- Détail de la facture --> + <rectangle x="1cm" y="24.6cm" width="19.5cm" height="0.4cm" + linewidth="0" fill="(0.75,0.75,0.75)"/> + <line x1="1cm" x2="20.5cm" y1="24.6cm" y2="24.6cm" width="1"/> + + <infostring align="left" x="2.8cm" y="24.7cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Dénomination des produits + </infostring> + <infostring align="left" x="10cm" y="24.7cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Répartition par tailles + </infostring> + <infostring align="left" x="15.4cm" y="24.7cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Quantité + </infostring> + <infostring align="left" x="17.1cm" y="24.7cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + P.U.H.T. + </infostring> + <infostring align="left" x="18.8cm" y="24.7cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Total H.T. + </infostring> + + <!-- Pied de facture --> + <rectangle x="1cm" y="5.0cm" width="19.5cm" height="0.8cm" + linewidth="0" fill="(0.75,0.75,0.75)"/> + <line x1="1cm" x2="20.5cm" y1="5.8cm" y2="5.8cm" width="1"/> + <line x1="1cm" x2="20.5cm" y1="5.0cm" y2="5.0cm" width="1"/> + + <infostring align="left" x="1.5cm" y="5.5cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Total H.T. + </infostring> + <infostring align="left" x="3.8cm" y="5.5cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Port taxable + </infostring> + <infostring align="left" x="6.2cm" y="5.5cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Montant taxable + </infostring> + <infostring align="left" x="9.2cm" y="5.5cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + T.V.A. + </infostring> + <tal:block tal:condition="python: vad_recoverable"> + <infostring align="left" x="9.3cm" y="5.1cm" size="9" + font="Helvetica" color="(0,0,0)" tal:content="python: '%.1f' % (vad_ratio * 100) + '%%'"> + 19,6%% + </infostring> + </tal:block> + <infostring align="left" x="11.2cm" y="5.5cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Port + </infostring> + <infostring align="left" x="10.7cm" y="5.1cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + non taxable + </infostring> + <infostring align="left" x="13.8cm" y="5.5cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Net a payer + </infostring> + <infostring align="left" x="12.6cm" y="5.1cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Gesamtbetrag / Total amount + </infostring> + <infostring align="left" x="17.5cm" y="5.5cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Date d'echeance + </infostring> + <infostring align="left" x="17cm" y="5.1cm" size="9" + font="Helvetica-Oblique" color="(0,0,0)"> + Falligkeitstag / Due date </infostring> - <infostring align="left" x="1.6cm" y="2.7cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - Nos marchandises sont grevees d'une clause de reserve de propriete, reprise dans nos conditions generales de venteindiquees au verso + <infostring align="center" x="2.2cm" y="4.5cm" size="9" + font="Helvetica" color="(0,0,0)" + tal:content="python: '%.2f' % income"> + income XXX </infostring> - <infostring align="left" x="4.5cm" y="2.4cm" size="8" font="Helvetica-Bold" color="(0,0,0)"> - Allegemeine Verkaufsbedingungen auf ruckseite - General sales conditions overleaf + <infostring align="center" x="3.8cm" y="4.5cm" size="9" + font="Helvetica" color="(0,0,0)"> + + </infostring> + <infostring align="left" x="6.5cm" y="4.5cm" size="9" + font="Helvetica" color="(0,0,0)" + tal:content="python: '%.2f' % income"> + + </infostring> + <tal:block tal:condition="python: vad_recoverable"> + <infostring align="center" x="9.7cm" y="4.5cm" size="9" + font="Helvetica" color="(0,0,0)" + tal:content="python: '%.2f' % vat"> + vat XXX + </infostring> + </tal:block> + <infostring align="left" x="10.7cm" y="4.5cm" size="9" + font="Helvetica" color="(0,0,0)"> + + </infostring> + <infostring align="center" x="13.8cm" y="4.5cm" size="10" + font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: '%.2f' % payable"> + payable XXX + </infostring> + <infostring align="center" x="16cm" y="4.5cm" size="10" + font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: resource_id"> + resource_id XXX + </infostring> + <infostring align="left" x="18cm" y="4.5cm" size="10" + font="Helvetica-Bold" color="(0,0,0)" + tal:content="python: due_date.strftime('%e/%m/%y')"> + due_date XXX + </infostring> + + <infostring align="left" x="1.1cm" y="3.8cm" size="5" font="Helvetica" color="(0,0,0)"> + En application de la loi du 31/12/1992, nous vous précisons que la presente facture devra être réglée à la date indiquée ci-dessus. En cas de règlement comptant sous 10 jours, date de facture, l'escompte ci-dessus mentionné pourra être déduit du + </infostring> + <infostring align="left" x="1.1cm" y="3.5cm" size="5" font="Helvetica" color="(0,0,0)"> + montant H.T. de la facture, auquel cas le montant de TVA déductible par vous devra être diminué du montant de celle afférente à l'escompte. Son règlement donnera lieu au versement d'un intérêt moratoire, calculé sur les sommes restant + </infostring> + <infostring align="left" x="1.1cm" y="3.2cm" size="5" font="Helvetica" color="(0,0,0)"> + dues à cette date de règlement en principal, frais et taxes inclus, et au taux de l'intérêt légal majoré de 5 points, sans que cette pénalité puisse être en toute hypothèse inférieure à 1,5 fois le taux de l'intérêt légal. </infostring> </static> @@ -491,7 +700,7 @@ x="1cm" y="5.8cm" width="19.5cm" - height="14.1cm" + height="18.8cm" leftpadding="0.1cm" rightpadding="0.1cm" toppadding="0.2cm" @@ -499,6 +708,10 @@ showBoundary="1"/> </pagetemplate> + + + + <pagetemplate id="Page" > <static> @@ -522,4 +735,4 @@ </pagetemplate> </tal:block> -</template> +</template> \ No newline at end of file diff --git a/product/Coramy/skins/coramy_trade/purchase_packing_list_view.form b/product/Coramy/skins/coramy_trade/purchase_packing_list_view.form index 042ee6419d..c39284b2e0 100755 --- a/product/Coramy/skins/coramy_trade/purchase_packing_list_view.form +++ b/product/Coramy/skins/coramy_trade/purchase_packing_list_view.form @@ -500,10 +500,10 @@ <field><id>listbox</id> <type>ListBox</type> <values> - <all_columns type="list">[('resource_title', 'Produit'), ('variation_text', 'Variantes'), ('quantity', 'Objectif quantit\xe9'), ('target_quantity', 'Quantit\xe9'), ('item_id_list', 'Lots associ\xe9s'), ('quantity_unit', 'Unit\xe9')]</all_columns> + <all_columns type="list">[('resource_title', 'Produit'), ('variation_text', 'Variantes'), ('quantity', 'Objectif quantit\xe9'), ('target_quantity', 'Quantit\xe9'), ('item_id_list', 'Lots associ\xe9s'), ('price', 'Prix'), ('quantity_unit', 'Unit\xe9')]</all_columns> <all_editable_columns type="list">[]</all_editable_columns> <alternate_name></alternate_name> - <columns type="list">[('resource_title', 'Produit'), ('variation_text', 'Variantes'), ('getPurchaseDeliveryCellSourceReference', 'R\xe9f. fournisseur'), ('quantity', 'Objectif quantit\xe9'), ('target_quantity', 'Quantit\xe9'), ('item_id_list', 'Lots associ\xe9s'), ('quantity_unit', 'Unit\xe9')]</columns> + <columns type="list">[('resource_title', 'Produit'), ('variation_text', 'Variantes'), ('getPurchaseDeliveryCellSourceReference', 'R\xe9f. fournisseur'), ('quantity', 'Objectif quantit\xe9'), ('target_quantity', 'Quantit\xe9'), ('item_id_list', 'Lots associ\xe9s'), ('price', 'Prix'), ('quantity_unit', 'Unit\xe9')]</columns> <css_class></css_class> <default></default> <default_params type="list">[]</default_params> diff --git a/product/Coramy/skins/coramy_trade/sales_invoice_list.form b/product/Coramy/skins/coramy_trade/sales_invoice_list.form index 65085c20b8..f90963633e 100755 --- a/product/Coramy/skins/coramy_trade/sales_invoice_list.form +++ b/product/Coramy/skins/coramy_trade/sales_invoice_list.form @@ -15,10 +15,10 @@ <field><id>listbox</id> <type>ListBox</type> <values> - <all_columns type="list">[('id', 'Commande'), ('default_destination_title', 'Client'), ('buyer_title', 'Acheteur'), ('Description', 'Description'), ('order_state', 'Etat')]</all_columns> + <all_columns type="list">[('id', 'Identifiant'), ('reference', 'Num\xe9ro de facture'), ('destination_administration_organisation_title', 'Factur\xe9e \xe0'), ('causality_id', 'Livraison vente'), ('description', 'Description'), ('simulation_state', 'Etat')]</all_columns> <all_editable_columns type="list">[]</all_editable_columns> <alternate_name></alternate_name> - <columns type="list">[('id', 'Facture'), ('default_destination_title', 'Client'), ('buyer_title', 'Acheteur'), ('Description', 'Description'), ('order_state', 'Etat')]</columns> + <columns type="list">[('id', 'Identifiant'), ('reference', 'Num\xe9ro de facture'), ('destination_administration_organisation_title', 'Factur\xe9e \xe0'), ('causality_id', 'Livraison vente'), ('description', 'Description'), ('simulation_state', 'Etat')]</columns> <css_class></css_class> <default></default> <default_params type="list">[('id', "''")]</default_params> @@ -37,7 +37,7 @@ <report_root_list type="list">[]</report_root_list> <report_tree type="int">0</report_tree> <search type="int">1</search> - <search_columns type="list">[]</search_columns> + <search_columns type="list">[('id', 'Identifiant'), ('reference', 'Num\xe9ro de facture'), ('destination_administration_organisation_title', 'Factur\xe9e \xe0'), ('causality_id', 'Livraison vente'), ('description', 'Description'), ('simulation_state', 'Etat')]</search_columns> <select type="int">1</select> <selection_name>order_selection</selection_name> <sort type="list">[('id', 'id')]</sort> diff --git a/product/Coramy/skins/coramy_trade/sales_packing_list_print.pt b/product/Coramy/skins/coramy_trade/sales_packing_list_print.pt index d823588061..cb6ca5a772 100755 --- a/product/Coramy/skins/coramy_trade/sales_packing_list_print.pt +++ b/product/Coramy/skins/coramy_trade/sales_packing_list_print.pt @@ -101,7 +101,7 @@ <TD align="left" tal:content="python:'coloris '+coloris_list[1][index]"></TD> <SPAN tal:define="toto python:delivery_line.PT_reset_total_list(totalizer,[2])"/> <SPAN tal:repeat="target_quantity python:delivery_line.DeliveryLine_getTargetQuantityList(taille_list[2],coloris_list[2][index])"> - <TD align = right tal:content="python: '%.0f' %target_quantity"/> + <TD tal:condition="python:taille_qty!=0" align = "right" tal:content="python: '%.0f' %target_quantity"/> <SPAN tal:define="toto python:delivery_line.PT_update_total_list(totalizer,[0,1,2],target_quantity)"/> </SPAN> <TD align="right" tal:content="python: '%.0f' %totalizer[2]"/> @@ -112,7 +112,8 @@ <TR><!-- PAS DE COLORIS --> <TD align="left"></TD> <SPAN tal:define="toto python:delivery_line.PT_reset_total_list(totalizer,[2])"/> - <SPAN tal:repeat="target_quantity python:delivery_line.DeliveryLine_getTargetQuantityList(taille_list[2])"> + <SPAN tal:condition="python:taille_qty!=0" + tal:repeat="target_quantity python:delivery_line.DeliveryLine_getTargetQuantityList(taille_list[2])"> <TD align = right tal:content="python: '%.0f' %target_quantity"/> <SPAN tal:define="toto python:delivery_line.PT_update_total_list(totalizer,[0,1,2],target_quantity)"/> </SPAN> diff --git a/product/ERP5/Document/Amount.py b/product/ERP5/Document/Amount.py index 2e5446d83b..823b86802c 100755 --- a/product/ERP5/Document/Amount.py +++ b/product/ERP5/Document/Amount.py @@ -116,17 +116,18 @@ class Amount(Base, Variated): self._setVariationValue(variation_value) self.reindexObject() + security.declareProtected(Permissions.AccessContentsInformation, - 'getVariationRangeCategoryItemList') + 'getVariationRangeCategoryItemList') def getVariationRangeCategoryItemList(self, base_category_list = (), - method_id='getTitle', base=1, current_category=None): + method_id='getTitle', base=1, start_with_item=None): """ Returns possible category items for this amount ie. the variation of the resource (not the variation range) """ try: return self.getDefaultResourceValue().getVariationCategoryItemList( - base_category_list, method_id=method_id, base=base, current_category=current_category) + base_category_list, method_id=method_id, base=base, start_with_item=start_with_item) except: # FIXME: method_name vs. method_id, start_with_item vs. start_with_empty, etc. -yo return self.portal_categories.getCategoryChildItemList() @@ -294,7 +295,7 @@ class Amount(Base, Variated): """ quantity = self.getConvertedTargetQuantity() efficiency = self.getTargetEfficiency() - if efficiency in (0, 0.0, None): + if efficiency in (0, 0.0, None, ''): efficiency = 1.0 if quantity not in (None, ''): return float(quantity) / efficiency @@ -425,6 +426,15 @@ class Amount(Base, Variated): else: return 0.0 + # Inventory + security.declareProtected(Permissions.AccessContentsInformation, 'getConvertedInventory') + def getConvertedInventory(self): + """ + provides a default inventory value - None since + no inventory was defined. + """ + return None + # Profit and Loss security.declareProtected(Permissions.ModifyPortalContent, 'getLostQuantity') def getLostQuantity(self): diff --git a/product/ERP5/Document/Container.py b/product/ERP5/Document/Container.py index f16f8fa93a..8947ddcb41 100755 --- a/product/ERP5/Document/Container.py +++ b/product/ERP5/Document/Container.py @@ -204,3 +204,17 @@ Une ligne tarifaire.""" more_result += container.getContainerText() result = result + '\n'.join(map(lambda x: " %s" % x, more_result.split('\n'))) return result + + # Used for optimization - requires reindexing using container_uid + security.declareProtected(Permissions.AccessContentsInformation, 'getContainerUid') + def getContainerUid(self): + return self.getUid() + + security.declareProtected(Permissions.AccessContentsInformation, 'getContainerValue') + def getContainerValue(self): + return self + + security.declareProtected(Permissions.AccessContentsInformation, 'getContainer') + def getContainer(self): + return self.getRelativeUrl() + diff --git a/product/ERP5/Document/DeliveryCell.py b/product/ERP5/Document/DeliveryCell.py index 8fded75deb..bb47e4cd75 100755 --- a/product/ERP5/Document/DeliveryCell.py +++ b/product/ERP5/Document/DeliveryCell.py @@ -257,6 +257,7 @@ Une ligne tarifaire.""" Computes total_quantity of all given items and stores this total_quantity in the quantity attribute of the cell """ + previous_item_list = self.getAggregateValueList() given_item_id_list = value item_object_list = [] for item in given_item_id_list : @@ -270,7 +271,17 @@ Une ligne tarifaire.""" object = None if object is not None : - item_object_list.append(object) + # if item was in previous_item_list keep it + if object in previous_item_list : + # we can add this item to the list of aggregated items + item_object_list.append(object) + # if new item verify if variated_resource of item == variated_resource of movement + elif (self.getResource() == object.getResource()) and (self.getVariationCategoryList() == object.getVariationCategoryList()) : + # now verify if item can be moved (not already done) + last_location_title = object.getLastLocationTitle() + if self.getDestinationTitle() != last_location_title or last_location_title == '' : + # we can add this item to the list of aggregated items + item_object_list.append(object) # update item_id_list and build relation self.setAggregateValueList(item_object_list) @@ -284,6 +295,8 @@ Une ligne tarifaire.""" quantity += object_item.getQuantity() else : quantity += object_item.getRemainingQuantity() + # we reset the location of the item + object_item.setLocation('') self.setTargetQuantity(quantity) @@ -305,6 +318,30 @@ Une ligne tarifaire.""" else: return Movement.getInventoriatedQuantity(self) + security.declareProtected(Permissions.AccessContentsInformation, 'getStartDate') + def getStartDate(self): + """ + Take into account efficiency in converted target quantity + """ + if self.getSimulationState() in current_inventory_state_list: + # When an order is delivered, the target quantity should be considered + # rather than the quantity + return Movement.getTargetStartDate(self) + else: + return Movement.getStartDate(self) + + security.declareProtected(Permissions.AccessContentsInformation, 'getStopDate') + def getStopDate(self): + """ + Take into account efficiency in converted target quantity + """ + if self.getSimulationState() in current_inventory_state_list: + # When an order is delivered, the target quantity should be considered + # rather than the quantity + return Movement.getTargetStopDate(self) + else: + return Movement.getStopDate(self) + # Simulation Consistency Check def getRelatedQuantity(self): """ diff --git a/product/ERP5/Document/InventoryCell.py b/product/ERP5/Document/InventoryCell.py index 7f6a092352..bf45af46f8 100755 --- a/product/ERP5/Document/InventoryCell.py +++ b/product/ERP5/Document/InventoryCell.py @@ -30,6 +30,8 @@ from Globals import InitializeClass, PersistentMapping from Acquisition import aq_base, aq_inner, aq_parent, aq_self from AccessControl import ClassSecurityInfo +from Products.ERP5.ERP5Globals import current_inventory_state_list + from Products.CMFCore.WorkflowCore import WorkflowAction from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface @@ -137,9 +139,9 @@ Une ligne tarifaire.""" # Update consumption last if item_id_list is not None: self._setItemIdList(item_id_list) - elif produced_item_id_list is not None: + if produced_item_id_list is not None : self._setProducedItemIdList(produced_item_id_list) - elif consumed_item_id_list is not None: + if consumed_item_id_list is not None : self._setConsumedItemIdList(consumed_item_id_list) security.declareProtected( Permissions.ModifyPortalContent, 'hasCellContent' ) @@ -180,6 +182,9 @@ Une ligne tarifaire.""" quantity = self._baseGetQuantity() if quantity not in (0.0, 0, None): return quantity + # Make sure inventory is defined somewhere (here or parent) + if getattr(aq_base(self), 'inventory', None) is None: + return 0.0 # No inventory defined, so no quantity # Find total of movements in the past - XXX resource_value = self.getResourceValue() if resource_value is not None: @@ -189,10 +194,11 @@ Une ligne tarifaire.""" at_date = self.getStartDate(), variation_text = self.getVariationText(), node = self.getDestination(), - section = self.getDestinationSection()) + section = self.getDestinationSection(), + simulation_state = current_inventory_state_list) inventory = self.getInventory() - if inventory in (None, ''): - return None # Do not change inventory if no inventory value provided + if current_inventory in (None, ''): + current_inventory = 0.0 return self.getInventory() - current_inventory return self.getInventory() @@ -216,6 +222,7 @@ Une ligne tarifaire.""" Computes total_quantity of all given items and stores this total_quantity in the inventory attribute of the cell """ + previous_item_list = self.getAggregateValueList() given_item_id_list = value item_object_list = [] for item in given_item_id_list : @@ -229,7 +236,14 @@ Une ligne tarifaire.""" object = None if object is not None : - item_object_list.append(object) + # if item was in previous_item_list keep it + if object in previous_item_list : + # we can add this item to the list of aggregated items + item_object_list.append(object) + # if new item verify if variated_resource of item == variated_resource of movement + elif (self.getResource() == object.getResource()) and (self.getVariationCategoryList() == object.getVariationCategoryList()) : + # we can add this item to the list of aggregated items + item_object_list.append(object) # update item_id_list and build relation self.setAggregateValueList(item_object_list) @@ -240,7 +254,7 @@ Une ligne tarifaire.""" quantity = 0 for object_item in item_object_list : - quantity += object_item.getQuantity() + quantity += object_item.getRemainingQuantity() self.setInventory(quantity) @@ -252,11 +266,27 @@ Une ligne tarifaire.""" """ return Movement.getInventoriatedQuantity(self) + + security.declareProtected(Permissions.AccessContentsInformation, 'getStartDate') + def getStartDate(self): + """ + Take into account efficiency in converted target quantity + """ + return Movement.getStartDate(self) + + security.declareProtected(Permissions.AccessContentsInformation, 'getStopDate') + def getStopDate(self): + """ + Take into account efficiency in converted target quantity + """ + return Movement.getStopDate(self) + def _setProducedItemIdList(self, value): """ Computes total_quantity of all given items and stores this total_quantity in the quantity attribute of the cell """ + previous_item_list = self.getAggregateValueList() given_item_id_list = value item_object_list = [] for item in given_item_id_list : @@ -270,7 +300,17 @@ Une ligne tarifaire.""" object = None if object is not None : - item_object_list.append(object) + # if item was in previous_item_list keep it + if object in previous_item_list : + # we can add this item to the list of aggregated items + item_object_list.append(object) + # if new item verify if variated_resource of item == variated_resource of movement + elif (self.getResource() == object.getResource()) and (self.getVariationCategoryList() == object.getVariationCategoryList()) : + # now verify if item can be moved (not already done) + last_location_title = object.getLastLocationTitle() + if self.getDestinationTitle() != last_location_title or last_location_title == '' : + # we can add this item to the list of aggregated items + item_object_list.append(object) # update item_id_list and build relation self.setAggregateValueList(item_object_list) @@ -290,6 +330,7 @@ Une ligne tarifaire.""" Computes total_quantity of all given items and stores this total_quantity in the quantity attribute of the cell """ + previous_item_list = self.getAggregateValueList() given_item_id_list = value item_object_list = [] for item in given_item_id_list : @@ -303,7 +344,17 @@ Une ligne tarifaire.""" object = None if object is not None : - item_object_list.append(object) + # if item was in previous_item_list keep it + if object in previous_item_list : + # we can add this item to the list of aggregated items + item_object_list.append(object) + # if new item verify if variated_resource of item == variated_resource of movement + elif (self.getResource() == object.getResource()) and (self.getVariationCategoryList() == object.getVariationCategoryList()) : + # now verify if item can be moved (not already done) + last_location_title = object.getLastLocationTitle() + if self.getDestinationTitle() == last_location_title or last_location_title == '' : + # we can add this item to the list of aggregated items + item_object_list.append(object) # update item_id_list and build relation self.setAggregateValueList(item_object_list) @@ -315,6 +366,8 @@ Une ligne tarifaire.""" for object_item in item_object_list : quantity += object_item.getRemainingQuantity() + # we reset the location of the item + object_item.setLocation('') self.setConsumptionQuantity(quantity) @@ -335,3 +388,12 @@ Une ligne tarifaire.""" return self.getItemIdList() else : return [] + + # Inventory cataloging + security.declareProtected(Permissions.AccessContentsInformation, 'getConvertedInventory') + def getConvertedInventory(self): + """ + provides a default inventory value - None since + no inventory was defined. + """ + return self.getInventory() # XXX quantity unit is missing diff --git a/product/ERP5/Document/InventoryLine.py b/product/ERP5/Document/InventoryLine.py index 9a23bde13e..89d00c131e 100755 --- a/product/ERP5/Document/InventoryLine.py +++ b/product/ERP5/Document/InventoryLine.py @@ -130,6 +130,23 @@ Une ligne tarifaire.""" ) } + def _edit(self, REQUEST=None, force_update = 0, **kw): + kw = kw.copy() + item_id_list = kw.get('item_id_list', None) + if item_id_list is not None: del kw['item_id_list'] + produced_item_id_list = kw.get('produced_item_id_list', None) + if produced_item_id_list is not None: del kw['produced_item_id_list'] + consumed_item_id_list = kw.get('consumed_item_id_list', None) + if consumed_item_id_list is not None: del kw['consumed_item_id_list'] + DeliveryLine._edit(self, REQUEST=REQUEST, force_update = force_update, **kw) + # Update consumption last + if item_id_list is not None: + self._setItemIdList(item_id_list) + if produced_item_id_list is not None : + self._setProducedItemIdList(produced_item_id_list) + if consumed_item_id_list is not None : + self._setConsumedItemIdList(consumed_item_id_list) + security.declareProtected(Permissions.AccessContentsInformation, 'getTotalInventory') def getTotalInventory(self): """ @@ -153,7 +170,9 @@ Une ligne tarifaire.""" quantity = self._baseGetQuantity() if quantity not in (0.0, 0, None): return quantity - return self.getInventory() + # Make sure inventory is defined somewhere (here or parent) + if getattr(aq_base(self), 'inventory', None) is None: + return 0.0 # No inventory defined, so no quantity # Find total of movements in the past - XXX resource_value = self.getResourceValue() if resource_value is not None: @@ -166,8 +185,8 @@ Une ligne tarifaire.""" section = self.getDestinationSection(), simulation_state = current_inventory_state_list) inventory = self.getInventory() - if inventory in (None, ''): - return None # Do not change inventory if no inventory value provided + if current_inventory in (None, ''): + current_inventory = 0.0 return self.getInventory() - current_inventory return self.getInventory() else: @@ -229,6 +248,7 @@ Une ligne tarifaire.""" Computes total_quantity of all given items and stores this total_quantity in the inventory attribute of the cell """ + previous_item_list = self.getAggregateValueList() given_item_id_list = value item_object_list = [] for item in given_item_id_list : @@ -242,7 +262,14 @@ Une ligne tarifaire.""" object = None if object is not None : - item_object_list.append(object) + # if item was in previous_item_list keep it + if object in previous_item_list : + # we can add this item to the list of aggregated items + item_object_list.append(object) + # if new item verify if variated_resource of item == variated_resource of movement + elif (self.getResource() == object.getResource()) and (self.getVariationCategoryList() == object.getVariationCategoryList()) : + # we can add this item to the list of aggregated items + item_object_list.append(object) # update item_id_list and build relation self.setAggregateValueList(item_object_list) @@ -262,6 +289,7 @@ Une ligne tarifaire.""" Computes total_quantity of all given items and stores this total_quantity in the quantity attribute of the cell """ + previous_item_list = self.getAggregateValueList() given_item_id_list = value item_object_list = [] for item in given_item_id_list : @@ -275,7 +303,17 @@ Une ligne tarifaire.""" object = None if object is not None : - item_object_list.append(object) + # if item was in previous_item_list keep it + if object in previous_item_list : + # we can add this item to the list of aggregated items + item_object_list.append(object) + # if new item verify if variated_resource of item == variated_resource of movement + elif (self.getResource() == object.getResource()) and (self.getVariationCategoryList() == object.getVariationCategoryList()) : + # now verify if item can be moved (not already done) + last_location_title = object.getLastLocationTitle() + if self.getDestinationTitle() != last_location_title or last_location_title == '' : + # we can add this item to the list of aggregated items + item_object_list.append(object) # update item_id_list and build relation self.setAggregateValueList(item_object_list) @@ -295,6 +333,7 @@ Une ligne tarifaire.""" Computes total_quantity of all given items and stores this total_quantity in the quantity attribute of the cell """ + previous_item_list = self.getAggregateValueList() given_item_id_list = value item_object_list = [] for item in given_item_id_list : @@ -308,7 +347,17 @@ Une ligne tarifaire.""" object = None if object is not None : - item_object_list.append(object) + # if item was in previous_item_list keep it + if object in previous_item_list : + # we can add this item to the list of aggregated items + item_object_list.append(object) + # if new item verify if variated_resource of item == variated_resource of movement + elif (self.getResource() == object.getResource()) and (self.getVariationCategoryList() == object.getVariationCategoryList()) : + # now verify if item can be moved (not already done) + last_location_title = object.getLastLocationTitle() + if self.getDestinationTitle() == last_location_title or last_location_title == '' : + # we can add this item to the list of aggregated items + item_object_list.append(object) # update item_id_list and build relation self.setAggregateValueList(item_object_list) @@ -320,6 +369,8 @@ Une ligne tarifaire.""" for object_item in item_object_list : quantity += object_item.getRemainingQuantity() + # we reset the location of the item + object_item.setLocation('') self.setConsumptionQuantity(quantity) @@ -340,3 +391,35 @@ Une ligne tarifaire.""" return self.getItemIdList() else : return [] + + # Inventory cataloging + security.declareProtected(Permissions.AccessContentsInformation, 'getConvertedInventory') + def getConvertedInventory(self): + """ + provides a default inventory value - None since + no inventory was defined. + """ + return self.getInventory() # XXX quantity unit is missing + + # Required for indexing + security.declareProtected(Permissions.AccessContentsInformation, 'getInventoriatedQuantity') + def getInventoriatedQuantity(self): + """ + Take into account efficiency in converted target quantity + """ + return Movement.getInventoriatedQuantity(self) + + security.declareProtected(Permissions.AccessContentsInformation, 'getStartDate') + def getStartDate(self): + """ + Take into account efficiency in converted target quantity + """ + return Movement.getStartDate(self) + + security.declareProtected(Permissions.AccessContentsInformation, 'getStopDate') + def getStopDate(self): + """ + Take into account efficiency in converted target quantity + """ + return Movement.getStopDate(self) + diff --git a/product/ERP5/Document/Invoice.py b/product/ERP5/Document/Invoice.py index 8285623b77..57d1cdf957 100755 --- a/product/ERP5/Document/Invoice.py +++ b/product/ERP5/Document/Invoice.py @@ -28,7 +28,7 @@ from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface - +from Products.CMFCore.utils import getToolByName from AccountingTransaction import AccountingTransaction class Invoice(AccountingTransaction): @@ -55,6 +55,9 @@ class Invoice(AccountingTransaction): , PropertySheet.Amount , PropertySheet.Reference , PropertySheet.PaymentCondition + , PropertySheet.ValueAddedTax + , PropertySheet.EcoTax + , PropertySheet.CopyrightTax ) # CMF Factory Type Information @@ -111,3 +114,34 @@ An order...""" ) } + security.declareProtected(Permissions.AccessContentsInformation, 'getTotalPrice') + def getTotalPrice(self): + """ + Returns the total price for this invoice + """ + aggregate = self.Invoice_zGetTotal()[0] + return aggregate.total_price + + security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity') + def getTotalQuantity(self): + """ + Returns the total quantity for this invoice + """ + aggregate = self.Invoice_zGetTotal()[0] + return aggregate.total_quantity + + security.declareProtected(Permissions.AccessContentsInformation, 'getTotalNetPrice') + def getTotalNetPrice(self): + """ + Returns the total net price for this invoice + """ + return self.Invoice_zGetTotalNetPrice() + + security.declareProtected(Permissions.AccessContentsInformation, 'getSimulationSate') + def getSimulationState(self, id_only=1): + """ + Returns the current state in simulation + """ + portal_workflow = getToolByName(self, 'portal_workflow') + wf = portal_workflow.getWorkflowById('sale_invoice_transaction_workflow') + return wf._getWorkflowStateOf(self, id_only=id_only ) diff --git a/product/ERP5/Document/Movement.py b/product/ERP5/Document/Movement.py index 0e07eccd9f..528c7ed74b 100755 --- a/product/ERP5/Document/Movement.py +++ b/product/ERP5/Document/Movement.py @@ -315,55 +315,49 @@ a service in a public administration).""" """ return self.getTargetQuantity() + # Industrial price API + security.declareProtected(Permissions.AccessContentsInformation, 'getIndustrialPrice') + def getIndustrialPrice(self): + """ + Calculates industrial price in context of this movement + """ + resource = self.getResourceValue() + if resource is not None: + return resource.getIndustrialPrice(context=self) + return None + # Asset price calculation - security.declareProtected(Permissions.AccessContentsInformation, 'getAssetPrice') - def getAssetPrice(self, exclude_path_list = []): + security.declareProtected(Permissions.AccessContentsInformation, 'getSourceTotalAssetPrice') + def getSourceTotalAssetPrice(self): """ Returns a price which can be used to calculate stock value (asset) """ - source_value = self.getSourceValue() - if not source_value: - # This is a production movement - return self.getIndustrialPrice() - if not source_value.isMemberOf('group/Coramy'): - # accountable price - return self.getPrice() - # This is an internal movement - current_asset_price = 0.0 - current_inventory = 0.0 - exclude_path_list.append(self.getRelativeUrl()) # Prevent infinite loops - for m in self.Movement_zGetPastMovementList(node_uid = self.getSourceUid(), section_uid = self.getDestinationUid(), - before_date = self.getStartDate()): - # NB we may want to consider instead all movements at the group level - # movements should be sorted by date - movement = m.getObject() - if movement is not None and m.relative_url not in exclude_path_list: - # Only considere non loop movements - inventory = m.quantity - if inventory >= 0: - # We use asset_price inside Coramy Group - asset_price = movement.getAssetPrice(exclude_path_list = exclude_path_list) # ??? - # Update price - previous_inventory = current_inventory - current_inventory += inventory - if current_inventory > 0: - # Update price with an average of incoming goods and current goods - current_asset_price = ( current_asset_price * previous_inventory + asset_price * inventory ) / float(current_inventory) - else: - # New price is the price of incoming goods - negative stock has no meaning for asset calculation - current_asset_price = asset_price - else: - # No change in asset_price - accumulate inventory - current_inventory += inventory - - return current_asset_price - - security.declareProtected(Permissions.AccessContentsInformation, 'getTotalAssetPrice') - def getTotalAssetPrice(self): + try: + price = self.getSourceAssetPrice() + if price is None: + return None + quantity = self.getQuantity() + if quantity is None: + return None + return quantity * price + except: + return None + + security.declareProtected(Permissions.AccessContentsInformation, 'getDestinationTotalAssetPrice') + def getDestinationTotalAssetPrice(self): """ Returns a price which can be used to calculate stock value (asset) """ - return self.getAssetPrice() * self.getQuantity() + try: + price = self.getDestinationAssetPrice() + if price is None: + return None + quantity = self.getQuantity() + if quantity is None: + return None + return quantity * price + except: + return None # Causality computation security.declareProtected(Permissions.View, 'isConvergent') diff --git a/product/ERP5/Document/Order.py b/product/ERP5/Document/Order.py index 597a33bcaf..ab09d7f674 100755 --- a/product/ERP5/Document/Order.py +++ b/product/ERP5/Document/Order.py @@ -215,11 +215,50 @@ An order...""" """ Sets the order to ordered (a Workflow Script is responsible of creating the delivery) + + Confirm is still not creating deliveries XXX - check activities seriously to make sure + they are not flushed in case of error """ self._createOrderRule() + # At confirm stage, we create deliveries for this order + self.activate().buildDeliveryList() confirm = WorkflowMethod(_confirm, 'confirm') + security.declareProtected(Permissions.ModifyPortalContent, 'buildDeliveryList') + def buildDeliveryList(self): + # Make sure there is exactly one applied rule + my_applied_rule_list = self.getCausalityRelatedValueList(portal_type='Applied Rule') + if len(my_applied_rule_list) != 1: + # Make sure we have an order rule + self._createOrderRule() + # Make sure there is exactly one applied rule + my_applied_rule_list = self.getCausalityRelatedValueList(portal_type='Applied Rule') + if len(my_applied_rule_list) != 1: + # XXX This is an error + return + applied_rule = my_applied_rule_list[0].getObject() + if applied_rule is None: + # XXX This is an error + return + # Make sure applied rule has been reindexed + applied_rule.flushActivity(invoke=1) + # Make sure there are no more activities on this order related to expand + self.flushActivity(invoke=1, method_id='expand') # Make sure expand is finished + # Build delivery list on applied rule + # Currently, we build it 'again' but we should actually only build + # deliveries for orphaned movements + if self.getPortalType() == 'Production Order' : + delivery_list = self.ProductionOrder_buildDeliveryList() # Coramy specific moved to portal_simulation + elif self.getPortalType() in ('Purchase Order', 'Sales Order') : + delivery_list = self.order_create_packing_list() # Coramy specific should be moved to portal_simulation + #self.informDeliveryList(delivery_list=delivery_list, comment=repr(delivery_list)) # XXX Not ready + + def _informDeliveryList(self, delivery_list=None, comment=None): + pass + + informDeliveryList = WorkflowMethod(_informDeliveryList, id='informDeliveryList') + security.declareProtected(Permissions.ModifyPortalContent, 'cancel') def cancel(self): """ diff --git a/product/ERP5/Document/PackingList.py b/product/ERP5/Document/PackingList.py index 5993219faa..a21dc8fd0f 100755 --- a/product/ERP5/Document/PackingList.py +++ b/product/ERP5/Document/PackingList.py @@ -30,6 +30,7 @@ from Globals import InitializeClass, PersistentMapping from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface from Products.ERP5.ERP5Globals import movement_type_list, draft_order_state +from Products.CMFCore.utils import getToolByName from Delivery import Delivery diff --git a/product/ERP5/Document/Resource.py b/product/ERP5/Document/Resource.py index ee16b3e9cb..9481417780 100755 --- a/product/ERP5/Document/Resource.py +++ b/product/ERP5/Document/Resource.py @@ -406,7 +406,9 @@ a service in a public administration).""" section=section, node=node, node_category=node_category, - section_category=section_category, **kw) + section_category=section_category, + simulation_state=simulation_state, + **kw) return result security.declareProtected(Permissions.AccessContentsInformation, 'getMovementHistoryStat') @@ -423,6 +425,7 @@ a service in a public administration).""" section=section, node=node, node_category=node_category, + simulation_state=simulation_state, section_category=section_category, **kw) return result @@ -494,3 +497,23 @@ a service in a public administration).""" return None + # Industrial price API + security.declareProtected(Permissions.AccessContentsInformation, 'getIndustrialPrice') + def getIndustrialPrice(self, context=None, REQUEST=None, **kw): + """ + Returns industrial price + """ + context = self.asContext(context=context, REQUEST=REQUEST, **kw) + result = self._getIndustrialPrice(context) + if result is None: + self._updateIndustrialPrice() + result = self._getIndustrialPrice(context) + return result + + def _getIndustrialPrice(self, context): + # Default value is None + return None + + def _updateIndustrialPrice(self, context): + # Do nothing by default + pass diff --git a/product/ERP5/Document/Transformation.py b/product/ERP5/Document/Transformation.py index 213d53b808..271c08b282 100755 --- a/product/ERP5/Document/Transformation.py +++ b/product/ERP5/Document/Transformation.py @@ -288,7 +288,7 @@ une gamme...""" for transformation in transformation_list: # Browse each transformed or assorted resource of the current transformation for transformed_resource in transformation.objectValues(): - LOG("for transformed_resource in transformation",0,transformed_resource.getId()) + #LOG("for transformed_resource in transformation",0,transformed_resource.getId()) line_item_list, total_base_price, total_source_base_price, \ total_variated_base_price, total_variated_source_base_price, duration \ = transformed_resource.getAggregatedAmountList(REQUEST) diff --git a/product/ERP5/Document/ZeroStockRule.py b/product/ERP5/Document/ZeroStockRule.py index 865feb0b36..a88c7ff1ab 100755 --- a/product/ERP5/Document/ZeroStockRule.py +++ b/product/ERP5/Document/ZeroStockRule.py @@ -186,7 +186,7 @@ An ERP5 Rule...""" source = source_section = 'role/Fournisseur' destination_section = 'group/Coramy' destination = 'site/Stock_MP/Gravelines' - movement.edit(target_quantity = movement.getTargetQuantity() + quantity_dict[key]) + movement._edit(target_quantity = movement.getTargetQuantity() + quantity_dict[key]) movement._edit( target_start_date = stop_date, target_stop_date = stop_date, source = source, diff --git a/product/ERP5/ERP5Globals.py b/product/ERP5/ERP5Globals.py index 5039336632..2014125f92 100755 --- a/product/ERP5/ERP5Globals.py +++ b/product/ERP5/ERP5Globals.py @@ -37,7 +37,7 @@ variation_type_list = ('Variation', 'Variante Tissu', 'Variante Modele', node_type_list = ('Organisation','Person','Category','MetaNode',) -invoice_type_list = ('Invoice', 'Sale Invoice', 'Sales Invoice') +invoice_type_list = ('Invoice', 'Sale Invoice', 'Sales Invoice', 'Sale Invoice Transaction') order_type_list = ('Order', 'Project', 'Samples Order', 'Production Order', 'Purchase Order', 'Sale Order', @@ -63,6 +63,7 @@ delivery_type_list = ('Delivery', order_or_delivery_type_list = tuple(list(order_type_list) + list(delivery_type_list)) variation_base_category_list = ('coloris', 'taille', 'variante', 'morphologie') +variation_base_category_id_list = variation_base_category_list # Temp Patch invoice_movement_type_list = ( 'Invoice Line', diff --git a/product/ERP5/Extensions/InventoryBrain.py b/product/ERP5/Extensions/InventoryBrain.py index 9763d28736..b11ecabdf2 100755 --- a/product/ERP5/Extensions/InventoryBrain.py +++ b/product/ERP5/Extensions/InventoryBrain.py @@ -12,7 +12,7 @@ # ############################################################################## -from Products.ERP5.ERP5Globals import default_section_category, current_inventory_state_list, reserved_inventory_state_list +from Products.ERP5.ERP5Globals import default_section_category, current_inventory_state_list, reserved_inventory_state_list,future_inventory_state_list from Products.ZSQLCatalog.zsqlbrain import ZSQLBrain from DateTime import DateTime from ZTUtils import make_query @@ -52,7 +52,7 @@ class InventoryBrain(ZSQLBrain): """ Returns current inventory """ - return self.getInventory(ignore_variation=1) + return self.getInventory(ignore_variation=1,simulation_state=list(future_inventory_state_list)+list(reserved_inventory_state_list)+list(current_inventory_state_list)) def getAvailableInventory(self): """ @@ -61,24 +61,15 @@ class InventoryBrain(ZSQLBrain): at_date=DateTime() current = self.getCurrentInventory() result = self.Resource_zGetInventory( resource_uid = [self.resource_uid], ignore_variation=1, - from_date=at_date, omit_simulation = 1, omit_input = 1, + omit_simulation = 1, omit_input = 1, section_category = default_section_category, - simulation_state = None) + simulation_state = reserved_inventory_state_list) reserved_inventory = None if len(result) > 0: reserved_inventory = result[0].inventory if reserved_inventory is None: reserved_inventory = 0.0 - result = self.Resource_zGetInventory( resource_uid = [self.resource_uid], ignore_variation=1, - to_date=at_date, omit_simulation = 1, omit_input = 1, - section_category = default_section_category, - simulation_state = ('confirmed', 'getting_ready', 'ready')) - past_reserved_inventory = None - if len(result) > 0: - past_reserved_inventory = result[0].inventory - if past_reserved_inventory is None: - past_reserved_inventory = 0.0 - return current + reserved_inventory + past_reserved_inventory + return current + reserved_inventory def getQuantityUnit(self, **kw): try: @@ -123,7 +114,7 @@ class InventoryListBrain(ZSQLBrain): """ Returns current inventory """ - return self.getInventory(ignore_variation=0) + return self.getInventory(ignore_variation=0, simulation_state=list(future_inventory_state_list)+list(reserved_inventory_state_list)+list(current_inventory_state_list)) def getAvailableInventory(self): """ @@ -132,28 +123,17 @@ class InventoryListBrain(ZSQLBrain): at_date=DateTime() current = self.getCurrentInventory() result = self.Resource_zGetInventory( resource_uid = [self.resource_uid], - from_date=at_date, omit_simulation = 1, omit_input = 1, + omit_simulation = 1, omit_input = 1, section=self.section_relative_url, node=self.node_relative_url, variation_text = self.variation_text, - simulation_state = None) + simulation_state = reserved_inventory_state_list) reserved_inventory = None if len(result) > 0: reserved_inventory = result[0].inventory if reserved_inventory is None: reserved_inventory = 0.0 - result = self.Resource_zGetInventory( resource_uid = [self.resource_uid], - to_date=at_date, omit_simulation = 1, omit_input = 1, - section=self.section_relative_url, - node=self.node_relative_url, - variation_text = self.variation_text, - simulation_state = ('confirmed', 'getting_ready', 'ready')) - past_reserved_inventory = None - if len(result) > 0: - past_reserved_inventory = result[0].inventory - if past_reserved_inventory is None: - past_reserved_inventory = 0.0 - return current + reserved_inventory + past_reserved_inventory + return current + reserved_inventory def getQuantity(self, **kw): result = self.Delivery_zGetTotal( resource_uid = [self.resource_uid], @@ -201,12 +181,27 @@ class InventoryListBrain(ZSQLBrain): ) elif cname_id in ('getCurrentInventory',): resource = self.portal_categories.unrestrictedTraverse(self.resource_relative_url) - return '%s/Resource_movementHistoryView?%s' % (resource.absolute_url(), + return '%s/Resource_movementHistoryView?%s&reset=1' % (resource.absolute_url(), make_query(variation_text=self.variation_text, selection_name=selection_name, selection_index=selection_index, simulation_state=list(current_inventory_state_list))) + elif cname_id in ('getAvailableInventory',): + resource = self.portal_categories.unrestrictedTraverse(self.resource_relative_url) + return '%s/Resource_movementHistoryView?%s&reset=1' % (resource.absolute_url(), + make_query(variation_text=self.variation_text, selection_name=selection_name, selection_index=selection_index,omit_simulation = 1, omit_input = 1, + simulation_state=list(reserved_inventory_state_list))) + elif cname_id in ('getFutureInventory','inventory', ): + resource = self.portal_categories.unrestrictedTraverse(self.resource_relative_url) + return '%s/Resource_movementHistoryView?%s&reset=1' % (resource.absolute_url(), + make_query(variation_text=self.variation_text, + selection_name=selection_name, selection_index=selection_index, simulation_state=list(future_inventory_state_list)+list(reserved_inventory_state_list))) + elif cname_id in ('getInventoryAtDate',): + resource = self.portal_categories.unrestrictedTraverse(self.resource_relative_url) + return '%s/Resource_movementHistoryView?%s&reset=1' % (resource.absolute_url(), + make_query(variation_text=self.variation_text, to_date=self.at_date, + selection_name=selection_name, selection_index=selection_index, simulation_state=list(future_inventory_state_list)+list(reserved_inventory_state_list))) else: resource = self.portal_categories.unrestrictedTraverse(self.resource_relative_url) - return '%s/Resource_movementHistoryView?%s' % (resource.absolute_url(), + return '%s/Resource_movementHistoryView?%s&reset=1' % (resource.absolute_url(), make_query(variation_text=self.variation_text, selection_name=selection_name, selection_index=selection_index)) except: return '' @@ -231,13 +226,18 @@ class InventoryListBrain(ZSQLBrain): if portal_type == "Simulation Movement": order = o.getExplanationValue() if order is not None: - return "Simulated Order %s" % (order.getId()) + return "%s %s" % ('Simulated Order', order.getId()) # Tried to use unicode but failed - ListBot must use unicode in % replacements else: LOG("Delivery Value",0,str(self.path)) delivery = o.getExplanationValue() LOG("Delivery Value",0,str(delivery)) if delivery is not None: - return "%s %s" % (delivery.getPortalType(), delivery.getId()) + causality = delivery.getCausalityValue() + if causality is None: + return "%s %s" % (delivery.getPortalType(), delivery.getId()) + else: + return "%s %s (%s %s)" % (delivery.getPortalType(), delivery.getId(), + causality.getPortalType(), causality.getId()) return "Unknown" class DeliveryListBrain(InventoryListBrain): @@ -274,42 +274,22 @@ class DeliveryListBrain(InventoryListBrain): at_date=DateTime() current = self.getCurrentInventory() result = self.Resource_zGetInventory( resource_uid = [self.resource_uid], - from_date=at_date, omit_simulation = 1, omit_input = 1, + omit_simulation = 1, omit_input = 1, section_category = default_section_category, variation_text = self.variation_text, - simulation_state = None) + simulation_state = reserved_inventory_state_list ) reserved_inventory = None if len(result) > 0: reserved_inventory = result[0].inventory if reserved_inventory is None: reserved_inventory = 0.0 - result = self.Resource_zGetInventory( resource_uid = [self.resource_uid], - to_date=at_date, omit_simulation = 1, omit_input = 1, - section_category = default_section_category, - variation_text = self.variation_text, - simulation_state = ('confirmed', 'getting_ready', 'ready')) - past_reserved_inventory = None - if len(result) > 0: - past_reserved_inventory = result[0].inventory - if past_reserved_inventory is None: - past_reserved_inventory = 0.0 - return current + reserved_inventory + past_reserved_inventory + return current + reserved_inventory - def getAvailableInventoryAtDate(self): + def getInventoryAtDate(self): """ - Returns available inventory at the date provided by the SQL method + Returns inventory at the date provided by the SQL method """ at_date=self.at_date - current = self.getCurrentInventory() - result = self.Resource_zGetInventory( resource_uid = [self.resource_uid], - from_date=at_date, omit_simulation = 1, omit_input = 1, - section_category = default_section_category, - variation_text = self.variation_text, - simulation_state = None) - reserved_inventory = None - if len(result) > 0: - reserved_inventory = result[0].inventory - if reserved_inventory is None: - reserved_inventory = 0.0 - return current + reserved_inventory + LOG("At Date",0,str(at_date)) + return self.getInventory(at_date=at_date, ignore_variation=0, simulation_state=list(future_inventory_state_list)+list(reserved_inventory_state_list)+list(current_inventory_state_list)) diff --git a/product/ERP5/Interface/__init__.py b/product/ERP5/Interface/__init__.py index 8341bd8c90..5d88c12593 100755 --- a/product/ERP5/Interface/__init__.py +++ b/product/ERP5/Interface/__init__.py @@ -1,4 +1,4 @@ +from Coordinate import Coordinate from Entity import Entity from Predicate import Predicate -from Coordinate import Coordinate from Variated import Variated \ No newline at end of file diff --git a/product/ERP5/TargetSolver/SplitAndDefer.py b/product/ERP5/TargetSolver/SplitAndDefer.py index 0edd1f1c84..e3986f0719 100755 --- a/product/ERP5/TargetSolver/SplitAndDefer.py +++ b/product/ERP5/TargetSolver/SplitAndDefer.py @@ -29,6 +29,7 @@ from Products.ERP5.Tool.SimulationTool import registerTargetSolver from CopyToTarget import CopyToTarget +from zLOG import LOG class SplitAndDefer(CopyToTarget): """ diff --git a/product/ERP5/Variated.py b/product/ERP5/Variated.py index 3a50b80be7..45ea2156ad 100755 --- a/product/ERP5/Variated.py +++ b/product/ERP5/Variated.py @@ -67,15 +67,17 @@ class Variated(Base): """ return self._getVariationCategoryList(base_category_list = base_category_list) + + security.declareProtected(Permissions.AccessContentsInformation, 'getVariationCategoryItemList') def getVariationCategoryItemList(self, base_category_list = (), base=1, - method_id='getTitle', current_category=None): + method_id='getTitle', start_with_item=None): """ - Returns the list of possible variation items + Returns the list of possible variations """ variation_category_item_list = [] - if current_category is not None: - variation_category_item_list.append(current_category) + if start_with_item is not None: + variation_category_item_list.append(start_with_item) variation_category_list = self.getVariationCategoryList(base_category_list=base_category_list) for variation_category in variation_category_list: resource = self.portal_categories.resolveCategory(variation_category) @@ -85,7 +87,7 @@ class Variated(Base): else: index = variation_category.find('/') + 1 label = variation_category[index:] - variation_category_item_list.append((value, label)) + variation_category_item_list.append((label, label)) # We do not know if value is on left or right return variation_category_item_list security.declareProtected(Permissions.ModifyPortalContent, '_setVariationCategoryList') @@ -127,7 +129,7 @@ class Variated(Base): security.declareProtected(Permissions.AccessContentsInformation, 'getVariationRangeBaseCategoryItemList') - def getVariationRangeBaseCategoryItemList(self, base=1, method_id='getTitle', current_category=None): + def getVariationRangeBaseCategoryItemList(self, base=1, method_id='getTitle', start_with_item=None): """ Returns possible variations of the resource as a list of tuples (id, title). This is mostly @@ -188,9 +190,6 @@ class Variated(Base): clist = [(None,None)] return clist - # Missing methods - # getVariationBaseCategoryItemList - # Help security.declareProtected(Permissions.AccessContentsInformation, 'getMatrixVariationRangeBaseCategoryList') diff --git a/product/ERP5/skins/erp5_accounting/sale_invoice_transaction_view.form b/product/ERP5/skins/erp5_accounting/sale_invoice_transaction_view.form index 2d2678351e..867cd5f936 100755 --- a/product/ERP5/skins/erp5_accounting/sale_invoice_transaction_view.form +++ b/product/ERP5/skins/erp5_accounting/sale_invoice_transaction_view.form @@ -138,7 +138,7 @@ <hidden type="int">0</hidden> <jump_method>base_jump_relation</jump_method> <max_length></max_length> - <portal_type type="list">[('Sale Packing List', 'Sale Packing List')]</portal_type> + <portal_type type="list">[('Sale Packing List', 'Sale Packing List'), ('Sales Packing List', 'Sales Packing List')]</portal_type> <required type="int">0</required> <title>Packing List</title> <truncate type="int">0</truncate> @@ -408,4 +408,4 @@ </fields> </group> </groups> -</form> \ No newline at end of file +</form> diff --git a/product/ERP5/skins/erp5_core/base_edit.py b/product/ERP5/skins/erp5_core/base_edit.py index 3b853c5062..a86669445d 100755 --- a/product/ERP5/skins/erp5_core/base_edit.py +++ b/product/ERP5/skins/erp5_core/base_edit.py @@ -103,7 +103,10 @@ try: o = context.restrictedTraverse(url) v.update(gv) o.edit(**v) - o.flushActivity(invoke = 1) # This is required if we wish to provide immediate display + o.flushActivity(method_id="immediateReindexObject", + invoke = 1) # This is required if we wish to provide immediate display + o.flushActivity(method_id="recursiveImmediateReindexObject", + invoke = 1) # Requires if we want to display indexed subobject data... but long # However it seems it reindexed many many times... XXX # Maybe we should build a list of objects we need # Update basic attributes diff --git a/product/ERP5/skins/erp5_core/base_update_relation.py b/product/ERP5/skins/erp5_core/base_update_relation.py index 6144c8024c..2e44245ba5 100755 --- a/product/ERP5/skins/erp5_core/base_update_relation.py +++ b/product/ERP5/skins/erp5_core/base_update_relation.py @@ -58,7 +58,7 @@ try: #if f.get_value('base_category') == base_category: k = f.id v = getattr(request,k,None) - if v in (None, '', 'None', []) and context.getProperty(k[3:]) in (None, '', 'None', []): + if v in (None, '', 'None', [], ()) and context.getProperty(k[3:]) in (None, '', 'None', [], ()): # The old value is None and the new value is not significant # This bug fix is probably temporary since '' means None pass @@ -108,7 +108,7 @@ try: uids, object_uid) elif len(relation_list) > 0: - # If we have only one in the list, we don't want to lost our time by + # If we have only one in the list, we don't want to lose our time by # selecting it. So we directly do the update if len(relation_list) == 1: selection_index=None diff --git a/product/ERP5/skins/erp5_core/doFavorite.py b/product/ERP5/skins/erp5_core/doFavorite.py index b4e6de1226..7a76543a62 100755 --- a/product/ERP5/skins/erp5_core/doFavorite.py +++ b/product/ERP5/skins/erp5_core/doFavorite.py @@ -2,7 +2,24 @@ import string -doAction = favorite_select.split() +#doAction = favorite_select.split() Previous implementation +if favorite_select.find('local_roles=') > 0: + # Some local roles are defined + url_items = favorite_select.split('&') # split parameters + new_items = [] + for item in url_items: + if item.find('local_roles=') >= 0: + local_roles = item[item.find('local_roles='):].split(';') + for role in local_roles: + role = role.split('=') + if len(role[len(role)-1]) > 0: + new_items.append("local_roles:list=%s" % role[len(role)-1]) + else: + new_items.append(item) + + favorite_select = '&'.join(new_items) + +doAction = (favorite_select,) doAction0 = doAction[0] request = context.REQUEST diff --git a/product/ERP5/skins/erp5_core/workflow_status_modify.py b/product/ERP5/skins/erp5_core/workflow_status_modify.py index cf7586bdc1..6cc4afc21a 100755 --- a/product/ERP5/skins/erp5_core/workflow_status_modify.py +++ b/product/ERP5/skins/erp5_core/workflow_status_modify.py @@ -3,6 +3,7 @@ from Products.Formulator.Errors import ValidationError, FormValidationError request=context.REQUEST + try: # Validate the form form = getattr(context,dialog_id) diff --git a/product/ERP5/skins/erp5_html_style/list_menu_box.pt b/product/ERP5/skins/erp5_html_style/list_menu_box.pt index 02b4a56f3c..e0b0c9d0d5 100755 --- a/product/ERP5/skins/erp5_html_style/list_menu_box.pt +++ b/product/ERP5/skins/erp5_html_style/list_menu_box.pt @@ -56,7 +56,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. <img src="/images/pro/images/sepacla.png" alt="|"/> <span tal:condition="print_actions"> <a href="print" - tal:attributes="href python:print_actions[0]['url']"> + tal:attributes="href python:print_actions[0]['url'] + + '?selection_name=%s&dialog_category=%s&form_id=%s' + % (selection_name , 'object_print', form_id) "> <img src="/images/pro/images/print.png" title="Print" width="22" height="22" alt="Print" border="0"/> </a> diff --git a/product/ERP5/skins/erp5_trade/sale_invoice_transaction_view.form b/product/ERP5/skins/erp5_trade/sale_invoice_transaction_view.form index 2b746fffea..f93e77f057 100755 --- a/product/ERP5/skins/erp5_trade/sale_invoice_transaction_view.form +++ b/product/ERP5/skins/erp5_trade/sale_invoice_transaction_view.form @@ -209,7 +209,7 @@ <list_action>folder_contents</list_action> <list_method type="method">searchFolder</list_method> <meta_types type="list">[]</meta_types> - <portal_types type="list">[]</portal_types> + <portal_types type="list">[('Sale Invoice Transaction Line','Sale Invoice Transaction Line')]</portal_types> <report_root_list type="list">[]</report_root_list> <report_tree type="int">0</report_tree> <search type="int">0</search> @@ -326,4 +326,4 @@ </fields> </group> </groups> -</form> \ No newline at end of file +</form> diff --git a/product/ERP5Form/ListBox.py b/product/ERP5Form/ListBox.py index 128bcdc7d9..7d83517830 100755 --- a/product/ERP5Form/ListBox.py +++ b/product/ERP5Form/ListBox.py @@ -1014,8 +1014,7 @@ onChange="submitAction(this.form,'%s/portal_selections/setReportRoot')"> list_body += '<td class="Data"> </td>' list_body += '</tr>' - list_html = header + selection_line + list_header + \ - list_search + list_body + footer + list_html = header + selection_line + list_header + list_search + list_body + footer #Create DomainTree Selector and DomainTree box diff --git a/product/ERP5Form/PDFTemplate.py b/product/ERP5Form/PDFTemplate.py index 50c637ab9d..56a8a2d16b 100755 --- a/product/ERP5Form/PDFTemplate.py +++ b/product/ERP5Form/PDFTemplate.py @@ -132,6 +132,8 @@ class PDFTemplate(ZopePageTemplate): def __call__(self, *args, **kwargs): doc_xml = ZopePageTemplate.__call__(self, *args, **kwargs) + batch_mode = kwargs.get('batch_mode', 0) + request = kwargs.get('REQUEST', None) if not request: request = get_request() @@ -141,7 +143,7 @@ class PDFTemplate(ZopePageTemplate): report_tool = getToolByName(self, 'portal_report') pdf = report_tool.renderPDF(self.pdf_stylesheet, doc_xml, context=self.pt_getContext()['here'], *args, **kwargs) - if request: + if request and not batch_mode: request.RESPONSE.setHeader('Content-Type','application/pdf') request.RESPONSE.setHeader('Content-Length',len(pdf)) request.RESPONSE.setHeader('Content-Disposition','inline;filename=%s.pdf' % self.id) diff --git a/product/ERP5Form/SelectionTool.py b/product/ERP5Form/SelectionTool.py index 6e33492444..cfc5211e78 100755 --- a/product/ERP5Form/SelectionTool.py +++ b/product/ERP5Form/SelectionTool.py @@ -69,6 +69,14 @@ class SelectionTool( UniqueObject, SimpleItem ): , 'manage_overview' ) manage_overview = DTMLFile( 'explainCategoryTool', _dtmldir ) + security.declareProtected(ERP5Permissions.View, 'callSelectionFor') + def callSelectionFor(self, selection_name, context=None, REQUEST=None): + if context is None: context = self + selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) + if selection is None: + return None + return selection(context=context) + security.declareProtected(ERP5Permissions.View, 'getSelectionFor') def getSelectionFor(self, selection_name, REQUEST=None): """ diff --git a/product/ERP5Type/ZopePatch.py b/product/ERP5Type/ZopePatch.py index 830269f480..c78be828a1 100755 --- a/product/ERP5Type/ZopePatch.py +++ b/product/ERP5Type/ZopePatch.py @@ -62,6 +62,7 @@ ObjectManager._importObjectFromFile=PatchedObjectManager._importObjectFromFile ############################################################################## # Properties from OFS.PropertyManager import PropertyManager, type_converters +from OFS.PropertyManager import escape class ERP5PropertyManager(PropertyManager): @@ -173,6 +174,7 @@ PropertyManager.propertyValues = ERP5PropertyManager.propertyValues PropertyManager.propertyItems = ERP5PropertyManager.propertyItems PropertyManager._propertyMap = ERP5PropertyManager._propertyMap PropertyManager.propdict = ERP5PropertyManager.propdict +PropertyManager.hasProperty = ERP5PropertyManager.hasProperty ############################################################################## diff --git a/product/ZSQLCatalog/SQLCatalog.py b/product/ZSQLCatalog/SQLCatalog.py index ed42cadbe4..0a0922af35 100755 --- a/product/ZSQLCatalog/SQLCatalog.py +++ b/product/ZSQLCatalog/SQLCatalog.py @@ -522,7 +522,7 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): else: kw['query'] = join(query, ' AND ') - LOG("Search Query Args:",0,str(kw)) + #LOG("Search Query Args:",0,str(kw)) # Compute "sort_index", which is a sort index, or none: if kw.has_key('sort-on'): diff --git a/product/ZSQLCatalog/zsqlbrain.py b/product/ZSQLCatalog/zsqlbrain.py index 2928b2205f..c7e0d6575b 100755 --- a/product/ZSQLCatalog/zsqlbrain.py +++ b/product/ZSQLCatalog/zsqlbrain.py @@ -58,7 +58,7 @@ class ZSQLBrain(Acquisition.Implicit): """Try to return the object for this record""" try: obj = self.aq_parent.unrestrictedTraverse(self.getPath()) - if not obj: + if obj is None: if REQUEST is None: REQUEST = self.REQUEST obj = self.aq_parent.portal_catalog.resolve_url(self.getPath(), REQUEST) @@ -72,3 +72,19 @@ class ZSQLBrain(Acquisition.Implicit): returns the path stored in the Catalog """ return self.path + + def resolve_url(self, path, REQUEST): + """ + Taken from ZCatalog + + Attempt to resolve a url into an object in the Zope + namespace. The url may be absolute or a catalog path + style url. If no object is found, None is returned. + No exceptions are raised. + """ + script=REQUEST.script + if string.find(path, script) != 0: + path='%s/%s' % (script, path) + try: return REQUEST.resolve_url(path) + except: pass + -- 2.30.9