"update_xml" : [
"stock_data.xml",
"wizard/stock_move_view.xml",
+ "wizard/stock_partial_picking_view.xml",
"wizard/stock_inventory_set_stock_zero_view.xml",
"wizard/stock_fill_inventory_view.xml",
"wizard/stock_invoice_onshipping_view.xml",
class product_product(osv.osv):
- _inherit = "product.product"
+ _inherit = "product.product"
def do_change_standard_price(self, cr, uid, ids, datas, context={}):
"""
"""
location_obj = self.pool.get('stock.location')
move_obj = self.pool.get('account.move')
- move_line_obj = self.pool.get('account.move.line')
- loc_ids = location_obj.search(cr, uid, [('account_id','<>',False),('usage','=','internal')])
-
+ move_line_obj = self.pool.get('account.move.line')
+
new_price = datas.get('new_price', 0.0)
stock_output_acc = datas.get('stock_output_account', False)
stock_input_acc = datas.get('stock_input_account', False)
journal_id = datas.get('stock_journal', False)
- move_ids = []
+ move_ids = []
for rec_id in ids:
+ loc_ids = location_obj.search(cr, uid, [('account_id','<>',False),('usage','=','internal')])
for location in location_obj.browse(cr, uid, loc_ids):
c = context.copy()
c.update({
product = self.browse(cr, uid, rec_id, context=c)
qty = product.qty_available
- diff = product.standard_price - new_price
+ diff = product.standard_price - new_price
assert diff, _("Could not find any difference between standard price and new price!")
if qty:
location_account = location.account_id and location.account_id.id or False
- company_id = location.company_id and location.company_id.id or False
+ company_id = location.company_id and location.company_id.id or False
assert location_account, _('Inventory Account is not specified for Location: %s' % (location.name))
assert company_id, _('Company is not specified in Location')
+ #
+ # Accounting Entries
+ #
+ if not journal_id:
+ journal_id = product.categ_id.property_stock_journal and product.categ_id.property_stock_journal.id or False
+ if not journal_id:
+ raise osv.except_osv(_('Error!'),
+ _('There is no journal defined '\
+ 'on the product category: "%s" (id: %d)') % \
+ (product.categ_id.name,
+ product.categ_id.id,))
move_id = move_obj.create(cr, uid, {
'journal_id': journal_id,
'company_id': company_id
})
move_ids.append(move_id)
- if diff > 0:
+
+
+ if diff > 0:
+ if not stock_input_acc:
+ stock_input_acc = product.product_tmpl_id.\
+ property_stock_account_input.id
+ if not stock_input_acc:
+ stock_input_acc = product.categ_id.\
+ property_stock_account_input_categ.id
+ if not stock_input_acc:
+ raise osv.except_osv(_('Error!'),
+ _('There is no stock input account defined ' \
+ 'for this product: "%s" (id: %d)') % \
+ (product.name,
+ product.id,))
amount_diff = qty * diff
move_line_obj.create(cr, uid, {
'name': product.name,
'move_id': move_id
})
elif diff < 0:
+ if not stock_output_acc:
+ stock_output_acc = product.product_tmpl_id.\
+ property_stock_account_output.id
+ if not stock_output_acc:
+ stock_output_acc = product.categ_id.\
+ property_stock_account_output_categ.id
+ if not stock_output_acc:
+ raise osv.except_osv(_('Error!'),
+ _('There is no stock output account defined ' \
+ 'for this product: "%s" (id: %d)') % \
+ (product.name,
+ product.id,))
amount_diff = qty * -diff
move_line_obj.create(cr, uid, {
'name': product.name,
self.write(cr, uid, rec_id, {'standard_price': new_price})
- return True
+ return move_ids
def view_header_get(self, cr, user, view_id, view_type, context):
res = super(product_product, self).view_header_get(cr, user, view_id, view_type, context)
'max_date': fields.function(get_min_max_date, fnct_inv=_set_maximum_date, multi="min_max_date",
method=True, store=True, type='datetime', string='Max. Expected Date', select=2),
'move_lines': fields.one2many('stock.move', 'picking_id', 'Entry lines', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}),
+ 'delivery_line':fields.one2many('stock.delivery', 'picking_id', 'Delivery lines', readonly=True),
'auto_picking': fields.boolean('Auto-Picking'),
'address_id': fields.many2one('res.partner.address', 'Partner', help="Address of partner"),
'invoice_state': fields.selection([
continue
return super(stock_picking, self).unlink(cr, uid, ids, context=context)
- def do_partial(self, cr, uid, ids, partial_datas, context):
+ 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
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)
new_picking = None
new_moves = []
- complete, too_many, too_few = [], [], []
+ complete, too_many, too_few = [], [], []
+ move_product_qty = {}
for move in pick.move_lines:
- partial_data = partial_datas.get('move%s'%(move.id), False)
+ 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)
{pricetype.field: new_std_price})
move_obj.write(cr, uid, [move.id], {'price_unit': new_price})
- delivery_id = delivery_obj.create(cr, uid, {
- 'name': pick.name,
- 'partner_id': partner_id,
- 'address_id': address_id,
- 'date': delivery_date,
- 'picking_id':pick.id
- }, context=context)
-
+
for move in too_few:
+ product_qty = move_product_qty[move.id]
if not new_picking:
new_picking = self.copy(cr, uid, pick.id,
{
- 'name': pool.get('ir.sequence').get(cr, uid, 'stock.picking.%s'%(pick.type)),
+ 'name': sequence_obj.get(cr, uid, 'stock.picking.%s'%(pick.type)),
'move_lines' : [],
'state':'draft',
})
{
'product_qty' : product_qty,
'product_uos_qty': product_qty, #TODO: put correct uos_qty
- 'picking_id' : new_picking,
- 'delivery_id' : delivery_id,
+ 'picking_id' : new_picking,
'state': 'assigned',
'move_dest_id': False,
'price_unit': move.price_unit,
if new_picking:
move_obj.write(cr, uid, [c.id for c in complete], {'picking_id': new_picking})
for move in too_many:
+ product_qty = move_product_qty[move.id]
move_obj.write(cr, uid, [move.id],
{
'product_qty' : product_qty,
})
else:
for move in too_many:
+ product_qty = move_product_qty[move.id]
move_obj.write(cr, uid, [move.id],
{
'product_qty': product_qty,
- 'product_uos_qty': product_qty
+ 'product_uos_qty': product_qty #TODO: put correct uos_qty
})
# At first we confirm the new picking (if necessary)
self.action_move(cr, uid, [new_picking])
wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_done', cr)
wf_service.trg_write(uid, 'stock.picking', pick.id, cr)
+ delivered_pack_id = new_picking
else:
self.action_move(cr, uid, [pick.id])
- wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_done', cr)
- bo_name = ''
- if new_picking:
- bo_name = pick_obj.read(cr, uid, [new_picking], ['name'])[0]['name']
- res[pick.id] = {'new_picking': new_picking or False, 'back_order':bo_name}
+ wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_done', cr)
+ delivered_pack_id = pick.id
+
+ delivered_pack = self.browse(cr, uid, delivered_pack_id, context=context)
+ delivery_id = delivery_obj.create(cr, uid, {
+ 'name': delivered_pack.name,
+ 'partner_id': partner_id,
+ 'address_id': address_id,
+ 'date': delivery_date,
+ 'picking_id' : pick.id,
+ 'move_delivered' : [(6,0, map(lambda x:x.id, delivered_pack.move_lines))]
+ }, context=context)
+ res[pick.id] = {'delivered_picking': delivered_pack.id or False}
return res
stock_picking()
stock_production_lot_revision()
class stock_delivery(osv.osv):
+
+ """ Tracability of partialdeliveries """
+
_name = "stock.delivery"
+ _description = "Delivery"
+ _columns = {
+ 'name': fields.char('Name', size=60, required=True),
+ 'date': fields.datetime('Date', required=True),
+ '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),
+
+ }
+
stock_delivery()
# ----------------------------------------------------
# Move
_defaults = {
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.inventory', context=c),
}
-stock_warehouse()
-
-class stock_delivery(osv.osv):
-
- """ Tracability of partialdeliveries """
-
- _name = "stock.delivery"
- _description = "Delivery"
- _columns = {
- 'name': fields.char('Name', size=60, required=True),
- 'date': fields.datetime('Date'),
- 'partner_id': fields.many2one('res.partner', 'Partner'),
- 'address_id': fields.many2one('res.partner.address', 'Address'),
- 'product_delivered':fields.one2many('stock.move', 'delivered_id', 'Product Delivered', domain=[('picking_id.type','=','in')]),
- 'picking_id': fields.many2one('stock.picking', 'Picking list'),
-
- }
+stock_warehouse()
-
-stock_delivery()
# Move wizard :
# get confirm or assign stock move lines of partner and put in current picking.
<field name="code">stock.picking.internal</field>
</record>
+ <record id="seq_type_picking_delivery" model="ir.sequence.type">
+ <field name="name">Picking Delivery</field>
+ <field name="code">stock.picking.delivery</field>
+ </record>
+
<!--
Sequences for pickings
-->
<field name="padding">5</field>
</record>
+ <record id="seq_picking_delivery" model="ir.sequence">
+ <field name="name">Picking DLV</field>
+ <field name="code">stock.picking.delivery</field>
+ <field name="prefix">DLV/</field>
+ <field name="padding">5</field>
+ </record>
+
<!--
Sequences from tracking numbers
-->
<field name="date"/>
<field name="min_date"/>
<field name="state"/>
- <button name="%(partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-go-forward" help="Validate Picking"/>
+ <button name="%(action_partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-go-forward" help="Validate Picking"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel" help="Cancel" confirm="This operation will cancel the picking. Do you want to continue?"/>
</tree>
</field>
<button name="draft_validate" states="draft" string="Process Now" type="object" icon="gtk-media-play"/>
<button name="action_assign" states="confirmed" string="Check Availability" type="object" icon="gtk-find"/>
<button name="force_assign" states="confirmed" string="Force Availability" type="object" icon="gtk-jump-to"/>
- <button name="%(partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-apply"/>
+ <button name="%(action_partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-apply"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel"/>
</group>
</page>
<field name="date" select="1"/>
<field name="min_date" select="1"/>
<field name="state" select="1"/>
- <button name="%(partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-go-forward" help="Validate Delivery"/>
+ <button name="%(action_partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-go-forward" help="Validate Delivery"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel" help="Cancel" confirm="This operation will cancel the delivery. Do you want to continue?"/>
</tree>
</field>
<button name="draft_validate" states="draft" string="Process Now" type="object" icon="gtk-media-play"/>
<button name="action_assign" states="confirmed" string="Check Availability" type="object" icon="gtk-find"/>
<button name="force_assign" states="confirmed" string="Force Availability" type="object" icon="gtk-jump-to"/>
- <button name="%(partial_picking)d" states="assigned" string="Products Sent" type="action" icon="gtk-go-forward"/>
+ <button name="%(action_partial_picking)d" states="assigned" string="Products Sent" type="action" icon="gtk-go-forward"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel"/>
</group>
</page>
<field name="min_date"/>
<field name="invoice_state"/>
<field name="state"/>
- <button name="%(partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-go-forward" help="Validate Picking"/>
+ <button name="%(action_partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-go-forward" help="Validate Picking"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel" help="Cancel" confirm="This operation will cancel the picking. Do you want to continue?"/>
</tree>
</field>
<button name="draft_validate" states="draft" string="Process Now" type="object" icon="gtk-yes"/>
<button name="action_assign" states="confirmed" string="Check Availability" type="object" groups="base.group_extended" icon="gtk-apply"/>
<button name="force_assign" states="confirmed" string="Force Availability" type="object" icon="gtk-jump-to"/>
- <button name="%(partial_picking)d" states="assigned" string="Picking Done" type="action" icon="gtk-execute"/>
+ <button name="%(action_partial_picking)d" states="assigned" string="Picking Done" type="action" icon="gtk-execute"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel"/>
</group>
</page>
+ <page string="Delivery Info">
+ <field colspan="4" name="delivery_line" nolabel="1"/>
+ </page>
<page string="Notes">
<field colspan="4" name="note" nolabel="1"/>
</page>
<field name="view_mode">calendar</field>
<field name="act_window_id" ref="action_picking_tree"/>
</record>
-<!-- <menuitem action="action_picking_tree" id="menu_action_picking_tree" parent="menu_stock_root" sequence="19"/>-->
+ <menuitem action="action_picking_tree" id="menu_action_picking_tree" parent="menu_stock_warehouse_mgmt" sequence="5"/>
<record id="view_picking_in_tree" model="ir.ui.view">
<field name="name">stock.picking.in.tree</field>
<field name="min_date"/>
<field name="invoice_state"/>
<field name="state"/>
- <button name="%(partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-ok" help="Receive products"/>
+ <button name="%(action_partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-ok" help="Receive products"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel" help="Cancel" confirm="This operation will cancel the shipment. Do you want to continue?" />
</tree>
</field>
<button name="draft_validate" states="draft" string="Process Now" type="object" icon="gtk-media-play"/>
<button name="action_assign" states="confirmed" string="Check Availability" type="object" icon="gtk-find"/>
<button name="force_assign" states="confirmed" string="Force Availability" type="object" groups="base.group_extended" icon="gtk-jump-to"/>
- <button name="%(partial_picking)d" states="assigned" string="Products Received" type="action" icon="gtk-ok"/>
+ <button name="%(action_partial_picking)d" states="assigned" string="Products Received" type="action" icon="gtk-ok"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel"/>
</group>
</page>
+ <page string="Delivery Info">
+ <field colspan="4" name="delivery_line" nolabel="1"/>
+ </page>
<page string="Notes">
<field colspan="4" name="note" nolabel="1"/>
</page>
<field name="address_id"/>
<field name="picking_id"/>
<separator string="Product Delivered Information" colspan="4" />
- <field name="product_delivered" colspan="4" nolabel="1" widget="one2many" mode="tree,form">
+ <field name="move_delivered" colspan="4" nolabel="1" widget="one2many" mode="tree,form">
<tree string="Stock Moves" editable="top">
<field name="picking_id" string="Reference"/>
<field name="origin" string="Latest Requisition"/>
<field name="name"/>
<field name="date"/>
<field name="partner_id"/>
- <field name="product_delivered"/>
+ <field name="address_id"/>
</tree>
</field>
</record>
<field name="name">Delivered Products</field>
<field name="res_model">stock.delivery</field>
<field name="type">ir.actions.act_window</field>
- <field name="view_type">form</field>
- <!-- <field name="target">new</field> -->
+ <field name="view_type">form</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="view_stock_delivery_tree"/>
</record>
multi="True"
name="stock.move.split"
string="Split move line"/>
-
- <wizard
- id="partial_picking"
- model="stock.picking"
- menu="False"
- keyword="client_action_multi"
- name="stock.partial_picking"
- string="Partial picking"/>
+
<wizard
id="make_picking"
id="wizard_merge_inventory"/>
</data>
-</openerp>
\ No newline at end of file
+</openerp>
import stock_traceability
import stock_move
-import wizard_partial_picking
+import stock_partial_picking
import wizard_partial_move
import wizard_picking_make
import wizard_replacement
price = product_obj.standard_price
diff = price - new_price
if diff > 0 :
- return {'value' : {'enable_stock_in_out_acc':False}}
- else :
return {'value' : {'enable_stock_in_out_acc':True}}
+ else :
+ return {'value' : {'enable_stock_in_out_acc':False}}
def change_price(self, cr, uid, ids, context):
"""
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Change Standard Price">
- <field name="new_price" on_change="onchange_price(new_price, context)" context="{'active_id': active_id}"/>
- <newline/>
- <field name="stock_account_input" domain="[('type','<>','view'),('type','<>','consolidation')]" attrs="{'readonly':[('enable_stock_in_out_acc','=',False)],'required': [('enable_stock_in_out_acc','=',True)]}"/>
- <newline/>
- <field name="stock_account_output" domain="[('type','<>','view'),('type','<>','consolidation')]" attrs="{'readonly':[('enable_stock_in_out_acc','=',True)],'required': [('enable_stock_in_out_acc','=',False)]}"/>
- <newline/>
- <field name="stock_journal"/>
- <field name="enable_stock_in_out_acc" invisible="1"/>
- <group col="2" colspan="4">
- <button special="cancel" string="Cancel" icon="gtk-cancel"/>
- <button name="change_price" string="Change" type="object" icon="gtk-ok"/>
+ <field name="new_price"/>
+ <separator string="" colspan="4" />
+ <label string="" colspan="2"/>
+ <group col="2" colspan="2">
+ <button special="cancel" string="_Cancel" icon="gtk-cancel"/>
+ <button name="change_price" string="_Apply" type="object" icon="gtk-apply"/>
</group>
</form>
</field>
--- /dev/null
+# -*- 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_picking(osv.osv_memory):
+ _name = "stock.partial.picking"
+ _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')
+ if not context:
+ context={}
+ moveids = []
+ 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
+ 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 (pick.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_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">
+ <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']
+ for pick in pick_obj.browse(cr, uid, picking_ids, context):
+ for m in pick.move_lines:
+ 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" />
+ <field name="move%s_product_qty" />
+ <field name="move%s_product_uom" />
+ """%(m.id, m.id, m.id)
+ if (pick.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" />
+ """%(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_picking, self).default_get(cr, uid, fields, context=context)
+ pick_obj = self.pool.get('stock.picking')
+ if not context:
+ context={}
+ moveids = []
+ 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})
+ for m in pick.move_lines:
+ 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 (pick.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(pick, 'purchase_id') and pick.purchase_id:
+ currency = pick.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):
+ 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
+ }
+ for pick in pick_obj.browse(cr, uid, picking_ids):
+ for m in pick.move_lines:
+ if m.state in ('done', 'cancel'):
+ continue
+ partial_datas['move%s'%(m.id)] = {
+ 'product_id' : getattr(partial, 'move%s_product_id'%(m.id)),
+ 'product_qty' : getattr(partial, 'move%s_product_qty'%(m.id)),
+ 'product_uom' : getattr(partial, 'move%s_product_uom'%(m.id))
+ }
+
+ if (pick.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))
+ })
+
+ 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:
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <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="target">new</field>
+ </record>
+
+ </data>
+</openerp>
+++ /dev/null
-# -*- 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="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}
- }
-
-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):
- pick_obj = pooler.get_pool(cr.dbname).get('stock.picking')
- pick = pick_obj.browse(cr, uid, [data['id']], context)[0]
- res = {}
-
- _moves_fields.clear()
- #TODO: cleanup and this code..
-
- _moves_arch_lst = ['<?xml version="1.0"?>', '<form string="Make picking">']
- _moves_arch_lst.append('<field name="partner_id%d"/>' % (pick.id,))
- _moves_fields['partner_id%s' % pick.id] ={'string':'Partner',
- 'type':'many2one', 'relation':'res.partner', 'required' : '1','default': make_default(pick.address_id.partner_id.id)}
- _moves_arch_lst.append('<field name="address_id%d"/>' % (pick.id))
-
- _moves_fields['address_id%s' % pick.id] ={'string':'Delivery Address',
- 'type':'many2one', 'relation':'res.partner.address', 'required' : '1','default': make_default(pick.address_id.id)}
- _moves_arch_lst.append('<newline/>')
- _moves_arch_lst.append('<field name="date%d"/>' % (pick.id))
-
- _moves_fields['date%s' % pick.id] ={'string':'Date',
- 'type':'date', 'required' : '1','default': make_default(pick.date)}
- _moves_arch_lst.append('<newline/>')
- _moves_arch_lst.append('<separator string="Delivery Detail" colspan="4"/>')
- _moves_arch_lst.append('<label string="Product" align="0.0" />')
- _moves_arch_lst.append('<label string="Quantity" align="10.0" />')
- _moves_arch_lst.append('<label string="UOM" align="10.0" />')
- for m in pick.move_lines:
- if m.state in ('done', 'cancel'):
- continue
- quantity = m.product_qty
- if m.state!='assigned':
- quantity = 0
- _moves_fields
-
- _moves_arch_lst.append('<group colspan="6" col="3">')
- _moves_arch_lst.append('<field name="name%s" nolabel="1" />' % (m.id,))
- _moves_fields['name%s' % m.id] = {
- 'string': 'Product',
- 'type' : 'many2one', 'relation': 'product.product', 'required' : True, 'default' : make_default(m.product_id.id)}
- _moves_arch_lst.append('<field name="move%s" nolabel="1" />' % (m.id,))
- _moves_fields['move%s' % m.id] = {
- 'string': 'Quantity',
- 'type' : 'float', 'required' : True, 'default' : make_default(quantity)}
-
- _moves_arch_lst.append('<field name="uom%s" nolabel="1"/>'% (m.id,))
-
- _moves_fields['uom%s' % m.id] = {'string': 'UOM', 'type': 'many2one',
- 'relation': 'product.uom', 'readonly':True,'required': True,
- 'default': make_default(m.product_uom.id)}
-
- _moves_arch_lst.append('</group>')
- if (pick.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=0
- if hasattr(pick, 'purchase_id') and pick.purchase_id:
- currency=pick.purchase_id.pricelist_id.currency_id.id
-
- _moves_arch_lst.append('<group col="6"><field name="uom%s" nolabel="1"/>\
- <field name="price%s"/>' % (m.id,m.id,))
-
- _moves_fields['price%s' % m.id] = {'string': 'Unit Price',
- 'type': 'float', 'required': True, 'default': make_default(price)}
-
- _moves_fields['uom%s' % m.id] = {'string': 'UOM', 'type': 'many2one',
- 'relation': 'product.uom', 'required': True,
- 'default': make_default(m.product_uom.id)}
-
- _moves_arch_lst.append('<field name="currency%d" nolabel="1"/></group>' % (m.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/>')
-
-
- _moves_arch_lst.append('<newline/>')
- res.setdefault('moves', []).append(m.id)
-
- _moves_arch_lst.append('</form>')
- _moves_arch.string = '\n'.join(_moves_arch_lst)
- return res
-
-def _do_split(self, cr, uid, data, context):
- move_obj = pooler.get_pool(cr.dbname).get('stock.move')
- pick_obj = pooler.get_pool(cr.dbname).get('stock.picking')
- delivery_obj = pooler.get_pool(cr.dbname).get('stock.delivery')
- pick = pick_obj.browse(cr, uid, [data['id']])[0]
- new_picking = None
- new_moves = []
-
- complete, too_many, too_few = [], [], []
- pool = pooler.get_pool(cr.dbname)
- for move in move_obj.browse(cr, uid, data['form'].get('moves',[])):
- 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 (pick.type == 'in') and (move.product_id.cost_method == 'average'):
- product_obj = pool.get('product.product')
- currency_obj = pool.get('res.currency')
- users_obj = pool.get('res.users')
- uom_obj = pool.get('product.uom')
-
- product = product_obj.browse(cr, uid, [move.product_id.id])[0]
- user = users_obj.browse(cr, uid, [uid])[0]
-
- 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)
-
- # Write the field according to price type field
- 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 not new_picking:
-
- new_picking = pick_obj.copy(cr, uid, pick.id,
- {
- 'name': pool.get('ir.sequence').get(cr, uid, 'stock.picking.in'),
- 'move_lines' : [],
- 'state':'draft',
- })
- if data['form']['move%s' % move.id] != 0:
-
- new_obj = 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' : new_picking,
- 'state': 'assigned',
- 'move_dest_id': False,
- 'partner_id': data['form']['partner_id%s' % pick.id],
- 'address_id': data['form']['address_id%s' % pick.id],
- 'price_unit': move.price_unit,
- })
- delivery_id = delivery_obj.search(cr,uid, [('name','=',pick.name)])
- if not delivery_id :
- delivery_id = delivery_obj.create(cr, uid, {
- 'name': pick.name,
- 'partner_id': data['form']['partner_id%s' % pick.id],
- 'address_id': data['form']['address_id%s' % pick.id],
- 'date': move.date,
- 'product_delivered':[(6,0, [new_obj])],
- 'picking_id':move.picking_id.id
- }, context=context)
- if not isinstance(delivery_id, (int, long)):
- delivery_id=delivery_id[0]
- delivery_obj.write(cr, uid, [delivery_id], {'product_delivered': [(4, new_obj)]})
-
- 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],
- # 'delivered_id':delivery_id
- })
-
- if new_picking:
- move_obj.write(cr, uid, [c.id for c in complete], {'picking_id': new_picking})
- 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],
- 'picking_id': new_picking,
- })
- else:
- 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]
- })
-
- # At first we confirm the new picking (if necessary)
- wf_service = netsvc.LocalService("workflow")
- if new_picking:
- wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr)
- # Then we finish the good picking
- if new_picking:
- pick_obj.write(cr, uid, [pick.id], {'backorder_id': new_picking})
- pick_obj.action_move(cr, uid, [new_picking])
- wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_done', cr)
- wf_service.trg_write(uid, 'stock.picking', pick.id, cr)
- else:
- pick_obj.action_move(cr, uid, [pick.id])
- wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_done', cr)
- bo_name = ''
- if new_picking:
- bo_name = pick_obj.read(cr, uid, [new_picking], ['name'])[0]['name']
- return {'new_picking':new_picking or False, 'back_order':bo_name}
-
-def _get_default(self, cr, uid, data, context):
- if data['form']['back_order']:
- data['form']['back_order_notification'] = _('Back Order %s Assigned to this Picking.') % (tools.ustr(data['form']['back_order']),)
- return data['form']
-
-class partial_picking(wizard.interface):
-
- states = {
- 'init': {
- 'actions': [ _get_moves ],
- 'result': {'type': 'form', 'arch': _moves_arch, 'fields': _moves_fields,
- 'state' : (
- ('end', 'Cancel', 'gtk-cancel'),
- ('split', 'Make Picking', 'gtk-apply', True)
- )
- },
- },
- 'split': {
- 'actions': [ _do_split ],
- 'result': {'type': 'state', 'state': 'end2'},
- },
- 'end2': {
- 'actions': [ _get_default ],
- 'result': {'type': 'form', 'arch': _moves_arch_end,
- 'fields': _moves_fields_end,
- 'state': (
- ('end', 'Close'),
- )
- },
- },
- }
-
-partial_picking('stock.partial_picking')
-
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-