diff --git a/inventory_forecast_analysis_report/__manifest__.py b/inventory_forecast_analysis_report/__manifest__.py index 90c4352ee..5e98cdaa6 100644 --- a/inventory_forecast_analysis_report/__manifest__.py +++ b/inventory_forecast_analysis_report/__manifest__.py @@ -20,7 +20,7 @@ ############################################################################# { "name": "Inventory Forecast Analysis Report", - "version": "16.0.1.0.0", + "version": "16.0.1.0.1", "category": "Warehouse", "summary": "Helps to find all the stock quantities", "description": "This module allows the user to find all the " diff --git a/inventory_forecast_analysis_report/doc/RELEASE_NOTES.md b/inventory_forecast_analysis_report/doc/RELEASE_NOTES.md index 5112e1c41..1e5197954 100644 --- a/inventory_forecast_analysis_report/doc/RELEASE_NOTES.md +++ b/inventory_forecast_analysis_report/doc/RELEASE_NOTES.md @@ -3,5 +3,9 @@ #### 28.02.2024 #### Version 16.0.1.0.0 #### ADD - - Initial Commit for Inventory Forecast Analysis Report + +#### 02.04.2024 +#### Version 16.0.1.0.1 +##### UPDT +- Bug Fix-Resolved corrected the issue in action_print_report method diff --git a/inventory_forecast_analysis_report/models/product_template.py b/inventory_forecast_analysis_report/models/product_template.py index 5577c6a90..4fa99dab0 100644 --- a/inventory_forecast_analysis_report/models/product_template.py +++ b/inventory_forecast_analysis_report/models/product_template.py @@ -18,7 +18,7 @@ # If not, see . # ############################################################################# -from odoo import api, fields, models +from odoo import fields, models class ProductTemplate(models.Model): @@ -26,16 +26,4 @@ class ProductTemplate(models.Model): product_brand_id = fields.Many2one('product.brand', string="Product Brand", help="Brand of the Product.") - supplier_id = fields.Many2one( - 'product.supplierinfo', string="Supplier", - compute="_compute_suppliers", - store=True, help="Supplier of the Product.") - @api.depends('seller_ids.partner_id') - def _compute_suppliers(self): - """This function is used to compute the main supplier - of the product.""" - for rec in self: - rec.supplier_id = False - if rec.seller_ids: - rec.supplier_id = rec.seller_ids[0] diff --git a/inventory_forecast_analysis_report/wizards/forecast_analysis_report.py b/inventory_forecast_analysis_report/wizards/forecast_analysis_report.py index cf8074737..14f29f0e9 100644 --- a/inventory_forecast_analysis_report/wizards/forecast_analysis_report.py +++ b/inventory_forecast_analysis_report/wizards/forecast_analysis_report.py @@ -18,9 +18,8 @@ # If not, see . # ############################################################################# -from datetime import datetime -from dateutil.relativedelta import relativedelta -from odoo import api, fields, models +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError class ForecastAnalysisReportWizard(models.TransientModel): @@ -33,9 +32,6 @@ class ForecastAnalysisReportWizard(models.TransientModel): parent_category_id = fields.Many2one( 'product.category', string="Parent Category", help="Parent category of product") - supplier_id = fields.Many2one( - 'product.supplierinfo', string="Supplier", - help="Supplier/Vendor of the Product.") product_brand_id = fields.Many2one('product.brand', string="Product Brand", help="Brand of the Product.") period = fields.Selection([('1week', 'Last 1 week'), @@ -72,30 +68,30 @@ class ForecastAnalysisReportWizard(models.TransientModel): return {'domain': { 'product_category_id': ()}} - def _compute_date(self): + def get_start_date(self, today): """This function will calculate the start_date with respect to the period and returns the result""" - res = datetime.today() + relativedelta(months=-3) + res = fields.Date.subtract(today, months=3) if self.period == '1week': - res = datetime.today() + relativedelta(weeks=-1) + res = fields.Date.subtract(today, weeks=1) elif self.period == '2week': - res = datetime.today() + relativedelta(weeks=-2) + res = fields.Date.subtract(today, weeks=2) elif self.period == '3week': - res = datetime.today() + relativedelta(weeks=-3) + res = fields.Date.subtract(today, weeks=3) elif self.period == '1month': - res = datetime.today() + relativedelta(months=-1) + res = fields.Date.subtract(today, months=1) elif self.period == '6months': - res = datetime.today() + relativedelta(months=-6) + res = fields.Date.subtract(today, months=6) elif self.period == '12months': - res = datetime.today() + relativedelta(months=-12) + res = fields.Date.subtract(today, months=12) elif self.period == '24months': - res = datetime.today() + relativedelta(months=-24) + res = fields.Date.subtract(today, months=24) elif self.period == '36months': - res = datetime.today() + relativedelta(months=-36) + res = fields.Date.subtract(today, months=36) elif self.period == '2months': - res = datetime.today() + relativedelta(months=-2) + res = fields.Date.subtract(today, months=2) elif self.period == '5months': - res = datetime.today() + relativedelta(months=-5) + res = fields.Date.subtract(today, months=5) return res def action_print_report(self): @@ -103,88 +99,81 @@ class ForecastAnalysisReportWizard(models.TransientModel): on the report wizard and returns the report.""" previous_report = self.env['forecast.report'].search([]) previous_report.unlink() if previous_report else False - suppliers = self.env['product.supplierinfo'].search( - [('partner_id', '=', self.partner_id.id)]) - category_ids = [] - if self.parent_category_id: - # if there is a parent category, the report will be generated based - # on the product category as the sub-sub categories - category_ids = self.env['product.category'].search( - [('parent_id', '=', self.parent_category_id.id)]) - categ_list = category_ids.ids if category_ids else [] - if categ_list: - for rec in categ_list: - sub_category = self.env['product.category'].search( - [('parent_id', '=', rec)]) - for category in sub_category.ids: - if category not in categ_list: - categ_list.append(category) - category_ids = self.env['product.category'].browse(categ_list) + if (not self.product_category_id and not self.parent_category_id and + not self.partner_id and not self.product_brand_id and + not self.location_ids): + raise ValidationError(_("Data missing")) domain = [] - # if both categories are present, it will generate the - # report based on the product category only - if self.parent_category_id and self.product_category_id: - domain += [('categ_id', '=', self.product_category_id.id)] - elif self.product_category_id and not self.parent_category_id: + if self.product_category_id: domain += [('categ_id', '=', self.product_category_id.id)] elif not self.product_category_id and self.parent_category_id: domain += [('categ_id', '=', self.parent_category_id.id)] if self.partner_id: - domain += [('supplier_id', 'in', suppliers.ids)] + suppliers = self.env['product.supplierinfo'].search( + [('partner_id', '=', self.partner_id.id)]) + domain += [('seller_ids', 'in', suppliers.ids)] if self.product_brand_id: domain += [('product_brand_id', '=', self.product_brand_id.id)] products = self.env['product.product'].search(domain) product_ids = tuple([product.id for product in products]) - start_date = self._compute_date() - current_date = datetime.today() + current_date = fields.date.today() + start_date = self.get_start_date(current_date) query = """ - SELECT sum(sl.product_uom_qty) AS product_uom_qty, - sl.product_id, sum(sl.qty_invoiced) AS qty_invoiced - FROM sale_order_line AS sl - JOIN sale_order AS so ON sl.order_id = so.id - WHERE so.state IN ('sale','done') - AND so.date_order::date >= %s - AND so.date_order::date <= %s - AND sl.product_id in %s - group by sl.product_id""" - params = start_date.date(), current_date.date(), \ + SELECT sum(sl.product_uom_qty) AS product_uom_qty, + sl.product_id, sum(sl.qty_invoiced) AS qty_invoiced + FROM sale_order_line AS sl + JOIN sale_order AS so ON sl.order_id = so.id + WHERE so.state IN ('sale','done') + AND so.date_order::date >= %s + AND so.date_order::date <= %s + AND sl.product_id in %s + group by sl.product_id""" + params = start_date, current_date, \ product_ids if product_ids else (0, 0, 0, 0) self._cr.execute(query, params) result = self._cr.dictfetchall() - locations = self.location_ids - if not locations: - locations = self.env['stock.location'].search([ - ('name', '=', 'Stock')]) for product in products: - for location in locations: - warehouse = location.warehouse_id.id + internal_locations = self.env['stock.location'].search( + [('usage', '=', 'internal')]) + locations = self.env['stock.quant'].search([ + ('product_id', '=', product.id), + ('location_id', 'in', internal_locations.ids)]).location_id + for location in self.location_ids if self.location_ids else locations: + stock_quant = self.env['stock.quant'].search([ + ('location_id', '=', location.id), + ('product_id', '=', product.id), + ('write_date', '>=', start_date), + ('write_date', '<=', current_date)]) + available_qty = sum( + [quant.quantity for quant in stock_quant]) sold = 0 for sol_product in result: if sol_product['product_id'] == product.id: sold = sol_product['qty_invoiced'] - available_qty = product.with_context( - {'from_date': start_date, 'to_date': current_date, - 'warehouse': warehouse}).qty_available forecasted_qty = product.with_context( - {'warehouse': warehouse}).virtual_available + {'warehouse': location.warehouse_id.id}).virtual_available reorder_qty = self.env['stock.warehouse.orderpoint'].search( [('product_id', '=', product.id), - ('location_id', '=', product.id)]) + ('location_id', '=', location.id)]) reorder_min = sum( - [q.product_min_qty for q in reorder_qty]) - minimum_qty = 0 - if available_qty < reorder_min: - minimum_qty = reorder_min + [qty.product_min_qty for qty in reorder_qty]) + minimum_qty = reorder_min if available_qty < reorder_min else 0 pending = product.with_context( {'from_date': start_date, 'to_date': current_date, - 'location': location.id}).incoming_qty + 'location_id': location.id}).incoming_qty suggested = sold - (forecasted_qty + pending + minimum_qty) + if self.partner_id: + supplier = product.seller_ids.filtered( + lambda seller: seller.partner_id == self.partner_id).id + elif not self.partner_id and product.seller_ids: + supplier = product.seller_ids.ids[0] + else: + supplier = False vals = { 'sold': sold, 'product_id': product.id, 'product_category_id': product.categ_id.id, - 'supplier_id': product.seller_ids.ids[ - 0] if product.seller_ids else False, + 'supplier_id': supplier, 'product_brand_id': product.product_brand_id.id, 'on_hand': available_qty, 'pending': pending,