[ADD]:website_rma:Add new module website_rma

This commit is contained in:
Rutuba Chavda 2018-03-05 13:01:06 +05:30
parent 7e41d0f1d3
commit 49eddebd0e
66 changed files with 2456 additions and 339 deletions

View File

@ -7,7 +7,7 @@
'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
consumer returning a product to receive a refund or or replacement
during the product's warranty period.
""",
'category': 'Sales',
@ -16,10 +16,10 @@
'security/ir.model.access.csv',
'data/mail_message_subtype_data.xml',
'data/mail_template_data.xml',
'data/replacement_reason_data.xml',
'data/return_reason_data.xml',
'sequences/data_rma_order_sequence.xml',
'views/rma_request_view.xml',
'views/replacement_reason_view.xml',
'views/return_reason_view.xml',
'views/rma_line_view.xml',
'views/stock_production_lot_view.xml',
'views/stock_picking_view.xml',

View File

@ -6,7 +6,7 @@
<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>
<field name="description">RMA Request is Created</field>
</record>
<record id="mt_salesteam_request" model="mail.message.subtype">
<field name="name">Request Created</field>
@ -22,7 +22,7 @@
<field name="hidden" eval="True"/>
<field name="res_model">rma.request</field>
<field name="default" eval="False"/>
<field name="description">Replacement Request has been
<field name="description">RMA Request has been
Confirmed</field>
</record>
<record id="mt_salesteam_request_confirm" model="mail.message.subtype">
@ -34,19 +34,35 @@
<field name="relation_field">team_id</field>
</record>
<record id="mt_request_replaced" model="mail.message.subtype">
<record id="mt_request_return" model="mail.message.subtype">
<field name="name">Return 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 returned</field>
</record>
<record id="mt_salesteam_request_return" model="mail.message.subtype">
<field name="name">Return 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_return')"/>
<field name="relation_field">team_id</field>
</record>
<record id="mt_replacement_create" 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">
<record id="mt_salesteam_request_replacement" 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="parent_id" eval="ref('mt_replacement_create')"/>
<field name="relation_field">team_id</field>
</record>
</flectra>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record id="email_template_notify_warranty_new" model="mail.template">
<record id="email_template_notify_warranty_date" 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}
@ -12,50 +12,86 @@
<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>
% if object.is_website:
%if object.is_replacement:
<div>
<p>Dear ${object.partner_id.name}</p>
<p>We do hereby confirm the reception of your
request regarding replacement of products
<b>${object.rma_line.product_id.name}</b>, Please accept our apologies
for this incident.</p>
<p> As per your request, a new shipment for
<b>${object.rma_line.product_id.name}</b> will be created
soon and we will replace product.</p>
<p>We are sorry that this occurred and appreciate
your continued patronage, As a thanks for
being one of our best client.
Should you have any questions,
please do not hesitate to contact us.
</p>
<p>Thank You</p>
</div>
%else:
<div>
<p>Dear ${object.partner_id.name}</p>
<p>We do hereby confirm the reception of your
request regarding return of products
<b>${object.rma_line.product_id.name}</b>, Please accept our apologies
for this incident.</p>
<p>We are sorry that this occurred and appreciate
your continued patronage, As a thanks for
being one of our best client.
Should you have any questions,
please do not hesitate to contact us.
</p>
<p>Thank You</p>
</div>
%endif
<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>
% 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.
</p>
</div>
% endif
% endif
]]>
</field>

View File

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

View File

@ -27,4 +27,16 @@
<field name="default_code">DEMO-PROD2</field>
<field name="tracking">lot</field>
</record>
<record id="demo_product_3" model="product.product">
<field name="name">Demo Product3</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="standard_price">150.0</field>
<field name="list_price">300.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 product3
</field>
<field name="default_code">DEMO-PROD3</field>
</record>
</flectra>

View File

@ -4,10 +4,10 @@
#
msgid ""
msgstr ""
"Project-Id-Version: Flectra Server 1.0alpha\n"
"Project-Id-Version: Flectra Server 1.0\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"
"POT-Creation-Date: 2018-03-14 06:04+0000\n"
"PO-Revision-Date: 2018-03-14 06:04+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@ -16,63 +16,100 @@ msgstr ""
"Plural-Forms: \n"
#. module: rma
#: model:mail.template,body_html:rma.email_template_notify_warranty_new
#: model:mail.template,body_html:rma.email_template_notify_warranty_date
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"
" % if object.is_website:\n"
" %if object.is_replacement:\n"
" <div>\n"
" <p>Dear ${object.partner_id.name}</p>\n"
" <p>We do hereby confirm the reception of your\n"
" request regarding replacement of products\n"
" <b>${object.rma_line.product_id.name}</b>, Please accept our apologies\n"
" for this incident.</p>\n"
" <p> As per your request, a new shipment for\n"
" <b>${object.rma_line.product_id.name}</b> will be created\n"
" soon and we will replace product.</p>\n"
" <p>We are sorry that this occurred and appreciate\n"
" your continued patronage, As a thanks for\n"
" being one of our best client.\n"
" Should you have any questions,\n"
" please do not hesitate to contact us.\n"
" </p>\n"
" <p>Thank You</p>\n"
" </div>\n"
" %else:\n"
" <div>\n"
" <p>Dear ${object.partner_id.name}</p>\n"
" <p>We do hereby confirm the reception of your\n"
" request regarding return of products\n"
" <b>${object.rma_line.product_id.name}</b>, Please accept our apologies\n"
" for this incident.</p>\n"
" <p>We are sorry that this occurred and appreciate\n"
" your continued patronage, As a thanks for\n"
" being one of our best client.\n"
" Should you have any questions,\n"
" please do not hesitate to contact us.\n"
" </p>\n"
" <p>Thank You</p>\n"
" </div>\n"
" %endif\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"
" % else:\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"
" </p>\n"
" <p> 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.</p>\n"
" <p>We would like to be able to make the necessary\n"
" adjustment at no charge to you.\n"
" </p>\n"
" </div>\n"
" % endif\n"
" % endif\n"
"\n"
" "
msgstr ""
#. module: rma
#: model:mail.template,subject:rma.email_template_notify_warranty_new
#: model:mail.template,subject:rma.email_template_notify_warranty_date
msgid "${object.name or 'n/a'}"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_request.py:147
#: code:addons/rma/models/rma_request.py:150
#, python-format
msgid "Compose Email"
msgstr ""
@ -89,11 +126,11 @@ msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_form
msgid "Create Replacement"
msgid "Create RMA"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_create_uid
#: model:ir.model.fields,field_description:rma.field_return_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
@ -101,7 +138,7 @@ 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_return_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
@ -139,6 +176,12 @@ msgstr ""
msgid "Demo Product2"
msgstr ""
#. module: rma
#: model:product.product,name:rma.demo_product_3
#: model:product.template,name:rma.demo_product_3_product_template
msgid "Demo Product3"
msgstr ""
#. module: rma
#: model:product.product,description:rma.demo_product_1
#: model:product.template,description:rma.demo_product_1_product_template
@ -154,7 +197,14 @@ msgid "Demo product2\n"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_display_name
#: model:product.product,description:rma.demo_product_3
#: model:product.template,description:rma.demo_product_3_product_template
msgid "Demo product3\n"
" "
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_return_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
@ -177,7 +227,7 @@ 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_return_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
@ -185,7 +235,13 @@ msgid "ID"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason___last_update
#: code:addons/rma/wizard/stock_return_picking.py:16
#, python-format
msgid "It is not replacement request!"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_return_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
@ -193,7 +249,7 @@ 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_return_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
@ -201,7 +257,7 @@ 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_return_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
@ -224,19 +280,19 @@ msgid "My Requests"
msgstr ""
#. module: rma
#: code:addons/rma/wizard/stock_return_picking.py:62
#: model:ir.actions.act_window,help:rma.return_request_action_reports
msgid "No Return request."
msgstr ""
#. module: rma
#: code:addons/rma/wizard/stock_return_picking.py:68
#, python-format
msgid "No products to replace (only lines in Done state andnot fully replaced yet can be replaced)!"
msgid "No products to return (only lines in Done state andnot fully returned yet can be returned)!"
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"
#: model:ir.model.fields,field_description:rma.field_crm_team_returns_count
msgid "Number of returns"
msgstr ""
#. module: rma
@ -256,10 +312,26 @@ msgid "Product"
msgstr ""
#. module: rma
#: model:mail.message.subtype,description:rma.mt_request_replaced
#: model:mail.message.subtype,description:rma.mt_replacement_create
msgid "Products have been replaced"
msgstr ""
#. module: rma
#: model:mail.message.subtype,description:rma.mt_request_return
msgid "Products have been returned"
msgstr ""
#. module: rma
#: model:ir.ui.menu,name:rma.rma_request_menu
msgid "RMA"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
#: selection:rma.request,state:0
msgid "RMA Created"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_rma_line
msgid "RMA Line"
@ -281,30 +353,46 @@ 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.actions.act_window,name:rma.action_open_rma_request_rmateam
#: model:ir.model,name:rma.model_rma_request
#: model:ir.ui.menu,name:rma.menu_request_rma
#: model:ir.ui.view,arch_db:rma.crm_team_rma_teams_view_kanban
#: model:ir.ui.view,arch_db:rma.rma_view_kanban
#: 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
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_rma_id
msgid "RMA Request Number"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_rma_request
msgid "RMA Reuqest"
#: model:mail.message.subtype,description:rma.mt_request_confirm
msgid "RMA Request has been\n"
" Confirmed"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_warranty_expire_line_rma_id
msgid "RMA Reuqest Number"
#: model:mail.message.subtype,description:rma.mt_request_create
msgid "RMA Request is Created"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_replacement_reason_name
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "RMA Request type"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.crm_team_rma_teams_view_kanban
msgid "RMA Requests"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_return_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
#: model:ir.ui.view,arch_db:rma.view_return_reason_form
msgid "Reason"
msgstr ""
@ -314,73 +402,30 @@ 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
#: model:ir.actions.act_window,name:rma.action_open_replacement_request_rmateam
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
#: model:mail.message.subtype,name:rma.mt_replacement_create
#: model:mail.message.subtype,name:rma.mt_salesteam_request_replacement
msgid "Replacement created"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.crm_team_replacement_teams_view_kanban
msgid "Replacements"
#: model:ir.model.fields,field_description:rma.field_rma_request_is_replacement
msgid "Replacement?"
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."
#: model:ir.ui.view,arch_db:rma.crm_team_rma_teams_view_kanban
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Replacements"
msgstr ""
#. module: rma
@ -420,11 +465,76 @@ msgstr ""
msgid "Requests for RMA"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_crm_team_use_return
msgid "Return"
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_line_qty_return
msgid "Return Quantity"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.act_open_return_reason_view
#: model:ir.model,name:rma.model_return_reason
msgid "Return Reason"
msgstr ""
#. module: rma
#: model:ir.ui.menu,name:rma.menu_return_reason
msgid "Return Reasons"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_line_graph
msgid "Return Request"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.return_request_action_reports
msgid "Return Requests"
msgstr ""
#. module: rma
#: model:mail.message.subtype,name:rma.mt_request_return
#: model:mail.message.subtype,name:rma.mt_salesteam_request_return
msgid "Return created"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_line.py:35
#, python-format
msgid "Return quantity of %s should not be greater than ordered quantity."
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_line.py:40
#, python-format
msgid "Return quantity should not be 0."
msgstr ""
#. module: rma
#: selection:rma.request,type:0
msgid "Return/Replace"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Return/Replacement"
msgstr ""
#. module: rma
#: model:ir.ui.view,arch_db:rma.crm_team_rma_teams_view_kanban
#: model:ir.ui.view,arch_db:rma.view_rma_request_filter
msgid "Returns"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_request_sale_order_id
msgid "SO Number"
@ -507,31 +617,36 @@ 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."
#: model:ir.model.fields,field_description:rma.field_rma_request_is_website
msgid "Website"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_request.py:183
#: code:addons/rma/models/rma_line.py:30
#, python-format
msgid "You can only return %s quantity for product %s as its warranty has been expired."
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_request.py:187
#, 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
#: code:addons/rma/wizard/stock_return_picking.py:32
#, python-format
msgid "You may only return Done pickings"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_request.py:174
#: code:addons/rma/wizard/stock_return_picking.py:22
#, python-format
msgid "You may only return single picking at a time!"
msgstr ""
#. module: rma
#: code:addons/rma/models/rma_request.py:177
#, python-format
msgid "You must select rma lines!"
msgstr ""

View File

@ -6,4 +6,4 @@ from . import rma_request
from . import stock_production_lot
from . import stock_picking
from . import sales_team
from . import replacement_reason
from . import return_reason

View File

@ -3,8 +3,8 @@
from flectra import fields, models
class ReplacementReason(models.Model):
_name = "replacement.reason"
_description = "Replacement Reason"
class ReturnReason(models.Model):
_name = "return.reason"
_description = "Return Reason"
name = fields.Char(string='Reason')

View File

@ -11,30 +11,30 @@ class RMALine(models.Model):
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')
qty_return = fields.Float(string='Return 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')
reason_id = fields.Many2one("return.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 '
@api.onchange('qty_return')
def _onchange_qty_return(self):
if not self.rma_id.is_website and self.product_id.tracking != 'none':
can_be_return_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_return > can_be_return_qty:
raise UserError(_('You can only return %s quantity for '
'product %s as its warranty has been '
'expired.') % (replaceable_qty,
'expired.') % (can_be_return_qty,
self.product_id.name))
elif self.qty_replaced > self.qty_delivered:
raise UserError(_('Replacemet quantity of %s should not be '
elif self.qty_return > self.qty_delivered:
raise UserError(_('Return 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.'))
if self.qty_return == 0:
raise UserError(_('Return quantity should not be 0.'))

View File

@ -6,7 +6,7 @@ from flectra.exceptions import UserError
class RmaRequest(models.Model):
_name = "rma.request"
_inherit = ['mail.thread', 'mail.activity.mixin']
_inherit = ['mail.thread', 'mail.activity.mixin', 'portal.mixin']
_description = "RMA Request"
name = fields.Char(string='RMA Order Number')
@ -16,7 +16,7 @@ class RmaRequest(models.Model):
default=fields.Date.context_today)
partner_id = fields.Many2one('res.partner', string='Customer')
type = fields.Selection([
('replacement', 'Replacement')
('return_replace', 'Return/Replace')
], string='Request Type')
rma_line = fields.One2many('rma.line', 'rma_id', string='RMA Lines')
warranty_expire_line = fields.One2many('warranty.expire.line', 'rma_id',
@ -24,6 +24,7 @@ class RmaRequest(models.Model):
state = fields.Selection([
('draft', 'Draft'),
('confirmed', 'Confirmed'),
('rma_created', 'RMA Created'),
('replacement_created', 'Replacement Created'),
], string='Request Status', track_visibility='onchange', readonly=True,
copy=False, default='draft')
@ -35,6 +36,8 @@ class RmaRequest(models.Model):
user_id = fields.Many2one('res.users', string='User',
default=lambda self: self.env.user)
team_id = fields.Many2one('crm.team', string='Team')
is_website = fields.Boolean(string="Website")
is_replacement = fields.Boolean(string="Replacement?")
@api.multi
def _compute_picking(self):
@ -54,7 +57,7 @@ class RmaRequest(models.Model):
@api.onchange('picking_id')
def _get_rma_lines(self):
if self.picking_id:
if self.picking_id and not self.is_website:
move_line_ids = self.env['stock.move'].search([(
'picking_id', '=', self.picking_id.id)])
move_lines = [(5, 0, 0)]
@ -63,11 +66,11 @@ class RmaRequest(models.Model):
'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
),
'qty_return': 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
}))
@ -127,7 +130,7 @@ class RmaRequest(models.Model):
ir_model_data = self.env['ir.model.data']
try:
template_id = ir_model_data.get_object_reference(
'rma', 'email_template_notify_warranty_new')[1]
'rma', 'email_template_notify_warranty_date')[1]
except ValueError:
template_id = False
try:
@ -163,8 +166,8 @@ class RmaRequest(models.Model):
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'
elif 'state' in init_values and self.state == 'rma_created':
return 'rma.mt_request_return'
return super(RmaRequest, self)._track_subtype(init_values)
@api.multi
@ -172,8 +175,9 @@ class RmaRequest(models.Model):
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()
if not self.is_website:
for line in self.rma_line:
line._onchange_qty_return()
self.state = 'confirmed'
@api.multi

View File

@ -6,14 +6,14 @@ 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')
use_return = fields.Boolean(string='Return')
returns_count = fields.Integer(
compute='_compute_returns',
string='Number of returns')
def _compute_replacements(self):
for replace in self:
if replace.use_replacement:
def _compute_returns(self):
for return_req in self:
if return_req.use_return:
rma_ids = self.env['rma.request'].search([
('team_id.id', '=', replace.id)])
replace.replacements_count = len(rma_ids)
('team_id.id', '=', return_req.id)])
return_req.returns_count = len(rma_ids)

View File

@ -1,5 +1,9 @@
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
access_rma_request_manager,access_rma_request_manager,model_rma_request,stock.group_stock_manager,1,1,1,1
access_rma_request_portal,access_rma_request_portal,model_rma_request,base.group_portal,1,0,0,0
access_rma_line_manager,access_rma_line_manager,model_rma_line,stock.group_stock_manager,1,1,1,1
access_rma_line_portal,access_rma_line_potal,model_rma_line,base.group_portal,1,0,0,0
access_warranty_expire_line_manager,access_warranty_expire_line_manager,model_warranty_expire_line,stock.group_stock_manager,1,1,1,0
access_warranty_expire_line_portal,access_warranty_expire_line_portal,model_warranty_expire_line,base.group_portal,1,0,0,0
access_return_reason_manager,access_return_reason_manager,model_return_reason,stock.group_stock_manager,1,1,1,0
access_return_reason_portal,access_return_reason_portal,model_return_reason,base.group_portal,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_manager access_rma_request access_rma_request_manager model_rma_request stock.group_stock_manager 1 1 1 0 1
3 access_rma_line access_rma_request_portal access_rma_line access_rma_request_portal model_rma_line model_rma_request base.group_portal 1 1 0 1 0 0
4 access_warranty_expire_line access_rma_line_manager access_warranty_expire_line access_rma_line_manager model_warranty_expire_line model_rma_line stock.group_stock_manager 1 1 1 0 1
5 access_replacement_reason access_rma_line_portal access_replacement_reason access_rma_line_potal model_replacement_reason model_rma_line base.group_portal 1 1 0 1 0 0
6 access_warranty_expire_line_manager access_warranty_expire_line_manager model_warranty_expire_line stock.group_stock_manager 1 1 1 0
7 access_warranty_expire_line_portal access_warranty_expire_line_portal model_warranty_expire_line base.group_portal 1 0 0 0
8 access_return_reason_manager access_return_reason_manager model_return_reason stock.group_stock_manager 1 1 1 0
9 access_return_reason_portal access_return_reason_portal model_return_reason base.group_portal 1 1 1 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View File

@ -0,0 +1,233 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan" style="">Return Merchandise Authorizationing</h2>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Products by lots/serial numbers.</h3>
<p class="oe_mt32">
If product is managed by lots/serial number then warranty
expiry date is set. When return request is created, product
from expiry lot can not be return.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="lot_number1.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Add warranty expiry date for
particular lot.</h3>
<p class="oe_mt32">
When product is managed by lots/serial numbers then warranty
expirey date must be set.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="expiry_date2.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Sale Order Created</h3>
<p class="oe_mt32">
Sale order is created for [E-COM08] Apple In-Ear Headphones
product. After confirming order, Delivery Order is generated.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="sale_order3.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Delivery Order generated</h3>
<p class="oe_mt32">
Delivery order is created with lot numbers. Warranty expiry date
for lot number 0000004 is set before today's date.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="delivery_order4.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Return request is created for particular sale order and for a
particular picking.</h3>
<p class="oe_mt32">
In RMA Lines tab, Return quantity
is set to 5 because 2 quantity from lot number 0000004 has
been expired, so product from that lot can not be return.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="rma_request5.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Warranty expire lines</h3>
<p class="oe_mt32">
In warranty Expire Lines tab, Details
of expired lot number, it's quantity and expired date is
visible.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="warranty_lines6.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Email for product expiration</h3>
<p class="oe_mt32">
Email can be sent for product expiration by clicking "Send By
Email" button.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="email7.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Create a rma by clicking "Create
RMA" button</h3>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="create_rma_btn8.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Incoming DO created</h3>
<p class="oe_mt32">
By clicking a button, Incoming Delivery Order is created.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="incoming_do9.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Details of return requests.</h3>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="rma_tree10.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Return button for replacement</h3>
<p class="oe_mt32">
By clicking "Return" button, Outgoing Delivery is generated
if RMA request is for replacement.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="replace_do11.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Outgoing DO generated</h3>
<p class="oe_mt32">
This RMA request is for replacement as Replacement checkbox
is checked. So system will allow to create replacement.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="replace_out_do12.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Only return request</h3>
<p class="oe_mt32">
This RMA request is for return products as Replacement
checkbox is not checked. So system will not allow to create
outgoing DO.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="rma_request13.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Create replacement is not allowed</h3>
<p class="oe_mt32">
From return DO, If you try to create replacement eventhough
it is not replacement request, Then this warning will appear.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="replacement_req14.png">
</div>
</div>
</div>
</section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

View File

@ -56,28 +56,28 @@ class TestSaleOrder(TransactionCase):
'picking_id': picking_ids[0].id,
'date': datetime.now() - relativedelta(days=15),
'partner_id': self.sale_order_id_1.partner_id.id,
'type': 'replacement'
'type': 'return_replace'
})
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!')
'You can not create RMA 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 '
'This RMA 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))
can_be_return_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_return <= can_be_return_qty,
"You can only return %d quantity for %s" %
(can_be_return_qty, rma_line.product_id.name))
self.rma_id_1.action_confirm_request()
self.assertEquals(self.rma_id_1.state, 'confirmed')
@ -90,9 +90,9 @@ class TestSaleOrder(TransactionCase):
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.assertEquals(self.rma_id_1.state, 'rma_created')
self.assertTrue(len(self.sale_order_id_1.picking_ids.ids) > 1,
'Product has not been replaced yet')
'Product has not been returned yet')
incoming_shipment = False
for pick in self.sale_order_id_1.picking_ids:
@ -104,6 +104,9 @@ class TestSaleOrder(TransactionCase):
pick.button_validate()
pick.action_done()
self.assertTrue(incoming_shipment, 'Incoming shipment is not created')
self.assertEqual(len(self.sale_order_id_1.picking_ids.filtered(
lambda pick: pick.picking_type_code == 'outgoing')), 1,
"Replacement request can not be created!")
def test_01_rma_request(self):
self.sale_order_id_2.action_confirm()
@ -122,26 +125,27 @@ class TestSaleOrder(TransactionCase):
'picking_id': picking_ids[0].id,
'date': datetime.now() - relativedelta(days=10),
'partner_id': self.sale_order_id_2.partner_id.id,
'type': 'replacement'
'type': 'return_replace',
'is_replacement': True
})
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!')
'You can not create RMA 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!')
'RMA 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,
can_be_return_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_return <= can_be_return_qty,
"You can only return %d quantity for %s" %
(replaceable_qty, rma_line.product_id.name))
(can_be_return_qty, rma_line.product_id.name))
self.rma_id_2.state = 'confirmed'
self.assertEquals(self.rma_id_2.state, 'confirmed')
@ -153,10 +157,10 @@ class TestSaleOrder(TransactionCase):
'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')
picking = self.return_picking_id_2.create_returns()
self.assertEquals(self.rma_id_2.state, 'rma_created')
self.assertTrue(len(self.sale_order_id_2.picking_ids.ids) > 1,
'Product has not been replaced yet')
'Product has not been returned yet')
incoming_shipment = False
for pick in self.sale_order_id_2.picking_ids:
@ -170,3 +174,12 @@ class TestSaleOrder(TransactionCase):
pick.button_validate()
pick.action_done()
self.assertTrue(incoming_shipment, 'Incoming shipment is not created')
replace_context = {"active_model": 'stock.picking',
"active_ids": [picking['res_id']], "active_id":
picking['res_id']}
self.replace_picking_id_2 = self.env[
'stock.return.picking'].with_context(replace_context).create(
dict(picking_id=picking['res_id']))
self.replace_picking_id_2.create_returns()
self.assertEquals(self.rma_id_2.state, 'replacement_created')

View File

@ -2,19 +2,19 @@
<flectra>
<menuitem id="rma_request_menu"
name="Replacement"
name="RMA"
parent="sale.sale_menu_root"
sequence="3"/>
<menuitem id="menu_request_rma"
name="Replace Request"
name="RMA 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"
<menuitem id="menu_return_reason"
name="Return Reasons"
action="act_open_return_reason_view"
parent="sale.menu_sale_config"
/>
</flectra>

View File

@ -1,10 +1,9 @@
<?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>
<record id="view_return_reason_tree" model="ir.ui.view">
<field name="name">return.reason.tree</field>
<field name="model">return.reason</field>
<field name="type">tree</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<tree>
<field name="name"/>
@ -12,11 +11,10 @@
</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>
<record id="view_return_reason_form" model="ir.ui.view">
<field name="name">return.reason.form</field>
<field name="model">return.reason</field>
<field name="type">form</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<form string="Reason">
<sheet>
@ -29,10 +27,10 @@
</record>
<record model="ir.actions.act_window"
id="act_open_replacement_reason_view">
<field name="name">Replacement Reason</field>
id="act_open_return_reason_view">
<field name="name">Return Reason</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">replacement.reason</field>
<field name="res_model">return.reason</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>

View File

@ -5,7 +5,6 @@
<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>
@ -13,7 +12,7 @@
<group>
<field name="product_id"/>
<field name="qty_delivered"/>
<field name="qty_replaced" required="1"/>
<field name="qty_return" required="1"/>
<field name="uom_id"/>
</group>
<group>
@ -50,22 +49,21 @@
<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">
<graph string="Return Request">
<field name="product_id"/>
</graph>
</field>
</record>
<record id="replacement_request_action_reports"
<record id="return_request_action_reports"
model="ir.actions.act_window">
<field name="name">Replacement Requests</field>
<field name="name">Return 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.
No Return request.
</p>
</field>
<field name="context">{'search_default_team_id': active_id}</field>

View File

@ -4,7 +4,6 @@
<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"/>
@ -21,23 +20,24 @@
<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"/>
type="object" class="oe_highlight"
groups="stock.group_stock_manager"
attrs="{'invisible': [('state', '=', 'draft')]}"/>
<button name="%(stock.act_stock_return_picking)d"
string="Create Replacement"
string="Create RMA"
type="action" class="btn-primary"
attrs="{'invisible': [('state', 'in', ['draft', 'replacement_created'])]}"
attrs="{'invisible': ['|', ('state', 'in', ['draft', 'rma_created', 'replacement_created']), ('is_website', '=', True)]}"
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'])]}"/>
attrs="{'invisible': [('state', 'in', ['confirmed', 'rma_created', 'replacement_created'])]}"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
@ -70,11 +70,14 @@
options="{'no_create': True}"
attrs="{'readonly': [('state', '!=', 'draft')]}"
/>
<field name="picking_id" required="1"
<field name="is_website" invisible="1"/>
<field name="picking_id"
options="{'no_create': True}"
domain="[('sale_id', '=', sale_order_id),
('state', '=', 'done'), ('picking_type_code', '=', 'outgoing')]"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
attrs="{'readonly': [('state', '!=', 'draft')], 'required': [('is_website', '=', False)],
'invisible': [('is_website', '=', True)]}"/>
<field name="is_replacement" attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="user_id" invisible="1"/>
</group>
@ -85,7 +88,7 @@
attrs="{'readonly': [('state', '!=', 'draft')]}"
options="{'no_create': True}"/>
<field name="type" required="1"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
attrs="{'readonly': ['|', ('state', '!=', 'draft'), ('is_website', '=', True)]}"/>
</group>
</group>
<notebook>
@ -99,7 +102,7 @@
force_save="1"/>
<field name="qty_delivered" readonly="1"
force_save="1"/>
<field name="qty_replaced" required="1"/>
<field name="qty_return" required="1"/>
<field name="reason_id" required="1"
options="{'no_create': True}"/>
<field name="remark"/>
@ -115,8 +118,7 @@
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"
groups="base.group_user"/>
<field name="message_follower_ids" widget="mail_followers"/>
<field name="activity_ids" widget="mail_activity"/>
<field name="message_ids" widget="mail_thread"/>
</div>
@ -138,9 +140,15 @@
<filter string="My Requests"
domain="[('user_id','=',uid)]"
name="my_rma_request_filter"/>
<filter string="Replacement Created"
domain="[('state','=','replacement_created')]"
<filter string="RMA Created"
domain="[('state','=','rma_created')]"
name="rma_request_state_filter"/>
<filter string="Replacements"
domain="[('is_replacement', '=', True)]"
name="replacement_filter"/>
<filter string="Returns"
domain="[('is_replacement', '=', False)]"
name="return_filter"/>
<separator/>
<group expand="1" string="Group By">
<filter string="Partner" name="Partner"
@ -149,9 +157,13 @@
context="{'group_by':'sale_order_id'}"/>
<filter string="State"
context="{'group_by':'state'}"/>
<filter string="RMA Request type"
context="{'group_by':'type'}"/>
<separator/>
<filter string="Request Month"
context="{'group_by':'date:month'}"/>
<filter string="Return/Replacement"
context="{'group_by':'is_replacement'}"/>
</group>
</search>
</field>
@ -168,7 +180,7 @@
</record>
<record model="ir.actions.act_window"
id="action_open_rma_request_replacementteam">
id="action_open_rma_request_rmateam">
<field name="name">RMA Request</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">rma.request</field>
@ -177,6 +189,23 @@
<field name="domain">[]</field>
<field name="context">{
'search_default_team_id': [active_id],
'search_default_return_filter': 1,
'default_team_id': active_id,
}
</field>
<field name="search_view_id" ref="view_rma_request_filter"/>
</record>
<record model="ir.actions.act_window"
id="action_open_replacement_request_rmateam">
<field name="name">Replacement 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],
'search_default_replacement_filter': 1,
'default_team_id': active_id,
}
</field>

View File

@ -1,21 +1,21 @@
<?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>
<record id="crm_team_rma_teams_view_form" model="ir.ui.view">
<field name="name">rma.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"/>
<field name="use_return"/>
<label for="use_return"/>
</div>
</xpath>
</field>
</record>
<record id="crm_team_replacement_teams_view_kanban" model="ir.ui.view">
<field name="name">replacement.team.kanban</field>
<record id="crm_team_rma_teams_view_kanban" model="ir.ui.view">
<field name="name">rma.team.kanban</field>
<field name="model">crm.team</field>
<field name="inherit_id"
ref="sale.crm_team_salesteams_view_kanban"/>
@ -24,23 +24,28 @@
<xpath expr="//div[hasclass('o_kanban_primary_left')]"
position="inside">
<div>
<button name="%(rma.action_open_rma_request_replacementteam)d"
<button name="%(rma.action_open_rma_request_rmateam)d"
type="action"
class="btn btn-primary mt8">Returns
</button>
<button name="%(rma.action_open_replacement_request_rmateam)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="row" t-if="record.returns_count.raw_value">
<div class="col-xs-8">
<a name="%(rma.action_open_rma_request_replacementteam)d"
<a name="%(rma.action_open_rma_request_rmateam)d"
type="action">
<field name="replacements_count"/>
<t t-if="record.replacements_count.raw_value == 1">
Replacement
<field name="returns_count"/>
<t t-if="record.returns_count.raw_value == 1">
RMA Request
</t>
<t t-else="">Replacements</t>
<t t-else="">RMA Requests</t>
</a>
</div>
</div>
@ -48,8 +53,8 @@
<xpath expr="//div[hasclass('o_kanban_manage_view')]"
position="inside">
<div>
<a name="%(rma.action_open_rma_request_replacementteam)d"
type="action">Replacements
<a name="%(rma.action_open_rma_request_rmateam)d"
type="action">RMA Requests
</a>
</div>
</xpath>
@ -57,8 +62,8 @@
</field>
</record>
<record id="replacement_view_kanban" model="ir.ui.view">
<field name="name">replacement.kanban</field>
<record id="rma_view_kanban" model="ir.ui.view">
<field name="name">rma.kanban</field>
<field name="model">crm.team</field>
<field name="inherit_id"
ref="sales_team.crm_team_salesteams_view_kanban"/>
@ -66,10 +71,10 @@
<data>
<xpath expr="//div[hasclass('o_kanban_manage_reports')]"
position="inside">
<div name="replacement_report">
<a name="%(rma.replacement_request_action_reports)d"
<div name="return_request_report">
<a name="%(rma.return_request_action_reports)d"
type="action" context="{'search_default_team_id': active_id}">
Replacement
RMA Request
</a>
</div>
</xpath>

View File

@ -4,7 +4,6 @@
<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"/>
@ -20,9 +19,8 @@
<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">
<form string="Warranty Expire Lines" create="false" edit="false">
<sheet>
<group>
<field name="product_id" readonly="1"/>

View File

@ -9,12 +9,18 @@ class ReturnPicking(models.TransientModel):
@api.model
def default_get(self, fields):
if self._context.get('active_model') == 'stock.picking':
picking = self.env['stock.picking'].browse(
self.env.context.get('active_id'))
if picking.rma_id and not picking.rma_id.is_replacement:
raise UserError(_("It is not replacement request!"))
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!"))
"You may only return single picking at a time!"))
move_dest_exists = False
product_return_moves = []
rma_id = self.env['rma.request'].browse(
@ -33,7 +39,7 @@ class ReturnPicking(models.TransientModel):
vals = {}
for rma_line in rma_id.rma_line:
vals.update({
rma_line.product_id.id: rma_line.qty_replaced,
rma_line.product_id.id: rma_line.qty_return,
})
for prod_id in product_ids:
if vals.get(prod_id.id):
@ -60,8 +66,8 @@ class ReturnPicking(models.TransientModel):
if not product_return_moves:
raise UserError(_(
"No products to replace (only lines in Done state and"
"not fully replaced yet can be replaced)!"))
"No products to return (only lines in Done state and"
"not fully returned yet can be returned)!"))
if 'product_return_moves' in fields:
res.update({'product_return_moves': product_return_moves})
if 'move_dest_exists' in fields:
@ -94,5 +100,10 @@ class ReturnPicking(models.TransientModel):
'rma.request':
rma_id = self.env['rma.request'].browse(
self.env.context.get('active_id'))
rma_id.state = 'replacement_created'
rma_id.state = 'rma_created'
if self._context.get('active_model') == 'stock.picking':
picking = self.env['stock.picking'].browse(
self.env.context.get('active_id'))
if picking.rma_id:
picking.rma_id.state = 'replacement_created'
return super(ReturnPicking, self).create_returns()

View File

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

View File

@ -0,0 +1,29 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
{
'name': 'Website 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 or replacement
during the product's warranty period.
""",
'category': 'Sales',
'depends': ['rma', 'website_sale', 'portal'],
'data': [
'wizard/stock_return_web_view.xml',
'views/rma_request_view.xml',
'views/return_portal_template.xml',
'views/templates.xml',
],
'demo': [
'demo/sale_order_demo.xml'
],
'images': [
'static/description/website-rma-app-banner.jpg',
],
'application': True,
}

View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import portal

View File

@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
# Part of Odoo,Flectra. See LICENSE file for full copyright and licensing
# details.
from flectra import http
from flectra.http import request, route
from flectra.addons.portal.controllers.portal import CustomerPortal, pager as \
portal_pager
class CustomerPortal(CustomerPortal):
@http.route()
def home(self, **kw):
response = super(CustomerPortal, self).home(**kw)
request_count = request.env['rma.request'].sudo().search_count(
[('state', 'in', ['draft', 'confirmed', 'rma_created',
'replacement_created'])])
response.qcontext.update({
'request_count': request_count
})
return response
def _order_get_page_view_values(self, order, access_token, **kwargs):
values = super(CustomerPortal, self)._order_get_page_view_values(
order, access_token, **kwargs)
reason_ids = request.env['return.reason'].search([])
return_ids = request.env['rma.request'].search([
('sale_order_id', '=', order.id)])
values.update({
'reasons': reason_ids,
'return_ids': return_ids,
})
return values
@http.route(['/my/request', '/my/request/page/<int:page>'], type='http',
auth="user", website=True)
def portal_my_requet(self, page=1, date_begin=None, date_end=None,
sortby=None, **kw):
values = self._prepare_portal_layout_values()
ReturnRequest = request.env['rma.request']
domain = [
('state', 'in', ['draft', 'confirmed', 'rma_created',
'replacement_created'])
]
request_count = ReturnRequest.search_count(domain)
pager = portal_pager(
url="/my/request",
url_args={},
total=request_count,
page=page,
step=self._items_per_page
)
# content according to pager and archive selected
requests = ReturnRequest.sudo().search(domain,
limit=self._items_per_page,
offset=pager['offset'])
request.session['my_requests_history'] = requests.ids[:100]
values.update({
'date': date_begin,
'requests': requests.sudo(),
'page_name': 'return_request',
'pager': pager,
'archive_groups': '',
'default_url': '/my/request',
'searchbar_sortings': '',
'sortby': sortby,
})
return request.render("website_rma.portal_my_requests", values)
@http.route(['/my/request/<int:return_req>'], type='http',
auth="public",
website=True)
def portal_request_page(self, return_req=None, access_token=None, **kw):
req = request.env['rma.request'].sudo().browse(return_req)
values = {
'return_request': req,
}
return request.render("website_rma.portal_request_page", values)
@http.route(['/return/request'], type='http', auth="public",
website=True, csrf=False)
def add_return_request(self, **kw):
is_replacement = False
if 'is_replacement_check' in kw and kw['is_replacement_check'] == 'on':
is_replacement = True
sale_order = request.env['sale.order'].browse(int(kw['order_id']))
request_id = request.env['rma.request'].sudo().create({
'partner_id': kw['partner_id'],
'sale_order_id': kw['order_id'],
'team_id': sale_order.team_id and sale_order.team_id.id or False,
'type': 'web_return_replace',
'is_website': True,
'is_replacement': is_replacement,
'rma_line': [(0, 0, {
'product_id': kw['product_id'],
'uom_id': kw['uom_id'],
'qty_return': kw['quantity'],
'reason_id': kw['reason'],
'qty_delivered': kw['qty_delivered'],
'remark': kw['remark'],
})
],
})
request_id.rma_line.write({'rma_id': request_id.id})
request.session['request_last_return_id'] = request_id.id
return request.redirect('/return/confirmation')
@http.route(['/return/confirmation'], type='http', auth="public",
website=True)
def return_confirmation(self, **post):
return_request_id = request.session.get('request_last_return_id')
if return_request_id:
return_request = request.env['rma.request'].sudo().browse(
return_request_id)
return request.render("website_rma.return_confirmation",
{'return_req_id': return_request})
else:
return request.redirect('/shop')
@route(['/sale/order/pdf/<int:order_id>'], type='http', auth="public",
website=True)
def portal_sale_order_report(self, order_id, access_token=None, **kw):
pdf = request.env.ref('sale.action_report_saleorder'
).sudo().render_qweb_pdf([order_id])[0]
pdfhttpheaders = [
('Content-Type', 'application/pdf'),
('Content-Length', len(pdf)),
]
return request.make_response(pdf, headers=pdfhttpheaders)

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="demo_sale_order_website" 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')"/>
<field name="website_id">1</field>
<field name="can_directly_mark_as_paid" eval="True"></field>
</record>
<record id="demo_sale_order_website_line_1"
model="sale.order.line">
<field name="order_id" ref="demo_sale_order_website"/>
<field name="name">Demo Product3</field>
<field name="product_id" ref="rma.demo_product_3"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">300.00</field>
</record>
<function model="sale.order" name="action_confirm"
eval="[ref('demo_sale_order_website')]"/>
<function model="stock.picking" name="force_assign">
<function
eval="[[('sale_id', '=', ref('demo_sale_order_website'))]]"
model="stock.picking" name="search"/>
</function>
<record id="demo_stock_immediate_transfer1"
model="stock.immediate.transfer">
<field name="pick_ids"
search="[('sale_id', '=', ref('demo_sale_order_website'))]"/>
</record>
<function
model="stock.immediate.transfer" name="process"
eval="[ref('demo_stock_immediate_transfer1')]"
/>
<record id="demo_sale_order_website_user" model="sale.order">
<field name="partner_id" ref="base.partner_demo"/>
<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_demo"/>
<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')"/>
<field name="website_id">1</field>
<field name="can_directly_mark_as_paid" eval="True"></field>
</record>
<record id="demo_sale_order_website_line_user_1"
model="sale.order.line">
<field name="order_id" ref="demo_sale_order_website_user"/>
<field name="name">Demo Product3</field>
<field name="product_id" ref="rma.demo_product_3"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">250.00</field>
</record>
<function model="sale.order" name="action_confirm"
eval="[ref('demo_sale_order_website_user')]"/>
<function model="stock.picking" name="force_assign">
<function
eval="[[('sale_id', '=', ref('demo_sale_order_website_user'))]]"
model="stock.picking" name="search"/>
</function>
<record id="demo_stock_immediate_transfer1"
model="stock.immediate.transfer">
<field name="pick_ids"
search="[('sale_id', '=', ref('demo_sale_order_website_user'))]"/>
</record>
<function
model="stock.immediate.transfer" name="process"
eval="[ref('demo_stock_immediate_transfer1')]"
/>
</flectra>

View File

@ -0,0 +1,396 @@
# Translation of Flectra Server.
# This file contains the translation of the following modules:
# * website_rma
#
msgid ""
msgstr ""
"Project-Id-Version: Flectra Server 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-14 05:57+0000\n"
"PO-Revision-Date: 2018-03-14 05:57+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: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "&amp;nbsp;"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "<span aria-hidden=\"true\">&amp;times;</span>\n"
" <span class=\"sr-only\">Close</span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "<span class=\"hidden-xs\">Return Reuqest #\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<span class=\"label label-danger label-text-align\">\n"
" <i class=\"fa fa-fw fa-times\"/>\n"
" Cancelled\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "<span class=\"label label-default hidden-xs\">\n"
" <i class=\"fa fa-pencil-square-o\"/>\n"
" <span class=\"hidden-xs\">Draft\n"
" </span>\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<span class=\"label label-info label-text-align\">\n"
" <i class=\"fa fa-fw fa-clock-o\"/>\n"
" Preparation\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "<span class=\"label label-info\">\n"
" <i class=\"fa fa-fw fa-clock-o\"/>\n"
" <span class=\"hidden-xs\">Confirmed\n"
" </span>\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "<span class=\"label label-primary hidden-xs\">\n"
" <i class=\"fa fa-arrows-h\"/>\n"
" <span class=\"hidden-xs\">Replacement Created\n"
" </span>\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "<span class=\"label label-primary hidden-xs\">\n"
" <i class=\"fa fa-fw fa-check\"/>\n"
" <span class=\"hidden-xs\">RMA\n"
" Request\n"
" Created\n"
" </span>\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<span class=\"label label-success label-text-align\">\n"
" <i class=\"fa fa-fw fa-truck\"/>\n"
" Shipped\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<span class=\"label label-success label-text-align\">\n"
" <i class=\"fa fa-check\"/>\n"
" Confirm\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<span class=\"label label-success label-text-align\">\n"
" <i class=\"fa fa-exchange\"/>\n"
" RMA Request created\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<span class=\"label label-success label-text-align\">\n"
" <i class=\"fa fa-pencil-square-o\"/>\n"
" Draft\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<span class=\"label label-warning label-text-align\">\n"
" <i class=\"fa fa-fw fa-clock-o\"/>\n"
" Partially Available\n"
" </span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.return_confirmation
msgid "<span>\n"
" Confirmed</span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.return_confirmation
msgid "<span>Return Request</span>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>Date:</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>Delivered Quantity</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>Delivery Order</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>Invoicing Address</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>Order</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "<strong>Partner</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "<strong>Product to Return\n"
" </strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>Product</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "<strong>Quantity</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "<strong>Reason</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "<strong>Replacement?</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>Return Quantity</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "<strong>Return Requests</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "<strong>Sale Order</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>Shipping/Picking Address</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>State</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_request_page
msgid "<strong>UOM</strong>"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.view_stock_return_web
msgid "Cancel"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "Close"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.view_rma_request_form_inherit
msgid "Create RMA"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_create_uid
msgid "Created by"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_create_date
msgid "Created on"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_destination_location_id
msgid "Destination Location"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_display_name
msgid "Display Name"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_id
msgid "ID"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web___last_update
msgid "Last Modified on"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_write_uid
msgid "Last Updated by"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_write_date
msgid "Last Updated on"
msgstr ""
#. module: website_rma
#: code:addons/website_rma/wizard/stock_return_web.py:58
#, python-format
msgid "New Move:"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_picking_type_id
msgid "Picking Type"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_product_id
msgid "Product"
msgstr ""
#. module: website_rma
#: model:ir.model,name:website_rma.model_rma_request
msgid "RMA Request"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "Remark"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "Request Date"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
#: model:ir.ui.view,arch_db:website_rma.view_stock_return_web
msgid "Return"
msgstr ""
#. module: website_rma
#: model:ir.actions.act_window,name:website_rma.action_stock_return_web
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
#: model:ir.ui.view,arch_db:website_rma.view_stock_return_web
msgid "Return Product"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_qty_return
msgid "Return Quantity"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_rma_id
msgid "Return Request Number"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_home_menu_request
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "Return Requests"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.return_confirmation
msgid "Return request will be\n"
" processed soon."
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "Return/Replace"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_home_menu_return_request
msgid "Returns"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_order_id
msgid "SO Number"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "Sale Order #"
msgstr ""
#. module: website_rma
#: model:ir.model,name:website_rma.model_sale_order_line
msgid "Sales Order Line"
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_source_location_id
msgid "Source Location"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_my_requests
msgid "There are currently no requests for your account."
msgstr ""
#. module: website_rma
#: model:ir.model.fields,field_description:website_rma.field_stock_return_web_uom_id
msgid "UOM"
msgstr ""
#. module: website_rma
#: model:ir.ui.view,arch_db:website_rma.portal_return_page_button
msgid "remark(optional)"
msgstr ""
#. module: website_rma
#: model:ir.model,name:website_rma.model_stock_return_web
msgid "stock.return.web"
msgstr ""

View File

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

View File

@ -0,0 +1,18 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import api, fields, models
class RmaReuqest(models.Model):
_inherit = ['rma.request']
type = fields.Selection([
('return_replace', 'Return/Replace'),
('web_return_replace', 'Web Return/Replace')
], string='Request Type', help="Type of return request")
@api.multi
def _compute_is_website(self):
for request in self:
request.is_website = request.type and request.type == \
'web_return_replace' or False

View File

@ -0,0 +1,23 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import models
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
def get_return_qty(self, order_id, line_id):
self._cr.execute("select s_line.id, r_line.product_id, "
"sum(r_line.qty_return) as return_qty from "
"rma_line "
"r_line, "
"rma_request req, sale_order so, "
"sale_order_line s_line where req.id = "
"r_line.rma_id and so.id = req.sale_order_id and "
"so.id = s_line.order_id and s_line.product_id = "
"r_line.product_id and so.id = %s and s_line.id "
"= %s " % (order_id, line_id) +
"group by(r_line.product_id, s_line.id)")
result = self._cr.dictfetchall()
if result:
return result

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,132 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan" style="">Website Return Merchandise
Authorizationing</h2>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Ecommerce Sale Order</h3>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="web_sale_order.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Return/Replace product</h3>
<p class="oe_mt32">
Product can be returned/replaced by clicking "Return/Replace"
button from particular order line.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="web_return_btn.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Return/Replace product dialog</h3>
<p class="oe_mt32">
By clicking "Return/Replace" button, A dialog box will open
with some auto fill details. You have to enter quantity to be
return/replace, reason for return/replace products and check
replacement checkbox if you want to replace product.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="web_return_dialog.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">RMA request created</h3>
<p class="oe_mt32">
By clicking "Return" button of dialog box, RMA request is
created with all required details.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="web_rma_request.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Return Product Wizard</h3>
<p class="oe_mt32">
By clicking "Create RMA" button, A wizard will open. You
have to select a picking type.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="web_picking.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">Incoming DO Created</h3>
<p class="oe_mt32">
By clicking "Return" button, An Incoming delivery order is
generated.
</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="web_picking_incoming.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">"Returns" will redirect to all
return/replacement
requests.</h3>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="web_return_tab.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">RMA Request</h3>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="web_rma_request_tab.png">
</div>
</div>
</div>
</section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,11 @@
.modal-body .form-horizontal .col-sm-2,
.modal-body .form-horizontal .col-sm-10 {
width: 100%
}
.modal-body .form-horizontal .control-label {
text-align: left;
}
.modal-body .form-horizontal .col-sm-offset-2 {
margin-left: 15px;
}

View File

@ -0,0 +1,37 @@
flectra.define('website_rma.rma_tour', function (require) {
'use strict';
var tour = require("web_tour.tour");
var base = require("web_editor.base");
tour.register('web_rma', {
test: true,
url: '/my/home',
wait_for: base.ready()
},
[
{
content: "sales order list",
trigger: 'a[href="/my/orders"]',
},
{
content: "select sale order",
trigger: 'a:contains("SO035")',
},
{
content: "click on return button on order line",
trigger: '#order_line_return a:contains("Return")',
},
{
content: "click on return button",
trigger: 'button[id="prod_return"]',
},
{
content: "create rma request",
trigger: 'form[action^="/return/request"]',
},
]
);
});

View File

@ -0,0 +1,37 @@
flectra.define('website_rma.rma_tour_demo', function (require) {
'use strict';
var tour = require("web_tour.tour");
var base = require("web_editor.base");
tour.register('web_rma_demo', {
test: true,
url: '/my/home',
wait_for: base.ready()
},
[
{
content: "sales order list",
trigger: 'a[href="/my/orders"]',
},
{
content: "select sale order",
trigger: 'a:contains("SO036")',
},
{
content: "click on return button on order line",
trigger: '#order_line_return a:contains("Return")',
},
{
content: "click on return button",
trigger: 'button[id="prod_return"]',
},
{
content: "create rma request",
trigger: 'form[action^="/return/request"]',
},
]
);
});

View File

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

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Part of Flectra. See LICENSE file for full copyright and licensing details.
import flectra.tests
@flectra.tests.common.at_install(False)
@flectra.tests.common.post_install(True)
class TestUi(flectra.tests.HttpCase):
def test_01_web_rma(self):
self.phantom_js("/my/home", "flectra.__DEBUG__.services["
"'web_tour.tour'].run('web_rma')",
"flectra.__DEBUG__.services['web_tour.tour'"
"].tours.web_rma.ready", login="admin")
def test_02_web_rma(self):
self.phantom_js("/my/home", "flectra.__DEBUG__.services["
"'web_tour.tour'].run('web_rma_demo')",
"flectra.__DEBUG__.services['web_tour.tour'"
"].tours.web_rma_demo.ready", login="demo")

View File

@ -0,0 +1,540 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<template id="portal_my_home_menu_request"
inherit_id="portal.portal_layout">
<xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
<li
t-if="page_name == 'return_request' or req">
<a t-if="req"
t-attf-href="/my/request?{{ keep_query() }}">Return Requests
</a>
<t t-else="">Return Requests</t>
</li>
<li t-if="req">
<t t-esc="req.name"/>
</li>
</xpath>
</template>
<template id="portal_my_home_menu_return_request"
inherit_id="portal.portal_my_home">
<xpath expr="//ul[hasclass('o_portal_docs')]" position="inside">
<li t-if="request_count" class="list-group-item">
<span class="badge" t-esc="request_count"/>
<a href="/my/request">Returns</a>
</li>
</xpath>
</template>
<template id="portal_my_requests" name="My Return Requests">
<t t-call="portal.portal_layout">
<h3>Return Requests
<t t-call="portal.portal_searchbar"/>
</h3>
<t t-if="not requests">
<p>There are currently no requests for your account.</p>
</t>
<div t-if="requests" class="panel panel-default">
<div class="table-responsive">
<table class="table table-hover o_portal_my_doc_table">
<thead>
<tr class="active">
<th>
<span class='hidden-xs'>Return Reuqest #
</span>
</th>
<th>Request Date</th>
<th></th>
<th>Sale Order #</th>
</tr>
</thead>
<t t-foreach="requests" t-as="req">
<tr>
<td>
<a
t-attf-href="/my/request/{{req.id}}?{{keep_query()}}">
<t t-esc="req.name"/>
</a>
</td>
<td>
<span t-field="req.date"
t-options="{'widget': 'date'}"/>&amp;nbsp;
</td>
<td>
<t
t-if="req.state == 'draft'">
<span
class="label label-default hidden-xs">
<i class="fa fa-pencil-square-o"></i>
<span class="hidden-xs">Draft
</span>
</span>
</t>
<t t-if="req.state == 'confirmed'">
<span class="label label-info">
<i
class="fa fa-fw fa-clock-o"></i>
<span class="hidden-xs">Confirmed
</span>
</span>
</t>
<t
t-if="req.state == 'rma_created'">
<span
class="label label-primary hidden-xs">
<i class="fa fa-fw fa-check"></i>
<span class="hidden-xs">RMA
Request
Created
</span>
</span>
</t>
<t
t-if="req.state == 'replacement_created'">
<span
class="label label-primary hidden-xs">
<i class="fa fa-arrows-h"></i>
<span
class="hidden-xs">Replacement Created
</span>
</span>
</t>
</td>
<td>
<a t-attf-href="/my/orders/{{req.sale_order_id.id}}?{{keep_query()}}">
<t
t-esc="req.sale_order_id.name"/>
</a>
</td>
</tr>
</t>
</table>
</div>
<div t-if="pager" class="o_portal_pager text-center">
<t t-call="portal.pager"/>
</div>
</div>
</t>
</template>
<template id="portal_request_page" name="Return Request">
<t t-call="portal.portal_layout">
<t t-set="req" t-value="return_request"/>
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">
<div class="row">
<div class="col-md-6 col-xs-9 col-sm-9">
<h4>
<t t-call='portal.record_pager'/>
<t t-esc="RMA"/>
<span t-esc="req.name"/>
</h4>
</div>
</div>
</div>
<div class="panel-body">
<div class="mb8">
<strong>Date:</strong>
<span t-field="req.date"
t-options='{"widget": "date"}'/>
</div>
<div class='row'>
<div class="col-md-6">
<div>
<strong>Invoicing Address</strong>
</div>
<div>
<address
t-field="req.sale_order_id.partner_invoice_id"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
</div>
</div>
<div id="shipping_address" class="col-md-6"
groups="sale.group_delivery_invoice_address">
<div>
<strong>Shipping/Picking Address</strong>
</div>
<div>
<address
t-field="req.sale_order_id.partner_shipping_id"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
</div>
</div>
<div class="col-md-6">
<t t-if="req.sale_order_id">
<t t-set="sale_report_url"
t-value="'/sale/order/pdf/%s?%s' % (req.sale_order_id.id, keep_query())"/>
<div>
<strong>Order</strong>
</div>
<div>
<a t-att-href="sale_report_url"><span class="fa fa-download"/></a>
<a
t-att-href="sale_report_url"><span t-esc="req.sale_order_id.name"/></a>
<span class="text-muted"
t-field="req.sale_order_id.create_date"/>
</div>
</t>
</div>
<div class="col-md-6">
<div>
<strong>State</strong>
</div>
<div>
<t t-if="req.state == 'draft'">
<span class="label label-success label-text-align">
<i class="fa fa-pencil-square-o"/>
Draft
</span>
</t>
<t t-if="req.state == 'confirmed'">
<span class="label label-success label-text-align">
<i class="fa fa-check"/>
Confirm
</span>
</t>
<t
t-if="req.state == 'rma_created'">
<span class="label label-success label-text-align">
<i class="fa fa-exchange"/>
RMA Request created
</span>
</t>
</div>
</div>
<div class="col-md-6">
<t t-if="req.picking_ids">
<div>
<strong>Delivery Order</strong>
</div>
<div>
<t
t-foreach="req.picking_ids.filtered(lambda picking: picking.picking_type_id.code != 'internal')"
t-as="i">
<t t-set="report_url" t-value="'/my/picking/pdf/%s?%s' % (i.id, keep_query())"/>
<div id='picking_info'>
<a t-att-href="report_url"><span class="fa fa-download"/></a>
<a
t-att-href="report_url"><span t-esc="i.name"/></a>
<span class="text-muted"
t-field="i.date"
t-options='{"widget": "date"}'/>
<t t-if="i.state == 'done'">
<span class="label label-success label-text-align">
<i class="fa fa-fw fa-truck"/>
Shipped
</span>
</t>
<t t-if="i.state == 'partially_available'">
<span class="label label-warning label-text-align">
<i class="fa fa-fw fa-clock-o"/>
Partially Available
</span>
</t>
<t t-if="i.state == 'cancel'">
<span class="label label-danger label-text-align">
<i class="fa fa-fw fa-times"/>
Cancelled
</span>
</t>
<t t-if="i.state in ['draft', 'waiting', 'confirmed', 'assigned']">
<span class="label label-info label-text-align">
<i class="fa fa-fw fa-clock-o"/>
Preparation
</span>
</t>
</div>
</t>
</div>
</t>
</div>
</div>
<hr/>
<div class="row">
<div class="col-md-6">
<strong>Product</strong>
</div>
<div class="hidden-sm hidden-xs col-md-2 text-right">
<strong>UOM</strong>
</div>
<div class="hidden-sm hidden-xs col-md-2 text-right">
<strong>Delivered Quantity</strong>
</div>
<div class="hidden-sm hidden-xs col-md-2 text-right">
<strong>Return Quantity</strong>
</div>
</div>
<t t-foreach="req.rma_line" t-as="rl">
<div class="row orders_vertical_align">
<div id='product_name'
class="col-lg-5 col-sm-6 col-xs-3">
<span t-esc="rl.product_id.name"/>
</div>
<div class="col-xs-3 text-right">
<span t-field="rl.uom_id"/>
</div>
<div class="col-xs-2 text-right">
<span t-esc="rl.qty_delivered"/>
</div>
<div class="col-sm-2 col-xs-4 text-right">
<span t-field="rl.qty_return"/>
</div>
</div>
</t>
<hr/>
</div>
</div>
</div>
</t>
</template>
<template id="portal_return_page_button"
inherit_id="sale.portal_order_page">
<xpath expr="//t[@t-if='invoices']" position="after">
<t t-if="return_ids">
<div>
<strong>Return Requests</strong>
</div>
<div>
<t t-foreach="return_ids" t-as="return_id">
<a
t-attf-href="/my/request/{{return_id.id}}?{{keep_query()}}">
<t
t-esc="return_id.name"/>
</a>
</t>
</div>
</t>
</xpath>
<xpath
expr="//div[hasclass('panel-body')]/div[4]//div[hasclass('col-md-6')]"
position="attributes">
<attribute name="class">col-md-4</attribute>
</xpath>
<xpath
expr="//div[@id='product_name']"
position="attributes">
<attribute name="id">product_name</attribute>
<attribute name="class">col-lg-2 col-sm-6 col-xs-3</attribute>
</xpath>
<xpath expr="//t[@t-foreach='order.order_line']/div/div[5]"
position="after">
<div class="col-sm-2 col-xs-4" id="order_line_return">
<t t-set="return_res"
t-value="ol.get_return_qty(order.id,ol.id)"/>
<t
t-if="order.picking_ids and order.picking_ids.sorted(key=lambda pick: pick.id)[0].state == 'done'">
<t t-if="not return_res">
<a
t-attf-href="##{ol.id}"
data-toggle="modal"
type="action"
class="btn btn-primary mt8 pull-right">Return/Replace
</a>
</t>
<t t-else="return_res">
<a
t-if="((ol.product_uom_qty - return_res[0]['return_qty']) != 0)"
t-attf-href="##{ol.id}"
data-toggle="modal"
type="action"
class="btn btn-primary mt8 pull-right">Return/Replace
</a>
</t>
</t>
</div>
<div class="modal fade" t-attf-id="#{ol.id}" tabindex="-1"
role="dialog"
aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal">
<span aria-hidden="true">&amp;times;</span>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title" id="myModalLabel">
Return Product
</h4>
</div>
<!-- Modal Body -->
<div class="modal-body" id="return_form">
<form action="/return/request" method="POST" t-if="reasons">
<div class="container">
<div class="row">
<div class="col-md-6 mt8 mb8">
<lable>
<strong>Partner</strong>
</lable>
<input type="hidden"
name="partner_id"
id="partner_id"
t-attf-value="#{order.partner_id.id}"/>
<input type="text"
name="partner_id"
class="form-control"
t-attf-value="#{order.partner_id.name}"
readonly="True"
>
</input>
</div>
<div class="col-md-6 mt8 mb8">
<lable>
<strong>Sale Order</strong>
</lable>
<input type="hidden"
name="order_id"
id="order_id"
t-attf-value="#{order.id}"/>
<input type="text"
name="order_id"
class="form-control"
t-attf-value="#{order.name}"
readonly="True">
</input>
</div>
<div class="col-md-6 mt8 mb8">
<lable>
<strong>Product to Return
</strong>
</lable>
<input type="hidden"
name="product_id"
id="product_id"
t-attf-value="#{ol.product_id.id}"/>
<input type="hidden"
name="uom_id"
id="uom_id"
t-attf-value="#{ol.product_uom.id}"/>
<input type="hidden"
name="qty_delivered"
id="qty_delivered"
t-attf-value="#{ol.qty_delivered}"/>
<input type="text"
name="product_name"
class="form-control"
t-attf-value="#{ol.product_id.name}"
readonly="True">
</input>
</div>
<div class="col-md-6 mt8 mb8">
<lable>
<strong>Quantity</strong>
</lable>
<t t-esc="return_result"/>
<t t-set="return_res"
t-value="ol.get_return_qty(order.id,ol.id)"/>
<t t-if="return_res">
<input type="number"
name="quantity"
class="form-control"
t-attf-value="#{ol.product_uom_qty - return_res[0]['return_qty']}"
min="1"
t-attf-max="#{ol.product_uom_qty - return_res[0]['return_qty']}"
onkeydown="return false"
autocomplete="off"
/>
</t>
<t t-else="not return_res">
<input type="number"
name="quantity"
class="form-control"
t-attf-value="#{ol.product_uom_qty}"
min="1"
t-attf-max="#{ol.product_uom_qty}"
onkeydown="return false"
/>
</t>
</div>
<div class="col-md-6 mt8 mb8">
<lable>
<strong>Reason</strong>
</lable>
<select class="form-control"
name="reason" required="True">
<t t-set="reason_id"
t-value="reasons"/>
<option
t-foreach="reason_id"
t-as="res"
t-att-value="res.id or ''"
t-att-selected="res.id == (res and res.id or -1)">
<t t-esc="res.name"/>
</option>
</select>
</div>
<div class="col-md-6 mt32 mb8">
<lable>
<strong>Replacement?</strong>
</lable>
<input type="checkbox"
name="is_replacement_check"
class="ml8">
</input>
</div>
</div>
<div class="row mt16 mb16 col-lg-12 col-md-12 col-sm-12 ">
<label>Remark</label>
<textarea
style="resize:vertical;"
class="form-control"
placeholder="remark(optional)"
rows="4" name="remark"
></textarea>
</div>
</div>
<div class="modal-footer">
<button type="submit"
class="btn btn-primary"
id="prod_return">
Return
</button>
<button type="button"
class="btn btn-default"
data-dismiss="modal">
Close
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</xpath>
</template>
<template id="return_confirmation">
<t t-call="website.layout">
<div id="wrap">
<div class="container">
<div class="row">
<div class="col-md-9">
<h1 class="mb32"><span>Return Request</span> <em
t-field="return_req_id.name" /> <span>
Confirmed</span></h1>
<div class="thanks_msg">
<h2>Return request will be
processed soon.
</h2>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
</flectra>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_rma_request_form_inherit" model="ir.ui.view">
<field name="name">rma.request.form.inherit</field>
<field name="model">rma.request</field>
<field name="inherit_id" ref="rma.view_rma_request_form"/>
<field name="arch" type="xml">
<xpath expr="//form/header" position="inside">
<button name="%(website_rma.action_stock_return_web)d"
string="Create RMA"
type="action" class="btn-primary"
attrs="{'invisible': ['|', ('state', 'in', ['draft', 'rma_created']), ('is_website', '=', False)]}"
context="{'rma': True}"
groups="stock.group_stock_manager"/>
</xpath>
</field>
</record>
</flectra>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<!-- Layout and common templates -->
<template id="assets_frontend" inherit_id="website.assets_frontend"
name="web_rma">
<xpath expr="." position="inside">
<script type="text/javascript"
src="/website_rma/static/src/js/website_rma_tour.js"></script>
<script type="text/javascript"
src="/website_rma/static/src/js/website_rma_tour_demo.js"></script>
</xpath>
</template>
</flectra>

View File

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

View File

@ -0,0 +1,85 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra import api, fields, models, _
class StockReturnWeb(models.TransientModel):
_name = 'stock.return.web'
order_id = fields.Many2one('sale.order', string='SO Number')
product_id = fields.Many2one('product.product', string='Product')
uom_id = fields.Many2one('product.uom', string='UOM')
qty_return = fields.Float(string='Return Quantity')
picking_type_id = fields.Many2one('stock.picking.type',
string='Picking Type')
source_location_id = fields.Many2one('stock.location',
sting='Source Location')
destination_location_id = fields.Many2one('stock.location',
sting='Destination Location')
rma_id = fields.Many2one('rma.request', string='Return Request Number')
@api.model
def default_get(self, fields):
res = super(StockReturnWeb, self).default_get(fields)
return_id = self.env['rma.request'].browse(
self._context.get('active_id'))
picking_id = return_id.sale_order_id.picking_ids.filtered(
lambda pick: pick.state == 'done' and pick.picking_type_id.code ==
'outgoing').sorted(key=lambda pick_id: pick_id.id)[0]
res.update({
'order_id': return_id.sale_order_id and
return_id.sale_order_id.id or False,
'rma_id': return_id and return_id.id or False,
'source_location_id': picking_id.location_dest_id and
picking_id.location_dest_id.id or False,
'destination_location_id': picking_id.location_id and
picking_id.location_id.id or False,
})
for line in return_id.rma_line:
res.update({
'product_id': line.product_id and line.product_id.id or False,
'qty_return': line.qty_return or 0.0,
'uom_id': line.uom_id and line.uom_id.id or False,
})
return res
def return_product(self):
picking_id = self.env['stock.picking'].create({
'picking_type_id': self.env.ref('stock.picking_type_in').id,
'partner_id': self.rma_id.partner_id.id,
'location_id': self.source_location_id.id,
'location_dest_id': self.destination_location_id.id,
'rma_id': self.rma_id.id,
})
new_move_id = self.env['stock.move'].create({
'name': _('New Move:') + self.product_id.display_name,
'product_id': self.product_id.id,
'product_uom_qty': self.qty_return,
'product_uom': self.uom_id.id,
'location_id': self.source_location_id.id,
'location_dest_id': self.destination_location_id.id,
'has_tracking': self.product_id.tracking,
'origin': self.rma_id.name,
'date': self.rma_id.date,
'picking_id': picking_id.id,
'picking_type_id': self.env.ref('stock.picking_type_in').id,
'group_id': self.order_id.procurement_group_id and
self.order_id.procurement_group_id.id or False
})
new_move_id._action_confirm()
picking_id.action_confirm()
move_line_id = self.env['stock.move.line'].create({
'move_id': new_move_id and new_move_id.id or False,
'product_id': new_move_id.product_id.id,
'product_uom_id': new_move_id.product_uom.id,
'date': new_move_id.date,
'location_id': new_move_id.location_id.id,
'location_dest_id': new_move_id.location_dest_id.id,
'product_uom_qty': new_move_id.product_uom_qty or 0.0,
})
self.rma_id.state = "rma_created"

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_stock_return_web" model="ir.ui.view">
<field name="name">stock.return.web.form</field>
<field name="model">stock.return.web</field>
<field name="arch" type="xml">
<form string="Return Product">
<group>
<group>
<field name="order_id" readonly="1"/>
<field name="product_id" readonly="1"/>
<field name="qty_return" readonly="1"/>
</group>
<group>
<field name="rma_id" readonly="1"/>
<field name="picking_type_id"
domain="[('code', '=', 'incoming')]"/>
<field name="source_location_id"
domain="[('usage', '!=', 'view')]"/>
<field name="destination_location_id"
domain="[('usage', '!=', 'view')]"/>
</group>
</group>
<footer>
<button string='Return' name="return_product"
type="object" class="btn-primary"/>
<button string="Cancel" class="btn-default" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_stock_return_web" model="ir.actions.act_window">
<field name="name">Return Product</field>
<field name="res_model">stock.return.web</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_stock_return_web"/>
<field name="target">new</field>
</record>
</flectra>