[ADD]add RMA (Return Merchandise Authorizationing) module

This commit is contained in:
Rutuba Chavda 2018-01-17 12:58:52 +05:30
parent 0ee5993e2e
commit aa7a8326a3
32 changed files with 1920 additions and 0 deletions

4
addons/rma/__init__.py Normal file
View File

@ -0,0 +1,4 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from . import models
from . import wizard

View File

@ -0,0 +1,39 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
{
'name': 'Return Merchandise Authorizationing',
'version': '1.0',
'author': 'Flectra',
'website': 'https://flectrahq.com',
'description': """
Return Merchandise Authorizationing is part of the process of a
consumer returning a product to receive a refund, replacement or repair
during the product's warranty period.
""",
'category': 'Sales',
'depends': ['sale_management', 'stock', 'purchase'],
'data': [
'security/ir.model.access.csv',
'data/mail_message_subtype_data.xml',
'data/mail_template_data.xml',
'data/replacement_reason_data.xml',
'sequences/data_rma_order_sequence.xml',
'views/rma_request_view.xml',
'views/replacement_reason_view.xml',
'views/rma_line_view.xml',
'views/stock_production_lot_view.xml',
'views/stock_picking_view.xml',
'views/warranty_expire_line_view.xml',
'views/sales_team_view.xml',
'views/menuitems_view.xml',
],
'demo': [
'demo/product_demo.xml',
'demo/stock_demo.xml',
'demo/sale_order_demo.xml',
],
'application': True,
}

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="mt_request_create" model="mail.message.subtype">
<field name="name">Request Created</field>
<field name="hidden" eval="True"/>
<field name="res_model">rma.request</field>
<field name="default" eval="False"/>
<field name="description">Replacement Request is Created</field>
</record>
<record id="mt_salesteam_request" model="mail.message.subtype">
<field name="name">Request Created</field>
<field name="sequence">10</field>
<field name="res_model">rma.request</field>
<field name="default" eval="False"/>
<field name="parent_id" eval="ref('mt_request_create')"/>
<field name="relation_field">team_id</field>
</record>
<record id="mt_request_confirm" model="mail.message.subtype">
<field name="name">Request Confirmed</field>
<field name="hidden" eval="True"/>
<field name="res_model">rma.request</field>
<field name="default" eval="False"/>
<field name="description">Replacement Request has been
Confirmed</field>
</record>
<record id="mt_salesteam_request_confirm" model="mail.message.subtype">
<field name="name">Request Confirmed</field>
<field name="sequence">11</field>
<field name="res_model">rma.request</field>
<field name="default" eval="False"/>
<field name="parent_id" eval="ref('mt_request_confirm')"/>
<field name="relation_field">team_id</field>
</record>
<record id="mt_request_replaced" model="mail.message.subtype">
<field name="name">Replacement created</field>
<field name="hidden" eval="True"/>
<field name="res_model">rma.request</field>
<field name="default" eval="False"/>
<field name="description">Products have been replaced</field>
</record>
<record id="mt_salesteam_request_replaced" model="mail.message.subtype">
<field name="name">Replacement created</field>
<field name="sequence">12</field>
<field name="res_model">rma.request</field>
<field name="default" eval="False"/>
<field name="parent_id" eval="ref('mt_request_replaced')"/>
<field name="relation_field">team_id</field>
</record>
</flectra>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record id="email_template_notify_warranty_new" model="mail.template">
<field name="name">Warranty: Product Warranty email</field>
<field name="email_from">
${(object.user_id.email and '%s &lt;%s&gt;' % (object.user_id.name, object.user_id.email) or '')|safe}
</field>
<field name="subject">${object.name or 'n/a'}</field>
<field name="partner_to">${object.partner_id.id}</field>
<field name="model_id" ref="rma.model_rma_request"/>
<field name="auto_delete" eval="True"/>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html"><![CDATA[
% if object.warranty_expire_line:
<div>
<p>Dear ${object.partner_id.name}</p>
<p>We are sorry to hear about the problem you have had
with your product.
</p>
<p> We would like to be able to make the necessary
adjustment at no charge to you,
but unfortunately the warranty is expired of
following products:
</p>
</div>
<table border="1" width="100%">
<thead>
<tr>
<th>Product</th>
<th>Lot</th>
<th>Quantity</th>
<th>Warranty Date</th>
</tr>
</thead>
<tbody>
% for line in object.warranty_expire_line:
<tr>
<td>${line.product_id.name}</td>
<td>${line.lot_id.name}</td>
<td>${line.qty_expired}</td>
<td>${line.warranty_date}</td>
</tr>
% endfor
</tbody>
</table>
% else:
<div>
<p>Dear ${object.partner_id.name}</p>
<p>We are sorry to hear about the problem you have had
with your product.</p>
<p>We would like to be able to make the necessary
adjustment at no charge to you, We are going to
replace your product. We will deliver it to
you as possible.
</p>
</div>
% endif
]]>
</field>
</record>
</flectra>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record model="replacement.reason" id="data_replace_reason_1">
<field name="name">Better price available</field>
</record>
<record model="replacement.reason" id="data_replace_reason_2">
<field name="name">Incompatible or not useful</field>
</record>
<record model="replacement.reason" id="data_replace_reason_3">
<field name="name">Product damaged, but shipping box OK</field>
</record>
<record model="replacement.reason" id="data_replace_reason_4">
<field name="name">Item arrived too late</field>
</record>
<record model="replacement.reason" id="data_replace_reason_5">
<field name="name">Missing parts or accessories</field>
</record>
<record model="replacement.reason" id="data_replace_reason_6">
<field name="name">Both product and shipping box damaged</field>
</record>
<record model="replacement.reason" id="data_replace_reason_7">
<field name="name">Wrong item was sent</field>
</record>
<record model="replacement.reason" id="data_replace_reason_8">
<field name="name">No longer needed</field>
</record>
<record model="replacement.reason" id="data_replace_reason_9">
<field name="name">Item defective or doesn't work</field>
</record>
<record model="replacement.reason" id="data_replace_reason_10">
<field name="name">Didn't approve purchase</field>
</record>
<record model="replacement.reason" id="data_replace_reason_11">
<field name="name">Performace or quality not adequate</field>
</record>
<record model="replacement.reason" id="data_replace_reason_12">
<field name="name">Inaccurate website description</field>
</record>
</flectra>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record id="demo_product_1" model="product.product">
<field name="name">Demo Product1</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="standard_price">100.0</field>
<field name="list_price">200.0</field>
<field name="type">product</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="uom_po_id" ref="product.product_uom_unit"/>
<field name="description">Demo product1
</field>
<field name="default_code">DEMO-PROD1</field>
<field name="tracking">lot</field>
</record>
<record id="demo_product_2" model="product.product">
<field name="name">Demo Product2</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="standard_price">200.0</field>
<field name="list_price">250.0</field>
<field name="type">product</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="uom_po_id" ref="product.product_uom_unit"/>
<field name="description">Demo product2
</field>
<field name="default_code">DEMO-PROD2</field>
<field name="tracking">lot</field>
</record>
</flectra>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record id="demo_sale_order_rma_request1" model="sale.order">
<field name="partner_id" ref="base.res_partner_4"/>
<field name="partner_invoice_id" ref="base.res_partner_address_13"/>
<field name="partner_shipping_id" ref="base.res_partner_address_13"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="demo_sale_order_rma_request1_line_1"
model="sale.order.line">
<field name="order_id" ref="demo_sale_order_rma_request1"/>
<field name="name">Demo Product1</field>
<field name="product_id" ref="rma.demo_product_1"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">150.00</field>
</record>
<record id="demo_sale_order_rma_request2" model="sale.order">
<field name="partner_id" ref="base.res_partner_4"/>
<field name="partner_invoice_id" ref="base.res_partner_address_13"/>
<field name="partner_shipping_id" ref="base.res_partner_address_13"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="demo_sale_order_rma_request2_line_1"
model="sale.order.line">
<field name="order_id" ref="demo_sale_order_rma_request2"/>
<field name="name">Demo Product1</field>
<field name="product_id" ref="rma.demo_product_1"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">150.00</field>
</record>
<record id="demo_sale_order_rma_request2_line_2"
model="sale.order.line">
<field name="order_id" ref="demo_sale_order_rma_request2"/>
<field name="name">Demo Product2</field>
<field name="product_id" ref="rma.demo_product_2"/>
<field name="product_uom_qty">10</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">200.00</field>
</record>
</flectra>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record id="demo_stock_inventory_line_1" model="stock.inventory.line">
<field name="product_id" ref="rma.demo_product_1"/>
<field name="product_uom_id" ref="product.product_uom_unit"/>
<field name="inventory_id" ref="stock.stock_inventory_0"/>
<field name="product_qty">20.0</field>
<field name="location_id" ref="stock.stock_location_14"/>
</record>
<record id="demo_stock_inventory_line_2" model="stock.inventory.line">
<field name="product_id" ref="rma.demo_product_2"/>
<field name="product_uom_id" ref="product.product_uom_unit"/>
<field name="inventory_id" ref="stock.stock_inventory_0"/>
<field name="product_qty">30.0</field>
<field name="location_id" ref="stock.stock_location_14"/>
</record>
</flectra>

538
addons/rma/i18n/rma.pot Normal file
View File

@ -0,0 +1,538 @@
# Translation of Flectra Server.
# This file contains the translation of the following modules:
# * rma
#
msgid ""
msgstr ""
"Project-Id-Version: Flectra Server 1.0alpha\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-12-25 11:22+0000\n"
"PO-Revision-Date: 2017-12-25 11:22+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: rma
#: model:mail.template,body_html:rma.email_template_notify_warranty_new
msgid "\n"
" % if object.warranty_expire_line:\n"
" <div>\n"
" <p>Dear ${object.partner_id.name}</p>\n"
" <p>We are sorry to hear about the problem you have had\n"
" with your product.\n"
" We would like to be able to make the necessary\n"
" adjustment at no charge to you,\n"
" but unfortunately the warranty is expired of\n"
" following products:\n"
" </p>\n"
" </div>\n"
"\n"
" <table border=\"1\" width=\"100%\">\n"
" <thead>\n"
" <tr>\n"
" <th>Product</th>\n"
" <th>Lot</th>\n"
" <th>Quantity</th>\n"
" <th>Warranty Date</th>\n"
" </tr>\n"
" </thead>\n"
" <tbody>\n"
" % for line in object.warranty_expire_line:\n"
" <tr>\n"
" <td>${line.product_id.name}</td>\n"
" <td>${line.lot_id.name}</td>\n"
" <td>${line.qty_expired}</td>\n"
" <td>${line.warranty_date}</td>\n"
" </tr>\n"
" % endfor\n"
" </tbody>\n"
" </table>\n"
" % else:\n"
" <div>\n"
" <p>Dear ${object.partner_id.name}</p>\n"
" <p>We are sorry to hear about the problem you have had\n"
" with your product.\n"
" We would like to be able to make the necessary\n"
" adjustment at no charge to you, We are going to\n"
" replace your product. We will deliver it to\n"
" you as possible.\n"
" </p>\n"
" </div>\n"
" % endif\n"
"\n"
" "
msgstr ""
#. module: rma
#: model:mail.template,subject:rma.email_template_notify_warranty_new
msgid "${object.name or 'n/a'}"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_request.py:147
#, python-format
msgid "Compose Email"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_form
msgid "Confirm"
msgstr ""
#. module: rma
#: selection:rma.request,state:0
msgid "Confirmed"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_form
msgid "Create Replacement"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_create_uid
#: model:ir.model.fields,field_description:rma.field_rma_line_create_uid
#: model:ir.model.fields,field_description:rma.field_rma_request_create_uid
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_create_uid
msgid "Created by"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_create_date
#: model:ir.model.fields,field_description:rma.field_rma_line_create_date
#: model:ir.model.fields,field_description:rma.field_rma_request_create_date
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_create_date
msgid "Created on"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_partner_id
msgid "Customer"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_line_qty_delivered
msgid "Delivered Quantity"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_picking_count
#: model:ir.model.fields,field_description:rma.field_rma_request_picking_ids
#: model:ir.ui.view,arch_db:rma.view_rma_request_form
msgid "Delivery"
msgstr ""
#. module: rma
#: model:product.product,name:rma.demo_product_1
#: model:product.template,name:rma.demo_product_1_product_template
#: model:stock.inventory.line,product_name:rma.demo_stock_inventory_line_1
msgid "Demo Product1"
msgstr ""
#. module: rma
#: model:product.product,name:rma.demo_product_2
#: model:product.template,name:rma.demo_product_2_product_template
#: model:stock.inventory.line,product_name:rma.demo_stock_inventory_line_2
msgid "Demo Product2"
msgstr ""
#. module: rma
#: model:product.product,description:rma.demo_product_1
#: model:product.template,description:rma.demo_product_1_product_template
msgid "Demo product1\n"
" "
msgstr ""
#. module: rma
#: model:product.product,description:rma.demo_product_2
#: model:product.template,description:rma.demo_product_2_product_template
msgid "Demo product2\n"
" "
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_display_name
#: model:ir.model.fields,field_description:rma.field_rma_line_display_name
#: model:ir.model.fields,field_description:rma.field_rma_request_display_name
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_display_name
msgid "Display Name"
msgstr ""
#. module: rma
#: selection:rma.request,state:0
msgid "Draft"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_qty_expired
msgid "Expired Quantity"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Group By"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_id
#: model:ir.model.fields,field_description:rma.field_rma_line_id
#: model:ir.model.fields,field_description:rma.field_rma_request_id
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_id
msgid "ID"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason___last_update
#: model:ir.model.fields,field_description:rma.field_rma_line___last_update
#: model:ir.model.fields,field_description:rma.field_rma_request___last_update
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line___last_update
msgid "Last Modified on"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_write_uid
#: model:ir.model.fields,field_description:rma.field_rma_line_write_uid
#: model:ir.model.fields,field_description:rma.field_rma_request_write_uid
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_write_uid
msgid "Last Updated by"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_write_date
#: model:ir.model.fields,field_description:rma.field_rma_line_write_date
#: model:ir.model.fields,field_description:rma.field_rma_request_write_date
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_write_date
msgid "Last Updated on"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_warranty_date
msgid "Lot Warranty Date"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_stock_production_lot
msgid "Lot/Serial"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "My Requests"
msgstr ""
#. module: rma
#: code:addons/rma/wizard/stock_return_picking.py:62
#, python-format
msgid "No products to replace (only lines in Done state andnot fully replaced yet can be replaced)!"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,help:rma.replacement_request_action_reports
msgid "No replacement request."
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_crm_team_replacements_count
msgid "Number of replacements"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Partner"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_picking_id
msgid "Picking Number"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_line_product_id
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_product_id
msgid "Product"
msgstr ""
#. module: rma
#: model:mail.message.subtype,description:rma.mt_request_replaced
msgid "Products have been replaced"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_rma_line
msgid "RMA Line"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.act_open_rma_line_view
#: model:ir.model.fields,field_description:rma.field_rma_request_rma_line
#: model:ir.ui.view,arch_db:rma.view_rma_line_form
#: model:ir.ui.view,arch_db:rma.view_rma_request_form
msgid "RMA Lines"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_name
#: model:ir.model.fields,field_description:rma.field_stock_picking_rma_id
msgid "RMA Order Number"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.act_open_rma_request_view
#: model:ir.actions.act_window,name:rma.action_open_rma_request_replacementteam
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "RMA Request"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_line_rma_id
msgid "RMA Request Number"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_rma_request
msgid "RMA Reuqest"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_rma_id
msgid "RMA Reuqest Number"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_name
#: model:ir.model.fields,field_description:rma.field_rma_line_reason_id
#: model:ir.ui.view,arch_db:rma.view_replacement_reason_form
msgid "Reason"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_line_remark
msgid "Remark"
msgstr ""
#. module: rma
#: model:ir.ui.menu,name:rma.menu_request_rma
msgid "Replace Request"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_crm_team_use_replacement
#: model:ir.ui.menu,name:rma.rma_request_menu
#: model:ir.ui.view,arch_db:rma.crm_team_replacement_teams_view_kanban
#: model:ir.ui.view,arch_db:rma.replacement_view_kanban
#: selection:rma.request,type:0
msgid "Replacement"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
#: selection:rma.request,state:0
msgid "Replacement Created"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_line_qty_replaced
msgid "Replacement Quantity"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.act_open_replacement_reason_view
#: model:ir.model,name:rma.model_replacement_reason
#: model:ir.ui.menu,name:rma.menu_replacement_reason
msgid "Replacement Reason"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_line_graph
msgid "Replacement Request"
msgstr ""
#. module: rma
#: model:mail.message.subtype,description:rma.mt_request_confirm
msgid "Replacement Request has been\n"
" Confirmed"
msgstr ""
#. module: rma
#: model:mail.message.subtype,description:rma.mt_request_create
msgid "Replacement Request is Created"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.replacement_request_action_reports
msgid "Replacement Requests"
msgstr ""
#. module: rma
#: model:mail.message.subtype,name:rma.mt_request_replaced
#: model:mail.message.subtype,name:rma.mt_salesteam_request_replaced
msgid "Replacement created"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.crm_team_replacement_teams_view_kanban
msgid "Replacements"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_line.py:35
#, python-format
msgid "Replacemet quantity of %s should not be greater than ordered quantity."
msgstr ""
#. module: rma
#: model:mail.message.subtype,name:rma.mt_request_confirm
#: model:mail.message.subtype,name:rma.mt_salesteam_request_confirm
msgid "Request Confirmed"
msgstr ""
#. module: rma
#: model:mail.message.subtype,name:rma.mt_request_create
#: model:mail.message.subtype,name:rma.mt_salesteam_request
msgid "Request Created"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_date
msgid "Request Date"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Request Month"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_state
msgid "Request Status"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_type
msgid "Request Type"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_form
msgid "Requests for RMA"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_stock_return_picking
msgid "Return Picking"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_sale_order_id
msgid "SO Number"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Sale Order"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_crm_team
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Sales Channel"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_line_filter
msgid "Search RMA Line"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Search RMA Request"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_form
msgid "Send By Email"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "State"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_line_move_line_id
msgid "Stock Move"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_lot_id
msgid "Stock production lot"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_line_team_id
#: model:ir.model.fields,field_description:rma.field_rma_request_team_id
msgid "Team"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_stock_picking
msgid "Transfer"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_line_uom_id
msgid "UOM"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_user_id
msgid "User"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.act_open_warranty_expire_line_view
#: model:ir.model,name:rma.model_warranty_expire_line
#: model:ir.model.fields,field_description:rma.field_rma_request_warranty_expire_line
#: model:ir.ui.view,arch_db:rma.view_rma_request_form
#: model:ir.ui.view,arch_db:rma.view_warranty_expire_line_form
msgid "Warranty Expire Lines"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_stock_production_lot_warranty_date
msgid "Warranty Expiry Date"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_line.py:30
#, python-format
msgid "You can only replace %s quantity for product %s as its warranty has been expired."
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_request.py:183
#, python-format
msgid "You cannot delete a request which is not in draft state."
msgstr ""
#. module: rma
#: code:addons/rma/wizard/stock_return_picking.py:16
#, python-format
msgid "You may only replace single picking at a time!"
msgstr ""
#. module: rma
#: code:addons/rma/wizard/stock_return_picking.py:26
#, python-format
msgid "You may only return Done pickings"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_request.py:174
#, python-format
msgid "You must select rma lines!"
msgstr ""

View File

@ -0,0 +1,9 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from . import rma_line
from . import warranty_expire_line
from . import rma_request
from . import stock_production_lot
from . import stock_picking
from . import sales_team
from . import replacement_reason

View File

@ -0,0 +1,10 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import fields, models
class ReplacementReason(models.Model):
_name = "replacement.reason"
_description = "Replacement Reason"
name = fields.Char(string='Reason')

View File

@ -0,0 +1,40 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import api, fields, models, _
from flectra.exceptions import UserError
class RMALine(models.Model):
_name = "rma.line"
_description = "RMA Line"
product_id = fields.Many2one('product.product', string='Product')
uom_id = fields.Many2one('product.uom', string='UOM')
qty_delivered = fields.Float(string='Delivered Quantity')
qty_replaced = fields.Float(string='Replacement Quantity')
rma_id = fields.Many2one('rma.request', string='RMA Request Number')
move_line_id = fields.Many2one('stock.move', string='Stock Move')
reason_id = fields.Many2one("replacement.reason", sting='Reason for RMA')
remark = fields.Text(sting='Remark')
team_id = fields.Many2one('crm.team', 'Team', related='rma_id.team_id')
@api.onchange('qty_replaced')
def _onchange_qty_replaced(self):
if self.product_id.tracking != 'none':
replaceable_qty = sum(line.qty_done for line in
self.move_line_id.move_line_ids if
line.lot_id.warranty_date and
line.lot_id.warranty_date >=
self.rma_id.date)
if self.qty_replaced > replaceable_qty:
raise UserError(_('You can only replace %s quantity for '
'product %s as its warranty has been '
'expired.') % (replaceable_qty,
self.product_id.name))
elif self.qty_replaced > self.qty_delivered:
raise UserError(_('Replacemet quantity of %s should not be '
'greater than ordered quantity.') %
(self.product_id.name))
if self.qty_replaced == 0:
raise UserError(_('Replacement quantity should not be 0.'))

View File

@ -0,0 +1,186 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import api, fields, models, _
from flectra.exceptions import UserError
class RmaRequest(models.Model):
_name = "rma.request"
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = "RMA Request"
name = fields.Char(string='RMA Order Number')
sale_order_id = fields.Many2one('sale.order', string='SO Number')
picking_id = fields.Many2one('stock.picking', string='Picking Number')
date = fields.Date(string='Request Date',
default=fields.Date.context_today)
partner_id = fields.Many2one('res.partner', string='Customer')
type = fields.Selection([
('replacement', 'Replacement')
], string='Request Type')
rma_line = fields.One2many('rma.line', 'rma_id', string='RMA Lines')
warranty_expire_line = fields.One2many('warranty.expire.line', 'rma_id',
string='Warranty Expire Lines')
state = fields.Selection([
('draft', 'Draft'),
('confirmed', 'Confirmed'),
('replacement_created', 'Replacement Created'),
], string='Request Status', track_visibility='onchange', readonly=True,
copy=False, default='draft')
picking_count = fields.Integer(string='Delivery',
compute="_compute_picking")
picking_ids = fields.Many2many('stock.picking',
string='Delivery',
compute="_compute_picking")
user_id = fields.Many2one('res.users', string='User',
default=lambda self: self.env.user)
team_id = fields.Many2one('crm.team', string='Team')
@api.multi
def _compute_picking(self):
for request in self:
picking_ids = self.env['stock.picking'].search([(
'rma_id', '=', request.id)])
request.picking_ids = picking_ids and picking_ids.ids or False
request.picking_count = len(picking_ids)
@api.onchange('sale_order_id')
def _get_partner(self):
if self.sale_order_id:
self.partner_id = self.sale_order_id.partner_id and \
self.sale_order_id.partner_id.id or False
self.team_id = self.sale_order_id.team_id and \
self.sale_order_id.team_id.id or False
@api.onchange('picking_id')
def _get_rma_lines(self):
if self.picking_id:
move_line_ids = self.env['stock.move'].search([(
'picking_id', '=', self.picking_id.id)])
move_lines = [(5, 0, 0)]
for line in move_line_ids:
move_lines.append((0, 0, {
'product_id': line.product_id.id,
'uom_id': line.product_uom.id,
'qty_delivered': line.quantity_done,
'qty_replaced': sum(line.qty_done for line in
line.move_line_ids if
line.lot_id.warranty_date and
line.lot_id.warranty_date >= self.date
),
'rma_id': self.id,
'move_line_id': line.id
}))
self.rma_line = move_lines
@api.onchange('rma_line', 'date')
def _get_warranty_lines(self):
warranty_lines = [(5, 0, 0)]
for line in self.rma_line:
if line.move_line_id and \
line.move_line_id.product_id.tracking != 'none':
for move_line in line.move_line_id.move_line_ids:
if move_line.lot_id.warranty_date and \
move_line.lot_id.warranty_date < self.date:
warranty_lines.append((0, 0, {
'product_id': move_line.product_id.id,
'lot_id': move_line.lot_id.id,
'warranty_date':
move_line.lot_id.warranty_date,
'qty_expired': sum(line.qty_done for line in
line.move_line_id.move_line_ids
if line.lot_id.warranty_date and
line.lot_id.
warranty_date < self.date),
'rma_id': self.id,
}))
self.warranty_expire_line = warranty_lines
@api.model
def create(self, vals):
vals.update({
'name': self.env['ir.sequence'].next_by_code(
'rma_order')
})
return super(RmaRequest, self).create(vals)
@api.multi
def action_create_delivery(self):
self.ensure_one()
action = self.env.ref('stock.action_picking_tree_all')
result = action.read()[0]
if len(self.picking_ids) != 1:
result.update({
'domain': "[('id', 'in', " + str(self.picking_ids.ids) + ")]"
})
elif len(self.picking_ids) == 1:
res = self.env.ref('rma.view_picking_form', False)
result.update({
'views': [(res and res.id or False, 'form')],
'res_id': self.picking_ids.id
})
return result
@api.multi
def action_notify_warranty(self):
self.ensure_one()
ir_model_data = self.env['ir.model.data']
try:
template_id = ir_model_data.get_object_reference(
'rma', 'email_template_notify_warranty_new')[1]
except ValueError:
template_id = False
try:
compose_form_id = ir_model_data.get_object_reference(
'mail', 'email_compose_message_wizard_form')[1]
except ValueError:
compose_form_id = False
ctx = dict(
default_model='rma.request',
default_res_id=self.id,
default_use_template=bool(template_id),
default_template_id=template_id,
default_composition_mode='comment',
force_email=True
)
return {
'name': _('Compose Email'),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'mail.compose.message',
'views': [(compose_form_id, 'form')],
'view_id': compose_form_id,
'target': 'new',
'context': ctx,
}
@api.multi
def _track_subtype(self, init_values):
self.ensure_one()
if 'state' in init_values and self.state == 'draft' and self.rma_line:
return 'rma.mt_request_create'
elif 'state' in init_values and self.state == 'confirmed' and \
self.rma_line:
return 'rma.mt_request_confirm'
elif 'state' in init_values and self.state == 'replacement_created':
return 'rma.mt_request_replaced'
return super(RmaRequest, self)._track_subtype(init_values)
@api.multi
def action_confirm_request(self):
self.ensure_one()
if not self.rma_line:
raise UserError(_('You must select rma lines!'))
for line in self.rma_line:
line._onchange_qty_replaced()
self.state = 'confirmed'
@api.multi
def unlink(self):
for request in self:
if request.state != 'draft':
raise UserError(_(
'You cannot delete a request which is not in draft '
'state.'))
return super(RmaRequest, self).unlink()

View File

@ -0,0 +1,19 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import fields, models
class CrmTeam(models.Model):
_inherit = 'crm.team'
use_replacement = fields.Boolean(string='Replacement')
replacements_count = fields.Integer(
compute='_compute_replacements',
string='Number of replacements')
def _compute_replacements(self):
for replace in self:
if replace.use_replacement:
rma_ids = self.env['rma.request'].search([
('team_id.id', '=', replace.id)])
replace.replacements_count = len(rma_ids)

View File

@ -0,0 +1,20 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import api, fields, models
class StockPicking(models.Model):
_inherit = 'stock.picking'
rma_id = fields.Many2one('rma.request', string='RMA Order Number')
@api.model
def create(self, vals):
result = super(StockPicking, self).create(vals)
rma_id = False
if self._context.get('active_model') == 'stock.picking':
rma_id = result.rma_id and result.rma_id.id or False
elif self._context.get('active_model') == 'rma.request':
rma_id = self._context.get('active_id')
result.update({'rma_id': rma_id})
return result

View File

@ -0,0 +1,8 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import fields, models
class StockProductionLot(models.Model):
_inherit = 'stock.production.lot'
warranty_date = fields.Date(string='Warranty Expiry Date')

View File

@ -0,0 +1,15 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import fields, models
class WarrantyExpireLine(models.Model):
_name = "warranty.expire.line"
_description = "Warranty Expire Lines"
rma_id = fields.Many2one('rma.request', string='RMA Request Number')
product_id = fields.Many2one('product.product', string='Product')
lot_id = fields.Many2one('stock.production.lot',
string='Stock production lot')
qty_expired = fields.Float(string="Expired Quantity")
warranty_date = fields.Date('Lot Warranty Date')

View File

@ -0,0 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_rma_request,access_rma_request,model_rma_request,,1,1,1,0
access_rma_line,access_rma_line,model_rma_line,,1,1,1,0
access_warranty_expire_line,access_warranty_expire_line,model_warranty_expire_line,,1,1,1,0
access_replacement_reason,access_replacement_reason,model_replacement_reason,,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_rma_request access_rma_request model_rma_request 1 1 1 0
3 access_rma_line access_rma_line model_rma_line 1 1 1 0
4 access_warranty_expire_line access_warranty_expire_line model_warranty_expire_line 1 1 1 0
5 access_replacement_reason access_replacement_reason model_replacement_reason 1 1 1 0

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record id="seq_rma_order" model="ir.sequence">
<field name="name">RMA Order Sequence</field>
<field name="code">rma_order</field>
<field name="prefix">RMA</field>
<field name="padding">4</field>
</record>
</flectra>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,3 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from . import test_rma_request

View File

@ -0,0 +1,172 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra.tests.common import TransactionCase
from datetime import datetime
from dateutil.relativedelta import relativedelta
class TestSaleOrder(TransactionCase):
def setUp(self):
super(TestSaleOrder, self).setUp()
self.demo_product1_id = self.env.ref('rma.demo_product_1')
self.demo_product2_id = self.env.ref('rma.demo_product_2')
self.product1_lot_id = self.env['stock.production.lot'].create({
'name': 'L001',
'product_id': self.demo_product1_id.id,
'warranty_date': datetime.now() + relativedelta(years=1)
})
self.change_prod1_qty_id = self.env[
'stock.change.product.qty'].create({
'product_id': self.demo_product1_id.id,
'new_quantity': 10,
'lot_id': self.product1_lot_id.id
})
self.change_prod1_qty_id.change_product_qty()
self.sale_order_id_1 = self.env.ref(
'rma.demo_sale_order_rma_request1')
self.product2_lot_id = self.env['stock.production.lot'].create({
'name': 'L002',
'product_id': self.demo_product2_id.id,
'warranty_date': datetime.now() - relativedelta(years=1)
})
self.change_prod2_qty_id = self.env[
'stock.change.product.qty'].create({
'product_id': self.demo_product2_id.id,
'new_quantity': 10,
'lot_id': self.product2_lot_id.id
})
self.change_prod2_qty_id.change_product_qty()
self.sale_order_id_2 = self.env.ref(
'rma.demo_sale_order_rma_request2')
def test_00_rma_request(self):
self.sale_order_id_1.action_confirm()
picking_ids = self.sale_order_id_1.picking_ids[0]
for move_line in picking_ids.move_lines[0].move_line_ids:
move_line.lot_id = self.product1_lot_id.id
move_line.qty_done = 5
picking_ids.button_validate()
picking_ids.action_done()
self.rma_id_1 = self.env['rma.request'].create({
'sale_order_id': self.sale_order_id_1.id,
'picking_id': picking_ids[0].id,
'date': datetime.now() - relativedelta(days=15),
'partner_id': self.sale_order_id_1.partner_id.id,
'type': 'replacement'
})
self.assertEquals(self.rma_id_1.state, 'draft')
self.rma_id_1._get_rma_lines()
self.assertTrue((len(self.rma_id_1.rma_line.ids)) != 0,
'You can not create replacement request!')
self.rma_id_1._get_warranty_lines()
self.assertEquals((len(self.rma_id_1.warranty_expire_line.ids)), 0,
'This Replacement request should not have expiry '
'product!')
for rma_line in self.rma_id_1.rma_line:
replaceable_qty = sum(line.qty_done for line in
rma_line.move_line_id.move_line_ids if
line.lot_id.warranty_date and
line.lot_id.warranty_date >=
self.rma_id_1.date)
self.assertTrue(rma_line.qty_replaced <= replaceable_qty,
"You can only replace %d quantity for %s" %
(replaceable_qty, rma_line.product_id.name))
self.rma_id_1.action_confirm_request()
self.assertEquals(self.rma_id_1.state, 'confirmed')
context = {"active_model": 'rma.request',
"active_ids": [self.rma_id_1.id], "active_id":
self.rma_id_1.id, "rma": True}
self.return_picking_id_1 = self.env[
'stock.return.picking'].with_context(context).create(dict(
picking_id=self.rma_id_1.picking_id.id,
))
self.return_picking_id_1.create_returns()
self.assertEquals(self.rma_id_1.state, 'replacement_created')
self.assertTrue(len(self.sale_order_id_1.picking_ids.ids) > 1,
'Product has not been replaced yet')
incoming_shipment = False
for pick in self.sale_order_id_1.picking_ids:
if pick.picking_type_code == 'incoming':
incoming_shipment = True
for move_line in pick.move_lines[0].move_line_ids:
move_line.lot_id = self.product1_lot_id.id
move_line.qty_done = 5
pick.button_validate()
pick.action_done()
self.assertTrue(incoming_shipment, 'Incoming shipment is not created')
def test_01_rma_request(self):
self.sale_order_id_2.action_confirm()
picking_ids = self.sale_order_id_2.picking_ids[0]
for move_line in picking_ids.move_lines[0].move_line_ids:
move_line.lot_id = self.product2_lot_id.id
move_line.qty_done = 10
for move_line in picking_ids.move_lines[1].move_line_ids:
move_line.lot_id = self.product1_lot_id.id
move_line.qty_done = 5
picking_ids.button_validate()
picking_ids.action_done()
self.rma_id_2 = self.env['rma.request'].create({
'sale_order_id': self.sale_order_id_2.id,
'picking_id': picking_ids[0].id,
'date': datetime.now() - relativedelta(days=10),
'partner_id': self.sale_order_id_2.partner_id.id,
'type': 'replacement'
})
self.assertEquals(self.rma_id_2.state, 'draft')
self.rma_id_2._get_rma_lines()
self.assertTrue((len(self.rma_id_2.rma_line.ids)) != 0,
'You can not create replacement request!')
self.rma_id_2._get_warranty_lines()
self.assertEquals((len(self.rma_id_2.warranty_expire_line.ids)), 1,
'Replacement request must have expiry product!')
for rma_line in self.rma_id_2.rma_line:
replaceable_qty = sum(line.qty_done for line in
rma_line.move_line_id.move_line_ids if
line.lot_id.warranty_date and
line.lot_id.warranty_date >=
self.rma_id_2.date)
self.assertTrue(rma_line.qty_replaced <= replaceable_qty,
"You can only return %d quantity for %s" %
(replaceable_qty, rma_line.product_id.name))
self.rma_id_2.state = 'confirmed'
self.assertEquals(self.rma_id_2.state, 'confirmed')
context = {"active_model": 'rma.request',
"active_ids": [self.rma_id_2.id], "active_id":
self.rma_id_2.id, "rma": True}
self.return_picking_id_2 = self.env[
'stock.return.picking'].with_context(context).create(dict(
picking_id=self.rma_id_2.picking_id.id,
))
self.return_picking_id_2.create_returns()
self.assertEquals(self.rma_id_2.state, 'replacement_created')
self.assertTrue(len(self.sale_order_id_2.picking_ids.ids) > 1,
'Product has not been replaced yet')
incoming_shipment = False
for pick in self.sale_order_id_2.picking_ids:
if pick.picking_type_code == 'incoming':
incoming_shipment = True
for move_line in pick.move_lines[0].move_line_ids:
move_line.lot_id = self.product1_lot_id.id
move_line.qty_done = 10
self.assertEquals(len(pick.move_lines[0].move_line_ids.ids), 1,
'Only one product can be returned')
pick.button_validate()
pick.action_done()
self.assertTrue(incoming_shipment, 'Incoming shipment is not created')

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<menuitem id="rma_request_menu"
name="Replacement"
parent="sale.sale_menu_root"
sequence="3"/>
<menuitem id="menu_request_rma"
name="Replace Request"
action="act_open_rma_request_view"
parent="rma_request_menu"
/>
<menuitem id="menu_replacement_reason"
name="Replacement Reason"
action="act_open_replacement_reason_view"
parent="sale.menu_sale_config"
/>
</flectra>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_replacement_reason_tree" model="ir.ui.view">
<field name="name">replacement.reason.tree</field>
<field name="model">replacement.reason</field>
<field name="type">tree</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<tree>
<field name="name"/>
</tree>
</field>
</record>
<record id="view_replacement_reason_form" model="ir.ui.view">
<field name="name">replacement.reason.form</field>
<field name="model">replacement.reason</field>
<field name="type">form</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<form string="Reason">
<sheet>
<group>
<field name="name"/>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.actions.act_window"
id="act_open_replacement_reason_view">
<field name="name">Replacement Reason</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">replacement.reason</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
</flectra>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_rma_line_form" model="ir.ui.view">
<field name="name">rma.line.form</field>
<field name="model">rma.line</field>
<field name="type">form</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<form string="RMA Lines">
<sheet>
<group>
<group>
<field name="product_id"/>
<field name="qty_delivered"/>
<field name="qty_replaced" required="1"/>
<field name="uom_id"/>
</group>
<group>
<field name="rma_id"/>
<field name="reason_id" required="1" options="{'no_create': True}"/>
<field name="remark"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="act_open_rma_line_view">
<field name="name">RMA Lines</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">rma.line</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record id="view_rma_line_filter" model="ir.ui.view">
<field name="name">rma.line.search.view</field>
<field name="model">rma.line</field>
<field name="arch" type="xml">
<search string="Search RMA Line">
<field name="team_id"/>
</search>
</field>
</record>
<record id="view_rma_line_graph" model="ir.ui.view">
<field name="name">rma.line.graph</field>
<field name="model">rma.line</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<graph string="Replacement Request">
<field name="product_id"/>
</graph>
</field>
</record>
<record id="replacement_request_action_reports"
model="ir.actions.act_window">
<field name="name">Replacement Requests</field>
<field name="res_model">rma.line</field>
<field name="view_mode">graph,tree,form</field>
<field name="help" type="html">
<p>
No replacement request.
</p>
</field>
<field name="context">{'search_default_team_id': active_id}</field>
</record>
</flectra>

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_rma_request_tree" model="ir.ui.view">
<field name="name">rma.request.tree</field>
<field name="model">rma.request</field>
<field name="type">tree</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="sale_order_id"/>
<field name="partner_id"/>
<field name="type"/>
<field name="team_id"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="view_rma_request_form" model="ir.ui.view">
<field name="name">rma.request.form</field>
<field name="model">rma.request</field>
<field name="type">form</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<form string="Requests for RMA">
<header>
<button name="action_notify_warranty"
string="Send By Email"
type="object" class="oe_highlight"/>
<button name="%(stock.act_stock_return_picking)d"
string="Create Replacement"
type="action" class="btn-primary"
attrs="{'invisible': [('state', 'in', ['draft', 'replacement_created'])]}"
context="{'rma': True}"
groups="stock.group_stock_manager"/>
<button name="action_confirm_request"
string="Confirm"
type="object" class="oe_highlight"
attrs="{'invisible': [('state', 'in', ['confirmed', 'replacement_created'])]}"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button type="object"
name="action_create_delivery"
class="oe_stat_button"
icon="fa-truck"
attrs="{'invisible': [('state', 'in', ['draft', 'confirmed'])]}">
<field name="picking_count"
widget="statinfo"
string="Delivery"
/>
</button>
</div>
<div class="oe_title">
<h1>
<field name="name" readonly="1"
attrs="{'invisible': [('state', '=', 'draft')]}"
nolabel="1"/>
</h1>
</div>
<group>
<group>
<field name="sale_order_id" required="1"
attrs="{'readonly': [('state', '!=', 'draft')]}"
options="{'no_create': True}"
/>
<field name="partner_id" required="1"
options="{'no_create': True}"
attrs="{'readonly': [('state', '!=', 'draft')]}"
/>
<field name="picking_id" required="1"
options="{'no_create': True}"
domain="[('sale_id', '=', sale_order_id),
('state', '=', 'done'), ('picking_type_code', '=', 'outgoing')]"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="user_id" invisible="1"/>
</group>
<group>
<field name="date" required="1"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="team_id" required="1"
attrs="{'readonly': [('state', '!=', 'draft')]}"
options="{'no_create': True}"/>
<field name="type" required="1"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
</group>
</group>
<notebook>
<page string="RMA Lines">
<field name="rma_line"
attrs="{'readonly': [('state', '!=', 'draft')]}">
<tree editable="bottom" create="false">
<field name="product_id" readonly="1"
force_save="1"/>
<field name="uom_id" readonly="1"
force_save="1"/>
<field name="qty_delivered" readonly="1"
force_save="1"/>
<field name="qty_replaced" required="1"/>
<field name="reason_id" required="1"
options="{'no_create': True}"/>
<field name="remark"/>
<field name="rma_id" invisible="1"/>
<field name="move_line_id" invisible="1"/>
</tree>
</field>
</page>
<page string="Warranty Expire Lines">
<field name="warranty_expire_line"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"
groups="base.group_user"/>
<field name="activity_ids" widget="mail_activity"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="view_rma_request_filter" model="ir.ui.view">
<field name="name">rma.request.search.view</field>
<field name="model">rma.request</field>
<field name="arch" type="xml">
<search string="Search RMA Request">
<field name="name" string="RMA Request"
filter_domain="[('name','ilike',self)]"/>
<field name="partner_id" operator="child_of"/>
<field name="user_id"/>
<field name="state"/>
<field name="team_id" string="Sales Channel"/>
<filter string="My Requests"
domain="[('user_id','=',uid)]"
name="my_rma_request_filter"/>
<filter string="Replacement Created"
domain="[('state','=','replacement_created')]"
name="rma_request_state_filter"/>
<separator/>
<group expand="1" string="Group By">
<filter string="Partner" name="Partner"
context="{'group_by':'partner_id'}"/>
<filter string="Sale Order"
context="{'group_by':'sale_order_id'}"/>
<filter string="State"
context="{'group_by':'state'}"/>
<separator/>
<filter string="Request Month"
context="{'group_by':'date:month'}"/>
</group>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="act_open_rma_request_view">
<field name="name">RMA Request</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">rma.request</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.actions.act_window"
id="action_open_rma_request_replacementteam">
<field name="name">RMA Request</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">rma.request</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{
'search_default_team_id': [active_id],
'default_team_id': active_id,
}
</field>
<field name="search_view_id" ref="view_rma_request_filter"/>
</record>
</flectra>

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="crm_team_replacement_teams_view_form" model="ir.ui.view">
<field name="name">replacement.team.form</field>
<field name="model">crm.team</field>
<field name="inherit_id" ref="sales_team.crm_team_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='options_active']" position="inside">
<div class="o_row" style="display:inherit">
<field name="use_replacement"/>
<label for="use_replacement"/>
</div>
</xpath>
</field>
</record>
<record id="crm_team_replacement_teams_view_kanban" model="ir.ui.view">
<field name="name">replacement.team.kanban</field>
<field name="model">crm.team</field>
<field name="inherit_id"
ref="sale.crm_team_salesteams_view_kanban"/>
<field name="arch" type="xml">
<data>
<xpath expr="//div[hasclass('o_kanban_primary_left')]"
position="inside">
<div>
<button name="%(rma.action_open_rma_request_replacementteam)d"
type="action"
class="btn btn-primary mt8">Replacements
</button>
</div>
</xpath>
<xpath expr="//t[@name='second_options']"
position="after">
<div class="row" t-if="record.replacements_count.raw_value">
<div class="col-xs-8">
<a name="%(rma.action_open_rma_request_replacementteam)d"
type="action">
<field name="replacements_count"/>
<t t-if="record.replacements_count.raw_value == 1">
Replacement
</t>
<t t-else="">Replacements</t>
</a>
</div>
</div>
</xpath>
<xpath expr="//div[hasclass('o_kanban_manage_view')]"
position="inside">
<div>
<a name="%(rma.action_open_rma_request_replacementteam)d"
type="action">Replacements
</a>
</div>
</xpath>
</data>
</field>
</record>
<record id="replacement_view_kanban" model="ir.ui.view">
<field name="name">replacement.kanban</field>
<field name="model">crm.team</field>
<field name="inherit_id"
ref="sales_team.crm_team_salesteams_view_kanban"/>
<field name="arch" type="xml">
<data>
<xpath expr="//div[hasclass('o_kanban_manage_reports')]"
position="inside">
<div name="replacement_report">
<a name="%(rma.replacement_request_action_reports)d"
type="action" context="{'search_default_team_id': active_id}">
Replacement
</a>
</div>
</xpath>
</data>
</field>
</record>
</flectra>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_stock_picking_form" model="ir.ui.view">
<field name="name">stock.picking.form</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='extra']/group/group" position="inside">
<field name="rma_id"/>
</xpath>
</field>
</record>
</flectra>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_stock_production_lot_form_inherit" model="ir.ui.view">
<field name="name">stock.production.lot.form.inherit</field>
<field name="model">stock.production.lot</field>
<field name="inherit_id" ref="stock.view_production_lot_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='ref']" position="after">
<field name="warranty_date" groups="stock.group_stock_manager"/>
</xpath>
</field>
</record>
</flectra>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_warranty_expire_line_tree" model="ir.ui.view">
<field name="name">warranty.expire..line.tree</field>
<field name="model">warranty.expire.line</field>
<field name="type">tree</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<tree create="false" edit="false">
<field name="rma_id" invisible="1"/>
<field name="product_id"/>
<field name="lot_id"/>
<field name="qty_expired"/>
<field name="warranty_date"/>
</tree>
</field>
</record>
<record id="view_warranty_expire_line_form" model="ir.ui.view">
<field name="name">warranty.expire.line.form</field>
<field name="model">warranty.expire.line</field>
<field name="type">form</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<form string="Warranty Expire Lines">
<sheet>
<group>
<field name="product_id" readonly="1"/>
<field name="lot_id" readonly="1"/>
<field name="qty_expired" readonly="1"/>
<field name="warranty_date" readonly="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="act_open_warranty_expire_line_view">
<field name="name">Warranty Expire Lines</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">warranty.expire.line</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
</flectra>

View File

@ -0,0 +1,3 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from . import stock_return_picking

View File

@ -0,0 +1,98 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import api, models, _
from flectra.exceptions import UserError
class ReturnPicking(models.TransientModel):
_inherit = 'stock.return.picking'
@api.model
def default_get(self, fields):
if self._context.get('rma') and self._context.get('active_model') ==\
'rma.request':
res = {}
if len(self.env.context.get('active_ids', list())) > 1:
raise UserError(_(
"You may only replace single picking at a time!"))
move_dest_exists = False
product_return_moves = []
rma_id = self.env['rma.request'].browse(
self.env.context.get('active_id'))
picking = rma_id.picking_id
if picking:
res.update({'picking_id': picking.id})
if picking.state != 'done':
raise UserError(_("You may only return Done pickings"))
for move_line in picking.move_lines:
qty = move_line.product_qty or 0.00
if move_line.move_line_ids:
product_ids = [line.product_id for line in
move_line.move_line_ids]
vals = {}
for rma_line in rma_id.rma_line:
vals.update({
rma_line.product_id.id: rma_line.qty_replaced,
})
for prod_id in product_ids:
if vals.get(prod_id.id):
qty = vals.get(prod_id.id)
if move_line.scrapped:
continue
if move_line.move_dest_ids:
move_dest_exists = True
quantity = qty - sum(
move_line.move_dest_ids.filtered(
lambda m: m.state in [
'partially_available', 'assigned', 'done']
).mapped('move_line_ids').mapped('product_qty'))
product = [line.product_id for line in rma_id.rma_line]
for pid in product:
if move_line.product_id.id == pid.id:
product_return_moves.append(
(0, 0,
{
'product_id': move_line.product_id.id,
'quantity': quantity,
'move_id': move_line.id
}))
if not product_return_moves:
raise UserError(_(
"No products to replace (only lines in Done state and"
"not fully replaced yet can be replaced)!"))
if 'product_return_moves' in fields:
res.update({'product_return_moves': product_return_moves})
if 'move_dest_exists' in fields:
res.update({'move_dest_exists': move_dest_exists})
if 'parent_location_id' in fields and picking.\
location_id.usage == 'internal':
res.update(
{
'parent_location_id':
picking.picking_type_id.warehouse_id and
picking.picking_type_id.warehouse_id.
view_location_id.id or picking.
location_id.location_id.id
})
if 'original_location_id' in fields:
res.update(
{'original_location_id': picking.location_id.id})
if 'location_id' in fields:
location_id = picking.location_id.id
if picking.picking_type_id.return_picking_type_id.\
default_location_dest_id.return_location:
location_id = picking.picking_type_id.\
return_picking_type_id.default_location_dest_id.id
res['location_id'] = location_id
return res
return super(ReturnPicking, self).default_get(fields)
def create_returns(self):
if self._context.get('rma') and self._context.get('active_model') == \
'rma.request':
rma_id = self.env['rma.request'].browse(
self.env.context.get('active_id'))
rma_id.state = 'replacement_created'
return super(ReturnPicking, self).create_returns()