From 8088c3a829fd7c54a43c12f70e45eae303eba8cd Mon Sep 17 00:00:00 2001 From: Jordi Ballester Date: Thu, 27 Jul 2017 18:17:19 +0200 Subject: [PATCH 001/175] 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 000000000..68a325631 --- /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 000000000..4105ff51d --- /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 000000000..9fc1d7f83 --- /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 000000000..ad39aff48 --- /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 000000000..1162e9adc --- /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 000000000..7dd24cdc8 --- /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 000000000..5af76da50 --- /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 000000000..ad034891e --- /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 000000000..a55e8910c --- /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 000000000..2a992b253 --- /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 000000000..efc8f43c1 --- /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 000000000..87d271e0a --- /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 000000000..9f99a6366 --- /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 000000000..a2847bb76 --- /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 000000000..ec3c92559 --- /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 000000000..cc70c1742 --- /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 000000000..3d465a601 --- /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 000000000..291e1e5d9 --- /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 000000000..ab04e69c6 --- /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 000000000..1c2b27c0d --- /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 000000000..6ae75d89e --- /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 000000000..a79015f66 --- /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 000000000..74a9fd35f --- /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 000000000..a2f01d205 --- /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 000000000..1fc26e7ac --- /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 000000000..649552f42 --- /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 000000000..b5a897023 --- /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 000000000..788ffb6c6 --- /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 000000000..a2f06c743 --- /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 000000000..a626781f4 --- /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 000000000..64d335a44 --- /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 000000000..e5007085d --- /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 000000000..92df56545 --- /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 000000000..80f2f5bac --- /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 000000000..da05ac71e --- /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 000000000..79137bd56 --- /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 000000000..856094941 --- /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 000000000..ab19c4c4e --- /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 000000000..2bcb851bf --- /dev/null +++ b/rma/wizards/stock_config_settings.xml @@ -0,0 +1,17 @@ + + + + + stock.config.settings.rma + stock.config.settings + + + + + + + + + + + From 5e2f6c46d990e35bdc2cf5dcc4d1b8291e2a8ff6 Mon Sep 17 00:00:00 2001 From: lreficent Date: Wed, 2 Aug 2017 14:04:18 +0200 Subject: [PATCH 002/175] [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 68a325631..fd8a338d7 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 9fc1d7f83..80bc8f3fb 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 ad39aff48..fea67f4f6 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 ad034891e..348fb2bfd 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 a55e8910c..6838c5d1b 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -16,7 +16,7 @@ def _run_move_create(self, 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: + 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 2a992b253..d7f878bc3 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 000000000..decfce283 --- /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 efc8f43c1..000000000 --- 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 9f99a6366..e307b35c6 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 @@ def _compute_line_count(self): 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 @@ def action_view_out_shipments(self): @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 @@ def action_rma_draft(self): @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 ec3c92559..000000000 --- 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 74a9fd35f..c14144a63 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 a2f01d205..000000000 --- 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 788ffb6c6..000000000 --- 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 313929206971bef4909f3af93424082b7b453efb Mon Sep 17 00:00:00 2001 From: lreficent Date: Wed, 2 Aug 2017 17:05:58 +0200 Subject: [PATCH 003/175] [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 80bc8f3fb..c4e251627 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 6838c5d1b..c8cd39db3 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -18,8 +18,8 @@ def _run_move_create(self, procurement): 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 87d271e0a..5d3b230d1 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 @@ def _default_supplier_location_id(self): 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 e307b35c6..28a9ff8d4 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 @@ 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) + 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 @@ def action_rma_to_approve(self): @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 @@ def action_rma_approve(self): @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 a2847bb76..8eb1f9177 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 @@ def _compute_qty_to_deliver(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 + 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 @@ def _compute_procurement_count(self): 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 @@ def _compute_procurement_count(self): 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 @@ def _compute_procurement_count(self): 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 @@ def action_view_out_shipments(self): @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 cc70c1742..c8fdaf888 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 3d465a601..26ff4b08c 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 6ae75d89e..95bbe572d 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -13,7 +13,7 @@ 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.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 @@ def setUp(self): 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 @@ def test_00_receive_items(self): 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 @@ def test_00_receive_items(self): 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 @@ def test_00_receive_items(self): "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 @@ def test_00_receive_items(self): "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 @@ def test_00_receive_items(self): "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 @@ def test_00_receive_items(self): 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 @@ def test_00_receive_items(self): "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 @@ def test_00_receive_items(self): "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 @@ def test_00_receive_items(self): "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 649552f42..29d8797d5 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 e5007085d..64ce435fe 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 @@ def add_lines(self): 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 80f2f5bac..c81aa6a5d 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 @@ def default_get(self, fields): 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 @@ def _get_procurement_group_data(self, item): @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 @@ def _get_procurement_data(self, item, group, qty, picking_type): 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 @@ def _create_picking(self): 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 @@ def action_create_picking(self): 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 79137bd56..2f258c687 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 @@ def _prepare_supplier_rma(self, company): @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 80a6b0afd251bc243466c2322c04e9181eb80fe2 Mon Sep 17 00:00:00 2001 From: aheficent Date: Wed, 16 Aug 2017 12:52:35 +0200 Subject: [PATCH 004/175] [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 fea67f4f6..5baa6fcab 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 d7f878bc3..5ee028ecc 100644 --- a/rma/models/product.py +++ b/rma/models/product.py @@ -8,7 +8,9 @@ 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 decfce283..9674ad8df 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 5d3b230d1..4f2950093 100644 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -26,10 +26,7 @@ def _default_supplier_location_id(self): 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 @@ def _default_supplier_location_id(self): '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 28a9ff8d4..8061dea53 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 @@ def _compute_supplier_line_count(self): @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 @@ def _compute_line_count(self): 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 @@ def _compute_line_count(self): 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 @@ def action_rma_done(self): 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 @@ 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] + 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 8eb1f9177..6fddca531 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -308,8 +308,12 @@ def _onchange_product_id(self): 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 1c2b27c0d..dfa77946c 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 95bbe572d..2e36b989b 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -13,61 +13,95 @@ def setUp(self): super(TestRma, self).setUp() self.rma_make_picking = self.env['rma_make_picking.wizard'] + self.make_supplier_rma = self.env["rma.order.line.make.supplier.rma"] self.rma_add_stock_move = self.env['rma_add_stock_move'] self.stockpicking = self.env['stock.picking'] self.rma = self.env['rma.order'] self.rma_line = self.env['rma.order.line'] self.rma_op = self.env['rma.operation'] - self.rma_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 @@ def _prepare_move(self, product, qty): '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 @@ def test_00_receive_items(self): 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 @@ def test_00_receive_items(self): "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 @@ def test_00_receive_items(self): 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 @@ def test_00_receive_items(self): 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 @@ def test_00_receive_items(self): "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 @@ def test_00_receive_items(self): "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 000000000..a531734f1 --- /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 000000000..e67b55bae --- /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 c14144a63..bb35950b9 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 1fc26e7ac..b9f556335 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 29d8797d5..3b9399a8d 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 64ce435fe..fd6e2e184 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 @@ def default_get(self, fields): 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 @@ def _prepare_rma_line_from_stock_move(self, sm, lot=False): [('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 2f258c687..59ae981e1 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 @@ def default_get(self, fields): 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 @@ def _prepare_supplier_rma(self, company): 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 @@ def _prepare_supplier_rma_line(self, rma, item): '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 @@ def make_supplier_rma(self): 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 856094941..e7ad43c6b 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 005/175] [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 4f2950093..eec8f38a4 100644 --- a/rma/models/rma_operation.py +++ b/rma/models/rma_operation.py @@ -29,7 +29,7 @@ def _default_supplier_location_id(self): 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 6df6b80e02e6d7fa3505dff0407e7896b8cfc685 Mon Sep 17 00:00:00 2001 From: lreficent Date: Fri, 25 Aug 2017 12:22:53 +0200 Subject: [PATCH 006/175] [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 8061dea53..ae1afc4d0 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -179,8 +179,8 @@ def action_rma_done(self): 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 @@ def action_view_lines(self): 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 3b9399a8d..edabd55f7 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 3c0e629f5706b2e51f3bbd78eb6d3e0d2eb9ec2c Mon Sep 17 00:00:00 2001 From: lreficent Date: Wed, 18 Oct 2017 12:20:27 +0200 Subject: [PATCH 008/175] [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 1162e9adc..e59ec85f1 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 c8cd39db3..eb4a46b75 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -8,7 +8,10 @@ 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 @@ def _run_move_create(self, procurement): 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 ae1afc4d0..39130e409 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -47,30 +47,17 @@ def _default_date_rma(self): 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 @@ def _default_date_rma(self): @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 @@ def action_view_out_shipments(self): 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 6fddca531..acecfb066 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 @@ 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 @@ def _default_delivery_address(self): 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 @@ def _compute_in_shipment_count(self): 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 @@ def _get_supplier_rma_qty(self): @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 @@ def _compute_procurement_count(self): 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 @@ def _compute_procurement_count(self): ) 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 @@ def _compute_procurement_count(self): 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 @@ def _compute_procurement_count(self): 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 edabd55f7..002a3d918 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 c81aa6a5d..02b972238 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -21,7 +21,7 @@ def _prepare_item(self, line): '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 @@ def default_get(self, fields): '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 @@ def _get_address(self, item): 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 @@ def _get_procurement_data(self, item, group, qty, picking_type): 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 @@ def _get_procurement_data(self, item, group, qty, picking_type): 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 @@ def _get_procurement_data(self, item, group, qty, picking_type): 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 @@ def _create_picking(self): 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 7aea0713d618cff906c3304b33205cca5933e54b Mon Sep 17 00:00:00 2001 From: lreficent Date: Thu, 19 Oct 2017 10:10:19 +0200 Subject: [PATCH 009/175] [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 acecfb066..00f43309b 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -425,6 +425,17 @@ def _onchange_reference_move_id(self): 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 7f14ff8377870df86d35165feee079519adab29f Mon Sep 17 00:00:00 2001 From: lreficent Date: Thu, 19 Oct 2017 11:12:20 +0200 Subject: [PATCH 010/175] [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 fd6e2e184..4bbc48344 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 @@ def default_get(self, fields): 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 @@ def _prepare_rma_line_from_stock_move(self, sm, lot=False): 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 eb2b47e88f0fa5b3a35d0529af4776b81b82f148 Mon Sep 17 00:00:00 2001 From: lreficent Date: Thu, 19 Oct 2017 16:06:45 +0200 Subject: [PATCH 011/175] 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 002a3d918..614253361 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 2947a87e7b180269dc67fd9244bb64e7505487ed Mon Sep 17 00:00:00 2001 From: lreficent Date: Mon, 23 Oct 2017 14:00:01 +0200 Subject: [PATCH 013/175] 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 39130e409..998a154cb 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 @@ def _default_date_rma(self): 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 f3c592a1bab23408217ab2f08572ba07fe5b3ed0 Mon Sep 17 00:00:00 2001 From: lreficent Date: Wed, 25 Oct 2017 13:59:19 +0200 Subject: [PATCH 014/175] [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 00f43309b..acfdf1241 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -353,6 +353,10 @@ def _compute_procurement_count(self): 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 614253361..c43b3dc9c 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 015/175] [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 59ae981e1..79723b015 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 @@ def default_get(self, fields): 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 @@ def default_get(self, fields): @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 @@ def _prepare_supplier_rma(self, company): 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 @@ def _prepare_supplier_rma_line(self, rma, item): '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 @@ def make_supplier_rma(self): 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 e7ad43c6b..964c0e362 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 ae8548d234e12819ce90be3864cb2665a3ad5af0 Mon Sep 17 00:00:00 2001 From: aheficent Date: Tue, 19 Dec 2017 16:38:50 +0100 Subject: [PATCH 016/175] [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 574a28582..56dc20b2b 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 eb4a46b75..bfca58550 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 5ee028ecc..04557e210 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 9674ad8df..927de2712 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 1ce4885f9..32a5de7f3 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 eec8f38a4..2c24165f4 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 998a154cb..f23fab1fb 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 acfdf1241..ba807d50e 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 @@ def _get_rma_move_qty(self, states, direction='in'): 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 c8fdaf888..1fad0b8fc 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 26ff4b08c..52c26a61e 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 2e36b989b..9bca71042 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 a531734f1..798d9a75d 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 e67b55bae..8c83e0395 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 c43b3dc9c..6a184dc43 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 4bbc48344..fd12a19fb 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 02b972238..c716c9a21 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 79723b015..91041b8fa 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 964c0e362..455eed25e 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 ab19c4c4e..430585261 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 2bcb851bf..4df67cfaf 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 97cb9aff5e2aa27f7bec49fd1c0f8c6c419296f6 Mon Sep 17 00:00:00 2001 From: aheficent Date: Thu, 21 Dec 2017 12:44:57 +0100 Subject: [PATCH 017/175] [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 0cdf7adb8..59d0060e7 100644 --- a/rma/views/rma_order_view.xml +++ b/rma/views/rma_order_view.xml @@ -79,11 +79,9 @@ colspan="4" /> - - - - - + + + From 5ea392345a13eefea324258a72d0cb4d2cfdd286 Mon Sep 17 00:00:00 2001 From: Nikul Chaudhary Date: Fri, 10 Nov 2017 12:48:55 +0530 Subject: [PATCH 018/175] [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 56dc20b2b..3bd4eab8a 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 f23fab1fb..97866ebd5 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -171,7 +171,6 @@ def action_view_lines(self): 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 @@ 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.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 ba807d50e..5b06044a5 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -372,21 +372,21 @@ def _prepare_rma_line_from_stock_move(self, sm, lot=False): 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 9bca71042..0281349fe 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 798d9a75d..9f942f643 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -24,8 +24,9 @@ def test_dropship(self): }).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 @@ def test_dropship(self): "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 8c83e0395..107af6e3a 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 a79015f66..91f55dd51 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 019/175] [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 bfca58550..eeeb9eb20 100644 --- a/rma/models/procurement.py +++ b/rma/models/procurement.py @@ -23,6 +23,10 @@ def _run_move_create(self, procurement): 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 5b06044a5..a7672ab83 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -144,7 +144,8 @@ def _get_supplier_rma_qty(self): 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 @@ def _onchange_reference_move_id(self): 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 0281349fe..287234265 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -26,8 +26,8 @@ def setUp(self): '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 @@ def setUp(self): 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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, }) 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', + } + ) + 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', } - ).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() + 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 @@ def _prepare_move(self, product, qty, src, dest): '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 @@ def test_customer_rma(self): # 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 @@ def test_customer_rma(self): "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 9f942f643..9c99a538b 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 107af6e3a..f1f975462 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -66,12 +66,8 @@ def test_supplier_rma(self): 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 @@ def test_supplier_rma(self): 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 @@ def test_supplier_rma(self): "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 f2b5680307cd0945f5ad8824da1c1386626a196b Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 8 Jan 2018 16:18:47 +0100 Subject: [PATCH 020/175] [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 a7672ab83..8b108b922 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -86,8 +86,8 @@ def _compute_qty_to_receive(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 + 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 @@ def _get_supplier_rma_qty(self): 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 4bf794bb1cd7a4f5a3c73e2e0d1e0900c11f95e6 Mon Sep 17 00:00:00 2001 From: Nikul Chaudhary Date: Fri, 5 Jan 2018 16:43:54 +0530 Subject: [PATCH 021/175] [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 8b108b922..a68445ee9 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -435,7 +435,7 @@ def _check_move_partner(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)): + 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 287234265..4ebcfe900 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -30,6 +30,9 @@ def setUp(self): 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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, '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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, '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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, } ) 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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, 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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, 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 @@ def test_customer_rma(self): '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 @@ def test_customer_rma(self): "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 @@ def test_customer_rma(self): 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 9c99a538b..b7b5b11c8 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 @@ def test_dropship(self): '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 @@ def test_dropship(self): 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 f1f975462..1c3fd67f3 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -64,24 +64,24 @@ def test_supplier_rma(self): "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 @@ def test_supplier_rma(self): 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 @@ def test_supplier_rma(self): "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 @@ def test_supplier_rma(self): 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 66f741001d0476067173019a72e75f6ef9ba6de1 Mon Sep 17 00:00:00 2001 From: Nikul Chaudhary Date: Tue, 9 Jan 2018 15:35:29 +0530 Subject: [PATCH 022/175] [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 eeeb9eb20..d51dc5853 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 4ebcfe900..b31adfccb 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -275,6 +275,9 @@ def test_customer_rma(self): '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 1c213466140b3c24567b2bd6e55ca8b93dca64c8 Mon Sep 17 00:00:00 2001 From: aheficent Date: Tue, 9 Jan 2018 14:02:51 +0100 Subject: [PATCH 023/175] [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 a68445ee9..f057795bb 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -196,6 +196,7 @@ def _compute_procurement_count(self): 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 59d0060e7..955082f6e 100644 --- a/rma/views/rma_order_view.xml +++ b/rma/views/rma_order_view.xml @@ -86,7 +86,7 @@ @@ -172,7 +172,7 @@ From 138ea708bacc6d0f7ff03c8bd019e61c3dba4cfe Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 22 Jan 2018 11:46:33 +0100 Subject: [PATCH 024/175] [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 f057795bb..63945ec3c 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -71,7 +71,7 @@ def _get_rma_move_qty(self, states, direction='in'): 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 87fadd1d84c7a8f6231397fb23c71576c89b1ad1 Mon Sep 17 00:00:00 2001 From: aheficent Date: Fri, 26 Jan 2018 18:03:28 +0100 Subject: [PATCH 025/175] [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 97866ebd5..cd0249717 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -21,7 +21,7 @@ def _get_default_type(self): 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 @@ def _compute_in_shipment_count(self): 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 c663cd2db232926abc91976f3fc35000f70d6fe3 Mon Sep 17 00:00:00 2001 From: Bhavesh Odedra Date: Fri, 9 Feb 2018 21:56:28 +0530 Subject: [PATCH 026/175] [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 fd8a338d7..4fe6cf07e --- 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 4105ff51d..6209ddcae --- 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 3bd4eab8a..4c9f25fbc --- 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 d51dc5853..5bcc1a8fc --- 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 cd0249717..a0872f8bd --- 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 @@ def _get_default_type(self): @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 @@ def action_view_in_shipments(self): 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 @@ def action_view_out_shipments(self): 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 @@ def _get_valid_lines(self): 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 @@ def action_view_supplier_lines(self): 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 63945ec3c..a85a5a34a --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -47,20 +47,16 @@ def _default_delivery_address(self): @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 @@ def _compute_qty_supplier_rma(self): 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 @@ def _compute_procurement_count(self): 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 @@ def _compute_procurement_count(self): 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 @@ def _compute_procurement_count(self): 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 @@ def _prepare_rma_line_from_stock_move(self, sm, lot=False): @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 @@ def _onchange_receipt_policy(self): 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 1fad0b8fc..ef137fb33 --- 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 291e1e5d9..7362e7ebd --- 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 91f55dd51..000000000 --- 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 bb35950b9..c00c2c2ff --- 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 b9f556335..933cee23a --- 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')] - - + + + + + + + + + + + + + + + + + + + - - Supplier Operations - rma.operation - form - tree,form - {'default_type': "supplier"} - [('type','=', 'supplier')] - - + + Customer Operations + rma.operation + form + tree,form + {'default_type': "customer"} + [('type','=', 'customer')] + + - + + 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 6a184dc43..fa7a69638 --- 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 955082f6e..1d78d2e86 --- 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.supplier.tree - rma.order - - - + + rma.order.form + rma.order + +
+
+ +
+ + + + +
+
+

+ +

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

- -

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

+ +

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

- -

-
- - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
- - - - - - rma.order.select - rma.order - - - - - - - - - - - - - + + + + + + + +
+ + +
+ + + - - Customer RMA Group - rma.order - form - [('type','=', 'customer')] - {'customer':1} - tree,form - - + + rma.order.select + rma.order + + + + + + + + + + + + + - - Supplier RMA Group - rma.order - form - [('type','=', 'supplier')] - {'supplier':1} - tree,form - - + + Customer RMA Group + rma.order + form + [('type','=', 'customer')] + {'customer':1} + tree,form + + - - - tree - - + + Supplier RMA Group + rma.order + form + [('type','=', 'supplier')] + {'supplier':1} + tree,form + + - - - form - - - + + + tree + + - + + + form + + + - + - + - + - + - + diff --git a/rma/views/stock_view.xml b/rma/views/stock_view.xml old mode 100644 new mode 100755 index a2f06c743..c2120a7ef --- 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.location.route.form - - stock.location.route - - - - - - - - - procurement.order.form.stock.inherit - procurement.order - - - - [('usage', '!=', 'view')] - - - + + stock.move.form + stock.move + + + + + + + + + - + + 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 2bad25ede..424d11d68 --- 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 717137c6e..129ec08e4 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -32,6 +32,7 @@ def default_get(self, fields): 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 @@ def default_get(self, fields): 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 @@ def find_procurement_group(self, item): 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 @@ def _get_procurement_data(self, item, group, qty, picking_type): 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 @@ def _create_procurement(self, item, picking_type): 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 @@ def _create_picking(self): 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 @@ def _get_action(self, pickings, procurements): 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 c3f656a0a..3c6a17dfb --- 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 455eed25e..632285454 --- 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 430585261..8c9a2ef98 --- a/rma/wizards/stock_config_settings.py +++ b/rma/wizards/stock_config_settings.py @@ -6,7 +6,7 @@ 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 4df67cfaf..b07b0438c --- 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 5bfa9d13235acbca9d50c7e477194516217622e3 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Fri, 9 Feb 2018 12:24:45 -0600 Subject: [PATCH 027/175] [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 6209ddcae..f3284a963 --- 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 4c9f25fbc..53d887de2 --- 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 5baa6fcab..469ed58db 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 e59ec85f1..cca2b65a8 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 7dd24cdc8..ee9438754 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 5af76da50..96659f5bb 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 06c86f1ea..4e9429ad5 --- 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 5bcc1a8fc..7583ee881 --- 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 04557e210..a235cc897 --- 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 927de2712..7bfd61006 --- 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 32a5de7f3..896b03a10 --- 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 2c24165f4..07335754a --- 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 a0872f8bd..a22e8f424 --- 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 a85a5a34a..6280947a9 --- 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 ef137fb33..e5c132410 --- 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 52c26a61e..3dddc32ed --- 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 ab04e69c6..f9b0ccedf 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 dfa77946c..8a00d4333 --- 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 b31adfccb..67f9b2a9e --- 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 b7b5b11c8..7380d881c --- 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 1c3fd67f3..109c784cb --- 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 c00c2c2ff..aeb6da9de 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 97ec12b7f..19b34670b 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 933cee23a..0b96ff4e9 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 fa7a69638..17fa9fcf5 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 1d78d2e86..da09e3279 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 c2120a7ef..831a82d1c 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 a626781f4..fa0a76c00 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 64d335a44..d676aaede --- 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 cb3178ddd..da95eda0d --- 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 424d11d68..df0b7e657 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 129ec08e4..a69362a09 --- 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 3c6a17dfb..126bf191b 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 511aab317..c84aab6da --- 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 632285454..1129702f8 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 8c9a2ef98..f9d668e32 --- 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 b07b0438c..4ea1a48e4 100755 --- a/rma/wizards/stock_config_settings.xml +++ b/rma/wizards/stock_config_settings.xml @@ -1,4 +1,4 @@ - + stock.config.settings.rma From 0844d0cebd2da412c9418bff3d1a27a96f0b32a7 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Fri, 9 Feb 2018 12:35:23 -0600 Subject: [PATCH 028/175] [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 f3284a963..4733391a3 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 53d887de2..66256b0eb 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 7583ee881..36140e551 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 a235cc897..b1da22216 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 07335754a..9e9c12d67 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 a22e8f424..4b7caf001 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 6280947a9..f33946706 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 e5c132410..1ccf52cc5 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 3dddc32ed..3111e137f 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 8a00d4333..619dbb541 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 67f9b2a9e..425dd0306 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 7380d881c..b22dfbc24 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 109c784cb..276663864 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 d676aaede..7fa8500f0 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 da95eda0d..75cf39ab6 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 a69362a09..f361b4278 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 c84aab6da..f127327ec 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 f9d668e32..265eeaa5e 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 3367ce78e4a5ebb12f3f7ca725adf18761ef6a6f Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Fri, 9 Feb 2018 16:52:31 -0600 Subject: [PATCH 029/175] [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 4b7caf001..253f968a5 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 @@ def action_view_in_shipments(self): 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 @@ def action_view_out_shipments(self): 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 @@ def action_view_lines(self): 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 @@ def action_view_supplier_lines(self): 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 f33946706..7f0743651 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -514,15 +514,13 @@ def action_view_in_shipments(self): 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 @@ def action_view_out_shipments(self): 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 619dbb541..7262aab18 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 425dd0306..81d20e436 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -224,7 +224,6 @@ def test_rma_order_line(self): })._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 @@ def test_rma_order_line(self): 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 @@ def test_customer_rma(self): '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 @@ def test_customer_rma(self): '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 b22dfbc24..d149fc18b 100644 --- a/rma/tests/test_rma_dropship.py +++ b/rma/tests/test_rma_dropship.py @@ -48,9 +48,7 @@ def test_dropship(self): '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 276663864..b5444691d 100644 --- a/rma/tests/test_supplier_rma.py +++ b/rma/tests/test_supplier_rma.py @@ -22,9 +22,7 @@ def test_supplier_rma(self): '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 @@ def test_supplier_rma(self): '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 75cf39ab6..1f276a2c6 100644 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -101,15 +101,16 @@ def add_lines(self): 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 f361b4278..5da02b0fb 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -209,7 +209,7 @@ def action_create_picking(self): 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 216891b1a9b4ba6f5478a1a6af618c4733933b2a Mon Sep 17 00:00:00 2001 From: Jordi Ballester Date: Wed, 14 Feb 2018 13:35:09 +0100 Subject: [PATCH 030/175] 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 469ed58db..27e9be66b 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 7f0743651..78e60dee7 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -139,7 +139,7 @@ def _get_supplier_rma_qty(self): 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 @@ def _onchange_operation_id(self): 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 @@ def _onchange_lot_id(self): 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 @@ def action_view_in_shipments(self): 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 81d20e436..3548589a1 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -160,6 +160,8 @@ def _create_rma_from_move(self, products2move, type, partner, 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) # approve the RMA Line self.rma_line.action_rma_to_approve() @@ -264,18 +266,18 @@ def test_customer_rma(self): '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 @@ def test_customer_rma(self): "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 @@ def test_customer_rma(self): '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 d149fc18b..dedb7a395 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 @@ def test_dropship(self): '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 @@ def test_dropship(self): '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 b5444691d..6cc3c15c4 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 @@ def setUp(self): 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 @@ def test_supplier_rma(self): "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 @@ def test_supplier_rma(self): '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 0b96ff4e9..e4fd4824c 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 17fa9fcf5..38093034f 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 5da02b0fb..db785c2f7 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 @@ def _get_procurement_data(self, item, group, qty, picking_type): 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 @@ def _get_procurement_data(self, item, group, qty, picking_type): @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 @@ def _create_procurement(self, item, picking_type): 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 @@ def _get_action(self, pickings, procurements): @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 f127327ec..f6def3b6a 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 @@ def _prepare_supplier_rma(self, company): 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 @@ def _prepare_supplier_rma_line(self, rma, item): '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 020583b8606802140f119be59db6c97046279de1 Mon Sep 17 00:00:00 2001 From: Bhavesh Odedra Date: Wed, 14 Feb 2018 19:22:41 +0530 Subject: [PATCH 031/175] [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 78e60dee7..454af5cca 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -46,16 +46,18 @@ def _default_delivery_address(self): @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 aeb6da9de..a28106004 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 126bf191b..61bd41de0 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 1129702f8..1ba479214 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 0c9abac186cf18a4cb9d1185d73d469edced17da Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Mon, 25 Jun 2018 12:04:11 -0500 Subject: [PATCH 032/175] [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 7362e7ebd..e899b9c93 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 8ca44fbabecebec97e2d7bfa5a1324b5245599d2 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Tue, 26 Jun 2018 12:02:00 -0500 Subject: [PATCH 033/175] [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 e899b9c93..de0f55350 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 7c7b1ad38cab689e66db4ecd8ad1f3348b160ed6 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Wed, 27 Jun 2018 08:09:46 -0500 Subject: [PATCH 034/175] [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 de0f55350..e899b9c93 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 f9b0ccedf..99e6a6645 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 4571901891f9e85af618d48b2d7be22e07a92bf0 Mon Sep 17 00:00:00 2001 From: Bhavesh Odedra Date: Thu, 19 Jul 2018 20:08:43 +0530 Subject: [PATCH 035/175] [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 253f968a5..541345427 100644 --- a/rma/models/rma_order.py +++ b/rma/models/rma_order.py @@ -109,9 +109,9 @@ def action_view_in_shipments(self): 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 @@ def action_view_out_shipments(self): 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 454af5cca..58287ba71 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -519,13 +519,14 @@ def action_view_in_shipments(self): ('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 @@ def action_view_out_shipments(self): ('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 db785c2f7..dfbac6140 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -187,7 +187,7 @@ def _create_picking(self): @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 4de6a2d1b696d0768d6dccecfe7f5a6341d9aa4d Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Tue, 26 Jun 2018 12:02:00 -0500 Subject: [PATCH 036/175] [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 e899b9c93..de0f55350 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 92e1033c9f72d1bdeaa706542aed3fffb46627b8 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Wed, 27 Jun 2018 08:09:46 -0500 Subject: [PATCH 037/175] [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 de0f55350..e899b9c93 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 f7f3e960a118ec783f93b826316359cafbefaf8b Mon Sep 17 00:00:00 2001 From: aheficent Date: Thu, 26 Jul 2018 18:41:44 +0200 Subject: [PATCH 038/175] [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 4fe6cf07e..196174646 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 66256b0eb..7335d0d6b 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 27e9be66b..9d1fc02fa 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 ee9438754..b9f100bde 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 9e9c12d67..bee159589 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 @@ def _default_customer_location_id(self): 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 @@ def _default_supplier_location_id(self): ('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 @@ def _default_supplier_location_id(self): 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 58287ba71..fceeaa940 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -46,18 +46,26 @@ def _default_delivery_address(self): @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 @@ 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 + 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 @@ def _compute_qty_incoming(self): @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 @@ def _compute_qty_outgoing(self): @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 @@ def _get_supplier_rma_qty(self): '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 @@ def _compute_qty_supplier_rma(self): ) 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 @@ def _compute_qty_supplier_rma(self): 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 @@ def _compute_qty_supplier_rma(self): '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 @@ def _prepare_rma_line_from_stock_move(self, sm, lot=False): [('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 @@ def _prepare_rma_line_from_stock_move(self, sm, lot=False): @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 @@ 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 @@ -467,16 +520,20 @@ 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 + 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 @@ def _onchange_operation_id(self): 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 @@ def _onchange_receipt_policy(self): @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 1ccf52cc5..aecb0cff3 100644 --- a/rma/models/stock.py +++ b/rma/models/stock.py @@ -34,3 +34,10 @@ def create(self, vals): 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 3111e137f..50ba21d80 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 a28106004..ffb37dcd0 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 e4fd4824c..5de6a5502 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 38093034f..08b20fb09 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 dfbac6140..54fae91dc 100644 --- a/rma/wizards/rma_make_picking.py +++ b/rma/wizards/rma_make_picking.py @@ -78,10 +78,12 @@ def _get_procurement_group_data(self, item): @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 f6def3b6a..8a33ca7b0 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 @@ def default_get(self, fields): 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 @@ def _prepare_supplier_rma(self, company): 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 @@ def _prepare_supplier_rma_line(self, rma, item): '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 @@ def make_supplier_rma(self): 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 1ba479214..25ad8e389 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 0dd045d27a4668e50de74de2dca315fbeff08fb6 Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Fri, 3 Aug 2018 12:48:52 +0200 Subject: [PATCH 039/175] [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 96659f5bb..e3b4c2e8c 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 fa0a76c00..4b1cc6c45 100755 --- a/rma/views/stock_warehouse.xml +++ b/rma/views/stock_warehouse.xml @@ -8,6 +8,9 @@ + + + From 6e9092a277e0bbf4bd1f3f70eaab17e3827076e9 Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Mon, 14 May 2018 17:05:57 +0200 Subject: [PATCH 040/175] [9.0][IMP] rma: tests moved to Savedpointcase and optimized (66% time reduction) --- rma/tests/__init__.py | 2 - rma/tests/test_rma.py | 539 ++++++++++++++++++++++++--------- rma/tests/test_rma_dropship.py | 110 ------- rma/tests/test_supplier_rma.py | 144 --------- 4 files changed, 390 insertions(+), 405 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 7262aab18..a708954ba 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 3548589a1..45e62abe1 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() - - 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( + @classmethod + def setUpClass(cls): + super(TestRma, cls).setUpClass() + + 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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, 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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, 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 @@ def _create_rma_from_move(self, products2move, type, partner, dropship, 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 @@ def _prepare_move(self, product, qty, src, dest, picking_in): } 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 @@ def test_rma_order_line(self): })._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 @@ def test_rma_order_line(self): 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 @@ def test_rma_order_line(self): 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 @@ def test_customer_rma(self): # 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 @@ def test_customer_rma(self): 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 @@ def test_customer_rma(self): '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 @@ def test_customer_rma(self): "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 dedb7a395..000000000 --- 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 6cc3c15c4..000000000 --- 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 361c7ad31aee0ccb0305876160185f92b6f2f7c8 Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 30 Jul 2018 18:36:49 +0200 Subject: [PATCH 041/175] [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 45e62abe1..e69bfe476 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -163,9 +163,6 @@ def _create_rma_from_move(cls, products2move, type, partner, dropship, 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 5de6a5502..ba8f9be73 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 25ad8e389..3fff3c39d 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 78b1f4c4e631b8b04e1065c3fa5b4300b9418276 Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 30 Jul 2018 18:37:14 +0200 Subject: [PATCH 042/175] [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 fceeaa940..03f7e3ba4 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -91,10 +91,10 @@ def _compute_qty_to_receive(self): 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 @@ def _compute_qty_supplier_rma(self): 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 @@ def _compute_rma_line_count(self): 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 @@ def _onchange_reference_move_id(self): 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 @@ def action_view_out_shipments(self): 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 6bd70721227aa5c261739a88853912de9c0955ef Mon Sep 17 00:00:00 2001 From: aheficent Date: Mon, 30 Jul 2018 18:37:35 +0200 Subject: [PATCH 043/175] [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 e69bfe476..eea469d09 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -23,10 +23,12 @@ def setUpClass(cls): '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 @@ def setUpClass(cls): 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 @@ def setUpClass(cls): 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 @@ def _create_rma_from_move(cls, products2move, type, partner, dropship, }) 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 @@ def _create_rma_from_move(cls, products2move, type, partner, dropship, 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 @@ def _prepare_move(cls, product, qty, src, dest, picking_in): } 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 @@ def test_01_rma_order_line(self): })._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() - - def test_02_customer_rma(self): - wizard = self.rma_make_picking.with_context({ - 'active_ids': self.rma_customer_id.rma_line_ids.ids, + 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(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") - - 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_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 = 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, - '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: + def test_03_dropship(cls): + for line in cls.rma_droship_id.rma_line_ids: line.action_rma_to_approve() line.action_rma_approve() - wizard = self.rma_make_picking.with_context({ + line._onchange_operation_id() + wizard = cls.rma_make_picking.with_context({ 'active_id': 1, - 'active_ids': supplier_rma.rma_line_ids.ids, + 'active_ids': cls.rma_droship_id.rma_line_ids.ids, 'active_model': 'rma.order.line', 'picking_type': 'incoming', }).create({}) - procurements = wizard._create_picking() - group_ids = set([proc.group_id.id for proc in procurements if - proc.group_id]) - domain = [('group_id', 'in', list(group_ids))] - picking = self.stockpicking.search(domain) - self.assertEquals(len(picking), 1, - "Incorrect number of pickings created") + 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 - self.assertEquals(len(moves), 3, - "Incorrect number of moves created") + 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 = 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") - - 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: + 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 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 e16a91f316473945abaf49d4cc3037a4c343f981 Mon Sep 17 00:00:00 2001 From: aheficent Date: Fri, 3 Aug 2018 11:01:09 +0200 Subject: [PATCH 044/175] [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 08b20fb09..092378148 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 cba83e69f01b9711ea8465041f30229b7feaee4e Mon Sep 17 00:00:00 2001 From: aheficent Date: Fri, 3 Aug 2018 11:24:58 +0200 Subject: [PATCH 045/175] [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 99e6a6645..ecefd303e 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 da09e3279..27000c345 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 6a52a708585825ef06e9277ac2753f70f3b4d1cd Mon Sep 17 00:00:00 2001 From: aaron Date: Thu, 24 May 2018 11:50:28 +0200 Subject: [PATCH 046/175] [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 50ba21d80..77465ab88 100644 --- a/rma/models/stock_warehouse.py +++ b/rma/models/stock_warehouse.py @@ -73,6 +73,7 @@ def write(self, vals): '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 306ff7586df82389504143dc7aecaea7f3e33842 Mon Sep 17 00:00:00 2001 From: aheficent Date: Fri, 24 Aug 2018 10:18:30 +0200 Subject: [PATCH 047/175] [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 d18758210ef9ea0ddbc1076fc0a04eb0f83fb6ae Mon Sep 17 00:00:00 2001 From: aheficent Date: Thu, 4 Oct 2018 12:10:51 +0200 Subject: [PATCH 048/175] [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 3fff3c39d..0dff174e8 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 82e90ece75ea2696a8466c8fb27011f056e350e5 Mon Sep 17 00:00:00 2001 From: aaron Date: Fri, 25 May 2018 15:34:39 +0200 Subject: [PATCH 049/175] [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 7335d0d6b..a3538425a 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 000000000..07a2a1106 --- /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 000000000..997dc28fc --- /dev/null +++ b/rma/report/rma_report_templates.xml @@ -0,0 +1,99 @@ + + + + + + + From 5658fcc32f5416422b489341c9a826296c7d5832 Mon Sep 17 00:00:00 2001 From: aheficent Date: Thu, 4 Oct 2018 16:26:45 +0200 Subject: [PATCH 050/175] [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 a3538425a..662d5b15e 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 997dc28fc..698d60f51 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 1434cc392..6f089e84f 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 c8972eb684ff41c1c262b06a782ca6718e06986d Mon Sep 17 00:00:00 2001 From: ahenriquez Date: Fri, 3 Jan 2020 13:41:25 +0100 Subject: [PATCH 077/175] [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 6a3144d20..9771691c0 100644 --- a/rma/report/rma_report_templates.xml +++ b/rma/report/rma_report_templates.xml @@ -100,10 +100,10 @@ - + - +