Commit d1b2028e authored by Jérome Perrin's avatar Jérome Perrin

erp5_trade: Order Report improvements

- Optionally group by function
- Give higher priority to Order Report compared to Workflow Report
- Optionally filter by Quantity Unit and enable Stat Columns for Quantity

TODO: Quantity also for Thirs Party if filtered by quantity Unit

Conflicts:
	bt5/erp5_trade/SkinTemplateItem/portal_skins/erp5_trade/OrderModule_getOrderReportSectionList.xml
	bt5/erp5_trade/SkinTemplateItem/portal_skins/erp5_trade/OrderModule_getOrderStatList.xml
parent 1fa13c63
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>8.0</float> </value>
<value> <float>12.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
......
......@@ -52,8 +52,98 @@
<key> <string>_body</string> </key>
<value> <string>from Products.ERP5Form.Report import ReportSection\n
from DateTime import DateTime\n
<<<<<<< HEAD
\n
params, stat_columns, selection_columns = context.OrderModule_getOrderReportParameterDict()\n
=======
result=[]\n
\n
request = container.REQUEST\n
# list only if user has a login defined\n
aggregation_level = request.get(\'aggregation_level\')\n
from_date = request.get(\'from_date\')\n
to_date = request.get(\'at_date\')\n
group_by = request.get(\'group_by\')\n
quantity_unit = request.get(\'quantity_unit\')\n
simulation_state = request.get(\'simulation_state\', ())\n
\n
# define some parameter dependings on module\n
if "Sale" in context.getPortalType():\n
report_type = "sale"\n
line_portal_type = "Sale Order Line"\n
doc_portal_type = "Sale Order"\n
elif "Purchase" in context.getPortalType():\n
report_type = "purchase"\n
line_portal_type = "Purchase Order Line"\n
doc_portal_type = "Purchase Order"\n
elif request.get(\'order_report_document_portal_type\'):\n
doc_portal_type = request.get(\'order_report_document_portal_type\')\n
if doc_portal_type == \'Purchase Invoice Transaction\':\n
line_portal_type = \'Invoice Line\'\n
report_type = \'purchase\'\n
elif doc_portal_type == \'Sale Invoice Transaction\':\n
line_portal_type = \'Invoice Line\'\n
report_type = \'sale\'\n
else:\n
raise ValueError, "unknown document portal type for report %s" % doc_portal_type\n
else:\n
raise ValueError, "unknown type for report"\n
\n
selection_columns = [(\'group_by\', "Group by")]\n
if from_date is None:\n
# get the minimum start date in catalog\n
from Products.ZSQLCatalog.SQLCatalog import Query, NegatedQuery\n
kw = {"delivery.start_date" : None, "key":"DefaultKey"}\n
q = NegatedQuery(Query(**kw))\n
select_expression = "MIN(delivery.start_date)"\n
group_by = "delivery.start_date"\n
from_date = DateTime()\n
result_list = context.portal_catalog(\n
select_expression=select_expression,\n
group_by_expression=group_by,\n
simulation_state=simulation_state,\n
portal_type=doc_portal_type,\n
query=q,\n
limit=1)\n
if result_list:\n
from_date = DateTime(result_list[0][2])\n
\n
\n
# get period list between given date\n
interval_list_dict = getIntervalListBetweenDates(from_date=from_date, to_date=to_date,\n
keys={\'year\':aggregation_level=="year",\n
\'month\':aggregation_level=="month",\n
\'week\' : aggregation_level=="week",\n
\'day\':aggregation_level=="day"})\n
interval_list = interval_list_dict[aggregation_level]\n
\n
# FIXME: translate column names\n
# list columns of the listbox\n
interval_column_list = []\n
if group_by == "client":\n
interval_column_list.extend([("Amount %s" %x,"Amount %s" %x) for x in interval_list])\n
selection_columns = [(\'client\', "Client")]\n
stat_columns = [(\'client\', "client")]\n
total_column_list = [(\'total amount\', \'Total Amount\'),]\n
total_stat_list = [(\'total amount\', \'total amount\'),]\n
else:\n
if group_by == "product":\n
selection_columns = [(\'product\', "Product")]\n
stat_columns = [(\'product\', "product")]\n
elif group_by == "function":\n
function_title = context.AccountingTransactionLine_getFunctionBaseCategoryTitle()\n
selection_columns = [(\'product\', function_title)]\n
stat_columns = [(\'product\', "product")]\n
else:\n
selection_columns = [(\'client\', "Client"), (\'product\', "Product")]\n
stat_columns = [(\'client\', "client"), (\'product\', "product")]\n
for x in interval_list:\n
interval_column_list.extend([("Amount %s" %x,"Amount %s" %x), ("Quantity %s" %x,"Quantity %s" %x)])\n
if not quantity_unit:\n
interval_column_list.extend([("Quantity Unit %s" %x,"Quantity Unit %s" %x)])\n
total_column_list = [(\'total amount\', \'Total Amount\'),(\'total quantity\', \'Total Quantity\')]\n
total_stat_list = [(\'total amount\', \'total amount\'),(\'total quantity\', \'total quantity\')]\n
>>>>>>> db89097... erp5_trade: Order Report improvements
\n
context.REQUEST.set(\'stat_columns\', stat_columns)\n
result=[]\n
......
......@@ -59,7 +59,75 @@ portal = context.getPortalObject()\n
\n
request = container.REQUEST\n
report_group_by = request.get(\'group_by\', None)\n
<<<<<<< HEAD
active_process_path = request.get(\'active_process\')\n
=======
quantity_unit = request.get(\'quantity_unit\', None)\n
# get all category\n
incoterm = request.get(\'incoterm\', None)\n
section_category = request.get(\'section_category\', None)\n
order = request.get(\'order\', None)\n
delivery_mode = request.get(\'delivery_mode\', None)\n
\n
catalog_params = {}\n
\n
# get all organisations for the selected section category\n
if section_category:\n
group_uid = category_tool.getCategoryValue(section_category).getUid()\n
organisation_uid_list = [x.uid for x in portal.portal_catalog(\n
portal_type="Organisation",\n
default_group_uid=group_uid)]\n
if report_type == "sale":\n
catalog_params[\'default_source_section_uid\'] = organisation_uid_list or -1\n
elif report_type:\n
catalog_params[\'default_destination_section_uid\'] = organisation_uid_list or -1\n
\n
# add category params if defined\n
if incoterm not in (\'\', None):\n
incoterm_uid = category_tool.incoterm.restrictedTraverse(incoterm).getUid()\n
catalog_params[\'default_incoterm_uid\'] = incoterm_uid\n
if order not in (\'\', None):\n
order_uid = category_tool.order.restrictedTraverse(order).getUid()\n
catalog_params[\'default_order_uid\'] = order_uid\n
if delivery_mode not in (\'\', None):\n
delivery_mode_uid = category_tool.delivery_mode.restrictedTraverse(delivery_mode).getUid()\n
catalog_params[\'default_delivery_mode_uid\'] = delivery_mode_uid\n
\n
# compute sql params, we group and order by date and portal type\n
if aggregation_level == "year":\n
date_format = "%Y"\n
elif aggregation_level == "month":\n
date_format = "%Y-%m"\n
elif aggregation_level == "week":\n
date_format = "%Y-%U"\n
elif aggregation_level == "day":\n
date_format = "%Y-%m-%d"\n
\n
params = {"delivery.start_date":(from_date, to_date)}\n
query=None\n
if from_date is not None and to_date is not None:\n
params = {"delivery.start_date":(from_date, to_date)}\n
query = Query(range="minngt", **params)\n
elif from_date is not None:\n
params = {"delivery.start_date":from_date}\n
query = Query(range="min", **params)\n
elif to_date is not None:\n
params = {"delivery.start_date":to_date}\n
query = Query(range="ngt", **params)\n
\n
sort_on_list = [ (\'delivery.destination_section_uid\', \'ASC\'), (\'delivery.start_date\',\'ASC\')]\n
\n
if request.get(\'use_selection\'):\n
selection_name = request[\'selection_name\']\n
result_list = \\\n
context.portal_selections.callSelectionFor(request[\'selection_name\'])\n
else:\n
result_list = context.portal_catalog.searchResults(limit=None,query=query,\n
portal_type=doc_portal_type,\n
simulation_state=simulation_state,\n
sort_on=sort_on_list,\n
**catalog_params)\n
>>>>>>> db89097... erp5_trade: Order Report improvements
\n
# We have to sum product_dict and client_dict from the results of active process\n
def _addDict(global_dict, local_dict, only_amount=False):\n
......@@ -106,9 +174,46 @@ if active_process_path:\n
if not len(product_dict) and len(result_product_dict):\n
product_dict = result_product_dict.copy()\n
else:\n
<<<<<<< HEAD
_addDict(product_dict, result_product_dict)\n
else:\n
raise ValueError("No active process found to process report")\n
=======
line_dict = product_dict[client_title]\n
else:\n
line_dict = product_dict\n
\n
if report_group_by != "client":\n
# client_title -> product_title -> period -> amount/quantity...\n
# or product_title -> period -> amount/quantity...\n
for line in result.contentValues(filter = {\'portal_type\':line_portal_type}):\n
# Filter by quantity_unit\n
if quantity_unit:\n
if line.getQuantityUnit() != quantity_unit:\n
continue\n
# FIXME: if two resources have the same title, do we want to group ?\n
if report_group_by == "function":\n
if report_type == "sale":\n
product_title = line.getSourceFunctionTitle()\n
else:\n
product_title = line.getDestinationFunctionTitle()\n
else:\n
product_title = line.getResourceTitle()\n
if not line_dict.has_key(product_title):\n
line_dict[product_title] = {period :{"amount" : line.getTotalPrice(),\n
"quantity" : line.getTotalQuantity(),\n
"quantity_unit" : line.getQuantityUnitTranslatedTitle()}}\n
else:\n
if not line_dict[product_title].has_key(period):\n
line_dict[product_title][period] = {"amount" : line.getTotalPrice(),\n
"quantity" : line.getTotalQuantity(),\n
"quantity_unit" : line.getQuantityUnitTranslatedTitle()}\n
else:\n
line_dict[product_title][period][\'amount\'] = line_dict[product_title][period][\'amount\'] + line.getTotalPrice()\n
line_dict[product_title][period][\'quantity\'] = line_dict[product_title][period][\'quantity\'] + line.getTotalQuantity()\n
\n
\n
>>>>>>> db89097... erp5_trade: Order Report improvements
\n
def sortProduct(a, b):\n
return cmp(a[\'product\'], b[\'product\'])\n
......@@ -169,6 +274,12 @@ if len(client_dict):\n
line_product_dict[product_title][period][\'amount\']\n
else:\n
period_counter_dict[\'Amount %s\' %(period)] = line_product_dict[product_title][period][\'amount\']\n
if quantity_unit:\n
if period_counter_dict.has_key(\'Quantity %s\' %(period)):\n
period_counter_dict[\'Quantity %s\' %(period)] = period_counter_dict[\'Quantity %s\' %(period)] + \\\n
line_product_dict[product_title][period][\'quantity\']\n
else:\n
period_counter_dict[\'Quantity %s\' %(period)] = line_product_dict[product_title][period][\'quantity\']\n
\n
else:\n
obj[\'Amount %s\' %(period)] = 0\n
......@@ -182,6 +293,11 @@ if len(client_dict):\n
period_counter_dict[\'total amount\'] = period_counter_dict[\'total amount\'] + line_total_amount\n
else:\n
period_counter_dict[\'total amount\'] = line_total_amount\n
if quantity_unit:\n
if period_counter_dict.has_key(\'total quantity\'):\n
period_counter_dict[\'total quantity\'] = period_counter_dict[\'total quantity\'] + line_total_quantity\n
else:\n
period_counter_dict[\'total quantity\'] = line_total_quantity\n
\n
product_lines_list.append(obj)\n
# sort product list\n
......@@ -189,7 +305,7 @@ if len(client_dict):\n
extend(product_lines_list)\n
else:\n
# products\n
if report_group_by == "product":\n
if report_group_by in ("product", "function"):\n
for product_title in product_dict.keys():\n
obj = Object(uid="new_")\n
obj[\'product\'] = product_title\n
......@@ -208,6 +324,11 @@ else:\n
period_counter_dict[\'Amount %s\' %(period)] = period_counter_dict[\'Amount %s\' %(period)] + product_dict[product_title][period][\'amount\']\n
else:\n
period_counter_dict[\'Amount %s\' %(period)] = product_dict[product_title][period][\'amount\']\n
if quantity_unit:\n
if period_counter_dict.has_key(\'Quantity %s\' %(period)):\n
period_counter_dict[\'Quantity %s\' %(period)] = period_counter_dict[\'Quantity %s\' %(period)] + product_dict[product_title][period][\'quantity\']\n
else:\n
period_counter_dict[\'Quantity %s\' %(period)] = product_dict[product_title][period][\'quantity\']\n
else:\n
obj[\'Amount %s\' %(period)] = 0\n
obj[\'Quantity %s\' %(period)] = 0\n
......@@ -220,6 +341,11 @@ else:\n
period_counter_dict[\'total amount\'] = period_counter_dict[\'total amount\'] + line_total_amount\n
else:\n
period_counter_dict[\'total amount\'] = line_total_amount\n
if quantity_unit:\n
if period_counter_dict.has_key(\'total quantity\'):\n
period_counter_dict[\'total quantity\'] = period_counter_dict[\'total quantity\'] + line_total_quantity\n
else:\n
period_counter_dict[\'total quantity\'] = line_total_quantity\n
append(obj)\n
\n
line_list.sort(sortProduct)\n
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5Form" module="Products.ERP5Form.Form"/>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......@@ -94,6 +94,7 @@
<string>your_delivery_mode</string>
<string>your_from_date</string>
<string>your_group_by</string>
<string>your_quantity_unit</string>
<string>your_incoterm</string>
<string>your_order</string>
<string>your_section_category</string>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>your_quantity_unit</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_dialog_mode_category</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Quantity Unit</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -112,6 +112,7 @@
<list>
<string>your_aggregation_level</string>
<string>your_group_by</string>
<string>your_quantity_unit</string>
<string>your_simulation_state</string>
</list>
</value>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>your_quantity_unit</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_dialog_mode_category</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Quantity Unit</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5Form" module="Products.ERP5Form.Form"/>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment