diff --git a/product_catalog_aeroo_report/__manifest__.py b/product_catalog_aeroo_report/__manifest__.py index d48bd5d39..ad9502e23 100644 --- a/product_catalog_aeroo_report/__manifest__.py +++ b/product_catalog_aeroo_report/__manifest__.py @@ -18,33 +18,32 @@ # ############################################################################## { - 'name': 'Product Catalog Aeroo Report', - 'version': "16.0.1.3.0", - 'category': 'Aeroo Reporting', - 'sequence': 14, - 'summary': '', - 'author': 'ADHOC SA', - 'website': 'www.adhoc.com.ar', - 'license': 'AGPL-3', - 'images': [ + "name": "Product Catalog Aeroo Report", + "version": "16.0.1.4.0", + "category": "Aeroo Reporting", + "sequence": 14, + "summary": "", + "author": "ADHOC SA", + "website": "www.adhoc.com.ar", + "license": "AGPL-3", + "images": [], + "depends": [ + "product_price_taxes_included", + "report_aeroo", + "sale", + "stock", ], - 'depends': [ - 'product_price_taxes_included', - 'report_aeroo', - 'sale', - 'stock', + "data": [ + "wizards/product_catalog_wizard_views.xml", + "security/ir.model.access.csv", + "views/product_catalog_report_views.xml", + "report/product_catalog_report_data.xml", ], - 'data': [ - 'wizards/product_catalog_wizard_views.xml', - 'security/ir.model.access.csv', - 'views/product_catalog_report_views.xml', - 'report/product_catalog_report_data.xml' + "demo": [ + "demo/product_template_demo.xml", + "demo/product_product_demo.xml", ], - 'demo': [ - 'demo/product_template_demo.xml', - 'demo/product_product_demo.xml', - ], - 'installable': True, - 'auto_install': False, - 'application': True, + "installable": True, + "auto_install": False, + "application": True, } diff --git a/product_catalog_aeroo_report/models/product_catalog_report.py b/product_catalog_aeroo_report/models/product_catalog_report.py index d39941aa4..1e0592cf6 100644 --- a/product_catalog_aeroo_report/models/product_catalog_report.py +++ b/product_catalog_aeroo_report/models/product_catalog_report.py @@ -6,74 +6,72 @@ class ProductCatalogReport(models.Model): - _name = 'product.product_catalog_report' - _description = 'Product Catalog Report with Aeroo' + _name = "product.product_catalog_report" + _description = "Product Catalog Report with Aeroo" name = fields.Char( required=True, ) products_order = fields.Char( - 'Products Order Sintax', - help='for eg. name desc', + "Products Order Sintax", + help="for eg. name desc", required=False, ) categories_order = fields.Char( - 'Categories Order Sintax', - help='for eg. name desc', + "Categories Order Sintax", + help="for eg. name desc", ) include_sub_categories = fields.Boolean( - 'Include Subcategories?', + "Include Subcategories?", ) only_with_stock = fields.Boolean( - 'Only With Stock Products?', + "Only With Stock Products?", ) taxes_included = fields.Boolean( - 'Taxes Included?', - help='Export prices with taxes included by default? This value will be' - ' used as default on print catalog wizard', + "Taxes Included?", + help="Export prices with taxes included by default? This value will be used as default on print catalog wizard", ) print_product_uom = fields.Boolean( - 'Print Product UOM?', + "Print Product UOM?", ) product_type = fields.Selection( - [('product.template', 'Product Template'), - ('product.product', 'Product')], - 'Product Type', + [("product.template", "Product Template"), ("product.product", "Product")], + "Product Type", required=True, ) prod_display_type = fields.Selection( - [('prod_per_line', 'One Product Per Line'), - ('prod_list', 'Product List'), - ('variants', 'Variants'), - ], 'Product Display Type', + [ + ("prod_per_line", "One Product Per Line"), + ("prod_list", "Product List"), + ("variants", "Variants"), + ], + "Product Display Type", ) report_id = fields.Many2one( - 'ir.actions.report', - string='Report', - domain=[('report_type', '=', 'aeroo'), - ('model', '=', 'product.product_catalog_report')], - context={'default_report_type': 'aeroo', - 'default_model': 'product.product'}, + "ir.actions.report", + string="Report", + domain=[("report_type", "=", "aeroo"), ("model", "=", "product.product_catalog_report")], + context={"default_report_type": "aeroo", "default_model": "product.product"}, required=True, ) category_ids = fields.Many2many( - 'product.category', - 'product_catalog_report_categories', - 'product_catalog_report_id', - 'category_id', - 'Product Categories', + "product.category", + "product_catalog_report_categories", + "product_catalog_report_id", + "category_id", + "Product Categories", ) pricelist_ids = fields.Many2many( - 'product.pricelist', - 'product_catalog_report_pricelists', - 'product_catalog_report_id', - 'pricelist_id', - 'Pricelist', + "product.pricelist", + "product_catalog_report_pricelists", + "product_catalog_report_id", + "pricelist_id", + "Pricelist", ) category_type = fields.Selection( - [('accounting_category', 'Accounting Category')], - default='accounting_category', + [("accounting_category", "Accounting Category")], + default="accounting_category", required=True, ) @@ -82,27 +80,58 @@ def prepare_report(self): categories = self.category_ids # because this value usually cames from wizard, if we call report from # this model, we add taxes_included parameter - if 'taxes_included' not in context: - context.update({'taxes_included': self.taxes_included}) + if "taxes_included" not in context: + context.update({"taxes_included": self.taxes_included}) if self.include_sub_categories and categories: - categories = self.env['product.category'].search( - [('id', 'child_of', categories.ids)]) - context.update({ - 'category_ids': categories.ids, - 'product_type': self.product_type, - 'pricelist_ids': self.pricelist_ids.ids, - 'products_order': self.products_order, - 'categories_order': self.categories_order, - 'only_with_stock': self.only_with_stock, - 'prod_display_type': self.prod_display_type, - 'print_product_uom': self.print_product_uom, - 'category_type': self.category_type, - }) + categories = self.env["product.category"].search([("id", "child_of", categories.ids)]) + context.update( + { + "category_ids": categories.ids, + "product_type": self.product_type, + "pricelist_ids": self.pricelist_ids.ids, + "products_order": self.products_order, + "categories_order": self.categories_order, + "only_with_stock": self.only_with_stock, + "prod_display_type": self.prod_display_type, + "print_product_uom": self.print_product_uom, + "category_type": self.category_type, + } + ) return self.with_context(context) def generate_report(self): - """ Print the catalog - """ + """Print the catalog""" self.ensure_one() self = self.prepare_report() return self.report_id.report_action(self) + + # NUEVO + def get_reported_product_data(self): + self.ensure_one() + domain = [] + if self.category_ids: + categories = self.category_ids + if self.include_sub_categories: + categories = self.env["product.category"].search([("id", "child_of", categories.ids)]) + domain.append(("categ_id", "in", categories.ids)) + + if self.only_with_stock: + domain.append(("qty_available", ">", 0)) + + if self.product_type == "product.template": + templates = self.env["product.template"].search(domain) + variant_count = sum(len(t.product_variant_ids) for t in templates) + return { + "template_count": len(templates), + "variant_count": variant_count, + "product_count": variant_count or len(templates), + "pricelist_count": len(self.pricelist_ids), + } + else: + products = self.env["product.product"].search(domain) + return { + "template_count": 0, + "variant_count": len(products), + "product_count": len(products), + "pricelist_count": len(self.pricelist_ids), + } diff --git a/product_catalog_aeroo_report/wizards/product_catalog_wizard.py b/product_catalog_aeroo_report/wizards/product_catalog_wizard.py index 6cc27ce9c..07260cc48 100644 --- a/product_catalog_aeroo_report/wizards/product_catalog_wizard.py +++ b/product_catalog_aeroo_report/wizards/product_catalog_wizard.py @@ -2,31 +2,80 @@ # For copyright and license notices, see __manifest__.py file in module root # directory ############################################################################## -from odoo import fields, api, models +from odoo import api, fields, models class ProductCatalog(models.TransientModel): - _name = 'product.product_catalog.wizard' - _description = 'Wizard to generate the Product Catalog Report with Aeroo' + _name = "product.product_catalog.wizard" + _description = "Wizard to generate the Product Catalog Report with Aeroo" product_catalog_report_id = fields.Many2one( - 'product.product_catalog_report', - 'Product Catalog', + "product.product_catalog_report", + "Product Catalog", required=True, ) - taxes_included = fields.Boolean( - ) + taxes_included = fields.Boolean() use_planned_price = fields.Boolean( help="Use planned price instead of list price (if planned price module" " is not installed, nothing is going to change)", ) + product_count = fields.Integer("Cantidad de productos", compute="compute_estimated_info", store=True) + pricelist_count = fields.Integer("Cantidad de listas", compute="compute_estimated_info", store=True) + estimated_time = fields.Char("Tiempo estimado", compute="compute_estimated_info", store=True) - @api.onchange('product_catalog_report_id') + @api.onchange("product_catalog_report_id") def change_product_catalog_report(self): self.taxes_included = self.product_catalog_report_id.taxes_included def generate_report(self): self.ensure_one() return self.product_catalog_report_id.with_context( - taxes_included=self.taxes_included, - use_planned_price=self.use_planned_price).generate_report() + taxes_included=self.taxes_included, use_planned_price=self.use_planned_price + ).generate_report() + + @api.onchange("product_catalog_report_id") + def compute_estimated_info(self): + def format_time(seconds): + if seconds < 60: + return "menos de 1 minuto" + elif seconds < 120: + return "más de 1 minuto" + elif seconds < 180: + return "más de 2 minutos" + elif seconds < 240: + return "más de 3 minutos" + elif seconds < 300: + return "más de 4 minutos" + else: + return "más de 5 minutos" + + for rec in self: + report = rec.product_catalog_report_id + + if report.category_type == "public_category": + public_categories = report.public_category_ids + if report.include_sub_categories and public_categories: + public_categories = report.env["product.public.category"].search( + [("id", "child_of", public_categories.ids)] + ) + productos_publicos = self.env["product.template"].search_count( + [("public_categ_ids", "in", public_categories.ids)] + ) + rec.product_count = productos_publicos + + # Estimación ajustada para públicas + TIEMPO_POR_PRODUCTO_PUBLIC = 0.0495 + tiempo_total = productos_publicos * TIEMPO_POR_PRODUCTO_PUBLIC + rec.estimated_time = format_time(tiempo_total) + + else: + categories = report.category_ids + if report.include_sub_categories and categories: + categories = report.env["product.category"].search([("id", "child_of", categories.ids)]) + productos_internos = self.env["product.template"].search_count([("categ_id", "in", categories.ids)]) + rec.product_count = productos_internos + + # Estimación ajustada para internas + TIEMPO_POR_PRODUCTO_INTERNAL = 0.00825 + tiempo_total = productos_internos * TIEMPO_POR_PRODUCTO_INTERNAL + rec.estimated_time = format_time(tiempo_total) diff --git a/product_catalog_aeroo_report/wizards/product_catalog_wizard_views.xml b/product_catalog_aeroo_report/wizards/product_catalog_wizard_views.xml index b6cec252a..90bf4fe1c 100644 --- a/product_catalog_aeroo_report/wizards/product_catalog_wizard_views.xml +++ b/product_catalog_aeroo_report/wizards/product_catalog_wizard_views.xml @@ -10,9 +10,13 @@ + + +