From 02c082f9662db78ac4dca613f2cca75c51c835a0 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 21 Oct 2024 14:46:24 +0200 Subject: [PATCH] [MIG] stock_valuation_xlsx from v14 to v16 --- stock_valuation_xlsx/__manifest__.py | 7 +- .../models/stock_expiry_depreciation_rule.py | 2 +- .../security/ir.model.access.csv | 2 +- .../views/stock_expiry_depreciation_rule.xml | 4 +- .../views/stock_inventory.xml | 25 ---- .../wizard/stock_valuation_xlsx.py | 125 ++++++------------ .../wizard/stock_valuation_xlsx_view.xml | 19 ++- .../wizard/stock_variation_xlsx.py | 41 +++--- .../wizard/stock_variation_xlsx_view.xml | 3 +- 9 files changed, 76 insertions(+), 152 deletions(-) delete mode 100644 stock_valuation_xlsx/views/stock_inventory.xml diff --git a/stock_valuation_xlsx/__manifest__.py b/stock_valuation_xlsx/__manifest__.py index 541f130..8e1e46c 100644 --- a/stock_valuation_xlsx/__manifest__.py +++ b/stock_valuation_xlsx/__manifest__.py @@ -1,11 +1,11 @@ -# Copyright 2020-2021 Akretion France (http://www.akretion.com) +# Copyright 2020-2024 Akretion France (http://www.akretion.com) # @author Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { 'name': 'Stock Valuation XLSX', - 'version': '14.0.1.0.0', + 'version': '16.0.1.0.0', 'category': 'Tools', 'license': 'AGPL-3', 'summary': 'Generate XLSX reports for past or present stock levels', @@ -42,8 +42,7 @@ This module has been written by Alexis de Lattre from Akretion # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). diff --git a/stock_valuation_xlsx/security/ir.model.access.csv b/stock_valuation_xlsx/security/ir.model.access.csv index 5bea9e2..3996546 100644 --- a/stock_valuation_xlsx/security/ir.model.access.csv +++ b/stock_valuation_xlsx/security/ir.model.access.csv @@ -1,5 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_stock_expiry_depreciation_rule_full,Full access on stock.expiry.depreciation.rule to account manager,model_stock_expiry_depreciation_rule,account.group_account_manager,1,1,1,1 -access_stock_expiry_depreciation_rule_read,Read access on stock.expiry.depreciation.rule to stock manager,model_stock_expiry_depreciation_rule,stock.group_stock_manager,1,0,0,0 +access_stock_expiry_depreciation_rule_read,Read access on stock.expiry.depreciation.rule to stock user,model_stock_expiry_depreciation_rule,stock.group_stock_user,1,0,0,0 access_stock_valuation_xlsx,stock.valuation.xlsx wizard,model_stock_valuation_xlsx,stock.group_stock_user,1,1,1,0 access_stock_variation_xlsx,stock.variation.xlsx wizard,model_stock_variation_xlsx,stock.group_stock_user,1,1,1,0 diff --git a/stock_valuation_xlsx/views/stock_expiry_depreciation_rule.xml b/stock_valuation_xlsx/views/stock_expiry_depreciation_rule.xml index 6d0c784..2733584 100644 --- a/stock_valuation_xlsx/views/stock_expiry_depreciation_rule.xml +++ b/stock_valuation_xlsx/views/stock_expiry_depreciation_rule.xml @@ -1,12 +1,11 @@ - stock.expiry.depreciation.rule @@ -31,5 +30,4 @@ parent="account.account_management_menu" sequence="100"/> - diff --git a/stock_valuation_xlsx/views/stock_inventory.xml b/stock_valuation_xlsx/views/stock_inventory.xml deleted file mode 100644 index 82228b1..0000000 --- a/stock_valuation_xlsx/views/stock_inventory.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - xlsx.stock.inventory.form - stock.inventory - - - - - - - - diff --git a/stock_valuation_xlsx/wizard/stock_valuation_xlsx.py b/stock_valuation_xlsx/wizard/stock_valuation_xlsx.py index 38df9bc..de5b506 100644 --- a/stock_valuation_xlsx/wizard/stock_valuation_xlsx.py +++ b/stock_valuation_xlsx/wizard/stock_valuation_xlsx.py @@ -1,4 +1,4 @@ -# Copyright 2020 Akretion France (http://www.akretion.com/) +# Copyright 2020-2024 Akretion France (http://www.akretion.com/) # @author Alexis de Lattre # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). @@ -29,33 +29,26 @@ class StockValuationXlsx(models.TransientModel): 'stock.warehouse', string='Warehouse', check_company=True, domain="[('company_id', '=', company_id)]") location_id = fields.Many2one( - 'stock.location', string='Root Stock Location', required=True, - domain="[('usage', 'in', ('view', 'internal')), ('company_id', '=', company_id)]", - default=lambda self: self._default_location(), check_company=True, + 'stock.location', string='Root Stock Location', required=True, check_company=True, + compute='_compute_location_id', readonly=False, precompute=True, store=True, + domain="[('usage', 'in', ('view', 'internal')), ('company_id', 'in', [False, company_id])]", help="The childen locations of the selected locations will " "be taken in the valuation.") categ_ids = fields.Many2many( 'product.category', string='Product Category Filter', help="Leave this field empty to have a stock valuation for all your products.", ) - source = fields.Selection([ - ('inventory', 'Physical Inventory'), - ('stock', 'Stock Levels'), - ], string='Source data', default='stock', required=True) - inventory_id = fields.Many2one( - 'stock.inventory', string='Inventory', check_company=True, - domain="[('state', '=', 'done'), ('company_id', '=', company_id)]") stock_date_type = fields.Selection([ ('present', 'Present'), ('past', 'Past'), - ], string='Present or Past', default='present') + ], string='Present or Past', default='present', required=True) past_date = fields.Datetime( string='Past Date', default=fields.Datetime.now) categ_subtotal = fields.Boolean( string='Subtotals per Categories', default=True, help="Show a subtotal per product category.") standard_price_date = fields.Selection([ - ('past', 'Past Date or Inventory Date'), + ('past', 'Past Date'), ('present', 'Current'), ], default='past', string='Cost Price Date') has_expiry_date = fields.Boolean( @@ -67,38 +60,28 @@ class StockValuationXlsx(models.TransientModel): @api.model def _default_has_expiry_date(self): - splo = self.env['stock.production.lot'] has_expiry_date = False - if hasattr(splo, 'expiry_date'): + if hasattr(self.env['stock.lot'], 'expiry_date'): has_expiry_date = True return has_expiry_date - @api.model - def _default_location(self): - wh = self.env.ref('stock.warehouse0') - return wh.lot_stock_id + @api.depends('warehouse_id', 'company_id') + def _compute_location_id(self): + for wiz in self: + wh = wiz.warehouse_id + if not wh: + wh = self.env["stock.warehouse"].search([('company_id', '=', wiz.company_id.id)], limit=1) + if wh: + wiz.location_id = wh.view_location_id.id - @api.onchange('warehouse_id') - def warehouse_id_change(self): - if self.warehouse_id: - self.location_id = self.warehouse_id.view_location_id.id - - def _check_config(self, company_id): + def _check_config(self): self.ensure_one() if ( - self.source == 'stock' and self.stock_date_type == 'past' and self.past_date > fields.Datetime.now()): raise UserError(_("The 'Past Date' must be in the past !")) - if self.source == 'inventory': - if not self.inventory_id: - raise UserError(_("You must select an inventory.")) - elif self.inventory_id.state != 'done': - raise UserError(_( - "The selected inventory (%s) is not in done state.") - % self.inventory_id.display_name) cost_method_real_count = self.env['ir.property'].sudo().search([ - ('company_id', '=', company_id), + ('company_id', '=', self.company_id.id), ('name', '=', 'property_cost_method'), ('value_text', '=', 'real'), ('type', '=', 'selection'), @@ -159,7 +142,7 @@ class StockValuationXlsx(models.TransientModel): if not std_price_date: # present product_id2data[p['id']][std_price_field_name] = p['standard_price'] else: - layer_rg = svlo.read_group( + layer_rg = svlo._read_group( [ ('product_id', '=', p['id']), ('company_id', '=', company_id), @@ -201,13 +184,13 @@ class StockValuationXlsx(models.TransientModel): @api.model def prodlot_id2data(self, product_ids, has_expiry_date, depreciation_rules): - splo = self.env['stock.production.lot'] + slo = self.env['stock.lot'] lot_id2data = {} lot_fields = ['name'] if has_expiry_date: lot_fields.append('expiry_date') - lots = splo.search_read( + lots = slo.search_read( [('product_id', 'in', product_ids)], lot_fields) for lot in lots: lot_id2data[lot['id']] = lot @@ -230,30 +213,6 @@ class StockValuationXlsx(models.TransientModel): loc_id2name[loc['id']] = loc['display_name'] return loc_id2name - def compute_data_from_inventory(self, product_ids, prec_qty): - self.ensure_one() - logger.debug('Start compute_data_from_inventory') - # Can he modify UoM ? - inv_lines = self.env['stock.inventory.line'].search_read([ - ('inventory_id', '=', self.inventory_id.id), - ('location_id', 'child_of', self.location_id.id), - ('product_id', 'in', product_ids), - ('product_qty', '>', 0), - ], ['product_id', 'location_id', 'prod_lot_id', 'product_qty']) - res = [] - in_stock_products = {} - for l in inv_lines: - if not float_is_zero(l['product_qty'], precision_digits=prec_qty): - res.append({ - 'product_id': l['product_id'][0], - 'lot_id': l['prod_lot_id'] and l['prod_lot_id'][0] or False, - 'qty': l['product_qty'], - 'location_id': l['location_id'][0], - }) - in_stock_products[l['product_id'][0]] = True - logger.debug('End compute_data_from_inventory') - return res, in_stock_products - def compute_data_from_present_stock(self, company_id, product_ids, prec_qty): self.ensure_one() logger.debug('Start compute_data_from_present_stock') @@ -361,40 +320,34 @@ class StockValuationXlsx(models.TransientModel): company = self.company_id company_id = company.id prec_cur_rounding = company.currency_id.rounding - self._check_config(company_id) + self._check_config() - apply_depreciation = self.apply_depreciation if ( - (self.source == 'stock' and self.stock_date_type == 'past') or + self.stock_date_type == 'past' or not self.split_by_lot or not self.has_expiry_date): apply_depreciation = False + else: + apply_depreciation = self.apply_depreciation product_ids = self.get_product_ids() if not product_ids: raise UserError(_("There are no products to analyse.")) - split_by_lot = self.split_by_lot - split_by_location = self.split_by_location - if self.source == 'stock': - if self.stock_date_type == 'present': - past_date = False - data, in_stock_products = self.compute_data_from_present_stock( - company_id, product_ids, prec_qty) - elif self.stock_date_type == 'past': - split_by_lot = False - split_by_location = False - past_date = self.past_date - data, in_stock_products = self.compute_data_from_past_stock( - product_ids, prec_qty, past_date) - elif self.source == 'inventory': - past_date = self.inventory_id.date - data, in_stock_products = self.compute_data_from_inventory(product_ids, prec_qty) - if self.source == 'stock' and self.stock_date_type == 'present': + if self.stock_date_type == 'present': + split_by_lot = self.split_by_lot + split_by_location = self.split_by_location + past_date = False standard_price_past_date = False - else: # field standard_price_date is shown on screen - if self.standard_price_date == 'present': - standard_price_past_date = False - else: - standard_price_past_date = past_date + data, in_stock_products = self.compute_data_from_present_stock( + company_id, product_ids, prec_qty) + elif self.stock_date_type == 'past': + split_by_lot = False + split_by_location = False + past_date = self.past_date + standard_price_past_date = past_date + data, in_stock_products = self.compute_data_from_past_stock( + product_ids, prec_qty, past_date) + else: + raise depreciation_rules = [] if apply_depreciation: depreciation_rules = self._prepare_expiry_depreciation_rules(company_id, past_date) diff --git a/stock_valuation_xlsx/wizard/stock_valuation_xlsx_view.xml b/stock_valuation_xlsx/wizard/stock_valuation_xlsx_view.xml index 55f892e..7147139 100644 --- a/stock_valuation_xlsx/wizard/stock_valuation_xlsx_view.xml +++ b/stock_valuation_xlsx/wizard/stock_valuation_xlsx_view.xml @@ -1,6 +1,6 @@ @@ -12,25 +12,24 @@ stock.valuation.xlsx.form stock.valuation.xlsx -
+

The generated XLSX report has the valuation of stockable products located on the selected stock locations (and their childrens).

+ - - - - - + + + - - - + + +