[IMP] purchase: adaptation due to the new Purchase module
Major changes: - No generation of invoice from PO - Remove workflow Reason: complete rewrite of the Purchase module. Responsible: fp, nim
This commit is contained in:
@@ -5,8 +5,8 @@ import mail_mail
|
||||
import purchase
|
||||
import partner
|
||||
import stock
|
||||
import wizard
|
||||
import report
|
||||
import stock
|
||||
import company
|
||||
import res_config
|
||||
import invoice
|
||||
|
||||
@@ -30,13 +30,11 @@ Dashboard / Reports for Purchase Management will include:
|
||||
'data': [
|
||||
'security/purchase_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'purchase_workflow.xml',
|
||||
'invoice_view.xml',
|
||||
'purchase_sequence.xml',
|
||||
'company_view.xml',
|
||||
'purchase_data.xml',
|
||||
'purchase_data.yml',
|
||||
'wizard/purchase_order_group_view.xml',
|
||||
'wizard/purchase_line_invoice_view.xml',
|
||||
'purchase_report.xml',
|
||||
'purchase_view.xml',
|
||||
'stock_view.xml',
|
||||
@@ -57,15 +55,9 @@ Dashboard / Reports for Purchase Management will include:
|
||||
'test/fifo_returns.yml',
|
||||
# 'test/costmethodchange.yml',
|
||||
'test/process/cancel_order.yml',
|
||||
'test/process/rfq2order2done.yml',
|
||||
'test/process/generate_invoice_from_reception.yml',
|
||||
'test/process/merge_order.yml',
|
||||
'test/process/invoice_on_poline.yml',
|
||||
'test/ui/duplicate_order.yml',
|
||||
'test/ui/delete_order.yml',
|
||||
'test/average_price.yml',
|
||||
'test/anglo_saxon.yml',
|
||||
'test/anglo_saxon_avg_fifo.yml',
|
||||
],
|
||||
'demo': [
|
||||
'purchase_order_demo.yml',
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import osv,fields
|
||||
from openerp import api, fields, models, _
|
||||
|
||||
class company(osv.osv):
|
||||
class company(models.Model):
|
||||
_inherit = 'res.company'
|
||||
_columns = {
|
||||
'po_lead': fields.float(
|
||||
'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 "\
|
||||
"to cope with unexpected vendor delays."),
|
||||
}
|
||||
_defaults = {
|
||||
'po_lead': lambda *a: 1.0,
|
||||
}
|
||||
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 "\
|
||||
"to cope with unexpected vendor delays.", default=1.0)
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
# -*- 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
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
purchase_id = fields.Many2one('purchase.order', string='Purchase Order', domain=[('invoice_status', '=', 'to invoice')])
|
||||
|
||||
# Load all unsold PO lines
|
||||
@api.onchange('purchase_id')
|
||||
def purchase_order_change(self):
|
||||
result = []
|
||||
if not self.purchase_id:
|
||||
return {}
|
||||
if not self.partner_id:
|
||||
self.partner_id = self.purchase_id.partner_id.id
|
||||
done = False
|
||||
for line in self.purchase_id.order_line:
|
||||
if line.product_id.purchase_method == 'purchase':
|
||||
qty = line.product_qty - line.qty_invoiced
|
||||
else:
|
||||
qty = line.qty_received - line.qty_invoiced
|
||||
if float_compare(qty, 0.0, precision_rounding=line.product_uom.rounding) <= 0:
|
||||
continue
|
||||
done = True
|
||||
account = self.env['account.invoice.line'].get_invoice_line_account('in_invoice', line.product_id, self.purchase_id.fiscal_position_id, self.env.user.company_id)
|
||||
taxes = line.taxes_id or line.product_id.supplier_taxes_id
|
||||
invoice_line_tax_ids = self.purchase_id.fiscal_position_id.map_tax(taxes)
|
||||
result.append({
|
||||
'purchase_line_id': line.id,
|
||||
'name': line.name,
|
||||
'origin': self.purchase_id.origin,
|
||||
'uom_id': line.product_uom.id,
|
||||
'product_id': line.product_id.id,
|
||||
'account_id': account,
|
||||
'price_unit': line.price_unit,
|
||||
'quantity': qty,
|
||||
'discount': 0.0,
|
||||
'account_analytic_id': line.account_analytic_id.id,
|
||||
'invoice_line_tax_ids': invoice_line_tax_ids
|
||||
})
|
||||
self.invoice_line_ids = result
|
||||
if not done:
|
||||
warning = {
|
||||
'title': _('Bill Control Warning!'),
|
||||
'message' : _('None of the products from this purchase order can be billed. You should control the purchase order.')
|
||||
}
|
||||
return {'warning': warning}
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
""" Override AccountInvoice_line to add the link to the purchase order line it is related to"""
|
||||
_inherit = 'account.invoice.line'
|
||||
purchase_line_id = fields.Many2one('purchase.order.line', 'Purchase Order Line', ondelete='set null', select=True, readonly=True)
|
||||
|
||||
@api.model
|
||||
def move_line_get(self, invoice_id):
|
||||
res = super(AccountInvoiceLine, self).move_line_get(invoice_id)
|
||||
invoice = self.browse(invoice_id)
|
||||
if self.env.user.company_id.anglo_saxon_accounting:
|
||||
if invoice.type in ['in_invoice', 'in_refund']:
|
||||
for i_line in invoice.invoice_line_ids:
|
||||
res.extend(self._anglo_saxon_purchase_move_lines(i_line, res))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _anglo_saxon_purchase_move_lines(self, i_line, res):
|
||||
"""Return the additional move lines for purchase invoices and refunds.
|
||||
|
||||
i_line: An account.invoice.line object.
|
||||
res: The move line entries produced so far by the parent move_line_get.
|
||||
"""
|
||||
inv = i_line.invoice_id
|
||||
company_currency = inv.company_id.currency_id
|
||||
if i_line.product_id and i_line.product_id.valuation == 'real_time':
|
||||
if i_line.product_id.type != 'service':
|
||||
# get the price difference account at the product
|
||||
acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id
|
||||
if not acc:
|
||||
# if not found on the product get the price difference account at the category
|
||||
acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id
|
||||
a = None
|
||||
|
||||
# oa will be the stock input account
|
||||
# first check the product, if empty check the category
|
||||
oa = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id
|
||||
if not oa:
|
||||
oa = i_line.product_id.categ_id.property_stock_account_input_categ_id and i_line.product_id.categ_id.property_stock_account_input_categ_id.id
|
||||
if oa:
|
||||
# get the fiscal position
|
||||
fpos = i_line.invoice_id.fiscal_position_id or False
|
||||
a = fpos.map_account(oa)
|
||||
diff_res = []
|
||||
account_prec = inv.company_id.currency_id.decimal_places
|
||||
# calculate and write down the possible price difference between invoice price and product price
|
||||
for line in res:
|
||||
if line.get('invl_id', 0) == i_line.id and a == line['account_id']:
|
||||
uom = i_line.product_id.uom_id
|
||||
valuation_price_unit = uom._compute_price(i_line.product_id.standard_price, i_line.uom_id.id)
|
||||
if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id:
|
||||
#for average/fifo/lifo costing method, fetch real cost price from incomming moves
|
||||
stock_move_obj = self.env['stock.move']
|
||||
valuation_stock_move = stock_move_obj.search([('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1)
|
||||
if valuation_stock_move:
|
||||
valuation_price_unit = valuation_stock_move[0].price_unit
|
||||
if inv.currency_id.id != company_currency.id:
|
||||
valuation_price_unit = company_currency.compute(inv.currency_id, valuation_price_unit, context={'date': inv.date_invoice})
|
||||
if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
|
||||
# price with discount and without tax included
|
||||
price_unit = self.env['account.tax'].compute_all(line['taxes'], i_line.price_unit * (1-(i_line.discount or 0.0)/100.0),\
|
||||
inv.currency_id.id, line['quantity'])['total_excluded']
|
||||
price_line = round(valuation_price_unit * line['quantity'], account_prec)
|
||||
price_diff = round(price_unit - price_line, account_prec)
|
||||
line.update({'price': price_line})
|
||||
diff_res.append({
|
||||
'type': 'src',
|
||||
'name': i_line.name[:64],
|
||||
'price_unit': round(price_diff / line['quantity'], account_prec),
|
||||
'quantity': line['quantity'],
|
||||
'price': price_diff,
|
||||
'account_id': acc,
|
||||
'product_id': line['product_id'],
|
||||
'uom_id': line['uom_id'],
|
||||
'account_analytic_id': line['account_analytic_id'],
|
||||
'taxes': line.get('taxes', []),
|
||||
})
|
||||
return diff_res
|
||||
return []
|
||||
@@ -0,0 +1,68 @@
|
||||
<odoo>
|
||||
<record id="action_invoice_pending" model="ir.actions.act_window">
|
||||
<field name="name">Vendor Bills</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar,pivot,graph</field>
|
||||
<field eval="False" name="view_id"/>
|
||||
<field name="domain">[('type','=','in_invoice')]</field>
|
||||
<field name="context">{'default_type':'in_invoice', 'type':'in_invoice', 'journal_type': 'purchase'}</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a draft invoice.
|
||||
</p><p>
|
||||
Use this menu to control the invoices to be received from your
|
||||
vendor. When registering a new bill, set the purchase order
|
||||
and Odoo will fill the bill automatically according to ordered
|
||||
or received quantities.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_open_invoice" model="ir.actions.act_window">
|
||||
<field name="name">Vendor Bills</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot,graph</field>
|
||||
<field eval="False" name="view_id"/>
|
||||
<field name="domain">[('type','in',('in_invoice', 'in_refund')),('purchase_id','=',active_id)]</field>
|
||||
<field name="context">{'default_type': 'in_invoice', 'type': 'in_invoice', 'journal_type': 'purchase', 'default_purchase_id': active_id}</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to record a vendor bill related to this purchase.
|
||||
</p>
|
||||
<p>
|
||||
You can control the invoice from your vendor according to
|
||||
what you purchased (services) or received (products).
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_invoice_supplier_tree1_view1" model="ir.actions.act_window.view">
|
||||
<field eval="1" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="account.invoice_supplier_tree"/>
|
||||
<field name="act_window_id" ref="purchase_open_invoice"/>
|
||||
</record>
|
||||
<record id="action_invoice__supplier_tree1_view2" model="ir.actions.act_window.view">
|
||||
<field eval="2" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="act_window_id" ref="purchase_open_invoice"/>
|
||||
</record>
|
||||
|
||||
<record id="view_invoice_supplier_purchase_form" model="ir.ui.view">
|
||||
<field name="name">account.invoice.supplier.purchase</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="reference" position="after" >
|
||||
<field name="purchase_id" domain="[('invoice_status', '=', 'to invoice'), ('partner_id', '=', partner_id)]" attrs="{'invisible': [('state', '<>', 'draft')]}" class="oe_edit_only"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='company_id']" position="after">
|
||||
<field name="purchase_line_id" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
+16
-23
@@ -1,32 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp import api, fields, models
|
||||
|
||||
class res_partner(osv.osv):
|
||||
class res_partner(models.Model):
|
||||
_name = 'res.partner'
|
||||
_inherit = 'res.partner'
|
||||
|
||||
def _purchase_invoice_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
PurchaseOrder = self.pool['purchase.order']
|
||||
Invoice = self.pool['account.invoice']
|
||||
return {
|
||||
partner_id: {
|
||||
'purchase_order_count': PurchaseOrder.search_count(cr,uid, [('partner_id', 'child_of', partner_id)], context=context),
|
||||
'supplier_invoice_count': Invoice.search_count(cr,uid, [('partner_id', 'child_of', partner_id), ('type','=','in_invoice')], context=context)
|
||||
}
|
||||
for partner_id in ids
|
||||
}
|
||||
@api.multi
|
||||
def _purchase_invoice_count(self):
|
||||
PurchaseOrder = self.env['purchase.order']
|
||||
Invoice = self.env['account.invoice']
|
||||
for partner in self:
|
||||
partner.purchase_order_count = PurchaseOrder.search_count([('partner_id', 'child_of', partner.id)])
|
||||
partner.supplier_invoice_count = Invoice.search_count([('partner_id', 'child_of', partner.id), ('type', '=', 'in_invoice')])
|
||||
|
||||
def _commercial_fields(self, cr, uid, context=None):
|
||||
return super(res_partner, self)._commercial_fields(cr, uid, context=context)
|
||||
@api.model
|
||||
def _commercial_fields(self):
|
||||
return super(res_partner, self)._commercial_fields()
|
||||
|
||||
_columns = {
|
||||
'property_purchase_currency_id': fields.property(
|
||||
type='many2one',
|
||||
relation='res.currency',
|
||||
string="Supplier Currency",
|
||||
help="This currency will be used, instead of the default one, for purchases from the current partner"),
|
||||
'purchase_order_count': fields.function(_purchase_invoice_count, string='# of Purchase Order', type='integer', multi="count"),
|
||||
'supplier_invoice_count': fields.function(_purchase_invoice_count, string='# Vendor Bills', type='integer', multi="count"),
|
||||
}
|
||||
property_purchase_currency_id = fields.Many2one('res.currency', string="Supplier Currency",\
|
||||
help="This currency will be used, instead of the default one, for purchases from the current partner")
|
||||
purchase_order_count = fields.Integer(compute='_purchase_invoice_count', string='# of Purchase Order')
|
||||
supplier_invoice_count = fields.Integer(compute='_purchase_invoice_count', string='# Vendor Bills')
|
||||
|
||||
+665
-1712
File diff suppressed because it is too large
Load Diff
@@ -3,86 +3,135 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_1}:
|
||||
partner_id: base.res_partner_1
|
||||
invoice_method: order
|
||||
order_line:
|
||||
- product_id: product.product_product_15
|
||||
price_unit: 79.80
|
||||
product_qty: 15.0
|
||||
- product_id: product.product_product_25
|
||||
price_unit: 2868.70
|
||||
product_qty: 5.0
|
||||
- product_id: product.product_product_27
|
||||
price_unit: 3297.20
|
||||
product_qty: 4.0
|
||||
|
||||
-
|
||||
!record {model: purchase.order.line, id: purchase_order_line_1}:
|
||||
order_id: purchase.purchase_order_1
|
||||
product_id: product.product_product_15
|
||||
name: RAM SR3
|
||||
price_unit: 79.80
|
||||
product_qty: 15.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
-
|
||||
!record {model: purchase.order.line, id: purchase_order_line_2}:
|
||||
order_id: purchase_order_1
|
||||
product_id: product.product_product_25
|
||||
name: Laptop E5023
|
||||
price_unit: 2868.70
|
||||
product_qty: 5.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
-
|
||||
!record {model: purchase.order.line, id: purchase_order_line_3}:
|
||||
order_id: purchase_order_1
|
||||
product_id: product.product_product_27
|
||||
name: Laptop Customized
|
||||
price_unit: 3297.20
|
||||
product_qty: 4.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
-
|
||||
Creating second order
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_2}:
|
||||
partner_id: base.res_partner_3
|
||||
invoice_method: picking
|
||||
order_line:
|
||||
- product_id: product.product_product_31
|
||||
name: Multimedia Speakers
|
||||
price_unit: 132.50
|
||||
product_qty: 20.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_29
|
||||
name: Pen drive, SP-2
|
||||
price_unit: 89
|
||||
product_qty: 5
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_3}:
|
||||
partner_id: base.res_partner_12
|
||||
order_line:
|
||||
- product_id: product.product_product_2
|
||||
name: Support Services
|
||||
price_unit: 25.50
|
||||
product_qty: 10.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_4}:
|
||||
partner_id: base.res_partner_4
|
||||
order_line:
|
||||
- product_id: product.product_product_14
|
||||
name: RAM SR2 (kit)
|
||||
price_unit: 85.50
|
||||
product_qty: 6.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_20
|
||||
name: Motherboard I9P57
|
||||
price_unit: 1690
|
||||
product_qty: 5.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_6
|
||||
name: iPad Mini
|
||||
price_unit: 800
|
||||
product_qty: 7.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_5}:
|
||||
partner_id: base.res_partner_2
|
||||
order_line:
|
||||
- product_id: product.product_product_22
|
||||
name: Processor Core i5 2.70 Ghz
|
||||
product_qty: 3
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_24
|
||||
name: Graphics Card
|
||||
product_qty: 3
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_6}:
|
||||
partner_id: base.res_partner_1
|
||||
order_line:
|
||||
- product_id: product.product_product_38
|
||||
name: Ink Cartridge
|
||||
price_unit: 58
|
||||
product_qty: 9
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_39
|
||||
name: Toner Cartridge
|
||||
product_qty: 3
|
||||
price_unit: 65
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_44
|
||||
name: GrapWorks Software
|
||||
product_qty: 4
|
||||
price_unit: 154.5
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_7}:
|
||||
partner_id: base.res_partner_4
|
||||
order_line:
|
||||
- product_id: product.product_product_12
|
||||
name: Mouse, Wireless
|
||||
product_qty: 5
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_34
|
||||
name: Webcam
|
||||
product_qty: 15
|
||||
-
|
||||
!python {model: purchase.order} : |
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('user_type_id', '=', ref('account.data_account_type_expenses'))])
|
||||
if account_id:
|
||||
self.signal_workflow(cr, uid, [ref('purchase_order_2')], 'purchase_confirm')
|
||||
self.signal_workflow(cr, uid, [ref('purchase_order_6')], 'purchase_confirm')
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
+105
-251
@@ -18,9 +18,10 @@
|
||||
<menuitem
|
||||
id="menu_purchase_config_pricelist" name="Pricelists"
|
||||
parent="menu_purchase_config" sequence="20" groups="base.group_no_one"/>
|
||||
|
||||
<menuitem
|
||||
action="product.product_supplierinfo_type_action" id="menu_product_pricelist_action2_purchase"
|
||||
parent="menu_purchase_config_pricelist" sequence="1" groups="base.group_no_one"/>
|
||||
action="product.product_supplierinfo_type_action" id="menu_product_pricelist_action2_purchase"
|
||||
parent="menu_purchase_config_pricelist" sequence="1" groups="base.group_no_one"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_product_in_config_purchase" name="Products"
|
||||
@@ -50,39 +51,16 @@
|
||||
<!-- Purchase Control Menu -->
|
||||
<menuitem id="menu_purchase_control" name="Control" parent="base.menu_purchase_root" sequence="4"/>
|
||||
|
||||
<!--Inventory control-->
|
||||
<menuitem id="menu_procurement_management_inventory" name="Products"
|
||||
parent="menu_purchase_control" sequence="4"/>
|
||||
<!--Inventory control-->
|
||||
<menuitem action="stock.action_receipt_picking_move" id="menu_action_picking_tree_in_move"
|
||||
parent="menu_procurement_management_inventory" sequence="11"/>
|
||||
parent="menu_purchase_control" sequence="11"/>
|
||||
|
||||
<!--Invoice control-->
|
||||
<menuitem id="menu_procurement_management_invoice" name="Bills"
|
||||
parent="menu_purchase_control" sequence="6"/>
|
||||
|
||||
<record id="action_invoice_pending" model="ir.actions.act_window">
|
||||
<field name="name">Draft Bills</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar,pivot,graph</field>
|
||||
<field eval="False" name="view_id"/>
|
||||
<field name="domain">[('type','=','in_invoice')]</field>
|
||||
<field name="context">{'default_type':'in_invoice', 'type':'in_invoice', 'journal_type': 'purchase', 'search_default_draft': 1}</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a draft invoice.
|
||||
</p><p>
|
||||
Use this menu to control the invoices to be received from your
|
||||
vendor. Odoo generates draft invoices from your purchase
|
||||
orders or receipts, according to your settings.
|
||||
</p><p>
|
||||
Once you receive a vendor bill, you can match it with the
|
||||
draft invoice and validate it.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_procurement_management_pending_invoice"
|
||||
action="action_invoice_pending"
|
||||
parent="menu_purchase_control"
|
||||
sequence="13"/>
|
||||
|
||||
<record id="product_normal_action_puchased" model="ir.actions.act_window">
|
||||
<field name="name">Products</field>
|
||||
@@ -108,13 +86,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<menuitem
|
||||
id="menu_procurement_management_pending_invoice"
|
||||
action="action_invoice_pending"
|
||||
parent="menu_procurement_management_invoice"
|
||||
sequence="13"/>
|
||||
|
||||
<!-- Product menu-->
|
||||
<menuitem name="Products" id="menu_procurement_partner_contact_form" action="product_normal_action_puchased"
|
||||
parent="menu_procurement_management" sequence="20"/>
|
||||
@@ -124,7 +95,7 @@
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Calendar View" date_start="minimum_planned_date" color="partner_id">
|
||||
<calendar string="Calendar View" date_start="date_planned" color="partner_id">
|
||||
<field name="name"/>
|
||||
<field name="amount_total" widget="monetary"/>
|
||||
<field name="partner_id"/>
|
||||
@@ -152,30 +123,49 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_open_picking" model="ir.actions.act_window">
|
||||
<field name="name">Receptions</field>
|
||||
<field name="res_model">stock.picking</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('purchase_id', '=', active_id)]</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_order_form" model="ir.ui.view">
|
||||
<field name="name">purchase.order.form</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Purchase Order">
|
||||
<header>
|
||||
<button name="bid_received" states="sent" string="Bid Received" class="oe_highlight"/>
|
||||
<button name="wkf_send_rfq" states="draft" string="Send RFQ by Email" type="object" context="{'send_rfq':True}" class="oe_highlight"/>
|
||||
<button name="wkf_send_rfq" states="sent" string="Re-Send RFQ by Email" type="object" context="{'send_rfq':True}"/>
|
||||
<button name="action_rfq_send" states="draft" string="Send RFQ by Email" type="object" context="{'send_rfq':True}" class="oe_highlight"/>
|
||||
<button name="action_rfq_send" states="sent" string="Re-Send RFQ by Email" type="object" context="{'send_rfq':True}"/>
|
||||
<button name="print_quotation" string="Print RFQ" type="object" states="draft" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="print_quotation" string="Re-Print RFQ" type="object" states="sent" groups="base.group_user"/>
|
||||
<button name="purchase_confirm" states="draft" string="Confirm Order" id="draft_confirm"/>
|
||||
<button name="purchase_confirm" states="bid" string="Confirm Order" class="oe_highlight" id="bid_confirm"/>
|
||||
<button name="picking_ok" states="except_picking" string="Manually Corrected"/>
|
||||
<button name="invoice_ok" states="except_invoice" string="Manually Corrected"/>
|
||||
<button name="purchase_approve" states="confirmed" string="Approve Order" class="oe_highlight" groups="purchase.group_purchase_manager"/>
|
||||
<button name="wkf_send_rfq" states="approved" string="Send PO by Email" type="object" context="{'send_rfq':False}"/>
|
||||
<button name="view_picking" string="Receive Products" type="object" attrs="{'invisible': ['|', ('shipped','=',True), ('state','!=', 'approved')]}" class="oe_highlight"/>
|
||||
<button name="view_invoice" string="Receive Invoice" type="object" attrs="{'invisible': ['|', ('invoice_method','in', ['picking', 'manual']), '|', ('state','!=', 'approved'), ('invoiced','=',True) ]}" class="oe_highlight"/>
|
||||
<button name="action_cancel_draft" states="cancel,sent,confirmed" string="Set to Draft" type="object" />
|
||||
<button name="action_cancel" states="draft,confirmed,sent,bid,approved,except_picking,except_invoice" string="Cancel" type="object" />
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,sent,bid,approved,done" statusbar_colors='{"except_picking":"red","except_invoice":"red","confirmed":"blue"}' readonly="1"/>
|
||||
<button name="button_confirm" type="object" states="draft" string="Confirm Order" id="draft_confirm"/>
|
||||
<button name="button_confirm" type="object" states="sent" string="Confirm Order" class="oe_highlight" id="bid_confirm"/>
|
||||
<button name="button_approve" type="object" states="to approve" string="Approve Order" class="oe_highlight" groups="purchase.group_purchase_manager"/>
|
||||
<button name="action_rfq_send" states="approved" string="Send PO by Email" type="object" context="{'send_rfq':False}"/>
|
||||
<button name="%(purchase_open_picking)d" string="Receive Products" type="action" attrs="{'invisible': [('state','not in', ('purchase','done'))]}"/>
|
||||
<button name="button_draft" states="cancel" string="Set to Draft" type="object" />
|
||||
<button name="button_cancel" states="draft,to approve,sent,purchase" string="Cancel" type="object" />
|
||||
<button name="button_done" type="object" string="Set to Done" states="purchase"
|
||||
help="If a purchase order is done, you can not modify it manually anymore. But you will still be able to bill or receive."/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,sent,purchase,done" readonly="1"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button type="action"
|
||||
name="%(purchase_open_picking)d"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck">
|
||||
<field name="picking_count" widget="statinfo" string="Shipment" help="Incoming Shipments"/>
|
||||
</button>
|
||||
<button type="action" name="%(purchase_open_invoice)d"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o">
|
||||
<field name="invoice_count" widget="statinfo" string="Invoices"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label string="Request for Quotation " attrs="{'invisible': [('state','not in',('draft','sent','bid'))]}"/>
|
||||
<label string="Purchase Order " attrs="{'invisible': [('state','in',('draft','sent','bid'))]}"/>
|
||||
@@ -185,81 +175,63 @@
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id, context)" context="{'search_default_supplier':1, 'default_supplier':1, 'default_customer':0}" domain="[('supplier','=',True)]"/>
|
||||
<field name="partner_id" context="{'search_default_supplier':1, 'default_supplier':1, 'default_customer':0}" domain="[('supplier','=',True)]"/>
|
||||
<field name="partner_ref"/>
|
||||
<field name="currency_id" groups="base.group_multi_currency"/>
|
||||
<field name="journal_id" invisible='1'/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date_order"/>
|
||||
<field name="origin" attrs="{'invisible': [('origin','=',False)]}"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="related_usage" invisible="1"/>
|
||||
<field name="bid_date" invisible="1"/>
|
||||
<field name="bid_validity" attrs="{'invisible':[('bid_date','=',False)]}"/>
|
||||
<field name="dest_address_id" string="Customer Address" on_change="onchange_dest_address_id(dest_address_id, context)"
|
||||
attrs="{'invisible':[('related_usage','!=','customer')],
|
||||
'required': [('related_usage','=', 'customer')]}"
|
||||
groups="stock.group_locations"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Products">
|
||||
<field name="order_line">
|
||||
<tree string="Purchase Order Lines" editable="bottom">
|
||||
<field name="product_id"
|
||||
on_change="onchange_product_id(product_id, 0, False,
|
||||
parent.partner_id, parent.date_order, parent.fiscal_position_id, date_planned,
|
||||
name, False, parent.state, True, parent.currency_id,context)"
|
||||
context="{'partner_id': parent.partner_id}"/>
|
||||
<field name="product_id" context="{'partner_id': parent.partner_id}"/>
|
||||
<field name="name"/>
|
||||
<field name="date_planned"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="account_analytic_id" context="{'default_partner_id':parent.partner_id}" groups="purchase.group_analytic_accounting" domain="[('type','not in',('view','template'))]"/>
|
||||
<field name="product_qty"
|
||||
on_change="onchange_product_id(product_id, product_qty,
|
||||
product_uom, parent.partner_id, parent.date_order, parent.fiscal_position_id,
|
||||
date_planned, name, False, parent.state, False, parent.currency_id, context)"/>
|
||||
<field name="product_uom" groups="product.group_uom" on_change="onchange_product_uom(product_id,product_qty,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position_id,date_planned,name,False,parent.state,parent.currency_id,context)"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="qty_received" invisible="not context.get('show_purchase', False)"/>
|
||||
<field name="qty_invoiced" invisible="not context.get('show_purchase', False)"/>
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use','=','purchase')]"/>
|
||||
<field name="price_subtotal" widget="monetary"/>
|
||||
<field name="state" invisible="1"/>
|
||||
</tree>
|
||||
<form>
|
||||
<group>
|
||||
<form string="Purchase Order Line">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="product_id"
|
||||
on_change="onchange_product_id(product_id, 0, False,
|
||||
parent.partner_id, parent.date_order, parent.fiscal_position_id, date_planned,
|
||||
name, False, parent.state, True, parent.currency_id, context)"
|
||||
context="{'partner_id': parent.partner_id}"/>
|
||||
<label for="product_qty"/>
|
||||
<div>
|
||||
<field name="product_qty" class="oe_inline"
|
||||
on_change="onchange_product_id(product_id, product_qty,
|
||||
product_uom, parent.partner_id, parent.date_order, parent.fiscal_position_id,
|
||||
date_planned, name, False, parent.state, False, parent.currency_id, context)"/>
|
||||
<field name="product_uom" groups="product.group_uom" class="oe_inline"
|
||||
on_change="onchange_product_uom(product_id,product_qty,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position_id,date_planned,name,False,parent.state,parent.currency_id,context)"/>
|
||||
</div>
|
||||
<field name="price_unit"/>
|
||||
<group>
|
||||
<field name="product_id"
|
||||
context="{'partner_id': parent.partner_id}"/>
|
||||
<label for="product_qty"/>
|
||||
<div>
|
||||
<field name="product_qty"
|
||||
class="oe_inline"/>
|
||||
<field name="product_uom" groups="product.group_uom" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="price_unit"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use', '=', 'purchase')]"/>
|
||||
<field name="date_planned" widget="date"/>
|
||||
<field name="account_analytic_id" colspan="2" groups="purchase.group_analytic_accounting"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use', '=', 'purchase')]"/>
|
||||
<field name="date_planned" widget="date"/>
|
||||
<field name="account_analytic_id" colspan="2" groups="purchase.group_analytic_accounting"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Notes">
|
||||
<field name="name"/>
|
||||
</page><page string="Invoices and Incoming Shipments">
|
||||
<field name="invoice_lines"/>
|
||||
<field name="move_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<notebook>
|
||||
<page string="Notes">
|
||||
<field name="name"/>
|
||||
</page><page string="Invoices and Incoming Shipments">
|
||||
<field name="invoice_lines"/>
|
||||
<field name="move_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
<group class="oe_subtotal_footer oe_right">
|
||||
@@ -267,8 +239,6 @@
|
||||
<field name="amount_tax" widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||
<div class="oe_subtotal_footer_separator oe_inline">
|
||||
<label for="amount_total"/>
|
||||
<button name="button_dummy"
|
||||
states="draft" string="(update)" type="object" class="oe_edit_only oe_link"/>
|
||||
</div>
|
||||
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator" widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||
</group>
|
||||
@@ -278,19 +248,14 @@
|
||||
<page string="Deliveries & Invoices">
|
||||
<group>
|
||||
<group>
|
||||
<field name="minimum_planned_date"/>
|
||||
<field name="picking_type_id" on_change="onchange_picking_type_id(picking_type_id, context)" domain="[('code','=','incoming')]" options="{'no_create': True}" context="{'special_shortened_wh_name': True}" groups="stock.group_locations"/>
|
||||
<field name="location_id" groups="stock.group_locations" string="Location"/>
|
||||
<field name="shipped" groups="base.group_no_one"/>
|
||||
<field name="date_planned"/>
|
||||
<field name="picking_type_id" domain="[('code','=','incoming')]" options="{'no_create': True}" context="{'special_shortened_wh_name': True}" groups="stock.group_locations"/>
|
||||
<field name="incoterm_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="invoice_method"/>
|
||||
<field name="invoiced" invisible="1"/>
|
||||
<field name="payment_term_id" options="{'no_open': True, 'no_create': True}"/>
|
||||
<field name="fiscal_position_id" attrs="{'readonly': [('invoiced','=', True)]}" />
|
||||
<!-- We do not need these fields anymore, the information is in open chatter -->
|
||||
<field name="validator" groups="base.group_no_one"/>
|
||||
<field name="invoice_status"/>
|
||||
<field name="payment_term_id" options="{'no_open': True, 'no_create': True}" attrs="{'readonly': [('invoice_status','=', 'invoiced')]}"/>
|
||||
<field name="fiscal_position_id" attrs="{'readonly': [('invoice_status','=', 'invoiced')]}" />
|
||||
<field name="date_approve" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</group>
|
||||
@@ -305,7 +270,7 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_request_for_quotation_filter" model="ir.ui.view">
|
||||
<record id="view_purchase_order_filter" model="ir.ui.view">
|
||||
<field name="name">request.quotation.select</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="arch" type="xml">
|
||||
@@ -314,45 +279,21 @@
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="product_id"/>
|
||||
<field name="create_uid"/>
|
||||
<filter name="draft" string="Quotations" domain="[('state','=','draft')]"/>
|
||||
<filter name="approved" string="Approved" domain="[('state','in',('approved','done'))]"/>
|
||||
<filter name="exception" string="Exception" domain="[('state','in',('except_invoice','except_picking'))]"/>
|
||||
<filter name="draft" string="Quotations" domain="[('state','in',('draft','sent','to approve'))]"/>
|
||||
<filter name="approved" string="Purchase Orders" domain="[('state','in',('purchase','done'))]"/>
|
||||
<separator/>
|
||||
<filter name="not_invoiced" string="Not Invoiced" domain="[('invoice_ids','=', False)]" help="Purchase orders that include lines not invoiced."/>
|
||||
<filter name="not_invoiced" string="Not Invoiced" domain="[('invoice_status','=', 'to invoice')]" help="Purchase orders that include lines not invoiced."/>
|
||||
<filter name="invoiced" string="Invoiced" domain="[('invoice_status','=', 'invoiced')]" help="Purchase orders that include lines not invoiced."/>
|
||||
<filter string="New Mail" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Vendor" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Order Date" domain="[]" context="{'group_by':'date_order'}"/>
|
||||
<filter string="Expected Date" domain="[]" context="{'group_by':'minimum_planned_date'}"/>
|
||||
<filter string="Expected Date" domain="[]" context="{'group_by':'date_planned'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_purchase_order_filter" model="ir.ui.view">
|
||||
<field name="name">purchase.order.list.select</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Purchase Order">
|
||||
<field name="name" string="Reference"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="product_id"/>
|
||||
<field name="create_uid"/>
|
||||
<filter name="draft" string="Quotations" domain="[('state','in',('draft','sent'))]"/>
|
||||
<filter name="approved" string="Purchase Orders" domain="[('state','not in',('draft','cancel'))]"/>
|
||||
<filter name="todo" string="To Do" domain="[('state','not in',('cancel','done'))]"/>
|
||||
<filter name="exception" string="Exception" domain="[('state','in',('except_invoice','except_picking'))]"/>
|
||||
<separator/>
|
||||
<filter name="not_invoiced" string="Not Invoiced" domain="[('invoice_ids','=', False)]"/>
|
||||
<separator/>
|
||||
<filter string="Important Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Vendor" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Order Month" domain="[]" context="{'group_by':'date_order'}"/>
|
||||
<filter string="Expected Month" domain="[]" context="{'group_by':'minimum_planned_date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Purchase Orders Kanban View -->
|
||||
<record model="ir.ui.view" id="view_sale_order_kanban">
|
||||
@@ -381,7 +322,7 @@
|
||||
<span><t t-esc="record.name.value"/> <t t-esc="record.date_order.value and record.date_order.value.split(' ')[0] or False"/></span>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<span t-attf-class="pull-right text-right label #{['draft', 'cancel'].indexOf(record.state.raw_value) > -1 ? 'label-default' : ['except_picking', 'except_invoice'].indexOf(record.state.raw_value) > -1 ? 'label-danger' : ['approved'].indexOf(record.state.raw_value) > -1 ? 'label-warning' : ['done'].indexOf(record.state.raw_value) > -1 ? 'label-success' : 'label-primary'}"><t t-esc="record.state.value"/></span>
|
||||
<span t-attf-class="pull-right text-right label #{['draft', 'cancel'].indexOf(record.state.raw_value) > -1 ? 'label-default' : ['approved'].indexOf(record.state.raw_value) > -1 ? 'label-warning' : ['done'].indexOf(record.state.raw_value) > -1 ? 'label-success' : 'label-primary'}"><t t-esc="record.state.value"/></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -395,13 +336,13 @@
|
||||
<field name="name">purchase.order.tree</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-bf="message_needaction==True" decoration-muted="state=='cancel'" decoration-info="state in ('wait','confirmed')" decoration-danger="state in ('except_invoice','except_picking')" string="Purchase Order">
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<tree decoration-bf="message_unread==True" decoration-muted="state=='cancel'" decoration-info="state in ('wait','confirmed')" string="Purchase Order">
|
||||
<field name="message_unread" invisible="1"/>
|
||||
<field name="name" string="Reference"/>
|
||||
<field name="date_order" />
|
||||
<field name="partner_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="minimum_planned_date" invisible="context.get('quotation_only', False)"/>
|
||||
<field name="date_planned" invisible="context.get('quotation_only', False)"/>
|
||||
<field name="origin"/>
|
||||
<field name="amount_untaxed" sum="Total Untaxed amount" string="Untaxed" widget="monetary"/>
|
||||
<field name="amount_total" sum="Total amount" widget="monetary"/>
|
||||
@@ -440,7 +381,7 @@
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">purchase.order</field>
|
||||
<field name="view_mode">tree,kanban,form,pivot,graph,calendar</field>
|
||||
<field name="context">{'search_default_todo':1}</field>
|
||||
<field name="context">{'search_default_todo':1, 'show_purchase': True}</field>
|
||||
<field name="domain">[('state','not in',('draft','sent','bid', 'confirmed'))]</field>
|
||||
<field name="search_view_id" ref="view_purchase_order_filter"/>
|
||||
<field name="help" type="html">
|
||||
@@ -456,42 +397,6 @@
|
||||
</record>
|
||||
<menuitem action="purchase_form_action" id="menu_purchase_form_action" parent="menu_procurement_management" sequence="6"/>
|
||||
|
||||
<record id="purchase_order_line_form" model="ir.ui.view">
|
||||
<field name="name">purchase.order.line.form</field>
|
||||
<field name="model">purchase.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Purchase Order Line">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id"/>
|
||||
<label for="product_qty"/>
|
||||
<div>
|
||||
<field name="product_qty" class="oe_inline"/>
|
||||
<field name="product_uom" groups="product.group_uom" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="price_unit"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use', '=', 'purchase')]"/>
|
||||
<field name="date_planned" widget="date"/>
|
||||
<field name="account_analytic_id" colspan="2" groups="purchase.group_analytic_accounting"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Notes">
|
||||
<field name="name"/>
|
||||
</page><page string="Invoices and Incoming Shipments">
|
||||
<field name="invoice_lines"/>
|
||||
<field name="move_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_order_line_tree" model="ir.ui.view">
|
||||
<field name="name">purchase.order.line.tree</field>
|
||||
<field name="model">purchase.order.line</field>
|
||||
@@ -506,12 +411,10 @@
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="price_subtotal" widget="monetary"/>
|
||||
<field name="date_planned" widget="date" width="135"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="invoiced" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="purchase_order_line_form2" model="ir.ui.view">
|
||||
<field name="name">purchase.order.line.form2</field>
|
||||
<field name="model">purchase.order.line</field>
|
||||
@@ -521,7 +424,7 @@
|
||||
<sheet>
|
||||
<label for="order_id" class="oe_edit_only"/>
|
||||
<h1>
|
||||
<field name="order_id" class="oe_inline" domain="[('invoice_method','=','manual')]" />
|
||||
<field name="order_id" class="oe_inline"/>
|
||||
<label string="," attrs="{'invisible':[('date_order','=',False)]}"/>
|
||||
<field name="date_order" class="oe_inline"/>
|
||||
</h1>
|
||||
@@ -543,7 +446,6 @@
|
||||
<field name="date_planned" widget="date" readonly="1"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="account_analytic_id" colspan="4" groups="purchase.group_analytic_accounting"/>
|
||||
<field name="invoiced"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="name"/>
|
||||
@@ -574,42 +476,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_line_form_action2" model="ir.actions.act_window">
|
||||
<field name="name">Purchase Order Lines</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">purchase.order.line</field>
|
||||
<field name="domain">[('order_id.invoice_method','=','manual'), ('state','in',('confirmed','done')), ('invoiced', '=', False)]</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="purchase_order_line_search"/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
Here you can track all the lines of purchase orders where the
|
||||
invoicing is "Based on Purchase Order Lines", and for which you
|
||||
have not received a vendor bill yet. You can generate a
|
||||
draft vendor bill based on the lines from this list.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_line_form_action_tree2" model="ir.actions.act_window.view">
|
||||
<field eval="1" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="purchase_order_line_tree"/>
|
||||
<field name="act_window_id" ref="purchase_line_form_action2"/>
|
||||
</record>
|
||||
<record id="purchase_line_form_action_form2" model="ir.actions.act_window.view">
|
||||
<field eval="2" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="purchase_order_line_form2"/>
|
||||
<field name="act_window_id" ref="purchase_line_form_action2"/>
|
||||
</record>
|
||||
<menuitem
|
||||
action="purchase_line_form_action2"
|
||||
id="menu_purchase_line_order_draft"
|
||||
parent="menu_procurement_management_invoice"
|
||||
sequence="72"/>
|
||||
|
||||
<!-- Procurements -->
|
||||
|
||||
<record id="view_procurement_form_inherit" model="ir.ui.view">
|
||||
@@ -636,6 +502,9 @@
|
||||
<label for="purchase_ok"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name="uom_po_id" position="after">
|
||||
<field name="purchase_method" widget="radio" groups="base.group_no_one"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -664,7 +533,8 @@
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_purchase_line_product_tree">
|
||||
<field name="context">{}</field><!-- force empty -->
|
||||
<field name="context">{}</field>
|
||||
<field name="domain">[('product_id','in',active_ids)]</field>
|
||||
<field name="name">Purchases</field>
|
||||
<field name="res_model">purchase.order.line</field>
|
||||
<field name="view_id" ref="purchase_order_line_tree"/>
|
||||
@@ -691,25 +561,9 @@
|
||||
<field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button class="oe_stat_button" name="action_view_purchases" type="object"
|
||||
icon="fa-shopping-cart"
|
||||
groups="base.group_no_one">
|
||||
<field string="Purchases" name="purchase_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_product_normal_purchase_buttons_from" model="ir.ui.view">
|
||||
<field name="name">product.product.purchase.button.inherit</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button class="oe_stat_button" name="action_view_purchases" type="object"
|
||||
icon="fa-shopping-cart"
|
||||
groups="base.group_no_one">
|
||||
<button class="oe_stat_button" name="%(purchase.action_purchase_line_product_tree)d"
|
||||
type="action" icon="fa-shopping-cart"
|
||||
groups="base.group_no_one">
|
||||
<field string="Purchases" name="purchase_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="purchase_order" model="workflow">
|
||||
<field name="name">Purchase Order Basic Workflow</field>
|
||||
<field name="osv">purchase.order</field>
|
||||
<field name="on_create">True</field>
|
||||
</record>
|
||||
|
||||
<record id="act_draft" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="flow_start">True</field>
|
||||
<field name="name">draft</field>
|
||||
</record>
|
||||
<record id="act_sent" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">sent</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">write({'state':'sent'})</field>
|
||||
</record>
|
||||
<record id="act_bid" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">bid</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">wkf_bid_received()</field>
|
||||
</record>
|
||||
<record id="act_confirmed" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">confirmed</field>
|
||||
<field name="split_mode">OR</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">wkf_confirm_order()</field>
|
||||
</record>
|
||||
<record id="act_cancel" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">cancel</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="flow_stop">True</field>
|
||||
<field name="action">wkf_action_cancel()</field>
|
||||
</record>
|
||||
<record id="act_except_invoice" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">except_invoice</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">write({'state':'except_invoice'})</field>
|
||||
</record>
|
||||
<record id="act_except_picking" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">except_picking</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">write({'state':'except_picking'})</field>
|
||||
</record>
|
||||
<record id="act_router" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">router</field>
|
||||
<field name="split_mode">OR</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="join_mode">AND</field>
|
||||
<field name="action">wkf_approve_order()</field>
|
||||
</record>
|
||||
<record id="act_invoice" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">invoice</field>
|
||||
<field name="kind">subflow</field>
|
||||
<field name="subflow_id" search="[('osv','=','account.invoice')]"/>
|
||||
<field name="action">action_invoice_create()</field>
|
||||
</record>
|
||||
<record id="act_invoice_done" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">invoice_done</field>
|
||||
<field name="action">invoice_done()</field>
|
||||
<field name="kind">function</field>
|
||||
</record>
|
||||
<record id="act_invoice_end" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">invoice_end</field>
|
||||
</record>
|
||||
<record id="act_picking" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">picking</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">action_picking_create()</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<record id="act_picking_done" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">picking_done</field>
|
||||
<field name="action">picking_done()</field>
|
||||
<field name="kind">function</field>
|
||||
</record>
|
||||
<record id="act_done" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">done</field>
|
||||
<field name="action">wkf_po_done()</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="flow_stop">True</field>
|
||||
<field name="join_mode">AND</field>
|
||||
</record>
|
||||
|
||||
<record id="trans_draft_confirmed" model="workflow.transition">
|
||||
<field name="act_from" ref="act_draft"/>
|
||||
<field name="act_to" ref="act_confirmed"/>
|
||||
<field name="signal">purchase_confirm</field>
|
||||
</record>
|
||||
<record id="trans_draft_sent" model="workflow.transition">
|
||||
<field name="act_from" ref="act_draft"/>
|
||||
<field name="act_to" ref="act_sent"/>
|
||||
<field name="signal">send_rfq</field>
|
||||
</record>
|
||||
<record id="trans_bid_confirmed" model="workflow.transition">
|
||||
<field name="act_from" ref="act_bid"/>
|
||||
<field name="act_to" ref="act_confirmed"/>
|
||||
<field name="signal">purchase_confirm</field>
|
||||
</record>
|
||||
<record id="trans_sent_bid" model="workflow.transition">
|
||||
<field name="act_from" ref="act_sent"/>
|
||||
<field name="act_to" ref="act_bid"/>
|
||||
<field name="signal">bid_received</field>
|
||||
</record>
|
||||
<record id="trans_sent_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_sent"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_bid_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_bid"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
|
||||
<record id="trans_confirmed_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_confirmed"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_draft_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_draft"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_confirmed_router" model="workflow.transition">
|
||||
<field name="act_from" ref="act_confirmed"/>
|
||||
<field name="act_to" ref="act_router"/>
|
||||
<!-- <field name="signal">purchase_approve</field> removed from simplification/useability -->
|
||||
</record>
|
||||
<record id="trans_router_picking" model="workflow.transition">
|
||||
<field name="act_from" ref="act_router"/>
|
||||
<field name="act_to" ref="act_picking"/>
|
||||
<field name="condition">has_stockable_product()</field>
|
||||
</record>
|
||||
<record id="trans_router_picking_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_router"/>
|
||||
<field name="act_to" ref="act_picking_done"/>
|
||||
<field name="condition">not has_stockable_product()</field>
|
||||
</record>
|
||||
<record id="trans_router_invoice" model="workflow.transition">
|
||||
<field name="act_from" ref="act_router"/>
|
||||
<field name="act_to" ref="act_invoice"/>
|
||||
<field name="condition">invoice_method=='order'</field>
|
||||
</record>
|
||||
<record id="trans_router_invoice_no_order" model="workflow.transition">
|
||||
<field name="act_from" ref="act_router"/>
|
||||
<field name="act_to" ref="act_invoice_end"/>
|
||||
<field name="condition">invoice_method<>'order'</field>
|
||||
</record>
|
||||
<record id="trans_except_picking_picking_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_except_picking"/>
|
||||
<field name="act_to" ref="act_picking_done"/>
|
||||
<field name="signal">picking_ok</field>
|
||||
</record>
|
||||
<record id="trans_except_invoice_invoice_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_except_invoice"/>
|
||||
<field name="act_to" ref="act_invoice_done"/>
|
||||
<field name="signal">invoice_ok</field>
|
||||
</record>
|
||||
<record id="trans_except_picking" model="workflow.transition">
|
||||
<field name="act_from" ref="act_except_picking"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_except_invoice" model="workflow.transition">
|
||||
<field name="act_from" ref="act_except_invoice"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_picking_except_picking" model="workflow.transition">
|
||||
<field name="act_from" ref="act_picking"/>
|
||||
<field name="act_to" ref="act_except_picking"/>
|
||||
<field name="signal">picking_cancel</field>
|
||||
</record>
|
||||
<record id="trans_invoice_except_invoice" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice"/>
|
||||
<field name="act_to" ref="act_except_invoice"/>
|
||||
<field name="signal">subflow.cancel</field>
|
||||
</record>
|
||||
<record id="trans_picking_picking_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_picking"/>
|
||||
<field name="act_to" ref="act_picking_done"/>
|
||||
<field name="signal">picking_done</field>
|
||||
|
||||
</record>
|
||||
<record id="trans_invoice_invoice_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice"/>
|
||||
<field name="act_to" ref="act_invoice_done"/>
|
||||
<field name="signal">subflow.paid</field>
|
||||
</record>
|
||||
<record id="trans_picking_done_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_picking_done"/>
|
||||
<field name="act_to" ref="act_done"/>
|
||||
</record>
|
||||
<record id="trans_invoice_done_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice_done"/>
|
||||
<field name="act_to" ref="act_invoice_end"/>
|
||||
</record>
|
||||
<record id="trans_invoice_end_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice_end"/>
|
||||
<field name="act_to" ref="act_done"/>
|
||||
<field name="condition">invoiced</field>
|
||||
</record>
|
||||
<record id="trans_invoice_end_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice_end"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
<field name="condition">invoice_method<>'order'</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -14,20 +14,17 @@ class purchase_report(osv.osv):
|
||||
_auto = False
|
||||
_columns = {
|
||||
'date': fields.datetime('Order Date', readonly=True, help="Date on which this document has been created"), # TDE FIXME master: rename into date_order
|
||||
'state': fields.selection([('draft', 'Request for Quotation'),
|
||||
('confirmed', 'Waiting Vendor Ack'),
|
||||
('approved', 'Approved'),
|
||||
('except_picking', 'Shipping Exception'),
|
||||
('except_invoice', 'Invoice Exception'),
|
||||
('done', 'Done'),
|
||||
('cancel', 'Cancelled')],'Order Status', readonly=True),
|
||||
'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),
|
||||
'location_id': fields.many2one('stock.location', 'Destination', readonly=True),
|
||||
'partner_id':fields.many2one('res.partner', 'Vendor', readonly=True),
|
||||
'date_approve':fields.date('Date Approved', readonly=True),
|
||||
'expected_date':fields.date('Expected Date', readonly=True),
|
||||
'validator' : fields.many2one('res.users', 'Validated By', 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),
|
||||
@@ -64,11 +61,9 @@ class purchase_report(osv.osv):
|
||||
select
|
||||
min(l.id) as id,
|
||||
s.date_order as date,
|
||||
l.state,
|
||||
s.state,
|
||||
s.date_approve,
|
||||
s.minimum_planned_date as expected_date,
|
||||
s.dest_address_id,
|
||||
s.validator,
|
||||
spt.warehouse_id as picking_type_id,
|
||||
s.partner_id as partner_id,
|
||||
s.create_uid as user_id,
|
||||
@@ -78,7 +73,6 @@ class purchase_report(osv.osv):
|
||||
p.product_tmpl_id,
|
||||
t.categ_id as category_id,
|
||||
t.uom_id as product_uom,
|
||||
s.location_id as location_id,
|
||||
sum(l.product_qty/u.factor*u2.factor) as quantity,
|
||||
extract(epoch from age(s.date_approve,s.date_order))/(24*60*60)::decimal(16,2) as delay,
|
||||
extract(epoch from age(l.date_planned,s.date_order))/(24*60*60)::decimal(16,2) as delay_pass,
|
||||
@@ -108,20 +102,17 @@ class purchase_report(osv.osv):
|
||||
s.create_uid,
|
||||
s.partner_id,
|
||||
u.factor,
|
||||
s.location_id,
|
||||
l.price_unit,
|
||||
s.date_approve,
|
||||
l.date_planned,
|
||||
l.product_uom,
|
||||
s.minimum_planned_date,
|
||||
s.validator,
|
||||
s.dest_address_id,
|
||||
s.fiscal_position_id,
|
||||
l.product_id,
|
||||
p.product_tmpl_id,
|
||||
t.categ_id,
|
||||
s.date_order,
|
||||
l.state,
|
||||
s.state,
|
||||
spt.warehouse_id,
|
||||
u.uom_type,
|
||||
u.category_id,
|
||||
|
||||
@@ -61,13 +61,10 @@
|
||||
<field name="product_id"/>
|
||||
<group expand="0" string="Extended Filters">
|
||||
<field name="user_id"/>
|
||||
<field name="validator"/>
|
||||
<field name="location_id"/>
|
||||
<field name="picking_type_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="date"/>
|
||||
<field name="date_approve"/>
|
||||
<field name="expected_date"/>
|
||||
</group>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Vendor" name="group_partner_id" context="{'group_by':'partner_id'}"/>
|
||||
|
||||
@@ -15,11 +15,6 @@ class purchase_config_settings(osv.osv_memory):
|
||||
], "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'),
|
||||
'default_invoice_method': fields.selection(
|
||||
[('manual', 'Control vendor bill on purchase order line'),
|
||||
('picking', 'Control vendor bill on incoming shipments'),
|
||||
('order', 'Control vendor bill on a pregenerated draft invoice'),
|
||||
], 'Default invoicing control method', required=True, default_model='purchase.order'),
|
||||
'group_uom':fields.selection([
|
||||
(0, 'Products have only one unit of measure (easier)'),
|
||||
(1, 'Some products may be sold/puchased in different unit of measures (advanced)')
|
||||
@@ -53,10 +48,6 @@ class purchase_config_settings(osv.osv_memory):
|
||||
'-This installs the module stock_dropshipping.'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'default_invoice_method': 'order',
|
||||
}
|
||||
|
||||
|
||||
class account_config_settings(osv.osv_memory):
|
||||
_inherit = 'account.config.settings'
|
||||
|
||||
@@ -22,12 +22,6 @@
|
||||
<button string="Apply" type="object" name="execute" class="oe_highlight"/>
|
||||
<button string="Cancel" type="object" name="cancel" class="oe_link"/>
|
||||
</header>
|
||||
<group string="Invoicing Process">
|
||||
<label for="id" string="Default Invoicing Settings"/>
|
||||
<div>
|
||||
<field name="default_invoice_method" widget="radio"/>
|
||||
</div>
|
||||
</group>
|
||||
<group string="Purchase Order">
|
||||
<field name="group_product_variant" widget="radio"/>
|
||||
<field name="group_uom" widget="radio"/>
|
||||
|
||||
+8
-141
@@ -6,6 +6,14 @@ from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
class stock_picking(osv.osv):
|
||||
_inherit = 'stock.picking'
|
||||
_columns = {
|
||||
'purchase_id': fields.related('move_lines', 'purchase_line_id', 'order_id', string="Purchase Orders",
|
||||
readonly=True, relation="many2one"),
|
||||
}
|
||||
|
||||
|
||||
class stock_move(osv.osv):
|
||||
_inherit = 'stock.move'
|
||||
_columns = {
|
||||
@@ -18,34 +26,8 @@ class stock_move(osv.osv):
|
||||
""" Returns the unit price to store on the quant """
|
||||
if move.purchase_line_id:
|
||||
return move.price_unit
|
||||
|
||||
return super(stock_move, self).get_price_unit(cr, uid, move, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
res = super(stock_move, self).write(cr, uid, ids, vals, context=context)
|
||||
from openerp import workflow
|
||||
if vals.get('state') in ['done', 'cancel']:
|
||||
po_to_check = []
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
if move.purchase_line_id and move.purchase_line_id.order_id:
|
||||
order = move.purchase_line_id.order_id
|
||||
order_id = order.id
|
||||
# update linked purchase order as superuser as the warehouse
|
||||
# user may not have rights to access purchase.order
|
||||
if self.pool.get('purchase.order').test_moves_done(cr, uid, [order_id], context=context):
|
||||
workflow.trg_validate(SUPERUSER_ID, 'purchase.order', order_id, 'picking_done', cr)
|
||||
if self.pool.get('purchase.order').test_moves_except(cr, uid, [order_id], context=context):
|
||||
workflow.trg_validate(SUPERUSER_ID, 'purchase.order', order_id, 'picking_cancel', cr)
|
||||
if order_id not in po_to_check and vals['state'] == 'cancel' and order.invoice_method == 'picking':
|
||||
po_to_check.append(order_id)
|
||||
# Some moves which are cancelled might be part of a PO line which is partially
|
||||
# invoiced, so we check if some PO line can be set on "invoiced = True".
|
||||
if po_to_check:
|
||||
self.pool.get('purchase.order')._set_po_lines_invoiced(cr, uid, po_to_check, context=context)
|
||||
return res
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
default = default or {}
|
||||
context = context or {}
|
||||
@@ -54,121 +36,6 @@ class stock_move(osv.osv):
|
||||
default['purchase_line_id'] = False
|
||||
return super(stock_move, self).copy(cr, uid, id, default, context)
|
||||
|
||||
def _get_master_data(self, cr, uid, move, inv_type, context=None):
|
||||
if inv_type == 'in_invoice' and move.purchase_line_id:
|
||||
purchase_order = move.purchase_line_id.order_id
|
||||
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
|
||||
if inv_type == 'in_refund' and move.origin_returned_move_id.purchase_line_id:
|
||||
purchase_order = move.origin_returned_move_id.purchase_line_id.order_id
|
||||
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
|
||||
elif inv_type in ('in_invoice', 'in_refund') and move.picking_id:
|
||||
# In case of an extra move, it is better to use the data from the original moves
|
||||
for purchase_move in move.picking_id.move_lines:
|
||||
if purchase_move.purchase_line_id:
|
||||
purchase_order = purchase_move.purchase_line_id.order_id
|
||||
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
|
||||
|
||||
partner = move.picking_id and move.picking_id.partner_id or False
|
||||
code = self.get_code_from_locs(cr, uid, move, context=context)
|
||||
if partner and code == 'incoming':
|
||||
currency = purchase_order.currency_id.id
|
||||
return partner, uid, currency
|
||||
return super(stock_move, self)._get_master_data(cr, uid, move, inv_type, context=context)
|
||||
|
||||
def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None):
|
||||
res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context)
|
||||
purchase_line = False
|
||||
if inv_type == 'in_invoice' and move.purchase_line_id:
|
||||
purchase_line = move.purchase_line_id
|
||||
elif inv_type == 'in_refund' and move.origin_returned_move_id.purchase_line_id:
|
||||
purchase_line = move.origin_returned_move_id.purchase_line_id
|
||||
if purchase_line:
|
||||
res['invoice_line_tax_ids'] = [(6, 0, [x.id for x in purchase_line.taxes_id])]
|
||||
res['price_unit'] = purchase_line.price_unit
|
||||
res['account_analytic_id'] = purchase_line.account_analytic_id.id
|
||||
res['purchase_line_ids'] = [(4, purchase_line.id)]
|
||||
return res
|
||||
|
||||
def _get_moves_taxes(self, cr, uid, moves, inv_type, context=None):
|
||||
is_extra_move, extra_move_tax = super(stock_move, self)._get_moves_taxes(cr, uid, moves, inv_type, context=context)
|
||||
if inv_type == 'in_invoice':
|
||||
for move in moves:
|
||||
if move.purchase_line_id:
|
||||
is_extra_move[move.id] = False
|
||||
extra_move_tax[move.picking_id, move.product_id] = [(6, 0, [x.id for x in move.purchase_line_id.taxes_id])]
|
||||
elif move.product_id.product_tmpl_id.supplier_taxes_id:
|
||||
mov_id = self.search(cr, uid, [('purchase_line_id', '!=', False), ('picking_id', '=', move.picking_id.id)], limit=1, context=context)
|
||||
if mov_id:
|
||||
mov = self.browse(cr, uid, mov_id[0], context=context)
|
||||
fp = mov.purchase_line_id.order_id.fiscal_position
|
||||
res = self.pool.get("account.invoice.line").product_id_change(cr, uid, [], move.product_id.id, None, partner_id=move.picking_id.partner_id.id, fposition_id=(fp and fp.id), type='in_invoice', context=context)
|
||||
extra_move_tax[0, move.product_id] = [(6, 0, res['value']['invoice_line_tax_ids'])]
|
||||
return (is_extra_move, extra_move_tax)
|
||||
|
||||
def _get_taxes(self, cr, uid, move, context=None):
|
||||
if move.origin_returned_move_id.purchase_line_id.taxes_id:
|
||||
return [tax.id for tax in move.origin_returned_move_id.purchase_line_id.taxes_id]
|
||||
return super(stock_move, self)._get_taxes(cr, uid, move, context=context)
|
||||
|
||||
class stock_picking(osv.osv):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
def _get_to_invoice(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
for picking in self.browse(cr, uid, ids, context=context):
|
||||
res[picking.id] = False
|
||||
for move in picking.move_lines:
|
||||
if move.purchase_line_id and move.purchase_line_id.order_id.invoice_method == 'picking':
|
||||
if not move.move_orig_ids:
|
||||
res[picking.id] = True
|
||||
return res
|
||||
|
||||
def _get_picking_to_recompute(self, cr, uid, ids, context=None):
|
||||
picking_ids = set()
|
||||
for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
|
||||
if move.picking_id and move.purchase_line_id:
|
||||
picking_ids.add(move.picking_id.id)
|
||||
return list(picking_ids)
|
||||
|
||||
_columns = {
|
||||
'reception_to_invoice': fields.function(_get_to_invoice, type='boolean', string='Invoiceable on incoming shipment',
|
||||
help='Does the picking contain some moves related to a purchase order invoiceable on the receipt?',
|
||||
store={
|
||||
'stock.move': (_get_picking_to_recompute, ['purchase_line_id', 'picking_id'], 10),
|
||||
}),
|
||||
}
|
||||
|
||||
def _get_invoice_vals(self, cr, uid, key, inv_type, journal_id, moves, context=None):
|
||||
inv_vals = super(stock_picking, self)._get_invoice_vals(cr, uid, key, inv_type, journal_id, moves, context=context)
|
||||
purchases = []
|
||||
for move in moves:
|
||||
if move.purchase_line_id or move.origin_returned_move_id.purchase_line_id:
|
||||
purchase = move.purchase_line_id.order_id or move.origin_returned_move_id.purchase_line_id.order_id
|
||||
inv_vals.update({
|
||||
'fiscal_position_id': purchase.fiscal_position_id.id,
|
||||
'payment_term_id': purchase.payment_term_id.id,
|
||||
})
|
||||
purchases.append(purchase.id)
|
||||
if purchases:
|
||||
inv_vals['purchase_ids'] = [(6, 0, list(set(purchases)))]
|
||||
return inv_vals
|
||||
|
||||
def get_service_line_vals(self, cr, uid, moves, partner, inv_type, context=None):
|
||||
purchase_obj = self.pool['purchase.order']
|
||||
purchase_line_obj = self.pool['purchase.order.line']
|
||||
res = super(stock_picking, self).get_service_line_vals(cr, uid, moves, partner, inv_type, context=context)
|
||||
# Add service lines for purchases
|
||||
if inv_type == 'in_invoice':
|
||||
purchase_ids = list(set([x.purchase_line_id.order_id.id for x in moves if x.purchase_line_id]))
|
||||
purchase_line_ids = purchase_line_obj.search(cr, uid, [('order_id', 'in', purchase_ids), ('invoice_lines', '=', False), '|', ('product_id', '=', False),
|
||||
('product_id.type', '=', 'service')], context=context)
|
||||
for po_line in purchase_line_obj.browse(cr, uid, purchase_line_ids, context=context):
|
||||
acc_id = purchase_obj._choose_account_from_po_line(cr, uid, po_line, context=context)
|
||||
inv_line_data = purchase_obj._prepare_inv_line(cr, uid, acc_id, po_line, context=context)
|
||||
inv_line_data['purchase_line_ids'] = [(4, po_line.id)]
|
||||
res += [(0, 0, inv_line_data)]
|
||||
return res
|
||||
|
||||
|
||||
class stock_warehouse(osv.osv):
|
||||
_inherit = 'stock.warehouse'
|
||||
|
||||
@@ -23,32 +23,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- is it need ? we have another method "Receive Products"-->
|
||||
<record id="purchase_order_2_stock_picking" model="ir.ui.view">
|
||||
<field name="name">Purchase Picking Inherited</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="inherit_id" ref="purchase.purchase_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[contains(@class, 'oe_title')]" position="before">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button type="object"
|
||||
name="view_picking"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
attrs="{'invisible': [('shipment_count', '=', 0)]}">
|
||||
<field name="shipment_count" widget="statinfo" string="Shipment" help="Incoming Shipments"/>
|
||||
</button>
|
||||
<button type="object" name="invoice_open"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o"
|
||||
attrs="{'invisible': [('invoice_count', '=', 0)]}">
|
||||
<field name="invoice_count" widget="statinfo" string="Invoices"/>
|
||||
</button>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_warehouse_inherited" model="ir.ui.view">
|
||||
<field name="name">Stock Warehouse Inherited</field>
|
||||
<field name="model">stock.warehouse</field>
|
||||
@@ -60,28 +34,5 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_picking_tree_picking_to_invoice" model="ir.actions.act_window">
|
||||
<field name="name">Incoming Shipments</field>
|
||||
<field name="res_model">stock.picking</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar</field>
|
||||
<field name="context">{"default_type": "in", "contact_display": "partner_address", "search_default_done": 1, "search_default_reception_to_invoice": 1}</field>
|
||||
<field name="search_view_id" ref="stock.view_picking_internal_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new incoming shipment.
|
||||
</p><p>
|
||||
Here you can track all the product receipts of purchase
|
||||
orders where the invoicing is "Based on Incoming Shipments",
|
||||
and for which you have not received a supplier bill yet.
|
||||
You can generate a supplier bill based on those receipts.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_picking_tree_picking_to_invoice"
|
||||
id="menu_action_picking_tree_picking_to_invoice"
|
||||
parent="purchase.menu_procurement_management_invoice" sequence="90"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
-
|
||||
I first set the company to use anglo saxon accounting.
|
||||
-
|
||||
!python {model: res.company}: |
|
||||
self.pool.get('res.company').write(cr, uid, ref("base.main_company"), {'anglo_saxon_accounting': True,})
|
||||
-
|
||||
In order to test anglo_saxon Configure Different Accounts.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_valuation}:
|
||||
code: X3000
|
||||
name: Stock Valuation Account- (test)
|
||||
user_type_id: account.data_account_type_current_assets
|
||||
-
|
||||
Configure Stock Interim account (Received).
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_input}:
|
||||
code: X2800
|
||||
name: Stock Interim account (Received)
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Stock Interim account (Delivered).
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_output}:
|
||||
code: X2801
|
||||
name: Stock Interim account (Delivered)
|
||||
user_type_id: account.data_account_type_revenue
|
||||
-
|
||||
Configure Price difference creditor Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_price_difference}:
|
||||
code: X7095
|
||||
name: Price difference creditor Account
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Cash Bank Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_cash}:
|
||||
code: X5000
|
||||
name: Cash/Bank Account
|
||||
user_type_id: account.data_account_type_liquidity
|
||||
reconcile: True
|
||||
-
|
||||
Configure Creditor Account Payable.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_payable}:
|
||||
code: X440001
|
||||
name: Creditor Account Payable
|
||||
user_type_id: account.data_account_type_payable
|
||||
reconcile: True
|
||||
-
|
||||
Configure Debtor Account Receivable.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_receivable}:
|
||||
code: X400001
|
||||
name: Debtor Account Receivable
|
||||
user_type_id: account.data_account_type_receivable
|
||||
reconcile: True
|
||||
-
|
||||
Configure Cost of Good sale Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_cogs}:
|
||||
code: X7000
|
||||
name: Cost of goods sale account
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Income Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_income}:
|
||||
code: X8000
|
||||
name: Income Account
|
||||
user_type_id: account.data_account_type_revenue
|
||||
-
|
||||
I configure the account receivable of supplier
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_3}:
|
||||
property_account_payable_id: account_anglo_payable
|
||||
property_account_receivable_id: account_anglo_receivable
|
||||
-
|
||||
I configure the account receivable of Customer.
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_2}:
|
||||
property_account_payable_id: account_anglo_payable
|
||||
property_account_receivable_id: account_anglo_receivable
|
||||
-
|
||||
I configure the product category with stock valuation account.
|
||||
-
|
||||
!record {model: product.category, id: product.product_category_5}:
|
||||
property_stock_valuation_account_id: account_anglo_stock_valuation
|
||||
-
|
||||
I configure the product with required accounts, and cost method = standard
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
self.write(cr, uid, [ref('product.product_product_10')], {'list_price': 20.00,'standard_price': 9,'categ_id': ref('product.product_category_5'),'valuation': 'real_time',
|
||||
'property_account_income_id': ref('account_anglo_income'),'property_account_expense_id': ref('account_anglo_cogs'),
|
||||
'property_account_creditor_price_difference': ref('account_anglo_price_difference'),'property_stock_account_input': ref('account_anglo_stock_input'),
|
||||
'property_stock_account_output': ref('account_anglo_stock_output'), 'cost_method': 'standard'})
|
||||
-
|
||||
I create a draft Purchase Order.
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_001}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product.product_product_10
|
||||
product_qty: 1
|
||||
price_unit: 10
|
||||
date_planned: !eval "'%s' % (time.strftime('%Y-%m-%d'))"
|
||||
-
|
||||
I confirm the purchase order.
|
||||
-
|
||||
!workflow {model: purchase.order, ref: purchase_order_001, action: purchase_confirm}
|
||||
-
|
||||
Receipt is ready for process so now we do it.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking_id = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001"), context=context).picking_ids[0]
|
||||
picking_id.do_transfer()
|
||||
-
|
||||
I check the Stock Interim account (Received) is credited successfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_stock_input')).credit
|
||||
# float_compare(credit, 9, precision_digits=2) == 0, "Stock Interim account (Received) is not credited successfully."
|
||||
-
|
||||
I check the Stock valuation account is debited sucessfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_valuation')).debit
|
||||
# float_compare(debit, 9, precision_digits=2) == 0, "Stock valuation account is not debited successfully."
|
||||
-
|
||||
I Validate Invoice of Purchase Order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001")).invoice_ids]
|
||||
self.pool.get('account.invoice').signal_workflow(cr, uid, invoice_ids, 'invoice_open')
|
||||
-
|
||||
I check the Stock Interim account (Received) is debited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_input')).debit
|
||||
# float_compare(debit, 9, precision_digits=2) == 0, "Stock Interim account (Received) is not debited successfully."
|
||||
-
|
||||
I check the Price difference creditor Account is debited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_price_difference')).debit
|
||||
# float_compare(debit, 1, precision_digits=2) == 0, "Price difference creditor Account is not debited successfully."
|
||||
-
|
||||
I check Payable(creditor) Account is Credited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_payable')).credit
|
||||
# float_compare(credit, 10, precision_digits=2) == 0, "Payable(creditor) Account is not Credited successfully."
|
||||
-
|
||||
I open the Invoice.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
po = self.browse(cr, uid, ref("purchase_order_001"))
|
||||
for invoice in po.invoice_ids:
|
||||
invoice.signal_workflow('invoice_open')
|
||||
-
|
||||
I pay the invoice.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_ids = self.browse(cr, uid, ref("purchase_order_001")).invoice_ids
|
||||
order = self.browse(cr, uid, ref("purchase_order_001"))
|
||||
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
|
||||
import time
|
||||
for invoice in invoice_ids:
|
||||
self.pool.get('account.invoice').pay_and_reconcile(cr, uid, [invoice.id], journal_ids[0])
|
||||
-
|
||||
I check Payable(Creditors) Account is Debited sucessfully after invoice paid.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_payable')).debit
|
||||
# assert float_compare(debit, 10, precision_digits=2) == 0, "Payable(Creditors) Account is not Debited successfully."
|
||||
-
|
||||
I check Bank/Cash account is credited sucessfully after invoice paid.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_cash')).credit
|
||||
# float_compare(credit, 10, precision_digits=2) == 0, "Bank/Cash account is not credited successfully."
|
||||
-
|
||||
I create an Outgoing Picking order
|
||||
-
|
||||
!record {model: stock.picking, id: stock_picking_out001}:
|
||||
partner_id: base.res_partner_2
|
||||
move_lines:
|
||||
- company_id: base.main_company
|
||||
location_id: stock.stock_location_stock
|
||||
product_id: product.product_product_10
|
||||
product_uom_qty: 1.0
|
||||
product_uom: product.product_uom_unit
|
||||
location_dest_id: stock.stock_location_customers
|
||||
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)
|
||||
|
||||
-
|
||||
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"))
|
||||
assert picking.state == "confirmed", "Picking should be confirmed."
|
||||
for move_line in picking.move_lines:
|
||||
assert move_line.state == "confirmed", "Move should be confirmed."
|
||||
|
||||
-
|
||||
I process the delivery.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.pool.get('stock.picking').browse(cr, uid, ref("stock_picking_out001"), context=context)
|
||||
picking.do_transfer()
|
||||
-
|
||||
I check Stock Interim account (Delivery) is debited successfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_output')).debit
|
||||
# float_compare(debit, 9, precision_digits=2) == 0, "Stock Interim account (Delivery) is not debited successfully."
|
||||
-
|
||||
I check the Stock valuation account is credited sucessfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_stock_valuation')).credit
|
||||
# float_compare(credit, 9, precision_digits=2) == 0, "Stock valuation account is not credited successfully."
|
||||
@@ -1,247 +0,0 @@
|
||||
-
|
||||
I first set the company to use anglo saxon accounting.
|
||||
-
|
||||
!python {model: res.company}: |
|
||||
self.pool.get('res.company').write(cr, uid, ref("base.main_company"), {'anglo_saxon_accounting': True,})
|
||||
-
|
||||
In order to test anglo_saxon Configure Different Accounts.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_valuation_fifo}:
|
||||
code: X3000f
|
||||
name: Stock Valuation Account- (test)
|
||||
user_type_id: account.data_account_type_current_assets
|
||||
-
|
||||
Configure Stock Interim account (Received).
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_input_fifo}:
|
||||
code: X2800f
|
||||
name: Stock Interim account (Received)
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Stock Interim account (Delivered).
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_output_fifo}:
|
||||
code: X2801f
|
||||
name: Stock Interim account (Delivered)
|
||||
user_type_id: account.data_account_type_revenue
|
||||
-
|
||||
Configure Price difference creditor Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_price_difference_fifo}:
|
||||
code: X7095f
|
||||
name: Price difference creditor Account
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Cash Bank Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_cash_fifo}:
|
||||
code: X5000f
|
||||
name: Cash/Bank Account
|
||||
user_type_id: account.data_account_type_liquidity
|
||||
reconcile: True
|
||||
-
|
||||
Configure Creditor Account Payable.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_payable_fifo}:
|
||||
code: X440001f
|
||||
name: Creditor Account Payable
|
||||
user_type_id: account.data_account_type_payable
|
||||
reconcile: True
|
||||
-
|
||||
Configure Debtor Account Receivable.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_receivable_fifo}:
|
||||
code: X400001f
|
||||
name: Debtor Account Receivable
|
||||
user_type_id: account.data_account_type_receivable
|
||||
reconcile: True
|
||||
-
|
||||
Configure Cost of Good sale Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_cogs_fifo}:
|
||||
code: X7000f
|
||||
name: Cost of goods sale account
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Income Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_income_fifo}:
|
||||
code: X8000f
|
||||
name: Income Account
|
||||
user_type_id: account.data_account_type_revenue
|
||||
-
|
||||
I configure the account receivable of supplier
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_3}:
|
||||
property_account_payable_id: account_anglo_payable_fifo
|
||||
property_account_receivable_id: account_anglo_receivable_fifo
|
||||
-
|
||||
I configure the account receivable of Customer.
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_2}:
|
||||
property_account_payable_id: account_anglo_payable_fifo
|
||||
property_account_receivable_id: account_anglo_receivable_fifo
|
||||
-
|
||||
I configure the product category with stock valuation account.
|
||||
-
|
||||
!record {model: product.category, id: product.product_category_5}:
|
||||
property_stock_valuation_account_id: account_anglo_stock_valuation_fifo
|
||||
-
|
||||
I create a product with required accounts, and cost method average (but same applies for fifo)
|
||||
-
|
||||
!record {model: product.product, id: product_fifo_anglo_saxon}:
|
||||
name: 'FIFO product for anglo saxon tests'
|
||||
lst_price: 20.00
|
||||
standard_price: 0
|
||||
categ_id: product.product_category_5
|
||||
valuation: 'real_time'
|
||||
property_account_income_id: account_anglo_income_fifo
|
||||
property_account_expense_id: account_anglo_cogs_fifo
|
||||
property_account_creditor_price_difference: account_anglo_price_difference_fifo
|
||||
property_stock_account_input: account_anglo_stock_input_fifo
|
||||
property_stock_account_output: account_anglo_stock_output_fifo
|
||||
cost_method: 'average'
|
||||
-
|
||||
I create a draft Purchase Order.
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_001_fifo}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_anglo_saxon
|
||||
product_qty: 1
|
||||
price_unit: 9
|
||||
date_planned: !eval "'%s' % (time.strftime('%Y-%m-%d'))"
|
||||
taxes_id: []
|
||||
-
|
||||
I confirm the purchase order.
|
||||
-
|
||||
!workflow {model: purchase.order, ref: purchase_order_001_fifo, action: purchase_confirm}
|
||||
-
|
||||
Receipt is ready for process so now we do it.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking_id = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001_fifo"), context=context).picking_ids[0]
|
||||
picking_id.do_transfer()
|
||||
-
|
||||
I check the Stock Interim account (Received) is credit successfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_stock_input_fifo')).credit
|
||||
# assert float_compare(credit, 9, precision_digits=2) == 0, "Stock Interim account (Received) is not credited successfully."
|
||||
-
|
||||
I check the Stock valuation account is debit sucessfully.
|
||||
-
|
||||
!python {model: account.account, id}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_valuation_fifo')).debit
|
||||
# assert float_compare(debit, 9, precision_digits=2) == 0, "Stock valuation account is not debited successfully."
|
||||
-
|
||||
I Validate Invoice of Purchase Order after having changed the price to 10.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids]
|
||||
line_ids = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', invoice_ids)])
|
||||
self.pool.get('account.invoice.line').write(cr, uid, line_ids, {'price_unit': 10})
|
||||
self.pool.get('account.invoice').signal_workflow(cr, uid, invoice_ids, 'invoice_open')
|
||||
-
|
||||
I check the Stock Interim account (Received) is debited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_input_fifo')).debit
|
||||
# assert float_compare(debit, 9, precision_digits=2) == 0, "Stock Interim account (Received) is not debited successfully."
|
||||
-
|
||||
I check the Price difference creditor Account is debited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_price_difference_fifo')).debit
|
||||
# assert float_compare(debit, 1, precision_digits=2) == 0, "Price difference creditor Account is not debited successfully."
|
||||
-
|
||||
I check Payable(creditor) Account is Credited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_payable_fifo')).credit
|
||||
# assert float_compare(credit, 10, precision_digits=2) == 0, "Payable(creditor) Account is not Credited successfully."
|
||||
-
|
||||
I pay the invoice.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_ids = self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids
|
||||
order = self.browse(cr, uid, ref("purchase_order_001_fifo"))
|
||||
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
|
||||
import time
|
||||
for invoice in invoice_ids:
|
||||
self.pool.get('account.invoice').pay_and_reconcile(cr, uid, [invoice.id], journal_ids[0])
|
||||
-
|
||||
I check Payable(Creditors) Account is Debited sucessfully after invoice paid.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_payable_fifo')).debit
|
||||
# assert float_compare(debit, 10, precision_digits=2) == 0, "Payable(Creditors) Account is not Debited successfully."
|
||||
-
|
||||
I check Bank/Cash account is credited sucessfully after invoice paid.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_cash_fifo')).credit
|
||||
# assert float_compare(credit, 10, precision_digits=2) == 0, "Bank/Cash account is not credited successfully."
|
||||
-
|
||||
I create an Outgoing Picking order
|
||||
-
|
||||
!record {model: stock.picking, id: stock_picking_out001_fifo}:
|
||||
partner_id: base.res_partner_2
|
||||
move_lines:
|
||||
- company_id: base.main_company
|
||||
location_id: stock.stock_location_stock
|
||||
product_id: product_fifo_anglo_saxon
|
||||
product_uom_qty: 1.0
|
||||
location_dest_id: stock.stock_location_customers
|
||||
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_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_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."
|
||||
-
|
||||
I process the delivery.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.pool.get('stock.picking').browse(cr, uid, ref("stock_picking_out001_fifo"), context=context)
|
||||
picking.do_transfer()
|
||||
-
|
||||
I check Stock Interim account (Delivery) is debited successfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_output_fifo')).debit
|
||||
# assert float_compare(debit, 9, precision_digits=2) == 0, "Stock Interim account (Delivery) is not debited successfully."
|
||||
-
|
||||
I check the Stock valuation account is credited sucessfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_stock_valuation_fifo')).credit
|
||||
# assert float_compare(credit, 9, precision_digits=2) == 0, "Stock valuation account is not credited successfully."
|
||||
@@ -18,7 +18,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_average1}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_average_icecream
|
||||
product_qty: 10.0
|
||||
@@ -28,12 +27,13 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_average1}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_average1")])
|
||||
-
|
||||
I check the "Approved" status of purchase order 1
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_average1}:
|
||||
- state == 'approved'
|
||||
- state == 'purchase'
|
||||
-
|
||||
Process the reception of purchase order 1
|
||||
-
|
||||
@@ -52,7 +52,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_average2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_average_icecream
|
||||
product_qty: 30.0
|
||||
@@ -62,7 +61,8 @@
|
||||
-
|
||||
I confirm the second purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_average2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_average2")])
|
||||
-
|
||||
Process the reception of purchase order 2
|
||||
-
|
||||
@@ -106,7 +106,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_average3}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_average_icecream
|
||||
product_qty: 500.0
|
||||
@@ -116,7 +115,8 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_average3}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_average3")])
|
||||
-
|
||||
Process the reception of purchase order 3 in grams
|
||||
-
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_variable1}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_variable_icecream
|
||||
product_qty: 10.0
|
||||
@@ -31,7 +30,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_variable2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_variable_icecream
|
||||
product_qty: 30.0
|
||||
@@ -41,16 +39,18 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_variable1}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_variable1")])
|
||||
-
|
||||
I confirm the second purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_variable2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_variable2")])
|
||||
-
|
||||
I check the "Approved" status of purchase order 1
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_variable1}:
|
||||
- state == 'approved'
|
||||
- state == 'purchase'
|
||||
-
|
||||
Process the reception of purchase order 1
|
||||
-
|
||||
@@ -113,7 +113,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_variable3}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_variable_icecream
|
||||
product_qty: 20.0
|
||||
@@ -123,7 +122,8 @@
|
||||
-
|
||||
I confirm this third purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_variable3}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_variable3")])
|
||||
-
|
||||
Process the reception of purchase order 3
|
||||
-
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
!record {model: purchase.order, id: purchase_order_fifo1}:
|
||||
partner_id: base.res_partner_3
|
||||
currency_id: base.EUR
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_icecream
|
||||
product_qty: 10.0
|
||||
@@ -36,12 +35,13 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo1}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo1")])
|
||||
-
|
||||
I check the "Approved" status of purchase order 1
|
||||
I check the "Purchase" status of purchase order 1
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_fifo1}:
|
||||
- state == 'approved'
|
||||
- state == 'purchase'
|
||||
-
|
||||
Process the reception of purchase order 1 and set date
|
||||
-
|
||||
@@ -58,7 +58,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fifo2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_icecream
|
||||
product_qty: 30.0
|
||||
@@ -68,7 +67,8 @@
|
||||
-
|
||||
I confirm the second purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo2")])
|
||||
-
|
||||
Process the reception of purchase order 2
|
||||
-
|
||||
@@ -160,7 +160,6 @@
|
||||
!record {model: purchase.order, id: purchase_order_fifo_usd}:
|
||||
partner_id: base.res_partner_3
|
||||
currency_id: new_USD
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_icecream
|
||||
product_qty: 30000
|
||||
@@ -174,7 +173,8 @@
|
||||
-
|
||||
I confirm the purchase order in USD
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_usd}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo_usd")])
|
||||
-
|
||||
Process the reception of purchase order with usd
|
||||
-
|
||||
@@ -202,7 +202,7 @@
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
self.action_assign(cr, uid, [ref("outgoing_fifo_shipment_cur")])
|
||||
-
|
||||
-
|
||||
Process the delivery of the outgoing shipment
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
@@ -218,7 +218,7 @@
|
||||
-
|
||||
!record {model: stock.picking, id: outgoing_fifo_shipment_ret}:
|
||||
picking_type_id: stock.picking_type_out
|
||||
-
|
||||
-
|
||||
Picking needs movement from stock
|
||||
-
|
||||
!record {model: stock.move, id: outgoing_shipment_fifo_icecream_ret}:
|
||||
@@ -320,7 +320,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fifo_neg}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_negative
|
||||
product_qty: 50.0
|
||||
@@ -330,7 +329,8 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_neg}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo_neg")])
|
||||
-
|
||||
Process the reception of purchase order 1
|
||||
-
|
||||
@@ -348,7 +348,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fifo_neg2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_negative
|
||||
product_qty: 60.0
|
||||
@@ -358,7 +357,8 @@
|
||||
-
|
||||
I confirm the second negative purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_neg2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo_neg2")])
|
||||
-
|
||||
Process the reception of purchase order 2
|
||||
-
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fiforet1}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fiforet_icecream
|
||||
product_qty: 10.0
|
||||
@@ -31,7 +30,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fiforet2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fiforet_icecream
|
||||
product_qty: 30.0
|
||||
@@ -41,7 +39,8 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fiforet1}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fiforet1")])
|
||||
-
|
||||
Process the reception of purchase order 1
|
||||
-
|
||||
@@ -56,7 +55,8 @@
|
||||
-
|
||||
I confirm the second purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fiforet2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fiforet2")])
|
||||
-
|
||||
Process the reception of purchase order 2
|
||||
-
|
||||
|
||||
@@ -8,50 +8,24 @@
|
||||
-
|
||||
I confirm the purchase order.
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_5}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_5")])
|
||||
-
|
||||
I check the "Approved" status after confirmed RFQ.
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_5}:
|
||||
- state == 'approved'
|
||||
- state == 'purchase'
|
||||
-
|
||||
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])
|
||||
-
|
||||
I check order status in "Shipping Exception".
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
order = self.browse(cr, uid, ref("purchase_order_5"))
|
||||
assert order.state == "except_picking", "order should be in Ship Exception state after cancel shipment"
|
||||
-
|
||||
Now I am able to cancel purchase order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
self.action_cancel(cr, uid, [ref("purchase_order_5")])
|
||||
-
|
||||
I check that order is cancelled.
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_5}:
|
||||
- state == 'cancel'
|
||||
-
|
||||
After cancel the order, I check that it's related invoice cancelled.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
order = self.browse(cr, uid, ref("purchase_order_5"))
|
||||
assert order.invoice_ids[0].state == "cancel", "order's related invoice should be cancelled"
|
||||
-
|
||||
Now again set cancelled order to draft.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
self.action_cancel_draft(cr, uid, [ref("purchase_order_5")])
|
||||
-
|
||||
Now I again to cancel draft order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
self.action_cancel(cr, uid, [ref("purchase_order_5")])
|
||||
self.button_cancel(cr, uid, [ref("purchase_order_5")])
|
||||
-
|
||||
I check that order is cancelled.
|
||||
-
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
-
|
||||
Purchase user can create an invoice for order on receptions therfore test with that user which have Purchase user rights.
|
||||
-
|
||||
!context
|
||||
uid: 'res_users_purchase_user'
|
||||
-
|
||||
I confirm another order where invoice control is 'Bases on incoming shipments'.
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_2}
|
||||
-
|
||||
I check that the invoice of order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_2"))
|
||||
assert len(purchase_order.invoice_ids) == 0, "Invoice should not be generated on order confirmation."
|
||||
-
|
||||
Now I create an invoice for order on reception.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
pick_ids = [self.browse(cr, uid, ref("purchase_order_2")).id]
|
||||
self.action_invoice_create(cr, uid, pick_ids)
|
||||
-
|
||||
I check that the invoice of order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_2"))
|
||||
assert len(purchase_order.invoice_ids) == 1, "Invoice should be generated."
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
-
|
||||
Purchase User confirm the order and create invoice based on purchase order line.
|
||||
-
|
||||
!context
|
||||
uid: 'res_users_purchase_user'
|
||||
-
|
||||
I confirm purchase order which has invoicing control method "Based on Purchase Order Lines".
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_6}
|
||||
-
|
||||
In order to test create invoice for purchase order line.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_line_obj = self.pool.get('purchase.order.line_invoice')
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_6"))
|
||||
context.update({'active_model': 'purchase.order', 'active_ids': [ref("purchase_order_6")]})
|
||||
for purchase_line in purchase_order.order_line:
|
||||
invoice_line_obj.makeInvoices(cr, uid, purchase_line.id, context=context)
|
||||
-
|
||||
I check the invoice of order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_6"))
|
||||
for purchase_line in purchase_order.order_line:
|
||||
assert len(purchase_order.invoice_ids) == 1, "Invoice should be generated."
|
||||
@@ -1,44 +0,0 @@
|
||||
-
|
||||
Give access rights of Purchase user to merge two RFQ.
|
||||
-
|
||||
!context
|
||||
uid: 'res_users_purchase_user'
|
||||
-
|
||||
In order to merge RFQ, I merge two RFQ which has same supplier and check new merged order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
context.update({"mail_create_nolog" : True })
|
||||
order3 = self.browse(cr, uid, ref('purchase_order_4'))
|
||||
order7 = self.browse(cr, uid, ref('purchase_order_7'))
|
||||
total_qty = sum([x.product_qty for x in order3.order_line] + [x.product_qty for x in order7.order_line])
|
||||
new_id = self.do_merge(cr, uid, [ref('purchase_order_4'), ref('purchase_order_7')], context=context)
|
||||
|
||||
assert order3.state == 'cancel', "Merged order should be canceled"
|
||||
assert order7.state == 'cancel', "Merged order should be canceled"
|
||||
|
||||
def merged_data(lines):
|
||||
product_id =[]
|
||||
product_uom = []
|
||||
res = {}
|
||||
for line in lines:
|
||||
product_id.append(line.product_id.id)
|
||||
product_uom.append(line.product_uom.id)
|
||||
res.update({'product_ids': product_id,'product_uom':product_uom})
|
||||
return res
|
||||
|
||||
for order in self.browse(cr, uid, new_id.keys()):
|
||||
assert order.state == 'draft',"New created order state should be in draft"
|
||||
assert order.partner_id == order3.partner_id ,"partner is not correspond"
|
||||
assert order.location_id == order3.location_id ,"Location is not correspond"
|
||||
|
||||
total_new_qty = sum(x.product_qty for x in order.order_line)
|
||||
assert total_new_qty == total_qty,"product quantities are not correspond"
|
||||
|
||||
date_order = min(order3.date_order, order7.date_order)
|
||||
assert order.date_order == date_order, "Date of order is not correspond"
|
||||
|
||||
n_product_data = merged_data(order.order_line)
|
||||
o_product_data= merged_data(order3.order_line)
|
||||
o_pro_data = merged_data(order7.order_line)
|
||||
assert n_product_data == o_product_data or o_pro_data,"product data are not correspond"
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
-
|
||||
In order to test the purchase order flow I compute the total of the listed products
|
||||
-
|
||||
I check the total untaxed amount of the RFQ is correctly computed
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
from openerp.tools import float_compare
|
||||
po = self.browse(cr, uid, ref('purchase_order_1'))
|
||||
assert float_compare(sum([l.price_subtotal for l in po.order_line]), po.amount_untaxed, precision_digits=2) == 0, "The amount of RFQ is not correctly computed"
|
||||
-
|
||||
I confirm the RFQ.
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_1}
|
||||
-
|
||||
I check the "Approved" status after confirmed RFQ.
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_1}:
|
||||
- state == 'approved'
|
||||
-
|
||||
I check that the invoice details which is generated after confirmed RFQ.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
from openerp.tools import float_compare
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_1"))
|
||||
assert len(purchase_order.invoice_ids) >= 1, "Invoice is not generated more or less than one"
|
||||
for invoice in purchase_order.invoice_ids:
|
||||
assert invoice.state == "draft", "Invoice state should be draft"
|
||||
assert invoice.partner_id.id == purchase_order.partner_id.id, "Vendor is not correspond with purchase order"
|
||||
assert invoice.reference == purchase_order.partner_ref or purchase_order.name,"Invoice reference is not correspond with purchase order"
|
||||
assert invoice.type == 'in_invoice',"Invoice type is not correspond with purchase order"
|
||||
assert invoice.origin == purchase_order.name,"Invoice origin is not correspond with purchase order"
|
||||
assert invoice.company_id.id == purchase_order.company_id.id ,"Invoice company is not correspond with purchase order"
|
||||
assert float_compare(invoice.amount_untaxed, purchase_order.amount_untaxed, precision_digits=2) == 0, "Invoice untaxed amount is not correspond with purchase order"
|
||||
assert float_compare(invoice.amount_tax, purchase_order.amount_tax, precision_digits=2) == 0, "Invoice tax amount is not correspond with purchase order"
|
||||
assert float_compare(invoice.amount_total, purchase_order.amount_total, precision_digits=2) == 0, "Invoice total amount is not correspond with purchase order"
|
||||
assert len(invoice.invoice_line_ids) == len(purchase_order.order_line), "Lines of Invoice and Purchase Order are not correspond"
|
||||
-
|
||||
I check that Reception details after confirmed RFQ.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_1"))
|
||||
assert len(purchase_order.picking_ids) >= 1, "You should have only one reception order"
|
||||
for picking in purchase_order.picking_ids:
|
||||
assert picking.state == "assigned", "Reception state should be in assigned state"
|
||||
assert picking.partner_id.id == purchase_order.partner_id.id, "Delivery address of reception id is different from order"
|
||||
assert picking.company_id.id == purchase_order.company_id.id, "Company is not correspond with purchase order"
|
||||
-
|
||||
Reception is ready for process so now done the reception.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_1"), context=context).picking_ids[0]
|
||||
pick_ids.do_transfer()
|
||||
-
|
||||
I check that purchase order is shipped.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
assert self.browse(cr, uid, ref("purchase_order_1")).shipped == True,"Purchase order should be delivered"
|
||||
|
||||
-
|
||||
I Validate Invoice of Purchase Order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
for invoice in self.browse(cr, uid, ref('purchase_order_1'), context=context).invoice_ids:
|
||||
invoice.signal_workflow('invoice_open')
|
||||
-
|
||||
I check that purchase order is invoiced.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
assert self.browse(cr, uid, ref("purchase_order_1")).invoiced == True,"Purchase Order should be invoiced"
|
||||
|
||||
@@ -1,5 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_purchase_to_invoice
|
||||
from . import test_onchange_product_id
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
from openerp.tests.common import TransactionCase
|
||||
|
||||
class TestOnchangeProductId(TransactionCase):
|
||||
"""Test that when an included tax is mapped by a fiscal position, the included tax must be
|
||||
subtracted to the price of the product.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestOnchangeProductId, self).setUp()
|
||||
self.fiscal_position_model = self.registry('account.fiscal.position')
|
||||
self.fiscal_position_tax_model = self.registry('account.fiscal.position.tax')
|
||||
self.tax_model = self.registry('account.tax')
|
||||
self.res_partner_model = self.registry('res.partner')
|
||||
self.product_model = self.registry('product.product')
|
||||
self.product_uom_model = self.registry('product.uom')
|
||||
self.po_line_model = self.registry('purchase.order.line')
|
||||
|
||||
def test_onchange_product_id(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
uom_id = self.product_uom_model.search(cr, uid, [('name', '=', 'Unit(s)')])[0]
|
||||
partner_id = self.res_partner_model.create(cr, uid, dict(name="George"))
|
||||
tax_include_id = self.tax_model.create(cr, uid, dict(name="Include tax",
|
||||
amount_type='percent',
|
||||
amount='21.0',
|
||||
type_tax_use='purchase',
|
||||
price_include=True))
|
||||
tax_exclude_id = self.tax_model.create(cr, uid, dict(name="Exclude tax",
|
||||
amount_type='percent',
|
||||
type_tax_use='purchase',
|
||||
amount='0.00'))
|
||||
product_id = self.product_model.create(cr, uid, dict(name="Voiture",
|
||||
list_price='121',
|
||||
supplier_taxes_id=[(6, 0, [tax_include_id])]))
|
||||
fp_id = self.fiscal_position_model.create(cr, uid, dict(name="fiscal position",
|
||||
sequence=1))
|
||||
self.fiscal_position_tax_model.create(cr, uid, dict(position_id=fp_id,
|
||||
tax_src_id=tax_include_id,
|
||||
tax_dest_id=tax_exclude_id))
|
||||
res = self.po_line_model.onchange_product_id(cr, uid, [], product_id, 1.0, uom_id, partner_id,
|
||||
fiscal_position_id=fp_id)
|
||||
|
||||
self.assertEquals(0, res['value']['price_unit'], "The default price for products having no seller set is 0")
|
||||
#TODO: add back a test on this
|
||||
#self.assertEquals(100, res['value']['price_unit'], "The included tax must be subtracted to the price")
|
||||
@@ -1,60 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.tests import common
|
||||
|
||||
|
||||
class TestPurchase(common.TransactionCase):
|
||||
|
||||
def test_purchase_to_invoice(self):
|
||||
""" Testing for invoice create,validate and pay with invoicing and payment user."""
|
||||
group_id = self.ref('account.group_account_invoice')
|
||||
product_id = self.ref('product.product_category_3')
|
||||
company_id = self.ref('base.main_company')
|
||||
location_id = self.ref('stock.stock_location_3')
|
||||
|
||||
# Useful accounts
|
||||
user_type_id = self.ref('account.data_account_type_expenses')
|
||||
account_exp_id = self.env['account.account'].create({'code': 'X2020', 'name': 'Purchase - Test Expense Account', 'user_type_id': user_type_id, 'reconcile': True})
|
||||
user_type_id = self.ref('account.data_account_type_payable')
|
||||
account_pay_id = self.env['account.account'].create({'code': 'X1012', 'name': 'Purchase - Test Payable Account', 'user_type_id': user_type_id, 'reconcile': True})
|
||||
|
||||
self.env['product.product'].browse(product_id).product_tmpl_id.write({'property_account_expense_id': account_exp_id})
|
||||
|
||||
# Create Purchase Journal
|
||||
self.env['account.journal'].create({'name': 'Purchase Journal - Test', 'code': 'PTPJ', 'type': 'purchase'})
|
||||
|
||||
# In order to test, I create new user and applied Invoicing & Payments group.
|
||||
user = self.env['res.users'].with_context({'no_reset_password': True}).create({
|
||||
'name': 'Test User',
|
||||
'login': 'test@test.com',
|
||||
'company_id': company_id,
|
||||
'groups_id': [(6, 0, [group_id])]})
|
||||
assert user, "User will not created."
|
||||
# I create partner for purchase order.
|
||||
partner = self.env['res.partner'].create({
|
||||
'name': 'Test Customer',
|
||||
'email': 'testcustomer@test.com',
|
||||
'property_account_payable_id': account_pay_id,
|
||||
})
|
||||
|
||||
# In order to test I create purchase order and confirmed it.
|
||||
order = self.env['purchase.order'].create({
|
||||
'partner_id': partner.id,
|
||||
'location_id': location_id, })
|
||||
self.env['purchase.order.line'].create({
|
||||
'order_id': order.id,
|
||||
'product_id': product_id,
|
||||
'product_qty': 100.0,
|
||||
'product_uom': 1,
|
||||
'price_unit': 89.0,
|
||||
'name': 'Service',
|
||||
'date_planned': '2014-05-31'})
|
||||
assert order, "purchase order will not created."
|
||||
context = {"active_model": 'purchase.order', "active_ids": [order.id], "active_id": order.id}
|
||||
order.with_context(context).wkf_confirm_order()
|
||||
# In order to test I create invoice.
|
||||
invoice = order.with_context(context).action_invoice_create()
|
||||
assert invoice, "No any invoice is created for this purchase order"
|
||||
# In order to test I validate invoice wihth Test User(invoicing and payment).
|
||||
res = self.env['account.invoice'].browse(invoice).with_context(context).invoice_validate()
|
||||
self.assertTrue(res, 'Invoice will not validated')
|
||||
@@ -43,10 +43,6 @@
|
||||
<strong>Order Date:</strong>
|
||||
<p t-field="o.date_order"/>
|
||||
</div>
|
||||
<div t-if="o.validator" class="col-xs-3">
|
||||
<strong>Validated By:</strong>
|
||||
<p t-field="o.validator"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-condensed">
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import purchase_order_group
|
||||
import purchase_line_invoice
|
||||
@@ -1,99 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class purchase_line_invoice(osv.osv_memory):
|
||||
|
||||
""" To create invoice for purchase order line"""
|
||||
|
||||
_name = 'purchase.order.line_invoice'
|
||||
_description = 'Purchase Order Line Make Invoice'
|
||||
|
||||
def _make_invoice_by_partner(self, cr, uid, partner, orders, lines_ids, context=None):
|
||||
"""
|
||||
create a new invoice for one vendor
|
||||
@param cr : Cursor
|
||||
@param uid : Id of current user
|
||||
@param partner : The object partner
|
||||
@param orders : The set of orders to add in the invoice
|
||||
@param lines : The list of line's id
|
||||
"""
|
||||
purchase_obj = self.pool.get('purchase.order')
|
||||
account_jrnl_obj = self.pool.get('account.journal')
|
||||
invoice_obj = self.pool.get('account.invoice')
|
||||
name = orders and orders[0].name or ''
|
||||
journal_id = account_jrnl_obj\
|
||||
.search(cr, uid, [('type', '=', 'purchase')], context=None)
|
||||
journal_id = journal_id and journal_id[0] or False
|
||||
a = partner.property_account_payable_id.id
|
||||
inv = {
|
||||
'name': name,
|
||||
'origin': name,
|
||||
'type': 'in_invoice',
|
||||
'journal_id': journal_id,
|
||||
'reference': partner.ref,
|
||||
'account_id': a,
|
||||
'partner_id': partner.id,
|
||||
'invoice_line_ids': [(6, 0, lines_ids)],
|
||||
'currency_id': orders[0].currency_id.id,
|
||||
'comment': " \n".join([order.notes for order in orders if order.notes]),
|
||||
'payment_term_id': orders[0].payment_term_id.id,
|
||||
'fiscal_position_id': partner.property_account_position_id.id
|
||||
}
|
||||
inv_id = invoice_obj.create(cr, uid, inv, context=context)
|
||||
purchase_obj.write(cr, uid, [order.id for order in orders], {'invoice_ids': [(4, inv_id)]}, context=context)
|
||||
return inv_id
|
||||
|
||||
def makeInvoices(self, cr, uid, ids, context=None):
|
||||
|
||||
"""
|
||||
To get Purchase Order line and create Invoice
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param context: A standard dictionary
|
||||
@return : retrun view of Invoice
|
||||
"""
|
||||
|
||||
if context is None:
|
||||
context={}
|
||||
|
||||
record_ids = context.get('active_ids',[])
|
||||
if record_ids:
|
||||
res = False
|
||||
invoices = {}
|
||||
purchase_obj = self.pool.get('purchase.order')
|
||||
purchase_line_obj = self.pool.get('purchase.order.line')
|
||||
invoice_line_obj = self.pool.get('account.invoice.line')
|
||||
|
||||
for line in purchase_line_obj.browse(cr, uid, record_ids, context=context):
|
||||
if (not line.invoiced) and (line.state not in ('draft', 'cancel')):
|
||||
if not line.partner_id.id in invoices:
|
||||
invoices[line.partner_id.id] = []
|
||||
acc_id = purchase_obj._choose_account_from_po_line(cr, uid, line, context=context)
|
||||
inv_line_data = purchase_obj._prepare_inv_line(cr, uid, acc_id, line, context=context)
|
||||
inv_line_data.update({'origin': line.order_id.name})
|
||||
inv_id = invoice_line_obj.create(cr, uid, inv_line_data, context=context)
|
||||
purchase_line_obj.write(cr, uid, [line.id], {'invoiced': True, 'invoice_lines': [(4, inv_id)]})
|
||||
invoices[line.partner_id.id].append((line,inv_id))
|
||||
|
||||
res = []
|
||||
for result in invoices.values():
|
||||
il = map(lambda x: x[1], result)
|
||||
orders = list(set(map(lambda x : x[0].order_id, result)))
|
||||
|
||||
res.append(self._make_invoice_by_partner(cr, uid, orders[0].partner_id, orders, il, context=context))
|
||||
|
||||
return {
|
||||
'domain': "[('id','in', ["+','.join(map(str,res))+"])]",
|
||||
'name': _('Vendor Bills'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'account.invoice',
|
||||
'view_id': False,
|
||||
'context': "{'type':'in_invoice', 'journal_type': 'purchase'}",
|
||||
'type': 'ir.actions.act_window'
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Make the invoice-->
|
||||
|
||||
<record id="view_purchase_line_invoice" model="ir.ui.view">
|
||||
<field name="name">Create invoices</field>
|
||||
<field name="model">purchase.order.line_invoice</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Select an Open Sales Order">
|
||||
<group>
|
||||
<label string="Do you want to generate the supplier bills?"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="makeInvoices" string="Confirm" type="object" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window name="Create invoices"
|
||||
res_model="purchase.order.line_invoice"
|
||||
src_model="purchase.order.line"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
id="action_view_purchase_line_invoice"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import time
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
class purchase_order_group(osv.osv_memory):
|
||||
_name = "purchase.order.group"
|
||||
_description = "Purchase Order Merge"
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form',
|
||||
context=None, toolbar=False, submenu=False):
|
||||
"""
|
||||
Changes the view dynamically
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param context: A standard dictionary
|
||||
@return: New arch of view.
|
||||
"""
|
||||
if context is None:
|
||||
context={}
|
||||
res = super(purchase_order_group, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
|
||||
if context.get('active_model','') == 'purchase.order' and len(context['active_ids']) < 2:
|
||||
raise UserError(_('Please select multiple order to merge in the list view.'))
|
||||
return res
|
||||
def merge_orders(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
To merge similar type of purchase orders.
|
||||
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param ids: the ID or list of IDs
|
||||
@param context: A standard dictionary
|
||||
|
||||
@return: purchase order view
|
||||
|
||||
"""
|
||||
order_obj = self.pool.get('purchase.order')
|
||||
proc_obj = self.pool.get('procurement.order')
|
||||
mod_obj =self.pool.get('ir.model.data')
|
||||
if context is None:
|
||||
context = {}
|
||||
result = mod_obj._get_id(cr, uid, 'purchase', 'view_purchase_order_filter')
|
||||
id = mod_obj.read(cr, uid, result, ['res_id'])
|
||||
|
||||
allorders = order_obj.do_merge(cr, uid, context.get('active_ids',[]), context)
|
||||
|
||||
return {
|
||||
'domain': "[('id','in', [" + ','.join(map(str, allorders.keys())) + "])]",
|
||||
'name': _('Purchase Orders'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'purchase.order',
|
||||
'view_id': False,
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': id['res_id']
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_purchase_order_group" model="ir.ui.view">
|
||||
<field name="name">Merger Purchase Orders</field>
|
||||
<field name="model">purchase.order.group</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Merge orders">
|
||||
<group>
|
||||
<separator string="Are you sure you want to merge these orders?"/>
|
||||
<label string="
|
||||
Please note that:
|
||||
Orders will only be merged if:
|
||||
* Purchase Orders are in draft
|
||||
* Purchase Orders belong to the same supplier
|
||||
* Purchase Orders are have same stock location, same pricelist, same currency
|
||||
Lines will only be merged if:
|
||||
* Order lines are exactly the same except for the product,quantity and unit
|
||||
" colspan="4"/>
|
||||
</group>
|
||||
|
||||
<footer>
|
||||
<button name="merge_orders" string="Merge orders" type="object" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window name="Merge Purchase orders"
|
||||
context="{'search_default_draft': 1, 'search_default_approved': False}"
|
||||
res_model="purchase.order.group"
|
||||
src_model="purchase.order"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
multi="True"
|
||||
key2="client_action_multi"
|
||||
id="action_view_purchase_order_group"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
Reference in New Issue
Block a user