summaryrefslogtreecommitdiff
path: root/addons/purchase
diff options
context:
space:
mode:
Diffstat (limited to 'addons/purchase')
-rw-r--r--addons/purchase/__manifest__.py2
-rw-r--r--addons/purchase/models/account_invoice.py271
-rw-r--r--addons/purchase/models/purchase.py62
-rw-r--r--addons/purchase/models/res_partner.py2
-rw-r--r--addons/purchase/report/purchase_bill.py10
-rw-r--r--addons/purchase/security/ir.model.access.csv7
-rw-r--r--addons/purchase/tests/test_purchase_order_report.py4
-rw-r--r--addons/purchase/views/account_invoice_views.xml88
-rw-r--r--addons/purchase/views/account_move_views.xml32
-rw-r--r--addons/purchase/views/purchase_views.xml2
-rw-r--r--addons/purchase/views/res_partner_views.xml4
11 files changed, 186 insertions, 298 deletions
diff --git a/addons/purchase/__manifest__.py b/addons/purchase/__manifest__.py
index 1565066cc8e..cf3743bb15d 100644
--- a/addons/purchase/__manifest__.py
+++ b/addons/purchase/__manifest__.py
@@ -13,7 +13,7 @@
'data': [
'security/purchase_security.xml',
'security/ir.model.access.csv',
- 'views/account_invoice_views.xml',
+ 'views/account_move_views.xml',
'data/purchase_data.xml',
'report/purchase_reports.xml',
'views/purchase_views.xml',
diff --git a/addons/purchase/models/account_invoice.py b/addons/purchase/models/account_invoice.py
index 130c40a7d61..9e1f867a7ea 100644
--- a/addons/purchase/models/account_invoice.py
+++ b/addons/purchase/models/account_invoice.py
@@ -2,191 +2,112 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
-from odoo.tools.float_utils import float_compare
-
-
-class AccountInvoice(models.Model):
- _inherit = 'account.invoice'
-
- purchase_id = fields.Many2one(
- comodel_name='purchase.order',
- string='Add Purchase Order',
- readonly=True, states={'draft': [('readonly', False)]},
- help='Load the vendor bill based on selected purchase order. Several PO can be selected.'
- )
- vendor_bill_purchase_id = fields.Many2one(
- comodel_name='purchase.bill.union',
- string='Auto-Complete'
- )
-
- @api.onchange('vendor_bill_purchase_id')
- def _onchange_bill_purchase_order(self):
- if not self.vendor_bill_purchase_id:
- return {}
- self.purchase_id = self.vendor_bill_purchase_id.purchase_order_id
- self.vendor_bill_id = self.vendor_bill_purchase_id.vendor_bill_id
- self.vendor_bill_purchase_id = False
- return {}
-
- @api.onchange('state', 'partner_id', 'invoice_line_ids')
- def _onchange_allowed_purchase_ids(self):
- '''
- The purpose of the method is to define a domain for the available
- purchase orders.
+
+
+class AccountMove(models.Model):
+ _inherit = 'account.move'
+
+ purchase_vendor_bill_id = fields.Many2one('purchase.bill.union', store=False, readonly=True,
+ states={'draft': [('readonly', False)]},
+ string='Auto-complete',
+ help="Auto-complete from a past bill / purchase order.")
+ purchase_id = fields.Many2one('purchase.order', store=False, readonly=True,
+ states={'draft': [('readonly', False)]},
+ string='Purchase Order',
+ help="Auto-complete from a past purchase order.")
+
+ @api.onchange('purchase_vendor_bill_id', 'purchase_id')
+ def _onchange_purchase_auto_complete(self):
+ ''' Load from either an old purchase order, either an old vendor bill.
+
+ When setting a 'purchase.bill.union' in 'purchase_vendor_bill_id':
+ * If it's a vendor bill, 'invoice_vendor_bill_id' is set and the loading is done by '_onchange_invoice_vendor_bill'.
+ * If it's a purchase order, 'purchase_id' is set and this method will load lines.
+
+ /!\ All this not-stored fields must be empty at the end of this function.
'''
- result = {}
-
- # A PO can be selected only if at least one PO line is not already in the invoice
- purchase_line_ids = self.invoice_line_ids.mapped('purchase_line_id')
- purchase_ids = self.invoice_line_ids.mapped('purchase_id').filtered(lambda r: r.order_line <= purchase_line_ids)
-
- domain = [('invoice_status', 'in', ['to invoice', 'no'])]
- if self.partner_id:
- domain += [('partner_id', 'child_of', self.partner_id.id)]
- if purchase_ids:
- domain += [('id', 'not in', purchase_ids.ids)]
- result['domain'] = {'purchase_id': domain}
- return result
-
- def _prepare_invoice_line_from_po_line(self, 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:
- qty = 0.0
- taxes = line.taxes_id
- invoice_line_tax_ids = line.order_id.fiscal_position_id.map_tax(taxes, line.product_id, line.order_id.partner_id)
- invoice_line = self.env['account.invoice.line']
- date = self.date or self.date_invoice
- data = {
- 'purchase_line_id': line.id,
- 'name': line.order_id.name + ': ' + line.name,
- 'origin': line.order_id.origin,
- 'uom_id': line.product_uom.id,
- 'product_id': line.product_id.id,
- 'account_id': invoice_line.with_context({'journal_id': self.journal_id.id, 'type': 'in_invoice'})._default_account(),
- 'price_unit': line.order_id.currency_id._convert(
- line.price_unit, self.currency_id, line.company_id, date or fields.Date.today(), round=False),
- 'quantity': qty,
- 'discount': 0.0,
- 'account_analytic_id': line.account_analytic_id.id,
- 'analytic_tag_ids': line.analytic_tag_ids.ids,
- 'invoice_line_tax_ids': invoice_line_tax_ids.ids
- }
- account = invoice_line.get_invoice_line_account('in_invoice', line.product_id, line.order_id.fiscal_position_id, self.env.company)
- if account:
- data['account_id'] = account.id
- return data
-
- def _onchange_product_id(self):
- domain = super(AccountInvoice, self)._onchange_product_id()
- if self.purchase_id:
- # Use the purchase uom by default
- self.uom_id = self.product_id.uom_po_id
- return domain
-
- # Load all unsold PO lines
- @api.onchange('purchase_id')
- def purchase_order_change(self):
+ if self.purchase_vendor_bill_id.vendor_bill_id:
+ self.invoice_vendor_bill_id = self.purchase_vendor_bill_id.vendor_bill_id
+ self._onchange_invoice_vendor_bill()
+ elif self.purchase_vendor_bill_id.purchase_order_id:
+ self.purchase_id = self.purchase_vendor_bill_id.purchase_order_id
+ self.purchase_vendor_bill_id = False
+
if not self.purchase_id:
- return {}
- if not self.partner_id:
- self.partner_id = self.purchase_id.partner_id.id
-
- vendor_ref = self.purchase_id.partner_ref
- if vendor_ref and (not self.reference or (
- vendor_ref + ", " not in self.reference and not self.reference.endswith(vendor_ref))):
- self.reference = ", ".join([self.reference, vendor_ref]) if self.reference else vendor_ref
-
- if not self.invoice_line_ids:
- #as there's no invoice line yet, we keep the currency of the PO
- self.currency_id = self.purchase_id.currency_id
-
- new_lines = self.env['account.invoice.line']
- for line in self.purchase_id.order_line - self.invoice_line_ids.mapped('purchase_line_id'):
- data = self._prepare_invoice_line_from_po_line(line)
- new_line = new_lines.new(data)
+ return
+
+ # Copy partner.
+ self.partner_id = self.purchase_id.partner_id
+ self.fiscal_position_id = self.purchase_id.fiscal_position_id
+ self.invoice_payment_term_id = self.purchase_id.payment_term_id
+ self.currency_id = self.purchase_id.currency_id
+
+ # Copy purchase lines.
+ po_lines = self.purchase_id.order_line - self.line_ids.mapped('purchase_line_id')
+ new_lines = self.env['account.move.line']
+ for line in po_lines:
+ new_line = new_lines.new(line._prepare_account_move_line(self))
+ new_line.account_id = new_line._get_computed_account()
+ new_line._onchange_price_subtotal()
new_lines += new_line
+ new_lines._onchange_mark_recompute_taxes()
- self.invoice_line_ids += new_lines
- self.payment_term_id = self.purchase_id.payment_term_id
- self.env.context = dict(self.env.context, from_purchase_order_change=True)
- self.purchase_id = False
- return {}
-
- @api.onchange('currency_id')
- def _onchange_currency_id(self):
- if self.currency_id:
- for line in self.invoice_line_ids.filtered(lambda r: r.purchase_line_id):
- date = self.date or self.date_invoice or fields.Date.today()
- company = self.company_id
- line.price_unit = line.purchase_id.currency_id._convert(
- line.purchase_line_id.price_unit, self.currency_id, company, date, round=False)
-
- @api.onchange('invoice_line_ids')
- def _onchange_origin(self):
- purchase_ids = self.invoice_line_ids.mapped('purchase_id')
- if purchase_ids:
- self.origin = ', '.join(purchase_ids.mapped('name'))
-
- @api.onchange('partner_id', 'company_id')
- def _onchange_partner_id(self):
- payment_term_id = self.env.context.get('from_purchase_order_change') and self.payment_term_id or False
- res = super(AccountInvoice, self)._onchange_partner_id()
- if payment_term_id:
- self.payment_term_id = payment_term_id
- if not self.env.context.get('default_journal_id') and self.partner_id and\
- self.type in ['in_invoice', 'in_refund'] and\
- self.currency_id != self.partner_id.property_purchase_currency_id and\
- self.partner_id.property_purchase_currency_id.id:
- journal_domain = [
- ('type', '=', 'purchase'),
- ('company_id', '=', self.company_id.id),
- ('currency_id', '=', self.partner_id.property_purchase_currency_id.id),
- ]
- default_journal_id = self.env['account.journal'].search(journal_domain, limit=1)
- if default_journal_id:
- self.journal_id = default_journal_id
- if self.env.context.get('default_currency_id'):
- self.currency_id = self.env.context['default_currency_id']
- if self.partner_id.property_purchase_currency_id:
- self.currency_id = self.partner_id.property_purchase_currency_id
- return res
+ # Compute invoice_origin.
+ origins = set(self.line_ids.mapped('purchase_line_id.order_id.name'))
+ self.invoice_origin = ','.join(list(origins))
- @api.model
- def create(self, vals):
- invoice = super(AccountInvoice, self).create(vals)
- purchase = invoice.invoice_line_ids.mapped('purchase_line_id.order_id')
- if purchase and not invoice.refund_invoice_id:
- message = _("This vendor bill has been created from: %s") % (",".join(["<a href=# data-oe-model=purchase.order data-oe-id=" + str(order.id) + ">" + order.name + "</a>" for order in purchase]))
- invoice.message_post(body=message)
- return invoice
+ # Compute ref.
+ refs = set(self.line_ids.mapped('purchase_line_id.order_id.partner_ref'))
+ refs = [ref for ref in refs if ref]
+ self.ref = ','.join(refs)
+
+ # Compute _invoice_payment_ref.
+ if len(refs) == 1:
+ self._invoice_payment_ref = refs[0]
+
+ self.purchase_id = False
+ self._onchange_currency()
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ # OVERRIDE
+ moves = super(AccountMove, self).create(vals_list)
+ for move in moves:
+ if move.reversed_entry_id:
+ continue
+ purchase = move.line_ids.mapped('purchase_line_id.order_id')
+ if not purchase:
+ continue
+ refs = ["<a href=# data-oe-model=purchase.order data-oe-id=%s>%s</a>" % tuple(name_get) for name_get in purchase.name_get()]
+ message = _("This vendor bill has been created from: %s") % ','.join(refs)
+ move.message_post(body=message)
+ return moves
@api.multi
def write(self, vals):
- result = True
- for invoice in self:
- purchase_old = invoice.invoice_line_ids.mapped('purchase_line_id.order_id')
- result = result and super(AccountInvoice, invoice).write(vals)
- purchase_new = invoice.invoice_line_ids.mapped('purchase_line_id.order_id')
- #To get all po reference when updating invoice line or adding purchase order reference from vendor bill.
- purchase = (purchase_old | purchase_new) - (purchase_old & purchase_new)
- if purchase:
- message = _("This vendor bill has been modified from: %s") % (",".join(["<a href=# data-oe-model=purchase.order data-oe-id=" + str(order.id) + ">" + order.name + "</a>" for order in purchase]))
- invoice.message_post(body=message)
- return result
-
- def _get_onchange_create(self):
- res = super()._get_onchange_create()
- res['_onchange_partner_id'].append('currency_id')
+ # OVERRIDE
+ old_purchases = [move.mapped('line_ids.purchase_line_id.order_id') for move in self]
+ res = super(AccountMove, self).write(vals)
+ for i, move in enumerate(self):
+ new_purchases = move.mapped('line_ids.purchase_line_id.order_id')
+ if not new_purchases:
+ continue
+ diff_purchases = new_purchases - old_purchases[i]
+ if diff_purchases:
+ refs = ["<a href=# data-oe-model=purchase.order data-oe-id=%s>%s</a>" % tuple(name_get) for name_get in diff_purchases.name_get()]
+ message = _("This vendor bill has been modified from: %s") % ','.join(refs)
+ move.message_post(body=message)
return res
-class AccountInvoiceLine(models.Model):
+class AccountMoveLine(models.Model):
""" Override AccountInvoice_line to add the link to the purchase order line it is related to"""
- _inherit = 'account.invoice.line'
+ _inherit = 'account.move.line'
+
+ purchase_line_id = fields.Many2one('purchase.order.line', 'Purchase Order Line', ondelete='set null', index=True)
- purchase_line_id = fields.Many2one('purchase.order.line', 'Purchase Order Line', ondelete='set null', index=True, readonly=True)
- purchase_id = fields.Many2one('purchase.order', related='purchase_line_id.order_id', string='Purchase Order', store=False, readonly=True, related_sudo=False,
- help='Associated Purchase Order. Filled in automatically when a PO is chosen on the vendor bill.')
+ @api.multi
+ def _copy_data_extend_business_fields(self, values):
+ # OVERRIDE to copy the 'purchase_line_id' field as well.
+ super(AccountMoveLine, self)._copy_data_extend_business_fields(values)
+ values['purchase_line_id'] = self.purchase_line_id.id
diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py
index c6aee321bab..7169399e3f7 100644
--- a/addons/purchase/models/purchase.py
+++ b/addons/purchase/models/purchase.py
@@ -59,12 +59,10 @@ class PurchaseOrder(models.Model):
else:
order.invoice_status = 'no'
- @api.depends('order_line.invoice_lines.invoice_id')
+ @api.depends('order_line.invoice_lines.move_id')
def _compute_invoice(self):
for order in self:
- invoices = self.env['account.invoice']
- for line in order.order_line:
- invoices |= line.invoice_lines.mapped('invoice_id')
+ invoices = order.mapped('order_line.invoice_lines.move_id')
order.invoice_ids = invoices
order.invoice_count = len(invoices)
@@ -104,7 +102,7 @@ class PurchaseOrder(models.Model):
notes = fields.Text('Terms and Conditions')
invoice_count = fields.Integer(compute="_compute_invoice", string='Bill Count', copy=False, default=0, store=True)
- invoice_ids = fields.Many2many('account.invoice', compute="_compute_invoice", string='Bills', copy=False, store=True)
+ invoice_ids = fields.Many2many('account.move', compute="_compute_invoice", string='Bills', copy=False, store=True)
invoice_status = fields.Selection([
('no', 'Nothing to Bill'),
('to invoice', 'Waiting Bills'),
@@ -398,22 +396,19 @@ class PurchaseOrder(models.Model):
This function returns an action that display existing vendor bills of given purchase order ids.
When only one found, show the vendor bill immediately.
'''
- action = self.env.ref('account.action_vendor_bill_template')
+ action = self.env.ref('account.action_move_in_invoice_type')
result = action.read()[0]
create_bill = self.env.context.get('create_bill', False)
# override the context to get rid of the default filtering
result['context'] = {
- 'type': 'in_invoice',
+ 'default_type': 'in_invoice',
'default_purchase_id': self.id,
- 'default_currency_id': self.currency_id.id,
- 'default_company_id': self.company_id.id,
- 'company_id': self.company_id.id
}
# choose the view_mode accordingly
if len(self.invoice_ids) > 1 and not create_bill:
result['domain'] = "[('id', 'in', " + str(self.invoice_ids.ids) + ")]"
else:
- res = self.env.ref('account.invoice_supplier_form', False)
+ res = self.env.ref('account.view_move_form', False)
result['views'] = [(res and res.id or False, 'form')]
# Do not set an invoice_id if we want to create a new bill.
if not create_bill:
@@ -455,7 +450,7 @@ class PurchaseOrderLine(models.Model):
company_id = fields.Many2one('res.company', related='order_id.company_id', string='Company', store=True, readonly=True)
state = fields.Selection(related='order_id.state', store=True, readonly=False)
- invoice_lines = fields.One2many('account.invoice.line', 'purchase_line_id', string="Bill Lines", readonly=True, copy=False)
+ invoice_lines = fields.One2many('account.move.line', 'purchase_line_id', string="Bill Lines", readonly=True, copy=False)
# Replace by invoiced Qty
qty_invoiced = fields.Float(compute='_compute_qty_invoiced', string="Billed Qty", digits=dp.get_precision('Product Unit of Measure'), store=True)
@@ -510,16 +505,16 @@ class PurchaseOrderLine(models.Model):
taxes = line.product_id.supplier_taxes_id.filtered(lambda r: not line.company_id or r.company_id == line.company_id)
line.taxes_id = fpos.map_tax(taxes, line.product_id, line.order_id.partner_id) if fpos else taxes
- @api.depends('invoice_lines.invoice_id.state', 'invoice_lines.quantity')
+ @api.depends('invoice_lines.move_id.state', 'invoice_lines.quantity')
def _compute_qty_invoiced(self):
for line in self:
qty = 0.0
for inv_line in line.invoice_lines:
- if inv_line.invoice_id.state not in ['cancel']:
- if inv_line.invoice_id.type == 'in_invoice':
- qty += inv_line.uom_id._compute_quantity(inv_line.quantity, line.product_uom)
- elif inv_line.invoice_id.type == 'in_refund':
- qty -= inv_line.uom_id._compute_quantity(inv_line.quantity, line.product_uom)
+ if inv_line.move_id.state not in ['cancel']:
+ if inv_line.move_id.type == 'in_invoice':
+ qty += inv_line.product_uom_id._compute_quantity(inv_line.quantity, line.product_uom)
+ elif inv_line.move_id.type == 'in_refund':
+ qty -= inv_line.product_uom_id._compute_quantity(inv_line.quantity, line.product_uom)
line.qty_invoiced = qty
@api.multi
@@ -696,3 +691,34 @@ class PurchaseOrderLine(models.Model):
self.product_uom = seller_min_qty[0].product_uom
else:
self.product_qty = 1.0
+
+ @api.multi
+ def _prepare_account_move_line(self, move):
+ self.ensure_one()
+ if self.product_id.purchase_method == 'purchase':
+ qty = self.product_qty - self.qty_invoiced
+ else:
+ qty = self.qty_received - self.qty_invoiced
+ if float_compare(qty, 0.0, precision_rounding=self.product_uom.rounding) <= 0:
+ qty = 0.0
+
+ if self.currency_id == move.company_id.currency_id:
+ currency = False
+ else:
+ currency = move.currency_id
+
+ return {
+ 'name': '%s: %s' % (self.order_id.name, self.name),
+ 'move_id': move.id,
+ 'currency_id': currency and currency.id or False,
+ 'purchase_line_id': self.id,
+ 'date_maturity': move.invoice_date_due,
+ 'product_uom_id': self.product_uom.id,
+ 'product_id': self.product_id.id,
+ 'price_unit': self.price_unit,
+ 'quantity': qty,
+ 'partner_id': move.partner_id.id,
+ 'analytic_account_id': self.account_analytic_id.id,
+ 'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)],
+ 'tax_ids': [(6, 0, self.taxes_id.ids)],
+ }
diff --git a/addons/purchase/models/res_partner.py b/addons/purchase/models/res_partner.py
index f62f589e57c..3fbe6acd12c 100644
--- a/addons/purchase/models/res_partner.py
+++ b/addons/purchase/models/res_partner.py
@@ -32,7 +32,7 @@ class res_partner(models.Model):
all_partners = self.search([('id', 'child_of', self.ids)])
all_partners.read(['parent_id'])
- supplier_invoice_groups = self.env['account.invoice'].read_group(
+ supplier_invoice_groups = self.env['account.move'].read_group(
domain=[('partner_id', 'in', all_partners.ids),
('type', 'in', ('in_invoice', 'in_refund'))],
fields=['partner_id'], groupby=['partner_id']
diff --git a/addons/purchase/report/purchase_bill.py b/addons/purchase/report/purchase_bill.py
index 009ce1f6ac8..0a9609144b8 100644
--- a/addons/purchase/report/purchase_bill.py
+++ b/addons/purchase/report/purchase_bill.py
@@ -17,7 +17,7 @@ class PurchaseBillUnion(models.Model):
amount = fields.Float(string='Amount', readonly=True)
currency_id = fields.Many2one('res.currency', string='Currency', readonly=True)
company_id = fields.Many2one('res.company', 'Company', readonly=True)
- vendor_bill_id = fields.Many2one('account.invoice', string='Vendor Bill', readonly=True)
+ vendor_bill_id = fields.Many2one('account.move', string='Vendor Bill', readonly=True)
purchase_order_id = fields.Many2one('purchase.order', string='Purchase Order', readonly=True)
@api.model_cr
@@ -26,14 +26,14 @@ class PurchaseBillUnion(models.Model):
self.env.cr.execute("""
CREATE OR REPLACE VIEW purchase_bill_union AS (
SELECT
- id, number as name, reference, partner_id, date, amount_untaxed as amount, currency_id, company_id,
+ id, name, ref as reference, partner_id, date, amount_untaxed as amount, currency_id, company_id,
id as vendor_bill_id, NULL as purchase_order_id
- FROM account_invoice
+ FROM account_move
WHERE
- type='in_invoice' and COALESCE(number, '') != ''
+ type='in_invoice' and state = 'posted'
UNION
SELECT
- -id, name, partner_ref, partner_id, date_order::date as date, amount_untaxed as amount, currency_id, company_id,
+ -id, name, partner_ref as reference, partner_id, date_order::date as date, amount_untaxed as amount, currency_id, company_id,
NULL as vendor_bill_id, id as purchase_order_id
FROM purchase_order
WHERE
diff --git a/addons/purchase/security/ir.model.access.csv b/addons/purchase/security/ir.model.access.csv
index 7c8e0e11ad6..6784aa839e9 100644
--- a/addons/purchase/security/ir.model.access.csv
+++ b/addons/purchase/security/ir.model.access.csv
@@ -12,11 +12,8 @@ access_account_tax_purchase_user_manager,account.tax,account.model_account_tax,g
access_product_product_purchase_user,product.product.purchase.user,product.model_product_product,group_purchase_user,1,0,0,0
access_product_product_purchase_manager,product.product purchase_manager,product.model_product_product,purchase.group_purchase_manager,1,1,1,1
access_product_template_purchase_user,product.template purchase_user,product.model_product_template,group_purchase_user,1,0,0,0
-access_account_invoice_purchase,account_invoice purchase,account.model_account_invoice,group_purchase_user,1,1,1,1
-access_account_invoice_line_purchase,account_invoice.line purchase,account.model_account_invoice_line,group_purchase_user,1,1,1,1
-access_account_invoice_purchase_manager,account_invoice purchase manager,account.model_account_invoice,group_purchase_manager,1,0,0,0
-access_account_invoice_line_purchase_manager,account_invoice.line purchase manager,account.model_account_invoice_line,group_purchase_manager,1,0,0,0
-access_account_invoice_tax_purchase,account_invoice.tax purchase,account.model_account_invoice_tax,group_purchase_user,1,1,1,1
+access_account_move_purchase,account_move purchase,account.model_account_move,group_purchase_user,1,1,1,1
+access_account_move_purchase_manager,account_move purchase manager,account.model_account_move,group_purchase_manager,1,0,0,0
access_account_fiscal_position_purchase_user,account.fiscal.position purchase,account.model_account_fiscal_position,group_purchase_user,1,0,0,0
access_res_partner_purchase_user,res.partner purchase,base.model_res_partner,group_purchase_user,1,0,0,0
access_account_journal,account.journal,account.model_account_journal,group_purchase_user,1,0,0,0
diff --git a/addons/purchase/tests/test_purchase_order_report.py b/addons/purchase/tests/test_purchase_order_report.py
index 24750e71d60..b78a83d9829 100644
--- a/addons/purchase/tests/test_purchase_order_report.py
+++ b/addons/purchase/tests/test_purchase_order_report.py
@@ -56,11 +56,11 @@ class TestPurchaseOrderReport(common.TransactionCase):
})
po.button_confirm()
- f = Form(self.env['account.invoice'])
+ f = Form(self.env['account.move'])
f.partner_id = po.partner_id
f.purchase_id = po
invoice = f.save()
- invoice.action_invoice_open()
+ invoice.post()
res_product1 = self.PurchaseReport.search([
('order_id', '=', po.id), ('product_id', '=', self.product1.id)])
diff --git a/addons/purchase/views/account_invoice_views.xml b/addons/purchase/views/account_invoice_views.xml
deleted file mode 100644
index a8b1affcbde..00000000000
--- a/addons/purchase/views/account_invoice_views.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<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_mode">tree,kanban,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="o_view_nocontent_smiling_face">
- Create a vendor bill
- </p><p>
- Use this menu to control the invoices to be received from your
- vendors. 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_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="o_view_nocontent_smiling_face">
- 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="groups_id" eval="[(4,ref('purchase.group_purchase_user'))]"/>
- <field name="arch" type="xml">
- <field name="vendor_bill_id" position="after">
- <field name="vendor_bill_purchase_id" attrs="{'invisible': ['|', '|', ('state','not in',['draft']), ('state', '=', 'purchase'), ('type', '=', 'in_refund')]}"
- class="oe_edit_only" domain="[('partner_id','child_of',[partner_id])]"
- placeholder="Select a purchase order or an old bill"
- options="{'no_create': True, 'no_open': True}"/>
- <field name="purchase_id" class="oe_edit_only"
- invisible="1" context="{'show_total_amount': True}"/>
- </field>
- <field name="vendor_bill_id" position="attributes">
- <attribute name="attrs">{'invisible': ['|', ('type', '=', 'in_invoice'), ('state', 'not in', ['draft'])]}</attribute>
- </field>
- <xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='company_id']" position="after">
- <field name="purchase_line_id" invisible="1" readonly="0"/>
- <field name="purchase_id" invisible="1" readonly="0"/>
- </xpath>
- </field>
- </record>
-
- <record id="view_invoice_line_form_inherit_purchase" model="ir.ui.view">
- <field name="name">account.invoice.line.form.inherit.purchase</field>
- <field name="model">account.invoice.line</field>
- <field name="inherit_id" ref="account.view_invoice_line_form"/>
- <field name="arch" type="xml">
- <field name="account_id" position="before">
- <field name="purchase_id" invisible="context.get('type') in ('out_invoice', 'out_refund')"/>
- </field>
- </field>
- </record>
-
-</odoo>
diff --git a/addons/purchase/views/account_move_views.xml b/addons/purchase/views/account_move_views.xml
new file mode 100644
index 00000000000..f60fe6490b1
--- /dev/null
+++ b/addons/purchase/views/account_move_views.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <record id="view_move_form_inherit_purchase" model="ir.ui.view">
+ <field name="name">account.move.inherit.purchase</field>
+ <field name="model">account.move</field>
+ <field name="inherit_id" ref="account.view_move_form"/>
+ <field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
+ <field name="arch" type="xml">
+ <!-- Auto-complete could be done from either a bill either a purchase order -->
+ <field name="invoice_vendor_bill_id" position="after">
+ <field name="purchase_id" invisible="1"/>
+ <field name="purchase_vendor_bill_id"
+ attrs="{'invisible': ['|', '|', ('state','not in',['draft']), ('state', '=', 'purchase'), ('type', '!=', 'in_invoice')]}"
+ class="oe_edit_only"
+ domain="[('company_id', '=', company_id), ('partner_id','child_of', [partner_id])]"
+ placeholder="Select a purchase order or an old bill"
+ context="{'show_total_amount': True}"
+ options="{'no_create': True, 'no_open': True}"/>
+ </field>
+ <field name="invoice_vendor_bill_id" position="attributes">
+ <attribute name="invisible">1</attribute>
+ </field>
+ <!-- Add link to purchase_line_id to account.move.line -->
+ <xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='company_id']" position="after">
+ <field name="purchase_line_id" invisible="1"/>
+ </xpath>
+ <xpath expr="//field[@name='line_ids']/tree/field[@name='company_id']" position="after">
+ <field name="purchase_line_id" invisible="1"/>
+ </xpath>
+ </field>
+ </record>
+</odoo>
diff --git a/addons/purchase/views/purchase_views.xml b/addons/purchase/views/purchase_views.xml
index 6ff2769eb7e..d5b320c6d33 100644
--- a/addons/purchase/views/purchase_views.xml
+++ b/addons/purchase/views/purchase_views.xml
@@ -45,7 +45,7 @@
<!--Invoice control-->
<menuitem
id="menu_procurement_management_pending_invoice"
- action="action_invoice_pending"
+ action="account.action_move_in_invoice_type"
parent="menu_purchase_control"
sequence="13"/>
diff --git a/addons/purchase/views/res_partner_views.xml b/addons/purchase/views/res_partner_views.xml
index 8bd9514d40c..460b8e81219 100644
--- a/addons/purchase/views/res_partner_views.xml
+++ b/addons/purchase/views/res_partner_views.xml
@@ -48,10 +48,10 @@
<record id="act_res_partner_2_supplier_invoices" model="ir.actions.act_window">
<field name="name">Vendor Bills</field>
- <field name="res_model">account.invoice</field>
+ <field name="res_model">account.move</field>
<field name="view_mode">tree,form,graph</field>
<field name="domain">[('type','in',('in_invoice', 'in_refund'))]</field>
- <field name="context">{'search_default_partner_id': active_id, 'default_type': 'in_invoice', 'type': 'in_invoice', 'journal_type': 'purchase'}</field>
+ <field name="context">{'search_default_partner_id': active_id, 'default_type': 'in_invoice'}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Record a new vendor bill