mirror of
https://github.com/ForgeFlow/stock-rma.git
synced 2025-01-21 12:57:49 +02:00
init branch
This commit is contained in:
committed by
ahenriquez
parent
571e437f16
commit
8939fc8c7a
96
rma/README.rst
Normal file
96
rma/README.rst
Normal file
@@ -0,0 +1,96 @@
|
||||
.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
|
||||
:alt: License LGPL-3
|
||||
|
||||
RMA
|
||||
===
|
||||
|
||||
A return merchandise authorization (RMA), is a part of the process of
|
||||
returning a product in order to receive a refund, replacement, or repair
|
||||
during the product's warranty period.
|
||||
|
||||
The purchaser of the product must contact the manufacturer (or distributor
|
||||
or retailer) to obtain authorization to return the product.
|
||||
|
||||
The resulting RMA number must be displayed on or included in the returned
|
||||
product's packaging.
|
||||
|
||||
The issuance of an RMA is a key gatekeeping moment in the reverse logistics
|
||||
cycle, providing the vendor with a final opportunity to diagnose and correct
|
||||
the customer's problem with the product (such as improper installation or
|
||||
configuration) before the customer permanently relinquishes ownership
|
||||
of the product to the manufacturer, commonly referred to as a return.
|
||||
|
||||
As returns are costly for the vendor and inconvenient for the customer,
|
||||
any return that can be prevented benefits both parties.
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Security
|
||||
--------
|
||||
Go to Settings > Users and assign the appropiate permissions to users.
|
||||
Different security groups grant distinct levels of access to the RMA features.
|
||||
|
||||
* Users in group "RMA Customer User" or "RMA Supplier User" can access to,
|
||||
create and process RMA's associated to customers or suppliers respectively.
|
||||
|
||||
* Users in group "RMA Manager" can access to, create, approve and process RMA's
|
||||
associated to both customers and suppliers.
|
||||
|
||||
|
||||
|
||||
|
||||
#. Go to Settings > Users and assign the appropiate permissions to users.
|
||||
Users assigned to the group 'RMA
|
||||
#. Go to Inventory > Settings > Return Merchandising Authorization and select
|
||||
the option "Display 3 fields on rma: partner, invoice address, delivery
|
||||
address" if needed.
|
||||
#. Go to Inventory > Settings > Configuration > Warehouse management >
|
||||
Warehouses and add a default RMA location and RMA picking type for customers
|
||||
and suppliers RMA picking type. In case the warehouse is configured to
|
||||
use routes, you need to create at least one route per rma type with at
|
||||
least two push rules (one for inbound another for outbound) it's very
|
||||
important to select the typeof operation supplier if we are moving in the
|
||||
company and customer if we are moving out of the company.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
RMA are accessible though Inventory menu. There's four menus, divided by type
|
||||
. Users can access to the list of RMA or RMA lines.
|
||||
|
||||
Create an RMA:
|
||||
#. Select a partner. Enter RMA lines associated to an existing picking, or
|
||||
manually.
|
||||
#. Request approval and approve.
|
||||
#. Click on RMA Lines button.
|
||||
#. Click on more and select an option: "Receive products", "Create Delivery
|
||||
Order".
|
||||
#. Go back to the RMA. Set the RMA to done if not further action is required.
|
||||
|
||||
|
||||
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
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||
* Aaron Henriquez <ahenriquez@eficent.com>
|
||||
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
This module is maintained by Eficent.
|
||||
|
||||
5
rma/__init__.py
Normal file
5
rma/__init__.py
Normal file
@@ -0,0 +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
|
||||
41
rma/__openerp__.py
Normal file
41
rma/__openerp__.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# -*- 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': 'rma',
|
||||
'version': '9.0.1.0.0',
|
||||
'license': 'LGPL-3',
|
||||
'category': 'RMA',
|
||||
'summary': 'Introduces the return merchandise authorization (RMA) process '
|
||||
'in odoo',
|
||||
'author': "Eficent",
|
||||
'website': 'http://www.github.com/OCA/rma',
|
||||
'depends': ['account', 'stock', 'mail',
|
||||
'procurement'],
|
||||
'demo': [
|
||||
'demo/stock_demo.xml',
|
||||
],
|
||||
'data': ['security/rma.xml',
|
||||
'security/ir.model.access.csv',
|
||||
|
||||
'data/rma_sequence.xml',
|
||||
'data/stock_data.xml',
|
||||
'data/rma_operation.xml',
|
||||
'views/rma_order_view.xml',
|
||||
'views/rma_operation_view.xml',
|
||||
'views/rma_rule_view.xml',
|
||||
'views/rma_order_line_view.xml',
|
||||
'views/stock_view.xml',
|
||||
'views/stock_warehouse.xml',
|
||||
'views/product_view.xml',
|
||||
'views/procurement_view.xml',
|
||||
'views/res_company_view.xml',
|
||||
'wizards/rma_make_picking_view.xml',
|
||||
'wizards/rma_add_stock_move_view.xml',
|
||||
'wizards/stock_config_settings.xml',
|
||||
'wizards/rma_order_line_make_supplier_rma_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
81
rma/data/rma_operation.xml
Normal file
81
rma/data/rma_operation.xml
Normal file
@@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
<record id="rma_operation_customer_replace" model="rma.operation">
|
||||
<field name="name">Replace After Receive</field>
|
||||
<field name="code">RPLC</field>
|
||||
<field name="refund_policy">no</field>
|
||||
<field name="receipt_policy">ordered</field>
|
||||
<field name="delivery_policy">received</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_replace" model="rma.operation">
|
||||
<field name="name">Replace</field>
|
||||
<field name="code">RPLS</field>
|
||||
<field name="refund_policy">no</field>
|
||||
<field name="receipt_policy">ordered</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>
|
||||
|
||||
<record id="rma_operation_customer_refund" model="rma.operation">
|
||||
<field name="name">Refund before receive</field>
|
||||
<field name="code">RFC</field>
|
||||
<field name="refund_policy">ordered</field>
|
||||
<field name="receipt_policy">no</field>
|
||||
<field name="delivery_policy">no</field>
|
||||
<field name="type">customer</field>
|
||||
<field name="in_route_id" ref="rma.route_rma_customer"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_operation_supplier_refund" model="rma.operation">
|
||||
<field name="name">Refund only</field>
|
||||
<field name="code">RFS</field>
|
||||
<field name="refund_policy">ordered</field>
|
||||
<field name="receipt_policy">no</field>
|
||||
<field name="delivery_policy">no</field>
|
||||
<field name="type">supplier</field>
|
||||
<field name="out_route_id" ref="rma.route_rma_supplier"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_operation_ds_replace" model="rma.operation">
|
||||
<field name="name">Replace deliver to vendor</field>
|
||||
<field name="code">DSRPLB</field>
|
||||
<field name="refund_policy">no</field>
|
||||
<field name="receipt_policy">ordered</field>
|
||||
<field name="delivery_policy">no</field>
|
||||
<field name="type">customer</field>
|
||||
<field name="out_route_id" ref="rma.route_rma_dropship"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_operation_ds_replace_customer" model="rma.operation">
|
||||
<field name="name">Replace receive in vendor</field>
|
||||
<field name="code">DSRPLV</field>
|
||||
<field name="refund_policy">no</field>
|
||||
<field name="receipt_policy">no</field>
|
||||
<field name="delivery_policy">received</field>
|
||||
<field name="type">customer</field>
|
||||
<field name="out_route_id" ref="rma.route_rma_dropship"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_operation_ds_replace_supplier" model="rma.operation">
|
||||
<field name="name">Replace deliver to customer</field>
|
||||
<field name="code">DSRPC</field>
|
||||
<field name="refund_policy">no</field>
|
||||
<field name="receipt_policy">no</field>
|
||||
<field name="delivery_policy">received</field>
|
||||
<field name="type">supplier</field>
|
||||
<field name="out_route_id" ref="rma.route_rma_dropship"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_rule_always" model="rma.rule">
|
||||
<field name="name">Always</field>
|
||||
<field name="code">alw</field>
|
||||
<field name="approval_policy">always</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
39
rma/data/rma_sequence.xml
Normal file
39
rma/data/rma_sequence.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
<record id="rma_seq" model="ir.sequence">
|
||||
<field name="name">Customer RMA sequence</field>
|
||||
<field name="code">rma.order.customer</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="prefix">RMA/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_supplier_seq" model="ir.sequence">
|
||||
<field name="name">Supplier RMA sequence</field>
|
||||
<field name="code">rma.order.supplier</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="prefix">RTV/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_line_seq" model="ir.sequence">
|
||||
<field name="name">Customer RMA Line sequence</field>
|
||||
<field name="code">rma.order.line.customer</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="prefix">RMAL/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
</record>
|
||||
|
||||
<record id="rma_line_supplier_seq" model="ir.sequence">
|
||||
<field name="name">Supplier RMA Line sequence</field>
|
||||
<field name="code">rma.order.line.supplier</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="prefix">RTVL/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
212
rma/data/stock_data.xml
Normal file
212
rma/data/stock_data.xml
Normal file
@@ -0,0 +1,212 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
<record id="location_rma" model="stock.location">
|
||||
<field name="name">WH RMA</field>
|
||||
<field name="usage">internal</field>
|
||||
<field name="location_id" ref="stock.stock_location_stock"/>
|
||||
</record>
|
||||
|
||||
<record id="seq_picking_type_rma_cust_out" model="ir.sequence">
|
||||
<field name="name">DOC</field>
|
||||
<field name="prefix">RCO</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="seq_picking_type_rma_cust_in" model="ir.sequence">
|
||||
<field name="name">INC</field>
|
||||
<field name="prefix">RCI</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="seq_picking_type_rma_sup_out" model="ir.sequence">
|
||||
<field name="name">DOS</field>
|
||||
<field name="prefix">RSO</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="seq_picking_type_rma_sup_in" model="ir.sequence">
|
||||
<field name="name">INS</field>
|
||||
<field name="prefix">RSI</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="seq_picking_type_rma_dropship" model="ir.sequence">
|
||||
<field name="name">DSS</field>
|
||||
<field name="prefix">DSS</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="picking_type_rma_cust_out" model="stock.picking.type">
|
||||
<field name="name">RMA → Customer</field>
|
||||
<field name="sequence_id" ref="seq_picking_type_rma_cust_out"/>
|
||||
<field name="default_location_src_id" ref="rma.location_rma"/>
|
||||
<field name="default_location_dest_id"
|
||||
ref="stock.stock_location_customers"/>
|
||||
<field name="warehouse_id" eval="False"/>
|
||||
<field name="code">outgoing</field>
|
||||
</record>
|
||||
|
||||
<record id="picking_type_rma_cust_in" model="stock.picking.type">
|
||||
<field name="name">Customer → RMA</field>
|
||||
<field name="sequence_id" ref="seq_picking_type_rma_cust_in"/>
|
||||
<field name="default_location_src_id" ref="stock.stock_location_customers"/>
|
||||
<field name="default_location_dest_id"
|
||||
ref="rma.location_rma"/>
|
||||
<field name="warehouse_id" eval="False"/>
|
||||
<field name="code">incoming</field>
|
||||
</record>
|
||||
|
||||
<record id="picking_type_rma_sup_out" model="stock.picking.type">
|
||||
<field name="name">RMA -> Supplier</field>
|
||||
<field name="sequence_id" ref="seq_picking_type_rma_sup_out"/>
|
||||
<field name="default_location_src_id" ref="rma.location_rma"/>
|
||||
<field name="default_location_dest_id"
|
||||
ref="stock.stock_location_suppliers"/>
|
||||
<field name="warehouse_id" eval="False"/>
|
||||
<field name="code">outgoing</field>
|
||||
</record>
|
||||
|
||||
<record id="picking_type_rma_sup_in" model="stock.picking.type">
|
||||
<field name="name">Supplier -> RMA</field>
|
||||
<field name="sequence_id" ref="seq_picking_type_rma_sup_in"/>
|
||||
<field name="default_location_src_id" ref="stock.stock_location_suppliers"/>
|
||||
<field name="default_location_dest_id"
|
||||
ref="rma.location_rma"/>
|
||||
<field name="warehouse_id" eval="False"/>
|
||||
<field name="code">incoming</field>
|
||||
</record>
|
||||
|
||||
<record id="picking_type_rma_dropship_return" model="stock.picking.type">
|
||||
<field name="name">Customer -> Supplier</field>
|
||||
<field name="sequence_id" ref="seq_picking_type_rma_dropship"/>
|
||||
<field name="default_location_src_id"
|
||||
ref="stock.stock_location_customers"/>
|
||||
<field name="default_location_dest_id"
|
||||
ref="stock.stock_location_suppliers"/>
|
||||
<field name="warehouse_id" eval="False"/>
|
||||
<field name="code">incoming</field>
|
||||
</record>
|
||||
|
||||
<record id="picking_type_rma_dropship" model="stock.picking.type">
|
||||
<field name="name">Supplier -> Customer</field>
|
||||
<field name="sequence_id" ref="seq_picking_type_rma_dropship"/>
|
||||
<field name="default_location_src_id"
|
||||
ref="stock.stock_location_suppliers"/>
|
||||
<field name="default_location_dest_id"
|
||||
ref="stock.stock_location_customers"/>
|
||||
<field name="warehouse_id" eval="False"/>
|
||||
<field name="code">incoming</field>
|
||||
</record>
|
||||
|
||||
<record id="stock.warehouse0" model="stock.warehouse">
|
||||
<field name="lot_rma_id" ref="location_rma"/>
|
||||
<field name="rma_cust_out_type_id" ref="picking_type_rma_cust_out"/>
|
||||
<field name="rma_cust_in_type_id" ref="picking_type_rma_cust_in"/>
|
||||
<field name="rma_sup_out_type_id" ref="picking_type_rma_sup_out"/>
|
||||
<field name="rma_sup_in_type_id" ref="picking_type_rma_sup_in"/>
|
||||
</record>
|
||||
|
||||
<record id="route_rma_customer" model='stock.location.route'>
|
||||
<field name="name">RMA Customer</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="sale_selectable" eval="False"/>
|
||||
<field name="product_selectable" eval="False"/>
|
||||
<field name="product_categ_selectable" eval="False"/>
|
||||
<field name="warehouse_selectable" eval="False"/>
|
||||
<field name="rma_selectable" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="route_rma_supplier" model='stock.location.route'>
|
||||
<field name="name">RMA Supplier</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="sale_selectable" eval="False"/>
|
||||
<field name="product_selectable" eval="False"/>
|
||||
<field name="product_categ_selectable" eval="False"/>
|
||||
<field name="warehouse_selectable" eval="False"/>
|
||||
<field name="rma_selectable" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="route_rma_dropship" model='stock.location.route'>
|
||||
<field name="name">RMA Dropship</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="sale_selectable" eval="False"/>
|
||||
<field name="product_selectable" eval="False"/>
|
||||
<field name="product_categ_selectable" eval="False"/>
|
||||
<field name="warehouse_selectable" eval="False"/>
|
||||
<field name="rma_selectable" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="rule_rma_customer_in_pull" model="procurement.rule">
|
||||
<field name="name">Customer → RMA</field>
|
||||
<field name="action">move</field>
|
||||
<field name="warehouse_id" ref="stock.warehouse0"/>
|
||||
<field name="location_src_id" ref="stock.stock_location_customers"/>
|
||||
<field name="location_id" ref="rma.location_rma"/>
|
||||
<field name="procure_method">make_to_stock</field>
|
||||
<field name="route_id" ref="rma.route_rma_customer"/>
|
||||
<field name="picking_type_id" ref="rma.picking_type_rma_cust_in"/>
|
||||
</record>
|
||||
|
||||
<record id="rule_rma_customer_out_pull" model="procurement.rule">
|
||||
<field name="name">RMA → Customer</field>
|
||||
<field name="action">move</field>
|
||||
<field name="warehouse_id" ref="stock.warehouse0"/>
|
||||
<field name="location_src_id" ref="rma.location_rma"/>
|
||||
<field name="location_id" ref="stock.stock_location_customers"/>
|
||||
<field name="procure_method">make_to_stock</field>
|
||||
<field name="route_id" ref="rma.route_rma_customer"/>
|
||||
<field name="picking_type_id" ref="rma.picking_type_rma_cust_out"/>
|
||||
</record>
|
||||
|
||||
<record id="rule_rma_supplier_out_pull" model="procurement.rule">
|
||||
<field name="name">RMA → 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="rma.location_rma"/>
|
||||
<field name="procure_method">make_to_stock</field>
|
||||
<field name="route_id" ref="rma.route_rma_supplier"/>
|
||||
<field name="picking_type_id" ref="rma.picking_type_rma_sup_out"/>
|
||||
</record>
|
||||
|
||||
<record id="rule_rma_supplier_in_pull" model="procurement.rule">
|
||||
<field name="name">Supplier → RMA</field>
|
||||
<field name="action">move</field>
|
||||
<field name="warehouse_id" ref="stock.warehouse0"/>
|
||||
<field name="location_id" ref="rma.location_rma"/>
|
||||
<field name="location_src_id" ref="stock.stock_location_suppliers"/>
|
||||
<field name="procure_method">make_to_stock</field>
|
||||
<field name="route_id" ref="rma.route_rma_supplier"/>
|
||||
<field name="picking_type_id" ref="rma.picking_type_rma_sup_in"/>
|
||||
</record>
|
||||
|
||||
<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>
|
||||
<field name="route_id" ref="rma.route_rma_dropship"/>
|
||||
<field name="picking_type_id"
|
||||
ref="rma.picking_type_rma_dropship_return"/>
|
||||
</record>
|
||||
|
||||
<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>
|
||||
<field name="route_id" ref="rma.route_rma_dropship"/>
|
||||
<field name="picking_type_id"
|
||||
ref="rma.picking_type_rma_dropship"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
19
rma/demo/stock_demo.xml
Normal file
19
rma/demo/stock_demo.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="location_rma_shop0" model="stock.location">
|
||||
<field name="name">RMA</field>
|
||||
<field name="usage">internal</field>
|
||||
<field name="location_id" ref="stock.stock_location_shop0"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="stock.stock_warehouse_shop0" model="stock.warehouse">
|
||||
<field name="lot_rma_id" ref="location_rma_shop0"/>
|
||||
<field name="rma_cust_out_type_id" ref="picking_type_rma_cust_out"/>
|
||||
<field name="rma_cust_in_type_id" ref="picking_type_rma_cust_in"/>
|
||||
<field name="rma_sup_out_type_id" ref="picking_type_rma_sup_out"/>
|
||||
<field name="rma_sup_in_type_id" ref="picking_type_rma_sup_in"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
13
rma/models/__init__.py
Normal file
13
rma/models/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# -*- 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 rma_order
|
||||
from . import rma_order_line
|
||||
from . import rma_operation
|
||||
from . import rma_rule
|
||||
from . import stock
|
||||
from . import stock_warehouse
|
||||
from . import product
|
||||
from . import procurement
|
||||
from . import res_company
|
||||
29
rma/models/procurement.py
Normal file
29
rma/models/procurement.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# -*- 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 import api, fields, models
|
||||
|
||||
|
||||
class ProcurementOrder(models.Model):
|
||||
_inherit = 'procurement.order'
|
||||
|
||||
rma_line_id = fields.Many2one('rma.order.line', 'RMA', ondelete="set null")
|
||||
|
||||
@api.model
|
||||
def _run_move_create(self, procurement):
|
||||
res = super(ProcurementOrder, self)._run_move_create(procurement)
|
||||
if procurement.rma_line_id:
|
||||
line = procurement.rma_line_id
|
||||
res['rma_line_id'] = line.id
|
||||
if line.delivery_address_id and line.delivery_address_id.id:
|
||||
res['partner_id'] = line.delivery_address_id.id
|
||||
elif line.invoice_line_id.invoice_id.partner_id:
|
||||
res['partner_id'] = line.invoice_id.partner_id.id
|
||||
return res
|
||||
|
||||
|
||||
class ProcurementGroup(models.Model):
|
||||
_inherit = 'procurement.group'
|
||||
|
||||
rma_id = fields.Many2one('rma.order', 'RMA', ondelete="set null")
|
||||
19
rma/models/product.py
Normal file
19
rma/models/product.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp import fields, models
|
||||
|
||||
|
||||
class ProductCategory(models.Model):
|
||||
_inherit = 'product.category'
|
||||
|
||||
rma_operation_id = fields.Many2one(
|
||||
comodel_name="rma.operation", string="RMA Operation")
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
rma_operation_id = fields.Many2one(
|
||||
comodel_name="rma.operation", string="RMA Operation")
|
||||
11
rma/models/res_company.py
Normal file
11
rma/models/res_company.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# -*- 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 import models, fields
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
rma_rule_id = fields.Many2one('rma.rule', 'Default RMA Approval Policy')
|
||||
63
rma/models/rma_operation.py
Normal file
63
rma/models/rma_operation.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# -*- 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 import _, api, fields, models
|
||||
|
||||
|
||||
class RmaOperation(models.Model):
|
||||
_name = 'rma.operation'
|
||||
_description = 'RMA Operation'
|
||||
|
||||
@api.model
|
||||
def _default_warehouse_id(self):
|
||||
company = self.env.user.company_id.id
|
||||
warehouse = self.env['stock.warehouse'].search(
|
||||
[('company_id', '=', company)], limit=1)
|
||||
return warehouse
|
||||
|
||||
@api.model
|
||||
def _default_customer_location_id(self):
|
||||
return self.env.ref('stock.stock_location_customers') or False
|
||||
|
||||
@api.model
|
||||
def _default_supplier_location_id(self):
|
||||
return self.env.ref('stock.stock_location_suppliers') or False
|
||||
|
||||
name = fields.Char('Description', required=True)
|
||||
code = fields.Char('Code', required=True)
|
||||
refund_policy = fields.Selection([
|
||||
('no', 'No refund'), ('ordered', 'Based on Ordered Quantities'),
|
||||
('received', 'Based on Received Quantities')], string="Refund Policy",
|
||||
default='no')
|
||||
receipt_policy = fields.Selection([
|
||||
('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'),
|
||||
('received', 'Based on Delivered Quantities')],
|
||||
string="Receipts Policy", default='no')
|
||||
delivery_policy = fields.Selection([
|
||||
('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'),
|
||||
('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)])
|
||||
out_route_id = fields.Many2one(
|
||||
'stock.location.route', string='Outbound Route',
|
||||
domain=[('rma_selectable', '=', True)])
|
||||
customer_to_supplier= fields.Boolean(
|
||||
'The customer will send to the supplier', default=False)
|
||||
supplier_to_customer = fields.Boolean(
|
||||
'The supplier will send to the customer', default=False)
|
||||
in_warehouse_id = fields.Many2one('stock.warehouse',
|
||||
string='Inbound Warehouse',
|
||||
default=_default_warehouse_id)
|
||||
out_warehouse_id = fields.Many2one('stock.warehouse',
|
||||
string='Outbound Warehouse',
|
||||
default=_default_warehouse_id)
|
||||
location_id = fields.Many2one(
|
||||
'stock.location', 'Send To This Company Location')
|
||||
type = fields.Selection([
|
||||
('customer', 'Customer'), ('supplier', 'Supplier')],
|
||||
string="Used in RMA of this type", required=True, default='customer')
|
||||
rma_line_ids = fields.One2many('rma.order.line', 'operation_id',
|
||||
'RMA lines')
|
||||
234
rma/models/rma_order.py
Normal file
234
rma/models/rma_order.py
Normal file
@@ -0,0 +1,234 @@
|
||||
# -*- 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 import _, api, fields, models
|
||||
from openerp.addons import decimal_precision as dp
|
||||
from openerp.exceptions import UserError
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class RmaOrder(models.Model):
|
||||
_name = "rma.order"
|
||||
_inherit = ['mail.thread']
|
||||
|
||||
@api.model
|
||||
def _compute_rule_id(self):
|
||||
if self.company_id and self.company_id.id:
|
||||
if self.company_id.rma_rule_id and self.company_id.rma_rule_id.id:
|
||||
self.rule_id = self.company_id.rma_rule_id
|
||||
|
||||
@api.model
|
||||
def _get_default_type(self):
|
||||
if 'supplier' in self.env.context:
|
||||
return "supplier"
|
||||
else:
|
||||
return "customer"
|
||||
|
||||
@api.multi
|
||||
def _compute_in_shipment_count(self):
|
||||
for rec in self:
|
||||
rec.in_shipment_count = len(rec.rma_line_ids.mapped(
|
||||
'procurement_ids.move_ids').filtered(
|
||||
lambda m: m.location_dest_id.usage == 'internal').mapped(
|
||||
'picking_id'))
|
||||
|
||||
@api.multi
|
||||
def _compute_out_shipment_count(self):
|
||||
for rec in self:
|
||||
rec.out_shipment_count = len(rec.rma_line_ids.mapped(
|
||||
'procurement_ids.move_ids').filtered(
|
||||
lambda m: m.location_id.usage == 'internal').mapped(
|
||||
'picking_id'))
|
||||
|
||||
@api.multi
|
||||
def _compute_supplier_line_count(self):
|
||||
self.supplier_line_count = len(self.rma_line_ids.filtered(
|
||||
lambda r: r.supplier_rma_line_ids))
|
||||
|
||||
@api.multi
|
||||
def _compute_line_count(self):
|
||||
self.ensure_one()
|
||||
self.line_count = len(self._get_valid_lines())
|
||||
|
||||
name = fields.Char(string='Order Number', index=True,
|
||||
readonly=True,
|
||||
states={'progress': [('readonly', False)]},
|
||||
copy=False)
|
||||
type = fields.Selection(
|
||||
[('customer', 'Customer'), ('supplier', 'Supplier')],
|
||||
string="Type", required=True, default=_get_default_type, readonly=True)
|
||||
reference = fields.Char(string='Reference',
|
||||
help="The partner reference of this RMA order.")
|
||||
|
||||
comment = fields.Text('Additional Information', readonly=True, states={
|
||||
'draft': [('readonly', False)]})
|
||||
|
||||
state = fields.Selection([('draft', 'Draft'), ('to_approve', 'To Approve'),
|
||||
('approved', 'Approved'),
|
||||
('done', 'Done')], string='State', index=True,
|
||||
default='draft')
|
||||
date_rma = fields.Datetime(string='Order Date', index=True, copy=False)
|
||||
partner_id = fields.Many2one('res.partner', string='Partner',
|
||||
required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)]})
|
||||
assigned_to = fields.Many2one('res.users', 'Assigned to',
|
||||
track_visibility='onchange')
|
||||
requested_by = fields.Many2one('res.users', 'Requested by',
|
||||
track_visibility='onchange',
|
||||
default=lambda self: self.env.user)
|
||||
rule_id = fields.Many2one('rma.rule', string='Approval Criteria',
|
||||
compute=_compute_rule_id)
|
||||
rma_line_ids = fields.One2many('rma.order.line', 'rma_id',
|
||||
string='RMA lines')
|
||||
in_shipment_count = fields.Integer(compute=_compute_in_shipment_count,
|
||||
string='# of Invoices')
|
||||
out_shipment_count = fields.Integer(compute=_compute_out_shipment_count,
|
||||
string='# of Outgoing Shipments')
|
||||
line_count = fields.Integer(compute=_compute_line_count,
|
||||
string='# of Outgoing Shipments',
|
||||
copy=False)
|
||||
supplier_line_count = fields.Integer(compute=_compute_supplier_line_count,
|
||||
string='# of Outgoing Shipments',
|
||||
copy=False)
|
||||
company_id = fields.Many2one('res.company', string='Company',
|
||||
required=True, default=lambda self:
|
||||
self.env.user.company_id)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if self.env.context.get('supplier'):
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code(
|
||||
'rma.order.supplier')
|
||||
else:
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code(
|
||||
'rma.order.customer')
|
||||
return super(RmaOrder, self).create(vals)
|
||||
|
||||
@api.multi
|
||||
def action_view_in_shipments(self):
|
||||
action = self.env.ref('stock.action_picking_tree_all')
|
||||
result = action.read()[0]
|
||||
picking_ids = []
|
||||
suppliers = self.env.ref('stock.stock_location_suppliers')
|
||||
customers = self.env.ref('stock.stock_location_customers')
|
||||
for line in self.rma_line_ids:
|
||||
if line.type == 'customer':
|
||||
for move in line.move_ids:
|
||||
if move.picking_id.location_id == customers:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
else:
|
||||
for move in line.move_ids:
|
||||
if move.picking_id.location_id == suppliers:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
shipments = list(set(picking_ids))
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) != 1:
|
||||
result['domain'] = "[('id', 'in', " + \
|
||||
str(shipments) + ")]"
|
||||
elif len(shipments) == 1:
|
||||
res = self.env.ref('stock.view_picking_form', False)
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = shipments[0]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_view_out_shipments(self):
|
||||
action = self.env.ref('stock.action_picking_tree_all')
|
||||
result = action.read()[0]
|
||||
picking_ids = []
|
||||
suppliers = self.env.ref('stock.stock_location_suppliers')
|
||||
customers = self.env.ref('stock.stock_location_customers')
|
||||
for line in self.rma_line_ids:
|
||||
if line.type == 'customer':
|
||||
for move in line.move_ids:
|
||||
if move.picking_id.location_id != customers:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
else:
|
||||
for move in line.move_ids:
|
||||
if move.picking_id.location_id != suppliers:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
shipments = list(set(picking_ids))
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) != 1:
|
||||
result['domain'] = "[('id', 'in', " + \
|
||||
str(shipments) + ")]"
|
||||
elif len(shipments) == 1:
|
||||
res = self.env.ref('stock.view_picking_form', False)
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = shipments[0]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_rma_to_approve(self):
|
||||
for rec in self:
|
||||
rec.state = 'to_approve'
|
||||
if rec.rule_id and rec.rule_id.id:
|
||||
if rec.rule_id.approval_policy == 'always':
|
||||
rec.assigned_to = self.env.uid
|
||||
rec.action_rma_approve()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_rma_draft(self):
|
||||
for rec in self:
|
||||
rec.state = 'draft'
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_rma_approve(self):
|
||||
# pass the supplier address in case this is a customer RMA
|
||||
for rec in self:
|
||||
rec.state = 'approved'
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_rma_done(self):
|
||||
for rec in self:
|
||||
rec.state = 'done'
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _get_valid_lines(self):
|
||||
self.ensure_one()
|
||||
return self.rma_line_ids
|
||||
|
||||
@api.multi
|
||||
def action_view_lines(self):
|
||||
if self.type == 'customer':
|
||||
action = self.env.ref('rma.action_rma_customer_lines')
|
||||
else:
|
||||
action = self.env.ref('rma.action_rma_supplier_lines')
|
||||
result = action.read()[0]
|
||||
lines = self._get_valid_lines()
|
||||
# choose the view_mode accordingly
|
||||
if len(lines) != 1:
|
||||
result['domain'] = "[('id', 'in', " + \
|
||||
str(lines.ids) + ")]"
|
||||
elif len(lines) == 1:
|
||||
if self.type == 'customer':
|
||||
res = self.env.ref('rma.view_rma_line_form', False)
|
||||
else:
|
||||
res = self.env.ref('rma.view_rma_line_supplier_form', False)
|
||||
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = lines.id
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_view_supplier_lines(self):
|
||||
action = self.env.ref('rma.action_rma_supplier_lines')
|
||||
result = action.read()[0]
|
||||
lines = self.rma_line_ids
|
||||
related_lines = [line.id for line in lines.children_ids]
|
||||
# choose the view_mode accordingly
|
||||
if len(related_lines) != 1:
|
||||
result['domain'] = "[('id', 'in', " + \
|
||||
str(related_lines) + ")]"
|
||||
elif len(related_lines) == 1:
|
||||
res = self.env.ref('rma.view_rma_line_supplier_form', False)
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = related_lines[0]
|
||||
return result
|
||||
423
rma/models/rma_order_line.py
Normal file
423
rma/models/rma_order_line.py
Normal file
@@ -0,0 +1,423 @@
|
||||
# -*- 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 import _, api, fields, models
|
||||
from openerp.addons import decimal_precision as dp
|
||||
import operator
|
||||
ops = {'=': operator.eq,
|
||||
'!=': operator.ne}
|
||||
|
||||
|
||||
class RmaOrderLine(models.Model):
|
||||
_name = "rma.order.line"
|
||||
_rec_name = "rma_id"
|
||||
|
||||
@api.model
|
||||
def _default_warehouse_id(self):
|
||||
rma_id = self.env.context.get('default_rma_id', False)
|
||||
warehouse = self.env['stock.warehouse']
|
||||
if rma_id:
|
||||
rma = self.env['rma.order'].browse(rma_id)
|
||||
warehouse = self.env['stock.warehouse'].search(
|
||||
[('company_id', '=', rma.company_id.id)], limit=1)
|
||||
return warehouse
|
||||
|
||||
@api.model
|
||||
def _default_location_id(self):
|
||||
wh = self._default_warehouse_id()
|
||||
return wh.lot_rma_id
|
||||
|
||||
@api.model
|
||||
def _default_delivery_address(self):
|
||||
partner_id = self.env.context.get('partner_id', False)
|
||||
if partner_id:
|
||||
partner = self.env['res.partner'].browse(partner_id)
|
||||
addr = partner.address_get(['delivery'])
|
||||
return self.env['res.partner'].browse(addr['delivery'])
|
||||
return False
|
||||
|
||||
@api.multi
|
||||
def _compute_in_shipment_count(self):
|
||||
for line in self:
|
||||
moves = line.procurement_ids.mapped('move_ids').filtered(
|
||||
lambda m: m.location_dest_id.usage == 'internal')
|
||||
pickings = moves.mapped('picking_id')
|
||||
line.in_shipment_count = len(pickings)
|
||||
|
||||
@api.multi
|
||||
def _compute_out_shipment_count(self):
|
||||
for line in self:
|
||||
moves = line.procurement_ids.mapped('move_ids').filtered(
|
||||
lambda m: m.location_dest_id.usage != 'internal')
|
||||
pickings = moves.mapped('picking_id')
|
||||
line.out_shipment_count = len(pickings)
|
||||
|
||||
@api.multi
|
||||
def _get_rma_move_qty(self, states, direction='in'):
|
||||
for rec in self:
|
||||
product_obj = self.env['product.uom']
|
||||
qty = 0.0
|
||||
if direction == 'in':
|
||||
op = ops['=']
|
||||
else:
|
||||
op = ops['!=']
|
||||
for move in rec.procurement_ids.mapped('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)
|
||||
return qty
|
||||
|
||||
@api.multi
|
||||
@api.depends('move_ids', 'move_ids.state', 'qty_received',
|
||||
'receipt_policy', 'product_qty', 'type')
|
||||
def _compute_qty_to_receive(self):
|
||||
for rec in self:
|
||||
rec.qty_to_receive = 0.0
|
||||
if rec.receipt_policy == 'ordered':
|
||||
rec.qty_to_receive = rec.product_qty - rec.qty_received
|
||||
elif self.receipt_policy == 'delivered':
|
||||
self.qty_to_receive = rec.qty_delivered - rec.qty_received
|
||||
|
||||
@api.multi
|
||||
@api.depends('move_ids', 'move_ids.state',
|
||||
'delivery_policy', 'product_qty', 'type', 'qty_delivered',
|
||||
'qty_received')
|
||||
def _compute_qty_to_deliver(self):
|
||||
for rec in self:
|
||||
rec.qty_to_deliver = 0.0
|
||||
if rec.delivery_policy == 'ordered':
|
||||
rec.qty_to_deliver = rec.product_qty - rec.qty_delivered
|
||||
elif self.delivery_policy == 'received':
|
||||
self.qty_to_deliver = rec.qty_received - rec.qty_delivered
|
||||
|
||||
@api.multi
|
||||
@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')
|
||||
rec.qty_incoming = qty
|
||||
|
||||
@api.multi
|
||||
@api.depends('move_ids', 'move_ids.state', 'type')
|
||||
def _compute_qty_received(self):
|
||||
for rec in self:
|
||||
qty = rec._get_rma_move_qty('done', direction='in')
|
||||
rec.qty_received = qty
|
||||
|
||||
@api.multi
|
||||
@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')
|
||||
rec.qty_outgoing = qty
|
||||
|
||||
@api.multi
|
||||
@api.depends('move_ids', 'move_ids.state', 'type')
|
||||
def _compute_qty_delivered(self):
|
||||
for rec in self:
|
||||
qty = rec._get_rma_move_qty('done', direction='out')
|
||||
rec.qty_delivered = qty
|
||||
|
||||
@api.model
|
||||
def _get_supplier_rma_qty(self):
|
||||
return sum(self.supplier_rma_line_ids.filtered(
|
||||
lambda r: r.state != 'cancel').mapped(
|
||||
'product_qty'))
|
||||
|
||||
@api.multi
|
||||
@api.depends('customer_to_supplier', 'supplier_rma_line_ids',
|
||||
'supplier_rma_line_ids.rma_id.state',
|
||||
'move_ids', 'move_ids.state', 'qty_received',
|
||||
'receipt_policy', 'product_qty', 'type')
|
||||
def _compute_qty_supplier_rma(self):
|
||||
for rec in self:
|
||||
qty = rec._get_supplier_rma_qty()
|
||||
rec.qty_to_supplier_rma = rec.qty_to_receive - qty
|
||||
rec.qty_in_supplier_rma = qty
|
||||
|
||||
@api.multi
|
||||
def _compute_procurement_count(self):
|
||||
for rec in self:
|
||||
rec.procurement_count = len(rec.procurement_ids.filtered(
|
||||
lambda p: p.state == 'exception'))
|
||||
|
||||
delivery_address_id = fields.Many2one(
|
||||
'res.partner', string='Partner delivery address',
|
||||
default=_default_delivery_address,
|
||||
help="This address will be used to "
|
||||
"deliver repaired or replacement products.")
|
||||
|
||||
rma_id = fields.Many2one('rma.order', string='RMA',
|
||||
ondelete='cascade', required=True)
|
||||
name = fields.Char(string='Reference', required=True, default='/',
|
||||
help='Add here the supplier RMA #. Otherwise an '
|
||||
'internal code is assigned.')
|
||||
description = fields.Text(string='Description')
|
||||
origin = fields.Char(string='Source Document',
|
||||
help="Reference of the document that produced "
|
||||
"this rma.")
|
||||
state = fields.Selection(related='rma_id.state')
|
||||
operation_id = fields.Many2one(
|
||||
comodel_name="rma.operation", string="Operation")
|
||||
|
||||
assigned_to = fields.Many2one('res.users', related='rma_id.assigned_to')
|
||||
requested_by = fields.Many2one('res.users', related='rma_id.requested_by')
|
||||
partner_id = fields.Many2one('res.partner', related='rma_id.partner_id',
|
||||
store=True)
|
||||
sequence = fields.Integer(default=10,
|
||||
help="Gives the sequence of this line "
|
||||
"when displaying the rma.")
|
||||
product_id = fields.Many2one('product.product', string='Product',
|
||||
ondelete='restrict', required=-True)
|
||||
product_tracking = fields.Selection(related="product_id.tracking")
|
||||
lot_id = fields.Many2one(
|
||||
comodel_name="stock.production.lot", string="Lot/Serial Number",
|
||||
readonly=True, states={"new": [("readonly", False)]},
|
||||
)
|
||||
product_qty = fields.Float(
|
||||
string='Ordered Qty', copy=False,
|
||||
digits=dp.get_precision('Product Unit of Measure'))
|
||||
uom_id = fields.Many2one('product.uom', string='Unit of Measure',
|
||||
required=True)
|
||||
price_unit = fields.Monetary(string='Price Unit', readonly=False,
|
||||
states={'approved': [('readonly', True)],
|
||||
'done': [('readonly', True)],
|
||||
'to_approve': [('readonly', True)]})
|
||||
|
||||
procurement_count = fields.Integer(compute=_compute_procurement_count,
|
||||
string='# of Procurements', copy=False,
|
||||
default=0)
|
||||
in_shipment_count = fields.Integer(compute=_compute_in_shipment_count,
|
||||
string='# of Shipments', default=0)
|
||||
out_shipment_count = fields.Integer(compute=_compute_out_shipment_count,
|
||||
string='# of Deliveries', default=0)
|
||||
move_ids = fields.One2many('stock.move', 'rma_line_id',
|
||||
string='Stock Moves', readonly=True
|
||||
, copy=False)
|
||||
reference_move_id = fields.Many2one(comodel_name='stock.move',
|
||||
string='Originating stock move',
|
||||
readonly=True, copy=False)
|
||||
procurement_ids = fields.One2many('procurement.order', 'rma_line_id',
|
||||
string='Procurements', readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
copy=False)
|
||||
currency_id = fields.Many2one('res.currency', string="Currency")
|
||||
company_id = fields.Many2one('res.company', string='Company',
|
||||
related='rma_id.company_id', store=True)
|
||||
type = fields.Selection(related='rma_id.type')
|
||||
customer_to_supplier = fields.Boolean(
|
||||
'The customer will send to the supplier')
|
||||
supplier_to_customer = fields.Boolean(
|
||||
'The supplier will send to the customer')
|
||||
receipt_policy = fields.Selection([
|
||||
('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'),
|
||||
('delivered', 'Based on Delivered Quantities')],
|
||||
required=True, string="Receipts Policy")
|
||||
delivery_policy = fields.Selection([
|
||||
('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'),
|
||||
('received', 'Based on Received Quantities')], required=True,
|
||||
string="Delivery Policy")
|
||||
in_route_id = fields.Many2one(
|
||||
'stock.location.route', string='Inbound Route',
|
||||
required=True,
|
||||
domain=[('rma_selectable', '=', True)])
|
||||
out_route_id = fields.Many2one(
|
||||
'stock.location.route', string='Outbound Route',
|
||||
required=True,
|
||||
domain=[('rma_selectable', '=', True)])
|
||||
in_warehouse_id = fields.Many2one('stock.warehouse',
|
||||
string='Inbound Warehouse',
|
||||
required=True,
|
||||
default=_default_warehouse_id)
|
||||
out_warehouse_id = fields.Many2one('stock.warehouse',
|
||||
string='Outbound Warehouse',
|
||||
required=True,
|
||||
default=_default_warehouse_id)
|
||||
location_id = fields.Many2one(
|
||||
'stock.location', 'Send To This Company Location', required=True,
|
||||
default=_default_location_id)
|
||||
customer_rma_id = fields.Many2one(
|
||||
'rma.order.line', string='Customer RMA line', ondelete='cascade')
|
||||
supplier_rma_line_ids = fields.One2many('rma.order.line', 'customer_rma_id')
|
||||
supplier_address_id = fields.Many2one(
|
||||
'res.partner', readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
string='Supplier Address',
|
||||
help="This address of the supplier in case of Customer RMA operation "
|
||||
"dropship.")
|
||||
qty_to_receive = fields.Float(
|
||||
string='Qty To Receive',
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
compute=_compute_qty_to_receive, store=True)
|
||||
qty_incoming = fields.Float(
|
||||
string='Incoming Qty', copy=False,
|
||||
readonly=True, digits=dp.get_precision('Product Unit of Measure'),
|
||||
compute=_compute_qty_incoming, store=True)
|
||||
qty_received = fields.Float(
|
||||
string='Qty Received', copy=False,
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
compute=_compute_qty_received,
|
||||
store=True)
|
||||
qty_to_deliver = fields.Float(
|
||||
string='Qty To Deliver', copy=False,
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True, compute=_compute_qty_to_deliver,
|
||||
store=True)
|
||||
qty_outgoing = fields.Float(
|
||||
string='Outgoing Qty', copy=False,
|
||||
readonly=True, digits=dp.get_precision('Product Unit of Measure'),
|
||||
compute=_compute_qty_outgoing,
|
||||
store=True)
|
||||
qty_delivered = fields.Float(
|
||||
string='Qty Delivered', copy=False,
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True, compute=_compute_qty_delivered,
|
||||
store=True)
|
||||
qty_to_supplier_rma = fields.Float(
|
||||
string='Qty to send to Supplier RMA',
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True, compute=_compute_qty_supplier_rma,
|
||||
store=True)
|
||||
qty_in_supplier_rma = fields.Float(
|
||||
string='Qty in Supplier RMA',
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True, compute=_compute_qty_supplier_rma,
|
||||
store=True)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if self.env.context.get('supplier'):
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code(
|
||||
'rma.order.line.supplier')
|
||||
else:
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code(
|
||||
'rma.order.line.customer')
|
||||
return super(RmaOrderLine, self).create(vals)
|
||||
|
||||
@api.onchange('product_id')
|
||||
def _onchange_product_id(self):
|
||||
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
|
||||
self.operation_id = self.product_id.rma_operation_id or \
|
||||
self.product_id.categ_id.rma_operation_id
|
||||
return result
|
||||
|
||||
@api.onchange('operation_id')
|
||||
def _onchange_operation_id(self):
|
||||
result = {}
|
||||
if not self.operation_id:
|
||||
return result
|
||||
self.receipt_policy = self.operation_id.receipt_policy
|
||||
self.delivery_policy = self.operation_id.delivery_policy
|
||||
self.in_warehouse_id = self.operation_id.in_warehouse_id
|
||||
self.out_warehouse_id = self.operation_id.out_warehouse_id
|
||||
self.location_id = self.operation_id.location_id or \
|
||||
self.in_warehouse_id.lot_rma_id
|
||||
self.customer_to_supplier = self.operation_id.customer_to_supplier
|
||||
self.supplier_to_customer = self.operation_id.supplier_to_customer
|
||||
self.in_route_id = self.operation_id.in_route_id
|
||||
self.out_route_id = self.operation_id.out_route_id
|
||||
return result
|
||||
|
||||
@api.onchange('customer_to_supplier', 'type')
|
||||
def _onchange_receipt_policy(self):
|
||||
if self.type == 'supplier' and self.customer_to_supplier:
|
||||
self.receipt_policy = 'no'
|
||||
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
|
||||
if product:
|
||||
self.product_id = product
|
||||
self.uom_id = product.uom_id
|
||||
|
||||
@api.multi
|
||||
def action_view_in_shipments(self):
|
||||
action = self.env.ref('stock.action_picking_tree_all')
|
||||
result = action.read()[0]
|
||||
picking_ids = []
|
||||
suppliers = self.env.ref('stock.stock_location_suppliers')
|
||||
customers = self.env.ref('stock.stock_location_customers')
|
||||
for line in self:
|
||||
if line.type == 'customer':
|
||||
for move in line.move_ids:
|
||||
if move.picking_id.location_id == customers:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
else:
|
||||
for move in line.move_ids:
|
||||
if move.picking_id.location_id == suppliers:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
shipments = list(set(picking_ids))
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) != 1:
|
||||
result['domain'] = "[('id', 'in', " + \
|
||||
str(shipments) + ")]"
|
||||
elif len(shipments) == 1:
|
||||
res = self.env.ref('stock.view_picking_form', False)
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = shipments[0]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_view_out_shipments(self):
|
||||
action = self.env.ref('stock.action_picking_tree_all')
|
||||
result = action.read()[0]
|
||||
picking_ids = []
|
||||
suppliers = self.env.ref('stock.stock_location_suppliers')
|
||||
customers = self.env.ref('stock.stock_location_customers')
|
||||
for line in self:
|
||||
if line.type == 'customer':
|
||||
for move in line.move_ids:
|
||||
if move.picking_id.location_id != customers:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
else:
|
||||
for move in line.move_ids:
|
||||
if move.picking_id.location_id != suppliers:
|
||||
picking_ids.append(move.picking_id.id)
|
||||
shipments = list(set(picking_ids))
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) != 1:
|
||||
result['domain'] = "[('id', 'in', " + \
|
||||
str(shipments) + ")]"
|
||||
elif len(shipments) == 1:
|
||||
res = self.env.ref('stock.view_picking_form', False)
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = shipments[0]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_view_procurements(self):
|
||||
action = self.env.ref('procurement.procurement_order_action_exceptions')
|
||||
result = action.read()[0]
|
||||
procurements = self.procurement_ids.filtered(
|
||||
lambda p: p.state == 'exception').ids
|
||||
# choose the view_mode accordingly
|
||||
if len(procurements) != 1:
|
||||
result['domain'] = "[('id', 'in', " + \
|
||||
str(procurements) + ")]"
|
||||
elif len(procurements) == 1:
|
||||
res = self.env.ref('procurement.procurement_form_view', False)
|
||||
result['views'] = [(res and res.id or False, 'form')]
|
||||
result['res_id'] = procurements[0]
|
||||
return result
|
||||
16
rma/models/rma_rule.py
Normal file
16
rma/models/rma_rule.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# -*- 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 import _, api, fields, models
|
||||
|
||||
|
||||
class RmaRule(models.Model):
|
||||
_name = 'rma.rule'
|
||||
_description = 'RMA Approval Conditions'
|
||||
|
||||
name = fields.Char('Description', required=True)
|
||||
code = fields.Char('Code', required=True)
|
||||
approval_policy = fields.Selection([
|
||||
('always', 'Always')], string="Approval Policy",
|
||||
required=True, default='always')
|
||||
37
rma/models/stock.py
Normal file
37
rma/models/stock.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# -*- 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 import api, fields, models
|
||||
|
||||
|
||||
class StockPicking(models.Model):
|
||||
_inherit = "stock.picking"
|
||||
|
||||
@api.multi
|
||||
def action_assign(self):
|
||||
for picking in self:
|
||||
for move in picking.move_lines:
|
||||
if len(move.rma_line_id):
|
||||
if move.state in ('confirmed', 'waiting', 'assigned') \
|
||||
and move.location_id.usage in (
|
||||
'supplier', 'customer'):
|
||||
move.force_assign()
|
||||
return super(StockPicking, self).action_assign()
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
|
||||
_inherit = "stock.move"
|
||||
|
||||
rma_line_id = fields.Many2one('rma.order.line', string='RMA',
|
||||
ondelete='restrict')
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('procurement_id', False):
|
||||
procurement = self.env['procurement.order'].browse(
|
||||
vals['procurement_id'])
|
||||
if procurement.rma_line_id and procurement.rma_line_id.id:
|
||||
vals['rma_line_id'] = procurement.rma_line_id.id
|
||||
return super(StockMove, self).create(vals)
|
||||
26
rma/models/stock_warehouse.py
Normal file
26
rma/models/stock_warehouse.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# -*- 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 import api, fields, models
|
||||
|
||||
|
||||
class StockWarehouse(models.Model):
|
||||
|
||||
_inherit = "stock.warehouse"
|
||||
|
||||
lot_rma_id = fields.Many2one('stock.location', 'RMA Location')
|
||||
rma_cust_out_type_id = fields.Many2one('stock.picking.type',
|
||||
'RMA Customer out Type')
|
||||
rma_sup_out_type_id = fields.Many2one('stock.picking.type',
|
||||
'RMA Supplier out Type')
|
||||
rma_cust_in_type_id = fields.Many2one('stock.picking.type',
|
||||
'RMA Customer in Type')
|
||||
rma_sup_in_type_id = fields.Many2one('stock.picking.type',
|
||||
'RMA Supplier in Type')
|
||||
|
||||
|
||||
class StockLocationRoute(models.Model):
|
||||
_inherit = "stock.location.route"
|
||||
|
||||
rma_selectable = fields.Boolean(string="Selectable on RMA Lines")
|
||||
11
rma/security/ir.model.access.csv
Normal file
11
rma/security/ir.model.access.csv
Normal file
@@ -0,0 +1,11 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_rma_user_customer,rma.order.customer.user,model_rma_order,group_rma_customer_user,1,1,1,1
|
||||
access_rma_user_supplier,rma.order.supplier.user,model_rma_order,group_rma_supplier_user,1,1,1,1
|
||||
access_rma_manager,rma.order.manager,model_rma_order,group_rma_manager,1,1,1,1
|
||||
access_rma_line_customer_user,rma.order.line.customer.user,model_rma_order_line,group_rma_customer_user,1,1,1,1
|
||||
access_rma_line_supplier_user,rma.order.line.customer.supplier,model_rma_order_line,group_rma_supplier_user,1,1,1,1
|
||||
access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1,1,1,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
|
||||
|
38
rma/security/rma.xml
Normal file
38
rma/security/rma.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="0">
|
||||
|
||||
<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('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('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_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>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
4
rma/tests/__init__.py
Normal file
4
rma/tests/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- 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
|
||||
242
rma/tests/test_rma.py
Normal file
242
rma/tests/test_rma.py
Normal file
@@ -0,0 +1,242 @@
|
||||
# -*- 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
|
||||
|
||||
|
||||
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.rma_add_invoice = self.env['rma_add_invoice']
|
||||
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_op_id = self.env.ref('rma.rma_operation_customer_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_30')
|
||||
self.product_3 = self.env.ref('product.product_product_33')
|
||||
self.uom_unit = self.env.ref('product.product_uom_unit')
|
||||
# assign an operation
|
||||
self.product_1.write({'rma_operation_id': self.rma_op_id.id})
|
||||
self.product_2.write({'rma_operation_id': self.rma_op_id.id})
|
||||
self.product_3.write({'rma_operation_id': self.rma_op_id.id})
|
||||
self.partner_id = self.env.ref('base.res_partner_12')
|
||||
|
||||
self.customer_location_id = self.env.ref(
|
||||
'stock.stock_location_customers'
|
||||
)
|
||||
uom_unit = self.env.ref('product.product_uom_unit')
|
||||
sale_values = self._prepare_sale()
|
||||
self.sale_order = self.env['sale.order'].create(sale_values)
|
||||
invoice_id = self.sale_order.action_invoice_create()[0]
|
||||
self.invoice = self.env['account.invoice'].browse(invoice_id)
|
||||
# Create the RMA from the invoice
|
||||
self.rma_id = self.rma.create(
|
||||
{
|
||||
'reference': '0001',
|
||||
'type': 'customer',
|
||||
'partner_id': self.env.ref('base.res_partner_2').id
|
||||
})
|
||||
|
||||
for line in self.invoice.invoice_line_ids:
|
||||
data = self.rma_add_invoice.with_context(
|
||||
{'invoice_id': self.invoice.id}
|
||||
)._prepare_rma_line_from_inv_line(line)
|
||||
data.update(rma_id=self.rma_id.id)
|
||||
self.rma_line.create(data)
|
||||
#approve the RMA
|
||||
self.rma_id.action_rma_to_approve()
|
||||
self.rma_id.action_rma_approve()
|
||||
|
||||
def _prepare_sale(self):
|
||||
values = {
|
||||
'state': 'done',
|
||||
'partner_id': self.env.ref('base.res_partner_2').id,
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'warehouse_id': self.env.ref('stock.warehouse0').id,
|
||||
'partner_invoice_id': self.env.ref('base.res_partner_2').id,
|
||||
'partner_shipping_id': self.env.ref('base.res_partner_2').id,
|
||||
'picking_policy': 'direct',
|
||||
'order_line': [
|
||||
(0, False, {
|
||||
'name': product.name,
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': qty,
|
||||
'qty_delivered': qty,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'price_unit': product.list_price
|
||||
|
||||
}) for product, qty in [
|
||||
(self.product_1, 3),
|
||||
(self.product_2, 5),
|
||||
(self.product_3, 2),
|
||||
]
|
||||
]
|
||||
}
|
||||
return values
|
||||
|
||||
def test_00_receive_items(self):
|
||||
wizard = self.rma_make_picking.with_context({
|
||||
'active_ids': self.rma_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',[" + ','.join(
|
||||
map(str, 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_id.rma_line_ids:
|
||||
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")
|
||||
self.assertEquals(line.qty_to_refund, 0,
|
||||
"Wrong qty to refund")
|
||||
self.assertEquals(line.qty_to_refunded, 0,
|
||||
"Wrong qty refunded")
|
||||
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")
|
||||
pickings.action_assign()
|
||||
pickings.do_transfer()
|
||||
for line in self.rma_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")
|
||||
self.assertEquals(line.qty_to_refund, 0,
|
||||
"Wrong qty to refund")
|
||||
self.assertEquals(line.qty_to_refunded, 0,
|
||||
"Wrong qty refunded")
|
||||
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_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',[" + ','.join(
|
||||
map(str, 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_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")
|
||||
self.assertEquals(line.qty_to_refund, 0,
|
||||
"Wrong qty to refund")
|
||||
self.assertEquals(line.qty_to_refunded, 0,
|
||||
"Wrong qty refunded")
|
||||
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")
|
||||
pickings.action_assign()
|
||||
pickings.do_transfer()
|
||||
for line in self.rma_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_to_refund, 0,
|
||||
"Wrong qty to refund")
|
||||
self.assertEquals(line.qty_to_refunded, 0,
|
||||
"Wrong qty refunded")
|
||||
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.rma_id.action_rma_done()
|
||||
31
rma/views/procurement_view.xml
Normal file
31
rma/views/procurement_view.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="procurement_form_view" model="ir.ui.view">
|
||||
<field name="name">procurement.order.form</field>
|
||||
<field name="model">procurement.order</field>
|
||||
<field name="inherit_id"
|
||||
ref="procurement.procurement_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="origin" position="after">
|
||||
<field name="rma_line_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="procurement_form_view_usage" model="ir.ui.view">
|
||||
<field name="name">procurement.order.form.stock.inherit</field>
|
||||
<field name="model">procurement.order</field>
|
||||
<field name="inherit_id"
|
||||
ref="stock.view_procurement_form_stock_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="location_id" position="attributes">
|
||||
<attribute name="domain">[('usage', '!=', 'view')]</attribute>
|
||||
</field>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
30
rma/views/product_view.xml
Normal file
30
rma/views/product_view.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="product_category_form_view" model="ir.ui.view">
|
||||
<field name="name">product.category.form</field>
|
||||
<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">
|
||||
<field name="rma_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">product.template.stock.property.form.inherit</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="inventory" position="inside">
|
||||
<group name="rma" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user">
|
||||
<field name="rma_operation_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
17
rma/views/res_company_view.xml
Normal file
17
rma/views/res_company_view.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="view_company_form" model="ir.ui.view">
|
||||
<field name="name">base_phone.company.form</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="inherit_id" ref="base.view_company_form" />
|
||||
<field name="arch" type="xml">
|
||||
<group name="account_grp" position="after">
|
||||
<group name="rma" string="RMA">
|
||||
<field name="rma_rule_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
69
rma/views/rma_operation_view.xml
Normal file
69
rma/views/rma_operation_view.xml
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="rma_operation_tree" model="ir.ui.view">
|
||||
<field name="name">rma.operation.tree</field>
|
||||
<field name="model">rma.operation</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="RMA Operations">
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
<field name="receipt_policy"/>
|
||||
<field name="delivery_policy"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="rma_operation_form" model="ir.ui.view">
|
||||
<field name="name">rma.operation.form</field>
|
||||
<field name="model">rma.operation</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="RMA Operations">
|
||||
<group colspan="4" col="2">
|
||||
<group name="description"
|
||||
string="Description">
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
<field name="type"/>
|
||||
</group>
|
||||
<group name="policies"
|
||||
string="Policies">
|
||||
<field name="receipt_policy"/>
|
||||
<field name="delivery_policy"/>
|
||||
</group>
|
||||
<group name="inbound" string="Inbound">
|
||||
<field name="in_route_id"/>
|
||||
<field name="in_warehouse_id"/>
|
||||
<field name="location_id"
|
||||
domain="[('usage', '=', 'internal')]"/>
|
||||
<field name="customer_to_supplier"
|
||||
attrs="{'invisible':[('type', '=', 'customer')]}"/>
|
||||
</group>
|
||||
<group name="outbound" string="Outbound">
|
||||
<field name="out_route_id"/>
|
||||
<field name="out_warehouse_id"/>
|
||||
<field name="supplier_to_customer"
|
||||
attrs="{'invisible':[('type', '=', 'supplier')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_operation" model="ir.actions.act_window">
|
||||
<field name="name">Operations</field>
|
||||
<field name="res_model">rma.operation</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="rma_operation_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_rma_operation"
|
||||
name="Operations"
|
||||
groups="rma.group_rma_manager"
|
||||
sequence="35"
|
||||
parent="rma.menu_rma_config"
|
||||
action="action_rma_operation"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
387
rma/views/rma_order_line_view.xml
Normal file
387
rma/views/rma_order_line_view.xml
Normal file
@@ -0,0 +1,387 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="view_rma_line_tree" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.tree</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="RMA Line" nocreate="1"
|
||||
decoration-muted="state in ('draft','to_approve')">
|
||||
<field name="rma_id"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="name"/>
|
||||
<field name="origin"/>
|
||||
<field name="operation_id"/>
|
||||
<field name="supplier_address_id"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="price_unit"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_line_supplier_tree" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.supplier.tree</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="RMA Line" nocreate="1"
|
||||
decoration-muted="state in ('draft','to_approve')">
|
||||
<field name="rma_id"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="name"/>
|
||||
<field name="origin"/>
|
||||
<field name="operation_id" domain="[('type','=','supplier')]"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="price_unit"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_line_supplier_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.supplier.form</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="RMA Line" nocreate="1">
|
||||
<sheet>
|
||||
<header/>
|
||||
<div name="button_box" class="oe_button_box">
|
||||
<button type="object" name="action_view_in_shipments"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="in_shipment_count" widget="statinfo"
|
||||
string="Shipments"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_out_shipments"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="out_shipment_count" widget="statinfo"
|
||||
string="Deliveries"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_procurements"
|
||||
class="oe_stat_button"
|
||||
icon="fa-warning"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="procurement_count" widget="statinfo"
|
||||
string="Proc. Exceptions"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title" name="title">
|
||||
<h1>
|
||||
<field name="rma_id" required="False"
|
||||
readonly="True"
|
||||
invisible="context.get('hide_title',False)"/>
|
||||
</h1>
|
||||
</div>
|
||||
<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" colspan="2">
|
||||
<field name="operation_id"
|
||||
domain="[('type','=','supplier')]"/>
|
||||
<field name="receipt_policy"/>
|
||||
<field name="delivery_policy"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="description" string="Description">
|
||||
<field name="description" nolabel="1"/>
|
||||
</page>
|
||||
<page name="route" string="Routes" groups="stock.group_adv_location">
|
||||
<group>
|
||||
<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"/>
|
||||
</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>
|
||||
</page>
|
||||
<page name="stock" string="Stock Moves">
|
||||
<field name="move_ids" nolabel="1" readonly="1"/>
|
||||
</page>
|
||||
<page name="quantities" string="Quantities">
|
||||
<group>
|
||||
<group name="quantities" col="4" string="Quantities">
|
||||
<group name="receive">
|
||||
<field name="qty_to_receive"/>
|
||||
<field name="qty_incoming"/>
|
||||
<field name="qty_received"/>
|
||||
</group>
|
||||
<group name="deliver">
|
||||
<field name="qty_to_deliver"/>
|
||||
<field name="qty_outgoing"/>
|
||||
<field name="qty_delivered"/>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page name="other" string="Other Info">
|
||||
<group name="general" string="General">
|
||||
<field name="name"/>
|
||||
<field name="origin"/>
|
||||
<field name="reference_move_id"/>
|
||||
<field name="state" invisible="1"/>
|
||||
</group>
|
||||
<group name="contact" string="Contact">
|
||||
<field name="requested_by" readonly="1"/>
|
||||
<field name="assigned_to" readonly="1"/>
|
||||
</group>
|
||||
<group name="company" string="Company"
|
||||
groups="base.group_multi_company">
|
||||
<field name="company_id"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_line_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.form</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Rma Line" nocreate="1">
|
||||
<sheet>
|
||||
<header/>
|
||||
<div name="button_box" class="oe_button_box">
|
||||
<button type="object" name="action_view_in_shipments"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="in_shipment_count" widget="statinfo"
|
||||
string="Shipments"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_out_shipments"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
groups="stock.group_stock_user">
|
||||
<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"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="procurement_count" widget="statinfo"
|
||||
string="Exceptions"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title" name="title">
|
||||
<h1>
|
||||
<field name="rma_id" required="False"
|
||||
readonly="True"
|
||||
invisible="context.get('hide_title',False)"/>
|
||||
</h1>
|
||||
</div>
|
||||
<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"/>
|
||||
<field name="delivery_policy"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="route" string="Routes">
|
||||
<group>
|
||||
<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>
|
||||
</page>
|
||||
<page name="stock" string="Stock Moves">
|
||||
<field name="move_ids" nolabel="1" readonly="1"/>
|
||||
</page>
|
||||
<page name="quantities" string="Quantities">
|
||||
<group>
|
||||
<group name="quantities" col="4" string="Quantities">
|
||||
<group name="receive">
|
||||
<field name="qty_to_receive"/>
|
||||
<field name="qty_incoming"/>
|
||||
<field name="qty_received"/>
|
||||
</group>
|
||||
<group name="deliver">
|
||||
<field name="qty_to_deliver"/>
|
||||
<field name="qty_outgoing"/>
|
||||
<field name="qty_delivered"/>
|
||||
</group>
|
||||
<group name="supplier_rma"
|
||||
attrs="{'invisible':[('customer_to_supplier','=',False)]}">
|
||||
<field name="qty_to_supplier_rma"/>
|
||||
<field name="qty_in_supplier_rma"/>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page name="other" string="Other Info">
|
||||
<group name="general" string="General">
|
||||
<field name="name"/>
|
||||
<field name="origin"/>
|
||||
<field name="reference_move_id"/>
|
||||
<field name="state" invisible="1"/>
|
||||
</group>
|
||||
<group name="contact" string="Contact">
|
||||
<field name="requested_by" readonly="1"/>
|
||||
<field name="assigned_to" readonly="1"/>
|
||||
</group>
|
||||
<group name="company" string="Company"
|
||||
groups="base.group_multi_company">
|
||||
<field name="company_id"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</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="arch" type="xml">
|
||||
<search string="Search RMA line">
|
||||
<field name="rma_id"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="requested_by"/>
|
||||
<field name="assigned_to"/>
|
||||
<field name="product_id"/>
|
||||
<field name="lot_id"/>
|
||||
<separator/>
|
||||
<filter domain="[('assigned_to','=',uid)]" help="My RMAs"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="partner" string="Partner" domain="[]"
|
||||
context="{'group_by':'partner_id'}"/>
|
||||
<filter name="operation" string="Operation" domain="[]"
|
||||
context="{'group_by':'operation_id'}"/>
|
||||
<filter name="product" string="Product" domain="[]"
|
||||
context="{'group_by':'product_id'}"/>
|
||||
<filter name="to_receive" string="To Receive" domain="[('qty_to_receive', '>', 0)]"
|
||||
context="{'group_by':'partner_id'}"/>
|
||||
<filter name="to_deliver" string="To Deliver" domain="[('qty_to_deliver', '>', 0)]"
|
||||
context="{'group_by':'partner_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_customer_lines" model="ir.actions.act_window">
|
||||
<field name="name">Customer RMA Lines</field>
|
||||
<field name="res_model">rma.order.line</field>
|
||||
<field name="domain">[('state','in', ['approved', 'done']),
|
||||
('type','=', 'customer'),
|
||||
('customer_to_supplier','=', False)
|
||||
]</field>
|
||||
<field name="context">{"search_default_assigned_to":uid}</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_rma_line_tree"/>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_supplier_lines" model="ir.actions.act_window">
|
||||
<field name="name">Supplier RMA Lines</field>
|
||||
<field name="res_model">rma.order.line</field>
|
||||
<field name="domain">[('state','in', ['approved', 'done']),
|
||||
('type','=', 'supplier')]</field>
|
||||
<field name="context">{"search_default_assigned_to":uid, "supplier":1}</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_rma_line_supplier_tree"/>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_line_supplier_tree"
|
||||
model="ir.actions.act_window.view">
|
||||
<field eval="3" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="act_window_id" ref="action_rma_supplier_lines"/>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_line_supplier_form"
|
||||
model="ir.actions.act_window.view">
|
||||
<field eval="4" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_rma_line_supplier_form"/>
|
||||
<field name="act_window_id" ref="action_rma_supplier_lines"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_rma_line_customer"
|
||||
sequence="20"
|
||||
parent="menu_customer_rma"
|
||||
groups="rma.group_rma_customer_user"
|
||||
action="action_rma_customer_lines"
|
||||
/>
|
||||
|
||||
<menuitem
|
||||
id="menu_rma_line_supplier"
|
||||
sequence="20"
|
||||
parent="menu_supplier_rma"
|
||||
groups="rma.group_rma_supplier_user"
|
||||
action="action_rma_supplier_lines"
|
||||
/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
365
rma/views/rma_order_view.xml
Normal file
365
rma/views/rma_order_view.xml
Normal file
@@ -0,0 +1,365 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="view_rma_tree" model="ir.ui.view">
|
||||
<field name="name">rma.order.tree</field>
|
||||
<field name="model">rma.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-info="state == 'draft'"
|
||||
decoration-muted="state== 'done'" string="RMA">
|
||||
<field name="name"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="reference"/>
|
||||
<field name="partner_id" groups="base.group_user" string="Customer"/>
|
||||
<field name="requested_by" groups="base.group_user"/>
|
||||
<field name="assigned_to" groups="base.group_user"/>
|
||||
<field name="date_rma"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_supplier_tree" model="ir.ui.view">
|
||||
<field name="name">rma.order.supplier.tree</field>
|
||||
<field name="model">rma.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-info="state == 'draft'"
|
||||
decoration-muted="state== 'done'" string="RMA">
|
||||
<field name="name"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="reference"/>
|
||||
<field name="partner_id" groups="base.group_user"
|
||||
string="Supplier"/>
|
||||
<field name="requested_by" groups="base.group_user"/>
|
||||
<field name="assigned_to" groups="base.group_user"/>
|
||||
<field name="date_rma"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.form</field>
|
||||
<field name="model">rma.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="RMA">
|
||||
<field name="state" invisible="True"/>
|
||||
<header>
|
||||
<button name="action_rma_to_approve" type="object"
|
||||
string="Request Approval"
|
||||
attrs="{'invisible':[('state', '!=', 'draft')]}"
|
||||
class="oe_highlight" groups="rma.group_rma_customer_user"/>
|
||||
<button name="action_rma_draft" type="object"
|
||||
string="Back to Draft"
|
||||
attrs="{'invisible':[('state', '=', 'draft')]}" class="oe_highlight"
|
||||
groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
|
||||
<button name="action_rma_approve" type="object"
|
||||
string="Approve"
|
||||
attrs="{'invisible':[('state', '!=', 'to_approve')]}" class="oe_highlight" groups="rma.group_rma_customer_user"/>
|
||||
<button name="action_rma_done" type="object"
|
||||
string="Done"
|
||||
attrs="{'invisible':[('state', 'in', ('done', 'draft'))]}"
|
||||
groups="rma.group_rma_customer_user"/>
|
||||
<field name="state" widget="statusbar" nolabel="1"/>
|
||||
</header>
|
||||
<sheet name='rma' string="RMA">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button type="object" name="action_view_in_shipments"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="in_shipment_count" widget="statinfo"
|
||||
string="Shipments"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_out_shipments"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="out_shipment_count" widget="statinfo"
|
||||
string="Deliveries"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_lines"
|
||||
class="oe_stat_button"
|
||||
icon="fa-list"
|
||||
groups="rma.group_rma_customer_user">
|
||||
<field name="line_count" widget="statinfo"
|
||||
string="RMA Lines"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_supplier_lines"
|
||||
class="oe_stat_button"
|
||||
attrs="{'invisible':[('supplier_line_count', '=', 0)]}"
|
||||
icon="fa-list"
|
||||
groups="rma.group_rma_supplier_user">
|
||||
<field name="supplier_line_count" widget="statinfo"
|
||||
string="Rel. RMA Lines"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title" name="title">
|
||||
<h1>
|
||||
<field name="name"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group name="partner">
|
||||
<field name="partner_id"
|
||||
domain="[('customer','=',True)]"
|
||||
string="Customer"
|
||||
colspan="4"
|
||||
/>
|
||||
</group>
|
||||
<group>
|
||||
<group col="4">
|
||||
<field name="assigned_to"
|
||||
groups="base.group_user"
|
||||
context="{'default_groups_ref': ['rma.rma_user']}"/>
|
||||
<field name="reference"/>
|
||||
<field name="requested_by"
|
||||
groups="base.group_user"
|
||||
context="{'default_groups_ref': ['rma.rma_user']}"/>
|
||||
<field name="date_rma"/>
|
||||
<field name="type" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="RMA Lines" name="lines">
|
||||
<field name="rma_line_ids" context="{'default_rma_id': active_id,
|
||||
'partner_id': partner_id,
|
||||
'hide_title': True}">
|
||||
<tree string="RMA Lines" name="lines">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="state" invisible="True"/>
|
||||
<field name="product_id"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="name"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="operation_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="price_unit"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page name="other_info" string="Other Info">
|
||||
<group name="company">
|
||||
<field name="company_id"
|
||||
groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group name="comments">
|
||||
<field name="comment"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_supplier_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.supplier.form</field>
|
||||
<field name="model">rma.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="RMA">
|
||||
<field name="state" invisible="True"/>
|
||||
<header>
|
||||
<button name="action_rma_to_approve" type="object"
|
||||
string="Request Approval"
|
||||
attrs="{'invisible':[('state', '!=', 'draft')]}"
|
||||
class="oe_highlight"
|
||||
groups="rma.group_rma_supplier_user"/>
|
||||
<button name="action_rma_draft" type="object"
|
||||
string="Back to Draft"
|
||||
attrs="{'invisible':[('state', '=', 'draft')]}" class="oe_highlight"
|
||||
groups="rma.group_rma_supplier_user"/>
|
||||
<button name="action_rma_approve" type="object"
|
||||
string="Approve"
|
||||
attrs="{'invisible':[('state', '!=', 'to_approve')]}" class="oe_highlight" groups="rma.group_rma_supplier_user"/>
|
||||
<button name="action_rma_done" type="object"
|
||||
string="Done"
|
||||
attrs="{'invisible':[('state', 'in', ('done', 'draft'))]}"
|
||||
groups="rma.group_rma_manager"/>
|
||||
<field name="state" widget="statusbar" nolabel="1"/>
|
||||
</header>
|
||||
<sheet string="RMA">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button type="object" name="action_view_in_shipments"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="in_shipment_count" widget="statinfo"
|
||||
string="Shipments"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_out_shipments"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="out_shipment_count" widget="statinfo"
|
||||
string="Deliveries"/>
|
||||
</button>
|
||||
<button type="object" name="action_view_lines"
|
||||
class="oe_stat_button"
|
||||
icon="fa-list"
|
||||
groups="rma.group_rma_supplier_user">
|
||||
<field name="line_count" widget="statinfo"
|
||||
string="RMA Lines"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title" name="title">
|
||||
<h1>
|
||||
<field name="name"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group name="partner">
|
||||
<field name="partner_id"
|
||||
domain="[('supplier','=',True)]"
|
||||
string="Supplier"/>
|
||||
</group>
|
||||
<group>
|
||||
<group col="4">
|
||||
<field name="assigned_to"
|
||||
groups="base.group_user"
|
||||
context="{'default_groups_ref': ['rma.rma_user']}"/>
|
||||
<field name="reference"/>
|
||||
<field name="requested_by"
|
||||
groups="base.group_user"
|
||||
context="{'default_groups_ref': ['rma.rma_user']}"/>
|
||||
<field name="date_rma"/>
|
||||
<field name="type" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="RMA Lines" name="lines">
|
||||
<field name="rma_line_ids"
|
||||
context="{'form_view_ref':'rma.view_rma_line_supplier_form',
|
||||
'default_rma_id': active_id,
|
||||
'partner_id': partner_id,
|
||||
'supplier': 1,
|
||||
'hide_title': True}">
|
||||
<tree string="RMA Lines">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="state" invisible="True"/>
|
||||
<field name="name"/>
|
||||
<field name="product_id"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="name"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="operation_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="origin"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page name="other_info" string="Other Info">
|
||||
<group name="company">
|
||||
<field name="company_id"
|
||||
groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group name="comments">
|
||||
<field name="comment"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_rma_filter" model="ir.ui.view">
|
||||
<field name="name">rma.order.select</field>
|
||||
<field name="model">rma.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search RMA">
|
||||
<field name="reference"/>
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="requested_by"/>
|
||||
<field name="assigned_to"/>
|
||||
<separator/>
|
||||
<filter domain="[('assigned_to','=',uid)]" help="My RMAs"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="partner" string="Partner" domain="[]"
|
||||
context="{'group_by':'partner_id'}"/>
|
||||
<filter name="rma_date" string="RMA Date" domain="[]"
|
||||
context="{'group_by':'rma_date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_customer" model="ir.actions.act_window">
|
||||
<field name="name">Customer RMA</field>
|
||||
<field name="res_model">rma.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain">[('type','=', 'customer')]</field>
|
||||
<field name="context">{"search_default_assigned_to":uid,
|
||||
'customer':1}</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_rma_tree"/>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_supplier" model="ir.actions.act_window">
|
||||
<field name="name">Supplier RMA</field>
|
||||
<field name="res_model">rma.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain">[('type','=', 'supplier')]</field>
|
||||
<field name="context">{"search_default_assigned_to":uid,
|
||||
'supplier':1}</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_rma_supplier_tree"/>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_supplier_tree"
|
||||
model="ir.actions.act_window.view">
|
||||
<field eval="1" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="act_window_id" ref="action_rma_supplier"/>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_supplier_form"
|
||||
model="ir.actions.act_window.view">
|
||||
<field eval="2" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_rma_supplier_form"/>
|
||||
<field name="act_window_id" ref="action_rma_supplier"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_customer_rma"
|
||||
name="Customer RMA"
|
||||
groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"
|
||||
sequence="30"
|
||||
parent="stock.menu_stock_root"/>
|
||||
|
||||
<menuitem id="menu_supplier_rma"
|
||||
name="Supplier RMA"
|
||||
groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"
|
||||
sequence="31"
|
||||
parent="stock.menu_stock_root"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_rma_act_customer"
|
||||
sequence="10"
|
||||
parent="menu_customer_rma"
|
||||
groups="rma.group_rma_customer_user"
|
||||
action="action_rma_customer"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_rma_act_supplier"
|
||||
sequence="10"
|
||||
parent="menu_supplier_rma"
|
||||
groups="rma.group_rma_supplier_user"
|
||||
action="action_rma_supplier"/>
|
||||
|
||||
<menuitem id="menu_rma_config"
|
||||
name="RMA"
|
||||
groups="rma.group_rma_manager"
|
||||
sequence="30"
|
||||
parent="stock.menu_stock_config_settings"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
51
rma/views/rma_rule_view.xml
Normal file
51
rma/views/rma_rule_view.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="rma_rule_tree" model="ir.ui.view">
|
||||
<field name="name">rma.rule.tree</field>
|
||||
<field name="model">rma.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="RMA rules">
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="rma_rule_form" model="ir.ui.view">
|
||||
<field name="name">rma.rule.form</field>
|
||||
<field name="model">rma.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="RMA Rules">
|
||||
<group colspan="4" col="2">
|
||||
<group name="description"
|
||||
string="Description">
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
</group>
|
||||
<group name="policies"
|
||||
string="Policies">
|
||||
<field name="approval_policy"/>
|
||||
</group>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_rule" model="ir.actions.act_window">
|
||||
<field name="name">Rules</field>
|
||||
<field name="res_model">rma.rule</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="rma_rule_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_rma_rule"
|
||||
name="Rules"
|
||||
groups="rma.group_rma_manager"
|
||||
sequence="36"
|
||||
parent="rma.menu_rma_config"
|
||||
action="action_rma_rule"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
55
rma/views/stock_view.xml
Normal file
55
rma/views/stock_view.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="view_move_form" model="ir.ui.view">
|
||||
<field name="name">rma.move.form</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_form" />
|
||||
<field name="arch" type="xml">
|
||||
<group name="destination_grp" position="after">
|
||||
<group name="rma">
|
||||
<field name="rma_line_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_move_picking_form" model="ir.ui.view" >
|
||||
<field name="name">stock.move.form</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_picking_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[1]" position="inside">
|
||||
<group name="rma" colspan="4">
|
||||
<field name="rma_line_id"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_location_route_form_view_inherit_rma_stock" model="ir.ui.view">
|
||||
<field name="name">stock.location.route.form</field>
|
||||
<field name="inherit_id" ref="stock.stock_location_route_form_view"/>
|
||||
<field name="model">stock.location.route</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='warehouse_ids']" position="before">
|
||||
<field name="rma_selectable" string="RMA Order Lines"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="procurement_form_view" model="ir.ui.view">
|
||||
<field name="name">procurement.order.form.stock.inherit</field>
|
||||
<field name="model">procurement.order</field>
|
||||
<field name="inherit_id"
|
||||
ref="stock.view_procurement_form_stock_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="location_id" position="attributes">
|
||||
<attribute name="domain">[('usage', '!=', 'view')]</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
20
rma/views/stock_warehouse.xml
Normal file
20
rma/views/stock_warehouse.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_warehouse_form" model="ir.ui.view">
|
||||
<field name="name">view_warehouse_form</field>
|
||||
<field name="model">stock.warehouse</field>
|
||||
<field name="inherit_id" ref="stock.view_warehouse"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='wh_output_stock_loc_id']" position="after">
|
||||
<field name="lot_rma_id"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='out_type_id']" position="after">
|
||||
<field name="rma_cust_in_type_id"/>
|
||||
<field name="rma_cust_out_type_id"/>
|
||||
<field name="rma_sup_in_type_id"/>
|
||||
<field name="rma_sup_out_type_id"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
8
rma/wizards/__init__.py
Normal file
8
rma/wizards/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# -*- 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 rma_add_stock_move
|
||||
from . import rma_make_picking
|
||||
from . import stock_config_settings
|
||||
from . import rma_order_line_make_supplier_rma
|
||||
106
rma/wizards/rma_add_stock_move.py
Normal file
106
rma/wizards/rma_add_stock_move.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# -*- 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 import models, fields, exceptions, api, _
|
||||
from openerp.exceptions import ValidationError
|
||||
|
||||
|
||||
class RmaAddStockMove(models.TransientModel):
|
||||
_name = 'rma_add_stock_move'
|
||||
_description = 'Wizard to add rma lines from pickings'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(RmaAddStockMove, self).default_get(fields)
|
||||
rma_obj = self.env['rma.order']
|
||||
rma_id = self.env.context['active_ids'] or []
|
||||
active_model = self.env.context['active_model']
|
||||
if not rma_id:
|
||||
return res
|
||||
assert active_model == 'rma.order', 'Bad context propagation'
|
||||
|
||||
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
|
||||
|
||||
rma_id = fields.Many2one('rma.order',
|
||||
string='RMA Order',
|
||||
readonly=True,
|
||||
ondelete='cascade')
|
||||
|
||||
partner_id = fields.Many2one(comodel_name='res.partner', string='Partner',
|
||||
readonly=True)
|
||||
|
||||
move_ids = fields.Many2many('stock.move',
|
||||
string='Stock Moves',
|
||||
domain="[('state', '=', 'done')]")
|
||||
|
||||
def _prepare_rma_line_from_stock_move(self, sm, lot=False):
|
||||
operation = sm.product_id.rma_operation_id or \
|
||||
sm.product_id.categ_id.rma_operation_id
|
||||
data = {
|
||||
'reference_move_id': sm.id,
|
||||
'product_id': sm.product_id.id,
|
||||
'lot_id': lot and lot.id or False,
|
||||
'name': sm.product_id.name_template,
|
||||
'origin': sm.picking_id.name,
|
||||
'uom_id': sm.product_uom.id,
|
||||
'operation_id': operation.id,
|
||||
'product_qty': sm.product_uom_qty,
|
||||
'delivery_address_id': sm.picking_id.partner_id.id,
|
||||
'rma_id': self.rma_id.id
|
||||
}
|
||||
if not operation:
|
||||
operation = self.env['rma.operation'].search(
|
||||
[('type', '=', self.rma_id.type)], limit=1)
|
||||
if not operation:
|
||||
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")
|
||||
data.update(
|
||||
{'in_route_id': operation.in_route_id.id,
|
||||
'out_route_id': operation.out_route_id.id,
|
||||
'receipt_policy': operation.receipt_policy,
|
||||
'operation_id': operation.id,
|
||||
'refund_policy': operation.refund_policy,
|
||||
'delivery_policy': operation.delivery_policy
|
||||
})
|
||||
if operation.in_warehouse_id:
|
||||
data['in_warehouse_id'] = operation.in_warehouse_id.id
|
||||
if operation.out_warehouse_id:
|
||||
data['out_warehouse_id'] = operation.out_warehouse_id.id
|
||||
if operation.location_id:
|
||||
data['location_id'] = operation.location_id.id
|
||||
return data
|
||||
|
||||
@api.model
|
||||
def _get_existing_stock_moves(self):
|
||||
existing_move_lines = []
|
||||
for rma_line in self.rma_id.rma_line_ids:
|
||||
existing_move_lines.append(rma_line.reference_move_id)
|
||||
return existing_move_lines
|
||||
|
||||
@api.multi
|
||||
def add_lines(self):
|
||||
rma_line_obj = self.env['rma.order.line']
|
||||
existing_stock_moves = self._get_existing_stock_moves()
|
||||
for sm in self.move_ids:
|
||||
if sm not in existing_stock_moves:
|
||||
if sm.lot_ids:
|
||||
for lot in sm.lot_ids:
|
||||
data = self._prepare_rma_line_from_stock_move(sm,
|
||||
lot=lot)
|
||||
rma_line_obj.with_context(
|
||||
default_rma_id=self.rma_id.id).create(data)
|
||||
else:
|
||||
data = self._prepare_rma_line_from_stock_move(sm, lot=False)
|
||||
rma_line_obj.with_context(
|
||||
default_rma_id=self.rma_id.id).create(data)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
128
rma/wizards/rma_add_stock_move_view.xml
Normal file
128
rma/wizards/rma_add_stock_move_view.xml
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<odoo>
|
||||
<record id="view_rma_add_stock_move_customer" model="ir.ui.view">
|
||||
<field name="name">rma.add.stock.move.customer</field>
|
||||
<field name="model">rma_add_stock_move</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Select Move">
|
||||
<group>
|
||||
<field name="partner_id"
|
||||
domain="[('customer','=',True)]"
|
||||
string="Customer"/>
|
||||
</group>
|
||||
<separator string="Select Stock Moves to add"/>
|
||||
<field name="move_ids"
|
||||
domain="[('picking_id.partner_id', '=', partner_id), ('location_dest_id.usage', '=', 'customer')]">
|
||||
<tree>
|
||||
<field name="product_id"/>
|
||||
<field name="product_uom_qty"/>
|
||||
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
|
||||
<field name="product_packaging" domain="[('product_tmpl_id','=',product_tmpl_id)]" groups="product.group_stock_packaging"/>
|
||||
<field name="picking_id"/>
|
||||
<field name="location_id" groups="stock.group_locations"/>
|
||||
<field name="location_dest_id" groups="stock.group_locations"/>
|
||||
<field name="create_date" groups="base.group_no_one"/>
|
||||
<field name="date" string="Date" groups="base.group_no_one"/>
|
||||
<field name="date_expected" string="Date Expected"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
<footer>
|
||||
<button
|
||||
string="Confirm"
|
||||
name="add_lines" type="object"
|
||||
class="oe_highlight"/>
|
||||
or
|
||||
<button name="action_cancel"
|
||||
string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_add_stock_move_customer"
|
||||
model="ir.actions.act_window">
|
||||
<field name="name">Add from Stock Move</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">rma_add_stock_move</field>
|
||||
<field name="src_model">rma.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="view_id" ref="view_rma_add_stock_move_customer"/>
|
||||
<field name="groups_id"
|
||||
eval="[(4, ref('rma.group_rma_customer_user'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="view_rma_add_stock_move_customer_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.form</field>
|
||||
<field name="model">rma.order</field>
|
||||
<field name="inherit_id" ref="rma.view_rma_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_rma_done" position="after">
|
||||
<button name="%(action_rma_add_stock_move_customer)d"
|
||||
string="Add From Stock Move"
|
||||
type="action"
|
||||
states="draft,to_approve"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_add_stock_move_supplier" model="ir.ui.view">
|
||||
<field name="name">rma.add.stock.move.supplier</field>
|
||||
<field name="model">rma_add_stock_move</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Select Move">
|
||||
<group>
|
||||
<field name="partner_id"
|
||||
domain="[('supplier','=',True)]"
|
||||
string="Supplier"/>
|
||||
</group>
|
||||
<separator string="Select Stock Moves to add"/>
|
||||
<field name="move_ids"
|
||||
domain="[('picking_id.partner_id', '=', partner_id), ('location_dest_id.usage', '=', 'supplier')]"/>
|
||||
<footer>
|
||||
<button
|
||||
string="Confirm"
|
||||
name="add_lines" type="object"
|
||||
class="oe_highlight"/>
|
||||
or
|
||||
<button name="action_cancel"
|
||||
string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_add_stock_move_supplier"
|
||||
model="ir.actions.act_window">
|
||||
<field name="name">Add from Stock Move</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">rma_add_stock_move</field>
|
||||
<field name="src_model">rma.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="view_id" ref="view_rma_add_stock_move_supplier"/>
|
||||
<field name="groups_id"
|
||||
eval="[(4, ref('rma.group_rma_supplier_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_add_stock_move_button_supplier_form"
|
||||
model="ir.ui.view">
|
||||
<field name="name">rma.order.line.supplier.form</field>
|
||||
<field name="model">rma.order</field>
|
||||
<field name="inherit_id" ref="rma.view_rma_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_rma_done" position="after">
|
||||
<button name="%(action_rma_add_stock_move_supplier)d"
|
||||
string="Add From Stock Move"
|
||||
type="action"
|
||||
states="draft,to_approve"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
233
rma/wizards/rma_make_picking.py
Normal file
233
rma/wizards/rma_make_picking.py
Normal file
@@ -0,0 +1,233 @@
|
||||
# -*- 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)
|
||||
|
||||
import time
|
||||
from openerp import models, fields, exceptions, api, _
|
||||
from openerp.exceptions import ValidationError
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT_FORMAT
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class RmaMakePicking(models.TransientModel):
|
||||
_name = 'rma_make_picking.wizard'
|
||||
_description = 'Wizard to create pickings from rma lines'
|
||||
|
||||
@api.returns('rma.order.line')
|
||||
def _prepare_item(self, line):
|
||||
values = {'product_id': line.product_id.id,
|
||||
'product_qty': line.product_qty,
|
||||
'uom_id': line.uom_id.id,
|
||||
'qty_to_receive': line.qty_to_receive,
|
||||
'qty_to_deliver': line.qty_to_deliver,
|
||||
'line_id': line.id,
|
||||
'rma_id': line.rma_id.id,
|
||||
'wiz_id': self.env.context['active_id'],
|
||||
}
|
||||
return values
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
"""Default values for wizard, if there is more than one supplier on
|
||||
lines the supplier field is empty otherwise is the unique line
|
||||
supplier.
|
||||
"""
|
||||
res = super(RmaMakePicking, 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)
|
||||
if len(lines.mapped('partner_id')) > 1:
|
||||
raise exceptions.Warning(
|
||||
_('Only RMA lines from the same partner can be processed at '
|
||||
'the same time'))
|
||||
for line in lines:
|
||||
items.append([0, 0, self._prepare_item(line)])
|
||||
res['item_ids'] = items
|
||||
return res
|
||||
|
||||
item_ids = fields.One2many(
|
||||
'rma_make_picking.wizard.item',
|
||||
'wiz_id', string='Items')
|
||||
|
||||
def find_procurement_group(self, item):
|
||||
return self.env['procurement.group'].search([('rma_id', '=',
|
||||
item.line_id.rma_id.id)])
|
||||
|
||||
def _get_procurement_group_data(self, item):
|
||||
group_data = {
|
||||
'name': item.line_id.rma_id.name,
|
||||
'rma_id': item.line_id.rma_id.id,
|
||||
}
|
||||
return group_data
|
||||
|
||||
@api.model
|
||||
def _get_address(self, item):
|
||||
if item.line_id.delivery_address_id:
|
||||
delivery_address = item.line_id.delivery_address_id or \
|
||||
item.line_id.partner_id
|
||||
elif item.line_id.customer_to_supplier:
|
||||
delivery_address = item.line_id.supplier_address_id
|
||||
else:
|
||||
raise exceptions.Warning('Unknown delivery address')
|
||||
return delivery_address
|
||||
|
||||
def _get_address_location(self, delivery_address_id, type):
|
||||
if type == 'supplier':
|
||||
return delivery_address_id.property_stock_supplier
|
||||
elif type == 'customer':
|
||||
return delivery_address_id.property_stock_customer
|
||||
|
||||
@api.model
|
||||
def _get_procurement_data(self, item, group, qty, picking_type):
|
||||
line = item.line_id
|
||||
delivery_address_id = self._get_address(item)
|
||||
if picking_type == 'incoming':
|
||||
if line.customer_to_supplier:
|
||||
location = self._get_address_location(
|
||||
delivery_address_id, 'supplier')
|
||||
else:
|
||||
location = line.location_id
|
||||
warehouse = line.in_warehouse_id
|
||||
route = line.in_route_id
|
||||
else:
|
||||
location = self._get_address_location(delivery_address_id,
|
||||
line.rma_id.type)
|
||||
warehouse = line.out_warehouse_id
|
||||
route = line.out_route_id
|
||||
if not route:
|
||||
raise exceptions.Warning("No route specified")
|
||||
if not warehouse:
|
||||
raise exceptions.Warning("No warehouse specified")
|
||||
procurement_data = {
|
||||
'name': line.rma_id.name,
|
||||
'group_id': group.id,
|
||||
'origin': line.rma_id.name,
|
||||
'warehouse_id': warehouse.id,
|
||||
'date_planned': time.strftime(DT_FORMAT),
|
||||
'product_id': item.product_id.id,
|
||||
'product_qty': qty,
|
||||
'partner_dest_id': delivery_address_id.id,
|
||||
'product_uom': line.product_id.product_tmpl_id.uom_id.id,
|
||||
'location_id': location.id,
|
||||
'rma_line_id': line.id,
|
||||
'route_ids': [(4, route.id)]
|
||||
}
|
||||
return procurement_data
|
||||
|
||||
@api.model
|
||||
def _create_procurement(self, item, picking_type):
|
||||
group = self.find_procurement_group(item)
|
||||
if not group:
|
||||
procurement_group = self._get_procurement_group_data(item)
|
||||
group = self.env['procurement.group'].create(procurement_group)
|
||||
if picking_type == 'incoming':
|
||||
qty = item.qty_to_receive
|
||||
else:
|
||||
qty = item.qty_to_deliver
|
||||
procurement_data = self._get_procurement_data(
|
||||
item, group, qty, picking_type)
|
||||
# create picking
|
||||
procurement = self.env['procurement.order'].create(procurement_data)
|
||||
procurement.run()
|
||||
return procurement.id
|
||||
|
||||
@api.multi
|
||||
def _create_picking(self):
|
||||
"""Method called when the user clicks on create picking"""
|
||||
picking_type = self.env.context.get('picking_type')
|
||||
procurement_list = []
|
||||
for item in self.item_ids:
|
||||
line = item.line_id
|
||||
if line.state != 'approved':
|
||||
raise exceptions.Warning(
|
||||
_('RMA %s is not approved') %
|
||||
line.rma_id.name)
|
||||
if line.receipt_policy == 'no' and picking_type == \
|
||||
'incoming':
|
||||
raise exceptions.Warning(
|
||||
_('No shipments needed for this operation'))
|
||||
if line.delivery_policy == 'no' and picking_type == \
|
||||
'outgoing':
|
||||
raise exceptions.Warning(
|
||||
_('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)
|
||||
return procurements
|
||||
|
||||
@api.model
|
||||
def _get_action(self, pickings, procurements):
|
||||
if pickings:
|
||||
action = procurements.do_view_pickings()
|
||||
else:
|
||||
action = self.env.ref(
|
||||
'procurement.procurement_order_action_exceptions')
|
||||
action = action.read()[0]
|
||||
# choose the view_mode accordingly
|
||||
procurement_ids = procurements.ids
|
||||
if len(procurement_ids) != 1:
|
||||
action['domain'] = "[('id', 'in', " + \
|
||||
str(procurement_ids) + ")]"
|
||||
elif len(procurements) == 1:
|
||||
res = self.env.ref('procurement.procurement_form_view',
|
||||
False)
|
||||
action['views'] = [(res and res.id or False, 'form')]
|
||||
action['res_id'] = procurement_ids[0]
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def action_create_picking(self):
|
||||
procurements = self._create_picking()
|
||||
groups = []
|
||||
for proc in procurements:
|
||||
if proc.group_id:
|
||||
groups.append(proc.group_id.id)
|
||||
if len(groups):
|
||||
pickings =self.env['stock.picking'].search(
|
||||
[('group_id', 'in', groups)])
|
||||
|
||||
action = self._get_action(pickings, procurements)
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def action_cancel(self):
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
class RmaMakePickingItem(models.TransientModel):
|
||||
_name = "rma_make_picking.wizard.item"
|
||||
_description = "Items to receive"
|
||||
|
||||
wiz_id = fields.Many2one(
|
||||
'rma_make_picking.wizard',
|
||||
string='Wizard', required=True)
|
||||
line_id = fields.Many2one('rma.order.line',
|
||||
string='RMA order Line',
|
||||
readonly=True,
|
||||
ondelete='cascade')
|
||||
rma_id = fields.Many2one('rma.order',
|
||||
related='line_id.rma_id',
|
||||
string='RMA',
|
||||
readonly=True)
|
||||
product_id = fields.Many2one('product.product', string='Product',
|
||||
readonly=True)
|
||||
product_qty = fields.Float(
|
||||
related='line_id.product_qty',
|
||||
string='Quantity Ordered', copy=False,
|
||||
digits=dp.get_precision('Product Unit of Measure'), readonly=True)
|
||||
qty_to_receive = fields.Float(
|
||||
string='Quantity to Receive',
|
||||
digits=dp.get_precision('Product Unit of Measure'))
|
||||
qty_to_deliver = fields.Float(
|
||||
string='Quantity To Deliver',
|
||||
digits=dp.get_precision('Product Unit of Measure'))
|
||||
uom_id = fields.Many2one('product.uom', string='Unit of Measure',
|
||||
readonly=True)
|
||||
139
rma/wizards/rma_make_picking_view.xml
Normal file
139
rma/wizards/rma_make_picking_view.xml
Normal file
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<odoo>
|
||||
<record id="view_rma_picking" model="ir.ui.view">
|
||||
<field name="name">rma_picking</field>
|
||||
<field name="model">rma_make_picking.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Select lines for picking" name="lines">
|
||||
<separator string="Select lines for picking"/>
|
||||
<field name="item_ids">
|
||||
<tree string="RMA Lines" editable="bottom" create="false">
|
||||
<field name="rma_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="qty_to_receive" readonly="0"/>
|
||||
</tree>
|
||||
</field>
|
||||
<footer>
|
||||
<button
|
||||
string="Confirm"
|
||||
name="action_create_picking" type="object"
|
||||
class="oe_highlight"/>
|
||||
or
|
||||
<button name="action_cancel"
|
||||
string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_picking_out" model="ir.ui.view">
|
||||
<field name="name">Create Delivery</field>
|
||||
<field name="model">rma_make_picking.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Select lines for picking" name="lines">
|
||||
<separator string="Select lines for picking"/>
|
||||
<field name="item_ids">
|
||||
<tree string="RMA Lines" editable="bottom" create="false">
|
||||
<field name="rma_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="qty_to_deliver" readonly="0"/>
|
||||
</tree>
|
||||
</field>
|
||||
<footer>
|
||||
<button
|
||||
string="Confirm"
|
||||
name="action_create_picking" type="object"
|
||||
class="oe_highlight"/>
|
||||
or
|
||||
<button name="action_cancel"
|
||||
string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_picking_in" model="ir.actions.act_window">
|
||||
<field name="name">Create Incoming Shipment</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">rma_make_picking.wizard</field>
|
||||
<field name="src_model">rma.order.line</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="view_id" ref="view_rma_picking"/>
|
||||
<field name="groups_id" eval="[(4, ref('stock.group_stock_user'))]"/>
|
||||
<field name="context">{'picking_type': 'incoming'}</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_picking_out" model="ir.actions.act_window">
|
||||
<field name="name">Create Delivery</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">rma_make_picking.wizard</field>
|
||||
<field name="src_model">rma.order.line</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="view_id" ref="view_rma_picking_out"/>
|
||||
<field name="groups_id" eval="[(4, ref('stock.group_stock_user'))]"/>
|
||||
<field name="context">{'picking_type': 'outgoing'}</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_line_button_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.form</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="inherit_id" ref="rma.view_rma_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<header position="inside">
|
||||
<button name="%(action_rma_picking_in)d" states="approved"
|
||||
string="Create Incoming Shipment" class="oe_highlight"
|
||||
type="action"/>
|
||||
<button name="%(action_rma_picking_out)d" states="approved"
|
||||
string="Create Delivery" class="oe_highlight"
|
||||
type="action"/>
|
||||
</header>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_line_supplier_button_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_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="before">
|
||||
<header>
|
||||
<button name="%(action_rma_picking_in)d" states="approved"
|
||||
string="Create Incoming Shipment" class="oe_highlight"
|
||||
type="action"/>
|
||||
<button name="%(action_rma_picking_out)d" states="approved"
|
||||
string="Create Delivery" class="oe_highlight"
|
||||
type="action"/>
|
||||
</header>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.values" id="values_action_rma_picking_in">
|
||||
<field name="model_id" ref="model_rma_order_line"/>
|
||||
<field name="name">Create Incoming Shipment</field>
|
||||
<field name="key2">client_action_multi</field>
|
||||
<field name="value" eval="'ir.actions.act_window,' + str(ref('action_rma_picking_in'))" />
|
||||
<field name="key">action</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.values" id="values_action_rma_picking_out">
|
||||
<field name="model_id" ref="model_rma_order_line"/>
|
||||
<field name="name">Create Delivery</field>
|
||||
<field name="key2">client_action_multi</field>
|
||||
<field name="value"
|
||||
eval="'ir.actions.act_window,' + str(ref('action_rma_picking_out'))" />
|
||||
<field name="key">action</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
148
rma/wizards/rma_order_line_make_supplier_rma.py
Normal file
148
rma/wizards/rma_order_line_make_supplier_rma.py
Normal file
@@ -0,0 +1,148 @@
|
||||
# -*- 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)
|
||||
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp import _, api, exceptions, fields, models
|
||||
|
||||
|
||||
class RmaLineMakeSupplierRma(models.TransientModel):
|
||||
_name = "rma.order.line.make.supplier.rma"
|
||||
_description = "RMA Line Make Supplier RMA"
|
||||
|
||||
partner_id = fields.Many2one('res.partner', string='Supplier',
|
||||
required=False,
|
||||
domain=[('supplier', '=', True)])
|
||||
item_ids = fields.One2many(
|
||||
'rma.order.line.make.supplier.rma.item',
|
||||
'wiz_id', string='Items')
|
||||
supplier_rma_id = fields.Many2one('rma.order',
|
||||
string='Supplier RMA Order',
|
||||
required=False,
|
||||
domain=[('state', '=', 'draft')])
|
||||
|
||||
@api.model
|
||||
def _prepare_item(self, line):
|
||||
return {
|
||||
'line_id': line.id,
|
||||
'product_id': line.product_id.id,
|
||||
'name': line.name,
|
||||
'product_qty': line.qty_to_supplier_rma,
|
||||
'uom_id': line.uom_id.id,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(RmaLineMakeSupplierRma, 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)])
|
||||
suppliers = lines.mapped('supplier_address_id')
|
||||
if len(suppliers) == 1:
|
||||
res['partner_id'] = suppliers.id
|
||||
else:
|
||||
raise exceptions.Warning(
|
||||
_('Only RMA lines from the same supplier address can be '
|
||||
'processed at the same time'))
|
||||
res['item_ids'] = items
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _prepare_supplier_rma(self, company):
|
||||
if not self.partner_id:
|
||||
raise exceptions.Warning(
|
||||
_('Enter a supplier.'))
|
||||
return {
|
||||
'partner_id': self.partner_id.id,
|
||||
'delivery_address_id': self.partner_id.id,
|
||||
'type': 'supplier',
|
||||
'company_id': company.id,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _prepare_supplier_rma_line(self, rma, item):
|
||||
operation = self.env['rma.operation'].search(
|
||||
[('type', '=', 'supplier')], limit=1)
|
||||
return {
|
||||
'origin': item.line_id.rma_id.name,
|
||||
'delivery_address_id':
|
||||
item.line_id.delivery_address_id.id,
|
||||
'product_id': item.line_id.product_id.id,
|
||||
'customer_rma_id': item.line_id.id,
|
||||
'product_qty': item.product_qty,
|
||||
'rma_id': rma.id,
|
||||
'operation_id': operation.id,
|
||||
'receipt_policy': operation.receipt_policy,
|
||||
'delivery_policy': operation.delivery_policy,
|
||||
'in_warehouse_id': operation.in_warehouse_id.id,
|
||||
'out_warehouse_id': operation.out_warehouse_id.id,
|
||||
'location_id': operation.location_id.id,
|
||||
'supplier_to_customer': operation.supplier_to_customer,
|
||||
'in_route_id': operation.in_route_id.id,
|
||||
'out_route_id': operation.out_route_id.id,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def make_supplier_rma(self):
|
||||
res = []
|
||||
rma_obj = self.env['rma.order']
|
||||
rma_line_obj = self.env['rma.order.line']
|
||||
rma = False
|
||||
|
||||
for item in self.item_ids:
|
||||
line = item.line_id
|
||||
if item.product_qty <= 0.0:
|
||||
raise exceptions.Warning(
|
||||
_('Enter a positive quantity.'))
|
||||
|
||||
if self.supplier_rma_id:
|
||||
rma = self.supplier_rma_id
|
||||
if not rma:
|
||||
rma_data = self._prepare_supplier_rma(line.company_id)
|
||||
rma = rma_obj.create(rma_data)
|
||||
|
||||
rma_line_data = self._prepare_supplier_rma_line(rma, item)
|
||||
rma_line_obj.create(rma_line_data)
|
||||
res.append(rma.id)
|
||||
|
||||
return {
|
||||
'domain': "[('id','in', ["+','.join(map(str, res))+"])]",
|
||||
'name': _('Supplier RMA'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'rma.order',
|
||||
'view_id': False,
|
||||
'context': {'supplier': 1},
|
||||
'type': 'ir.actions.act_window'
|
||||
}
|
||||
|
||||
|
||||
class RmaLineMakeRmaOrderItem(models.TransientModel):
|
||||
_name = "rma.order.line.make.supplier.rma.item"
|
||||
_description = "RMA Line Make Supplier RMA Item"
|
||||
|
||||
wiz_id = fields.Many2one(
|
||||
'rma.order.line.make.supplier.rma',
|
||||
string='Wizard', required=True, ondelete='cascade',
|
||||
readonly=True)
|
||||
line_id = fields.Many2one('rma.order.line',
|
||||
string='RMA Line',
|
||||
required=True)
|
||||
rma_id = fields.Many2one('rma.order', related='line_id.rma_id',
|
||||
string='RMA Order', readonly=True)
|
||||
product_id = fields.Many2one('product.product',
|
||||
related='line_id.product_id', readony=True)
|
||||
name = fields.Char(related='line_id.name', readonly=True)
|
||||
uom_id = fields.Many2one('product.uom', string='UoM', readonly=True)
|
||||
product_qty = fields.Float(string='Quantity to sell',
|
||||
digits=dp.get_precision('Product UoS'))
|
||||
89
rma/wizards/rma_order_line_make_supplier_rma_view.xml
Normal file
89
rma/wizards/rma_order_line_make_supplier_rma_view.xml
Normal file
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2016 Eficent Business and IT Consulting Services S.L.
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_rma_order_line_make_supplier_rma"
|
||||
model="ir.ui.view">
|
||||
<field name="name">RMA Line Make Supplier RMA</field>
|
||||
<field name="model">rma.order.line.make.supplier.rma</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create Supplier RMA">
|
||||
<separator string="Existing Supplier RMA to update:"/>
|
||||
<newline/>
|
||||
<group>
|
||||
<field name="supplier_rma_id"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<separator
|
||||
string="New RMA 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="uom_id"
|
||||
groups="product.group_uom"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<newline/>
|
||||
<group colspan="2">
|
||||
<button name="make_supplier_rma"
|
||||
string="Create/Update Supplier RMA"
|
||||
type="object"
|
||||
class="oe_highlight"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rma_order_line_make_supplier_rma"
|
||||
model="ir.actions.act_window">
|
||||
<field name="name">Create Supplier RMA</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">rma.order.line.make.supplier.rma</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_rma_order_line_make_supplier_rma"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<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</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'))" />
|
||||
<field name="key">action</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rma_line_supplier_rma_button_form" model="ir.ui.view">
|
||||
<field name="name">rma.order.line.supplier.rma.form</field>
|
||||
<field name="model">rma.order.line</field>
|
||||
<field name="inherit_id" ref="rma.view_rma_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<header position="inside">
|
||||
<button name="%(action_rma_order_line_make_supplier_rma)d"
|
||||
states="approved"
|
||||
string="Create Supplier RMA" class="oe_highlight"
|
||||
type="action"/>
|
||||
</header>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
17
rma/wizards/stock_config_settings.py
Normal file
17
rma/wizards/stock_config_settings.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from openerp import models, fields
|
||||
|
||||
|
||||
class StockConfigSettings(models.Model):
|
||||
_inherit = 'stock.config.settings'
|
||||
|
||||
group_rma_delivery_address = fields.Selection([
|
||||
(0, "Invoicing and shipping addresses are always the same "
|
||||
"(Example: services companies)"),
|
||||
(1, 'Display 3 fields on rma: partner, invoice address, delivery '
|
||||
'address')
|
||||
], "Addresses",
|
||||
implied_group='rma.group_rma_delivery_invoice_address')
|
||||
17
rma/wizards/stock_config_settings.xml
Normal file
17
rma/wizards/stock_config_settings.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_stock_config_settings_rma" model="ir.ui.view">
|
||||
<field name="name">stock.config.settings.rma</field>
|
||||
<field name="model">stock.config.settings</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_config_settings"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[@name='shipping']" position="after">
|
||||
<group string="Return Merchandise Authorization">
|
||||
<field name="group_rma_delivery_address" widget="radio"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user