From 2b76897d216e8397076779e18e452d02fd225c1a Mon Sep 17 00:00:00 2001 From: Cyril Gaudin Date: Tue, 3 May 2016 09:46:54 +0200 Subject: [PATCH] crm_claim_rma: use procurement for delivery --- crm_claim_rma/models/__init__.py | 1 + crm_claim_rma/models/crm_claim.py | 18 +++- crm_claim_rma/models/procurement_group.py | 11 +++ crm_claim_rma/tests/test_picking_creation.py | 54 ++++++------ crm_claim_rma/wizards/claim_make_picking.py | 92 +++++++++++--------- crm_claim_rma/wizards/claim_make_picking.xml | 5 +- 6 files changed, 108 insertions(+), 73 deletions(-) create mode 100644 crm_claim_rma/models/procurement_group.py diff --git a/crm_claim_rma/models/__init__.py b/crm_claim_rma/models/__init__.py index bd35d8bb..a44e5bde 100644 --- a/crm_claim_rma/models/__init__.py +++ b/crm_claim_rma/models/__init__.py @@ -28,6 +28,7 @@ from . import claim_line from . import crm_claim from . import invoice_no_date from . import product_no_supplier +from . import procurement_group from . import stock_move from . import stock_picking from . import substate_substate diff --git a/crm_claim_rma/models/crm_claim.py b/crm_claim_rma/models/crm_claim.py index ec8824fd..64be490d 100644 --- a/crm_claim_rma/models/crm_claim.py +++ b/crm_claim_rma/models/crm_claim.py @@ -40,6 +40,20 @@ class CrmClaim(models.Model): _('There is no warehouse for the current user\'s company.')) return wh + def _get_picking_ids(self): + """ Search all stock_picking associated with this claim. + + Either directly with claim_id in stock_picking or through a + procurement_group. + """ + picking_model = self.env['stock.picking'] + for claim in self: + claim.picking_ids = picking_model.search([ + '|', + ('claim_id', '=', claim.id), + ('group_id.claim_id', '=', claim.id) + ]) + @api.multi def name_get(self): res = [] @@ -61,7 +75,9 @@ class CrmClaim(models.Model): real_cost = fields.Float() invoice_ids = fields.One2many('account.invoice', 'claim_id', 'Refunds', copy=False) - picking_ids = fields.One2many('stock.picking', 'claim_id', 'RMA', + picking_ids = fields.One2many('stock.picking', + compute=_get_picking_ids, + string='RMA', copy=False) invoice_id = fields.Many2one('account.invoice', string='Invoice', help='Related original Cusotmer invoice') diff --git a/crm_claim_rma/models/procurement_group.py b/crm_claim_rma/models/procurement_group.py new file mode 100644 index 00000000..a7b81d77 --- /dev/null +++ b/crm_claim_rma/models/procurement_group.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# © 2016 Cyril Gaudin (Camptocamp) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import fields, models + + +class ProcurementGroup(models.Model): + _inherit = 'procurement.group' + + claim_id = fields.Many2one('crm.claim', 'Claim') diff --git a/crm_claim_rma/tests/test_picking_creation.py b/crm_claim_rma/tests/test_picking_creation.py index f0bdcf6a..c884da8c 100644 --- a/crm_claim_rma/tests/test_picking_creation.py +++ b/crm_claim_rma/tests/test_picking_creation.py @@ -21,6 +21,7 @@ # ############################################################################## from openerp.tests import common +from openerp.tools.safe_eval import safe_eval class TestPickingCreation(common.TransactionCase): @@ -86,10 +87,11 @@ class TestPickingCreation(common.TransactionCase): "Incorrect destination location") def test_01_new_delivery(self): - """Test wizard creates a correct picking for a new delivery - + """Test wizard creates and runs a procurement for a new delivery """ + group_model = self.env['procurement.group'] + wizardchangeproductqty = self.env['stock.change.product.qty'] wizard_chg_qty = wizardchangeproductqty.with_context({ 'active_id': self.product_id.id, @@ -100,6 +102,9 @@ class TestPickingCreation(common.TransactionCase): wizard_chg_qty.change_product_qty() + self.assertEqual(0, group_model.search_count([ + ('claim_id', '=', self.claim_id.id) + ])) wizard = self.wizard_make_picking.with_context({ 'active_id': self.claim_id.id, 'partner_id': self.partner_id.id, @@ -108,29 +113,37 @@ class TestPickingCreation(common.TransactionCase): }).create({}) wizard.action_create_picking() + procurement_group = group_model.search([ + ('claim_id', '=', self.claim_id.id) + ]) + self.assertEqual(1, len(procurement_group)) + self.assertEquals(len(self.claim_id.picking_ids), 1, "Incorrect number of pickings created") - picking = self.claim_id.picking_ids[0] - self.assertEquals(picking.location_id, self.warehouse_id.lot_stock_id, + # Should have 1 procurement by product: + # One on Customer location and one on output + self.assertEqual(3, len(procurement_group.procurement_ids)) + + # And 2 pickings + self.assertEqual(1, len(self.claim_id.picking_ids)) + + self.assertEquals(self.warehouse_id.lot_stock_id, + self.claim_id.picking_ids.location_id, "Incorrect source location") - self.assertEquals(picking.location_dest_id, self.customer_location_id, + self.assertEquals(self.customer_location_id, + self.claim_id.picking_ids.location_dest_id, "Incorrect destination location") def test_02_new_product_return(self): """Test wizard creates a correct picking for product return """ - company = self.env.ref('base.main_company') - warehouse_obj = self.env['stock.warehouse'] - warehouse_rec = \ - warehouse_obj.search([('company_id', - '=', company.id)])[0] wizard = self.wizard_make_picking.with_context({ 'active_id': self.claim_id.id, 'partner_id': self.partner_id.id, 'warehouse_id': self.warehouse_id.id, - 'picking_type': warehouse_rec.in_type_id.id, + 'picking_type': 'in', }).create({}) wizard.action_create_picking() @@ -144,23 +157,6 @@ class TestPickingCreation(common.TransactionCase): self.warehouse_id.lot_stock_id, "Incorrect destination location") - def create_invoice(self): - sale_order_id = self.env['sale.order'].create({ - 'partner_id': self.ref('base.res_partner_9'), - 'client_order_ref': 'TEST_SO', - 'order_policy': 'manual', - 'order_line': [(0, 0, { - 'product_id': self.ref('product.product_product_8'), - 'product_uom_qty': 2 - })] - }) - sale_order_id.action_button_confirm() - sale_order_id.action_invoice_create() - self.assertTrue(sale_order_id.invoice_ids) - invoice_id = sale_order_id.invoice_ids - invoice_id.signal_workflow('invoice_open') - return invoice_id - def test_03_invoice_refund(self): claim_id = self.env['crm.claim'].browse( self.ref('crm_claim.crm_claim_6')) @@ -185,7 +181,7 @@ class TestPickingCreation(common.TransactionCase): self.assertTrue(res) self.assertEquals(res['res_model'], 'account.invoice') - self.assertEquals(eval(res['context'])['type'], 'out_refund') + self.assertEquals(safe_eval(res['context'])['type'], 'out_refund') def test_04_display_name(self): """ diff --git a/crm_claim_rma/wizards/claim_make_picking.py b/crm_claim_rma/wizards/claim_make_picking.py index 60bf4157..a174b6a4 100644 --- a/crm_claim_rma/wizards/claim_make_picking.py +++ b/crm_claim_rma/wizards/claim_make_picking.py @@ -55,13 +55,8 @@ class ClaimMakePicking(models.TransientModel): def _default_claim_line_source_location_id(self): picking_type = self.env.context.get('picking_type') partner_id = self.env.context.get('partner_id') - warehouse_id = self.env.context.get('warehouse_id') - if picking_type == 'out' and warehouse_id: - return self.env['stock.warehouse'].browse( - warehouse_id).lot_stock_id - - if partner_id: + if picking_type == 'in' and partner_id: partner = self.env['res.partner'].browse(partner_id) return partner.property_stock_customer @@ -78,11 +73,6 @@ class ClaimMakePicking(models.TransientModel): picking_type = self.env.context.get('picking_type') partner_id = self.env.context.get('partner_id') - if isinstance(picking_type, int): - picking_obj = self.env['stock.picking.type'] - return picking_obj.browse(picking_type)\ - .default_location_dest_id - if picking_type == 'out' and partner_id: return self.env['res.partner'].browse( partner_id).property_stock_customer @@ -100,13 +90,6 @@ class ClaimMakePicking(models.TransientModel): # TODO use custom states to show buttons of this wizard or not instead # of raise an error picking_type = self.env.context.get('picking_type') - if isinstance(picking_type, int): - picking_obj = self.env['stock.picking.type'] - if picking_obj.browse(picking_type).code == 'incoming': - picking_type = 'in' - else: - picking_type = 'out' - move_field = 'move_in_id' if picking_type == 'in' else 'move_out_id' domain = [('claim_id', '=', self.env.context['active_id'])] lines = self.env['claim.line'].\ @@ -121,8 +104,14 @@ class ClaimMakePicking(models.TransientModel): _('A picking has already been created for this claim.')) return lines + delivery_warehouse_id = fields.Many2one( + 'stock.warehouse', string='Source Warehouse', + default=lambda self: self.env.context.get('warehouse_id'), + help="Warehouse where to take the replacement products for customers.", + ) + claim_line_source_location_id = fields.Many2one( - 'stock.location', string='Source Location', required=True, + 'stock.location', string='Source Location', default=_default_claim_line_source_location_id, help="Location where the returned products are from.") @@ -180,34 +169,17 @@ class ClaimMakePicking(models.TransientModel): 'note': self._get_picking_note(), } - @api.multi - def action_create_picking(self): - - context = self._context - picking_type = self.env.context.get('picking_type') - if isinstance(picking_type, int): - picking_obj = self.env['stock.picking.type'] - picking_type_rec = picking_obj.browse(picking_type) - if picking_type_rec.code == 'incoming': - picking_type = 'in' - elif picking_type_rec.code == 'outgoing': - picking_type = 'out' - else: - picking_type = 'int' - - warehouse_obj = self.env['stock.warehouse'] - warehouse_rec = warehouse_obj.browse(context.get('warehouse_id')) - if picking_type == 'out': - picking_type = warehouse_rec.out_type_id - write_field = 'move_out_id' - elif picking_type == 'in': + def _create_picking(self, claim, picking_type): + warehouse_rec = self.env['stock.warehouse'].browse( + self.env.context.get('warehouse_id') + ) + if picking_type == 'in': picking_type = warehouse_rec.in_type_id write_field = 'move_in_id' else: picking_type = warehouse_rec.int_type_id write_field = 'move_out_id' - claim = self.env['crm.claim'].browse(self.env.context['active_id']) partner_id = claim.delivery_address_id.id claim_lines = self.claim_line_ids @@ -266,6 +238,44 @@ class ClaimMakePicking(models.TransientModel): 'type': 'ir.actions.act_window', } + def _create_procurement(self, claim): + """ Create a procurement order for each line in this claim and put + all procurements in a procurement group linked to this claim. + + :type claim: crm_claim + """ + group = self.env['procurement.group'].create({ + 'name': claim.code, + 'claim_id': claim.id, + 'move_type': 'direct', + }) + + for line in self.claim_line_ids: + procurement = self.env['procurement.order'].create({ + 'name': line.product_id.name_template, + 'group_id': group.id, + 'origin': claim.code, + 'warehouse_id': self.delivery_warehouse_id.id, + 'date_planned': time.strftime(DT_FORMAT), + 'product_id': line.product_id.id, + 'product_qty': line.product_returned_quantity, + 'product_uom': line.product_id.product_tmpl_id.uom_id.id, + 'location_id': self.claim_line_dest_location_id.id, + 'company_id': claim.company_id.id, + }) + procurement.run() + + @api.multi + def action_create_picking(self): + claim = self.env['crm.claim'].browse(self.env.context['active_id']) + picking_type = self.env.context.get('picking_type') + + if picking_type == 'out': + return self._create_procurement(claim) + + else: + return self._create_picking(claim, picking_type) + @api.multi def action_cancel(self): return {'type': 'ir.actions.act_window_close'} diff --git a/crm_claim_rma/wizards/claim_make_picking.xml b/crm_claim_rma/wizards/claim_make_picking.xml index a21a8e0a..f0f31101 100644 --- a/crm_claim_rma/wizards/claim_make_picking.xml +++ b/crm_claim_rma/wizards/claim_make_picking.xml @@ -12,9 +12,10 @@ claim_picking claim_make_picking.wizard -
+ - + +