[MRG] merge wit main branch.
bzr revid: tpa@tinyerp.com-20130903053254-clkr9xcmbg3m7dt7
This commit is contained in:
commit
e3cabe1da5
|
@ -195,6 +195,7 @@
|
|||
product_qty: 1.0
|
||||
product_uom: product.product_uom_unit
|
||||
location_dest_id: stock.stock_location_customers
|
||||
invoice_state: 2binvoiced
|
||||
move_type: direct
|
||||
picking_type_id: stock.picking_type_out
|
||||
-
|
||||
|
|
|
@ -197,18 +197,19 @@
|
|||
product_id: product_fifo_anglo_saxon
|
||||
product_qty: 1.0
|
||||
location_dest_id: stock.stock_location_customers
|
||||
invoice_state: 2binvoiced
|
||||
move_type: direct
|
||||
picking_type_id: stock.picking_type_out
|
||||
-
|
||||
I need to check the availability of the product, So I make my picking order for processing later.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
self.action_confirm(cr, uid, [ref('stock_picking_out001')], context=context)
|
||||
self.action_confirm(cr, uid, [ref('stock_picking_out001_fifo')], context=context)
|
||||
-
|
||||
I check the product availability, Product is available in the stock and ready to be sent.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.browse(cr, uid, ref("stock_picking_out001"))
|
||||
picking = self.browse(cr, uid, ref("stock_picking_out001_fifo"))
|
||||
assert picking.state == "confirmed", "Picking should be confirmed."
|
||||
for move_line in picking.move_lines:
|
||||
assert move_line.state == "confirmed", "Move should be confirmed."
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
!python {model: procurement.order}: |
|
||||
self.run_scheduler(cr, uid)
|
||||
-
|
||||
I check that procurement order is done
|
||||
I check that procurement order is in exception, as at first there isn't any suitable rule
|
||||
-
|
||||
!python {model: procurement.order}: |
|
||||
proc_order = self.browse(cr, uid, ref('procurement_order0'), context=context)
|
||||
assert proc_order.state == 'done'
|
||||
assert proc_order.state == 'exception'
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
</record>
|
||||
|
||||
<record id="stock_picking_in_inherit_purchase" model="ir.ui.view">
|
||||
<field name="name">Incoming Picking Inherited</field>
|
||||
<field name="name">Picking Inherited</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='date']" position="before">
|
||||
<field name="purchase_id" domain="[('invoice_method','=','picking')]" context="{'search_default_partner_id':partner_id,'default_partner_id':partner_id, 'default_invoice_method':'picking'}"/>
|
||||
<xpath expr="//field[@name='move_type']" position="before">
|
||||
<field name="purchase_id" domain="[('invoice_method','=','picking')]" groups="base.group_no_one" context="{'search_default_partner_id':partner_id,'default_partner_id':partner_id, 'default_invoice_method':'picking'}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='company_id']" position="after">
|
||||
<field name="warehouse_id" groups="stock.group_locations"/>
|
||||
|
|
|
@ -6,13 +6,8 @@
|
|||
!record {model: procurement.order, id: procurement_order_testcase0}:
|
||||
location_id: stock.stock_location_stock
|
||||
name: Test scheduler for RFQ
|
||||
procure_method: make_to_order
|
||||
product_id: product.product_product_45
|
||||
product_qty: 15.0
|
||||
-
|
||||
I confirm on procurement order.
|
||||
-
|
||||
!workflow {model: procurement.order, action: button_confirm, ref: procurement_order_testcase0}
|
||||
-
|
||||
I run the scheduler.
|
||||
-
|
||||
|
|
|
@ -1072,14 +1072,5 @@ class procurement_order(osv.osv):
|
|||
_inherit = 'procurement.order'
|
||||
_columns = {
|
||||
'sale_line_id': fields.many2one('sale.order.line', string='Sale Order Line'),
|
||||
'invoice_state': fields.selection(
|
||||
[
|
||||
("invoiced", "Invoiced"),
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")
|
||||
], "Invoice Control", required=True),
|
||||
}
|
||||
_defaults = {
|
||||
'invoice_state': 'none',
|
||||
}
|
||||
|
|
@ -168,11 +168,12 @@ class sale_order(osv.osv):
|
|||
# if order_policy<>picking: super()
|
||||
# else: call invoice_on_picking_method()
|
||||
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_invoice = False, context=None):
|
||||
picking_obj = self.pool.get('stock.picking')
|
||||
move_obj = self.pool.get("stock.move")
|
||||
res = super(sale_order,self).action_invoice_create(cr, uid, ids, grouped=grouped, states=states, date_invoice = date_invoice, context=context)
|
||||
for order in self.browse(cr, uid, ids, context=context):
|
||||
if order.order_policy == 'picking':
|
||||
picking_obj.write(cr, uid, map(lambda x: x.id, order.picking_ids), {'invoice_state': 'invoiced'})
|
||||
for picking in order.picking_ids:
|
||||
move_obj.write(cr, uid, [x.id for x in picking.move_lines], {'invoice_state': 'invoiced'}, context=context)
|
||||
return res
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -90,7 +90,9 @@ Dashboard / Reports for Warehouse Management will include:
|
|||
'test': [
|
||||
'test/inventory.yml',
|
||||
'test/move.yml',
|
||||
# 'test/shipment.yml',
|
||||
'test/procrule.yml',
|
||||
'test/shipment.yml',
|
||||
'test/packing.yml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
|
|
|
@ -208,6 +208,7 @@ class product_product(osv.osv):
|
|||
'track_outgoing': fields.boolean('Track Outgoing Lots', help="Forces to specify a Serial Number for all moves containing this product and going to a Customer Location"),
|
||||
'location_id': fields.dummy(string='Location', relation='stock.location', type='many2one'),
|
||||
'warehouse_id': fields.dummy(string='Warehouse', relation='stock.warehouse', type='many2one'),
|
||||
'orderpoint_ids': fields.one2many('stock.warehouse.orderpoint', 'product_id', 'Minimum Stock Rules'),
|
||||
}
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
|
@ -258,6 +259,7 @@ class product_template(osv.osv):
|
|||
_name = 'product.template'
|
||||
_inherit = 'product.template'
|
||||
_columns = {
|
||||
'type': fields.selection([('product', 'Stockable Product'), ('consu', 'Consumable'), ('service', 'Service')], 'Product Type', required=True, help="Consumable: Will not imply stock management for this product. \nStockable product: Will imply stock management for this product."),
|
||||
'property_stock_procurement': fields.property(
|
||||
type='many2one',
|
||||
relation='stock.location',
|
||||
|
|
|
@ -62,6 +62,9 @@ This installs the module product_expiry."""),
|
|||
'group_stock_tracking_lot': fields.boolean("Track serial number on logistic units (pallets)",
|
||||
implied_group='stock.group_tracking_lot',
|
||||
help="""When you select a serial number on product moves, you can get the upstream or downstream traceability of that product."""),
|
||||
'group_stock_tracking_owner': fields.boolean("Manage owner on stock",
|
||||
implied_group='stock.group_tracking_owner',
|
||||
help="""This way you can receive products attributed to a certain owner. """),
|
||||
'module_stock_account': fields.boolean("Generate accounting entries per stock movement",
|
||||
implied_group='stock.group_inventory_valuation',
|
||||
help="""Allows to configure inventory valuations on products and product categories."""),
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
<field name="group_stock_tracking_lot" class="oe_inline"/>
|
||||
<label for="group_stock_tracking_lot"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="group_stock_tracking_owner" class="oe_inline"/>
|
||||
<label for="group_stock_tracking_owner"/>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<separator string="Accounting"/>
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record id="group_tracking_owner" model="res.groups">
|
||||
<field name="name">Manage Different Stock Owners</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
<!-- multi -->
|
||||
|
|
|
@ -157,7 +157,7 @@ class stock_quant(osv.osv):
|
|||
'reservation_id': fields.many2one('stock.move', 'Reserved for Move', help="Is this quant reserved for a stock.move?"),
|
||||
'lot_id': fields.many2one('stock.production.lot', 'Lot'),
|
||||
'cost': fields.float('Unit Cost'),
|
||||
'partner_id': fields.related('lot_id', 'partner_id', type='many2one', relation="res.partner", string="Owner", store=True), # TODO implement store={}
|
||||
'owner_id': fields.many2one('res.partner', 'Owner', help="This is the owner of the quant"),
|
||||
|
||||
'create_date': fields.datetime('Creation Date'),
|
||||
'in_date': fields.datetime('Incoming Date'),
|
||||
|
@ -634,7 +634,9 @@ class stock_picking(osv.osv):
|
|||
})
|
||||
back_order_name = self.browse(cr, uid, backorder_id, context=context).name
|
||||
self.message_post(cr, uid, picking.id, body=_("Back order <em>%s</em> <b>created</b>.") % (back_order_name), context=context)
|
||||
self.pool.get('stock.move').write(cr, uid, backorder_move_ids, {'picking_id': backorder_id}, context=context)
|
||||
move_obj = self.pool.get("stock.move")
|
||||
move_obj.write(cr, uid, backorder_move_ids, {'picking_id': backorder_id}, context=context)
|
||||
self.pool.get("stock.picking").action_confirm(cr, uid, [picking.id], context=context)
|
||||
return backorder_id
|
||||
return False
|
||||
|
||||
|
@ -653,9 +655,11 @@ class stock_picking(osv.osv):
|
|||
'product_qty': qty,
|
||||
'quant_id': quant.id,
|
||||
'product_id': quant.product_id.id,
|
||||
'lot_id': quant.lot_id.id,
|
||||
'lot_id': quant.lot_id and quant.lot_id.id or False,
|
||||
'product_uom_id': quant.product_id.uom_id.id,
|
||||
'owner_id': quant.owner_id and quant.owner_id.id or False,
|
||||
'cost': quant.cost,
|
||||
'package_id': quant.package_id and quant.package_id.id or False,
|
||||
}, context=context)
|
||||
if remaining_qty > 0:
|
||||
pack_operation_obj.create(cr, uid, {
|
||||
|
@ -725,7 +729,13 @@ class stock_picking(osv.osv):
|
|||
for move in picking.move_lines:
|
||||
quant_obj.quants_unreserve(cr, uid, move, context=context)
|
||||
res2[move.id] = move.product_qty
|
||||
for ops in picking.pack_operation_ids:
|
||||
# Resort pack_operation_ids
|
||||
|
||||
orderedpackops = picking.pack_operation_ids
|
||||
#Sort packing operations such that packing operations with most specific information
|
||||
orderedpackops.sort(key = lambda x: (x.package_id and -1 or 0) + (x.lot_id and -1 or 0))
|
||||
|
||||
for ops in orderedpackops:
|
||||
#Find moves that correspond
|
||||
if ops.product_id:
|
||||
#TODO: Should have order such that things with lots and packings are searched first
|
||||
|
@ -750,17 +760,21 @@ class stock_picking(osv.osv):
|
|||
'history_ids': [(4, move.id)],
|
||||
'in_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'company_id': move.company_id.id,
|
||||
'lot_id': ops.lot_id and ops.lot_id.id or False,
|
||||
'lot_id': ops.lot_id and ops.lot_id.id or False,
|
||||
'owner_id': ops.owner_id and ops.owner_id.id or False,
|
||||
'reservation_id': move.id, #Reserve at once
|
||||
'package_id': ops.result_package_id and ops.result_package_id.id or False,
|
||||
}
|
||||
quant_id = quant_obj.create(cr, uid, vals, context=context)
|
||||
else:
|
||||
#Quants get
|
||||
domain = [('reservation_id', '=', False)]
|
||||
prefered_order = op_obj._get_preferred_order(cr, uid, ops.id, context=context)
|
||||
prefered_order = "reservation_id IS NOT NULL"
|
||||
domain = op_obj._get_domain(cr, uid, ops, context=context)
|
||||
quants = quant_obj.quants_get(cr, uid, move.location_id, move.product_id, qty, domain=domain, prefered_order=prefered_order, context=context)
|
||||
quant_obj.quants_reserve(cr, uid, quants, move, context=context)
|
||||
#In the end, move quants in correct package
|
||||
if create and ops.result_package_id:
|
||||
quant_obj.write(cr, uid, [x[0] for x in quants], {'package_id': ops.result_package_id.id}, context=context)
|
||||
res2[move.id] -= qty
|
||||
res[ops.id] = {}
|
||||
res[ops.id][ops.product_id.id] = qty_to_do
|
||||
|
@ -781,6 +795,9 @@ class stock_picking(osv.osv):
|
|||
res2[move.id] -= qty
|
||||
res.setdefault(ops.id, {}).setdefault(quant.product_id.id, 0.0)
|
||||
res[ops.id][quant.product_id.id] += qty_to_do
|
||||
#Add parent package
|
||||
if create and ops.result_package_id:
|
||||
self.pool.get("stock.package").write(cr, uid, [ops.package_id.id], {'parent_id': ops.result_package_id.id}, context=context)
|
||||
return (res, res2)
|
||||
|
||||
|
||||
|
@ -929,7 +946,7 @@ class stock_production_lot(osv.osv):
|
|||
'product_id': fields.many2one('product.product', 'Product', required=True, domain=[('type', '<>', 'service')]),
|
||||
'quant_ids': fields.one2many('stock.quant', 'lot_id', 'Quants'),
|
||||
'create_date': fields.datetime('Creation Date'),
|
||||
'partner_id': fields.many2one('res.partner', 'Owner'),
|
||||
# 'partner_id': fields.many2one('res.partner', 'Owner'),
|
||||
}
|
||||
_defaults = {
|
||||
'name': lambda x, y, z, c: x.pool.get('ir.sequence').get(y, z, 'stock.lot.serial'),
|
||||
|
@ -942,8 +959,8 @@ class stock_production_lot(osv.osv):
|
|||
res = []
|
||||
for lot in self.browse(cr, uid, ids, context=context):
|
||||
name = lot.name
|
||||
if lot.partner_id:
|
||||
name += ' (' + lot.partner_id.name + ')'
|
||||
# if lot.partner_id:
|
||||
# name += ' (' + lot.partner_id.name + ')'
|
||||
res.append((lot.id, name))
|
||||
return res
|
||||
|
||||
|
@ -1130,7 +1147,10 @@ class stock_move(osv.osv):
|
|||
'origin_returned_move_id': fields.many2one('stock.move', 'Origin return move', help='move that created the return move'),
|
||||
'returned_move_ids': fields.one2many('stock.move', 'origin_returned_move_id', 'All returned moves', help='Optional: all returned moves created from this move'),
|
||||
'availability': fields.function(_get_product_availability, type='float', string='Availability'),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
|
@ -1617,10 +1637,11 @@ class stock_move(osv.osv):
|
|||
self.action_done(cr, uid, res, context=context)
|
||||
return res
|
||||
|
||||
|
||||
|
||||
def split(self, cr, uid, move, qty, context=None):
|
||||
"""
|
||||
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
|
||||
|
@ -1651,7 +1672,7 @@ class stock_move(osv.osv):
|
|||
}, context=context)
|
||||
|
||||
if move.move_dest_id and move.propagate:
|
||||
self.split(self, cr, uid, move.move_dest_id, qty, context=context)
|
||||
self.split(cr, uid, move.move_dest_id, qty, context=context)
|
||||
return new_move
|
||||
|
||||
class stock_inventory(osv.osv):
|
||||
|
@ -2082,6 +2103,7 @@ class stock_pack_operation(osv.osv):
|
|||
'lot_id': fields.many2one('stock.production.lot', 'Lot/Serial Number'),
|
||||
'result_package_id': fields.many2one('stock.quant.package', 'Container Package', help="If set, the operations are packed into this package", required=False, ondelete='cascade'),
|
||||
'date': fields.datetime('Date', required=True),
|
||||
'owner_id': fields.many2one('res.partner', 'Owner', help="Owner of the quants"),
|
||||
#'update_cost': fields.boolean('Need cost update'),
|
||||
'cost': fields.float("Cost", help="Unit Cost for this product line"),
|
||||
'currency': fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed", ondelete='CASCADE'),
|
||||
|
@ -2091,18 +2113,21 @@ class stock_pack_operation(osv.osv):
|
|||
'date': fields.date.context_today,
|
||||
}
|
||||
|
||||
def _get_preferred_order(self, cr, uid, id, context=None):
|
||||
ops = self.browse(cr, uid, id, context=context)
|
||||
res = ""
|
||||
if ops.package_id:
|
||||
res += "package_id <> " + str(ops.package_id.id)
|
||||
if ops.lot_id:
|
||||
if res:
|
||||
res += ", lot_id <> " + str(ops.lot_id.id)
|
||||
else:
|
||||
res += "lot_id <> " + str(ops.lot_id.id)
|
||||
return res
|
||||
|
||||
def _get_domain(self, cr, uid, ops, context=None):
|
||||
'''
|
||||
Gives domain for different
|
||||
'''
|
||||
res = []
|
||||
if ops.package_id:
|
||||
res.append(('package_id', '=', ops.package_id.id), )
|
||||
if ops.lot_id:
|
||||
res.append(('lot_id', '=', ops.lot_id.id), )
|
||||
if ops.owner_id:
|
||||
res.append(('owner_id', '=', ops.owner_id.id), )
|
||||
else:
|
||||
res.append(('owner_id', '=', False), )
|
||||
return res
|
||||
|
||||
#TODO: this function can be refactored
|
||||
def _search_and_increment(self, cr, uid, picking_id, key, context=None):
|
||||
|
@ -2259,19 +2284,12 @@ class stock_warehouse_orderpoint(osv.osv):
|
|||
class product_template(osv.osv):
|
||||
_inherit = "product.template"
|
||||
_columns = {
|
||||
'type': fields.selection([('product', 'Stockable Product'), ('consu', 'Consumable'), ('service', 'Service')], 'Product Type', required=True, help="Consumable: Will not imply stock management for this product. \nStockable product: Will imply stock management for this product."),
|
||||
'supply_method': fields.selection([('produce', 'Manufacture'), ('buy', 'Buy'), ('wait', 'None')], 'Supply Method', required=True, help="Manufacture: When procuring the product, a manufacturing order or a task will be generated, depending on the product type. \nBuy: When procuring the product, a purchase order will be generated."),
|
||||
}
|
||||
_defaults = {
|
||||
'supply_method': 'buy',
|
||||
}
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = "product.product"
|
||||
_columns = {
|
||||
'orderpoint_ids': fields.one2many('stock.warehouse.orderpoint', 'product_id', 'Minimum Stock Rules'),
|
||||
}
|
||||
|
||||
class stock_picking_code(osv.osv):
|
||||
_name = "stock.picking.code"
|
||||
_description = "Will group picking types for kanban view"
|
||||
|
|
|
@ -603,11 +603,12 @@
|
|||
<field name="pack_operation_ids" attrs="{'invisible': [('pack_operation_exist', '=', False)]}">
|
||||
<tree editable="top">
|
||||
<field name="product_id"/>
|
||||
<field name="product_uom_id"/>
|
||||
<field name="lot_id"/>
|
||||
<field name="package_id"/>
|
||||
<field name="product_uom_id" groups="product.group_uom"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="package_id" groups="stock.group_tracking_lot"/>
|
||||
<field name="owner_id" groups="stock.group_tracking_owner"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="result_package_id"/>
|
||||
<field name="result_package_id" groups="stock.group_tracking_lot"/>
|
||||
</tree>
|
||||
</field>
|
||||
<field name="move_lines" context="{'address_in_id': partner_id, 'form_view_ref':'view_move_picking_form', 'tree_view_ref':'view_move_picking_tree', 'default_picking_type_id': picking_type_id}"/>
|
||||
|
@ -1533,6 +1534,7 @@
|
|||
<field name="reservation_id"/>
|
||||
<field name="propagated_from_id"/>
|
||||
<field name="history_ids"/>
|
||||
<field name="owner_id"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -1548,7 +1550,7 @@
|
|||
<field name="qty"/>
|
||||
<field name="location_id"/>
|
||||
<field name="lot_id"/>
|
||||
<field name="package_id" invisible="1"/>
|
||||
<field name="package_id"/>
|
||||
<field name="packaging_type_id" invisible="1"/>
|
||||
<field name="in_date"/>
|
||||
<field name="reservation_id" invisible='1'/>
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
-
|
||||
I create an inventory
|
||||
In order to test the inventory, I create a new product
|
||||
-
|
||||
!record {model: product.product, id: inventory_product}:
|
||||
name: inventory prod
|
||||
type: product
|
||||
-
|
||||
I create an inventory for this product only
|
||||
-
|
||||
!record {model: stock.inventory, id: inventory_test0}:
|
||||
name: Test
|
||||
product_id: inventory_product
|
||||
-
|
||||
I start this inventory
|
||||
I confirm the inventory and check that my inventory has no line, as the product is a new one.
|
||||
-
|
||||
!python {model: stock.inventory}: |
|
||||
self.prepare_inventory(cr, uid, [ref('inventory_test0')], context=context)
|
||||
inv = self.browse(cr, uid, ref('inventory_test0'), context=context)
|
||||
assert len(inv.line_ids) == 0, "Wrong number of inventory lines."
|
||||
-
|
||||
I create an inventory line with 10 product
|
||||
I add an inventory line and say i have 10 products in stock
|
||||
-
|
||||
!record {model: stock.inventory.line, id: inventory_testline0}:
|
||||
inventory_id: stock.inventory_test0
|
||||
product_id: product.product_product_3
|
||||
product_id: inventory_product
|
||||
product_qty: 10
|
||||
location_id: stock.stock_location_14
|
||||
-
|
||||
|
@ -29,40 +38,43 @@
|
|||
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.
|
||||
I check that the quantity on hand is 10 on the location and its 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==10, 'Expecting 10 products, got %.2f on location stock_location_14!' % (product.qty_available,)
|
||||
product = self.browse(cr, uid, ref('inventory_product'), context=context)
|
||||
assert product.qty_available == 10, 'Expecting 10 products, got %.2f on location stock_location_14!' % (product.qty_available,)
|
||||
context['location'] = ref('stock.stock_location_stock')
|
||||
product = self.browse(cr, uid, ref('product.product_product_3'), context=context)
|
||||
assert product.qty_available==10, 'Expecting 10 products, got %.2f on location stock_location_stock!' % (product.qty_available,)
|
||||
product = self.browse(cr, uid, ref('inventory_product'), context=context)
|
||||
assert product.qty_available == 10, 'Expecting 10 products, got %.2f on location stock_location_stock!' % (product.qty_available,)
|
||||
-
|
||||
I check that the quantity on hand is 0 on a brother location
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
context['location'] = ref('stock.stock_location_components')
|
||||
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,)
|
||||
product = self.browse(cr, uid, ref('inventory_product'), context=context)
|
||||
assert product.qty_available == 0, 'Expecting 0 products, got %.2f on location stock_location_components!' % (product.qty_available,)
|
||||
-
|
||||
I create another inventory
|
||||
-
|
||||
!record {model: stock.inventory, id: inventory_test1}:
|
||||
name: Test2
|
||||
name: second test inventory
|
||||
product_id: inventory_product
|
||||
-
|
||||
I start this inventory
|
||||
I confirm the inventory and check that my inventory has one line, with a quantity of 10.
|
||||
-
|
||||
!python {model: stock.inventory}: |
|
||||
self.prepare_inventory(cr, uid, [ref('inventory_test1')], context=context)
|
||||
inv = self.browse(cr, uid, ref('inventory_test1'), context=context)
|
||||
assert inv.line_ids and len(inv.line_ids) == 1, "Wrong number of inventory lines."
|
||||
assert len(inv.line_ids[0].product_qty) == 10, "Wrong quantity in inventory line."
|
||||
assert len(inv.line_ids[0].product_id.id) == ref('inventory_product'), "Wrong product in inventory line."
|
||||
-
|
||||
I create an inventory line with 20 product on this new inventory
|
||||
I modify the inventory line and set the quantity to 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
|
||||
!python {model: stock.inventory}: |
|
||||
inv = self.browse(cr, uid, ref('inventory_test1'), context=context)
|
||||
self.pool.get('stock.inventory.line').write(cr, uid, inv.line_ids[0].id, {'product_qty': 20})
|
||||
-
|
||||
I Validate this inventory
|
||||
-
|
||||
|
@ -72,6 +84,7 @@
|
|||
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_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_components!' % (product.qty_available,)
|
||||
context['location'] = ref('stock.stock_location_14')
|
||||
product = self.browse(cr, uid, ref('inventory_product'), context=context)
|
||||
assert product.qty_available == 20, 'Expecting 20 products, got %.2f on location stock_location_14!' % (product.qty_available,)
|
||||
|
||||
|
|
|
@ -1,68 +1,171 @@
|
|||
-
|
||||
-
|
||||
Create a new stockable product
|
||||
-
|
||||
!record {model: product.product, id: packingtest}:
|
||||
name: nice product
|
||||
!record {model: product.product, id: product1}:
|
||||
name: Nice product
|
||||
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 an incoming picking for this product of 300 PCE from suppliers to stock
|
||||
-
|
||||
!record{model: stock.picking}: |
|
||||
!record {model: stock.picking, id: pick1}:
|
||||
name: Incoming picking
|
||||
partner_id: base.res_partner_2
|
||||
picking_type_id: picking_type_in
|
||||
move_lines:
|
||||
- product_id: product1
|
||||
product_uom_qty: 300.00
|
||||
location_id: stock_location_suppliers
|
||||
location_dest_id: stock_location_stock
|
||||
-
|
||||
Confirm and assign picking and prepare partial
|
||||
-
|
||||
!python {model: stock.picking, id:}: |
|
||||
self.action_confirm(cr, uid, ref())
|
||||
!python {model: stock.picking}: |
|
||||
self.action_confirm(cr, uid, [ref('pick1')], context=context)
|
||||
self.do_prepare_partial(cr, uid, [ref('pick1')], context=context)
|
||||
-
|
||||
Put 120 pieces on Pallet 1 (package), 120 pieces on Pallet 2 with lot A and 60 pieces on Pallet 3
|
||||
-
|
||||
!python {model: stock.picking, id:} |
|
||||
!python {model: stock.picking}: |
|
||||
#Change quantity of first to 120 and create 2 others quant operations
|
||||
record = self.browse(cr, uid, ref('pick1'), context=context)
|
||||
stock_pack = self.pool.get('stock.pack.operation')
|
||||
stock_quant_pack = self.pool.get('stock.quant.package')
|
||||
#create lot A
|
||||
lot_a = self.pool.get('stock.production.lot').create(cr, uid, {'name': 'Lot A', 'product_id': ref('product1')}, context=context)
|
||||
#create package
|
||||
package1 = stock_quant_pack.create(cr, uid, {'name': 'Pallet 1'}, context=context)
|
||||
package2 = stock_quant_pack.create(cr, uid, {'name': 'Pallet 2'}, context=context)
|
||||
package3 = stock_quant_pack.create(cr, uid, {'name': 'Pallet 3'}, context=context)
|
||||
#Create package for each line and assign it as result_package_id
|
||||
#create pack operation
|
||||
stock_pack.write(cr, uid, record.pack_operation_ids[0].id, {'package_id': package1, 'result_package_id': package1, 'product_qty': 120})
|
||||
new_pack1 = stock_pack.create(cr, uid, {'product_id': ref('product1'), 'product_uom_id': ref('product.product_uom_unit'), 'picking_id': ref('pick1'), 'lot_id': lot_a, 'package_id': package2, 'result_package_id': package2, 'product_qty': 120}, context=context)
|
||||
new_pack2 = stock_pack.create(cr, uid, {'product_id': ref('product1'), 'product_uom_id': ref('product.product_uom_unit'), 'picking_id': ref('pick1'), 'package_id': package3, 'result_package_id': package3, 'product_qty': 60}, context=context)
|
||||
-
|
||||
Use button rereserve and check the qtyremaining on the moves are correct (=0)
|
||||
Use button rereserve and check the qtyremaining on the moves are correct (=original quantities)
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
self.rereserve(cr, uid, [ref('pick1')], context=context)
|
||||
picking = self.browse(cr, uid, ref('pick1'), context=context)
|
||||
move_reco = picking.move_lines[0]
|
||||
assert move_reco.remaining_qty == 300.0, "Remaining quantities should not change upon receiving"
|
||||
-
|
||||
Transfer the reception
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
self.do_partial(cr, uid, [ref('pick1')], context=context)
|
||||
-
|
||||
Check the system created 3 quants one with 120 pieces on pallet 1, one with 120 pieces on pallet 2 with lot A and 60 pieces on pallet 3
|
||||
-
|
||||
|
||||
!python {model: stock.quant}: |
|
||||
reco_id = self.search(cr ,uid , [('product_id','=',ref('product1'))], context=context)
|
||||
assert len(reco_id) == 3, "The number of quants created is not correct"
|
||||
for rec in self.browse(cr, uid, reco_id, context=context):
|
||||
if rec.package_id.name == 'Pallet 1':
|
||||
assert rec.qty == 120, "Should have 120 pîeces on pallet 1"
|
||||
elif rec.package_id.name == 'Pallet 2':
|
||||
assert rec.qty == 120, "Should have 120 pieces on pallet 2"
|
||||
elif rec.package_id.name == 'Pallet 3':
|
||||
assert rec.qty == 60, "Should have 60 pieces on pallet 3"
|
||||
-
|
||||
Check there is no backorder or extra moves created
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.browse(cr, uid, ref('pick1'), context=context)
|
||||
backorder = self.search(cr, uid, [('backorder_id', '=', ref('pick1'))])
|
||||
assert not backorder, ""
|
||||
#Check extra moves created
|
||||
assert len(picking.move_lines) == 1, ""
|
||||
-
|
||||
Make a delivery order of 300 pieces to the customer
|
||||
-
|
||||
|
||||
!record {model: stock.picking, id: delivery_order1}:
|
||||
name: outgoing picking
|
||||
partner_id: base.res_partner_4
|
||||
picking_type_id: stock.picking_type_out
|
||||
move_lines:
|
||||
- product_id: product1
|
||||
product_uom_qty: 300.00
|
||||
location_id: stock_location_stock
|
||||
location_dest_id: stock_location_customers
|
||||
-
|
||||
Assign and confirm
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
self.action_confirm(cr, uid, [ref('delivery_order1')], context=context)
|
||||
self.action_assign(cr, uid, [ref('delivery_order1')])
|
||||
self.force_assign(cr, uid, [ref('delivery_order1')], context=context)
|
||||
-
|
||||
Instead of doing the 300 pieces, you decide to take pallet 1 (do not mention product in operation here) and 20 pieces from lot A and 10 pieces from pallet 3
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
stock_pack = self.pool.get('stock.pack.operation')
|
||||
self.do_prepare_partial(cr, uid, [ref('delivery_order1')], context=context)
|
||||
delivery_id = self.browse(cr, uid, ref('delivery_order1'), context=context)
|
||||
for rec in delivery_id.pack_operation_ids:
|
||||
if rec.package_id.name == 'Pallet 1' or rec.product_qty == 120:
|
||||
stock_pack.write(cr, uid, rec.id, {'product_qty': 120}, context=context)
|
||||
if rec.package_id.name == 'Pallet 2' or rec.lot_id.name == 'Lot A' :
|
||||
stock_pack.write(cr, uid, rec.id, {'product_qty': 20}, context=context)
|
||||
if rec.package_id.name == 'Pallet 3' or rec.product_qty == 60:
|
||||
stock_pack.write(cr, uid, rec.id, {'product_qty': 10}, context=context)
|
||||
-
|
||||
Process this picking
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
self.rereserve(cr, uid, [ref('delivery_order1')], context=context)
|
||||
self.do_partial(cr, uid, [ref('delivery_order1')], context=context)
|
||||
-
|
||||
Check the quants that you have 120 pieces pallet 1 in customers, 100 pieces pallet 2 in stock and 20 with customers and 50 in stock, 10 in customers from pallet 3
|
||||
-
|
||||
|
||||
!python {model: stock.quant}: |
|
||||
reco_id = self.search(cr ,uid , [('product_id','=',ref('product1'))], context=context)
|
||||
for rec in self.browse(cr, uid, reco_id, context=context):
|
||||
if rec.package_id.name == 'Pallet 1' and rec.location_id.id == ref('stock_location_customers'):
|
||||
assert rec.qty == 120, "Should have 120 pieces on pallet 1"
|
||||
if rec.package_id.name == 'Pallet 2' and rec.location_id.id == ref('stock_location_stock'):
|
||||
assert rec.qty == 20, "Should have 20 pieces in stock on pallet 2"
|
||||
if rec.package_id.name == 'Pallet 3' and rec.location_id.id == ref('stock_location_stock'):
|
||||
assert rec.qty == 10, "Should have 10 pieces in stock on pallet 3"
|
||||
-
|
||||
Check a backorder was created and on that backorder, prepare partial and add an op with 20 pieces (20 that cannot be assigned) with lot B
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.browse(cr, uid, ref('delivery_order1'), context=context)
|
||||
backorder = self.search(cr, uid, [('backorder_id.id', '=', picking.id)], context=context)
|
||||
assert backorder, "Backorder should have been created"
|
||||
backorder_id = self.browse(cr, uid, backorder, context=context)
|
||||
self.action_confirm(cr, uid, backorder, context=context)
|
||||
self.action_assign(cr, uid, backorder)
|
||||
self.force_assign(cr, uid, backorder, context=context)
|
||||
self.do_prepare_partial(cr, uid, backorder, context=context)
|
||||
#create lot B
|
||||
lot_b = self.pool.get('stock.production.lot').create(cr, uid, {'name': 'Lot B', 'product_id': ref('product1')}, context=context)
|
||||
stock_pack = self.pool.get('stock.pack.operation').create(cr, uid, {'picking_id': backorder_id[0].id, 'lot_id': lot_b, 'product_qty': 20})
|
||||
-
|
||||
Process this backorder
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.browse(cr, uid, ref('delivery_order1'), context=context)
|
||||
backorder = self.search(cr, uid, [('backorder_id.id', '=', picking.id)], context=context)
|
||||
backorder_id = self.browse(cr, uid, backorder, context=context)
|
||||
self.rereserve(cr, uid, [backorder_id[0].id], context=context)
|
||||
self.do_partial(cr, uid, [backorder_id[0].id], context=context)
|
||||
-
|
||||
Check you have a negative quant because there were 20 too many that were transferred with lot B
|
||||
-
|
||||
|
||||
!python {model: stock.quant}: |
|
||||
reco_id = self.search(cr ,uid , [('product_id','=',ref('product1'))], context=context)
|
||||
for rec in self.browse(cr, uid, reco_id, context=context):
|
||||
if rec.lot_id.name == 'Lot B':
|
||||
assert rec.qty != -20, ""
|
||||
|
|
|
@ -1,22 +1,35 @@
|
|||
-
|
||||
Create new global procurement rule from Stock -> Output
|
||||
-
|
||||
!record {model: procurement.rule, ref:}
|
||||
location_id: stock
|
||||
location_dest_id: output
|
||||
!record {model: procurement.rule, id: global_proc_rule}:
|
||||
name: Stock -> output
|
||||
action: move
|
||||
picking_type_id: stock.picking_type_out
|
||||
location_src_id: stock.stock_location_stock
|
||||
location_id: stock.stock_location_output
|
||||
-
|
||||
Create Delivery Order from Output -> Customer
|
||||
-
|
||||
!record {model: stock.picking, ref:}
|
||||
!record {model: stock.picking, id: pick_output}:
|
||||
name: Delivery order for procurement
|
||||
partner_id: base.res_partner_2
|
||||
picking_type_id: stock.picking_type_out
|
||||
move_lines:
|
||||
- product_id: product.product_product_3
|
||||
product_uom_qty: 10.00
|
||||
location_id: stock.stock_location_output
|
||||
location_dest_id: stock.stock_location_customers
|
||||
procure_method: make_to_order
|
||||
-
|
||||
Confirm delivery order
|
||||
Confirm delivery order.
|
||||
-
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
self.action_confirm(cr, uid, [ref('pick_output')])
|
||||
-
|
||||
Check procurement was created in output (as there is the global procurement rule) related to this delivery order
|
||||
Check a picking was created from stock to output.
|
||||
-
|
||||
|
||||
-
|
||||
Check a picking was created from stock to output
|
||||
-
|
||||
|
||||
!python {model: stock.move }: |
|
||||
picking = self.pool.get("stock.picking").browse(cr, uid, ref("pick_output"))
|
||||
move_id = self.search(cr, uid, [('product_id', '=', ref('product.product_product_3')),('location_id', '=', ref('stock.stock_location_stock')),
|
||||
('location_dest_id', '=', ref('stock.stock_location_output'), ('move_dest_id', '=', picking.move_lines[0].id))])
|
||||
assert len(move_id) == 1, "It should have created a picking from Stock to Output with the original picking as destination"
|
|
@ -1,7 +1,8 @@
|
|||
-
|
||||
I confirm outgoing shipment of 130 kgm Ice-cream.
|
||||
-
|
||||
!workflow {model: stock.picking, action: button_confirm, ref: outgoing_shipment}
|
||||
!python {model: stock.picking}: |
|
||||
self.action_confirm(cr, uid, [ref("outgoing_shipment")])
|
||||
-
|
||||
I check shipment details after confirmed.
|
||||
-
|
||||
|
@ -10,99 +11,72 @@
|
|||
assert shipment.state == "confirmed", "Shipment should be confirmed."
|
||||
for move_line in shipment.move_lines:
|
||||
assert move_line.state == "confirmed", "Move should be confirmed."
|
||||
|
||||
-
|
||||
Now I check vitual stock of Ice-cream after confirmed outgoing shipment.
|
||||
Now I check virtual stock of Ice-cream after confirmed outgoing shipment.
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
product = self.browse(cr, uid, ref('product_icecream'), context=context)
|
||||
product.virtual_available == -30, "Vitual stock is not updated."
|
||||
|
||||
-
|
||||
I confirm incomming shipment of 50 kgm Ice-cream.
|
||||
-
|
||||
!workflow {model: stock.picking, action: button_confirm, ref: incomming_shipment}
|
||||
!python {model: stock.picking}: |
|
||||
self.action_confirm(cr, uid, [ref("incomming_shipment")])
|
||||
-
|
||||
I receive 40kgm Ice-cream so I make backorder of incomming shipment for 40 kgm.
|
||||
I receive 40kgm Ice-cream so It will make backorder of incomming shipment for 10 kgm.
|
||||
-
|
||||
!python {model: stock.partial.picking}: |
|
||||
!python {model: stock.picking}: |
|
||||
pick = self.browse(cr, uid, ref("incomming_shipment"), context=context)
|
||||
self.pool.get('stock.pack.operation').create(cr, uid, {
|
||||
'picking_id': pick.id,
|
||||
'product_id': ref('product_icecream'),
|
||||
'product_uom_id': ref('product.product_uom_kgm'),
|
||||
'product_qty': 40
|
||||
})
|
||||
context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]})
|
||||
pick.do_partial(context=context)
|
||||
-
|
||||
!record {model: stock.partial.picking, id: partial_incomming}:
|
||||
move_ids:
|
||||
- quantity: 40
|
||||
product_id: product_icecream
|
||||
product_uom: product.product_uom_kgm
|
||||
move_id: incomming_shipment_icecream
|
||||
location_id: location_convenience_shop
|
||||
location_dest_id: location_refrigerator
|
||||
-
|
||||
!python {model: stock.partial.picking }: |
|
||||
self.do_partial(cr, uid, [ref('partial_incomming')], context=context)
|
||||
-
|
||||
I check backorder shipment after received partial shipment.
|
||||
I check backorder shipment after received partial shipment and check remaining shipment.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
shipment = self.browse(cr, uid, ref("incomming_shipment"))
|
||||
backorder = shipment.backorder_id
|
||||
assert backorder, "Backorder should be created after partial shipment."
|
||||
assert backorder.state == 'done', "Backorder should be close after received."
|
||||
for move_line in shipment.move_lines:
|
||||
assert move_line.product_qty == 40, "Qty in shipment does not correspond."
|
||||
assert move_line.state == 'done', "Move line of shipment should be closed."
|
||||
backorder_id = self.search(cr, uid, [('backorder_id', '=', ref("incomming_shipment"))],context=context)
|
||||
backorder = self.browse(cr, uid, backorder_id)[0]
|
||||
for move_line in backorder.move_lines:
|
||||
assert move_line.product_qty == 40, "Qty in backorder does not correspond."
|
||||
assert move_line.state == 'done', "Move line of backorder should be closed."
|
||||
assert move_line.product_qty == 10, "Qty in backorder does not correspond."
|
||||
assert move_line.state == 'draft', "Move line of backorder should be draft."
|
||||
context.update({'active_model': 'stock.picking', 'active_id': backorder_id[0], 'active_ids': backorder_id})
|
||||
self.action_confirm(cr, uid, backorder_id, context=context)
|
||||
self.do_partial(cr, uid, backorder_id, context=context)
|
||||
-
|
||||
I receive another 10kgm Ice-cream.
|
||||
-
|
||||
!record {model: stock.partial.picking, id: partial_incomming}:
|
||||
move_ids:
|
||||
- quantity: 10
|
||||
product_id: product_icecream
|
||||
product_uom: product.product_uom_kgm
|
||||
move_id: incomming_shipment_icecream
|
||||
location_id: location_convenience_shop
|
||||
location_dest_id: location_refrigerator
|
||||
-
|
||||
!python {model: stock.partial.picking }: |
|
||||
self.do_partial(cr, uid, [ref('partial_incomming')], context=context)
|
||||
|
||||
!python {model: stock.picking}: |
|
||||
pick = self.browse(cr, uid, ref("incomming_shipment"))
|
||||
self.pool.get('stock.pack.operation').create(cr, uid, {
|
||||
'picking_id': pick.id,
|
||||
'product_id': ref('product_icecream'),
|
||||
'product_uom_id': ref('product.product_uom_kgm'),
|
||||
'product_qty': 10
|
||||
})
|
||||
context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]})
|
||||
pick.do_partial(context=context)
|
||||
-
|
||||
I check incomming shipment after received.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
shipment = self.browse(cr, uid, ref("incomming_shipment"))
|
||||
shipment = self.browse(cr, uid, self.search(cr, uid, [('backorder_id', '=', ref("incomming_shipment"))]))[0]
|
||||
assert shipment.state == 'done', "shipment should be close after received."
|
||||
for move_line in shipment.move_lines:
|
||||
assert move_line.product_qty == 10, "Qty does not correspond."
|
||||
assert move_line.product_id.virtual_available == 20, "Virtual stock does not correspond."
|
||||
assert move_line.state == 'done', "Move line should be closed."
|
||||
|
||||
-
|
||||
I return last incomming shipment for 10 kgm Ice-cream.
|
||||
-
|
||||
!record {model: stock.return.picking, id: return_incomming}:
|
||||
invoice_state: none
|
||||
Return picking
|
||||
-
|
||||
!python {model: stock.return.picking }: |
|
||||
# this work without giving the id of the picking to return, magically, thanks to the context
|
||||
self.create_returns(cr, uid, [ref('return_incomming')], context=context)
|
||||
-
|
||||
I cancel incomming shipment after return it.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
# the cancel is not on the return, but on the incomming shipment (which now has a quantity of 10, thanks to the
|
||||
# backorder). This situation is a little weird as we returned a move that we finally cancelled... As result, only
|
||||
# 30Kg from the original 50Kg will be counted in the stock (50 - 10 (cancelled quantity) - 10 (returned quantity))
|
||||
self.action_cancel(cr, uid, [ref("incomming_shipment")], context=context)
|
||||
-
|
||||
I make invoice of backorder of incomming shipment.
|
||||
-
|
||||
!python {model: stock.invoice.onshipping}: |
|
||||
shipment = self.pool.get('stock.picking').browse(cr, uid, ref("incomming_shipment"))
|
||||
context.update({'active_model': 'stock.picking', 'active_id': shipment.backorder_id.id, 'active_ids': [shipment.backorder_id.id]})
|
||||
-
|
||||
I check available stock after received incomming shipping. (removed invoicing here)
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
product = self.browse(cr, uid, ref('product_icecream'), context=context)
|
||||
assert product.qty_available == 140, "Stock does not correspond."
|
||||
assert product.virtual_available == 0, "Vitual stock does not correspond."
|
||||
# TODO: Should still work out according to the previous steps of shipment.yml
|
||||
pass
|
||||
|
|
|
@ -22,6 +22,66 @@
|
|||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Procurement Rule
|
||||
#----------------------------------------------------------
|
||||
class procurement_rule(osv.osv):
|
||||
_inherit = 'procurement.rule'
|
||||
_columns= {
|
||||
'invoice_state': fields.selection([
|
||||
("invoiced", "Invoiced"),
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")], "Invoice Status",
|
||||
required=False),
|
||||
}
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Procurement Order
|
||||
#----------------------------------------------------------
|
||||
|
||||
|
||||
class procurement_order(osv.osv):
|
||||
_inherit = "procurement.order"
|
||||
_columns = {
|
||||
'invoice_state': fields.selection(
|
||||
[("invoiced", "Invoiced"),
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")
|
||||
], "Invoice Control", required=True),
|
||||
}
|
||||
|
||||
def _run_move_create(self, cr, uid, procurement, context=None):
|
||||
res = super(procurement_order, self)._run_move_create(cr, uid, procurement, context=context)
|
||||
res.update({'invoice_state': (procurement.rule_id.invoice_state in ('none', False) and procurement.invoice_state or procurement.rule_id.invoice_state) or 'none'})
|
||||
return res
|
||||
|
||||
_defaults = {
|
||||
'invoice_state': 'none'
|
||||
}
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Move
|
||||
#----------------------------------------------------------
|
||||
|
||||
class stock_move(osv.osv):
|
||||
_inherit = "stock.move"
|
||||
_columns = {
|
||||
'invoice_state': fields.selection([("invoiced", "Invoiced"),
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")], "Invoice Control",
|
||||
select=True, required=True, track_visibility='onchange',
|
||||
states={'draft': [('readonly', False)]}),
|
||||
}
|
||||
_defaults= {
|
||||
'invoice_state': lambda *args, **argv: 'none'
|
||||
}
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Picking
|
||||
#----------------------------------------------------------
|
||||
|
||||
class stock_picking(osv.osv):
|
||||
_inherit = 'stock.picking'
|
||||
|
@ -30,22 +90,13 @@ class stock_picking(osv.osv):
|
|||
for pick in self.browse(cr, uid, ids, context=context):
|
||||
result[pick.id] = 'none'
|
||||
for move in pick.move_lines:
|
||||
if move.procurement_id:
|
||||
if move.procurement_id.invoice_state=='invoiced':
|
||||
result[pick.id] = 'invoiced'
|
||||
elif move.procurement_id.invoice_state=='2binvoiced':
|
||||
result[pick.id] = '2binvoiced'
|
||||
break
|
||||
if move.invoice_state=='invoiced':
|
||||
result[pick.id] = 'invoiced'
|
||||
elif move.invoice_state=='2binvoiced':
|
||||
result[pick.id] = '2binvoiced'
|
||||
break
|
||||
return result
|
||||
|
||||
def __get_picking_procurement(self, cr, uid, ids, context={}):
|
||||
result = {}
|
||||
for proc in self.pool.get('procurement.order').browse(cr, uid, ids, context=context):
|
||||
for move in proc.move_ids:
|
||||
if move.picking_id:
|
||||
result[move.picking_id.id] = True
|
||||
return result.keys()
|
||||
|
||||
def __get_picking_move(self, cr, uid, ids, context={}):
|
||||
res = []
|
||||
for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
|
||||
|
@ -59,8 +110,8 @@ class stock_picking(osv.osv):
|
|||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")
|
||||
], string="Invoice Control", required=True,
|
||||
|
||||
store={
|
||||
'procurement.order': (__get_picking_procurement, ['invoice_state'], 10),
|
||||
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10),
|
||||
'stock.move': (__get_picking_move, ['picking_id'], 10),
|
||||
},
|
||||
|
|
|
@ -34,11 +34,6 @@ import openerp.addons.decimal_precision as dp
|
|||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Invoice state
|
||||
#----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
|
|
|
@ -29,7 +29,27 @@
|
|||
<xpath expr="//field[@name='move_type']" position="after">
|
||||
<field name="invoice_state" groups="account.group_account_invoice"/>
|
||||
</xpath>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_move_form_inherit" model="ir.ui.view">
|
||||
<field name="name">stock.move.form.inherit</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='picking_type_id']" position="after">
|
||||
<field name="invoice_state" groups="account.group_account_invoice"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<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="invoice_state"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
|
|
|
@ -133,18 +133,13 @@ class procurement_rule(osv.osv):
|
|||
'delay': fields.integer('Number of Hours'),
|
||||
'procure_method': fields.selection([('make_to_stock','Make to Stock'),('make_to_order','Make to Order')], 'Procure Method', required=True, help="'Make to Stock': When needed, take from the stock or wait until re-supplying. 'Make to Order': When needed, purchase or produce for the procurement request."),
|
||||
'partner_address_id': fields.many2one('res.partner', 'Partner Address'),
|
||||
'invoice_state': fields.selection([
|
||||
("invoiced", "Invoiced"),
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")], "Invoice Status",
|
||||
required=True,),
|
||||
|
||||
'route_sequence': fields.related('route_id', 'sequence', string='Route Sequence', store={'stock.location.route': (_get_rules, ['sequence'], 10)}),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'propagate': fields.boolean('Propagate cancel and split', help='If checked, when the previous move of the move (which was generated by a next procurement) is cancelled or split, the move generated by this move will too'),
|
||||
}
|
||||
_defaults = {
|
||||
'procure_method': 'make_to_stock',
|
||||
'invoice_state': 'none',
|
||||
'propagate': True,
|
||||
'delay': 0,
|
||||
}
|
||||
|
@ -155,7 +150,7 @@ class procurement_rule(osv.osv):
|
|||
class procurement_order(osv.osv):
|
||||
_inherit = 'procurement.order'
|
||||
_columns = {
|
||||
'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Destination route', help="Preferred route to be followed by the procurement order"),
|
||||
'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Followed Route', help="Preferred route to be followed by the procurement order"),
|
||||
}
|
||||
|
||||
def _run_move_create(self, cr, uid, procurement, context=None):
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
<field name="location_src_id" ref="stock.stock_location_intermediatelocation0"/>
|
||||
<field name="location_id" ref="stock.stock_location_shop0"/>
|
||||
<field name="partner_address_id" ref="base.main_partner"/>
|
||||
<field name="invoice_state">none</field>
|
||||
<field name="company_id" ref="stock.res_company_1"/>
|
||||
<field name="type_proc">move</field>
|
||||
<field eval="0" name="propagate"/>
|
||||
|
@ -53,7 +52,6 @@
|
|||
<field name="location_src_id" ref="stock.stock_location_stock"/>
|
||||
<field name="partner_address_id" ref="stock.res_partner_address_41"/>
|
||||
<field name="type_proc">move</field>
|
||||
<field name="invoice_state">none</field>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field eval="0" name="propagate"/>
|
||||
<field name="procure_method">make_to_stock</field>
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
</field>
|
||||
<field name="group_id" position="before">
|
||||
<field name="procure_method"/>
|
||||
<field name="invoice_state"/>
|
||||
<field name="partner_address_id"/>
|
||||
</field>
|
||||
</field>
|
||||
|
|
Loading…
Reference in New Issue