mirror of
https://github.com/ForgeFlow/stock-rma.git
synced 2025-01-21 12:57:49 +02:00
Merge pull request #35 from ForgeFlow/10.0-imp-rma
[10.0]RMA improvement
This commit is contained in:
@@ -9,6 +9,7 @@ python:
|
||||
- "2.7"
|
||||
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
apt:
|
||||
packages:
|
||||
- expect-dev # provides unbuffer utility
|
||||
|
||||
66
account_move_line_rma_order_line/README.rst
Normal file
66
account_move_line_rma_order_line/README.rst
Normal 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.
|
||||
5
account_move_line_rma_order_line/__init__.py
Normal file
5
account_move_line_rma_order_line/__init__.py
Normal 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
|
||||
20
account_move_line_rma_order_line/__manifest__.py
Normal file
20
account_move_line_rma_order_line/__manifest__.py
Normal 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,
|
||||
}
|
||||
7
account_move_line_rma_order_line/models/__init__.py
Normal file
7
account_move_line_rma_order_line/models/__init__.py
Normal 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
|
||||
29
account_move_line_rma_order_line/models/account_invoice.py
Normal file
29
account_move_line_rma_order_line/models/account_invoice.py
Normal 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
|
||||
14
account_move_line_rma_order_line/models/account_move.py
Normal file
14
account_move_line_rma_order_line/models/account_move.py
Normal 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)
|
||||
20
account_move_line_rma_order_line/models/stock_move.py
Normal file
20
account_move_line_rma_order_line/models/stock_move.py
Normal 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).
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
@api.multi
|
||||
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:
|
||||
if line[2]["account_id"] != self.product_id.categ_id.\
|
||||
property_stock_valuation_account_id.id:
|
||||
line[2]['rma_line_id'] = self.rma_line_id.id
|
||||
return res
|
||||
@@ -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>
|
||||
5
account_move_line_rma_order_line/tests/__init__.py
Normal file
5
account_move_line_rma_order_line/tests/__init__.py
Normal 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
|
||||
@@ -0,0 +1,254 @@
|
||||
# -*- 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, atype):
|
||||
acc_type = cls.acc_type_model.create({
|
||||
'name': name,
|
||||
'type': atype
|
||||
})
|
||||
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()
|
||||
|
||||
if move.product_id.rma_customer_operation_id:
|
||||
move.product_id.rma_customer_operation_id.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_cogs.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.')
|
||||
66
account_move_line_rma_order_line/views/account_move_view.xml
Normal file
66
account_move_line_rma_order_line/views/account_move_view.xml
Normal 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>
|
||||
@@ -1,5 +1,5 @@
|
||||
stock-logistics-workflow
|
||||
manufacture
|
||||
operating-unit
|
||||
account-analytic
|
||||
pidgeon https://github.com/acsone/account-analytic.git 10.0-purchase_analytic-cpi
|
||||
pmis https://github.com/eficent/pmis 10.0
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
'data/rma_sequence.xml',
|
||||
'data/stock_data.xml',
|
||||
'data/rma_operation.xml',
|
||||
'report/rma_report.xml',
|
||||
'report/rma_report_templates.xml',
|
||||
'views/rma_order_view.xml',
|
||||
'views/rma_operation_view.xml',
|
||||
'views/rma_order_line_view.xml',
|
||||
|
||||
@@ -95,7 +95,6 @@
|
||||
<record id="rule_rma_dropship_return" model="procurement.rule">
|
||||
<field name="name">Customer → Supplier</field>
|
||||
<field name="action">move</field>
|
||||
<field name="warehouse_id" ref="stock.warehouse0"/>
|
||||
<field name="location_id" ref="stock.stock_location_suppliers"/>
|
||||
<field name="location_src_id" ref="stock.stock_location_customers"/>
|
||||
<field name="procure_method">make_to_stock</field>
|
||||
@@ -107,7 +106,6 @@
|
||||
<record id="rule_rma_dropship" model="procurement.rule">
|
||||
<field name="name">Supplier → Customer</field>
|
||||
<field name="action">move</field>
|
||||
<field name="warehouse_id" ref="stock.warehouse0"/>
|
||||
<field name="location_id" ref="stock.stock_location_customers"/>
|
||||
<field name="location_src_id" ref="stock.stock_location_suppliers"/>
|
||||
<field name="procure_method">make_to_stock</field>
|
||||
|
||||
@@ -10,22 +10,23 @@ class ProcurementOrder(models.Model):
|
||||
|
||||
rma_line_id = fields.Many2one(
|
||||
comodel_name='rma.order.line', string='RMA line',
|
||||
ondelete="set null",
|
||||
ondelete="set null", copy=False
|
||||
)
|
||||
|
||||
@api.model
|
||||
@api.multi
|
||||
def _get_stock_move_values(self):
|
||||
res = super(ProcurementOrder, self)._get_stock_move_values()
|
||||
if self.rma_line_id:
|
||||
line = self.rma_line_id
|
||||
res['rma_line_id'] = line.id
|
||||
# Propagate partner_dest_id for proper drop-shipment reports.
|
||||
if procurement.partner_dest_id:
|
||||
res['partner_id'] = procurement.partner_dest_id.id
|
||||
dest_loc = self.env["stock.location"].browse([
|
||||
res["location_dest_id"]])[0]
|
||||
if dest_loc.usage == "internal":
|
||||
res["price_unit"] = line.price_unit
|
||||
for procurement in self:
|
||||
if self.rma_line_id:
|
||||
line = self.rma_line_id
|
||||
res['rma_line_id'] = line.id
|
||||
# Propagate partner_dest_id for proper drop-shipment reports.
|
||||
if procurement.partner_dest_id:
|
||||
res['partner_id'] = procurement.partner_dest_id.id
|
||||
dest_loc = self.env["stock.location"].browse([
|
||||
res["location_dest_id"]])[0]
|
||||
if dest_loc.usage == "internal":
|
||||
res["price_unit"] = line.price_unit
|
||||
return res
|
||||
|
||||
|
||||
@@ -34,9 +35,9 @@ class ProcurementGroup(models.Model):
|
||||
|
||||
rma_id = fields.Many2one(
|
||||
comodel_name='rma.order', string='RMA',
|
||||
ondelete="set null",
|
||||
ondelete="set null", copy=False
|
||||
)
|
||||
rma_line_id = fields.Many2one(
|
||||
comodel_name='rma.order.line', string='RMA line',
|
||||
ondelete="set null",
|
||||
ondelete="set null", copy=False,
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, fields, models
|
||||
@@ -24,6 +24,14 @@ class RmaOperation(models.Model):
|
||||
def _default_supplier_location_id(self):
|
||||
return self.env.ref('stock.stock_location_suppliers') or False
|
||||
|
||||
@api.model
|
||||
def _default_routes(self):
|
||||
op_type = self.env.context.get('default_type')
|
||||
if op_type == 'customer':
|
||||
return self.env.ref('rma.route_rma_customer')
|
||||
elif op_type == 'supplier':
|
||||
return self.env.ref('rma.route_rma_supplier')
|
||||
|
||||
name = fields.Char('Description', required=True)
|
||||
code = fields.Char('Code', required=True)
|
||||
active = fields.Boolean(string='Active', default=True)
|
||||
@@ -36,15 +44,21 @@ class RmaOperation(models.Model):
|
||||
('received', 'Based on Received Quantities')],
|
||||
string="Delivery Policy", default='no')
|
||||
in_route_id = fields.Many2one(
|
||||
'stock.location.route', string='Inbound Route',
|
||||
domain=[('rma_selectable', '=', True)])
|
||||
comodel_name='stock.location.route', string='Inbound Route',
|
||||
domain=[('rma_selectable', '=', True)],
|
||||
default=_default_routes,
|
||||
)
|
||||
out_route_id = fields.Many2one(
|
||||
'stock.location.route', string='Outbound Route',
|
||||
domain=[('rma_selectable', '=', True)])
|
||||
comodel_name='stock.location.route', string='Outbound Route',
|
||||
domain=[('rma_selectable', '=', True)],
|
||||
default=_default_routes,
|
||||
)
|
||||
customer_to_supplier = fields.Boolean(
|
||||
'The customer will send to the supplier', default=False)
|
||||
string='The customer will send to the supplier',
|
||||
)
|
||||
supplier_to_customer = fields.Boolean(
|
||||
'The supplier will send to the customer', default=False)
|
||||
string='The supplier will send to the customer',
|
||||
)
|
||||
in_warehouse_id = fields.Many2one(
|
||||
comodel_name='stock.warehouse', string='Inbound Warehouse',
|
||||
default=_default_warehouse_id)
|
||||
@@ -56,5 +70,7 @@ class RmaOperation(models.Model):
|
||||
type = fields.Selection([
|
||||
('customer', 'Customer'), ('supplier', 'Supplier')],
|
||||
string="Used in RMA of this type", required=True)
|
||||
rma_line_ids = fields.One2many('rma.order.line', 'operation_id',
|
||||
'RMA lines')
|
||||
rma_line_ids = fields.One2many(
|
||||
comodel_name='rma.order.line', inverse_name='operation_id',
|
||||
string='RMA lines',
|
||||
)
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo import api, fields, models
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@@ -20,18 +19,14 @@ class RmaOrder(models.Model):
|
||||
@api.multi
|
||||
def _compute_in_shipment_count(self):
|
||||
for rec in self:
|
||||
rec.in_shipment_count = len(rec.rma_line_ids.mapped(
|
||||
'move_ids').filtered(
|
||||
lambda m: m.location_dest_id.usage == 'internal').mapped(
|
||||
'picking_id'))
|
||||
rec.in_shipment_count = sum(
|
||||
set(rec.rma_line_ids.mapped('in_shipment_count')))
|
||||
|
||||
@api.multi
|
||||
def _compute_out_shipment_count(self):
|
||||
for rec in self:
|
||||
rec.out_shipment_count = len(rec.rma_line_ids.mapped(
|
||||
'move_ids').filtered(
|
||||
lambda m: m.location_id.usage == 'internal').mapped(
|
||||
'picking_id'))
|
||||
rec.out_shipment_count = sum(
|
||||
set(rec.rma_line_ids.mapped('out_shipment_count')))
|
||||
|
||||
@api.multi
|
||||
def _compute_supplier_line_count(self):
|
||||
@@ -73,16 +68,6 @@ class RmaOrder(models.Model):
|
||||
required=True, default=lambda self:
|
||||
self.env.user.company_id)
|
||||
|
||||
@api.constrains("partner_id", "rma_line_ids")
|
||||
def _check_partner_id(self):
|
||||
if self.rma_line_ids and self.partner_id != self.mapped(
|
||||
"rma_line_ids.partner_id"):
|
||||
raise UserError(_(
|
||||
"Group partner and RMA's partner must be the same."))
|
||||
if len(self.mapped("rma_line_ids.partner_id")) > 1:
|
||||
raise UserError(_(
|
||||
"All grouped RMA's should have same partner."))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if (self.env.context.get('supplier') or
|
||||
|
||||
@@ -13,6 +13,7 @@ ops = {'=': operator.eq,
|
||||
class RmaOrderLine(models.Model):
|
||||
_name = "rma.order.line"
|
||||
_inherit = ['mail.thread']
|
||||
_order = 'create_date desc, id desc'
|
||||
|
||||
@api.model
|
||||
def _get_default_type(self):
|
||||
@@ -47,18 +48,27 @@ class RmaOrderLine(models.Model):
|
||||
@api.multi
|
||||
def _compute_in_shipment_count(self):
|
||||
for line in self:
|
||||
moves = line.mapped('move_ids').filtered(
|
||||
lambda m: m.location_dest_id.usage == 'internal')
|
||||
pickings = moves.mapped('picking_id')
|
||||
line.in_shipment_count = len(pickings)
|
||||
picking_ids = []
|
||||
for move in line.move_ids:
|
||||
if move.location_dest_id.usage == 'internal':
|
||||
picking_ids.append(move.picking_id.id)
|
||||
else:
|
||||
if line.customer_to_supplier:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
shipments = list(set(picking_ids))
|
||||
line.in_shipment_count = len(shipments)
|
||||
|
||||
@api.multi
|
||||
def _compute_out_shipment_count(self):
|
||||
picking_ids = []
|
||||
for line in self:
|
||||
moves = line.mapped('move_ids').filtered(
|
||||
lambda m: m.location_dest_id.usage != 'internal')
|
||||
pickings = moves.mapped('picking_id')
|
||||
line.out_shipment_count = len(pickings)
|
||||
for move in line.move_ids:
|
||||
if move.location_dest_id.usage in ('supplier', 'customer'):
|
||||
if (not line.customer_to_supplier or
|
||||
line.supplier_to_customer):
|
||||
picking_ids.append(move.picking_id.id)
|
||||
shipments = list(set(picking_ids))
|
||||
line.out_shipment_count = len(shipments)
|
||||
|
||||
@api.multi
|
||||
def _get_rma_move_qty(self, states, direction='in'):
|
||||
@@ -72,9 +82,8 @@ class RmaOrderLine(models.Model):
|
||||
for move in rec.move_ids.filtered(
|
||||
lambda m: m.state in states and op(m.location_id.usage,
|
||||
rec.type)):
|
||||
qty += product_obj._compute_qty_obj(
|
||||
move.product_uom, move.product_uom_qty,
|
||||
rec.uom_id)
|
||||
qty += product_obj._compute_quantity(
|
||||
move.product_uom_qty, rec.uom_id)
|
||||
return qty
|
||||
|
||||
@api.multi
|
||||
@@ -85,10 +94,10 @@ class RmaOrderLine(models.Model):
|
||||
rec.qty_to_receive = 0.0
|
||||
if rec.receipt_policy == 'ordered':
|
||||
rec.qty_to_receive = \
|
||||
rec.product_qty - rec.qty_incoming -rec.qty_received
|
||||
rec.product_qty - rec.qty_received
|
||||
elif rec.receipt_policy == 'delivered':
|
||||
rec.qty_to_receive = \
|
||||
rec.qty_delivered - rec.qty_incoming - rec.qty_received
|
||||
rec.qty_delivered - rec.qty_received
|
||||
|
||||
@api.multi
|
||||
@api.depends('move_ids', 'move_ids.state',
|
||||
@@ -106,8 +115,12 @@ class RmaOrderLine(models.Model):
|
||||
@api.depends('move_ids', 'move_ids.state', 'type')
|
||||
def _compute_qty_incoming(self):
|
||||
for rec in self:
|
||||
qty = rec._get_rma_move_qty(
|
||||
('draft', 'confirmed', 'assigned'), direction='in')
|
||||
if rec.supplier_to_customer:
|
||||
qty = rec._get_rma_move_qty(
|
||||
('draft', 'confirmed', 'assigned'), direction='out')
|
||||
else:
|
||||
qty = rec._get_rma_move_qty(
|
||||
('draft', 'confirmed', 'assigned'), direction='in')
|
||||
rec.qty_incoming = qty
|
||||
|
||||
@api.multi
|
||||
@@ -121,8 +134,12 @@ class RmaOrderLine(models.Model):
|
||||
@api.depends('move_ids', 'move_ids.state', 'type')
|
||||
def _compute_qty_outgoing(self):
|
||||
for rec in self:
|
||||
qty = rec._get_rma_move_qty(
|
||||
('draft', 'confirmed', 'assigned'), direction='out')
|
||||
if rec.supplier_to_customer:
|
||||
qty = rec._get_rma_move_qty(
|
||||
('draft', 'confirmed', 'assigned'), direction='in')
|
||||
else:
|
||||
qty = rec._get_rma_move_qty(
|
||||
('draft', 'confirmed', 'assigned'), direction='out')
|
||||
rec.qty_outgoing = qty
|
||||
|
||||
@api.multi
|
||||
@@ -158,6 +175,13 @@ class RmaOrderLine(models.Model):
|
||||
rec.procurement_count = len(rec.procurement_ids.filtered(
|
||||
lambda p: p.state == 'exception'))
|
||||
|
||||
@api.multi
|
||||
def _compute_rma_line_count(self):
|
||||
for rec in self.filtered(lambda r: r.type == 'customer'):
|
||||
rec.rma_line_count = len(rec.supplier_rma_line_ids)
|
||||
for rec in self.filtered(lambda r: r.type == 'supplier'):
|
||||
rec.rma_line_count = len(rec.customer_rma_id)
|
||||
|
||||
delivery_address_id = fields.Many2one(
|
||||
comodel_name='res.partner', string='Partner delivery address',
|
||||
default=_default_delivery_address,
|
||||
@@ -168,14 +192,17 @@ class RmaOrderLine(models.Model):
|
||||
rma_id = fields.Many2one(
|
||||
comodel_name='rma.order', string='RMA Group',
|
||||
track_visibility='onchange', readonly=True,
|
||||
copy=False
|
||||
)
|
||||
name = fields.Char(
|
||||
string='Reference', required=True, default='/',
|
||||
readonly=True, states={'draft': [('readonly', False)]},
|
||||
copy=False,
|
||||
help='Add here the supplier RMA #. Otherwise an internal code is'
|
||||
' assigned.',
|
||||
)
|
||||
description = fields.Text(string='Description')
|
||||
conditions = fields.Html(string='Terms and conditions')
|
||||
origin = fields.Char(
|
||||
string='Source Document',
|
||||
readonly=True, states={'draft': [('readonly', False)]},
|
||||
@@ -194,9 +221,11 @@ class RmaOrderLine(models.Model):
|
||||
)
|
||||
assigned_to = fields.Many2one(
|
||||
comodel_name='res.users', track_visibility='onchange',
|
||||
default=lambda self: self.env.uid,
|
||||
)
|
||||
requested_by = fields.Many2one(
|
||||
comodel_name='res.users', track_visibility='onchange',
|
||||
default=lambda self: self.env.uid,
|
||||
)
|
||||
partner_id = fields.Many2one(
|
||||
comodel_name='res.partner', required=True, store=True,
|
||||
@@ -227,7 +256,7 @@ class RmaOrderLine(models.Model):
|
||||
required=True,
|
||||
readonly=True, states={'draft': [('readonly', False)]},
|
||||
)
|
||||
price_unit = fields.Monetary(
|
||||
price_unit = fields.Float(
|
||||
string='Price Unit',
|
||||
readonly=True, states={'draft': [('readonly', False)]},
|
||||
)
|
||||
@@ -310,14 +339,25 @@ class RmaOrderLine(models.Model):
|
||||
default=_default_location_id,
|
||||
)
|
||||
customer_rma_id = fields.Many2one(
|
||||
'rma.order.line', string='Customer RMA line', ondelete='cascade')
|
||||
'rma.order.line', string='Customer RMA line', ondelete='cascade',
|
||||
copy=False)
|
||||
supplier_rma_line_ids = fields.One2many(
|
||||
'rma.order.line', 'customer_rma_id')
|
||||
rma_line_count = fields.Integer(
|
||||
compute='_compute_rma_line_count',
|
||||
string='# of RMA lines associated',
|
||||
)
|
||||
supplier_address_id = fields.Many2one(
|
||||
'res.partner', readonly=True,
|
||||
comodel_name='res.partner', readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
string='Supplier Address',
|
||||
help="This address of the supplier in case of Customer RMA operation "
|
||||
help="Address of the supplier in case of Customer RMA operation "
|
||||
"dropship.")
|
||||
customer_address_id = fields.Many2one(
|
||||
comodel_name='res.partner', readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
string='Customer Address',
|
||||
help="Address of the customer in case of Supplier RMA operation "
|
||||
"dropship.")
|
||||
qty_to_receive = fields.Float(
|
||||
string='Qty To Receive',
|
||||
@@ -361,6 +401,9 @@ class RmaOrderLine(models.Model):
|
||||
string="Under Warranty?",
|
||||
readonly=True, states={'draft': [('readonly', False)]},
|
||||
)
|
||||
create_date = fields.Datetime(string='Creation Date', readonly=True,
|
||||
index=True,
|
||||
help="Date on which RMA order is created.")
|
||||
|
||||
@api.multi
|
||||
def _prepare_rma_line_from_stock_move(self, sm, lot=False):
|
||||
@@ -377,13 +420,13 @@ class RmaOrderLine(models.Model):
|
||||
operation = self.env['rma.operation'].search(
|
||||
[('type', '=', self.type)], limit=1)
|
||||
if not operation:
|
||||
raise ValidationError("Please define an operation first.")
|
||||
raise ValidationError(_("Please define an operation first."))
|
||||
|
||||
if not operation.in_route_id or not operation.out_route_id:
|
||||
route = self.env['stock.location.route'].search(
|
||||
[('rma_selectable', '=', True)], limit=1)
|
||||
if not route:
|
||||
raise ValidationError("Please define an RMA route.")
|
||||
raise ValidationError(_("Please define an RMA route."))
|
||||
|
||||
if not operation.in_warehouse_id or not operation.out_warehouse_id:
|
||||
warehouse = self.env['stock.warehouse'].search(
|
||||
@@ -391,7 +434,8 @@ class RmaOrderLine(models.Model):
|
||||
('lot_rma_id', '!=', False)], limit=1)
|
||||
if not warehouse:
|
||||
raise ValidationError(
|
||||
"Please define a warehouse with a default RMA location.")
|
||||
_("Please define a warehouse with a default RMA "
|
||||
"location."))
|
||||
|
||||
data = {
|
||||
'product_id': sm.product_id.id,
|
||||
@@ -455,7 +499,6 @@ class RmaOrderLine(models.Model):
|
||||
self.write({'state': 'to_approve'})
|
||||
for rec in self:
|
||||
if rec.product_id.rma_approval_policy == 'one_step':
|
||||
rec.write({'assigned_to': self.env.uid})
|
||||
rec.action_rma_approve()
|
||||
return True
|
||||
|
||||
@@ -493,15 +536,18 @@ class RmaOrderLine(models.Model):
|
||||
result = {}
|
||||
if not self.product_id:
|
||||
return result
|
||||
self.product_qty = 1
|
||||
self.uom_id = self.product_id.uom_id.id
|
||||
self.price_unit = self.product_id.standard_price
|
||||
if not self.type:
|
||||
self.type = self._get_default_type()
|
||||
if self.type == 'customer':
|
||||
self.operation_id = self.product_id.rma_customer_operation_id or \
|
||||
self.product_id.categ_id.rma_customer_operation_id
|
||||
else:
|
||||
self.operation_id = self.product_id.rma_supplier_operation_id or \
|
||||
self.product_id.categ_id.rma_supplier_operation_id
|
||||
if self.lot_id.product_id != self.product_id:
|
||||
self.lot_id = False
|
||||
return result
|
||||
|
||||
@api.onchange('operation_id')
|
||||
@@ -528,16 +574,6 @@ class RmaOrderLine(models.Model):
|
||||
elif self.type == 'customer' and self.supplier_to_customer:
|
||||
self.delivery_policy = 'no'
|
||||
|
||||
@api.onchange('product_id')
|
||||
def _onchange_product_id(self):
|
||||
self.uom_id = self.product_id.uom_id
|
||||
if self.lot_id.product_id != self.product_id:
|
||||
self.lot_id = False
|
||||
if self.product_id:
|
||||
return {'domain': {
|
||||
'lot_id': [('product_id', '=', self.product_id.id)]}}
|
||||
return {'domain': {'lot_id': []}}
|
||||
|
||||
@api.onchange("lot_id")
|
||||
def _onchange_lot_id(self):
|
||||
product = self.lot_id.product_id
|
||||
@@ -545,6 +581,16 @@ class RmaOrderLine(models.Model):
|
||||
self.product_id = product
|
||||
self.uom_id = product.uom_id
|
||||
|
||||
@api.onchange("in_warehouse_id")
|
||||
def _onchange_in_warehouse_id(self):
|
||||
if self.in_warehouse_id and self._get_default_type() == 'customer':
|
||||
self.location_id = self.in_warehouse_id.lot_rma_id
|
||||
|
||||
@api.onchange("out_warehouse_id")
|
||||
def _onchange_out_warehouse_id(self):
|
||||
if self.out_warehouse_id and self._get_default_type() == 'supplier':
|
||||
self.location_id = self.out_warehouse_id.lot_rma_id
|
||||
|
||||
@api.multi
|
||||
def action_view_in_shipments(self):
|
||||
action = self.env.ref('stock.action_picking_tree_all')
|
||||
@@ -554,6 +600,10 @@ class RmaOrderLine(models.Model):
|
||||
for move in line.move_ids:
|
||||
if move.location_dest_id.usage == 'internal':
|
||||
picking_ids.append(move.picking_id.id)
|
||||
else:
|
||||
if line.customer_to_supplier:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
|
||||
shipments = list(set(picking_ids))
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) != 1:
|
||||
@@ -573,7 +623,8 @@ class RmaOrderLine(models.Model):
|
||||
for line in self:
|
||||
for move in line.move_ids:
|
||||
if move.location_dest_id.usage in ('supplier', 'customer'):
|
||||
picking_ids.append(move.picking_id.id)
|
||||
if not line.customer_to_supplier:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
shipments = list(set(picking_ids))
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) != 1:
|
||||
@@ -601,3 +652,33 @@ class RmaOrderLine(models.Model):
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = procurements[0]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_view_rma_lines(self):
|
||||
if self.type == 'customer':
|
||||
# from customer we link to supplier rma
|
||||
action = self.env.ref(
|
||||
'rma.action_rma_supplier_lines')
|
||||
rma_lines = self.supplier_rma_line_ids
|
||||
res = self.env.ref('rma.view_rma_line_supplier_form', False)
|
||||
else:
|
||||
# from supplier we link to customer rma
|
||||
action = self.env.ref(
|
||||
'rma.action_rma_customer_lines')
|
||||
rma_lines = self.customer_rma_id
|
||||
res = self.env.ref('rma.view_rma_line_form', False)
|
||||
result = action.read()[0]
|
||||
# choose the view_mode accordingly
|
||||
if rma_lines and len(rma_lines) != 1:
|
||||
result['domain'] = "[('id', 'in', " + \
|
||||
str(rma_lines.ids) + ")]"
|
||||
elif len(rma_lines) == 1:
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = rma_lines.id
|
||||
return result
|
||||
|
||||
@api.constrains("partner_id", "rma_id")
|
||||
def _check_partner_id(self):
|
||||
if self.rma_id and self.partner_id != self.rma_id.partner_id:
|
||||
raise ValidationError(_(
|
||||
"Group partner and RMA's partner must be the same."))
|
||||
|
||||
@@ -26,7 +26,7 @@ class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
rma_line_id = fields.Many2one('rma.order.line', string='RMA line',
|
||||
ondelete='restrict')
|
||||
ondelete='restrict', copy=False)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@@ -37,9 +37,8 @@ class StockMove(models.Model):
|
||||
vals['rma_line_id'] = procurement.rma_line_id.id
|
||||
return super(StockMove, self).create(vals)
|
||||
|
||||
@api.model
|
||||
def _prepare_picking_assign(self, move):
|
||||
res = super(StockMove, self)._prepare_picking_assign(move)
|
||||
if move.rma_line_id:
|
||||
res['partner_id'] = move.rma_line_id.partner_id.id or False
|
||||
def _get_new_picking_values(self):
|
||||
res = super(StockMove, self)._get_new_picking_values()
|
||||
if self.rma_line_id:
|
||||
res['partner_id'] = self.rma_line_id.partner_id.id or False
|
||||
return res
|
||||
|
||||
@@ -58,8 +58,8 @@ class StockWarehouse(models.Model):
|
||||
def _rma_types_available(self):
|
||||
self.ensure_one()
|
||||
rma_types = self._get_rma_types()
|
||||
for type in rma_types:
|
||||
if not type:
|
||||
for rtype in rma_types:
|
||||
if not rtype:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -74,21 +74,22 @@ class StockWarehouse(models.Model):
|
||||
'name': 'RMA',
|
||||
'usage': 'internal',
|
||||
'location_id': wh.lot_stock_id.id,
|
||||
'company_id': wh.company_id.id,
|
||||
})
|
||||
# RMA types
|
||||
if not wh._rma_types_available():
|
||||
wh._create_rma_picking_types()
|
||||
else:
|
||||
for type in wh._get_rma_types():
|
||||
if type:
|
||||
type.active = True
|
||||
for rtype in wh._get_rma_types():
|
||||
if rtype:
|
||||
rtype.active = True
|
||||
# RMA rules:
|
||||
wh._create_or_update_rma_pull()
|
||||
else:
|
||||
for wh in self:
|
||||
for type in wh._get_rma_types():
|
||||
if type:
|
||||
type.active = False
|
||||
for rtype in wh._get_rma_types():
|
||||
if rtype:
|
||||
rtype.active = False
|
||||
# Unlink rules:
|
||||
self.mapped('rma_customer_in_pull_id').unlink()
|
||||
self.mapped('rma_customer_out_pull_id').unlink()
|
||||
|
||||
13
rma/report/rma_report.xml
Normal file
13
rma/report/rma_report.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<report
|
||||
id="rma_order_line_report"
|
||||
string="RMA"
|
||||
model="rma.order.line"
|
||||
report_type="qweb-pdf"
|
||||
file="rma.report_rma_order_line"
|
||||
name="rma.report_rma_order_line"
|
||||
/>
|
||||
</data>
|
||||
</odoo>
|
||||
103
rma/report/rma_report_templates.xml
Normal file
103
rma/report/rma_report_templates.xml
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="report_rma_order_line_document">
|
||||
<t t-call="report.external_layout">
|
||||
<t t-set="doc" t-value="doc.with_context({'lang':doc.partner_id.lang})" />
|
||||
<div class="page">
|
||||
<div class="oe_structure"/>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<t t-if="((doc.customer_to_supplier==False and doc.type=='customer') or (doc.supplier_to_customer==False and doc.type=='supplier')) and doc.in_warehouse_id.partner_id">
|
||||
<strong>Shipping address:</strong>
|
||||
<div class="mt8">
|
||||
<div t-field="doc.in_warehouse_id.partner_id"
|
||||
t-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": True, "phone_icons": True}'/>
|
||||
<p t-if="doc.in_warehouse_id.partner_id.vat">VAT: <span t-field="doc.in_warehouse_id.partner_id.vat"/></p>
|
||||
</div>
|
||||
</t>
|
||||
<div t-if="doc.customer_to_supplier and doc.type=='customer'" class="mt8">
|
||||
<strong>Shipping address:</strong>
|
||||
<div t-field="doc.supplier_address_id"
|
||||
t-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": True, "phone_icons": True}'/>
|
||||
<p t-if="doc.supplier_address_id.vat">VAT: <span t-field="doc.supplier_address_id.vat"/></p>
|
||||
</div>
|
||||
<div t-if="doc.supplier_to_customer and doc.type=='supplier'" class="mt8">
|
||||
<strong>Shipping address:</strong>
|
||||
<div t-field="doc.customer_address_id"
|
||||
t-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": True, "phone_icons": True}'/>
|
||||
<p t-if="doc.customer_address_id.vat">VAT: <span t-field="doc.customer_address_id.vat"/></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-3 col-xs-offset-1">
|
||||
<strong t-if="doc.type=='customer'">Customer:</strong>
|
||||
<strong t-if="doc.type=='supplier'">Supplier:</strong>
|
||||
<div t-field="doc.partner_id"
|
||||
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>
|
||||
<span t-field="doc.name"/>
|
||||
</h2>
|
||||
|
||||
<div class="row mt32 mb32" id="informations">
|
||||
<div t-if="doc.origin" class="col-xs-3">
|
||||
<strong>Origin Reference:</strong>
|
||||
<p t-field="doc.origin"/>
|
||||
</div>
|
||||
<div t-if="doc.create_date" class="col-xs-3">
|
||||
<strong>Date Ordered:</strong>
|
||||
<p t-field="doc.create_date"/>
|
||||
</div>
|
||||
<div t-if="doc.requested_by.name" class="col-xs-3">
|
||||
<strong>Contact Person:</strong>
|
||||
<p t-field="doc.requested_by.name"/>
|
||||
</div>
|
||||
<div name="operation_id" t-if="doc.operation_id" class="col-xs-3">
|
||||
<strong>Operation:</strong>
|
||||
<p t-field="doc.operation_id.name"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th class="text-right">Quantity</th>
|
||||
<th class="text-right">Unit Price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><span t-field="doc.product_id"/></td>
|
||||
<td class="text-right">
|
||||
<span t-field="doc.product_qty"/>
|
||||
<span t-field="doc.uom_id" groups="product.group_uom"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="doc.price_unit"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div t-if="doc.type=='supplier' and doc.description">
|
||||
<strong><p>Description</p></strong>
|
||||
<span t-field="doc.description"></span>
|
||||
</div>
|
||||
<div>
|
||||
<strong><p>Term and Conditions</p></strong>
|
||||
<span t-field="doc.conditions"></span>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
<template id="report_rma_order_line">
|
||||
<t t-call="report.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="rma.report_rma_order_line_document" t-lang="doc.partner_id.lang"/>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
||||
@@ -8,4 +8,4 @@ access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1,
|
||||
access_rma_operation_manager,access_rma_operation,model_rma_operation,group_rma_manager,1,1,1,1
|
||||
access_rma_operation_customer_user,access_rma_operation,model_rma_operation,group_rma_customer_user,1,0,0,0
|
||||
access_rma_operation_supplier_user,access_rma_operation,model_rma_operation,group_rma_supplier_user,1,0,0,0
|
||||
access_stock_config_settings,access_stock_config_settings,model_stock_config_settings,stock.group_stock_manager,1,1,1,1
|
||||
access_rma_order_line_user,access_rma_order_line,model_rma_order_line,base.group_user,1,0,0,0
|
||||
|
||||
|
@@ -1,48 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="0">
|
||||
<odoo noupdate="1">
|
||||
<record model="ir.module.category" id="module_category_rma">
|
||||
<field name="name">RMA</field>
|
||||
<field name="parent_id" ref="base.module_category_sales_management"/>
|
||||
<field name="sequence">30</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.module.category" id="module_category_rma">
|
||||
<field name="name">RMA</field>
|
||||
<field name="parent_id" ref="base.module_category_sales_management"/>
|
||||
<field name="sequence">30</field>
|
||||
</record>
|
||||
<record id="group_rma_customer_user" model="res.groups">
|
||||
<field name="name">RMA Customer User</field>
|
||||
<field name="implied_ids" eval="[(4, ref('stock.group_stock_user'))]"/>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
</record>º
|
||||
|
||||
<record id="group_rma_customer_user" model="res.groups">
|
||||
<field name="name">RMA Customer User</field>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
</record>
|
||||
<record id="group_rma_supplier_user" model="res.groups">
|
||||
<field name="name">RMA Supplier User</field>
|
||||
<field name="implied_ids" eval="[(4, ref('stock.group_stock_user'))]"/>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
</record>
|
||||
|
||||
<record id="group_rma_supplier_user" model="res.groups">
|
||||
<field name="name">RMA Supplier User</field>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
</record>
|
||||
<record id="group_rma_manager" model="res.groups">
|
||||
<field name="name">RMA Manager</field>
|
||||
<field name="implied_ids"
|
||||
eval="[(4, ref('rma.group_rma_customer_user')), (4, ref('rma.group_rma_supplier_user'))]"/>
|
||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
</record>
|
||||
|
||||
<record id="group_rma_manager" model="res.groups">
|
||||
<field name="name">RMA Manager</field>
|
||||
<field name="implied_ids"
|
||||
eval="[(4, ref('rma.group_rma_customer_user')), (4, ref('rma.group_rma_supplier_user'))]"/>
|
||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
</record>
|
||||
<record id="group_rma_delivery_invoice_address" model="res.groups">
|
||||
<field name="name">Addresses in RMA</field>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
</record>
|
||||
|
||||
<record id="group_rma_delivery_invoice_address" model="res.groups">
|
||||
<field name="name">Addresses in RMA</field>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
</record>
|
||||
<record id="group_rma_groups" model="res.groups">
|
||||
<field name="name">RMA Groups</field>
|
||||
<field name="category_id" ref="module_category_rma"/>
|
||||
</record>
|
||||
|
||||
<record id="stock.group_stock_manager" model="res.groups">
|
||||
<field name="implied_ids" eval="[(4, ref('group_rma_manager'))]"/>
|
||||
</record>
|
||||
<record id="stock.group_stock_user" model="res.groups">
|
||||
<field name="implied_ids" eval="[(4, ref('group_rma_customer_user'))]"/>
|
||||
</record>
|
||||
<record id="stock.group_stock_user" model="res.groups">
|
||||
<field name="implied_ids" eval="[(4, ref('group_rma_supplier_user'))]"/>
|
||||
</record>
|
||||
<record id="stock.group_stock_manager" model="res.groups">
|
||||
<field name="implied_ids" eval="[(4, ref('group_rma_manager'))]"/>
|
||||
</record>
|
||||
<record id="stock.group_stock_user" model="res.groups">
|
||||
<field name="implied_ids" eval="[(4, ref('group_rma_customer_user')),
|
||||
(4, ref('group_rma_supplier_user'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
BIN
rma/static/description/icon.png
Normal file
BIN
rma/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -2,5 +2,3 @@
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
from . import test_rma
|
||||
from . import test_supplier_rma
|
||||
from . import test_rma_dropship
|
||||
|
||||
@@ -6,166 +6,156 @@ from odoo.tests import common
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class TestRma(common.TransactionCase):
|
||||
|
||||
class TestRma(common.SavepointCase):
|
||||
""" Test the routes and the quantities """
|
||||
|
||||
def setUp(self):
|
||||
super(TestRma, self).setUp()
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestRma, cls).setUpClass()
|
||||
|
||||
self.rma_make_picking = self.env['rma_make_picking.wizard']
|
||||
self.make_supplier_rma = self.env["rma.order.line.make.supplier.rma"]
|
||||
self.rma_add_stock_move = self.env['rma_add_stock_move']
|
||||
self.stockpicking = self.env['stock.picking']
|
||||
self.rma = self.env['rma.order']
|
||||
self.rma_line = self.env['rma.order.line']
|
||||
self.rma_op = self.env['rma.operation']
|
||||
self.rma_cust_replace_op_id = self.env.ref(
|
||||
cls.rma_make_picking = cls.env['rma_make_picking.wizard']
|
||||
cls.make_supplier_rma = cls.env["rma.order.line.make.supplier.rma"]
|
||||
cls.rma_add_stock_move = cls.env['rma_add_stock_move']
|
||||
cls.stockpicking = cls.env['stock.picking']
|
||||
cls.udpate_qty = cls.env['stock.change.product.qty']
|
||||
cls.rma = cls.env['rma.order']
|
||||
cls.rma_line = cls.env['rma.order.line']
|
||||
cls.rma_op = cls.env['rma.operation']
|
||||
cls.rma_cust_replace_op_id = cls.env.ref(
|
||||
'rma.rma_operation_customer_replace')
|
||||
self.rma_sup_replace_op_id = self.env.ref(
|
||||
cls.rma_sup_replace_op_id = cls.env.ref(
|
||||
'rma.rma_operation_supplier_replace')
|
||||
self.product_id = self.env.ref('product.product_product_4')
|
||||
self.product_1 = self.env.ref('product.product_product_25')
|
||||
self.product_2 = self.env.ref('product.product_product_7')
|
||||
self.product_3 = self.env.ref('product.product_product_11')
|
||||
self.uom_unit = self.env.ref('product.product_uom_unit')
|
||||
cls.product_id = cls.env.ref('product.product_product_4')
|
||||
cls.product_1 = cls.env.ref('product.product_product_25')
|
||||
cls.product_2 = cls.env.ref('product.product_product_8')
|
||||
cls.product_3 = cls.env.ref('product.product_product_9')
|
||||
cls.uom_unit = cls.env.ref('product.product_uom_unit')
|
||||
# assign an operation
|
||||
self.product_id.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_1.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_2.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_3.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.partner_id = self.env.ref('base.res_partner_12')
|
||||
self.stock_location = self.env.ref('stock.stock_location_stock')
|
||||
wh = self.env.ref('stock.warehouse0')
|
||||
self.stock_rma_location = wh.lot_rma_id
|
||||
self.customer_location = self.env.ref(
|
||||
cls.product_1.write(
|
||||
{'rma_customer_operation_id': cls.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': cls.rma_sup_replace_op_id.id})
|
||||
cls.product_2.write(
|
||||
{'rma_customer_operation_id': cls.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': cls.rma_sup_replace_op_id.id})
|
||||
cls.product_3.write(
|
||||
{'rma_customer_operation_id': cls.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': cls.rma_sup_replace_op_id.id})
|
||||
cls.partner_id = cls.env.ref('base.res_partner_12')
|
||||
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')
|
||||
self.supplier_location = self.env.ref(
|
||||
cls.supplier_location = cls.env.ref(
|
||||
'stock.stock_location_suppliers')
|
||||
self.product_uom_id = self.env.ref('product.product_uom_unit')
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_customer_id = self._create_rma_from_move(
|
||||
products2move, 'customer', self.partner_id,
|
||||
cls.product_uom_id = cls.env.ref('product.product_uom_unit')
|
||||
# Customer RMA:
|
||||
products2move = [(cls.product_1, 3), (cls.product_2, 5),
|
||||
(cls.product_3, 2)]
|
||||
cls.rma_customer_id = cls._create_rma_from_move(
|
||||
products2move, 'customer', cls.env.ref('base.res_partner_2'),
|
||||
dropship=False)
|
||||
# Dropship:
|
||||
cls.rma_droship_id = cls._create_rma_from_move(
|
||||
products2move, 'customer', cls.env.ref('base.res_partner_2'),
|
||||
dropship=True,
|
||||
supplier_address_id=cls.env.ref('base.res_partner_3'))
|
||||
# Supplier RMA:
|
||||
cls.rma_supplier_id = cls._create_rma_from_move(
|
||||
products2move, 'supplier', cls.env.ref('base.res_partner_1'),
|
||||
dropship=False)
|
||||
|
||||
def _create_picking(self, partner):
|
||||
return self.stockpicking.create({
|
||||
@classmethod
|
||||
def _create_picking(cls, partner):
|
||||
return cls.stockpicking.create({
|
||||
'partner_id': partner.id,
|
||||
'picking_type_id': self.env.ref('stock.picking_type_in').id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.supplier_location.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
|
||||
})
|
||||
|
||||
def _create_rma_from_move(self, products2move, type, partner, dropship,
|
||||
@classmethod
|
||||
def _create_rma_from_move(cls, products2move, rtype, partner, dropship,
|
||||
supplier_address_id=None):
|
||||
picking_in = self._create_picking(partner)
|
||||
picking_in = cls._create_picking(partner)
|
||||
|
||||
moves = []
|
||||
if type == 'customer':
|
||||
if rtype == 'customer':
|
||||
for item in products2move:
|
||||
move_values = self._prepare_move(
|
||||
item[0], item[1], self.stock_location,
|
||||
self.customer_location, picking_in)
|
||||
moves.append(self.env['stock.move'].create(move_values))
|
||||
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))
|
||||
else:
|
||||
for item in products2move:
|
||||
move_values = self._prepare_move(
|
||||
item[0], item[1], self.supplier_location,
|
||||
self.stock_rma_location, picking_in)
|
||||
moves.append(self.env['stock.move'].create(move_values))
|
||||
move_values = cls._prepare_move(
|
||||
item[0], item[1], cls.supplier_location,
|
||||
cls.stock_rma_location, picking_in)
|
||||
moves.append(cls.env['stock.move'].create(move_values))
|
||||
# Create the RMA from the stock_move
|
||||
rma_id = self.rma.create(
|
||||
rma_id = cls.rma.create(
|
||||
{
|
||||
'reference': '0001',
|
||||
'type': type,
|
||||
'type': rtype,
|
||||
'partner_id': partner.id,
|
||||
'company_id': self.env.ref('base.main_company').id
|
||||
'company_id': cls.env.ref('base.main_company').id
|
||||
})
|
||||
for move in moves:
|
||||
if type == 'customer':
|
||||
wizard = self.rma_add_stock_move.new(
|
||||
if rtype == 'customer':
|
||||
wizard = cls.rma_add_stock_move.with_context(
|
||||
{'stock_move_id': move.id, 'customer': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}
|
||||
)
|
||||
wizard.with_context({
|
||||
'stock_move_id': move.id, 'customer': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}).default_get([str(move.id),
|
||||
str(self.partner_id.id)])
|
||||
data = wizard.with_context(customer=1).\
|
||||
_prepare_rma_line_from_stock_move(move)
|
||||
).create({})
|
||||
data = wizard._prepare_rma_line_from_stock_move(move)
|
||||
wizard.add_lines()
|
||||
data['partner_id'] = move.partner_id.id
|
||||
for operation in move.product_id.rma_customer_operation_id:
|
||||
operation.in_route_id = False
|
||||
|
||||
if move.product_id.rma_customer_operation_id:
|
||||
move.product_id.rma_customer_operation_id.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)
|
||||
|
||||
else:
|
||||
wizard = self.rma_add_stock_move.new(
|
||||
wizard = cls.rma_add_stock_move.with_context(
|
||||
{'stock_move_id': move.id, 'supplier': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{'stock_move_id': move.id, 'supplier': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}).default_get([str(move.id),
|
||||
str(self.partner_id.id)])
|
||||
).create({})
|
||||
wizard._prepare_rma_line_from_stock_move(move)
|
||||
wizard.add_lines()
|
||||
|
||||
wizard = self.rma_add_stock_move.new(
|
||||
wizard = cls.rma_add_stock_move.with_context(
|
||||
{'stock_move_id': move.id, 'supplier': True,
|
||||
'active_ids': [],
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}
|
||||
)
|
||||
).create({})
|
||||
wizard.add_lines()
|
||||
|
||||
wizard = self.rma_add_stock_move.new(
|
||||
wizard = cls.rma_add_stock_move.with_context(
|
||||
{'stock_move_id': move.id, 'supplier': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}
|
||||
)
|
||||
).create({})
|
||||
data = wizard._prepare_rma_line_from_stock_move(move)
|
||||
data['partner_id'] = move.partner_id.id
|
||||
for operation in move.product_id.rma_customer_operation_id:
|
||||
operation.in_route_id = False
|
||||
if move.product_id.rma_customer_operation_id:
|
||||
move.product_id.rma_customer_operation_id.in_route_id = \
|
||||
False
|
||||
move.product_id.rma_customer_operation_id = False
|
||||
wizard.add_lines()
|
||||
|
||||
if dropship:
|
||||
data.update(customer_to_supplier=dropship,
|
||||
supplier_address_id=supplier_address_id.id)
|
||||
data['partner_id'] = move.partner_id.id
|
||||
data['rma_id'] = rma_id.id
|
||||
self.line = self.rma_line.create(data)
|
||||
cls.line = cls.rma_line.create(data)
|
||||
# approve the RMA Line
|
||||
self.rma_line.action_rma_to_approve()
|
||||
self.line.action_rma_approve()
|
||||
cls.line.action_rma_to_approve()
|
||||
cls.line.action_rma_approve()
|
||||
rma_id._get_default_type()
|
||||
rma_id._compute_in_shipment_count()
|
||||
rma_id._compute_out_shipment_count()
|
||||
@@ -177,20 +167,16 @@ class TestRma(common.TransactionCase):
|
||||
|
||||
rma_id.partner_id.action_open_partner_rma()
|
||||
rma_id.partner_id._compute_rma_line_count()
|
||||
# approve the RMA
|
||||
for line in rma_id.rma_line_ids:
|
||||
line.action_rma_to_approve()
|
||||
line.action_rma_approve()
|
||||
return rma_id
|
||||
|
||||
def _prepare_move(self, product, qty, src, dest, picking_in):
|
||||
|
||||
@classmethod
|
||||
def _prepare_move(cls, product, qty, src, dest, picking_in):
|
||||
res = {
|
||||
'partner_id': self.partner_id.id,
|
||||
'partner_id': cls.partner_id.id,
|
||||
'product_id': product.id,
|
||||
'name': product.partner_ref,
|
||||
'state': 'confirmed',
|
||||
'product_uom': self.product_uom_id.id or product.uom_id.id,
|
||||
'product_uom': cls.product_uom_id.id or product.uom_id.id,
|
||||
'product_uom_qty': qty,
|
||||
'origin': 'Test RMA',
|
||||
'location_id': src.id,
|
||||
@@ -199,23 +185,29 @@ class TestRma(common.TransactionCase):
|
||||
}
|
||||
return res
|
||||
|
||||
def test_rma_order_line(self):
|
||||
partner2 = self.env.ref('base.res_partner_2')
|
||||
picking_in = self._create_picking(partner2)
|
||||
def update_product_qty(cls, product, qty=10.0):
|
||||
up_wiz = cls.udpate_qty.create({
|
||||
'product_id': product.id,
|
||||
'new_quantity': qty,
|
||||
'location_id': cls.stock_location.id,
|
||||
})
|
||||
up_wiz.change_product_qty()
|
||||
return True
|
||||
|
||||
def test_01_rma_order_line(self):
|
||||
picking_in = self._create_picking(self.env.ref('base.res_partner_2'))
|
||||
moves_1 = []
|
||||
move_values = self._prepare_move(self.product_1, 3,
|
||||
self.stock_location,
|
||||
self.customer_location, picking_in)
|
||||
moves_1.append(self.env['stock.move'].create(move_values))
|
||||
wizard_1 = self.rma_add_stock_move.new(
|
||||
wizard_1 = self.rma_add_stock_move.with_context(
|
||||
{'supplier': True,
|
||||
'stock_move_id': [(6, 0, [m.id for m in moves_1])],
|
||||
'active_ids': self.rma_customer_id.id,
|
||||
'active_model': 'rma.order',
|
||||
'partner_id': self.partner_id.id,
|
||||
'move_ids': [(6, 0, [m.id for m in moves_1])]
|
||||
}
|
||||
)
|
||||
).create({'move_ids': [(6, 0, [m.id for m in moves_1])]})
|
||||
wizard_1.add_lines()
|
||||
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
@@ -232,6 +224,20 @@ class TestRma(common.TransactionCase):
|
||||
new_line = self.rma_line.new(data)
|
||||
new_line._onchange_reference_move_id()
|
||||
|
||||
# check assert if call reference_move_id onchange
|
||||
self.assertEquals(new_line.product_id,
|
||||
line.reference_move_id.product_id)
|
||||
self.assertEquals(new_line.product_qty,
|
||||
line.reference_move_id.product_uom_qty)
|
||||
self.assertEquals(new_line.location_id.location_id,
|
||||
line.reference_move_id.location_id)
|
||||
self.assertEquals(new_line.origin,
|
||||
line.reference_move_id.picking_id.name)
|
||||
self.assertEquals(new_line.delivery_address_id,
|
||||
line.reference_move_id.picking_partner_id)
|
||||
self.assertEquals(new_line.qty_to_receive,
|
||||
line.reference_move_id.product_uom_qty)
|
||||
|
||||
line.action_rma_to_approve()
|
||||
line.action_rma_draft()
|
||||
line.action_rma_done()
|
||||
@@ -244,6 +250,10 @@ class TestRma(common.TransactionCase):
|
||||
new_line = self.rma_line.new(data)
|
||||
new_line._onchange_operation_id()
|
||||
|
||||
# check assert if call operation_id onchange
|
||||
self.assertEquals(new_line.operation_id.receipt_policy,
|
||||
line.receipt_policy)
|
||||
|
||||
data = {'customer_to_supplier': line.customer_to_supplier}
|
||||
new_line = self.rma_line.new(data)
|
||||
new_line._onchange_receipt_policy()
|
||||
@@ -257,28 +267,28 @@ class TestRma(common.TransactionCase):
|
||||
line.action_view_procurements()
|
||||
self.rma_customer_id.action_view_supplier_lines()
|
||||
with self.assertRaises(ValidationError):
|
||||
line.rma_id.partner_id = partner2.id
|
||||
line.rma_id.partner_id = self.partner_id.id
|
||||
self.rma_customer_id.rma_line_ids[0].\
|
||||
partner_id = partner2.id
|
||||
partner_id = self.partner_id.id
|
||||
self.rma_customer_id.action_view_supplier_lines()
|
||||
|
||||
def test_customer_rma(self):
|
||||
def test_02_customer_rma(self):
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'incoming',
|
||||
'active_id': 1
|
||||
}).create({'rma_id': self.rma_customer_id.id})
|
||||
wizard.with_context({
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'incoming',
|
||||
'active_id': 1
|
||||
}).default_get({})
|
||||
procurements = wizard._create_picking()
|
||||
for proc in procurements:
|
||||
proc._get_stock_move_values()
|
||||
}).create({})
|
||||
# Before creating the picking:
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2.0)
|
||||
|
||||
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))]
|
||||
@@ -288,64 +298,47 @@ class TestRma(common.TransactionCase):
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
# After creating the picking:
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_received, 0, "Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered")
|
||||
# product specific
|
||||
# qty to receive should not consider qty incoming
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
self.assertEquals(line.qty_incoming, 3.0)
|
||||
self.assertEquals(line.qty_to_receive, 3.0,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 3,
|
||||
"Wrong qty incoming")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
self.assertEquals(line.qty_incoming, 5.0)
|
||||
self.assertEquals(line.qty_to_receive, 5.0,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 5,
|
||||
"Wrong qty incoming")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
self.assertEquals(line.qty_to_receive, 2.0,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 2,
|
||||
"Wrong qty incoming")
|
||||
picking.action_assign()
|
||||
picking.force_assign()
|
||||
picking.do_new_transfer()
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty to_receive")
|
||||
# self.assertEquals(line.qty_incoming, 5,
|
||||
# "Wrong qty incoming")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to received")
|
||||
self.assertEquals(line.qty_incoming, 3,
|
||||
"Wrong qty incoming")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to received")
|
||||
self.assertEquals(line.qty_incoming, 5,
|
||||
"Wrong qty incoming")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to received")
|
||||
self.assertEquals(line.qty_incoming, 2,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_incoming, 2.0)
|
||||
|
||||
# Validate the picking:
|
||||
picking.action_assign()
|
||||
picking.do_transfer()
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_receive, 0, "Wrong qty to_receive")
|
||||
self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming")
|
||||
self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 3.0)
|
||||
self.assertEquals(line.qty_to_deliver, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5.0)
|
||||
self.assertEquals(line.qty_to_deliver, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2.0)
|
||||
self.assertEquals(line.qty_to_deliver, 2.0)
|
||||
|
||||
# Create delivery:
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
@@ -359,67 +352,252 @@ class TestRma(common.TransactionCase):
|
||||
pickings = self.stockpicking.search(domain)
|
||||
self.assertEquals(len(pickings), 2,
|
||||
"Incorrect number of pickings created")
|
||||
picking_out = pickings[0]
|
||||
picking_out = pickings[1]
|
||||
moves = picking_out.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty receive")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 0, "Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
self.assertEquals(line.qty_to_deliver, 3.0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_received, 3.0)
|
||||
self.assertEquals(line.qty_outgoing, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to received")
|
||||
self.assertEquals(line.qty_incoming, 5,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_to_deliver, 5.0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_received, 5.0)
|
||||
self.assertEquals(line.qty_outgoing, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to received")
|
||||
self.assertEquals(line.qty_incoming, 2,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_to_deliver, 2.0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_received, 2.0)
|
||||
self.assertEquals(line.qty_outgoing, 2.0)
|
||||
|
||||
# Validate delivery:
|
||||
picking_out.action_assign()
|
||||
picking_out.do_new_transfer()
|
||||
for line in self.rma_customer_id.rma_line_ids[0]:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 3,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
picking_out.do_transfer()
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_receive, 0, "Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming")
|
||||
self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to received")
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to delivered")
|
||||
self.assertEquals(line.qty_received, 3.0)
|
||||
self.assertEquals(line.qty_delivered, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 5,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_received, 5.0)
|
||||
self.assertEquals(line.qty_delivered, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 2,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_received, 2.0)
|
||||
self.assertEquals(line.qty_delivered, 2.0)
|
||||
self.line.action_rma_done()
|
||||
self.assertEquals(self.line.state, 'done',
|
||||
"Wrong State")
|
||||
self.assertEquals(self.line.state, 'done', "Wrong State")
|
||||
|
||||
# Dummy call to action_view methods.
|
||||
self.rma_customer_id.action_view_in_shipments()
|
||||
self.rma_customer_id.action_view_out_shipments()
|
||||
self.rma_customer_id.action_view_lines()
|
||||
# Check counts:
|
||||
self.assertEquals(self.rma_customer_id.out_shipment_count, 1)
|
||||
self.assertEquals(self.rma_customer_id.in_shipment_count, 1)
|
||||
|
||||
# DROPSHIP
|
||||
def test_03_dropship(self):
|
||||
# Before receiving or creating the delivery from supplier rma:
|
||||
for line in self.rma_droship_id.rma_line_ids:
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 2.0)
|
||||
|
||||
# TODO: receive dropship
|
||||
|
||||
# Create supplier rma:
|
||||
wizard = self.make_supplier_rma.with_context({
|
||||
'active_ids': self.rma_droship_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'active_id': 1
|
||||
}).create({})
|
||||
res = wizard.make_supplier_rma()
|
||||
supplier_rma = self.rma.browse(res['res_id'])
|
||||
for line in supplier_rma.rma_line_ids:
|
||||
line.action_rma_to_approve()
|
||||
line.action_rma_approve()
|
||||
|
||||
for line in self.rma_droship_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0.0)
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3.0)
|
||||
self.assertEquals(line.qty_in_supplier_rma, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5.0)
|
||||
self.assertEquals(line.qty_in_supplier_rma, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2.0)
|
||||
self.assertEquals(line.qty_in_supplier_rma, 2.0)
|
||||
|
||||
# Create deliveries from supplier rma:
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': supplier_rma.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'outgoing',
|
||||
}).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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in supplier_rma.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_to_receive, 0, "Wrong qty to receive")
|
||||
self.assertEquals(line.qty_received, 0, "Wrong qty received")
|
||||
self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(
|
||||
line.qty_to_deliver, 3.0, "Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_outgoing, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_outgoing, 2.0)
|
||||
|
||||
for line in self.rma_droship_id.rma_line_ids:
|
||||
line.action_rma_done()
|
||||
self.assertEquals(line.state, 'done', "Wrong State")
|
||||
|
||||
# Check counts:
|
||||
self.assertEquals(self.rma_droship_id.out_shipment_count, 0)
|
||||
self.assertEquals(supplier_rma.out_shipment_count, 1)
|
||||
self.assertEquals(supplier_rma.in_shipment_count, 0)
|
||||
|
||||
# Supplier RMA
|
||||
def test_04_supplier_rma(self):
|
||||
# Update quantities:
|
||||
self.update_product_qty(self.product_1)
|
||||
self.update_product_qty(self.product_2)
|
||||
self.update_product_qty(self.product_3)
|
||||
# Check correct RMA type:
|
||||
self.assertEqual(self.rma_supplier_id.type, 'supplier')
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
self.assertEqual(line.type, 'supplier')
|
||||
# Create delivery:
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_supplier_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'outgoing',
|
||||
'active_id': 1
|
||||
}).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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0, "Wrong qty received")
|
||||
self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(
|
||||
line.qty_to_deliver, 3.0, "Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_to_receive, 3.0)
|
||||
self.assertEquals(line.qty_outgoing, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5.0)
|
||||
self.assertEquals(line.qty_outgoing, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2.0)
|
||||
self.assertEquals(line.qty_outgoing, 2.0)
|
||||
|
||||
# Validate Delivery:
|
||||
picking.action_assign()
|
||||
picking.do_transfer()
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming")
|
||||
self.assertEquals(line.qty_received, 0, "Wrong qty received")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_delivered, 3.0)
|
||||
self.assertEquals(line.qty_to_receive, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_delivered, 5.0)
|
||||
self.assertEquals(line.qty_to_receive, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_delivered, 2.0)
|
||||
self.assertEquals(line.qty_to_receive, 2.0)
|
||||
|
||||
# Create incoming shipment
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': self.rma_supplier_id.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_type_code', '=', 'incoming')]
|
||||
pickings = self.stockpicking.search(domain)
|
||||
self.assertEquals(len(pickings), 1,
|
||||
"Incorrect number of pickings created")
|
||||
picking_out = pickings[0]
|
||||
moves = picking_out.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(
|
||||
line.qty_to_receive, 3.0, "Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 3.0)
|
||||
self.assertEquals(line.qty_delivered, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_incoming, 5.0)
|
||||
self.assertEquals(line.qty_delivered, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_incoming, 2.0)
|
||||
self.assertEquals(line.qty_delivered, 2.0)
|
||||
|
||||
# Validate incoming shipment:
|
||||
picking_out.action_assign()
|
||||
picking_out.do_transfer()
|
||||
for line in self.rma_supplier_id.rma_line_ids[0]:
|
||||
self.assertEquals(line.qty_to_receive, 0, "Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming")
|
||||
self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 3.0)
|
||||
self.assertEquals(line.qty_delivered, 3.0)
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5.0)
|
||||
self.assertEquals(line.qty_delivered, 5.0)
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2.0)
|
||||
self.assertEquals(line.qty_delivered, 2.0)
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
line.action_rma_done()
|
||||
self.assertEquals(line.state, 'done', "Wrong State")
|
||||
|
||||
# Check counts:
|
||||
self.assertEquals(self.rma_supplier_id.out_shipment_count, 1)
|
||||
self.assertEquals(self.rma_supplier_id.in_shipment_count, 1)
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from . import test_rma
|
||||
|
||||
|
||||
class TestRmaDropship(test_rma.TestRma):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRmaDropship, self).setUp()
|
||||
self.product_id.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_1.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_2.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_3.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_droship_id = self._create_rma_from_move(
|
||||
products2move, 'customer', self.env.ref('base.res_partner_12'),
|
||||
dropship=True,
|
||||
supplier_address_id=self.env.ref('base.res_partner_3'))
|
||||
|
||||
def test_dropship(self):
|
||||
wizard = self.make_supplier_rma.with_context({
|
||||
'active_ids': self.rma_droship_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'active_id': 1
|
||||
}).create({'partner_id': self.partner_id.id,
|
||||
'supplier_rma_id': self.rma_droship_id.id,
|
||||
})
|
||||
|
||||
res = wizard.make_supplier_rma()
|
||||
supplier_rma = self.rma.browse(res['res_id'])
|
||||
for line in supplier_rma.rma_line_ids:
|
||||
line.action_rma_to_approve()
|
||||
line.action_rma_approve()
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': supplier_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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in supplier_rma.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty receive")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
|
||||
for line in self.rma_droship_id.rma_line_ids[0]:
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 3,
|
||||
"Wrong qty in supplier rma")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 5,
|
||||
"Wrong qty in supplier rma")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 2,
|
||||
"Wrong qty in supplier rma")
|
||||
for line in self.rma_droship_id.rma_line_ids:
|
||||
line.action_rma_done()
|
||||
self.assertEquals(line.state, 'done',
|
||||
"Wrong State")
|
||||
@@ -1,156 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from . import test_rma
|
||||
|
||||
|
||||
class TestSupplierRma(test_rma.TestRma):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSupplierRma, self).setUp()
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_supplier_id = self._create_rma_from_move(
|
||||
products2move, 'supplier', self.env.ref('base.res_partner_1'),
|
||||
dropship=False)
|
||||
|
||||
def test_supplier_rma(self):
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_supplier_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'outgoing',
|
||||
'active_id': 1
|
||||
}).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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 3,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 5,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 2,
|
||||
"Wrong qty outgoing")
|
||||
|
||||
picking.action_assign()
|
||||
picking.do_new_transfer()
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': self.rma_supplier_id.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))]
|
||||
pickings = self.stockpicking.search(domain)
|
||||
self.assertEquals(len(pickings), 2,
|
||||
"Incorrect number of pickings created")
|
||||
picking_out = pickings[0]
|
||||
moves = picking_out.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
picking_out.action_assign()
|
||||
picking_out.do_new_transfer()
|
||||
for line in self.rma_supplier_id.rma_line_ids[0]:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 6,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 5,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 2,
|
||||
"Wrong qty delivered")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
line.action_rma_done()
|
||||
self.assertEquals(line.state, 'done',
|
||||
"Wrong State")
|
||||
@@ -7,12 +7,14 @@
|
||||
<field name="model">product.category</field>
|
||||
<field name="inherit_id" ref="product.product_category_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<group name="rma">
|
||||
<field name="removal_strategy_id" position="after">
|
||||
<field name="rma_approval_policy" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
|
||||
<field name="rma_customer_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
|
||||
<field name="rma_supplier_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
|
||||
</group>
|
||||
<field name="rma_customer_operation_id"
|
||||
groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"
|
||||
domain="[('type','=','customer')]"/>
|
||||
<field name="rma_supplier_operation_id"
|
||||
groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"
|
||||
domain="[('type','=','supplier')]"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
@@ -25,8 +27,12 @@
|
||||
<group name="inventory" position="inside">
|
||||
<group name="rma" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user">
|
||||
<field name="rma_approval_policy"/>
|
||||
<field name="rma_customer_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
|
||||
<field name="rma_supplier_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
|
||||
<field name="rma_customer_operation_id"
|
||||
groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"
|
||||
domain="[('type','=','customer')]"/>
|
||||
<field name="rma_supplier_operation_id"
|
||||
groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"
|
||||
domain="[('type','=','supplier')]"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<tree string="RMA Line"
|
||||
decoration-info="state in ('draft','to_approve')">
|
||||
<field name="name"/>
|
||||
<field name="create_date"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
@@ -30,6 +31,7 @@
|
||||
<tree string="RMA Line"
|
||||
decoration-info="state in ('draft','to_approve')">
|
||||
<field name="name"/>
|
||||
<field name="create_date"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
@@ -90,6 +92,13 @@
|
||||
<field name="procurement_count" widget="statinfo"
|
||||
string="Proc. Exceptions"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_rma_lines"
|
||||
class="oe_stat_button"
|
||||
icon="fa-link"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="rma_line_count" widget="statinfo"
|
||||
string="Customer RMA"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title" name="title">
|
||||
<h1>
|
||||
@@ -101,6 +110,23 @@
|
||||
<field name="partner_id"
|
||||
domain="[('supplier','=',True)]"
|
||||
string="Supplier"/>
|
||||
<field name="create_date"/>
|
||||
</group>
|
||||
<group>
|
||||
<group name="product" string="Product">
|
||||
<field name="product_id"/>
|
||||
<newline/>
|
||||
<field name="product_tracking" invisible="1"/>
|
||||
<field name="lot_id"
|
||||
groups="stock.group_production_lot"
|
||||
attrs="{'required': [('product_tracking', 'in', ('serial', 'lot'))]}"
|
||||
domain="[('product_id', '=', product_id)]"/>
|
||||
</group>
|
||||
<group name="product_qty" string="Quantity">
|
||||
<field name="product_qty"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="main_info" string="Origin">
|
||||
<field name="reference_move_id"
|
||||
@@ -110,20 +136,6 @@
|
||||
('state', '=', 'done')]"/>
|
||||
</group>
|
||||
<group>
|
||||
<group name="product" string="Product">
|
||||
<field name="product_id"/>
|
||||
<newline/>
|
||||
<field name="product_tracking" invisible="1"/>
|
||||
<field name="lot_id"
|
||||
groups="stock.group_production_lot"
|
||||
attrs="{'required': [('product_tracking', 'in', ('serial', 'lot'))]}"/>
|
||||
</group>
|
||||
<group name="product_qty" string="Quantity">
|
||||
<field name="product_qty"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group name="operation" string="Operation">
|
||||
<field name="operation_id"
|
||||
domain="[('type','=','supplier')]"/>
|
||||
@@ -132,27 +144,36 @@
|
||||
</group>
|
||||
<group name="contact" string="Contact">
|
||||
<field name="requested_by" readonly="1"/>
|
||||
<field name="assigned_to" readonly="1"/>
|
||||
<field name="assigned_to"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="route" string="Routes" groups="stock.group_adv_location">
|
||||
<page name="description" string="Description">
|
||||
<field name="description" nolabel="1"/>
|
||||
</page>
|
||||
<page name="route" string="Routes">
|
||||
<group>
|
||||
<group name="inbound" string="Inbound">
|
||||
<field name="in_warehouse_id"/>
|
||||
<field name="location_id"
|
||||
domain="[('usage', '=', 'internal')]"/>
|
||||
<field name="in_route_id"/>
|
||||
<field name="supplier_to_customer"/>
|
||||
<field name="in_route_id" groups="stock.group_adv_location"/>
|
||||
</group>
|
||||
<group name="outbound" string="Outbound">
|
||||
<field name="out_warehouse_id"/>
|
||||
<field name="out_route_id"/>
|
||||
</group>
|
||||
<group name="delivery_address"
|
||||
string="Delivery Address (drop ship">
|
||||
<field name="delivery_address_id"
|
||||
groups='rma.group_rma_delivery_invoice_address'/>
|
||||
domain="['|', ('parent_id', '=', partner_id),
|
||||
('id', '=', partner_id)]"
|
||||
context="{'show_address': 1}"
|
||||
options="{'always_reload': 1}"
|
||||
groups='rma.group_rma_delivery_invoice_address'/>
|
||||
<field name="out_route_id" groups="stock.group_adv_location"/>
|
||||
<field name="supplier_to_customer"/>
|
||||
<field name="customer_address_id"
|
||||
context="{'show_address': 1}"
|
||||
options="{'always_reload': 1}"
|
||||
attrs="{'required':[('supplier_to_customer', '=', True)],
|
||||
'invisible':[('supplier_to_customer', '=', False)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
@@ -177,6 +198,7 @@
|
||||
</page>
|
||||
<page name="other" string="Other Info">
|
||||
<group name="general" string="General">
|
||||
<field name="conditions"/>
|
||||
<field name="rma_id"/>
|
||||
<field name="origin"/>
|
||||
|
||||
@@ -200,7 +222,7 @@
|
||||
<field name="name">rma.order.line.form</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Rma Line">
|
||||
<form string="RMA Line">
|
||||
<header>
|
||||
<button name="action_rma_to_approve" type="object"
|
||||
string="Request Approval"
|
||||
@@ -235,11 +257,6 @@
|
||||
<field name="out_shipment_count" widget="statinfo"
|
||||
string="Deliveries"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_invoice"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o"
|
||||
string="Origin Inv">
|
||||
</button>
|
||||
<button type="object" name="action_view_procurements"
|
||||
class="oe_stat_button"
|
||||
icon="fa-warning"
|
||||
@@ -247,6 +264,13 @@
|
||||
<field name="procurement_count" widget="statinfo"
|
||||
string="Exceptions"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_rma_lines"
|
||||
class="oe_stat_button"
|
||||
icon="fa-link"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="rma_line_count" widget="statinfo"
|
||||
string="Supplier RMA"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title" name="title">
|
||||
<h1>
|
||||
@@ -259,11 +283,28 @@
|
||||
<field name="partner_id"
|
||||
domain="[('customer','=',True)]"
|
||||
string="Customer"/>
|
||||
<field name="create_date"/>
|
||||
</group>
|
||||
<group name="warranty">
|
||||
<field name="under_warranty"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<group name="product" string="Product">
|
||||
<field name="product_id"/>
|
||||
<newline/>
|
||||
<field name="product_tracking" invisible="1"/>
|
||||
<field name="lot_id"
|
||||
groups="stock.group_production_lot"
|
||||
attrs="{'required': [('product_tracking', 'in', ('serial', 'lot'))]}"
|
||||
domain="[('product_id', '=', product_id)]"/>
|
||||
</group>
|
||||
<group name="product_qty" string="Quantity">
|
||||
<field name="product_qty"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="price_unit"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="main_info" string="Origin">
|
||||
<field name="reference_move_id"
|
||||
options="{'no_create': True}"
|
||||
@@ -272,20 +313,6 @@
|
||||
('state', '=', 'done')]"/>
|
||||
</group>
|
||||
<group>
|
||||
<group name="product" string="Product">
|
||||
<field name="product_id"/>
|
||||
<newline/>
|
||||
<field name="product_tracking" invisible="1"/>
|
||||
<field name="lot_id"
|
||||
groups="stock.group_production_lot"
|
||||
attrs="{'required': [('product_tracking', 'in', ('serial', 'lot'))]}"/>
|
||||
</group>
|
||||
<group name="product_qty" string="Quantity">
|
||||
<field name="product_qty"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="price_unit"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group name="operation" string="Operation">
|
||||
<field name="operation_id" domain="[('type','=','customer')]"/>
|
||||
<field name="receipt_policy"/>
|
||||
@@ -293,37 +320,39 @@
|
||||
</group>
|
||||
<group name="contact" string="Contact">
|
||||
<field name="requested_by" readonly="1"/>
|
||||
<field name="assigned_to" readonly="1"/>
|
||||
<field name="assigned_to"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="route" string="Routes">
|
||||
|
||||
<group>
|
||||
<group name="inbound" string="Inbound">
|
||||
<field name="in_warehouse_id"/>
|
||||
<field name="location_id"
|
||||
domain="[('usage', '=', 'internal')]"/>
|
||||
<field name="in_route_id"/>
|
||||
<field name="customer_to_supplier"/>
|
||||
<field name="supplier_address_id"
|
||||
attrs="{'required':[('customer_to_supplier', '=', True)],
|
||||
'invisible':[('customer_to_supplier', '=', False)]}"/>
|
||||
</group>
|
||||
<group name="outbound" string="Outbound">
|
||||
<field name="out_warehouse_id"/>
|
||||
<field name="delivery_address_id"
|
||||
groups='rma.group_rma_delivery_invoice_address'/>
|
||||
<field name="out_route_id"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<group name="inbound" string="Inbound">
|
||||
<field name="in_warehouse_id"/>
|
||||
<field name="location_id"
|
||||
domain="[('usage', '=', 'internal')]"/>
|
||||
<field name="in_route_id" groups="stock.group_adv_location"/>
|
||||
<field name="customer_to_supplier"/>
|
||||
<field name="supplier_address_id"
|
||||
context="{'show_address': 1}"
|
||||
options="{'always_reload': 1}"
|
||||
attrs="{'required':[('customer_to_supplier', '=', True)],
|
||||
'invisible':[('customer_to_supplier', '=', False)]}"/>
|
||||
</group>
|
||||
<group name="outbound" string="Outbound">
|
||||
<field name="out_warehouse_id"/>
|
||||
<field name="delivery_address_id"
|
||||
domain="['|', ('parent_id', '=', partner_id),
|
||||
('id', '=', partner_id)]"
|
||||
context="{'show_address': 1}"
|
||||
options="{'always_reload': 1}"
|
||||
groups='rma.group_rma_delivery_invoice_address'/>
|
||||
<field name="out_route_id" groups="stock.group_adv_location"/>
|
||||
</group>
|
||||
</page>
|
||||
<page name="stock" string="Stock Moves">
|
||||
<field name="move_ids" nolabel="1" readonly="1"/>
|
||||
</page>
|
||||
<page name="quantities" string="Quantities">
|
||||
<group name="quantities" string="Quantities">
|
||||
<group name="quantities" col="4" string="Quantities">
|
||||
<group name="receive">
|
||||
<field name="qty_to_receive"/>
|
||||
<field name="qty_incoming"/>
|
||||
@@ -343,6 +372,7 @@
|
||||
</page>
|
||||
<page name="other" string="Other Info">
|
||||
<group name="general" string="General">
|
||||
<field name="conditions"/>
|
||||
<field name="rma_id"/>
|
||||
<field name="origin"/>
|
||||
</group>
|
||||
@@ -373,8 +403,17 @@
|
||||
<field name="assigned_to"/>
|
||||
<field name="product_id"/>
|
||||
<field name="lot_id"/>
|
||||
<field name="create_date"/>
|
||||
<separator/>
|
||||
<filter domain="[('assigned_to','=',uid)]" help="My RMAs"/>
|
||||
<separator/>
|
||||
<group name="stock_quantities" groups="stock.group_stock_user">
|
||||
<filter domain="[('state','!=', 'done'),('qty_to_receive','>',0.0)]" help="To Receive"/>
|
||||
<filter domain="[('state','!=', 'done'),('qty_to_deliver','>',0.0)]" help="To Deliver"/>
|
||||
</group>
|
||||
<group name="rma_supplier_quantities">
|
||||
<filter domain="[('state','!=', 'done'),('qty_to_supplier_rma','>',0.0)]" help="To Send to Supplier RMA"/>
|
||||
</group>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="status" string="State" domain="[]"
|
||||
context="{'group_by':'state'}"/>
|
||||
|
||||
@@ -279,14 +279,14 @@
|
||||
id="menu_rma_act_customer"
|
||||
sequence="50"
|
||||
parent="menu_customer_rma"
|
||||
groups="rma.group_rma_customer_user"
|
||||
groups="rma.group_rma_groups"
|
||||
action="action_rma_customer"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_rma_act_supplier"
|
||||
sequence="50"
|
||||
parent="menu_supplier_rma"
|
||||
groups="rma.group_rma_supplier_user"
|
||||
groups="rma.group_rma_groups"
|
||||
action="action_rma_supplier"/>
|
||||
|
||||
<menuitem id="menu_rma_config"
|
||||
|
||||
@@ -23,7 +23,6 @@ class RmaAddStockMove(models.TransientModel):
|
||||
rma = rma_obj.browse(rma_id)
|
||||
res['rma_id'] = rma.id
|
||||
res['partner_id'] = rma.partner_id.id
|
||||
res['picking_id'] = False
|
||||
res['move_ids'] = False
|
||||
return res
|
||||
|
||||
@@ -44,9 +43,11 @@ class RmaAddStockMove(models.TransientModel):
|
||||
if self.env.context.get('customer'):
|
||||
operation = sm.product_id.rma_customer_operation_id or \
|
||||
sm.product_id.categ_id.rma_customer_operation_id
|
||||
rma_type = 'customer'
|
||||
else:
|
||||
operation = sm.product_id.rma_supplier_operation_id or \
|
||||
sm.product_id.categ_id.rma_supplier_operation_id
|
||||
rma_type = 'supplier'
|
||||
if not operation:
|
||||
operation = self.env['rma.operation'].search(
|
||||
[('type', '=', self.rma_id.type)], limit=1)
|
||||
@@ -73,6 +74,7 @@ class RmaAddStockMove(models.TransientModel):
|
||||
'lot_id': lot and lot.id or False,
|
||||
'origin': sm.picking_id.name or sm.name,
|
||||
'uom_id': sm.product_uom.id,
|
||||
'type': rma_type,
|
||||
'operation_id': operation.id,
|
||||
'product_qty': sm.product_uom_qty,
|
||||
'delivery_address_id': sm.picking_id.partner_id.id,
|
||||
|
||||
@@ -81,6 +81,8 @@ class RmaMakePicking(models.TransientModel):
|
||||
def _get_address(self, item):
|
||||
if item.line_id.customer_to_supplier:
|
||||
delivery_address = item.line_id.supplier_address_id
|
||||
elif item.line_id.supplier_to_customer:
|
||||
delivery_address = item.line_id.customer_address_id
|
||||
elif item.line_id.delivery_address_id:
|
||||
delivery_address = item.line_id.delivery_address_id
|
||||
elif item.line_id.partner_id:
|
||||
@@ -90,10 +92,10 @@ class RmaMakePicking(models.TransientModel):
|
||||
return delivery_address
|
||||
|
||||
@api.model
|
||||
def _get_address_location(self, delivery_address_id, type):
|
||||
if type == 'supplier':
|
||||
def _get_address_location(self, delivery_address_id, rtype):
|
||||
if rtype == 'supplier':
|
||||
return delivery_address_id.property_stock_supplier
|
||||
elif type == 'customer':
|
||||
elif rtype == 'customer':
|
||||
return delivery_address_id.property_stock_customer
|
||||
|
||||
@api.model
|
||||
@@ -168,14 +170,6 @@ class RmaMakePicking(models.TransientModel):
|
||||
raise ValidationError(
|
||||
_('RMA %s is not approved') %
|
||||
line.name)
|
||||
if line.receipt_policy == 'no' and picking_type == \
|
||||
'incoming':
|
||||
raise ValidationError(
|
||||
_('No shipments needed for this operation'))
|
||||
if line.delivery_policy == 'no' and picking_type == \
|
||||
'outgoing':
|
||||
raise ValidationError(
|
||||
_('No deliveries needed for this operation'))
|
||||
procurement = self._create_procurement(item, picking_type)
|
||||
procurement_list.append(procurement)
|
||||
procurements = self.env['procurement.order'].browse(procurement_list)
|
||||
|
||||
@@ -63,15 +63,13 @@ class RmaLineMakeSupplierRma(models.TransientModel):
|
||||
lines = rma_line_obj.browse(rma_line_ids)
|
||||
for line in lines:
|
||||
items.append([0, 0, self._prepare_item(line)])
|
||||
suppliers = lines.mapped('supplier_address_id')
|
||||
if len(suppliers) == 0:
|
||||
pass
|
||||
elif len(suppliers) == 1:
|
||||
res['partner_id'] = suppliers.id
|
||||
else:
|
||||
suppliers = lines.mapped(
|
||||
lambda r: r.supplier_address_id.parent_id or r.supplier_address_id)
|
||||
if len(suppliers) > 1:
|
||||
raise ValidationError(
|
||||
_('Only RMA lines from the same supplier address can be '
|
||||
_('Only RMA lines from the same supplier can be '
|
||||
'processed at the same time'))
|
||||
res['partner_id'] = suppliers.id
|
||||
res['item_ids'] = items
|
||||
return res
|
||||
|
||||
@@ -81,7 +79,6 @@ class RmaLineMakeSupplierRma(models.TransientModel):
|
||||
raise ValidationError(_('Enter a supplier.'))
|
||||
return {
|
||||
'partner_id': self.partner_id.id,
|
||||
'delivery_address_id': self.partner_id.id,
|
||||
'type': 'supplier',
|
||||
'company_id': company.id,
|
||||
}
|
||||
@@ -108,8 +105,9 @@ class RmaLineMakeSupplierRma(models.TransientModel):
|
||||
'partner_id': self.partner_id.id,
|
||||
'type': 'supplier',
|
||||
'origin': item.line_id.rma_id.name,
|
||||
'delivery_address_id':
|
||||
item.line_id.delivery_address_id.id,
|
||||
'customer_address_id':
|
||||
item.line_id.delivery_address_id.id or
|
||||
item.line_id.partner_id.id,
|
||||
'product_id': item.line_id.product_id.id,
|
||||
'customer_rma_id': item.line_id.id,
|
||||
'product_qty': item.product_qty,
|
||||
@@ -151,27 +149,18 @@ class RmaLineMakeSupplierRma(models.TransientModel):
|
||||
rma_line_data = self._prepare_supplier_rma_line(rma, item)
|
||||
rma_line = rma_line_obj.create(rma_line_data)
|
||||
if rma:
|
||||
return {
|
||||
'name': _('Supplier RMA'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'rma.order',
|
||||
'view_id': False,
|
||||
'res_id': rma.id,
|
||||
'context': {'supplier': True, 'customer': False},
|
||||
'type': 'ir.actions.act_window'
|
||||
}
|
||||
action = self.env.ref('rma.action_rma_supplier')
|
||||
result = action.read()[0]
|
||||
res = self.env.ref('rma.view_rma_supplier_form', False)
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = rma.id
|
||||
else:
|
||||
return {
|
||||
'name': _('Supplier RMA Line'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'rma.order.line',
|
||||
'view_id': False,
|
||||
'res_id': rma_line.id,
|
||||
'context': {'supplier': True, 'customer': False},
|
||||
'type': 'ir.actions.act_window'
|
||||
}
|
||||
action = self.env.ref('rma.action_rma_supplier_lines')
|
||||
result = action.read()[0]
|
||||
res = self.env.ref('rma.view_rma_line_supplier_form', False)
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = rma_line.id
|
||||
return result
|
||||
|
||||
|
||||
class RmaLineMakeRmaOrderItem(models.TransientModel):
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
<record model="ir.values" id="rma_order_line_make_supplier_rma">
|
||||
<field name="model_id" ref="model_rma_order_line" />
|
||||
<field name="name">Create Supplier RMA Group</field>
|
||||
<field name="name">Create Supplier RMA</field>
|
||||
<field name="key2">client_action_multi</field>
|
||||
<field name="value"
|
||||
eval="'ir.actions.act_window,' + str(ref('action_rma_order_line_make_supplier_rma'))" />
|
||||
@@ -80,7 +80,7 @@
|
||||
<header position="inside">
|
||||
<button name="%(action_rma_order_line_make_supplier_rma)d"
|
||||
states="approved"
|
||||
string="Create Supplier RMA Group" class="oe_highlight"
|
||||
string="Create Supplier RMA" class="oe_highlight"
|
||||
type="action"/>
|
||||
</header>
|
||||
</field>
|
||||
|
||||
@@ -13,5 +13,11 @@ class StockConfigSettings(models.TransientModel):
|
||||
"(Example: services companies)"),
|
||||
(1, 'Display 3 fields on rma: partner, invoice address, delivery '
|
||||
'address')
|
||||
], "Addresses",
|
||||
implied_group='rma.group_rma_delivery_invoice_address')
|
||||
], "Addresses", implied_group='rma.group_rma_delivery_invoice_address')
|
||||
|
||||
group_rma_lines = fields.Selection([
|
||||
(0, "Do not group RMA lines"),
|
||||
(1, 'Group RMA lines in one RMA group')
|
||||
], "Grouping",
|
||||
implied_group='rma.group_rma_groups',
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<xpath expr="//group[@name='shipping']" position="after">
|
||||
<group string="Return Merchandise Authorization">
|
||||
<field name="group_rma_delivery_address" widget="radio"/>
|
||||
<field name="group_rma_lines" widget="radio"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
{
|
||||
'name': 'RMA Account',
|
||||
'version': '9.0.1.0.0',
|
||||
'version': '10.0.2.0.0',
|
||||
'license': 'LGPL-3',
|
||||
'category': 'RMA',
|
||||
'summary': 'Integrates RMA with Invoice Processing',
|
||||
@@ -18,9 +18,9 @@
|
||||
'views/rma_operation_view.xml',
|
||||
'views/rma_order_line_view.xml',
|
||||
'views/invoice_view.xml',
|
||||
'views/rma_account_menu.xml',
|
||||
'wizards/rma_add_invoice.xml',
|
||||
'wizards/rma_refund.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': True,
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<field name="delivery_policy">no</field>
|
||||
<field name="type">customer</field>
|
||||
<field name="in_route_id" ref="rma.route_rma_customer"/>
|
||||
<field name="out_route_id" ref="rma.route_rma_customer"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_operation_supplier_refund" model="rma.operation">
|
||||
@@ -26,6 +27,7 @@
|
||||
<field name="receipt_policy">no</field>
|
||||
<field name="delivery_policy">ordered</field>
|
||||
<field name="type">supplier</field>
|
||||
<field name="in_route_id" ref="rma.route_rma_supplier"/>
|
||||
<field name="out_route_id" ref="rma.route_rma_supplier"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.float_utils import float_compare
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
@@ -14,9 +15,56 @@ class AccountInvoice(models.Model):
|
||||
rmas = self.mapped('invoice_line_ids.rma_line_ids')
|
||||
inv.rma_count = len(rmas)
|
||||
|
||||
def _prepare_invoice_line_from_rma_line(self, line):
|
||||
qty = line.qty_to_refund
|
||||
if float_compare(
|
||||
qty, 0.0, precision_rounding=line.uom_id.rounding) <= 0:
|
||||
qty = 0.0
|
||||
# Todo fill taxes from somewhere
|
||||
invoice_line = self.env['account.invoice.line']
|
||||
data = {
|
||||
'purchase_line_id': line.id,
|
||||
'name': line.name,
|
||||
'origin': line.origin,
|
||||
'uom_id': line.uom_id.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.company_id.currency_id.with_context(
|
||||
date=self.date_invoice).compute(
|
||||
line.price_unit, self.currency_id, round=False),
|
||||
'quantity': qty,
|
||||
'discount': 0.0,
|
||||
'account_analytic_id': line.analytic_account_id.id,
|
||||
'rma_line_id': line.id,
|
||||
}
|
||||
return data
|
||||
|
||||
@api.onchange('add_rma_line_id')
|
||||
def on_change_add_rma_line_id(self):
|
||||
if not self.add_rma_line_id:
|
||||
return {}
|
||||
new_line = self.env['account.invoice.line']
|
||||
if self.add_rma_line_id not in (
|
||||
self.invoice_line_ids.mapped('rma_line_id')):
|
||||
data = self._prepare_invoice_line_from_rma_line(
|
||||
self.add_rma_line_id)
|
||||
new_line = new_line.new(data)
|
||||
new_line._set_additional_fields(self)
|
||||
self.invoice_line_ids += new_line
|
||||
self.add_rma_line_id = False
|
||||
return {}
|
||||
|
||||
rma_count = fields.Integer(
|
||||
compute=_compute_rma_count, string='# of RMA')
|
||||
|
||||
add_rma_line_id = fields.Many2one(
|
||||
comodel_name='rma.order.line',
|
||||
string="Add from RMA line",
|
||||
ondelete="set null",
|
||||
help="Create a refund in based on an existing rma_line")
|
||||
|
||||
@api.multi
|
||||
def action_view_rma_supplier(self):
|
||||
action = self.env.ref('rma.action_rma_supplier_lines')
|
||||
@@ -78,13 +126,20 @@ class AccountInvoiceLine(models.Model):
|
||||
if self.env.context.get('rma'):
|
||||
for inv in self:
|
||||
if inv.invoice_id.reference:
|
||||
res.append((inv.id, "%s %s %s qty:%s" % (
|
||||
inv.invoice_id.number, inv.invoice_id.reference,
|
||||
inv.product_id.name, inv.quantity)))
|
||||
res.append(
|
||||
(inv.id,
|
||||
"INV:%s | REF:%s | ORIG:%s | PART:%s | QTY:%s" % (
|
||||
inv.invoice_id.number or '',
|
||||
inv.origin or '',
|
||||
inv.invoice_id.reference or "",
|
||||
inv.product_id.name, inv.quantity)))
|
||||
elif inv.invoice_id.number:
|
||||
res.append((inv.id, "%s %s qty:%s" % (
|
||||
inv.invoice_id.number or '',
|
||||
inv.product_id.name, inv.quantity)))
|
||||
res.append(
|
||||
(inv.id,
|
||||
"INV:%s | ORIG:%s | PART:%s | QTY:%s" % (
|
||||
inv.invoice_id.number or '',
|
||||
inv.origin or '',
|
||||
inv.product_id.name, inv.quantity)))
|
||||
else:
|
||||
res.append(super(AccountInvoiceLine, inv).name_get()[0])
|
||||
return res
|
||||
@@ -101,11 +156,12 @@ class AccountInvoiceLine(models.Model):
|
||||
compute=_compute_rma_count, string='# of RMA')
|
||||
rma_line_ids = fields.One2many(
|
||||
comodel_name='rma.order.line', inverse_name='invoice_line_id',
|
||||
string="RMA", readonly=True,
|
||||
string="RMA", readonly=True, copy=False,
|
||||
help="This will contain the RMA lines for the invoice line")
|
||||
|
||||
rma_line_id = fields.Many2one(
|
||||
comodel_name='rma.order.line',
|
||||
string="RMA line refund",
|
||||
copy=False,
|
||||
ondelete="set null",
|
||||
help="This will contain the rma line that originated the refund line")
|
||||
|
||||
@@ -69,8 +69,6 @@ class RmaOrder(models.Model):
|
||||
|
||||
self.rma_line_ids += new_lines
|
||||
self.date_rma = fields.Datetime.now()
|
||||
self.delivery_address_id = self.add_invoice_id.partner_id.id
|
||||
self.invoice_address_id = self.add_invoice_id.partner_id.id
|
||||
self.add_invoice_id = False
|
||||
return {}
|
||||
|
||||
|
||||
@@ -82,6 +82,21 @@ class RmaOrderLine(models.Model):
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True, compute=_compute_qty_refunded, store=True)
|
||||
|
||||
@api.onchange('product_id', 'partner_id')
|
||||
def _onchange_product_id(self):
|
||||
"""Domain for invoice_line_id is computed here to make it dynamic."""
|
||||
res = super(RmaOrderLine, self)._onchange_product_id()
|
||||
if not res.get('domain'):
|
||||
res['domain'] = {}
|
||||
domain = [
|
||||
'|',
|
||||
('invoice_id.partner_id', '=', self.partner_id.id),
|
||||
('invoice_id.partner_id', 'child_of', self.partner_id.id)]
|
||||
if self.product_id:
|
||||
domain.append(('product_id', '=', self.product_id.id))
|
||||
res['domain']['invoice_line_id'] = domain
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _prepare_rma_line_from_inv_line(self, line):
|
||||
self.ensure_one()
|
||||
@@ -149,7 +164,7 @@ class RmaOrderLine(models.Model):
|
||||
def _check_invoice_partner(self):
|
||||
for rec in self:
|
||||
if (rec.invoice_line_id and
|
||||
rec.invoice_line_id.invoice_id.partner_id !=
|
||||
rec.invoice_line_id.invoice_id.commercial_partner_id !=
|
||||
rec.partner_id):
|
||||
raise ValidationError(_(
|
||||
"RMA customer and originating invoice line customer "
|
||||
@@ -165,9 +180,8 @@ class RmaOrderLine(models.Model):
|
||||
@api.onchange('operation_id')
|
||||
def _onchange_operation_id(self):
|
||||
result = super(RmaOrderLine, self)._onchange_operation_id()
|
||||
if not self.operation_id:
|
||||
return result
|
||||
self.refund_policy = self.operation_id.refund_policy
|
||||
if self.operation_id:
|
||||
self.refund_policy = self.operation_id.refund_policy or 'no'
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
@@ -207,3 +221,16 @@ class RmaOrderLine(models.Model):
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = invoice_ids[0]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def name_get(self):
|
||||
res = []
|
||||
if self.env.context.get('rma'):
|
||||
for rma in self:
|
||||
res.append((rma.id, "%s %s qty:%s" % (
|
||||
rma.name,
|
||||
rma.product_id.name,
|
||||
rma.product_qty)))
|
||||
return res
|
||||
else:
|
||||
return super(RmaOrderLine, self).name_get()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
from . import test_rma
|
||||
from . import test_supplier_rma
|
||||
from . import test_rma_dropship
|
||||
|
||||
from . import test_rma_account
|
||||
|
||||
@@ -1,415 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp.tests import common
|
||||
from openerp import fields
|
||||
|
||||
|
||||
class TestRma(common.TransactionCase):
|
||||
|
||||
""" Test the routes and the quantities """
|
||||
|
||||
def setUp(self):
|
||||
super(TestRma, self).setUp()
|
||||
|
||||
self.rma_make_picking = self.env['rma_make_picking.wizard']
|
||||
self.make_supplier_rma = self.env["rma.order.line.make.supplier.rma"]
|
||||
self.rma_add_stock_move = self.env['rma_add_stock_move']
|
||||
self.stockpicking = self.env['stock.picking']
|
||||
self.rma = self.env['rma.order']
|
||||
self.rma_line = self.env['rma.order.line']
|
||||
self.rma_op = self.env['rma.operation']
|
||||
self.rma_cust_replace_op_id = self.env.ref(
|
||||
'rma.rma_operation_customer_replace')
|
||||
self.rma_sup_replace_op_id = self.env.ref(
|
||||
'rma.rma_operation_supplier_replace')
|
||||
self.product_id = self.env.ref('product.product_product_4')
|
||||
self.product_id.product_tmpl_id.categ_id.\
|
||||
property_stock_account_input_categ_id =\
|
||||
self.env.ref('account.data_account_type_receivable').id
|
||||
self.product_id.product_tmpl_id.categ_id.\
|
||||
property_stock_account_output_categ_id =\
|
||||
self.env.ref('account.data_account_type_expenses').id
|
||||
self.product_1 = self.env.ref('product.product_product_25')
|
||||
self.product_2 = self.env.ref('product.product_product_7')
|
||||
self.product_3 = self.env.ref('product.product_product_11')
|
||||
self.uom_unit = self.env.ref('product.product_uom_unit')
|
||||
# assign an operation
|
||||
self.product_1.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_2.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_3.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.partner_id = self.env.ref('base.res_partner_12')
|
||||
self.stock_location = self.env.ref('stock.stock_location_stock')
|
||||
wh = self.env.ref('stock.warehouse0')
|
||||
self.stock_rma_location = wh.lot_rma_id
|
||||
self.customer_location = self.env.ref(
|
||||
'stock.stock_location_customers')
|
||||
self.supplier_location = self.env.ref(
|
||||
'stock.stock_location_suppliers')
|
||||
self.product_uom_id = self.env.ref('product.product_uom_unit')
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_customer_id = self._create_rma_from_move(
|
||||
products2move, 'customer', self.env.ref('base.res_partner_2'),
|
||||
dropship=False)
|
||||
|
||||
def _create_picking(self, partner):
|
||||
return self.stockpicking.create({
|
||||
'partner_id': partner.id,
|
||||
'picking_type_id': self.env.ref('stock.picking_type_in').id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.supplier_location.id
|
||||
})
|
||||
|
||||
def _create_rma_from_move(self, products2move, type, partner, dropship,
|
||||
supplier_address_id=None):
|
||||
picking_in = self._create_picking(partner)
|
||||
|
||||
moves = []
|
||||
if type == 'customer':
|
||||
for item in products2move:
|
||||
move_values = self._prepare_move(
|
||||
item[0], item[1], self.stock_location,
|
||||
self.customer_location, picking_in)
|
||||
moves.append(self.env['stock.move'].create(move_values))
|
||||
else:
|
||||
for item in products2move:
|
||||
move_values = self._prepare_move(
|
||||
item[0], item[1], self.supplier_location,
|
||||
self.stock_rma_location, picking_in)
|
||||
moves.append(self.env['stock.move'].create(move_values))
|
||||
# Create the RMA from the stock_move
|
||||
rma_id = self.rma.create(
|
||||
{
|
||||
'reference': '0001',
|
||||
'type': type,
|
||||
'partner_id': partner.id,
|
||||
'company_id': self.env.ref('base.main_company').id
|
||||
})
|
||||
rma_id._compute_invoice_refund_count()
|
||||
rma_id._compute_invoice_count()
|
||||
|
||||
data = {'add_invoice_id': self._create_invoice().id}
|
||||
new_line = self.rma.new(data)
|
||||
new_line.on_change_invoice()
|
||||
|
||||
rma_id.action_view_invoice_refund()
|
||||
rma_id.action_view_invoice()
|
||||
|
||||
for move in moves:
|
||||
if type == 'customer':
|
||||
wizard = self.rma_add_stock_move.new(
|
||||
{'stock_move_id': move.id, 'customer': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}
|
||||
)
|
||||
wizard.with_context({
|
||||
'stock_move_id': move.id, 'customer': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
})
|
||||
data = wizard.with_context(customer=1).\
|
||||
_prepare_rma_line_from_stock_move(move)
|
||||
data['partner_id'] = move.partner_id.id
|
||||
else:
|
||||
wizard = self.rma_add_stock_move.new(
|
||||
{'stock_move_id': move.id, 'supplier': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{'stock_move_id': move.id, 'supplier': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
})
|
||||
data = wizard._prepare_rma_line_from_stock_move(move)
|
||||
data['partner_id'] = move.partner_id.id
|
||||
if dropship:
|
||||
data.update(customer_to_supplier=dropship,
|
||||
supplier_address_id=supplier_address_id.id)
|
||||
data['partner_id'] = move.partner_id.id
|
||||
data['rma_id'] = rma_id.id
|
||||
self.line = self.rma_line.create(data)
|
||||
# approve the RMA Line
|
||||
self.line._compute_refund_count()
|
||||
self.rma_line.action_rma_to_approve()
|
||||
|
||||
self.line.action_rma_approve()
|
||||
self.line.action_view_invoice()
|
||||
self.line.action_view_refunds()
|
||||
|
||||
# approve the RMA
|
||||
# rma_id.action_rma_to_approve()
|
||||
# rma_id.action_rma_approve()
|
||||
return rma_id
|
||||
|
||||
def _prepare_move(self, product, qty, src, dest, picking_in):
|
||||
res = {
|
||||
'partner_id': self.partner_id.id,
|
||||
'product_id': product.id,
|
||||
'name': product.partner_ref,
|
||||
'state': 'confirmed',
|
||||
'product_uom': self.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
|
||||
|
||||
def test_rma_refund(self):
|
||||
|
||||
self.rma_refund_item = self.env['rma.refund.item']
|
||||
self.rma_refund = self.env['rma.refund']
|
||||
|
||||
self.product_id.income =\
|
||||
self.env.ref('account.data_account_type_receivable').id
|
||||
self.product_id.expense =\
|
||||
self.env.ref('account.data_account_type_expenses').id
|
||||
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
line.refund_policy = 'ordered'
|
||||
|
||||
refund = self.rma_refund.with_context({
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'active_id': 1
|
||||
}).create({'description': 'Test Reason',
|
||||
'date_invoice': fields.datetime.now()
|
||||
})
|
||||
self.rma_refund_item.create({
|
||||
'line_id': self.rma_customer_id.rma_line_ids[0].id,
|
||||
'rma_id': self.rma_customer_id.id,
|
||||
'product_id': self.product_id.id,
|
||||
'name': 'Test RMA Refund',
|
||||
'product_qty': self.rma_customer_id.rma_line_ids[0].product_qty,
|
||||
'wiz_id': refund.id
|
||||
})
|
||||
refund.invoice_refund()
|
||||
|
||||
data = {'invoice_line_id': self._create_invoice().invoice_line_ids.id}
|
||||
new_line = self.rma_line.new(data)
|
||||
new_line._onchange_invoice_line_id()
|
||||
self.rma_customer_id.action_view_invoice_refund()
|
||||
self.rma_customer_id.action_view_invoice()
|
||||
|
||||
def test_on_change_invoice_rma(self):
|
||||
|
||||
wizard = self.env['rma_add_invoice'].with_context({
|
||||
'active_ids': self.rma_customer_id.ids,
|
||||
'active_model': 'rma.order',
|
||||
'active_id': self.rma_customer_id.id
|
||||
}).create({'partner_id': self.partner_id.id,
|
||||
'rma_id': self.rma_customer_id.id,
|
||||
'invoice_line_ids':
|
||||
[(6, 0, [self._create_invoice().invoice_line_ids.id])],
|
||||
})
|
||||
wizard.default_get([str(self._create_invoice().id),
|
||||
str(self._create_invoice().invoice_line_ids.id),
|
||||
str(self.partner_id.id)])
|
||||
wizard.add_lines()
|
||||
self.rma_customer_id.action_view_invoice_refund()
|
||||
self.rma_customer_id.action_view_invoice()
|
||||
self.rma_customer_id.rma_line_ids[0].\
|
||||
invoice_id = self._create_invoice().id
|
||||
self.rma_customer_id.action_view_invoice()
|
||||
self.rma_customer_id.add_invoice_id = self._create_invoice().id
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
line.invoice_id.action_view_rma_supplier()
|
||||
line.invoice_id.action_view_rma_customer()
|
||||
|
||||
def _create_invoice(self):
|
||||
self.Account = self.env['account.account']
|
||||
self.AccountInvoice = self.env['account.invoice']
|
||||
self.AccountInvoiceLine = self.env['account.invoice.line']
|
||||
|
||||
self.account_receivable =\
|
||||
self.env.ref('account.data_account_type_receivable')
|
||||
self.account_expenses =\
|
||||
self.env.ref('account.data_account_type_expenses')
|
||||
invoice_account = self.Account.\
|
||||
search([('user_type_id', '=', self.account_receivable.id)], limit=1
|
||||
).id
|
||||
invoice_line_account = self.Account.\
|
||||
search([('user_type_id', '=', self.account_expenses.id)], limit=1
|
||||
).id
|
||||
|
||||
invoice = self.AccountInvoice.create({
|
||||
'partner_id': self.partner_id.id,
|
||||
'account_id': invoice_account,
|
||||
'type': 'in_invoice',
|
||||
})
|
||||
|
||||
invoice_line = self.AccountInvoiceLine.create({
|
||||
'product_id': self.product_1.id,
|
||||
'quantity': 1.0,
|
||||
'price_unit': 100.0,
|
||||
'invoice_id': invoice.id,
|
||||
'uom_id': 1,
|
||||
'name': 'product that cost 100',
|
||||
'account_id': invoice_line_account,
|
||||
})
|
||||
invoice._compute_rma_count()
|
||||
invoice_line._compute_rma_count()
|
||||
invoice.action_view_rma_customer()
|
||||
invoice.action_view_rma_supplier()
|
||||
return invoice
|
||||
|
||||
def test_customer_rma(self):
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'incoming',
|
||||
'active_id': 1
|
||||
}).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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 3,
|
||||
"Wrong qty incoming")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 5,
|
||||
"Wrong qty incoming")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 2,
|
||||
"Wrong qty incoming")
|
||||
picking.action_assign()
|
||||
picking.do_transfer()
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_receive, 0,
|
||||
"Wrong qty to_receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 3,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to_deliver")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to_deliver")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to_deliver")
|
||||
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'outgoing',
|
||||
}).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))]
|
||||
pickings = self.stockpicking.search(domain)
|
||||
self.assertEquals(len(pickings), 2,
|
||||
"Incorrect number of pickings created")
|
||||
picking_out = pickings[1]
|
||||
moves = picking_out.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_receive, 0,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 3,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_received, 3,
|
||||
"Wrong qty received")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 5,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 2,
|
||||
"Wrong qty outgoing")
|
||||
picking_out.action_assign()
|
||||
picking_out.do_transfer()
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_receive, 0,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 3,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 3,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 5,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 2,
|
||||
"Wrong qty delivered")
|
||||
self.line.action_rma_done()
|
||||
self.assertEquals(self.line.state, 'done',
|
||||
"Wrong State")
|
||||
211
rma_account/tests/test_rma_account.py
Normal file
211
rma_account/tests/test_rma_account.py
Normal file
@@ -0,0 +1,211 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestRmaAccount(common.SingleTransactionCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestRmaAccount, cls).setUpClass()
|
||||
|
||||
cls.rma_obj = cls.env['rma.order']
|
||||
cls.rma_line_obj = cls.env['rma.order.line']
|
||||
cls.rma_op_obj = cls.env['rma.operation']
|
||||
cls.rma_add_invoice_wiz = cls.env['rma_add_invoice']
|
||||
cls.rma_refund_wiz = cls.env['rma.refund']
|
||||
cls.acc_obj = cls.env['account.account']
|
||||
cls.inv_obj = cls.env['account.invoice']
|
||||
cls.invl_obj = cls.env['account.invoice.line']
|
||||
cls.product_obj = cls.env['product.product']
|
||||
cls.partner_obj = cls.env['res.partner']
|
||||
|
||||
cls.rma_route_cust = cls.env.ref('rma.route_rma_customer')
|
||||
receivable_type = cls.env.ref('account.data_account_type_receivable')
|
||||
payable_type = cls.env.ref('account.data_account_type_payable')
|
||||
cls.cust_refund_op = cls.env.ref(
|
||||
'rma_account.rma_operation_customer_refund')
|
||||
|
||||
# Create partners
|
||||
customer1 = cls.partner_obj.create({'name': 'Customer 1'})
|
||||
supplier1 = cls.partner_obj.create({'name': 'Supplier 1'})
|
||||
|
||||
# Create RMA group and operation:
|
||||
cls.rma_group_customer = cls.rma_obj.create({
|
||||
'partner_id': customer1.id,
|
||||
'type': 'customer',
|
||||
})
|
||||
cls.rma_group_supplier = cls.rma_obj.create({
|
||||
'partner_id': supplier1.id,
|
||||
'type': 'supplier',
|
||||
})
|
||||
cls.operation_1 = cls.rma_op_obj.create({
|
||||
'code': 'TEST',
|
||||
'name': 'Refund and receive',
|
||||
'type': 'customer',
|
||||
'receipt_policy': 'ordered',
|
||||
'refund_policy': 'ordered',
|
||||
'in_route_id': cls.rma_route_cust.id,
|
||||
'out_route_id': cls.rma_route_cust.id,
|
||||
})
|
||||
|
||||
# Create products
|
||||
cls.product_1 = cls.product_obj.create({
|
||||
'name': 'Test Product 1',
|
||||
'type': 'product',
|
||||
'list_price': 100.0,
|
||||
'rma_customer_operation_id': cls.cust_refund_op.id,
|
||||
})
|
||||
cls.product_2 = cls.product_obj.create({
|
||||
'name': 'Test Product 2',
|
||||
'type': 'product',
|
||||
'list_price': 150.0,
|
||||
'rma_customer_operation_id': cls.operation_1.id,
|
||||
})
|
||||
cls.product_3 = cls.product_obj.create({
|
||||
'name': 'Test Product 3',
|
||||
'type': 'product',
|
||||
})
|
||||
cls.product_4 = cls.product_obj.create({
|
||||
'name': 'Test Product 4',
|
||||
'type': 'product',
|
||||
})
|
||||
|
||||
# Create Invoices:
|
||||
customer_account = cls.acc_obj. search(
|
||||
[('user_type_id', '=', receivable_type.id)], limit=1).id
|
||||
cls.inv_customer = cls.inv_obj.create({
|
||||
'partner_id': customer1.id,
|
||||
'account_id': customer_account,
|
||||
'type': 'out_invoice',
|
||||
})
|
||||
cls.inv_line_1 = cls.invl_obj.create({
|
||||
'name': cls.product_1.name,
|
||||
'product_id': cls.product_1.id,
|
||||
'quantity': 12.0,
|
||||
'price_unit': 100.0,
|
||||
'invoice_id': cls.inv_customer.id,
|
||||
'uom_id': cls.product_1.uom_id.id,
|
||||
'account_id': customer_account,
|
||||
})
|
||||
cls.inv_line_2 = cls.invl_obj.create({
|
||||
'name': cls.product_2.name,
|
||||
'product_id': cls.product_2.id,
|
||||
'quantity': 15.0,
|
||||
'price_unit': 150.0,
|
||||
'invoice_id': cls.inv_customer.id,
|
||||
'uom_id': cls.product_2.uom_id.id,
|
||||
'account_id': customer_account,
|
||||
})
|
||||
|
||||
supplier_account = cls.acc_obj.search(
|
||||
[('user_type_id', '=', payable_type.id)], limit=1).id
|
||||
cls.inv_supplier = cls.inv_obj.create({
|
||||
'partner_id': supplier1.id,
|
||||
'account_id': supplier_account,
|
||||
'type': 'in_invoice',
|
||||
})
|
||||
cls.inv_line_3 = cls.invl_obj.create({
|
||||
'name': cls.product_3.name,
|
||||
'product_id': cls.product_3.id,
|
||||
'quantity': 17.0,
|
||||
'price_unit': 250.0,
|
||||
'invoice_id': cls.inv_supplier.id,
|
||||
'uom_id': cls.product_3.uom_id.id,
|
||||
'account_id': supplier_account,
|
||||
})
|
||||
cls.inv_line_4 = cls.invl_obj.create({
|
||||
'name': cls.product_4.name,
|
||||
'product_id': cls.product_4.id,
|
||||
'quantity': 9.0,
|
||||
'price_unit': 300.0,
|
||||
'invoice_id': cls.inv_supplier.id,
|
||||
'uom_id': cls.product_4.uom_id.id,
|
||||
'account_id': supplier_account,
|
||||
})
|
||||
|
||||
def test_01_add_from_invoice_customer(self):
|
||||
"""Test wizard to create RMA from a customer invoice."""
|
||||
add_inv = self.rma_add_invoice_wiz.with_context({
|
||||
'customer': True,
|
||||
'active_ids': self.rma_group_customer.id,
|
||||
'active_model': 'rma.order',
|
||||
}).create({
|
||||
'invoice_line_ids':
|
||||
[(6, 0, self.inv_customer.invoice_line_ids.ids)],
|
||||
})
|
||||
add_inv.add_lines()
|
||||
self.assertEqual(len(self.rma_group_customer.rma_line_ids), 2)
|
||||
for t in self.rma_group_supplier.rma_line_ids.mapped('type'):
|
||||
self.assertEqual(t, 'customer')
|
||||
rma_1 = self.rma_group_customer.rma_line_ids.filtered(
|
||||
lambda r: r.product_id == self.product_1)
|
||||
self.assertEqual(rma_1.operation_id, self.cust_refund_op)
|
||||
rma_2 = self.rma_group_customer.rma_line_ids.filtered(
|
||||
lambda r: r.product_id == self.product_2)
|
||||
self.assertEqual(rma_2.operation_id, self.operation_1)
|
||||
|
||||
def test_02_add_from_invoice_supplier(self):
|
||||
"""Test wizard to create RMA from a vendor bill."""
|
||||
add_inv = self.rma_add_invoice_wiz.with_context({
|
||||
'supplier': True,
|
||||
'active_ids': self.rma_group_supplier.id,
|
||||
'active_model': 'rma.order',
|
||||
}).create({
|
||||
'invoice_line_ids':
|
||||
[(6, 0, self.inv_supplier.invoice_line_ids.ids)],
|
||||
})
|
||||
add_inv.add_lines()
|
||||
self.assertEqual(len(self.rma_group_supplier.rma_line_ids), 2)
|
||||
for t in self.rma_group_supplier.rma_line_ids.mapped('type'):
|
||||
self.assertEqual(t, 'supplier')
|
||||
|
||||
def test_03_rma_refund_operation(self):
|
||||
"""Test RMA quantities using refund operations."""
|
||||
# Received refund_policy:
|
||||
rma_1 = self.rma_group_customer.rma_line_ids.filtered(
|
||||
lambda r: r.product_id == self.product_1)
|
||||
self.assertEqual(rma_1.refund_policy, 'received')
|
||||
self.assertEqual(rma_1.qty_to_refund, 0.0)
|
||||
# TODO: receive and check qty_to_refund is 12.0
|
||||
# Ordered refund_policy:
|
||||
rma_2 = self.rma_group_customer.rma_line_ids.filtered(
|
||||
lambda r: r.product_id == self.product_2)
|
||||
rma_2._onchange_operation_id()
|
||||
self.assertEqual(rma_2.refund_policy, 'ordered')
|
||||
self.assertEqual(rma_2.qty_to_refund, 15.0)
|
||||
|
||||
def test_04_rma_create_refund(self):
|
||||
"""Generate a Refund from a customer RMA."""
|
||||
rma = self.rma_group_customer.rma_line_ids.filtered(
|
||||
lambda r: r.product_id == self.product_2)
|
||||
rma.action_rma_to_approve()
|
||||
rma.action_rma_approve()
|
||||
self.assertEqual(rma.refund_count, 0)
|
||||
self.assertEqual(rma.qty_to_refund, 15.0)
|
||||
self.assertEqual(rma.qty_refunded, 0.0)
|
||||
make_refund = self.rma_refund_wiz.with_context({
|
||||
'customer': True,
|
||||
'active_ids': rma.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
}).create({
|
||||
'description': 'Test refund',
|
||||
})
|
||||
make_refund.invoice_refund()
|
||||
rma.refund_line_ids.invoice_id.invoice_validate()
|
||||
self.assertEqual(rma.refund_count, 1)
|
||||
self.assertEqual(rma.qty_to_refund, 0.0)
|
||||
self.assertEqual(rma.qty_refunded, 15.0)
|
||||
|
||||
def test_05_fill_rma_from_inv_line(self):
|
||||
"""Test filling a RMA (line) from a invoice line."""
|
||||
rma = self.rma_line_obj.new({
|
||||
'partner_id': self.inv_customer.partner_id.id,
|
||||
'invoice_line_id': self.inv_line_1.id,
|
||||
})
|
||||
self.assertFalse(rma.product_id)
|
||||
rma._onchange_invoice_line_id()
|
||||
self.assertEqual(rma.product_id, self.product_1)
|
||||
self.assertEqual(rma.product_qty, 12.0)
|
||||
@@ -1,108 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp.addons.rma.tests import test_rma
|
||||
|
||||
|
||||
class TestRmaDropship(test_rma.TestRma):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRmaDropship, self).setUp()
|
||||
self.product_id.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_1.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_2.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_3.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_droship_id = self._create_rma_from_move(
|
||||
products2move, 'customer', self.env.ref('base.res_partner_2'),
|
||||
dropship=True,
|
||||
supplier_address_id=self.env.ref('base.res_partner_3'))
|
||||
|
||||
def test_dropship(self):
|
||||
wizard = self.make_supplier_rma.with_context({
|
||||
'active_ids': self.rma_droship_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'active_id': 1
|
||||
}).create({})
|
||||
res = wizard.make_supplier_rma()
|
||||
supplier_rma = self.rma.browse(res['res_id'])
|
||||
for line in supplier_rma.rma_line_ids:
|
||||
line.action_rma_to_approve()
|
||||
line.action_rma_approve()
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': supplier_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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in supplier_rma.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_incoming, 3,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_incoming, 5,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_incoming, 2,
|
||||
"Wrong qty outgoing")
|
||||
|
||||
for line in self.rma_droship_id.rma_line_ids:
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 3,
|
||||
"Wrong qty in supplier rma")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 5,
|
||||
"Wrong qty in supplier rma")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 2,
|
||||
"Wrong qty in supplier rma")
|
||||
for line in self.rma_droship_id.rma_line_ids:
|
||||
line.action_rma_done()
|
||||
self.assertEquals(line.state, 'done',
|
||||
"Wrong State")
|
||||
@@ -1,156 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp.addons.rma.tests import test_rma
|
||||
|
||||
|
||||
class TestSupplierRma(test_rma.TestRma):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSupplierRma, self).setUp()
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_supplier_id = self._create_rma_from_move(
|
||||
products2move, 'supplier', self.env.ref('base.res_partner_1'),
|
||||
dropship=False)
|
||||
|
||||
def test_supplier_rma(self):
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_supplier_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'outgoing',
|
||||
'active_id': 1
|
||||
}).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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 3,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 5,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 2,
|
||||
"Wrong qty outgoing")
|
||||
|
||||
picking.action_assign()
|
||||
picking.do_transfer()
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_delivered, 3,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': self.rma_supplier_id.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))]
|
||||
pickings = self.stockpicking.search(domain)
|
||||
self.assertEquals(len(pickings), 2,
|
||||
"Incorrect number of pickings created")
|
||||
picking_out = pickings[1]
|
||||
moves = picking_out.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 3,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
picking_out.action_assign()
|
||||
picking_out.do_transfer()
|
||||
for line in self.rma_supplier_id.rma_line_ids[0]:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 6,
|
||||
"Wrong qty deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 6,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 5,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 2,
|
||||
"Wrong qty delivered")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
line.action_rma_done()
|
||||
self.assertEquals(line.state, 'done',
|
||||
"Wrong State")
|
||||
@@ -62,6 +62,48 @@
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<record id="view_invoice_supplier_rma_form" model="ir.ui.view">
|
||||
<field name="name">account.invoice.supplier.rma</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="add_rma_line_id"
|
||||
context="{'rma': True}"
|
||||
domain="[('type', '=', 'supplier'),
|
||||
('partner_id', '=', partner_id)]"
|
||||
attrs="{'readonly': [('state','not in',['draft'])],
|
||||
'invisible': ['|', ('state', '=', 'done'),
|
||||
('type', '=', 'in_invoice')]}" class="oe_edit_only"
|
||||
options="{'no_create': True}"/>
|
||||
</field>
|
||||
<xpath expr="//sheet/notebook/page/field[@name='invoice_line_ids']/tree" position="inside">
|
||||
<field name="rma_line_id" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_invoice_customer_rma_form" model="ir.ui.view">
|
||||
<field name="name">account.invoice.customer.rma</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="payment_term_id" position="after">
|
||||
<field name="add_rma_line_id"
|
||||
context="{'rma': True}"
|
||||
domain="[('type', '=', 'customer'),
|
||||
('partner_id', '=', partner_id)]"
|
||||
attrs="{'readonly': [('state','not in',['draft'])],
|
||||
'invisible': ['|', ('state', '=', 'done'),
|
||||
('type', '=', 'out_invoice')]}" class="oe_edit_only"
|
||||
options="{'no_create': True}"/>
|
||||
</field>
|
||||
<xpath expr="//sheet/notebook/page/field[@name='invoice_line_ids']/tree" position="inside">
|
||||
<field name="rma_line_id" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_invoice_line" model="ir.actions.act_window">
|
||||
<field name="name">Invoice Line</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
|
||||
39
rma_account/views/rma_account_menu.xml
Normal file
39
rma_account/views/rma_account_menu.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
|
||||
<odoo>
|
||||
|
||||
<record id="action_rma_account_customer_lines" model="ir.actions.act_window">
|
||||
<field name="name">Customer RMA</field>
|
||||
<field name="res_model">rma.order.line</field>
|
||||
<field name="domain">[('type','=', 'customer')]</field>
|
||||
<field name="context">{"search_default_to_refund":1}</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_supplier_lines" model="ir.actions.act_window">
|
||||
<field name="name">Supplier RMA</field>
|
||||
<field name="res_model">rma.order.line</field>
|
||||
<field name="domain">[('type','=', 'supplier')]</field>
|
||||
<field name="context">{"search_default_to_refund":1, "supplier":1}</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="rma.view_rma_line_supplier_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_rma_line_account_customer"
|
||||
name="Customer RMA to Refund"
|
||||
sequence="20"
|
||||
parent="account.menu_finance_receivables"
|
||||
groups="rma.group_rma_customer_user"
|
||||
action="action_rma_account_customer_lines"/>
|
||||
|
||||
<menuitem id="menu_rma_line_account_supplier"
|
||||
name="Supplier RMA to Refund"
|
||||
sequence="20"
|
||||
parent="account.menu_finance_payables"
|
||||
groups="rma.group_rma_supplier_user"
|
||||
action="action_rma_supplier_lines"/>
|
||||
|
||||
</odoo>
|
||||
@@ -17,8 +17,8 @@
|
||||
</button>
|
||||
<group name="main_info" position="inside">
|
||||
<field name="invoice_line_id"
|
||||
context="{'rma': True}"
|
||||
options="{'no_create': True}"
|
||||
context="{'rma': True}"
|
||||
domain="['|',
|
||||
('invoice_id.partner_id', '=', partner_id),
|
||||
('invoice_id.partner_id', 'child_of', partner_id)]"/>
|
||||
@@ -33,6 +33,8 @@
|
||||
</page>
|
||||
<field name="delivery_address_id" position="after">
|
||||
<field name="invoice_address_id"
|
||||
domain="['|', ('parent_id', '=', partner_id),
|
||||
('id', '=', partner_id)]"
|
||||
groups='rma.group_rma_delivery_invoice_address'/>
|
||||
</field>
|
||||
<group name="deliver" position="after">
|
||||
@@ -50,21 +52,23 @@
|
||||
<field name="inherit_id" ref="rma.view_rma_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_view_out_shipments" position="after">
|
||||
<button type="object" name="action_view_refunds"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o"
|
||||
groups="account.group_account_user">
|
||||
<field name="refund_count" widget="statinfo"
|
||||
string="Refunds"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_invoice"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o"
|
||||
string="Origin Inv">
|
||||
</button>
|
||||
<button type="object" name="action_view_refunds"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o"
|
||||
groups="account.group_account_user">
|
||||
<field name="refund_count" widget="statinfo"
|
||||
string="Refunds"/>
|
||||
</button>
|
||||
</button>
|
||||
<group name="main_info" position="inside">
|
||||
<field name="invoice_line_id"
|
||||
context="{'rma': True}"
|
||||
options="{'no_create': True}"
|
||||
domain="['|',
|
||||
('invoice_id.partner_id', '=', partner_id),
|
||||
('invoice_id.partner_id', 'child_of', partner_id)]"/>
|
||||
options="{'no_create': True}"/>
|
||||
</group>
|
||||
<field name="operation_id" position="after">
|
||||
<field name="refund_policy"/>
|
||||
@@ -76,6 +80,8 @@
|
||||
</page>
|
||||
<field name="delivery_address_id" position="after">
|
||||
<field name="invoice_address_id"
|
||||
domain="['|', ('parent_id', '=', partner_id),
|
||||
('id', '=', partner_id)]"
|
||||
groups='rma.group_rma_delivery_invoice_address'/>
|
||||
</field>
|
||||
<group name="supplier_rma" position="after">
|
||||
@@ -90,12 +96,17 @@
|
||||
<record id="view_rma_rma_line_filter" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.select</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="inherit_id" ref="rma.view_rma_line_form"/>
|
||||
<field name="inherit_id" ref="rma.view_rma_rma_line_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_id" position="after">
|
||||
<filter name="to_refund" string="To Refund" domain="[('qty_to_refund', '>', 0)]"
|
||||
context="{'group_by':'partner_id'}"/>
|
||||
</field>
|
||||
<group name="stock_quantities" position="after">
|
||||
<group name="account_quantities" groups="account.group_account_user">
|
||||
<filter name="to_refund" domain="[('state','!=', 'done'),('qty_to_refund','>',0.0)]" help="To Refund"/>
|
||||
</group>
|
||||
</group>
|
||||
<filter name="to_deliver" position="after">
|
||||
<filter name="group_to_refund" string="To Refund" domain="[('qty_to_refund', '>', 0)]"
|
||||
context="{'group_by':'partner_id'}"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -90,10 +90,6 @@ class RmaAddInvoice(models.TransientModel):
|
||||
def _get_rma_data(self):
|
||||
data = {
|
||||
'date_rma': fields.Datetime.now(),
|
||||
'delivery_address_id':
|
||||
self.invoice_line_ids[0].invoice_id.partner_id.id,
|
||||
'invoice_address_id':
|
||||
self.invoice_line_ids[0].invoice_id.partner_id.id
|
||||
}
|
||||
return data
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</group>
|
||||
<separator string="Select Invoices lines to add"/>
|
||||
<field name="invoice_line_ids"
|
||||
domain="[('invoice_id.partner_id', '=', partner_id),
|
||||
domain="[('invoice_id.commercial_partner_id', 'child_of', partner_id),
|
||||
('invoice_id.type', '=', 'out_invoice')]">
|
||||
<tree string="Invoice Lines">
|
||||
<field name="invoice_id"/>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tools.safe_eval import safe_eval as eval
|
||||
from odoo.tools.safe_eval import safe_eval as seval
|
||||
import odoo.addons.decimal_precision as dp
|
||||
|
||||
|
||||
@@ -19,16 +19,17 @@ class RmaRefund(models.TransientModel):
|
||||
|
||||
@api.returns('rma.order.line')
|
||||
def _prepare_item(self, line):
|
||||
values = {'product_id': line.product_id.id,
|
||||
'name': line.name,
|
||||
'product_qty': line.product_qty,
|
||||
'uom_id': line.uom_id.id,
|
||||
'qty_to_refund': line.qty_to_refund,
|
||||
'refund_policy': line.refund_policy,
|
||||
'invoice_address_id': line.invoice_address_id.id,
|
||||
'line_id': line.id,
|
||||
'rma_id': line.rma_id.id,
|
||||
'wiz_id': self.env.context['active_id']}
|
||||
values = {
|
||||
'product_id': line.product_id.id,
|
||||
'name': line.name,
|
||||
'product_qty': line.product_qty,
|
||||
'uom_id': line.uom_id.id,
|
||||
'qty_to_refund': line.qty_to_refund,
|
||||
'refund_policy': line.refund_policy,
|
||||
'invoice_address_id': line.invoice_address_id.id,
|
||||
'line_id': line.id,
|
||||
'rma_id': line.rma_id.id,
|
||||
}
|
||||
return values
|
||||
|
||||
@api.model
|
||||
@@ -97,7 +98,7 @@ class RmaRefund(models.TransientModel):
|
||||
new_invoice.type in ['out_refund', 'out_invoice']) \
|
||||
else 'action_invoice_tree2'
|
||||
result = self.env.ref('account.%s' % action).read()[0]
|
||||
invoice_domain = eval(result['domain'])
|
||||
invoice_domain = seval(result['domain'])
|
||||
invoice_domain.append(('id', '=', new_invoice.id))
|
||||
result['domain'] = invoice_domain
|
||||
return result
|
||||
@@ -204,5 +205,6 @@ class RmaRefundItem(models.TransientModel):
|
||||
readonly=True)
|
||||
refund_policy = fields.Selection(selection=[
|
||||
('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'),
|
||||
('delivered', 'Based on Delivered Quantities'),
|
||||
('received', 'Based on Received Quantities')],
|
||||
string="Refund Policy")
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
"license": "LGPL-3",
|
||||
"website": "http://www.eficent.com",
|
||||
"category": "Analytic",
|
||||
"depends": ["rma_account", "rma_analytic", "stock_analytic_account"],
|
||||
"depends": ["rma_account", "rma_analytic"],
|
||||
"data": [
|
||||
],
|
||||
'installable': True,
|
||||
'installable': False,
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
from odoo import _, api, exceptions, models
|
||||
|
||||
|
||||
class AccountInvocieLine(models.Model):
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = "account.invoice.line"
|
||||
|
||||
@api.constrains('analytic_account_id')
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
"license": "LGPL-3",
|
||||
"website": "http://www.eficent.com",
|
||||
"category": "Analytic",
|
||||
"depends": ["rma", "analytic", "procurement_analytic",
|
||||
'stock_analytic_account'],
|
||||
"depends": ["rma", "procurement_analytic", "stock_analytic"],
|
||||
"data": [
|
||||
"views/rma_order_line_view.xml"
|
||||
],
|
||||
'installable': True,
|
||||
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ class ProcurementOrder(models.Model):
|
||||
|
||||
_inherit = "procurement.order"
|
||||
|
||||
@api.constrains('analytic_account_id')
|
||||
@api.constrains('account_analytic_id')
|
||||
def check_analytic(self):
|
||||
for order in self:
|
||||
if (order.analytic_account_id !=
|
||||
if (order.account_analytic_id !=
|
||||
order.rma_line_id.analytic_account_id):
|
||||
raise exceptions.ValidationError(
|
||||
_("The analytic account in the procurement it's not the "
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# © 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class RmaOrderLine(models.Model):
|
||||
@@ -13,3 +13,14 @@ class RmaOrderLine(models.Model):
|
||||
comodel_name='account.analytic.account',
|
||||
string='Analytic Account',
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def _prepare_rma_line_from_inv_line(self, line):
|
||||
res = super(
|
||||
RmaOrderLine, self
|
||||
)._prepare_rma_line_from_inv_line(line)
|
||||
if line.account_analytic_id:
|
||||
res.update(
|
||||
analytic_account_id=line.account_analytic_id.id
|
||||
)
|
||||
return res
|
||||
|
||||
@@ -7,26 +7,244 @@ from odoo.addons.rma.tests import test_rma
|
||||
|
||||
class TestRmaAnalytic(test_rma.TestRma):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRmaAnalytic, self).setUp()
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_ana_id = self._create_rma_from_move(
|
||||
products2move, 'supplier', self.env.ref('base.res_partner_1'),
|
||||
dropship=False)
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestRmaAnalytic, cls).setUpClass()
|
||||
cls.rma_add_invoice_wiz = cls.env["rma_add_invoice"]
|
||||
cls.rma_refund_wiz = cls.env["rma.refund"]
|
||||
products2move = [
|
||||
(cls.product_1, 3),
|
||||
(cls.product_2, 5),
|
||||
(cls.product_3, 2),
|
||||
]
|
||||
cls.rma_add_invoice_wiz = cls.env["rma_add_invoice"]
|
||||
cls.rma_ana_id = cls._create_rma_from_move(
|
||||
products2move,
|
||||
"supplier",
|
||||
cls.env.ref("base.res_partner_2"),
|
||||
dropship=False,
|
||||
)
|
||||
receivable_type = cls.env.ref(
|
||||
"account.data_account_type_receivable"
|
||||
)
|
||||
# Create Invoices:
|
||||
customer_account = (
|
||||
cls.env["account.account"]
|
||||
.search(
|
||||
[("user_type_id", "=", receivable_type.id)], limit=1
|
||||
)
|
||||
.id
|
||||
)
|
||||
cls.inv_customer = cls.env["account.invoice"].create(
|
||||
{
|
||||
"partner_id": cls.partner_id.id,
|
||||
"account_id": customer_account,
|
||||
"type": "out_invoice",
|
||||
}
|
||||
)
|
||||
cls.anal = cls.env["account.analytic.account"].create(
|
||||
{"name": "Name"}
|
||||
)
|
||||
cls.inv_line_1 = cls.env["account.invoice.line"].create(
|
||||
{
|
||||
"name": cls.partner_id.name,
|
||||
"product_id": cls.product_1.id,
|
||||
"quantity": 12.0,
|
||||
"price_unit": 100.0,
|
||||
"account_analytic_id": cls.anal.id,
|
||||
"invoice_id": cls.inv_customer.id,
|
||||
"uom_id": cls.product_1.uom_id.id,
|
||||
"account_id": customer_account,
|
||||
}
|
||||
)
|
||||
|
||||
def _prepare_move(self, product, qty, src, dest, picking_in):
|
||||
res = super(TestRmaAnalytic, self)._prepare_move(
|
||||
product, qty, src, dest, picking_in)
|
||||
analytic_1 = self.env['account.analytic.account'].create({
|
||||
'name': 'Test account #1',
|
||||
})
|
||||
res.update({'analytic_account_id': analytic_1.id})
|
||||
@classmethod
|
||||
def _prepare_move(cls, product, qty, src, dest, picking_in):
|
||||
res = super(TestRmaAnalytic, cls)._prepare_move(
|
||||
product, qty, src, dest, picking_in
|
||||
)
|
||||
analytic_1 = cls.env["account.analytic.account"].create(
|
||||
{"name": "Test account #1"}
|
||||
)
|
||||
res.update({"analytic_account_id": analytic_1.id})
|
||||
return res
|
||||
|
||||
@classmethod
|
||||
def _create_rma_analytic(cls, products2move, partner):
|
||||
picking_in = cls._create_picking(partner)
|
||||
moves = []
|
||||
for item in products2move:
|
||||
move_values = cls._prepare_anal_move(
|
||||
item[0],
|
||||
item[1],
|
||||
cls.stock_location,
|
||||
cls.customer_location,
|
||||
picking_in,
|
||||
cls.analytic_1,
|
||||
)
|
||||
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()
|
||||
|
||||
if move.product_id.rma_customer_operation_id:
|
||||
move.product_id.rma_customer_operation_id.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 test_analytic(self):
|
||||
for line in self.rma_ana_id.rma_line_ids:
|
||||
for move in line.move_ids:
|
||||
self.assertEqual(
|
||||
line.analytic_account_id, move.analytic_account_id,
|
||||
"the analytic account is not propagated")
|
||||
line.analytic_account_id,
|
||||
move.analytic_account_id,
|
||||
"the analytic account is not propagated",
|
||||
)
|
||||
|
||||
def test_invoice_analytic(self):
|
||||
"""Test wizard to create RMA from a customer invoice."""
|
||||
rma_line = (
|
||||
self.env["rma.order.line"]
|
||||
.with_context(customer=True)
|
||||
.new(
|
||||
{
|
||||
"partner_id": self.partner_id.id,
|
||||
"product_id": self.product_1.id,
|
||||
"operation_id": self.env.ref(
|
||||
"rma.rma_operation_customer_replace"
|
||||
).id,
|
||||
"in_route_id": self.env.ref(
|
||||
"rma.route_rma_customer"
|
||||
),
|
||||
"out_route_id": self.env.ref(
|
||||
"rma.route_rma_customer"
|
||||
),
|
||||
"in_warehouse_id": self.env.ref(
|
||||
"stock.warehouse0"
|
||||
),
|
||||
"out_warehouse_id": self.env.ref(
|
||||
"stock.warehouse0"
|
||||
),
|
||||
"location_id": self.env.ref(
|
||||
"stock.stock_location_stock"
|
||||
),
|
||||
"type": "customer",
|
||||
"invoice_line_id": self.inv_line_1.id,
|
||||
"uom_id": self.product_1.uom_id.id,
|
||||
}
|
||||
)
|
||||
)
|
||||
rma_line._onchange_invoice_line_id()
|
||||
self.assertEqual(
|
||||
rma_line.analytic_account_id,
|
||||
self.inv_line_1.account_analytic_id,
|
||||
)
|
||||
|
||||
def test_invoice_analytic02(self):
|
||||
self.product_1.rma_customer_operation_id = self.env.ref(
|
||||
"rma.rma_operation_customer_replace"
|
||||
).id
|
||||
rma_order = (
|
||||
self.env["rma.order"]
|
||||
.with_context(customer=True)
|
||||
.create(
|
||||
{
|
||||
"name": "RMA",
|
||||
"partner_id": self.partner_id.id,
|
||||
"type": "customer",
|
||||
"rma_line_ids": [],
|
||||
}
|
||||
)
|
||||
)
|
||||
add_inv = self.rma_add_invoice_wiz.with_context(
|
||||
{
|
||||
"customer": True,
|
||||
"active_ids": [rma_order.id],
|
||||
"active_model": "rma.order",
|
||||
}
|
||||
).create(
|
||||
{
|
||||
"invoice_line_ids": [
|
||||
(6, 0, self.inv_customer.invoice_line_ids.ids)
|
||||
]
|
||||
}
|
||||
)
|
||||
add_inv.add_lines()
|
||||
|
||||
self.assertEqual(
|
||||
rma_order.mapped("rma_line_ids.analytic_account_id"),
|
||||
self.inv_line_1.account_analytic_id,
|
||||
)
|
||||
|
||||
def test_refund_analytic(self):
|
||||
self.product_1.rma_customer_operation_id = self.env.ref(
|
||||
"rma_account.rma_operation_customer_refund"
|
||||
).id
|
||||
rma_line = (
|
||||
self.env["rma.order.line"]
|
||||
.with_context(customer=True)
|
||||
.create(
|
||||
{
|
||||
"partner_id": self.partner_id.id,
|
||||
"product_id": self.product_1.id,
|
||||
"operation_id": self.env.ref(
|
||||
"rma_account.rma_operation_customer_refund"
|
||||
).id,
|
||||
"in_route_id": self.env.ref(
|
||||
"rma.route_rma_customer"
|
||||
).id,
|
||||
"out_route_id": self.env.ref(
|
||||
"rma.route_rma_customer"
|
||||
).id,
|
||||
"in_warehouse_id": self.env.ref(
|
||||
"stock.warehouse0"
|
||||
).id,
|
||||
"out_warehouse_id": self.env.ref(
|
||||
"stock.warehouse0"
|
||||
).id,
|
||||
"location_id": self.env.ref(
|
||||
"stock.stock_location_stock"
|
||||
).id,
|
||||
"type": "customer",
|
||||
"invoice_line_id": self.inv_line_1.id,
|
||||
"delivery_policy": "no",
|
||||
"receipt_policy": "ordered",
|
||||
"uom_id": self.product_1.uom_id.id,
|
||||
}
|
||||
)
|
||||
)
|
||||
rma_line._onchange_invoice_line_id()
|
||||
rma_line.action_rma_to_approve()
|
||||
rma_line.action_rma_approve()
|
||||
make_refund = self.rma_refund_wiz.with_context(
|
||||
{
|
||||
"customer": True,
|
||||
"active_ids": rma_line.ids,
|
||||
"active_model": "rma.order.line",
|
||||
}
|
||||
).create({"description": "Test refund"})
|
||||
make_refund.invoice_refund()
|
||||
self.assertEqual(
|
||||
rma_line.mapped("analytic_account_id"),
|
||||
rma_line.mapped("refund_line_ids.account_analytic_id"),
|
||||
)
|
||||
|
||||
@@ -4,3 +4,5 @@
|
||||
|
||||
from . import rma_add_stock_move
|
||||
from . import rma_make_picking
|
||||
from . import rma_add_invoice
|
||||
from . import rma_refund
|
||||
|
||||
19
rma_analytic/wizards/rma_add_invoice.py
Normal file
19
rma_analytic/wizards/rma_add_invoice.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class RmaAddInvoice(models.TransientModel):
|
||||
_inherit = "rma_add_invoice"
|
||||
|
||||
def _prepare_rma_line_from_inv_line(self, line):
|
||||
res = super(
|
||||
RmaAddInvoice, self
|
||||
)._prepare_rma_line_from_inv_line(line)
|
||||
if line.account_analytic_id:
|
||||
res.update(
|
||||
analytic_account_id=line.account_analytic_id.id
|
||||
)
|
||||
return res
|
||||
@@ -6,7 +6,7 @@ from odoo import models, api
|
||||
|
||||
|
||||
class RmaMakePicking(models.TransientModel):
|
||||
_name = 'rma_make_picking.wizard'
|
||||
_inherit = 'rma_make_picking.wizard'
|
||||
_description = 'Wizard to create pickings from rma lines'
|
||||
|
||||
@api.model
|
||||
@@ -14,5 +14,5 @@ class RmaMakePicking(models.TransientModel):
|
||||
procurement_data = super(RmaMakePicking, self)._get_procurement_data(
|
||||
item, group, qty, picking_type)
|
||||
procurement_data.update(
|
||||
analytic_account_id=item.line_id.analytic_account_id.id)
|
||||
account_analytic_id=item.line_id.analytic_account_id.id)
|
||||
return procurement_data
|
||||
|
||||
18
rma_analytic/wizards/rma_refund.py
Normal file
18
rma_analytic/wizards/rma_refund.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class RmaRefund(models.TransientModel):
|
||||
_inherit = "rma.refund"
|
||||
|
||||
@api.model
|
||||
def prepare_refund_line(self, item, refund):
|
||||
res = super(RmaRefund, self).prepare_refund_line(item, refund)
|
||||
if item.line_id.analytic_account_id:
|
||||
res.update(
|
||||
account_analytic_id=item.line_id.analytic_account_id.id
|
||||
)
|
||||
return res
|
||||
@@ -10,7 +10,7 @@
|
||||
"license": "LGPL-3",
|
||||
"website": "http://www.eficent.com",
|
||||
"category": "Operating Units",
|
||||
"depends": ["rma", "operating_unit"],
|
||||
"depends": ["rma", "stock_operating_unit"],
|
||||
"data": [
|
||||
"security/rma_security.xml",
|
||||
"views/rma_order_view.xml",
|
||||
|
||||
@@ -11,7 +11,7 @@ class RmaOrder(models.Model):
|
||||
_inherit = "rma.order"
|
||||
|
||||
@api.multi
|
||||
@api.constrains('rma_line_ids', 'rma_line_ids.operating_unit_id')
|
||||
@api.constrains('rma_line_ids', 'operating_unit_id')
|
||||
def _check_operating_unit(self):
|
||||
for rma in self:
|
||||
bad_lines = rma.rma_line_ids.filtered(
|
||||
|
||||
@@ -70,7 +70,6 @@ class TestRmaOperatingUnit(common.TransactionCase):
|
||||
rma_order = self.rma_model.sudo(uid).create({
|
||||
'operating_unit_id': operating_unit.id,
|
||||
'partner_id': self.partner.id,
|
||||
'user_id': uid,
|
||||
})
|
||||
return rma_order
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
<field name="origin" position="after">
|
||||
<field name="operating_unit_id" groups="operating_unit.group_multi_operating_unit"/>
|
||||
</field>
|
||||
<field name="operation_id" position="attributes">
|
||||
<attribute name="domain">[('type','=','supplier'),('out_warehouse_id.operating_unit_id', '=', operating_unit_id)]</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -43,13 +46,16 @@
|
||||
<field name="origin" position="after">
|
||||
<field name="operating_unit_id" groups="operating_unit.group_multi_operating_unit"/>
|
||||
</field>
|
||||
<field name="operation_id" position="attributes">
|
||||
<attribute name="domain">[('type','=','customer'),('in_warehouse_id.operating_unit_id', '=', operating_unit_id)]</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_rma_line_filter" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.select</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="inherit_id" ref="rma.view_rma_line_form"/>
|
||||
<field name="inherit_id" ref="rma.view_rma_rma_line_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="partner_id" position="after">
|
||||
<field name="operating_unit_id" groups="operating_unit.group_multi_operating_unit"/>
|
||||
|
||||
@@ -35,3 +35,4 @@ class RmaAddStockMove(models.TransientModel):
|
||||
raise ValidationError(_(
|
||||
"Please define a warehouse with a default RMA location"))
|
||||
res.update(warehouse_id=warehouse.id)
|
||||
return res
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from . import models
|
||||
from . import wizards
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
{
|
||||
'name': 'RMA Purchase',
|
||||
'version': '9.0.1.0.0',
|
||||
'version': '10.0.2.0.0',
|
||||
'category': 'RMA',
|
||||
'summary': 'RMA from PO',
|
||||
'license': 'LGPL-3',
|
||||
'author': 'Eficent, Odoo Community Association (OCA)',
|
||||
'website': 'http://www.github.com/OCA/rma',
|
||||
'depends': ['rma_account', 'purchase'],
|
||||
'data': ['views/rma_order_view.xml',
|
||||
'views/rma_order_line_view.xml',
|
||||
'wizards/rma_add_purchase.xml'],
|
||||
'data': [
|
||||
'wizards/rma_order_line_make_purchase_order_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/rma_operation_view.xml',
|
||||
'views/rma_order_view.xml',
|
||||
'views/rma_order_line_view.xml',
|
||||
'wizards/rma_add_purchase.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': True,
|
||||
}
|
||||
|
||||
@@ -3,4 +3,6 @@
|
||||
|
||||
from . import rma_order
|
||||
from . import rma_order_line
|
||||
from . import purchase_order
|
||||
from . import purchase_order_line
|
||||
from . import rma_operation
|
||||
|
||||
29
rma_purchase/models/purchase_order.py
Normal file
29
rma_purchase/models/purchase_order.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class PurchaseOrder(models.Model):
|
||||
_inherit = "purchase.order"
|
||||
|
||||
@api.model
|
||||
def new(self, vals):
|
||||
"""Allows to propose a line based on the RMA information."""
|
||||
res = super(PurchaseOrder, self).new(vals)
|
||||
rma_line_id = self.env.context.get('rma_line_id')
|
||||
if rma_line_id:
|
||||
rma_line = self.env['rma.order.line'].browse(rma_line_id)
|
||||
line = self.env['purchase.order.line'].new({
|
||||
'product_id': rma_line.product_id.id,
|
||||
})
|
||||
line.onchange_product_id()
|
||||
line.update({
|
||||
'product_qty': rma_line.qty_to_purchase,
|
||||
'product_uom': rma_line.uom_id.id,
|
||||
})
|
||||
res.order_line = line
|
||||
# TODO: maybe this line is not needed in v10:
|
||||
res.date_planned = res._compute_date_planned()
|
||||
return res
|
||||
@@ -1,13 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, models
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class PurchaseOrderLine(models.Model):
|
||||
_inherit = "purchase.order.line"
|
||||
|
||||
# TODO: to be removed on migration to v10:
|
||||
# This is needed because odoo misspelled `store` in v9 :facepalm:
|
||||
state = fields.Selection(related='order_id.state', store=True)
|
||||
|
||||
rma_line_id = fields.Many2one(
|
||||
comodel_name='rma.order.line', string='RMA', copy=False
|
||||
)
|
||||
|
||||
@api.model
|
||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
||||
"""Allows to search by PO reference."""
|
||||
@@ -32,9 +40,14 @@ class PurchaseOrderLine(models.Model):
|
||||
res = []
|
||||
if self.env.context.get('rma'):
|
||||
for purchase in self:
|
||||
invoices = self.env['account.invoice.line'].search(
|
||||
[('purchase_line_id', '=', purchase.id)])
|
||||
if purchase.order_id.name:
|
||||
res.append((purchase.id, "%s %s qty:%s" % (
|
||||
res.append((purchase.id, "%s %s %s qty:%s" % (
|
||||
purchase.order_id.name,
|
||||
" ".join(str(x) for x in [
|
||||
inv.number for inv in invoices.mapped(
|
||||
'invoice_id')]),
|
||||
purchase.product_id.name, purchase.product_qty)))
|
||||
else:
|
||||
res.append(
|
||||
@@ -42,3 +55,10 @@ class PurchaseOrderLine(models.Model):
|
||||
return res
|
||||
else:
|
||||
return super(PurchaseOrderLine, self).name_get()
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
rma_line_id = self.env.context.get('rma_line_id')
|
||||
if rma_line_id:
|
||||
vals['rma_line_id'] = rma_line_id
|
||||
return super(PurchaseOrderLine, self).create(vals)
|
||||
|
||||
25
rma_purchase/models/rma_operation.py
Normal file
25
rma_purchase/models/rma_operation.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class RmaOperation(models.Model):
|
||||
_inherit = 'rma.operation'
|
||||
|
||||
purchase_policy = fields.Selection(
|
||||
selection=[('no', 'Not required'),
|
||||
('ordered', 'Based on Ordered Quantities'),
|
||||
('delivered', 'Based on Delivered Quantities')],
|
||||
string="Purchase Policy", default='no',
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.constrains('purchase_policy')
|
||||
def _check_purchase_policy(self):
|
||||
if self.filtered(
|
||||
lambda r: r.purchase_policy != 'no' and r.type != 'supplier'):
|
||||
raise ValidationError(_(
|
||||
'Purchase Policy can only apply to supplier operations'))
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
@@ -12,12 +12,9 @@ class RmaOrderLine(models.Model):
|
||||
@api.multi
|
||||
def _compute_purchase_count(self):
|
||||
for rec in self:
|
||||
purchase_list = []
|
||||
for procurement_id in rec.procurement_ids:
|
||||
if procurement_id.purchase_id and \
|
||||
procurement_id.purchase_id.id:
|
||||
purchase_list.append(procurement_id.purchase_id.id)
|
||||
rec.purchase_count = len(list(set(purchase_list)))
|
||||
purchase_line_count = self.env['purchase.order.line'].search(
|
||||
[('rma_line_id', '=', rec.id)])
|
||||
rec.purchase_count = len(purchase_line_count.mapped('order_id'))
|
||||
|
||||
@api.multi
|
||||
@api.depends('procurement_ids.purchase_line_id')
|
||||
@@ -31,10 +28,18 @@ class RmaOrderLine(models.Model):
|
||||
rec.purchase_order_line_ids = [(6, 0, purchase_list)]
|
||||
|
||||
@api.multi
|
||||
@api.depends('procurement_ids.purchase_line_id')
|
||||
def _compute_qty_purchased(self):
|
||||
@api.depends('procurement_ids.purchase_line_id',
|
||||
'manual_purchase_line_ids',
|
||||
'manual_purchase_line_ids.state', 'qty_delivered')
|
||||
def _compute_qty_purchase(self):
|
||||
for rec in self:
|
||||
rec.qty_purchased = rec._get_rma_purchased_qty()
|
||||
if rec.purchase_policy == 'ordered':
|
||||
rec.qty_to_purchase = rec.product_qty - rec.qty_purchased
|
||||
elif rec.purchase_policy == 'delivered':
|
||||
rec.qty_to_purchase = rec.qty_delivered - rec.qty_purchased
|
||||
else:
|
||||
rec.qty_to_purchase = 0.0
|
||||
|
||||
purchase_count = fields.Integer(
|
||||
compute='_compute_purchase_count', string='# of Purchases',
|
||||
@@ -55,12 +60,36 @@ class RmaOrderLine(models.Model):
|
||||
column1='rma_order_line_id', column2='purchase_order_line_id',
|
||||
string='Purchase Order Lines', compute='_compute_purchase_order_lines',
|
||||
)
|
||||
purchase_policy = fields.Selection(
|
||||
selection=[('no', 'Not required'),
|
||||
('ordered', 'Based on Ordered Quantities'),
|
||||
('delivered', 'Based on Delivered Quantities')],
|
||||
string="Purchase Policy", default='no',
|
||||
required=True,
|
||||
)
|
||||
manual_purchase_line_ids = fields.One2many(
|
||||
comodel_name='purchase.order.line',
|
||||
inverse_name='rma_line_id',
|
||||
string='Manual Purchase Order Lines',
|
||||
readonly=True, copy=False)
|
||||
qty_to_purchase = fields.Float(
|
||||
string='Qty To Purchase', copy=False,
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True, compute='_compute_qty_purchase', store=True,
|
||||
)
|
||||
qty_purchased = fields.Float(
|
||||
string='Qty Purchased', copy=False,
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True, compute='_compute_qty_purchased', store=True,
|
||||
readonly=True, compute='_compute_qty_purchase', store=True,
|
||||
)
|
||||
|
||||
@api.onchange('operation_id')
|
||||
def _onchange_operation_id(self):
|
||||
res = super(RmaOrderLine, self)._onchange_operation_id()
|
||||
if self.operation_id:
|
||||
self.purchase_policy = self.operation_id.purchase_policy or 'no'
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _prepare_rma_line_from_po_line(self, line):
|
||||
self.ensure_one()
|
||||
@@ -144,20 +173,24 @@ class RmaOrderLine(models.Model):
|
||||
def action_view_purchase_order(self):
|
||||
action = self.env.ref('purchase.purchase_rfq')
|
||||
result = action.read()[0]
|
||||
order_ids = []
|
||||
for procurement_id in self.procurement_ids:
|
||||
order_ids.append(procurement_id.purchase_id.id)
|
||||
result['domain'] = [('id', 'in', order_ids)]
|
||||
orders = self.mapped('procurement_ids.purchase_id')
|
||||
orders += self.mapped('manual_purchase_line_ids.order_id')
|
||||
result['domain'] = [('id', 'in', orders.ids)]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def _get_rma_purchased_qty(self):
|
||||
self.ensure_one()
|
||||
qty = 0.0
|
||||
if self.type == 'customer':
|
||||
return qty
|
||||
uom_obj = self.env['product.uom']
|
||||
for procurement_id in self.procurement_ids:
|
||||
purchase_line = procurement_id.purchase_line_id
|
||||
if self.type == 'supplier':
|
||||
qty += purchase_line.product_qty
|
||||
else:
|
||||
qty = 0.0
|
||||
qty += purchase_line.product_qty
|
||||
|
||||
for line in self.manual_purchase_line_ids.filtered(
|
||||
lambda p: p.state not in ('draft', 'sent', 'cancel')):
|
||||
qty += uom_obj._compute_quantity(
|
||||
self.uom_id.id, line.product_qty, line.product_uom.id)
|
||||
return qty
|
||||
|
||||
3
rma_purchase/security/ir.model.access.csv
Executable file
3
rma_purchase/security/ir.model.access.csv
Executable file
@@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_purchase_order_supplier_user,access_purchase_order,purchase.model_purchase_order,rma.group_rma_supplier_user,1,0,0,0
|
||||
access_purchase_order_line_supplier_user,access_purchase_order_line,purchase.model_purchase_order_line,rma.group_rma_supplier_user,1,0,0,0
|
||||
|
@@ -1,6 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
from . import test_rma
|
||||
from . import test_supplier_rma
|
||||
from . import test_rma_dropship
|
||||
|
||||
from . import test_rma_purchase
|
||||
|
||||
@@ -1,475 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp.tests import common
|
||||
from openerp import fields
|
||||
|
||||
|
||||
class TestRma(common.TransactionCase):
|
||||
|
||||
""" Test the routes and the quantities """
|
||||
|
||||
def setUp(self):
|
||||
super(TestRma, self).setUp()
|
||||
|
||||
self.rma_make_picking = self.env['rma_make_picking.wizard']
|
||||
self.make_supplier_rma = self.env["rma.order.line.make.supplier.rma"]
|
||||
self.rma_add_stock_move = self.env['rma_add_stock_move']
|
||||
self.stockpicking = self.env['stock.picking']
|
||||
self.rma = self.env['rma.order']
|
||||
self.rma_line = self.env['rma.order.line']
|
||||
self.rma_op = self.env['rma.operation']
|
||||
self.rma_cust_replace_op_id = self.env.ref(
|
||||
'rma.rma_operation_customer_replace')
|
||||
self.rma_sup_replace_op_id = self.env.ref(
|
||||
'rma.rma_operation_supplier_replace')
|
||||
self.product_id = self.env.ref('product.product_product_4')
|
||||
self.product_id.product_tmpl_id.categ_id.\
|
||||
property_stock_account_input_categ_id =\
|
||||
self.env.ref('account.data_account_type_receivable').id
|
||||
self.product_id.product_tmpl_id.categ_id.\
|
||||
property_stock_account_output_categ_id =\
|
||||
self.env.ref('account.data_account_type_expenses').id
|
||||
self.product_1 = self.env.ref('product.product_product_25')
|
||||
self.product_2 = self.env.ref('product.product_product_7')
|
||||
self.product_3 = self.env.ref('product.product_product_11')
|
||||
self.uom_unit = self.env.ref('product.product_uom_unit')
|
||||
self.valuation_account = self.env.ref(
|
||||
'l10n_generic_coa.1_conf_cas')
|
||||
self.stock_input_account = self.env.ref(
|
||||
'l10n_generic_coa.1_current_liabilities')
|
||||
self.stock_output_account = self.env.ref(
|
||||
'l10n_generic_coa.1_conf_a_expense')
|
||||
# assign an operation
|
||||
self.product_1.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_2.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_3.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.partner_id = self.env.ref('base.res_partner_12')
|
||||
self.stock_location = self.env.ref('stock.stock_location_stock')
|
||||
wh = self.env.ref('stock.warehouse0')
|
||||
self.stock_rma_location = wh.lot_rma_id
|
||||
self.customer_location = self.env.ref(
|
||||
'stock.stock_location_customers')
|
||||
self.supplier_location = self.env.ref(
|
||||
'stock.stock_location_suppliers')
|
||||
self.product_uom_id = self.env.ref('product.product_uom_unit')
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_customer_id = self._create_rma_from_move(
|
||||
products2move, 'customer', self.env.ref('base.res_partner_2'),
|
||||
dropship=False)
|
||||
|
||||
def _create_picking(self, partner):
|
||||
return self.stockpicking.create({
|
||||
'partner_id': partner.id,
|
||||
'picking_type_id': self.env.ref('stock.picking_type_in').id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.supplier_location.id
|
||||
})
|
||||
|
||||
def _create_rma_from_move(self, products2move, type, partner, dropship,
|
||||
supplier_address_id=None):
|
||||
picking_in = self._create_picking(partner)
|
||||
|
||||
moves = []
|
||||
if type == 'customer':
|
||||
for item in products2move:
|
||||
move_values = self._prepare_move(
|
||||
item[0], item[1], self.stock_location,
|
||||
self.customer_location, picking_in)
|
||||
moves.append(self.env['stock.move'].create(move_values))
|
||||
else:
|
||||
for item in products2move:
|
||||
move_values = self._prepare_move(
|
||||
item[0], item[1], self.supplier_location,
|
||||
self.stock_rma_location, picking_in)
|
||||
moves.append(self.env['stock.move'].create(move_values))
|
||||
# Create the RMA from the stock_move
|
||||
rma_id = self.rma.create(
|
||||
{
|
||||
'reference': '0001',
|
||||
'type': type,
|
||||
'partner_id': partner.id,
|
||||
'company_id': self.env.ref('base.main_company').id
|
||||
})
|
||||
rma_id._compute_invoice_refund_count()
|
||||
rma_id._compute_invoice_count()
|
||||
|
||||
data = {'add_invoice_id': self._create_invoice().id}
|
||||
new_line = self.rma.new(data)
|
||||
new_line.on_change_invoice()
|
||||
|
||||
rma_id.action_view_invoice_refund()
|
||||
rma_id.action_view_invoice()
|
||||
|
||||
for move in moves:
|
||||
if type == 'customer':
|
||||
wizard = self.rma_add_stock_move.new(
|
||||
{'stock_move_id': move.id, 'customer': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}
|
||||
)
|
||||
wizard.with_context({
|
||||
'stock_move_id': move.id, 'customer': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
})
|
||||
data = wizard.with_context(customer=1).\
|
||||
_prepare_rma_line_from_stock_move(move)
|
||||
data['partner_id'] = move.partner_id.id
|
||||
else:
|
||||
wizard = self.rma_add_stock_move.new(
|
||||
{'stock_move_id': move.id, 'supplier': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
}
|
||||
)
|
||||
wizard.with_context(
|
||||
{'stock_move_id': move.id, 'supplier': True,
|
||||
'active_ids': rma_id.id,
|
||||
'partner_id': move.partner_id.id,
|
||||
'active_model': 'rma.order',
|
||||
})
|
||||
data = wizard._prepare_rma_line_from_stock_move(move)
|
||||
data['partner_id'] = move.partner_id.id
|
||||
if dropship:
|
||||
data.update(customer_to_supplier=dropship,
|
||||
supplier_address_id=supplier_address_id.id)
|
||||
data['partner_id'] = move.partner_id.id
|
||||
data['rma_id'] = rma_id.id
|
||||
self.line = self.rma_line.create(data)
|
||||
# approve the RMA Line
|
||||
self.rma_line.action_rma_to_approve()
|
||||
|
||||
self.line.action_rma_approve()
|
||||
self.line.action_view_invoice()
|
||||
self.line.action_view_refunds()
|
||||
|
||||
# approve the RMA
|
||||
# rma_id.action_rma_to_approve()
|
||||
# rma_id.action_rma_approve()
|
||||
return rma_id
|
||||
|
||||
def _prepare_move(self, product, qty, src, dest, picking_in):
|
||||
res = {
|
||||
'partner_id': self.partner_id.id,
|
||||
'product_id': product.id,
|
||||
'name': product.partner_ref,
|
||||
'state': 'confirmed',
|
||||
'product_uom': self.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
|
||||
|
||||
def test_rma_refund(self):
|
||||
|
||||
self.rma_refund_item = self.env['rma.refund.item']
|
||||
self.rma_refund = self.env['rma.refund']
|
||||
|
||||
self.product_categ = self.env.ref('product.product_category_5')
|
||||
self.product_categ.update({
|
||||
'property_valuation': 'real_time',
|
||||
'property_stock_valuation_account_id': self.valuation_account.id,
|
||||
'property_stock_account_input_categ_id':
|
||||
self.stock_input_account.id,
|
||||
'property_stock_account_output_categ_id':
|
||||
self.stock_output_account.id,
|
||||
})
|
||||
self.product_id.update({
|
||||
'categ_id': self.product_categ.id,
|
||||
})
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
line.refund_policy = 'ordered'
|
||||
|
||||
refund = self.rma_refund.with_context({
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'active_id': 1
|
||||
}).create({'description': 'Test Reason',
|
||||
'date_invoice': fields.datetime.now()
|
||||
})
|
||||
self.rma_refund_item.create({
|
||||
'line_id': self.rma_customer_id.rma_line_ids[0].id,
|
||||
'rma_id': self.rma_customer_id.id,
|
||||
'product_id': self.product_id.id,
|
||||
'name': 'Test RMA Refund',
|
||||
'product_qty': self.rma_customer_id.rma_line_ids[0].product_qty,
|
||||
'wiz_id': refund.id
|
||||
})
|
||||
refund.invoice_refund()
|
||||
|
||||
def test_rma_add_invoice_wizard(self):
|
||||
|
||||
wizard = self.env['rma_add_invoice'].with_context({
|
||||
'active_ids': self.rma_customer_id.ids,
|
||||
'active_model': 'rma.order',
|
||||
'active_id': self.rma_customer_id.id
|
||||
}).create({'partner_id': self.partner_id.id,
|
||||
'rma_id': self.rma_customer_id.id,
|
||||
'invoice_line_ids':
|
||||
[(6, 0, [self._create_invoice().invoice_line_ids.id])],
|
||||
})
|
||||
wizard.add_lines()
|
||||
|
||||
def _create_invoice(self):
|
||||
self.Account = self.env['account.account']
|
||||
self.AccountInvoice = self.env['account.invoice']
|
||||
self.AccountInvoiceLine = self.env['account.invoice.line']
|
||||
|
||||
self.account_receivable =\
|
||||
self.env.ref('account.data_account_type_receivable')
|
||||
self.account_expenses =\
|
||||
self.env.ref('account.data_account_type_expenses')
|
||||
invoice_account = self.Account.\
|
||||
search([('user_type_id', '=', self.account_receivable.id)], limit=1
|
||||
).id
|
||||
invoice_line_account = self.Account.\
|
||||
search([('user_type_id', '=', self.account_expenses.id)], limit=1
|
||||
).id
|
||||
|
||||
invoice = self.AccountInvoice.create({
|
||||
'partner_id': self.partner_id.id,
|
||||
'account_id': invoice_account,
|
||||
'type': 'in_invoice',
|
||||
})
|
||||
|
||||
invoice_line = self.AccountInvoiceLine.create({
|
||||
'product_id': self.product_1.id,
|
||||
'quantity': 1.0,
|
||||
'price_unit': 100.0,
|
||||
'invoice_id': invoice.id,
|
||||
'uom_id': 1,
|
||||
'name': 'product that cost 100',
|
||||
'account_id': invoice_line_account,
|
||||
})
|
||||
invoice._compute_rma_count()
|
||||
invoice_line._compute_rma_count()
|
||||
invoice.action_view_rma_customer()
|
||||
invoice.action_view_rma_supplier()
|
||||
return invoice
|
||||
|
||||
def test_rma_make_picking(self):
|
||||
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'incoming',
|
||||
'active_id': 1
|
||||
}).create({})
|
||||
|
||||
wizard.action_create_picking()
|
||||
data = {'purchase_order_line_id':
|
||||
self._create_purchase_order().order_line.id}
|
||||
new_line = self.rma_line.new(data)
|
||||
new_line._onchange_purchase_order_line_id()
|
||||
|
||||
self.rma_customer_id._compute_po_count()
|
||||
self.rma_customer_id._compute_origin_po_count()
|
||||
|
||||
self.rma_customer_id.action_view_purchase_order()
|
||||
self.rma_customer_id.action_view_origin_purchase_order()
|
||||
|
||||
self.rma_customer_id.rma_line_ids[0]._compute_purchase_count()
|
||||
self.rma_customer_id.rma_line_ids[0]._compute_purchase_order_lines()
|
||||
self.rma_customer_id.rma_line_ids[0].action_view_purchase_order()
|
||||
self.rma_customer_id.rma_line_ids[0]._get_rma_purchased_qty()
|
||||
|
||||
def test_rma_add_purchase_wizard(self):
|
||||
wizard = self.env['rma_add_purchase'].with_context({
|
||||
'active_ids': self.rma_customer_id.ids,
|
||||
'active_model': 'rma.order',
|
||||
'active_id': self.rma_customer_id.id
|
||||
}).create({'partner_id': self.partner_id.id,
|
||||
'rma_id': self.rma_customer_id.id,
|
||||
'purchase_id': self._create_purchase_order().id,
|
||||
'purchase_line_ids':
|
||||
[(6, 0, [self._create_purchase_order().order_line.id])],
|
||||
})
|
||||
wizard.default_get([str(self._create_purchase_order().id),
|
||||
str(self._create_purchase_order().order_line.id),
|
||||
str(self.partner_id.id)])
|
||||
wizard.add_lines()
|
||||
|
||||
def _create_purchase_order(self):
|
||||
purchase_order_id = self.env["purchase.order"].create({
|
||||
"partner_id": self.partner_id.id,
|
||||
"order_line": [
|
||||
(0, 0, {
|
||||
"product_id": self.product_id.id,
|
||||
"name": self.product_id.name,
|
||||
"product_qty": 5,
|
||||
"price_unit": 100,
|
||||
"product_uom": self.product_id.uom_id.id,
|
||||
"date_planned": fields.datetime.now(),
|
||||
}),
|
||||
],
|
||||
})
|
||||
self.env["purchase.order.line"].\
|
||||
name_search(name=self.product_id.name, operator='ilike',
|
||||
args=[('id', 'in', purchase_order_id.order_line.ids)])
|
||||
self.env["purchase.order.line"].\
|
||||
_name_search(name=self.product_id.name, operator='ilike',
|
||||
args=[('id', 'in', purchase_order_id.order_line.ids)])
|
||||
return purchase_order_id
|
||||
|
||||
def test_customer_rma(self):
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'incoming',
|
||||
'active_id': 1
|
||||
}).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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 3,
|
||||
"Wrong qty incoming")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 5,
|
||||
"Wrong qty incoming")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 2,
|
||||
"Wrong qty incoming")
|
||||
picking.action_assign()
|
||||
picking.do_transfer()
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_receive, 0,
|
||||
"Wrong qty to_receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 3,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to_deliver")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to_deliver")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to_deliver")
|
||||
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': self.rma_customer_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'outgoing',
|
||||
}).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))]
|
||||
pickings = self.stockpicking.search(domain)
|
||||
procurements[0].purchase_id = self._create_purchase_order().id
|
||||
wizard._get_action(pickings, procurements)
|
||||
self.assertEquals(len(pickings), 2,
|
||||
"Incorrect number of pickings created")
|
||||
picking_out = pickings[1]
|
||||
moves = picking_out.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_receive, 0,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 3,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_received, 3,
|
||||
"Wrong qty received")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 5,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 2,
|
||||
"Wrong qty outgoing")
|
||||
picking_out.action_assign()
|
||||
picking_out.do_transfer()
|
||||
for line in self.rma_customer_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_to_receive, 0,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_to_deliver, 0,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 3,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 3,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 5,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 5,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 2,
|
||||
"Wrong qty delivered")
|
||||
self.line.action_rma_done()
|
||||
self.assertEquals(self.line.state, 'done',
|
||||
"Wrong State")
|
||||
@@ -1,108 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp.addons.rma.tests import test_rma
|
||||
|
||||
|
||||
class TestRmaDropship(test_rma.TestRma):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRmaDropship, self).setUp()
|
||||
self.product_id.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_1.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_2.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
self.product_3.write(
|
||||
{'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
|
||||
'rma_supplier_operation_id': self.rma_sup_replace_op_id.id})
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_droship_id = self._create_rma_from_move(
|
||||
products2move, 'customer', self.env.ref('base.res_partner_2'),
|
||||
dropship=True,
|
||||
supplier_address_id=self.env.ref('base.res_partner_3'))
|
||||
|
||||
def test_dropship(self):
|
||||
wizard = self.make_supplier_rma.with_context({
|
||||
'active_ids': self.rma_droship_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'active_id': 1
|
||||
}).create({})
|
||||
res = wizard.make_supplier_rma()
|
||||
supplier_rma = self.rma.browse(res['res_id'])
|
||||
for line in supplier_rma.rma_line_ids:
|
||||
line.action_rma_to_approve()
|
||||
line.action_rma_approve()
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': supplier_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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in supplier_rma.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_outgoing, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_incoming, 3,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_incoming, 5,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_incoming, 2,
|
||||
"Wrong qty outgoing")
|
||||
|
||||
for line in self.rma_droship_id.rma_line_ids:
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 3,
|
||||
"Wrong qty in supplier rma")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 5,
|
||||
"Wrong qty in supplier rma")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_supplier_rma, 0,
|
||||
"Wrong qty to supplier rma")
|
||||
self.assertEquals(line.qty_in_supplier_rma, 2,
|
||||
"Wrong qty in supplier rma")
|
||||
for line in self.rma_droship_id.rma_line_ids:
|
||||
line.action_rma_done()
|
||||
self.assertEquals(line.state, 'done',
|
||||
"Wrong State")
|
||||
95
rma_purchase/tests/test_rma_purchase.py
Normal file
95
rma_purchase/tests/test_rma_purchase.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo.tests import common
|
||||
from odoo.fields import Datetime
|
||||
|
||||
|
||||
class TestRmaPurchase(common.SingleTransactionCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestRmaPurchase, cls).setUpClass()
|
||||
|
||||
cls.rma_obj = cls.env['rma.order']
|
||||
cls.rma_line_obj = cls.env['rma.order.line']
|
||||
cls.rma_op_obj = cls.env['rma.operation']
|
||||
cls.rma_add_purchase_wiz = cls.env['rma_add_purchase']
|
||||
cls.po_obj = cls.env['purchase.order']
|
||||
cls.pol_obj = cls.env['purchase.order.line']
|
||||
cls.product_obj = cls.env['product.product']
|
||||
cls.partner_obj = cls.env['res.partner']
|
||||
|
||||
cls.rma_route_cust = cls.env.ref('rma.route_rma_customer')
|
||||
|
||||
# Create supplier
|
||||
supplier1 = cls.partner_obj.create({'name': 'Supplier 1'})
|
||||
|
||||
# Create products
|
||||
cls.product_1 = cls.product_obj.create({
|
||||
'name': 'Test Product 1',
|
||||
'type': 'product',
|
||||
})
|
||||
cls.product_2 = cls.product_obj.create({
|
||||
'name': 'Test Product 2',
|
||||
'type': 'product',
|
||||
})
|
||||
|
||||
# Create PO:
|
||||
cls.po = cls.po_obj.create({
|
||||
'partner_id': supplier1.id,
|
||||
})
|
||||
cls.pol_1 = cls.pol_obj.create({
|
||||
'name': cls.product_1.name,
|
||||
'order_id': cls.po.id,
|
||||
'product_id': cls.product_1.id,
|
||||
'product_qty': 20.0,
|
||||
'product_uom': cls.product_1.uom_id.id,
|
||||
'price_unit': 100.0,
|
||||
'date_planned': Datetime.now(),
|
||||
})
|
||||
cls.pol_2 = cls.pol_obj.create({
|
||||
'name': cls.product_2.name,
|
||||
'order_id': cls.po.id,
|
||||
'product_id': cls.product_2.id,
|
||||
'product_qty': 18.0,
|
||||
'product_uom': cls.product_2.uom_id.id,
|
||||
'price_unit': 150.0,
|
||||
'date_planned': Datetime.now(),
|
||||
})
|
||||
|
||||
# Create RMA group:
|
||||
cls.rma_group = cls.rma_obj.create({
|
||||
'partner_id': supplier1.id,
|
||||
'type': 'supplier',
|
||||
})
|
||||
|
||||
def test_01_add_from_purchase_order(self):
|
||||
"""Test wizard to create supplier RMA from Purchase Orders."""
|
||||
self.assertEqual(self.rma_group.origin_po_count, 0)
|
||||
add_purchase = self.rma_add_purchase_wiz.with_context({
|
||||
'supplier': True,
|
||||
'active_ids': self.rma_group.id,
|
||||
'active_model': 'rma.order',
|
||||
}).create({
|
||||
'purchase_id': self.po.id,
|
||||
'purchase_line_ids': [(6, 0, self.po.order_line.ids)],
|
||||
})
|
||||
add_purchase.add_lines()
|
||||
self.assertEqual(len(self.rma_group.rma_line_ids), 2)
|
||||
for t in self.rma_group.rma_line_ids.mapped('type'):
|
||||
self.assertEqual(t, 'supplier')
|
||||
self.assertEqual(self.rma_group.origin_po_count, 1)
|
||||
|
||||
def test_02_fill_rma_from_po_line(self):
|
||||
"""Test filling a RMA (line) from a Purchase Order line."""
|
||||
rma = self.rma_line_obj.new({
|
||||
'partner_id': self.po.partner_id.id,
|
||||
'purchase_order_line_id': self.pol_1.id,
|
||||
'type': 'supplier',
|
||||
})
|
||||
self.assertFalse(rma.product_id)
|
||||
rma._onchange_purchase_order_line_id()
|
||||
self.assertEqual(rma.product_id, self.product_1)
|
||||
self.assertEqual(rma.product_qty, 20.0)
|
||||
@@ -1,156 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp.addons.rma.tests import test_rma
|
||||
|
||||
|
||||
class TestSupplierRma(test_rma.TestRma):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSupplierRma, self).setUp()
|
||||
products2move = [(self.product_1, 3), (self.product_2, 5),
|
||||
(self.product_3, 2)]
|
||||
self.rma_supplier_id = self._create_rma_from_move(
|
||||
products2move, 'supplier', self.env.ref('base.res_partner_1'),
|
||||
dropship=False)
|
||||
|
||||
def test_supplier_rma(self):
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_supplier_id.rma_line_ids.ids,
|
||||
'active_model': 'rma.order.line',
|
||||
'picking_type': 'outgoing',
|
||||
'active_id': 1
|
||||
}).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.stockpicking.search(domain)
|
||||
self.assertEquals(len(picking), 1,
|
||||
"Incorrect number of pickings created")
|
||||
moves = picking.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
# common qtys for all products
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
# product specific
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 3,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 3,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 5,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
self.assertEquals(line.qty_outgoing, 2,
|
||||
"Wrong qty outgoing")
|
||||
|
||||
picking.action_assign()
|
||||
picking.do_new_transfer()
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_outgoing, 5,
|
||||
"Wrong qty outgoing")
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_outgoing, 2,
|
||||
"Wrong qty delivered")
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_id': 1,
|
||||
'active_ids': self.rma_supplier_id.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))]
|
||||
pickings = self.stockpicking.search(domain)
|
||||
self.assertEquals(len(pickings), 2,
|
||||
"Incorrect number of pickings created")
|
||||
picking_out = pickings[1]
|
||||
moves = picking_out.move_lines
|
||||
self.assertEquals(len(moves), 3,
|
||||
"Incorrect number of moves created")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_to_receive, 5,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 5,
|
||||
"Wrong qty to deliver")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_to_receive, 2,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_to_deliver, 2,
|
||||
"Wrong qty to deliver")
|
||||
picking_out.action_assign()
|
||||
picking_out.do_new_transfer()
|
||||
for line in self.rma_supplier_id.rma_line_ids[0]:
|
||||
self.assertEquals(line.qty_to_receive, 3,
|
||||
"Wrong qty to receive")
|
||||
self.assertEquals(line.qty_incoming, 0,
|
||||
"Wrong qty incoming")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty deliver")
|
||||
self.assertEquals(line.qty_outgoing, 6,
|
||||
"Wrong qty outgoing")
|
||||
if line.product_id == self.product_1:
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 0,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_2:
|
||||
self.assertEquals(line.qty_received, 0,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 5,
|
||||
"Wrong qty delivered")
|
||||
if line.product_id == self.product_3:
|
||||
self.assertEquals(line.qty_received, 2,
|
||||
"Wrong qty received")
|
||||
self.assertEquals(line.qty_delivered, 2,
|
||||
"Wrong qty delivered")
|
||||
for line in self.rma_supplier_id.rma_line_ids:
|
||||
line.action_rma_done()
|
||||
self.assertEquals(line.state, 'done',
|
||||
"Wrong State")
|
||||
28
rma_purchase/views/rma_operation_view.xml
Normal file
28
rma_purchase/views/rma_operation_view.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
|
||||
<odoo>
|
||||
|
||||
<record id="rma_operation_tree" model="ir.ui.view">
|
||||
<field name="name">rma.operation.tree - rma_purchase</field>
|
||||
<field name="model">rma.operation</field>
|
||||
<field name="inherit_id" ref="rma.rma_operation_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="delivery_policy" position="after">
|
||||
<field name="purchase_policy"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="rma_operation_form" model="ir.ui.view">
|
||||
<field name="name">rma.operation.form - rma_purchase</field>
|
||||
<field name="model">rma.operation</field>
|
||||
<field name="inherit_id" ref="rma.rma_operation_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="delivery_policy" position="after">
|
||||
<field name="purchase_policy"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,6 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="action_rma_line_purchase" model="ir.actions.act_window">
|
||||
<field name="name">Purchase Order</field>
|
||||
<field name="res_model">purchase.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="target">current</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_line_supplier_button_sale_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.supplier.form</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="inherit_id" ref="rma.view_rma_line_supplier_button_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<header position="inside">
|
||||
<button name="%(action_rma_order_line_make_purchase_order)d"
|
||||
string="Create Purchase Order" class="oe_highlight"
|
||||
context="{'rma_line_id': active_id, 'default_partner_id': partner_id}"
|
||||
type="action"/>
|
||||
</header>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_line_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.supplier.form</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
@@ -25,9 +47,13 @@
|
||||
</group>
|
||||
<group name="quantities" position="inside">
|
||||
<group>
|
||||
<field name="qty_to_purchase"/>
|
||||
<field name="qty_purchased"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="delivery_policy" position="after">
|
||||
<field name="purchase_policy"/>
|
||||
</field>
|
||||
<field name="origin" position="after">
|
||||
<field name="purchase_id"
|
||||
attrs="{'invisible': [('purchase_order_line_id', '=', False)]}"/>
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
from . import rma_make_picking
|
||||
from . import rma_add_purchase
|
||||
from . import rma_order_line_make_purchase_order
|
||||
|
||||
147
rma_purchase/wizards/rma_order_line_make_purchase_order.py
Normal file
147
rma_purchase/wizards/rma_order_line_make_purchase_order.py
Normal file
@@ -0,0 +1,147 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0).
|
||||
|
||||
import odoo.addons.decimal_precision as dp
|
||||
from odoo import _, api, exceptions, fields, models
|
||||
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class RmaLineMakePurchaseOrder(models.TransientModel):
|
||||
_name = "rma.order.line.make.purchase.order"
|
||||
_description = "Make Purchases Order from RMA Line"
|
||||
|
||||
partner_id = fields.Many2one(
|
||||
comodel_name='res.partner', string='Customer', required=False,
|
||||
domain=[('customer', '=', True)])
|
||||
item_ids = fields.One2many(
|
||||
comodel_name='rma.order.line.make.purchase.order.item',
|
||||
inverse_name='wiz_id', string='Items')
|
||||
purchase_order_id = fields.Many2one(
|
||||
comodel_name='purchase.order', string='Purchases Order',
|
||||
required=False, domain=[('state', '=', 'draft')])
|
||||
|
||||
@api.model
|
||||
def _prepare_item(self, line):
|
||||
return {
|
||||
'line_id': line.id,
|
||||
'rma_line_id': line.id,
|
||||
'product_id': line.product_id.id,
|
||||
'name': line.product_id.name,
|
||||
'product_qty': line.qty_to_purchase,
|
||||
'rma_id': line.rma_id.id,
|
||||
'product_uom_id': line.uom_id.id,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(RmaLineMakePurchaseOrder, self).default_get(
|
||||
fields)
|
||||
rma_line_obj = self.env['rma.order.line']
|
||||
rma_line_ids = self.env.context['active_ids'] or []
|
||||
active_model = self.env.context['active_model']
|
||||
|
||||
if not rma_line_ids:
|
||||
return res
|
||||
assert active_model == 'rma.order.line', 'Bad context propagation'
|
||||
|
||||
items = []
|
||||
lines = rma_line_obj.browse(rma_line_ids)
|
||||
for line in lines:
|
||||
items.append([0, 0, self._prepare_item(line)])
|
||||
customers = lines.mapped('partner_id')
|
||||
if len(customers) == 1:
|
||||
res['partner_id'] = customers.id
|
||||
else:
|
||||
raise exceptions.Warning(
|
||||
_('Only RMA lines from the same partner can be processed at '
|
||||
'the same time'))
|
||||
res['item_ids'] = items
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _prepare_purchase_order(self, item):
|
||||
if not self.partner_id:
|
||||
raise exceptions.Warning(
|
||||
_('Enter a supplier.'))
|
||||
supplier = self.partner_id
|
||||
data = {
|
||||
'origin': '',
|
||||
'partner_id': supplier.id,
|
||||
'company_id': item.line_id.company_id.id,
|
||||
}
|
||||
return data
|
||||
|
||||
@api.model
|
||||
def _prepare_purchase_order_line(self, po, item):
|
||||
product = item.product_id
|
||||
vals = {
|
||||
'name': product.name,
|
||||
'order_id': po.id,
|
||||
'product_id': product.id,
|
||||
'price_unit': item.line_id.price_unit,
|
||||
'date_planned': datetime.today().strftime(
|
||||
DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
'product_uom': product.uom_po_id.id,
|
||||
'product_qty': item.product_qty,
|
||||
'rma_line_id': item.line_id.id
|
||||
}
|
||||
if item.free_of_charge:
|
||||
vals['price_unit'] = 0.0
|
||||
return vals
|
||||
|
||||
@api.multi
|
||||
def create_purchase_order(self):
|
||||
res = []
|
||||
purchase_obj = self.env['purchase.order']
|
||||
po_line_obj = self.env['purchase.order.line']
|
||||
purchase = False
|
||||
|
||||
for item in self.item_ids:
|
||||
if item.product_qty <= 0.0:
|
||||
raise exceptions.Warning(
|
||||
_('Enter a positive quantity.'))
|
||||
|
||||
if self.purchase_order_id:
|
||||
purchase = self.purchase_order_id
|
||||
if not purchase:
|
||||
po_data = self._prepare_purchase_order(item)
|
||||
purchase = purchase_obj.create(po_data)
|
||||
|
||||
po_line_data = self._prepare_purchase_order_line(purchase, item)
|
||||
po_line_obj.create(po_line_data)
|
||||
res.append(purchase.id)
|
||||
|
||||
return {
|
||||
'domain': "[('id','in', ["+','.join(map(str, res))+"])]",
|
||||
'name': _('Request for Quotation'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'purchase.order',
|
||||
'view_id': False,
|
||||
'context': False,
|
||||
'type': 'ir.actions.act_window'
|
||||
}
|
||||
|
||||
|
||||
class RmaLineMakePurchaseOrderItem(models.TransientModel):
|
||||
_name = "rma.order.line.make.purchase.order.item"
|
||||
_description = "RMA Line Make Purchase Order Item"
|
||||
|
||||
wiz_id = fields.Many2one(
|
||||
comodel_name='rma.order.line.make.purchase.order', string='Wizard')
|
||||
line_id = fields.Many2one(
|
||||
comodel_name='rma.order.line', string='RMA Line')
|
||||
rma_id = fields.Many2one(
|
||||
comodel_name='rma.order', related='line_id.rma_id',
|
||||
string='RMA Order')
|
||||
product_id = fields.Many2one(
|
||||
comodel_name='product.product', string='Product')
|
||||
name = fields.Char(string='Description')
|
||||
product_qty = fields.Float(
|
||||
string='Quantity to purchase',
|
||||
digits=dp.get_precision('Product Unit of Measure'),)
|
||||
product_uom_id = fields.Many2one(
|
||||
comodel_name='product.uom', string='UoM')
|
||||
free_of_charge = fields.Boolean(string='Free of Charge')
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_rma_order_line_make_purchase_order" model="ir.ui.view">
|
||||
<field name="name">RMA Line Make Purchase Order</field>
|
||||
<field name="model">rma.order.line.make.purchase.order</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create Quotation" create="false" edit="false">
|
||||
<separator string="Existing Quotation to update:"/>
|
||||
<newline/>
|
||||
<group>
|
||||
<field name="purchase_order_id"
|
||||
domain="[('partner_id','=',partner_id)]"
|
||||
context="{'partner_id': partner_id}"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<separator
|
||||
string="New Purchases Order details:"/>
|
||||
<newline/>
|
||||
<group>
|
||||
<field name="partner_id"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group>
|
||||
<field name="item_ids" nolabel="1" colspan="2">
|
||||
<tree string="Details" editable="bottom" create="false">
|
||||
<field name="line_id"
|
||||
options="{'no_open': true}"/>
|
||||
<field name="product_id"/>
|
||||
<field name="name"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom_id"
|
||||
groups="product.group_uom"/>
|
||||
<field name="free_of_charge"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<newline/>
|
||||
<footer colspan="2">
|
||||
<button name="create_purchase_order"
|
||||
string="Create RFQ" type="object"
|
||||
class="oe_highlight"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_order_line_make_purchase_order"
|
||||
model="ir.actions.act_window">
|
||||
<field name="name">Create RFQ</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">rma.order.line.make.purchase.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_rma_order_line_make_purchase_order"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -8,10 +8,10 @@ from odoo import _, api, exceptions, models
|
||||
class PurchaseOrderLine(models.Model):
|
||||
_inherit = "purchase.order.line"
|
||||
|
||||
@api.constrains('analytic_account_id')
|
||||
@api.constrains('account_analytic_id')
|
||||
def check_analytic(self):
|
||||
for line in self:
|
||||
if (line.analytic_account_id !=
|
||||
for line in self.filtered(lambda p: p.rma_line_id):
|
||||
if (line.account_analytic_id !=
|
||||
line.rma_line_id.analytic_account_id):
|
||||
raise exceptions.ValidationError(
|
||||
_("The analytic account in the PO line it's not the same"
|
||||
|
||||
@@ -13,3 +13,16 @@ class RmaAddPurchase(models.TransientModel):
|
||||
data = super(RmaAddPurchase, self)._prepare_rma_line_from_po_line(line)
|
||||
data.update(analytic_account_id=line.analytic_account_id.id)
|
||||
return data
|
||||
|
||||
|
||||
class RmaLineMakePurchaseOrder(models.TransientModel):
|
||||
_inherit = "rma.order.line.make.purchase.order"
|
||||
_description = "Make Purchases Order from RMA Line"
|
||||
|
||||
@api.model
|
||||
def _prepare_purchase_order_line(self, po, item):
|
||||
res = super(
|
||||
RmaLineMakePurchaseOrder, self)._prepare_purchase_order_line(
|
||||
po, item)
|
||||
res['account_analytic_id'] = item.line_id.analytic_account_id.id
|
||||
return res
|
||||
|
||||
28
rma_purchase_operating_unit/README.rst
Normal file
28
rma_purchase_operating_unit/README.rst
Normal file
@@ -0,0 +1,28 @@
|
||||
.. image:: https://img.shields.io/badge/license-LGPLv3-blue.svg
|
||||
:target: https://www.gnu.org/licenses/lgpl.html
|
||||
:alt: License: LGPL-3
|
||||
|
||||
=================================
|
||||
RMA Purchase with Operating Units
|
||||
=================================
|
||||
|
||||
This module introduces the following features:
|
||||
|
||||
* Adds the operating unit to the quotation
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
* No changes
|
||||
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Aaron Henriquez <ahenriquez@eficent.com>
|
||||
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
This module is maintained by Eficent.
|
||||
4
rma_purchase_operating_unit/__init__.py
Normal file
4
rma_purchase_operating_unit/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from . import wizards
|
||||
17
rma_purchase_operating_unit/__manifest__.py
Normal file
17
rma_purchase_operating_unit/__manifest__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
{
|
||||
"name": "Analytic Account in RMA purchase",
|
||||
"version": "10.0.1.0.0",
|
||||
"author": "Eficent,"
|
||||
"Odoo Community Association (OCA)",
|
||||
"license": "LGPL-3",
|
||||
"website": "http://www.eficent.com",
|
||||
"category": "Analytic",
|
||||
"depends": ["rma_operating_unit", "rma_purchase"],
|
||||
"data": [
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
5
rma_purchase_operating_unit/wizards/__init__.py
Normal file
5
rma_purchase_operating_unit/wizards/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from . import rma_line_make_purchase_order
|
||||
@@ -0,0 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class RmaLineMakePurchaseOrder(models.TransientModel):
|
||||
_inherit = "rma.order.line.make.purchase.order"
|
||||
|
||||
@api.model
|
||||
def _prepare_purchase_order(self, item):
|
||||
res = super(RmaLineMakePurchaseOrder, self)._prepare_purchase_order(item)
|
||||
res.update(operating_unit_id=item.line_id.operating_unit_id.id)
|
||||
return res
|
||||
@@ -2,7 +2,7 @@
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp import api, fields, models
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class QualityControlIssue(models.Model):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp import fields, models
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class RmaOrderLine(models.Model):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp.tests import common
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestRma(common.TransactionCase):
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
# Copyright 2016 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0).
|
||||
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp import api, fields, models, _
|
||||
from openerp.exceptions import ValidationError
|
||||
import odoo.addons.decimal_precision as dp
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class QcIssueMakeSupplierRma(models.TransientModel):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp import fields, models
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class MrpRepair(models.Model):
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user