From 2852918831c02b85181f27c29cbfad5c8d0b1d2a Mon Sep 17 00:00:00 2001 From: Joan Sisquella Date: Mon, 20 Jan 2020 15:22:53 +0100 Subject: [PATCH] [IMP] stock_orderpoint_manual_procurement: black, isort --- .../__manifest__.py | 17 +- .../models/stock_warehouse_orderpoint.py | 47 ++--- ...est_stock_orderpoint_manual_procurement.py | 168 +++++++++--------- .../wizards/make_procurement_orderpoint.py | 122 ++++++------- 4 files changed, 178 insertions(+), 176 deletions(-) diff --git a/stock_orderpoint_manual_procurement/__manifest__.py b/stock_orderpoint_manual_procurement/__manifest__.py index 7c961b4e6..1d394892e 100644 --- a/stock_orderpoint_manual_procurement/__manifest__.py +++ b/stock_orderpoint_manual_procurement/__manifest__.py @@ -5,24 +5,19 @@ { "name": "Stock Orderpoint Manual Procurement", "summary": "Allows to create procurement orders from orderpoints instead " - "of relying only on the scheduler.", + "of relying only on the scheduler.", "version": "12.0.1.1.0", - "author": "Eficent, " - "Odoo Community Association (OCA)", + "author": "Eficent, " "Odoo Community Association (OCA)", "website": "https://github.com/OCA/stock-logistics-warehouse", "category": "Warehouse Management", - "depends": [ - "purchase_stock", - ], - "demo": [ - "demo/product.xml", - ], + "depends": ["purchase_stock"], + "demo": ["demo/product.xml"], "data": [ "security/stock_orderpoint_manual_procurement_security.xml", "wizards/make_procurement_orderpoint_view.xml", "views/stock_warehouse_orderpoint_view.xml", ], "license": "AGPL-3", - 'installable': True, - 'application': False, + "installable": True, + "application": False, } diff --git a/stock_orderpoint_manual_procurement/models/stock_warehouse_orderpoint.py b/stock_orderpoint_manual_procurement/models/stock_warehouse_orderpoint.py index eeb675e1f..ebcaae70a 100644 --- a/stock_orderpoint_manual_procurement/models/stock_warehouse_orderpoint.py +++ b/stock_orderpoint_manual_procurement/models/stock_warehouse_orderpoint.py @@ -2,26 +2,26 @@ # (http://www.eficent.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models from datetime import datetime -from odoo.addons import decimal_precision as dp + +from odoo import api, fields, models from odoo.tools import float_compare, float_round +from odoo.addons import decimal_precision as dp -UNIT = dp.get_precision('Product Unit of Measure') +UNIT = dp.get_precision("Product Unit of Measure") class StockWarehouseOrderpoint(models.Model): - _inherit = 'stock.warehouse.orderpoint' + _inherit = "stock.warehouse.orderpoint" procure_recommended_qty = fields.Float( - string='Procure Recommendation', + string="Procure Recommendation", compute="_compute_procure_recommended", digits=UNIT, ) procure_recommended_date = fields.Date( - string='Recommended Request Date', - compute="_compute_procure_recommended", + string="Recommended Request Date", compute="_compute_procure_recommended" ) @api.multi @@ -29,21 +29,18 @@ class StockWarehouseOrderpoint(models.Model): self.ensure_one() procure_recommended_qty = 0.0 qty = max(self.product_min_qty, self.product_max_qty) - virtual_qty - remainder = \ - self.qty_multiple > 0 and qty % self.qty_multiple or 0.0 - if float_compare( - remainder, 0.0, - precision_rounding=self.product_uom.rounding) > 0: + remainder = self.qty_multiple > 0 and qty % self.qty_multiple or 0.0 + if ( + float_compare(remainder, 0.0, precision_rounding=self.product_uom.rounding) + > 0 + ): qty += self.qty_multiple - remainder - if float_compare( - qty, 0.0, - precision_rounding=self.product_uom.rounding) <= 0: + if float_compare(qty, 0.0, precision_rounding=self.product_uom.rounding) <= 0: return procure_recommended_qty qty -= op_qtys[self.id] - qty_rounded = float_round( - qty, precision_rounding=self.product_uom.rounding) + qty_rounded = float_round(qty, precision_rounding=self.product_uom.rounding) if qty_rounded > 0: procure_recommended_qty = qty_rounded return procure_recommended_qty @@ -55,10 +52,16 @@ class StockWarehouseOrderpoint(models.Model): for op in self: qty = 0.0 virtual_qty = op.with_context( - location=op.location_id.id).product_id.virtual_available - if float_compare(virtual_qty, op.product_min_qty, - precision_rounding=op.product_uom.rounding) < 0: + location=op.location_id.id + ).product_id.virtual_available + if ( + float_compare( + virtual_qty, + op.product_min_qty, + precision_rounding=op.product_uom.rounding, + ) + < 0 + ): qty = op._get_procure_recommended_qty(virtual_qty, op_qtys) op.procure_recommended_qty = qty - op.procure_recommended_date = op._get_date_planned( - qty, datetime.today()) + op.procure_recommended_date = op._get_date_planned(qty, datetime.today()) diff --git a/stock_orderpoint_manual_procurement/tests/test_stock_orderpoint_manual_procurement.py b/stock_orderpoint_manual_procurement/tests/test_stock_orderpoint_manual_procurement.py index de1abd258..81e37700a 100644 --- a/stock_orderpoint_manual_procurement/tests/test_stock_orderpoint_manual_procurement.py +++ b/stock_orderpoint_manual_procurement/tests/test_stock_orderpoint_manual_procurement.py @@ -3,52 +3,54 @@ # Copyright 2016 Serpent Consulting Services Pvt. Ltd. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo.tests import common -from odoo import fields from datetime import timedelta +from odoo import fields +from odoo.tests import common + class TestStockWarehouseOrderpoint(common.TransactionCase): - def setUp(self): super(TestStockWarehouseOrderpoint, self).setUp() # Refs - self.group_stock_manager = self.env.ref('stock.group_stock_manager') - self.group_purchase_manager = self.env.ref( - 'purchase.group_purchase_manager') + self.group_stock_manager = self.env.ref("stock.group_stock_manager") + self.group_purchase_manager = self.env.ref("purchase.group_purchase_manager") self.group_change_procure_qty = self.env.ref( - 'stock_orderpoint_manual_procurement.' - 'group_change_orderpoint_procure_qty') - self.company1 = self.env.ref('base.main_company') + "stock_orderpoint_manual_procurement." "group_change_orderpoint_procure_qty" + ) + self.company1 = self.env.ref("base.main_company") # Get required Model - self.reordering_rule_model = self.env['stock.warehouse.orderpoint'] - self.product_model = self.env['product.product'] - self.purchase_model = self.env['purchase.order'] - self.purchase_line_model = self.env['purchase.order.line'] - self.user_model = self.env['res.users'] - self.product_ctg_model = self.env['product.category'] - self.stock_change_model = self.env['stock.change.product.qty'] - self.make_procurement_orderpoint_model =\ - self.env['make.procurement.orderpoint'] + self.reordering_rule_model = self.env["stock.warehouse.orderpoint"] + self.product_model = self.env["product.product"] + self.purchase_model = self.env["purchase.order"] + self.purchase_line_model = self.env["purchase.order.line"] + self.user_model = self.env["res.users"] + self.product_ctg_model = self.env["product.category"] + self.stock_change_model = self.env["stock.change.product.qty"] + self.make_procurement_orderpoint_model = self.env["make.procurement.orderpoint"] # Create users - self.user = self._create_user('user_1', - [self.group_stock_manager, - self.group_change_procure_qty, - self.group_purchase_manager], - self.company1) + self.user = self._create_user( + "user_1", + [ + self.group_stock_manager, + self.group_change_procure_qty, + self.group_purchase_manager, + ], + self.company1, + ) # Get required Model data - self.product_uom = self.env.ref('uom.product_uom_unit') - self.location = self.env.ref('stock.stock_location_stock') - self.product = self.env.ref('product.product_product_7') + self.product_uom = self.env.ref("uom.product_uom_unit") + self.location = self.env.ref("stock.stock_location_stock") + self.product = self.env.ref("product.product_product_7") # Create vendor and supplier info - test_seller = self.env['res.partner'].create({'name': 'Test seller'}) - self.vendor = self.env['product.supplierinfo'].create({ - 'name': test_seller.id, - 'price': 8.0}) + test_seller = self.env["res.partner"].create({"name": "Test seller"}) + self.vendor = self.env["product.supplierinfo"].create( + {"name": test_seller.id, "price": 8.0} + ) # Create Product category and Product self.product_ctg = self._create_product_category() @@ -64,68 +66,76 @@ class TestStockWarehouseOrderpoint(common.TransactionCase): def _create_user(self, login, groups, company): """ Create a user.""" group_ids = [group.id for group in groups] - user = \ - self.user_model.with_context({'no_reset_password': True}).create({ - 'name': 'Test User', - 'login': login, - 'password': 'demo', - 'email': 'test@yourcompany.com', - 'company_id': company.id, - 'company_ids': [(4, company.id)], - 'groups_id': [(6, 0, group_ids)] - }) + user = self.user_model.with_context({"no_reset_password": True}).create( + { + "name": "Test User", + "login": login, + "password": "demo", + "email": "test@yourcompany.com", + "company_id": company.id, + "company_ids": [(4, company.id)], + "groups_id": [(6, 0, group_ids)], + } + ) return user def _create_product_category(self): """Create a Product Category.""" - product_ctg = self.product_ctg_model.create({ - 'name': 'test_product_ctg', - }) + product_ctg = self.product_ctg_model.create({"name": "test_product_ctg"}) return product_ctg def _create_product(self): """Create a Product.""" - product = self.product_model.create({ - 'name': 'Test Product', - 'categ_id': self.product_ctg.id, - 'type': 'product', - 'uom_id': self.product_uom.id, - 'variant_seller_ids': [(6, 0, [self.vendor.id])], - }) + product = self.product_model.create( + { + "name": "Test Product", + "categ_id": self.product_ctg.id, + "type": "product", + "uom_id": self.product_uom.id, + "variant_seller_ids": [(6, 0, [self.vendor.id])], + } + ) return product def _update_product_qty(self, product, location, quantity): """Update Product quantity.""" - change_product_qty = self.stock_change_model.create({ - 'location_id': location.id, - 'product_id': product.id, - 'new_quantity': quantity, - }) + change_product_qty = self.stock_change_model.create( + { + "location_id": location.id, + "product_id": product.id, + "new_quantity": quantity, + } + ) change_product_qty.change_product_qty() return change_product_qty def create_orderpoint(self): """Create a Reordering Rule""" - reorder = self.reordering_rule_model.sudo(self.user).create({ - 'name': 'Order-point', - 'product_id': self.product.id, - 'product_min_qty': '100', - 'product_max_qty': '500', - 'qty_multiple': '1' - }) + reorder = self.reordering_rule_model.sudo(self.user).create( + { + "name": "Order-point", + "product_id": self.product.id, + "product_min_qty": "100", + "product_max_qty": "500", + "qty_multiple": "1", + } + ) return reorder def create_orderpoint_procurement(self, manual_date=None): """Make Procurement from Reordering Rule""" context = { - 'active_model': 'stock.warehouse.orderpoint', - 'active_ids': self.reorder.ids, - 'active_id': self.reorder.id + "active_model": "stock.warehouse.orderpoint", + "active_ids": self.reorder.ids, + "active_id": self.reorder.id, } - wizard = self.make_procurement_orderpoint_model.sudo(self.user).\ - with_context(context).create({}) + wizard = ( + self.make_procurement_orderpoint_model.sudo(self.user) + .with_context(context) + .create({}) + ) if manual_date: - wizard.item_ids.write({'date_planned': manual_date}) + wizard.item_ids.write({"date_planned": manual_date}) wizard.make_procurement() return wizard @@ -137,28 +147,26 @@ class TestStockWarehouseOrderpoint(common.TransactionCase): # As per route configuration, it will create Purchase order # Assert that Procurement is created with the desired quantity - purchase = self.purchase_model.search( - [('origin', 'ilike', self.reorder.name)]) + purchase = self.purchase_model.search([("origin", "ilike", self.reorder.name)]) self.assertEquals(len(purchase), 1) purchase_line = self.purchase_line_model.search( - [('orderpoint_id', '=', self.reorder.id), - ('order_id', '=', purchase.id)]) + [("orderpoint_id", "=", self.reorder.id), ("order_id", "=", purchase.id)] + ) self.assertEquals(len(purchase_line), 1) - self.assertNotEqual(self.reorder.procure_recommended_qty, - purchase_line.product_qty) + self.assertNotEqual( + self.reorder.procure_recommended_qty, purchase_line.product_qty + ) self.assertEqual(purchase_line.product_qty, 480.0) def test_manual_procurement_modified_date(self): """Test manual procurement created from an orderpoint with modified date.""" - manual_date = fields.Date.from_string( - fields.Date.today()) + timedelta(days=30) + manual_date = fields.Date.from_string(fields.Date.today()) + timedelta(days=30) self.create_orderpoint_procurement(manual_date) - purchase = self.purchase_model.search( - [('origin', 'ilike', self.reorder.name)]) + purchase = self.purchase_model.search([("origin", "ilike", self.reorder.name)]) purchase_line = self.purchase_line_model.search( - [('orderpoint_id', '=', self.reorder.id), - ('order_id', '=', purchase.id)]) + [("orderpoint_id", "=", self.reorder.id), ("order_id", "=", purchase.id)] + ) self.assertEquals(len(purchase_line), 1) pol_date = fields.Date.from_string(purchase_line.date_planned) self.assertEquals(pol_date, manual_date) diff --git a/stock_orderpoint_manual_procurement/wizards/make_procurement_orderpoint.py b/stock_orderpoint_manual_procurement/wizards/make_procurement_orderpoint.py index 2f5286b10..1313abec2 100644 --- a/stock_orderpoint_manual_procurement/wizards/make_procurement_orderpoint.py +++ b/stock_orderpoint_manual_procurement/wizards/make_procurement_orderpoint.py @@ -2,59 +2,61 @@ # (http://www.eficent.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models, _ +from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError class MakeProcurementOrderpoint(models.TransientModel): - _name = 'make.procurement.orderpoint' - _description = 'Make Procurements from Orderpoints' + _name = "make.procurement.orderpoint" + _description = "Make Procurements from Orderpoints" item_ids = fields.One2many( - 'make.procurement.orderpoint.item', - 'wiz_id', string='Items') + "make.procurement.orderpoint.item", "wiz_id", string="Items" + ) @api.model def _prepare_item(self, orderpoint): return { - 'qty': orderpoint.procure_recommended_qty, - 'qty_without_security': orderpoint.procure_recommended_qty, - 'uom_id': orderpoint.product_uom.id, - 'date_planned': orderpoint.procure_recommended_date, # string - 'orderpoint_id': orderpoint.id, - 'product_id': orderpoint.product_id.id, - 'warehouse_id': orderpoint.warehouse_id.id, - 'location_id': orderpoint.location_id.id + "qty": orderpoint.procure_recommended_qty, + "qty_without_security": orderpoint.procure_recommended_qty, + "uom_id": orderpoint.product_uom.id, + "date_planned": orderpoint.procure_recommended_date, # string + "orderpoint_id": orderpoint.id, + "product_id": orderpoint.product_id.id, + "warehouse_id": orderpoint.warehouse_id.id, + "location_id": orderpoint.location_id.id, } @api.model - def fields_view_get(self, view_id=None, view_type='form', toolbar=False, - submenu=False): + def fields_view_get( + self, view_id=None, view_type="form", toolbar=False, submenu=False + ): if not self.user_has_groups( - "stock_orderpoint_manual_procurement.group_change_orderpoint_procure_qty"): # noqa + "stock_orderpoint_manual_procurement.group_change_orderpoint_procure_qty" + ): # noqa # Redirect to readonly qty form view view_id = self.env.ref( - 'stock_orderpoint_manual_procurement.view_make_procure_without_security').id # noqa + "stock_orderpoint_manual_procurement.view_make_procure_without_security" + ).id # noqa return super(MakeProcurementOrderpoint, self).fields_view_get( - view_id=view_id, view_type=view_type, toolbar=toolbar, - submenu=submenu) + view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu + ) @api.model def default_get(self, fields): res = super(MakeProcurementOrderpoint, self).default_get(fields) - orderpoint_obj = self.env['stock.warehouse.orderpoint'] - orderpoint_ids = self.env.context['active_ids'] or [] - active_model = self.env.context['active_model'] + orderpoint_obj = self.env["stock.warehouse.orderpoint"] + orderpoint_ids = self.env.context["active_ids"] or [] + active_model = self.env.context["active_model"] if not orderpoint_ids: return res - assert active_model == 'stock.warehouse.orderpoint', \ - 'Bad context propagation' + assert active_model == "stock.warehouse.orderpoint", "Bad context propagation" items = [] for line in orderpoint_obj.browse(orderpoint_ids): items.append([0, 0, self._prepare_item(line)]) - res['item_ids'] = items + res["item_ids"] = items return res @api.multi @@ -63,16 +65,16 @@ class MakeProcurementOrderpoint(models.TransientModel): errors = [] # User requesting the procurement is passed by context to be able to # update final MO, PO or trasfer with that information. - pg_obj = self.env['procurement.group'].with_context( - requested_uid=self.env.user) + pg_obj = self.env["procurement.group"].with_context(requested_uid=self.env.user) for item in self.item_ids: if not item.qty: raise ValidationError(_("Quantity must be positive.")) if not item.orderpoint_id: raise ValidationError(_("No reordering rule found!")) values = item.orderpoint_id._prepare_procurement_values(item.qty) - values['date_planned'] = fields.Datetime.to_string( - fields.Date.from_string(item.date_planned)) + values["date_planned"] = fields.Datetime.to_string( + fields.Date.from_string(item.date_planned) + ) # Run procurement try: pg_obj.run( @@ -82,55 +84,49 @@ class MakeProcurementOrderpoint(models.TransientModel): item.orderpoint_id.location_id, item.orderpoint_id.name, item.orderpoint_id.name, - values + values, ) except UserError as error: - errors.append(error.name) + errors.append(error.name) if errors: - raise UserError('\n'.join(errors)) - return {'type': 'ir.actions.act_window_close'} + raise UserError("\n".join(errors)) + return {"type": "ir.actions.act_window_close"} class MakeProcurementOrderpointItem(models.TransientModel): - _name = 'make.procurement.orderpoint.item' - _description = 'Make Procurements from Orderpoint Item' + _name = "make.procurement.orderpoint.item" + _description = "Make Procurements from Orderpoint Item" wiz_id = fields.Many2one( - 'make.procurement.orderpoint', - string='Wizard', + "make.procurement.orderpoint", + string="Wizard", required=True, - ondelete='cascade', - readonly=True) - qty = fields.Float( - string='Qty') - qty_without_security = fields.Float( - string='Quantity') - uom_id = fields.Many2one( - string='Unit of Measure', - comodel_name='uom.uom') - date_planned = fields.Date( - string='Planned Date', - required=False) + ondelete="cascade", + readonly=True, + ) + qty = fields.Float(string="Qty") + qty_without_security = fields.Float(string="Quantity") + uom_id = fields.Many2one(string="Unit of Measure", comodel_name="uom.uom") + date_planned = fields.Date(string="Planned Date", required=False) orderpoint_id = fields.Many2one( - string='Reordering rule', - comodel_name='stock.warehouse.orderpoint', - readonly=False) + string="Reordering rule", + comodel_name="stock.warehouse.orderpoint", + readonly=False, + ) product_id = fields.Many2one( - string='Product', - comodel_name='product.product', - readonly=True) + string="Product", comodel_name="product.product", readonly=True + ) warehouse_id = fields.Many2one( - string='Warehouse', - comodel_name='stock.warehouse', - readonly=True) + string="Warehouse", comodel_name="stock.warehouse", readonly=True + ) location_id = fields.Many2one( - string='Location', - comodel_name='stock.location', - readonly=True) + string="Location", comodel_name="stock.location", readonly=True + ) @api.multi - @api.onchange('uom_id') + @api.onchange("uom_id") def onchange_uom_id(self): for rec in self: rec.qty = rec.orderpoint_id.product_uom._compute_quantity( - rec.orderpoint_id.procure_recommended_qty, rec.uom_id) + rec.orderpoint_id.procure_recommended_qty, rec.uom_id + )