diff --git a/setup/stock_inventory_valuation_report/odoo/addons/stock_inventory_valuation_report b/setup/stock_inventory_valuation_report/odoo/addons/stock_inventory_valuation_report new file mode 120000 index 0000000..663d8c8 --- /dev/null +++ b/setup/stock_inventory_valuation_report/odoo/addons/stock_inventory_valuation_report @@ -0,0 +1 @@ +../../../../stock_inventory_valuation_report \ No newline at end of file diff --git a/setup/stock_inventory_valuation_report/setup.py b/setup/stock_inventory_valuation_report/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/stock_inventory_valuation_report/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_inventory_valuation_report/__manifest__.py b/stock_inventory_valuation_report/__manifest__.py index b43830c..22e4b8c 100644 --- a/stock_inventory_valuation_report/__manifest__.py +++ b/stock_inventory_valuation_report/__manifest__.py @@ -2,22 +2,22 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Stock Inventory Valuation Report', - 'summary': 'Add report button on Inventory Valuation.', - 'version': '12.0.1.1.2', - 'category': 'Warehouse', - 'website': 'https://github.com/OCA/stock-logistics-reporting', - 'author': 'Ecosoft,Odoo Community Association (OCA)', - 'license': 'AGPL-3', - 'depends': [ - 'stock_account', - 'report_xlsx_helper', + "name": "Stock Inventory Valuation Report", + "summary": "Add report button on Inventory Valuation.", + "version": "14.0.1.0.0", + "category": "Warehouse", + "website": "https://github.com/OCA/stock-logistics-reporting", + "author": "Ecosoft,Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": [ + "stock_account", + "report_xlsx_helper", ], - 'data': [ - 'data/paper_format.xml', - 'data/report_data.xml', - 'reports/stock_inventory_valuation_report.xml', - 'wizard/stock_quantity_history_view.xml', + "data": [ + "data/paper_format.xml", + "data/report_data.xml", + "reports/stock_inventory_valuation_report.xml", + "wizard/stock_quantity_history_view.xml", ], - 'installable': True, + "installable": True, } diff --git a/stock_inventory_valuation_report/data/paper_format.xml b/stock_inventory_valuation_report/data/paper_format.xml index 8b793eb..68f416e 100644 --- a/stock_inventory_valuation_report/data/paper_format.xml +++ b/stock_inventory_valuation_report/data/paper_format.xml @@ -2,7 +2,7 @@ Inventory Valuation Report A4 - + A4 0 0 @@ -11,7 +11,7 @@ 28 7 7 - + 24 90 diff --git a/stock_inventory_valuation_report/data/report_data.xml b/stock_inventory_valuation_report/data/report_data.xml index 5300ff3..7abb53e 100644 --- a/stock_inventory_valuation_report/data/report_data.xml +++ b/stock_inventory_valuation_report/data/report_data.xml @@ -3,24 +3,31 @@ Inventory Valuation Report stock_inventory_valuation_report_backend - + - + - + diff --git a/stock_inventory_valuation_report/reports/stock_inventory_valuation_report.py b/stock_inventory_valuation_report/reports/stock_inventory_valuation_report.py index 315a5aa..f0c2b47 100644 --- a/stock_inventory_valuation_report/reports/stock_inventory_valuation_report.py +++ b/stock_inventory_valuation_report/reports/stock_inventory_valuation_report.py @@ -5,21 +5,21 @@ from odoo import api, fields, models class StockInventoryValuationView(models.TransientModel): - _name = 'stock.inventory.valuation.view' - _description = 'Stock Inventory Valuation View' + _name = "stock.inventory.valuation.view" + _description = "Stock Inventory Valuation View" name = fields.Char() reference = fields.Char() barcode = fields.Char() qty_at_date = fields.Float() uom_id = fields.Many2one( - comodel_name='uom.uom', + comodel_name="uom.uom", ) currency_id = fields.Many2one( - comodel_name='res.currency', + comodel_name="res.currency", ) cost_currency_id = fields.Many2one( - comodel_name='res.currency', + comodel_name="res.currency", ) standard_price = fields.Float() stock_value = fields.Float() @@ -27,21 +27,21 @@ class StockInventoryValuationView(models.TransientModel): class StockInventoryValuationReport(models.TransientModel): - _name = 'report.stock.inventory.valuation.report' - _description = 'Stock Inventory Valuation Report' + _name = "report.stock.inventory.valuation.report" + _description = "Stock Inventory Valuation Report" # Filters fields, used for data computation company_id = fields.Many2one( - comodel_name='res.company', + comodel_name="res.company", ) compute_at_date = fields.Integer() date = fields.Datetime() # Data fields, used to browse report data results = fields.Many2many( - comodel_name='stock.inventory.valuation.view', - compute='_compute_results', - help='Use compute fields, so there is nothing store in database', + comodel_name="stock.inventory.valuation.view", + compute="_compute_results", + help="Use compute fields, so there is nothing store in database", ) @api.multi @@ -49,52 +49,61 @@ class StockInventoryValuationReport(models.TransientModel): self.ensure_one() if not self.compute_at_date: self.date = fields.Datetime.now() - products = self.env['product.product'].\ - with_context(dict(to_date=self.date, company_owned=True, - create=False, edit=False)).\ - search([('type', '=', 'product'), ('qty_available', '!=', 0)]) - ReportLine = self.env['stock.inventory.valuation.view'] + products = ( + self.env["product.product"] + .with_context( + dict(to_date=self.date, company_owned=True, create=False, edit=False) + ) + .search([("type", "=", "product"), ("qty_available", "!=", 0)]) + ) + ReportLine = self.env["stock.inventory.valuation.view"] for product in products: standard_price = product.standard_price if self.date: standard_price = product.get_history_price( - self.env.user.company_id.id, - date=self.date) + self.env.user.company_id.id, date=self.date + ) line = { - 'name': product.name, - 'reference': product.default_code, - 'barcode': product.barcode, - 'qty_at_date': product.qty_at_date, - 'uom_id': product.uom_id, - 'currency_id': product.currency_id, - 'cost_currency_id': product.cost_currency_id, - 'standard_price': standard_price, - 'stock_value': product.qty_at_date * standard_price, - 'cost_method': product.cost_method, + "name": product.name, + "reference": product.default_code, + "barcode": product.barcode, + "qty_at_date": product.qty_at_date, + "uom_id": product.uom_id, + "currency_id": product.currency_id, + "cost_currency_id": product.cost_currency_id, + "standard_price": standard_price, + "stock_value": product.qty_at_date * standard_price, + "cost_method": product.cost_method, } if product.qty_at_date != 0: self.results += ReportLine.new(line) @api.multi - def print_report(self, report_type='qweb'): + def print_report(self, report_type="qweb"): self.ensure_one() - action = report_type == 'xlsx' and self.env.ref( - 'stock_inventory_valuation_report.' - 'action_stock_inventory_valuation_report_xlsx') or \ - self.env.ref('stock_inventory_valuation_report.' - 'action_stock_inventory_valuation_report_pdf') + action = ( + report_type == "xlsx" + and self.env.ref( + "stock_inventory_valuation_report." + "action_stock_inventory_valuation_report_xlsx" + ) + or self.env.ref( + "stock_inventory_valuation_report." + "action_stock_inventory_valuation_report_pdf" + ) + ) return action.report_action(self, config=False) def _get_html(self): result = {} rcontext = {} - report = self.browse(self._context.get('active_id')) + report = self.browse(self._context.get("active_id")) if report: - rcontext['o'] = report - result['html'] = self.env.ref( - 'stock_inventory_valuation_report.' - 'report_stock_inventory_valuation_report_html').render( - rcontext) + rcontext["o"] = report + result["html"] = self.env.ref( + "stock_inventory_valuation_report." + "report_stock_inventory_valuation_report_html" + ).render(rcontext) return result @api.model diff --git a/stock_inventory_valuation_report/reports/stock_inventory_valuation_report.xml b/stock_inventory_valuation_report/reports/stock_inventory_valuation_report.xml index c927aba..6b46cd4 100644 --- a/stock_inventory_valuation_report/reports/stock_inventory_valuation_report.xml +++ b/stock_inventory_valuation_report/reports/stock_inventory_valuation_report.xml @@ -1,24 +1,39 @@ - + - - + + - - + + @@ -26,55 +41,77 @@ - Print - Export + Print + Export - - + + - + - + - + Inventory Valuation Report - + - + - + - - + + - - - + + + - + - + Date @@ -83,19 +120,21 @@ - + - + - + - + # @@ -109,36 +148,49 @@ - + - + - + - + - + - + - + - + - + - + diff --git a/stock_inventory_valuation_report/reports/stock_inventory_valuation_report_xlsx.py b/stock_inventory_valuation_report/reports/stock_inventory_valuation_report_xlsx.py index 12e51fd..7801038 100644 --- a/stock_inventory_valuation_report/reports/stock_inventory_valuation_report_xlsx.py +++ b/stock_inventory_valuation_report/reports/stock_inventory_valuation_report_xlsx.py @@ -2,93 +2,95 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import logging + from odoo import models _logger = logging.getLogger(__name__) class ReportStockInventoryValuationReportXlsx(models.TransientModel): - _name = 'report.s_i_v_r.report_stock_inventory_valuation_report_xlsx' - _inherit = 'report.report_xlsx.abstract' + _name = "report.s_i_v_r.report_stock_inventory_valuation_report_xlsx" + _inherit = "report.report_xlsx.abstract" def _get_ws_params(self, wb, data, objects): stock_inventory_valuation_template = { - '1_number': { - 'header': { - 'value': '#', + "1_number": { + "header": { + "value": "#", }, - 'data': { - 'value': self._render('n'), + "data": { + "value": self._render("n"), }, - 'width': 12, + "width": 12, }, - '2_reference': { - 'header': { - 'value': 'Reference', + "2_reference": { + "header": { + "value": "Reference", }, - 'data': { - 'value': self._render('reference'), + "data": { + "value": self._render("reference"), }, - 'width': 15, + "width": 15, }, - '3_name': { - 'header': { - 'value': 'Name', + "3_name": { + "header": { + "value": "Name", }, - 'data': { - 'value': self._render('name'), + "data": { + "value": self._render("name"), }, - 'width': 36, + "width": 36, }, - '4_barcode': { - 'header': { - 'value': 'Barcode', + "4_barcode": { + "header": { + "value": "Barcode", }, - 'data': { - 'value': self._render('barcode'), + "data": { + "value": self._render("barcode"), }, - 'width': 15, + "width": 15, }, - '5_qty_at_date': { - 'header': { - 'value': 'Quantity', + "5_qty_at_date": { + "header": { + "value": "Quantity", }, - 'data': { - 'value': self._render('qty_at_date'), - 'format': self.format_tcell_amount_conditional_right, + "data": { + "value": self._render("qty_at_date"), + "format": self.format_tcell_amount_conditional_right, }, - 'width': 18, + "width": 18, }, - '6_standard_price': { - 'header': { - 'value': 'Cost', + "6_standard_price": { + "header": { + "value": "Cost", }, - 'data': { - 'value': self._render('standard_price'), - 'format': self.format_tcell_amount_conditional_right, + "data": { + "value": self._render("standard_price"), + "format": self.format_tcell_amount_conditional_right, }, - 'width': 18, + "width": 18, }, - '7_stock_value': { - 'header': { - 'value': 'Value', + "7_stock_value": { + "header": { + "value": "Value", }, - 'data': { - 'value': self._render('stock_value'), - 'format': self.format_tcell_amount_conditional_right, + "data": { + "value": self._render("stock_value"), + "format": self.format_tcell_amount_conditional_right, }, - 'width': 18, + "width": 18, }, } ws_params = { - 'ws_name': 'Inventory Valuation Report', - 'generate_ws_method': '_inventory_valuation_report', - 'title': 'Inventory Valuation Report', - 'wanted_list': [k for k in sorted( - stock_inventory_valuation_template.keys())], - 'col_specs': stock_inventory_valuation_template, + "ws_name": "Inventory Valuation Report", + "generate_ws_method": "_inventory_valuation_report", + "title": "Inventory Valuation Report", + "wanted_list": [ + k for k in sorted(stock_inventory_valuation_template.keys()) + ], + "col_specs": stock_inventory_valuation_template, } return [ws_params] @@ -96,8 +98,8 @@ class ReportStockInventoryValuationReportXlsx(models.TransientModel): ws.set_portrait() ws.fit_to_pages(1, 0) - ws.set_header(self.xls_headers['standard']) - ws.set_footer(self.xls_footers['standard']) + ws.set_header(self.xls_headers["standard"]) + ws.set_footer(self.xls_footers["standard"]) self._set_column_width(ws, ws_params) @@ -106,35 +108,47 @@ class ReportStockInventoryValuationReportXlsx(models.TransientModel): for o in objects: ws.write_row( - row_pos, 0, ['Date', 'Partner', 'Tax ID'], - self.format_theader_blue_center) + row_pos, + 0, + ["Date", "Partner", "Tax ID"], + self.format_theader_blue_center, + ) + ws.write_row(row_pos + 1, 0, [o.date or ""], self.format_tcell_date_center) ws.write_row( - row_pos+1, 0, [o.date or ''], self.format_tcell_date_center) - ws.write_row( - row_pos+1, 1, - [o.company_id.name or '', o.company_id.vat or ''], - self.format_tcell_center) + row_pos + 1, + 1, + [o.company_id.name or "", o.company_id.vat or ""], + self.format_tcell_center, + ) row_pos += 3 row_pos = self._write_line( - ws, row_pos, ws_params, col_specs_section='header', - default_format=self.format_theader_blue_center) + ws, + row_pos, + ws_params, + col_specs_section="header", + default_format=self.format_theader_blue_center, + ) ws.freeze_panes(row_pos, 0) total = 0.00 for line in o.results: row_pos = self._write_line( - ws, row_pos, ws_params, col_specs_section='data', + ws, + row_pos, + ws_params, + col_specs_section="data", render_space={ - 'n': row_pos-5, - 'name': line.name or '', - 'reference': line.reference or '', - 'barcode': line.barcode or '', - 'qty_at_date': line.qty_at_date or 0.000, - 'standard_price': line.standard_price or 0.00, - 'stock_value': line.stock_value or 0.00, + "n": row_pos - 5, + "name": line.name or "", + "reference": line.reference or "", + "barcode": line.barcode or "", + "qty_at_date": line.qty_at_date or 0.000, + "standard_price": line.standard_price or 0.00, + "stock_value": line.stock_value or 0.00, }, - default_format=self.format_tcell_left) + default_format=self.format_tcell_left, + ) total += line.stock_value ws.write(row_pos, 6, total, self.format_theader_blue_amount_right) diff --git a/stock_inventory_valuation_report/static/src/css/report.css b/stock_inventory_valuation_report/static/src/css/report.css index 286087b..8b2b949 100644 --- a/stock_inventory_valuation_report/static/src/css/report.css +++ b/stock_inventory_valuation_report/static/src/css/report.css @@ -2,7 +2,7 @@ display: table !important; background-color: white; } -.act_as_row { +.act_as_row { display: table-row !important; page-break-inside: avoid; } @@ -17,9 +17,11 @@ width: 100% !important; } .act_as_row.labels { - background-color: #F0F0F0 !important; + background-color: #f0f0f0 !important; } -.data_table, .total_row, .act_as_row { +.data_table, +.total_row, +.act_as_row { border-left: 0px; border-right: 0px; text-align: center; @@ -30,7 +32,7 @@ padding-bottom: 2px; border-collapse: collapse; } -.data_table .act_as_cell{ +.data_table .act_as_cell { border: 1px solid lightGrey; text-align: center; } @@ -41,7 +43,7 @@ font-weight: bold; } .data_table .total_row { - background-color:#F0F0F0 !important; + background-color: #f0f0f0 !important; border-left: 1px solid lightGrey; border-right: 1px solid lightGrey; border-bottom: 1px solid lightGrey; diff --git a/stock_inventory_valuation_report/static/src/js/stock_inventory_valuation_report_backend.js b/stock_inventory_valuation_report/static/src/js/stock_inventory_valuation_report_backend.js index 9830189..87edaab 100644 --- a/stock_inventory_valuation_report/static/src/js/stock_inventory_valuation_report_backend.js +++ b/stock_inventory_valuation_report/static/src/js/stock_inventory_valuation_report_backend.js @@ -1,112 +1,113 @@ -odoo.define('stock_inventory_valuation_report.stock_inventory_valuation_report_backend', function (require) { - 'use strict'; +odoo.define( + "stock_inventory_valuation_report.stock_inventory_valuation_report_backend", + function (require) { + "use strict"; - var core = require('web.core'); - var Widget = require('web.Widget'); - var ControlPanelMixin = require('web.ControlPanelMixin'); - var ReportWidget = require('web.Widget'); + var core = require("web.core"); + var Widget = require("web.Widget"); + var ControlPanelMixin = require("web.ControlPanelMixin"); + var ReportWidget = require("web.Widget"); - - var report_backend = Widget.extend(ControlPanelMixin, { - // Stores all the parameters of the action. - events: { - 'click .o_stock_inventory_valuation_report_print': 'print', - 'click .o_stock_inventory_valuation_report_export': 'export', - }, - init: function (parent, action) { - this.actionManager = parent; - this.given_context = {}; - this.odoo_context = action.context; - this.controller_url = action.context.url; - if (action.context.context) { - this.given_context = action.context.context; - } - this.given_context.active_id = action.context.active_id || - action.params.active_id; - this.given_context.model = action.context.active_model || false; - this.given_context.ttype = action.context.ttype || false; - return this._super.apply(this, arguments); - }, - willStart: function () { - return $.when(this.get_html()); - }, - set_html: function () { - var self = this; - var def = $.when(); - if (!this.report_widget) { - this.report_widget = new ReportWidget(this, this.given_context); - def = this.report_widget.appendTo(this.$el); - } - def.then(function () { - self.report_widget.$el.html(self.html); - }); - }, - start: function () { - this.set_html(); - return this._super(); - }, - // Fetches the html and is previous report.context if any, - // else create it - get_html: function () { - var self = this; - var defs = []; - return this._rpc({ - model: this.given_context.model, - method: 'get_html', - args: [self.given_context], - context: self.odoo_context, - }) - .then(function (result) { + var report_backend = Widget.extend(ControlPanelMixin, { + // Stores all the parameters of the action. + events: { + "click .o_stock_inventory_valuation_report_print": "print", + "click .o_stock_inventory_valuation_report_export": "export", + }, + init: function (parent, action) { + this.actionManager = parent; + this.given_context = {}; + this.odoo_context = action.context; + this.controller_url = action.context.url; + if (action.context.context) { + this.given_context = action.context.context; + } + this.given_context.active_id = + action.context.active_id || action.params.active_id; + this.given_context.model = action.context.active_model || false; + this.given_context.ttype = action.context.ttype || false; + return this._super.apply(this, arguments); + }, + willStart: function () { + return $.when(this.get_html()); + }, + set_html: function () { + var self = this; + var def = $.when(); + if (!this.report_widget) { + this.report_widget = new ReportWidget(this, this.given_context); + def = this.report_widget.appendTo(this.$el); + } + def.then(function () { + self.report_widget.$el.html(self.html); + }); + }, + start: function () { + this.set_html(); + return this._super(); + }, + // Fetches the html and is previous report.context if any, + // else create it + get_html: function () { + var self = this; + var defs = []; + return this._rpc({ + model: this.given_context.model, + method: "get_html", + args: [self.given_context], + context: self.odoo_context, + }).then(function (result) { self.html = result.html; defs.push(self.update_cp()); return $.when.apply($, defs); }); - }, - // Updates the control panel and render the elements that have yet - // to be rendered - update_cp: function () { - if (this.$buttons) { - var status = { - breadcrumbs: this.actionManager.get_breadcrumbs(), - cp_content: {$buttons: this.$buttons}, - }; - return this.update_control_panel(status); - } - }, - do_show: function () { - this._super(); - this.update_cp(); - }, - print: function () { - var self = this; - this._rpc({ - model: this.given_context.model, - method: 'print_report', - args: [this.given_context.active_id, 'qweb-pdf'], - context: self.odoo_context, - }).then(function (result) { - self.do_action(result); - }); - }, - export: function () { - var self = this; - this._rpc({ - model: this.given_context.model, - method: 'print_report', - args: [this.given_context.active_id, 'xlsx'], - context: self.odoo_context, - }).then(function (result) { - self.do_action(result); - }); - }, - canBeRemoved: function () { - return $.when(); - }, - }); + }, + // Updates the control panel and render the elements that have yet + // to be rendered + update_cp: function () { + if (this.$buttons) { + var status = { + breadcrumbs: this.actionManager.get_breadcrumbs(), + cp_content: {$buttons: this.$buttons}, + }; + return this.update_control_panel(status); + } + }, + do_show: function () { + this._super(); + this.update_cp(); + }, + print: function () { + var self = this; + this._rpc({ + model: this.given_context.model, + method: "print_report", + args: [this.given_context.active_id, "qweb-pdf"], + context: self.odoo_context, + }).then(function (result) { + self.do_action(result); + }); + }, + export: function () { + var self = this; + this._rpc({ + model: this.given_context.model, + method: "print_report", + args: [this.given_context.active_id, "xlsx"], + context: self.odoo_context, + }).then(function (result) { + self.do_action(result); + }); + }, + canBeRemoved: function () { + return $.when(); + }, + }); - core.action_registry.add( - "stock_inventory_valuation_report_backend", - report_backend - ); - return report_backend; -}); + core.action_registry.add( + "stock_inventory_valuation_report_backend", + report_backend + ); + return report_backend; + } +); diff --git a/stock_inventory_valuation_report/tests/test_stock_inventory_valuation_report.py b/stock_inventory_valuation_report/tests/test_stock_inventory_valuation_report.py index ffbd2e2..dd01976 100644 --- a/stock_inventory_valuation_report/tests/test_stock_inventory_valuation_report.py +++ b/stock_inventory_valuation_report/tests/test_stock_inventory_valuation_report.py @@ -1,8 +1,8 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import logging import datetime +import logging from dateutil.relativedelta import relativedelta @@ -13,7 +13,6 @@ _logger = logging.getLogger(__name__) class TestStockInventoryValuation(common.TransactionCase): - def setUp(cls): super(TestStockInventoryValuation, cls).setUp() @@ -31,77 +30,91 @@ class TestStockInventoryValuation(common.TransactionCase): cls.report._compute_results() def test_html(self): - test_reports.try_report(self.env.cr, self.env.uid, - self.qweb_report_name, - [self.report.id], - report_type='qweb-html') + test_reports.try_report( + self.env.cr, + self.env.uid, + self.qweb_report_name, + [self.report.id], + report_type="qweb-html", + ) def test_qweb(self): - test_reports.try_report(self.env.cr, self.env.uid, - self.qweb_report_name, - [self.report.id], - report_type='qweb-pdf') + test_reports.try_report( + self.env.cr, + self.env.uid, + self.qweb_report_name, + [self.report.id], + report_type="qweb-pdf", + ) def test_xlsx(self): - test_reports.try_report(self.env.cr, self.env.uid, - self.xlsx_report_name, - [self.report.id], - report_type='xlsx') + test_reports.try_report( + self.env.cr, + self.env.uid, + self.xlsx_report_name, + [self.report.id], + report_type="xlsx", + ) def test_print(self): - self.report.print_report('qweb') - self.report.print_report('xlsx') + self.report.print_report("qweb") + self.report.print_report("xlsx") def _getReportModel(self): - return self.env['report.stock.inventory.valuation.report'] + return self.env["report.stock.inventory.valuation.report"] def _getQwebReportName(self): - return 'stock_inventory_valuation_report.'\ - 'report_stock_inventory_valuation_report_pdf' + return ( + "stock_inventory_valuation_report." + "report_stock_inventory_valuation_report_pdf" + ) def _getXlsxReportName(self): - return 's_i_v_r.report_stock_inventory_valuation_report_xlsx' + return "s_i_v_r.report_stock_inventory_valuation_report_xlsx" def _getXlsxReportActionName(self): - return 'stock_inventory_valuation_report.'\ - 'action_stock_inventory_valuation_report_xlsx' + return ( + "stock_inventory_valuation_report." + "action_stock_inventory_valuation_report_xlsx" + ) def _getReportTitle(self): - return 'Inventory Valuation Report' + return "Inventory Valuation Report" def _getBaseFilters(self): return { - 'company_id': self.env.user.company_id.id, - 'compute_at_date': 0, - 'date': datetime.datetime.now(), - } + "company_id": self.env.user.company_id.id, + "compute_at_date": 0, + "date": datetime.datetime.now(), + } class TestStockInventoryValuationReport(common.TransactionCase): - def setUp(self): super(TestStockInventoryValuationReport, self).setUp() - self.company_id = self.env.ref('base.main_company') + self.company_id = self.env.ref("base.main_company") self.compute_at_date = 0 self.date = datetime.datetime.now() def test_get_report_html(self): - report = self.env['report.stock.inventory.valuation.report'].create({ - 'company_id': self.company_id.id, - 'compute_at_date': self.compute_at_date, - 'date': self.date, - }) + report = self.env["report.stock.inventory.valuation.report"].create( + { + "company_id": self.company_id.id, + "compute_at_date": self.compute_at_date, + "date": self.date, + } + ) report._compute_results() - report.get_html(given_context={ - 'active_id': report.id - }) + report.get_html(given_context={"active_id": report.id}) def test_wizard(self): - wizard = self.env['stock.quantity.history'].create({ - 'compute_at_date': 0, - 'date': datetime.datetime.now(), - }) - wizard._export('qweb-pdf') + wizard = self.env["stock.quantity.history"].create( + { + "compute_at_date": 0, + "date": datetime.datetime.now(), + } + ) + wizard._export("qweb-pdf") wizard.button_export_html() wizard.button_export_pdf() wizard.button_export_xlsx() @@ -111,84 +124,108 @@ class TestStockInventoryValuationReport(common.TransactionCase): Check that report shows the correct product quantity when specifying a date in the past. """ - product = self.env['product.product'].create({ - 'name': 'test valuation report date', - 'type': 'product', - 'categ_id': self.env.ref('product.product_category_all').id, - }) - stock_location_id = self.ref('stock.stock_location_stock') - partner_id = self.ref('base.res_partner_4') + product = self.env["product.product"].create( + { + "name": "test valuation report date", + "type": "product", + "categ_id": self.env.ref("product.product_category_all").id, + } + ) + stock_location_id = self.ref("stock.stock_location_stock") + partner_id = self.ref("base.res_partner_4") product_qty = 100 date_with_stock = datetime.datetime.now() + relativedelta(days=-1) # Receive the product - receipt = self.env['stock.picking'].create({ - 'location_id': self.ref('stock.stock_location_suppliers'), - 'location_dest_id': stock_location_id, - 'partner_id': partner_id, - 'picking_type_id': self.ref('stock.picking_type_in'), - 'move_lines': [(0, 0, { - 'name': 'Receive product', - 'product_id': product.id, - 'product_uom': product.uom_id.id, - 'product_uom_qty': product_qty, - 'quantity_done': product_qty, - })] - }) + receipt = self.env["stock.picking"].create( + { + "location_id": self.ref("stock.stock_location_suppliers"), + "location_dest_id": stock_location_id, + "partner_id": partner_id, + "picking_type_id": self.ref("stock.picking_type_in"), + "move_lines": [ + ( + 0, + 0, + { + "name": "Receive product", + "product_id": product.id, + "product_uom": product.uom_id.id, + "product_uom_qty": product_qty, + "quantity_done": product_qty, + }, + ) + ], + } + ) receipt.action_confirm() receipt.action_done() receipt.move_lines.date = date_with_stock self.assertEqual( - product.with_context(to_date=date_with_stock).qty_available, - product_qty) + product.with_context(to_date=date_with_stock).qty_available, product_qty + ) self.assertEqual(product.qty_available, product_qty) # Report should have a line with the product and its quantity - report = self.env['report.stock.inventory.valuation.report'].create({ - 'company_id': self.company_id.id, - 'compute_at_date': 0, - }) + report = self.env["report.stock.inventory.valuation.report"].create( + { + "company_id": self.company_id.id, + "compute_at_date": 0, + } + ) product_row = report.results.filtered(lambda r: r.name == product.name) self.assertEqual(len(product_row), 1) self.assertEqual(product_row.qty_at_date, product_qty) # Delivery the product - delivery = self.env['stock.picking'].create({ - 'location_id': stock_location_id, - 'location_dest_id': self.ref('stock.stock_location_customers'), - 'partner_id': partner_id, - 'picking_type_id': self.ref('stock.picking_type_out'), - 'move_lines': [(0, 0, { - 'name': 'Deliver product', - 'product_id': product.id, - 'product_uom': product.uom_id.id, - 'product_uom_qty': product_qty, - 'quantity_done': product_qty, - })] - }) + delivery = self.env["stock.picking"].create( + { + "location_id": stock_location_id, + "location_dest_id": self.ref("stock.stock_location_customers"), + "partner_id": partner_id, + "picking_type_id": self.ref("stock.picking_type_out"), + "move_lines": [ + ( + 0, + 0, + { + "name": "Deliver product", + "product_id": product.id, + "product_uom": product.uom_id.id, + "product_uom_qty": product_qty, + "quantity_done": product_qty, + }, + ) + ], + } + ) delivery.action_confirm() delivery.action_done() self.assertEqual( - product.with_context(to_date=date_with_stock).qty_available, - product_qty) + product.with_context(to_date=date_with_stock).qty_available, product_qty + ) self.assertEqual(product.qty_available, 0) # Report should not have a line with the product # because it is not available - report = self.env['report.stock.inventory.valuation.report'].create({ - 'company_id': self.company_id.id, - 'compute_at_date': 0, - }) + report = self.env["report.stock.inventory.valuation.report"].create( + { + "company_id": self.company_id.id, + "compute_at_date": 0, + } + ) product_row = report.results.filtered(lambda r: r.name == product.name) self.assertFalse(product_row) # Report computed specifying the date # when there was stock should have the product and its quantity - report = self.env['report.stock.inventory.valuation.report'].create({ - 'company_id': self.company_id.id, - 'compute_at_date': 1, - 'date': date_with_stock, - }) + report = self.env["report.stock.inventory.valuation.report"].create( + { + "company_id": self.company_id.id, + "compute_at_date": 1, + "date": date_with_stock, + } + ) product_row = report.results.filtered(lambda r: r.name == product.name) self.assertEqual(len(product_row), 1) self.assertEqual(product_row.qty_at_date, product_qty) diff --git a/stock_inventory_valuation_report/wizard/stock_quantity_history.py b/stock_inventory_valuation_report/wizard/stock_quantity_history.py index c3360a9..e4d0663 100644 --- a/stock_inventory_valuation_report/wizard/stock_quantity_history.py +++ b/stock_inventory_valuation_report/wizard/stock_quantity_history.py @@ -2,51 +2,52 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import api, models -from odoo.tools.safe_eval import safe_eval from odoo.tools import pycompat +from odoo.tools.safe_eval import safe_eval class StockQuantityHistory(models.TransientModel): - _inherit = 'stock.quantity.history' + _inherit = "stock.quantity.history" @api.multi def button_export_html(self): self.ensure_one() action = self.env.ref( - 'stock_inventory_valuation_report.' - 'action_stock_inventory_valuation_report_html') + "stock_inventory_valuation_report." + "action_stock_inventory_valuation_report_html" + ) vals = action.read()[0] - context1 = vals.get('context', {}) + context1 = vals.get("context", {}) if isinstance(context1, pycompat.string_types): context1 = safe_eval(context1) - model = self.env['report.stock.inventory.valuation.report'] + model = self.env["report.stock.inventory.valuation.report"] report = model.create(self._prepare_stock_inventory_valuation_report()) - context1['active_id'] = report.id - context1['active_ids'] = report.ids - vals['context'] = context1 + context1["active_id"] = report.id + context1["active_ids"] = report.ids + vals["context"] = context1 return vals @api.multi def button_export_pdf(self): self.ensure_one() - report_type = 'qweb-pdf' + report_type = "qweb-pdf" return self._export(report_type) @api.multi def button_export_xlsx(self): self.ensure_one() - report_type = 'xlsx' + report_type = "xlsx" return self._export(report_type) def _prepare_stock_inventory_valuation_report(self): self.ensure_one() return { - 'company_id': self.env.user.company_id.id, - 'compute_at_date': self.compute_at_date, - 'date': self.date, + "company_id": self.env.user.company_id.id, + "compute_at_date": self.compute_at_date, + "date": self.date, } def _export(self, report_type): - model = self.env['report.stock.inventory.valuation.report'] + model = self.env["report.stock.inventory.valuation.report"] report = model.create(self._prepare_stock_inventory_valuation_report()) return report.print_report(report_type) diff --git a/stock_inventory_valuation_report/wizard/stock_quantity_history_view.xml b/stock_inventory_valuation_report/wizard/stock_quantity_history_view.xml index 5e73abc..769e498 100644 --- a/stock_inventory_valuation_report/wizard/stock_quantity_history_view.xml +++ b/stock_inventory_valuation_report/wizard/stock_quantity_history_view.xml @@ -3,12 +3,12 @@ view_stock_quantity_history_inherit stock.quantity.history - + - - - + + +