Merge pull request #35 from ForgeFlow/10.0-imp-rma

[10.0]RMA improvement
This commit is contained in:
Aaron ForgeFlow
2019-12-13 09:48:42 +01:00
committed by GitHub
125 changed files with 3086 additions and 3098 deletions

View File

@@ -9,6 +9,7 @@ python:
- "2.7"
addons:
postgresql: "9.6"
apt:
packages:
- expect-dev # provides unbuffer utility

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,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

View File

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

View File

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

View File

@@ -0,0 +1,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.')

View File

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

View File

@@ -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

View File

@@ -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',

View File

@@ -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>

View File

@@ -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,
)

View File

@@ -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',
)

View File

@@ -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

View File

@@ -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."))

View File

@@ -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

View File

@@ -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
View 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>

View 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>

View File

@@ -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 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
8 access_rma_operation_manager access_rma_operation model_rma_operation group_rma_manager 1 1 1 1
9 access_rma_operation_customer_user access_rma_operation model_rma_operation group_rma_customer_user 1 0 0 0
10 access_rma_operation_supplier_user access_rma_operation model_rma_operation group_rma_supplier_user 1 0 0 0
11 access_stock_config_settings access_rma_order_line_user access_stock_config_settings access_rma_order_line model_stock_config_settings model_rma_order_line stock.group_stock_manager base.group_user 1 1 0 1 0 1 0

View File

@@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -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

View File

@@ -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)

View File

@@ -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")

View File

@@ -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")

View File

@@ -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>

View File

@@ -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'}"/>

View File

@@ -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"

View File

@@ -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,

View File

@@ -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)

View File

@@ -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):

View File

@@ -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>

View File

@@ -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',
)

View File

@@ -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>

View File

@@ -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,
}

View File

@@ -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>

View File

@@ -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")

View File

@@ -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 {}

View File

@@ -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()

View File

@@ -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

View File

@@ -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")

View 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)

View File

@@ -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")

View File

@@ -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")

View File

@@ -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>

View 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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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"/>

View File

@@ -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")

View File

@@ -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,
}

View File

@@ -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')

View File

@@ -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,
}

View File

@@ -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 "

View File

@@ -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

View File

@@ -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"),
)

View File

@@ -4,3 +4,5 @@
from . import rma_add_stock_move
from . import rma_make_picking
from . import rma_add_invoice
from . import rma_refund

View 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

View File

@@ -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

View 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

View File

@@ -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",

View File

@@ -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(

View File

@@ -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

View File

@@ -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"/>

View File

@@ -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

View File

@@ -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

View File

@@ -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,
}

View File

@@ -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

View 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

View File

@@ -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)

View 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'))

View File

@@ -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

View 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 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_purchase_order_supplier_user access_purchase_order purchase.model_purchase_order rma.group_rma_supplier_user 1 0 0 0
3 access_purchase_order_line_supplier_user access_purchase_order_line purchase.model_purchase_order_line rma.group_rma_supplier_user 1 0 0 0

View File

@@ -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

View File

@@ -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")

View File

@@ -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")

View 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)

View File

@@ -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")

View 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>

View File

@@ -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)]}"/>

View File

@@ -4,3 +4,4 @@
from . import rma_make_picking
from . import rma_add_purchase
from . import rma_order_line_make_purchase_order

View 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')

View File

@@ -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>

View File

@@ -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"

View File

@@ -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

View 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.

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import wizards

View 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,
}

View 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

View File

@@ -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

View File

@@ -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):

View File

@@ -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):

View File

@@ -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):

View File

@@ -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):

View File

@@ -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