[FIX] improvements in stock management

bzr revid: fp@tinyerp.com-20100613223525-qmtypsjrhio58rcy
This commit is contained in:
Fabien Pinckaers 2010-06-14 00:35:25 +02:00
parent cd511aa7a0
commit f5b4319b04
7 changed files with 233 additions and 258 deletions

View File

@ -1296,6 +1296,7 @@ class stock_move(osv.osv):
return (res and res[0]) or False
_name = "stock.move"
_description = "Stock Move"
_order = 'date_planned desc'
_log_create = False
def name_get(self, cr, uid, ids, context={}):
@ -1368,7 +1369,7 @@ class stock_move(osv.osv):
digits_compute= dp.get_precision('Account')),
'company_id': fields.many2one('res.company', 'Company', required=True,select=1),
'partner_id': fields.related('picking_id','address_id','partner_id',type='many2one', relation="res.partner", string="Partner"),
'backorder_id': fields.related('picking_id','backorder_id',type='many2one', relation="stock.picking", string="Back Orders"),
'backorder_id': fields.related('picking_id','backorder_id',type='many2one', relation="stock.picking", string="Back Order"),
'origin': fields.related('picking_id','origin',type='char', size=64, relation="stock.picking", string="Origin"),
'scraped': fields.related('location_dest_id','scrap_location',type='boolean',relation='stock.location',string='Scraped'),
}

View File

@ -713,7 +713,7 @@
<filter icon="terp-check" name="available" string="Available" domain="[('state','=','assigned')]" help="Available Pickings"/>
<filter icon="terp-camera_test" string="Confirmed" domain="[('state','=','confirmed')]" help="Confirmed Pickings"/>
<separator orientation="vertical"/>
<filter icon="terp-accessories-archiver-minus" string="Back Order" domain="[('backorder_id', '!=', False)]" help="Has Back Order" />
<filter icon="terp-accessories-archiver-minus" string="Back Order" domain="[('backorder_id', '&lt;&gt;', False)]" help="Has Back Order" />
<separator orientation="vertical"/>
<field name="location_id"/>
<field name="location_dest_id"/>
@ -915,10 +915,10 @@
<tree colors="blue:state in ('draft');grey:state in ('cancel');red:state not in ('cancel', 'done') and date &lt; current_date" string="Picking list">
<field name="name"/>
<field name="address_id"/>
<field name="backorder_id" groups="base.group_extended"/>
<field name="origin"/>
<field name="date"/>
<field name="min_date"/>
<field name="backorder_id" groups="base.group_extended"/>
<field name="invoice_state"/>
<field name="state"/>
<button name="%(action_partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-go-forward" help="Validate Picking"/>
@ -1035,14 +1035,15 @@
<field name="arch" type="xml">
<search string="Picking list">
<group col="8" colspan="4">
<filter icon="terp-check" string="Available" domain="[('state','=','assigned')]" help="Assigned Outgoing Orders"/>
<filter icon="terp-camera_test" string="Confirmed" domain="[('state','=','confirmed')]" help="Confirmed Outgoing Orders"/>
<filter icon="terp-check" name="available" string="Available" domain="[('state','=','assigned')]" help="Assigned Outgoing Orders"/>
<filter icon="terp-camera_test" name="confirmed" string="Confirmed" domain="[('state','=','confirmed')]" help="Confirmed Outgoing Orders"/>
<separator orientation="vertical"/>
<filter icon="terp-accessories-archiver-minus" string="Back Orders" domain="[('backorder_id', '&lt;&gt;', False)]" help="Has Back Order" />
<separator orientation="vertical"/>
<field name="name"/>
<field name="address_id" />
<!-- <field name="company_id" widget="selection"/>-->
<field name="origin"/>
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
</group>
<newline/>
<group expand="0" string="Group By..." colspan="4" col="8">
@ -1308,7 +1309,15 @@
<field name="product_id"/>
<field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/>
<field name="product_uom" string="Unit Of Measure"/>
<button name="%(stock.move_scrap)d"
string="Scrap Products" type="action"
icon="gtk-convert" context="{'scrap': True}"
states="draft,waiting,confirmed,assigned" />
<field name="prodlot_id" groups="base.group_extended"/>
<button name="%(track_line)d" string="Split" type="action"
icon="gtk-justify-fill" attrs="{'invisible': [('prodlot_id','&lt;&gt;',False)]}"
states="assigned,confirmed"
groups="base.group_extended"/>
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date_planned"/>
@ -1335,7 +1344,8 @@
<field name="product_id" on_change="onchange_product_id(product_id,location_id,location_dest_id, parent.address_id)"/>
<field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/>
<field name="product_uom" string="Unit Of Measure" widget="selection"/>
<field name="product_uos" groups="base.group_extended" />
<field name="product_uos_qty" groups="product.product_uos" />
<field name="product_uos" groups="product.product_uos" />
</group>
<group colspan="2" col="2">
@ -1440,13 +1450,20 @@
<field name="product_id"/>
<field name="product_qty" />
<field name="product_uom" string="UoM"/>
<button name="%(stock.move_scrap)d"
string="Scrap Products" type="action"
icon="gtk-convert" context="{'scrap': True}"
states="draft,waiting,confirmed,assigned" />
<field name="prodlot_id" groups="base.group_extended"/>
<button name="%(track_line)d" string="Split" type="action"
icon="gtk-justify-fill" attrs="{'invisible': [('prodlot_id','&lt;&gt;',False)]}"
states="assigned,confirmed,done"
groups="base.group_extended"/>
<field name="date_planned"/>
<field name="backorder_id" groups="base.group_extended"/>
<field name="state"/>
<button name="%(action_partial_move)d" string="Partial" type="action" states="assigned" icon="gtk-justify-fill"/>
<button name="action_done" states="assigned" string="Done" type="object" icon="gtk-jump-to"/>
<button name="action_cancel" states="assigned,confirmed" string="Cancel" type="object" icon="gtk-cancel"/>
</tree>
</field>
</record>
@ -1466,7 +1483,8 @@
<field colspan="4" name="product_id" on_change="onchange_product_id(product_id, location_id, location_dest_id, parent.address_id)"/>
<field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/>
<field name="product_uom" widget="selection"/>
<field name="product_uos" widget="selection" groups="base.group_extended"/>
<field name="product_uos_qty" groups="product.product_uos"/>
<field name="product_uos" widget="selection" groups="product.product_uos"/>
<field colspan="4" name="name"/>
<field name="date"/>
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
@ -1512,13 +1530,13 @@
<group col="8" colspan="4">
<filter icon="terp-go-today" string="Today" domain="[('date_planned','&lt;=',time.strftime('%%Y-%%m-%%d 23:59:59')),('date_planned','&gt;=',time.strftime('%%Y-%%m-%%d 00:00:00'))]" help="Orders planned for today"/>
<separator orientation="vertical"/>
<filter icon="terp-gtk-go-back-rtl" name="receive" string="To Receive" domain="[('state','in',('confirmed','assigned'))]" help="Stock to be received"/>
<filter icon="terp-check" name="received" string="Received" domain="[('state','=','done'))]"/>
<filter icon="terp-gtk-go-back-rtl" name="receive" string="To Do" domain="[('state','in',('confirmed','assigned'))]" help="Stock to be received"/>
<filter icon="terp-check" name="received" string="Done" domain="[('state','=','done'))]"/>
<separator orientation="vertical"/>
<filter icon="terp-accessories-archiver-minus" string="Back Orders" domain="[('backorder_id','!=',False)]" help="Back Orders"/>
<filter icon="terp-accessories-archiver-minus" string="Back Order" domain="[('backorder_id','!=',False)]" help="Back Order"/>
<separator orientation="vertical"/>
<field name="origin"/>
<field name="partner_id" string="Supplier"/>
<field name="partner_id" string="Partner"/>
<field name="product_id"/>
</group>
<newline/>
@ -1720,7 +1738,7 @@
</record>
<record id="action_picking_tree_out" model="ir.actions.act_window">
<field name="name">Outgoing Products</field>
<field name="name">Customers Packings</field>
<field name="res_model">stock.picking</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
@ -1748,7 +1766,7 @@
</record>
<record id="action_out_picking_move" model="ir.actions.act_window">
<field name="name">Outcoming Packings</field>
<field name="name">Outgoing Products</field>
<field name="res_model">stock.move</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# 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/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -25,25 +25,25 @@ from tools.translate import _
class stock_move_track(osv.osv_memory):
_name = "stock.move.track"
_description = "Track moves"
_columns = {
'tracking_prefix': fields.char('Tracking prefix', size=64),
'tracking_prefix': fields.char('Tracking prefix', size=64),
'quantity': fields.float("Quantity per lot")
}
_defaults = {
'quantity': lambda *x: 1
}
def track_lines(self, cr, uid, ids, context={}):
""" To track stock moves lines
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: An ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
@param ids: An ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
datas = self.read(cr, uid, ids)[0]
move_obj = self.pool.get('stock.move')
move_obj._track_lines(cr, uid, context['active_id'], datas, context=context)
@ -54,11 +54,11 @@ stock_move_track()
class stock_move_consume(osv.osv_memory):
_name = "stock.move.consume"
_description = "Consume Products"
_columns = {
'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
'product_qty': fields.float('Quantity', required=True),
'product_uom': fields.many2one('product.uom', 'Product UOM', required=True),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
'product_qty': fields.float('Quantity', required=True),
'product_uom': fields.many2one('product.uom', 'Product UOM', required=True),
'location_id': fields.many2one('stock.location', 'Location', required=True)
}
@ -67,37 +67,37 @@ class stock_move_consume(osv.osv_memory):
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for default value
@param context: A standard dictionary
@param fields: List of fields for default value
@param context: A standard dictionary
@return: default values of fields
"""
res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
if 'product_id' in fields:
res.update({'product_id': move.product_id.id})
res.update({'product_id': move.product_id.id})
if 'product_uom' in fields:
res.update({'product_uom': move.product_uom.id})
res.update({'product_uom': move.product_uom.id})
if 'product_qty' in fields:
res.update({'product_qty': move.product_qty})
if 'location_id' in fields:
res.update({'location_id': move.location_id.id})
return res
return res
def do_move_consume(self, cr, uid, ids, context={}):
""" To move consumed products
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: the ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
@param ids: the ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
move_obj = self.pool.get('stock.move')
move_ids = context['active_ids']
for data in self.read(cr, uid, ids):
move_obj.action_consume(cr, uid, move_ids,
data['product_qty'], data['location_id'],
for data in self.read(cr, uid, ids):
move_obj.action_consume(cr, uid, move_ids,
data['product_qty'], data['location_id'],
context=context)
return {}
@ -108,7 +108,7 @@ class stock_move_scrap(osv.osv_memory):
_name = "stock.move.scrap"
_description = "Scrap Products"
_inherit = "stock.move.consume"
_defaults = {
'location_id': lambda *x: False
}
@ -118,19 +118,19 @@ class stock_move_scrap(osv.osv_memory):
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for default value
@param context: A standard dictionary
@param fields: List of fields for default value
@param context: A standard dictionary
@return: default values of fields
"""
res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
location_obj = self.pool.get('stock.location')
scrpaed_location_ids = location_obj.search(cr, uid, [('scrap_location','=',True)])
if 'product_id' in fields:
res.update({'product_id': move.product_id.id})
res.update({'product_id': move.product_id.id})
if 'product_uom' in fields:
res.update({'product_uom': move.product_uom.id})
res.update({'product_uom': move.product_uom.id})
if 'product_qty' in fields:
res.update({'product_qty': move.product_qty})
if 'location_id' in fields:
@ -138,23 +138,23 @@ class stock_move_scrap(osv.osv_memory):
res.update({'location_id': scrpaed_location_ids[0]})
else:
res.update({'location_id': False})
return res
def move_scrap(self, cr, uid, ids, context={}):
""" To move scraped products
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: the ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
move_obj = self.pool.get('stock.move')
@param ids: the ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
move_obj = self.pool.get('stock.move')
move_ids = context['active_ids']
for data in self.read(cr, uid, ids):
move_obj.action_scrap(cr, uid, move_ids,
data['product_qty'], data['location_id'],
move_obj.action_scrap(cr, uid, move_ids,
data['product_qty'], data['location_id'],
context=context)
return {}
@ -164,42 +164,42 @@ stock_move_scrap()
class split_in_production_lot(osv.osv_memory):
_name = "stock.move.split"
_description = "Split in Production lots"
def default_get(self, cr, uid, fields, context=None):
""" Get default values
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for default value
@param context: A standard dictionary
@param fields: List of fields for default value
@param context: A standard dictionary
@return: Default values of fields
"""
res = super(split_in_production_lot, self).default_get(cr, uid, fields, context=context)
move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
res = super(split_in_production_lot, self).default_get(cr, uid, fields, context=context)
move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
if 'product_id' in fields:
res.update({'product_id': move.product_id.id})
res.update({'product_id': move.product_id.id})
if 'qty' in fields:
res.update({'qty': move.product_qty})
res.update({'qty': move.product_qty})
return res
_columns = {
'qty': fields.integer('Quantity'),
'qty': fields.integer('Quantity'),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
'line_ids': fields.one2many('stock.move.split.lines', 'lot_id', 'Lots Number'),
'line_exist_ids': fields.one2many('stock.move.split.lines.exist', 'lot_id', 'Lots Existing Numbers'),
'use_exist' : fields.boolean('Use Exist'),
}
def split_lot(self, cr, uid, ids, context=None):
""" To split a lot
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: An ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
@param ids: An ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
self.split(cr, uid, ids, context.get('active_ids'), context=context)
return {}
@ -208,21 +208,21 @@ class split_in_production_lot(osv.osv_memory):
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: the ID or list of IDs if we want more than one
@param ids: the ID or list of IDs if we want more than one
@param move_ids: the ID or list of IDs of stock move we want to split
@param context: A standard dictionary
@return:
"""
@param context: A standard dictionary
@return:
"""
prodlot_obj = self.pool.get('stock.production.lot')
ir_sequence_obj = self.pool.get('ir.sequence')
move_obj = self.pool.get('stock.move')
new_move = []
new_move = []
for data in self.browse(cr, uid, ids):
for move in move_obj.browse(cr, uid, move_ids):
move_qty = move.product_qty
quantity_rest = move.product_qty
uos_qty_rest = move.product_uos_qty
new_move = []
new_move = []
if data.use_exist:
lines = [l for l in data.line_exist_ids if l]
else:
@ -238,12 +238,17 @@ class split_in_production_lot(osv.osv_memory):
quantity_rest = quantity
break
default_val = {
'product_qty': quantity,
'product_uos_qty': uos_qty,
'state': move.state
'product_qty': quantity,
'product_uos_qty': uos_qty,
'state': 'draft'
}
if quantity_rest > 0:
current_move = move_obj.copy(cr, uid, move.id, default_val)
move_obj.action_confirm(cr, uid, [current_move])
if move.state=='assigned':
move_obj.force_assign(cr, uid, [current_move])
elif move.state<>'confirmed':
move_obj.write(cr, uid, [current_move], {'state': move.state})
new_move.append(current_move)
if quantity_rest == 0:
current_move = move.id
@ -255,19 +260,19 @@ class split_in_production_lot(osv.osv_memory):
if not prodlot_id:
# sequence = ir_sequence_obj.get(cr, uid, 'stock.lot.serial')
prodlot_id = prodlot_obj.create(cr, uid, {'name': line.name},
# 'prefix' : line.name},
{'product_id': move.product_id.id})
# 'prefix' : line.name},
{'product_id': move.product_id.id})
move_obj.write(cr, uid, [current_move], {'prodlot_id': prodlot_id})
prodlot = prodlot_obj.browse(cr, uid, prodlot_id)
prodlot = prodlot_obj.browse(cr, uid, prodlot_id)
# ref = '%d' % (move.id)
# if prodlot.ref:
# ref = '%s, %s' % (prodlot.ref, ref)
# ref = '%s, %s' % (prodlot.ref, ref)
# prodlot_obj.write(cr, uid, [prodlot_id], {'ref': ref})
update_val = {}
if quantity_rest > 0:
if quantity_rest > 0:
update_val['product_qty'] = quantity_rest
update_val['product_uos_qty'] = uos_qty_rest
update_val['product_uos_qty'] = uos_qty_rest
move_obj.write(cr, uid, [move.id], update_val)
return new_move
split_in_production_lot()
@ -276,8 +281,8 @@ class stock_move_split_lines_exist(osv.osv_memory):
_name = "stock.move.split.lines.exist"
_description = "Exist Split lines"
_columns = {
'name': fields.char('Tracking serial', size=64),
'quantity': fields.integer('Quantity'),
'name': fields.char('Tracking serial', size=64),
'quantity': fields.integer('Quantity'),
'lot_id': fields.many2one('stock.move.split', 'Lot'),
'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot'),
}
@ -291,16 +296,14 @@ class stock_move_split_lines(osv.osv_memory):
_name = "stock.move.split.lines"
_description = "Split lines"
_columns = {
'name': fields.char('Tracking serial', size=64),
'quantity': fields.integer('Quantity'),
'name': fields.char('Tracking serial', size=64),
'quantity': fields.integer('Quantity'),
'use_exist' : fields.boolean('Use Exist'),
'lot_id': fields.many2one('stock.move.split', 'Lot'),
'action': fields.selection([('split','Split'),('keepinone','Keep in one lot')],'Action'),
}
_defaults = {
'quantity': lambda *x: 1,
'action' : lambda *x: 'split',
'action' : lambda *x: 'split',
}
stock_move_split_lines()

View File

@ -27,21 +27,19 @@ import pooler
import time
class stock_partial_move(osv.osv_memory):
_name = "stock.partial.move"
_description = "Partial Move"
_name = "stock.partial.move"
_description = "Partial Move"
_columns = {
'date': fields.datetime('Date', required=True),
'partner_id': fields.many2one('res.partner',string="Partner", required=True),
'address_id': fields.many2one('res.partner.address', 'Delivery Address', help="Address where goods are to be delivered", required=True),
}
def view_init(self, cr, uid, fields_list, context=None):
res = super(stock_partial_move, self).view_init(cr, uid, fields_list, context=context)
move_obj = self.pool.get('stock.move')
move_obj = self.pool.get('stock.move')
if not context:
context={}
moveids = []
for m in move_obj.browse(cr, uid, context.get('active_ids', [])):
for m in move_obj.browse(cr, uid, context.get('active_ids', [])):
if m.state in ('done', 'cancel'):
continue
if 'move%s_product_id'%(m.id) not in self._columns:
@ -56,55 +54,53 @@ class stock_partial_move(osv.osv_memory):
self._columns['move%s_product_price'%(m.id)] = fields.float("Price")
if 'move%s_product_currency'%(m.id) not in self._columns:
self._columns['move%s_product_currency'%(m.id)] = fields.many2one('res.currency',string="Currency")
return res
return res
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
result = super(stock_partial_move, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
result = super(stock_partial_move, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
move_obj = self.pool.get('stock.move')
move_ids = context.get('active_ids', False)
move_ids = context.get('active_ids', False)
move_ids = move_obj.search(cr, uid, [('id','in',move_ids)])
_moves_arch_lst = """<form string="Deliver Products">
<separator colspan="4" string="Delivery Information"/>
<field name="date" colspan="4" />
<field name="partner_id"/>
<field name="address_id"/>
<newline/>
<separator colspan="4" string="Move Detail"/>
"""
_moves_fields = result['fields']
if move_ids and view_type in ['form']:
for m in move_obj.browse(cr, uid, move_ids, context):
if move_ids and view_type in ['form']:
for m in move_obj.browse(cr, uid, move_ids, context):
if m.state in ('done', 'cancel'):
continue
_moves_fields.update({
'move%s_product_id'%(m.id) : {
'string': _('Product'),
'type' : 'many2one',
'relation': 'product.product',
'required' : True,
'readonly' : True,
'type' : 'many2one',
'relation': 'product.product',
'required' : True,
'readonly' : True,
},
'move%s_product_qty'%(m.id) : {
'string': _('Quantity'),
'type' : 'float',
'required': True,
'required': True,
},
'move%s_product_uom'%(m.id) : {
'string': _('Product UOM'),
'type' : 'many2one',
'relation': 'product.uom',
'required' : True,
'readonly' : True,
'type' : 'many2one',
'relation': 'product.uom',
'required' : True,
'readonly' : True,
}
})
})
_moves_arch_lst += """
<group colspan="4" col="10">
<field name="move%s_product_id" nolabel="1"/>
<field name="move%s_product_qty" string="Qty" />
<field name="move%s_product_uom" nolabel="1" />
"""%(m.id, m.id, m.id)
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
_moves_fields.update({
'move%s_product_price'%(m.id) : {
'string': _('Price'),
@ -112,9 +108,9 @@ class stock_partial_move(osv.osv_memory):
},
'move%s_product_currency'%(m.id): {
'string': _('Currency'),
'type' : 'float',
'type' : 'many2one',
'relation': 'res.currency',
'type' : 'float',
'type' : 'many2one',
'relation': 'res.currency',
}
})
_moves_arch_lst += """
@ -135,7 +131,7 @@ class stock_partial_move(osv.osv_memory):
</group>
</form>"""
result['arch'] = _moves_arch_lst
result['fields'] = _moves_fields
result['fields'] = _moves_fields
return result
def default_get(self, cr, uid, fields, context=None):
@ -143,13 +139,13 @@ class stock_partial_move(osv.osv_memory):
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context)
move_obj = self.pool.get('stock.move')
move_obj = self.pool.get('stock.move')
if not context:
context={}
moveids = []
@ -157,17 +153,9 @@ class stock_partial_move(osv.osv_memory):
res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
move_ids = context.get('active_ids', [])
move_ids = move_obj.search(cr, uid, [('id','in',move_ids)])
for m in move_obj.browse(cr, uid, context.get('active_ids', [])):
for m in move_obj.browse(cr, uid, context.get('active_ids', [])):
if m.state in ('done', 'cancel'):
continue
address_ids = list(set([(pick.address_id and pick.address_id.id, pick.address_id and pick.address_id.partner_id and pick.address_id.partner_id.id) for pick in move_obj.browse(cr, uid, move_ids)]))
if len(address_ids) == 1:
address_id = address_ids[0][0]
partner_id = address_ids[0][1]
res['address_id'] = address_ids[0][0]
res['partner_id'] = address_ids[0][1]
else:
address_id = partner_id = False
if 'move%s_product_id'%(m.id) in fields:
res['move%s_product_id'%(m.id)] = m.product_id.id
if 'move%s_product_qty'%(m.id) in fields:
@ -183,7 +171,7 @@ class stock_partial_move(osv.osv_memory):
currency = False
if hasattr(m.picking_id, 'sale_id') and m.picking_id.sale_id:
currency = m.picking_id.sale_id.pricelist_id.currency_id.id
if 'move%s_product_price'%(m.id) in fields:
res['move%s_product_price'%(m.id)] = price
if 'move%s_product_currency'%(m.id) in fields:
@ -197,38 +185,37 @@ class stock_partial_move(osv.osv_memory):
currency = False
if hasattr(m.picking_id, 'purchase_id') and m.picking_id.purchase_id:
currency = m.picking_id.purchase_id.pricelist_id.currency_id.id
if 'move%s_product_price'%(m.id) in fields:
res['move%s_product_price'%(m.id)] = price
if 'move%s_product_currency'%(m.id) in fields:
res['move%s_product_currency'%(m.id)] = currency
return res
print res
return res
def do_partial(self, cr, uid, ids, context):
""" Makes partial moves and pickings done.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
rec_id = context and context.get('active_id', False)
tracking_lot = context.get('tracking_lot', False)
if tracking_lot:
tracking = self.pool.get('stock.tracking')
tracking_lot = tracking.get_create_tracking_lot(cr, uid,[rec_id], tracking_lot)
context ['tracking_lot'] = tracking_lot
move_obj = self.pool.get('stock.move')
tracking_lot = tracking.get_create_tracking_lot(cr, uid,[rec_id], tracking_lot)
context ['tracking_lot'] = tracking_lot
move_obj = self.pool.get('stock.move')
move_ids = context.get('active_ids', False)
partial = self.browse(cr, uid, ids[0], context)
partial_datas = {
'partner_id' : partial.partner_id and partial.partner_id.id or False,
'address_id' : partial.address_id and partial.address_id.id or False,
'delivery_date' : partial.date
'delivery_date' : partial.date
}
for m in move_obj.browse(cr, uid, move_ids):
for m in move_obj.browse(cr, uid, move_ids):
if m.state in ('done', 'cancel'):
continue
partial_datas['move%s'%(m.id)] = {
@ -237,15 +224,15 @@ class stock_partial_move(osv.osv_memory):
'product_uom' : getattr(partial, 'move%s_product_uom'%(m.id)).id
}
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
partial_datas['move%s'%(m.id)].update({
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
partial_datas['move%s'%(m.id)].update({
'product_price' : getattr(partial, 'move%s_product_price'%(m.id)),
'product_currency': getattr(partial, 'move%s_product_currency'%(m.id)).id
})
})
res = move_obj.do_partial(cr, uid, move_ids, partial_datas, context=context)
return {}
stock_partial_move()
stock_partial_move()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,25 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<data>
<record id="view_stock_partial_move" model="ir.ui.view">
<field name="name">Delivery Product</field>
<field name="model">stock.partial.move</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Delivery Product">
</form>
</field>
</record>
<act_window name="Delivery Product"
res_model="stock.partial.move"
src_model="stock.move"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_partial_move"/>
<act_window name="Delivery Product"
res_model="stock.partial.move"
src_model="stock.move"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_partial_move"/>
</data>
</openerp>

View File

@ -30,17 +30,15 @@ class stock_partial_picking(osv.osv_memory):
_description = "Partial Picking"
_columns = {
'date': fields.datetime('Date', required=True),
'partner_id': fields.many2one('res.partner',string="Partner", required=True),
'address_id': fields.many2one('res.partner.address', 'Delivery Address', help="Address where goods are to be delivered", required=True),
}
def view_init(self, cr, uid, fields_list, context=None):
res = super(stock_partial_picking, self).view_init(cr, uid, fields_list, context=context)
pick_obj = self.pool.get('stock.picking')
pick_obj = self.pool.get('stock.picking')
if not context:
context={}
moveids = []
for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])):
for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])):
for m in pick.move_lines:
if m.state in ('done', 'cancel'):
continue
@ -56,20 +54,18 @@ class stock_partial_picking(osv.osv_memory):
self._columns['move%s_product_price'%(m.id)] = fields.float("Price")
if 'move%s_product_currency'%(m.id) not in self._columns:
self._columns['move%s_product_currency'%(m.id)] = fields.many2one('res.currency',string="Currency")
return res
return res
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
pick_obj = self.pool.get('stock.picking')
picking_ids = context.get('active_ids', False)
_moves_arch_lst = """<form string="Deliver Products">
<separator colspan="4" string="Delivery Information"/>
<field name="date" colspan="4" />
<field name="partner_id"/>
<field name="address_id"/>
<newline/>
picking_ids = context.get('active_ids', False)
_moves_arch_lst = """<form string="Process Packing">
<separator colspan="4" string="Product Information"/>
<field name="date" colspan="4" />
<newline/>
<separator colspan="4" string="Move Detail"/>
"""
"""
_moves_fields = result['fields']
if picking_ids and view_type in ['form']:
for pick in pick_obj.browse(cr, uid, picking_ids, context):
@ -79,32 +75,32 @@ class stock_partial_picking(osv.osv_memory):
_moves_fields.update({
'move%s_product_id'%(m.id) : {
'string': _('Product'),
'type' : 'many2one',
'relation': 'product.product',
'required' : True,
'readonly' : True,
'type' : 'many2one',
'relation': 'product.product',
'required' : True,
'readonly' : True,
},
'move%s_product_qty'%(m.id) : {
'string': _('Quantity'),
'type' : 'float',
'required': True,
'required': True,
},
'move%s_product_uom'%(m.id) : {
'string': _('Product UOM'),
'type' : 'many2one',
'relation': 'product.uom',
'required' : True,
'readonly' : True,
'type' : 'many2one',
'relation': 'product.uom',
'required' : True,
'readonly' : True,
}
})
})
_moves_arch_lst += """
<group colspan="4" col="10">
<field name="move%s_product_id" nolabel="1"/>
<field name="move%s_product_qty" string="Qty" />
<field name="move%s_product_uom" nolabel="1" />
"""%(m.id, m.id, m.id)
if (m.product_id.cost_method == 'average'):
if (m.product_id.cost_method == 'average'):
_moves_fields.update({
'move%s_product_price'%(m.id) : {
'string': _('Price'),
@ -112,9 +108,9 @@ class stock_partial_picking(osv.osv_memory):
},
'move%s_product_currency'%(m.id): {
'string': _('Currency'),
'type' : 'float',
'type' : 'many2one',
'relation': 'res.currency',
'type' : 'float',
'type' : 'many2one',
'relation': 'res.currency',
}
})
_moves_arch_lst += """
@ -128,14 +124,14 @@ class stock_partial_picking(osv.osv_memory):
<separator string="" colspan="4" />
<label string="" colspan="2"/>
<group col="2" colspan="2">
<button icon='gtk-cancel' special="cancel"
string="_Cancel" />
<button name="do_partial" string="_Deliver"
colspan="1" type="object" icon="gtk-apply" />
</group>
<button icon='gtk-cancel' special="cancel"
string="_Cancel" />
<button name="do_partial" string="_Process"
colspan="1" type="object" icon="gtk-apply" />
</group>
</form>"""
result['arch'] = _moves_arch_lst
result['fields'] = _moves_fields
result['fields'] = _moves_fields
return result
def default_get(self, cr, uid, fields, context=None):
@ -143,23 +139,19 @@ class stock_partial_picking(osv.osv_memory):
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
pick_obj = self.pool.get('stock.picking')
pick_obj = self.pool.get('stock.picking')
if not context:
context={}
moveids = []
if 'date' in fields:
res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])):
if 'partner_id' in fields:
res.update({'partner_id': pick.address_id.partner_id and pick.address_id.partner_id.id or False })
if 'address_id' in fields:
res.update({'address_id': pick.address_id.id})
for m in pick.move_lines:
if m.state in ('done', 'cancel'):
continue
@ -187,24 +179,22 @@ class stock_partial_picking(osv.osv_memory):
res['move%s_product_price'%(m.id)] = price
if 'move%s_product_currency'%(m.id) in fields:
res['move%s_product_currency'%(m.id)] = currency
return res
return res
def do_partial(self, cr, uid, ids, context):
def do_partial(self, cr, uid, ids, context):
""" Makes partial moves and pickings done.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
pick_obj = self.pool.get('stock.picking')
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
pick_obj = self.pool.get('stock.picking')
picking_ids = context.get('active_ids', False)
partial = self.browse(cr, uid, ids[0], context)
partial_datas = {
'partner_id' : partial.partner_id and partial.partner_id.id or False,
'address_id' : partial.address_id and partial.address_id.id or False,
'delivery_date' : partial.date
'delivery_date' : partial.date
}
for pick in pick_obj.browse(cr, uid, picking_ids):
for m in pick.move_lines:
@ -216,26 +206,13 @@ class stock_partial_picking(osv.osv_memory):
'product_uom' : getattr(partial, 'move%s_product_uom'%(m.id)).id
}
if (m.product_id.cost_method == 'average'):
partial_datas['move%s'%(m.id)].update({
if (m.product_id.cost_method == 'average'):
partial_datas['move%s'%(m.id)].update({
'product_price' : getattr(partial, 'move%s_product_price'%(m.id)),
'product_currency': getattr(partial, 'move%s_product_currency'%(m.id)).id
})
})
res = pick_obj.do_partial(cr, uid, picking_ids, partial_datas, context=context)
return {}
stock_partial_picking()
#_moves_arch_end = '''<?xml version="1.0"?>
#<form string="Picking result">
# <label string="The picking has been successfully made !" colspan="4"/>
# <field name="back_order_notification" colspan="4" nolabel="1"/>
#</form>'''
#_moves_fields_end = {
# 'back_order_notification': {'string':'Back Order' ,'type':'text', 'readonly':True}
# }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
stock_partial_picking()

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="action_partial_picking" model="ir.actions.act_window">
<data>
<record id="action_partial_picking" model="ir.actions.act_window">
<field name="name">Making Picking</field>
<field name="res_model">stock.partial.picking</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="res_model">stock.partial.picking</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</record>
</data>
</openerp>