[Merge] :lp:~openerp-dev/openobject-addons/trunk-wmsimplement-seduce-fp-inventory-form-tpa

bzr revid: sunilsharma.sharma07@gmail.com-20130902050310-ihapor6oe1fh1tcs
This commit is contained in:
Sunil Sharma (OpenERP Trainee)
2013-09-02 10:33:10 +05:30
36 changed files with 390 additions and 325 deletions
+1 -1
View File
@@ -700,7 +700,7 @@ class pos_order(osv.osv):
picking_id = picking_obj.create(cr, uid, {
'origin': order.name,
'partner_id': addr.get('delivery',False),
'type': 'out',
'picking_type_id': self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'picking_type_out', context=context).id,
'company_id': order.company_id.id,
'move_type': 'direct',
'note': order.note or "",
+1 -1
View File
@@ -213,7 +213,7 @@ class add_product(osv.osv_memory):
'name':'%s (Added)' %order_id.name,
'move_lines':[],
'state':'draft',
'type':'out',
'picking_type_id': self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'picking_type_out', context=context).id,
'date':date_cur
})
stock_move_obj.create(cr, uid, {
@@ -14,8 +14,7 @@
!record {model: product.product, id: product_product_hrmanger0}:
categ_id: product.product_category_6
mes_type: fixed
name: HR Manger
procure_method: make_to_stock
name: HR Manager
standard_price: 1.0
supply_method: buy
type: service
+9 -1
View File
@@ -150,6 +150,10 @@ class purchase_order(osv.osv):
limit=1)
return res and res[0] or False
def _get_picking_in(self, cr, uid, context=None):
obj_data = self.pool.get('ir.model.data')
return obj_data.get_object_reference(cr, uid, 'stock','picking_type_in')[1]
STATE_SELECTION = [
('draft', 'Draft PO'),
('sent', 'RFQ Sent'),
@@ -230,6 +234,7 @@ class purchase_order(osv.osv):
'journal_id': fields.many2one('account.journal', 'Journal'),
'bid_date': fields.date('Bid Received On', readonly=True, help="Date on which the bid was received"),
'bid_validity': fields.date('Bid Valid Until', help="Date on which the bid expired"),
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', help="This will determine picking type of incoming shipment"),
}
_defaults = {
'date_order': fields.date.context_today,
@@ -241,7 +246,8 @@ class purchase_order(osv.osv):
'pricelist_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').browse(cr, uid, context['partner_id']).property_product_pricelist_purchase.id,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'purchase.order', context=c),
'journal_id': _get_journal,
'currency_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
'currency_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id,
'picking_type_id': _get_picking_in,
}
_sql_constraints = [
('name_uniq', 'unique(name, company_id)', 'Order Reference must be unique per Company!'),
@@ -380,6 +386,8 @@ class purchase_order(osv.osv):
'''
This function returns an action that display existing picking orders of given purchase order ids.
'''
if context is None:
context = {}
mod_obj = self.pool.get('ir.model.data')
pick_ids = []
for po in self.browse(cr, uid, ids, context=context):
+1
View File
@@ -198,6 +198,7 @@
<field name="origin" attr="{'invisible': [('origin','=',False)]}"/>
<field name="warehouse_id" on_change="onchange_warehouse_id(warehouse_id)" widget="selection" groups="stock.group_locations"/>
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
<field name="picking_type_id"/>
</group>
</group>
<notebook>
+9 -18
View File
@@ -55,10 +55,9 @@
-
Process the reception of purchase order 1
-
!python {model: stock.partial.picking}: |
!python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average1")).picking_ids
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_partial(cr, uid, [partial_id])
self.do_partial(cr, uid, [pick_ids[0].id])
-
Check the standard price of the product (average icecream).
-
@@ -69,10 +68,9 @@
-
Process the reception of purchase order 2
-
!python {model: stock.partial.picking}: |
!python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average2")).picking_ids
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_partial(cr, uid, [partial_id])
self.do_partial(cr, uid, [pick_ids[0].id])
-
Check the standard price
-
@@ -82,7 +80,7 @@
Create picking to send some goods
-
!record {model: stock.picking, id: outgoing_average_shipment}:
type: out
picking_type_id: stock.picking_type_out
-
Create move for picking
-
@@ -91,18 +89,12 @@
product_id: product_average_icecream
product_uom: product.product_uom_kgm
product_qty: 20.0
type: out
-
I assign this outgoing shipment
I assign this outgoing shipment and process the delivery
-
!python {model: stock.picking}: |
self.action_assign(cr, uid, [ref("outgoing_average_shipment")])
-
Process the delivery of the outgoing shipment
-
!python {model: stock.partial.picking}: |
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_average_shipment")], 'default_type':'out'})
self.do_partial(cr, uid, [partial_id])
self.do_partial(cr, uid, [ref("outgoing_average_shipment")])
-
Check the standard price (60 * 10 + 30 * 80) / 40 = 75.0 did not change
-
@@ -129,10 +121,9 @@
-
Process the reception of purchase order 3 in grams
-
!python {model: stock.partial.picking}: |
!python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average3")).picking_ids
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_partial(cr, uid, [partial_id])
self.do_partial(cr, uid, [pick_ids[0].id])
-
Check price is (75.0*20 + 500) / 20.5 = 97.56097561
-
+2 -2
View File
@@ -658,7 +658,7 @@ class sale_order(osv.osv):
for order in self.browse(cr, uid, ids, context=context):
proc_ids = []
group_id = self.pool.get("procurement.group").create(cr, uid, {
'name': order.name, 'partner_id': order.partner_shipping_id.id
'name': order.name, 'partner_id': order.partner_shipping_id.id, 'move_type': order.picking_policy
}, context=context)
order.write({'procurement_group_id': group_id}, context=context)
for line in order.order_line:
@@ -1082,4 +1082,4 @@ class procurement_order(osv.osv):
_defaults = {
'invoice_state': 'none',
}
-2
View File
@@ -20,9 +20,7 @@
##############################################################################
import sale_stock
import stock
import report
import company
import res_config
import wizard
-1
View File
@@ -51,7 +51,6 @@ You can choose flexible invoicing methods:
'security/sale_stock_security.xml',
'security/ir.model.access.csv',
'company_view.xml',
'wizard/stock_invoice_onshipping_view.xml',
'sale_stock_view.xml',
'sale_stock_workflow.xml',
'stock_view.xml',
+14 -4
View File
@@ -61,7 +61,14 @@ class sale_order(osv.osv):
if move.procurement_id and move.procurement_id.sale_line_id:
res.add(move.procurement_id.sale_line_id.order_id.id)
return list(res)
def _get_orders_procurements(self, cr, uid, ids, context=None):
res = set()
for proc in self.pool.get('procurement.order').browse(cr, uid, ids, context=context):
if proc.sale_line_id:
res.add(proc.sale_line_id.order_id.id)
return list(res)
def _get_picking_ids(self, cr, uid, ids, name, args, context=None):
res = {}
for sale in self.browse(cr, uid, ids, context=context):
@@ -107,7 +114,10 @@ class sale_order(osv.osv):
('prepaid', 'Before Delivery'),
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
help="""On demand: A draft invoice can be created from the sales order when needed. \nOn delivery order: A draft invoice can be created from the delivery order when the products have been delivered. \nBefore delivery: A draft invoice is created from the sales order and must be paid before the products can be delivered."""),
'shipped': fields.function(_get_shipped, string='Delivered', type='boolean', store={'stock.move': (_get_orders, ['state'], 10)}),
'shipped': fields.function(_get_shipped, string='Delivered', type='boolean', store={
'stock.move': (_get_orders, ['state'], 10),
'procurement.order': (_get_orders_procurements, ['state'], 10)
}),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True),
'picking_ids': fields.function(_get_picking_ids, method=True, type='one2many', relation='stock.picking', string='Picking associated to this sale'),
}
@@ -223,7 +233,7 @@ class sale_order(osv.osv):
self.pool.get('sale.order.line').write(cr, uid, write_done_ids, {'state': 'done'})
if write_cancel_ids:
self.pool.get('sale.order.line').write(cr, uid, write_cancel_ids, {'state': 'exception'})
if mode == 'finished':
return finished
elif mode == 'canceled':
@@ -265,7 +275,7 @@ class sale_order(osv.osv):
class sale_order_line(osv.osv):
_inherit = 'sale.order.line'
def _number_packages(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for line in self.browse(cr, uid, ids, context=context):
-14
View File
@@ -104,21 +104,7 @@
groups="sale.group_delivery_invoice_address"
/>
<record id="view_picking_inherit_form2" model="ir.ui.view">
<field name="name">stock.picking.form.inherit</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='do_prepare_partial']" position="after">
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice" attrs="{'invisible': ['|',('state','&lt;&gt;','done'),('invoice_state','&lt;&gt;','2binvoiced')]}" type="action" class="oe_highlight" groups="base.group_user"/>
<button name="%(action_stock_invoice_onshipping)d" string="Refund Invoice" attrs="{'invisible': ['|',('state','&lt;&gt;','done'),('invoice_state','&lt;&gt;','invoiced')]}" type="action" class="oe_highlight" groups="base.group_user" context="{'inv_type': 'out_refund'}"/>
</xpath>
<xpath expr="//field[@name='move_type']" position="after">
<field name="invoice_state" groups="account.group_account_invoice"/>
</xpath>
</field>
</record>
<record id="view_picking_internal_search_inherit" model="ir.ui.view">
<field name="name">stock.picking.search.inherit</field>
-22
View File
@@ -1,22 +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 stock_invoice_onshipping
-1
View File
@@ -69,7 +69,6 @@ Dashboard / Reports for Warehouse Management will include:
'stock_data.xml',
'wizard/stock_move_view.xml',
'wizard/stock_change_product_qty_view.xml',
'wizard/stock_fill_inventory_view.xml',
'wizard/stock_inventory_merge_view.xml',
'wizard/stock_location_product_view.xml',
'wizard/stock_inventory_line_split_view.xml',
+1 -1
View File
@@ -40,7 +40,7 @@ class procurement_rule(osv.osv):
'location_id': fields.many2one('stock.location', 'Destination Location'),
'location_src_id': fields.many2one('stock.location', 'Source Location',
help="Source location is action=move"),
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', required=True,
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type',
help="Picking Type determines the way the picking should be shown in the view, reports, ...")
}
+16 -12
View File
@@ -332,7 +332,7 @@ class stock_quant(osv.osv):
def quants_unreserve(self, cr, uid, move, context=None):
#cr.execute('update stock_quant set reservation_id=NULL where reservation_id=%s', (move.id,))
#need write for related store of remaining qty
related_quants = self.search(cr, uid, [('reservation_id', '=', move.id)], context=context)
related_quants = [x.id for x in move.reserved_quant_ids]
self.write(cr, uid, related_quants, {'reservation_id': False}, context=context)
return True
@@ -530,7 +530,8 @@ class stock_picking(osv.osv):
picking_obj = self.browse(cr, uid, id, context=context)
if ('name' not in default) or (picking_obj.name == '/'):
default['name'] = '/'
default['backorder_id'] = False
if not default.get('backorder_id'):
default['backorder_id'] = False
return super(stock_picking, self).copy(cr, uid, id, default, context)
def action_confirm(self, cr, uid, ids, context=None):
@@ -1441,6 +1442,8 @@ class stock_move(osv.osv):
"""
context = context or {}
for move in self.browse(cr, uid, ids, context=context):
if move.reserved_quant_ids:
self.pool.get("stock.quant").quants_unreserve(cr, uid, move, context=context)
if move.move_dest_id:
if move.propagate:
self.action_cancel(cr, uid, [move.move_dest_id.id], context=context)
@@ -1482,7 +1485,7 @@ class stock_move(osv.osv):
# quant_obj.quants_move(cr, uid, quants, move, location_dest_id, context=context)
# should replace the above 2 lines
domain = ['|', ('reservation_id', '=', False), ('reservation_id', '=', move.id)]
prefered_order = 'reservation_id<>' + str(move.id)
prefered_order = 'reservation_id <> ' + str(move.id)
# if lot_id:
# prefered_order = 'lot_id<>' + lot_id + ", " + prefered_order
# if pack_id:
@@ -1615,10 +1618,9 @@ class stock_move(osv.osv):
return res
def split(self, cr, uid, move, qty, context=None):
""" Partially (or not) moves a stock.move.
@param partial_datas: Dictionary containing details of partial picking
like partner_id, delivery_date, delivery
moves with product_id, product_qty, uom
"""
Splits qty from move move into a new move
It will check if it can propagate the split
"""
if move.product_qty==qty:
return move.id
@@ -1647,6 +1649,9 @@ class stock_move(osv.osv):
'product_uos_qty': move.product_uos_qty - uos_qty,
# 'reserved_quant_ids': [(6,0,[])] SHOULD NOT CHANGE as it has been reserved already
}, context=context)
if move.move_dest_id and move.propagate:
self.split(self, cr, uid, move.move_dest_id, qty, context=context)
return new_move
class stock_inventory(osv.osv):
@@ -1722,6 +1727,7 @@ class stock_inventory(osv.osv):
for inv in self.browse(cr, uid, ids, context=context):
if not inv.move_ids:
self.action_check(cr, uid, [inv.id], context=context)
inv.refresh()
move_obj.action_done(cr, uid, [x.id for x in inv.move_ids], context=context)
self.write(cr, uid, [inv.id], {'state': 'done', 'date_done': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
return True
@@ -1784,7 +1790,7 @@ class stock_inventory(osv.osv):
#TODO test
self.action_cancel_draft(cr, uid, ids, context=context)
def _prepare_inventory(self, cr, uid, ids, full_of_zeros=False, context=None):
def prepare_inventory(self, cr, uid, ids, context=None):
inventory_line_obj = self.pool.get('stock.inventory.line')
for inventory in self.browse(cr, uid, ids, context=context):
#clean the existing inventory lines before redoing an inventory proposal
@@ -1793,8 +1799,6 @@ class stock_inventory(osv.osv):
#compute the inventory lines and create them
vals = self._get_inventory_lines(cr, uid, inventory, context=context)
for product_line in vals:
if full_of_zeros:
product_line['product_qty'] = 0
inventory_line_obj.create(cr, uid, product_line, context=context)
return self.write(cr, uid, ids, {'state': 'confirm'})
@@ -1843,7 +1847,7 @@ class stock_inventory_line(osv.osv):
'company_id': fields.related('inventory_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, select=True, readonly=True),
'prod_lot_id': fields.many2one('stock.production.lot', 'Serial Number', domain="[('product_id','=',product_id)]"),
'state': fields.related('inventory_id', 'state', type='char', string='Status', readonly=True),
'real_qty':fields.related('product_id','qty_available', type='float', string='Real Quantity', store=True),
'real_qty':fields.related('product_id','qty_available', type='float', string='Real Quantity'),
}
def _resolve_inventory_line(self, cr, uid, inventory_line, theorical_lines, context=None):
@@ -1931,7 +1935,7 @@ report_sxw.report_sxw('report.stock.quant.package.barcode', 'stock.quant.package
class stock_package(osv.osv):
"""
These are the packages, containing quants and/or others packages
These are the packages, containing quants and/or other packages
"""
_name = "stock.quant.package"
_description = "Physical Packages"
+59 -38
View File
@@ -101,65 +101,52 @@
<field name="arch" type="xml">
<form string="Physical Inventory" version="7.0">
<header>
<button name="%(action_view_stock_fill_inventory)d" states="draft" string="Start Inventory" type="action" class="oe_highlight" groups="stock.group_stock_user"/>
<button name="prepare_inventory" states="draft" string="Start Inventory" type="object" class="oe_highlight" groups="stock.group_stock_user"/>
<button name="action_done" states="confirm" string="Validate Inventory" type="object" class="oe_highlight" groups="stock.group_stock_manager"/>
<button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object"/>
<button name="action_cancel_inventory" states="draft,confirm,done" string="Cancel Inventory" type="object"/>
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,done"/>
</header>
<sheet>
<div class="oe_right oe_button_box">
<button name="action_check" string="Check Inventory Adjustments" states="draft,confirm" type="object" />
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name" placeholder="e.g. Annual inventory"/></h1>
</div>
<group>
<group>
<field name="location_id"/>
</group>
<group>
<field name="date"/>
</group>
<div class="oe_grey" colspan="4">Specify filters to focus your inventory a on particular product, lot, pack and products owner</div>
<group>
<field name="product_id"/>
<field name="lot_id"/>
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
</group>
<group>
<field name="date"/>
<field name="partner_id"/>
<field name="package_id"/>
</group>
</group>
<field name="move_ids_exist" invisible="1"/>
<notebook>
<page string="Inventory Details" attrs="{'invisible':[('state','=','draft')]}">
<button name="set_checked_qty" states="confirm" icon="gtk-go-forward" string="Set Checked Quantity to 0" type="object" class="oe_link oe_right" groups="stock.group_stock_user"/>
<field name="line_ids" string="Inventory Details">
<tree string="Inventory Details" editable="bottom" colors="blue: product_qty != real_qty">
<field context="{'location':location_id, 'uom':product_uom_id, 'to_date':parent.date}" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom_id,parent.date)" domain="[('type','=','product')]"/>
<field name="real_qty" readonly="1"/>
<field name="product_qty" string="Checked Quantity"/>
<field name="product_uom_id" groups="product.group_uom"/>
<field name="prod_lot_id"/>
<field name="package_id" readonly="1"/>
<field domain="[('usage','=','internal')]" name="location_id" groups="stock.group_locations"/>
<field name="state" invisible="True"/>
</tree>
</field>
</page>
<page string="Inventory Adjustments" attrs="{'invisible': [('move_ids_exist', '=', False)],'invisible': [('state','=','draft')] }">
<field name="move_ids" context="{'inventory_id':active_id}" readonly="1">
<tree string="Inventory Adjustments">
<field name="product_id"/>
<field name="lot_ids"/>
<field name="product_uom_qty" on_change="onchange_quantity(product_id, product_uom_qty, product_uom, product_uos)"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="state" invisible="True"/>
</tree>
</field>
</page>
<notebook attrs="{'invisible':[('state','=','draft')]}">
<page string="Inventory Details" >
<button name="set_checked_qty" states="confirm" icon="gtk-go-forward" string="Set Checked Quantity to 0" type="object" class="oe_link oe_right" groups="stock.group_stock_user"/>
<field name="line_ids" string="Inventory Details">
<tree string="Inventory Details" editable="bottom" colors="blue: product_qty != real_qty">
<field context="{'location':location_id, 'uom':product_uom_id, 'to_date':parent.date}" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom_id,parent.date)" domain="[('type','=','product')]"/>
<field name="real_qty" readonly="1"/>
<field name="product_qty" string="Checked Quantity"/>
<field name="product_uom_id" groups="product.group_uom"/>
<field name="prod_lot_id"/>
<field name="package_id" readonly="1"/>
<field domain="[('usage','=','internal')]" name="location_id" groups="stock.group_locations"/>
<field name="state" invisible="True"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</sheet>
</form>
</field>
</record>
@@ -495,6 +482,7 @@
<field name="model">stock.warehouse</field>
<field name="arch" type="xml">
<form string="Warehouse" version="7.0">
<sheet>
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
<group>
@@ -508,6 +496,7 @@
<field name="partner_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
@@ -1453,10 +1442,41 @@
<field name="location_src_id"/>
<field name="location_id"/>
<field name="action"/>
<field name="picking_type_id"/>
<field name="picking_type_id" attrs="{'required': [('action', '!=', 'manufacture')]}"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_procurement_rule_form">
<field name="name">stock.procurement.form</field>
<field name="model">procurement.rule</field>
<field eval="10" name="priority"/>
<field name="arch" type="xml">
<form string="Procurement Rules" version="7.0">
<sheet>
<div class="oe_title">
<h1>
<label string="Name"/>
<field name="name" class="oe_inline"/>
</h1>
</div>
<group>
<group>
<field name="location_src_id"/>
<field name="location_id"/>
</group>
<group>
<field name="action"/>
<field name="picking_type_id" attrs="{'required': [('action', '!=', 'manufacture')]}"/>
<field name="group_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
@@ -1540,6 +1560,7 @@
<!-- Procurements are located in Warehouse menu hierarchy, MRP users should come to Stock application to use it. -->
<menuitem id="menu_stock_sched" name="Schedulers" parent="stock.menu_stock_root" sequence="4" groups="stock.group_stock_manager"/>
<menuitem action="action_procurement_compute" id="menu_procurement_compute" parent="menu_stock_sched" groups="stock.group_stock_manager"/>
<menuitem action="procurement.action_compute_schedulers" id="menu_stock_proc_schedulers" parent="menu_stock_sched" sequence="20" groups="stock.group_stock_manager"/>
<menuitem action="procurement.procurement_exceptions" id="menu_stock_procurement_action" parent="menu_stock_sched" sequence="50" groups="stock.group_stock_manager"/>
<menuitem id="menu_stock_procurement" name="Automatic Procurements" parent="stock.menu_stock_configuration" sequence="5"/>
+34 -40
View File
@@ -1,24 +1,32 @@
-
I create an inventory of 10 products
I create an inventory
-
!record {model: stock.inventory, id: inventory_test0}:
name: Test
inventory_line_id:
- product_id: product.product_product_3
product_qty: 10
location_id: stock.stock_location_14
-
I post this inventory
I start this inventory
-
!python {model: stock.inventory}: |
self.prepare_inventory(cr, uid, [ref('inventory_test0')], context=context)
-
I create an inventory line with 10 product
-
!record {model: stock.inventory.line, id: inventory_testline0}:
inventory_id: stock.inventory_test0
product_id: product.product_product_3
product_qty: 10
location_id: stock.stock_location_14
-
I Validate this inventory
-
!python {model: stock.inventory}: |
self.action_confirm(cr, uid, [ref('inventory_test0')], context=context)
self.action_done(cr, uid, [ref('inventory_test0')], context=context)
-
I check that this inventory has a stock.move and a quant
-
!python {model: stock.inventory}: |
inv = self.browse(cr, uid, ref('inventory_test0'), context=context)
assert len(inv.move_ids) == 1, "No move created for the inventory."
assert len(inv.move_ids) >= 1, "No move created for the inventory."
assert len(inv.move_ids[0].quant_ids) >= 1, "No quant created for this inventory"
-
I check that the quantity on hand is 10 on the location and it's parent.
@@ -38,46 +46,32 @@
product = self.browse(cr, uid, ref('product.product_product_3'), context=context)
assert product.qty_available==0, 'Expecting 0 products, got %.2f on location stock_location_components!' % (product.qty_available,)
-
I create an inventory of 20 products
I create another inventory
-
!record {model: stock.inventory, id: inventory_test1}:
name: Test
inventory_line_id:
- product_id: product.product_product_3
product_qty: 20
location_id: stock.stock_location_14
name: Test2
-
I post this new inventory
I start this inventory
-
!python {model: stock.inventory}: |
self.prepare_inventory(cr, uid, [ref('inventory_test1')], context=context)
-
I create an inventory line with 20 product on this new inventory
-
!record {model: stock.inventory.line, id: inventory_testline0}:
inventory_id: stock.inventory_test1
product_id: product.product_product_3
product_qty: 20
location_id: stock.stock_location_components
-
I Validate this inventory
-
!python {model: stock.inventory}: |
self.action_confirm(cr, uid, [ref('inventory_test1')], context=context)
self.action_done(cr, uid, [ref('inventory_test1')], context=context)
-
I check that the quantity on hand is 20 on the location and it's parent.
-
!python {model: product.product}: |
context['location'] = ref('stock.stock_location_14')
context['location'] = ref('stock.stock_location_components')
product = self.browse(cr, uid, ref('product.product_product_3'), context=context)
assert product.qty_available==20, 'Expecting 20 products, got %.2f on location stock_location_14!' % (product.qty_available,)
-
!record {model: stock.inventory, id: inventory_test2}:
name: Test
inventory_line_id:
- product_id: product.product_product_3
product_qty: 18
location_id: stock.stock_location_14
-
I post this new inventory
-
!python {model: stock.inventory}: |
self.action_confirm(cr, uid, [ref('inventory_test2')], context=context)
self.action_done(cr, uid, [ref('inventory_test2')], context=context)
-
I check that the quantity on hand is 18 on the location and it's parent.
-
!python {model: product.product}: |
context['location'] = ref('stock.stock_location_14')
product = self.browse(cr, uid, ref('product.product_product_3'), context=context)
assert product.qty_available==18, 'Expecting 18 products, got %.2f on location stock_location_14!' % (product.qty_available,)
assert product.qty_available==20, 'Expecting 20 products, got %.2f on location stock_location_components!' % (product.qty_available,)
-1
View File
@@ -21,7 +21,6 @@
import stock_move
import stock_inventory_merge
import stock_fill_inventory
import stock_inventory_line_split
import stock_location_product
import stock_return_picking
@@ -31,6 +31,7 @@
target="new"
key2="client_action_multi"
id="action_procurement_compute"/>
</data>
</openerp>
@@ -1,51 +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/>.
#
##############################################################################
from openerp.osv import fields, osv
class stock_fill_inventory(osv.osv_memory):
_name = "stock.fill.inventory"
_description = "Import Inventory"
_columns = {
'set_stock_zero': fields.boolean("Set to zero", help="If checked, all product quantities will be set to zero to help ensure a real physical inventory is done"),
}
def fill_inventory(self, cr, uid, ids, context=None):
""" To Import stock inventory according to products available in the selected locations.
@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:
"""
if context is None:
context = {}
inventory_obj = self.pool.get('stock.inventory')
if ids and len(ids):
ids = ids[0]
fill_inventory = self.browse(cr, uid, ids, context=context)
inventory_obj._prepare_inventory(cr, uid, context.get('active_ids', []), fill_inventory.set_stock_zero, context=context)
return {'type': 'ir.actions.act_window_close'}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_stock_fill_inventory" model="ir.ui.view">
<field name="name">Import Inventory</field>
<field name="model">stock.fill.inventory</field>
<field name="arch" type="xml">
<form string="Import Inventory" version="7.0">
<separator string="Import the current inventory"/>
<group>
<field name="set_stock_zero"/>
</group>
<footer>
<button name="fill_inventory" string="Fill Inventory" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="action_view_stock_fill_inventory" model="ir.actions.act_window">
<field name="name">Fill Inventory</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">stock.fill.inventory</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_stock_fill_inventory"/>
<field name="target">new</field>
</record>
</data>
</openerp>
+1
View File
@@ -21,5 +21,6 @@
import product
import stock_account
import stock
import wizard
+1
View File
@@ -49,6 +49,7 @@ Dashboard / Reports for Warehouse Management will include:
'data': [
'stock_account_data.xml',
'wizard/stock_change_standard_price_view.xml',
'wizard/stock_invoice_onshipping_view.xml',
'product_data.xml',
'product_view.xml',
'stock_account_view.xml',
+6
View File
@@ -34,6 +34,12 @@ import openerp.addons.decimal_precision as dp
import logging
_logger = logging.getLogger(__name__)
#----------------------------------------------------------
# Invoice state
#----------------------------------------------------------
#----------------------------------------------------------
# Stock Location
@@ -16,5 +16,21 @@
</field>
</record>
<record id="view_picking_inherit_form2" model="ir.ui.view">
<field name="name">stock.picking.form.inherit</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='do_prepare_partial']" position="after">
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice" attrs="{'invisible': ['|',('state','&lt;&gt;','done'),('invoice_state','&lt;&gt;','2binvoiced')]}" type="action" class="oe_highlight" groups="base.group_user"/>
<button name="%(action_stock_invoice_onshipping)d" string="Refund Invoice" attrs="{'invisible': ['|',('state','&lt;&gt;','done'),('invoice_state','&lt;&gt;','invoiced')]}" type="action" class="oe_highlight" groups="base.group_user" context="{'inv_type': 'out_refund'}"/>
</xpath>
<xpath expr="//field[@name='move_type']" position="after">
<field name="invoice_state" groups="account.group_account_invoice"/>
</xpath>
</field>
</record>
</data>
</openerp>
+1
View File
@@ -20,3 +20,4 @@
##############################################################################
import stock_change_standard_price
import stock_invoice_onshipping
+6 -1
View File
@@ -38,7 +38,12 @@ This adds a route on the sales order and sales order line (mini module)
'init_xml': [],
'update_xml': ['stock_complex_routes.xml'],
'demo_xml': [],
'test': ['test/lifo_price.yml'],
'test': [
'test/crossdock.yml',
'test/dropship.yml',
'test/procurementexception.yml',
'test/lifo_price.yml'
],
'installable': True,
'auto_install': True,
}
@@ -0,0 +1,37 @@
-
Create new product without any routes
-
!record {model: product.product, id: cross_shop_product}:
name: PCE
type: product
categ_id: product.product_category_1
list_price: 100.0
standard_price: 70.0
seller_ids:
- delay: 1
name: base.res_partner_2
min_qty: 2.0
qty: 5.0
type: product
uom_id: product.product_uom_unit
uom_po_id: product.product_uom_unit
-
Create a sales order with a line of 100 PCE incoming shipment, with route_id crossdock shipping.
-
!record {model: sale.order, id: sale_order_crossdock_shpng}:
partner_id: base.res_partner_4
note: Create Sales order
order_line:
- product_id: cross_shop_product
product_uom_qty: 100.00
route_id: stock_location.route_warehouse0_crossdock
-
Confirm sales order
-
!workflow {model: sale.order, action: order_confirm, ref: sale_order_crossdock_shpng}
-
Check a quotation was created to a certain supplier and confirm so it becomes a confirmed purchase order
-
!python {model: purchase.order}: |
po_id = self.search(cr, uid, [('partner_id', '=', ref('base.res_partner_2'))])
self.wkf_confirm_order(cr, uid, po_id)
+55 -40
View File
@@ -1,53 +1,68 @@
-
Create new product without any routes
Create new product without any routes
-
!record {model:product.product, id:}
!record {model: product.product, id: drop_shop_product}:
name: Pen drive
type: product
categ_id: product.product_category_1
list_price: 100.0
standard_price: 70.0
seller_ids:
- delay: 1
name: base.res_partner_2
min_qty: 2.0
qty: 5.0
uom_id: product.product_uom_unit
uom_po_id: product.product_uom_unit
-
Create a sales order with a line of 200 PCE incoming shipment, with route_id drop shipping
Create a sales order with a line of 200 PCE incoming shipment, with route_id drop shipping.
-
!record {model: sale.order, id: } :
customer:
- product_id:
product_qty: 200
product_uom:
supplier_ids:
!record {model: sale.order, id: sale_order_drp_shpng}:
partner_id: base.res_partner_2
note: Create sale order for drop shipping
payment_term: account.account_payment_term
order_line:
- product_id: drop_shop_product
product_uom_qty: 200
price_unit: 100.00
route_id: route_drop_shipping
-
Confirm sales order
Confirm sales order
-
!python{model: sale.order}: |
self.browse(cr, uid, ref()).action_b
!workflow {model: sale.order, action: order_confirm, ref: sale_order_drp_shpng}
-
Check the sales order created a procurement group which has a procurement of 200 pieces
Check the sales order created a procurement group which has a procurement of 200 pieces
-
!python{model: procurement.group}: |
proc_group = self.search(cr, uid, [('sale_id', '=', ref())])
assert self.browse(cr, uid, proc_group)[0].procurement_ids[0].product_qty == 200
!python {model: procurement.group}: |
sale_record = self.pool.get("sale.order").browse(cr, uid, ref('sale_order_drp_shpng'))
assert self.browse(cr, uid, sale_record.procurement_group_id.id).procurement_ids[0].product_qty == 200
-
Check a quotation was created to a certain supplier and confirm so it becomes a confirmed purchase order
Check a quotation was created to a certain supplier and confirm so it becomes a confirmed purchase order
-
!python {model: purchase.order}: |
from openerp import netsvc
sale_record = self.pool.get("sale.order").browse(cr, uid, ref('sale_order_drp_shpng'))
procurement_order = self.pool.get("procurement.group").browse(cr, uid, sale_record.procurement_group_id.id).procurement_ids[0]
purchase_id = procurement_order.purchase_id.id
wf_service = netsvc.LocalService('workflow')
wf_service.trg_validate(uid, 'purchase.order', purchase_id, 'purchase_confirm', cr)
-
Use 'Receive Products' button to immediately view this picking, it should have created a picking with 200 pieces..
-
!python {model: purchase.order}: |
po_id = self.search(cr, uid, [('partner_id', '=', ref('base.res_partner_2'))])
self.view_picking(cr, uid, po_id)
-
Send the 200 pieces.
-
Check the sales order has one picking with 200 pieces
!python {model: stock.picking}: |
po_id = self.pool.get('purchase.order').search(cr, uid, [('partner_id', '=', ref('base.res_partner_2'))])
picking_id = self.search(cr, uid, [('purchase_id', '=', po_id[0])])
self.do_partial(cr, uid, picking_id)
-
!python{model: sale.order}: |
assert len(self.browse(cr, uid, ref()).picking_ids) == 1
Check one quant was created in Customers location with 200 pieces and one move in the history_ids
-
Use 'View Delivery Order' button to immediately view this picking and check shipped of purchase order is False
-
-
Send the 200 pieces
-
!python{model: stock.partial.picking}: |
-
Check one quant was created in Customers location with 200 pieces and one move in the move_history_ids
-
-
Check the sum of the moves related to this product and the sum of the quants is equal
-
!python {model: stock.quant}: |
quant_id = self.search(cr, uid, [('location_id', '=', ref('stock.stock_location_customers')),('qty', '=', 200)])
assert len(self.browse(cr, uid, quant_id)[0].history_ids) == 1
assert len(quant_id) == 1
@@ -1,37 +1,63 @@
-
Create product with no seller_ids
-
-
Create a sales order with 1 piece for that product and route crossdock
-
!record{sale.order}
-
Confirm sales order
-
!python {
-
Check there is a procurement in exception that has the procurement group of the sales order
-
!python {
assert
-
Adjust the product that it has at least one seller_id
-
!record{id: model: product.product) or in !python
-
Run the Scheduler
-
!python
-
Check the status changed there is no procurement order in exception any more from that procurement group
-
!python{model: procurement.order}
search procurement from
-
Check a purchase quotation was created
-
I create a product with no supplier define for it.
-
!record {model: product.product, id: product_with_no_seller}:
name: 'product with no seller'
list_price: 20.00
standard_price: 15.00
categ_id: product.product_category_1
-
I create a sales order with this product with route crossdock.
-
!record {model: sale.order, id: sale_order_route_crossdock}:
partner_id: base.res_partner_2
partner_invoice_id: base.res_partner_address_3
partner_shipping_id: base.res_partner_address_3
note: crossdock route
payment_term: account.account_payment_term
order_line:
- product_id: product_with_no_seller
product_uom_qty: 1
route_id: stock_location.route_warehouse0_crossdock
-
I confirm the sales order.
-
!workflow {model: sale.order, ref: sale_order_route_crossdock, action: order_confirm}
-
I check there is a procurement in exception that has the procurement group of the sales order created before.
-
!python {model: procurement.order}: |
self.run_scheduler(cr, uid)
sale_id = self.pool.get('sale.order').browse(cr, uid, ref("sale_order_route_crossdock"))
proc_id = self.search(cr, uid, [('group_id.name', '=', sale_id.name), ('state', '=', 'exception')])
assert proc_id, 'No Procurement!'
-
I set the at least one supplier on the product.
-
!record {model: product.product, id: product_with_no_seller}:
seller_ids:
- delay: 1
name: base.res_partner_2
min_qty: 2.0
-
I run the Procurement.
-
!python {model: procurement.order}: |
sale_id = self.pool.get('sale.order').browse(cr, uid, ref("sale_order_route_crossdock"))
proc_id = self.search(cr, uid, [('group_id.name', '=', sale_id.name), ('state', '=', 'exception')])
self.run(cr, uid, proc_id)
-
I check the status changed there is no procurement order in exception any more from that procurement group
-
!python {model: procurement.order}: |
sale_id = self.pool.get('sale.order').browse(cr, uid, ref("sale_order_route_crossdock"))
proc_id = self.search(cr, uid, [('group_id.name', '=', sale_id.name), ('state', '=', 'exception')])
assert not proc_id, 'Procurement should be in running state'
-
I check a purchase quotation was created.
-
!python {model: procurement.order}: |
sale_id = self.pool.get('sale.order').browse(cr, uid, ref("sale_order_route_crossdock"))
proc_ids = self.search(cr, uid, [('group_id.name', '=', sale_id.name)])
purchase_id = [proc.purchase_id for proc in self.browse(cr, uid, proc_ids) if proc.purchase_id]
assert purchase_id, 'No Purchase Quotation is created'
+10 -1
View File
@@ -28,20 +28,29 @@ class stock_location_route(osv.osv):
_name = 'stock.location.route'
_description = "Inventory Routes"
_order = 'sequence'
def _default_warehouse(self, cr, uid, context=None):
user = self.pool.get('res.users').browse(cr, uid, uid, context)
res = self.pool.get('stock.warehouse').search(cr, uid, [('company_id', '=', user.company_id.id)], limit=1, context=context)
return res and res[0] or False
_columns = {
'name': fields.char('Route Name', required=True),
'sequence': fields.integer('Sequence'),
'pull_ids': fields.one2many('procurement.rule', 'route_id', 'Pull Rules'),
'push_ids': fields.one2many('stock.location.path', 'route_id', 'Push Rules'),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
}
_defaults = {
'sequence': lambda self,cr,uid,ctx: 0,
'warehouse_id': _default_warehouse,
}
class stock_warehouse(osv.osv):
_inherit = 'stock.warehouse'
_columns = {
'route_id': fields.many2one('stock.location.route', 'Default Logistic Route', help='Default route through the warehouse', required=True),
'route_ids': fields.one2many('stock.location.route', 'warehouse_id', 'All Routes'),
}
@@ -60,7 +69,7 @@ class stock_location_path(osv.osv):
("2binvoiced", "To Be Invoiced"),
("none", "Not Applicable")], "Invoice Status",
required=True,),
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', help="This is the picking type associated with the different pickings"),
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', required=True, help="This is the picking type associated with the different pickings"),
'auto': fields.selection(
[('auto','Automatic Move'), ('manual','Manual Operation'),('transparent','Automatic No Step Added')],
'Automatic Move',
+44 -2
View File
@@ -2,6 +2,26 @@
<openerp>
<data>
<record model="ir.ui.view" id="view_procurement_rule_form_inherit">
<field name="name">stock.procurement.rule.inherit.form</field>
<field name="model">procurement.rule</field>
<field name="inherit_id" ref="stock.view_procurement_rule_form"/>
<field name="arch" type="xml">
<field name="location_id" position="after">
<field name="route_id"/>
<field name="route_sequence"/>
<field name="sequence"/>
<field name="delay"/>
<field name="propagate"/>
</field>
<field name="group_id" position="before">
<field name="procure_method"/>
<field name="invoice_state"/>
<field name="partner_address_id"/>
</field>
</field>
</record>
<record id="view_location_form_inherit" model="ir.ui.view">
<field name="name">stock.location.form</field>
@@ -137,6 +157,14 @@
<xpath expr="//field[@name='partner_id']" position="after">
<field name="route_id"/>
</xpath>
<xpath expr="//group[last()]" position="after">
<separator string="All Associated Routes"/>
<field name="route_ids" nolabel="1" colspan="4">
<tree string="All Routes">
<field name="name"/>
</tree>
</field>
</xpath>
</field>
</record>
@@ -147,6 +175,7 @@
<tree string="Routes">
<field name="sequence" widget="handle" />
<field name="name"/>
<field name="warehouse_id"/>
</tree>
</field>
</record>
@@ -159,6 +188,7 @@
<form string="Route">
<field name="name" />
<field name="sequence" groups="base.group_no_one"/>
<field name="warehouse_id"/>
<group string="Push Rules" colspan="4" >
<field name="push_ids" colspan="4" nolabel="1"/>
</group>
@@ -182,8 +212,8 @@
</p>
<p>You can define here the main logistic routes that run through
your warehouses and that define the flows of your products. These
routes can be assigned to a product, a product category or on a
location.</p>
routes can be assigned to a product, a product category or be fixed
on procurement or sales order. </p>
</field>
</record>
@@ -191,5 +221,17 @@
<menuitem action="action_routes_form" id="menu_stock_routes"
parent="stock.menu_stock_configuration" sequence="11" />
<!-- Procurement -->
<record id="procurement_form_view_inherit" model="ir.ui.view">
<field name="name">procurement.order.form.view.inherit</field>
<field name="inherit_id" ref="procurement.procurement_form_view"/>
<field name="model">procurement.order</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='rule_id']" position="after">
<field name="route_ids" widget="many2many_tags"/>
</xpath>
</field>
</record>
</data>
</openerp>
@@ -32,9 +32,11 @@
- invoice_state: none
location_dest_id: stock_location.stock_location_qualitytest0
location_from_id: stock.stock_location_stock
picking_type_id: stock.picking_type_internal
- invoice_state: none
location_dest_id: stock.stock_location_components
location_from_id: stock_location.stock_location_qualitytest0
picking_type_id: stock.picking_type_internal
-
!record {model: product.product, id: product_product_hpcdwriters01}:
list_price: 1000.0