2
0

module 'account_move_line_purchase_info'

This commit is contained in:
Jordi Ballester 2017-01-21 13:21:45 -07:00 committed by Andrea Stirpe
parent 0cd529dd16
commit 8a555efd5e
12 changed files with 440 additions and 0 deletions

View File

@ -0,0 +1,65 @@
.. image:: https://img.shields.io/badge/license-AGPLv3-blue.svg
:target: https://www.gnu.org/licenses/agpl.html
:alt: License: AGPL-3
===============================
Account Move Line Purchase Info
===============================
This module will add the purchase order line to journal items.
The ultimate goal is to establish the purchase order line as one of the key
fields to reconcile the Goods Received Not Invoiced accrual account.
Usage
=====
The purchase order line will be automatically copied to the journal items.
* When a supplier invoice is created referencing purchase orders, the
purchase order line will be copied to the corresponding journal item.
* When a stock move is validated and generates a journal entry, the purchase
order line is copied to the account move line.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/92/9.0
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/account-financial-tools/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* Jordi Ballester Alomar <jordi.ballester@eficent.com>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

View File

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# © 2017 Eficent Business and IT Consulting Services S.L. (www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import models

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# © 2017 Eficent Business and IT Consulting Services S.L. (www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Account Move Line Purchase Info",
"summary": "Introduces the purchase order line to the journal items",
"version": "9.0.1.0.0",
"author": "Eficent, "
"Odoo Community Association (OCA)",
"website": "http://www.github.com/OCA/account-financial-tools",
"category": "Generic",
"depends": ["account_accountant", "purchase"],
"license": "AGPL-3",
"data": [
"security/account_security.xml",
"views/account_move_view.xml",
],
'installable': True,
}

View File

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# © 2017 Eficent Business and IT Consulting Services S.L. (www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import account_move
from . import account_invoice
from . import stock

View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# © 2017 Eficent Business and IT Consulting Services S.L. (www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from openerp import api, models
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
@api.model
def invoice_line_move_line_get(self):
res = super(AccountInvoice, self).invoice_line_move_line_get()
invoice_line_model = self.env['account.invoice.line']
for move_line_dict in res:
if 'invl_id' in move_line_dict:
line = invoice_line_model.browse(move_line_dict['invl_id'])
move_line_dict['purchase_line_id'] = line.purchase_line_id.id
return res
@api.model
def line_get_convert(self, line, part):
res = super(AccountInvoice, self).line_get_convert(line, part)
if line.get('purchase_line_id', False):
res['purchase_line_id'] = line.get('purchase_line_id')
return res

View File

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# © 2017 Eficent Business and IT Consulting Services S.L. (www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from openerp import fields, models
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
purchase_line_id = fields.Many2one('purchase.order.line',
'Purchase Order Line',
ondelete='set null', select=True)

View File

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# © 2017 Eficent Business and IT Consulting Services S.L. (www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from openerp import api, models
class StockQuant(models.Model):
_inherit = "stock.quant"
@api.model
def _prepare_account_move_line(self, move, qty, cost,
credit_account_id, debit_account_id):
res = super(StockQuant, self)._prepare_account_move_line(
move, qty, cost, credit_account_id, debit_account_id)
for line in res:
line[2]['purchase_line_id'] = move.purchase_line_id.id
return res

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<record id="group_account_move_purchase_info" model="res.groups">
<field name="name">Purchase info in Journal Items</field>
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
</openerp>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# © 2017 Eficent - Jordi Ballester Alomar
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import test_account_move_line_purchase_info

View File

@ -0,0 +1,201 @@
# -*- coding: utf-8 -*-
# © 2017 Eficent Business and IT Consulting Services S.L. (www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from openerp.tests import common
from openerp import fields
class TestAccountMoveLinePurchaseInfo(common.TransactionCase):
def setUp(self):
super(TestAccountMoveLinePurchaseInfo, self).setUp()
self.purchase_model = self.env['purchase.order']
self.purchase_line_model = self.env['purchase.order.line']
self.invoice_model = self.env['account.invoice']
self.invoice_line_model = self.env['account.invoice.line']
self.product_model = self.env['product.product']
self.product_ctg_model = self.env['product.category']
self.acc_type_model = self.env['account.account.type']
self.account_model = self.env['account.account']
self.aml_model = self.env['account.move.line']
self.res_users_model = self.env['res.users']
self.partner1 = self.env.ref('base.res_partner_1')
self.location_stock = self.env.ref('stock.stock_location_stock')
self.company = self.env.ref('base.main_company')
self.group_purchase_user = self.env.ref('purchase.group_purchase_user')
self.group_account_invoice = self.env.ref(
'account.group_account_invoice')
self.group_account_manager = self.env.ref(
'account.group_account_manager')
# Create account for Goods Received Not Invoiced
acc_type = self._create_account_type('equity', 'other')
name = 'Goods Received Not Invoiced'
code = 'grni'
self.account_grni = self._create_account(acc_type, name, code,
self.company)
# Create account for Cost of Goods Sold
acc_type = self._create_account_type('expense', 'other')
name = 'Cost of Goods Sold'
code = 'cogs'
self.account_cogs = self._create_account(acc_type, name, code,
self.company)
# Create account for Inventory
acc_type = self._create_account_type('asset', 'other')
name = 'Inventory'
code = 'inventory'
self.account_inventory = self._create_account(acc_type, name, code,
self.company)
# Create Product
self.product = self._create_product()
# Create users
self.purchase_user = self._create_user('purchase_user',
[self.group_purchase_user,
self.group_account_invoice],
self.company)
self.account_invoice = self._create_user('account_invoice',
[self.group_account_invoice],
self.company)
self.account_manager = self._create_user('account_manager',
[self.group_account_manager],
self.company)
def _create_user(self, login, groups, company):
""" Create a user."""
group_ids = [group.id for group in groups]
user = \
self.res_users_model.with_context(
{'no_reset_password': True}).create({
'name': 'Test User',
'login': login,
'password': 'demo',
'email': 'test@yourcompany.com',
'company_id': company.id,
'company_ids': [(4, company.id)],
'groups_id': [(6, 0, group_ids)]
})
return user.id
def _create_account_type(self, name, type):
acc_type = self.acc_type_model.create({
'name': name,
'type': type
})
return acc_type
def _create_account(self, acc_type, name, code, company):
"""Create an account."""
account = self.account_model.create({
'name': name,
'code': code,
'user_type_id': acc_type.id,
'company_id': company.id
})
return account
def _create_product(self):
"""Create a Product."""
# group_ids = [group.id for group in groups]
product_ctg = self.product_ctg_model.create({
'name': 'test_product_ctg',
'property_stock_valuation_account_id': self.account_inventory.id
})
product = self.product_model.create({
'name': 'test_product',
'categ_id': product_ctg.id,
'type': 'product',
'standard_price': 1.0,
'list_price': 1.0,
'valuation': 'real_time',
'property_stock_account_input': self.account_grni.id,
'property_stock_account_output': self.account_cogs.id,
})
return product
def _create_purchase(self, line_products):
""" Create a purchase order.
``line_products`` is a list of tuple [(product, qty)]
"""
lines = []
for product, qty in line_products:
line_values = {
'name': product.name,
'product_id': product.id,
'product_qty': qty,
'product_uom': product.uom_id.id,
'price_unit': 500,
'date_planned': fields.datetime.now()
}
lines.append(
(0, 0, line_values)
)
return self.purchase_model.create({
'partner_id': self.partner1.id,
'order_line': lines
})
def _get_balance(self, domain):
"""
Call read_group method and return the balance of particular account.
"""
aml_rec = self.aml_model.read_group(domain,
['debit', 'credit', 'account_id'],
['account_id'])
if aml_rec:
return aml_rec[0].get('debit', 0) - aml_rec[0].get('credit', 0)
else:
return 0.0
def _check_account_balance(self, account_id, purchase_line=None,
expected_balance=0.0):
"""
Check the balance of the account
"""
domain = [('account_id', '=', account_id)]
if purchase_line:
domain.extend([('purchase_line_id', '=', purchase_line.id)])
balance = self._get_balance(domain)
if purchase_line:
self.assertEqual(balance, expected_balance,
'Balance is not %s for Purchase Line %s.'
% (str(expected_balance), purchase_line.name))
def test_purchase_invoice(self):
"""Test that the po line moves from the purchase order to the
account move line and to the invoice line.
"""
purchase = self._create_purchase([(self.product, 1)])
po_line = False
for line in purchase.order_line:
po_line = line
break
purchase.button_confirm()
picking = purchase.picking_ids[0]
picking.force_assign()
picking.pack_operation_product_ids.write({'qty_done': 1.0})
picking.do_new_transfer()
expected_balance = 1.0
self._check_account_balance(self.account_inventory.id,
purchase_line=po_line,
expected_balance=expected_balance)
invoice = self.invoice_model.create({
'partner_id': self.partner1.id,
'purchase_id': purchase.id,
'account_id': purchase.partner_id.property_account_payable_id.id,
})
invoice.purchase_order_change()
invoice.signal_workflow('invoice_open')
for aml in invoice.move_id.line_ids:
if aml.product_id == po_line.product_id and aml.invoice_id:
self.assertEqual(aml.purchase_line_id, po_line,
'Purchase Order line has not been copied '
'from the invoice to the account move line.')

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<record id="view_move_line_form" model="ir.ui.view">
<field name="name">account.move.line.form</field>
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_form"/>
<field name="arch" type="xml">
<field name="quantity" position="before">
<field name="purchase_line_id"
groups="account_move_line_purchase_info.group_account_move_purchase_info"/>
</field>
</field>
</record>
<record id="view_move_line_form2" model="ir.ui.view">
<field name="name">account.move.line.form2</field>
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_form2"/>
<field name="arch" type="xml">
<field name="quantity" position="before">
<field name="purchase_line_id"
groups="account_move_line_purchase_info.group_account_move_purchase_info"/>
</field>
</field>
</record>
<record id="view_move_line_tree" model="ir.ui.view">
<field name="name">account.move.line.tree</field>
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_tree"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="purchase_line_id"
groups="account_move_line_purchase_info.group_account_move_purchase_info"/>
</field>
</field>
</record>
<record id="view_account_move_line_filter" model="ir.ui.view">
<field name="name">Journal Items</field>
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_account_move_line_filter"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="purchase_line_id"
groups="account_move_line_purchase_info.group_account_move_purchase_info"/>
</field>
</field>
</record>
<record id="view_move_form" model="ir.ui.view">
<field name="name">account.move.form</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<xpath
expr="//field[@name='line_ids']/tree//field[@name='partner_id']" position="after">
<field name="purchase_line_id"
groups="account_move_line_purchase_info.group_account_move_purchase_info"/>
</xpath>
</field>
</record>
</openerp>