[IMP]: mrp: Manufacturing Order Usability Improvement: View improvement, Separated move_lines into 2, one for product to consume and the other for consumed products + wizard related changes
bzr revid: rpa@openerp.co.in-20100219105543-rc1jxi0lrimfk21i
This commit is contained in:
parent
819f2a33fe
commit
0abe371437
|
@ -60,6 +60,7 @@
|
|||
'security/ir.model.access.csv',
|
||||
'mrp_workflow.xml',
|
||||
'mrp_data.xml',
|
||||
'wizard/wizard_split_in_lots.xml',
|
||||
'mrp_view.xml',
|
||||
'mrp_wizard.xml',
|
||||
'mrp_report.xml',
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from mx import DateTime
|
||||
from osv import fields
|
||||
from osv import osv
|
||||
from tools.translate import _
|
||||
import ir
|
||||
|
||||
import netsvc
|
||||
import time
|
||||
from mx import DateTime
|
||||
from tools.translate import _
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Work Centers
|
||||
|
@ -334,6 +333,45 @@ def rounding(f, r):
|
|||
return f
|
||||
return round(f / r) * r
|
||||
|
||||
class many2many_domain(fields.many2many):
|
||||
def set(self, cr, obj, id, name, values, user=None, context=None):
|
||||
if not values:
|
||||
return
|
||||
return super(many2many_domain, self).set(cr, obj, id, name, values, user=user,
|
||||
context=context)
|
||||
|
||||
def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
|
||||
if not context:
|
||||
context = {}
|
||||
res = {}
|
||||
move_obj = obj.pool.get('stock.move')
|
||||
for prod in obj.browse(cr, user, ids, context=context):
|
||||
cr.execute("SELECT move_id from mrp_production_move_ids where\
|
||||
production_id=%s" % (prod.id))
|
||||
m_ids = map(lambda x: x[0], cr.fetchall())
|
||||
final = move_obj.search(cr, user, self._domain + [('id', 'in', tuple(m_ids))])
|
||||
res[prod.id] = final
|
||||
return res
|
||||
|
||||
class one2many_domain(fields.one2many):
|
||||
def set(self, cr, obj, id, field, values, user=None, context=None):
|
||||
if not values:
|
||||
return
|
||||
return super(one2many_domain, self).set(cr, obj, id, field, values,
|
||||
user=user, context=context)
|
||||
|
||||
def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
|
||||
if not context:
|
||||
context = {}
|
||||
res = {}
|
||||
move_obj = obj.pool.get('stock.move')
|
||||
for prod in obj.browse(cr, user, ids, context=context):
|
||||
cr.execute("SELECT id from stock_move where production_id=%s" % (prod.id))
|
||||
m_ids = map(lambda x: x[0], cr.fetchall())
|
||||
final = move_obj.search(cr, user, self._domain + [('id', 'in', tuple(m_ids))])
|
||||
res[prod.id] = final
|
||||
return res
|
||||
|
||||
class mrp_production(osv.osv):
|
||||
_name = 'mrp.production'
|
||||
_description = 'Production'
|
||||
|
@ -420,9 +458,10 @@ class mrp_production(osv.osv):
|
|||
'picking_id': fields.many2one('stock.picking', 'Picking list', readonly=True,
|
||||
help="This is the internal picking list that brings the finished product to the production plan"),
|
||||
'move_prod_id': fields.many2one('stock.move', 'Move product', readonly=True),
|
||||
'move_lines': fields.many2many('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Products Consummed'),
|
||||
|
||||
'move_created_ids': fields.one2many('stock.move', 'production_id', 'Moves Created'),
|
||||
'move_lines': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Products to Consumme', domain=[('state','not in', ('done', 'cancel'))]),
|
||||
'move_lines2': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Consummed Products', domain=[('state','in', ('done', 'cancel'))]),
|
||||
'move_created_ids': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','not in', ('done', 'cancel'))]),
|
||||
'move_created_ids2': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','in', ('done', 'cancel'))]),
|
||||
'product_lines': fields.one2many('mrp.production.product.line', 'production_id', 'Scheduled goods'),
|
||||
'workcenter_lines': fields.one2many('mrp.production.workcenter.line', 'production_id', 'Work Centers Utilisation'),
|
||||
'state': fields.selection([('draft','Draft'),('picking_except', 'Picking Exception'),('confirmed','Waiting Goods'),('ready','Ready to Produce'),('in_production','In Production'),('cancel','Cancelled'),('done','Done')],'State', readonly=True,
|
||||
|
@ -541,6 +580,10 @@ class mrp_production(osv.osv):
|
|||
self.pool.get('stock.move').write(cr, uid, [production.move_prod_id.id],
|
||||
{'location_id':production.location_dest_id.id})
|
||||
return True
|
||||
|
||||
def action_start(self, cr, uid, ids, context=None):
|
||||
self.write(cr, uid, ids, {'state':'in_production'})
|
||||
return True
|
||||
|
||||
#TODO Review materials in function in_prod and prod_end.
|
||||
def action_production_end(self, cr, uid, ids):
|
||||
|
@ -562,7 +605,7 @@ class mrp_production(osv.osv):
|
|||
self.pool.get('stock.move').check_assign(cr, uid, new_moves)
|
||||
self.pool.get('stock.move').action_done(cr, uid, new_moves)
|
||||
self._costs_generate(cr, uid, production)
|
||||
# self.pool.get('stock.move').action_done(cr, uid, move_ids)
|
||||
self.pool.get('stock.move').action_done(cr, uid, move_ids)
|
||||
self.write(cr, uid, ids, {'state': 'done'})
|
||||
return True
|
||||
|
||||
|
@ -606,7 +649,7 @@ class mrp_production(osv.osv):
|
|||
if not production.date_start:
|
||||
self.write(cr, uid, [production.id],
|
||||
{'date_start': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
self.pool.get('stock.move').action_done(cr, uid, move_ids)
|
||||
# self.pool.get('stock.move').action_done(cr, uid, move_ids)
|
||||
self.write(cr, uid, ids, {'state': 'in_production'})
|
||||
return True
|
||||
|
||||
|
@ -1299,6 +1342,40 @@ class StockMove(osv.osv):
|
|||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_validate(uid, 'mrp.procurement', m, 'button_wait_done', cr)
|
||||
return True
|
||||
|
||||
def _track_lines(self, cr, uid, ids, data, context=None):
|
||||
production_ids = []
|
||||
new_move = super(StockMove, self)._track_lines(cr, uid, ids, data, context=context)
|
||||
if new_move:
|
||||
production_obj = self.pool.get('mrp.production')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
move = move_obj.browse(cr, uid, ids)
|
||||
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
|
||||
for new in new_move:
|
||||
production_obj.write(cr, uid, production_ids, {'move_lines': [(4, new)]})
|
||||
move_obj.action_done(cr, uid, [new])
|
||||
return new_move
|
||||
|
||||
def split_moves(self, cr, uid, ids, datas, context=None):
|
||||
new_move = super(StockMove, self).split_moves(cr, uid, ids, datas, context=context)
|
||||
if new_move:
|
||||
production_obj = self.pool.get('mrp.production')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
move = move_obj.browse(cr, uid, ids)
|
||||
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
|
||||
production_obj.write(cr, uid, production_ids, {'move_lines': [(4, new_move)]})
|
||||
return {}
|
||||
|
||||
def scrap_moves(self, cr, uid, ids, datas, context=None):
|
||||
new_move = super(StockMove, self).scrap_moves(cr, uid, ids, datas, context=context)
|
||||
if new_move:
|
||||
production_obj = self.pool.get('mrp.production')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
move = move_obj.browse(cr, uid, ids)
|
||||
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
|
||||
production_obj.write(cr, uid, production_ids, {'move_lines': [(4, new_move)]})
|
||||
return {}
|
||||
|
||||
StockMove()
|
||||
|
||||
|
||||
|
|
|
@ -438,6 +438,7 @@
|
|||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<wizard
|
||||
string="Change Product Qty."
|
||||
model="mrp.production"
|
||||
|
@ -445,54 +446,102 @@
|
|||
id="mrp.wizard_change_production_qty"
|
||||
keyword="client_action_multi"
|
||||
multi="True"/>
|
||||
|
||||
|
||||
<record id="mrp_production_form_view" model="ir.ui.view">
|
||||
<field name="name">mrp.production.form</field>
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Manufacturing Orders">
|
||||
<group colspan="4" col="7">
|
||||
<field name="name" select="1"/>
|
||||
<group colspan="4" col="6">
|
||||
<field name="name" select="1" string="Reference"/>
|
||||
<field name="date_planned" select="1"/>
|
||||
<field name="origin" select="1"/>
|
||||
<newline/>
|
||||
<field name="product_id" on_change="product_id_change(product_id)" select="1"/>
|
||||
<field name="product_id" on_change="product_id_change(product_id)" select="1"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom"/>
|
||||
<button type="action" name="%(mrp.wizard_change_production_qty)d" string="Change Qty" states="ready,confirmed,in_production" icon="gtk-ok"/>
|
||||
<field name="product_uos_qty" groups="product.group_uos"/>
|
||||
<field name="product_uos" groups="product.group_uos"/>
|
||||
<field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
|
||||
<group colspan="2" col="3">
|
||||
<field name="product_uom"/>
|
||||
<!-- TODO Fix change qty accroding to move_lines and move_lines2 -->
|
||||
<!-- <button type="action" name="%(mrp.wizard_change_production_qty)d" string="Change Qty" states="ready,confirmed,in_production" icon="gtk-ok"/>-->
|
||||
</group>
|
||||
<label string="" colspan="2"/>
|
||||
<field name="product_uos_qty" groups="product.group_uos"/>
|
||||
<group colspan="2" col="3" groups="product.group_uos">
|
||||
<field name="product_uos"/>
|
||||
<label string=""/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<notebook colspan="4">
|
||||
<page string="Consumed Products">
|
||||
<field name="location_src_id" select="2" domain="[('usage','=','internal')]" on_change="location_id_change(location_src_id,location_dest_id)"/>
|
||||
<field name="location_dest_id" domain="[('usage','=','internal')]"/>
|
||||
<field name="bom_id" select="2" domain="[('product_id','=',product_id),('bom_id','=',False)]" on_change="bom_id_change(bom_id)"/>
|
||||
<field name="routing_id" groups="base.group_extended" select="1"/>
|
||||
<newline/>
|
||||
<field colspan="4" name="move_lines" nolabel="1" widget="one2many_list">
|
||||
<tree string="Moves">
|
||||
<field name="product_id" select="1"/>
|
||||
<field name="product_qty" select="1"/>
|
||||
<field name="product_uom" select="1" string="UOM"/>
|
||||
<field name="prodlot_id" select="1"/>
|
||||
<field name="product_packaging" domain="[('product_id','=',product_id)]"/>
|
||||
<field name="picking_id"/>
|
||||
<field name="location_id" select="1"/>
|
||||
<field name="location_dest_id" select="1"/>
|
||||
<field name="date" select="1"/>
|
||||
<field name="date_planned" select="1" string="Date"/>
|
||||
<field name="location_src_id" select="2" domain="[('usage','=','internal')]" on_change="location_id_change(location_src_id,location_dest_id)"/>
|
||||
<field name="location_dest_id" domain="[('usage','=','internal')]"/>
|
||||
<separator string="" colspan="4"/>
|
||||
|
||||
</tree>
|
||||
<field colspan="2" name="move_lines" nolabel="1" widget="one2many_list"
|
||||
mode="tree,form" height="275" domain="[('state','<>', ('done', 'cancel'))]">
|
||||
<tree string="Products to Consume">
|
||||
<field name="product_id" />
|
||||
<field name="product_qty" />
|
||||
<field name="product_uom" />
|
||||
<field name="state" invisible="1" />
|
||||
<button
|
||||
name="%(stock.move_consume)d"
|
||||
string=">" type="action"
|
||||
icon="gtk-go-forward" context="{'consume': True}"
|
||||
states="draft,waiting,confirmed,assigned"/>
|
||||
<button name="%(stock.move_scrap)d"
|
||||
string="D" type="action"
|
||||
icon="gtk-justify-fill" context="{'scrap': True}"
|
||||
states="draft,waiting,confirmed,assigned" />
|
||||
</tree>
|
||||
<form string="Products to Consume">
|
||||
<field name="product_id" />
|
||||
<field name="product_qty" />
|
||||
<field name="product_uom" />
|
||||
</form>
|
||||
</field>
|
||||
|
||||
<field colspan="2" name="move_lines2" nolabel="1" domain="[('state','in', ('done', 'cancel'))]"
|
||||
widget="one2many_list" mode="tree,form" height="275">
|
||||
<tree string="Consumed Products" editable="bottom">
|
||||
<field name="product_id" readonly="1"/>
|
||||
<field name="product_qty" readonly="1"/>
|
||||
<field name="product_uom" readonly="1" />
|
||||
<field name="state" invisible="1" />
|
||||
<field name="location_id" readonly="1"/>
|
||||
<field name="prodlot_id" />
|
||||
<!-- <button-->
|
||||
<!-- name="%(stock.track_line)d"-->
|
||||
<!-- string="Split in production lots"-->
|
||||
<!-- type="action" icon="gtk-justify-fill"-->
|
||||
<!-- states="done,cancel" />-->
|
||||
<button
|
||||
name="%(mrp.split_in_lots)d"
|
||||
string="Split in production lots"
|
||||
type="action" icon="gtk-justify-fill"
|
||||
states="done,cancel" />
|
||||
<button
|
||||
name="%(stock.move_scrap)d"
|
||||
string="D" type="action"
|
||||
icon="gtk-convert"
|
||||
states="done,cancel" />
|
||||
</tree>
|
||||
<form string="Consumed Products">
|
||||
<field name="product_id" />
|
||||
<field name="product_qty" />
|
||||
<field name="product_uom" />
|
||||
</form>
|
||||
</field>
|
||||
|
||||
<group col="9" colspan="4">
|
||||
<field name="state" select="2"/>
|
||||
<button name="action_compute" states="draft" string="Compute Data" type="object" icon="gtk-execute"/>
|
||||
<button name="button_confirm" states="draft" string="Confirm Production" icon="gtk-apply"/>
|
||||
<button name="button_produce" states="ready" string="Start Production" icon="gtk-media-play"/>
|
||||
<!-- <button name="action_start" states="ready" string="Mark as Start" icon="gtk-media-play" type="object"/>-->
|
||||
<button name="button_produce" states="ready" string="Produce" icon="gtk-execute"/>
|
||||
<button name="button_produce_done" states="in_production" string="Production done" icon="gtk-ok"/>
|
||||
<button name="force_production" states="confirmed,picking_except" string="Force Reservation" type="object" icon="gtk-jump-to"/>
|
||||
<button name="button_cancel" states="draft,ready,confirmed,in_production,picking_except" string="Cancel" icon="gtk-cancel"/>
|
||||
|
@ -503,7 +552,51 @@
|
|||
<field colspan="4" name="product_lines" nolabel="1" widget="one2many_list"/>
|
||||
</page>
|
||||
<page string="Finished Products">
|
||||
<field colspan="4" name="move_created_ids" nolabel="1"/>
|
||||
<field colspan="2" name="move_created_ids" nolabel="1" widget="one2many_list"
|
||||
mode="tree,form" height="275" domain="[('state','<>', ('done', 'cancel'))]">
|
||||
<tree string="Products to Consume">
|
||||
<field name="product_id" />
|
||||
<field name="product_qty" />
|
||||
<field name="product_uom" />
|
||||
<field name="state" invisible="1" />
|
||||
<button
|
||||
name="%(stock.move_consume)d"
|
||||
string=">" type="action"
|
||||
icon="gtk-go-forward"
|
||||
states="draft,waiting,confirmed,assigned"/>
|
||||
<button name="%(stock.move_scrap)d"
|
||||
string="D" type="action"
|
||||
icon="gtk-justify-fill" context="{'scrap': True}"
|
||||
states="draft,waiting,confirmed,assigned" />
|
||||
</tree>
|
||||
<form string="Products to Consume">
|
||||
<field name="product_id" />
|
||||
<field name="product_qty" />
|
||||
<field name="product_uom" />
|
||||
</form>
|
||||
</field>
|
||||
|
||||
<field colspan="2" name="move_created_ids2" nolabel="1" domain="[('state','in', ('done', 'cancel'))]"
|
||||
widget="one2many_list" mode="tree,form" height="275">
|
||||
<tree string="Consumed Products" editable="bottom">
|
||||
<field name="product_id" readonly="1"/>
|
||||
<field name="product_qty" readonly="1"/>
|
||||
<field name="product_uom" readonly="1" />
|
||||
<field name="state" invisible="1" />
|
||||
<field name="location_id" readonly="1"/>
|
||||
<field name="prodlot_id" />
|
||||
<button name="%(stock.track_line)d"
|
||||
string="Split in production lots" type="action" icon="gtk-justify-fill" states="done,cancel"/>
|
||||
<button name="%(stock.move_scrap)d"
|
||||
string="D" type="action" icon="gtk-go-forward"
|
||||
states="done,cancel" />
|
||||
</tree>
|
||||
<form string="Consumed Products">
|
||||
<field name="product_id" />
|
||||
<field name="product_qty" />
|
||||
<field name="product_uom" />
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Work Orders">
|
||||
<field colspan="4" name="workcenter_lines" nolabel="1">
|
||||
|
@ -525,6 +618,7 @@
|
|||
|
||||
</page>
|
||||
<page string="Extra Information">
|
||||
<field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
|
||||
<field name="priority" groups="base.group_extended"/>
|
||||
<newline/>
|
||||
<field name="date_start" select="2"/>
|
||||
|
|
|
@ -31,12 +31,5 @@
|
|||
keyword="client_action_multi"
|
||||
id="product_procurement_wizard"/>
|
||||
|
||||
<wizard
|
||||
id="stock.track_line"
|
||||
model="stock.move"
|
||||
multi="True"
|
||||
name="mrp.stock.move.track"
|
||||
string="Track line"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -27,7 +27,7 @@ import wizard_workcenter_load
|
|||
import wizard_track_prod
|
||||
import wizard_change_production_qty
|
||||
import make_procurement
|
||||
import wizard_track_line
|
||||
import wizard_split_in_lots
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
import re
|
||||
import time
|
||||
import tools
|
||||
|
||||
class spilt_in_lot(osv.osv_memory):
|
||||
_name = "spilt.in.lot"
|
||||
_description = "Split in lots"
|
||||
|
||||
_columns = {
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
|
||||
'line_ids': fields.one2many('track.lines', 'lot_id', 'Lots Number')
|
||||
}
|
||||
|
||||
def _get_product_id(self, cr, uid, context):
|
||||
move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
|
||||
return move.product_id.id
|
||||
|
||||
_defaults = {
|
||||
'product_id': _get_product_id,
|
||||
}
|
||||
|
||||
spilt_in_lot()
|
||||
|
||||
class track_lines(osv.osv_memory):
|
||||
_name = "track.lines"
|
||||
_description = "Track lines"
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Tracking serial', size=64),
|
||||
'lot_id': fields.many2one('spilt.in.lot', 'Lot')
|
||||
}
|
||||
|
||||
track_lines()
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_split_in_lots" model="ir.ui.view">
|
||||
<field name="name">Split in lots</field>
|
||||
<field name="model">spilt.in.lot</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Split in lots">
|
||||
<field name="product_id" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="line_ids" colspan="4" nolabel="1">
|
||||
<tree string="Lots Number" editable="top">
|
||||
<field name="name" string="Lots"/>
|
||||
</tree>
|
||||
<form string="Lots Number">
|
||||
<field name="name" string="Lots"/>
|
||||
</form>
|
||||
</field>
|
||||
<separator string="" colspan="4" />
|
||||
<label string="" colspan="2" />
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button name="track_lines" string="Ok"
|
||||
type="object" icon="gtk-ok" />
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="split_in_lots" model="ir.actions.act_window">
|
||||
<field name="name">Split in lots</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">spilt.in.lot</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,138 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import wizard
|
||||
import netsvc
|
||||
import pooler
|
||||
|
||||
import time
|
||||
from osv import osv
|
||||
from tools.translate import _
|
||||
|
||||
track_form = '''<?xml version="1.0"?>
|
||||
<form string="Tracking a move">
|
||||
<field name="tracking_prefix"/>
|
||||
<newline/>
|
||||
<field name="quantity"/>
|
||||
</form>
|
||||
'''
|
||||
fields = {
|
||||
'tracking_prefix': {
|
||||
'string': 'Tracking prefix',
|
||||
'type': 'char',
|
||||
'size': 64,
|
||||
},
|
||||
'quantity': {
|
||||
'string': 'Quantity per lot',
|
||||
'type': 'float',
|
||||
'default': 1,
|
||||
}
|
||||
}
|
||||
|
||||
def _check_picking(self, cr, uid, data, context):
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
move_obj = pool.get('stock.move').browse(cr, uid, data['id'])
|
||||
if not move_obj.picking_id:
|
||||
raise wizard.except_wizard(_('Caution!'), _('Before splitting the production lots,make sure this move has a Picking attached !\nYou must save the move before performing this operation.'))
|
||||
return data['form']
|
||||
|
||||
def _track_lines(self, cr, uid, data, context):
|
||||
move_id = data['id']
|
||||
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
prodlot_obj = pool.get('stock.production.lot')
|
||||
move_obj = pool.get('stock.move')
|
||||
production_obj = pool.get('mrp.production')
|
||||
ir_sequence_obj = pool.get('ir.sequence')
|
||||
|
||||
sequence = ir_sequence_obj.get(cr, uid, 'stock.lot.serial')
|
||||
if not sequence:
|
||||
raise wizard.except_wizard(_('Error!'), _('No production sequence defined'))
|
||||
if data['form']['tracking_prefix']:
|
||||
sequence=data['form']['tracking_prefix']+'/'+(sequence or '')
|
||||
|
||||
move = move_obj.browse(cr, uid, [move_id])[0]
|
||||
quantity=data['form']['quantity']
|
||||
if quantity <= 0 or move.product_qty == 0:
|
||||
return {}
|
||||
uos_qty=quantity/move.product_qty*move.product_uos_qty
|
||||
|
||||
quantity_rest = move.product_qty%quantity
|
||||
uos_qty_rest = quantity_rest/move.product_qty*move.product_uos_qty
|
||||
|
||||
update_val = {
|
||||
'product_qty': quantity,
|
||||
'product_uos_qty': uos_qty,
|
||||
}
|
||||
new_move = []
|
||||
production_ids = []
|
||||
for idx in range(int(move.product_qty//quantity)):
|
||||
if idx:
|
||||
current_move = move_obj.copy(cr, uid, move.id, {'state': move.state, 'production_id': move.production_id.id})
|
||||
new_move.append(current_move)
|
||||
else:
|
||||
current_move = move.id
|
||||
new_prodlot = prodlot_obj.create(cr, uid, {'name': sequence, 'ref': '%d'%idx}, {'product_id': move.product_id.id})
|
||||
update_val['prodlot_id'] = new_prodlot
|
||||
move_obj.write(cr, uid, [current_move], update_val)
|
||||
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
|
||||
|
||||
if quantity_rest > 0:
|
||||
idx = int(move.product_qty//quantity)
|
||||
update_val['product_qty']=quantity_rest
|
||||
update_val['product_uos_qty']=uos_qty_rest
|
||||
if idx:
|
||||
current_move = move_obj.copy(cr, uid, move.id, {'state': move.state, 'production_id': move.production_id.id})
|
||||
current_move = move_obj.copy(cr, uid, move.id, {'state': move.state})
|
||||
new_move.append(current_move)
|
||||
else:
|
||||
current_move = move.id
|
||||
new_prodlot = prodlot_obj.create(cr, uid, {'name': sequence, 'ref': '%d'%idx}, {'product_id': move.product_id.id})
|
||||
update_val['prodlot_id'] = new_prodlot
|
||||
move_obj.write(cr, uid, [current_move], update_val)
|
||||
|
||||
products = production_obj.read(cr, uid, production_ids, ['move_lines'])
|
||||
for p in products:
|
||||
for new in new_move:
|
||||
if new not in p['move_lines']:
|
||||
p['move_lines'].append(new)
|
||||
production_obj.write(cr, uid, [p['id']], {'move_lines': [(6, 0, p['move_lines'])]})
|
||||
|
||||
return {}
|
||||
|
||||
class wizard_track_move(wizard.interface):
|
||||
states = {
|
||||
'init': {
|
||||
'actions': [_check_picking],
|
||||
'result': {'type': 'form', 'arch': track_form, 'fields': fields, 'state': [('end', 'Cancel', 'gtk-cancel'), ('track', 'Ok', 'gtk-ok')]},
|
||||
},
|
||||
'track': {
|
||||
'actions': [_track_lines],
|
||||
'result': {'type':'state', 'state':'end'}
|
||||
}
|
||||
}
|
||||
|
||||
wizard_track_move('mrp.stock.move.track')
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
Loading…
Reference in New Issue