Commit 8b78c1a7 authored by Sebastien Robin's avatar Sebastien Robin

mrp: add Gantt chart of manufacturing available in renderjs interface

parent 2f00c84c
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>manufacturing_order_module_view_gantt</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>2.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Manufacturing Order Module Gantt</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/ManufacturingOrderModule_viewGantt</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>manufacturing_gantt</string>
</list>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ManufacturingOrderModule_viewGantt</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Delivery_viewPlanning</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_view</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Planning</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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>default</string>
<string>gadget_url</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>manufacturing_gantt</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>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<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>gadget_url</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</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>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_gadget_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>gadget_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Manufacturing Gantt</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: {\'portal_type\': ["Manufacturing Order", "Manufacturing Execution"],}</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python:\'gadget_officejs_manufacturing_gantt.html\'</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -12,6 +12,7 @@ Manufacturing Order Line | jump_to_transformation
Manufacturing Order Line | price_view
Manufacturing Order Line | quantity_view
Manufacturing Order Line | view
Manufacturing Order Module | manufacturing_order_module_view_gantt
Manufacturing Order Module | view
Manufacturing Order | jump_to_related_internal_packing_list
Manufacturing Order | jump_to_related_manufacturing_execution
......
This source diff could not be displayed because it is too large. You can view the blob instead.
<!DOCTYPE html>
<html>
<head>
<title>Gantt Interface</title>
</head>
<body>
<h1>widget_gantt_interface</h1>
<h3>A Gantt gadget allows to display various types of schedules using Gantt diagrams</h3>
<dl>
<dt>render</dt>
<dd>render a Gantt diagram</dd>
<dl>
<dt data-parameter-required="required" data-parameter-type="object">configuration_dict</dt>
<dd><code style="display:block;white-space:pre-wrap">
Generic timeline gadget. The purpose of this gadget is to provide an unique
API for various gantt libraries
Options supported are :
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Parameters to generate a gantt",
"properties": {
"data_list": {
"description": "the list of task to be displayed in timeline",
"items": {
"properties" : {
"title": {
"description": "The title of the task",
"type": "string"
},
"id": {
"description": "an identifier for the task",
"type": "string"
},
"parent_id": {
"description": "the identifier of the corresponding parent, this is optional for top level task",
"type": "string"
},
"start_date": {
"description": "task starting date",
"type": "string"
},
"stop_date": {
"description": "task end date",
"type": "string"
},
"background_color": {
"description": "task color",
"type": "string"
},
"type": {
"description": "type of task. project is for a task depending on subtast, milestone represent a milestone, and task is a standard task",
"type": "string",
"default": "task",
"enum": ["task", "project", "milestone"]
},
},
"additionalProperties": false,
"type": "object",
},
"type": "array",
}
},
"additionalProperties": false
}
Example of options:
{ data_list : [{'id': '1',
'title': 'Phase 1',
'start_date': '2017-03-01',
'stop_date': '2017-04-15',
'type': 'project'},
{'id': '1.1',
'parent_id': '1',
'title': 'Task A in Phase 1',
'start_date': '2017-03-01',
'stop_date': '2017-04-10',
'type': 'task'},
{'id': '1.2',
'parent_id': '1.1',
'title': 'Task B in Phase 1',
'start_date': '2017-04-01',
'stop_date': '2017-04-15',
'type': 'task'},
{'id': '2',
'title': 'Phase 2',
'start_date': '2017-04-15',
'stop_date': '2017-06-30',
'type': 'task'}]
}
</code></dd>
</dl>
</dl>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 Widget Timeline with Vis</title>
<!-- interfaces -->
<link rel="http://www.renderjs.org/rel/interface" href="gadget_officejs_interface_widget_gantt.html">
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_officejs_manufacturing_gantt.js" type="text/javascript"></script>
</head>
<body>
<div class="gantt-content">
</div>
</body>
</html>
\ No newline at end of file
/*global window, rJS, RSVP, console */
/*jslint nomen: true, indent: 2 */
(function (window, rJS, RSVP) {
"use strict";
/////////////////////////////////////////////////////////////////
// templates
/////////////////////////////////////////////////////////////////
var gadget_klass = rJS(window);
/////////////////////////////////////////////////////////////////
// some methods
/////////////////////////////////////////////////////////////////
gadget_klass
/////////////////////////////////////////////////////////////////
// ready
/////////////////////////////////////////////////////////////////
.ready(function (gadget) {
gadget.property_dict = {};
})
/////////////////////////////////////////////////////////////////
// published methods
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// acquired methods
/////////////////////////////////////////////////////////////////
.declareAcquiredMethod("jio_allDocs", "jio_allDocs")
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.declareMethod('render', function (option_dict) {
var gadget = this,
container,
graph_data_and_parameter,
chart;
gadget.property_dict.option_dict = option_dict.value;
console.log("gantt option_dict", option_dict.value);
gadget.renderGantt(); //Launched as service, not blocking
})
.declareJob("renderGantt", function () {
var gadget = this,
option_dict = gadget.property_dict.option_dict;
return gadget.declareGadget(
"unsafe/gadget_officejs_widget_gantt_dhtmlx.html",
{scope: "gantt",
sandbox: "iframe",
element: gadget.element.querySelector(".gantt-content")
})
.push(function (gantt_widget) {
// First search all production report not finished to find out the
// list of production orders still having work on them
var query;
gadget.property_dict.gantt_widget = gantt_widget;
console.log("gantt_widget", gantt_widget);
query = 'portal_type:="Manufacturing Execution" AND NOT simulation_state: ("draft", "cancelled", "delivered")';
return gadget.jio_allDocs({
query: query,
limit: 10000,
sort_on: [['delivery.start_date', 'ascending']],
select_list: ['reference', 'title', 'start_date', 'stop_date', 'uid', 'causality_uid']
});
})
.push(function (delivery_list) {
var causality_uid_list = [0], // Initiliaze with 0 to make sure to have at least one uid to search for
i, delivery, query;
delivery_list = delivery_list.data.rows;
for (i = 0; i < delivery_list.length; i = i + 1) {
delivery = delivery_list[i].value;
if (causality_uid_list.indexOf(delivery.causality_uid) === -1) {
causality_uid_list.push(delivery.causality_uid);
}
}
query = 'portal_type:="Manufacturing Execution" AND causality_uid: (' + causality_uid_list.join(', ') + ') AND NOT simulation_state: ("draft", "cancelled")';
console.log("QUERY", query);
return gadget.jio_allDocs({
query: query,
limit: 10000,
sort_on: [['delivery.start_date', 'ascending']],
select_list: ['reference', 'title', 'start_date', 'stop_date', 'uid', 'causality_uid', 'causality_title']
});
})
.push(function (delivery_list) {
var i, delivery, causality_list = [],
causality_dict = {}, causality_data,
gantt_data = {},
tree_list = [],
data_list = [],
sale_order_uid,
delivery_data, tree_data;
delivery_list = delivery_list.data.rows;
for (i = 0; i < delivery_list.length; i = i + 1) {
delivery = delivery_list[i].value;
if (delivery.causality_uid !== undefined) {
if (causality_list.indexOf(delivery.causality_uid) === -1) {
causality_list.push(delivery.causality_uid);
}
causality_data = causality_dict[delivery.causality_uid] || {'start_date': new Date(delivery.start_date),
'stop_date': new Date(delivery.stop_date),
'title': delivery.causality_title,
'type': 'project',
'id': delivery.causality_uid};
causality_data.start_date = new Date(Math.min.apply(
null, [causality_data.start_date, new Date(delivery.start_date)]));
causality_data.stop_date = new Date(Math.max.apply(
null, [causality_data.stop_date, new Date(delivery.stop_date)]));
causality_dict[delivery.causality_uid] = causality_data;
}
if (i === 0) {
// We assume that by the sort on order_reference that the first line is a level 1 line
sale_order_uid = delivery.parent_uid;
}
if (delivery.start_date !== undefined && delivery.stop_date !== undefined) {
delivery_data = {'title': delivery.title,
'id': delivery.uid,
//'tree_id': delivery.uid,
'parent_id': delivery.causality_uid,
'start_date': delivery.start_date,
'stop_date': delivery.stop_date};
if (delivery.parent_uid !== sale_order_uid) {
delivery_data.parent_id = delivery.parent_uid;
}
data_list.push(delivery_data);
}
}
for (i = 0; i < causality_list.length; i = i + 1) {
causality_data = causality_dict[causality_list[i]];
data_list.push(causality_data);
}
gantt_data.data_list = data_list;
console.log("gantt_data", gantt_data);
return gadget.property_dict.gantt_widget.render(gantt_data);
});
});
}(window, rJS, RSVP));
\ No newline at end of file
/*global window, rJS, RSVP, console, gantt */
/*jslint nomen: true, indent: 2 */
(function (window, rJS, RSVP, gantt) {
"use strict";
/////////////////////////////////////////////////////////////////
// templates
/////////////////////////////////////////////////////////////////
var gadget_klass = rJS(window);
var transformDateStringToDhtmlxDate = function (date_string) {
var my_date;
my_date = new Date(date_string);
return "" + my_date.getDate() + "-" + (my_date.getMonth() + 1) + "-" + my_date.getFullYear();
};
var getGanttDataAndParameterFromConfiguration = function (configuration_dict) {
var gantt_configuration = {},
data_list = configuration_dict.data_list,
task,
data,
start_date,
stop_date,
owner_section_dict = {name: "owner", height: 22, map_to: "owner", type: "select", options: []},
i;
gantt_configuration.data = {};
gantt_configuration.data.data = [];