[ADD]account_move_line_rma_order_line v10

This commit is contained in:
aheficent
2018-10-31 16:23:58 +01:00
committed by AlexPForgeFlow
parent 758a2a7d3f
commit 18a2199e2a
11 changed files with 493 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
.. 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 RMA Line
==========================
This module will add the RMA order line to journal items.
The ultimate goal is to establish the RMA order line as one of the key
fields to reconcile the Goods Received Not Invoiced accrual account.
Usage
=====
The RMA order line will be automatically copied to the journal items.
* When a supplier invoice is created referencing RMA orders, the
RMA order line will be copied to the corresponding journal item.
* When a stock move is validated and generates a journal entry, the RMA
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/Eficent/stock_rma/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>
* Aarón Henríquez Quintana <ahenriquez@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 Rma Order Line",
"summary": "Introduces the rma order line to the journal items",
"version": "10.0.1.0.0",
"author": "Eficent, "
"Odoo Community Association (OCA)",
"website": "http://www.github.com/OCA/account-financial-tools",
"category": "Generic",
"depends": ["account_accountant", "rma_account"],
"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_move

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 odoo 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['rma_line_id'] = line.rma_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('rma_line_id', False):
res['rma_line_id'] = line.get('rma_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 odoo import fields, models
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
rma_line_id = fields.Many2one('rma.order.line',
'Rma Order Line',
ondelete='set null', index=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 odoo import api, models
class StockMove(models.Model):
_inherit = "stock.move"
@api.model
def _prepare_account_move_line(self, qty, cost,
credit_account_id, debit_account_id):
res = super(StockMove, self)._prepare_account_move_line(
qty, cost, credit_account_id, debit_account_id)
for line in res:
line[2]['rma_line_id'] = self.rma_line_id.id
return res

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="group_account_move_rma_order_line" model="res.groups">
<field name="name">Rma Order Line 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>
</odoo>

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_rma_order_line

View File

@@ -0,0 +1,253 @@
# -*- 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 odoo.tests import common
class TestAccountMoveLineRmaOrderLine(common.SavepointCase):
@classmethod
def setUpClass(cls):
super(TestAccountMoveLineRmaOrderLine, cls).setUpClass()
cls.rma_model = cls.env['rma.order']
cls.rma_line_model = cls.env['rma.order.line']
cls.rma_add_stock_move = cls.env['rma_add_stock_move']
cls.rma_make_picking = cls.env['rma_make_picking.wizard']
cls.invoice_model = cls.env['account.invoice']
cls.stock_picking_model = cls.env['stock.picking']
cls.invoice_line_model = cls.env['account.invoice.line']
cls.product_model = cls.env['product.product']
cls.product_ctg_model = cls.env['product.category']
cls.acc_type_model = cls.env['account.account.type']
cls.account_model = cls.env['account.account']
cls.aml_model = cls.env['account.move.line']
cls.res_users_model = cls.env['res.users']
cls.partner1 = cls.env.ref('base.res_partner_1')
cls.location_stock = cls.env.ref('stock.stock_location_stock')
cls.company = cls.env.ref('base.main_company')
cls.group_rma_user = cls.env.ref('rma.group_rma_customer_user')
cls.group_account_invoice = cls.env.ref(
'account.group_account_invoice')
cls.group_account_manager = cls.env.ref(
'account.group_account_manager')
cls.stock_location = cls.env.ref('stock.stock_location_stock')
wh = cls.env.ref('stock.warehouse0')
cls.stock_rma_location = wh.lot_rma_id
cls.customer_location = cls.env.ref(
'stock.stock_location_customers')
cls.supplier_location = cls.env.ref(
'stock.stock_location_suppliers')
# Create account for Goods Received Not Invoiced
acc_type = cls._create_account_type('equity', 'other')
name = 'Goods Received Not Invoiced'
code = 'grni'
cls.account_grni = cls._create_account(
acc_type, name, code,cls.company)
# Create account for Cost of Goods Sold
acc_type = cls._create_account_type('expense', 'other')
name = 'Cost of Goods Sold'
code = 'cogs'
cls.account_cogs = cls._create_account(
acc_type, name, code, cls.company)
# Create account for Inventory
acc_type = cls._create_account_type('asset', 'other')
name = 'Inventory'
code = 'inventory'
cls.account_inventory = cls._create_account(
acc_type, name, code, cls.company)
# Create Product
cls.product = cls._create_product()
cls.product_uom_id = cls.env.ref('product.product_uom_unit')
# Create users
cls.rma_user = cls._create_user(
'rma_user', [cls.group_rma_user,
cls.group_account_invoice], cls.company)
cls.account_invoice = cls._create_user(
'account_invoice', [cls.group_account_invoice], cls.company)
cls.account_manager = cls._create_user(
'account_manager', [cls.group_account_manager], cls.company)
@classmethod
def _create_user(cls, login, groups, company):
""" Create a user."""
group_ids = [group.id for group in groups]
user = \
cls.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
@classmethod
def _create_account_type(cls, name, type):
acc_type = cls.acc_type_model.create({
'name': name,
'type': type
})
return acc_type
@classmethod
def _create_account(cls, acc_type, name, code, company):
"""Create an account."""
account = cls.account_model.create({
'name': name,
'code': code,
'user_type_id': acc_type.id,
'company_id': company.id
})
return account
@classmethod
def _create_product(cls):
"""Create a Product."""
# group_ids = [group.id for group in groups]
product_ctg = cls.product_ctg_model.create({
'name': 'test_product_ctg',
'property_stock_valuation_account_id': cls.account_inventory.id,
'property_valuation': 'real_time',
'property_stock_account_input_categ_id': cls.account_grni.id,
'property_stock_account_output_categ_id': cls.account_cogs.id,
})
product = cls.product_model.create({
'name': 'test_product',
'categ_id': product_ctg.id,
'type': 'product',
'standard_price': 1.0,
'list_price': 1.0,
})
return product
@classmethod
def _create_picking(cls, partner):
return cls.stock_picking_model.create({
'partner_id': partner.id,
'picking_type_id': cls.env.ref('stock.picking_type_in').id,
'location_id': cls.stock_location.id,
'location_dest_id': cls.supplier_location.id
})
@classmethod
def _prepare_move(cls, product, qty, src, dest, picking_in):
res = {
'partner_id': cls.partner1.id,
'product_id': product.id,
'name': product.partner_ref,
'state': 'confirmed',
'product_uom': cls.product_uom_id.id or product.uom_id.id,
'product_uom_qty': qty,
'origin': 'Test RMA',
'location_id': src.id,
'location_dest_id': dest.id,
'picking_id': picking_in.id
}
return res
@classmethod
def _create_rma(cls, products2move, partner):
picking_in = cls._create_picking(partner)
moves = []
for item in products2move:
move_values = cls._prepare_move(
item[0], item[1], cls.stock_location,
cls.customer_location, picking_in)
moves.append(cls.env['stock.move'].create(move_values))
rma_id = cls.rma_model.create(
{
'reference': '0001',
'type': 'customer',
'partner_id': partner.id,
'company_id': cls.env.ref('base.main_company').id
})
for move in moves:
wizard = cls.rma_add_stock_move.with_context(
{'stock_move_id': move.id, 'customer': True,
'active_ids': rma_id.id,
'active_model': 'rma.order',
}
).create({})
data = wizard._prepare_rma_line_from_stock_move(move)
wizard.add_lines()
for operation in move.product_id.rma_customer_operation_id:
operation.in_route_id = False
move.product_id.categ_id.rma_customer_operation_id = False
move.product_id.rma_customer_operation_id = False
wizard._prepare_rma_line_from_stock_move(move)
cls.line = cls.rma_line_model.create(data)
return rma_id
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, rma_line=None,
expected_balance=0.0):
"""
Check the balance of the account
"""
domain = [('account_id', '=', account_id)]
if rma_line:
domain.extend([('rma_line_id', '=', rma_line.id)])
balance = self._get_balance(domain)
if rma_line:
self.assertEqual(balance, expected_balance,
'Balance is not %s for rma Line %s.'
% (str(expected_balance), rma_line.name))
def test_rma_invoice(self):
"""Test that the rma line moves from the rma order to the
account move line and to the invoice line.
"""
products2move = [(self.product, 1), ]
rma = self._create_rma(products2move, self.partner1)
rma_line = rma.rma_line_ids[0]
rma_line.action_rma_approve()
wizard = self.rma_make_picking.with_context({
'active_id': 1,
'active_ids': rma.rma_line_ids.ids,
'active_model': 'rma.order.line',
'picking_type': 'incoming',
}).create({})
procurements = wizard._create_picking()
group_ids = set([proc.group_id.id for proc in procurements if
proc.group_id])
domain = [('group_id', 'in', list(group_ids))]
picking = self.stock_picking_model.search(domain)
picking.action_assign()
picking.do_transfer()
expected_balance = 1.0
self._check_account_balance(self.account_inventory.id,
rma_line=rma_line,
expected_balance=expected_balance)
invoice = self.invoice_model.create({
'partner_id': self.partner1.id,
'rma_id': rma.id,
'account_id': rma.partner_id.property_account_payable_id.id,
})
invoice.signal_workflow('invoice_open')
for aml in invoice.move_id.line_ids:
if aml.product_id == rma_line.product_id and aml.invoice_id:
self.assertEqual(aml.rma_line_id, rma_line,
'Rma 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"?>
<odoo>
<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="rma_line_id"
groups="account_move_line_rma_order_line.group_account_move_rma_order_line"/>
</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="rma_line_id"
groups="account_move_line_rma_order_line.group_account_move_rma_order_line"/>
</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="rma_line_id"
groups="account_move_line_rma_order_line.group_account_move_rma_order_line"/>
</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="rma_line_id"
groups="account_move_line_rma_order_line.group_account_move_rma_order_line"/>
</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="rma_line_id"
groups="account_move_line_rma_order_line.group_account_move_rma_order_line"/>
</xpath>
</field>
</record>
</odoo>