[IMP] Stock Picking Type

bzr revid: fp@openerp.com-20130728124201-jcazoieogux7ehu6
This commit is contained in:
Fabien Pinckaers 2013-07-28 14:42:01 +02:00
parent 90aa53ad15
commit a08801f603
7 changed files with 3257 additions and 18 deletions

View File

@ -101,6 +101,8 @@ Dashboard / Reports for Warehouse Management will include:
'static/src/css/stock.css', 'static/src/css/stock.css',
], ],
'js': [ 'js': [
'static/lib/sparkline/jquery.sparkline.js',
'static/src/js/stock_picking_type.js',
'static/src/js/widgets.js', 'static/src/js/widgets.js',
'static/src/js/main.js', 'static/src/js/main.js',
], ],

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,24 @@
openerp.stock = function(openerp) {
openerp.stock.SparklineBarWidget = openerp.web_kanban.AbstractField.extend({
className: "oe_sparkline_bar",
start: function() {
var self = this;
var title = this.$node.html();
setTimeout(function () {
var value = _.pluck(self.field.value, 'value');
var tooltips = _.pluck(self.field.value, 'tooltip');
self.$el.sparkline(value, {
type: 'bar',
barWidth: 5,
tooltipFormat: '{{offset:offset}} {{value}}',
tooltipValueLookups: {
'offset': tooltips
},
});
self.$el.tipsy({'delayIn': 0, 'html': true, 'title': function(){return title}, 'gravity': 'n'});
}, 0);
},
});
openerp.web_kanban.fields_registry.add("stock_sparkline_bar", "openerp.stock.SparklineBarWidget");
};

View File

@ -19,8 +19,9 @@
# #
############################################################################## ##############################################################################
from datetime import datetime from datetime import date, datetime
from dateutil.relativedelta import relativedelta from dateutil import relativedelta
import time import time
from operator import itemgetter from operator import itemgetter
from itertools import groupby from itertools import groupby
@ -1970,10 +1971,7 @@ class stock_package(osv.osv):
""" """
_name = "stock.quant.package" _name = "stock.quant.package"
_description = "Physical Packages" _description = "Physical Packages"
_parent_name = "parent_id" _order = 'name'
_parent_store = True
_parent_order = 'name'
_order = 'parent_left'
def name_get(self, cr, uid, ids, context=None): def name_get(self, cr, uid, ids, context=None):
res = self._complete_name(cr, uid, ids, 'complete_name', None, context=context) res = self._complete_name(cr, uid, ids, 'complete_name', None, context=context)
@ -2271,22 +2269,120 @@ class stock_picking_code(osv.osv):
_name = "stock.picking.code" _name = "stock.picking.code"
_description = "Will group picking types for kanban view" _description = "Will group picking types for kanban view"
_columns = { _columns = {
'name': fields.char("Name", size=30), 'name': fields.char("Picking Type", translate=True),
} }
class stock_picking_type(osv.osv): class stock_picking_type(osv.osv):
_name = "stock.picking.type" _name = "stock.picking.type"
_description = "The picking type determines the picking view" _description = "The picking type determines the picking view"
def __get_bar_values(self, cr, uid, obj, domain, read_fields, value_field, groupby_field, context=None):
""" Generic method to generate data for bar chart values using SparklineBarWidget.
This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field).
:param obj: the target model (i.e. crm_lead)
:param domain: the domain applied to the read_group
:param list read_fields: the list of fields to read in the read_group
:param str value_field: the field used to compute the value of the bar slice
:param str groupby_field: the fields used to group
:return list section_result: a list of dicts: [
{ 'value': (int) bar_column_value,
'tootip': (str) bar_column_tooltip,
}
]
"""
month_begin = date.today().replace(day=1)
section_result = [{
'value': 0,
'tooltip': (month_begin + relativedelta.relativedelta(months=-i)).strftime('%B'),
} for i in range(10, -1, -1)]
group_obj = obj.read_group(cr, uid, domain, read_fields, groupby_field, context=context)
for group in group_obj:
group_begin_date = datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATE_FORMAT)
month_delta = relativedelta.relativedelta(month_begin, group_begin_date)
section_result[10 - (month_delta.months + 1)] = {'value': group.get(value_field, 0), 'tooltip': group_begin_date.strftime('%B')}
return section_result
def _get_picking_data(self, cr, uid, ids, field_name, arg, context=None):
obj = self.pool.get('stock.picking')
res = dict.fromkeys(ids, False)
month_begin = date.today().replace(day=1)
groupby_begin = (month_begin + relativedelta.relativedelta(months=-4)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
groupby_end = (month_begin + relativedelta.relativedelta(months=3)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
for id in ids:
created_domain = [
('picking_type_id', '=', id),
('state', 'not in', ['draft', 'cancel']),
('date', '>=', groupby_begin),
('date', '<', groupby_end),
]
res[id] = self.__get_bar_values(cr, uid, obj, created_domain, ['date'], '__count', 'date', context=context)
print '_get_picking_data', res
return res
def _get_picking_count(self, cr, uid, ids, field_names, arg, context=None):
obj = self.pool.get('stock.picking')
domains = {
'count_picking': [],
'count_picking_late': [('min_date','<', time.strftime('%Y-%m-%d %H:%M:%S'))],
'count_picking_backorders': [('backorder_id','<>', False)],
}
result = {}
for field in field_names:
data = obj.read_group(cr, uid, domains[field] +
[('state', 'not in',('done','cancel','draft')), ('picking_type_id', 'in', ids)],
['picking_type_id'], ['picking_type_id'], context=context)
count = dict(map(lambda x: (x['picking_type_id'], x['__count']), data))
for tid in ids:
result.setdefault(tid, {})[field] = count.get(tid, 0)
print '_get_picking_count', result
return result
def _get_picking_history(self, cr, uid, ids, field_names, arg, context=None):
obj = self.pool.get('stock.picking')
result = {}
for id in ids:
result[id] = {
'latest_picking_late': [],
'latest_picking_backorders': []
}
for type_id in ids:
pick_ids = obj.search(cr, uid, [('state', '=','done'), ('picking_type_id','=',type_id)], limit=12, order="date desc", context=context)
for pick in obj.browse(cr, uid, pick_ids, context=context):
result[type_id]['latest_picking_late'] = cmp(pick.date[:10], time.strftime('%Y-%m-%d'))
result[type_id]['latest_picking_backorders'] = bool(pick.backorder_id)
print '_get_picking_history', result
return result
_columns = { _columns = {
'name': fields.char('name', size=30), 'name': fields.char('name', translate=True),
'pack': fields.boolean('Pack', 'This picking type needs packing interface'), 'pack': fields.boolean('Pack', 'This picking type needs packing interface'),
'color': fields.integer('Color Index'),
'delivery': fields.boolean('Print delivery'), 'delivery': fields.boolean('Print delivery'),
'sequence_id': fields.many2one('ir.sequence', 'Sequence', required = True), 'sequence_id': fields.many2one('ir.sequence', 'Sequence', required = True),
'default_location_src_id': fields.many2one('stock.location', 'Default Source Location'), 'default_location_src_id': fields.many2one('stock.location', 'Default Source Location'),
'default_location_dest_id': fields.many2one('stock.location', 'Default Destination Location'), 'default_location_dest_id': fields.many2one('stock.location', 'Default Destination Location'),
'code_id': fields.many2one('stock.picking.code', 'Picking type code', required = True), 'code_id': fields.many2one('stock.picking.code', 'Picking type code', required = True),
}
# Statistics for the kanban view
'weekly_picking': fields.function(_get_picking_data,
type='string',
string='Scheduled pickings per week'),
'count_picking': fields.function(_get_picking_count,
type='integer', multi='_get_picking_count'),
'count_picking_late': fields.function(_get_picking_count,
type='integer', multi='_get_picking_count'),
'count_picking_backorders': fields.function(_get_picking_count,
type='integer', multi='_get_picking_count'),
'latest_picking_late': fields.function(_get_picking_history,
type='string', multi='_get_picking_history'),
'latest_picking_backorders': fields.function(_get_picking_history,
type='string', multi='_get_picking_history'),
}

View File

@ -115,11 +115,11 @@
</record> </record>
<record id="picking_code_internal" model="stock.picking.code"> <record id="picking_code_internal" model="stock.picking.code">
<field name="name">Internals</field> <field name="name">Internal</field>
</record> </record>
<record id="picking_type_in" model="stock.picking.type"> <record id="picking_type_in" model="stock.picking.type">
<field name="name">in</field> <field name="name">Receptions</field>
<field name="sequence_id" ref="seq_picking_type_in"/> <field name="sequence_id" ref="seq_picking_type_in"/>
<field name="default_location_src_id" ref="stock_location_suppliers"/> <field name="default_location_src_id" ref="stock_location_suppliers"/>
<field name="default_location_dest_id" ref="stock_location_stock"/> <field name="default_location_dest_id" ref="stock_location_stock"/>
@ -127,7 +127,7 @@
</record> </record>
<record id="picking_type_out" model="stock.picking.type"> <record id="picking_type_out" model="stock.picking.type">
<field name="name">out</field> <field name="name">Delivery Orders</field>
<field name="sequence_id" ref="seq_picking_type_out"/> <field name="sequence_id" ref="seq_picking_type_out"/>
<field name="default_location_src_id" ref="stock_location_stock"/> <field name="default_location_src_id" ref="stock_location_stock"/>
<field name="default_location_dest_id" ref="stock_location_customers"/> <field name="default_location_dest_id" ref="stock_location_customers"/>
@ -135,7 +135,7 @@
</record> </record>
<record id="picking_type_internal" model="stock.picking.type"> <record id="picking_type_internal" model="stock.picking.type">
<field name="name">internal</field> <field name="name">Internal Transfers</field>
<field name="sequence_id" ref="seq_picking_type_internal"/> <field name="sequence_id" ref="seq_picking_type_internal"/>
<field name="code_id" ref="picking_code_internal"/> <field name="code_id" ref="picking_code_internal"/>
</record> </record>

View File

@ -1172,11 +1172,83 @@
</form> </form>
</field> </field>
</record> </record>
<record id="stock_picking_type_kanban" model="ir.ui.view">
<field name="name">stock.picking.type.kanban</field>
<field name="model">stock.picking.type</field>
<field name="arch" type="xml">
<kanban version="7.0" class="oe_background_grey">
<field name="name"/>
<field name="color"/>
<field name="count_picking"/>
<field name="count_picking_late"/>
<field name="count_picking_backorders"/>
<field name="latest_picking_late"/>
<field name="latest_picking_backorders"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_stock_picking_type">
<div class="oe_dropdown_toggle oe_dropdown_kanban" groups="stock.group_stock_manager">
<span class="oe_e">í</span>
<ul class="oe_dropdown_menu">
<li t-if="widget.view.is_action_enabled('edit')"><a type="edit">Settings</a></li>
<li t-if="widget.view.is_action_enabled('delete')"><a type="delete">Delete</a></li>
<li t-if="widget.view.is_action_enabled('edit')"><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
<div class="oe_kanban_content">
<h4 class="oe_center"><field name="name"/></h4>
<div class="oe_right">
<a name="%(action_stock_stock_ui)d" type="action">
<img src="/stock/static/src/img/scan.png" alt="Click to launch the barcode interface"/>
</a>
</div>
<div class="oe_items_list">
<div>
<a name="%(action_picking_tree)d" type="action">
<field name="count_picking"/>
<t t-esc="record.name.raw_value"/>
</a>
<a name="%(action_picking_tree)d" type="action" class="oe_sparkline_bar_link">
<field name="weekly_picking" widget="stock_sparkline_bar"/>
</a>
</div>
<div>
<a name="%(action_picking_tree)d" type="action">
<field name="count_picking_late"/>
Late <t t-esc="record.name.raw_value"/>
</a>
<a name="%(action_picking_tree)d" type="action" class="oe_sparkline_bar_link">
<field name="latest_picking_late" widget="sparkline_bar"/>
</a>
</div>
<div>
<a name="%(action_picking_tree)d" type="action">
<field name="count_picking_backorders"/>
Partial <t t-esc="record.name.raw_value"/>
</a>
<a name="%(action_picking_tree)d" type="action" class="oe_sparkline_bar_link">
<field name="latest_picking_backorders" widget="sparkline_bar"/>
</a>
</div>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="action_picking_type_form" model="ir.actions.act_window"> <record id="action_picking_type_form" model="ir.actions.act_window">
<field name="name">Picking Types</field> <field name="name">Picking Types</field>
<field name="res_model">stock.picking.type</field> <field name="res_model">stock.picking.type</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="view_type">form</field> <field name="view_type">form</field>
<field name="view_mode">kanban,list,form</field>
<field name="help" type="html"> <field name="help" type="html">
<p class="oe_view_nocontent_create"> <p class="oe_view_nocontent_create">
Click to create a new picking type. Click to create a new picking type.
@ -1185,15 +1257,13 @@
operation a specific type which will alter its views accordingly. operation a specific type which will alter its views accordingly.
On the picking type you could e.g. specify if packing is needed by default, On the picking type you could e.g. specify if packing is needed by default,
if it should show the customer. if it should show the customer.
<br/>
Examples are in, out, internal, packing, quality control, ...
</p> </p>
</field> </field>
</record> </record>
<menuitem <menuitem
action="action_picking_type_form" action="action_picking_type_form"
id="menu_action_picking_type_form" id="menu_action_picking_type_form"
parent="menu_warehouse_config" sequence="1"/> parent="menu_stock_warehouse_mgmt" sequence="1"/>
<!-- Order Point --> <!-- Order Point -->
<record id="view_warehouse_orderpoint_tree" model="ir.ui.view"> <record id="view_warehouse_orderpoint_tree" model="ir.ui.view">