[MIG] purchase: Migrate to new API

This commit is contained in:
Denis Vermylen (dve)
2016-08-05 14:04:37 +02:00
committed by Yannick Tivisse
parent 197c410557
commit ba3d3582bc
38 changed files with 409 additions and 446 deletions
-2
View File
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Purchase Management',
'version': '1.2',
@@ -51,7 +50,6 @@ Dashboard / Reports for Purchase Management will include:
'test/process/run_scheduler.yml',
'test/fifo_price.yml',
'test/fifo_returns.yml',
# 'test/costmethodchange.yml',
'test/process/cancel_order.yml',
'test/ui/duplicate_order.yml',
'test/ui/delete_order.yml',
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!--Email template -->
<record id="email_template_edi_purchase" model="mail.template">
<field name="name">RFQ - Send by Email</field>
+2 -2
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<odoo>
<data noupdate="1">
<!-- notify all employees of module installation -->
@@ -53,4 +53,4 @@
<field name="company_id" eval="False"/>
</record>
</data>
</openerp>
</odoo>
+2 -3
View File
@@ -1,6 +1,5 @@
-
!python {model: stock.warehouse}: |
!python {model: stock.warehouse, id: stock.warehouse0}: |
#enable purchase on main warehouse
main_warehouse = self.browse(cr, uid, ref('stock.warehouse0'), context=context)
self.write(cr, uid, main_warehouse.id, {'buy_to_resupply': True}, context=context)
self.write({'buy_to_resupply': True})
+2 -2
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<odoo>
<data noupdate="1">
<record id="base.user_demo" model="res.users">
@@ -22,5 +22,5 @@
<field name="route_ids" eval="[(4,ref('route_warehouse0_buy'))]"></field>
</record>
</data>
</openerp>
</odoo>
+4 -8
View File
@@ -1,12 +1,8 @@
-
!python {model: stock.warehouse}: |
pull_obj = self.pool.get('procurement.rule')
!python {model: stock.warehouse, id: False}: |
pull_obj = self.env['procurement.rule']
wh_to_assign = ['stock_warehouse_shop0']
for wh_ref in wh_to_assign:
warehouse = self.browse(cr, uid, ref('stock.' + wh_ref), context=context)
warehouse = self.browse(ref('stock.' + wh_ref))
#Force the rewriting of route and rule
self.write(cr, uid, warehouse.id, {'buy_to_resupply': True}, context=context)
warehouse.write({'buy_to_resupply': True})
+2 -2
View File
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp import api, fields, models, _
from openerp.tools.float_utils import float_compare
from odoo import api, fields, models, _
from odoo.tools.float_utils import float_compare
class AccountInvoice(models.Model):
+12 -8
View File
@@ -1,14 +1,18 @@
from openerp.osv import osv
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models
class mail_mail(osv.Model):
class MailMail(models.Model):
_name = 'mail.mail'
_inherit = 'mail.mail'
def _postprocess_sent_message(self, cr, uid, ids, context=None, mail_sent=True):
for mail in self.browse(cr, uid, ids, context=context):
@api.multi
def _postprocess_sent_message(self, mail_sent=True):
for mail in self:
if mail_sent and mail.model == 'purchase.order':
obj = self.pool.get('purchase.order').browse(cr, uid, mail.res_id, context=context)
if obj.state == 'draft':
self.pool.get('purchase.order').signal_workflow(cr, uid, [mail.res_id], 'send_rfq')
return super(mail_mail, self)._postprocess_sent_message(cr, uid, ids, context=context, mail_sent=mail_sent)
purchase_order = self.env['purchase.order'].browse(mail.res_id)
if purchase_order.state == 'draft':
self.env['purchase.order'].signal_workflow([mail.res_id], 'send_rfq')
return super(MailMail, self)._postprocess_sent_message(mail_sent=mail_sent)
+19 -16
View File
@@ -3,14 +3,15 @@
from datetime import datetime
from dateutil.relativedelta import relativedelta
from openerp import api, fields, models, _, SUPERUSER_ID
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.translate import _
from openerp.tools.float_utils import float_is_zero, float_compare
import openerp.addons.decimal_precision as dp
from openerp.exceptions import UserError, AccessError
from openerp.tools.misc import formatLang
from openerp.addons.base.res.res_partner import WARNING_MESSAGE, WARNING_HELP
from odoo import api, fields, models, SUPERUSER_ID, _
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tools.float_utils import float_is_zero, float_compare
from odoo.exceptions import UserError, AccessError
from odoo.tools.misc import formatLang
from odoo.addons.base.res.res_partner import WARNING_MESSAGE, WARNING_HELP
import odoo.addons.decimal_precision as dp
class PurchaseOrder(models.Model):
_name = "purchase.order"
@@ -96,7 +97,7 @@ class PurchaseOrder(models.Model):
'cancel': [('readonly', True)],
}
name = fields.Char('Order Reference', required=True, select=True, copy=False, default='New')
name = fields.Char('Order Reference', required=True, index=True, copy=False, default='New')
origin = fields.Char('Source Document', copy=False,\
help="Reference of the document that generated this purchase order "
"request (e.g. a sale order or an internal procurement request)")
@@ -105,9 +106,9 @@ class PurchaseOrder(models.Model):
"It's used to do the matching when you receive the "
"products as this reference is usually written on the "
"delivery order sent by your vendor.")
date_order = fields.Datetime('Order Date', required=True, states=READONLY_STATES, select=True, copy=False, default=fields.Datetime.now,\
date_order = fields.Datetime('Order Date', required=True, states=READONLY_STATES, index=True, copy=False, default=fields.Datetime.now,\
help="Depicts the date where the Quotation should be validated and converted into a purchase order.")
date_approve = fields.Date('Approval Date', readonly=1, select=True, copy=False)
date_approve = fields.Date('Approval Date', readonly=1, index=True, copy=False)
partner_id = fields.Many2one('res.partner', string='Vendor', required=True, states=READONLY_STATES, change_default=True, track_visibility='always')
dest_address_id = fields.Many2one('res.partner', string='Drop Ship Address', states=READONLY_STATES,\
help="Put an address if you want to deliver directly from the vendor to the customer. "\
@@ -121,7 +122,7 @@ class PurchaseOrder(models.Model):
('purchase', 'Purchase Order'),
('done', 'Locked'),
('cancel', 'Cancelled')
], string='Status', readonly=True, select=True, copy=False, default='draft', track_visibility='onchange')
], string='Status', readonly=True, index=True, copy=False, default='draft', track_visibility='onchange')
order_line = fields.One2many('purchase.order.line', 'order_id', string='Order Lines', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True)
notes = fields.Text('Terms and Conditions')
@@ -137,7 +138,7 @@ class PurchaseOrder(models.Model):
picking_ids = fields.Many2many('stock.picking', compute='_compute_picking', string='Receptions', copy=False)
# There is no inverse function on purpose since the date may be different on each line
date_planned = fields.Datetime(string='Scheduled Date', compute='_compute_date_planned', store=True, select=True, oldname='minimum_planned_date')
date_planned = fields.Datetime(string='Scheduled Date', compute='_compute_date_planned', store=True, index=True, oldname='minimum_planned_date')
amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all', track_visibility='always')
amount_tax = fields.Monetary(string='Taxes', store=True, readonly=True, compute='_amount_all')
@@ -149,7 +150,7 @@ class PurchaseOrder(models.Model):
product_id = fields.Many2one('product.product', related='order_line.product_id', string='Product')
create_uid = fields.Many2one('res.users', 'Responsible')
company_id = fields.Many2one('res.company', 'Company', required=True, select=1, states=READONLY_STATES, default=lambda self: self.env.user.company_id.id)
company_id = fields.Many2one('res.company', 'Company', required=True, index=True, states=READONLY_STATES, default=lambda self: self.env.user.company_id.id)
picking_type_id = fields.Many2one('stock.picking.type', 'Deliver To', states=READONLY_STATES, required=True, default=_default_picking_type,\
help="This will determine picking type of incoming shipment")
@@ -548,7 +549,7 @@ class PurchaseOrderLine(models.Model):
name = fields.Text(string='Description', required=True)
sequence = fields.Integer(string='Sequence', default=10)
product_qty = fields.Float(string='Quantity', digits=dp.get_precision('Product Unit of Measure'), required=True)
date_planned = fields.Datetime(string='Scheduled Date', required=True, select=True)
date_planned = fields.Datetime(string='Scheduled Date', required=True, index=True)
taxes_id = fields.Many2many('account.tax', string='Taxes', domain=['|', ('active', '=', False), ('active', '=', True)])
product_uom = fields.Many2one('product.uom', string='Product Unit of Measure', required=True)
product_id = fields.Many2one('product.product', string='Product', domain=[('purchase_ok', '=', True)], change_default=True, required=True)
@@ -559,7 +560,7 @@ class PurchaseOrderLine(models.Model):
price_total = fields.Monetary(compute='_compute_amount', string='Total', store=True)
price_tax = fields.Monetary(compute='_compute_amount', string='Tax', store=True)
order_id = fields.Many2one('purchase.order', string='Order Reference', select=True, required=True, ondelete='cascade')
order_id = fields.Many2one('purchase.order', string='Order Reference', index=True, required=True, ondelete='cascade')
account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags')
company_id = fields.Many2one('res.company', related='order_id.company_id', string='Company', store=True, readonly=True)
@@ -776,6 +777,7 @@ class PurchaseOrderLine(models.Model):
class ProcurementRule(models.Model):
_inherit = 'procurement.rule'
@api.model
def _get_action(self):
return [('buy', _('Buy'))] + super(ProcurementRule, self)._get_action()
@@ -1052,6 +1054,7 @@ class ProductProduct(models.Model):
purchase_count = fields.Integer(compute='_purchase_count', string='# Purchases')
class ProductCategory(models.Model):
_inherit = "product.category"
+5 -5
View File
@@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp import fields, models
from odoo import fields, models
class company(models.Model):
class Company(models.Model):
_inherit = 'res.company'
po_lead = fields.Float(string='Purchase Lead Time', required=True,\
po_lead = fields.Float(string='Purchase Lead Time', required=True,
help="Margin of error for vendor lead times. When the system "
"generates Purchase Orders for procuring products, "
"they will be scheduled that many days earlier "
@@ -21,8 +21,8 @@ class company(models.Model):
po_double_validation = fields.Selection([
('one_step', 'Confirm purchase orders in one step'),
('two_step', 'Get 2 levels of approvals to confirm a purchase order')
], string="Levels of Approvals", default='one_step',\
], string="Levels of Approvals", default='one_step',
help="Provide a double validation mechanism for purchases")
po_double_validation_amount = fields.Monetary(string='Double validation amount', default=5000,\
po_double_validation_amount = fields.Monetary(string='Double validation amount', default=5000,
help="Minimum amount for which a double validation is required")
+47 -52
View File
@@ -1,62 +1,57 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp import SUPERUSER_ID
from openerp.osv import fields, osv
from openerp.tools.translate import _
from odoo import fields, models
class purchase_config_settings(osv.osv_memory):
class PurchaseConfigSettings(models.TransientModel):
_name = 'purchase.config.settings'
_inherit = 'res.config.settings'
_columns = {
'group_product_variant': fields.selection([
(0, "No variants on products"),
(1, 'Products can have several attributes, defining variants (Example: size, color,...)')
], "Product Variants",
help='Work with product variant allows you to define some variant of the same products, an ease the product management in the ecommerce for example',
implied_group='product.group_product_variant'),
'group_uom':fields.selection([
(0, 'Products have only one unit of measure (easier)'),
(1, 'Some products may be sold/puchased in different units of measure (advanced)')
], "Units of Measure",
implied_group='product.group_uom',
help="""Allows you to select and maintain different units of measure for products."""),
'group_costing_method':fields.selection([
(0, 'Set a fixed cost price on each product'),
(1, "Use a 'Fixed', 'Real' or 'Average' price costing method")
], "Costing Methods",
implied_group='stock_account.group_inventory_valuation',
help="""Allows you to compute product cost price based on average cost."""),
'module_purchase_requisition': fields.selection([
(0, 'Purchase propositions trigger draft purchase orders to a single supplier'),
(1, 'Allow using call for tenders to get quotes from multiple suppliers (advanced)')
], "Calls for Tenders",
help="Calls for tenders are used when you want to generate requests for quotations to several vendors for a given set of products.\n"
"You can configure per product if you directly do a Request for Quotation "
"to one vendor or if you want a Call for Tenders to compare offers from several vendors."),
'group_warning_purchase': fields.selection([
(0, 'All the products and the customers can be used in purchase orders'),
(1, 'An informative or blocking warning can be set on a product or a customer')
], "Warning", implied_group='purchase.group_warning_purchase'),
'module_stock_dropshipping': fields.selection([
(0, 'Suppliers always deliver to your warehouse(s)'),
(1, "Allow suppliers to deliver directly to your customers")
], "Dropshipping",
help='\nCreates the dropship Route and add more complex tests\n'
'-This installs the module stock_dropshipping.'),
'group_manage_vendor_price': fields.selection([
(0, 'Manage vendor price on the product form'),
(1, 'Allow using and importing vendor pricelists')
], "Vendor Price",
implied_group="purchase.group_manage_vendor_price"),
}
group_product_variant = fields.Selection([
(0, "No variants on products"),
(1, 'Products can have several attributes, defining variants (Example: size, color,...)')
], "Product Variants",
help='Work with product variant allows you to define some variant of the same products, an ease the product management in the ecommerce for example',
implied_group='product.group_product_variant')
group_uom = fields.Selection([
(0, 'Products have only one unit of measure (easier)'),
(1, 'Some products may be sold/puchased in different units of measure (advanced)')
], "Units of Measure",
implied_group='product.group_uom',
help="""Allows you to select and maintain different units of measure for products.""")
group_costing_method = fields.Selection([
(0, 'Set a fixed cost price on each product'),
(1, "Use a 'Fixed', 'Real' or 'Average' price costing method")
], "Costing Methods",
implied_group='stock_account.group_inventory_valuation',
help="""Allows you to compute product cost price based on average cost.""")
module_purchase_requisition = fields.Selection([
(0, 'Purchase propositions trigger draft purchase orders to a single supplier'),
(1, 'Allow using call for tenders to get quotes from multiple suppliers (advanced)')
], "Calls for Tenders",
help="Calls for tenders are used when you want to generate requests for quotations to several vendors for a given set of products.\n"
"You can configure per product if you directly do a Request for Quotation "
"to one vendor or if you want a Call for Tenders to compare offers from several vendors.")
group_warning_purchase = fields.Selection([
(0, 'All the products and the customers can be used in purchase orders'),
(1, 'An informative or blocking warning can be set on a product or a customer')
], "Warning", implied_group='purchase.group_warning_purchase')
module_stock_dropshipping = fields.Selection([
(0, 'Suppliers always deliver to your warehouse(s)'),
(1, "Allow suppliers to deliver directly to your customers")
], "Dropshipping",
help='\nCreates the dropship Route and add more complex tests\n'
'-This installs the module stock_dropshipping.')
group_manage_vendor_price = fields.Selection([
(0, 'Manage vendor price on the product form'),
(1, 'Allow using and importing vendor pricelists')
], "Vendor Price",
implied_group="purchase.group_manage_vendor_price")
class account_config_settings(osv.osv_memory):
class AccountConfigSettings(models.TransientModel):
_inherit = 'account.config.settings'
_columns = {
'group_analytic_account_for_purchases': fields.boolean('Analytic accounting for purchases',
implied_group='purchase.group_analytic_accounting',
help="Allows you to specify an analytic account on purchase order lines."),
}
group_analytic_account_for_purchases = fields.Boolean('Analytic accounting for purchases',
implied_group='purchase.group_analytic_accounting',
help="Allows you to specify an analytic account on purchase order lines.")
+3 -2
View File
@@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp import api, fields, models
from openerp.addons.base.res.res_partner import WARNING_MESSAGE, WARNING_HELP
from odoo import api, fields, models
from odoo.addons.base.res.res_partner import WARNING_MESSAGE, WARNING_HELP
class res_partner(models.Model):
_name = 'res.partner'
+63 -72
View File
@@ -1,20 +1,19 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp import api
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.exceptions import UserError
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class stock_picking(osv.osv):
class StockPicking(models.Model):
_inherit = 'stock.picking'
_columns = {
'purchase_id': fields.related('move_lines', 'purchase_line_id', 'order_id', string="Purchase Orders",
readonly=True, type="many2one", relation="purchase.order"),
}
def _prepare_values_extra_move(self, cr, uid, op, product, remaining_qty, context=None):
res = super(stock_picking, self)._prepare_values_extra_move(cr, uid, op, product, remaining_qty, context=context)
purchase_id = fields.Many2one('purchase.order', related='move_lines.purchase_line_id.order_id',
string="Purchase Orders", readonly=True)
@api.model
def _prepare_values_extra_move(self, op, product, remaining_qty):
res = super(StockPicking, self)._prepare_values_extra_move(op, product, remaining_qty)
for m in op.linked_move_operation_ids:
if m.move_id.purchase_line_id and m.move_id.product_id == product:
res['purchase_line_id'] = m.move_id.purchase_line_id.id
@@ -23,7 +22,7 @@ class stock_picking(osv.osv):
@api.model
def _create_backorder(self, backorder_moves=[]):
res = super(stock_picking, self)._create_backorder(backorder_moves)
res = super(StockPicking, self)._create_backorder(backorder_moves)
for picking in self:
if picking.picking_type_id.code == 'incoming':
backorder = self.search([('backorder_id', '=', picking.id)])
@@ -32,13 +31,12 @@ class stock_picking(osv.osv):
subtype_id=self.env.ref('mail.mt_note').id)
return res
class stock_move(osv.osv):
class StockMove(models.Model):
_inherit = 'stock.move'
_columns = {
'purchase_line_id': fields.many2one('purchase.order.line',
'Purchase Order Line', ondelete='set null', select=True,
readonly=True),
}
purchase_line_id = fields.Many2one('purchase.order.line',
'Purchase Order Line', ondelete='set null', index=True, readonly=True)
@api.multi
def get_price_unit(self):
@@ -56,95 +54,88 @@ class stock_move(osv.osv):
self.write({'price_unit': price_unit})
return price_unit
return self.price_unit
return super(stock_move, self).get_price_unit()
return super(StockMove, self).get_price_unit()
def copy(self, cr, uid, id, default=None, context=None):
@api.multi
def copy(self, default=None):
self.ensure_one()
default = default or {}
context = context or {}
if not default.get('split_from'):
#we don't want to propagate the link to the purchase order line except in case of move split
default['purchase_line_id'] = False
return super(stock_move, self).copy(cr, uid, id, default, context)
return super(StockMove, self).copy(default)
class stock_warehouse(osv.osv):
class StockWarehouse(models.Model):
_inherit = 'stock.warehouse'
_columns = {
'buy_to_resupply': fields.boolean('Purchase to resupply this warehouse',
help="When products are bought, they can be delivered to this warehouse"),
'buy_pull_id': fields.many2one('procurement.rule', 'Buy rule'),
}
_defaults = {
'buy_to_resupply': True,
}
def _get_buy_pull_rule(self, cr, uid, warehouse, context=None):
route_obj = self.pool.get('stock.location.route')
data_obj = self.pool.get('ir.model.data')
buy_to_resupply = fields.Boolean('Purchase to resupply this warehouse', default=True,
help="When products are bought, they can be delivered to this warehouse")
buy_pull_id = fields.Many2one('procurement.rule', 'Buy rule')
@api.multi
def _get_buy_pull_rule(self):
try:
buy_route_id = data_obj.get_object_reference(cr, uid, 'purchase', 'route_warehouse0_buy')[1]
buy_route_id = self.env['ir.model.data'].get_object_reference('purchase', 'route_warehouse0_buy')[1]
except:
buy_route_id = route_obj.search(cr, uid, [('name', 'like', _('Buy'))], context=context)
buy_route_id = buy_route_id and buy_route_id[0] or False
buy_route_id = self.env['stock.location.route'].search([('name', 'like', _('Buy'))])
buy_route_id = buy_route_id[0].id if buy_route_id else False
if not buy_route_id:
raise UserError(_('Can\'t find any generic Buy route.'))
raise UserError(_("Can't find any generic Buy route."))
return {
'name': warehouse._format_routename(_(' Buy')),
'location_id': warehouse.in_type_id.default_location_dest_id.id,
'name': self._format_routename(_(' Buy')),
'location_id': self.in_type_id.default_location_dest_id.id,
'route_id': buy_route_id,
'action': 'buy',
'picking_type_id': warehouse.in_type_id.id,
'warehouse_id': warehouse.id,
'picking_type_id': self.in_type_id.id,
'warehouse_id': self.id,
'group_propagation_option': 'none',
}
def create_routes(self, cr, uid, ids, context=None):
pull_obj = self.pool.get('procurement.rule')
res = super(stock_warehouse, self).create_routes(cr, uid, ids, context=context)
warehouse = self.browse(cr, uid, ids, context=context)[0]
if warehouse.buy_to_resupply:
buy_pull_vals = self._get_buy_pull_rule(cr, uid, warehouse, context=context)
buy_pull_id = pull_obj.create(cr, uid, buy_pull_vals, context=context)
res['buy_pull_id'] = buy_pull_id
@api.multi
def create_routes(self):
res = super(StockWarehouse, self).create_routes() # super applies ensure_one()
if self.buy_to_resupply:
buy_pull_vals = self._get_buy_pull_rule()
buy_pull = self.env['procurement.rule'].create(buy_pull_vals)
res['buy_pull_id'] = buy_pull.id
return res
def write(self, cr, uid, ids, vals, context=None):
pull_obj = self.pool.get('procurement.rule')
if isinstance(ids, (int, long)):
ids = [ids]
@api.multi
def write(self, vals):
if 'buy_to_resupply' in vals:
if vals.get("buy_to_resupply"):
for warehouse in self.browse(cr, uid, ids, context=context):
for warehouse in self:
if not warehouse.buy_pull_id:
buy_pull_vals = self._get_buy_pull_rule(cr, uid, warehouse, context=context)
buy_pull_id = pull_obj.create(cr, uid, buy_pull_vals, context=context)
vals['buy_pull_id'] = buy_pull_id
buy_pull_vals = self._get_buy_pull_rule()
buy_pull = self.env['procurement.rule'].create(buy_pull_vals)
vals['buy_pull_id'] = buy_pull.id
else:
for warehouse in self.browse(cr, uid, ids, context=context):
for warehouse in self:
if warehouse.buy_pull_id:
buy_pull_id = pull_obj.unlink(cr, uid, warehouse.buy_pull_id.id, context=context)
return super(stock_warehouse, self).write(cr, uid, ids, vals, context=None)
warehouse.buy_pull_id.unlink()
return super(StockWarehouse, self).write(vals)
@api.multi
def _get_all_routes(self):
routes = super(stock_warehouse, self).get_all_routes_for_wh()
routes = super(StockWarehouse, self).get_all_routes_for_wh()
routes |= self.filtered(lambda self: self.buy_to_resupply and self.buy_pull_id and self.buy_pull_id.route_id).mapped('buy_pull_id').mapped('route_id')
return routes
def _handle_renaming(self, cr, uid, ids, name, code, context=None):
res = super(stock_warehouse, self)._handle_renaming(cr, uid, ids, name, code, context=context)
warehouse = self.browse(cr, uid, ids[0], context=context)
pull_obj = self.pool.get('procurement.rule')
@api.multi
def _handle_renaming(self, name, code):
res = super(StockWarehouse, self)._handle_renaming(name, code)
warehouse = self[0]
#change the buy procurement rule name
if warehouse.buy_pull_id:
pull_obj.write(cr, uid, warehouse.buy_pull_id.id, {'name': warehouse.buy_pull_id.name.replace(warehouse.name, name, 1)}, context=context)
warehouse.buy_pull_id.write({'name': warehouse.buy_pull_id.name.replace(warehouse.name, name, 1)})
return res
def change_route(self, cr, uid, ids, context=None):
res = super(stock_warehouse, self).change_route(cr, uid, ids, context=context)
for warehouse in self.browse(cr, uid, ids[0], context=context):
@api.multi
def change_route(self):
res = super(StockWarehouse, self).change_route()
for warehouse in self:
if warehouse.in_type_id.default_location_dest_id != warehouse.buy_pull_id.location_id:
self.pool.get('procurement.rule').write(cr, uid, warehouse.buy_pull_id.id, {'location_id': warehouse.in_type_id.default_location_dest_id.id}, context=context)
warehouse.buy_pull_id.write({'location_id': warehouse.in_type_id.default_location_dest_id.id})
return res
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<template id="report_purchaseorder_document">
<t t-call="report.external_layout">
<t t-set="o" t-value="o.with_context({'lang':o.partner_id.lang})"/>
@@ -123,5 +122,4 @@
</t>
</t>
</template>
</data>
</openerp>
</odoo>
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<template id="report_purchasequotation_document">
<t t-call="report.external_layout">
<t t-set="o" t-value="o.with_context({'lang':o.partner_id.lang})"/>
@@ -67,6 +66,5 @@
</t>
</t>
</template>
</data>
</openerp>
</odoo>
+40 -38
View File
@@ -5,50 +5,52 @@
# Please note that these reports are not multi-currency !!!
#
from openerp.osv import fields,osv
from openerp import tools
from odoo import fields, models
from odoo import tools
class purchase_report(osv.osv):
class PurchaseReport(models.Model):
_name = "purchase.report"
_description = "Purchases Orders"
_auto = False
_columns = {
'date_order': fields.datetime('Order Date', readonly=True, help="Date on which this document has been created", oldname='date'),
'state': fields.selection([('draft', 'Draft RFQ'),
('sent', 'RFQ Sent'),
('to approve', 'To Approve'),
('purchase', 'Purchase Order'),
('done', 'Done'),
('cancel', 'Cancelled')
],'Order Status', readonly=True),
'product_id':fields.many2one('product.product', 'Product', readonly=True),
'picking_type_id': fields.many2one('stock.warehouse', 'Warehouse', readonly=True),
'partner_id':fields.many2one('res.partner', 'Vendor', readonly=True),
'date_approve':fields.date('Date Approved', readonly=True),
'product_uom' : fields.many2one('product.uom', 'Reference Unit of Measure', required=True),
'company_id':fields.many2one('res.company', 'Company', readonly=True),
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
'user_id':fields.many2one('res.users', 'Responsible', readonly=True),
'delay':fields.float('Days to Validate', digits=(16,2), readonly=True),
'delay_pass':fields.float('Days to Deliver', digits=(16,2), readonly=True),
'unit_quantity': fields.float('Product Quantity', readonly=True, oldname='quantity'),
'price_total': fields.float('Total Price', readonly=True),
'price_average': fields.float('Average Price', readonly=True, group_operator="avg"),
'negociation': fields.float('Purchase-Standard Price', readonly=True, group_operator="avg"),
'price_standard': fields.float('Products Value', readonly=True, group_operator="sum"),
'nbr_lines': fields.integer('# of Lines', readonly=True, oldname='nbr'),
'category_id': fields.many2one('product.category', 'Product Category', readonly=True),
'product_tmpl_id': fields.many2one('product.template', 'Product Template', readonly=True),
'country_id': fields.many2one('res.country', 'Partner Country', readonly=True),
'fiscal_position_id': fields.many2one('account.fiscal.position', string='Fiscal Position', oldname='fiscal_position', readonly=True),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True),
'commercial_partner_id': fields.many2one('res.partner', 'Commercial Entity', readonly=True),
'weight': fields.float('Gross Weight', readonly=True),
'volume': fields.float('Volume', readonly=True),
}
_order = 'date_order desc, price_total desc'
date_order = fields.Datetime('Order Date', readonly=True, help="Date on which this document has been created", oldname='date')
state = fields.Selection([
('draft', 'Draft RFQ'),
('sent', 'RFQ Sent'),
('to approve', 'To Approve'),
('purchase', 'Purchase Order'),
('done', 'Done'),
('cancel', 'Cancelled')
], 'Order Status', readonly=True)
product_id = fields.Many2one('product.product', 'Product', readonly=True)
picking_type_id = fields.Many2one('stock.warehouse', 'Warehouse', readonly=True)
partner_id = fields.Many2one('res.partner', 'Vendor', readonly=True)
date_approve = fields.Date('Date Approved', readonly=True)
product_uom = fields.Many2one('product.uom', 'Reference Unit of Measure', required=True)
company_id = fields.Many2one('res.company', 'Company', readonly=True)
currency_id = fields.Many2one('res.currency', 'Currency', readonly=True)
user_id = fields.Many2one('res.users', 'Responsible', readonly=True)
delay = fields.Float('Days to Validate', digits=(16, 2), readonly=True)
delay_pass = fields.Float('Days to Deliver', digits=(16, 2), readonly=True)
unit_quantity = fields.Float('Product Quantity', readonly=True, oldname='quantity')
price_total = fields.Float('Total Price', readonly=True)
price_average = fields.Float('Average Price', readonly=True, group_operator="avg")
negociation = fields.Float('Purchase-Standard Price', readonly=True, group_operator="avg")
price_standard = fields.Float('Products Value', readonly=True, group_operator="sum")
nbr_lines = fields.Integer('# of Lines', readonly=True, oldname='nbr')
category_id = fields.Many2one('product.category', 'Product Category', readonly=True)
product_tmpl_id = fields.Many2one('product.template', 'Product Template', readonly=True)
country_id = fields.Many2one('res.country', 'Partner Country', readonly=True)
fiscal_position_id = fields.Many2one('account.fiscal.position', string='Fiscal Position', oldname='fiscal_position', readonly=True)
account_analytic_id = fields.Many2one('account.analytic.account', 'Analytic Account', readonly=True)
commercial_partner_id = fields.Many2one('res.partner', 'Commercial Entity', readonly=True)
weight = fields.Float('Gross Weight', readonly=True)
volume = fields.Float('Volume', readonly=True)
def init(self, cr):
tools.sql.drop_view_if_exists(cr, 'purchase_report')
tools.sql.drop_view_if_exists(cr, 'purchase_report') # to remove, 2 lines below : create or replace.
cr.execute("""
create or replace view purchase_report as (
WITH currency_rate as (%s)
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<record model="ir.ui.view" id="view_purchase_order_pivot">
<field name="name">product.month.pivot</field>
<field name="model">purchase.report</field>
@@ -95,5 +94,4 @@
<menuitem id="base.purchase_report" name="Reports" parent="base.menu_purchase_root" sequence="99"
groups="purchase.group_purchase_manager" action="action_purchase_order_report_all"/>
</data>
</openerp>
</odoo>
+2 -4
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<report
string="Purchase Order"
id="action_report_purchase_order"
@@ -18,5 +17,4 @@
name="purchase.report_purchasequotation"
file="purchase.report_purchasequotation"
/>
</data>
</openerp>
</odoo>
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<odoo>
<data noupdate="0">
<record id="group_purchase_user" model="res.groups">
@@ -53,4 +53,4 @@
</record>
</data>
</openerp>
</odoo>
+29 -31
View File
@@ -28,8 +28,8 @@
-
I confirm the first purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_average1")])
!python {model: purchase.order, id: purchase_order_average1}: |
self.button_confirm()
-
I check the "Approved" status of purchase order 1
-
@@ -38,16 +38,15 @@
-
Process the reception of purchase order 1
-
!python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average1")).picking_ids
self.do_transfer(cr, uid, [pick_ids[0].id])
!python {model: purchase.order, id: purchase_order_average1}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
Check the standard price of the product (average icecream).
-
!python {model: product.product}: |
product = self.browse(cr, uid, ref("product_average_icecream"))
assert product.qty_available == 10.0, 'Wrong quantity in stock after first reception'
assert product.standard_price == 60.0, 'Standard price should be the price of the first reception!'
!python {model: product.product, id: product_average_icecream}: |
assert self.qty_available == 10.0, 'Wrong quantity in stock after first reception'
assert self.standard_price == 60.0, 'Standard price should be the price of the first reception!'
-
I create a draft Purchase Order for second incoming shipment for 30 pieces at 80€
-
@@ -63,19 +62,19 @@
-
I confirm the second purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_average2")])
!python {model: purchase.order, id: purchase_order_average2}: |
self.button_confirm()
-
Process the reception of purchase order 2
-
!python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average2")).picking_ids
self.do_transfer(cr, uid, [pick_ids[0].id])
!python {model: purchase.order, id: purchase_order_average2}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
Check the standard price
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_average_icecream")).standard_price == 75.0, 'After second reception, we should have an average price of 75.0 on the product'
!python {model: product.product, id: product_average_icecream}: |
assert self.standard_price == 75.0, 'After second reception, we should have an average price of 75.0 on the product'
-
Create picking to send some goods
-
@@ -94,15 +93,15 @@
-
I assign this outgoing shipment and process the delivery
-
!python {model: stock.picking}: |
self.action_assign(cr, uid, [ref("outgoing_average_shipment")])
self.do_transfer(cr, uid, [ref("outgoing_average_shipment")])
!python {model: stock.picking, id: outgoing_average_shipment}: |
self.action_assign()
self.do_transfer()
-
Check the standard price (60 * 10 + 30 * 80) / 40 = 75.0 did not change
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_average_icecream")).standard_price == 75.0, 'Standard price should not have changed with outgoing picking!'
assert self.browse(cr, uid, ref("product_average_icecream")).qty_available == 20.0, 'Pieces were not picked correctly as the quantity on hand is wrong'
!python {model: product.product, id: product_average_icecream}: |
assert self.standard_price == 75.0, 'Standard price should not have changed with outgoing picking!'
assert self.qty_available == 20.0, 'Pieces were not picked correctly as the quantity on hand is wrong'
-
Make a new purchase order with 500 g Average Ice Cream at a price of 0.2€/g
-
@@ -118,18 +117,17 @@
-
I confirm the first purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_average3")])
!python {model: purchase.order, id: purchase_order_average3}: |
self.button_confirm()
-
Process the reception of purchase order 3 in grams
-
!python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average3")).picking_ids
self.do_transfer(cr, uid, [pick_ids[0].id])
!python {model: purchase.order, id: purchase_order_average3}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
Check price is (75.0*20 + 200*0.5) / 20.5 = 78.04878
-
!python {model: product.product}: |
product = self.browse(cr, uid, ref("product_average_icecream"))
assert product.qty_available == 20.5, 'Reception of purchase order in grams leads to wrong quantity in stock'
assert round(self.browse(cr, uid, ref("product_average_icecream")).standard_price, 2) == 78.05, 'Standard price as average price of third reception with other UoM incorrect! Got %s instead of 78.05' % (round(self.browse(cr, uid, ref("product_average_icecream")).standard_price, 2),)
!python {model: product.product, id: product_average_icecream}: |
assert self.qty_available == 20.5, 'Reception of purchase order in grams leads to wrong quantity in stock'
assert round(self.standard_price, 2) == 78.05, 'Standard price as average price of third reception with other UoM incorrect! Got %s instead of 78.05' % (round(self.standard_price, 2),)
+33 -34
View File
@@ -39,13 +39,13 @@
-
I confirm the first purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_variable1")])
!python {model: purchase.order, id: purchase_order_variable1}: |
self.button_confirm()
-
I confirm the second purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_variable2")])
!python {model: purchase.order, id: purchase_order_variable2}: |
self.button_confirm()
-
I check the "Approved" status of purchase order 1
-
@@ -54,30 +54,29 @@
-
Process the reception of purchase order 1
-
!python {model: stock.partial.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_variable1")).picking_ids
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_transfer(cr, uid, [partial_id])
!python {model: stock.partial.picking, id: False}: |
pickings = self.env['purchase.order'].browse(ref("purchase_order_variable1")).picking_ids
partial = self.with_context({'active_model': 'stock.picking','active_ids': [pickings[0].id]}).create({})
partial.do_transfer()
-
Check the standard price of the product (variable icecream).
-
!python {model: product.product}: |
product = self.browse(cr, uid, ref("product_variable_icecream"))
assert product.qty_available == 10.0, 'Wrong quantity in stock after first reception'
assert product.standard_price == 60.0, 'Standard price should be the price of the first reception!'
!python {model: product.product, id: product_variable_icecream}: |
assert self.qty_available == 10.0, 'Wrong quantity in stock after first reception'
assert self.standard_price == 60.0, 'Standard price should be the price of the first reception!'
-
Process the reception of purchase order 2
-
!python {model: stock.partial.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_variable2")).picking_ids
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_transfer(cr, uid, [partial_id])
!python {model: stock.partial.picking, id: False}: |
pickings = self.env['purchase.order'].browse(ref("purchase_order_variable2")).picking_ids
partial = self.with_context({'active_model': 'stock.picking','active_ids': [pickings[0].id]}).create({})
partial.do_transfer()
-
Check the standard price and change the product's cost method towards fifo
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_variable_icecream")).standard_price == 75.0, 'After second reception, we should have an average price of 75.0 on the product'
self.write(cr, uid, [ref("product_variable_icecream")], {'cost_method': 'real'}, context=context)
!python {model: product.product, id: product_variable_icecream}: |
assert self.standard_price == 75.0, 'After second reception, we should have an average price of 75.0 on the product'
self.write({'cost_method': 'real'})
-
Create picking to send some goods
-
@@ -99,15 +98,15 @@
-
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_variable_shipment")], 'default_type':'out'})
self.do_transfer(cr, uid, [partial_id])
!python {model: stock.partial.picking, id: False}: |
partial = self.with_context({'active_model': 'stock.picking','active_ids': [ref("outgoing_variable_shipment")], 'default_type':'out'}).create({})
partial.do_transfer()
-
Check the standard price (60 * 10 + 30 * 80) / 40 = 75.0 did not change
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_variable_icecream")).standard_price == 75.0, 'Standard price should not have changed with outgoing picking!'
assert self.browse(cr, uid, ref("product_variable_icecream")).qty_available == 20.0, 'Pieces were not picked correctly as the quantity on hand is wrong'
!python {model: product.product, id: product_variable_icecream}: |
assert self.standard_price == 75.0, 'Standard price should not have changed with outgoing picking!'
assert self.qty_available == 20.0, 'Pieces were not picked correctly as the quantity on hand is wrong'
-
I create a draft Purchase Order for third incoming shipment for 20 pieces at 60 euro
-
@@ -122,18 +121,18 @@
-
I confirm this third purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_variable3")])
!python {model: purchase.order, id: purchase_order_variable3}: |
self.button_confirm()
-
Process the reception of purchase order 3
-
!python {model: stock.partial.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_variable3")).picking_ids
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_transfer(cr, uid, [partial_id])
!python {model: stock.partial.picking, id: False}: |
pickings = self.env['purchase.order'].browse(ref("purchase_order_variable3")).picking_ids
partial = self.with_context({'active_model': 'stock.picking','active_ids': [pickings[0].id]}).create({})
partial.do_transfer()
-
Change the cost method back to average and check price on product changed back to 70.0 = (20*60 + 10*60 + 30*80) / 60
-
!python {model: product.product}: |
self.write(cr, uid, [ref("product_variable_icecream")], {'cost_method': 'average'}, context=context)
assert self.browse(cr, uid, ref("product_variable_icecream")).standard_price == 70.0, 'After third reception and changing to average again, we should have an average price of 70.0 on the product'
!python {model: product.product, id: product_variable_icecream}: |
self.write({'cost_method': 'average'})
assert self.standard_price == 70.0, 'After third reception and changing to average again, we should have an average price of 70.0 on the product'
+63 -70
View File
@@ -36,8 +36,8 @@
-
I confirm the first purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_fifo1")])
!python {model: purchase.order, id: purchase_order_fifo1}: |
self.button_confirm()
-
I check the "Purchase" status of purchase order 1
-
@@ -46,14 +46,14 @@
-
Process the reception of purchase order 1 and set date
-
!python {model: stock.picking}: |
picking_obj = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo1"), context=context).picking_ids[0]
picking_obj.do_transfer()
!python {model: purchase.order, id: purchase_order_fifo1}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
Check the standard price of the product (fifo icecream), that should have not changed because the standard price is supposed to be updated only when goods are going out of the stock
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 70.0, 'Standard price should not have changed!'
!python {model: product.product, id: product_fifo_icecream}: |
assert self.standard_price == 70.0, 'Standard price should not have changed!'
-
I create a draft Purchase Order for second shipment for 30 kg at 80 euro
-
@@ -69,19 +69,19 @@
-
I confirm the second purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_fifo2")])
!python {model: purchase.order, id: purchase_order_fifo2}: |
self.button_confirm()
-
Process the reception of purchase order 2
-
!python {model: stock.picking}: |
picking_obj = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo2"), context=context).picking_ids[0]
picking_obj.do_transfer()
!python {model: purchase.order, id: purchase_order_fifo2}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
Check the standard price of the product, that should have not changed because the standard price is supposed to be updated only when goods are going out of the stock
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 70.0, 'Standard price as fifo price of second reception incorrect!'
!python {model: product.product, id: product_fifo_icecream}: |
assert self.standard_price == 70.0, 'Standard price as fifo price of second reception incorrect!'
-
Let us send some goods
-
@@ -101,19 +101,18 @@
-
I assign this outgoing shipment
-
!python {model: stock.picking}: |
self.action_assign(cr, uid, [ref("outgoing_fifo_shipment")])
!python {model: stock.picking, id: outgoing_fifo_shipment}: |
self.action_assign()
-
Process the delivery of the outgoing shipment
-
!python {model: stock.picking}: |
pick_obj = self.pool.get('stock.picking').browse(cr, uid, ref("outgoing_fifo_shipment"), context=context)
pick_obj.do_transfer()
!python {model: stock.picking, id: outgoing_fifo_shipment}: |
self.do_transfer()
-
Check product standard price changed to 65.0 (because last outgoing shipment was made of 10 kg at 50€ and 10 kg at 80€)
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 65.0, "Product price not updated accordingly. %s found instead of 65" %(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price,)
!python {model: product.product, id: product_fifo_icecream}: |
assert self.standard_price == 65.0, "Product price not updated accordingly. %s found instead of 65" % (self.standard_price,)
-
Do a delivery of an extra 500 g (delivery order)
-
@@ -133,19 +132,18 @@
-
I assign this outgoing shipment
-
!python {model: stock.picking}: |
self.action_assign(cr, uid, [ref("outgoing_fifo_shipment_uom")])
!python {model: stock.picking, id: outgoing_fifo_shipment_uom}: |
self.action_assign()
-
Process the delivery of the outgoing shipment
-
!python {model: stock.picking}: |
pick_obj = self.pool.get('stock.picking').browse(cr, uid, ref("outgoing_fifo_shipment_uom"), context=context)
pick_obj.do_transfer()
!python {model: stock.picking, id: outgoing_fifo_shipment_uom}: |
self.do_transfer()
-
Check product price changed to 80.0 (because last outgoing shipment was made of 0.5 kg at 80€)
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 80.0, "Product price not updated accordingly. %s found instead of 80" %(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price,)
!python {model: product.product, id: product_fifo_icecream}: |
assert self.standard_price == 80.0, "Product price not updated accordingly. %s found instead of 80" % (self.standard_price,)
-
We will temporarily change the currency rate on the sixth of June to have the same results all year
-
@@ -179,14 +177,14 @@
-
I confirm the purchase order in USD
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_fifo_usd")])
!python {model: purchase.order, id: purchase_order_fifo_usd}: |
self.button_confirm()
-
Process the reception of purchase order with usd
-
!python {model: stock.picking}: |
pick_obj = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo_usd"), context=context).picking_ids[0]
pick_obj.do_transfer()
!python {model: purchase.order, id: purchase_order_fifo_usd}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
We create delivery order of 49.5 kg
-
@@ -206,19 +204,18 @@
-
I assign this outgoing shipment
-
!python {model: stock.picking}: |
self.action_assign(cr, uid, [ref("outgoing_fifo_shipment_cur")])
!python {model: stock.picking, id: outgoing_fifo_shipment_cur}: |
self.action_assign()
-
Process the delivery of the outgoing shipment
-
!python {model: stock.picking}: |
picking_obj = self.pool.get('stock.picking').browse(cr, uid, ref("outgoing_fifo_shipment_cur"), context=context)
picking_obj.do_transfer()
!python {model: stock.picking, id: outgoing_fifo_shipment_cur}: |
self.do_transfer()
-
Check rounded price is 102 euro (because last outgoing shipment was made of 19.5kg at 80€ and 30kg at $150 (rate=1.2834)
-
!python {model: product.product}: |
assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == 102, "Product price not updated accordingly. %s found instead of 102 (rounded values)" %(round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price),)
!python {model: product.product, id: product_fifo_icecream}: |
assert round(self.standard_price) == 102, "Product price not updated accordingly. %s found instead of 102 (rounded values)" %(round(self.standard_price),)
-
Do a delivery of an extra 10 kg
-
@@ -238,21 +235,19 @@
-
I assign this outgoing shipment
-
!python {model: stock.picking}: |
self.action_assign(cr, uid, [ref("outgoing_fifo_shipment_ret")])
!python {model: stock.picking, id: outgoing_fifo_shipment_ret}: |
self.action_assign()
-
Process the delivery of the outgoing shipment
-
!python {model: stock.picking}: |
picking_obj = self.pool.get('stock.picking').browse(cr, uid, ref("outgoing_fifo_shipment_ret"), context=context)
picking_obj.do_transfer()
!python {model: stock.picking, id: outgoing_fifo_shipment_ret}: |
self.do_transfer()
-
Check rounded price is 150.0 / 1.2834
-
!python {model: product.product}: |
product = self.browse(cr, uid, ref("product_fifo_icecream"))
assert round(product.standard_price) == round(150.0 / 1.2834), "Product price not updated accordingly. %s found instead of %s" %(product.standard_price, round(150.0/1.2834))
assert product.qty_available == 0.0, 'Wrong quantity in stock after first reception'
!python {model: product.product, id: product_fifo_icecream}: |
assert round(self.standard_price) == round(150.0 / 1.2834), "Product price not updated accordingly. %s found instead of %s" %(self.standard_price, round(150.0/1.2834))
assert self.qty_available == 0.0, 'Wrong quantity in stock after first reception'
-
Let us create some outs to get negative stock for a new product using the same config
-
@@ -289,13 +284,12 @@
-
Process the delivery of the first outgoing shipment
-
!python {model: stock.picking}: |
picking_obj = self.browse(cr, uid, ref("outgoing_fifo_shipment_neg"), context=context)
picking_obj.do_transfer()
!python {model: stock.picking, id: outgoing_fifo_shipment_neg}: |
self.do_transfer()
-
The behavior of fifo/lifo is not garantee if the quants are created at the same second, so i just wait one second
-
!python {model: stock.picking}: |
!python {model: stock.picking, id: False}: |
import time
time.sleep(1)
-
@@ -317,9 +311,8 @@
-
Process the delivery of the outgoing shipments
-
!python {model: stock.picking}: |
picking_obj1 = self.browse(cr, uid, ref("outgoing_fifo_shipment_neg2"), context=context)
picking_obj1.do_transfer()
!python {model: stock.picking, id: outgoing_fifo_shipment_neg2}: |
self.do_transfer()
-
Receive purchase order with 50 kg FIFO Ice Cream at 50 euro/kg
@@ -336,20 +329,20 @@
-
I confirm the first purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_fifo_neg")])
!python {model: purchase.order, id: purchase_order_fifo_neg}: |
self.button_confirm()
-
Process the reception of purchase order 1
-
!python {model: stock.picking}: |
picking_obj = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo_neg"), context=context).picking_ids[0]
picking_obj.do_transfer()
!python {model: purchase.order, id: purchase_order_fifo_neg}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
Assert price on product is still the old price as the out move has not been received fully yet
-
!python {model: product.product}: |
!python {model: product.product, id: product_fifo_negative}: |
assert self.browse(cr, uid, ref("product_fifo_negative")).standard_price == 70, 'The product price should not have been updated'
assert self.standard_price == 70, 'The product price should not have been updated'
-
Receive purchase order with 60 kg FIFO Ice Cream at 80 euro/kg
-
@@ -365,16 +358,16 @@
-
I confirm the second negative purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_fifo_neg2")])
!python {model: purchase.order, id: purchase_order_fifo_neg2}: |
self.button_confirm()
-
Process the reception of purchase order 2
-
!python {model: stock.picking}: |
picking_obj = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo_neg2"), context=context).picking_ids[0]
picking_obj.do_transfer()
!python {model: purchase.order, id: purchase_order_fifo_neg2}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
The price of the product should have changed back to 65.0
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_fifo_negative")).standard_price == 65.0, "Product price not updated accordingly. %s found instead of 65" %(self.browse(cr, uid, ref("product_fifo_negative")).standard_price,)
!python {model: product.product, id: product_fifo_negative}: |
assert self.standard_price == 65.0, "Product price not updated accordingly. %s found instead of 65" %(self.standard_price,)
+22 -22
View File
@@ -41,44 +41,44 @@
-
I confirm the first purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_fiforet1")])
!python {model: purchase.order, id: purchase_order_fiforet1}: |
self.button_confirm()
-
Process the reception of purchase order 1
-
!python {model: stock.picking}: |
picking_obj = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fiforet1")).picking_ids[0]
self.do_transfer(cr,uid,[picking_obj.id], context=context)
!python {model: purchase.order, id: purchase_order_fiforet1}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
Check the standard price of the product (fifo icecream)
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_fiforet_icecream")).standard_price == 0.0, 'Standard price should not have changed!'
!python {model: product.product, id: product_fiforet_icecream}: |
assert self.standard_price == 0.0, 'Standard price should not have changed!'
-
I confirm the second purchase order
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_fiforet2")])
!python {model: purchase.order, id: purchase_order_fiforet2}: |
self.button_confirm()
-
Process the reception of purchase order 2
-
!python {model: stock.picking}: |
picking_obj = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fiforet2")).picking_ids[0]
self.do_transfer(cr,uid,[picking_obj.id], context=context)
!python {model: purchase.order, id: purchase_order_fiforet2}: |
picking = self.picking_ids[0]
picking.do_transfer()
-
Return the goods of purchase order 2
-
!python {model: stock.return.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fiforet2")).picking_ids
return_id = self.create(cr, uid, {}, context={'active_model':'stock.picking', 'active_id': pick_ids[0].id})
return_picking_id, dummy = self._create_returns(cr, uid, [return_id], context={'active_id': pick_ids[0].id})
!python {model: purchase.order, id: purchase_order_fiforet2}: |
picking = self.picking_ids[0]
return_id = self.env['stock.return.picking'].with_context(active_model='stock.picking', active_id=picking.id).create({})
return_picking_id, dummy = return_id.with_context(active_id=picking.id)._create_returns()
# Important to pass through confirmation and assignation
pick_obj = self.pool.get('stock.picking')
pick_obj.action_confirm(cr, uid, [return_picking_id])
pick_obj.action_assign(cr, uid, [return_picking_id])
pick_obj.do_transfer(cr, uid, [return_picking_id])
return_picking = self.env['stock.picking'].browse(return_picking_id)
return_picking.action_confirm()
return_picking.action_assign()
return_picking.do_transfer()
-
Check the standard price of the product changed to 80.0 as we returned the quants of purchase order 2
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_fiforet_icecream")).standard_price == 80.0, 'Standard price should have changed to 80.0! %s found instead' % (self.browse(cr, uid, ref("product_fiforet_icecream")).standard_price,)
!python {model: product.product, id: product_fiforet_icecream}: |
assert self.standard_price == 80.0, 'Standard price should have changed to 80.0! %s found instead' % (self.standard_price,)
@@ -8,8 +8,8 @@
-
I confirm the purchase order.
-
!python {model: purchase.order}: |
self.button_confirm(cr, uid, [ref("purchase_order_5")])
!python {model: purchase.order, id: purchase_order_5}: |
self.button_confirm()
-
I check the "Approved" status after confirmed RFQ.
-
@@ -18,14 +18,13 @@
-
First I cancel receptions related to this order if order shipped.
-
!python {model: purchase.order}: |
order = self.browse(cr, uid, ref("purchase_order_5"))
self.pool.get('stock.picking').action_cancel(cr, uid, [picking.id for picking in order.picking_ids])
!python {model: purchase.order, id: purchase_order_5}: |
self.env['stock.picking'].browse([picking.id for picking in self.picking_ids]).action_cancel()
-
Now I am able to cancel purchase order.
-
!python {model: purchase.order}: |
self.button_cancel(cr, uid, [ref("purchase_order_5")])
!python {model: purchase.order, id: purchase_order_5}: |
self.button_cancel()
-
I check that order is cancelled.
-
+10 -12
View File
@@ -11,8 +11,8 @@
-
Add Buy route
-
!python {model: product.product}: |
self.write(cr, uid, [ref("scheduler_product")], {"route_ids": [(4, ref("purchase.route_warehouse0_buy"))]})
!python {model: product.product, id: scheduler_product}: |
self.write({"route_ids": [(4, ref("purchase.route_warehouse0_buy"))]})
-
I create a procurement order.
-
@@ -24,19 +24,17 @@
-
I run the scheduler.
-
!python {model: procurement.order}: |
self.run_scheduler(cr, uid)
!python {model: procurement.order, id: False}: |
self.run_scheduler()
-
I check Generated RFQ.
-
!python {model: procurement.order}: |
procurement = self.browse(cr, uid, ref('procurement_order_testcase0'))
assert procurement.purchase_line_id, 'RFQ should be generated!'
!python {model: procurement.order, id: procurement_order_testcase0}: |
assert self.purchase_line_id, 'RFQ should be generated!'
-
I delete the line from the purchase order and check that the move and the procurement are cancelled
-
!python {model: procurement.order}: |
procurement = self.browse(cr, uid, ref('procurement_order_testcase0'))
procurement.purchase_line_id.unlink()
procurement.refresh()
assert procurement.state == 'exception', 'Procurement should be in exception'
!python {model: procurement.order, id: procurement_order_testcase0}: |
self.purchase_line_id.unlink()
self.refresh()
assert self.state == 'exception', 'Procurement should be in exception'
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<odoo>
<data noupdate="1">
<record forcecreate="True" id="property_stock_valuation_account_id" model="ir.property">
@@ -16,4 +16,4 @@
</record>
</data>
</openerp>
</odoo>
+7 -7
View File
@@ -8,24 +8,24 @@
-
I try to delete confirmed order and check Error Message.
-
!python {model: purchase.order}: |
!python {model: purchase.order, id: purchase_order_1}: |
try:
self.unlink(cr, uid, [ref("purchase_order_1")])
self.unlink()
except Exception,e:
pass
-
I delete a cancelled order.
-
!python {model: purchase.order}: |
from openerp.exceptions import UserError
!python {model: purchase.order, id: purchase_order_7}: |
from odoo.exceptions import UserError
try:
self.unlink(cr, uid, [ref("purchase_order_7")])
self.unlink()
except UserError:
pass
-
I delete a draft order.
-
!python {model: purchase.order}: |
self.unlink(cr, uid, [ref("purchase_order_5")])
!python {model: purchase.order, id: purchase_order_5}: |
self.unlink()
+2 -2
View File
@@ -3,5 +3,5 @@
-
I duplicate order.
-
!python {model: purchase.order}: |
self.copy(cr, uid, ref('purchase_order_1'), context)
!python {model: purchase.order, id: purchase_order_1}: |
self.copy()
+1 -1
View File
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_onchange_product_id, test_purchase_order, test_create_picking
from . import test_onchange_product_id, test_purchase_order, test_create_picking
+1 -1
View File
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.addons.product.tests import common
@@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from openerp.tests.common import TransactionCase
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tests.common import TransactionCase
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
class TestOnchangeProductId(TransactionCase):
"""Test that when an included tax is mapped by a fiscal position, the included tax must be
+3 -3
View File
@@ -2,10 +2,10 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tests import common
from openerp.addons.account.tests.account_test_classes import AccountingTestCase
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
class TestPurchaseOrder(AccountingTestCase):
@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="action_invoice_pending" model="ir.actions.act_window">
<field name="name">Vendor Bills</field>
+2 -4
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<!-- Top menu item -->
<menuitem name="Purchases"
@@ -632,5 +631,4 @@
</field>
</field>
</record>
</data>
</openerp>
</odoo>
+3 -5
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" ?>
<openerp>
<data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="mrp_company" model="ir.ui.view">
<field name="name">res.company.mrp.config</field>
@@ -17,5 +16,4 @@
</field>
</record>
</data>
</openerp>
</odoo>
+2 -4
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<record id="view_purchase_configuration" model="ir.ui.view">
<field name="name">purchase.res.config.view</field>
<field name="model">purchase.config.settings</field>
@@ -56,5 +55,4 @@
</xpath>
</field>
</record>
</data>
</openerp>
</odoo>
+3 -4
View File
@@ -1,5 +1,5 @@
<openerp>
<data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_partner_property_form" model="ir.ui.view">
<field name="name">res.partner.purchase.property.form.inherit</field>
@@ -105,5 +105,4 @@
</div>
</field>
</record>
</data>
</openerp>
</odoo>
+2 -4
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<record id="stock_move_purchase" model="ir.ui.view">
<field name="name">stock.move.form</field>
<field name="model">stock.move</field>
@@ -23,5 +22,4 @@
</field>
</record>
</data>
</openerp>
</odoo>