From 8939fc8c7a9dc7997c0b522d040cd956dff49530 Mon Sep 17 00:00:00 2001 From: Jordi Ballester Date: Thu, 27 Jul 2017 18:17:19 +0200 Subject: [PATCH 01/81] init branch --- rma/README.rst | 96 ++++ rma/__init__.py | 5 + rma/__openerp__.py | 41 ++ rma/data/rma_operation.xml | 81 ++++ rma/data/rma_sequence.xml | 39 ++ rma/data/stock_data.xml | 212 +++++++++ rma/demo/stock_demo.xml | 19 + rma/models/__init__.py | 13 + rma/models/procurement.py | 29 ++ rma/models/product.py | 19 + rma/models/res_company.py | 11 + rma/models/rma_operation.py | 63 +++ rma/models/rma_order.py | 234 ++++++++++ rma/models/rma_order_line.py | 423 ++++++++++++++++++ rma/models/rma_rule.py | 16 + rma/models/stock.py | 37 ++ rma/models/stock_warehouse.py | 26 ++ rma/security/ir.model.access.csv | 11 + rma/security/rma.xml | 38 ++ rma/tests/__init__.py | 4 + rma/tests/test_rma.py | 242 ++++++++++ rma/views/procurement_view.xml | 31 ++ rma/views/product_view.xml | 30 ++ rma/views/res_company_view.xml | 17 + rma/views/rma_operation_view.xml | 69 +++ rma/views/rma_order_line_view.xml | 387 ++++++++++++++++ rma/views/rma_order_view.xml | 365 +++++++++++++++ rma/views/rma_rule_view.xml | 51 +++ rma/views/stock_view.xml | 55 +++ rma/views/stock_warehouse.xml | 20 + rma/wizards/__init__.py | 8 + rma/wizards/rma_add_stock_move.py | 106 +++++ rma/wizards/rma_add_stock_move_view.xml | 128 ++++++ rma/wizards/rma_make_picking.py | 233 ++++++++++ rma/wizards/rma_make_picking_view.xml | 139 ++++++ .../rma_order_line_make_supplier_rma.py | 148 ++++++ .../rma_order_line_make_supplier_rma_view.xml | 89 ++++ rma/wizards/stock_config_settings.py | 17 + rma/wizards/stock_config_settings.xml | 17 + 39 files changed, 3569 insertions(+) create mode 100644 rma/README.rst create mode 100644 rma/__init__.py create mode 100644 rma/__openerp__.py create mode 100644 rma/data/rma_operation.xml create mode 100644 rma/data/rma_sequence.xml create mode 100644 rma/data/stock_data.xml create mode 100644 rma/demo/stock_demo.xml create mode 100644 rma/models/__init__.py create mode 100644 rma/models/procurement.py create mode 100644 rma/models/product.py create mode 100644 rma/models/res_company.py create mode 100644 rma/models/rma_operation.py create mode 100644 rma/models/rma_order.py create mode 100644 rma/models/rma_order_line.py create mode 100644 rma/models/rma_rule.py create mode 100644 rma/models/stock.py create mode 100644 rma/models/stock_warehouse.py create mode 100644 rma/security/ir.model.access.csv create mode 100644 rma/security/rma.xml create mode 100644 rma/tests/__init__.py create mode 100644 rma/tests/test_rma.py create mode 100644 rma/views/procurement_view.xml create mode 100644 rma/views/product_view.xml create mode 100644 rma/views/res_company_view.xml create mode 100644 rma/views/rma_operation_view.xml create mode 100644 rma/views/rma_order_line_view.xml create mode 100644 rma/views/rma_order_view.xml create mode 100644 rma/views/rma_rule_view.xml create mode 100644 rma/views/stock_view.xml create mode 100644 rma/views/stock_warehouse.xml create mode 100644 rma/wizards/__init__.py create mode 100644 rma/wizards/rma_add_stock_move.py create mode 100644 rma/wizards/rma_add_stock_move_view.xml create mode 100644 rma/wizards/rma_make_picking.py create mode 100644 rma/wizards/rma_make_picking_view.xml create mode 100644 rma/wizards/rma_order_line_make_supplier_rma.py create mode 100644 rma/wizards/rma_order_line_make_supplier_rma_view.xml create mode 100644 rma/wizards/stock_config_settings.py create mode 100644 rma/wizards/stock_config_settings.xml diff --git a/rma/README.rst b/rma/README.rst new file mode 100644 index 00000000..68a32563 --- /dev/null +++ b/rma/README.rst @@ -0,0 +1,96 @@ +.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg + :alt: License LGPL-3 + +RMA +=== + +A return merchandise authorization (RMA), is a part of the process of +returning a product in order to receive a refund, replacement, or repair +during the product's warranty period. + +The purchaser of the product must contact the manufacturer (or distributor +or retailer) to obtain authorization to return the product. + +The resulting RMA number must be displayed on or included in the returned +product's packaging. + +The issuance of an RMA is a key gatekeeping moment in the reverse logistics +cycle, providing the vendor with a final opportunity to diagnose and correct +the customer's problem with the product (such as improper installation or +configuration) before the customer permanently relinquishes ownership +of the product to the manufacturer, commonly referred to as a return. + +As returns are costly for the vendor and inconvenient for the customer, +any return that can be prevented benefits both parties. + + +Configuration +============= + +Security +-------- +Go to Settings > Users and assign the appropiate permissions to users. +Different security groups grant distinct levels of access to the RMA features. + +* Users in group "RMA Customer User" or "RMA Supplier User" can access to, + create and process RMA's associated to customers or suppliers respectively. + +* Users in group "RMA Manager" can access to, create, approve and process RMA's + associated to both customers and suppliers. + + + + +#. Go to Settings > Users and assign the appropiate permissions to users. + Users assigned to the group 'RMA +#. Go to Inventory > Settings > Return Merchandising Authorization and select + the option "Display 3 fields on rma: partner, invoice address, delivery + address" if needed. +#. Go to Inventory > Settings > Configuration > Warehouse management > + Warehouses and add a default RMA location and RMA picking type for customers + and suppliers RMA picking type. In case the warehouse is configured to + use routes, you need to create at least one route per rma type with at + least two push rules (one for inbound another for outbound) it's very + important to select the typeof operation supplier if we are moving in the + company and customer if we are moving out of the company. + +Usage +===== + +RMA are accessible though Inventory menu. There's four menus, divided by type +. Users can access to the list of RMA or RMA lines. + +Create an RMA: +#. Select a partner. Enter RMA lines associated to an existing picking, or + manually. +#. Request approval and approve. +#. Click on RMA Lines button. +#. Click on more and select an option: "Receive products", "Create Delivery + Order". +#. Go back to the RMA. Set the RMA to done if not further action is required. + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. + + +Credits +======= + +Contributors +------------ + +* Jordi Ballester Alomar +* Aaron Henriquez + + +Maintainer +---------- + +This module is maintained by Eficent. + diff --git a/rma/__init__.py b/rma/__init__.py new file mode 100644 index 00000000..4105ff51 --- /dev/null +++ b/rma/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) +from . import models +from . import wizards diff --git a/rma/__openerp__.py b/rma/__openerp__.py new file mode 100644 index 00000000..9fc1d7f8 --- /dev/null +++ b/rma/__openerp__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +{ + 'name': 'rma', + 'version': '9.0.1.0.0', + 'license': 'LGPL-3', + 'category': 'RMA', + 'summary': 'Introduces the return merchandise authorization (RMA) process ' + 'in odoo', + 'author': "Eficent", + 'website': 'http://www.github.com/OCA/rma', + 'depends': ['account', 'stock', 'mail', + 'procurement'], + 'demo': [ + 'demo/stock_demo.xml', + ], + 'data': ['security/rma.xml', + 'security/ir.model.access.csv', + + 'data/rma_sequence.xml', + 'data/stock_data.xml', + 'data/rma_operation.xml', + 'views/rma_order_view.xml', + 'views/rma_operation_view.xml', + 'views/rma_rule_view.xml', + 'views/rma_order_line_view.xml', + 'views/stock_view.xml', + 'views/stock_warehouse.xml', + 'views/product_view.xml', + 'views/procurement_view.xml', + 'views/res_company_view.xml', + 'wizards/rma_make_picking_view.xml', + 'wizards/rma_add_stock_move_view.xml', + 'wizards/stock_config_settings.xml', + 'wizards/rma_order_line_make_supplier_rma_view.xml', + ], + 'installable': True, + 'auto_install': False, +} diff --git a/rma/data/rma_operation.xml b/rma/data/rma_operation.xml new file mode 100644 index 00000000..ad39aff4 --- /dev/null +++ b/rma/data/rma_operation.xml @@ -0,0 +1,81 @@ + + + + Replace After Receive + RPLC + no + ordered + received + customer + + + + + + Replace + RPLS + no + ordered + ordered + supplier + + + + + + Refund before receive + RFC + ordered + no + no + customer + + + + + Refund only + RFS + ordered + no + no + supplier + + + + + Replace deliver to vendor + DSRPLB + no + ordered + no + customer + + + + + Replace receive in vendor + DSRPLV + no + no + received + customer + + + + + Replace deliver to customer + DSRPC + no + no + received + supplier + + + + + Always + alw + always + + + diff --git a/rma/data/rma_sequence.xml b/rma/data/rma_sequence.xml new file mode 100644 index 00000000..1162e9ad --- /dev/null +++ b/rma/data/rma_sequence.xml @@ -0,0 +1,39 @@ + + + + Customer RMA sequence + rma.order.customer + 5 + RMA/%(year)s/ + + + + + + Supplier RMA sequence + rma.order.supplier + 5 + RTV/%(year)s/ + + + + + + Customer RMA Line sequence + rma.order.line.customer + 5 + RMAL/%(year)s/ + + + + + + Supplier RMA Line sequence + rma.order.line.supplier + 5 + RTVL/%(year)s/ + + + + + diff --git a/rma/data/stock_data.xml b/rma/data/stock_data.xml new file mode 100644 index 00000000..7dd24cdc --- /dev/null +++ b/rma/data/stock_data.xml @@ -0,0 +1,212 @@ + + + + WH RMA + internal + + + + + DOC + RCO + 5 + + + + + INC + RCI + 5 + + + + + DOS + RSO + 5 + + + + + INS + RSI + 5 + + + + + DSS + DSS + 5 + + + + + RMA → Customer + + + + + outgoing + + + + Customer → RMA + + + + + incoming + + + + RMA -> Supplier + + + + + outgoing + + + + Supplier -> RMA + + + + + incoming + + + + Customer -> Supplier + + + + + incoming + + + + Supplier -> Customer + + + + + incoming + + + + + + + + + + + + RMA Customer + 10 + + + + + + + + + RMA Supplier + 10 + + + + + + + + + RMA Dropship + 10 + + + + + + + + + Customer → RMA + move + + + + make_to_stock + + + + + + RMA → Customer + move + + + + make_to_stock + + + + + + RMA → Supplier + move + + + + make_to_stock + + + + + + Supplier → RMA + move + + + + make_to_stock + + + + + + Customer → Supplier + move + + + + make_to_stock + + + + + + Supplier → Customer + move + + + + make_to_stock + + + + + diff --git a/rma/demo/stock_demo.xml b/rma/demo/stock_demo.xml new file mode 100644 index 00000000..5af76da5 --- /dev/null +++ b/rma/demo/stock_demo.xml @@ -0,0 +1,19 @@ + + + + + RMA + internal + + + + + + + + + + + + + diff --git a/rma/models/__init__.py b/rma/models/__init__.py new file mode 100644 index 00000000..ad034891 --- /dev/null +++ b/rma/models/__init__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from . import rma_order +from . import rma_order_line +from . import rma_operation +from . import rma_rule +from . import stock +from . import stock_warehouse +from . import product +from . import procurement +from . import res_company diff --git a/rma/models/procurement.py b/rma/models/procurement.py new file mode 100644 index 00000000..a55e8910 --- /dev/null +++ b/rma/models/procurement.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import api, fields, models + + +class ProcurementOrder(models.Model): + _inherit = 'procurement.order' + + rma_line_id = fields.Many2one('rma.order.line', 'RMA', ondelete="set null") + + @api.model + def _run_move_create(self, procurement): + res = super(ProcurementOrder, self)._run_move_create(procurement) + if procurement.rma_line_id: + line = procurement.rma_line_id + res['rma_line_id'] = line.id + if line.delivery_address_id and line.delivery_address_id.id: + res['partner_id'] = line.delivery_address_id.id + elif line.invoice_line_id.invoice_id.partner_id: + res['partner_id'] = line.invoice_id.partner_id.id + return res + + +class ProcurementGroup(models.Model): + _inherit = 'procurement.group' + + rma_id = fields.Many2one('rma.order', 'RMA', ondelete="set null") diff --git a/rma/models/product.py b/rma/models/product.py new file mode 100644 index 00000000..2a992b25 --- /dev/null +++ b/rma/models/product.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import fields, models + + +class ProductCategory(models.Model): + _inherit = 'product.category' + + rma_operation_id = fields.Many2one( + comodel_name="rma.operation", string="RMA Operation") + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + rma_operation_id = fields.Many2one( + comodel_name="rma.operation", string="RMA Operation") diff --git a/rma/models/res_company.py b/rma/models/res_company.py new file mode 100644 index 00000000..efc8f43c --- /dev/null +++ b/rma/models/res_company.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import models, fields + + +class ResCompany(models.Model): + _inherit = 'res.company' + + rma_rule_id = fields.Many2one('rma.rule', 'Default RMA Approval Policy') diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py new file mode 100644 index 00000000..87d271e0 --- /dev/null +++ b/rma/models/rma_operation.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import _, api, fields, models + + +class RmaOperation(models.Model): + _name = 'rma.operation' + _description = 'RMA Operation' + + @api.model + def _default_warehouse_id(self): + company = self.env.user.company_id.id + warehouse = self.env['stock.warehouse'].search( + [('company_id', '=', company)], limit=1) + return warehouse + + @api.model + def _default_customer_location_id(self): + return self.env.ref('stock.stock_location_customers') or False + + @api.model + def _default_supplier_location_id(self): + return self.env.ref('stock.stock_location_suppliers') or False + + name = fields.Char('Description', required=True) + code = fields.Char('Code', required=True) + refund_policy = fields.Selection([ + ('no', 'No refund'), ('ordered', 'Based on Ordered Quantities'), + ('received', 'Based on Received Quantities')], string="Refund Policy", + default='no') + receipt_policy = fields.Selection([ + ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), + ('received', 'Based on Delivered Quantities')], + string="Receipts Policy", default='no') + delivery_policy = fields.Selection([ + ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), + ('received', 'Based on Received Quantities')], + string="Delivery Policy", default='no') + in_route_id = fields.Many2one( + 'stock.location.route', string='Inbound Route', + domain=[('rma_selectable', '=', True)]) + out_route_id = fields.Many2one( + 'stock.location.route', string='Outbound Route', + domain=[('rma_selectable', '=', True)]) + customer_to_supplier= fields.Boolean( + 'The customer will send to the supplier', default=False) + supplier_to_customer = fields.Boolean( + 'The supplier will send to the customer', default=False) + in_warehouse_id = fields.Many2one('stock.warehouse', + string='Inbound Warehouse', + default=_default_warehouse_id) + out_warehouse_id = fields.Many2one('stock.warehouse', + string='Outbound Warehouse', + default=_default_warehouse_id) + location_id = fields.Many2one( + 'stock.location', 'Send To This Company Location') + type = fields.Selection([ + ('customer', 'Customer'), ('supplier', 'Supplier')], + string="Used in RMA of this type", required=True, default='customer') + rma_line_ids = fields.One2many('rma.order.line', 'operation_id', + 'RMA lines') diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py new file mode 100644 index 00000000..9f99a636 --- /dev/null +++ b/rma/models/rma_order.py @@ -0,0 +1,234 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import _, api, fields, models +from openerp.addons import decimal_precision as dp +from openerp.exceptions import UserError +from dateutil.relativedelta import relativedelta +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT +from datetime import datetime + + +class RmaOrder(models.Model): + _name = "rma.order" + _inherit = ['mail.thread'] + + @api.model + def _compute_rule_id(self): + if self.company_id and self.company_id.id: + if self.company_id.rma_rule_id and self.company_id.rma_rule_id.id: + self.rule_id = self.company_id.rma_rule_id + + @api.model + def _get_default_type(self): + if 'supplier' in self.env.context: + return "supplier" + else: + return "customer" + + @api.multi + def _compute_in_shipment_count(self): + for rec in self: + rec.in_shipment_count = len(rec.rma_line_ids.mapped( + 'procurement_ids.move_ids').filtered( + lambda m: m.location_dest_id.usage == 'internal').mapped( + 'picking_id')) + + @api.multi + def _compute_out_shipment_count(self): + for rec in self: + rec.out_shipment_count = len(rec.rma_line_ids.mapped( + 'procurement_ids.move_ids').filtered( + lambda m: m.location_id.usage == 'internal').mapped( + 'picking_id')) + + @api.multi + def _compute_supplier_line_count(self): + self.supplier_line_count = len(self.rma_line_ids.filtered( + lambda r: r.supplier_rma_line_ids)) + + @api.multi + def _compute_line_count(self): + self.ensure_one() + self.line_count = len(self._get_valid_lines()) + + name = fields.Char(string='Order Number', index=True, + readonly=True, + states={'progress': [('readonly', False)]}, + copy=False) + type = fields.Selection( + [('customer', 'Customer'), ('supplier', 'Supplier')], + string="Type", required=True, default=_get_default_type, readonly=True) + reference = fields.Char(string='Reference', + help="The partner reference of this RMA order.") + + comment = fields.Text('Additional Information', readonly=True, states={ + 'draft': [('readonly', False)]}) + + state = fields.Selection([('draft', 'Draft'), ('to_approve', 'To Approve'), + ('approved', 'Approved'), + ('done', 'Done')], string='State', index=True, + default='draft') + date_rma = fields.Datetime(string='Order Date', index=True, copy=False) + partner_id = fields.Many2one('res.partner', string='Partner', + required=True, readonly=True, + states={'draft': [('readonly', False)]}) + assigned_to = fields.Many2one('res.users', 'Assigned to', + track_visibility='onchange') + requested_by = fields.Many2one('res.users', 'Requested by', + track_visibility='onchange', + default=lambda self: self.env.user) + rule_id = fields.Many2one('rma.rule', string='Approval Criteria', + compute=_compute_rule_id) + rma_line_ids = fields.One2many('rma.order.line', 'rma_id', + string='RMA lines') + in_shipment_count = fields.Integer(compute=_compute_in_shipment_count, + string='# of Invoices') + out_shipment_count = fields.Integer(compute=_compute_out_shipment_count, + string='# of Outgoing Shipments') + line_count = fields.Integer(compute=_compute_line_count, + string='# of Outgoing Shipments', + copy=False) + supplier_line_count = fields.Integer(compute=_compute_supplier_line_count, + string='# of Outgoing Shipments', + copy=False) + company_id = fields.Many2one('res.company', string='Company', + required=True, default=lambda self: + self.env.user.company_id) + + @api.model + def create(self, vals): + if self.env.context.get('supplier'): + vals['name'] = self.env['ir.sequence'].next_by_code( + 'rma.order.supplier') + else: + vals['name'] = self.env['ir.sequence'].next_by_code( + 'rma.order.customer') + return super(RmaOrder, self).create(vals) + + @api.multi + def action_view_in_shipments(self): + action = self.env.ref('stock.action_picking_tree_all') + result = action.read()[0] + picking_ids = [] + suppliers = self.env.ref('stock.stock_location_suppliers') + customers = self.env.ref('stock.stock_location_customers') + for line in self.rma_line_ids: + if line.type == 'customer': + for move in line.move_ids: + if move.picking_id.location_id == customers: + picking_ids.append(move.picking_id.id) + else: + for move in line.move_ids: + if move.picking_id.location_id == suppliers: + picking_ids.append(move.picking_id.id) + shipments = list(set(picking_ids)) + # choose the view_mode accordingly + if len(shipments) != 1: + result['domain'] = "[('id', 'in', " + \ + str(shipments) + ")]" + elif len(shipments) == 1: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = shipments[0] + return result + + @api.multi + def action_view_out_shipments(self): + action = self.env.ref('stock.action_picking_tree_all') + result = action.read()[0] + picking_ids = [] + suppliers = self.env.ref('stock.stock_location_suppliers') + customers = self.env.ref('stock.stock_location_customers') + for line in self.rma_line_ids: + if line.type == 'customer': + for move in line.move_ids: + if move.picking_id.location_id != customers: + picking_ids.append(move.picking_id.id) + else: + for move in line.move_ids: + if move.picking_id.location_id != suppliers: + picking_ids.append(move.picking_id.id) + shipments = list(set(picking_ids)) + # choose the view_mode accordingly + if len(shipments) != 1: + result['domain'] = "[('id', 'in', " + \ + str(shipments) + ")]" + elif len(shipments) == 1: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = shipments[0] + return result + + @api.multi + def action_rma_to_approve(self): + for rec in self: + rec.state = 'to_approve' + if rec.rule_id and rec.rule_id.id: + if rec.rule_id.approval_policy == 'always': + rec.assigned_to = self.env.uid + rec.action_rma_approve() + return True + + @api.multi + def action_rma_draft(self): + for rec in self: + rec.state = 'draft' + return True + + @api.multi + def action_rma_approve(self): + # pass the supplier address in case this is a customer RMA + for rec in self: + rec.state = 'approved' + return True + + @api.multi + def action_rma_done(self): + for rec in self: + rec.state = 'done' + return True + + @api.multi + def _get_valid_lines(self): + self.ensure_one() + return self.rma_line_ids + + @api.multi + def action_view_lines(self): + if self.type == 'customer': + action = self.env.ref('rma.action_rma_customer_lines') + else: + action = self.env.ref('rma.action_rma_supplier_lines') + result = action.read()[0] + lines = self._get_valid_lines() + # choose the view_mode accordingly + if len(lines) != 1: + result['domain'] = "[('id', 'in', " + \ + str(lines.ids) + ")]" + elif len(lines) == 1: + if self.type == 'customer': + res = self.env.ref('rma.view_rma_line_form', False) + else: + res = self.env.ref('rma.view_rma_line_supplier_form', False) + + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = lines.id + return result + + @api.multi + def action_view_supplier_lines(self): + action = self.env.ref('rma.action_rma_supplier_lines') + result = action.read()[0] + lines = self.rma_line_ids + related_lines = [line.id for line in lines.children_ids] + # choose the view_mode accordingly + if len(related_lines) != 1: + result['domain'] = "[('id', 'in', " + \ + str(related_lines) + ")]" + elif len(related_lines) == 1: + res = self.env.ref('rma.view_rma_line_supplier_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = related_lines[0] + return result diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py new file mode 100644 index 00000000..a2847bb7 --- /dev/null +++ b/rma/models/rma_order_line.py @@ -0,0 +1,423 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import _, api, fields, models +from openerp.addons import decimal_precision as dp +import operator +ops = {'=': operator.eq, + '!=': operator.ne} + + +class RmaOrderLine(models.Model): + _name = "rma.order.line" + _rec_name = "rma_id" + + @api.model + def _default_warehouse_id(self): + rma_id = self.env.context.get('default_rma_id', False) + warehouse = self.env['stock.warehouse'] + if rma_id: + rma = self.env['rma.order'].browse(rma_id) + warehouse = self.env['stock.warehouse'].search( + [('company_id', '=', rma.company_id.id)], limit=1) + return warehouse + + @api.model + def _default_location_id(self): + wh = self._default_warehouse_id() + return wh.lot_rma_id + + @api.model + def _default_delivery_address(self): + partner_id = self.env.context.get('partner_id', False) + if partner_id: + partner = self.env['res.partner'].browse(partner_id) + addr = partner.address_get(['delivery']) + return self.env['res.partner'].browse(addr['delivery']) + return False + + @api.multi + def _compute_in_shipment_count(self): + for line in self: + moves = line.procurement_ids.mapped('move_ids').filtered( + lambda m: m.location_dest_id.usage == 'internal') + pickings = moves.mapped('picking_id') + line.in_shipment_count = len(pickings) + + @api.multi + def _compute_out_shipment_count(self): + for line in self: + moves = line.procurement_ids.mapped('move_ids').filtered( + lambda m: m.location_dest_id.usage != 'internal') + pickings = moves.mapped('picking_id') + line.out_shipment_count = len(pickings) + + @api.multi + def _get_rma_move_qty(self, states, direction='in'): + for rec in self: + product_obj = self.env['product.uom'] + qty = 0.0 + if direction == 'in': + op = ops['='] + else: + op = ops['!='] + for move in rec.procurement_ids.mapped('move_ids').filtered( + lambda m: m.state in states and op(m.location_id.usage, + rec.type)): + qty += product_obj._compute_qty_obj( + move.product_uom, move.product_uom_qty, + rec.uom_id) + return qty + + @api.multi + @api.depends('move_ids', 'move_ids.state', 'qty_received', + 'receipt_policy', 'product_qty', 'type') + def _compute_qty_to_receive(self): + for rec in self: + rec.qty_to_receive = 0.0 + if rec.receipt_policy == 'ordered': + rec.qty_to_receive = rec.product_qty - rec.qty_received + elif self.receipt_policy == 'delivered': + self.qty_to_receive = rec.qty_delivered - rec.qty_received + + @api.multi + @api.depends('move_ids', 'move_ids.state', + 'delivery_policy', 'product_qty', 'type', 'qty_delivered', + 'qty_received') + def _compute_qty_to_deliver(self): + for rec in self: + rec.qty_to_deliver = 0.0 + if rec.delivery_policy == 'ordered': + rec.qty_to_deliver = rec.product_qty - rec.qty_delivered + elif self.delivery_policy == 'received': + self.qty_to_deliver = rec.qty_received - rec.qty_delivered + + @api.multi + @api.depends('move_ids', 'move_ids.state', 'type') + def _compute_qty_incoming(self): + for rec in self: + qty = rec._get_rma_move_qty( + ('draft', 'confirmed', 'assigned'), direction='in') + rec.qty_incoming = qty + + @api.multi + @api.depends('move_ids', 'move_ids.state', 'type') + def _compute_qty_received(self): + for rec in self: + qty = rec._get_rma_move_qty('done', direction='in') + rec.qty_received = qty + + @api.multi + @api.depends('move_ids', 'move_ids.state', 'type') + def _compute_qty_outgoing(self): + for rec in self: + qty = rec._get_rma_move_qty( + ('draft', 'confirmed', 'assigned'), direction='out') + rec.qty_outgoing = qty + + @api.multi + @api.depends('move_ids', 'move_ids.state', 'type') + def _compute_qty_delivered(self): + for rec in self: + qty = rec._get_rma_move_qty('done', direction='out') + rec.qty_delivered = qty + + @api.model + def _get_supplier_rma_qty(self): + return sum(self.supplier_rma_line_ids.filtered( + lambda r: r.state != 'cancel').mapped( + 'product_qty')) + + @api.multi + @api.depends('customer_to_supplier', 'supplier_rma_line_ids', + 'supplier_rma_line_ids.rma_id.state', + 'move_ids', 'move_ids.state', 'qty_received', + 'receipt_policy', 'product_qty', 'type') + def _compute_qty_supplier_rma(self): + for rec in self: + qty = rec._get_supplier_rma_qty() + rec.qty_to_supplier_rma = rec.qty_to_receive - qty + rec.qty_in_supplier_rma = qty + + @api.multi + def _compute_procurement_count(self): + for rec in self: + rec.procurement_count = len(rec.procurement_ids.filtered( + lambda p: p.state == 'exception')) + + delivery_address_id = fields.Many2one( + 'res.partner', string='Partner delivery address', + default=_default_delivery_address, + help="This address will be used to " + "deliver repaired or replacement products.") + + rma_id = fields.Many2one('rma.order', string='RMA', + ondelete='cascade', required=True) + name = fields.Char(string='Reference', required=True, default='/', + help='Add here the supplier RMA #. Otherwise an ' + 'internal code is assigned.') + description = fields.Text(string='Description') + origin = fields.Char(string='Source Document', + help="Reference of the document that produced " + "this rma.") + state = fields.Selection(related='rma_id.state') + operation_id = fields.Many2one( + comodel_name="rma.operation", string="Operation") + + assigned_to = fields.Many2one('res.users', related='rma_id.assigned_to') + requested_by = fields.Many2one('res.users', related='rma_id.requested_by') + partner_id = fields.Many2one('res.partner', related='rma_id.partner_id', + store=True) + sequence = fields.Integer(default=10, + help="Gives the sequence of this line " + "when displaying the rma.") + product_id = fields.Many2one('product.product', string='Product', + ondelete='restrict', required=-True) + product_tracking = fields.Selection(related="product_id.tracking") + lot_id = fields.Many2one( + comodel_name="stock.production.lot", string="Lot/Serial Number", + readonly=True, states={"new": [("readonly", False)]}, + ) + product_qty = fields.Float( + string='Ordered Qty', copy=False, + digits=dp.get_precision('Product Unit of Measure')) + uom_id = fields.Many2one('product.uom', string='Unit of Measure', + required=True) + price_unit = fields.Monetary(string='Price Unit', readonly=False, + states={'approved': [('readonly', True)], + 'done': [('readonly', True)], + 'to_approve': [('readonly', True)]}) + + procurement_count = fields.Integer(compute=_compute_procurement_count, + string='# of Procurements', copy=False, + default=0) + in_shipment_count = fields.Integer(compute=_compute_in_shipment_count, + string='# of Shipments', default=0) + out_shipment_count = fields.Integer(compute=_compute_out_shipment_count, + string='# of Deliveries', default=0) + move_ids = fields.One2many('stock.move', 'rma_line_id', + string='Stock Moves', readonly=True + , copy=False) + reference_move_id = fields.Many2one(comodel_name='stock.move', + string='Originating stock move', + readonly=True, copy=False) + procurement_ids = fields.One2many('procurement.order', 'rma_line_id', + string='Procurements', readonly=True, + states={'draft': [('readonly', False)]}, + copy=False) + currency_id = fields.Many2one('res.currency', string="Currency") + company_id = fields.Many2one('res.company', string='Company', + related='rma_id.company_id', store=True) + type = fields.Selection(related='rma_id.type') + customer_to_supplier = fields.Boolean( + 'The customer will send to the supplier') + supplier_to_customer = fields.Boolean( + 'The supplier will send to the customer') + receipt_policy = fields.Selection([ + ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), + ('delivered', 'Based on Delivered Quantities')], + required=True, string="Receipts Policy") + delivery_policy = fields.Selection([ + ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), + ('received', 'Based on Received Quantities')], required=True, + string="Delivery Policy") + in_route_id = fields.Many2one( + 'stock.location.route', string='Inbound Route', + required=True, + domain=[('rma_selectable', '=', True)]) + out_route_id = fields.Many2one( + 'stock.location.route', string='Outbound Route', + required=True, + domain=[('rma_selectable', '=', True)]) + in_warehouse_id = fields.Many2one('stock.warehouse', + string='Inbound Warehouse', + required=True, + default=_default_warehouse_id) + out_warehouse_id = fields.Many2one('stock.warehouse', + string='Outbound Warehouse', + required=True, + default=_default_warehouse_id) + location_id = fields.Many2one( + 'stock.location', 'Send To This Company Location', required=True, + default=_default_location_id) + customer_rma_id = fields.Many2one( + 'rma.order.line', string='Customer RMA line', ondelete='cascade') + supplier_rma_line_ids = fields.One2many('rma.order.line', 'customer_rma_id') + supplier_address_id = fields.Many2one( + 'res.partner', readonly=True, + states={'draft': [('readonly', False)]}, + string='Supplier Address', + help="This address of the supplier in case of Customer RMA operation " + "dropship.") + qty_to_receive = fields.Float( + string='Qty To Receive', + digits=dp.get_precision('Product Unit of Measure'), + compute=_compute_qty_to_receive, store=True) + qty_incoming = fields.Float( + string='Incoming Qty', copy=False, + readonly=True, digits=dp.get_precision('Product Unit of Measure'), + compute=_compute_qty_incoming, store=True) + qty_received = fields.Float( + string='Qty Received', copy=False, + digits=dp.get_precision('Product Unit of Measure'), + compute=_compute_qty_received, + store=True) + qty_to_deliver = fields.Float( + string='Qty To Deliver', copy=False, + digits=dp.get_precision('Product Unit of Measure'), + readonly=True, compute=_compute_qty_to_deliver, + store=True) + qty_outgoing = fields.Float( + string='Outgoing Qty', copy=False, + readonly=True, digits=dp.get_precision('Product Unit of Measure'), + compute=_compute_qty_outgoing, + store=True) + qty_delivered = fields.Float( + string='Qty Delivered', copy=False, + digits=dp.get_precision('Product Unit of Measure'), + readonly=True, compute=_compute_qty_delivered, + store=True) + qty_to_supplier_rma = fields.Float( + string='Qty to send to Supplier RMA', + digits=dp.get_precision('Product Unit of Measure'), + readonly=True, compute=_compute_qty_supplier_rma, + store=True) + qty_in_supplier_rma = fields.Float( + string='Qty in Supplier RMA', + digits=dp.get_precision('Product Unit of Measure'), + readonly=True, compute=_compute_qty_supplier_rma, + store=True) + + @api.model + def create(self, vals): + if self.env.context.get('supplier'): + vals['name'] = self.env['ir.sequence'].next_by_code( + 'rma.order.line.supplier') + else: + vals['name'] = self.env['ir.sequence'].next_by_code( + 'rma.order.line.customer') + return super(RmaOrderLine, self).create(vals) + + @api.onchange('product_id') + def _onchange_product_id(self): + result = {} + if not self.product_id: + return result + self.product_qty = 1 + self.uom_id = self.product_id.uom_id.id + self.price_unit = self.product_id.standard_price + self.operation_id = self.product_id.rma_operation_id or \ + self.product_id.categ_id.rma_operation_id + return result + + @api.onchange('operation_id') + def _onchange_operation_id(self): + result = {} + if not self.operation_id: + return result + self.receipt_policy = self.operation_id.receipt_policy + self.delivery_policy = self.operation_id.delivery_policy + self.in_warehouse_id = self.operation_id.in_warehouse_id + self.out_warehouse_id = self.operation_id.out_warehouse_id + self.location_id = self.operation_id.location_id or \ + self.in_warehouse_id.lot_rma_id + self.customer_to_supplier = self.operation_id.customer_to_supplier + self.supplier_to_customer = self.operation_id.supplier_to_customer + self.in_route_id = self.operation_id.in_route_id + self.out_route_id = self.operation_id.out_route_id + return result + + @api.onchange('customer_to_supplier', 'type') + def _onchange_receipt_policy(self): + if self.type == 'supplier' and self.customer_to_supplier: + self.receipt_policy = 'no' + elif self.type == 'customer' and self.supplier_to_customer: + self.delivery_policy = 'no' + + @api.onchange('product_id') + def _onchange_product_id(self): + self.uom_id = self.product_id.uom_id + if self.lot_id.product_id != self.product_id: + self.lot_id = False + if self.product_id: + return {'domain': { + 'lot_id': [('product_id', '=', self.product_id.id)]}} + return {'domain': {'lot_id': []}} + + @api.onchange("lot_id") + def _onchange_lot_id(self): + product = self.lot_id.product_id + if product: + self.product_id = product + self.uom_id = product.uom_id + + @api.multi + def action_view_in_shipments(self): + action = self.env.ref('stock.action_picking_tree_all') + result = action.read()[0] + picking_ids = [] + suppliers = self.env.ref('stock.stock_location_suppliers') + customers = self.env.ref('stock.stock_location_customers') + for line in self: + if line.type == 'customer': + for move in line.move_ids: + if move.picking_id.location_id == customers: + picking_ids.append(move.picking_id.id) + else: + for move in line.move_ids: + if move.picking_id.location_id == suppliers: + picking_ids.append(move.picking_id.id) + shipments = list(set(picking_ids)) + # choose the view_mode accordingly + if len(shipments) != 1: + result['domain'] = "[('id', 'in', " + \ + str(shipments) + ")]" + elif len(shipments) == 1: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = shipments[0] + return result + + @api.multi + def action_view_out_shipments(self): + action = self.env.ref('stock.action_picking_tree_all') + result = action.read()[0] + picking_ids = [] + suppliers = self.env.ref('stock.stock_location_suppliers') + customers = self.env.ref('stock.stock_location_customers') + for line in self: + if line.type == 'customer': + for move in line.move_ids: + if move.picking_id.location_id != customers: + picking_ids.append(move.picking_id.id) + else: + for move in line.move_ids: + if move.picking_id.location_id != suppliers: + picking_ids.append(move.picking_id.id) + shipments = list(set(picking_ids)) + # choose the view_mode accordingly + if len(shipments) != 1: + result['domain'] = "[('id', 'in', " + \ + str(shipments) + ")]" + elif len(shipments) == 1: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = shipments[0] + return result + + @api.multi + def action_view_procurements(self): + action = self.env.ref('procurement.procurement_order_action_exceptions') + result = action.read()[0] + procurements = self.procurement_ids.filtered( + lambda p: p.state == 'exception').ids + # choose the view_mode accordingly + if len(procurements) != 1: + result['domain'] = "[('id', 'in', " + \ + str(procurements) + ")]" + elif len(procurements) == 1: + res = self.env.ref('procurement.procurement_form_view', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = procurements[0] + return result diff --git a/rma/models/rma_rule.py b/rma/models/rma_rule.py new file mode 100644 index 00000000..ec3c9255 --- /dev/null +++ b/rma/models/rma_rule.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import _, api, fields, models + + +class RmaRule(models.Model): + _name = 'rma.rule' + _description = 'RMA Approval Conditions' + + name = fields.Char('Description', required=True) + code = fields.Char('Code', required=True) + approval_policy = fields.Selection([ + ('always', 'Always')], string="Approval Policy", + required=True, default='always') diff --git a/rma/models/stock.py b/rma/models/stock.py new file mode 100644 index 00000000..cc70c174 --- /dev/null +++ b/rma/models/stock.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import api, fields, models + + +class StockPicking(models.Model): + _inherit = "stock.picking" + + @api.multi + def action_assign(self): + for picking in self: + for move in picking.move_lines: + if len(move.rma_line_id): + if move.state in ('confirmed', 'waiting', 'assigned') \ + and move.location_id.usage in ( + 'supplier', 'customer'): + move.force_assign() + return super(StockPicking, self).action_assign() + + +class StockMove(models.Model): + + _inherit = "stock.move" + + rma_line_id = fields.Many2one('rma.order.line', string='RMA', + ondelete='restrict') + + @api.model + def create(self, vals): + if vals.get('procurement_id', False): + procurement = self.env['procurement.order'].browse( + vals['procurement_id']) + if procurement.rma_line_id and procurement.rma_line_id.id: + vals['rma_line_id'] = procurement.rma_line_id.id + return super(StockMove, self).create(vals) diff --git a/rma/models/stock_warehouse.py b/rma/models/stock_warehouse.py new file mode 100644 index 00000000..3d465a60 --- /dev/null +++ b/rma/models/stock_warehouse.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import api, fields, models + + +class StockWarehouse(models.Model): + + _inherit = "stock.warehouse" + + lot_rma_id = fields.Many2one('stock.location', 'RMA Location') + rma_cust_out_type_id = fields.Many2one('stock.picking.type', + 'RMA Customer out Type') + rma_sup_out_type_id = fields.Many2one('stock.picking.type', + 'RMA Supplier out Type') + rma_cust_in_type_id = fields.Many2one('stock.picking.type', + 'RMA Customer in Type') + rma_sup_in_type_id = fields.Many2one('stock.picking.type', + 'RMA Supplier in Type') + + +class StockLocationRoute(models.Model): + _inherit = "stock.location.route" + + rma_selectable = fields.Boolean(string="Selectable on RMA Lines") diff --git a/rma/security/ir.model.access.csv b/rma/security/ir.model.access.csv new file mode 100644 index 00000000..291e1e5d --- /dev/null +++ b/rma/security/ir.model.access.csv @@ -0,0 +1,11 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_rma_user_customer,rma.order.customer.user,model_rma_order,group_rma_customer_user,1,1,1,1 +access_rma_user_supplier,rma.order.supplier.user,model_rma_order,group_rma_supplier_user,1,1,1,1 +access_rma_manager,rma.order.manager,model_rma_order,group_rma_manager,1,1,1,1 +access_rma_line_customer_user,rma.order.line.customer.user,model_rma_order_line,group_rma_customer_user,1,1,1,1 +access_rma_line_supplier_user,rma.order.line.customer.supplier,model_rma_order_line,group_rma_supplier_user,1,1,1,1 +access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1,1,1,1 +access_rma_operation_manager,access_rma_operation,model_rma_operation,group_rma_manager,1,1,1,1 +access_rma_operation_customer_user,access_rma_operation,model_rma_operation,group_rma_customer_user,1,0,0,0 +access_rma_operation_supplier_user,access_rma_operation,model_rma_operation,group_rma_supplier_user,1,0,0,0 +access_stock_config_settings,access_stock_config_settings,model_stock_config_settings,stock.group_stock_manager,1,1,1,1 diff --git a/rma/security/rma.xml b/rma/security/rma.xml new file mode 100644 index 00000000..ab04e69c --- /dev/null +++ b/rma/security/rma.xml @@ -0,0 +1,38 @@ + + + + + + RMA + + 30 + + + + RMA Customer User + + + + + + RMA Supplier User + + + + + + RMA Manager + + + + + + + Addresses in RMA + + + + + + diff --git a/rma/tests/__init__.py b/rma/tests/__init__.py new file mode 100644 index 00000000..1c2b27c0 --- /dev/null +++ b/rma/tests/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) +from . import test_rma diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py new file mode 100644 index 00000000..6ae75d89 --- /dev/null +++ b/rma/tests/test_rma.py @@ -0,0 +1,242 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp.tests import common + + +class TestRma(common.TransactionCase): + + """ Test the routes and the quantities """ + + def setUp(self): + super(TestRma, self).setUp() + + self.rma_make_picking = self.env['rma_make_picking.wizard'] + self.rma_add_invoice = self.env['rma_add_invoice'] + self.stockpicking = self.env['stock.picking'] + self.rma = self.env['rma.order'] + self.rma_line = self.env['rma.order.line'] + self.rma_op = self.env['rma.operation'] + self.rma_op_id = self.env.ref('rma.rma_operation_customer_replace') + self.product_id = self.env.ref('product.product_product_4') + self.product_1 = self.env.ref('product.product_product_25') + self.product_2 = self.env.ref('product.product_product_30') + self.product_3 = self.env.ref('product.product_product_33') + self.uom_unit = self.env.ref('product.product_uom_unit') + # assign an operation + self.product_1.write({'rma_operation_id': self.rma_op_id.id}) + self.product_2.write({'rma_operation_id': self.rma_op_id.id}) + self.product_3.write({'rma_operation_id': self.rma_op_id.id}) + self.partner_id = self.env.ref('base.res_partner_12') + + self.customer_location_id = self.env.ref( + 'stock.stock_location_customers' + ) + uom_unit = self.env.ref('product.product_uom_unit') + sale_values = self._prepare_sale() + self.sale_order = self.env['sale.order'].create(sale_values) + invoice_id = self.sale_order.action_invoice_create()[0] + self.invoice = self.env['account.invoice'].browse(invoice_id) + # Create the RMA from the invoice + self.rma_id = self.rma.create( + { + 'reference': '0001', + 'type': 'customer', + 'partner_id': self.env.ref('base.res_partner_2').id + }) + + for line in self.invoice.invoice_line_ids: + data = self.rma_add_invoice.with_context( + {'invoice_id': self.invoice.id} + )._prepare_rma_line_from_inv_line(line) + data.update(rma_id=self.rma_id.id) + self.rma_line.create(data) + #approve the RMA + self.rma_id.action_rma_to_approve() + self.rma_id.action_rma_approve() + + def _prepare_sale(self): + values = { + 'state': 'done', + 'partner_id': self.env.ref('base.res_partner_2').id, + 'pricelist_id': self.env.ref('product.list0').id, + 'warehouse_id': self.env.ref('stock.warehouse0').id, + 'partner_invoice_id': self.env.ref('base.res_partner_2').id, + 'partner_shipping_id': self.env.ref('base.res_partner_2').id, + 'picking_policy': 'direct', + 'order_line': [ + (0, False, { + 'name': product.name, + 'product_id': product.id, + 'product_uom_qty': qty, + 'qty_delivered': qty, + 'product_uom': self.uom_unit.id, + 'price_unit': product.list_price + + }) for product, qty in [ + (self.product_1, 3), + (self.product_2, 5), + (self.product_3, 2), + ] + ] + } + return values + + def test_00_receive_items(self): + wizard = self.rma_make_picking.with_context({ + 'active_ids': self.rma_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'incoming', + 'active_id': 1 + }).create({}) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = "[('group_id','in',[" + ','.join( + map(str, list(group_ids))) + "])]" + picking = self.stockpicking.search(domain) + self.assertEquals(len(picking), 1, + "Incorrect number of pickings created") + moves = picking.move_lines + self.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in self.rma_id.rma_line_ids: + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + self.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + self.assertEquals(line.qty_to_refund, 0, + "Wrong qty to refund") + self.assertEquals(line.qty_to_refunded, 0, + "Wrong qty refunded") + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 3, + "Wrong qty incoming") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 5, + "Wrong qty incoming") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 2, + "Wrong qty incoming") + pickings.action_assign() + pickings.do_transfer() + for line in self.rma_id.rma_line_ids: + self.assertEquals(line.qty_to_receive, 0, + "Wrong qty to_receive") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + self.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + self.assertEquals(line.qty_to_refund, 0, + "Wrong qty to refund") + self.assertEquals(line.qty_to_refunded, 0, + "Wrong qty refunded") + if line.product_id == self.product_1: + self.assertEquals(line.qty_received, 3, + "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to_deliver") + if line.product_id == self.product_2: + self.assertEquals(line.qty_received, 5, + "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to_deliver") + if line.product_id == self.product_3: + self.assertEquals(line.qty_received, 2, + "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to_deliver") + + wizard = self.rma_make_picking.with_context({ + 'active_id': 1, + 'active_ids': self.rma_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'outgoing', + }).create({}) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = "[('group_id','in',[" + ','.join( + map(str, list(group_ids))) + "])]" + picking = self.stockpicking.search(domain) + self.assertEquals(len(picking), 1, + "Incorrect number of pickings created") + moves = picking.move_lines + self.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in self.rma_id.rma_line_ids: + self.assertEquals(line.qty_to_receive, 0, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + self.assertEquals(line.qty_to_refund, 0, + "Wrong qty to refund") + self.assertEquals(line.qty_to_refunded, 0, + "Wrong qty refunded") + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 3, + "Wrong qty outgoing") + self.assertEquals(line.qty_received, 3, + "Wrong qty received") + if line.product_id == self.product_2: + self.assertEquals(line.qty_received, 5, + "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 5, + "Wrong qty outgoing") + if line.product_id == self.product_3: + self.assertEquals(line.qty_received, 2, + "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 2, + "Wrong qty outgoing") + pickings.action_assign() + pickings.do_transfer() + for line in self.rma_id.rma_line_ids: + self.assertEquals(line.qty_to_receive, 0, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + self.assertEquals(line.qty_to_refund, 0, + "Wrong qty to refund") + self.assertEquals(line.qty_to_refunded, 0, + "Wrong qty refunded") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + if line.product_id == self.product_1: + self.assertEquals(line.qty_received, 3, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + if line.product_id == self.product_2: + self.assertEquals(line.qty_received, 5, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 5, + "Wrong qty delivered") + if line.product_id == self.product_3: + self.assertEquals(line.qty_received, 2, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 2, + "Wrong qty delivered") + self.rma_id.action_rma_done() diff --git a/rma/views/procurement_view.xml b/rma/views/procurement_view.xml new file mode 100644 index 00000000..a79015f6 --- /dev/null +++ b/rma/views/procurement_view.xml @@ -0,0 +1,31 @@ + + + + + + procurement.order.form + procurement.order + + + + + + + + + + procurement.order.form.stock.inherit + procurement.order + + + + [('usage', '!=', 'view')] + + + + + + + diff --git a/rma/views/product_view.xml b/rma/views/product_view.xml new file mode 100644 index 00000000..74a9fd35 --- /dev/null +++ b/rma/views/product_view.xml @@ -0,0 +1,30 @@ + + + + + + product.category.form + product.category + + + + + + + + + + product.template.stock.property.form.inherit + product.template + + + + + + + + + + + + diff --git a/rma/views/res_company_view.xml b/rma/views/res_company_view.xml new file mode 100644 index 00000000..a2f01d20 --- /dev/null +++ b/rma/views/res_company_view.xml @@ -0,0 +1,17 @@ + + + + + base_phone.company.form + res.company + + + + + + + + + + + \ No newline at end of file diff --git a/rma/views/rma_operation_view.xml b/rma/views/rma_operation_view.xml new file mode 100644 index 00000000..1fc26e7a --- /dev/null +++ b/rma/views/rma_operation_view.xml @@ -0,0 +1,69 @@ + + + + + rma.operation.tree + rma.operation + + + + + + + + + + + + rma.operation.form + rma.operation + +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Operations + rma.operation + form + tree,form + + + + + +
+
diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml new file mode 100644 index 00000000..649552f4 --- /dev/null +++ b/rma/views/rma_order_line_view.xml @@ -0,0 +1,387 @@ + + + + + rma.order.line.tree + rma.order.line + + + + + + + + + + + + + + + + + + + + rma.order.line.supplier.tree + rma.order.line + + + + + + + + + + + + + + + + + + + rma.order.line.supplier.form + rma.order.line + +
+ +
+
+ + + +
+
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rma.order.line.form + rma.order.line + +
+ +
+
+ + + + +
+
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rma.order.line.select + rma.order.line + + + + + + + + + + + + + + + + + + + + + + + Customer RMA Lines + rma.order.line + [('state','in', ['approved', 'done']), + ('type','=', 'customer'), + ('customer_to_supplier','=', False) + ] + {"search_default_assigned_to":uid} + form + tree,form + + + + + Supplier RMA Lines + rma.order.line + [('state','in', ['approved', 'done']), + ('type','=', 'supplier')] + {"search_default_assigned_to":uid, "supplier":1} + form + tree,form + + + + + + tree + + + + + + form + + + + + + + + + + diff --git a/rma/views/rma_order_view.xml b/rma/views/rma_order_view.xml new file mode 100644 index 00000000..b5a89702 --- /dev/null +++ b/rma/views/rma_order_view.xml @@ -0,0 +1,365 @@ + + + + + + rma.order.tree + rma.order + + + + + + + + + + + + + + + + rma.order.supplier.tree + rma.order + + + + + + + + + + + + + + + + rma.order.form + rma.order + +
+ +
+
+ +
+ + + + +
+
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+ + + rma.order.supplier.form + rma.order + +
+ +
+
+ +
+ + + +
+
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+ + + rma.order.select + rma.order + + + + + + + + + + + + + + + + + + + Customer RMA + rma.order + form + [('type','=', 'customer')] + {"search_default_assigned_to":uid, + 'customer':1} + tree,form + + + + + Supplier RMA + rma.order + form + [('type','=', 'supplier')] + {"search_default_assigned_to":uid, + 'supplier':1} + tree,form + + + + + + tree + + + + + + form + + + + + + + + + + + + + + +
+
diff --git a/rma/views/rma_rule_view.xml b/rma/views/rma_rule_view.xml new file mode 100644 index 00000000..788ffb6c --- /dev/null +++ b/rma/views/rma_rule_view.xml @@ -0,0 +1,51 @@ + + + + + rma.rule.tree + rma.rule + + + + + + + + + + rma.rule.form + rma.rule + +
+ + + + + + + + + +
+
+
+ + + Rules + rma.rule + form + tree,form + + + + + +
+
diff --git a/rma/views/stock_view.xml b/rma/views/stock_view.xml new file mode 100644 index 00000000..a2f06c74 --- /dev/null +++ b/rma/views/stock_view.xml @@ -0,0 +1,55 @@ + + + + + + rma.move.form + stock.move + + + + + + + + + + + + stock.move.form + stock.move + + + + + + + + + + + + stock.location.route.form + + stock.location.route + + + + + + + + + procurement.order.form.stock.inherit + procurement.order + + + + [('usage', '!=', 'view')] + + + + + + diff --git a/rma/views/stock_warehouse.xml b/rma/views/stock_warehouse.xml new file mode 100644 index 00000000..a626781f --- /dev/null +++ b/rma/views/stock_warehouse.xml @@ -0,0 +1,20 @@ + + + + view_warehouse_form + stock.warehouse + + + + + + + + + + + + + + + diff --git a/rma/wizards/__init__.py b/rma/wizards/__init__.py new file mode 100644 index 00000000..64d335a4 --- /dev/null +++ b/rma/wizards/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from . import rma_add_stock_move +from . import rma_make_picking +from . import stock_config_settings +from . import rma_order_line_make_supplier_rma diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py new file mode 100644 index 00000000..e5007085 --- /dev/null +++ b/rma/wizards/rma_add_stock_move.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import models, fields, exceptions, api, _ +from openerp.exceptions import ValidationError + + +class RmaAddStockMove(models.TransientModel): + _name = 'rma_add_stock_move' + _description = 'Wizard to add rma lines from pickings' + + @api.model + def default_get(self, fields): + res = super(RmaAddStockMove, self).default_get(fields) + rma_obj = self.env['rma.order'] + rma_id = self.env.context['active_ids'] or [] + active_model = self.env.context['active_model'] + if not rma_id: + return res + assert active_model == 'rma.order', 'Bad context propagation' + + rma = rma_obj.browse(rma_id) + res['rma_id'] = rma.id + res['partner_id'] = rma.partner_id.id + res['picking_id'] = False + res['move_ids'] = False + return res + + rma_id = fields.Many2one('rma.order', + string='RMA Order', + readonly=True, + ondelete='cascade') + + partner_id = fields.Many2one(comodel_name='res.partner', string='Partner', + readonly=True) + + move_ids = fields.Many2many('stock.move', + string='Stock Moves', + domain="[('state', '=', 'done')]") + + def _prepare_rma_line_from_stock_move(self, sm, lot=False): + operation = sm.product_id.rma_operation_id or \ + sm.product_id.categ_id.rma_operation_id + data = { + 'reference_move_id': sm.id, + 'product_id': sm.product_id.id, + 'lot_id': lot and lot.id or False, + 'name': sm.product_id.name_template, + 'origin': sm.picking_id.name, + 'uom_id': sm.product_uom.id, + 'operation_id': operation.id, + 'product_qty': sm.product_uom_qty, + 'delivery_address_id': sm.picking_id.partner_id.id, + 'rma_id': self.rma_id.id + } + if not operation: + operation = self.env['rma.operation'].search( + [('type', '=', self.rma_id.type)], limit=1) + if not operation: + raise ValidationError("Please define an operation first") + if not operation.in_route_id or not operation.out_route_id: + route = self.env['stock.location.route'].search( + [('rma_selectable', '=', True)], limit=1) + if not route: + raise ValidationError("Please define an rma route") + data.update( + {'in_route_id': operation.in_route_id.id, + 'out_route_id': operation.out_route_id.id, + 'receipt_policy': operation.receipt_policy, + 'operation_id': operation.id, + 'refund_policy': operation.refund_policy, + 'delivery_policy': operation.delivery_policy + }) + if operation.in_warehouse_id: + data['in_warehouse_id'] = operation.in_warehouse_id.id + if operation.out_warehouse_id: + data['out_warehouse_id'] = operation.out_warehouse_id.id + if operation.location_id: + data['location_id'] = operation.location_id.id + return data + + @api.model + def _get_existing_stock_moves(self): + existing_move_lines = [] + for rma_line in self.rma_id.rma_line_ids: + existing_move_lines.append(rma_line.reference_move_id) + return existing_move_lines + + @api.multi + def add_lines(self): + rma_line_obj = self.env['rma.order.line'] + existing_stock_moves = self._get_existing_stock_moves() + for sm in self.move_ids: + if sm not in existing_stock_moves: + if sm.lot_ids: + for lot in sm.lot_ids: + data = self._prepare_rma_line_from_stock_move(sm, + lot=lot) + rma_line_obj.with_context( + default_rma_id=self.rma_id.id).create(data) + else: + data = self._prepare_rma_line_from_stock_move(sm, lot=False) + rma_line_obj.with_context( + default_rma_id=self.rma_id.id).create(data) + return {'type': 'ir.actions.act_window_close'} diff --git a/rma/wizards/rma_add_stock_move_view.xml b/rma/wizards/rma_add_stock_move_view.xml new file mode 100644 index 00000000..92df5654 --- /dev/null +++ b/rma/wizards/rma_add_stock_move_view.xml @@ -0,0 +1,128 @@ + + + + + rma.add.stock.move.customer + rma_add_stock_move + +
+ + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + Add from Stock Move + ir.actions.act_window + rma_add_stock_move + rma.order + form + form + new + + + + + + + rma.order.line.form + rma.order + + + + + + + + rma.add.stock.move.supplier + rma_add_stock_move + +
+ + + + + +
+
+ +
+
+ + + Add from Stock Move + ir.actions.act_window + rma_add_stock_move + rma.order + form + form + new + + + + + + rma.order.line.supplier.form + rma.order + + + + + + +
diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py new file mode 100644 index 00000000..80f2f5ba --- /dev/null +++ b/rma/wizards/rma_make_picking.py @@ -0,0 +1,233 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +import time +from openerp import models, fields, exceptions, api, _ +from openerp.exceptions import ValidationError +from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT_FORMAT +import openerp.addons.decimal_precision as dp + + +class RmaMakePicking(models.TransientModel): + _name = 'rma_make_picking.wizard' + _description = 'Wizard to create pickings from rma lines' + + @api.returns('rma.order.line') + def _prepare_item(self, line): + values = {'product_id': line.product_id.id, + 'product_qty': line.product_qty, + 'uom_id': line.uom_id.id, + 'qty_to_receive': line.qty_to_receive, + 'qty_to_deliver': line.qty_to_deliver, + 'line_id': line.id, + 'rma_id': line.rma_id.id, + 'wiz_id': self.env.context['active_id'], + } + return values + + @api.model + def default_get(self, fields): + """Default values for wizard, if there is more than one supplier on + lines the supplier field is empty otherwise is the unique line + supplier. + """ + res = super(RmaMakePicking, self).default_get(fields) + rma_line_obj = self.env['rma.order.line'] + rma_line_ids = self.env.context['active_ids'] or [] + active_model = self.env.context['active_model'] + + if not rma_line_ids: + return res + assert active_model == 'rma.order.line', \ + 'Bad context propagation' + + items = [] + lines = rma_line_obj.browse(rma_line_ids) + if len(lines.mapped('partner_id')) > 1: + raise exceptions.Warning( + _('Only RMA lines from the same partner can be processed at ' + 'the same time')) + for line in lines: + items.append([0, 0, self._prepare_item(line)]) + res['item_ids'] = items + return res + + item_ids = fields.One2many( + 'rma_make_picking.wizard.item', + 'wiz_id', string='Items') + + def find_procurement_group(self, item): + return self.env['procurement.group'].search([('rma_id', '=', + item.line_id.rma_id.id)]) + + def _get_procurement_group_data(self, item): + group_data = { + 'name': item.line_id.rma_id.name, + 'rma_id': item.line_id.rma_id.id, + } + return group_data + + @api.model + def _get_address(self, item): + if item.line_id.delivery_address_id: + delivery_address = item.line_id.delivery_address_id or \ + item.line_id.partner_id + elif item.line_id.customer_to_supplier: + delivery_address = item.line_id.supplier_address_id + else: + raise exceptions.Warning('Unknown delivery address') + return delivery_address + + def _get_address_location(self, delivery_address_id, type): + if type == 'supplier': + return delivery_address_id.property_stock_supplier + elif type == 'customer': + return delivery_address_id.property_stock_customer + + @api.model + def _get_procurement_data(self, item, group, qty, picking_type): + line = item.line_id + delivery_address_id = self._get_address(item) + if picking_type == 'incoming': + if line.customer_to_supplier: + location = self._get_address_location( + delivery_address_id, 'supplier') + else: + location = line.location_id + warehouse = line.in_warehouse_id + route = line.in_route_id + else: + location = self._get_address_location(delivery_address_id, + line.rma_id.type) + warehouse = line.out_warehouse_id + route = line.out_route_id + if not route: + raise exceptions.Warning("No route specified") + if not warehouse: + raise exceptions.Warning("No warehouse specified") + procurement_data = { + 'name': line.rma_id.name, + 'group_id': group.id, + 'origin': line.rma_id.name, + 'warehouse_id': warehouse.id, + 'date_planned': time.strftime(DT_FORMAT), + 'product_id': item.product_id.id, + 'product_qty': qty, + 'partner_dest_id': delivery_address_id.id, + 'product_uom': line.product_id.product_tmpl_id.uom_id.id, + 'location_id': location.id, + 'rma_line_id': line.id, + 'route_ids': [(4, route.id)] + } + return procurement_data + + @api.model + def _create_procurement(self, item, picking_type): + group = self.find_procurement_group(item) + if not group: + procurement_group = self._get_procurement_group_data(item) + group = self.env['procurement.group'].create(procurement_group) + if picking_type == 'incoming': + qty = item.qty_to_receive + else: + qty = item.qty_to_deliver + procurement_data = self._get_procurement_data( + item, group, qty, picking_type) + # create picking + procurement = self.env['procurement.order'].create(procurement_data) + procurement.run() + return procurement.id + + @api.multi + def _create_picking(self): + """Method called when the user clicks on create picking""" + picking_type = self.env.context.get('picking_type') + procurement_list = [] + for item in self.item_ids: + line = item.line_id + if line.state != 'approved': + raise exceptions.Warning( + _('RMA %s is not approved') % + line.rma_id.name) + if line.receipt_policy == 'no' and picking_type == \ + 'incoming': + raise exceptions.Warning( + _('No shipments needed for this operation')) + if line.delivery_policy == 'no' and picking_type == \ + 'outgoing': + raise exceptions.Warning( + _('No deliveries needed for this operation')) + procurement = self._create_procurement(item, picking_type) + procurement_list.append(procurement) + procurements = self.env['procurement.order'].browse(procurement_list) + return procurements + + @api.model + def _get_action(self, pickings, procurements): + if pickings: + action = procurements.do_view_pickings() + else: + action = self.env.ref( + 'procurement.procurement_order_action_exceptions') + action = action.read()[0] + # choose the view_mode accordingly + procurement_ids = procurements.ids + if len(procurement_ids) != 1: + action['domain'] = "[('id', 'in', " + \ + str(procurement_ids) + ")]" + elif len(procurements) == 1: + res = self.env.ref('procurement.procurement_form_view', + False) + action['views'] = [(res and res.id or False, 'form')] + action['res_id'] = procurement_ids[0] + return action + + @api.multi + def action_create_picking(self): + procurements = self._create_picking() + groups = [] + for proc in procurements: + if proc.group_id: + groups.append(proc.group_id.id) + if len(groups): + pickings =self.env['stock.picking'].search( + [('group_id', 'in', groups)]) + + action = self._get_action(pickings, procurements) + return action + + @api.multi + def action_cancel(self): + return {'type': 'ir.actions.act_window_close'} + + +class RmaMakePickingItem(models.TransientModel): + _name = "rma_make_picking.wizard.item" + _description = "Items to receive" + + wiz_id = fields.Many2one( + 'rma_make_picking.wizard', + string='Wizard', required=True) + line_id = fields.Many2one('rma.order.line', + string='RMA order Line', + readonly=True, + ondelete='cascade') + rma_id = fields.Many2one('rma.order', + related='line_id.rma_id', + string='RMA', + readonly=True) + product_id = fields.Many2one('product.product', string='Product', + readonly=True) + product_qty = fields.Float( + related='line_id.product_qty', + string='Quantity Ordered', copy=False, + digits=dp.get_precision('Product Unit of Measure'), readonly=True) + qty_to_receive = fields.Float( + string='Quantity to Receive', + digits=dp.get_precision('Product Unit of Measure')) + qty_to_deliver = fields.Float( + string='Quantity To Deliver', + digits=dp.get_precision('Product Unit of Measure')) + uom_id = fields.Many2one('product.uom', string='Unit of Measure', + readonly=True) diff --git a/rma/wizards/rma_make_picking_view.xml b/rma/wizards/rma_make_picking_view.xml new file mode 100644 index 00000000..da05ac71 --- /dev/null +++ b/rma/wizards/rma_make_picking_view.xml @@ -0,0 +1,139 @@ + + + + + rma_picking + rma_make_picking.wizard + +
+ + + + + + + + + + +
+
+ +
+
+ + + Create Delivery + rma_make_picking.wizard + +
+ + + + + + + + + + +
+
+ +
+
+ + + Create Incoming Shipment + ir.actions.act_window + rma_make_picking.wizard + rma.order.line + form + form + new + + + {'picking_type': 'incoming'} + + + + Create Delivery + ir.actions.act_window + rma_make_picking.wizard + rma.order.line + form + form + new + + + {'picking_type': 'outgoing'} + + + + rma.order.line.form + rma.order.line + + +
+
+
+
+ + + rma.order.line.supplier.form + rma.order.line + + +
+
+
+
+
+
+ + + + Create Incoming Shipment + client_action_multi + + action + rma.order.line + + + + + Create Delivery + client_action_multi + + action + rma.order.line + + +
diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py new file mode 100644 index 00000000..79137bd5 --- /dev/null +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +import openerp.addons.decimal_precision as dp +from openerp import _, api, exceptions, fields, models + + +class RmaLineMakeSupplierRma(models.TransientModel): + _name = "rma.order.line.make.supplier.rma" + _description = "RMA Line Make Supplier RMA" + + partner_id = fields.Many2one('res.partner', string='Supplier', + required=False, + domain=[('supplier', '=', True)]) + item_ids = fields.One2many( + 'rma.order.line.make.supplier.rma.item', + 'wiz_id', string='Items') + supplier_rma_id = fields.Many2one('rma.order', + string='Supplier RMA Order', + required=False, + domain=[('state', '=', 'draft')]) + + @api.model + def _prepare_item(self, line): + return { + 'line_id': line.id, + 'product_id': line.product_id.id, + 'name': line.name, + 'product_qty': line.qty_to_supplier_rma, + 'uom_id': line.uom_id.id, + } + + @api.model + def default_get(self, fields): + res = super(RmaLineMakeSupplierRma, self).default_get( + fields) + rma_line_obj = self.env['rma.order.line'] + rma_line_ids = self.env.context['active_ids'] or [] + active_model = self.env.context['active_model'] + + if not rma_line_ids: + return res + assert active_model == 'rma.order.line', 'Bad context propagation' + + items = [] + lines = rma_line_obj.browse(rma_line_ids) + for line in lines: + items.append([0, 0, self._prepare_item(line)]) + suppliers = lines.mapped('supplier_address_id') + if len(suppliers) == 1: + res['partner_id'] = suppliers.id + else: + raise exceptions.Warning( + _('Only RMA lines from the same supplier address can be ' + 'processed at the same time')) + res['item_ids'] = items + return res + + @api.model + def _prepare_supplier_rma(self, company): + if not self.partner_id: + raise exceptions.Warning( + _('Enter a supplier.')) + return { + 'partner_id': self.partner_id.id, + 'delivery_address_id': self.partner_id.id, + 'type': 'supplier', + 'company_id': company.id, + } + + @api.model + def _prepare_supplier_rma_line(self, rma, item): + operation = self.env['rma.operation'].search( + [('type', '=', 'supplier')], limit=1) + return { + 'origin': item.line_id.rma_id.name, + 'delivery_address_id': + item.line_id.delivery_address_id.id, + 'product_id': item.line_id.product_id.id, + 'customer_rma_id': item.line_id.id, + 'product_qty': item.product_qty, + 'rma_id': rma.id, + 'operation_id': operation.id, + 'receipt_policy': operation.receipt_policy, + 'delivery_policy': operation.delivery_policy, + 'in_warehouse_id': operation.in_warehouse_id.id, + 'out_warehouse_id': operation.out_warehouse_id.id, + 'location_id': operation.location_id.id, + 'supplier_to_customer': operation.supplier_to_customer, + 'in_route_id': operation.in_route_id.id, + 'out_route_id': operation.out_route_id.id, + } + + @api.multi + def make_supplier_rma(self): + res = [] + rma_obj = self.env['rma.order'] + rma_line_obj = self.env['rma.order.line'] + rma = False + + for item in self.item_ids: + line = item.line_id + if item.product_qty <= 0.0: + raise exceptions.Warning( + _('Enter a positive quantity.')) + + if self.supplier_rma_id: + rma = self.supplier_rma_id + if not rma: + rma_data = self._prepare_supplier_rma(line.company_id) + rma = rma_obj.create(rma_data) + + rma_line_data = self._prepare_supplier_rma_line(rma, item) + rma_line_obj.create(rma_line_data) + res.append(rma.id) + + return { + 'domain': "[('id','in', ["+','.join(map(str, res))+"])]", + 'name': _('Supplier RMA'), + 'view_type': 'form', + 'view_mode': 'tree,form', + 'res_model': 'rma.order', + 'view_id': False, + 'context': {'supplier': 1}, + 'type': 'ir.actions.act_window' + } + + +class RmaLineMakeRmaOrderItem(models.TransientModel): + _name = "rma.order.line.make.supplier.rma.item" + _description = "RMA Line Make Supplier RMA Item" + + wiz_id = fields.Many2one( + 'rma.order.line.make.supplier.rma', + string='Wizard', required=True, ondelete='cascade', + readonly=True) + line_id = fields.Many2one('rma.order.line', + string='RMA Line', + required=True) + rma_id = fields.Many2one('rma.order', related='line_id.rma_id', + string='RMA Order', readonly=True) + product_id = fields.Many2one('product.product', + related='line_id.product_id', readony=True) + name = fields.Char(related='line_id.name', readonly=True) + uom_id = fields.Many2one('product.uom', string='UoM', readonly=True) + product_qty = fields.Float(string='Quantity to sell', + digits=dp.get_precision('Product UoS')) diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml new file mode 100644 index 00000000..85609494 --- /dev/null +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -0,0 +1,89 @@ + + + + + + RMA Line Make Supplier RMA + rma.order.line.make.supplier.rma + form + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + diff --git a/rma/wizards/stock_config_settings.py b/rma/wizards/stock_config_settings.py new file mode 100644 index 00000000..ab19c4c4 --- /dev/null +++ b/rma/wizards/stock_config_settings.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import models, fields + + +class StockConfigSettings(models.Model): + _inherit = 'stock.config.settings' + + group_rma_delivery_address = fields.Selection([ + (0, "Invoicing and shipping addresses are always the same " + "(Example: services companies)"), + (1, 'Display 3 fields on rma: partner, invoice address, delivery ' + 'address') + ], "Addresses", + implied_group='rma.group_rma_delivery_invoice_address') diff --git a/rma/wizards/stock_config_settings.xml b/rma/wizards/stock_config_settings.xml new file mode 100644 index 00000000..2bcb851b --- /dev/null +++ b/rma/wizards/stock_config_settings.xml @@ -0,0 +1,17 @@ + + + + + stock.config.settings.rma + stock.config.settings + + + + + + + + + + + From b0e497af126c17768556d9740ed61ddd4923459c Mon Sep 17 00:00:00 2001 From: lreficent Date: Wed, 2 Aug 2017 14:04:18 +0200 Subject: [PATCH 02/81] [9.0] rma: remove rma.rule and add that setting to product.category --- rma/README.rst | 36 +++++++++++++++++------- rma/__openerp__.py | 5 +--- rma/data/rma_operation.xml | 6 ---- rma/models/__init__.py | 3 +- rma/models/procurement.py | 2 +- rma/models/product.py | 9 ++---- rma/models/product_category.py | 20 +++++++++++++ rma/models/res_company.py | 11 -------- rma/models/rma_order.py | 21 ++++---------- rma/models/rma_rule.py | 16 ----------- rma/views/product_view.xml | 2 ++ rma/views/res_company_view.xml | 17 ------------ rma/views/rma_rule_view.xml | 51 ---------------------------------- 13 files changed, 59 insertions(+), 140 deletions(-) create mode 100644 rma/models/product_category.py delete mode 100644 rma/models/res_company.py delete mode 100644 rma/models/rma_rule.py delete mode 100644 rma/views/res_company_view.xml delete mode 100644 rma/views/rma_rule_view.xml diff --git a/rma/README.rst b/rma/README.rst index 68a32563..fd8a338d 100644 --- a/rma/README.rst +++ b/rma/README.rst @@ -1,10 +1,11 @@ .. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg :alt: License LGPL-3 -RMA -=== +====================================== +RMA (Return Merchandise Authorization) +====================================== -A return merchandise authorization (RMA), is a part of the process of +A Return Merchandise Authorization (RMA), is a part of the process of returning a product in order to receive a refund, replacement, or repair during the product's warranty period. @@ -29,6 +30,7 @@ Configuration Security -------- + Go to Settings > Users and assign the appropiate permissions to users. Different security groups grant distinct levels of access to the RMA features. @@ -38,11 +40,25 @@ Different security groups grant distinct levels of access to the RMA features. * Users in group "RMA Manager" can access to, create, approve and process RMA's associated to both customers and suppliers. +RMA Approval Policy +------------------- +There are two RMA approval policies in product catogories: +* One step: Always auto-approve RMAs that only contain products within + categories with this policy. +* Two steps: A RMA order containing a product within a category with this + policy will request the RMA manager approval. + +In order to change the approval policy of a product category follow the next +steps: + +#. Go to *Inventory > Configuration > Products > Product Categories*. +#. Select one and change the field *RMA Approval Policy* to your convenience. + +Other Settings +-------------- -#. Go to Settings > Users and assign the appropiate permissions to users. - Users assigned to the group 'RMA #. Go to Inventory > Settings > Return Merchandising Authorization and select the option "Display 3 fields on rma: partner, invoice address, delivery address" if needed. @@ -51,16 +67,17 @@ Different security groups grant distinct levels of access to the RMA features. and suppliers RMA picking type. In case the warehouse is configured to use routes, you need to create at least one route per rma type with at least two push rules (one for inbound another for outbound) it's very - important to select the typeof operation supplier if we are moving in the + important to select the type of operation supplier if we are moving in the company and customer if we are moving out of the company. Usage ===== -RMA are accessible though Inventory menu. There's four menus, divided by type -. Users can access to the list of RMA or RMA lines. +RMA are accessible though Inventory menu. There's four menus, divided by type. +Users can access to the list of RMA or RMA lines. Create an RMA: + #. Select a partner. Enter RMA lines associated to an existing picking, or manually. #. Request approval and approve. @@ -87,10 +104,9 @@ Contributors * Jordi Ballester Alomar * Aaron Henriquez - +* Lois Rilo Maintainer ---------- This module is maintained by Eficent. - diff --git a/rma/__openerp__.py b/rma/__openerp__.py index 9fc1d7f8..80bc8f3f 100644 --- a/rma/__openerp__.py +++ b/rma/__openerp__.py @@ -3,7 +3,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) { - 'name': 'rma', + 'name': 'RMA (Return Merchandise Authorization)', 'version': '9.0.1.0.0', 'license': 'LGPL-3', 'category': 'RMA', @@ -18,19 +18,16 @@ ], 'data': ['security/rma.xml', 'security/ir.model.access.csv', - 'data/rma_sequence.xml', 'data/stock_data.xml', 'data/rma_operation.xml', 'views/rma_order_view.xml', 'views/rma_operation_view.xml', - 'views/rma_rule_view.xml', 'views/rma_order_line_view.xml', 'views/stock_view.xml', 'views/stock_warehouse.xml', 'views/product_view.xml', 'views/procurement_view.xml', - 'views/res_company_view.xml', 'wizards/rma_make_picking_view.xml', 'wizards/rma_add_stock_move_view.xml', 'wizards/stock_config_settings.xml', diff --git a/rma/data/rma_operation.xml b/rma/data/rma_operation.xml index ad39aff4..fea67f4f 100644 --- a/rma/data/rma_operation.xml +++ b/rma/data/rma_operation.xml @@ -72,10 +72,4 @@ - - Always - alw - always - - diff --git a/rma/models/__init__.py b/rma/models/__init__.py index ad034891..348fb2bf 100644 --- a/rma/models/__init__.py +++ b/rma/models/__init__.py @@ -5,9 +5,8 @@ from . import rma_order from . import rma_order_line from . import rma_operation -from . import rma_rule from . import stock from . import stock_warehouse from . import product +from . import product_category from . import procurement -from . import res_company diff --git a/rma/models/procurement.py b/rma/models/procurement.py index a55e8910..6838c5d1 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -16,7 +16,7 @@ class ProcurementOrder(models.Model): if procurement.rma_line_id: line = procurement.rma_line_id res['rma_line_id'] = line.id - if line.delivery_address_id and line.delivery_address_id.id: + if line.delivery_address_id: res['partner_id'] = line.delivery_address_id.id elif line.invoice_line_id.invoice_id.partner_id: res['partner_id'] = line.invoice_id.partner_id.id diff --git a/rma/models/product.py b/rma/models/product.py index 2a992b25..d7f878bc 100644 --- a/rma/models/product.py +++ b/rma/models/product.py @@ -5,15 +5,10 @@ from openerp import fields, models -class ProductCategory(models.Model): - _inherit = 'product.category' - - rma_operation_id = fields.Many2one( - comodel_name="rma.operation", string="RMA Operation") - - class ProductTemplate(models.Model): _inherit = 'product.template' rma_operation_id = fields.Many2one( comodel_name="rma.operation", string="RMA Operation") + rma_approval_policy = fields.Selection( + related="categ_id.rma_approval_policy", readonly=True) diff --git a/rma/models/product_category.py b/rma/models/product_category.py new file mode 100644 index 00000000..decfce28 --- /dev/null +++ b/rma/models/product_category.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp import fields, models + + +class ProductCategory(models.Model): + _inherit = "product.category" + + rma_approval_policy = fields.Selection( + selection=[('one_step', 'One step'), ('two_step', 'Two steps')], + string="RMA Approval Policy", required=True, default='one_step', + help="Options: \n " + "* One step: Always auto-approve RMAs that only contain " + "products within categories with this policy.\n" + "* Two steps: A RMA containing a product within a category with " + "this policy will request the RMA manager approval.") + rma_operation_id = fields.Many2one( + comodel_name="rma.operation", string="RMA Operation") diff --git a/rma/models/res_company.py b/rma/models/res_company.py deleted file mode 100644 index efc8f43c..00000000 --- a/rma/models/res_company.py +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2017 Eficent Business and IT Consulting Services S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - -from openerp import models, fields - - -class ResCompany(models.Model): - _inherit = 'res.company' - - rma_rule_id = fields.Many2one('rma.rule', 'Default RMA Approval Policy') diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index 9f99a636..e307b35c 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -14,12 +14,6 @@ class RmaOrder(models.Model): _name = "rma.order" _inherit = ['mail.thread'] - @api.model - def _compute_rule_id(self): - if self.company_id and self.company_id.id: - if self.company_id.rma_rule_id and self.company_id.rma_rule_id.id: - self.rule_id = self.company_id.rma_rule_id - @api.model def _get_default_type(self): if 'supplier' in self.env.context: @@ -79,8 +73,6 @@ class RmaOrder(models.Model): requested_by = fields.Many2one('res.users', 'Requested by', track_visibility='onchange', default=lambda self: self.env.user) - rule_id = fields.Many2one('rma.rule', string='Approval Criteria', - compute=_compute_rule_id) rma_line_ids = fields.One2many('rma.order.line', 'rma_id', string='RMA lines') in_shipment_count = fields.Integer(compute=_compute_in_shipment_count, @@ -163,12 +155,12 @@ class RmaOrder(models.Model): @api.multi def action_rma_to_approve(self): + self.write({'state': 'to_approve'}) for rec in self: - rec.state = 'to_approve' - if rec.rule_id and rec.rule_id.id: - if rec.rule_id.approval_policy == 'always': - rec.assigned_to = self.env.uid - rec.action_rma_approve() + pols = rec.mapped('rma_line_ids.product_id.rma_approval_policy') + if not any(x != 'one_step' for x in pols): + rec.write({'assigned_to': self.env.uid}) + rec.action_rma_approve() return True @api.multi @@ -180,8 +172,7 @@ class RmaOrder(models.Model): @api.multi def action_rma_approve(self): # pass the supplier address in case this is a customer RMA - for rec in self: - rec.state = 'approved' + self.write({'state': 'approved'}) return True @api.multi diff --git a/rma/models/rma_rule.py b/rma/models/rma_rule.py deleted file mode 100644 index ec3c9255..00000000 --- a/rma/models/rma_rule.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2017 Eficent Business and IT Consulting Services S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - -from openerp import _, api, fields, models - - -class RmaRule(models.Model): - _name = 'rma.rule' - _description = 'RMA Approval Conditions' - - name = fields.Char('Description', required=True) - code = fields.Char('Code', required=True) - approval_policy = fields.Selection([ - ('always', 'Always')], string="Approval Policy", - required=True, default='always') diff --git a/rma/views/product_view.xml b/rma/views/product_view.xml index 74a9fd35..c14144a6 100644 --- a/rma/views/product_view.xml +++ b/rma/views/product_view.xml @@ -8,6 +8,7 @@ + @@ -20,6 +21,7 @@ + diff --git a/rma/views/res_company_view.xml b/rma/views/res_company_view.xml deleted file mode 100644 index a2f01d20..00000000 --- a/rma/views/res_company_view.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - base_phone.company.form - res.company - - - - - - - - - - - \ No newline at end of file diff --git a/rma/views/rma_rule_view.xml b/rma/views/rma_rule_view.xml deleted file mode 100644 index 788ffb6c..00000000 --- a/rma/views/rma_rule_view.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - rma.rule.tree - rma.rule - - - - - - - - - - rma.rule.form - rma.rule - -
- - - - - - - - - -
-
-
- - - Rules - rma.rule - form - tree,form - - - - - -
-
From 539be323ef449515d0d8860ef2a224f0fca446c9 Mon Sep 17 00:00:00 2001 From: lreficent Date: Wed, 2 Aug 2017 17:05:58 +0200 Subject: [PATCH 03/81] [9.0][FIX] rma: * fix assignment of moves. * default qty in rma lines. * remove account dependency. * test and flake8 fixes. --- rma/__openerp__.py | 6 +- rma/models/procurement.py | 4 +- rma/models/rma_operation.py | 20 +-- rma/models/rma_order.py | 32 ++--- rma/models/rma_order_line.py | 20 +-- rma/models/stock.py | 21 +-- rma/models/stock_warehouse.py | 3 +- rma/tests/test_rma.py | 122 ++++++++---------- rma/views/rma_order_line_view.xml | 8 +- rma/wizards/rma_add_stock_move.py | 5 +- rma/wizards/rma_make_picking.py | 23 ++-- .../rma_order_line_make_supplier_rma.py | 2 +- 12 files changed, 121 insertions(+), 145 deletions(-) diff --git a/rma/__openerp__.py b/rma/__openerp__.py index 80bc8f3f..c4e25162 100644 --- a/rma/__openerp__.py +++ b/rma/__openerp__.py @@ -11,10 +11,8 @@ 'in odoo', 'author': "Eficent", 'website': 'http://www.github.com/OCA/rma', - 'depends': ['account', 'stock', 'mail', - 'procurement'], - 'demo': [ - 'demo/stock_demo.xml', + 'depends': ['stock', 'mail', 'procurement'], + 'demo': ['demo/stock_demo.xml', ], 'data': ['security/rma.xml', 'security/ir.model.access.csv', diff --git a/rma/models/procurement.py b/rma/models/procurement.py index 6838c5d1..c8cd39db 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -18,8 +18,8 @@ class ProcurementOrder(models.Model): res['rma_line_id'] = line.id if line.delivery_address_id: res['partner_id'] = line.delivery_address_id.id - elif line.invoice_line_id.invoice_id.partner_id: - res['partner_id'] = line.invoice_id.partner_id.id + else: + res['partner_id'] = line.rma_id.partner_id.id return res diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py index 87d271e0..5d3b230d 100644 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import _, api, fields, models +from openerp import api, fields, models class RmaOperation(models.Model): @@ -11,9 +11,9 @@ class RmaOperation(models.Model): @api.model def _default_warehouse_id(self): - company = self.env.user.company_id.id + company_id = self.env.user.company_id.id warehouse = self.env['stock.warehouse'].search( - [('company_id', '=', company)], limit=1) + [('company_id', '=', company_id)], limit=1) return warehouse @api.model @@ -44,16 +44,16 @@ class RmaOperation(models.Model): out_route_id = fields.Many2one( 'stock.location.route', string='Outbound Route', domain=[('rma_selectable', '=', True)]) - customer_to_supplier= fields.Boolean( + customer_to_supplier = fields.Boolean( 'The customer will send to the supplier', default=False) supplier_to_customer = fields.Boolean( 'The supplier will send to the customer', default=False) - in_warehouse_id = fields.Many2one('stock.warehouse', - string='Inbound Warehouse', - default=_default_warehouse_id) - out_warehouse_id = fields.Many2one('stock.warehouse', - string='Outbound Warehouse', - default=_default_warehouse_id) + in_warehouse_id = fields.Many2one( + comodel_name='stock.warehouse', string='Inbound Warehouse', + default=_default_warehouse_id) + out_warehouse_id = fields.Many2one( + comodel_name='stock.warehouse', string='Outbound Warehouse', + default=_default_warehouse_id) location_id = fields.Many2one( 'stock.location', 'Send To This Company Location') type = fields.Selection([ diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index e307b35c..28a9ff8d 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -2,12 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import _, api, fields, models -from openerp.addons import decimal_precision as dp -from openerp.exceptions import UserError -from dateutil.relativedelta import relativedelta -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT -from datetime import datetime +from openerp import api, fields, models class RmaOrder(models.Model): @@ -18,8 +13,7 @@ class RmaOrder(models.Model): def _get_default_type(self): if 'supplier' in self.env.context: return "supplier" - else: - return "customer" + return "customer" @api.multi def _compute_in_shipment_count(self): @@ -47,23 +41,21 @@ class RmaOrder(models.Model): self.ensure_one() self.line_count = len(self._get_valid_lines()) - name = fields.Char(string='Order Number', index=True, - readonly=True, - states={'progress': [('readonly', False)]}, - copy=False) + name = fields.Char( + string='Order Number', index=True, readonly=True, + states={'progress': [('readonly', False)]}, copy=False) type = fields.Selection( [('customer', 'Customer'), ('supplier', 'Supplier')], string="Type", required=True, default=_get_default_type, readonly=True) - reference = fields.Char(string='Reference', + reference = fields.Char(string='Partner Reference', help="The partner reference of this RMA order.") - comment = fields.Text('Additional Information', readonly=True, states={ 'draft': [('readonly', False)]}) state = fields.Selection([('draft', 'Draft'), ('to_approve', 'To Approve'), ('approved', 'Approved'), ('done', 'Done')], string='State', index=True, - default='draft') + default='draft') date_rma = fields.Datetime(string='Order Date', index=True, copy=False) partner_id = fields.Many2one('res.partner', string='Partner', required=True, readonly=True, @@ -165,8 +157,7 @@ class RmaOrder(models.Model): @api.multi def action_rma_draft(self): - for rec in self: - rec.state = 'draft' + self.write({'state': 'draft'}) return True @api.multi @@ -177,12 +168,13 @@ class RmaOrder(models.Model): @api.multi def action_rma_done(self): - for rec in self: - rec.state = 'done' - return True + self.write({'state': 'done'}) + return True @api.multi def _get_valid_lines(self): + """:return: A recordset of rma lines. + """ self.ensure_one() return self.rma_line_ids diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index a2847bb7..8eb1f917 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import _, api, fields, models +from openerp import api, fields, models from openerp.addons import decimal_precision as dp import operator ops = {'=': operator.eq, @@ -90,8 +90,8 @@ class RmaOrderLine(models.Model): rec.qty_to_deliver = 0.0 if rec.delivery_policy == 'ordered': rec.qty_to_deliver = rec.product_qty - rec.qty_delivered - elif self.delivery_policy == 'received': - self.qty_to_deliver = rec.qty_received - rec.qty_delivered + elif rec.delivery_policy == 'received': + rec.qty_to_deliver = rec.qty_received - rec.qty_delivered @api.multi @api.depends('move_ids', 'move_ids.state', 'type') @@ -180,7 +180,7 @@ class RmaOrderLine(models.Model): readonly=True, states={"new": [("readonly", False)]}, ) product_qty = fields.Float( - string='Ordered Qty', copy=False, + string='Ordered Qty', copy=False, default=1.0, digits=dp.get_precision('Product Unit of Measure')) uom_id = fields.Many2one('product.uom', string='Unit of Measure', required=True) @@ -197,8 +197,8 @@ class RmaOrderLine(models.Model): out_shipment_count = fields.Integer(compute=_compute_out_shipment_count, string='# of Deliveries', default=0) move_ids = fields.One2many('stock.move', 'rma_line_id', - string='Stock Moves', readonly=True - , copy=False) + string='Stock Moves', readonly=True, + copy=False) reference_move_id = fields.Many2one(comodel_name='stock.move', string='Originating stock move', readonly=True, copy=False) @@ -243,7 +243,8 @@ class RmaOrderLine(models.Model): default=_default_location_id) customer_rma_id = fields.Many2one( 'rma.order.line', string='Customer RMA line', ondelete='cascade') - supplier_rma_line_ids = fields.One2many('rma.order.line', 'customer_rma_id') + supplier_rma_line_ids = fields.One2many( + 'rma.order.line', 'customer_rma_id') supplier_address_id = fields.Many2one( 'res.partner', readonly=True, states={'draft': [('readonly', False)]}, @@ -408,10 +409,11 @@ class RmaOrderLine(models.Model): @api.multi def action_view_procurements(self): - action = self.env.ref('procurement.procurement_order_action_exceptions') + action = self.env.ref( + 'procurement.procurement_order_action_exceptions') result = action.read()[0] procurements = self.procurement_ids.filtered( - lambda p: p.state == 'exception').ids + lambda p: p.state == 'exception').ids # choose the view_mode accordingly if len(procurements) != 1: result['domain'] = "[('id', 'in', " + \ diff --git a/rma/models/stock.py b/rma/models/stock.py index cc70c174..c8fdaf88 100644 --- a/rma/models/stock.py +++ b/rma/models/stock.py @@ -10,28 +10,29 @@ class StockPicking(models.Model): @api.multi def action_assign(self): + """When you try to bring back a product from a customer location, + it may happen that there is no quants available to perform the + picking.""" + res = super(StockPicking, self).action_assign() for picking in self: for move in picking.move_lines: - if len(move.rma_line_id): - if move.state in ('confirmed', 'waiting', 'assigned') \ - and move.location_id.usage in ( - 'supplier', 'customer'): - move.force_assign() - return super(StockPicking, self).action_assign() + if (move.rma_line_id and move.state == 'confirmed' and + move.location_id.usage == 'customer'): + move.force_assign() + return res class StockMove(models.Model): - _inherit = "stock.move" - rma_line_id = fields.Many2one('rma.order.line', string='RMA', + rma_line_id = fields.Many2one('rma.order.line', string='RMA line', ondelete='restrict') @api.model def create(self, vals): - if vals.get('procurement_id', False): + if vals.get('procurement_id'): procurement = self.env['procurement.order'].browse( vals['procurement_id']) - if procurement.rma_line_id and procurement.rma_line_id.id: + if procurement.rma_line_id: vals['rma_line_id'] = procurement.rma_line_id.id return super(StockMove, self).create(vals) diff --git a/rma/models/stock_warehouse.py b/rma/models/stock_warehouse.py index 3d465a60..26ff4b08 100644 --- a/rma/models/stock_warehouse.py +++ b/rma/models/stock_warehouse.py @@ -2,11 +2,10 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models +from openerp import fields, models class StockWarehouse(models.Model): - _inherit = "stock.warehouse" lot_rma_id = fields.Many2one('stock.location', 'RMA Location') diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 6ae75d89..95bbe572 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -13,7 +13,7 @@ class TestRma(common.TransactionCase): super(TestRma, self).setUp() self.rma_make_picking = self.env['rma_make_picking.wizard'] - self.rma_add_invoice = self.env['rma_add_invoice'] + self.rma_add_stock_move = self.env['rma_add_stock_move'] self.stockpicking = self.env['stock.picking'] self.rma = self.env['rma.order'] self.rma_line = self.env['rma.order.line'] @@ -29,59 +29,56 @@ class TestRma(common.TransactionCase): self.product_2.write({'rma_operation_id': self.rma_op_id.id}) self.product_3.write({'rma_operation_id': self.rma_op_id.id}) self.partner_id = self.env.ref('base.res_partner_12') - - self.customer_location_id = self.env.ref( - 'stock.stock_location_customers' - ) - uom_unit = self.env.ref('product.product_uom_unit') - sale_values = self._prepare_sale() - self.sale_order = self.env['sale.order'].create(sale_values) - invoice_id = self.sale_order.action_invoice_create()[0] - self.invoice = self.env['account.invoice'].browse(invoice_id) - # Create the RMA from the invoice + self.stock_location = self.env.ref('stock.stock_location_stock') + self.stock_rma_location = self.env.ref('rma.location_rma') + self.customer_location = self.env.ref( + 'stock.stock_location_customers') + self.product_uom_id = self.env.ref('product.product_uom_unit') + self.product_uom_id = self.env.ref('product.product_uom_unit') + moves = [] + products2move = [(self.product_1, 3), (self.product_2, 5), + (self.product_3, 2)] + for item in products2move: + move_values = self._prepare_move(item[0], item[1]) + moves.append(self.env['stock.move'].create(move_values)) + # Create the RMA from the stock_move self.rma_id = self.rma.create( { 'reference': '0001', 'type': 'customer', 'partner_id': self.env.ref('base.res_partner_2').id }) - - for line in self.invoice.invoice_line_ids: - data = self.rma_add_invoice.with_context( - {'invoice_id': self.invoice.id} - )._prepare_rma_line_from_inv_line(line) - data.update(rma_id=self.rma_id.id) + for move in moves: + data = self.rma_add_stock_move.with_context( + {'stock_move_id': move.id} + )._prepare_rma_line_from_stock_move(move) + operation = self.rma_op.browse(data['operation_id']) + data.update( + rma_id=self.rma_id.id, + receipt_policy=operation.receipt_policy, + delivery_policy=operation.delivery_policy, + in_warehouse_id=operation.in_warehouse_id.id, + out_warehouse_id=operation.out_warehouse_id.id, + location_id=self.stock_rma_location.id, + in_route_id=operation.in_route_id.id, + out_route_id=operation.out_route_id.id) self.rma_line.create(data) - #approve the RMA + # approve the RMA self.rma_id.action_rma_to_approve() self.rma_id.action_rma_approve() - def _prepare_sale(self): - values = { - 'state': 'done', - 'partner_id': self.env.ref('base.res_partner_2').id, - 'pricelist_id': self.env.ref('product.list0').id, - 'warehouse_id': self.env.ref('stock.warehouse0').id, - 'partner_invoice_id': self.env.ref('base.res_partner_2').id, - 'partner_shipping_id': self.env.ref('base.res_partner_2').id, - 'picking_policy': 'direct', - 'order_line': [ - (0, False, { - 'name': product.name, - 'product_id': product.id, - 'product_uom_qty': qty, - 'qty_delivered': qty, - 'product_uom': self.uom_unit.id, - 'price_unit': product.list_price - - }) for product, qty in [ - (self.product_1, 3), - (self.product_2, 5), - (self.product_3, 2), - ] - ] + def _prepare_move(self, product, qty): + res = { + 'product_id': product.id, + 'name': product.partner_ref, + 'state': 'confirmed', + 'product_uom': self.product_uom_id.id or product.uom_id.id, + 'product_uom_qty': qty, + 'origin': 'Test RMA', + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, } - return values + return res def test_00_receive_items(self): wizard = self.rma_make_picking.with_context({ @@ -93,8 +90,7 @@ class TestRma(common.TransactionCase): procurements = wizard._create_picking() group_ids = set([proc.group_id.id for proc in procurements if proc.group_id]) - domain = "[('group_id','in',[" + ','.join( - map(str, list(group_ids))) + "])]" + domain = [('group_id', 'in', list(group_ids))] picking = self.stockpicking.search(domain) self.assertEquals(len(picking), 1, "Incorrect number of pickings created") @@ -102,6 +98,7 @@ class TestRma(common.TransactionCase): self.assertEquals(len(moves), 3, "Incorrect number of moves created") for line in self.rma_id.rma_line_ids: + # common qtys for all products self.assertEquals(line.qty_received, 0, "Wrong qty received") self.assertEquals(line.qty_to_deliver, 0, @@ -110,10 +107,7 @@ class TestRma(common.TransactionCase): "Wrong qty outgoing") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") - self.assertEquals(line.qty_to_refund, 0, - "Wrong qty to refund") - self.assertEquals(line.qty_to_refunded, 0, - "Wrong qty refunded") + # product specific if line.product_id == self.product_1: self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") @@ -129,8 +123,8 @@ class TestRma(common.TransactionCase): "Wrong qty to receive") self.assertEquals(line.qty_incoming, 2, "Wrong qty incoming") - pickings.action_assign() - pickings.do_transfer() + picking.action_assign() + picking.do_transfer() for line in self.rma_id.rma_line_ids: self.assertEquals(line.qty_to_receive, 0, "Wrong qty to_receive") @@ -140,10 +134,6 @@ class TestRma(common.TransactionCase): "Wrong qty outgoing") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") - self.assertEquals(line.qty_to_refund, 0, - "Wrong qty to refund") - self.assertEquals(line.qty_to_refunded, 0, - "Wrong qty refunded") if line.product_id == self.product_1: self.assertEquals(line.qty_received, 3, "Wrong qty received") @@ -169,12 +159,12 @@ class TestRma(common.TransactionCase): procurements = wizard._create_picking() group_ids = set([proc.group_id.id for proc in procurements if proc.group_id]) - domain = "[('group_id','in',[" + ','.join( - map(str, list(group_ids))) + "])]" - picking = self.stockpicking.search(domain) - self.assertEquals(len(picking), 1, + domain = [('group_id', 'in', list(group_ids))] + pickings = self.stockpicking.search(domain) + self.assertEquals(len(pickings), 2, "Incorrect number of pickings created") - moves = picking.move_lines + picking_out = pickings[1] + moves = picking_out.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") for line in self.rma_id.rma_line_ids: @@ -184,10 +174,6 @@ class TestRma(common.TransactionCase): "Wrong qty incoming") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") - self.assertEquals(line.qty_to_refund, 0, - "Wrong qty to refund") - self.assertEquals(line.qty_to_refunded, 0, - "Wrong qty refunded") if line.product_id == self.product_1: self.assertEquals(line.qty_to_deliver, 3, "Wrong qty to deliver") @@ -209,8 +195,8 @@ class TestRma(common.TransactionCase): "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 2, "Wrong qty outgoing") - pickings.action_assign() - pickings.do_transfer() + picking_out.action_assign() + picking_out.do_transfer() for line in self.rma_id.rma_line_ids: self.assertEquals(line.qty_to_receive, 0, "Wrong qty to receive") @@ -218,10 +204,6 @@ class TestRma(common.TransactionCase): "Wrong qty incoming") self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") - self.assertEquals(line.qty_to_refund, 0, - "Wrong qty to refund") - self.assertEquals(line.qty_to_refunded, 0, - "Wrong qty refunded") self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") if line.product_id == self.product_1: diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index 649552f4..29d8797d 100644 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -5,7 +5,7 @@ rma.order.line.tree rma.order.line - @@ -27,7 +27,7 @@ rma.order.line.supplier.tree rma.order.line - @@ -48,7 +48,7 @@ rma.order.line.supplier.form rma.order.line -
+
@@ -171,7 +171,7 @@ rma.order.line.form rma.order.line - +
diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py index e5007085..64ce435f 100644 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import models, fields, exceptions, api, _ +from openerp import models, fields, api, _ from openerp.exceptions import ValidationError @@ -100,7 +100,8 @@ class RmaAddStockMove(models.TransientModel): rma_line_obj.with_context( default_rma_id=self.rma_id.id).create(data) else: - data = self._prepare_rma_line_from_stock_move(sm, lot=False) + data = self._prepare_rma_line_from_stock_move( + sm, lot=False) rma_line_obj.with_context( default_rma_id=self.rma_id.id).create(data) return {'type': 'ir.actions.act_window_close'} diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py index 80f2f5ba..c81aa6a5 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -3,7 +3,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) import time -from openerp import models, fields, exceptions, api, _ +from openerp import models, fields, api, _ from openerp.exceptions import ValidationError from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT_FORMAT import openerp.addons.decimal_precision as dp @@ -45,7 +45,7 @@ class RmaMakePicking(models.TransientModel): items = [] lines = rma_line_obj.browse(rma_line_ids) if len(lines.mapped('partner_id')) > 1: - raise exceptions.Warning( + raise ValidationError( _('Only RMA lines from the same partner can be processed at ' 'the same time')) for line in lines: @@ -71,12 +71,13 @@ class RmaMakePicking(models.TransientModel): @api.model def _get_address(self, item): if item.line_id.delivery_address_id: - delivery_address = item.line_id.delivery_address_id or \ - item.line_id.partner_id + delivery_address = item.line_id.delivery_address_id elif item.line_id.customer_to_supplier: delivery_address = item.line_id.supplier_address_id + elif item.line_id.partner_id: + delivery_address = item.line_id.partner_id else: - raise exceptions.Warning('Unknown delivery address') + raise ValidationError('Unknown delivery address') return delivery_address def _get_address_location(self, delivery_address_id, type): @@ -103,9 +104,9 @@ class RmaMakePicking(models.TransientModel): warehouse = line.out_warehouse_id route = line.out_route_id if not route: - raise exceptions.Warning("No route specified") + raise ValidationError("No route specified") if not warehouse: - raise exceptions.Warning("No warehouse specified") + raise ValidationError("No warehouse specified") procurement_data = { 'name': line.rma_id.name, 'group_id': group.id, @@ -147,16 +148,16 @@ class RmaMakePicking(models.TransientModel): for item in self.item_ids: line = item.line_id if line.state != 'approved': - raise exceptions.Warning( + raise ValidationError( _('RMA %s is not approved') % line.rma_id.name) if line.receipt_policy == 'no' and picking_type == \ 'incoming': - raise exceptions.Warning( + raise ValidationError( _('No shipments needed for this operation')) if line.delivery_policy == 'no' and picking_type == \ 'outgoing': - raise exceptions.Warning( + raise ValidationError( _('No deliveries needed for this operation')) procurement = self._create_procurement(item, picking_type) procurement_list.append(procurement) @@ -191,7 +192,7 @@ class RmaMakePicking(models.TransientModel): if proc.group_id: groups.append(proc.group_id.id) if len(groups): - pickings =self.env['stock.picking'].search( + pickings = self.env['stock.picking'].search( [('group_id', 'in', groups)]) action = self._get_action(pickings, procurements) diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py index 79137bd5..2f258c68 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma.py +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -72,7 +72,7 @@ class RmaLineMakeSupplierRma(models.TransientModel): @api.model def _prepare_supplier_rma_line(self, rma, item): operation = self.env['rma.operation'].search( - [('type', '=', 'supplier')], limit=1) + [('type', '=', 'supplier')], limit=1) return { 'origin': item.line_id.rma_id.name, 'delivery_address_id': From 3551ce078ad410de91efbb3de6b75639bf2f4ff4 Mon Sep 17 00:00:00 2001 From: aheficent Date: Wed, 16 Aug 2017 12:52:35 +0200 Subject: [PATCH 04/81] [IMP] default operation in product and product_categ for customer and supplier [IMP]Separate menus for customer and supplier operations * Add active field to rma operation * Added tests * Fix travis * Fix create supplier rma from customer rma --- rma/data/rma_operation.xml | 25 --- rma/models/product.py | 6 +- rma/models/product_category.py | 6 +- rma/models/rma_operation.py | 7 +- rma/models/rma_order.py | 26 +-- rma/models/rma_order_line.py | 8 +- rma/tests/__init__.py | 2 + rma/tests/test_rma.py | 112 ++++++++---- rma/tests/test_rma_dropship.py | 91 ++++++++++ rma/tests/test_supplier_rma.py | 165 ++++++++++++++++++ rma/views/product_view.xml | 10 +- rma/views/rma_operation_view.xml | 31 +++- rma/views/rma_order_line_view.xml | 3 +- rma/wizards/rma_add_stock_move.py | 40 +++-- .../rma_order_line_make_supplier_rma.py | 49 ++++-- .../rma_order_line_make_supplier_rma_view.xml | 2 +- 16 files changed, 459 insertions(+), 124 deletions(-) create mode 100644 rma/tests/test_rma_dropship.py create mode 100644 rma/tests/test_supplier_rma.py diff --git a/rma/data/rma_operation.xml b/rma/data/rma_operation.xml index fea67f4f..5baa6fca 100644 --- a/rma/data/rma_operation.xml +++ b/rma/data/rma_operation.xml @@ -3,7 +3,6 @@ Replace After Receive RPLC - no ordered received customer @@ -14,7 +13,6 @@ Replace RPLS - no ordered ordered supplier @@ -22,30 +20,9 @@ - - Refund before receive - RFC - ordered - no - no - customer - - - - - Refund only - RFS - ordered - no - no - supplier - - - Replace deliver to vendor DSRPLB - no ordered no customer @@ -55,7 +32,6 @@ Replace receive in vendor DSRPLV - no no received customer @@ -65,7 +41,6 @@ Replace deliver to customer DSRPC - no no received supplier diff --git a/rma/models/product.py b/rma/models/product.py index d7f878bc..5ee028ec 100644 --- a/rma/models/product.py +++ b/rma/models/product.py @@ -8,7 +8,9 @@ from openerp import fields, models class ProductTemplate(models.Model): _inherit = 'product.template' - rma_operation_id = fields.Many2one( - comodel_name="rma.operation", string="RMA Operation") + rma_customer_operation_id = fields.Many2one( + comodel_name="rma.operation", string="Default RMA Customer Operation") + rma_supplier_operation_id = fields.Many2one( + comodel_name="rma.operation", string="Default RMA Supplier Operation") rma_approval_policy = fields.Selection( related="categ_id.rma_approval_policy", readonly=True) diff --git a/rma/models/product_category.py b/rma/models/product_category.py index decfce28..9674ad8d 100644 --- a/rma/models/product_category.py +++ b/rma/models/product_category.py @@ -16,5 +16,7 @@ class ProductCategory(models.Model): "products within categories with this policy.\n" "* Two steps: A RMA containing a product within a category with " "this policy will request the RMA manager approval.") - rma_operation_id = fields.Many2one( - comodel_name="rma.operation", string="RMA Operation") + rma_customer_operation_id = fields.Many2one( + comodel_name="rma.operation", string="Default RMA Customer Operation") + rma_supplier_operation_id = fields.Many2one( + comodel_name="rma.operation", string="Default RMA Supplier Operation") diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py index 5d3b230d..4f295009 100644 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -26,10 +26,7 @@ class RmaOperation(models.Model): name = fields.Char('Description', required=True) code = fields.Char('Code', required=True) - refund_policy = fields.Selection([ - ('no', 'No refund'), ('ordered', 'Based on Ordered Quantities'), - ('received', 'Based on Received Quantities')], string="Refund Policy", - default='no') + active = fields.Boolean(string='Active', default=True) receipt_policy = fields.Selection([ ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), ('received', 'Based on Delivered Quantities')], @@ -58,6 +55,6 @@ class RmaOperation(models.Model): 'stock.location', 'Send To This Company Location') type = fields.Selection([ ('customer', 'Customer'), ('supplier', 'Supplier')], - string="Used in RMA of this type", required=True, default='customer') + string="Used in RMA of this type", required=True) rma_line_ids = fields.One2many('rma.order.line', 'operation_id', 'RMA lines') diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index 28a9ff8d..8061dea5 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -3,6 +3,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from openerp import api, fields, models +from datetime import datetime class RmaOrder(models.Model): @@ -38,8 +39,12 @@ class RmaOrder(models.Model): @api.multi def _compute_line_count(self): - self.ensure_one() - self.line_count = len(self._get_valid_lines()) + for rec in self: + rec.line_count = len(rec._get_valid_lines()) + + @api.model + def _default_date_rma(self): + return datetime.now() name = fields.Char( string='Order Number', index=True, readonly=True, @@ -55,8 +60,9 @@ class RmaOrder(models.Model): state = fields.Selection([('draft', 'Draft'), ('to_approve', 'To Approve'), ('approved', 'Approved'), ('done', 'Done')], string='State', index=True, - default='draft') - date_rma = fields.Datetime(string='Order Date', index=True, copy=False) + default='draft') + date_rma = fields.Datetime(string='Order Date', index=True, + default=_default_date_rma) partner_id = fields.Many2one('res.partner', string='Partner', required=True, readonly=True, states={'draft': [('readonly', False)]}) @@ -72,11 +78,9 @@ class RmaOrder(models.Model): out_shipment_count = fields.Integer(compute=_compute_out_shipment_count, string='# of Outgoing Shipments') line_count = fields.Integer(compute=_compute_line_count, - string='# of Outgoing Shipments', - copy=False) + string='# of Outgoing Shipments') supplier_line_count = fields.Integer(compute=_compute_supplier_line_count, - string='# of Outgoing Shipments', - copy=False) + string='# of Outgoing Shipments') company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.user.company_id) @@ -175,8 +179,8 @@ class RmaOrder(models.Model): def _get_valid_lines(self): """:return: A recordset of rma lines. """ - self.ensure_one() - return self.rma_line_ids + for rec in self: + return rec.rma_line_ids @api.multi def action_view_lines(self): @@ -205,7 +209,7 @@ class RmaOrder(models.Model): action = self.env.ref('rma.action_rma_supplier_lines') result = action.read()[0] lines = self.rma_line_ids - related_lines = [line.id for line in lines.children_ids] + related_lines = [line.id for line in lines.supplier_rma_line_ids] # choose the view_mode accordingly if len(related_lines) != 1: result['domain'] = "[('id', 'in', " + \ diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 8eb1f917..6fddca53 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -308,8 +308,12 @@ class RmaOrderLine(models.Model): self.product_qty = 1 self.uom_id = self.product_id.uom_id.id self.price_unit = self.product_id.standard_price - self.operation_id = self.product_id.rma_operation_id or \ - self.product_id.categ_id.rma_operation_id + if self.type == 'customer': + self.operation_id = self.product_id.rma_customer_operation_id or \ + self.product_id.categ_id.rma_customer_operation_id + else: + self.operation_id = self.product_id.rma_supplier_operation_id or \ + self.product_id.categ_id.rma_supplier_operation_id return result @api.onchange('operation_id') diff --git a/rma/tests/__init__.py b/rma/tests/__init__.py index 1c2b27c0..dfa77946 100644 --- a/rma/tests/__init__.py +++ b/rma/tests/__init__.py @@ -2,3 +2,5 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import test_rma +from . import test_supplier_rma +from . import test_rma_dropship diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 95bbe572..2e36b989 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -13,61 +13,95 @@ class TestRma(common.TransactionCase): super(TestRma, self).setUp() self.rma_make_picking = self.env['rma_make_picking.wizard'] + self.make_supplier_rma = self.env["rma.order.line.make.supplier.rma"] self.rma_add_stock_move = self.env['rma_add_stock_move'] self.stockpicking = self.env['stock.picking'] self.rma = self.env['rma.order'] self.rma_line = self.env['rma.order.line'] self.rma_op = self.env['rma.operation'] - self.rma_op_id = self.env.ref('rma.rma_operation_customer_replace') + self.rma_cust_replace_op_id = self.env.ref( + 'rma.rma_operation_customer_replace') + self.rma_sup_replace_op_id = self.env.ref( + 'rma.rma_operation_supplier_replace') self.product_id = self.env.ref('product.product_product_4') self.product_1 = self.env.ref('product.product_product_25') self.product_2 = self.env.ref('product.product_product_30') self.product_3 = self.env.ref('product.product_product_33') self.uom_unit = self.env.ref('product.product_uom_unit') # assign an operation - self.product_1.write({'rma_operation_id': self.rma_op_id.id}) - self.product_2.write({'rma_operation_id': self.rma_op_id.id}) - self.product_3.write({'rma_operation_id': self.rma_op_id.id}) + self.product_1.write( + {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + self.product_2.write( + {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + self.product_3.write( + {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) self.partner_id = self.env.ref('base.res_partner_12') self.stock_location = self.env.ref('stock.stock_location_stock') self.stock_rma_location = self.env.ref('rma.location_rma') self.customer_location = self.env.ref( 'stock.stock_location_customers') + self.supplier_location = self.env.ref( + 'stock.stock_location_suppliers') self.product_uom_id = self.env.ref('product.product_uom_unit') - self.product_uom_id = self.env.ref('product.product_uom_unit') - moves = [] products2move = [(self.product_1, 3), (self.product_2, 5), (self.product_3, 2)] - for item in products2move: - move_values = self._prepare_move(item[0], item[1]) - moves.append(self.env['stock.move'].create(move_values)) + self.rma_customer_id = self._create_rma_from_move( + products2move, 'customer', self.env.ref('base.res_partner_2'), + dropship=False) + + def _create_rma_from_move(self, products2move, type, partner, dropship, + supplier_address_id=None): + moves = [] + if type == 'customer': + for item in products2move: + move_values = self._prepare_move( + item[0], item[1], self.stock_location, + self.customer_location) + moves.append(self.env['stock.move'].create(move_values)) + else: + for item in products2move: + move_values = self._prepare_move( + item[0], item[1], self.supplier_location, + self.stock_rma_location) + moves.append(self.env['stock.move'].create(move_values)) # Create the RMA from the stock_move - self.rma_id = self.rma.create( + rma_id = self.rma.create( { 'reference': '0001', - 'type': 'customer', - 'partner_id': self.env.ref('base.res_partner_2').id + 'type': type, + 'partner_id': partner.id, + 'company_id': self.env.ref('base.main_company').id }) for move in moves: - data = self.rma_add_stock_move.with_context( - {'stock_move_id': move.id} - )._prepare_rma_line_from_stock_move(move) - operation = self.rma_op.browse(data['operation_id']) - data.update( - rma_id=self.rma_id.id, - receipt_policy=operation.receipt_policy, - delivery_policy=operation.delivery_policy, - in_warehouse_id=operation.in_warehouse_id.id, - out_warehouse_id=operation.out_warehouse_id.id, - location_id=self.stock_rma_location.id, - in_route_id=operation.in_route_id.id, - out_route_id=operation.out_route_id.id) + if type == 'customer': + wizard = self.rma_add_stock_move.with_context( + {'stock_move_id': move.id, 'customer': True, + 'active_ids': rma_id.id, + 'active_model': 'rma.order', + } + ).create({}) + data = wizard._prepare_rma_line_from_stock_move(move) + else: + wizard = self.rma_add_stock_move.with_context( + {'stock_move_id': move.id, 'supplier': True, + 'active_ids': rma_id.id, + 'active_model': 'rma.order', + } + ).create({}) + data = wizard._prepare_rma_line_from_stock_move(move) + if dropship: + data.update(customer_to_supplier=dropship, + supplier_address_id=supplier_address_id.id) self.rma_line.create(data) # approve the RMA - self.rma_id.action_rma_to_approve() - self.rma_id.action_rma_approve() + rma_id.action_rma_to_approve() + rma_id.action_rma_approve() + return rma_id - def _prepare_move(self, product, qty): + def _prepare_move(self, product, qty, src, dest): res = { 'product_id': product.id, 'name': product.partner_ref, @@ -75,14 +109,14 @@ class TestRma(common.TransactionCase): 'product_uom': self.product_uom_id.id or product.uom_id.id, 'product_uom_qty': qty, 'origin': 'Test RMA', - 'location_id': self.stock_location.id, - 'location_dest_id': self.customer_location.id, + 'location_id': src.id, + 'location_dest_id': dest.id, } return res - def test_00_receive_items(self): + def test_customer_rma(self): wizard = self.rma_make_picking.with_context({ - 'active_ids': self.rma_id.rma_line_ids.ids, + 'active_ids': self.rma_customer_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'incoming', 'active_id': 1 @@ -97,7 +131,7 @@ class TestRma(common.TransactionCase): moves = picking.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") - for line in self.rma_id.rma_line_ids: + for line in self.rma_customer_id.rma_line_ids: # common qtys for all products self.assertEquals(line.qty_received, 0, "Wrong qty received") @@ -125,7 +159,7 @@ class TestRma(common.TransactionCase): "Wrong qty incoming") picking.action_assign() picking.do_transfer() - for line in self.rma_id.rma_line_ids: + for line in self.rma_customer_id.rma_line_ids: self.assertEquals(line.qty_to_receive, 0, "Wrong qty to_receive") self.assertEquals(line.qty_incoming, 0, @@ -152,7 +186,7 @@ class TestRma(common.TransactionCase): wizard = self.rma_make_picking.with_context({ 'active_id': 1, - 'active_ids': self.rma_id.rma_line_ids.ids, + 'active_ids': self.rma_customer_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'outgoing', }).create({}) @@ -167,7 +201,7 @@ class TestRma(common.TransactionCase): moves = picking_out.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") - for line in self.rma_id.rma_line_ids: + for line in self.rma_customer_id.rma_line_ids: self.assertEquals(line.qty_to_receive, 0, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 0, @@ -197,7 +231,7 @@ class TestRma(common.TransactionCase): "Wrong qty outgoing") picking_out.action_assign() picking_out.do_transfer() - for line in self.rma_id.rma_line_ids: + for line in self.rma_customer_id.rma_line_ids: self.assertEquals(line.qty_to_receive, 0, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 0, @@ -221,4 +255,6 @@ class TestRma(common.TransactionCase): "Wrong qty received") self.assertEquals(line.qty_delivered, 2, "Wrong qty delivered") - self.rma_id.action_rma_done() + self.rma_customer_id.action_rma_done() + self.assertEquals(self.rma_customer_id.state, 'done', + "Wrong State") diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py new file mode 100644 index 00000000..a531734f --- /dev/null +++ b/rma/tests/test_rma_dropship.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp.addons.rma.tests import test_rma + + +class TestRmaDropship(test_rma.TestRma): + + def setUp(self): + super(TestRmaDropship, self).setUp() + products2move = [(self.product_1, 3), (self.product_2, 5), + (self.product_3, 2)] + self.rma_droship_id = self._create_rma_from_move( + products2move, 'customer', self.env.ref('base.res_partner_2'), + dropship=True, + supplier_address_id=self.env.ref('base.res_partner_3')) + + def test_dropship(self): + wizard = self.make_supplier_rma.with_context({ + 'active_ids': self.rma_droship_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'active_id': 1 + }).create({}) + res = wizard.make_supplier_rma() + supplier_rma = self.rma.browse(res['res_id']) + supplier_rma.action_rma_to_approve() + supplier_rma.action_rma_approve() + wizard = self.rma_make_picking.with_context({ + 'active_id': 1, + 'active_ids': supplier_rma.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'incoming', + }).create({}) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = [('group_id', 'in', list(group_ids))] + picking = self.stockpicking.search(domain) + self.assertEquals(len(picking), 1, + "Incorrect number of pickings created") + moves = picking.move_lines + self.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in supplier_rma.rma_line_ids: + # common qtys for all products + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + # product specific + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") + self.assertEquals(line.qty_incoming, 3, + "Wrong qty outgoing") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + self.assertEquals(line.qty_incoming, 5, + "Wrong qty outgoing") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + self.assertEquals(line.qty_incoming, 2, + "Wrong qty outgoing") + + for line in self.rma_droship_id.rma_line_ids: + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + self.assertEquals(line.qty_in_supplier_rma, 3, + "Wrong qty in supplier rma") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + self.assertEquals(line.qty_in_supplier_rma, 5, + "Wrong qty in supplier rma") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + self.assertEquals(line.qty_in_supplier_rma, 2, + "Wrong qty in supplier rma") diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py new file mode 100644 index 00000000..e67b55ba --- /dev/null +++ b/rma/tests/test_supplier_rma.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from openerp.addons.rma.tests import test_rma + + +class TestSupplierRma(test_rma.TestRma): + + def setUp(self): + super(TestSupplierRma, self).setUp() + products2move = [(self.product_1, 3), (self.product_2, 5), + (self.product_3, 2)] + self.rma_supplier_id = self._create_rma_from_move( + products2move, 'supplier', self.env.ref('base.res_partner_1'), + dropship=False) + + def test_supplier_rma(self): + wizard = self.rma_make_picking.with_context({ + 'active_ids': self.rma_supplier_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'outgoing', + 'active_id': 1 + }).create({}) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = [('group_id', 'in', list(group_ids))] + picking = self.stockpicking.search(domain) + self.assertEquals(len(picking), 1, + "Incorrect number of pickings created") + moves = picking.move_lines + self.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in self.rma_supplier_id.rma_line_ids: + # common qtys for all products + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + # product specific + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 3, + "Wrong qty outgoing") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 5, + "Wrong qty outgoing") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 2, + "Wrong qty outgoing") + + picking.action_assign() + picking.do_transfer() + for line in self.rma_supplier_id.rma_line_ids: + self.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + if line.product_id == self.product_1: + self.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + if line.product_id == self.product_2: + self.assertEquals(line.qty_delivered, 5, + "Wrong qty delivered") + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + if line.product_id == self.product_3: + self.assertEquals(line.qty_delivered, 2, + "Wrong qty delivered") + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + wizard = self.rma_make_picking.with_context({ + 'active_id': 1, + 'active_ids': self.rma_supplier_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'incoming', + }).create({}) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = [('group_id', 'in', list(group_ids))] + pickings = self.stockpicking.search(domain) + self.assertEquals(len(pickings), 2, + "Incorrect number of pickings created") + picking_out = pickings[1] + moves = picking_out.move_lines + self.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in self.rma_supplier_id.rma_line_ids: + self.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 3, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 5, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 5, + "Wrong qty delivered") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 2, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 2, + "Wrong qty delivered") + picking_out.action_assign() + picking_out.do_transfer() + for line in self.rma_supplier_id.rma_line_ids: + self.assertEquals(line.qty_to_receive, 0, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + if line.product_id == self.product_1: + self.assertEquals(line.qty_received, 3, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + if line.product_id == self.product_2: + self.assertEquals(line.qty_received, 5, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 5, + "Wrong qty delivered") + if line.product_id == self.product_3: + self.assertEquals(line.qty_received, 2, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 2, + "Wrong qty delivered") + self.rma_supplier_id.action_rma_done() + self.assertEquals(self.rma_supplier_id.state, 'done', + "Wrong State") diff --git a/rma/views/product_view.xml b/rma/views/product_view.xml index c14144a6..bb35950b 100644 --- a/rma/views/product_view.xml +++ b/rma/views/product_view.xml @@ -8,8 +8,11 @@ - - + + + + + @@ -22,7 +25,8 @@ - + + diff --git a/rma/views/rma_operation_view.xml b/rma/views/rma_operation_view.xml index 1fc26e7a..b9f55633 100644 --- a/rma/views/rma_operation_view.xml +++ b/rma/views/rma_operation_view.xml @@ -6,6 +6,7 @@ rma.operation + @@ -25,6 +26,7 @@ + @@ -50,20 +52,39 @@ - - Operations + + Customer Operations rma.operation form tree,form + {'default_type': "customer"} + [('type','=', 'customer')] - + Supplier Operations + rma.operation + form + tree,form + {'default_type': "supplier"} + [('type','=', 'supplier')] + + + + + action="action_rma_operation_customer"/> + + diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index 29d8797d..3b9399a8 100644 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -332,8 +332,7 @@ Customer RMA Lines rma.order.line [('state','in', ['approved', 'done']), - ('type','=', 'customer'), - ('customer_to_supplier','=', False) + ('type','=', 'customer') ] {"search_default_assigned_to":uid} form diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py index 64ce435f..fd6e2e18 100644 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import models, fields, api, _ +from openerp import api, fields, models from openerp.exceptions import ValidationError @@ -40,14 +40,18 @@ class RmaAddStockMove(models.TransientModel): domain="[('state', '=', 'done')]") def _prepare_rma_line_from_stock_move(self, sm, lot=False): - operation = sm.product_id.rma_operation_id or \ - sm.product_id.categ_id.rma_operation_id + if self.env.context.get('customer'): + operation = sm.product_id.rma_customer_operation_id or \ + sm.product_id.categ_id.rma_customer_operation_id + else: + operation = sm.product_id.rma_supplier_operation_id or \ + sm.product_id.categ_id.rma_supplier_operation_id data = { 'reference_move_id': sm.id, 'product_id': sm.product_id.id, 'lot_id': lot and lot.id or False, 'name': sm.product_id.name_template, - 'origin': sm.picking_id.name, + 'origin': sm.picking_id.name or sm.name, 'uom_id': sm.product_uom.id, 'operation_id': operation.id, 'product_qty': sm.product_uom_qty, @@ -64,20 +68,26 @@ class RmaAddStockMove(models.TransientModel): [('rma_selectable', '=', True)], limit=1) if not route: raise ValidationError("Please define an rma route") + + if not operation.in_warehouse_id or not operation.out_warehouse_id: + warehouse = self.env['stock.warehouse'].search( + [('company_id', '=', self.rma_id.company_id.id), + ('lot_rma_id', '!=', False)], limit=1) + if not warehouse: + raise ValidationError("Please define a warehouse with a " + "default rma location") data.update( - {'in_route_id': operation.in_route_id.id, - 'out_route_id': operation.out_route_id.id, - 'receipt_policy': operation.receipt_policy, + {'receipt_policy': operation.receipt_policy, 'operation_id': operation.id, - 'refund_policy': operation.refund_policy, - 'delivery_policy': operation.delivery_policy + 'delivery_policy': operation.delivery_policy, + 'in_warehouse_id': operation.in_warehouse_id.id or warehouse.id, + 'out_warehouse_id': operation.out_warehouse_id.id or warehouse.id, + 'in_route_id': operation.in_route_id.id or route.id, + 'out_route_id': operation.out_route_id.id or route.id, + 'location_id': (operation.location_id.id or + operation.in_warehouse_id.lot_rma_id.id or + warehouse.lot_rma_id.id) }) - if operation.in_warehouse_id: - data['in_warehouse_id'] = operation.in_warehouse_id.id - if operation.out_warehouse_id: - data['out_warehouse_id'] = operation.out_warehouse_id.id - if operation.location_id: - data['location_id'] = operation.location_id.id return data @api.model diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py index 2f258c68..59ae981e 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma.py +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -4,6 +4,7 @@ import openerp.addons.decimal_precision as dp from openerp import _, api, exceptions, fields, models +from openerp.exceptions import ValidationError class RmaLineMakeSupplierRma(models.TransientModel): @@ -48,7 +49,10 @@ class RmaLineMakeSupplierRma(models.TransientModel): for line in lines: items.append([0, 0, self._prepare_item(line)]) suppliers = lines.mapped('supplier_address_id') - if len(suppliers) == 1: + if len(suppliers) == 0: + raise exceptions.Warning( + _('Please specify a supplier address')) + elif len(suppliers) == 1: res['partner_id'] = suppliers.id else: raise exceptions.Warning( @@ -73,7 +77,8 @@ class RmaLineMakeSupplierRma(models.TransientModel): def _prepare_supplier_rma_line(self, rma, item): operation = self.env['rma.operation'].search( [('type', '=', 'supplier')], limit=1) - return { + data = { + 'type': 'supplier', 'origin': item.line_id.rma_id.name, 'delivery_address_id': item.line_id.delivery_address_id.id, @@ -81,20 +86,38 @@ class RmaLineMakeSupplierRma(models.TransientModel): 'customer_rma_id': item.line_id.id, 'product_qty': item.product_qty, 'rma_id': rma.id, + 'uom_id': item.uom_id.id, 'operation_id': operation.id, 'receipt_policy': operation.receipt_policy, 'delivery_policy': operation.delivery_policy, - 'in_warehouse_id': operation.in_warehouse_id.id, - 'out_warehouse_id': operation.out_warehouse_id.id, - 'location_id': operation.location_id.id, 'supplier_to_customer': operation.supplier_to_customer, - 'in_route_id': operation.in_route_id.id, - 'out_route_id': operation.out_route_id.id, } + if not operation.in_route_id or not operation.out_route_id: + route = self.env['stock.location.route'].search( + [('rma_selectable', '=', True)], limit=1) + if not route: + raise ValidationError(_("Please define an rma route")) + if not operation.in_warehouse_id or not operation.out_warehouse_id: + warehouse = self.env['stock.warehouse'].search( + [('company_id', '=', self.rma_id.company_id.id), + ('lot_rma_id', '!=', False)], limit=1) + if not warehouse: + raise ValidationError(_("Please define a warehouse with a" + " default rma location")) + data.update( + {'in_warehouse_id': operation.in_warehouse_id.id or warehouse.id, + 'out_warehouse_id': operation.out_warehouse_id.id or warehouse.id, + 'in_route_id': operation.in_route_id.id or route.id, + 'out_route_id': operation.out_route_id.id or route.id, + 'location_id': (operation.location_id.id or + operation.in_warehouse_id.lot_rma_id.id or + warehouse.lot_rma_id.id) + }) + return data @api.multi def make_supplier_rma(self): - res = [] + self = self.with_context(supplier=True, customer=False) rma_obj = self.env['rma.order'] rma_line_obj = self.env['rma.order.line'] rma = False @@ -113,16 +136,15 @@ class RmaLineMakeSupplierRma(models.TransientModel): rma_line_data = self._prepare_supplier_rma_line(rma, item) rma_line_obj.create(rma_line_data) - res.append(rma.id) return { - 'domain': "[('id','in', ["+','.join(map(str, res))+"])]", 'name': _('Supplier RMA'), 'view_type': 'form', - 'view_mode': 'tree,form', + 'view_mode': 'form', 'res_model': 'rma.order', 'view_id': False, - 'context': {'supplier': 1}, + 'res_id': rma.id, + 'context': {'supplier': True, 'customer': False}, 'type': 'ir.actions.act_window' } @@ -137,7 +159,8 @@ class RmaLineMakeRmaOrderItem(models.TransientModel): readonly=True) line_id = fields.Many2one('rma.order.line', string='RMA Line', - required=True) + required=True, + ondelete='cascade') rma_id = fields.Many2one('rma.order', related='line_id.rma_id', string='RMA Order', readonly=True) product_id = fields.Many2one('product.product', diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml index 85609494..e7ad43c6 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -13,7 +13,7 @@ - + Date: Thu, 24 Aug 2017 13:33:41 +0200 Subject: [PATCH 05/81] [9.0][FIX] * rma: receipt_policy selections not matching. * rma_sale: fix _prepare_rma_line_from_sale_order_line. --- rma/models/rma_operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py index 4f295009..eec8f38a 100644 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -29,7 +29,7 @@ class RmaOperation(models.Model): active = fields.Boolean(string='Active', default=True) receipt_policy = fields.Selection([ ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), - ('received', 'Based on Delivered Quantities')], + ('delivered', 'Based on Delivered Quantities')], string="Receipts Policy", default='no') delivery_policy = fields.Selection([ ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), From e12fbb329af3635344df535373016f92528dc899 Mon Sep 17 00:00:00 2001 From: lreficent Date: Fri, 25 Aug 2017 12:22:53 +0200 Subject: [PATCH 06/81] [9.0][IMP] rma_account: * remove unneded copy attributes. * simplify action_view methods. * fix wrong naming. * fix misplaced views. * fix wrong count and view actions for rma.orders in invoices. * fix error when installing the module. * remove unneded data update when preparing rma lines from invoice lines. * minor extra fixes. --- rma/models/rma_order.py | 7 +++---- rma/views/rma_order_line_view.xml | 4 ++-- rma/wizards/rma_add_stock_move_view.xml | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index 8061dea5..ae1afc4d 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -179,8 +179,8 @@ class RmaOrder(models.Model): def _get_valid_lines(self): """:return: A recordset of rma lines. """ - for rec in self: - return rec.rma_line_ids + self.ensure_one() + return self.rma_line_ids @api.multi def action_view_lines(self): @@ -192,8 +192,7 @@ class RmaOrder(models.Model): lines = self._get_valid_lines() # choose the view_mode accordingly if len(lines) != 1: - result['domain'] = "[('id', 'in', " + \ - str(lines.ids) + ")]" + result['domain'] = [('id', 'in', lines.ids)] elif len(lines) == 1: if self.type == 'customer': res = self.env.ref('rma.view_rma_line_form', False) diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index 3b9399a8..edabd55f 100644 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -49,8 +49,8 @@ rma.order.line +
-
@@ -104,16 +104,14 @@ rma.order.line -
-
-
-
+
+
From a82f603497e21726238387f63afd3ddab0c79d76 Mon Sep 17 00:00:00 2001 From: lreficent Date: Wed, 18 Oct 2017 12:20:27 +0200 Subject: [PATCH 08/81] [9.0][REW] rma: workflow centralized on rma.order.line and the use of rma.order is optional. --- rma/data/rma_sequence.xml | 8 +- rma/models/procurement.py | 14 +- rma/models/rma_order.py | 50 +--- rma/models/rma_order_line.py | 299 ++++++++++++++++++------ rma/views/rma_order_line_view.xml | 139 +++++++---- rma/views/rma_order_view.xml | 88 +------ rma/wizards/rma_add_stock_move_view.xml | 16 +- rma/wizards/rma_make_picking.py | 33 +-- 8 files changed, 395 insertions(+), 252 deletions(-) diff --git a/rma/data/rma_sequence.xml b/rma/data/rma_sequence.xml index 1162e9ad..e59ec85f 100644 --- a/rma/data/rma_sequence.xml +++ b/rma/data/rma_sequence.xml @@ -4,7 +4,7 @@ Customer RMA sequence rma.order.customer 5 - RMA/%(year)s/ + RMAG/%(year)s/ @@ -13,7 +13,7 @@ Supplier RMA sequence rma.order.supplier 5 - RTV/%(year)s/ + RTVG/%(year)s/ @@ -22,7 +22,7 @@ Customer RMA Line sequence rma.order.line.customer 5 - RMAL/%(year)s/ + RMA/%(year)s/ @@ -31,7 +31,7 @@ Supplier RMA Line sequence rma.order.line.supplier 5 - RTVL/%(year)s/ + RTV/%(year)s/ diff --git a/rma/models/procurement.py b/rma/models/procurement.py index c8cd39db..eb4a46b7 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -8,7 +8,10 @@ from openerp import api, fields, models class ProcurementOrder(models.Model): _inherit = 'procurement.order' - rma_line_id = fields.Many2one('rma.order.line', 'RMA', ondelete="set null") + rma_line_id = fields.Many2one( + comodel_name='rma.order.line', string='RMA line', + ondelete="set null", + ) @api.model def _run_move_create(self, procurement): @@ -26,4 +29,11 @@ class ProcurementOrder(models.Model): class ProcurementGroup(models.Model): _inherit = 'procurement.group' - rma_id = fields.Many2one('rma.order', 'RMA', ondelete="set null") + rma_id = fields.Many2one( + comodel_name='rma.order', string='RMA', + ondelete="set null", + ) + rma_line_id = fields.Many2one( + comodel_name='rma.order.line', string='RMA line', + ondelete="set null", + ) diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index ae1afc4d..39130e40 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -47,30 +47,17 @@ class RmaOrder(models.Model): return datetime.now() name = fields.Char( - string='Order Number', index=True, readonly=True, - states={'progress': [('readonly', False)]}, copy=False) + string='Group Number', index=True, copy=False) type = fields.Selection( [('customer', 'Customer'), ('supplier', 'Supplier')], string="Type", required=True, default=_get_default_type, readonly=True) reference = fields.Char(string='Partner Reference', help="The partner reference of this RMA order.") - comment = fields.Text('Additional Information', readonly=True, states={ - 'draft': [('readonly', False)]}) - - state = fields.Selection([('draft', 'Draft'), ('to_approve', 'To Approve'), - ('approved', 'Approved'), - ('done', 'Done')], string='State', index=True, - default='draft') + comment = fields.Text('Additional Information') date_rma = fields.Datetime(string='Order Date', index=True, default=_default_date_rma) - partner_id = fields.Many2one('res.partner', string='Partner', - required=True, readonly=True, - states={'draft': [('readonly', False)]}) - assigned_to = fields.Many2one('res.users', 'Assigned to', - track_visibility='onchange') - requested_by = fields.Many2one('res.users', 'Requested by', - track_visibility='onchange', - default=lambda self: self.env.user) + partner_id = fields.Many2one( + comodel_name='res.partner', string='Partner', required=True) rma_line_ids = fields.One2many('rma.order.line', 'rma_id', string='RMA lines') in_shipment_count = fields.Integer(compute=_compute_in_shipment_count, @@ -87,7 +74,8 @@ class RmaOrder(models.Model): @api.model def create(self, vals): - if self.env.context.get('supplier'): + if (self.env.context.get('supplier') or + vals.get('type') == 'supplier'): vals['name'] = self.env['ir.sequence'].next_by_code( 'rma.order.supplier') else: @@ -149,32 +137,6 @@ class RmaOrder(models.Model): result['res_id'] = shipments[0] return result - @api.multi - def action_rma_to_approve(self): - self.write({'state': 'to_approve'}) - for rec in self: - pols = rec.mapped('rma_line_ids.product_id.rma_approval_policy') - if not any(x != 'one_step' for x in pols): - rec.write({'assigned_to': self.env.uid}) - rec.action_rma_approve() - return True - - @api.multi - def action_rma_draft(self): - self.write({'state': 'draft'}) - return True - - @api.multi - def action_rma_approve(self): - # pass the supplier address in case this is a customer RMA - self.write({'state': 'approved'}) - return True - - @api.multi - def action_rma_done(self): - self.write({'state': 'done'}) - return True - @api.multi def _get_valid_lines(self): """:return: A recordset of rma lines. diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 6fddca53..acecfb06 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -2,7 +2,8 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models +from openerp import api, fields, models, _ +from openerp.exceptions import ValidationError, UserError from openerp.addons import decimal_precision as dp import operator ops = {'=': operator.eq, @@ -11,7 +12,13 @@ ops = {'=': operator.eq, class RmaOrderLine(models.Model): _name = "rma.order.line" - _rec_name = "rma_id" + _inherit = ['mail.thread'] + + @api.model + def _get_default_type(self): + if 'supplier' in self.env.context: + return "supplier" + return "customer" @api.model def _default_warehouse_id(self): @@ -41,7 +48,8 @@ class RmaOrderLine(models.Model): def _compute_in_shipment_count(self): for line in self: moves = line.procurement_ids.mapped('move_ids').filtered( - lambda m: m.location_dest_id.usage == 'internal') + lambda m: m.location_dest_id.usage == 'internal' and + m.state != 'cancel') pickings = moves.mapped('picking_id') line.in_shipment_count = len(pickings) @@ -49,7 +57,8 @@ class RmaOrderLine(models.Model): def _compute_out_shipment_count(self): for line in self: moves = line.procurement_ids.mapped('move_ids').filtered( - lambda m: m.location_dest_id.usage != 'internal') + lambda m: m.location_dest_id.usage != 'internal' and + m.state != 'cancel') pickings = moves.mapped('picking_id') line.out_shipment_count = len(pickings) @@ -131,7 +140,6 @@ class RmaOrderLine(models.Model): @api.multi @api.depends('customer_to_supplier', 'supplier_rma_line_ids', - 'supplier_rma_line_ids.rma_id.state', 'move_ids', 'move_ids.state', 'qty_received', 'receipt_policy', 'product_qty', 'type') def _compute_qty_supplier_rma(self): @@ -147,33 +155,58 @@ class RmaOrderLine(models.Model): lambda p: p.state == 'exception')) delivery_address_id = fields.Many2one( - 'res.partner', string='Partner delivery address', + comodel_name='res.partner', string='Partner delivery address', default=_default_delivery_address, - help="This address will be used to " - "deliver repaired or replacement products.") - - rma_id = fields.Many2one('rma.order', string='RMA', - ondelete='cascade', required=True) - name = fields.Char(string='Reference', required=True, default='/', - help='Add here the supplier RMA #. Otherwise an ' - 'internal code is assigned.') + readonly=True, states={'draft': [('readonly', False)]}, + help="This address will be used to deliver repaired or replacement " + "products.", + ) + rma_id = fields.Many2one( + comodel_name='rma.order', string='RMA Group', + track_visibility='onchange', readonly=True, + ) + name = fields.Char( + string='Reference', required=True, default='/', + readonly=True, states={'draft': [('readonly', False)]}, + help='Add here the supplier RMA #. Otherwise an internal code is' + ' assigned.', + ) description = fields.Text(string='Description') - origin = fields.Char(string='Source Document', - help="Reference of the document that produced " - "this rma.") - state = fields.Selection(related='rma_id.state') + origin = fields.Char( + string='Source Document', + readonly=True, states={'draft': [('readonly', False)]}, + help="Reference of the document that produced this rma.") + state = fields.Selection( + selection=[('draft', 'Draft'), + ('to_approve', 'To Approve'), + ('approved', 'Approved'), + ('done', 'Done')], + string='State', default='draft', + track_visibility='onchange', + ) operation_id = fields.Many2one( - comodel_name="rma.operation", string="Operation") - - assigned_to = fields.Many2one('res.users', related='rma_id.assigned_to') - requested_by = fields.Many2one('res.users', related='rma_id.requested_by') - partner_id = fields.Many2one('res.partner', related='rma_id.partner_id', - store=True) - sequence = fields.Integer(default=10, - help="Gives the sequence of this line " - "when displaying the rma.") - product_id = fields.Many2one('product.product', string='Product', - ondelete='restrict', required=-True) + comodel_name="rma.operation", string="Operation", + readonly=True, states={'draft': [('readonly', False)]}, + ) + assigned_to = fields.Many2one( + comodel_name='res.users', track_visibility='onchange', + ) + requested_by = fields.Many2one( + comodel_name='res.users', track_visibility='onchange', + ) + partner_id = fields.Many2one( + comodel_name='res.partner', required=True, store=True, + track_visibility='onchange', + readonly=True, states={'draft': [('readonly', False)]}, + ) + sequence = fields.Integer( + default=10, + help="Gives the sequence of this line when displaying the rma.") + product_id = fields.Many2one( + comodel_name='product.product', string='Product', + ondelete='restrict', required=True, + readonly=True, states={'draft': [('readonly', False)]}, + ) product_tracking = fields.Selection(related="product_id.tracking") lot_id = fields.Many2one( comodel_name="stock.production.lot", string="Lot/Serial Number", @@ -181,14 +214,18 @@ class RmaOrderLine(models.Model): ) product_qty = fields.Float( string='Ordered Qty', copy=False, default=1.0, - digits=dp.get_precision('Product Unit of Measure')) - uom_id = fields.Many2one('product.uom', string='Unit of Measure', - required=True) - price_unit = fields.Monetary(string='Price Unit', readonly=False, - states={'approved': [('readonly', True)], - 'done': [('readonly', True)], - 'to_approve': [('readonly', True)]}) - + digits=dp.get_precision('Product Unit of Measure'), + readonly=True, states={'draft': [('readonly', False)]}, + ) + uom_id = fields.Many2one( + comodel_name='product.uom', string='Unit of Measure', + required=True, + readonly=True, states={'draft': [('readonly', False)]}, + ) + price_unit = fields.Monetary( + string='Price Unit', + readonly=True, states={'draft': [('readonly', False)]}, + ) procurement_count = fields.Integer(compute=_compute_procurement_count, string='# of Procurements', copy=False, default=0) @@ -199,48 +236,75 @@ class RmaOrderLine(models.Model): move_ids = fields.One2many('stock.move', 'rma_line_id', string='Stock Moves', readonly=True, copy=False) - reference_move_id = fields.Many2one(comodel_name='stock.move', - string='Originating stock move', - readonly=True, copy=False) + reference_move_id = fields.Many2one( + comodel_name='stock.move', string='Originating Stock Move', + copy=False, + readonly=True, states={'draft': [('readonly', False)]}, + ) procurement_ids = fields.One2many('procurement.order', 'rma_line_id', string='Procurements', readonly=True, states={'draft': [('readonly', False)]}, copy=False) currency_id = fields.Many2one('res.currency', string="Currency") - company_id = fields.Many2one('res.company', string='Company', - related='rma_id.company_id', store=True) - type = fields.Selection(related='rma_id.type') + company_id = fields.Many2one( + comodel_name='res.company', string='Company', required=True, + default=lambda self: self.env.user.company_id) + type = fields.Selection( + selection=[('customer', 'Customer'), ('supplier', 'Supplier')], + string="Type", required=True, default=_get_default_type, + readonly=True, + ) customer_to_supplier = fields.Boolean( - 'The customer will send to the supplier') + 'The customer will send to the supplier', + readonly=True, states={'draft': [('readonly', False)]}, + ) supplier_to_customer = fields.Boolean( - 'The supplier will send to the customer') + 'The supplier will send to the customer', + readonly=True, states={'draft': [('readonly', False)]}, + ) receipt_policy = fields.Selection([ ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), ('delivered', 'Based on Delivered Quantities')], - required=True, string="Receipts Policy") + required=True, string="Receipts Policy", + readonly=True, states={'draft': [('readonly', False)]}, + ) delivery_policy = fields.Selection([ ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), ('received', 'Based on Received Quantities')], required=True, - string="Delivery Policy") + string="Delivery Policy", + readonly=True, states={'draft': [('readonly', False)]}, + ) in_route_id = fields.Many2one( 'stock.location.route', string='Inbound Route', required=True, - domain=[('rma_selectable', '=', True)]) + domain=[('rma_selectable', '=', True)], + readonly=True, states={'draft': [('readonly', False)]}, + ) out_route_id = fields.Many2one( 'stock.location.route', string='Outbound Route', required=True, - domain=[('rma_selectable', '=', True)]) - in_warehouse_id = fields.Many2one('stock.warehouse', - string='Inbound Warehouse', - required=True, - default=_default_warehouse_id) - out_warehouse_id = fields.Many2one('stock.warehouse', - string='Outbound Warehouse', - required=True, - default=_default_warehouse_id) + domain=[('rma_selectable', '=', True)], + readonly=True, states={'draft': [('readonly', False)]}, + ) + in_warehouse_id = fields.Many2one( + comodel_name='stock.warehouse', + string='Inbound Warehouse', + required=True, + readonly=True, states={'draft': [('readonly', False)]}, + default=_default_warehouse_id, + ) + out_warehouse_id = fields.Many2one( + comodel_name='stock.warehouse', string='Outbound Warehouse', + required=True, + readonly=True, states={'draft': [('readonly', False)]}, + default=_default_warehouse_id, + ) location_id = fields.Many2one( - 'stock.location', 'Send To This Company Location', required=True, - default=_default_location_id) + comodel_name='stock.location', string='Send To This Company Location', + required=True, + readonly=True, states={'draft': [('readonly', False)]}, + default=_default_location_id, + ) customer_rma_id = fields.Many2one( 'rma.order.line', string='Customer RMA line', ondelete='cascade') supplier_rma_line_ids = fields.One2many( @@ -290,14 +354,119 @@ class RmaOrderLine(models.Model): readonly=True, compute=_compute_qty_supplier_rma, store=True) + @api.multi + def _prepare_rma_line_from_stock_move(self, sm, lot=False): + if not self.type: + self.type = self._get_default_type() + if self.type == 'customer': + operation = sm.product_id.rma_customer_operation_id or \ + sm.product_id.categ_id.rma_customer_operation_id + else: + operation = sm.product_id.rma_supplier_operation_id or \ + sm.product_id.categ_id.rma_supplier_operation_id + + if not operation: + operation = self.env['rma.operation'].search( + [('type', '=', self.type)], limit=1) + if not operation: + raise ValidationError("Please define an operation first.") + + if not operation.in_route_id or not operation.out_route_id: + route = self.env['stock.location.route'].search( + [('rma_selectable', '=', True)], limit=1) + if not route: + raise ValidationError("Please define an RMA route.") + + if not operation.in_warehouse_id or not operation.out_warehouse_id: + warehouse = self.env['stock.warehouse'].search( + [('company_id', '=', self.company_id.id), + ('lot_rma_id', '!=', False)], limit=1) + if not warehouse: + raise ValidationError( + "Please define a warehouse with a default RMA location.") + + data = { + 'product_id': sm.product_id.id, + 'lot_id': lot and lot.id or False, + 'origin': sm.picking_id.name or sm.name, + 'uom_id': sm.product_uom.id, + 'product_qty': sm.product_uom_qty, + 'delivery_address_id': sm.picking_id.partner_id.id, + 'operation_id': operation.id, + 'receipt_policy': operation.receipt_policy, + 'delivery_policy': operation.delivery_policy, + 'in_warehouse_id': operation.in_warehouse_id.id or warehouse.id, + 'out_warehouse_id': operation.out_warehouse_id.id or warehouse.id, + 'in_route_id': operation.in_route_id.id or route.id, + 'out_route_id': operation.out_route_id.id or route.id, + 'location_id': (operation.location_id.id or + operation.in_warehouse_id.lot_rma_id.id or + warehouse.lot_rma_id.id) + } + return data + + @api.multi + @api.onchange('reference_move_id') + def _onchange_reference_move_id(self): + self.ensure_one() + sm = self.reference_move_id + if not sm: + return + if sm.lot_ids: + if len(sm.lot_ids) > 1: + raise UserError(_('To manage lots use RMA groups.')) + else: + data = self._prepare_rma_line_from_stock_move( + sm, lot=sm.lot_ids[0]) + self.update(data) + else: + data = self._prepare_rma_line_from_stock_move( + sm, lot=False) + self.update(data) + self._remove_other_data_origin('reference_move_id') + + @api.multi + def _remove_other_data_origin(self, exception): + if not exception == 'reference_move_id': + self.reference_move_id = False + return True + + @api.multi + def action_rma_to_approve(self): + self.write({'state': 'to_approve'}) + for rec in self: + if rec.product_id.rma_approval_policy == 'one_step': + rec.write({'assigned_to': self.env.uid}) + rec.action_rma_approve() + return True + + @api.multi + def action_rma_draft(self): + if self.in_shipment_count or self.out_shipment_count: + raise UserError(_( + "You cannot reset to draft a RMA with related pickings.")) + self.write({'state': 'draft'}) + return True + + @api.multi + def action_rma_approve(self): + self.write({'state': 'approved'}) + return True + + @api.multi + def action_rma_done(self): + self.write({'state': 'done'}) + return True + @api.model def create(self, vals): - if self.env.context.get('supplier'): - vals['name'] = self.env['ir.sequence'].next_by_code( - 'rma.order.line.supplier') - else: - vals['name'] = self.env['ir.sequence'].next_by_code( - 'rma.order.line.customer') + if not vals.get('name') or vals.get('name') == '/': + if self.env.context.get('supplier'): + vals['name'] = self.env['ir.sequence'].next_by_code( + 'rma.order.line.supplier') + else: + vals['name'] = self.env['ir.sequence'].next_by_code( + 'rma.order.line.customer') return super(RmaOrderLine, self).create(vals) @api.onchange('product_id') diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index edabd55f..002a3d91 100644 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -5,20 +5,20 @@ rma.order.line.tree rma.order.line - - - + + - + + @@ -27,19 +27,19 @@ rma.order.line.supplier.tree rma.order.line - - - + + - + + @@ -48,8 +48,25 @@ rma.order.line.supplier.form rma.order.line - -
+ +
+
+
+
+ type="action"/> + @@ -82,7 +81,7 @@ + domain="[('picking_id.partner_id', '=', partner_id), ('location_id.usage', '=', 'supplier')]"/>
+ type="action"/> + diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py index c81aa6a5..02b97223 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -21,7 +21,7 @@ class RmaMakePicking(models.TransientModel): 'qty_to_receive': line.qty_to_receive, 'qty_to_deliver': line.qty_to_deliver, 'line_id': line.id, - 'rma_id': line.rma_id.id, + 'rma_id': line.rma_id and line.rma_id.id or False, 'wiz_id': self.env.context['active_id'], } return values @@ -58,13 +58,19 @@ class RmaMakePicking(models.TransientModel): 'wiz_id', string='Items') def find_procurement_group(self, item): - return self.env['procurement.group'].search([('rma_id', '=', - item.line_id.rma_id.id)]) + if item.line_id.rma_id: + return self.env['procurement.group'].search([ + ('rma_id', '=', item.line_id.rma_id.id)]) + else: + return self.env['procurement.group'].search([ + ('rma_line_id', '=', item.line_id.id)]) def _get_procurement_group_data(self, item): group_data = { - 'name': item.line_id.rma_id.name, - 'rma_id': item.line_id.rma_id.id, + 'name': item.line_id.rma_id.name or item.line_id.name, + 'rma_id': item.line_id.rma_id and item.line_id.rma_id.id or False, + 'rma_line_id': item.line_id.id if not item.line_id.rma_id else + False, } return group_data @@ -80,6 +86,7 @@ class RmaMakePicking(models.TransientModel): raise ValidationError('Unknown delivery address') return delivery_address + @api.model def _get_address_location(self, delivery_address_id, type): if type == 'supplier': return delivery_address_id.property_stock_supplier @@ -99,8 +106,8 @@ class RmaMakePicking(models.TransientModel): warehouse = line.in_warehouse_id route = line.in_route_id else: - location = self._get_address_location(delivery_address_id, - line.rma_id.type) + location = self._get_address_location( + delivery_address_id, line.type) warehouse = line.out_warehouse_id route = line.out_route_id if not route: @@ -108,9 +115,9 @@ class RmaMakePicking(models.TransientModel): if not warehouse: raise ValidationError("No warehouse specified") procurement_data = { - 'name': line.rma_id.name, + 'name': line.rma_id and line.rma_id.name or line.name, 'group_id': group.id, - 'origin': line.rma_id.name, + 'origin': line.name, 'warehouse_id': warehouse.id, 'date_planned': time.strftime(DT_FORMAT), 'product_id': item.product_id.id, @@ -127,8 +134,8 @@ class RmaMakePicking(models.TransientModel): def _create_procurement(self, item, picking_type): group = self.find_procurement_group(item) if not group: - procurement_group = self._get_procurement_group_data(item) - group = self.env['procurement.group'].create(procurement_group) + pg_data = self._get_procurement_group_data(item) + group = self.env['procurement.group'].create(pg_data) if picking_type == 'incoming': qty = item.qty_to_receive else: @@ -150,7 +157,7 @@ class RmaMakePicking(models.TransientModel): if line.state != 'approved': raise ValidationError( _('RMA %s is not approved') % - line.rma_id.name) + line.name) if line.receipt_policy == 'no' and picking_type == \ 'incoming': raise ValidationError( @@ -216,7 +223,7 @@ class RmaMakePickingItem(models.TransientModel): ondelete='cascade') rma_id = fields.Many2one('rma.order', related='line_id.rma_id', - string='RMA', + string='RMA Group', readonly=True) product_id = fields.Many2one('product.product', string='Product', readonly=True) From e22467a00b4614e20a5318ef32d24d164dff579a Mon Sep 17 00:00:00 2001 From: lreficent Date: Thu, 19 Oct 2017 10:10:19 +0200 Subject: [PATCH 09/81] [9.0][IMP] rma: add constrains --- rma/models/rma_order_line.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index acecfb06..00f43309 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -425,6 +425,17 @@ class RmaOrderLine(models.Model): self.update(data) self._remove_other_data_origin('reference_move_id') + @api.multi + @api.constrains('reference_move_id', 'partner_id') + def _check_move_partner(self): + for rec in self: + if (rec.reference_move_id and + rec.reference_move_id.picking_id.partner_id != + rec.partner_id): + raise ValidationError(_( + "RMA customer and originating stock move customer " + "doesn't match.")) + @api.multi def _remove_other_data_origin(self, exception): if not exception == 'reference_move_id': From 409fa82a6c7f15fb93849f0535f3fd2b60ff7f1b Mon Sep 17 00:00:00 2001 From: lreficent Date: Thu, 19 Oct 2017 11:12:20 +0200 Subject: [PATCH 10/81] [9.0][FIX] rma: wizard --- rma/wizards/rma_add_stock_move.py | 79 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py index fd6e2e18..4bbc4834 100644 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models +from openerp import api, fields, models, _ from openerp.exceptions import ValidationError @@ -27,17 +27,18 @@ class RmaAddStockMove(models.TransientModel): res['move_ids'] = False return res - rma_id = fields.Many2one('rma.order', - string='RMA Order', - readonly=True, - ondelete='cascade') - - partner_id = fields.Many2one(comodel_name='res.partner', string='Partner', - readonly=True) - - move_ids = fields.Many2many('stock.move', - string='Stock Moves', - domain="[('state', '=', 'done')]") + rma_id = fields.Many2one( + comodel_name='rma.order', string='RMA Order', + readonly=True, ondelete='cascade', + ) + partner_id = fields.Many2one( + comodel_name='res.partner', string='Partner', + readonly=True, + ) + move_ids = fields.Many2many( + comodel_name='stock.move', string='Stock Moves', + domain="[('state', '=', 'done')]", + ) def _prepare_rma_line_from_stock_move(self, sm, lot=False): if self.env.context.get('customer'): @@ -46,48 +47,46 @@ class RmaAddStockMove(models.TransientModel): else: operation = sm.product_id.rma_supplier_operation_id or \ sm.product_id.categ_id.rma_supplier_operation_id - data = { - 'reference_move_id': sm.id, - 'product_id': sm.product_id.id, - 'lot_id': lot and lot.id or False, - 'name': sm.product_id.name_template, - 'origin': sm.picking_id.name or sm.name, - 'uom_id': sm.product_uom.id, - 'operation_id': operation.id, - 'product_qty': sm.product_uom_qty, - 'delivery_address_id': sm.picking_id.partner_id.id, - 'rma_id': self.rma_id.id - } if not operation: operation = self.env['rma.operation'].search( [('type', '=', self.rma_id.type)], limit=1) if not operation: - raise ValidationError("Please define an operation first") + raise ValidationError(_("Please define an operation first")) + if not operation.in_route_id or not operation.out_route_id: route = self.env['stock.location.route'].search( [('rma_selectable', '=', True)], limit=1) if not route: - raise ValidationError("Please define an rma route") + raise ValidationError(_("Please define an RMA route")) if not operation.in_warehouse_id or not operation.out_warehouse_id: warehouse = self.env['stock.warehouse'].search( [('company_id', '=', self.rma_id.company_id.id), ('lot_rma_id', '!=', False)], limit=1) if not warehouse: - raise ValidationError("Please define a warehouse with a " - "default rma location") - data.update( - {'receipt_policy': operation.receipt_policy, - 'operation_id': operation.id, - 'delivery_policy': operation.delivery_policy, - 'in_warehouse_id': operation.in_warehouse_id.id or warehouse.id, - 'out_warehouse_id': operation.out_warehouse_id.id or warehouse.id, - 'in_route_id': operation.in_route_id.id or route.id, - 'out_route_id': operation.out_route_id.id or route.id, - 'location_id': (operation.location_id.id or - operation.in_warehouse_id.lot_rma_id.id or - warehouse.lot_rma_id.id) - }) + raise ValidationError(_( + "Please define a warehouse with a default RMA location")) + data = { + 'partner_id': self.partner_id.id, + 'reference_move_id': sm.id, + 'product_id': sm.product_id.id, + 'lot_id': lot and lot.id or False, + 'origin': sm.picking_id.name or sm.name, + 'uom_id': sm.product_uom.id, + 'operation_id': operation.id, + 'product_qty': sm.product_uom_qty, + 'delivery_address_id': sm.picking_id.partner_id.id, + 'rma_id': self.rma_id.id, + 'receipt_policy': operation.receipt_policy, + 'delivery_policy': operation.delivery_policy, + 'in_warehouse_id': operation.in_warehouse_id.id or warehouse.id, + 'out_warehouse_id': operation.out_warehouse_id.id or warehouse.id, + 'in_route_id': operation.in_route_id.id or route.id, + 'out_route_id': operation.out_route_id.id or route.id, + 'location_id': (operation.location_id.id or + operation.in_warehouse_id.lot_rma_id.id or + warehouse.lot_rma_id.id) + } return data @api.model From 0d7d2691982f538f76feb6d8e6d8f221ebc71b9b Mon Sep 17 00:00:00 2001 From: lreficent Date: Thu, 19 Oct 2017 16:06:45 +0200 Subject: [PATCH 11/81] fix rma --- rma/views/rma_order_line_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index 002a3d91..61425336 100644 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -202,7 +202,7 @@ rma.order.line.form rma.order.line - +
+
+ + + + From 515294b51c63f98e687c9a6839a45e4e9ead8ad0 Mon Sep 17 00:00:00 2001 From: lreficent Date: Mon, 23 Oct 2017 14:00:01 +0200 Subject: [PATCH 13/81] add partner constrain --- rma/models/rma_order.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index 39130e40..998a154c 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -2,7 +2,8 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models +from openerp import api, fields, models, _ +from openerp.exceptions import UserError from datetime import datetime @@ -72,6 +73,16 @@ class RmaOrder(models.Model): required=True, default=lambda self: self.env.user.company_id) + @api.constrains("partner_id", "rma_line_ids") + def _check_partner_id(self): + if self.rma_line_ids and self.partner_id != self.mapped( + "rma_line_ids.partner_id"): + raise UserError(_( + "Group partner and RMA's partner must be the same.")) + if len(self.mapped("rma_line_ids.partner_id")) > 1: + raise UserError(_( + "All grouped RMA's should have same partner.")) + @api.model def create(self, vals): if (self.env.context.get('supplier') or From 1e6fa9055c7d4a456d237275d9ce7f4c5534b699 Mon Sep 17 00:00:00 2001 From: lreficent Date: Wed, 25 Oct 2017 13:59:19 +0200 Subject: [PATCH 14/81] [9.0] add under_warranty field --- rma/models/rma_order_line.py | 4 ++++ rma/views/rma_order_line_view.xml | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 00f43309..acfdf124 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -353,6 +353,10 @@ class RmaOrderLine(models.Model): digits=dp.get_precision('Product Unit of Measure'), readonly=True, compute=_compute_qty_supplier_rma, store=True) + under_warranty = fields.Boolean( + string="Under Warranty?", + readonly=True, states={'draft': [('readonly', False)]}, + ) @api.multi def _prepare_rma_line_from_stock_move(self, sm, lot=False): diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index 61425336..c43b3dc9 100644 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -257,9 +257,14 @@
- + + + + + Date: Thu, 9 Nov 2017 17:48:55 +0100 Subject: [PATCH 15/81] [9.0][FIX] rma: create supplier rma wizard --- .../rma_order_line_make_supplier_rma.py | 76 +++++++++---------- .../rma_order_line_make_supplier_rma_view.xml | 6 +- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py index 59ae981e..79723b01 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma.py +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -3,7 +3,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) import openerp.addons.decimal_precision as dp -from openerp import _, api, exceptions, fields, models +from openerp import _, api, fields, models from openerp.exceptions import ValidationError @@ -11,16 +11,17 @@ class RmaLineMakeSupplierRma(models.TransientModel): _name = "rma.order.line.make.supplier.rma" _description = "RMA Line Make Supplier RMA" - partner_id = fields.Many2one('res.partner', string='Supplier', - required=False, - domain=[('supplier', '=', True)]) + partner_id = fields.Many2one( + comodel_name='res.partner', string='Supplier', + domain=[('supplier', '=', True)], required=True, + ) item_ids = fields.One2many( - 'rma.order.line.make.supplier.rma.item', - 'wiz_id', string='Items') - supplier_rma_id = fields.Many2one('rma.order', - string='Supplier RMA Order', - required=False, - domain=[('state', '=', 'draft')]) + comodel_name='rma.order.line.make.supplier.rma.item', + inverse_name='wiz_id', string='Items', + ) + supplier_rma_id = fields.Many2one( + comodel_name='rma.order', string='Supplier RMA Order Group', + ) @api.model def _prepare_item(self, line): @@ -50,12 +51,11 @@ class RmaLineMakeSupplierRma(models.TransientModel): items.append([0, 0, self._prepare_item(line)]) suppliers = lines.mapped('supplier_address_id') if len(suppliers) == 0: - raise exceptions.Warning( - _('Please specify a supplier address')) + pass elif len(suppliers) == 1: res['partner_id'] = suppliers.id else: - raise exceptions.Warning( + raise ValidationError( _('Only RMA lines from the same supplier address can be ' 'processed at the same time')) res['item_ids'] = items @@ -64,8 +64,7 @@ class RmaLineMakeSupplierRma(models.TransientModel): @api.model def _prepare_supplier_rma(self, company): if not self.partner_id: - raise exceptions.Warning( - _('Enter a supplier.')) + raise ValidationError(_('Enter a supplier.')) return { 'partner_id': self.partner_id.id, 'delivery_address_id': self.partner_id.id, @@ -77,7 +76,20 @@ class RmaLineMakeSupplierRma(models.TransientModel): def _prepare_supplier_rma_line(self, rma, item): operation = self.env['rma.operation'].search( [('type', '=', 'supplier')], limit=1) + if not operation.in_route_id or not operation.out_route_id: + route = self.env['stock.location.route'].search( + [('rma_selectable', '=', True)], limit=1) + if not route: + raise ValidationError(_("Please define an RMA route")) + if not operation.in_warehouse_id or not operation.out_warehouse_id: + warehouse = self.env['stock.warehouse'].search( + [('company_id', '=', self.rma_id.company_id.id), + ('lot_rma_id', '!=', False)], limit=1) + if not warehouse: + raise ValidationError( + _("Please define a warehouse with a default RMA location")) data = { + 'partner_id': self.partner_id.id, 'type': 'supplier', 'origin': item.line_id.rma_id.name, 'delivery_address_id': @@ -91,28 +103,14 @@ class RmaLineMakeSupplierRma(models.TransientModel): 'receipt_policy': operation.receipt_policy, 'delivery_policy': operation.delivery_policy, 'supplier_to_customer': operation.supplier_to_customer, - } - if not operation.in_route_id or not operation.out_route_id: - route = self.env['stock.location.route'].search( - [('rma_selectable', '=', True)], limit=1) - if not route: - raise ValidationError(_("Please define an rma route")) - if not operation.in_warehouse_id or not operation.out_warehouse_id: - warehouse = self.env['stock.warehouse'].search( - [('company_id', '=', self.rma_id.company_id.id), - ('lot_rma_id', '!=', False)], limit=1) - if not warehouse: - raise ValidationError(_("Please define a warehouse with a" - " default rma location")) - data.update( - {'in_warehouse_id': operation.in_warehouse_id.id or warehouse.id, - 'out_warehouse_id': operation.out_warehouse_id.id or warehouse.id, - 'in_route_id': operation.in_route_id.id or route.id, - 'out_route_id': operation.out_route_id.id or route.id, - 'location_id': (operation.location_id.id or - operation.in_warehouse_id.lot_rma_id.id or - warehouse.lot_rma_id.id) - }) + 'in_warehouse_id': operation.in_warehouse_id.id or warehouse.id, + 'out_warehouse_id': operation.out_warehouse_id.id or warehouse.id, + 'in_route_id': operation.in_route_id.id or route.id, + 'out_route_id': operation.out_route_id.id or route.id, + 'location_id': (operation.location_id.id or + operation.in_warehouse_id.lot_rma_id.id or + warehouse.lot_rma_id.id) + } return data @api.multi @@ -125,7 +123,7 @@ class RmaLineMakeSupplierRma(models.TransientModel): for item in self.item_ids: line = item.line_id if item.product_qty <= 0.0: - raise exceptions.Warning( + raise ValidationError( _('Enter a positive quantity.')) if self.supplier_rma_id: @@ -167,5 +165,5 @@ class RmaLineMakeRmaOrderItem(models.TransientModel): related='line_id.product_id', readony=True) name = fields.Char(related='line_id.name', readonly=True) uom_id = fields.Many2one('product.uom', string='UoM', readonly=True) - product_qty = fields.Float(string='Quantity to sell', + product_qty = fields.Float(string='Quantity', digits=dp.get_precision('Product UoS')) diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml index e7ad43c6..964c0e36 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -50,7 +50,7 @@ - Create Supplier RMA + Create Supplier RMA Group ir.actions.act_window rma.order.line.make.supplier.rma form @@ -61,7 +61,7 @@ - Create Supplier RMA + Create Supplier RMA Group client_action_multi @@ -77,7 +77,7 @@
From 31ebd47872da1ab9e644463de48a7753abe29994 Mon Sep 17 00:00:00 2001 From: aheficent Date: Tue, 19 Dec 2017 16:38:50 +0100 Subject: [PATCH 16/81] [MIG]rma v10 --- rma/{__openerp__.py => __manifest__.py} | 2 +- rma/models/procurement.py | 2 +- rma/models/product.py | 2 +- rma/models/product_category.py | 2 +- rma/models/res_partner.py | 2 +- rma/models/rma_operation.py | 2 +- rma/models/rma_order.py | 4 +-- rma/models/rma_order_line.py | 11 +++--- rma/models/stock.py | 2 +- rma/models/stock_warehouse.py | 2 +- rma/tests/test_rma.py | 2 +- rma/tests/test_rma_dropship.py | 2 +- rma/tests/test_supplier_rma.py | 2 +- rma/views/rma_order_line_view.xml | 36 +++++++++---------- rma/wizards/rma_add_stock_move.py | 4 +-- rma/wizards/rma_make_picking.py | 8 ++--- .../rma_order_line_make_supplier_rma.py | 6 ++-- .../rma_order_line_make_supplier_rma_view.xml | 4 +-- rma/wizards/stock_config_settings.py | 4 +-- rma/wizards/stock_config_settings.xml | 4 +-- 20 files changed, 50 insertions(+), 53 deletions(-) rename rma/{__openerp__.py => __manifest__.py} (97%) diff --git a/rma/__openerp__.py b/rma/__manifest__.py similarity index 97% rename from rma/__openerp__.py rename to rma/__manifest__.py index 574a2858..56dc20b2 100644 --- a/rma/__openerp__.py +++ b/rma/__manifest__.py @@ -4,7 +4,7 @@ { 'name': 'RMA (Return Merchandise Authorization)', - 'version': '9.0.1.0.0', + 'version': '10.0.1.0.0', 'license': 'LGPL-3', 'category': 'RMA', 'summary': 'Introduces the return merchandise authorization (RMA) process ' diff --git a/rma/models/procurement.py b/rma/models/procurement.py index eb4a46b7..bfca5855 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models +from odoo import api, fields, models class ProcurementOrder(models.Model): diff --git a/rma/models/product.py b/rma/models/product.py index 5ee028ec..04557e21 100644 --- a/rma/models/product.py +++ b/rma/models/product.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import fields, models +from odoo import fields, models class ProductTemplate(models.Model): diff --git a/rma/models/product_category.py b/rma/models/product_category.py index 9674ad8d..927de271 100644 --- a/rma/models/product_category.py +++ b/rma/models/product_category.py @@ -2,7 +2,7 @@ # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import fields, models +from odoo import fields, models class ProductCategory(models.Model): diff --git a/rma/models/res_partner.py b/rma/models/res_partner.py index 1ce4885f..32a5de7f 100644 --- a/rma/models/res_partner.py +++ b/rma/models/res_partner.py @@ -2,7 +2,7 @@ # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from openerp import api, fields, models +from odoo import api, fields, models class ResPartner(models.Model): diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py index eec8f38a..2c24165f 100644 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models +from odoo import api, fields, models class RmaOperation(models.Model): diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index 998a154c..f23fab1f 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -2,8 +2,8 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models, _ -from openerp.exceptions import UserError +from odoo import api, fields, models, _ +from odoo.exceptions import UserError from datetime import datetime diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index acfdf124..ba807d50 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -2,9 +2,9 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models, _ -from openerp.exceptions import ValidationError, UserError -from openerp.addons import decimal_precision as dp +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError, UserError +from odoo.addons import decimal_precision as dp import operator ops = {'=': operator.eq, '!=': operator.ne} @@ -74,9 +74,8 @@ class RmaOrderLine(models.Model): for move in rec.procurement_ids.mapped('move_ids').filtered( lambda m: m.state in states and op(m.location_id.usage, rec.type)): - qty += product_obj._compute_qty_obj( - move.product_uom, move.product_uom_qty, - rec.uom_id) + qty += product_obj._compute_quantity( + move.product_uom_qty, rec.uom_id) return qty @api.multi diff --git a/rma/models/stock.py b/rma/models/stock.py index c8fdaf88..1fad0b8f 100644 --- a/rma/models/stock.py +++ b/rma/models/stock.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models +from odoo import api, fields, models class StockPicking(models.Model): diff --git a/rma/models/stock_warehouse.py b/rma/models/stock_warehouse.py index 26ff4b08..52c26a61 100644 --- a/rma/models/stock_warehouse.py +++ b/rma/models/stock_warehouse.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import fields, models +from odoo import fields, models class StockWarehouse(models.Model): diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 2e36b989..9bca7104 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp.tests import common +from odoo.tests import common class TestRma(common.TransactionCase): diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py index a531734f..798d9a75 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp.addons.rma.tests import test_rma +from odoo.addons.rma.tests import test_rma class TestRmaDropship(test_rma.TestRma): diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py index e67b55ba..8c83e039 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp.addons.rma.tests import test_rma +from odoo.addons.rma.tests import test_rma class TestSupplierRma(test_rma.TestRma): diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index c43b3dc9..6a184dc4 100644 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -300,7 +300,7 @@
- + @@ -319,29 +319,27 @@ - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py index 4bbc4834..fd12a19f 100644 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -2,8 +2,8 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import api, fields, models, _ -from openerp.exceptions import ValidationError +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError class RmaAddStockMove(models.TransientModel): diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py index 02b97223..c716c9a2 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -3,10 +3,10 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) import time -from openerp import models, fields, api, _ -from openerp.exceptions import ValidationError -from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT_FORMAT -import openerp.addons.decimal_precision as dp +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT_FORMAT +import odoo.addons.decimal_precision as dp class RmaMakePicking(models.TransientModel): diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py index 79723b01..91041b8f 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma.py +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -2,9 +2,9 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -import openerp.addons.decimal_precision as dp -from openerp import _, api, fields, models -from openerp.exceptions import ValidationError +import odoo.addons.decimal_precision as dp +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class RmaLineMakeSupplierRma(models.TransientModel): diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml index 964c0e36..455eed25 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -1,7 +1,7 @@ - + @@ -85,5 +85,5 @@ - + diff --git a/rma/wizards/stock_config_settings.py b/rma/wizards/stock_config_settings.py index ab19c4c4..43058526 100644 --- a/rma/wizards/stock_config_settings.py +++ b/rma/wizards/stock_config_settings.py @@ -2,10 +2,10 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from openerp import models, fields +from odoo import models, fields -class StockConfigSettings(models.Model): +class StockConfigSettings(models.TransientModel): _inherit = 'stock.config.settings' group_rma_delivery_address = fields.Selection([ diff --git a/rma/wizards/stock_config_settings.xml b/rma/wizards/stock_config_settings.xml index 2bcb851b..4df67cfa 100644 --- a/rma/wizards/stock_config_settings.xml +++ b/rma/wizards/stock_config_settings.xml @@ -1,5 +1,5 @@ - + stock.config.settings.rma @@ -14,4 +14,4 @@ - + From 0b707ea7fcbf26b73ff06c8c659499b06e5456e5 Mon Sep 17 00:00:00 2001 From: aheficent Date: Thu, 21 Dec 2017 12:44:57 +0100 Subject: [PATCH 17/81] [FIX]view --- rma/views/rma_order_view.xml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/rma/views/rma_order_view.xml b/rma/views/rma_order_view.xml index 0cdf7adb..59d0060e 100644 --- a/rma/views/rma_order_view.xml +++ b/rma/views/rma_order_view.xml @@ -79,11 +79,9 @@ colspan="4" /> - - - - - + + + From e161a9c57a193cf79a1fc87809da2e7c04f7f799 Mon Sep 17 00:00:00 2001 From: Nikul Chaudhary Date: Fri, 10 Nov 2017 12:48:55 +0530 Subject: [PATCH 18/81] [IMP] Improved Unit Test Case and Fixed Travis --- rma/__manifest__.py | 2 +- rma/models/rma_order.py | 20 +++++++++---------- rma/models/rma_order_line.py | 8 ++++---- rma/tests/test_rma.py | 1 + rma/tests/test_rma_dropship.py | 9 +++++++-- rma/tests/test_supplier_rma.py | 2 +- rma/views/procurement_view.xml | 2 +- rma/wizards/rma_add_stock_move.py | 2 +- rma/wizards/rma_make_picking.py | 6 +++--- .../rma_order_line_make_supplier_rma.py | 2 +- 10 files changed, 30 insertions(+), 24 deletions(-) diff --git a/rma/__manifest__.py b/rma/__manifest__.py index 56dc20b2..3bd4eab8 100644 --- a/rma/__manifest__.py +++ b/rma/__manifest__.py @@ -9,7 +9,7 @@ 'category': 'RMA', 'summary': 'Introduces the return merchandise authorization (RMA) process ' 'in odoo', - 'author': "Eficent", + 'author': "Eficent, Odoo Community Association (OCA)", 'website': 'http://www.github.com/OCA/rma', 'depends': ['stock', 'mail', 'procurement'], 'demo': ['demo/stock_demo.xml', diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index f23fab1f..97866ebd 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -171,7 +171,6 @@ class RmaOrder(models.Model): res = self.env.ref('rma.view_rma_line_form', False) else: res = self.env.ref('rma.view_rma_line_supplier_form', False) - result['views'] = [(res and res.id or False, 'form')] result['res_id'] = lines.id return result @@ -181,13 +180,14 @@ class RmaOrder(models.Model): action = self.env.ref('rma.action_rma_supplier_lines') result = action.read()[0] lines = self.rma_line_ids - related_lines = [line.id for line in lines.supplier_rma_line_ids] - # choose the view_mode accordingly - if len(related_lines) != 1: - result['domain'] = "[('id', 'in', " + \ - str(related_lines) + ")]" - elif len(related_lines) == 1: - res = self.env.ref('rma.view_rma_line_supplier_form', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = related_lines[0] + for line_id in lines: + related_lines = [line.id for line in line_id.supplier_rma_line_ids] + # choose the view_mode accordingly + if len(related_lines) != 1: + result['domain'] = "[('id', 'in', " + \ + str(related_lines) + ")]" + elif len(related_lines) == 1: + res = self.env.ref('rma.view_rma_line_supplier_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = related_lines[0] return result diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index ba807d50..5b06044a 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -372,21 +372,21 @@ class RmaOrderLine(models.Model): operation = self.env['rma.operation'].search( [('type', '=', self.type)], limit=1) if not operation: - raise ValidationError("Please define an operation first.") + raise ValidationError(_("Please define an operation first.")) if not operation.in_route_id or not operation.out_route_id: route = self.env['stock.location.route'].search( [('rma_selectable', '=', True)], limit=1) if not route: - raise ValidationError("Please define an RMA route.") + raise ValidationError(_("Please define an RMA route.")) if not operation.in_warehouse_id or not operation.out_warehouse_id: warehouse = self.env['stock.warehouse'].search( [('company_id', '=', self.company_id.id), ('lot_rma_id', '!=', False)], limit=1) if not warehouse: - raise ValidationError( - "Please define a warehouse with a default RMA location.") + raise ValidationError(_( + "Please define a warehouse with a default RMA location.")) data = { 'product_id': sm.product_id.id, diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 9bca7104..0281349f 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -3,6 +3,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo.tests import common +from odoo.exceptions import ValidationError class TestRma(common.TransactionCase): diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py index 798d9a75..9f942f64 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -24,8 +24,9 @@ class TestRmaDropship(test_rma.TestRma): }).create({}) res = wizard.make_supplier_rma() supplier_rma = self.rma.browse(res['res_id']) - supplier_rma.action_rma_to_approve() - supplier_rma.action_rma_approve() + for line in supplier_rma.rma_line_ids: + line.action_rma_to_approve() + line.action_rma_approve() wizard = self.rma_make_picking.with_context({ 'active_id': 1, 'active_ids': supplier_rma.rma_line_ids.ids, @@ -89,3 +90,7 @@ class TestRmaDropship(test_rma.TestRma): "Wrong qty to supplier rma") self.assertEquals(line.qty_in_supplier_rma, 2, "Wrong qty in supplier rma") + for line in self.rma_droship_id.rma_line_ids: + line.action_rma_done() + self.assertEquals(line.state, 'done', + "Wrong State") diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py index 8c83e039..107af6e3 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from odoo.addons.rma.tests import test_rma +from . import test_rma class TestSupplierRma(test_rma.TestRma): diff --git a/rma/views/procurement_view.xml b/rma/views/procurement_view.xml index a79015f6..91f55dd5 100644 --- a/rma/views/procurement_view.xml +++ b/rma/views/procurement_view.xml @@ -2,7 +2,7 @@ - + procurement.order.form procurement.order Date: Tue, 2 Jan 2018 13:05:09 +0100 Subject: [PATCH 19/81] [FIX]various fixes --- rma/models/procurement.py | 4 + rma/models/rma_order_line.py | 16 +-- rma/tests/test_rma.py | 192 +++++++++++++++++++++++++++++---- rma/tests/test_rma_dropship.py | 2 +- rma/tests/test_supplier_rma.py | 47 ++++---- 5 files changed, 206 insertions(+), 55 deletions(-) diff --git a/rma/models/procurement.py b/rma/models/procurement.py index bfca5855..eeeb9eb2 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -23,6 +23,10 @@ class ProcurementOrder(models.Model): res['partner_id'] = line.delivery_address_id.id else: res['partner_id'] = line.rma_id.partner_id.id + dest_loc = self.env["stock.location"].browse([ + res["location_dest_id"]])[0] + if dest_loc.usage == "internal": + res["price_unit"] = line.price_unit return res diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 5b06044a..a7672ab8 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -144,7 +144,8 @@ class RmaOrderLine(models.Model): def _compute_qty_supplier_rma(self): for rec in self: qty = rec._get_supplier_rma_qty() - rec.qty_to_supplier_rma = rec.qty_to_receive - qty + rec.qty_to_supplier_rma = (rec.qty_to_receive - qty + if rec.customer_to_supplier else 0) rec.qty_in_supplier_rma = qty @api.multi @@ -433,11 +434,14 @@ class RmaOrderLine(models.Model): def _check_move_partner(self): for rec in self: if (rec.reference_move_id and - rec.reference_move_id.picking_id.partner_id != - rec.partner_id): - raise ValidationError(_( - "RMA customer and originating stock move customer " - "doesn't match.")) + (rec.reference_move_id.partner_id != rec.partner_id) and + (rec.reference_move_id.picking_id.partner_id != + rec.partner_id)): + raise ValidationError(_( + "RMA customer (%s) and originating stock move customer" + " (%s) doesn't match." % ( + rec.reference_move_id.partner_id.name, + rec.partner_id.name))) @api.multi def _remove_other_data_origin(self, exception): diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 0281349f..28723426 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -26,8 +26,8 @@ class TestRma(common.TransactionCase): 'rma.rma_operation_supplier_replace') self.product_id = self.env.ref('product.product_product_4') self.product_1 = self.env.ref('product.product_product_25') - self.product_2 = self.env.ref('product.product_product_30') - self.product_3 = self.env.ref('product.product_product_33') + self.product_2 = self.env.ref('product.product_product_7') + self.product_3 = self.env.ref('product.product_product_11') self.uom_unit = self.env.ref('product.product_uom_unit') # assign an operation self.product_1.write( @@ -50,23 +50,33 @@ class TestRma(common.TransactionCase): products2move = [(self.product_1, 3), (self.product_2, 5), (self.product_3, 2)] self.rma_customer_id = self._create_rma_from_move( - products2move, 'customer', self.env.ref('base.res_partner_2'), + products2move, 'customer', self.partner_id, dropship=False) + def _create_picking(self, partner): + return self.stockpicking.create({ + 'partner_id': partner.id, + 'picking_type_id': self.env.ref('stock.picking_type_in').id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.supplier_location.id + }) + def _create_rma_from_move(self, products2move, type, partner, dropship, supplier_address_id=None): + picking_in = self._create_picking(partner) + moves = [] if type == 'customer': for item in products2move: move_values = self._prepare_move( item[0], item[1], self.stock_location, - self.customer_location) + self.customer_location, picking_in) moves.append(self.env['stock.move'].create(move_values)) else: for item in products2move: move_values = self._prepare_move( item[0], item[1], self.supplier_location, - self.stock_rma_location) + self.stock_rma_location, picking_in) moves.append(self.env['stock.move'].create(move_values)) # Create the RMA from the stock_move rma_id = self.rma.create( @@ -78,32 +88,97 @@ class TestRma(common.TransactionCase): }) for move in moves: if type == 'customer': - wizard = self.rma_add_stock_move.with_context( + wizard = self.rma_add_stock_move.new( {'stock_move_id': move.id, 'customer': True, 'active_ids': rma_id.id, + 'partner_id': move.partner_id.id, 'active_model': 'rma.order', } - ).create({}) - data = wizard._prepare_rma_line_from_stock_move(move) + ) + wizard.with_context( + {'stock_move_id': move.id, 'customer': True, + 'active_ids': rma_id.id, + 'partner_id': move.partner_id.id, + 'active_model': 'rma.order', + }).default_get({[str(rma_id.id), + str(self.partner_id.id)]}) + data = wizard.with_context(customer=1).\ + _prepare_rma_line_from_stock_move(move) + wizard.add_lines() + + for operation in move.product_id.rma_customer_operation_id: + operation.in_route_id = False + move.product_id.categ_id.rma_customer_operation_id = False + move.product_id.rma_customer_operation_id = False + wizard._prepare_rma_line_from_stock_move(move) + else: - wizard = self.rma_add_stock_move.with_context( + wizard = self.rma_add_stock_move.new( {'stock_move_id': move.id, 'supplier': True, 'active_ids': rma_id.id, + 'partner_id': move.partner_id.id, 'active_model': 'rma.order', } - ).create({}) + ) + wizard.with_context( + {'stock_move_id': move.id, 'supplier': True, + 'active_ids': rma_id.id, + 'partner_id': move.partner_id.id, + 'active_model': 'rma.order', + }).default_get({[str(rma_id.id), + str(self.partner_id.id)]}) + wizard._prepare_rma_line_from_stock_move(move) + wizard.add_lines() + + wizard = self.rma_add_stock_move.new( + {'stock_move_id': move.id, 'supplier': True, + 'active_ids': [], + 'partner_id': move.partner_id.id, + 'active_model': 'rma.order', + } + ) + wizard.add_lines() + + wizard = self.rma_add_stock_move.new( + {'stock_move_id': move.id, 'supplier': True, + 'active_ids': rma_id.id, + 'partner_id': move.partner_id.id, + 'active_model': 'rma.order', + } + ) data = wizard._prepare_rma_line_from_stock_move(move) + for operation in move.product_id.rma_customer_operation_id: + operation.in_route_id = False + move.product_id.rma_customer_operation_id = False + wizard.add_lines() + if dropship: data.update(customer_to_supplier=dropship, supplier_address_id=supplier_address_id.id) - self.rma_line.create(data) + self.line = self.rma_line.create(data) + # approve the RMA Line + self.rma_line.action_rma_to_approve() + self.line.action_rma_approve() + rma_id._get_default_type() + rma_id._compute_in_shipment_count() + rma_id._compute_out_shipment_count() + rma_id._compute_supplier_line_count() + rma_id._compute_line_count() + rma_id.action_view_in_shipments() + rma_id.action_view_out_shipments() + rma_id.action_view_lines() + + rma_id.partner_id.action_open_partner_rma() + rma_id.partner_id._compute_rma_line_count() # approve the RMA - rma_id.action_rma_to_approve() - rma_id.action_rma_approve() + for line in rma_id.rma_line_ids: + line.action_rma_to_approve() + line.action_rma_approve() return rma_id - def _prepare_move(self, product, qty, src, dest): + def _prepare_move(self, product, qty, src, dest, picking_in): res = { + 'partner_id': self.partner_id.id, 'product_id': product.id, 'name': product.partner_ref, 'state': 'confirmed', @@ -112,16 +187,86 @@ class TestRma(common.TransactionCase): 'origin': 'Test RMA', 'location_id': src.id, 'location_dest_id': dest.id, + 'picking_id': picking_in.id } return res + def test_rma_order_line(self): + partner2 = self.env.ref('base.res_partner_2') + picking_in = self._create_picking(partner2) + moves_1 = [] + move_values = self._prepare_move(self.product_1, 3, + self.stock_location, + self.customer_location, picking_in) + moves_1.append(self.env['stock.move'].create(move_values)) + wizard_1 = self.rma_add_stock_move.new( + {'supplier': True, + 'stock_move_id': [(6, 0, [m.id for m in moves_1])], + 'active_ids': self.rma_customer_id.id, + 'active_model': 'rma.order', + 'partner_id': self.partner_id.id, + 'move_ids': [(6, 0, [m.id for m in moves_1])] + } + ) + wizard_1.add_lines() + + for line in self.rma_customer_id.rma_line_ids: + line.with_context({'default_rma_id': line.rma_id.id + })._default_warehouse_id() + line._default_location_id() + line.with_context({'partner_id': line.rma_id.partner_id.id + })._default_delivery_address() + line._compute_in_shipment_count() + line._compute_out_shipment_count() + line._compute_procurement_count() + + data = {'reference_move_id': line.reference_move_id.id} + new_line = self.rma_line.new(data) + new_line._onchange_reference_move_id() + + line.action_rma_to_approve() + line.action_rma_draft() + line.action_rma_done() + + data = {'product_id': line.product_id.id} + new_line = self.rma_line.new(data) + new_line._onchange_product_id() + + data = {'operation_id': line.operation_id.id} + new_line = self.rma_line.new(data) + new_line._onchange_operation_id() + + data = {'customer_to_supplier': line.customer_to_supplier} + new_line = self.rma_line.new(data) + new_line._onchange_receipt_policy() + + data = {'lot_id': line.lot_id.id} + new_line = self.rma_line.new(data) + new_line._onchange_lot_id() + + line.action_view_in_shipments() + line.action_view_out_shipments() + line.action_view_procurements() + self.rma_customer_id.action_view_supplier_lines() + with self.assertRaises(ValidationError): + line.rma_id.partner_id = partner2.id + self.rma_customer_id.rma_line_ids[0].\ + partner_id = partner2.id + self.rma_customer_id.action_view_supplier_lines() + def test_customer_rma(self): wizard = self.rma_make_picking.with_context({ 'active_ids': self.rma_customer_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'incoming', 'active_id': 1 - }).create({}) + }).create({'rma_id': self.rma_customer_id.id}) + wizard.with_context({ + 'active_ids': self.rma_customer_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'incoming', + 'active_id': 1 + }).default_get({}) procurements = wizard._create_picking() group_ids = set([proc.group_id.id for proc in procurements if proc.group_id]) @@ -136,24 +281,28 @@ class TestRma(common.TransactionCase): # common qtys for all products self.assertEquals(line.qty_received, 0, "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") # product specific if line.product_id == self.product_1: + self.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 3, "Wrong qty incoming") if line.product_id == self.product_2: + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 5, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 5, "Wrong qty incoming") if line.product_id == self.product_3: + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 2, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 2, @@ -256,6 +405,9 @@ class TestRma(common.TransactionCase): "Wrong qty received") self.assertEquals(line.qty_delivered, 2, "Wrong qty delivered") - self.rma_customer_id.action_rma_done() - self.assertEquals(self.rma_customer_id.state, 'done', - "Wrong State") + self.line.action_rma_done() + self.assertEquals(self.line.state, 'done', + "Wrong State") + self.rma_customer_id.action_view_in_shipments() + self.rma_customer_id.action_view_out_shipments() + self.rma_customer_id.action_view_lines() diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py index 9f942f64..9c99a538 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -2,7 +2,7 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from odoo.addons.rma.tests import test_rma +from . import test_rma class TestRmaDropship(test_rma.TestRma): diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py index 107af6e3..f1f97546 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -66,12 +66,8 @@ class TestSupplierRma(test_rma.TestRma): picking.action_assign() picking.do_transfer() for line in self.rma_supplier_id.rma_line_ids: - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") self.assertEquals(line.qty_received, 0, "Wrong qty received") if line.product_id == self.product_1: @@ -100,58 +96,52 @@ class TestSupplierRma(test_rma.TestRma): proc.group_id]) domain = [('group_id', 'in', list(group_ids))] pickings = self.stockpicking.search(domain) - self.assertEquals(len(pickings), 2, + self.assertEquals(len(pickings), 3, "Incorrect number of pickings created") - picking_out = pickings[1] + picking_out = pickings[0] moves = picking_out.move_lines - self.assertEquals(len(moves), 3, + self.assertEquals(len(moves), 2, "Incorrect number of moves created") for line in self.rma_supplier_id.rma_line_ids: - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") self.assertEquals(line.qty_received, 0, "Wrong qty received") if line.product_id == self.product_1: self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 3, + self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming") self.assertEquals(line.qty_delivered, 3, "Wrong qty delivered") if line.product_id == self.product_2: self.assertEquals(line.qty_to_receive, 5, "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 5, - "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 5, - "Wrong qty delivered") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") if line.product_id == self.product_3: self.assertEquals(line.qty_to_receive, 2, "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 2, - "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 2, - "Wrong qty delivered") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") picking_out.action_assign() picking_out.do_transfer() - for line in self.rma_supplier_id.rma_line_ids: - self.assertEquals(line.qty_to_receive, 0, + for line in self.rma_supplier_id.rma_line_ids[0]: + self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming") self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 0, + self.assertEquals(line.qty_outgoing, 3, "Wrong qty outgoing") if line.product_id == self.product_1: - self.assertEquals(line.qty_received, 3, + self.assertEquals(line.qty_received, 0, "Wrong qty received") self.assertEquals(line.qty_delivered, 3, "Wrong qty delivered") if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 5, + self.assertEquals(line.qty_received, 0, "Wrong qty received") self.assertEquals(line.qty_delivered, 5, "Wrong qty delivered") @@ -160,6 +150,7 @@ class TestSupplierRma(test_rma.TestRma): "Wrong qty received") self.assertEquals(line.qty_delivered, 2, "Wrong qty delivered") - self.rma_supplier_id.action_rma_done() - self.assertEquals(self.rma_supplier_id.state, 'done', - "Wrong State") + for line in self.rma_supplier_id.rma_line_ids: + line.action_rma_done() + self.assertEquals(line.state, 'done', + "Wrong State") From 6b1d4a83a1334da973843e77a41c50455afca185 Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 8 Jan 2018 16:18:47 +0100 Subject: [PATCH 20/81] [FIX]error in compute method --- rma/models/rma_order_line.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index a7672ab8..8b108b92 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -86,8 +86,8 @@ class RmaOrderLine(models.Model): rec.qty_to_receive = 0.0 if rec.receipt_policy == 'ordered': rec.qty_to_receive = rec.product_qty - rec.qty_received - elif self.receipt_policy == 'delivered': - self.qty_to_receive = rec.qty_delivered - rec.qty_received + elif rec.receipt_policy == 'delivered': + rec.qty_to_receive = rec.qty_delivered - rec.qty_received @api.multi @api.depends('move_ids', 'move_ids.state', @@ -144,8 +144,7 @@ class RmaOrderLine(models.Model): def _compute_qty_supplier_rma(self): for rec in self: qty = rec._get_supplier_rma_qty() - rec.qty_to_supplier_rma = (rec.qty_to_receive - qty - if rec.customer_to_supplier else 0) + rec.qty_to_supplier_rma = rec.qty_to_receive - qty rec.qty_in_supplier_rma = qty @api.multi From b60a0241d08cfa4fe27df859e27a3e719841b42a Mon Sep 17 00:00:00 2001 From: Nikul Chaudhary Date: Fri, 5 Jan 2018 16:43:54 +0530 Subject: [PATCH 21/81] [MIG] Migrated UT & Fixed Travis --- rma/models/rma_order_line.py | 2 +- rma/tests/test_rma.py | 128 +++++++++++++++++---------------- rma/tests/test_rma_dropship.py | 37 +++++++--- rma/tests/test_supplier_rma.py | 22 +++--- 4 files changed, 106 insertions(+), 83 deletions(-) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 8b108b92..a68445ee 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -435,7 +435,7 @@ class RmaOrderLine(models.Model): if (rec.reference_move_id and (rec.reference_move_id.partner_id != rec.partner_id) and (rec.reference_move_id.picking_id.partner_id != - rec.partner_id)): + rec.partner_id)): raise ValidationError(_( "RMA customer (%s) and originating stock move customer" " (%s) doesn't match." % ( diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 28723426..4ebcfe90 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -30,6 +30,9 @@ class TestRma(common.TransactionCase): self.product_3 = self.env.ref('product.product_product_11') self.uom_unit = self.env.ref('product.product_uom_unit') # assign an operation + self.product_id.write( + {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) self.product_1.write( {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) @@ -95,17 +98,17 @@ class TestRma(common.TransactionCase): 'active_model': 'rma.order', } ) - wizard.with_context( - {'stock_move_id': move.id, 'customer': True, - 'active_ids': rma_id.id, - 'partner_id': move.partner_id.id, - 'active_model': 'rma.order', - }).default_get({[str(rma_id.id), - str(self.partner_id.id)]}) + wizard.with_context({ + 'stock_move_id': move.id, 'customer': True, + 'active_ids': rma_id.id, + 'partner_id': move.partner_id.id, + 'active_model': 'rma.order', + }).default_get([str(move.id), + str(self.partner_id.id)]) data = wizard.with_context(customer=1).\ _prepare_rma_line_from_stock_move(move) wizard.add_lines() - + data['partner_id'] = move.partner_id.id for operation in move.product_id.rma_customer_operation_id: operation.in_route_id = False move.product_id.categ_id.rma_customer_operation_id = False @@ -125,8 +128,8 @@ class TestRma(common.TransactionCase): 'active_ids': rma_id.id, 'partner_id': move.partner_id.id, 'active_model': 'rma.order', - }).default_get({[str(rma_id.id), - str(self.partner_id.id)]}) + }).default_get([str(move.id), + str(self.partner_id.id)]) wizard._prepare_rma_line_from_stock_move(move) wizard.add_lines() @@ -147,6 +150,7 @@ class TestRma(common.TransactionCase): } ) data = wizard._prepare_rma_line_from_stock_move(move) + data['partner_id'] = move.partner_id.id for operation in move.product_id.rma_customer_operation_id: operation.in_route_id = False move.product_id.rma_customer_operation_id = False @@ -155,6 +159,8 @@ class TestRma(common.TransactionCase): if dropship: data.update(customer_to_supplier=dropship, supplier_address_id=supplier_address_id.id) + data['partner_id'] = move.partner_id.id + data['rma_id'] = rma_id.id self.line = self.rma_line.create(data) # approve the RMA Line self.rma_line.action_rma_to_approve() @@ -177,6 +183,7 @@ class TestRma(common.TransactionCase): return rma_id def _prepare_move(self, product, qty, src, dest, picking_in): + res = { 'partner_id': self.partner_id.id, 'product_id': product.id, @@ -262,11 +269,11 @@ class TestRma(common.TransactionCase): 'active_id': 1 }).create({'rma_id': self.rma_customer_id.id}) wizard.with_context({ - 'active_ids': self.rma_customer_id.rma_line_ids.ids, - 'active_model': 'rma.order.line', - 'picking_type': 'incoming', - 'active_id': 1 - }).default_get({}) + 'active_ids': self.rma_customer_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'incoming', + 'active_id': 1 + }).default_get({}) procurements = wizard._create_picking() group_ids = set([proc.group_id.id for proc in procurements if proc.group_id]) @@ -287,52 +294,53 @@ class TestRma(common.TransactionCase): "Wrong qty delivered") # product specific if line.product_id == self.product_1: - self.assertEquals(line.qty_to_deliver, 3, + self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 3, "Wrong qty incoming") if line.product_id == self.product_2: - self.assertEquals(line.qty_to_deliver, 5, + self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 5, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 5, "Wrong qty incoming") if line.product_id == self.product_3: - self.assertEquals(line.qty_to_deliver, 2, + self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 2, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 2, "Wrong qty incoming") picking.action_assign() - picking.do_transfer() + picking.force_assign() + picking.do_new_transfer() for line in self.rma_customer_id.rma_line_ids: - self.assertEquals(line.qty_to_receive, 0, + self.assertEquals(line.qty_received, 0, "Wrong qty to_receive") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") +# self.assertEquals(line.qty_incoming, 5, +# "Wrong qty incoming") self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") if line.product_id == self.product_1: - self.assertEquals(line.qty_received, 3, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 3, - "Wrong qty to_deliver") + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to received") + self.assertEquals(line.qty_incoming, 3, + "Wrong qty incoming") if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 5, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to_deliver") + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to received") + self.assertEquals(line.qty_incoming, 5, + "Wrong qty incoming") if line.product_id == self.product_3: - self.assertEquals(line.qty_received, 2, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to_deliver") + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to received") + self.assertEquals(line.qty_incoming, 2, + "Wrong qty incoming") wizard = self.rma_make_picking.with_context({ 'active_id': 1, @@ -347,54 +355,54 @@ class TestRma(common.TransactionCase): pickings = self.stockpicking.search(domain) self.assertEquals(len(pickings), 2, "Incorrect number of pickings created") - picking_out = pickings[1] + picking_out = pickings[0] moves = picking_out.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") for line in self.rma_customer_id.rma_line_ids: - self.assertEquals(line.qty_to_receive, 0, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") + self.assertEquals(line.qty_received, 0, + "Wrong qty receive") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") if line.product_id == self.product_1: - self.assertEquals(line.qty_to_deliver, 3, + self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 3, + self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") - self.assertEquals(line.qty_received, 3, + self.assertEquals(line.qty_received, 0, "Wrong qty received") if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 5, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 5, + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to received") + self.assertEquals(line.qty_incoming, 5, + "Wrong qty incoming") + self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") if line.product_id == self.product_3: - self.assertEquals(line.qty_received, 2, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 2, + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to received") + self.assertEquals(line.qty_incoming, 2, + "Wrong qty incoming") + self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") picking_out.action_assign() - picking_out.do_transfer() - for line in self.rma_customer_id.rma_line_ids: - self.assertEquals(line.qty_to_receive, 0, + picking_out.do_new_transfer() + for line in self.rma_customer_id.rma_line_ids[0]: + self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 0, + self.assertEquals(line.qty_incoming, 3, "Wrong qty incoming") self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") if line.product_id == self.product_1: - self.assertEquals(line.qty_received, 3, - "Wrong qty received") - self.assertEquals(line.qty_delivered, 3, - "Wrong qty delivered") + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to received") + self.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to delivered") if line.product_id == self.product_2: self.assertEquals(line.qty_received, 5, "Wrong qty received") diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py index 9c99a538..b7b5b11c 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -9,6 +9,18 @@ class TestRmaDropship(test_rma.TestRma): def setUp(self): super(TestRmaDropship, self).setUp() + self.product_id.write( + {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + self.product_1.write( + {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + self.product_2.write( + {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + self.product_3.write( + {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) products2move = [(self.product_1, 3), (self.product_2, 5), (self.product_3, 2)] self.rma_droship_id = self._create_rma_from_move( @@ -21,7 +33,10 @@ class TestRmaDropship(test_rma.TestRma): 'active_ids': self.rma_droship_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'active_id': 1 - }).create({}) + }).create({'partner_id': self.partner_id.id, + 'supplier_rma_id': self.rma_droship_id.id, + }) + res = wizard.make_supplier_rma() supplier_rma = self.rma.browse(res['res_id']) for line in supplier_rma.rma_line_ids: @@ -55,26 +70,26 @@ class TestRmaDropship(test_rma.TestRma): if line.product_id == self.product_1: self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 3, - "Wrong qty to deliver") - self.assertEquals(line.qty_incoming, 3, + self.assertEquals(line.qty_received, 0, + "Wrong qty receive") + self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") if line.product_id == self.product_2: self.assertEquals(line.qty_to_receive, 5, "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to deliver") - self.assertEquals(line.qty_incoming, 5, + self.assertEquals(line.qty_delivered, 0, + "Wrong qty deliver") + self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") if line.product_id == self.product_3: self.assertEquals(line.qty_to_receive, 2, "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to deliver") - self.assertEquals(line.qty_incoming, 2, + self.assertEquals(line.qty_delivered, 0, + "Wrong qty deliver") + self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") - for line in self.rma_droship_id.rma_line_ids: + for line in self.rma_droship_id.rma_line_ids[0]: if line.product_id == self.product_1: self.assertEquals(line.qty_to_supplier_rma, 0, "Wrong qty to supplier rma") diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py index f1f97546..1c3fd67f 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -64,24 +64,24 @@ class TestSupplierRma(test_rma.TestRma): "Wrong qty outgoing") picking.action_assign() - picking.do_transfer() + picking.do_new_transfer() for line in self.rma_supplier_id.rma_line_ids: self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming") self.assertEquals(line.qty_received, 0, "Wrong qty received") if line.product_id == self.product_1: - self.assertEquals(line.qty_delivered, 3, + self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") if line.product_id == self.product_2: - self.assertEquals(line.qty_delivered, 5, + self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") self.assertEquals(line.qty_to_receive, 5, "Wrong qty to receive") if line.product_id == self.product_3: - self.assertEquals(line.qty_delivered, 2, + self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") self.assertEquals(line.qty_to_receive, 2, "Wrong qty to receive") @@ -96,11 +96,11 @@ class TestSupplierRma(test_rma.TestRma): proc.group_id]) domain = [('group_id', 'in', list(group_ids))] pickings = self.stockpicking.search(domain) - self.assertEquals(len(pickings), 3, + self.assertEquals(len(pickings), 2, "Incorrect number of pickings created") picking_out = pickings[0] moves = picking_out.move_lines - self.assertEquals(len(moves), 2, + self.assertEquals(len(moves), 3, "Incorrect number of moves created") for line in self.rma_supplier_id.rma_line_ids: self.assertEquals(line.qty_incoming, 0, @@ -112,7 +112,7 @@ class TestSupplierRma(test_rma.TestRma): "Wrong qty to receive") self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 3, + self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") if line.product_id == self.product_2: self.assertEquals(line.qty_to_receive, 5, @@ -125,20 +125,20 @@ class TestSupplierRma(test_rma.TestRma): self.assertEquals(line.qty_to_deliver, 2, "Wrong qty to deliver") picking_out.action_assign() - picking_out.do_transfer() + picking_out.do_new_transfer() for line in self.rma_supplier_id.rma_line_ids[0]: self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming") - self.assertEquals(line.qty_to_deliver, 0, + self.assertEquals(line.qty_to_deliver, 3, "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 3, + self.assertEquals(line.qty_outgoing, 6, "Wrong qty outgoing") if line.product_id == self.product_1: self.assertEquals(line.qty_received, 0, "Wrong qty received") - self.assertEquals(line.qty_delivered, 3, + self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") if line.product_id == self.product_2: self.assertEquals(line.qty_received, 0, From 37abae957e9f5dc362761e66037900721024b742 Mon Sep 17 00:00:00 2001 From: Nikul Chaudhary Date: Tue, 9 Jan 2018 15:35:29 +0530 Subject: [PATCH 22/81] [IMP] Improved Code. --- rma/models/procurement.py | 8 ++++---- rma/tests/test_rma.py | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/rma/models/procurement.py b/rma/models/procurement.py index eeeb9eb2..d51dc585 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -14,10 +14,10 @@ class ProcurementOrder(models.Model): ) @api.model - def _run_move_create(self, procurement): - res = super(ProcurementOrder, self)._run_move_create(procurement) - if procurement.rma_line_id: - line = procurement.rma_line_id + def _get_stock_move_values(self): + res = super(ProcurementOrder, self)._get_stock_move_values() + if self.rma_line_id: + line = self.rma_line_id res['rma_line_id'] = line.id if line.delivery_address_id: res['partner_id'] = line.delivery_address_id.id diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 4ebcfe90..b31adfcc 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -275,6 +275,9 @@ class TestRma(common.TransactionCase): 'active_id': 1 }).default_get({}) procurements = wizard._create_picking() + for proc in procurements: + proc._get_stock_move_values() + group_ids = set([proc.group_id.id for proc in procurements if proc.group_id]) domain = [('group_id', 'in', list(group_ids))] From a347b330284f55fefe66fa9503fab6f691eee9a7 Mon Sep 17 00:00:00 2001 From: aheficent Date: Tue, 9 Jan 2018 14:02:51 +0100 Subject: [PATCH 23/81] [MIG]rma_operating_unit to v10 --- rma/models/rma_order_line.py | 1 + rma/views/rma_order_view.xml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index a68445ee..f057795b 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -196,6 +196,7 @@ class RmaOrderLine(models.Model): partner_id = fields.Many2one( comodel_name='res.partner', required=True, store=True, track_visibility='onchange', + string="Partner", readonly=True, states={'draft': [('readonly', False)]}, ) sequence = fields.Integer( diff --git a/rma/views/rma_order_view.xml b/rma/views/rma_order_view.xml index 59d0060e..955082f6 100644 --- a/rma/views/rma_order_view.xml +++ b/rma/views/rma_order_view.xml @@ -86,7 +86,7 @@ @@ -172,7 +172,7 @@ From a84a0ec1f536e6eecd21b8a750556cef9723d50a Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 22 Jan 2018 11:46:33 +0100 Subject: [PATCH 24/81] [FIX]moved_qty uses moves not procurements --- rma/models/rma_order_line.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index f057795b..63945ec3 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -71,7 +71,7 @@ class RmaOrderLine(models.Model): op = ops['='] else: op = ops['!='] - for move in rec.procurement_ids.mapped('move_ids').filtered( + for move in rec.move_ids.filtered( lambda m: m.state in states and op(m.location_id.usage, rec.type)): qty += product_obj._compute_quantity( From f9c7b28af886434d37fe419810137728f82359a6 Mon Sep 17 00:00:00 2001 From: aheficent Date: Fri, 26 Jan 2018 18:03:28 +0100 Subject: [PATCH 25/81] [FIX]compute qty when stock moves but not procurements --- rma/models/rma_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index 97866ebd..cd024971 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -21,7 +21,7 @@ class RmaOrder(models.Model): def _compute_in_shipment_count(self): for rec in self: rec.in_shipment_count = len(rec.rma_line_ids.mapped( - 'procurement_ids.move_ids').filtered( + 'move_ids').filtered( lambda m: m.location_dest_id.usage == 'internal').mapped( 'picking_id')) @@ -29,7 +29,7 @@ class RmaOrder(models.Model): def _compute_out_shipment_count(self): for rec in self: rec.out_shipment_count = len(rec.rma_line_ids.mapped( - 'procurement_ids.move_ids').filtered( + 'move_ids').filtered( lambda m: m.location_id.usage == 'internal').mapped( 'picking_id')) From ae0a75499a83e2f698da2925f42c57acf0a07b46 Mon Sep 17 00:00:00 2001 From: Bhavesh Odedra Date: Fri, 9 Feb 2018 21:56:28 +0530 Subject: [PATCH 26/81] [11.0] MIG: RMA module --- rma/README.rst | 21 +- rma/__init__.py | 1 + rma/__manifest__.py | 5 +- rma/data/rma_operation.xml | 0 rma/data/rma_sequence.xml | 0 rma/data/stock_data.xml | 0 rma/demo/stock_demo.xml | 0 rma/models/__init__.py | 0 rma/models/procurement.py | 22 +- rma/models/product.py | 0 rma/models/product_category.py | 0 rma/models/res_partner.py | 0 rma/models/rma_operation.py | 0 rma/models/rma_order.py | 65 ++- rma/models/rma_order_line.py | 139 ++--- rma/models/stock.py | 9 +- rma/models/stock_warehouse.py | 0 rma/security/ir.model.access.csv | 2 +- rma/security/rma.xml | 0 rma/tests/__init__.py | 0 rma/tests/test_rma.py | 0 rma/tests/test_rma_dropship.py | 0 rma/tests/test_supplier_rma.py | 0 rma/views/procurement_view.xml | 31 - rma/views/product_view.xml | 56 +- rma/views/res_partner_view.xml | 0 rma/views/rma_operation_view.xml | 159 +++-- rma/views/rma_order_line_view.xml | 14 - rma/views/rma_order_view.xml | 550 +++++++++--------- rma/views/stock_view.xml | 82 ++- rma/views/stock_warehouse.xml | 0 rma/wizards/__init__.py | 0 rma/wizards/rma_add_stock_move.py | 0 rma/wizards/rma_add_stock_move_view.xml | 2 +- rma/wizards/rma_make_picking.py | 76 +-- rma/wizards/rma_make_picking_view.xml | 19 - .../rma_order_line_make_supplier_rma.py | 0 .../rma_order_line_make_supplier_rma_view.xml | 131 ++--- rma/wizards/stock_config_settings.py | 2 +- rma/wizards/stock_config_settings.xml | 35 +- 40 files changed, 640 insertions(+), 781 deletions(-) mode change 100644 => 100755 rma/README.rst mode change 100644 => 100755 rma/__init__.py mode change 100644 => 100755 rma/__manifest__.py mode change 100644 => 100755 rma/data/rma_operation.xml mode change 100644 => 100755 rma/data/rma_sequence.xml mode change 100644 => 100755 rma/data/stock_data.xml mode change 100644 => 100755 rma/demo/stock_demo.xml mode change 100644 => 100755 rma/models/__init__.py mode change 100644 => 100755 rma/models/procurement.py mode change 100644 => 100755 rma/models/product.py mode change 100644 => 100755 rma/models/product_category.py mode change 100644 => 100755 rma/models/res_partner.py mode change 100644 => 100755 rma/models/rma_operation.py mode change 100644 => 100755 rma/models/rma_order.py mode change 100644 => 100755 rma/models/rma_order_line.py mode change 100644 => 100755 rma/models/stock.py mode change 100644 => 100755 rma/models/stock_warehouse.py mode change 100644 => 100755 rma/security/ir.model.access.csv mode change 100644 => 100755 rma/security/rma.xml mode change 100644 => 100755 rma/tests/__init__.py mode change 100644 => 100755 rma/tests/test_rma.py mode change 100644 => 100755 rma/tests/test_rma_dropship.py mode change 100644 => 100755 rma/tests/test_supplier_rma.py delete mode 100644 rma/views/procurement_view.xml mode change 100644 => 100755 rma/views/product_view.xml mode change 100644 => 100755 rma/views/res_partner_view.xml mode change 100644 => 100755 rma/views/rma_operation_view.xml mode change 100644 => 100755 rma/views/rma_order_line_view.xml mode change 100644 => 100755 rma/views/rma_order_view.xml mode change 100644 => 100755 rma/views/stock_view.xml mode change 100644 => 100755 rma/views/stock_warehouse.xml mode change 100644 => 100755 rma/wizards/__init__.py mode change 100644 => 100755 rma/wizards/rma_add_stock_move.py mode change 100644 => 100755 rma/wizards/rma_add_stock_move_view.xml mode change 100644 => 100755 rma/wizards/rma_make_picking.py mode change 100644 => 100755 rma/wizards/rma_make_picking_view.xml mode change 100644 => 100755 rma/wizards/rma_order_line_make_supplier_rma.py mode change 100644 => 100755 rma/wizards/rma_order_line_make_supplier_rma_view.xml mode change 100644 => 100755 rma/wizards/stock_config_settings.py mode change 100644 => 100755 rma/wizards/stock_config_settings.xml diff --git a/rma/README.rst b/rma/README.rst old mode 100644 new mode 100755 index fd8a338d..4fe6cf07 --- a/rma/README.rst +++ b/rma/README.rst @@ -59,16 +59,16 @@ steps: Other Settings -------------- -#. Go to Inventory > Settings > Return Merchandising Authorization and select - the option "Display 3 fields on rma: partner, invoice address, delivery - address" if needed. -#. Go to Inventory > Settings > Configuration > Warehouse management > - Warehouses and add a default RMA location and RMA picking type for customers - and suppliers RMA picking type. In case the warehouse is configured to - use routes, you need to create at least one route per rma type with at - least two push rules (one for inbound another for outbound) it's very - important to select the type of operation supplier if we are moving in the - company and customer if we are moving out of the company. +#. Go to Inventory > Configuration > Settings > Return Merchandising + Authorization and select the option "Display 3 fields on rma: partner, + invoice address, delivery address" if needed. +#. Go to Inventory > Configuration > Warehouse management > Warehouses and add + a default RMA location and RMA picking type for customers and suppliers RMA + picking type. In case the warehouse is configured to use routes, you need to + create at least one route per rma type with at least two push rules (one for + inbound another for outbound) it's very important to select the type of + operation supplier if we are moving in the company and customer if we are + moving out of the company. Usage ===== @@ -105,6 +105,7 @@ Contributors * Jordi Ballester Alomar * Aaron Henriquez * Lois Rilo +* Bhavesh Odedra Maintainer ---------- diff --git a/rma/__init__.py b/rma/__init__.py old mode 100644 new mode 100755 index 4105ff51..6209ddca --- a/rma/__init__.py +++ b/rma/__init__.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + from . import models from . import wizards diff --git a/rma/__manifest__.py b/rma/__manifest__.py old mode 100644 new mode 100755 index 3bd4eab8..4c9f25fb --- a/rma/__manifest__.py +++ b/rma/__manifest__.py @@ -4,14 +4,14 @@ { 'name': 'RMA (Return Merchandise Authorization)', - 'version': '10.0.1.0.0', + 'version': '11.0.1.0.0', 'license': 'LGPL-3', 'category': 'RMA', 'summary': 'Introduces the return merchandise authorization (RMA) process ' 'in odoo', 'author': "Eficent, Odoo Community Association (OCA)", 'website': 'http://www.github.com/OCA/rma', - 'depends': ['stock', 'mail', 'procurement'], + 'depends': ['stock', 'mail'], 'demo': ['demo/stock_demo.xml', ], 'data': ['security/rma.xml', @@ -25,7 +25,6 @@ 'views/stock_view.xml', 'views/stock_warehouse.xml', 'views/product_view.xml', - 'views/procurement_view.xml', 'views/res_partner_view.xml', 'wizards/rma_make_picking_view.xml', 'wizards/rma_add_stock_move_view.xml', diff --git a/rma/data/rma_operation.xml b/rma/data/rma_operation.xml old mode 100644 new mode 100755 diff --git a/rma/data/rma_sequence.xml b/rma/data/rma_sequence.xml old mode 100644 new mode 100755 diff --git a/rma/data/stock_data.xml b/rma/data/stock_data.xml old mode 100644 new mode 100755 diff --git a/rma/demo/stock_demo.xml b/rma/demo/stock_demo.xml old mode 100644 new mode 100755 diff --git a/rma/models/__init__.py b/rma/models/__init__.py old mode 100644 new mode 100755 diff --git a/rma/models/procurement.py b/rma/models/procurement.py old mode 100644 new mode 100755 index d51dc585..5bcc1a8f --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -2,22 +2,28 @@ # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from odoo import api, fields, models +from odoo import fields, models -class ProcurementOrder(models.Model): - _inherit = 'procurement.order' +class ProcurementRule(models.Model): + _inherit = 'procurement.rule' rma_line_id = fields.Many2one( comodel_name='rma.order.line', string='RMA line', ondelete="set null", ) - @api.model - def _get_stock_move_values(self): - res = super(ProcurementOrder, self)._get_stock_move_values() - if self.rma_line_id: - line = self.rma_line_id + def _get_stock_move_values(self, product_id, product_qty, product_uom, + location_id, name, origin, values, group_id): + res = super(ProcurementRule, self)._get_stock_move_values(product_id, + product_qty, + product_uom, + location_id, + name, origin, + values, + group_id) + if 'rma_line_id' in values: + line = self.env['rma.order.line'].browse(values.get('rma_line_id')) res['rma_line_id'] = line.id if line.delivery_address_id: res['partner_id'] = line.delivery_address_id.id diff --git a/rma/models/product.py b/rma/models/product.py old mode 100644 new mode 100755 diff --git a/rma/models/product_category.py b/rma/models/product_category.py old mode 100644 new mode 100755 diff --git a/rma/models/res_partner.py b/rma/models/res_partner.py old mode 100644 new mode 100755 diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py old mode 100644 new mode 100755 diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py old mode 100644 new mode 100755 index cd024971..a0872f8b --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -3,7 +3,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models, _ -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError from datetime import datetime @@ -20,18 +20,18 @@ class RmaOrder(models.Model): @api.multi def _compute_in_shipment_count(self): for rec in self: - rec.in_shipment_count = len(rec.rma_line_ids.mapped( - 'move_ids').filtered( - lambda m: m.location_dest_id.usage == 'internal').mapped( - 'picking_id')) + rec.in_shipment_count = len( + rec.rma_line_ids.mapped('move_ids').filtered( + lambda m: m.location_dest_id.usage == 'internal').mapped( + 'picking_id')) @api.multi def _compute_out_shipment_count(self): for rec in self: - rec.out_shipment_count = len(rec.rma_line_ids.mapped( - 'move_ids').filtered( - lambda m: m.location_id.usage == 'internal').mapped( - 'picking_id')) + rec.out_shipment_count = len( + rec.rma_line_ids.mapped('move_ids').filtered( + lambda m: m.location_id.usage == 'internal').mapped( + 'picking_id')) @api.multi def _compute_supplier_line_count(self): @@ -111,14 +111,16 @@ class RmaOrder(models.Model): if move.picking_id.location_id == suppliers: picking_ids.append(move.picking_id.id) shipments = list(set(picking_ids)) + if not shipments: + raise ValidationError(_("No shipments found!")) # choose the view_mode accordingly - if len(shipments) != 1: - result['domain'] = "[('id', 'in', " + \ - str(shipments) + ")]" - elif len(shipments) == 1: - res = self.env.ref('stock.view_picking_form', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = shipments[0] + if shipments: + if len(shipments) > 1: + result['domain'] = [('id', 'in', shipments)] + else: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = shipments[0] return result @api.multi @@ -138,11 +140,12 @@ class RmaOrder(models.Model): if move.picking_id.location_id != suppliers: picking_ids.append(move.picking_id.id) shipments = list(set(picking_ids)) + if not shipments: + raise ValidationError(_("No deliveries found!")) # choose the view_mode accordingly - if len(shipments) != 1: - result['domain'] = "[('id', 'in', " + \ - str(shipments) + ")]" - elif len(shipments) == 1: + if len(shipments) > 1: + result['domain'] = [('id', 'in', shipments)] + else: res = self.env.ref('stock.view_picking_form', False) result['views'] = [(res and res.id or False, 'form')] result['res_id'] = shipments[0] @@ -159,20 +162,21 @@ class RmaOrder(models.Model): def action_view_lines(self): if self.type == 'customer': action = self.env.ref('rma.action_rma_customer_lines') + res = self.env.ref('rma.view_rma_line_form', False) else: action = self.env.ref('rma.action_rma_supplier_lines') + res = self.env.ref('rma.view_rma_line_supplier_form', False) result = action.read()[0] lines = self._get_valid_lines() + if not lines: + raise ValidationError(_("No rma %s lines found!") % self.type) # choose the view_mode accordingly - if len(lines) != 1: + if len(lines.ids) > 1: result['domain'] = [('id', 'in', lines.ids)] - elif len(lines) == 1: - if self.type == 'customer': - res = self.env.ref('rma.view_rma_line_form', False) - else: - res = self.env.ref('rma.view_rma_line_supplier_form', False) + else: result['views'] = [(res and res.id or False, 'form')] result['res_id'] = lines.id + result['context'] = {} return result @api.multi @@ -182,11 +186,12 @@ class RmaOrder(models.Model): lines = self.rma_line_ids for line_id in lines: related_lines = [line.id for line in line_id.supplier_rma_line_ids] + if not related_lines: + raise ValidationError(_("No rma supplier lines found!")) # choose the view_mode accordingly - if len(related_lines) != 1: - result['domain'] = "[('id', 'in', " + \ - str(related_lines) + ")]" - elif len(related_lines) == 1: + if len(related_lines) > 1: + result['domain'] = [('id', 'in', related_lines)] + else: res = self.env.ref('rma.view_rma_line_supplier_form', False) result['views'] = [(res and res.id or False, 'form')] result['res_id'] = related_lines[0] diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py old mode 100644 new mode 100755 index 63945ec3..a85a5a34 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -47,20 +47,16 @@ class RmaOrderLine(models.Model): @api.multi def _compute_in_shipment_count(self): for line in self: - moves = line.procurement_ids.mapped('move_ids').filtered( - lambda m: m.location_dest_id.usage == 'internal' and - m.state != 'cancel') - pickings = moves.mapped('picking_id') - line.in_shipment_count = len(pickings) + line.in_shipment_count = len(self.env['stock.picking'].search( + [('origin', '=', line.name), + ('picking_type_code', '=', 'incoming')]).ids) @api.multi def _compute_out_shipment_count(self): for line in self: - moves = line.procurement_ids.mapped('move_ids').filtered( - lambda m: m.location_dest_id.usage != 'internal' and - m.state != 'cancel') - pickings = moves.mapped('picking_id') - line.out_shipment_count = len(pickings) + line.out_shipment_count = len(self.env['stock.picking'].search( + [('origin', '=', line.name), + ('picking_type_code', '=', 'outgoing')]).ids) @api.multi def _get_rma_move_qty(self, states, direction='in'): @@ -147,12 +143,6 @@ class RmaOrderLine(models.Model): rec.qty_to_supplier_rma = rec.qty_to_receive - qty rec.qty_in_supplier_rma = qty - @api.multi - def _compute_procurement_count(self): - for rec in self: - rec.procurement_count = len(rec.procurement_ids.filtered( - lambda p: p.state == 'exception')) - delivery_address_id = fields.Many2one( comodel_name='res.partner', string='Partner delivery address', default=_default_delivery_address, @@ -210,7 +200,7 @@ class RmaOrderLine(models.Model): product_tracking = fields.Selection(related="product_id.tracking") lot_id = fields.Many2one( comodel_name="stock.production.lot", string="Lot/Serial Number", - readonly=True, states={"new": [("readonly", False)]}, + readonly=True, states={"draft": [("readonly", False)]}, ) product_qty = fields.Float( string='Ordered Qty', copy=False, default=1.0, @@ -226,9 +216,6 @@ class RmaOrderLine(models.Model): string='Price Unit', readonly=True, states={'draft': [('readonly', False)]}, ) - procurement_count = fields.Integer(compute=_compute_procurement_count, - string='# of Procurements', copy=False, - default=0) in_shipment_count = fields.Integer(compute=_compute_in_shipment_count, string='# of Shipments', default=0) out_shipment_count = fields.Integer(compute=_compute_out_shipment_count, @@ -241,10 +228,6 @@ class RmaOrderLine(models.Model): copy=False, readonly=True, states={'draft': [('readonly', False)]}, ) - procurement_ids = fields.One2many('procurement.order', 'rma_line_id', - string='Procurements', readonly=True, - states={'draft': [('readonly', False)]}, - copy=False) currency_id = fields.Many2one('res.currency', string="Currency") company_id = fields.Many2one( comodel_name='res.company', string='Company', required=True, @@ -413,21 +396,12 @@ class RmaOrderLine(models.Model): @api.onchange('reference_move_id') def _onchange_reference_move_id(self): self.ensure_one() - sm = self.reference_move_id - if not sm: - return - if sm.lot_ids: - if len(sm.lot_ids) > 1: - raise UserError(_('To manage lots use RMA groups.')) - else: - data = self._prepare_rma_line_from_stock_move( - sm, lot=sm.lot_ids[0]) - self.update(data) - else: - data = self._prepare_rma_line_from_stock_move( - sm, lot=False) + for move in self.reference_move_id: + data = self._prepare_rma_line_from_stock_move(move, lot=False) self.update(data) - self._remove_other_data_origin('reference_move_id') + self._remove_other_data_origin('reference_move_id') + lot_ids = [x.lot_id.id for x in move.move_line_ids if x.lot_id] + return {'domain': {'lot_id': [('id', 'in', lot_ids)]}} @api.multi @api.constrains('reference_move_id', 'partner_id') @@ -527,90 +501,45 @@ class RmaOrderLine(models.Model): elif self.type == 'customer' and self.supplier_to_customer: self.delivery_policy = 'no' - @api.onchange('product_id') - def _onchange_product_id(self): - self.uom_id = self.product_id.uom_id - if self.lot_id.product_id != self.product_id: - self.lot_id = False - if self.product_id: - return {'domain': { - 'lot_id': [('product_id', '=', self.product_id.id)]}} - return {'domain': {'lot_id': []}} - @api.onchange("lot_id") def _onchange_lot_id(self): - product = self.lot_id.product_id - if product: - self.product_id = product - self.uom_id = product.uom_id + if self.lot_id and self.reference_move_id: + data = self._prepare_rma_line_from_stock_move( + self.reference_move_id, lot=self.lot_id) + self.update(data) @api.multi def action_view_in_shipments(self): action = self.env.ref('stock.action_picking_tree_all') result = action.read()[0] - picking_ids = [] - suppliers = self.env.ref('stock.stock_location_suppliers') - customers = self.env.ref('stock.stock_location_customers') - for line in self: - if line.type == 'customer': - for move in line.move_ids: - if move.picking_id.location_id == customers: - picking_ids.append(move.picking_id.id) - else: - for move in line.move_ids: - if move.picking_id.location_id == suppliers: - picking_ids.append(move.picking_id.id) - shipments = list(set(picking_ids)) + picking_ids = self.env['stock.picking'].search( + [('origin', '=', self.name), + ('picking_type_code', '=', 'incoming')]).ids + if not picking_ids: + raise ValidationError(_("No shipments found!")) # choose the view_mode accordingly - if len(shipments) != 1: - result['domain'] = "[('id', 'in', " + \ - str(shipments) + ")]" - elif len(shipments) == 1: + if len(picking_ids) > 1: + result['domain'] = [('id', 'in', picking_ids)] + else: res = self.env.ref('stock.view_picking_form', False) result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = shipments[0] + result['res_id'] = picking_ids[0] return result @api.multi def action_view_out_shipments(self): action = self.env.ref('stock.action_picking_tree_all') result = action.read()[0] - picking_ids = [] - suppliers = self.env.ref('stock.stock_location_suppliers') - customers = self.env.ref('stock.stock_location_customers') - for line in self: - if line.type == 'customer': - for move in line.move_ids: - if move.picking_id.location_id != customers: - picking_ids.append(move.picking_id.id) - else: - for move in line.move_ids: - if move.picking_id.location_id != suppliers: - picking_ids.append(move.picking_id.id) - shipments = list(set(picking_ids)) + picking_ids = self.env['stock.picking'].search( + [('origin', '=', self.name), + ('picking_type_code', '=', 'outgoing')]).ids + if not picking_ids: + raise ValidationError(_("No deliveries found!")) # choose the view_mode accordingly - if len(shipments) != 1: - result['domain'] = "[('id', 'in', " + \ - str(shipments) + ")]" - elif len(shipments) == 1: + if len(picking_ids) > 1: + result['domain'] = [('id', 'in', picking_ids)] + else: res = self.env.ref('stock.view_picking_form', False) result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = shipments[0] - return result - - @api.multi - def action_view_procurements(self): - action = self.env.ref( - 'procurement.procurement_order_action_exceptions') - result = action.read()[0] - procurements = self.procurement_ids.filtered( - lambda p: p.state == 'exception').ids - # choose the view_mode accordingly - if len(procurements) != 1: - result['domain'] = "[('id', 'in', " + \ - str(procurements) + ")]" - elif len(procurements) == 1: - res = self.env.ref('procurement.procurement_form_view', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = procurements[0] + result['res_id'] = picking_ids[0] return result diff --git a/rma/models/stock.py b/rma/models/stock.py old mode 100644 new mode 100755 index 1fad0b8f..ef137fb3 --- a/rma/models/stock.py +++ b/rma/models/stock.py @@ -30,9 +30,8 @@ class StockMove(models.Model): @api.model def create(self, vals): - if vals.get('procurement_id'): - procurement = self.env['procurement.order'].browse( - vals['procurement_id']) - if procurement.rma_line_id: - vals['rma_line_id'] = procurement.rma_line_id.id + if vals.get('group_id'): + group = self.env['procurement.group'].browse(vals['group_id']) + if group.rma_line_id: + vals['rma_line_id'] = group.rma_line_id.id return super(StockMove, self).create(vals) diff --git a/rma/models/stock_warehouse.py b/rma/models/stock_warehouse.py old mode 100644 new mode 100755 diff --git a/rma/security/ir.model.access.csv b/rma/security/ir.model.access.csv old mode 100644 new mode 100755 index 291e1e5d..7362e7eb --- a/rma/security/ir.model.access.csv +++ b/rma/security/ir.model.access.csv @@ -8,4 +8,4 @@ access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1, access_rma_operation_manager,access_rma_operation,model_rma_operation,group_rma_manager,1,1,1,1 access_rma_operation_customer_user,access_rma_operation,model_rma_operation,group_rma_customer_user,1,0,0,0 access_rma_operation_supplier_user,access_rma_operation,model_rma_operation,group_rma_supplier_user,1,0,0,0 -access_stock_config_settings,access_stock_config_settings,model_stock_config_settings,stock.group_stock_manager,1,1,1,1 + diff --git a/rma/security/rma.xml b/rma/security/rma.xml old mode 100644 new mode 100755 diff --git a/rma/tests/__init__.py b/rma/tests/__init__.py old mode 100644 new mode 100755 diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py old mode 100644 new mode 100755 diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py old mode 100644 new mode 100755 diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py old mode 100644 new mode 100755 diff --git a/rma/views/procurement_view.xml b/rma/views/procurement_view.xml deleted file mode 100644 index 91f55dd5..00000000 --- a/rma/views/procurement_view.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - procurement.order.form - procurement.order - - - - - - - - - - procurement.order.form.stock.inherit - procurement.order - - - - [('usage', '!=', 'view')] - - - - - - - diff --git a/rma/views/product_view.xml b/rma/views/product_view.xml old mode 100644 new mode 100755 index bb35950b..c00c2c2f --- a/rma/views/product_view.xml +++ b/rma/views/product_view.xml @@ -1,36 +1,32 @@ - - - - product.category.form - product.category - - - - - - - - - - - - - - product.template.stock.property.form.inherit - product.template - - - - - - - - + + product.category.form + product.category + + + + + + + - + + - + + product.template.stock.property.form.inherit + product.template + + + + + + + + + + + diff --git a/rma/views/res_partner_view.xml b/rma/views/res_partner_view.xml old mode 100644 new mode 100755 diff --git a/rma/views/rma_operation_view.xml b/rma/views/rma_operation_view.xml old mode 100644 new mode 100755 index b9f55633..933cee23 --- a/rma/views/rma_operation_view.xml +++ b/rma/views/rma_operation_view.xml @@ -1,90 +1,87 @@ - - - rma.operation.tree - rma.operation - - - - - - - - - - + + rma.operation.tree + rma.operation + + + + + + + + + + - - rma.operation.form - rma.operation - - - - - - - - - - - - - - - - - - - - - - - - + + rma.operation.form + rma.operation + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + - - Customer Operations - rma.operation - form - tree,form - {'default_type': "customer"} - [('type','=', 'customer')] - - + + Customer Operations + rma.operation + form + tree,form + {'default_type': "customer"} + [('type','=', 'customer')] + + - - Supplier Operations - rma.operation - form - tree,form - {'default_type': "supplier"} - [('type','=', 'supplier')] - - + + Supplier Operations + rma.operation + form + tree,form + {'default_type': "supplier"} + [('type','=', 'supplier')] + + - + - - - + diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml old mode 100644 new mode 100755 index 6a184dc4..fa7a6963 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -83,13 +83,6 @@ -

@@ -242,13 +235,6 @@ icon="fa-pencil-square-o" string="Origin Inv"> -

diff --git a/rma/views/rma_order_view.xml b/rma/views/rma_order_view.xml old mode 100644 new mode 100755 index 955082f6..1d78d2e8 --- a/rma/views/rma_order_view.xml +++ b/rma/views/rma_order_view.xml @@ -1,299 +1,295 @@ - + + rma.order.tree + rma.order + + + + + + + + + - - rma.order.tree - rma.order - - - + + rma.order.supplier.tree + rma.order + + + + + + + + + + + + rma.order.form + rma.order + +
+
+ +
+ + + + +
+
+

+ +

+
+ + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + + - - rma.order.supplier.tree - rma.order - - - - - + rma.order.supplier.form + rma.order + +
+
+ +
+ + + +
+
+

+ +

+
+ + - - - - - - - rma.order.form - rma.order - - -
- -
- - - - -
-
-

- -

-
- - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
- - - - - - rma.order.supplier.form - rma.order - -
-
- -
- - - -
-
-

- -

-
- - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
- - - + + + + + + + +
+ + +
+ + + - - rma.order.select - rma.order - - - - - - - - - - - - - + + rma.order.select + rma.order + + + + + + + + + + + + + - - Customer RMA Group - rma.order - form - [('type','=', 'customer')] - {'customer':1} - tree,form - - + + Customer RMA Group + rma.order + form + [('type','=', 'customer')] + {'customer':1} + tree,form + + - - Supplier RMA Group - rma.order - form - [('type','=', 'supplier')] - {'supplier':1} - tree,form - - + + Supplier RMA Group + rma.order + form + [('type','=', 'supplier')] + {'supplier':1} + tree,form + + - - - tree - - + + + tree + + - - - form - - - + + + form + + + - + - + - + - + - - - + diff --git a/rma/views/stock_view.xml b/rma/views/stock_view.xml old mode 100644 new mode 100755 index a2f06c74..c2120a7e --- a/rma/views/stock_view.xml +++ b/rma/views/stock_view.xml @@ -1,55 +1,39 @@ - - - - rma.move.form - stock.move - - - - - - + + rma.move.form + stock.move + + + + + - - + + + - - stock.move.form - stock.move - - - - - - - - - + + stock.move.form + stock.move + + + + + + + + + - - stock.location.route.form - - stock.location.route - - - - - - - - - procurement.order.form.stock.inherit - procurement.order - - - - [('usage', '!=', 'view')] - - - - - + + stock.location.route.form + + stock.location.route + + + + + + diff --git a/rma/views/stock_warehouse.xml b/rma/views/stock_warehouse.xml old mode 100644 new mode 100755 diff --git a/rma/wizards/__init__.py b/rma/wizards/__init__.py old mode 100644 new mode 100755 diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py old mode 100644 new mode 100755 diff --git a/rma/wizards/rma_add_stock_move_view.xml b/rma/wizards/rma_add_stock_move_view.xml old mode 100644 new mode 100755 index 2bad25ed..424d11d6 --- a/rma/wizards/rma_add_stock_move_view.xml +++ b/rma/wizards/rma_add_stock_move_view.xml @@ -18,7 +18,7 @@ - + diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py old mode 100644 new mode 100755 index 717137c6..129ec08e --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -32,6 +32,7 @@ class RmaMakePicking(models.TransientModel): lines the supplier field is empty otherwise is the unique line supplier. """ + context = self._context.copy() res = super(RmaMakePicking, self).default_get(fields) rma_line_obj = self.env['rma.order.line'] rma_line_ids = self.env.context['active_ids'] or [] @@ -51,6 +52,7 @@ class RmaMakePicking(models.TransientModel): for line in lines: items.append([0, 0, self._prepare_item(line)]) res['item_ids'] = items + context.update({'items_ids': items}) return res item_ids = fields.One2many( @@ -67,6 +69,7 @@ class RmaMakePicking(models.TransientModel): def _get_procurement_group_data(self, item): group_data = { + 'partner_id': item.line_id.partner_id.id, 'name': item.line_id.rma_id.name or item.line_id.name, 'rma_id': item.line_id.rma_id and item.line_id.rma_id.id or False, 'rma_line_id': item.line_id.id if not item.line_id.rma_id else @@ -116,17 +119,17 @@ class RmaMakePicking(models.TransientModel): raise ValidationError(_("No warehouse specified")) procurement_data = { 'name': line.rma_id and line.rma_id.name or line.name, - 'group_id': group.id, + 'group_id': group, 'origin': line.name, - 'warehouse_id': warehouse.id, + 'warehouse_id': warehouse, 'date_planned': time.strftime(DT_FORMAT), - 'product_id': item.product_id.id, + 'product_id': item.product_id, 'product_qty': qty, - 'partner_dest_id': delivery_address_id.id, + 'partner_id': delivery_address_id.id, 'product_uom': line.product_id.product_tmpl_id.uom_id.id, - 'location_id': location.id, + 'location_id': location, 'rma_line_id': line.id, - 'route_ids': [(4, route.id)] + 'route_ids': route } return procurement_data @@ -140,18 +143,23 @@ class RmaMakePicking(models.TransientModel): qty = item.qty_to_receive else: qty = item.qty_to_deliver - procurement_data = self._get_procurement_data( - item, group, qty, picking_type) + values = self._get_procurement_data(item, group, qty, picking_type) # create picking - procurement = self.env['procurement.order'].create(procurement_data) - procurement.run() - return procurement.id + self.env['procurement.group'].run( + item.line_id.product_id, + qty, + item.line_id.product_id.product_tmpl_id.uom_id, + values.get('location_id'), + values.get('origin'), + values.get('origin'), + values + ) + return values.get('origin') @api.multi def _create_picking(self): """Method called when the user clicks on create picking""" picking_type = self.env.context.get('picking_type') - procurement_list = [] for item in self.item_ids: line = item.line_id if line.state != 'approved': @@ -167,9 +175,7 @@ class RmaMakePicking(models.TransientModel): raise ValidationError( _('No deliveries needed for this operation')) procurement = self._create_procurement(item, picking_type) - procurement_list.append(procurement) - procurements = self.env['procurement.order'].browse(procurement_list) - return procurements + return procurement @api.model def _get_action(self, pickings, procurements): @@ -179,30 +185,32 @@ class RmaMakePicking(models.TransientModel): action = self.env.ref( 'procurement.procurement_order_action_exceptions') action = action.read()[0] - # choose the view_mode accordingly - procurement_ids = procurements.ids - if len(procurement_ids) != 1: - action['domain'] = "[('id', 'in', " + \ - str(procurement_ids) + ")]" - elif len(procurements) == 1: - res = self.env.ref('procurement.procurement_form_view', - False) - action['views'] = [(res and res.id or False, 'form')] - action['res_id'] = procurement_ids[0] + if procurements: + # choose the view_mode accordingly + if len(procurements.ids) <= 1: + res = self.env.ref('procurement.procurement_form_view', + False) + action['views'] = [(res and res.id or False, 'form')] + action['res_id'] = procurements.ids[0] + else: + action['domain'] = [('id', 'in', procurements.ids)] return action @api.multi def action_create_picking(self): - procurements = self._create_picking() - groups = [] - for proc in procurements: - if proc.group_id: - groups.append(proc.group_id.id) - if len(groups): + procurement = self._create_picking() + pickings = False + action = self.env.ref('stock.do_view_pickings') + action = action.read()[0] + if procurement: pickings = self.env['stock.picking'].search( - [('group_id', 'in', groups)]) - - action = self._get_action(pickings, procurements) + [('origin', '=', procurement)]).ids + if len(pickings) > 1: + action['domain'] = [('id', 'in', pickings)] + else: + form = self.env.ref('stock.view_picking_form', False) + action['views'] = [(form and form.id or False, 'form')] + action['res_id'] = pickings[0] return action @api.multi diff --git a/rma/wizards/rma_make_picking_view.xml b/rma/wizards/rma_make_picking_view.xml old mode 100644 new mode 100755 index c3f656a0..3c6a17df --- a/rma/wizards/rma_make_picking_view.xml +++ b/rma/wizards/rma_make_picking_view.xml @@ -115,23 +115,4 @@ - - - Create Incoming Shipment - client_action_multi - - action - rma.order.line - - - - - Create Delivery - client_action_multi - - action - rma.order.line - - diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py old mode 100644 new mode 100755 diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml old mode 100644 new mode 100755 index 455eed25..63228545 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -2,72 +2,71 @@ - - - RMA Line Make Supplier RMA - rma.order.line.make.supplier.rma - form - -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - diff --git a/rma/wizards/stock_config_settings.py b/rma/wizards/stock_config_settings.py old mode 100644 new mode 100755 index 43058526..8c9a2ef9 --- a/rma/wizards/stock_config_settings.py +++ b/rma/wizards/stock_config_settings.py @@ -6,7 +6,7 @@ from odoo import models, fields class StockConfigSettings(models.TransientModel): - _inherit = 'stock.config.settings' + _inherit = 'res.config.settings' group_rma_delivery_address = fields.Selection([ (0, "Invoicing and shipping addresses are always the same " diff --git a/rma/wizards/stock_config_settings.xml b/rma/wizards/stock_config_settings.xml old mode 100644 new mode 100755 index 4df67cfa..b07b0438 --- a/rma/wizards/stock_config_settings.xml +++ b/rma/wizards/stock_config_settings.xml @@ -1,17 +1,24 @@ - - - stock.config.settings.rma - stock.config.settings - - - - - - - - - - + + stock.config.settings.rma + res.config.settings + + +
+

Return Merchandise Authorization

+
+
+
+
+
+ +
+
+
+
+
+
+
+
From 94135ff5fa641f2fedba05a04662f0a0e274c50f Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Fri, 9 Feb 2018 12:24:45 -0600 Subject: [PATCH 27/81] [FIX] Permissions and remove (en)coding --- rma/README.rst | 0 rma/__init__.py | 1 - rma/__manifest__.py | 1 - rma/data/rma_operation.xml | 2 +- rma/data/rma_sequence.xml | 2 +- rma/data/stock_data.xml | 2 +- rma/demo/stock_demo.xml | 2 +- rma/models/__init__.py | 1 - rma/models/procurement.py | 1 - rma/models/product.py | 1 - rma/models/product_category.py | 1 - rma/models/res_partner.py | 1 - rma/models/rma_operation.py | 1 - rma/models/rma_order.py | 1 - rma/models/rma_order_line.py | 1 - rma/models/stock.py | 1 - rma/models/stock_warehouse.py | 1 - rma/security/rma.xml | 2 +- rma/tests/__init__.py | 1 - rma/tests/test_rma.py | 1 - rma/tests/test_rma_dropship.py | 1 - rma/tests/test_supplier_rma.py | 1 - rma/views/product_view.xml | 2 +- rma/views/res_partner_view.xml | 2 +- rma/views/rma_operation_view.xml | 2 +- rma/views/rma_order_line_view.xml | 2 +- rma/views/rma_order_view.xml | 2 +- rma/views/stock_view.xml | 2 +- rma/views/stock_warehouse.xml | 2 +- rma/wizards/__init__.py | 1 - rma/wizards/rma_add_stock_move.py | 1 - rma/wizards/rma_add_stock_move_view.xml | 2 +- rma/wizards/rma_make_picking.py | 1 - rma/wizards/rma_make_picking_view.xml | 2 +- rma/wizards/rma_order_line_make_supplier_rma.py | 1 - rma/wizards/rma_order_line_make_supplier_rma_view.xml | 2 +- rma/wizards/stock_config_settings.py | 1 - rma/wizards/stock_config_settings.xml | 2 +- 38 files changed, 16 insertions(+), 37 deletions(-) mode change 100755 => 100644 rma/README.rst mode change 100755 => 100644 rma/__init__.py mode change 100755 => 100644 rma/__manifest__.py mode change 100755 => 100644 rma/models/__init__.py mode change 100755 => 100644 rma/models/procurement.py mode change 100755 => 100644 rma/models/product.py mode change 100755 => 100644 rma/models/product_category.py mode change 100755 => 100644 rma/models/res_partner.py mode change 100755 => 100644 rma/models/rma_operation.py mode change 100755 => 100644 rma/models/rma_order.py mode change 100755 => 100644 rma/models/rma_order_line.py mode change 100755 => 100644 rma/models/stock.py mode change 100755 => 100644 rma/models/stock_warehouse.py mode change 100755 => 100644 rma/tests/__init__.py mode change 100755 => 100644 rma/tests/test_rma.py mode change 100755 => 100644 rma/tests/test_rma_dropship.py mode change 100755 => 100644 rma/tests/test_supplier_rma.py mode change 100755 => 100644 rma/wizards/__init__.py mode change 100755 => 100644 rma/wizards/rma_add_stock_move.py mode change 100755 => 100644 rma/wizards/rma_make_picking.py mode change 100755 => 100644 rma/wizards/rma_order_line_make_supplier_rma.py mode change 100755 => 100644 rma/wizards/stock_config_settings.py diff --git a/rma/README.rst b/rma/README.rst old mode 100755 new mode 100644 diff --git a/rma/__init__.py b/rma/__init__.py old mode 100755 new mode 100644 index 6209ddca..f3284a96 --- a/rma/__init__.py +++ b/rma/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/__manifest__.py b/rma/__manifest__.py old mode 100755 new mode 100644 index 4c9f25fb..53d887de --- a/rma/__manifest__.py +++ b/rma/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/data/rma_operation.xml b/rma/data/rma_operation.xml index 5baa6fca..469ed58d 100755 --- a/rma/data/rma_operation.xml +++ b/rma/data/rma_operation.xml @@ -1,4 +1,4 @@ - + Replace After Receive diff --git a/rma/data/rma_sequence.xml b/rma/data/rma_sequence.xml index e59ec85f..cca2b65a 100755 --- a/rma/data/rma_sequence.xml +++ b/rma/data/rma_sequence.xml @@ -1,4 +1,4 @@ - + Customer RMA sequence diff --git a/rma/data/stock_data.xml b/rma/data/stock_data.xml index 7dd24cdc..ee943875 100755 --- a/rma/data/stock_data.xml +++ b/rma/data/stock_data.xml @@ -1,4 +1,4 @@ - + WH RMA diff --git a/rma/demo/stock_demo.xml b/rma/demo/stock_demo.xml index 5af76da5..96659f5b 100755 --- a/rma/demo/stock_demo.xml +++ b/rma/demo/stock_demo.xml @@ -1,4 +1,4 @@ - + diff --git a/rma/models/__init__.py b/rma/models/__init__.py old mode 100755 new mode 100644 index 06c86f1e..4e9429ad --- a/rma/models/__init__.py +++ b/rma/models/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import rma_order diff --git a/rma/models/procurement.py b/rma/models/procurement.py old mode 100755 new mode 100644 index 5bcc1a8f..7583ee88 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/models/product.py b/rma/models/product.py old mode 100755 new mode 100644 index 04557e21..a235cc89 --- a/rma/models/product.py +++ b/rma/models/product.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/models/product_category.py b/rma/models/product_category.py old mode 100755 new mode 100644 index 927de271..7bfd6100 --- a/rma/models/product_category.py +++ b/rma/models/product_category.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/models/res_partner.py b/rma/models/res_partner.py old mode 100755 new mode 100644 index 32a5de7f..896b03a1 --- a/rma/models/res_partner.py +++ b/rma/models/res_partner.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py old mode 100755 new mode 100644 index 2c24165f..07335754 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py old mode 100755 new mode 100644 index a0872f8b..a22e8f42 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py old mode 100755 new mode 100644 index a85a5a34..6280947a --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/models/stock.py b/rma/models/stock.py old mode 100755 new mode 100644 index ef137fb3..e5c13241 --- a/rma/models/stock.py +++ b/rma/models/stock.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/models/stock_warehouse.py b/rma/models/stock_warehouse.py old mode 100755 new mode 100644 index 52c26a61..3dddc32e --- a/rma/models/stock_warehouse.py +++ b/rma/models/stock_warehouse.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/security/rma.xml b/rma/security/rma.xml index ab04e69c..f9b0cced 100755 --- a/rma/security/rma.xml +++ b/rma/security/rma.xml @@ -1,4 +1,4 @@ - + diff --git a/rma/tests/__init__.py b/rma/tests/__init__.py old mode 100755 new mode 100644 index dfa77946..8a00d433 --- a/rma/tests/__init__.py +++ b/rma/tests/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import test_rma diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py old mode 100755 new mode 100644 index b31adfcc..67f9b2a9 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py old mode 100755 new mode 100644 index b7b5b11c..7380d881 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py old mode 100755 new mode 100644 index 1c3fd67f..109c784c --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/views/product_view.xml b/rma/views/product_view.xml index c00c2c2f..aeb6da9d 100755 --- a/rma/views/product_view.xml +++ b/rma/views/product_view.xml @@ -1,4 +1,4 @@ - + product.category.form diff --git a/rma/views/res_partner_view.xml b/rma/views/res_partner_view.xml index 97ec12b7..19b34670 100755 --- a/rma/views/res_partner_view.xml +++ b/rma/views/res_partner_view.xml @@ -1,4 +1,4 @@ - + diff --git a/rma/views/rma_operation_view.xml b/rma/views/rma_operation_view.xml index 933cee23..0b96ff4e 100755 --- a/rma/views/rma_operation_view.xml +++ b/rma/views/rma_operation_view.xml @@ -1,4 +1,4 @@ - + rma.operation.tree diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index fa7a6963..17fa9fcf 100755 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -1,4 +1,4 @@ - + diff --git a/rma/views/rma_order_view.xml b/rma/views/rma_order_view.xml index 1d78d2e8..da09e327 100755 --- a/rma/views/rma_order_view.xml +++ b/rma/views/rma_order_view.xml @@ -1,4 +1,4 @@ - + rma.order.tree diff --git a/rma/views/stock_view.xml b/rma/views/stock_view.xml index c2120a7e..831a82d1 100755 --- a/rma/views/stock_view.xml +++ b/rma/views/stock_view.xml @@ -1,4 +1,4 @@ - + rma.move.form diff --git a/rma/views/stock_warehouse.xml b/rma/views/stock_warehouse.xml index a626781f..fa0a76c0 100755 --- a/rma/views/stock_warehouse.xml +++ b/rma/views/stock_warehouse.xml @@ -1,4 +1,4 @@ - + view_warehouse_form diff --git a/rma/wizards/__init__.py b/rma/wizards/__init__.py old mode 100755 new mode 100644 index 64d335a4..d676aaed --- a/rma/wizards/__init__.py +++ b/rma/wizards/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py old mode 100755 new mode 100644 index cb3178dd..da95eda0 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/wizards/rma_add_stock_move_view.xml b/rma/wizards/rma_add_stock_move_view.xml index 424d11d6..df0b7e65 100755 --- a/rma/wizards/rma_add_stock_move_view.xml +++ b/rma/wizards/rma_add_stock_move_view.xml @@ -1,4 +1,4 @@ - + diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py old mode 100755 new mode 100644 index 129ec08e..a69362a0 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/wizards/rma_make_picking_view.xml b/rma/wizards/rma_make_picking_view.xml index 3c6a17df..126bf191 100755 --- a/rma/wizards/rma_make_picking_view.xml +++ b/rma/wizards/rma_make_picking_view.xml @@ -1,4 +1,4 @@ - + diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py old mode 100755 new mode 100644 index 511aab31..c84aab6d --- a/rma/wizards/rma_order_line_make_supplier_rma.py +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml index 63228545..1129702f 100755 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -1,4 +1,4 @@ - + diff --git a/rma/wizards/stock_config_settings.py b/rma/wizards/stock_config_settings.py old mode 100755 new mode 100644 index 8c9a2ef9..f9d668e3 --- a/rma/wizards/stock_config_settings.py +++ b/rma/wizards/stock_config_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) diff --git a/rma/wizards/stock_config_settings.xml b/rma/wizards/stock_config_settings.xml index b07b0438..4ea1a48e 100755 --- a/rma/wizards/stock_config_settings.xml +++ b/rma/wizards/stock_config_settings.xml @@ -1,4 +1,4 @@ - + stock.config.settings.rma From 854d9ec537de10b7e5c13bf6b5680d93c7778313 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Fri, 9 Feb 2018 12:35:23 -0600 Subject: [PATCH 28/81] [MIG] Migrate configuration and cleanup --- rma/__init__.py | 2 +- rma/__manifest__.py | 2 +- rma/models/procurement.py | 2 +- rma/models/product.py | 2 +- rma/models/rma_operation.py | 2 +- rma/models/rma_order.py | 2 +- rma/models/rma_order_line.py | 2 +- rma/models/stock.py | 2 +- rma/models/stock_warehouse.py | 2 +- rma/tests/__init__.py | 2 +- rma/tests/test_rma.py | 2 +- rma/tests/test_rma_dropship.py | 2 +- rma/tests/test_supplier_rma.py | 2 +- rma/wizards/__init__.py | 2 +- rma/wizards/rma_add_stock_move.py | 2 +- rma/wizards/rma_make_picking.py | 2 +- rma/wizards/rma_order_line_make_supplier_rma.py | 2 +- rma/wizards/stock_config_settings.py | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/rma/__init__.py b/rma/__init__.py index f3284a96..4733391a 100644 --- a/rma/__init__.py +++ b/rma/__init__.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import models diff --git a/rma/__manifest__.py b/rma/__manifest__.py index 53d887de..66256b0e 100644 --- a/rma/__manifest__.py +++ b/rma/__manifest__.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) { diff --git a/rma/models/procurement.py b/rma/models/procurement.py index 7583ee88..36140e55 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import fields, models diff --git a/rma/models/product.py b/rma/models/product.py index a235cc89..b1da2221 100644 --- a/rma/models/product.py +++ b/rma/models/product.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import fields, models diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py index 07335754..9e9c12d6 100644 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index a22e8f42..4b7caf00 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models, _ diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 6280947a..f3394670 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models, _ diff --git a/rma/models/stock.py b/rma/models/stock.py index e5c13241..1ccf52cc 100644 --- a/rma/models/stock.py +++ b/rma/models/stock.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models diff --git a/rma/models/stock_warehouse.py b/rma/models/stock_warehouse.py index 3dddc32e..3111e137 100644 --- a/rma/models/stock_warehouse.py +++ b/rma/models/stock_warehouse.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import fields, models diff --git a/rma/tests/__init__.py b/rma/tests/__init__.py index 8a00d433..619dbb54 100644 --- a/rma/tests/__init__.py +++ b/rma/tests/__init__.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import test_rma from . import test_supplier_rma diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 67f9b2a9..425dd030 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo.tests import common diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py index 7380d881..b22dfbc2 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import test_rma diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py index 109c784c..27666386 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import test_rma diff --git a/rma/wizards/__init__.py b/rma/wizards/__init__.py index d676aaed..7fa8500f 100644 --- a/rma/wizards/__init__.py +++ b/rma/wizards/__init__.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import rma_add_stock_move diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py index da95eda0..75cf39ab 100644 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models, _ diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py index a69362a0..f361b427 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) import time diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py index c84aab6d..f127327e 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma.py +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) import odoo.addons.decimal_precision as dp diff --git a/rma/wizards/stock_config_settings.py b/rma/wizards/stock_config_settings.py index f9d668e3..265eeaa5 100644 --- a/rma/wizards/stock_config_settings.py +++ b/rma/wizards/stock_config_settings.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import models, fields From 0f0558b88fa07523122409164a74190d33848ad2 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Fri, 9 Feb 2018 16:52:31 -0600 Subject: [PATCH 29/81] [FIX] Errors from tests --- rma/models/rma_order.py | 16 ++++------------ rma/models/rma_order_line.py | 8 ++------ rma/tests/__init__.py | 1 + rma/tests/test_rma.py | 13 ++----------- rma/tests/test_rma_dropship.py | 4 +--- rma/tests/test_supplier_rma.py | 8 ++------ rma/wizards/rma_add_stock_move.py | 15 ++++++++------- rma/wizards/rma_make_picking.py | 2 +- 8 files changed, 21 insertions(+), 46 deletions(-) diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index 4b7caf00..253f968a 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -2,7 +2,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models, _ -from odoo.exceptions import UserError, ValidationError +from odoo.exceptions import UserError from datetime import datetime @@ -110,8 +110,6 @@ class RmaOrder(models.Model): if move.picking_id.location_id == suppliers: picking_ids.append(move.picking_id.id) shipments = list(set(picking_ids)) - if not shipments: - raise ValidationError(_("No shipments found!")) # choose the view_mode accordingly if shipments: if len(shipments) > 1: @@ -139,10 +137,8 @@ class RmaOrder(models.Model): if move.picking_id.location_id != suppliers: picking_ids.append(move.picking_id.id) shipments = list(set(picking_ids)) - if not shipments: - raise ValidationError(_("No deliveries found!")) # choose the view_mode accordingly - if len(shipments) > 1: + if len(shipments) != 1: result['domain'] = [('id', 'in', shipments)] else: res = self.env.ref('stock.view_picking_form', False) @@ -167,10 +163,8 @@ class RmaOrder(models.Model): res = self.env.ref('rma.view_rma_line_supplier_form', False) result = action.read()[0] lines = self._get_valid_lines() - if not lines: - raise ValidationError(_("No rma %s lines found!") % self.type) # choose the view_mode accordingly - if len(lines.ids) > 1: + if len(lines.ids) != 1: result['domain'] = [('id', 'in', lines.ids)] else: result['views'] = [(res and res.id or False, 'form')] @@ -185,10 +179,8 @@ class RmaOrder(models.Model): lines = self.rma_line_ids for line_id in lines: related_lines = [line.id for line in line_id.supplier_rma_line_ids] - if not related_lines: - raise ValidationError(_("No rma supplier lines found!")) # choose the view_mode accordingly - if len(related_lines) > 1: + if len(related_lines) != 1: result['domain'] = [('id', 'in', related_lines)] else: res = self.env.ref('rma.view_rma_line_supplier_form', False) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index f3394670..7f074365 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -514,15 +514,13 @@ class RmaOrderLine(models.Model): picking_ids = self.env['stock.picking'].search( [('origin', '=', self.name), ('picking_type_code', '=', 'incoming')]).ids - if not picking_ids: - raise ValidationError(_("No shipments found!")) # choose the view_mode accordingly if len(picking_ids) > 1: result['domain'] = [('id', 'in', picking_ids)] else: res = self.env.ref('stock.view_picking_form', False) result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = picking_ids[0] + result['res_id'] = picking_ids and picking_ids[0] return result @api.multi @@ -532,13 +530,11 @@ class RmaOrderLine(models.Model): picking_ids = self.env['stock.picking'].search( [('origin', '=', self.name), ('picking_type_code', '=', 'outgoing')]).ids - if not picking_ids: - raise ValidationError(_("No deliveries found!")) # choose the view_mode accordingly if len(picking_ids) > 1: result['domain'] = [('id', 'in', picking_ids)] else: res = self.env.ref('stock.view_picking_form', False) result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = picking_ids[0] + result['res_id'] = picking_ids and picking_ids[0] return result diff --git a/rma/tests/__init__.py b/rma/tests/__init__.py index 619dbb54..7262aab1 100644 --- a/rma/tests/__init__.py +++ b/rma/tests/__init__.py @@ -1,5 +1,6 @@ # Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + from . import test_rma from . import test_supplier_rma from . import test_rma_dropship diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 425dd030..81d20e43 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -224,7 +224,6 @@ class TestRma(common.TransactionCase): })._default_delivery_address() line._compute_in_shipment_count() line._compute_out_shipment_count() - line._compute_procurement_count() data = {'reference_move_id': line.reference_move_id.id} new_line = self.rma_line.new(data) @@ -252,7 +251,6 @@ class TestRma(common.TransactionCase): line.action_view_in_shipments() line.action_view_out_shipments() - line.action_view_procurements() self.rma_customer_id.action_view_supplier_lines() with self.assertRaises(ValidationError): line.rma_id.partner_id = partner2.id @@ -274,12 +272,7 @@ class TestRma(common.TransactionCase): 'active_id': 1 }).default_get({}) procurements = wizard._create_picking() - for proc in procurements: - proc._get_stock_move_values() - - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] + domain = [('origin', '=', procurements)] picking = self.stockpicking.search(domain) self.assertEquals(len(picking), 1, "Incorrect number of pickings created") @@ -351,9 +344,7 @@ class TestRma(common.TransactionCase): 'picking_type': 'outgoing', }).create({}) procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] + domain = [('origin', '=', procurements)] pickings = self.stockpicking.search(domain) self.assertEquals(len(pickings), 2, "Incorrect number of pickings created") diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py index b22dfbc2..d149fc18 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -48,9 +48,7 @@ class TestRmaDropship(test_rma.TestRma): 'picking_type': 'incoming', }).create({}) procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] + domain = [('origin', '=', procurements)] picking = self.stockpicking.search(domain) self.assertEquals(len(picking), 1, "Incorrect number of pickings created") diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py index 27666386..b5444691 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -22,9 +22,7 @@ class TestSupplierRma(test_rma.TestRma): 'active_id': 1 }).create({}) procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] + domain = [('origin', '=', procurements)] picking = self.stockpicking.search(domain) self.assertEquals(len(picking), 1, "Incorrect number of pickings created") @@ -91,9 +89,7 @@ class TestSupplierRma(test_rma.TestRma): 'picking_type': 'incoming', }).create({}) procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] + domain = [('origin', '=', procurements)] pickings = self.stockpicking.search(domain) self.assertEquals(len(pickings), 2, "Incorrect number of pickings created") diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py index 75cf39ab..1f276a2c 100644 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -101,15 +101,16 @@ class RmaAddStockMove(models.TransientModel): existing_stock_moves = self._get_existing_stock_moves() for sm in self.move_ids: if sm not in existing_stock_moves: - if sm.lot_ids: - for lot in sm.lot_ids: - data = self._prepare_rma_line_from_stock_move(sm, - lot=lot) - rma_line_obj.with_context( - default_rma_id=self.rma_id.id).create(data) + if sm.product_id.tracking == 'none': + data = self._prepare_rma_line_from_stock_move(sm, + lot=False) + rma_line_obj.with_context( + default_rma_id=self.rma_id.id).create(data) else: + lot_ids = [x.lot_id.id for x in sm.move_line_ids if + x.lot_id] data = self._prepare_rma_line_from_stock_move( - sm, lot=False) + sm, lot=lot_ids[0]) rma_line_obj.with_context( default_rma_id=self.rma_id.id).create(data) return {'type': 'ir.actions.act_window_close'} diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py index f361b427..5da02b0f 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -209,7 +209,7 @@ class RmaMakePicking(models.TransientModel): else: form = self.env.ref('stock.view_picking_form', False) action['views'] = [(form and form.id or False, 'form')] - action['res_id'] = pickings[0] + action['res_id'] = pickings and pickings[0] return action @api.multi From e3de350b91862cba3ca187dbf566b83b24c6f295 Mon Sep 17 00:00:00 2001 From: Jordi Ballester Date: Wed, 14 Feb 2018 13:35:09 +0100 Subject: [PATCH 30/81] multiple fixes --- rma/data/rma_operation.xml | 23 ++-- rma/models/rma_order_line.py | 22 ++-- rma/tests/test_rma.py | 107 +++++++----------- rma/tests/test_rma_dropship.py | 48 ++++---- rma/tests/test_supplier_rma.py | 79 ++++++------- rma/views/rma_operation_view.xml | 4 +- rma/views/rma_order_line_view.xml | 7 +- rma/wizards/rma_make_picking.py | 30 +++-- .../rma_order_line_make_supplier_rma.py | 9 +- 9 files changed, 156 insertions(+), 173 deletions(-) diff --git a/rma/data/rma_operation.xml b/rma/data/rma_operation.xml index 469ed58d..27e9be66 100755 --- a/rma/data/rma_operation.xml +++ b/rma/data/rma_operation.xml @@ -1,5 +1,5 @@ - + Replace After Receive RPLC @@ -21,29 +21,24 @@ - Replace deliver to vendor + Drop Ship - Replace deliver to vendor DSRPLB ordered no customer - - - - - Replace receive in vendor - DSRPLV - no - received - customer + True + - Replace deliver to customer + Drop Ship - Replace deliver to customer DSRPC - no - received + ordered + no supplier + True + diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 7f074365..78e60dee 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -139,7 +139,7 @@ class RmaOrderLine(models.Model): def _compute_qty_supplier_rma(self): for rec in self: qty = rec._get_supplier_rma_qty() - rec.qty_to_supplier_rma = rec.qty_to_receive - qty + rec.qty_to_supplier_rma = rec.product_qty - qty rec.qty_in_supplier_rma = qty delivery_address_id = fields.Many2one( @@ -489,8 +489,10 @@ class RmaOrderLine(models.Model): self.in_warehouse_id.lot_rma_id self.customer_to_supplier = self.operation_id.customer_to_supplier self.supplier_to_customer = self.operation_id.supplier_to_customer - self.in_route_id = self.operation_id.in_route_id - self.out_route_id = self.operation_id.out_route_id + if self.operation_id.in_route_id: + self.in_route_id = self.operation_id.in_route_id + if self.operation_id.out_route_id: + self.out_route_id = self.operation_id.out_route_id return result @api.onchange('customer_to_supplier', 'type') @@ -511,9 +513,10 @@ class RmaOrderLine(models.Model): def action_view_in_shipments(self): action = self.env.ref('stock.action_picking_tree_all') result = action.read()[0] - picking_ids = self.env['stock.picking'].search( - [('origin', '=', self.name), - ('picking_type_code', '=', 'incoming')]).ids + moves = self.env['stock.move'].search([ + ('rma_line_id', 'in', self.ids)]) + picking_ids = moves.mapped('picking_id').filtered( + lambda p: p.picking_type_code == 'incoming').ids # choose the view_mode accordingly if len(picking_ids) > 1: result['domain'] = [('id', 'in', picking_ids)] @@ -527,9 +530,10 @@ class RmaOrderLine(models.Model): def action_view_out_shipments(self): action = self.env.ref('stock.action_picking_tree_all') result = action.read()[0] - picking_ids = self.env['stock.picking'].search( - [('origin', '=', self.name), - ('picking_type_code', '=', 'outgoing')]).ids + moves = self.env['stock.move'].search([ + ('rma_line_id', 'in', self.ids)]) + picking_ids = moves.mapped('picking_id').filtered( + lambda p: p.picking_type_code == 'outgoing').ids # choose the view_mode accordingly if len(picking_ids) > 1: result['domain'] = [('id', 'in', picking_ids)] diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 81d20e43..3548589a 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -160,6 +160,8 @@ class TestRma(common.TransactionCase): supplier_address_id=supplier_address_id.id) data['partner_id'] = move.partner_id.id data['rma_id'] = rma_id.id + if type == 'supplier': + self.rma_line = self.rma_line.with_context(supplier=True) self.line = self.rma_line.create(data) # approve the RMA Line self.rma_line.action_rma_to_approve() @@ -264,18 +266,18 @@ class TestRma(common.TransactionCase): 'active_model': 'rma.order.line', 'picking_type': 'incoming', 'active_id': 1 - }).create({'rma_id': self.rma_customer_id.id}) + }).create({}) wizard.with_context({ 'active_ids': self.rma_customer_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'incoming', 'active_id': 1 }).default_get({}) - procurements = wizard._create_picking() - domain = [('origin', '=', procurements)] - picking = self.stockpicking.search(domain) - self.assertEquals(len(picking), 1, - "Incorrect number of pickings created") + wizard._create_picking() + res = self.rma_customer_id.rma_line_ids.action_view_in_shipments() + self.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = self.env['stock.picking'].browse(res['res_id']) moves = picking.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") @@ -309,33 +311,29 @@ class TestRma(common.TransactionCase): "Wrong qty to receive") self.assertEquals(line.qty_incoming, 2, "Wrong qty incoming") + picking.action_confirm() picking.action_assign() - picking.force_assign() - picking.do_new_transfer() + for line in picking.move_line_ids: + line.qty_done = line.product_uom_qty + picking.action_done() for line in self.rma_customer_id.rma_line_ids: - self.assertEquals(line.qty_received, 0, + self.assertEquals(line.qty_to_receive, 0, "Wrong qty to_receive") -# self.assertEquals(line.qty_incoming, 5, -# "Wrong qty incoming") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to received") - self.assertEquals(line.qty_incoming, 3, - "Wrong qty incoming") + self.assertEquals(line.qty_received, 3, + "Wrong qty received") if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to received") - self.assertEquals(line.qty_incoming, 5, - "Wrong qty incoming") + self.assertEquals(line.qty_received, 5, + "Wrong qty received") if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to received") - self.assertEquals(line.qty_incoming, 2, - "Wrong qty incoming") + self.assertEquals(line.qty_received, 2, + "Wrong qty received") wizard = self.rma_make_picking.with_context({ 'active_id': 1, @@ -343,72 +341,51 @@ class TestRma(common.TransactionCase): 'active_model': 'rma.order.line', 'picking_type': 'outgoing', }).create({}) - procurements = wizard._create_picking() - domain = [('origin', '=', procurements)] - pickings = self.stockpicking.search(domain) - self.assertEquals(len(pickings), 2, - "Incorrect number of pickings created") - picking_out = pickings[0] - moves = picking_out.move_lines + wizard._create_picking() + res = self.rma_customer_id.rma_line_ids.action_view_out_shipments() + self.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = self.env['stock.picking'].browse(res['res_id']) + moves = picking.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") for line in self.rma_customer_id.rma_line_ids: - self.assertEquals(line.qty_received, 0, - "Wrong qty receive") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") if line.product_id == self.product_1: - self.assertEquals(line.qty_to_deliver, 0, + self.assertEquals(line.qty_to_deliver, 3, "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 0, + self.assertEquals(line.qty_outgoing, 3, "Wrong qty outgoing") - self.assertEquals(line.qty_received, 0, - "Wrong qty received") if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to received") - self.assertEquals(line.qty_incoming, 5, - "Wrong qty incoming") - self.assertEquals(line.qty_outgoing, 0, + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 5, "Wrong qty outgoing") if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to received") - self.assertEquals(line.qty_incoming, 2, - "Wrong qty incoming") - self.assertEquals(line.qty_outgoing, 0, + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 2, "Wrong qty outgoing") - picking_out.action_assign() - picking_out.do_new_transfer() + picking.action_confirm() + picking.action_assign() + for line in picking.move_line_ids: + line.qty_done = line.product_uom_qty + picking.action_done() for line in self.rma_customer_id.rma_line_ids[0]: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 3, - "Wrong qty incoming") self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to received") - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to delivered") + self.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 5, - "Wrong qty received") self.assertEquals(line.qty_delivered, 5, "Wrong qty delivered") if line.product_id == self.product_3: - self.assertEquals(line.qty_received, 2, - "Wrong qty received") self.assertEquals(line.qty_delivered, 2, "Wrong qty delivered") self.line.action_rma_done() self.assertEquals(self.line.state, 'done', "Wrong State") - self.rma_customer_id.action_view_in_shipments() - self.rma_customer_id.action_view_out_shipments() - self.rma_customer_id.action_view_lines() diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py index d149fc18..dedb7a39 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -8,18 +8,26 @@ class TestRmaDropship(test_rma.TestRma): def setUp(self): super(TestRmaDropship, self).setUp() + rma_operation_ds_replace = self.env.ref( + 'rma.rma_operation_ds_replace') + self.rma_operation_ds_replace_supplier = self.env.ref( + 'rma.rma_operation_ds_replace_supplier') self.product_id.write( - {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, - 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + {'rma_customer_operation_id': rma_operation_ds_replace.id, + 'rma_supplier_operation_id': + self.rma_operation_ds_replace_supplier.id}) self.product_1.write( - {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, - 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + {'rma_customer_operation_id': rma_operation_ds_replace.id, + 'rma_supplier_operation_id': + self.rma_operation_ds_replace_supplier.id}) self.product_2.write( - {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, - 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + {'rma_customer_operation_id': rma_operation_ds_replace.id, + 'rma_supplier_operation_id': + self.rma_operation_ds_replace_supplier.id}) self.product_3.write( - {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, - 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) + {'rma_customer_operation_id': rma_operation_ds_replace.id, + 'rma_supplier_operation_id': + self.rma_operation_ds_replace_supplier.id}) products2move = [(self.product_1, 3), (self.product_2, 5), (self.product_3, 2)] self.rma_droship_id = self._create_rma_from_move( @@ -32,13 +40,14 @@ class TestRmaDropship(test_rma.TestRma): 'active_ids': self.rma_droship_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'active_id': 1 - }).create({'partner_id': self.partner_id.id, - 'supplier_rma_id': self.rma_droship_id.id, - }) + }).create({}) res = wizard.make_supplier_rma() supplier_rma = self.rma.browse(res['res_id']) for line in supplier_rma.rma_line_ids: + line.delivery_address_id = self.env.ref('base.res_partner_2') + line.operation_id = self.rma_operation_ds_replace_supplier + line._onchange_operation_id() line.action_rma_to_approve() line.action_rma_approve() wizard = self.rma_make_picking.with_context({ @@ -47,22 +56,15 @@ class TestRmaDropship(test_rma.TestRma): 'active_model': 'rma.order.line', 'picking_type': 'incoming', }).create({}) - procurements = wizard._create_picking() - domain = [('origin', '=', procurements)] - picking = self.stockpicking.search(domain) - self.assertEquals(len(picking), 1, - "Incorrect number of pickings created") + wizard._create_picking() + res = supplier_rma.rma_line_ids.action_view_in_shipments() + self.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = self.env['stock.picking'].browse(res['res_id']) moves = picking.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") for line in supplier_rma.rma_line_ids: - # common qtys for all products - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") # product specific if line.product_id == self.product_1: self.assertEquals(line.qty_to_receive, 3, diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py index b5444691..6cc3c15c 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -8,6 +8,8 @@ class TestSupplierRma(test_rma.TestRma): def setUp(self): super(TestSupplierRma, self).setUp() + self.rma_operation_supplier_replace = self.env.ref( + 'rma.rma_operation_supplier_replace') products2move = [(self.product_1, 3), (self.product_2, 5), (self.product_3, 2)] self.rma_supplier_id = self._create_rma_from_move( @@ -15,17 +17,22 @@ class TestSupplierRma(test_rma.TestRma): dropship=False) def test_supplier_rma(self): + for line in self.rma_supplier_id.rma_line_ids: + line.operation_id = self.rma_operation_supplier_replace + line._onchange_operation_id() + line.action_rma_to_approve() + line.action_rma_approve() wizard = self.rma_make_picking.with_context({ 'active_ids': self.rma_supplier_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'outgoing', 'active_id': 1 }).create({}) - procurements = wizard._create_picking() - domain = [('origin', '=', procurements)] - picking = self.stockpicking.search(domain) - self.assertEquals(len(picking), 1, - "Incorrect number of pickings created") + wizard._create_picking() + res = self.rma_supplier_id.rma_line_ids.action_view_out_shipments() + self.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = self.env['stock.picking'].browse(res['res_id']) moves = picking.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") @@ -59,26 +66,27 @@ class TestSupplierRma(test_rma.TestRma): "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 2, "Wrong qty outgoing") - - picking.action_assign() - picking.do_new_transfer() + picking.force_assign() + for line in picking.move_lines: + line.quantity_done = line.product_uom_qty + picking.button_validate() for line in self.rma_supplier_id.rma_line_ids: self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming") self.assertEquals(line.qty_received, 0, "Wrong qty received") if line.product_id == self.product_1: - self.assertEquals(line.qty_delivered, 0, + self.assertEquals(line.qty_delivered, 3, "Wrong qty delivered") self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") if line.product_id == self.product_2: - self.assertEquals(line.qty_delivered, 0, + self.assertEquals(line.qty_delivered, 5, "Wrong qty delivered") self.assertEquals(line.qty_to_receive, 5, "Wrong qty to receive") if line.product_id == self.product_3: - self.assertEquals(line.qty_delivered, 0, + self.assertEquals(line.qty_delivered, 2, "Wrong qty delivered") self.assertEquals(line.qty_to_receive, 2, "Wrong qty to receive") @@ -88,63 +96,48 @@ class TestSupplierRma(test_rma.TestRma): 'active_model': 'rma.order.line', 'picking_type': 'incoming', }).create({}) - procurements = wizard._create_picking() - domain = [('origin', '=', procurements)] - pickings = self.stockpicking.search(domain) - self.assertEquals(len(pickings), 2, - "Incorrect number of pickings created") - picking_out = pickings[0] - moves = picking_out.move_lines + wizard._create_picking() + res = self.rma_supplier_id.rma_line_ids.action_view_in_shipments() + self.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = self.env['stock.picking'].browse(res['res_id']) + moves = picking.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") for line in self.rma_supplier_id.rma_line_ids: - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") self.assertEquals(line.qty_received, 0, "Wrong qty received") if line.product_id == self.product_1: self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 0, + self.assertEquals(line.qty_incoming, 3, "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") if line.product_id == self.product_2: self.assertEquals(line.qty_to_receive, 5, "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to deliver") + self.assertEquals(line.qty_incoming, 5, + "Wrong qty incoming") if line.product_id == self.product_3: self.assertEquals(line.qty_to_receive, 2, "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to deliver") - picking_out.action_assign() - picking_out.do_new_transfer() + self.assertEquals(line.qty_incoming, 2, + "Wrong qty incoming") + picking.action_assign() + for line in picking.move_line_ids: + line.qty_done = line.product_uom_qty + picking.action_done() for line in self.rma_supplier_id.rma_line_ids[0]: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") self.assertEquals(line.qty_incoming, 0, "Wrong qty incoming") - self.assertEquals(line.qty_to_deliver, 3, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 6, - "Wrong qty outgoing") if line.product_id == self.product_1: - self.assertEquals(line.qty_received, 0, + self.assertEquals(line.qty_received, 3, "Wrong qty received") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 0, + self.assertEquals(line.qty_received, 5, "Wrong qty received") - self.assertEquals(line.qty_delivered, 5, - "Wrong qty delivered") if line.product_id == self.product_3: self.assertEquals(line.qty_received, 2, "Wrong qty received") - self.assertEquals(line.qty_delivered, 2, - "Wrong qty delivered") for line in self.rma_supplier_id.rma_line_ids: line.action_rma_done() self.assertEquals(line.state, 'done', diff --git a/rma/views/rma_operation_view.xml b/rma/views/rma_operation_view.xml index 0b96ff4e..e4fd4824 100755 --- a/rma/views/rma_operation_view.xml +++ b/rma/views/rma_operation_view.xml @@ -38,13 +38,13 @@ + - diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index 17fa9fcf..38093034 100755 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -144,10 +144,13 @@ - + + + diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py index 5da02b0f..db785c2f 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -3,7 +3,7 @@ import time from odoo import models, fields, api, _ -from odoo.exceptions import ValidationError +from odoo.exceptions import UserError, ValidationError from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT_FORMAT import odoo.addons.decimal_precision as dp @@ -103,6 +103,9 @@ class RmaMakePicking(models.TransientModel): if line.customer_to_supplier: location = self._get_address_location( delivery_address_id, 'supplier') + elif line.supplier_to_customer: + location = self._get_address_location( + delivery_address_id, 'customer') else: location = line.location_id warehouse = line.in_warehouse_id @@ -134,6 +137,7 @@ class RmaMakePicking(models.TransientModel): @api.model def _create_procurement(self, item, picking_type): + errors = [] group = self.find_procurement_group(item) if not group: pg_data = self._get_procurement_group_data(item) @@ -144,15 +148,20 @@ class RmaMakePicking(models.TransientModel): qty = item.qty_to_deliver values = self._get_procurement_data(item, group, qty, picking_type) # create picking - self.env['procurement.group'].run( - item.line_id.product_id, - qty, - item.line_id.product_id.product_tmpl_id.uom_id, - values.get('location_id'), - values.get('origin'), - values.get('origin'), - values - ) + try: + self.env['procurement.group'].run( + item.line_id.product_id, + qty, + item.line_id.product_id.product_tmpl_id.uom_id, + values.get('location_id'), + values.get('origin'), + values.get('origin'), + values + ) + except UserError as error: + errors.append(error.name) + if errors: + raise UserError('\n'.join(errors)) return values.get('origin') @api.multi @@ -198,7 +207,6 @@ class RmaMakePicking(models.TransientModel): @api.multi def action_create_picking(self): procurement = self._create_picking() - pickings = False action = self.env.ref('stock.do_view_pickings') action = action.read()[0] if procurement: diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py index f127327e..f6def3b6 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma.py +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -66,15 +66,16 @@ class RmaLineMakeSupplierRma(models.TransientModel): raise ValidationError(_('Enter a supplier.')) return { 'partner_id': self.partner_id.id, - 'delivery_address_id': self.partner_id.id, 'type': 'supplier', 'company_id': company.id, } @api.model def _prepare_supplier_rma_line(self, rma, item): - operation = self.env['rma.operation'].search( - [('type', '=', 'supplier')], limit=1) + operation = item.line_id.product_id.rma_supplier_operation_id + if not operation: + operation = self.env['rma.operation'].search( + [('type', '=', 'supplier')], limit=1) if not operation.in_route_id or not operation.out_route_id: route = self.env['stock.location.route'].search( [('rma_selectable', '=', True)], limit=1) @@ -97,7 +98,7 @@ class RmaLineMakeSupplierRma(models.TransientModel): 'customer_rma_id': item.line_id.id, 'product_qty': item.product_qty, 'rma_id': rma.id, - 'uom_id': item.uom_id.id, + 'uom_id': item.line_id.uom_id.id, 'operation_id': operation.id, 'receipt_policy': operation.receipt_policy, 'delivery_policy': operation.delivery_policy, From 8d3cfd3e7022329ccb44fecf9bcf3f391201ae03 Mon Sep 17 00:00:00 2001 From: Bhavesh Odedra Date: Wed, 14 Feb 2018 19:22:41 +0530 Subject: [PATCH 31/81] [IMP] Various improvements --- rma/models/rma_order_line.py | 14 ++++---- rma/views/product_view.xml | 21 ++++++----- rma/wizards/rma_make_picking_view.xml | 4 +-- .../rma_order_line_make_supplier_rma_view.xml | 35 +++++++------------ 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 78e60dee..454af5cc 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -46,16 +46,18 @@ class RmaOrderLine(models.Model): @api.multi def _compute_in_shipment_count(self): for line in self: - line.in_shipment_count = len(self.env['stock.picking'].search( - [('origin', '=', line.name), - ('picking_type_code', '=', 'incoming')]).ids) + moves = self.env['stock.move'].search([ + ('rma_line_id', '=', line.id)]) + line.in_shipment_count = len(moves.mapped('picking_id').filtered( + lambda p: p.picking_type_code == 'incoming').ids) @api.multi def _compute_out_shipment_count(self): for line in self: - line.out_shipment_count = len(self.env['stock.picking'].search( - [('origin', '=', line.name), - ('picking_type_code', '=', 'outgoing')]).ids) + moves = self.env['stock.move'].search([ + ('rma_line_id', '=', line.id)]) + line.out_shipment_count = len(moves.mapped('picking_id').filtered( + lambda p: p.picking_type_code == 'outgoing').ids) @api.multi def _get_rma_move_qty(self, states, direction='in'): diff --git a/rma/views/product_view.xml b/rma/views/product_view.xml index aeb6da9d..a2810600 100755 --- a/rma/views/product_view.xml +++ b/rma/views/product_view.xml @@ -3,13 +3,16 @@ product.category.form product.category - + - + - - - + + + @@ -20,11 +23,13 @@ product.template - + - - + + diff --git a/rma/wizards/rma_make_picking_view.xml b/rma/wizards/rma_make_picking_view.xml index 126bf191..61bd41de 100755 --- a/rma/wizards/rma_make_picking_view.xml +++ b/rma/wizards/rma_make_picking_view.xml @@ -61,26 +61,26 @@ Create Incoming Shipment ir.actions.act_window rma_make_picking.wizard - rma.order.line form form new {'picking_type': 'incoming'} + Create Delivery ir.actions.act_window rma_make_picking.wizard - rma.order.line form form new {'picking_type': 'outgoing'} + diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml index 1129702f..1ba47921 100755 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -56,29 +56,20 @@ form new + - - - - rma.order.line.supplier.rma.form - rma.order.line - - -
-
-
+ + rma.order.line.supplier.rma.form + rma.order.line + + +
+
+
From d41ea652701898c7c30f5f0de8e77e5b3637f7f6 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Mon, 25 Jun 2018 12:04:11 -0500 Subject: [PATCH 32/81] [FIX] Cannot create partner --- rma/security/ir.model.access.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rma/security/ir.model.access.csv b/rma/security/ir.model.access.csv index 7362e7eb..e899b9c9 100755 --- a/rma/security/ir.model.access.csv +++ b/rma/security/ir.model.access.csv @@ -8,4 +8,4 @@ access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1, access_rma_operation_manager,access_rma_operation,model_rma_operation,group_rma_manager,1,1,1,1 access_rma_operation_customer_user,access_rma_operation,model_rma_operation,group_rma_customer_user,1,0,0,0 access_rma_operation_supplier_user,access_rma_operation,model_rma_operation,group_rma_supplier_user,1,0,0,0 - +access_rma_order_line_user,access_rma_order_line,model_rma_order_line,base.group_user,1,0,0,0 From 7826de9718eb7300a929f7e77b3c457d23b8ab4e Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Tue, 26 Jun 2018 12:02:00 -0500 Subject: [PATCH 33/81] [FIX] Add read access to stock.move --- rma/security/ir.model.access.csv | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rma/security/ir.model.access.csv b/rma/security/ir.model.access.csv index e899b9c9..de0f5535 100755 --- a/rma/security/ir.model.access.csv +++ b/rma/security/ir.model.access.csv @@ -6,6 +6,12 @@ access_rma_line_customer_user,rma.order.line.customer.user,model_rma_order_line, access_rma_line_supplier_user,rma.order.line.customer.supplier,model_rma_order_line,group_rma_supplier_user,1,1,1,1 access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1,1,1,1 access_rma_operation_manager,access_rma_operation,model_rma_operation,group_rma_manager,1,1,1,1 +access_product_template_customer_user,access_product_template,product.model_product_template,group_rma_customer_user,1,1,0,0 +access_product_template_supplier_user,access_product_template,product.model_product_template,group_rma_supplier_user,1,1,0,0 +access_product_product_customer_user,access_product_product,product.model_product_product,group_rma_customer_user,1,1,0,0 +access_product_product_supplier_user,access_product_product,product.model_product_product,group_rma_supplier_user,1,1,0,0 access_rma_operation_customer_user,access_rma_operation,model_rma_operation,group_rma_customer_user,1,0,0,0 access_rma_operation_supplier_user,access_rma_operation,model_rma_operation,group_rma_supplier_user,1,0,0,0 +access_stock_move_customer_user,access_stock_move,stock.model_stock_move,group_rma_customer_user,1,0,0,0 +access_stock_move_supplier_user,access_stock_move,stock.model_stock_move,group_rma_supplier_user,1,0,0,0 access_rma_order_line_user,access_rma_order_line,model_rma_order_line,base.group_user,1,0,0,0 From 82cb12c2e190d65ca86f49e97a9c6c7cee7897cd Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Wed, 27 Jun 2018 08:09:46 -0500 Subject: [PATCH 34/81] [FIX] Access rights with group deps --- rma/security/ir.model.access.csv | 6 ------ rma/security/rma.xml | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/rma/security/ir.model.access.csv b/rma/security/ir.model.access.csv index de0f5535..e899b9c9 100755 --- a/rma/security/ir.model.access.csv +++ b/rma/security/ir.model.access.csv @@ -6,12 +6,6 @@ access_rma_line_customer_user,rma.order.line.customer.user,model_rma_order_line, access_rma_line_supplier_user,rma.order.line.customer.supplier,model_rma_order_line,group_rma_supplier_user,1,1,1,1 access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1,1,1,1 access_rma_operation_manager,access_rma_operation,model_rma_operation,group_rma_manager,1,1,1,1 -access_product_template_customer_user,access_product_template,product.model_product_template,group_rma_customer_user,1,1,0,0 -access_product_template_supplier_user,access_product_template,product.model_product_template,group_rma_supplier_user,1,1,0,0 -access_product_product_customer_user,access_product_product,product.model_product_product,group_rma_customer_user,1,1,0,0 -access_product_product_supplier_user,access_product_product,product.model_product_product,group_rma_supplier_user,1,1,0,0 access_rma_operation_customer_user,access_rma_operation,model_rma_operation,group_rma_customer_user,1,0,0,0 access_rma_operation_supplier_user,access_rma_operation,model_rma_operation,group_rma_supplier_user,1,0,0,0 -access_stock_move_customer_user,access_stock_move,stock.model_stock_move,group_rma_customer_user,1,0,0,0 -access_stock_move_supplier_user,access_stock_move,stock.model_stock_move,group_rma_supplier_user,1,0,0,0 access_rma_order_line_user,access_rma_order_line,model_rma_order_line,base.group_user,1,0,0,0 diff --git a/rma/security/rma.xml b/rma/security/rma.xml index f9b0cced..99e6a664 100755 --- a/rma/security/rma.xml +++ b/rma/security/rma.xml @@ -10,20 +10,21 @@ RMA Customer User - + RMA Supplier User - + RMA Manager + eval="[(4, ref('rma.group_rma_customer_user')), + (4, ref('rma.group_rma_supplier_user'))]"/> @@ -34,5 +35,15 @@
+ + + + + + + +
From f45ccd16885b66f393fde25d4e5a135667c97564 Mon Sep 17 00:00:00 2001 From: Bhavesh Odedra Date: Thu, 19 Jul 2018 20:08:43 +0530 Subject: [PATCH 35/81] [FIX] TypeError: unhashable type: 'list' --- rma/models/rma_order.py | 23 ++++++++++++----------- rma/models/rma_order_line.py | 30 ++++++++++++++++-------------- rma/wizards/rma_make_picking.py | 2 +- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/rma/models/rma_order.py b/rma/models/rma_order.py index 253f968a..54134542 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -109,9 +109,9 @@ class RmaOrder(models.Model): for move in line.move_ids: if move.picking_id.location_id == suppliers: picking_ids.append(move.picking_id.id) - shipments = list(set(picking_ids)) - # choose the view_mode accordingly - if shipments: + if picking_ids: + shipments = list(set(picking_ids)) + # choose the view_mode accordingly if len(shipments) > 1: result['domain'] = [('id', 'in', shipments)] else: @@ -136,14 +136,15 @@ class RmaOrder(models.Model): for move in line.move_ids: if move.picking_id.location_id != suppliers: picking_ids.append(move.picking_id.id) - shipments = list(set(picking_ids)) - # choose the view_mode accordingly - if len(shipments) != 1: - result['domain'] = [('id', 'in', shipments)] - else: - res = self.env.ref('stock.view_picking_form', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = shipments[0] + if picking_ids: + shipments = list(set(picking_ids)) + # choose the view_mode accordingly + if len(shipments) != 1: + result['domain'] = [('id', 'in', shipments)] + else: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = shipments[0] return result @api.multi diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 454af5cc..58287ba7 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -519,13 +519,14 @@ class RmaOrderLine(models.Model): ('rma_line_id', 'in', self.ids)]) picking_ids = moves.mapped('picking_id').filtered( lambda p: p.picking_type_code == 'incoming').ids - # choose the view_mode accordingly - if len(picking_ids) > 1: - result['domain'] = [('id', 'in', picking_ids)] - else: - res = self.env.ref('stock.view_picking_form', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = picking_ids and picking_ids[0] + if picking_ids: + # choose the view_mode accordingly + if len(picking_ids) > 1: + result['domain'] = [('id', 'in', picking_ids)] + else: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = picking_ids and picking_ids[0] return result @api.multi @@ -536,11 +537,12 @@ class RmaOrderLine(models.Model): ('rma_line_id', 'in', self.ids)]) picking_ids = moves.mapped('picking_id').filtered( lambda p: p.picking_type_code == 'outgoing').ids - # choose the view_mode accordingly - if len(picking_ids) > 1: - result['domain'] = [('id', 'in', picking_ids)] - else: - res = self.env.ref('stock.view_picking_form', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = picking_ids and picking_ids[0] + if picking_ids: + # choose the view_mode accordingly + if len(picking_ids) > 1: + result['domain'] = [('id', 'in', picking_ids)] + else: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = picking_ids and picking_ids[0] return result diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py index db785c2f..dfbac614 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -187,7 +187,7 @@ class RmaMakePicking(models.TransientModel): @api.model def _get_action(self, pickings, procurements): - if pickings: + if pickings and procurements: action = procurements.do_view_pickings() else: action = self.env.ref( From 317aea6183db3bdcb9778cfbc10cc2ac70ffae5f Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Tue, 26 Jun 2018 12:02:00 -0500 Subject: [PATCH 36/81] [FIX] Add read access to stock.move --- rma/security/ir.model.access.csv | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rma/security/ir.model.access.csv b/rma/security/ir.model.access.csv index e899b9c9..de0f5535 100755 --- a/rma/security/ir.model.access.csv +++ b/rma/security/ir.model.access.csv @@ -6,6 +6,12 @@ access_rma_line_customer_user,rma.order.line.customer.user,model_rma_order_line, access_rma_line_supplier_user,rma.order.line.customer.supplier,model_rma_order_line,group_rma_supplier_user,1,1,1,1 access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1,1,1,1 access_rma_operation_manager,access_rma_operation,model_rma_operation,group_rma_manager,1,1,1,1 +access_product_template_customer_user,access_product_template,product.model_product_template,group_rma_customer_user,1,1,0,0 +access_product_template_supplier_user,access_product_template,product.model_product_template,group_rma_supplier_user,1,1,0,0 +access_product_product_customer_user,access_product_product,product.model_product_product,group_rma_customer_user,1,1,0,0 +access_product_product_supplier_user,access_product_product,product.model_product_product,group_rma_supplier_user,1,1,0,0 access_rma_operation_customer_user,access_rma_operation,model_rma_operation,group_rma_customer_user,1,0,0,0 access_rma_operation_supplier_user,access_rma_operation,model_rma_operation,group_rma_supplier_user,1,0,0,0 +access_stock_move_customer_user,access_stock_move,stock.model_stock_move,group_rma_customer_user,1,0,0,0 +access_stock_move_supplier_user,access_stock_move,stock.model_stock_move,group_rma_supplier_user,1,0,0,0 access_rma_order_line_user,access_rma_order_line,model_rma_order_line,base.group_user,1,0,0,0 From a24af7cd1e22c533fa40f42e5220b3a2ea3906bd Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Wed, 27 Jun 2018 08:09:46 -0500 Subject: [PATCH 37/81] [FIX] Access rights with group deps --- rma/security/ir.model.access.csv | 6 ------ 1 file changed, 6 deletions(-) diff --git a/rma/security/ir.model.access.csv b/rma/security/ir.model.access.csv index de0f5535..e899b9c9 100755 --- a/rma/security/ir.model.access.csv +++ b/rma/security/ir.model.access.csv @@ -6,12 +6,6 @@ access_rma_line_customer_user,rma.order.line.customer.user,model_rma_order_line, access_rma_line_supplier_user,rma.order.line.customer.supplier,model_rma_order_line,group_rma_supplier_user,1,1,1,1 access_rma_line_manager,rma.order.line,model_rma_order_line,group_rma_manager,1,1,1,1 access_rma_operation_manager,access_rma_operation,model_rma_operation,group_rma_manager,1,1,1,1 -access_product_template_customer_user,access_product_template,product.model_product_template,group_rma_customer_user,1,1,0,0 -access_product_template_supplier_user,access_product_template,product.model_product_template,group_rma_supplier_user,1,1,0,0 -access_product_product_customer_user,access_product_product,product.model_product_product,group_rma_customer_user,1,1,0,0 -access_product_product_supplier_user,access_product_product,product.model_product_product,group_rma_supplier_user,1,1,0,0 access_rma_operation_customer_user,access_rma_operation,model_rma_operation,group_rma_customer_user,1,0,0,0 access_rma_operation_supplier_user,access_rma_operation,model_rma_operation,group_rma_supplier_user,1,0,0,0 -access_stock_move_customer_user,access_stock_move,stock.model_stock_move,group_rma_customer_user,1,0,0,0 -access_stock_move_supplier_user,access_stock_move,stock.model_stock_move,group_rma_supplier_user,1,0,0,0 access_rma_order_line_user,access_rma_order_line,model_rma_order_line,base.group_user,1,0,0,0 From 1ba0c77f0c82c27ae4d6317164bf98266fd7a547 Mon Sep 17 00:00:00 2001 From: aheficent Date: Thu, 26 Jul 2018 18:41:44 +0200 Subject: [PATCH 38/81] [MIG]rma v110.0.2.0.0 --- rma/README.rst | 8 + rma/__manifest__.py | 2 +- rma/data/rma_operation.xml | 26 +- rma/data/stock_data.xml | 2 - rma/models/rma_operation.py | 34 ++- rma/models/rma_order_line.py | 242 ++++++++++++----- rma/models/stock.py | 7 + rma/models/stock_warehouse.py | 254 +++++++++++++++++- rma/views/product_view.xml | 43 +-- rma/views/rma_operation_view.xml | 161 +++++------ rma/views/rma_order_line_view.xml | 115 +++++--- rma/wizards/rma_make_picking.py | 8 +- .../rma_order_line_make_supplier_rma.py | 85 ++++-- .../rma_order_line_make_supplier_rma_view.xml | 1 + 14 files changed, 711 insertions(+), 277 deletions(-) diff --git a/rma/README.rst b/rma/README.rst index 4fe6cf07..19617464 100644 --- a/rma/README.rst +++ b/rma/README.rst @@ -86,6 +86,14 @@ Create an RMA: Order". #. Go back to the RMA. Set the RMA to done if not further action is required. +Known issues and Roadmap +======================== + +* Picking operations report in customer RMA dropshipping case is showing + "Vendor Address" while it should be "Customer Address". +* Dropshipping always counted as a delivery on the smart buttons. +* Uninstall hook. +* Constraints instead of required fields on rma.order.line. Bug Tracker =========== diff --git a/rma/__manifest__.py b/rma/__manifest__.py index 66256b0e..7335d0d6 100644 --- a/rma/__manifest__.py +++ b/rma/__manifest__.py @@ -3,7 +3,7 @@ { 'name': 'RMA (Return Merchandise Authorization)', - 'version': '11.0.1.0.0', + 'version': '11.0.2.0.0', 'license': 'LGPL-3', 'category': 'RMA', 'summary': 'Introduces the return merchandise authorization (RMA) process ' diff --git a/rma/data/rma_operation.xml b/rma/data/rma_operation.xml index 27e9be66..9d1fc02f 100755 --- a/rma/data/rma_operation.xml +++ b/rma/data/rma_operation.xml @@ -1,8 +1,8 @@ - + Replace After Receive - RPLC + RPL-C ordered received customer @@ -12,7 +12,7 @@ Replace - RPLS + RPL-S ordered ordered supplier @@ -21,25 +21,25 @@ - Drop Ship - Replace deliver to vendor - DSRPLB + Dropship - Deliver to vendor + DS-RPL-C ordered no customer - True - + + - Drop Ship - Replace deliver to customer - DSRPC - ordered - no + Dropship - Deliver to customer + DS-RPL-S + no + ordered supplier - True - + + diff --git a/rma/data/stock_data.xml b/rma/data/stock_data.xml index ee943875..b9f100bd 100755 --- a/rma/data/stock_data.xml +++ b/rma/data/stock_data.xml @@ -188,7 +188,6 @@ Customer → Supplier move - make_to_stock @@ -200,7 +199,6 @@ Supplier → Customer move - make_to_stock diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py index 9e9c12d6..bee15958 100644 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-18 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models @@ -23,6 +23,14 @@ class RmaOperation(models.Model): def _default_supplier_location_id(self): return self.env.ref('stock.stock_location_suppliers') or False + @api.model + def _default_routes(self): + op_type = self.env.context.get('default_type') + if op_type == 'customer': + return self.env.ref('rma.route_rma_customer') + elif op_type == 'supplier': + return self.env.ref('rma.route_rma_supplier') + name = fields.Char('Description', required=True) code = fields.Char('Code', required=True) active = fields.Boolean(string='Active', default=True) @@ -35,15 +43,21 @@ class RmaOperation(models.Model): ('received', 'Based on Received Quantities')], string="Delivery Policy", default='no') in_route_id = fields.Many2one( - 'stock.location.route', string='Inbound Route', - domain=[('rma_selectable', '=', True)]) + comodel_name='stock.location.route', string='Inbound Route', + domain=[('rma_selectable', '=', True)], + default=_default_routes, + ) out_route_id = fields.Many2one( - 'stock.location.route', string='Outbound Route', - domain=[('rma_selectable', '=', True)]) + comodel_name='stock.location.route', string='Outbound Route', + domain=[('rma_selectable', '=', True)], + default=_default_routes, + ) customer_to_supplier = fields.Boolean( - 'The customer will send to the supplier', default=False) + string='The customer will send to the supplier', + ) supplier_to_customer = fields.Boolean( - 'The supplier will send to the customer', default=False) + string='The supplier will send to the customer', + ) in_warehouse_id = fields.Many2one( comodel_name='stock.warehouse', string='Inbound Warehouse', default=_default_warehouse_id) @@ -55,5 +69,7 @@ class RmaOperation(models.Model): type = fields.Selection([ ('customer', 'Customer'), ('supplier', 'Supplier')], string="Used in RMA of this type", required=True) - rma_line_ids = fields.One2many('rma.order.line', 'operation_id', - 'RMA lines') + rma_line_ids = fields.One2many( + comodel_name='rma.order.line', inverse_name='operation_id', + string='RMA lines', + ) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 58287ba7..fceeaa94 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -46,18 +46,26 @@ class RmaOrderLine(models.Model): @api.multi def _compute_in_shipment_count(self): for line in self: - moves = self.env['stock.move'].search([ - ('rma_line_id', '=', line.id)]) - line.in_shipment_count = len(moves.mapped('picking_id').filtered( - lambda p: p.picking_type_code == 'incoming').ids) + picking_ids = [] + for move in line.move_ids: + if move.location_dest_id.usage == 'internal': + picking_ids.append(move.picking_id.id) + else: + if line.customer_to_supplier: + picking_ids.append(move.picking_id.id) + shipments = list(set(picking_ids)) + line.in_shipment_count = len(shipments) @api.multi def _compute_out_shipment_count(self): + picking_ids = [] for line in self: - moves = self.env['stock.move'].search([ - ('rma_line_id', '=', line.id)]) - line.out_shipment_count = len(moves.mapped('picking_id').filtered( - lambda p: p.picking_type_code == 'outgoing').ids) + for move in line.move_ids: + if move.location_dest_id.usage in ('supplier', 'customer'): + if not line.customer_to_supplier: + picking_ids.append(move.picking_id.id) + shipments = list(set(picking_ids)) + line.out_shipment_count = len(shipments) @api.multi def _get_rma_move_qty(self, states, direction='in'): @@ -82,9 +90,11 @@ class RmaOrderLine(models.Model): for rec in self: rec.qty_to_receive = 0.0 if rec.receipt_policy == 'ordered': - rec.qty_to_receive = rec.product_qty - rec.qty_received + rec.qty_to_receive = \ + rec.product_qty - rec.qty_incoming - rec.qty_received elif rec.receipt_policy == 'delivered': - rec.qty_to_receive = rec.qty_delivered - rec.qty_received + rec.qty_to_receive = \ + rec.qty_delivered - rec.qty_incoming - rec.qty_received @api.multi @api.depends('move_ids', 'move_ids.state', @@ -110,7 +120,10 @@ class RmaOrderLine(models.Model): @api.depends('move_ids', 'move_ids.state', 'type') def _compute_qty_received(self): for rec in self: - qty = rec._get_rma_move_qty('done', direction='in') + if rec.supplier_to_customer: + qty = rec._get_rma_move_qty('done', direction='out') + else: + qty = rec._get_rma_move_qty('done', direction='in') rec.qty_received = qty @api.multi @@ -125,7 +138,10 @@ class RmaOrderLine(models.Model): @api.depends('move_ids', 'move_ids.state', 'type') def _compute_qty_delivered(self): for rec in self: - qty = rec._get_rma_move_qty('done', direction='out') + if rec.supplier_to_customer: + qty = rec._get_rma_move_qty('done', direction='in') + else: + qty = rec._get_rma_move_qty('done', direction='out') rec.qty_delivered = qty @api.model @@ -140,9 +156,26 @@ class RmaOrderLine(models.Model): 'receipt_policy', 'product_qty', 'type') def _compute_qty_supplier_rma(self): for rec in self: - qty = rec._get_supplier_rma_qty() - rec.qty_to_supplier_rma = rec.product_qty - qty - rec.qty_in_supplier_rma = qty + if rec.customer_to_supplier: + supplier_rma_qty = rec._get_supplier_rma_qty() + rec.qty_to_supplier_rma = rec.product_qty - supplier_rma_qty + rec.qty_in_supplier_rma = supplier_rma_qty + else: + rec.qty_to_supplier_rma = 0.0 + rec.qty_in_supplier_rma = 0.0 + + @api.multi + def _compute_procurement_count(self): + for rec in self: + rec.procurement_count = len(rec.procurement_ids.filtered( + lambda p: p.state == 'exception')) + + @api.multi + def _compute_rma_line_count(self): + for rec in self.filtered(lambda r: r.type == 'customer'): + rec.rma_line_count = len(rec.supplier_rma_line_ids) + for rec in self.filtered(lambda r: r.type == 'supplier'): + rec.rma_line_count = len(rec.customer_rma_id) delivery_address_id = fields.Many2one( comodel_name='res.partner', string='Partner delivery address', @@ -180,9 +213,11 @@ class RmaOrderLine(models.Model): ) assigned_to = fields.Many2one( comodel_name='res.users', track_visibility='onchange', + default=lambda self: self.env.uid, ) requested_by = fields.Many2one( comodel_name='res.users', track_visibility='onchange', + default=lambda self: self.env.uid, ) partner_id = fields.Many2one( comodel_name='res.partner', required=True, store=True, @@ -217,10 +252,12 @@ class RmaOrderLine(models.Model): string='Price Unit', readonly=True, states={'draft': [('readonly', False)]}, ) + procurement_count = fields.Integer(compute=_compute_procurement_count, + string='# of Procurements', copy=False) in_shipment_count = fields.Integer(compute=_compute_in_shipment_count, - string='# of Shipments', default=0) + string='# of Shipments') out_shipment_count = fields.Integer(compute=_compute_out_shipment_count, - string='# of Deliveries', default=0) + string='# of Deliveries') move_ids = fields.One2many('stock.move', 'rma_line_id', string='Stock Moves', readonly=True, copy=False) @@ -293,11 +330,21 @@ class RmaOrderLine(models.Model): 'rma.order.line', string='Customer RMA line', ondelete='cascade') supplier_rma_line_ids = fields.One2many( 'rma.order.line', 'customer_rma_id') + rma_line_count = fields.Integer( + compute='_compute_rma_line_count', + string='# of RMA lines associated', + ) supplier_address_id = fields.Many2one( - 'res.partner', readonly=True, + comodel_name='res.partner', readonly=True, states={'draft': [('readonly', False)]}, string='Supplier Address', - help="This address of the supplier in case of Customer RMA operation " + help="Address of the supplier in case of Customer RMA operation " + "dropship.") + customer_address_id = fields.Many2one( + comodel_name='res.partner', readonly=True, + states={'draft': [('readonly', False)]}, + string='Customer Address', + help="Address of the customer in case of Supplier RMA operation " "dropship.") qty_to_receive = fields.Float( string='Qty To Receive', @@ -370,8 +417,9 @@ class RmaOrderLine(models.Model): [('company_id', '=', self.company_id.id), ('lot_rma_id', '!=', False)], limit=1) if not warehouse: - raise ValidationError(_( - "Please define a warehouse with a default RMA location.")) + raise ValidationError( + _("Please define a warehouse with a default RMA " + "location.")) data = { 'product_id': sm.product_id.id, @@ -397,26 +445,32 @@ class RmaOrderLine(models.Model): @api.onchange('reference_move_id') def _onchange_reference_move_id(self): self.ensure_one() - for move in self.reference_move_id: - data = self._prepare_rma_line_from_stock_move(move, lot=False) + sm = self.reference_move_id + if not sm: + return + if sm.lot_ids: + if len(sm.lot_ids) > 1: + raise UserError(_('To manage lots use RMA groups.')) + else: + data = self._prepare_rma_line_from_stock_move( + sm, lot=sm.lot_ids[0]) + self.update(data) + else: + data = self._prepare_rma_line_from_stock_move( + sm, lot=False) self.update(data) - self._remove_other_data_origin('reference_move_id') - lot_ids = [x.lot_id.id for x in move.move_line_ids if x.lot_id] - return {'domain': {'lot_id': [('id', 'in', lot_ids)]}} + self._remove_other_data_origin('reference_move_id') @api.multi @api.constrains('reference_move_id', 'partner_id') def _check_move_partner(self): for rec in self: if (rec.reference_move_id and - (rec.reference_move_id.partner_id != rec.partner_id) and - (rec.reference_move_id.picking_id.partner_id != - rec.partner_id)): - raise ValidationError(_( - "RMA customer (%s) and originating stock move customer" - " (%s) doesn't match." % ( - rec.reference_move_id.partner_id.name, - rec.partner_id.name))) + rec.reference_move_id.picking_id.partner_id != + rec.partner_id): + raise ValidationError(_( + "RMA customer and originating stock move customer " + "doesn't match.")) @api.multi def _remove_other_data_origin(self, exception): @@ -429,7 +483,6 @@ class RmaOrderLine(models.Model): self.write({'state': 'to_approve'}) for rec in self: if rec.product_id.rma_approval_policy == 'one_step': - rec.write({'assigned_to': self.env.uid}) rec.action_rma_approve() return True @@ -467,16 +520,20 @@ class RmaOrderLine(models.Model): result = {} if not self.product_id: return result - self.product_qty = 1 self.uom_id = self.product_id.uom_id.id self.price_unit = self.product_id.standard_price + if not self.type: + self.type = self._get_default_type() if self.type == 'customer': self.operation_id = self.product_id.rma_customer_operation_id or \ self.product_id.categ_id.rma_customer_operation_id else: self.operation_id = self.product_id.rma_supplier_operation_id or \ self.product_id.categ_id.rma_supplier_operation_id - return result + if self.lot_id.product_id != self.product_id: + self.lot_id = False + return {'domain': { + 'lot_id': [('product_id', '=', self.product_id.id)]}} @api.onchange('operation_id') def _onchange_operation_id(self): @@ -491,10 +548,8 @@ class RmaOrderLine(models.Model): self.in_warehouse_id.lot_rma_id self.customer_to_supplier = self.operation_id.customer_to_supplier self.supplier_to_customer = self.operation_id.supplier_to_customer - if self.operation_id.in_route_id: - self.in_route_id = self.operation_id.in_route_id - if self.operation_id.out_route_id: - self.out_route_id = self.operation_id.out_route_id + self.in_route_id = self.operation_id.in_route_id + self.out_route_id = self.operation_id.out_route_id return result @api.onchange('customer_to_supplier', 'type') @@ -506,43 +561,92 @@ class RmaOrderLine(models.Model): @api.onchange("lot_id") def _onchange_lot_id(self): - if self.lot_id and self.reference_move_id: - data = self._prepare_rma_line_from_stock_move( - self.reference_move_id, lot=self.lot_id) - self.update(data) + product = self.lot_id.product_id + if product: + self.product_id = product + self.uom_id = product.uom_id @api.multi def action_view_in_shipments(self): action = self.env.ref('stock.action_picking_tree_all') result = action.read()[0] - moves = self.env['stock.move'].search([ - ('rma_line_id', 'in', self.ids)]) - picking_ids = moves.mapped('picking_id').filtered( - lambda p: p.picking_type_code == 'incoming').ids - if picking_ids: - # choose the view_mode accordingly - if len(picking_ids) > 1: - result['domain'] = [('id', 'in', picking_ids)] - else: - res = self.env.ref('stock.view_picking_form', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = picking_ids and picking_ids[0] + picking_ids = [] + for line in self: + for move in line.move_ids: + if move.location_dest_id.usage == 'internal': + picking_ids.append(move.picking_id.id) + else: + if line.customer_to_supplier: + picking_ids.append(move.picking_id.id) + + shipments = list(set(picking_ids)) + # choose the view_mode accordingly + if len(shipments) != 1: + result['domain'] = "[('id', 'in', " + \ + str(shipments) + ")]" + elif len(shipments) == 1: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = shipments[0] return result @api.multi def action_view_out_shipments(self): action = self.env.ref('stock.action_picking_tree_all') result = action.read()[0] - moves = self.env['stock.move'].search([ - ('rma_line_id', 'in', self.ids)]) - picking_ids = moves.mapped('picking_id').filtered( - lambda p: p.picking_type_code == 'outgoing').ids - if picking_ids: - # choose the view_mode accordingly - if len(picking_ids) > 1: - result['domain'] = [('id', 'in', picking_ids)] - else: - res = self.env.ref('stock.view_picking_form', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = picking_ids and picking_ids[0] + picking_ids = [] + for line in self: + for move in line.move_ids: + if move.location_dest_id.usage in ('supplier', 'customer'): + if not line.customer_to_supplier: + picking_ids.append(move.picking_id.id) + shipments = list(set(picking_ids)) + # choose the view_mode accordingly + if len(shipments) != 1: + result['domain'] = "[('id', 'in', " + \ + str(shipments) + ")]" + elif len(shipments) == 1: + res = self.env.ref('stock.view_picking_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = shipments[0] + return result + + @api.multi + def action_view_procurements(self): + action = self.env.ref( + 'procurement.procurement_order_action_exceptions') + result = action.read()[0] + procurements = self.procurement_ids.filtered( + lambda p: p.state == 'exception').ids + # choose the view_mode accordingly + if len(procurements) != 1: + result['domain'] = "[('id', 'in', " + \ + str(procurements) + ")]" + elif len(procurements) == 1: + res = self.env.ref('procurement.procurement_form_view', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = procurements[0] + return result + + @api.multi + def action_view_rma_lines(self): + if self.type == 'customer': + # from customer we link to supplier rma + action = self.env.ref( + 'rma.action_rma_supplier_lines') + rma_lines = self.supplier_rma_line_ids.ids + res = self.env.ref('rma.view_rma_line_supplier_form', False) + else: + # from supplier we link to customer rma + action = self.env.ref( + 'rma.action_rma_customer_lines') + rma_lines = self.customer_rma_id.ids + res = self.env.ref('rma.view_rma_line_form', False) + result = action.read()[0] + # choose the view_mode accordingly + if rma_lines and len(rma_lines) != 1: + result['domain'] = rma_lines.ids + elif len(rma_lines) == 1: + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = rma_lines[0] return result diff --git a/rma/models/stock.py b/rma/models/stock.py index 1ccf52cc..aecb0cff 100644 --- a/rma/models/stock.py +++ b/rma/models/stock.py @@ -34,3 +34,10 @@ class StockMove(models.Model): if group.rma_line_id: vals['rma_line_id'] = group.rma_line_id.id return super(StockMove, self).create(vals) + + def _action_assign(self): + res = super(StockMove, self)._action_assign() + for move in self: + if move.rma_line_id: + move.partner_id = move.rma_line_id.partner_id.id or False + return res diff --git a/rma/models/stock_warehouse.py b/rma/models/stock_warehouse.py index 3111e137..50ba21d8 100644 --- a/rma/models/stock_warehouse.py +++ b/rma/models/stock_warehouse.py @@ -1,21 +1,255 @@ # Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from odoo import fields, models +from odoo import _, api, fields, models class StockWarehouse(models.Model): _inherit = "stock.warehouse" - lot_rma_id = fields.Many2one('stock.location', 'RMA Location') - rma_cust_out_type_id = fields.Many2one('stock.picking.type', - 'RMA Customer out Type') - rma_sup_out_type_id = fields.Many2one('stock.picking.type', - 'RMA Supplier out Type') - rma_cust_in_type_id = fields.Many2one('stock.picking.type', - 'RMA Customer in Type') - rma_sup_in_type_id = fields.Many2one('stock.picking.type', - 'RMA Supplier in Type') + lot_rma_id = fields.Many2one( + comodel_name='stock.location', string='RMA Location', + ) # not readonly to have the possibility to edit location and + # propagate to rma rules (add a auto-update when writing this field?) + rma_cust_out_type_id = fields.Many2one( + comodel_name='stock.picking.type', string='RMA Customer out Type', + readonly=True, + ) + rma_sup_out_type_id = fields.Many2one( + comodel_name='stock.picking.type', string='RMA Supplier out Type', + readonly=True, + ) + rma_cust_in_type_id = fields.Many2one( + comodel_name='stock.picking.type', string='RMA Customer in Type', + readonly=True, + ) + rma_sup_in_type_id = fields.Many2one( + comodel_name='stock.picking.type', string='RMA Supplier in Type', + readonly=True, + ) + rma_in_this_wh = fields.Boolean( + string='RMA in this Warehouse', + help="If set, it will create RMA location, picking types and routes " + "for this warehouse.", + ) + rma_customer_in_pull_id = fields.Many2one( + comodel_name='procurement.rule', string="RMA Customer In Rule", + ) + rma_customer_out_pull_id = fields.Many2one( + comodel_name='procurement.rule', string="RMA Customer Out Rule", + ) + rma_supplier_in_pull_id = fields.Many2one( + comodel_name='procurement.rule', string="RMA Supplier In Rule", + ) + rma_supplier_out_pull_id = fields.Many2one( + comodel_name='procurement.rule', string="RMA Supplier Out Rule", + ) + + @api.multi + def _get_rma_types(self): + return [ + self.rma_cust_out_type_id, + self.rma_sup_out_type_id, + self.rma_cust_in_type_id, + self.rma_sup_in_type_id] + + @api.multi + def _rma_types_available(self): + self.ensure_one() + rma_types = self._get_rma_types() + for type in rma_types: + if not type: + return False + return True + + @api.multi + def write(self, vals): + if 'rma_in_this_wh' in vals: + if vals.get("rma_in_this_wh"): + for wh in self: + # RMA location: + if not wh.lot_rma_id: + wh.lot_rma_id = self.env['stock.location'].create({ + 'name': 'RMA', + 'usage': 'internal', + 'location_id': wh.lot_stock_id.id, + }) + # RMA types + if not wh._rma_types_available(): + wh._create_rma_picking_types() + else: + for type in wh._get_rma_types(): + if type: + type.active = True + # RMA rules: + wh._create_or_update_rma_pull() + else: + for wh in self: + for type in wh._get_rma_types(): + if type: + type.active = False + # Unlink rules: + self.mapped('rma_customer_in_pull_id').unlink() + self.mapped('rma_customer_out_pull_id').unlink() + self.mapped('rma_supplier_in_pull_id').unlink() + self.mapped('rma_supplier_out_pull_id').unlink() + return super(StockWarehouse, self).write(vals) + + def _create_rma_picking_types(self): + picking_type_obj = self.env['stock.picking.type'] + customer_loc, supplier_loc = self._get_partner_locations() + for wh in self: + other_pick_type = picking_type_obj.search( + [('warehouse_id', '=', wh.id)], order='sequence desc', + limit=1) + color = other_pick_type.color if other_pick_type else 0 + max_sequence = other_pick_type and other_pick_type.sequence or 0 + # create rma_cust_out_type_id: + rma_cust_out_type_id = picking_type_obj.create({ + 'name': _('Customer RMA Deliveries'), + 'warehouse_id': wh.id, + 'code': 'outgoing', + 'use_create_lots': True, + 'use_existing_lots': False, + 'sequence_id': self.env.ref( + 'rma.seq_picking_type_rma_cust_out').id, + 'default_location_src_id': wh.lot_rma_id.id, + 'default_location_dest_id': customer_loc.id, + 'sequence': max_sequence, + 'color': color, + }) + # create rma_sup_out_type_id: + rma_sup_out_type_id = picking_type_obj.create({ + 'name': _('Supplier RMA Deliveries'), + 'warehouse_id': wh.id, + 'code': 'outgoing', + 'use_create_lots': True, + 'use_existing_lots': False, + 'sequence_id': self.env.ref( + 'rma.seq_picking_type_rma_sup_out').id, + 'default_location_src_id': wh.lot_rma_id.id, + 'default_location_dest_id': supplier_loc.id, + 'sequence': max_sequence, + 'color': color, + }) + # create rma_cust_in_type_id: + rma_cust_in_type_id = picking_type_obj.create({ + 'name': _('Customer RMA Receipts'), + 'warehouse_id': wh.id, + 'code': 'incoming', + 'use_create_lots': True, + 'use_existing_lots': False, + 'sequence_id': self.env.ref( + 'rma.seq_picking_type_rma_cust_in').id, + 'default_location_src_id': customer_loc.id, + 'default_location_dest_id': wh.lot_rma_id.id, + 'sequence': max_sequence, + 'color': color, + }) + # create rma_sup_in_type_id: + rma_sup_in_type_id = picking_type_obj.create({ + 'name': _('Supplier RMA Receipts'), + 'warehouse_id': wh.id, + 'code': 'incoming', + 'use_create_lots': True, + 'use_existing_lots': False, + 'sequence_id': self.env.ref( + 'rma.seq_picking_type_rma_sup_in').id, + 'default_location_src_id': supplier_loc.id, + 'default_location_dest_id': wh.lot_rma_id.id, + 'sequence': max_sequence, + 'color': color, + }) + wh.write({ + 'rma_cust_out_type_id': rma_cust_out_type_id.id, + 'rma_sup_out_type_id': rma_sup_out_type_id.id, + 'rma_cust_in_type_id': rma_cust_in_type_id.id, + 'rma_sup_in_type_id': rma_sup_in_type_id.id, + }) + return True + + @api.multi + def get_rma_rules_dict(self): + self.ensure_one() + rma_rules = dict() + customer_loc, supplier_loc = self._get_partner_locations() + # TODO: company_id? + rma_rules['rma_customer_in'] = { + 'name': self._format_rulename(self, customer_loc, self.lot_rma_id), + 'action': 'move', + 'warehouse_id': self.id, + 'location_src_id': customer_loc.id, + 'location_id': self.lot_rma_id.id, + 'procure_method': 'make_to_stock', + 'route_id': self.env.ref('rma.route_rma_customer').id, + 'picking_type_id': self.rma_cust_in_type_id.id, + 'active': True, + } + rma_rules['rma_customer_out'] = { + 'name': self._format_rulename(self, self.lot_rma_id, customer_loc), + 'action': 'move', + 'warehouse_id': self.id, + 'location_src_id': self.lot_rma_id.id, + 'location_id': customer_loc.id, + 'procure_method': 'make_to_stock', + 'route_id': self.env.ref('rma.route_rma_customer').id, + 'picking_type_id': self.rma_cust_out_type_id.id, + 'active': True, + } + rma_rules['rma_supplier_in'] = { + 'name': self._format_rulename(self, supplier_loc, self.lot_rma_id), + 'action': 'move', + 'warehouse_id': self.id, + 'location_src_id': supplier_loc.id, + 'location_id': self.lot_rma_id.id, + 'procure_method': 'make_to_stock', + 'route_id': self.env.ref('rma.route_rma_supplier').id, + 'picking_type_id': self.rma_sup_in_type_id.id, + 'active': True, + } + rma_rules['rma_supplier_out'] = { + 'name': self._format_rulename(self, self.lot_rma_id, supplier_loc), + 'action': 'move', + 'warehouse_id': self.id, + 'location_src_id': self.lot_rma_id.id, + 'location_id': supplier_loc.id, + 'procure_method': 'make_to_stock', + 'route_id': self.env.ref('rma.route_rma_supplier').id, + 'picking_type_id': self.rma_sup_out_type_id.id, + 'active': True, + } + return rma_rules + + def _create_or_update_rma_pull(self): + rule_obj = self.env['procurement.rule'] + for wh in self: + rules_dict = wh.get_rma_rules_dict() + if wh.rma_customer_in_pull_id: + wh.rma_customer_in_pull_id.write(rules_dict['rma_customer_in']) + else: + wh.rma_customer_in_pull_id = rule_obj.create( + rules_dict['rma_customer_in']) + + if wh.rma_customer_out_pull_id: + wh.rma_customer_out_pull_id.write( + rules_dict['rma_customer_out']) + else: + wh.rma_customer_out_pull_id = rule_obj.create( + rules_dict['rma_customer_out']) + + if wh.rma_supplier_in_pull_id: + wh.rma_supplier_in_pull_id.write(rules_dict['rma_supplier_in']) + else: + wh.rma_supplier_in_pull_id = rule_obj.create( + rules_dict['rma_supplier_in']) + + if wh.rma_supplier_out_pull_id: + wh.rma_supplier_out_pull_id.write( + rules_dict['rma_supplier_out']) + else: + wh.rma_supplier_out_pull_id = rule_obj.create( + rules_dict['rma_supplier_out']) + return True class StockLocationRoute(models.Model): diff --git a/rma/views/product_view.xml b/rma/views/product_view.xml index a2810600..ffb37dcd 100755 --- a/rma/views/product_view.xml +++ b/rma/views/product_view.xml @@ -5,16 +5,17 @@ product.category - - - - - - - + + + + + + + @@ -22,16 +23,18 @@ product.template.stock.property.form.inherit product.template - - - - - - + + + + + + + - - + diff --git a/rma/views/rma_operation_view.xml b/rma/views/rma_operation_view.xml index e4fd4824..5de6a550 100755 --- a/rma/views/rma_operation_view.xml +++ b/rma/views/rma_operation_view.xml @@ -1,87 +1,90 @@ - + - - rma.operation.tree - rma.operation - - - - - - - - - - + + + rma.operation.tree + rma.operation + + + + + + + + + + - - rma.operation.form - rma.operation - -
- - - - - - + + rma.operation.form + rma.operation + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - -
-
+ + +
- - Customer Operations - rma.operation - form - tree,form - {'default_type': "customer"} - [('type','=', 'customer')] - - + + Customer Operations + rma.operation + form + tree,form + {'default_type': "customer"} + [('type','=', 'customer')] + + - - Supplier Operations - rma.operation - form - tree,form - {'default_type': "supplier"} - [('type','=', 'supplier')] - - + + Supplier Operations + rma.operation + form + tree,form + {'default_type': "supplier"} + [('type','=', 'supplier')] + + - + - + + +
diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index 38093034..08b20fb0 100755 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -83,6 +83,13 @@ +

@@ -109,7 +116,8 @@ + attrs="{'required': [('product_tracking', 'in', ('serial', 'lot'))]}" + domain="[('product_id', '=', product_id)]"/> @@ -125,32 +133,36 @@ - + - + - - - - - - - - - - - - - - + + + + + + + + + + + @@ -198,7 +210,7 @@ rma.order.line.form rma.order.line -
+
+

@@ -284,37 +303,39 @@ - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + - + @@ -366,6 +387,14 @@ + + + + + + + + diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py index dfbac614..54fae91d 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -78,10 +78,12 @@ class RmaMakePicking(models.TransientModel): @api.model def _get_address(self, item): - if item.line_id.delivery_address_id: - delivery_address = item.line_id.delivery_address_id - elif item.line_id.customer_to_supplier: + if item.line_id.customer_to_supplier: delivery_address = item.line_id.supplier_address_id + elif item.line_id.supplier_to_customer: + delivery_address = item.line_id.customer_address_id + elif item.line_id.delivery_address_id: + delivery_address = item.line_id.delivery_address_id elif item.line_id.partner_id: delivery_address = item.line_id.partner_id else: diff --git a/rma/wizards/rma_order_line_make_supplier_rma.py b/rma/wizards/rma_order_line_make_supplier_rma.py index f6def3b6..8a33ca7b 100644 --- a/rma/wizards/rma_order_line_make_supplier_rma.py +++ b/rma/wizards/rma_order_line_make_supplier_rma.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) import odoo.addons.decimal_precision as dp @@ -22,14 +22,28 @@ class RmaLineMakeSupplierRma(models.TransientModel): comodel_name='rma.order', string='Supplier RMA Order Group', ) + @api.model + def _get_default_operation(self): + """Dropshipping is the most common use case of this wizard, thus + trying to default to a dropshipping operation first.""" + operation = self.env['rma.operation'].search([ + ('type', '=', 'supplier'), + ('supplier_to_customer', '=', True)], limit=1) + if not operation: + operation = self.env['rma.operation'].search( + [('type', '=', 'supplier')], limit=1) + return operation + @api.model def _prepare_item(self, line): + operation = self._get_default_operation() return { 'line_id': line.id, 'product_id': line.product_id.id, 'name': line.name, 'product_qty': line.qty_to_supplier_rma, 'uom_id': line.uom_id.id, + 'operation_id': operation.id if operation else False, } @api.model @@ -48,15 +62,13 @@ class RmaLineMakeSupplierRma(models.TransientModel): lines = rma_line_obj.browse(rma_line_ids) for line in lines: items.append([0, 0, self._prepare_item(line)]) - suppliers = lines.mapped('supplier_address_id') - if len(suppliers) == 0: - pass - elif len(suppliers) == 1: - res['partner_id'] = suppliers.id - else: + suppliers = lines.mapped( + lambda r: r.supplier_address_id.parent_id or r.supplier_address_id) + if len(suppliers) > 1: raise ValidationError( - _('Only RMA lines from the same supplier address can be ' + _('Only RMA lines from the same supplier can be ' 'processed at the same time')) + res['partner_id'] = suppliers.id res['item_ids'] = items return res @@ -66,16 +78,17 @@ class RmaLineMakeSupplierRma(models.TransientModel): raise ValidationError(_('Enter a supplier.')) return { 'partner_id': self.partner_id.id, + 'delivery_address_id': self.partner_id.id, 'type': 'supplier', 'company_id': company.id, } @api.model def _prepare_supplier_rma_line(self, rma, item): - operation = item.line_id.product_id.rma_supplier_operation_id - if not operation: - operation = self.env['rma.operation'].search( - [('type', '=', 'supplier')], limit=1) + if item.operation_id: + operation = item.operation_id + else: + operation = self._get_default_operation() if not operation.in_route_id or not operation.out_route_id: route = self.env['stock.location.route'].search( [('rma_selectable', '=', True)], limit=1) @@ -92,12 +105,13 @@ class RmaLineMakeSupplierRma(models.TransientModel): 'partner_id': self.partner_id.id, 'type': 'supplier', 'origin': item.line_id.rma_id.name, - 'delivery_address_id': - item.line_id.delivery_address_id.id, + 'customer_address_id': + item.line_id.delivery_address_id.id or + item.line_id.partner_id.id, 'product_id': item.line_id.product_id.id, 'customer_rma_id': item.line_id.id, 'product_qty': item.product_qty, - 'rma_id': rma.id, + 'rma_id': rma.id if rma else False, 'uom_id': item.line_id.uom_id.id, 'operation_id': operation.id, 'receipt_policy': operation.receipt_policy, @@ -128,23 +142,34 @@ class RmaLineMakeSupplierRma(models.TransientModel): if self.supplier_rma_id: rma = self.supplier_rma_id - if not rma: + if not rma and len(self.item_ids) > 1: rma_data = self._prepare_supplier_rma(line.company_id) rma = rma_obj.create(rma_data) rma_line_data = self._prepare_supplier_rma_line(rma, item) - rma_line_obj.create(rma_line_data) - - return { - 'name': _('Supplier RMA'), - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'rma.order', - 'view_id': False, - 'res_id': rma.id, - 'context': {'supplier': True, 'customer': False}, - 'type': 'ir.actions.act_window' - } + rma_line = rma_line_obj.create(rma_line_data) + if rma: + return { + 'name': _('Supplier RMA'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'rma.order', + 'view_id': False, + 'res_id': rma.id, + 'context': {'supplier': True, 'customer': False}, + 'type': 'ir.actions.act_window' + } + else: + return { + 'name': _('Supplier RMA Line'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'rma.order.line', + 'view_id': False, + 'res_id': rma_line.id, + 'context': {'supplier': True, 'customer': False}, + 'type': 'ir.actions.act_window' + } class RmaLineMakeRmaOrderItem(models.TransientModel): @@ -167,3 +192,7 @@ class RmaLineMakeRmaOrderItem(models.TransientModel): uom_id = fields.Many2one('product.uom', string='UoM', readonly=True) product_qty = fields.Float(string='Quantity', digits=dp.get_precision('Product UoS')) + operation_id = fields.Many2one( + comodel_name="rma.operation", string="Operation", + domain=[('type', '=', 'supplier')], + ) diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml index 1ba47921..25ad8e38 100755 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -29,6 +29,7 @@ options="{'no_open': true}"/> + From 4682f77ad4a2de69b5d4b91468540a9ed1d47ead Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Fri, 3 Aug 2018 12:48:52 +0200 Subject: [PATCH 39/81] [9.0][IMP] rma: configuring rma for a warehouse from the wh form view --- rma/demo/stock_demo.xml | 127 +++++++++++++++++++++++++++++++--- rma/views/stock_warehouse.xml | 3 + 2 files changed, 119 insertions(+), 11 deletions(-) diff --git a/rma/demo/stock_demo.xml b/rma/demo/stock_demo.xml index 96659f5b..e3b4c2e8 100755 --- a/rma/demo/stock_demo.xml +++ b/rma/demo/stock_demo.xml @@ -1,19 +1,124 @@ - + - - RMA - internal - + + + RMA Customer Sequence out + RMA/CUST/OUT + 5 + + + RMA Customer Sequence in + RMA/CUST/IN + 5 + + - - - - - - + + RMA Supplier Sequence out + RMA/SUPP/OUT + 5 + + + + + RMA Supplier Sequence in + RMA/SUPP/IN + 5 + + + + + RMA Dropship + RMA/DS + 5 + + + + + + Customer -> Supplier + + + + + incoming + + + + Supplier -> Customer + + + + + incoming + + + + + RMA Customer + 10 + + + + + + + + + RMA Supplier + 10 + + + + + + + + + RMA Dropship + 10 + + + + + + + + + + Customer → Supplier + move + + + + make_to_stock + + + + + + Supplier → Customer + move + + + + make_to_stock + + + + + + + diff --git a/rma/views/stock_warehouse.xml b/rma/views/stock_warehouse.xml index fa0a76c0..4b1cc6c4 100755 --- a/rma/views/stock_warehouse.xml +++ b/rma/views/stock_warehouse.xml @@ -8,6 +8,9 @@ + + + From 3752ef111c61143694feded428024d30b1af7002 Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Mon, 14 May 2018 17:05:57 +0200 Subject: [PATCH 40/81] [9.0][IMP] rma: tests moved to Savedpointcase and optimized (66% time reduction) --- rma/tests/__init__.py | 2 - rma/tests/test_rma.py | 537 ++++++++++++++++++++++++--------- rma/tests/test_rma_dropship.py | 110 ------- rma/tests/test_supplier_rma.py | 144 --------- 4 files changed, 389 insertions(+), 404 deletions(-) delete mode 100644 rma/tests/test_rma_dropship.py delete mode 100644 rma/tests/test_supplier_rma.py diff --git a/rma/tests/__init__.py b/rma/tests/__init__.py index 7262aab1..a708954b 100644 --- a/rma/tests/__init__.py +++ b/rma/tests/__init__.py @@ -2,5 +2,3 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import test_rma -from . import test_supplier_rma -from . import test_rma_dropship diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 3548589a..45e62abe 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -1,113 +1,114 @@ -# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. +# © 2017 Eficent Business and IT Consulting Services S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) -from odoo.tests import common -from odoo.exceptions import ValidationError +from openerp.tests import common +from openerp.exceptions import ValidationError -class TestRma(common.TransactionCase): - +class TestRma(common.SavepointCase): """ Test the routes and the quantities """ - def setUp(self): - super(TestRma, self).setUp() + @classmethod + def setUpClass(cls): + super(TestRma, cls).setUpClass() - self.rma_make_picking = self.env['rma_make_picking.wizard'] - self.make_supplier_rma = self.env["rma.order.line.make.supplier.rma"] - self.rma_add_stock_move = self.env['rma_add_stock_move'] - self.stockpicking = self.env['stock.picking'] - self.rma = self.env['rma.order'] - self.rma_line = self.env['rma.order.line'] - self.rma_op = self.env['rma.operation'] - self.rma_cust_replace_op_id = self.env.ref( + cls.rma_make_picking = cls.env['rma_make_picking.wizard'] + cls.make_supplier_rma = cls.env["rma.order.line.make.supplier.rma"] + cls.rma_add_stock_move = cls.env['rma_add_stock_move'] + cls.stockpicking = cls.env['stock.picking'] + cls.rma = cls.env['rma.order'] + cls.rma_line = cls.env['rma.order.line'] + cls.rma_op = cls.env['rma.operation'] + cls.rma_cust_replace_op_id = cls.env.ref( 'rma.rma_operation_customer_replace') - self.rma_sup_replace_op_id = self.env.ref( + cls.rma_sup_replace_op_id = cls.env.ref( 'rma.rma_operation_supplier_replace') - self.product_id = self.env.ref('product.product_product_4') - self.product_1 = self.env.ref('product.product_product_25') - self.product_2 = self.env.ref('product.product_product_7') - self.product_3 = self.env.ref('product.product_product_11') - self.uom_unit = self.env.ref('product.product_uom_unit') + cls.product_id = cls.env.ref('product.product_product_4') + cls.product_1 = cls.env.ref('product.product_product_25') + cls.product_2 = cls.env.ref('product.product_product_30') + cls.product_3 = cls.env.ref('product.product_product_33') + cls.uom_unit = cls.env.ref('product.product_uom_unit') # assign an operation - self.product_id.write( - {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, - 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) - self.product_1.write( - {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, - 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) - self.product_2.write( - {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, - 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) - self.product_3.write( - {'rma_customer_operation_id': self.rma_cust_replace_op_id.id, - 'rma_supplier_operation_id': self.rma_sup_replace_op_id.id}) - self.partner_id = self.env.ref('base.res_partner_12') - self.stock_location = self.env.ref('stock.stock_location_stock') - self.stock_rma_location = self.env.ref('rma.location_rma') - self.customer_location = self.env.ref( + cls.product_1.write( + {'rma_customer_operation_id': cls.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': cls.rma_sup_replace_op_id.id}) + cls.product_2.write( + {'rma_customer_operation_id': cls.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': cls.rma_sup_replace_op_id.id}) + cls.product_3.write( + {'rma_customer_operation_id': cls.rma_cust_replace_op_id.id, + 'rma_supplier_operation_id': cls.rma_sup_replace_op_id.id}) + cls.partner_id = cls.env.ref('base.res_partner_12') + cls.stock_location = cls.env.ref('stock.stock_location_stock') + wh = cls.env.ref('stock.warehouse0') + cls.stock_rma_location = wh.lot_rma_id + cls.customer_location = cls.env.ref( 'stock.stock_location_customers') - self.supplier_location = self.env.ref( + cls.supplier_location = cls.env.ref( 'stock.stock_location_suppliers') - self.product_uom_id = self.env.ref('product.product_uom_unit') - products2move = [(self.product_1, 3), (self.product_2, 5), - (self.product_3, 2)] - self.rma_customer_id = self._create_rma_from_move( - products2move, 'customer', self.partner_id, + cls.product_uom_id = cls.env.ref('product.product_uom_unit') + # Customer RMA: + products2move = [(cls.product_1, 3), (cls.product_2, 5), + (cls.product_3, 2)] + cls.rma_customer_id = cls._create_rma_from_move( + products2move, 'customer', cls.env.ref('base.res_partner_2'), + dropship=False) + # Dropship: + cls.rma_droship_id = cls._create_rma_from_move( + products2move, 'customer', cls.env.ref('base.res_partner_2'), + dropship=True, + supplier_address_id=cls.env.ref('base.res_partner_3')) + # Supplier RMA: + cls.rma_supplier_id = cls._create_rma_from_move( + products2move, 'supplier', cls.env.ref('base.res_partner_1'), dropship=False) - def _create_picking(self, partner): - return self.stockpicking.create({ + @classmethod + def _create_picking(cls, partner): + return cls.stockpicking.create({ 'partner_id': partner.id, - 'picking_type_id': self.env.ref('stock.picking_type_in').id, - 'location_id': self.stock_location.id, - 'location_dest_id': self.supplier_location.id + 'picking_type_id': cls.env.ref('stock.picking_type_in').id, + 'location_id': cls.stock_location.id, + 'location_dest_id': cls.supplier_location.id }) - def _create_rma_from_move(self, products2move, type, partner, dropship, + @classmethod + def _create_rma_from_move(cls, products2move, type, partner, dropship, supplier_address_id=None): - picking_in = self._create_picking(partner) + picking_in = cls._create_picking(partner) moves = [] if type == 'customer': for item in products2move: - move_values = self._prepare_move( - item[0], item[1], self.stock_location, - self.customer_location, picking_in) - moves.append(self.env['stock.move'].create(move_values)) + move_values = cls._prepare_move( + item[0], item[1], cls.stock_location, + cls.customer_location, picking_in) + moves.append(cls.env['stock.move'].create(move_values)) else: for item in products2move: - move_values = self._prepare_move( - item[0], item[1], self.supplier_location, - self.stock_rma_location, picking_in) - moves.append(self.env['stock.move'].create(move_values)) + move_values = cls._prepare_move( + item[0], item[1], cls.supplier_location, + cls.stock_rma_location, picking_in) + moves.append(cls.env['stock.move'].create(move_values)) # Create the RMA from the stock_move - rma_id = self.rma.create( + rma_id = cls.rma.create( { 'reference': '0001', 'type': type, 'partner_id': partner.id, - 'company_id': self.env.ref('base.main_company').id + 'company_id': cls.env.ref('base.main_company').id }) for move in moves: if type == 'customer': - wizard = self.rma_add_stock_move.new( + wizard = cls.rma_add_stock_move.with_context( {'stock_move_id': move.id, 'customer': True, 'active_ids': rma_id.id, - 'partner_id': move.partner_id.id, 'active_model': 'rma.order', } - ) - wizard.with_context({ - 'stock_move_id': move.id, 'customer': True, - 'active_ids': rma_id.id, - 'partner_id': move.partner_id.id, - 'active_model': 'rma.order', - }).default_get([str(move.id), - str(self.partner_id.id)]) - data = wizard.with_context(customer=1).\ - _prepare_rma_line_from_stock_move(move) + ).create({}) + data = wizard._prepare_rma_line_from_stock_move(move) wizard.add_lines() - data['partner_id'] = move.partner_id.id + for operation in move.product_id.rma_customer_operation_id: operation.in_route_id = False move.product_id.categ_id.rma_customer_operation_id = False @@ -115,41 +116,30 @@ class TestRma(common.TransactionCase): wizard._prepare_rma_line_from_stock_move(move) else: - wizard = self.rma_add_stock_move.new( + wizard = cls.rma_add_stock_move.with_context( {'stock_move_id': move.id, 'supplier': True, 'active_ids': rma_id.id, - 'partner_id': move.partner_id.id, 'active_model': 'rma.order', } - ) - wizard.with_context( - {'stock_move_id': move.id, 'supplier': True, - 'active_ids': rma_id.id, - 'partner_id': move.partner_id.id, - 'active_model': 'rma.order', - }).default_get([str(move.id), - str(self.partner_id.id)]) - wizard._prepare_rma_line_from_stock_move(move) + ).create({}) + data = wizard._prepare_rma_line_from_stock_move(move) wizard.add_lines() - wizard = self.rma_add_stock_move.new( + wizard = cls.rma_add_stock_move.with_context( {'stock_move_id': move.id, 'supplier': True, 'active_ids': [], - 'partner_id': move.partner_id.id, 'active_model': 'rma.order', } - ) + ).create({}) wizard.add_lines() - wizard = self.rma_add_stock_move.new( + wizard = cls.rma_add_stock_move.with_context( {'stock_move_id': move.id, 'supplier': True, 'active_ids': rma_id.id, - 'partner_id': move.partner_id.id, 'active_model': 'rma.order', } - ) + ).create({}) data = wizard._prepare_rma_line_from_stock_move(move) - data['partner_id'] = move.partner_id.id for operation in move.product_id.rma_customer_operation_id: operation.in_route_id = False move.product_id.rma_customer_operation_id = False @@ -158,14 +148,10 @@ class TestRma(common.TransactionCase): if dropship: data.update(customer_to_supplier=dropship, supplier_address_id=supplier_address_id.id) - data['partner_id'] = move.partner_id.id - data['rma_id'] = rma_id.id - if type == 'supplier': - self.rma_line = self.rma_line.with_context(supplier=True) - self.line = self.rma_line.create(data) + cls.line = cls.rma_line.create(data) # approve the RMA Line - self.rma_line.action_rma_to_approve() - self.line.action_rma_approve() + cls.line.action_rma_to_approve() + cls.line.action_rma_approve() rma_id._get_default_type() rma_id._compute_in_shipment_count() rma_id._compute_out_shipment_count() @@ -178,19 +164,18 @@ class TestRma(common.TransactionCase): rma_id.partner_id.action_open_partner_rma() rma_id.partner_id._compute_rma_line_count() # approve the RMA - for line in rma_id.rma_line_ids: - line.action_rma_to_approve() - line.action_rma_approve() +# rma_id.action_rma_to_approve() +# rma_id.action_rma_approve() return rma_id - def _prepare_move(self, product, qty, src, dest, picking_in): - + @classmethod + def _prepare_move(cls, product, qty, src, dest, picking_in): res = { - 'partner_id': self.partner_id.id, + 'partner_id': cls.partner_id.id, 'product_id': product.id, 'name': product.partner_ref, 'state': 'confirmed', - 'product_uom': self.product_uom_id.id or product.uom_id.id, + 'product_uom': cls.product_uom_id.id or product.uom_id.id, 'product_uom_qty': qty, 'origin': 'Test RMA', 'location_id': src.id, @@ -199,23 +184,20 @@ class TestRma(common.TransactionCase): } return res - def test_rma_order_line(self): - partner2 = self.env.ref('base.res_partner_2') - picking_in = self._create_picking(partner2) + def test_01_rma_order_line(self): + picking_in = self._create_picking(self.env.ref('base.res_partner_2')) moves_1 = [] move_values = self._prepare_move(self.product_1, 3, self.stock_location, self.customer_location, picking_in) moves_1.append(self.env['stock.move'].create(move_values)) - wizard_1 = self.rma_add_stock_move.new( + wizard_1 = self.rma_add_stock_move.with_context( {'supplier': True, 'stock_move_id': [(6, 0, [m.id for m in moves_1])], 'active_ids': self.rma_customer_id.id, 'active_model': 'rma.order', - 'partner_id': self.partner_id.id, - 'move_ids': [(6, 0, [m.id for m in moves_1])] } - ) + ).create({'move_ids': [(6, 0, [m.id for m in moves_1])]}) wizard_1.add_lines() for line in self.rma_customer_id.rma_line_ids: @@ -226,11 +208,26 @@ class TestRma(common.TransactionCase): })._default_delivery_address() line._compute_in_shipment_count() line._compute_out_shipment_count() + line._compute_procurement_count() data = {'reference_move_id': line.reference_move_id.id} new_line = self.rma_line.new(data) new_line._onchange_reference_move_id() + # check assert if call reference_move_id onchange + self.assertEquals(new_line.product_id, + line.reference_move_id.product_id) + self.assertEquals(new_line.product_qty, + line.reference_move_id.product_uom_qty) + self.assertEquals(new_line.location_id.location_id, + line.reference_move_id.location_id) + self.assertEquals(new_line.origin, + line.reference_move_id.picking_id.name) + self.assertEquals(new_line.delivery_address_id, + line.reference_move_id.picking_partner_id) + self.assertEquals(new_line.qty_to_receive, + line.reference_move_id.product_uom_qty) + line.action_rma_to_approve() line.action_rma_draft() line.action_rma_done() @@ -243,6 +240,10 @@ class TestRma(common.TransactionCase): new_line = self.rma_line.new(data) new_line._onchange_operation_id() + # check assert if call operation_id onchange + self.assertEquals(new_line.operation_id.receipt_policy, + line.receipt_policy) + data = {'customer_to_supplier': line.customer_to_supplier} new_line = self.rma_line.new(data) new_line._onchange_receipt_policy() @@ -253,31 +254,28 @@ class TestRma(common.TransactionCase): line.action_view_in_shipments() line.action_view_out_shipments() + line.action_view_procurements() self.rma_customer_id.action_view_supplier_lines() with self.assertRaises(ValidationError): - line.rma_id.partner_id = partner2.id + line.rma_id.partner_id = self.partner_id.id self.rma_customer_id.rma_line_ids[0].\ - partner_id = partner2.id + partner_id = self.partner_id.id self.rma_customer_id.action_view_supplier_lines() - def test_customer_rma(self): + def test_02_customer_rma(self): wizard = self.rma_make_picking.with_context({ 'active_ids': self.rma_customer_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'incoming', 'active_id': 1 }).create({}) - wizard.with_context({ - 'active_ids': self.rma_customer_id.rma_line_ids.ids, - 'active_model': 'rma.order.line', - 'picking_type': 'incoming', - 'active_id': 1 - }).default_get({}) - wizard._create_picking() - res = self.rma_customer_id.rma_line_ids.action_view_in_shipments() - self.assertTrue('res_id' in res, - "Incorrect number of pickings created") - picking = self.env['stock.picking'].browse(res['res_id']) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = [('group_id', 'in', list(group_ids))] + picking = self.stockpicking.search(domain) + self.assertEquals(len(picking), 1, + "Incorrect number of pickings created") moves = picking.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") @@ -285,37 +283,30 @@ class TestRma(common.TransactionCase): # common qtys for all products self.assertEquals(line.qty_received, 0, "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") # product specific if line.product_id == self.product_1: - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 3, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 3, "Wrong qty incoming") if line.product_id == self.product_2: - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 5, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 5, "Wrong qty incoming") if line.product_id == self.product_3: - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") self.assertEquals(line.qty_to_receive, 2, "Wrong qty to receive") self.assertEquals(line.qty_incoming, 2, "Wrong qty incoming") - picking.action_confirm() picking.action_assign() - for line in picking.move_line_ids: - line.qty_done = line.product_uom_qty - picking.action_done() + picking.do_transfer() for line in self.rma_customer_id.rma_line_ids: self.assertEquals(line.qty_to_receive, 0, "Wrong qty to_receive") @@ -328,12 +319,18 @@ class TestRma(common.TransactionCase): if line.product_id == self.product_1: self.assertEquals(line.qty_received, 3, "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to_deliver") if line.product_id == self.product_2: self.assertEquals(line.qty_received, 5, "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to_deliver") if line.product_id == self.product_3: self.assertEquals(line.qty_received, 2, "Wrong qty received") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to_deliver") wizard = self.rma_make_picking.with_context({ 'active_id': 1, @@ -341,15 +338,22 @@ class TestRma(common.TransactionCase): 'active_model': 'rma.order.line', 'picking_type': 'outgoing', }).create({}) - wizard._create_picking() - res = self.rma_customer_id.rma_line_ids.action_view_out_shipments() - self.assertTrue('res_id' in res, - "Incorrect number of pickings created") - picking = self.env['stock.picking'].browse(res['res_id']) - moves = picking.move_lines + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = [('group_id', 'in', list(group_ids))] + pickings = self.stockpicking.search(domain) + self.assertEquals(len(pickings), 2, + "Incorrect number of pickings created") + picking_out = pickings[1] + moves = picking_out.move_lines self.assertEquals(len(moves), 3, "Incorrect number of moves created") for line in self.rma_customer_id.rma_line_ids: + self.assertEquals(line.qty_to_receive, 0, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") self.assertEquals(line.qty_delivered, 0, "Wrong qty delivered") if line.product_id == self.product_1: @@ -357,35 +361,272 @@ class TestRma(common.TransactionCase): "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 3, "Wrong qty outgoing") + self.assertEquals(line.qty_received, 3, + "Wrong qty received") if line.product_id == self.product_2: + self.assertEquals(line.qty_received, 5, + "Wrong qty received") self.assertEquals(line.qty_to_deliver, 5, "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 5, "Wrong qty outgoing") if line.product_id == self.product_3: + self.assertEquals(line.qty_received, 2, + "Wrong qty received") self.assertEquals(line.qty_to_deliver, 2, "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 2, "Wrong qty outgoing") - picking.action_confirm() - picking.action_assign() - for line in picking.move_line_ids: - line.qty_done = line.product_uom_qty - picking.action_done() - for line in self.rma_customer_id.rma_line_ids[0]: + picking_out.action_assign() + picking_out.do_transfer() + for line in self.rma_customer_id.rma_line_ids: + self.assertEquals(line.qty_to_receive, 0, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") self.assertEquals(line.qty_to_deliver, 0, "Wrong qty to deliver") self.assertEquals(line.qty_outgoing, 0, "Wrong qty outgoing") if line.product_id == self.product_1: + self.assertEquals(line.qty_received, 3, + "Wrong qty received") self.assertEquals(line.qty_delivered, 3, "Wrong qty delivered") if line.product_id == self.product_2: + self.assertEquals(line.qty_received, 5, + "Wrong qty received") self.assertEquals(line.qty_delivered, 5, "Wrong qty delivered") if line.product_id == self.product_3: + self.assertEquals(line.qty_received, 2, + "Wrong qty received") self.assertEquals(line.qty_delivered, 2, "Wrong qty delivered") self.line.action_rma_done() self.assertEquals(self.line.state, 'done', "Wrong State") + self.rma_customer_id.action_view_in_shipments() + self.rma_customer_id.action_view_out_shipments() + self.rma_customer_id.action_view_lines() + + # DROPSHIP + def test_03_dropship(self): + wizard = self.make_supplier_rma.with_context({ + 'active_ids': self.rma_droship_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'active_id': 1 + }).create({}) + res = wizard.make_supplier_rma() + supplier_rma = self.rma.browse(res['res_id']) + for line in supplier_rma.rma_line_ids: + line.action_rma_to_approve() + line.action_rma_approve() + wizard = self.rma_make_picking.with_context({ + 'active_id': 1, + 'active_ids': supplier_rma.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'incoming', + }).create({}) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = [('group_id', 'in', list(group_ids))] + picking = self.stockpicking.search(domain) + self.assertEquals(len(picking), 1, + "Incorrect number of pickings created") + moves = picking.move_lines + self.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in supplier_rma.rma_line_ids: + # common qtys for all products + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + self.assertEquals(line.qty_outgoing, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + # product specific + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") + self.assertEquals(line.qty_incoming, 3, + "Wrong qty outgoing") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + self.assertEquals(line.qty_incoming, 5, + "Wrong qty outgoing") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + self.assertEquals(line.qty_incoming, 2, + "Wrong qty outgoing") + + for line in self.rma_droship_id.rma_line_ids: + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + self.assertEquals(line.qty_in_supplier_rma, 3, + "Wrong qty in supplier rma") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + self.assertEquals(line.qty_in_supplier_rma, 5, + "Wrong qty in supplier rma") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + self.assertEquals(line.qty_in_supplier_rma, 2, + "Wrong qty in supplier rma") + for line in self.rma_droship_id.rma_line_ids: + line.action_rma_done() + self.assertEquals(line.state, 'done', + "Wrong State") + + # Supplier RMA + def test_04_supplier_rma(self): + wizard = self.rma_make_picking.with_context({ + 'active_ids': self.rma_supplier_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'outgoing', + 'active_id': 1 + }).create({}) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = [('group_id', 'in', list(group_ids))] + picking = self.stockpicking.search(domain) + self.assertEquals(len(picking), 1, + "Incorrect number of pickings created") + moves = picking.move_lines + self.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in self.rma_supplier_id.rma_line_ids: + # common qtys for all products + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + # product specific + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 3, + "Wrong qty outgoing") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 5, + "Wrong qty outgoing") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 2, + "Wrong qty outgoing") + + picking.action_assign() + picking.do_transfer() + for line in self.rma_supplier_id.rma_line_ids: + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + if line.product_id == self.product_1: + self.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + if line.product_id == self.product_2: + self.assertEquals(line.qty_outgoing, 5, + "Wrong qty delivered") + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + if line.product_id == self.product_3: + self.assertEquals(line.qty_outgoing, 2, + "Wrong qty delivered") + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + wizard = self.rma_make_picking.with_context({ + 'active_id': 1, + 'active_ids': self.rma_supplier_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'incoming', + }).create({}) + procurements = wizard._create_picking() + group_ids = set([proc.group_id.id for proc in procurements if + proc.group_id]) + domain = [('group_id', 'in', list(group_ids))] + pickings = self.stockpicking.search(domain) + self.assertEquals(len(pickings), 3, + "Incorrect number of pickings created") + picking_out = pickings[0] + moves = picking_out.move_lines + self.assertEquals(len(moves), 2, + "Incorrect number of moves created") + for line in self.rma_supplier_id.rma_line_ids: + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + if line.product_id == self.product_1: + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + if line.product_id == self.product_2: + self.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + if line.product_id == self.product_3: + self.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + self.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + picking_out.action_assign() + picking_out.do_transfer() + for line in self.rma_supplier_id.rma_line_ids[0]: + self.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + self.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + self.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + self.assertEquals(line.qty_outgoing, 3, + "Wrong qty outgoing") + if line.product_id == self.product_1: + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + if line.product_id == self.product_2: + self.assertEquals(line.qty_received, 0, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 5, + "Wrong qty delivered") + if line.product_id == self.product_3: + self.assertEquals(line.qty_received, 2, + "Wrong qty received") + self.assertEquals(line.qty_delivered, 2, + "Wrong qty delivered") + for line in self.rma_supplier_id.rma_line_ids: + line.action_rma_done() + self.assertEquals(line.state, 'done', + "Wrong State") diff --git a/rma/tests/test_rma_dropship.py b/rma/tests/test_rma_dropship.py deleted file mode 100644 index dedb7a39..00000000 --- a/rma/tests/test_rma_dropship.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - -from . import test_rma - - -class TestRmaDropship(test_rma.TestRma): - - def setUp(self): - super(TestRmaDropship, self).setUp() - rma_operation_ds_replace = self.env.ref( - 'rma.rma_operation_ds_replace') - self.rma_operation_ds_replace_supplier = self.env.ref( - 'rma.rma_operation_ds_replace_supplier') - self.product_id.write( - {'rma_customer_operation_id': rma_operation_ds_replace.id, - 'rma_supplier_operation_id': - self.rma_operation_ds_replace_supplier.id}) - self.product_1.write( - {'rma_customer_operation_id': rma_operation_ds_replace.id, - 'rma_supplier_operation_id': - self.rma_operation_ds_replace_supplier.id}) - self.product_2.write( - {'rma_customer_operation_id': rma_operation_ds_replace.id, - 'rma_supplier_operation_id': - self.rma_operation_ds_replace_supplier.id}) - self.product_3.write( - {'rma_customer_operation_id': rma_operation_ds_replace.id, - 'rma_supplier_operation_id': - self.rma_operation_ds_replace_supplier.id}) - products2move = [(self.product_1, 3), (self.product_2, 5), - (self.product_3, 2)] - self.rma_droship_id = self._create_rma_from_move( - products2move, 'customer', self.env.ref('base.res_partner_2'), - dropship=True, - supplier_address_id=self.env.ref('base.res_partner_3')) - - def test_dropship(self): - wizard = self.make_supplier_rma.with_context({ - 'active_ids': self.rma_droship_id.rma_line_ids.ids, - 'active_model': 'rma.order.line', - 'active_id': 1 - }).create({}) - - res = wizard.make_supplier_rma() - supplier_rma = self.rma.browse(res['res_id']) - for line in supplier_rma.rma_line_ids: - line.delivery_address_id = self.env.ref('base.res_partner_2') - line.operation_id = self.rma_operation_ds_replace_supplier - line._onchange_operation_id() - line.action_rma_to_approve() - line.action_rma_approve() - wizard = self.rma_make_picking.with_context({ - 'active_id': 1, - 'active_ids': supplier_rma.rma_line_ids.ids, - 'active_model': 'rma.order.line', - 'picking_type': 'incoming', - }).create({}) - wizard._create_picking() - res = supplier_rma.rma_line_ids.action_view_in_shipments() - self.assertTrue('res_id' in res, - "Incorrect number of pickings created") - picking = self.env['stock.picking'].browse(res['res_id']) - moves = picking.move_lines - self.assertEquals(len(moves), 3, - "Incorrect number of moves created") - for line in supplier_rma.rma_line_ids: - # product specific - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_received, 0, - "Wrong qty receive") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty deliver") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty deliver") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") - - for line in self.rma_droship_id.rma_line_ids[0]: - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_supplier_rma, 0, - "Wrong qty to supplier rma") - self.assertEquals(line.qty_in_supplier_rma, 3, - "Wrong qty in supplier rma") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_supplier_rma, 0, - "Wrong qty to supplier rma") - self.assertEquals(line.qty_in_supplier_rma, 5, - "Wrong qty in supplier rma") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_supplier_rma, 0, - "Wrong qty to supplier rma") - self.assertEquals(line.qty_in_supplier_rma, 2, - "Wrong qty in supplier rma") - for line in self.rma_droship_id.rma_line_ids: - line.action_rma_done() - self.assertEquals(line.state, 'done', - "Wrong State") diff --git a/rma/tests/test_supplier_rma.py b/rma/tests/test_supplier_rma.py deleted file mode 100644 index 6cc3c15c..00000000 --- a/rma/tests/test_supplier_rma.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright (C) 2017 Eficent Business and IT Consulting Services S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - -from . import test_rma - - -class TestSupplierRma(test_rma.TestRma): - - def setUp(self): - super(TestSupplierRma, self).setUp() - self.rma_operation_supplier_replace = self.env.ref( - 'rma.rma_operation_supplier_replace') - products2move = [(self.product_1, 3), (self.product_2, 5), - (self.product_3, 2)] - self.rma_supplier_id = self._create_rma_from_move( - products2move, 'supplier', self.env.ref('base.res_partner_1'), - dropship=False) - - def test_supplier_rma(self): - for line in self.rma_supplier_id.rma_line_ids: - line.operation_id = self.rma_operation_supplier_replace - line._onchange_operation_id() - line.action_rma_to_approve() - line.action_rma_approve() - wizard = self.rma_make_picking.with_context({ - 'active_ids': self.rma_supplier_id.rma_line_ids.ids, - 'active_model': 'rma.order.line', - 'picking_type': 'outgoing', - 'active_id': 1 - }).create({}) - wizard._create_picking() - res = self.rma_supplier_id.rma_line_ids.action_view_out_shipments() - self.assertTrue('res_id' in res, - "Incorrect number of pickings created") - picking = self.env['stock.picking'].browse(res['res_id']) - moves = picking.move_lines - self.assertEquals(len(moves), 3, - "Incorrect number of moves created") - for line in self.rma_supplier_id.rma_line_ids: - # common qtys for all products - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") - # product specific - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 3, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 3, - "Wrong qty outgoing") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 5, - "Wrong qty outgoing") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 2, - "Wrong qty outgoing") - picking.force_assign() - for line in picking.move_lines: - line.quantity_done = line.product_uom_qty - picking.button_validate() - for line in self.rma_supplier_id.rma_line_ids: - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - if line.product_id == self.product_1: - self.assertEquals(line.qty_delivered, 3, - "Wrong qty delivered") - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - if line.product_id == self.product_2: - self.assertEquals(line.qty_delivered, 5, - "Wrong qty delivered") - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - if line.product_id == self.product_3: - self.assertEquals(line.qty_delivered, 2, - "Wrong qty delivered") - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - wizard = self.rma_make_picking.with_context({ - 'active_id': 1, - 'active_ids': self.rma_supplier_id.rma_line_ids.ids, - 'active_model': 'rma.order.line', - 'picking_type': 'incoming', - }).create({}) - wizard._create_picking() - res = self.rma_supplier_id.rma_line_ids.action_view_in_shipments() - self.assertTrue('res_id' in res, - "Incorrect number of pickings created") - picking = self.env['stock.picking'].browse(res['res_id']) - moves = picking.move_lines - self.assertEquals(len(moves), 3, - "Incorrect number of moves created") - for line in self.rma_supplier_id.rma_line_ids: - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 3, - "Wrong qty incoming") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 5, - "Wrong qty incoming") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 2, - "Wrong qty incoming") - picking.action_assign() - for line in picking.move_line_ids: - line.qty_done = line.product_uom_qty - picking.action_done() - for line in self.rma_supplier_id.rma_line_ids[0]: - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - if line.product_id == self.product_1: - self.assertEquals(line.qty_received, 3, - "Wrong qty received") - if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 5, - "Wrong qty received") - if line.product_id == self.product_3: - self.assertEquals(line.qty_received, 2, - "Wrong qty received") - for line in self.rma_supplier_id.rma_line_ids: - line.action_rma_done() - self.assertEquals(line.state, 'done', - "Wrong State") From 1dacdbb27acc0f4db251bb337d11d82583b96479 Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 30 Jul 2018 18:36:49 +0200 Subject: [PATCH 41/81] [FIX]views rma --- rma/tests/test_rma.py | 3 - rma/views/rma_operation_view.xml | 158 +++++++++--------- .../rma_order_line_make_supplier_rma_view.xml | 4 +- 3 files changed, 80 insertions(+), 85 deletions(-) diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 45e62abe..e69bfe47 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -163,9 +163,6 @@ class TestRma(common.SavepointCase): rma_id.partner_id.action_open_partner_rma() rma_id.partner_id._compute_rma_line_count() - # approve the RMA -# rma_id.action_rma_to_approve() -# rma_id.action_rma_approve() return rma_id @classmethod diff --git a/rma/views/rma_operation_view.xml b/rma/views/rma_operation_view.xml index 5de6a550..ba8f9be7 100755 --- a/rma/views/rma_operation_view.xml +++ b/rma/views/rma_operation_view.xml @@ -1,90 +1,88 @@ - - - rma.operation.tree - rma.operation - - - - - - - - - - + + rma.operation.tree + rma.operation + + + + + + + + + + - - rma.operation.form - rma.operation - - - - - - - - - - - - - - - - - - - - - - - - + + rma.operation.form + rma.operation + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + - - Customer Operations - rma.operation - form - tree,form - {'default_type': "customer"} - [('type','=', 'customer')] - - + + Customer Operations + rma.operation + form + tree,form + {'default_type': "customer"} + [('type','=', 'customer')] + + - - Supplier Operations - rma.operation - form - tree,form - {'default_type': "supplier"} - [('type','=', 'supplier')] - - + + Supplier Operations + rma.operation + form + tree,form + {'default_type': "supplier"} + [('type','=', 'supplier')] + + - + - + - diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml index 25ad8e38..3fff3c39 100755 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -37,13 +37,13 @@ - +
From 17e94adb1cdd287ca72f5f0f1c515302db787842 Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 30 Jul 2018 18:37:14 +0200 Subject: [PATCH 42/81] [FIX]compute_qty_to_receive --- rma/models/rma_order_line.py | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index fceeaa94..03f7e3ba 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -91,10 +91,10 @@ class RmaOrderLine(models.Model): rec.qty_to_receive = 0.0 if rec.receipt_policy == 'ordered': rec.qty_to_receive = \ - rec.product_qty - rec.qty_incoming - rec.qty_received + rec.product_qty - rec.qty_received elif rec.receipt_policy == 'delivered': rec.qty_to_receive = \ - rec.qty_delivered - rec.qty_incoming - rec.qty_received + rec.qty_delivered - rec.qty_received @api.multi @api.depends('move_ids', 'move_ids.state', @@ -164,12 +164,6 @@ class RmaOrderLine(models.Model): rec.qty_to_supplier_rma = 0.0 rec.qty_in_supplier_rma = 0.0 - @api.multi - def _compute_procurement_count(self): - for rec in self: - rec.procurement_count = len(rec.procurement_ids.filtered( - lambda p: p.state == 'exception')) - @api.multi def _compute_rma_line_count(self): for rec in self.filtered(lambda r: r.type == 'customer'): @@ -252,8 +246,6 @@ class RmaOrderLine(models.Model): string='Price Unit', readonly=True, states={'draft': [('readonly', False)]}, ) - procurement_count = fields.Integer(compute=_compute_procurement_count, - string='# of Procurements', copy=False) in_shipment_count = fields.Integer(compute=_compute_in_shipment_count, string='# of Shipments') out_shipment_count = fields.Integer(compute=_compute_out_shipment_count, @@ -448,12 +440,12 @@ class RmaOrderLine(models.Model): sm = self.reference_move_id if not sm: return - if sm.lot_ids: - if len(sm.lot_ids) > 1: + if sm.move_line_ids.lot_id: + if len(sm.move_line_ids.lot_id) > 1: raise UserError(_('To manage lots use RMA groups.')) else: data = self._prepare_rma_line_from_stock_move( - sm, lot=sm.lot_ids[0]) + sm, lot=sm.move_line_ids.lot_id[0]) self.update(data) else: data = self._prepare_rma_line_from_stock_move( @@ -611,23 +603,6 @@ class RmaOrderLine(models.Model): result['res_id'] = shipments[0] return result - @api.multi - def action_view_procurements(self): - action = self.env.ref( - 'procurement.procurement_order_action_exceptions') - result = action.read()[0] - procurements = self.procurement_ids.filtered( - lambda p: p.state == 'exception').ids - # choose the view_mode accordingly - if len(procurements) != 1: - result['domain'] = "[('id', 'in', " + \ - str(procurements) + ")]" - elif len(procurements) == 1: - res = self.env.ref('procurement.procurement_form_view', False) - result['views'] = [(res and res.id or False, 'form')] - result['res_id'] = procurements[0] - return result - @api.multi def action_view_rma_lines(self): if self.type == 'customer': From ddfe7d792d17640f3445bac046c3ce8ad3c6e185 Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 30 Jul 2018 18:37:35 +0200 Subject: [PATCH 43/81] [FIX]rma test --- rma/tests/test_rma.py | 773 ++++++++++++++++++++---------------------- 1 file changed, 376 insertions(+), 397 deletions(-) diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index e69bfe47..eea469d0 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -23,10 +23,12 @@ class TestRma(common.SavepointCase): 'rma.rma_operation_customer_replace') cls.rma_sup_replace_op_id = cls.env.ref( 'rma.rma_operation_supplier_replace') + cls.rma_ds_replace_op_id = cls.env.ref( + 'rma.rma_operation_ds_replace') cls.product_id = cls.env.ref('product.product_product_4') cls.product_1 = cls.env.ref('product.product_product_25') - cls.product_2 = cls.env.ref('product.product_product_30') - cls.product_3 = cls.env.ref('product.product_product_33') + cls.product_2 = cls.env.ref('product.product_product_17') + cls.product_3 = cls.env.ref('product.product_product_20') cls.uom_unit = cls.env.ref('product.product_uom_unit') # assign an operation cls.product_1.write( @@ -38,7 +40,7 @@ class TestRma(common.SavepointCase): cls.product_3.write( {'rma_customer_operation_id': cls.rma_cust_replace_op_id.id, 'rma_supplier_operation_id': cls.rma_sup_replace_op_id.id}) - cls.partner_id = cls.env.ref('base.res_partner_12') + cls.partner_id = cls.env.ref('base.res_partner_2') cls.stock_location = cls.env.ref('stock.stock_location_stock') wh = cls.env.ref('stock.warehouse0') cls.stock_rma_location = wh.lot_rma_id @@ -60,7 +62,7 @@ class TestRma(common.SavepointCase): supplier_address_id=cls.env.ref('base.res_partner_3')) # Supplier RMA: cls.rma_supplier_id = cls._create_rma_from_move( - products2move, 'supplier', cls.env.ref('base.res_partner_1'), + products2move, 'supplier', cls.env.ref('base.res_partner_2'), dropship=False) @classmethod @@ -100,13 +102,23 @@ class TestRma(common.SavepointCase): }) for move in moves: if type == 'customer': - wizard = cls.rma_add_stock_move.with_context( + wizard = cls.rma_add_stock_move.new( {'stock_move_id': move.id, 'customer': True, 'active_ids': rma_id.id, + 'rma_id': rma_id.id, + 'partner_id': move.partner_id.id, 'active_model': 'rma.order', } - ).create({}) - data = wizard._prepare_rma_line_from_stock_move(move) + ) + wizard.with_context({ + 'stock_move_id': move.id, 'customer': True, + 'active_ids': rma_id.id, + 'partner_id': move.partner_id.id, + 'active_model': 'rma.order', + }).default_get([str(move.id), + str(cls.partner_id.id)]) + data = wizard.with_context(customer=1).\ + _prepare_rma_line_from_stock_move(move) wizard.add_lines() for operation in move.product_id.rma_customer_operation_id: @@ -116,40 +128,36 @@ class TestRma(common.SavepointCase): wizard._prepare_rma_line_from_stock_move(move) else: - wizard = cls.rma_add_stock_move.with_context( + wizard = cls.rma_add_stock_move.new( {'stock_move_id': move.id, 'supplier': True, 'active_ids': rma_id.id, + 'rma_id': rma_id.id, + 'partner_id': move.partner_id.id, 'active_model': 'rma.order', } - ).create({}) - data = wizard._prepare_rma_line_from_stock_move(move) + ) + wizard.with_context({ + 'stock_move_id': move.id, 'supplier': True, + 'active_ids': rma_id.id, + 'partner_id': move.partner_id.id, + 'active_model': 'rma.order', + }).default_get([str(move.id), + str(cls.partner_id.id)]) + data = wizard.with_context(customer=1).\ + _prepare_rma_line_from_stock_move(move) wizard.add_lines() - wizard = cls.rma_add_stock_move.with_context( - {'stock_move_id': move.id, 'supplier': True, - 'active_ids': [], - 'active_model': 'rma.order', - } - ).create({}) - wizard.add_lines() - - wizard = cls.rma_add_stock_move.with_context( - {'stock_move_id': move.id, 'supplier': True, - 'active_ids': rma_id.id, - 'active_model': 'rma.order', - } - ).create({}) - data = wizard._prepare_rma_line_from_stock_move(move) for operation in move.product_id.rma_customer_operation_id: operation.in_route_id = False - move.product_id.rma_customer_operation_id = False - wizard.add_lines() + move.product_id.categ_id.rma_supplier_operation_id = False + move.product_id.rma_supplier_operation_id = False + wizard._prepare_rma_line_from_stock_move(move) if dropship: data.update(customer_to_supplier=dropship, + operation_id=cls.rma_ds_replace_op_id.id, supplier_address_id=supplier_address_id.id) cls.line = cls.rma_line.create(data) - # approve the RMA Line cls.line.action_rma_to_approve() cls.line.action_rma_approve() rma_id._get_default_type() @@ -181,23 +189,8 @@ class TestRma(common.SavepointCase): } return res - def test_01_rma_order_line(self): - picking_in = self._create_picking(self.env.ref('base.res_partner_2')) - moves_1 = [] - move_values = self._prepare_move(self.product_1, 3, - self.stock_location, - self.customer_location, picking_in) - moves_1.append(self.env['stock.move'].create(move_values)) - wizard_1 = self.rma_add_stock_move.with_context( - {'supplier': True, - 'stock_move_id': [(6, 0, [m.id for m in moves_1])], - 'active_ids': self.rma_customer_id.id, - 'active_model': 'rma.order', - } - ).create({'move_ids': [(6, 0, [m.id for m in moves_1])]}) - wizard_1.add_lines() - - for line in self.rma_customer_id.rma_line_ids: + def test_01_rma_order_line(cls): + for line in cls.rma_customer_id.rma_line_ids: line.with_context({'default_rma_id': line.rma_id.id })._default_warehouse_id() line._default_location_id() @@ -205,425 +198,411 @@ class TestRma(common.SavepointCase): })._default_delivery_address() line._compute_in_shipment_count() line._compute_out_shipment_count() - line._compute_procurement_count() data = {'reference_move_id': line.reference_move_id.id} - new_line = self.rma_line.new(data) + new_line = cls.rma_line.new(data) new_line._onchange_reference_move_id() # check assert if call reference_move_id onchange - self.assertEquals(new_line.product_id, - line.reference_move_id.product_id) - self.assertEquals(new_line.product_qty, - line.reference_move_id.product_uom_qty) - self.assertEquals(new_line.location_id.location_id, - line.reference_move_id.location_id) - self.assertEquals(new_line.origin, - line.reference_move_id.picking_id.name) - self.assertEquals(new_line.delivery_address_id, - line.reference_move_id.picking_partner_id) - self.assertEquals(new_line.qty_to_receive, - line.reference_move_id.product_uom_qty) + cls.assertEquals(new_line.product_id, + line.reference_move_id.product_id) + cls.assertEquals(new_line.product_qty, + line.reference_move_id.product_uom_qty) + cls.assertEquals(new_line.location_id.location_id, + line.reference_move_id.location_id) + cls.assertEquals(new_line.origin, + line.reference_move_id.picking_id.name) + cls.assertEquals(new_line.delivery_address_id, + line.reference_move_id.picking_partner_id) + cls.assertEquals(new_line.qty_to_receive, + line.reference_move_id.product_uom_qty) line.action_rma_to_approve() line.action_rma_draft() line.action_rma_done() data = {'product_id': line.product_id.id} - new_line = self.rma_line.new(data) + new_line = cls.rma_line.new(data) new_line._onchange_product_id() data = {'operation_id': line.operation_id.id} - new_line = self.rma_line.new(data) + new_line = cls.rma_line.new(data) new_line._onchange_operation_id() # check assert if call operation_id onchange - self.assertEquals(new_line.operation_id.receipt_policy, - line.receipt_policy) + cls.assertEquals(new_line.operation_id.receipt_policy, + line.receipt_policy) data = {'customer_to_supplier': line.customer_to_supplier} - new_line = self.rma_line.new(data) + new_line = cls.rma_line.new(data) new_line._onchange_receipt_policy() data = {'lot_id': line.lot_id.id} - new_line = self.rma_line.new(data) + new_line = cls.rma_line.new(data) new_line._onchange_lot_id() line.action_view_in_shipments() line.action_view_out_shipments() - line.action_view_procurements() - self.rma_customer_id.action_view_supplier_lines() - with self.assertRaises(ValidationError): - line.rma_id.partner_id = self.partner_id.id - self.rma_customer_id.rma_line_ids[0].\ - partner_id = self.partner_id.id - self.rma_customer_id.action_view_supplier_lines() + cls.rma_customer_id.action_view_supplier_lines() + with cls.assertRaises(ValidationError): + line.rma_id.partner_id = cls.partner_id.id + cls.rma_customer_id.rma_line_ids[0].\ + partner_id = cls.env.ref('base.res_partner_3').id + cls.rma_customer_id.action_view_supplier_lines() - def test_02_customer_rma(self): - wizard = self.rma_make_picking.with_context({ - 'active_ids': self.rma_customer_id.rma_line_ids.ids, + def test_02_customer_rma(cls): + wizard = cls.rma_make_picking.with_context({ + 'active_ids': cls.rma_customer_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'incoming', 'active_id': 1 }).create({}) - procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] - picking = self.stockpicking.search(domain) - self.assertEquals(len(picking), 1, - "Incorrect number of pickings created") + wizard._create_picking() + res = cls.rma_customer_id.rma_line_ids.action_view_in_shipments() + cls.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = cls.env['stock.picking'].browse(res['res_id']) + cls.assertEquals(len(picking), 1, + "Incorrect number of pickings created") moves = picking.move_lines - self.assertEquals(len(moves), 3, - "Incorrect number of moves created") - for line in self.rma_customer_id.rma_line_ids: + cls.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in cls.rma_customer_id.rma_line_ids: # common qtys for all products - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") + cls.assertEquals(line.qty_received, 0, + "Wrong qty received") + cls.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + cls.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") # product specific - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 3, - "Wrong qty incoming") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 5, - "Wrong qty incoming") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 2, - "Wrong qty incoming") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + cls.assertEquals(line.qty_incoming, 3, + "Wrong qty incoming") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + cls.assertEquals(line.qty_incoming, 5, + "Wrong qty incoming") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + cls.assertEquals(line.qty_incoming, 2, + "Wrong qty incoming") picking.action_assign() - picking.do_transfer() - for line in self.rma_customer_id.rma_line_ids: - self.assertEquals(line.qty_to_receive, 0, - "Wrong qty to_receive") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") - if line.product_id == self.product_1: - self.assertEquals(line.qty_received, 3, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 3, - "Wrong qty to_deliver") - if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 5, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to_deliver") - if line.product_id == self.product_3: - self.assertEquals(line.qty_received, 2, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to_deliver") + for mv in picking.move_lines: + mv.quantity_done = mv.product_uom_qty + picking.action_done() + for line in cls.rma_customer_id.rma_line_ids: + cls.assertEquals(line.qty_to_receive, 0, + "Wrong qty to_receive") + cls.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + cls.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + cls.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_received, 3, + "Wrong qty received") + cls.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to_deliver") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_received, 5, + "Wrong qty received") + cls.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to_deliver") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_received, 2, + "Wrong qty received") + cls.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to_deliver") - wizard = self.rma_make_picking.with_context({ + wizard = cls.rma_make_picking.with_context({ 'active_id': 1, - 'active_ids': self.rma_customer_id.rma_line_ids.ids, + 'active_ids': cls.rma_customer_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'outgoing', }).create({}) - procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] - pickings = self.stockpicking.search(domain) - self.assertEquals(len(pickings), 2, - "Incorrect number of pickings created") - picking_out = pickings[1] - moves = picking_out.move_lines - self.assertEquals(len(moves), 3, - "Incorrect number of moves created") - for line in self.rma_customer_id.rma_line_ids: - self.assertEquals(line.qty_to_receive, 0, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_deliver, 3, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 3, - "Wrong qty outgoing") - self.assertEquals(line.qty_received, 3, - "Wrong qty received") - if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 5, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 5, - "Wrong qty outgoing") - if line.product_id == self.product_3: - self.assertEquals(line.qty_received, 2, - "Wrong qty received") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 2, - "Wrong qty outgoing") - picking_out.action_assign() - picking_out.do_transfer() - for line in self.rma_customer_id.rma_line_ids: - self.assertEquals(line.qty_to_receive, 0, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty outgoing") - if line.product_id == self.product_1: - self.assertEquals(line.qty_received, 3, - "Wrong qty received") - self.assertEquals(line.qty_delivered, 3, - "Wrong qty delivered") - if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 5, - "Wrong qty received") - self.assertEquals(line.qty_delivered, 5, - "Wrong qty delivered") - if line.product_id == self.product_3: - self.assertEquals(line.qty_received, 2, - "Wrong qty received") - self.assertEquals(line.qty_delivered, 2, - "Wrong qty delivered") - self.line.action_rma_done() - self.assertEquals(self.line.state, 'done', - "Wrong State") - self.rma_customer_id.action_view_in_shipments() - self.rma_customer_id.action_view_out_shipments() - self.rma_customer_id.action_view_lines() + wizard._create_picking() + res = cls.rma_customer_id.rma_line_ids.action_view_out_shipments() + cls.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = cls.env['stock.picking'].browse(res['res_id']) + moves = picking.move_lines + cls.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in cls.rma_customer_id.rma_line_ids: + cls.assertEquals(line.qty_to_receive, 0, + "Wrong qty to receive") + cls.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + cls.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 3, + "Wrong qty outgoing") + cls.assertEquals(line.qty_received, 3, + "Wrong qty received") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_received, 5, + "Wrong qty received") + cls.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 5, + "Wrong qty outgoing") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_received, 2, + "Wrong qty received") + cls.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 2, + "Wrong qty outgoing") + picking.action_assign() + for mv in picking.move_lines: + mv.quantity_done = mv.product_uom_qty + picking.action_done() + for line in cls.rma_customer_id.rma_line_ids: + cls.assertEquals(line.qty_to_receive, 0, + "Wrong qty to receive") + cls.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + cls.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 0, + "Wrong qty outgoing") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_received, 3, + "Wrong qty received") + cls.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_received, 5, + "Wrong qty received") + cls.assertEquals(line.qty_delivered, 5, + "Wrong qty delivered") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_received, 2, + "Wrong qty received") + cls.assertEquals(line.qty_delivered, 2, + "Wrong qty delivered") + cls.line.action_rma_done() + cls.assertEquals(cls.line.state, 'done', + "Wrong State") + cls.rma_customer_id.action_view_in_shipments() + cls.rma_customer_id.action_view_out_shipments() + cls.rma_customer_id.action_view_lines() # DROPSHIP - def test_03_dropship(self): - wizard = self.make_supplier_rma.with_context({ - 'active_ids': self.rma_droship_id.rma_line_ids.ids, + def test_03_dropship(cls): + for line in cls.rma_droship_id.rma_line_ids: + line.action_rma_to_approve() + line.action_rma_approve() + line._onchange_operation_id() + wizard = cls.rma_make_picking.with_context({ + 'active_id': 1, + 'active_ids': cls.rma_droship_id.rma_line_ids.ids, + 'active_model': 'rma.order.line', + 'picking_type': 'incoming', + }).create({}) + wizard._create_picking() + res = cls.rma_droship_id.rma_line_ids.action_view_in_shipments() + cls.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = cls.env['stock.picking'].browse(res['res_id']) + cls.assertEquals(len(picking), 1, + "Incorrect number of pickings created") + moves = picking.move_lines + cls.assertEquals(len(moves), 3, + "Incorrect number of moves created") + wizard = cls.make_supplier_rma.with_context({ + 'active_ids': cls.rma_droship_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'active_id': 1 }).create({}) res = wizard.make_supplier_rma() - supplier_rma = self.rma.browse(res['res_id']) - for line in supplier_rma.rma_line_ids: - line.action_rma_to_approve() - line.action_rma_approve() - wizard = self.rma_make_picking.with_context({ - 'active_id': 1, - 'active_ids': supplier_rma.rma_line_ids.ids, - 'active_model': 'rma.order.line', - 'picking_type': 'incoming', - }).create({}) - procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] - picking = self.stockpicking.search(domain) - self.assertEquals(len(picking), 1, - "Incorrect number of pickings created") - moves = picking.move_lines - self.assertEquals(len(moves), 3, - "Incorrect number of moves created") + supplier_rma = cls.rma.browse(res['res_id']) for line in supplier_rma.rma_line_ids: # common qtys for all products - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - self.assertEquals(line.qty_outgoing, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") + cls.assertEquals(line.qty_received, 0, + "Wrong qty received") + cls.assertEquals(line.qty_outgoing, 0, + "Wrong qty incoming") + cls.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") # product specific - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 3, - "Wrong qty to deliver") - self.assertEquals(line.qty_incoming, 3, - "Wrong qty outgoing") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to deliver") - self.assertEquals(line.qty_incoming, 5, - "Wrong qty outgoing") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to deliver") - self.assertEquals(line.qty_incoming, 2, - "Wrong qty outgoing") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") - for line in self.rma_droship_id.rma_line_ids: - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_supplier_rma, 0, - "Wrong qty to supplier rma") - self.assertEquals(line.qty_in_supplier_rma, 3, - "Wrong qty in supplier rma") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_supplier_rma, 0, - "Wrong qty to supplier rma") - self.assertEquals(line.qty_in_supplier_rma, 5, - "Wrong qty in supplier rma") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_supplier_rma, 0, - "Wrong qty to supplier rma") - self.assertEquals(line.qty_in_supplier_rma, 2, - "Wrong qty in supplier rma") - for line in self.rma_droship_id.rma_line_ids: + for line in cls.rma_droship_id.rma_line_ids: + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + cls.assertEquals(line.qty_in_supplier_rma, 3, + "Wrong qty in supplier rma") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + cls.assertEquals(line.qty_in_supplier_rma, 5, + "Wrong qty in supplier rma") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_to_supplier_rma, 0, + "Wrong qty to supplier rma") + cls.assertEquals(line.qty_in_supplier_rma, 2, + "Wrong qty in supplier rma") + for line in cls.rma_droship_id.rma_line_ids: line.action_rma_done() - self.assertEquals(line.state, 'done', - "Wrong State") + cls.assertEquals(line.state, 'done', + "Wrong State") # Supplier RMA - def test_04_supplier_rma(self): - wizard = self.rma_make_picking.with_context({ - 'active_ids': self.rma_supplier_id.rma_line_ids.ids, + def test_04_supplier_rma(cls): + wizard = cls.rma_make_picking.with_context({ + 'active_ids': cls.rma_supplier_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'outgoing', 'active_id': 1 }).create({}) - procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] - picking = self.stockpicking.search(domain) - self.assertEquals(len(picking), 1, - "Incorrect number of pickings created") + wizard._create_picking() + res = cls.rma_supplier_id.rma_line_ids.action_view_out_shipments() + cls.assertTrue('res_id' in res, + "Incorrect number of pickings created") + picking = cls.env['stock.picking'].browse(res['res_id']) moves = picking.move_lines - self.assertEquals(len(moves), 3, - "Incorrect number of moves created") - for line in self.rma_supplier_id.rma_line_ids: + cls.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in cls.rma_supplier_id.rma_line_ids: # common qtys for all products - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 0, - "Wrong qty delivered") + cls.assertEquals(line.qty_received, 0, + "Wrong qty received") + cls.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + cls.assertEquals(line.qty_delivered, 0, + "Wrong qty delivered") # product specific - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 3, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 3, - "Wrong qty outgoing") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 5, - "Wrong qty outgoing") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 2, - "Wrong qty outgoing") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + cls.assertEquals(line.qty_to_deliver, 3, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 3, + "Wrong qty outgoing") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + cls.assertEquals(line.qty_to_deliver, 5, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 5, + "Wrong qty outgoing") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + cls.assertEquals(line.qty_to_deliver, 2, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 2, + "Wrong qty outgoing") picking.action_assign() - picking.do_transfer() - for line in self.rma_supplier_id.rma_line_ids: - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - if line.product_id == self.product_1: - self.assertEquals(line.qty_delivered, 3, - "Wrong qty delivered") - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - if line.product_id == self.product_2: - self.assertEquals(line.qty_outgoing, 5, - "Wrong qty delivered") - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - if line.product_id == self.product_3: - self.assertEquals(line.qty_outgoing, 2, - "Wrong qty delivered") - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - wizard = self.rma_make_picking.with_context({ + for mv in picking.move_lines: + mv.quantity_done = mv.product_uom_qty + picking.action_done() + for line in cls.rma_supplier_id.rma_line_ids: + cls.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + cls.assertEquals(line.qty_received, 0, + "Wrong qty received") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + cls.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_delivered, 5, + "Wrong qty delivered") + cls.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_delivered, 2, + "Wrong qty delivered") + cls.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") + wizard = cls.rma_make_picking.with_context({ 'active_id': 1, - 'active_ids': self.rma_supplier_id.rma_line_ids.ids, + 'active_ids': cls.rma_supplier_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'incoming', }).create({}) - procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] - pickings = self.stockpicking.search(domain) - self.assertEquals(len(pickings), 3, - "Incorrect number of pickings created") + wizard._create_picking() + res = cls.rma_supplier_id.rma_line_ids.action_view_in_shipments() + cls.assertTrue('res_id' in res, + "Incorrect number of pickings created") + pickings = cls.env['stock.picking'].browse(res['res_id']) + cls.assertEquals(len(pickings), 1, + "Incorrect number of pickings created") picking_out = pickings[0] moves = picking_out.move_lines - self.assertEquals(len(moves), 2, - "Incorrect number of moves created") - for line in self.rma_supplier_id.rma_line_ids: - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - if line.product_id == self.product_1: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_delivered, 3, - "Wrong qty delivered") - if line.product_id == self.product_2: - self.assertEquals(line.qty_to_receive, 5, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 5, - "Wrong qty to deliver") - if line.product_id == self.product_3: - self.assertEquals(line.qty_to_receive, 2, - "Wrong qty to receive") - self.assertEquals(line.qty_to_deliver, 2, - "Wrong qty to deliver") + cls.assertEquals(len(moves), 3, + "Incorrect number of moves created") + for line in cls.rma_supplier_id.rma_line_ids: + cls.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + cls.assertEquals(line.qty_received, 0, + "Wrong qty received") + cls.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + cls.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_to_receive, 5, + "Wrong qty to receive") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_to_receive, 2, + "Wrong qty to receive") picking_out.action_assign() - picking_out.do_transfer() - for line in self.rma_supplier_id.rma_line_ids[0]: - self.assertEquals(line.qty_to_receive, 3, - "Wrong qty to receive") - self.assertEquals(line.qty_incoming, 0, - "Wrong qty incoming") - self.assertEquals(line.qty_to_deliver, 0, - "Wrong qty to deliver") - self.assertEquals(line.qty_outgoing, 3, - "Wrong qty outgoing") - if line.product_id == self.product_1: - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - self.assertEquals(line.qty_delivered, 3, - "Wrong qty delivered") - if line.product_id == self.product_2: - self.assertEquals(line.qty_received, 0, - "Wrong qty received") - self.assertEquals(line.qty_delivered, 5, - "Wrong qty delivered") - if line.product_id == self.product_3: - self.assertEquals(line.qty_received, 2, - "Wrong qty received") - self.assertEquals(line.qty_delivered, 2, - "Wrong qty delivered") - for line in self.rma_supplier_id.rma_line_ids: + for mv in picking.move_lines: + mv.quantity_done = mv.product_uom_qty + picking_out.action_done() + for line in cls.rma_supplier_id.rma_line_ids[0]: + cls.assertEquals(line.qty_to_receive, 3, + "Wrong qty to receive") + cls.assertEquals(line.qty_incoming, 0, + "Wrong qty incoming") + cls.assertEquals(line.qty_to_deliver, 0, + "Wrong qty to deliver") + cls.assertEquals(line.qty_outgoing, 3, + "Wrong qty outgoing") + if line.product_id == cls.product_1: + cls.assertEquals(line.qty_received, 0, + "Wrong qty received") + cls.assertEquals(line.qty_delivered, 3, + "Wrong qty delivered") + if line.product_id == cls.product_2: + cls.assertEquals(line.qty_received, 0, + "Wrong qty received") + cls.assertEquals(line.qty_delivered, 5, + "Wrong qty delivered") + if line.product_id == cls.product_3: + cls.assertEquals(line.qty_received, 2, + "Wrong qty received") + cls.assertEquals(line.qty_delivered, 2, + "Wrong qty delivered") + for line in cls.rma_supplier_id.rma_line_ids: line.action_rma_done() - self.assertEquals(line.state, 'done', - "Wrong State") + cls.assertEquals(line.state, 'done', + "Wrong State") From 115b2df9464a9c4fb8eaf1417e3e93fd94858a60 Mon Sep 17 00:00:00 2001 From: aheficent Date: Fri, 3 Aug 2018 11:01:09 +0200 Subject: [PATCH 44/81] [IMP]product first on view then select document according to product --- rma/views/rma_order_line_view.xml | 50 ++++++++++++++++--------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/rma/views/rma_order_line_view.xml b/rma/views/rma_order_line_view.xml index 08b20fb0..09237814 100755 --- a/rma/views/rma_order_line_view.xml +++ b/rma/views/rma_order_line_view.xml @@ -102,13 +102,6 @@ domain="[('supplier','=',True)]" string="Supplier"/>
- - - @@ -124,17 +117,25 @@ - + + + + + + + + + - - - - @@ -274,13 +275,6 @@
- - - @@ -295,16 +289,24 @@ - + + + + + + + + + - - - - From 6d67fe838d4390297c53a919b6fa6e887fdcd63b Mon Sep 17 00:00:00 2001 From: aheficent Date: Fri, 3 Aug 2018 11:24:58 +0200 Subject: [PATCH 45/81] [IMP] add group to manage rma groups --- rma/security/rma.xml | 5 +++++ rma/views/rma_order_view.xml | 4 ++-- rma/wizards/stock_config_settings.py | 7 +++++++ rma/wizards/stock_config_settings.xml | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/rma/security/rma.xml b/rma/security/rma.xml index 99e6a664..ecefd303 100755 --- a/rma/security/rma.xml +++ b/rma/security/rma.xml @@ -35,6 +35,11 @@ + + RMA Groups + + + diff --git a/rma/views/rma_order_view.xml b/rma/views/rma_order_view.xml index da09e327..27000c34 100755 --- a/rma/views/rma_order_view.xml +++ b/rma/views/rma_order_view.xml @@ -277,14 +277,14 @@ id="menu_rma_act_customer" sequence="50" parent="menu_customer_rma" - groups="rma.group_rma_customer_user" + groups="rma.group_rma_groups" action="action_rma_customer"/>
+

From d13b9b80da774d1a0d79762edb44e3f8422f9bb6 Mon Sep 17 00:00:00 2001 From: aaron Date: Thu, 24 May 2018 11:50:28 +0200 Subject: [PATCH 46/81] [FIX]RMA location company is the warehouse company --- rma/models/stock_warehouse.py | 1 + 1 file changed, 1 insertion(+) diff --git a/rma/models/stock_warehouse.py b/rma/models/stock_warehouse.py index 50ba21d8..77465ab8 100644 --- a/rma/models/stock_warehouse.py +++ b/rma/models/stock_warehouse.py @@ -73,6 +73,7 @@ class StockWarehouse(models.Model): 'name': 'RMA', 'usage': 'internal', 'location_id': wh.lot_stock_id.id, + 'company_id': wh.company_id.id, }) # RMA types if not wh._rma_types_available(): From e55ac040c19f87f0e25414cccf0606713377ff13 Mon Sep 17 00:00:00 2001 From: aheficent Date: Fri, 24 Aug 2018 10:18:30 +0200 Subject: [PATCH 47/81] [IMP]add icon. Courtesy lreficent. --- rma/static/description/icon.png | Bin 0 -> 4261 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rma/static/description/icon.png diff --git a/rma/static/description/icon.png b/rma/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce758c20300c568fef329d9a5090c58bfeb29147 GIT binary patch literal 4261 zcmbuD1y>Z#*MJvMQdp2uLb_8BmTu`1kVd+@YblXN5NX&YL=a>N1u20gU3#Syq;pxi zbAkW*`v~tl=gfW1#64$b?##V2lc=YoNV^c^1SYUg0077=)Rh$sgCV=n5EBFAD})?j|3?-wG8|JrTXOE|s088~lka9ZUjr)5 z!oTQLdw94Zj2L!TDhz(yO8%`(tv0HjDw;QU*_}3{q*3Pf>`#ax{?^aqS$t1@1IW(C zmd_a%_>(>AW=<6JWy4LN9{{kZ z3P<&)KV@Def&q*Dz2)p8bm3b2oukq>3pCB#U^Q*b8%Cq{RI}<1lx+39bnfAqqhw%6lpg~4 z75&}Ra31FF&!_!P37mi`P{g<4ZdcKDIPvpx9$dgVA45k!PQ5*Y_96UV`7h-G;ob8? z_)$^UjJ?{+N=B|9#=^~hga{qiTmT9?aPG&e`naD1NoZA_cg`M>fn0g)Hg2_RWuHqH z=6QKFZss<*8U_b!Cx32A(+NkW>k6Iqt@qmtw}-p-ox^z}_?hR!R`*uDUeb>wTGBGP z_S*mKsGHmj)YS6+q0-kfu5osk-(NOI96B483VtKk-k^xM|8F{%qo~joTzj_tHI0{r zrq2kX=btb+t{HL+o8xUZsdx-O>)NHIa?<3jH2TsK+LH2M;-{YXVcP=AR#nS(ZiqL1 zV6C~q17W}mda}b+sH1IrJs2WZbca`=6Pbu;=*iio-Jd@fv2W=p?pdK?0G*kdnML==X9A>K7&?yL?!&L;o^ZKHD24MH$w zWsfzk;o$bzSG7pHMM1f5M-Dw4LjDrXITznEsj2F`uS{Y%Dv;<&whj}?`24Leagoe) z-5XxGmTj24<2}b1nFGs3_hrUfpSggdicm0||FUN5*s8wrN8i*3 z8Uw#oo?BXOZV98sq_igi#R_qFzGPAwRlG~OTXs7>*~$otK+YZ)iRBVP%$uHRV$Alk z2zN}ubvC$$hTIayp&5{Rrwhj(Rms_{Z=CerTo?zIZ5{voZ==Rb0BC zzrMLNUcuoQEsRfgb4z_XM=Y;%<|2RrW%N%kKqNvF(yR)5XT~*LwaDPm_%~T}aJ$i! zri!+RcQ6XH{QSE7@~Wna#-ks1r{(26sHM&R-q_;WyGWQ>DfQ#92p zjnS-m^qlx76N$uG*-X=o(Asq^{*)iOAg$agl(4A^LcTyq{>JUL zJz+~EYJEE;*-BGQnR05>^V8nt2+YLO;>RH4bw&cC7_Ae{Jn4K)JAMhQV&lMgSmhGb2{thp zRnt`1TT-)6TL>*8Nlqyj5{y4K{XCpBMM*JTb-~n`A@A3Ve?USY#&fGl5w|rJ*|Ejn zSQCO=`r2I@noqN1ISL(Jsug*<`ZsGRbQZhooi`p@>%`Y)e_K)PewxxHC$4PZq=hll zp_h%)65teWOe^2pTGxLac}18hIz`>*$wjf|k9v;u2IIqBANQ}jYZ*;`5f~ss_eHlC2bA4cH9I0$*HT|kverAXm`)Q zFXNG9BS&1*a}8eG4L-h1y|Yv;(JwW^N(UB+gyx6esxV!N&uV-U$!@6r1K4p>&k9J$*Sa zxIwhYq#Z~o^a4{nY6H7uev&tLQjkvfr$#Tgpr@>jp2$y7FE_`p2^_uhM%r+&{1T7e zOe&hK$Dg?5XufMWj7xxVV-AT4euC;KUdwje z4?IC|GUc8{GmE!0i19kwVZ#rec0{Vj5Xx*lINLe^H}~%>kaSlAZc|zv>Zyt_y1>I* zrF-n|eZ6ZA+PBa@641}gQPK&du9&(Xgw}{pRq!Vu=ms%0cYTid&Gzk%6|;bjND_d! zH2S&Py~53%m~HxW3ZizRF@7T%Pd+K}FbXMa5@%NJIGJfWLK`n8oCoPLKoMm>fR#r{ ztl$TbvPNujxk3N35c!TC-fVmaH~EmzjAB%OnXp`^b%H)sF`*ihaE9BFMMrbIBMVpC z$7AEh6*XTJD`Cs4>%{k=&CD4CkEPc`6h`NrsfMZK#2c!Xsw4N2i#|Jg-^wBB*@{P_ z`wvnGo^GBeFqsy=#H(8)T(plizZ*%S17FqLUdL`536!j~dLN&^9lS@)Ym<1v` zC~GE#9Lf*c9>IY$Ts5xnhi#G<8oZp%8aFE-P!0R`&JTmtuzQ zgovI)VnVOR<2;9`pDA0~A-As-%p=EBYsJ%BtqeTZ*Lop+UeChDh#(NC=;`Ni1ME36 zOCXEh*eA|~soC|O>jh5)srA@hXus$?b%RCf2C3&A*1s;c`#gH_AkY>AqX}rNjy%^^ zka|mg6F2eGa*PipJOFsdfTX!9j2zm^%FLm58|=VQ(E9Z#9NXL9=pMHqzvGZAvnu)_ zoP3`0c}0q&^=I-7i9yX|(|TKSsz0@6;D?$LL6R{HvtpZ*BdEvE zQ=#yOPh7b3TXQeEuugD(33Yddc}{xMVPLRFJ)aRIr|W+7+XQ=<#xmRK7k(rsBY;b* zf59T}QfP}M%6&q(+7i(@^2lhV#66KHG0#0CncEt#rlaK#t%mz+E8Tw?&*&KV`C2j& zJF3^dnr^YkoV$*EW;;$((VE#N&krFdLhKcql)O##oG0n8f* zrczRK&4ICUX`6jhLjjfkTgSw?m>o>mUX#ZzKDgt{p6^o0f#W=qyTJoxUY&fl13D^xa;Omym% zv{WD<1XV8@P+C50tJ5y4sPx!vJ&sHRT;T*TCx^>!IL7Z7AVOTmg`j8~ubLSRBo2^n zUbUbU|GX~vcd)i8N6v9qBlPVHl|?^z_Z+?c`QD26IDFuOweJ&Qjbake43A77)A?S& zqTRyrV1!O7IN+dE6@EXomy>MD2~a)T>e9%aB|2Or{Q;JN&Tm~HWDWK><*2tcI~+Hl zpU$e_4hpZp-}g|T%-avDU%^9=vS&1Ufm{ZDaB~lX(9^rpl+CWdGYZr8p6P1V7emcmF^OFH{Lr>%M&Gi6)a|gwRtWFX*lZ z#A8*HoqiE>biBUhkhxY!AxR0aPkS3S zJ8UJxC!D`bQ9jmg9GP71J1dM0*7Umbh>~8x<~-h=?##c_nK%tE8}{Xu{psh!fJ`hL zI`wT;?cOb)5)9Cl^qMn6Sa(6WvGJ<}D$?PpqZnTvGeTP|i(L`_A%!na)k# z1w|V*Zx8pE;5t^^NmXa1=WNYljXbi`Uvai3CgX%uv2EB3kOE#sS}OC^!(I?mKkSB| z%7V_EhS97J+vhzqjJa9tj7c`3A8_hp9K5{Bm|#|2-prKawq9PXZB2B>BHIvU+{3rN zwJr=jje*6=Bm%{b*y_rxy;frE0aZ3>|G~NzizpR42r!p6t@ux3*skGWua(#d2?&d7$l$;@%6ARI+%OMxvola*py z0A#gTDL=Uq(@(+_c&N~e_r4b%!$rcBXoa`~5E(hrPrvFZ!~Qz})L-Z**C<-Q`5!!| BS)2d> literal 0 HcmV?d00001 From 06598b6aed0d9d152a3b3230cbee31901c273b14 Mon Sep 17 00:00:00 2001 From: aheficent Date: Thu, 4 Oct 2018 12:10:51 +0200 Subject: [PATCH 48/81] [FIX]text on create supplier rma button --- rma/wizards/rma_order_line_make_supplier_rma_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rma/wizards/rma_order_line_make_supplier_rma_view.xml b/rma/wizards/rma_order_line_make_supplier_rma_view.xml index 3fff3c39..0dff174e 100755 --- a/rma/wizards/rma_order_line_make_supplier_rma_view.xml +++ b/rma/wizards/rma_order_line_make_supplier_rma_view.xml @@ -50,7 +50,7 @@ - Create Supplier RMA Group + Create Supplier RMA ir.actions.act_window rma.order.line.make.supplier.rma form @@ -68,7 +68,7 @@
From 5f60d2f87af530f263753f03984b803f516924dc Mon Sep 17 00:00:00 2001 From: aaron Date: Fri, 25 May 2018 15:34:39 +0200 Subject: [PATCH 49/81] [IMP]add rma line report --- rma/__manifest__.py | 2 + rma/report/rma_report.xml | 13 ++++ rma/report/rma_report_templates.xml | 99 +++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 rma/report/rma_report.xml create mode 100644 rma/report/rma_report_templates.xml diff --git a/rma/__manifest__.py b/rma/__manifest__.py index 7335d0d6..a3538425 100644 --- a/rma/__manifest__.py +++ b/rma/__manifest__.py @@ -18,6 +18,8 @@ 'data/rma_sequence.xml', 'data/stock_data.xml', 'data/rma_operation.xml', + 'report/rma_report.xml', + 'report/rma_report_templates.xml', 'views/rma_order_view.xml', 'views/rma_operation_view.xml', 'views/rma_order_line_view.xml', diff --git a/rma/report/rma_report.xml b/rma/report/rma_report.xml new file mode 100644 index 00000000..07a2a110 --- /dev/null +++ b/rma/report/rma_report.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/rma/report/rma_report_templates.xml b/rma/report/rma_report_templates.xml new file mode 100644 index 00000000..997dc28f --- /dev/null +++ b/rma/report/rma_report_templates.xml @@ -0,0 +1,99 @@ + + + + + + + From 0bb54057095927d10c240077b8ae7d653bc7f5cd Mon Sep 17 00:00:00 2001 From: aheficent Date: Thu, 4 Oct 2018 16:26:45 +0200 Subject: [PATCH 50/81] [UPT]report usable in v11 --- rma/__manifest__.py | 2 +- rma/report/rma_report_templates.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rma/__manifest__.py b/rma/__manifest__.py index a3538425..662d5b15 100644 --- a/rma/__manifest__.py +++ b/rma/__manifest__.py @@ -10,7 +10,7 @@ 'in odoo', 'author': "Eficent, Odoo Community Association (OCA)", 'website': 'http://www.github.com/OCA/rma', - 'depends': ['stock', 'mail'], + 'depends': ['stock', 'mail', 'web'], 'demo': ['demo/stock_demo.xml', ], 'data': ['security/rma.xml', diff --git a/rma/report/rma_report_templates.xml b/rma/report/rma_report_templates.xml index 997dc28f..698d60f5 100644 --- a/rma/report/rma_report_templates.xml +++ b/rma/report/rma_report_templates.xml @@ -1,7 +1,7 @@ + + + + + diff --git a/rma/views/rma_order_view.xml b/rma/views/rma_order_view.xml index 1434cc39..6f089e84 100755 --- a/rma/views/rma_order_view.xml +++ b/rma/views/rma_order_view.xml @@ -78,9 +78,26 @@ /> - - - + + + + + + + + + + + + + + + + + string="Supplier" + attrs="{'readonly':[('state', '!=', 'draft')]}"/> - + + + + + + + + + + + + + + @@ -292,4 +329,5 @@ groups="rma.group_rma_manager" sequence="30" parent="stock.menu_stock_config_settings"/> + From efd131b334ea25beebae448fc6e53b84e2b524a7 Mon Sep 17 00:00:00 2001 From: ahenriquez Date: Fri, 3 Jan 2020 13:41:25 +0100 Subject: [PATCH 77/81] [UPT]rma group report to v12 --- rma/report/rma_report_templates.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rma/report/rma_report_templates.xml b/rma/report/rma_report_templates.xml index 6a3144d2..9771691c 100644 --- a/rma/report/rma_report_templates.xml +++ b/rma/report/rma_report_templates.xml @@ -100,10 +100,10 @@ - + - +