[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
This commit is contained in:
aheficent
2017-08-16 12:52:35 +02:00
committed by ahenriquez
parent 539be323ef
commit 3551ce078a
16 changed files with 459 additions and 124 deletions

View File

@@ -3,7 +3,6 @@
<record id="rma_operation_customer_replace" model="rma.operation"> <record id="rma_operation_customer_replace" model="rma.operation">
<field name="name">Replace After Receive</field> <field name="name">Replace After Receive</field>
<field name="code">RPLC</field> <field name="code">RPLC</field>
<field name="refund_policy">no</field>
<field name="receipt_policy">ordered</field> <field name="receipt_policy">ordered</field>
<field name="delivery_policy">received</field> <field name="delivery_policy">received</field>
<field name="type">customer</field> <field name="type">customer</field>
@@ -14,7 +13,6 @@
<record id="rma_operation_supplier_replace" model="rma.operation"> <record id="rma_operation_supplier_replace" model="rma.operation">
<field name="name">Replace</field> <field name="name">Replace</field>
<field name="code">RPLS</field> <field name="code">RPLS</field>
<field name="refund_policy">no</field>
<field name="receipt_policy">ordered</field> <field name="receipt_policy">ordered</field>
<field name="delivery_policy">ordered</field> <field name="delivery_policy">ordered</field>
<field name="type">supplier</field> <field name="type">supplier</field>
@@ -22,30 +20,9 @@
<field name="out_route_id" ref="rma.route_rma_supplier"/> <field name="out_route_id" ref="rma.route_rma_supplier"/>
</record> </record>
<record id="rma_operation_customer_refund" model="rma.operation">
<field name="name">Refund before receive</field>
<field name="code">RFC</field>
<field name="refund_policy">ordered</field>
<field name="receipt_policy">no</field>
<field name="delivery_policy">no</field>
<field name="type">customer</field>
<field name="in_route_id" ref="rma.route_rma_customer"/>
</record>
<record id="rma_operation_supplier_refund" model="rma.operation">
<field name="name">Refund only</field>
<field name="code">RFS</field>
<field name="refund_policy">ordered</field>
<field name="receipt_policy">no</field>
<field name="delivery_policy">no</field>
<field name="type">supplier</field>
<field name="out_route_id" ref="rma.route_rma_supplier"/>
</record>
<record id="rma_operation_ds_replace" model="rma.operation"> <record id="rma_operation_ds_replace" model="rma.operation">
<field name="name">Replace deliver to vendor</field> <field name="name">Replace deliver to vendor</field>
<field name="code">DSRPLB</field> <field name="code">DSRPLB</field>
<field name="refund_policy">no</field>
<field name="receipt_policy">ordered</field> <field name="receipt_policy">ordered</field>
<field name="delivery_policy">no</field> <field name="delivery_policy">no</field>
<field name="type">customer</field> <field name="type">customer</field>
@@ -55,7 +32,6 @@
<record id="rma_operation_ds_replace_customer" model="rma.operation"> <record id="rma_operation_ds_replace_customer" model="rma.operation">
<field name="name">Replace receive in vendor</field> <field name="name">Replace receive in vendor</field>
<field name="code">DSRPLV</field> <field name="code">DSRPLV</field>
<field name="refund_policy">no</field>
<field name="receipt_policy">no</field> <field name="receipt_policy">no</field>
<field name="delivery_policy">received</field> <field name="delivery_policy">received</field>
<field name="type">customer</field> <field name="type">customer</field>
@@ -65,7 +41,6 @@
<record id="rma_operation_ds_replace_supplier" model="rma.operation"> <record id="rma_operation_ds_replace_supplier" model="rma.operation">
<field name="name">Replace deliver to customer</field> <field name="name">Replace deliver to customer</field>
<field name="code">DSRPC</field> <field name="code">DSRPC</field>
<field name="refund_policy">no</field>
<field name="receipt_policy">no</field> <field name="receipt_policy">no</field>
<field name="delivery_policy">received</field> <field name="delivery_policy">received</field>
<field name="type">supplier</field> <field name="type">supplier</field>

View File

@@ -8,7 +8,9 @@ from openerp import fields, models
class ProductTemplate(models.Model): class ProductTemplate(models.Model):
_inherit = 'product.template' _inherit = 'product.template'
rma_operation_id = fields.Many2one( rma_customer_operation_id = fields.Many2one(
comodel_name="rma.operation", string="RMA Operation") 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( rma_approval_policy = fields.Selection(
related="categ_id.rma_approval_policy", readonly=True) related="categ_id.rma_approval_policy", readonly=True)

View File

@@ -16,5 +16,7 @@ class ProductCategory(models.Model):
"products within categories with this policy.\n" "products within categories with this policy.\n"
"* Two steps: A RMA containing a product within a category with " "* Two steps: A RMA containing a product within a category with "
"this policy will request the RMA manager approval.") "this policy will request the RMA manager approval.")
rma_operation_id = fields.Many2one( rma_customer_operation_id = fields.Many2one(
comodel_name="rma.operation", string="RMA Operation") comodel_name="rma.operation", string="Default RMA Customer Operation")
rma_supplier_operation_id = fields.Many2one(
comodel_name="rma.operation", string="Default RMA Supplier Operation")

View File

@@ -26,10 +26,7 @@ class RmaOperation(models.Model):
name = fields.Char('Description', required=True) name = fields.Char('Description', required=True)
code = fields.Char('Code', required=True) code = fields.Char('Code', required=True)
refund_policy = fields.Selection([ active = fields.Boolean(string='Active', default=True)
('no', 'No refund'), ('ordered', 'Based on Ordered Quantities'),
('received', 'Based on Received Quantities')], string="Refund Policy",
default='no')
receipt_policy = fields.Selection([ receipt_policy = fields.Selection([
('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'), ('no', 'Not required'), ('ordered', 'Based on Ordered Quantities'),
('received', 'Based on Delivered Quantities')], ('received', 'Based on Delivered Quantities')],
@@ -58,6 +55,6 @@ class RmaOperation(models.Model):
'stock.location', 'Send To This Company Location') 'stock.location', 'Send To This Company Location')
type = fields.Selection([ type = fields.Selection([
('customer', 'Customer'), ('supplier', 'Supplier')], ('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_line_ids = fields.One2many('rma.order.line', 'operation_id',
'RMA lines') 'RMA lines')

View File

@@ -3,6 +3,7 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) # 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 datetime import datetime
class RmaOrder(models.Model): class RmaOrder(models.Model):
@@ -38,8 +39,12 @@ class RmaOrder(models.Model):
@api.multi @api.multi
def _compute_line_count(self): def _compute_line_count(self):
self.ensure_one() for rec in self:
self.line_count = len(self._get_valid_lines()) rec.line_count = len(rec._get_valid_lines())
@api.model
def _default_date_rma(self):
return datetime.now()
name = fields.Char( name = fields.Char(
string='Order Number', index=True, readonly=True, string='Order Number', index=True, readonly=True,
@@ -55,8 +60,9 @@ class RmaOrder(models.Model):
state = fields.Selection([('draft', 'Draft'), ('to_approve', 'To Approve'), state = fields.Selection([('draft', 'Draft'), ('to_approve', 'To Approve'),
('approved', 'Approved'), ('approved', 'Approved'),
('done', 'Done')], string='State', index=True, ('done', 'Done')], string='State', index=True,
default='draft') default='draft')
date_rma = fields.Datetime(string='Order Date', index=True, copy=False) date_rma = fields.Datetime(string='Order Date', index=True,
default=_default_date_rma)
partner_id = fields.Many2one('res.partner', string='Partner', partner_id = fields.Many2one('res.partner', string='Partner',
required=True, readonly=True, required=True, readonly=True,
states={'draft': [('readonly', False)]}) states={'draft': [('readonly', False)]})
@@ -72,11 +78,9 @@ class RmaOrder(models.Model):
out_shipment_count = fields.Integer(compute=_compute_out_shipment_count, out_shipment_count = fields.Integer(compute=_compute_out_shipment_count,
string='# of Outgoing Shipments') string='# of Outgoing Shipments')
line_count = fields.Integer(compute=_compute_line_count, line_count = fields.Integer(compute=_compute_line_count,
string='# of Outgoing Shipments', string='# of Outgoing Shipments')
copy=False)
supplier_line_count = fields.Integer(compute=_compute_supplier_line_count, supplier_line_count = fields.Integer(compute=_compute_supplier_line_count,
string='# of Outgoing Shipments', string='# of Outgoing Shipments')
copy=False)
company_id = fields.Many2one('res.company', string='Company', company_id = fields.Many2one('res.company', string='Company',
required=True, default=lambda self: required=True, default=lambda self:
self.env.user.company_id) self.env.user.company_id)
@@ -175,8 +179,8 @@ class RmaOrder(models.Model):
def _get_valid_lines(self): def _get_valid_lines(self):
""":return: A recordset of rma lines. """:return: A recordset of rma lines.
""" """
self.ensure_one() for rec in self:
return self.rma_line_ids return rec.rma_line_ids
@api.multi @api.multi
def action_view_lines(self): def action_view_lines(self):
@@ -205,7 +209,7 @@ class RmaOrder(models.Model):
action = self.env.ref('rma.action_rma_supplier_lines') action = self.env.ref('rma.action_rma_supplier_lines')
result = action.read()[0] result = action.read()[0]
lines = self.rma_line_ids 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 # choose the view_mode accordingly
if len(related_lines) != 1: if len(related_lines) != 1:
result['domain'] = "[('id', 'in', " + \ result['domain'] = "[('id', 'in', " + \

View File

@@ -308,8 +308,12 @@ class RmaOrderLine(models.Model):
self.product_qty = 1 self.product_qty = 1
self.uom_id = self.product_id.uom_id.id self.uom_id = self.product_id.uom_id.id
self.price_unit = self.product_id.standard_price self.price_unit = self.product_id.standard_price
self.operation_id = self.product_id.rma_operation_id or \ if self.type == 'customer':
self.product_id.categ_id.rma_operation_id 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 return result
@api.onchange('operation_id') @api.onchange('operation_id')

View File

@@ -2,3 +2,5 @@
# © 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) # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from . import test_rma from . import test_rma
from . import test_supplier_rma
from . import test_rma_dropship

View File

@@ -13,61 +13,95 @@ class TestRma(common.TransactionCase):
super(TestRma, self).setUp() super(TestRma, self).setUp()
self.rma_make_picking = self.env['rma_make_picking.wizard'] 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.rma_add_stock_move = self.env['rma_add_stock_move']
self.stockpicking = self.env['stock.picking'] self.stockpicking = self.env['stock.picking']
self.rma = self.env['rma.order'] self.rma = self.env['rma.order']
self.rma_line = self.env['rma.order.line'] self.rma_line = self.env['rma.order.line']
self.rma_op = self.env['rma.operation'] 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_id = self.env.ref('product.product_product_4')
self.product_1 = self.env.ref('product.product_product_25') self.product_1 = self.env.ref('product.product_product_25')
self.product_2 = self.env.ref('product.product_product_30') self.product_2 = self.env.ref('product.product_product_30')
self.product_3 = self.env.ref('product.product_product_33') self.product_3 = self.env.ref('product.product_product_33')
self.uom_unit = self.env.ref('product.product_uom_unit') self.uom_unit = self.env.ref('product.product_uom_unit')
# assign an operation # assign an operation
self.product_1.write({'rma_operation_id': self.rma_op_id.id}) self.product_1.write(
self.product_2.write({'rma_operation_id': self.rma_op_id.id}) {'rma_customer_operation_id': self.rma_cust_replace_op_id.id,
self.product_3.write({'rma_operation_id': self.rma_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.partner_id = self.env.ref('base.res_partner_12')
self.stock_location = self.env.ref('stock.stock_location_stock') self.stock_location = self.env.ref('stock.stock_location_stock')
self.stock_rma_location = self.env.ref('rma.location_rma') self.stock_rma_location = self.env.ref('rma.location_rma')
self.customer_location = self.env.ref( self.customer_location = self.env.ref(
'stock.stock_location_customers') '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')
self.product_uom_id = self.env.ref('product.product_uom_unit')
moves = []
products2move = [(self.product_1, 3), (self.product_2, 5), products2move = [(self.product_1, 3), (self.product_2, 5),
(self.product_3, 2)] (self.product_3, 2)]
for item in products2move: self.rma_customer_id = self._create_rma_from_move(
move_values = self._prepare_move(item[0], item[1]) products2move, 'customer', self.env.ref('base.res_partner_2'),
moves.append(self.env['stock.move'].create(move_values)) 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 # Create the RMA from the stock_move
self.rma_id = self.rma.create( rma_id = self.rma.create(
{ {
'reference': '0001', 'reference': '0001',
'type': 'customer', 'type': type,
'partner_id': self.env.ref('base.res_partner_2').id 'partner_id': partner.id,
'company_id': self.env.ref('base.main_company').id
}) })
for move in moves: for move in moves:
data = self.rma_add_stock_move.with_context( if type == 'customer':
{'stock_move_id': move.id} wizard = self.rma_add_stock_move.with_context(
)._prepare_rma_line_from_stock_move(move) {'stock_move_id': move.id, 'customer': True,
operation = self.rma_op.browse(data['operation_id']) 'active_ids': rma_id.id,
data.update( 'active_model': 'rma.order',
rma_id=self.rma_id.id, }
receipt_policy=operation.receipt_policy, ).create({})
delivery_policy=operation.delivery_policy, data = wizard._prepare_rma_line_from_stock_move(move)
in_warehouse_id=operation.in_warehouse_id.id, else:
out_warehouse_id=operation.out_warehouse_id.id, wizard = self.rma_add_stock_move.with_context(
location_id=self.stock_rma_location.id, {'stock_move_id': move.id, 'supplier': True,
in_route_id=operation.in_route_id.id, 'active_ids': rma_id.id,
out_route_id=operation.out_route_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) self.rma_line.create(data)
# approve the RMA # approve the RMA
self.rma_id.action_rma_to_approve() rma_id.action_rma_to_approve()
self.rma_id.action_rma_approve() rma_id.action_rma_approve()
return rma_id
def _prepare_move(self, product, qty): def _prepare_move(self, product, qty, src, dest):
res = { res = {
'product_id': product.id, 'product_id': product.id,
'name': product.partner_ref, 'name': product.partner_ref,
@@ -75,14 +109,14 @@ class TestRma(common.TransactionCase):
'product_uom': self.product_uom_id.id or product.uom_id.id, 'product_uom': self.product_uom_id.id or product.uom_id.id,
'product_uom_qty': qty, 'product_uom_qty': qty,
'origin': 'Test RMA', 'origin': 'Test RMA',
'location_id': self.stock_location.id, 'location_id': src.id,
'location_dest_id': self.customer_location.id, 'location_dest_id': dest.id,
} }
return res return res
def test_00_receive_items(self): def test_customer_rma(self):
wizard = self.rma_make_picking.with_context({ 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', 'active_model': 'rma.order.line',
'picking_type': 'incoming', 'picking_type': 'incoming',
'active_id': 1 'active_id': 1
@@ -97,7 +131,7 @@ class TestRma(common.TransactionCase):
moves = picking.move_lines moves = picking.move_lines
self.assertEquals(len(moves), 3, self.assertEquals(len(moves), 3,
"Incorrect number of moves created") "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 # common qtys for all products
self.assertEquals(line.qty_received, 0, self.assertEquals(line.qty_received, 0,
"Wrong qty received") "Wrong qty received")
@@ -125,7 +159,7 @@ class TestRma(common.TransactionCase):
"Wrong qty incoming") "Wrong qty incoming")
picking.action_assign() picking.action_assign()
picking.do_transfer() 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, self.assertEquals(line.qty_to_receive, 0,
"Wrong qty to_receive") "Wrong qty to_receive")
self.assertEquals(line.qty_incoming, 0, self.assertEquals(line.qty_incoming, 0,
@@ -152,7 +186,7 @@ class TestRma(common.TransactionCase):
wizard = self.rma_make_picking.with_context({ wizard = self.rma_make_picking.with_context({
'active_id': 1, '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', 'active_model': 'rma.order.line',
'picking_type': 'outgoing', 'picking_type': 'outgoing',
}).create({}) }).create({})
@@ -167,7 +201,7 @@ class TestRma(common.TransactionCase):
moves = picking_out.move_lines moves = picking_out.move_lines
self.assertEquals(len(moves), 3, self.assertEquals(len(moves), 3,
"Incorrect number of moves created") "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, self.assertEquals(line.qty_to_receive, 0,
"Wrong qty to receive") "Wrong qty to receive")
self.assertEquals(line.qty_incoming, 0, self.assertEquals(line.qty_incoming, 0,
@@ -197,7 +231,7 @@ class TestRma(common.TransactionCase):
"Wrong qty outgoing") "Wrong qty outgoing")
picking_out.action_assign() picking_out.action_assign()
picking_out.do_transfer() 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, self.assertEquals(line.qty_to_receive, 0,
"Wrong qty to receive") "Wrong qty to receive")
self.assertEquals(line.qty_incoming, 0, self.assertEquals(line.qty_incoming, 0,
@@ -221,4 +255,6 @@ class TestRma(common.TransactionCase):
"Wrong qty received") "Wrong qty received")
self.assertEquals(line.qty_delivered, 2, self.assertEquals(line.qty_delivered, 2,
"Wrong qty delivered") "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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -8,8 +8,11 @@
<field name="inherit_id" ref="product.product_category_form_view" /> <field name="inherit_id" ref="product.product_category_form_view" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="type" position="after"> <field name="type" position="after">
<field name="rma_approval_policy"/> <group name="rma">
<field name="rma_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/> <field name="rma_approval_policy" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
<field name="rma_customer_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
<field name="rma_supplier_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
</group>
</field> </field>
</field> </field>
</record> </record>
@@ -22,7 +25,8 @@
<group name="inventory" position="inside"> <group name="inventory" position="inside">
<group name="rma" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"> <group name="rma" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user">
<field name="rma_approval_policy"/> <field name="rma_approval_policy"/>
<field name="rma_operation_id"/> <field name="rma_customer_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
<field name="rma_supplier_operation_id" groups="rma.group_rma_customer_user,rma.group_rma_supplier_user"/>
</group> </group>
</group> </group>
</field> </field>

View File

@@ -6,6 +6,7 @@
<field name="model">rma.operation</field> <field name="model">rma.operation</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="RMA Operations"> <tree string="RMA Operations">
<field name="active" invisible="1"/>
<field name="code"/> <field name="code"/>
<field name="name"/> <field name="name"/>
<field name="receipt_policy"/> <field name="receipt_policy"/>
@@ -25,6 +26,7 @@
<field name="code"/> <field name="code"/>
<field name="name"/> <field name="name"/>
<field name="type"/> <field name="type"/>
<field name="active"/>
</group> </group>
<group name="policies" <group name="policies"
string="Policies"> string="Policies">
@@ -50,20 +52,39 @@
</field> </field>
</record> </record>
<record id="action_rma_operation" model="ir.actions.act_window"> <record id="action_rma_operation_customer" model="ir.actions.act_window">
<field name="name">Operations</field> <field name="name">Customer Operations</field>
<field name="res_model">rma.operation</field> <field name="res_model">rma.operation</field>
<field name="view_type">form</field> <field name="view_type">form</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
<field name="context">{'default_type': "customer"}</field>
<field name="domain">[('type','=', 'customer')]</field>
<field name="view_id" ref="rma_operation_tree"/> <field name="view_id" ref="rma_operation_tree"/>
</record> </record>
<menuitem id="menu_rma_operation" <record id="action_rma_operation_supplier" model="ir.actions.act_window">
name="Operations" <field name="name">Supplier Operations</field>
<field name="res_model">rma.operation</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'default_type': "supplier"}</field>
<field name="domain">[('type','=', 'supplier')]</field>
<field name="view_id" ref="rma_operation_tree"/>
</record>
<menuitem id="menu_rma_operation_customer"
name="Customer Operations"
groups="rma.group_rma_manager" groups="rma.group_rma_manager"
sequence="35" sequence="35"
parent="rma.menu_rma_config" parent="rma.menu_rma_config"
action="action_rma_operation"/> action="action_rma_operation_customer"/>
<menuitem id="menu_rma_operation_supplier"
name="Supplier Operations"
groups="rma.group_rma_manager"
sequence="40"
parent="rma.menu_rma_config"
action="action_rma_operation_supplier"/>
</data> </data>
</odoo> </odoo>

View File

@@ -332,8 +332,7 @@
<field name="name">Customer RMA Lines</field> <field name="name">Customer RMA Lines</field>
<field name="res_model">rma.order.line</field> <field name="res_model">rma.order.line</field>
<field name="domain">[('state','in', ['approved', 'done']), <field name="domain">[('state','in', ['approved', 'done']),
('type','=', 'customer'), ('type','=', 'customer')
('customer_to_supplier','=', False)
]</field> ]</field>
<field name="context">{"search_default_assigned_to":uid}</field> <field name="context">{"search_default_assigned_to":uid}</field>
<field name="view_type">form</field> <field name="view_type">form</field>

View File

@@ -2,7 +2,7 @@
# © 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) # 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 from openerp.exceptions import ValidationError
@@ -40,14 +40,18 @@ class RmaAddStockMove(models.TransientModel):
domain="[('state', '=', 'done')]") domain="[('state', '=', 'done')]")
def _prepare_rma_line_from_stock_move(self, sm, lot=False): def _prepare_rma_line_from_stock_move(self, sm, lot=False):
operation = sm.product_id.rma_operation_id or \ if self.env.context.get('customer'):
sm.product_id.categ_id.rma_operation_id 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 = { data = {
'reference_move_id': sm.id, 'reference_move_id': sm.id,
'product_id': sm.product_id.id, 'product_id': sm.product_id.id,
'lot_id': lot and lot.id or False, 'lot_id': lot and lot.id or False,
'name': sm.product_id.name_template, '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, 'uom_id': sm.product_uom.id,
'operation_id': operation.id, 'operation_id': operation.id,
'product_qty': sm.product_uom_qty, 'product_qty': sm.product_uom_qty,
@@ -64,20 +68,26 @@ class RmaAddStockMove(models.TransientModel):
[('rma_selectable', '=', True)], limit=1) [('rma_selectable', '=', True)], limit=1)
if not route: 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( data.update(
{'in_route_id': operation.in_route_id.id, {'receipt_policy': operation.receipt_policy,
'out_route_id': operation.out_route_id.id,
'receipt_policy': operation.receipt_policy,
'operation_id': operation.id, '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 return data
@api.model @api.model

View File

@@ -4,6 +4,7 @@
import openerp.addons.decimal_precision as dp import openerp.addons.decimal_precision as dp
from openerp import _, api, exceptions, fields, models from openerp import _, api, exceptions, fields, models
from openerp.exceptions import ValidationError
class RmaLineMakeSupplierRma(models.TransientModel): class RmaLineMakeSupplierRma(models.TransientModel):
@@ -48,7 +49,10 @@ class RmaLineMakeSupplierRma(models.TransientModel):
for line in lines: for line in lines:
items.append([0, 0, self._prepare_item(line)]) items.append([0, 0, self._prepare_item(line)])
suppliers = lines.mapped('supplier_address_id') 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 res['partner_id'] = suppliers.id
else: else:
raise exceptions.Warning( raise exceptions.Warning(
@@ -73,7 +77,8 @@ class RmaLineMakeSupplierRma(models.TransientModel):
def _prepare_supplier_rma_line(self, rma, item): def _prepare_supplier_rma_line(self, rma, item):
operation = self.env['rma.operation'].search( operation = self.env['rma.operation'].search(
[('type', '=', 'supplier')], limit=1) [('type', '=', 'supplier')], limit=1)
return { data = {
'type': 'supplier',
'origin': item.line_id.rma_id.name, 'origin': item.line_id.rma_id.name,
'delivery_address_id': 'delivery_address_id':
item.line_id.delivery_address_id.id, item.line_id.delivery_address_id.id,
@@ -81,20 +86,38 @@ class RmaLineMakeSupplierRma(models.TransientModel):
'customer_rma_id': item.line_id.id, 'customer_rma_id': item.line_id.id,
'product_qty': item.product_qty, 'product_qty': item.product_qty,
'rma_id': rma.id, 'rma_id': rma.id,
'uom_id': item.uom_id.id,
'operation_id': operation.id, 'operation_id': operation.id,
'receipt_policy': operation.receipt_policy, 'receipt_policy': operation.receipt_policy,
'delivery_policy': operation.delivery_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, '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 @api.multi
def make_supplier_rma(self): def make_supplier_rma(self):
res = [] self = self.with_context(supplier=True, customer=False)
rma_obj = self.env['rma.order'] rma_obj = self.env['rma.order']
rma_line_obj = self.env['rma.order.line'] rma_line_obj = self.env['rma.order.line']
rma = False rma = False
@@ -113,16 +136,15 @@ class RmaLineMakeSupplierRma(models.TransientModel):
rma_line_data = self._prepare_supplier_rma_line(rma, item) rma_line_data = self._prepare_supplier_rma_line(rma, item)
rma_line_obj.create(rma_line_data) rma_line_obj.create(rma_line_data)
res.append(rma.id)
return { return {
'domain': "[('id','in', ["+','.join(map(str, res))+"])]",
'name': _('Supplier RMA'), 'name': _('Supplier RMA'),
'view_type': 'form', 'view_type': 'form',
'view_mode': 'tree,form', 'view_mode': 'form',
'res_model': 'rma.order', 'res_model': 'rma.order',
'view_id': False, 'view_id': False,
'context': {'supplier': 1}, 'res_id': rma.id,
'context': {'supplier': True, 'customer': False},
'type': 'ir.actions.act_window' 'type': 'ir.actions.act_window'
} }
@@ -137,7 +159,8 @@ class RmaLineMakeRmaOrderItem(models.TransientModel):
readonly=True) readonly=True)
line_id = fields.Many2one('rma.order.line', line_id = fields.Many2one('rma.order.line',
string='RMA Line', string='RMA Line',
required=True) required=True,
ondelete='cascade')
rma_id = fields.Many2one('rma.order', related='line_id.rma_id', rma_id = fields.Many2one('rma.order', related='line_id.rma_id',
string='RMA Order', readonly=True) string='RMA Order', readonly=True)
product_id = fields.Many2one('product.product', product_id = fields.Many2one('product.product',

View File

@@ -13,7 +13,7 @@
<separator string="Existing Supplier RMA to update:"/> <separator string="Existing Supplier RMA to update:"/>
<newline/> <newline/>
<group> <group>
<field name="supplier_rma_id"/> <field name="supplier_rma_id" domain="[('partner_id', '=', partner_id)]"/>
</group> </group>
<newline/> <newline/>
<separator <separator