[IMP] stock: stock partial move wizard
bzr revid: hmo@tinyerp.com-20100326145201-3viwi4gcsujnvfhd
This commit is contained in:
parent
d9dc66b994
commit
373b2701c5
|
@ -44,6 +44,7 @@ Thanks to the double entry management, the inventory controlling is powerful and
|
|||
"stock_data.xml",
|
||||
"wizard/stock_move_view.xml",
|
||||
"wizard/stock_partial_picking_view.xml",
|
||||
"wizard/stock_partial_move_view.xml",
|
||||
"wizard/stock_inventory_set_stock_zero_view.xml",
|
||||
"wizard/stock_fill_inventory_view.xml",
|
||||
"wizard/stock_invoice_onshipping_view.xml",
|
||||
|
|
|
@ -890,6 +890,8 @@ class stock_picking(osv.osv):
|
|||
complete, too_many, too_few = [], [], []
|
||||
move_product_qty = {}
|
||||
for move in pick.move_lines:
|
||||
if move.state in ('done', 'cancel'):
|
||||
continue
|
||||
partial_data = partial_datas.get('move%s'%(move.id), False)
|
||||
assert partial_data, _('Do not Found Partial data of Stock Move Line :%s' %(move.id))
|
||||
product_qty = partial_data.get('product_qty',0.0)
|
||||
|
@ -1117,10 +1119,9 @@ class stock_delivery(osv.osv):
|
|||
'partner_id': fields.many2one('res.partner', 'Partner', required=True),
|
||||
'address_id': fields.many2one('res.partner.address', 'Address', required=True),
|
||||
'move_delivered':fields.one2many('stock.move', 'delivered_id', 'Move Delivered'),
|
||||
'picking_id': fields.many2one('stock.picking', 'Picking list', required=True),
|
||||
'picking_id': fields.many2one('stock.picking', 'Picking list'),
|
||||
|
||||
}
|
||||
|
||||
stock_delivery()
|
||||
# ----------------------------------------------------
|
||||
# Move
|
||||
|
@ -1788,7 +1789,134 @@ class stock_move(osv.osv):
|
|||
self.write(cr, uid, [move.id], update_val)
|
||||
|
||||
self.action_done(cr, uid, res)
|
||||
return res
|
||||
return res
|
||||
|
||||
def do_partial(self, cr, uid, ids, partial_datas, context={}):
|
||||
"""
|
||||
@ partial_datas : dict. contain details of partial picking
|
||||
like partner_id, address_id, delivery_date, delivery moves with product_id, product_qty, uom
|
||||
"""
|
||||
res = {}
|
||||
picking_obj = self.pool.get('stock.picking')
|
||||
delivery_obj = self.pool.get('stock.delivery')
|
||||
product_obj = self.pool.get('product.product')
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
users_obj = self.pool.get('res.users')
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
price_type_obj = self.pool.get('product.price.type')
|
||||
sequence_obj = self.pool.get('ir.sequence')
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
partner_id = partial_datas.get('partner_id', False)
|
||||
address_id = partial_datas.get('address_id', False)
|
||||
delivery_date = partial_datas.get('delivery_date', False)
|
||||
|
||||
new_moves = []
|
||||
|
||||
complete, too_many, too_few = [], [], []
|
||||
move_product_qty = {}
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
if move.state in ('done', 'cancel'):
|
||||
continue
|
||||
partial_data = partial_datas.get('move%s'%(move.id), False)
|
||||
assert partial_data, _('Do not Found Partial data of Stock Move Line :%s' %(move.id))
|
||||
product_qty = partial_data.get('product_qty',0.0)
|
||||
move_product_qty[move.id] = product_qty
|
||||
product_uom = partial_data.get('product_uom',False)
|
||||
product_price = partial_data.get('product_price',0.0)
|
||||
product_currency = partial_data.get('product_currency',False)
|
||||
if move.product_qty == product_qty:
|
||||
complete.append(move)
|
||||
elif move.product_qty > product_qty:
|
||||
too_few.append(move)
|
||||
else:
|
||||
too_many.append(move)
|
||||
|
||||
# Average price computation
|
||||
if (move.picking_id.type == 'in') and (move.product_id.cost_method == 'average'):
|
||||
product = product_obj.browse(cr, uid, move.product_id.id)
|
||||
user = users_obj.browse(cr, uid, uid)
|
||||
context['currency_id'] = move.company_id.currency_id.id
|
||||
qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
|
||||
pricetype = False
|
||||
if user.company_id.property_valuation_price_type:
|
||||
pricetype = price_type_obj.browse(cr, uid, user.company_id.property_valuation_price_type.id)
|
||||
if pricetype and qty > 0:
|
||||
new_price = currency_obj.compute(cr, uid, product_currency,
|
||||
user.company_id.currency_id.id, product_price)
|
||||
new_price = uom_obj._compute_price(cr, uid, product_uom, new_price,
|
||||
product.uom_id.id)
|
||||
if product.qty_available <= 0:
|
||||
new_std_price = new_price
|
||||
else:
|
||||
# Get the standard price
|
||||
amount_unit = product.price_get(pricetype.field, context)[product.id]
|
||||
new_std_price = ((amount_unit * product.qty_available)\
|
||||
+ (new_price * qty))/(product.qty_available + qty)
|
||||
|
||||
# Write the field according to price type field
|
||||
product_obj.write(cr, uid, [product.id],
|
||||
{pricetype.field: new_std_price})
|
||||
self.write(cr, uid, [move.id], {'price_unit': new_price})
|
||||
|
||||
for move in too_few:
|
||||
product_qty = move_product_qty[move.id]
|
||||
if product_qty != 0:
|
||||
new_move = self.copy(cr, uid, move.id,
|
||||
{
|
||||
'product_qty' : product_qty,
|
||||
'product_uos_qty': product_qty,
|
||||
'picking_id' : move.picking_id.id,
|
||||
'state': 'assigned',
|
||||
'move_dest_id': False,
|
||||
'price_unit': move.price_unit,
|
||||
})
|
||||
complete.append(self.browse(cr, uid, new_move))
|
||||
self.write(cr, uid, move.id,
|
||||
{
|
||||
'product_qty' : move.product_qty - product_qty,
|
||||
'product_uos_qty':move.product_qty - product_qty,
|
||||
})
|
||||
|
||||
|
||||
for move in too_many:
|
||||
self.write(cr, uid, move.id,
|
||||
{
|
||||
'product_qty': product_qty,
|
||||
'product_uos_qty': product_qty
|
||||
})
|
||||
complete.append(move)
|
||||
|
||||
for move in complete:
|
||||
self.action_done(cr, uid, [move.id])
|
||||
|
||||
# TOCHECK : Done picking if all moves are done
|
||||
cr.execute("""
|
||||
SELECT move.id FROM stock_picking pick
|
||||
RIGHT JOIN stock_move move ON move.picking_id = pick.id AND move.state = %s
|
||||
WHERE pick.id = %s""",
|
||||
('done', move.picking_id.id))
|
||||
res = cr.fetchall()
|
||||
if len(res) == len(move.picking_id.move_lines):
|
||||
picking_obj.action_move(cr, uid, [move.picking_id.id])
|
||||
wf_service.trg_validate(uid, 'stock.picking', move.picking_id.id, 'button_done', cr)
|
||||
|
||||
ref = {}
|
||||
done_move_ids = []
|
||||
for move in complete:
|
||||
done_move_ids.append(move.id)
|
||||
if move.picking_id.id not in ref:
|
||||
delivery_id = delivery_obj.create(cr, uid, {
|
||||
'partner_id': partner_id,
|
||||
'address_id': address_id,
|
||||
'date': delivery_date,
|
||||
'name' : move.picking_id.name,
|
||||
'picking_id': move.picking_id.id
|
||||
}, context=context)
|
||||
ref[move.picking_id.id] = delivery_id
|
||||
delivery_obj.write(cr, uid, ref[move.picking_id.id], {
|
||||
'move_delivered' : [(4,move.id)]
|
||||
})
|
||||
return done_move_ids
|
||||
|
||||
stock_move()
|
||||
|
||||
|
|
|
@ -1488,7 +1488,7 @@
|
|||
<field name="date_planned"/>
|
||||
<field name="backorder_id"/>
|
||||
<field name="state"/>
|
||||
<button name="%(partial_move)d" string="Partial" type="action" states="assigned" icon="gtk-justify-fill"/>
|
||||
<button name="%(action_partial_move)d" string="Partial" type="action" states="assigned" icon="gtk-justify-fill"/>
|
||||
<button name="action_cancel" states="assigned,confirmed" string="Cancel" type="object" icon="gtk-cancel"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
@ -1534,7 +1534,7 @@
|
|||
<button name="action_confirm" states="draft" string="Confirm" type="object" icon="gtk-apply"/>
|
||||
<button name="action_assign" states="confirmed" string="Set Available" type="object" icon="gtk-yes"/>
|
||||
<button name="action_cancel" states="assigned,confirmed" string="Cancel" type="object" icon="gtk-cancel"/>
|
||||
<button name="%(partial_move)d" states="assigned" string="Partial" type="action" icon="gtk-justify-fill"/>
|
||||
<button name="%(action_partial_move)d" states="assigned" string="Partial" type="action" icon="gtk-justify-fill"/>
|
||||
<button name="action_done" states="assigned" string="Done" type="object" icon="gtk-jump-to"/>
|
||||
</group>
|
||||
</page>
|
||||
|
|
|
@ -29,14 +29,7 @@
|
|||
menu="False"
|
||||
keyword="client_action_multi"
|
||||
name="stock.return.picking"
|
||||
string="Return picking"/>
|
||||
|
||||
<wizard
|
||||
id="partial_move"
|
||||
model="stock.move"
|
||||
multi="True"
|
||||
name="stock.partial_move"
|
||||
string="Partial Move"/>
|
||||
string="Return picking"/>
|
||||
|
||||
<wizard
|
||||
id="split_inventory_lots"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
import stock_traceability
|
||||
import stock_move
|
||||
import stock_partial_picking
|
||||
import wizard_partial_move
|
||||
import stock_partial_move
|
||||
import wizard_picking_make
|
||||
import wizard_replacement
|
||||
import wizard_return
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
# -*- 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 service import web_services
|
||||
from tools.translate import _
|
||||
import netsvc
|
||||
import pooler
|
||||
import time
|
||||
|
||||
class stock_partial_move(osv.osv_memory):
|
||||
_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')
|
||||
if not context:
|
||||
context={}
|
||||
moveids = []
|
||||
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:
|
||||
self._columns['move%s_product_id'%(m.id)] = fields.many2one('product.product',string="Product")
|
||||
if 'move%s_product_qty'%(m.id) not in self._columns:
|
||||
self._columns['move%s_product_qty'%(m.id)] = fields.float("Quantity")
|
||||
if 'move%s_product_uom'%(m.id) not in self._columns:
|
||||
self._columns['move%s_product_uom'%(m.id)] = fields.many2one('product.uom',string="Product UOM")
|
||||
|
||||
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
|
||||
if 'move%s_product_price'%(m.id) not in self._columns:
|
||||
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
|
||||
|
||||
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)
|
||||
move_obj = self.pool.get('stock.move')
|
||||
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 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,
|
||||
},
|
||||
'move%s_product_qty'%(m.id) : {
|
||||
'string': _('Quantity'),
|
||||
'type' : 'float',
|
||||
'required': True,
|
||||
},
|
||||
'move%s_product_uom'%(m.id) : {
|
||||
'string': _('Product UOM'),
|
||||
'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'):
|
||||
_moves_fields.update({
|
||||
'move%s_product_price'%(m.id) : {
|
||||
'string': _('Price'),
|
||||
'type' : 'float',
|
||||
},
|
||||
'move%s_product_currency'%(m.id): {
|
||||
'string': _('Currency'),
|
||||
'type' : 'float',
|
||||
'type' : 'many2one',
|
||||
'relation': 'res.currency',
|
||||
}
|
||||
})
|
||||
_moves_arch_lst += """
|
||||
<field name="move%s_product_price" />
|
||||
<field name="move%s_product_currency" nolabel="1"/>
|
||||
"""%(m.id, m.id)
|
||||
_moves_arch_lst += """
|
||||
</group>
|
||||
"""
|
||||
_moves_arch_lst += """
|
||||
<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>
|
||||
</form>"""
|
||||
result['arch'] = _moves_arch_lst
|
||||
result['fields'] = _moves_fields
|
||||
return result
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
To get default values for the object.
|
||||
|
||||
@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.
|
||||
|
||||
"""
|
||||
|
||||
res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context)
|
||||
move_obj = self.pool.get('stock.move')
|
||||
if not context:
|
||||
context={}
|
||||
moveids = []
|
||||
if 'date' in fields:
|
||||
res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
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) in fields:
|
||||
res['move%s_product_id'%(m.id)] = m.product_id.id
|
||||
if 'move%s_product_qty'%(m.id) in fields:
|
||||
res['move%s_product_qty'%(m.id)] = m.product_qty
|
||||
if 'move%s_product_uom'%(m.id) in fields:
|
||||
res['move%s_product_uom'%(m.id)] = m.product_uom.id
|
||||
|
||||
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
|
||||
price = 0
|
||||
if hasattr(m, 'purchase_line_id') and m.purchase_line_id:
|
||||
price = m.purchase_line_id.price_unit
|
||||
|
||||
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
|
||||
|
||||
def do_partial(self, cr, uid, ids, context):
|
||||
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
|
||||
}
|
||||
for m in move_obj.browse(cr, uid, move_ids):
|
||||
if m.state in ('done', 'cancel'):
|
||||
continue
|
||||
partial_datas['move%s'%(m.id)] = {
|
||||
'product_id' : getattr(partial, 'move%s_product_id'%(m.id)).id,
|
||||
'product_qty' : getattr(partial, 'move%s_product_qty'%(m.id)),
|
||||
'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({
|
||||
'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()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<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"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -62,11 +62,9 @@ class stock_partial_picking(osv.osv_memory):
|
|||
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)
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
picking_ids = context.get('active_ids', False)
|
||||
if not picking_ids:
|
||||
return result
|
||||
if view_type in ['form']:
|
||||
_moves_arch_lst = """<form string="Deliver Products">
|
||||
picking_ids = context.get('active_ids', False)
|
||||
picking_ids = pick_obj.search(cr, uid, [('id', 'in', picking_ids)])
|
||||
_moves_arch_lst = """<form string="Deliver Products">
|
||||
<separator colspan="4" string="Delivery Information"/>
|
||||
<field name="date" colspan="4" />
|
||||
<field name="partner_id"/>
|
||||
|
@ -74,7 +72,8 @@ class stock_partial_picking(osv.osv_memory):
|
|||
<newline/>
|
||||
<separator colspan="4" string="Move Detail"/>
|
||||
"""
|
||||
_moves_fields = result['fields']
|
||||
_moves_fields = result['fields']
|
||||
if picking_ids and view_type in ['form']:
|
||||
for pick in pick_obj.browse(cr, uid, picking_ids, context):
|
||||
for m in pick.move_lines:
|
||||
if m.state in ('done', 'cancel'):
|
||||
|
@ -127,18 +126,18 @@ class stock_partial_picking(osv.osv_memory):
|
|||
_moves_arch_lst += """
|
||||
</group>
|
||||
"""
|
||||
_moves_arch_lst += """
|
||||
<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>
|
||||
</form>"""
|
||||
result['arch'] = _moves_arch_lst
|
||||
result['fields'] = _moves_fields
|
||||
_moves_arch_lst += """
|
||||
<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>
|
||||
</form>"""
|
||||
result['arch'] = _moves_arch_lst
|
||||
result['fields'] = _moves_fields
|
||||
return result
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
|
@ -160,13 +159,13 @@ class stock_partial_picking(osv.osv_memory):
|
|||
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.id})
|
||||
if 'address_id' in fields:
|
||||
res.update({'address_id': pick.address_id.id})
|
||||
if 'date' in fields:
|
||||
res.update({'date': pick.date})
|
||||
res.update({'address_id': pick.address_id.id})
|
||||
for m in pick.move_lines:
|
||||
if m.state in ('done', 'cancel'):
|
||||
continue
|
||||
|
@ -215,8 +214,7 @@ class stock_partial_picking(osv.osv_memory):
|
|||
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 {}
|
||||
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
# -*- 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import netsvc
|
||||
from tools.misc import UpdateableStr, UpdateableDict
|
||||
import pooler
|
||||
|
||||
import wizard
|
||||
from osv import osv
|
||||
import tools
|
||||
from tools.translate import _
|
||||
|
||||
_moves_arch = UpdateableStr()
|
||||
_moves_fields = UpdateableDict()
|
||||
|
||||
_moves_arch_end = '''<?xml version="1.0"?>
|
||||
<form string="Picking result">
|
||||
<label string="Move(s) have been successfully Done !" colspan="4"/>
|
||||
</form>'''
|
||||
|
||||
def make_default(val):
|
||||
def fct(uid, data, state):
|
||||
return val
|
||||
return fct
|
||||
|
||||
def _to_xml(s):
|
||||
return (s or '').replace('&','&').replace('<','<').replace('>','>')
|
||||
|
||||
def _get_moves(self, cr, uid, data, context):
|
||||
move_obj = pooler.get_pool(cr.dbname).get('stock.move')
|
||||
move_lines = move_obj.browse(cr, uid, data['ids'], context)
|
||||
res = {}
|
||||
|
||||
_moves_fields.clear()
|
||||
_moves_arch_lst = ['<?xml version="1.0"?>', '<form string="Partial Stock Moves">']
|
||||
|
||||
for move in move_lines:
|
||||
quantity = move.product_qty
|
||||
if move.state != 'assigned':
|
||||
quantity = 0
|
||||
|
||||
_moves_arch_lst.append('<field name="move%s" />' % (move.id,))
|
||||
_moves_fields['move%s' % move.id] = {
|
||||
'string': _to_xml(move.name),
|
||||
'type' : 'float', 'required' : True, 'default' : make_default(quantity)}
|
||||
|
||||
if (move.picking_id.type == 'in') and (move.product_id.cost_method == 'average'):
|
||||
price = 0
|
||||
if hasattr(move, 'purchase_line_id') and move.purchase_line_id:
|
||||
price = move.purchase_line_id.price_unit
|
||||
|
||||
currency = 0
|
||||
if hasattr(move.picking_id, 'purchase_id') and move.picking_id.purchase_id:
|
||||
currency = move.picking_id.purchase_id.pricelist_id.currency_id.id
|
||||
|
||||
_moves_arch_lst.append('<group col="6"><field name="uom%s" nolabel="1"/>\
|
||||
<field name="price%s"/>' % (move.id, move.id,))
|
||||
|
||||
_moves_fields['price%s' % move.id] = {'string': 'Unit Price',
|
||||
'type': 'float', 'required': True, 'default': make_default(price)}
|
||||
|
||||
_moves_fields['uom%s' % move.id] = {'string': 'UOM', 'type': 'many2one',
|
||||
'relation': 'product.uom', 'required': True,
|
||||
'default': make_default(move.product_uom.id)}
|
||||
|
||||
_moves_arch_lst.append('<field name="currency%d" nolabel="1"/></group>' % (move.id,))
|
||||
_moves_fields['currency%s' % m.id] = {'string': 'Currency',
|
||||
'type': 'many2one', 'relation': 'res.currency',
|
||||
'required': True, 'default': make_default(currency)}
|
||||
|
||||
_moves_arch_lst.append('<newline/>')
|
||||
res.setdefault('moves', []).append(move.id)
|
||||
|
||||
_moves_arch_lst.append('</form>')
|
||||
_moves_arch.string = '\n'.join(_moves_arch_lst)
|
||||
return res
|
||||
|
||||
def _do_split(self, cr, uid, data, context):
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
move_obj = pool.get('stock.move')
|
||||
pick_obj = pool.get('stock.picking')
|
||||
product_obj = pool.get('product.product')
|
||||
currency_obj = pool.get('res.currency')
|
||||
users_obj = pool.get('res.users')
|
||||
uom_obj = pool.get('product.uom')
|
||||
move_lines = move_obj.browse(cr, uid, data['ids'])
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
complete, too_few, too_many = [], [], []
|
||||
for move in move_lines:
|
||||
states = []
|
||||
|
||||
if move.product_qty == data['form']['move%s' % move.id]:
|
||||
complete.append(move)
|
||||
elif move.product_qty > data['form']['move%s' % move.id]:
|
||||
too_few.append(move)
|
||||
else:
|
||||
too_many.append(move)
|
||||
# Average price computation
|
||||
if (move.picking_id.type == 'in') and (move.product_id.cost_method == 'average'):
|
||||
product = move.product_id
|
||||
user = users_obj.browse(cr, uid, uid)
|
||||
qty = data['form']['move%s' % move.id]
|
||||
uom = data['form']['uom%s' % move.id]
|
||||
price = data['form']['price%s' % move.id]
|
||||
currency = data['form']['currency%s' % move.id]
|
||||
|
||||
qty = uom_obj._compute_qty(cr, uid, uom, qty, product.uom_id.id)
|
||||
pricetype=pool.get('product.price.type').browse(cr,uid,user.company_id.property_valuation_price_type.id)
|
||||
|
||||
if (qty > 0):
|
||||
new_price = currency_obj.compute(cr, uid, currency,
|
||||
user.company_id.currency_id.id, price)
|
||||
new_price = uom_obj._compute_price(cr, uid, uom, new_price,
|
||||
product.uom_id.id)
|
||||
if product.qty_available<=0:
|
||||
new_std_price = new_price
|
||||
else:
|
||||
# Get the standard price
|
||||
amount_unit=product.price_get(pricetype.field, context)[product.id]
|
||||
new_std_price = ((amount_unit * product.qty_available)\
|
||||
+ (new_price * qty))/(product.qty_available + qty)
|
||||
|
||||
product_obj.write(cr, uid, [product.id],
|
||||
{pricetype.field: new_std_price})
|
||||
move_obj.write(cr, uid, move.id, {'price_unit': new_price})
|
||||
|
||||
for move in too_few:
|
||||
if data['form']['move%s' % move.id] != 0:
|
||||
new_move = move_obj.copy(cr, uid, move.id,
|
||||
{
|
||||
'product_qty' : data['form']['move%s' % move.id],
|
||||
'product_uos_qty':data['form']['move%s' % move.id],
|
||||
'picking_id' : move.picking_id.id,
|
||||
'state': 'assigned',
|
||||
'move_dest_id': False,
|
||||
'price_unit': move.price_unit,
|
||||
})
|
||||
complete.append(move_obj.browse(cr, uid, new_move))
|
||||
move_obj.write(cr, uid, move.id,
|
||||
{
|
||||
'product_qty' : move.product_qty - data['form']['move%s' % move.id],
|
||||
'product_uos_qty':move.product_qty - data['form']['move%s' % move.id],
|
||||
})
|
||||
|
||||
|
||||
for move in too_many:
|
||||
move_obj.write(cr, uid, move.id,
|
||||
{
|
||||
'product_qty': data['form']['move%s' % move.id],
|
||||
'product_uos_qty': data['form']['move%s' % move.id]
|
||||
})
|
||||
complete.append(move)
|
||||
|
||||
for move in complete:
|
||||
move_obj.action_done(cr, uid, [move.id])
|
||||
|
||||
# TOCHECK : Done picking if all moves are done
|
||||
cr.execute('select move.id from stock_picking pick \
|
||||
right join stock_move move on move.picking_id = pick.id and move.state = ''%s'' where pick.id = %s',
|
||||
('done', move.picking_id.id))
|
||||
res = cr.fetchall()
|
||||
if len(res) == len(move.picking_id.move_lines):
|
||||
pick_obj.action_move(cr, uid, [move.picking_id.id])
|
||||
wf_service.trg_validate(uid, 'stock.picking', move.picking_id.id, 'button_done', cr)
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
|
||||
class partial_move(wizard.interface):
|
||||
|
||||
states = {
|
||||
'init': {
|
||||
'actions': [ _get_moves ],
|
||||
'result': {'type': 'form', 'arch': _moves_arch, 'fields': _moves_fields,
|
||||
'state' : (
|
||||
('end', 'Cancel', 'gtk-cancel'),
|
||||
('split', 'Partial', 'gtk-apply', True)
|
||||
)
|
||||
},
|
||||
},
|
||||
'split': {
|
||||
'actions': [ _do_split ],
|
||||
'result': {'type': 'state', 'state': 'end2'},
|
||||
},
|
||||
'end2': {
|
||||
'actions': [],
|
||||
'result': {'type': 'form', 'arch': _moves_arch_end,
|
||||
'fields': {},
|
||||
'state': (
|
||||
('end', 'Close'),
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
partial_move('stock.partial_move')
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
Loading…
Reference in New Issue