[MRG] merge with lp:~openerp-dev/openobject-addons/trunk-wmsimplement-seduce-fp
bzr revid: tpa@tinyerp.com-20130829131513-hc7cap7gktcl3o2n
This commit is contained in:
@@ -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 "",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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',
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,7 @@
|
||||
##############################################################################
|
||||
|
||||
import sale_stock
|
||||
import stock
|
||||
import report
|
||||
import company
|
||||
import res_config
|
||||
import wizard
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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','<>','done'),('invoice_state','<>','2binvoiced')]}" type="action" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Refund Invoice" attrs="{'invisible': ['|',('state','<>','done'),('invoice_state','<>','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>
|
||||
|
||||
@@ -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
|
||||
@@ -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, ...")
|
||||
}
|
||||
|
||||
|
||||
+12
-7
@@ -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)
|
||||
@@ -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):
|
||||
@@ -1930,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"
|
||||
|
||||
@@ -484,6 +484,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>
|
||||
@@ -497,6 +498,7 @@
|
||||
<field name="partner_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
@@ -1442,10 +1444,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>
|
||||
|
||||
|
||||
|
||||
@@ -1529,6 +1562,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"/>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
id="action_procurement_compute"/>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -21,5 +21,6 @@
|
||||
|
||||
import product
|
||||
import stock_account
|
||||
import stock
|
||||
import wizard
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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','<>','done'),('invoice_state','<>','2binvoiced')]}" type="action" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Refund Invoice" attrs="{'invisible': ['|',('state','<>','done'),('invoice_state','<>','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>
|
||||
|
||||
@@ -20,3 +20,4 @@
|
||||
##############################################################################
|
||||
|
||||
import stock_change_standard_price
|
||||
import stock_invoice_onshipping
|
||||
|
||||
@@ -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)
|
||||
@@ -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'
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user