diff --git a/addons/stock/__init__.py b/addons/stock/__init__.py index f506abac..5138ca84 100644 --- a/addons/stock/__init__.py +++ b/addons/stock/__init__.py @@ -5,9 +5,8 @@ from . import controllers from . import models from . import report from . import wizard - - -from flectra import api, SUPERUSER_ID +from flectra import api +from flectra.api import Environment, SUPERUSER_ID # TODO: Apply proper fix & remove in master @@ -17,3 +16,13 @@ def pre_init_hook(cr): ('model', 'like', '%stock%'), ('module', '=', 'stock') ]).unlink() + + +def post_init_check(cr, registery): + env = Environment(cr, SUPERUSER_ID, {}) + move_obj = env['stock.move'] + move_ids = move_obj.search([]) + move_ids.set_move_type() + done_moves = move_obj.search([('state', '=', 'done')], order='date') + done_moves.check_move_bal_qty() + return True diff --git a/addons/stock/__manifest__.py b/addons/stock/__manifest__.py index 908cf27f..dee8cbe1 100644 --- a/addons/stock/__manifest__.py +++ b/addons/stock/__manifest__.py @@ -86,4 +86,5 @@ 'application': True, 'auto_install': False, 'pre_init_hook': 'pre_init_hook', + 'post_init_hook': 'post_init_check', } diff --git a/addons/stock/models/stock_location.py b/addons/stock/models/stock_location.py index 5f20bf2e..b569bd56 100644 --- a/addons/stock/models/stock_location.py +++ b/addons/stock/models/stock_location.py @@ -25,6 +25,13 @@ class Location(models.Model): res['barcode'] = res['complete_name'] return res + def _should_be_valued(self): + self.ensure_one() + if self.usage == 'internal' or ( + self.usage == 'transit' and self.company_id): + return True + return False + name = fields.Char('Location Name', required=True, translate=True) complete_name = fields.Char("Full Location Name", compute='_compute_complete_name', store=True) active = fields.Boolean('Active', default=True, help="By unchecking the active field, you may hide a location without deleting it.") diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 6ac00aa9..3b05bd53 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -159,6 +159,9 @@ class StockMove(models.Model): is_quantity_done_editable = fields.Boolean('Is quantity done editable', compute='_compute_is_quantity_done_editable') reference = fields.Char(compute='_compute_reference', string="Reference", store=True) has_move_lines = fields.Boolean(compute='_compute_has_move_lines') + out_qty = fields.Float("Out Qty") + bal_qty = fields.Float("Balance") + move_type = fields.Selection([('in', 'In'), ('out', 'Out')], "Move type") branch_id = fields.Many2one( related='location_id.branch_id', store=True, string='Source Location Branch', @@ -394,6 +397,17 @@ class StockMove(models.Model): move.location_id.name, move.location_dest_id.name))) return res + def set_move_type(self): + for self in self: + if self.picking_type_id and self.picking_type_id.code == 'incoming' or\ + not self.location_id._should_be_valued() and \ + self.location_dest_id._should_be_valued(): + self.move_type = 'in' + elif self.picking_type_id and self.picking_type_id.code == 'outgoing' \ + or self.location_id._should_be_valued() and not \ + self.location_dest_id._should_be_valued(): + self.move_type = 'out' + @api.model def create(self, vals): # TDE CLEANME: why doing this tracking on picking here ? seems weird @@ -403,6 +417,7 @@ class StockMove(models.Model): initial_values = {picking.id: {'state': picking.state}} vals['ordered_qty'] = vals.get('product_uom_qty') res = super(StockMove, self).create(vals) + res.set_move_type() if perform_tracking: picking.message_track(picking.fields_get(['state']), initial_values) return res @@ -1045,6 +1060,28 @@ class StockMove(models.Model): break return extra_move + def check_move_bal_qty(self): + for move in self: + if move.move_type == 'in': + move.bal_qty = move.product_uom_qty + if move.move_type == 'out': + prev_in_moves = self.search([ + ('product_id', '=', move.product_id.id), + ('state', '=', 'done'), + ('move_type', '=', 'in'), + ('bal_qty', '>', '0'), + ], order='date') + rem_qty = move.product_uom_qty + for pre_move in prev_in_moves: + if rem_qty: + pre_move.out_qty = move.product_uom_qty + if rem_qty > pre_move.bal_qty: + rem_qty -= pre_move.bal_qty + pre_move.bal_qty = 0 + else: + pre_move.bal_qty -= rem_qty + rem_qty -= rem_qty + def _action_done(self): self.filtered(lambda move: move.state == 'draft')._action_confirm() # MRP allows scrapping draft moves @@ -1105,6 +1142,9 @@ class StockMove(models.Model): if picking: picking._create_backorder() + #calculate balance quantity & out qty to track the age of each stock + moves_todo.check_move_bal_qty() + return moves_todo def unlink(self): diff --git a/addons/stock/views/stock_move_views.xml b/addons/stock/views/stock_move_views.xml index 24321c38..db7bea48 100644 --- a/addons/stock/views/stock_move_views.xml +++ b/addons/stock/views/stock_move_views.xml @@ -238,6 +238,9 @@ + + + diff --git a/addons/stock_ageing_report/__init__.py b/addons/stock_ageing_report/__init__.py new file mode 100644 index 00000000..e2c04cfe --- /dev/null +++ b/addons/stock_ageing_report/__init__.py @@ -0,0 +1,5 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from . import wizard +from . import report +from . import models diff --git a/addons/stock_ageing_report/__manifest__.py b/addons/stock_ageing_report/__manifest__.py new file mode 100644 index 00000000..3bb1bea8 --- /dev/null +++ b/addons/stock_ageing_report/__manifest__.py @@ -0,0 +1,31 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Stock Ageing Report', + 'version': '1.0', + 'category': 'Stock', + 'author': 'FlectraHQ', + 'website': "https://flectrahq.com", + 'depends': ['stock'], + 'sequence': 40, + 'summary': """Stock Ageing Report to display + product's stock by ageing period.""", + 'description': """ +Main Features +------------- +Stock Ageing Reports. +An Ageing Analysis Report in Flectra displays the age of the stock in hand. +This report lists the age-wise break-up of Inventory to point out old stock. +Flectra gives its users the flexibility to define their own ageing slabs. +""", + 'data': [ + 'wizard/stock_ageing_wizard_view.xml', + 'report/stock_ageing_report_view.xml', + 'report/stock_ageing_report_template.xml', + ], + 'demo': [], + 'qweb': [], + 'auto_install': False, + 'installable': True, + 'application': False, +} diff --git a/addons/stock_ageing_report/i18n/stock_ageing_report.pot b/addons/stock_ageing_report/i18n/stock_ageing_report.pot new file mode 100644 index 00000000..7d0b2f08 --- /dev/null +++ b/addons/stock_ageing_report/i18n/stock_ageing_report.pot @@ -0,0 +1,189 @@ +# Translation of Flectra Server. +# This file contains the translation of the following modules: +# * stock_ageing_report +# +msgid "" +msgstr "" +"Project-Id-Version: Flectra Server 1.2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-05-15 11:07+0000\n" +"PO-Revision-Date: 2018-05-15 11:07+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Brnach: " +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Company: " +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Date: " +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Location: " +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Period Length(days): " +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Product Category: " +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Warehouse: " +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_branch_id +msgid "Branch" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_wizard_form_view +msgid "Cancel" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,help:stock_ageing_report.field_stock_ageing_wizard_date +msgid "Choose a date to get the inventory ageing report" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_company_id +msgid "Company" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_create_uid +msgid "Created by" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_create_date +msgid "Created on" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_date +msgid "Date" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_report_stock_ageing_report_stock_ageing_report_template_display_name +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_display_name +msgid "Display Name" +msgstr "" + +#. module: stock_ageing_report +#: code:addons/stock_ageing_report/report/stock_ageing_report.py:17 +#, python-format +msgid "Form content is missing, this report cannot be printed." +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_report_stock_ageing_report_stock_ageing_report_template_id +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_id +msgid "ID" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model,name:stock_ageing_report.model_stock_location +msgid "Inventory Locations" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_report_stock_ageing_report_stock_ageing_report_template___last_update +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard___last_update +msgid "Last Modified on" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_write_uid +msgid "Last Updated by" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_write_date +msgid "Last Updated on" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_location_ids +msgid "Location" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_period_length +msgid "Period Length (days)" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_wizard_form_view +msgid "Print" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_product_ids +msgid "Product" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_product_category_ids +msgid "Product Category" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Products" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_wizard_form_view +msgid "Select following details" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.actions.act_window,name:stock_ageing_report.action_stock_ageing_wizard +#: model:ir.actions.report,name:stock_ageing_report.action_stock_ageing_report +#: model:ir.ui.menu,name:stock_ageing_report.stock_ageing_wizard_menu +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Stock Ageing Report" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.ui.view,arch_db:stock_ageing_report.stock_ageing_report_template +msgid "Total" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model.fields,field_description:stock_ageing_report.field_stock_ageing_wizard_warehouse_ids +msgid "Warehouse" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model,name:stock_ageing_report.model_stock_ageing_wizard +msgid "Wizard that opens the stock ageing" +msgstr "" + +#. module: stock_ageing_report +#: model:ir.model,name:stock_ageing_report.model_report_stock_ageing_report_stock_ageing_report_template +msgid "report.stock_ageing_report.stock_ageing_report_template" +msgstr "" + diff --git a/addons/stock_ageing_report/models/__init__.py b/addons/stock_ageing_report/models/__init__.py new file mode 100644 index 00000000..6bb763b0 --- /dev/null +++ b/addons/stock_ageing_report/models/__init__.py @@ -0,0 +1,3 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from . import stock_location diff --git a/addons/stock_ageing_report/models/stock_location.py b/addons/stock_ageing_report/models/stock_location.py new file mode 100644 index 00000000..9618aa46 --- /dev/null +++ b/addons/stock_ageing_report/models/stock_location.py @@ -0,0 +1,26 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from flectra import models, api + + +class Location(models.Model): + _inherit = "stock.location" + + @api.model + def name_search(self, name='', args=None, operator='ilike', limit=100): + args = args or [] + domain = [] + + if self.env.context.get('warehouse', False): + warehouse_ids = self.env['stock.warehouse'].browse( + self.env.context['warehouse'][0][2]) + lot_stock_ids = [wh.lot_stock_id.id for wh in warehouse_ids + if wh.lot_stock_id] + location_ids = self.env['stock.location'].search( + [('location_id', 'child_of', lot_stock_ids), + ('usage', '=', 'internal')]).ids + location_ids += lot_stock_ids + domain = [('id', 'in', location_ids)] + + recs = self.search(domain + args, limit=limit) + return recs.name_get() diff --git a/addons/stock_ageing_report/report/__init__.py b/addons/stock_ageing_report/report/__init__.py new file mode 100644 index 00000000..12976133 --- /dev/null +++ b/addons/stock_ageing_report/report/__init__.py @@ -0,0 +1,3 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from . import stock_ageing_report diff --git a/addons/stock_ageing_report/report/stock_ageing_report.py b/addons/stock_ageing_report/report/stock_ageing_report.py new file mode 100644 index 00000000..8e0fb5c5 --- /dev/null +++ b/addons/stock_ageing_report/report/stock_ageing_report.py @@ -0,0 +1,161 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from flectra import api, models, _ +from flectra.exceptions import UserError +from datetime import datetime, timedelta +from flectra.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT + + +class StockAgeingReport(models.AbstractModel): + _name = 'report.stock_ageing_report.stock_ageing_report_template' + + @api.model + def get_report_values(self, docids, data=None): + if not data.get('form') or not self.env.context.get( + 'active_model') or not self.env.context.get('active_id'): + raise UserError( + _("Form content is missing, this report cannot be printed.")) + report = self.env['ir.actions.report']._get_report_from_name( + 'stock_ageing_report.action_stock_ageing_report') + get_data = self._get_data(data) + return { + 'doc_ids': docids, + 'doc_model': report.model, + 'docs': self, + 'data': { + 'company': [get_data['company_id']], + 'branch': [get_data['branch_id']], + 'warehouse': [get_data['warehouse_id']], + 'location': [get_data['location_id']], + 'product_category': [get_data['product_category_id']], + 'product': [get_data['product_id']], + 'period_length': [get_data['period_length']], + 'date': [get_data['date']], + 'period_list': get_data['period_list'], + 'product_list': get_data['product_list'] + } + } + + def _get_product_wise_detail(self, product_ids, location_id, date, + period_length, branch_id, company_id): + product_list = [] + date_1 = datetime.strftime(date, DATETIME_FORMAT) + date_2 = datetime.strftime( + date - timedelta(days=period_length), DATETIME_FORMAT) + date_3 = datetime.strftime( + date - timedelta(days=(period_length * 2)), DATETIME_FORMAT) + date_4 = datetime.strftime( + date - timedelta(days=(period_length * 3)), DATETIME_FORMAT) + date_5 = datetime.strftime( + date - timedelta(days=(period_length * 4)), DATETIME_FORMAT) + date_period = [date_1, date_2, date_3, date_4, date_5] + final_dates = [ + (date, date_period[date_period.index(date) + 1] if + date_period.index(date) < 4 else date) + for date in date_period] + for product in product_ids: + qty_period_list = self.calculate_virtual_qty( + product, location_id, branch_id, company_id, final_dates) + product_dict = {'product_id': product.name_get()[0][1], + 'qty_period_list': qty_period_list, + 'qty_available': sum(qty_period_list)} + product_list.append(product_dict) + return product_list + + def calculate_virtual_qty(self, product, location_id, branch_id, + company_id, date_range): + product_list = [] + quant_obj = self.env['stock.quant'] + move_obj = self.env['stock.move'] + for date in date_range: + domain = [] + to_date = False + from_date = date[0] + if date[0] != date[1]: + to_date = date[1] + domain += [('product_id', '=', product.id)] + if product.tracking != 'none': + domain += [('location_id', 'in', location_id.ids), + ('in_date', '<=', from_date), + ('branch_id', '=', branch_id.id), + ('company_id', '=', company_id.id)] + if to_date: + domain += [('in_date', '>', to_date)] + virtual_available = sum( + [quant.quantity for quant in quant_obj.search(domain)]) + print ("\n domain", domain) + else: + domain += ['|', ('location_id', 'in', location_id.ids), + ('location_dest_id', 'in', location_id.ids), + ('state', '=', 'done'), ('bal_qty', '>', 0), + ('date', '<=', from_date), + ('branch_dest_id', '=', branch_id.id), + ('company_id', '=', company_id.id)] + if to_date: + domain += [('date', '>', to_date)] + virtual_available = sum( + [move.bal_qty for move in move_obj.search(domain)]) + product_list.append(virtual_available) + return product_list + + def _get_data(self, data): + domain = [] + company_id = self.env['res.company'].browse(data['form']['company_id']) + branch_id = self.env['res.branch'].browse(data['form']['branch_id']) + warehouse_id = self.env['stock.warehouse'].browse( + data['form']['warehouse_id']) + location_id = self.env['stock.location'].browse( + data['form']['location_id']) + product_category_id = self.env['product.category'].browse( + data['form']['product_category_id']) + product_id = self.env['product.product'].browse( + data['form']['product_id']) + if not location_id: + location_id = self.env['stock.location'].search([ + ('company_id', '=', company_id.id), + ('usage', '=', 'internal')]) + period_length = data['form']['period_length'] + date = datetime.strptime(data['form']['date'], DATETIME_FORMAT) + + if product_id: + domain += [('id', 'in', product_id.ids)] + elif product_category_id: + domain += [('categ_id', 'in', product_category_id.ids), + ('type', '=', 'product')] + else: + domain += [('qty_available', '>', 0)] + product_ids = self.env['product.product'].search(domain) + product_list = self._get_product_wise_detail( + product_ids, location_id, date, period_length, branch_id, + company_id) + warehouse = location = product_category = '' + if warehouse_id: + warehouse = ','.join( + wh.name_get()[0][1] for wh in + warehouse_id) if len(warehouse_id) > 1 else\ + warehouse_id.name_get()[0][1] + if data['form']['location_id']: + location = ','.join(loc.name_get()[0][1] for loc in location_id) \ + if len(location_id) > 1 else location_id.name_get()[0][1] or '' + if product_category_id: + product_category = ','.join( + categ.name_get()[0][1] for categ in product_category_id + ) if len(product_category_id) > 1 else\ + product_category_id.name_get()[0][1] or '' + period_list = ['0 - ' + str(period_length), + str(period_length) + ' - ' + str(period_length * 2), + str(period_length * 2) + ' - ' + str(period_length * 3), + str(period_length * 3) + ' - ' + str(period_length * 4), + ' + ' + str(period_length * 4)] + data['form'].update({ + 'company_id': company_id, + 'branch_id': branch_id, + 'warehouse_id': warehouse or '', + 'location_id': location or '', + 'product_category_id': product_category or '', + 'product_id': product_id or '', + 'period_length': period_length, + 'date': datetime.strftime(date, DATETIME_FORMAT), + 'period_list': period_list, + 'product_list': product_list}) + return data['form'] diff --git a/addons/stock_ageing_report/report/stock_ageing_report_template.xml b/addons/stock_ageing_report/report/stock_ageing_report_template.xml new file mode 100644 index 00000000..e142204b --- /dev/null +++ b/addons/stock_ageing_report/report/stock_ageing_report_template.xml @@ -0,0 +1,86 @@ + + + + \ No newline at end of file diff --git a/addons/stock_ageing_report/report/stock_ageing_report_view.xml b/addons/stock_ageing_report/report/stock_ageing_report_view.xml new file mode 100644 index 00000000..74b0e4c7 --- /dev/null +++ b/addons/stock_ageing_report/report/stock_ageing_report_view.xml @@ -0,0 +1,27 @@ + + + + + + Stock Ageing Report Format + + A4 + 0 + 0 + Portrait + 40 + 23 + 7 + 7 + + 40 + 90 + + + + 'stock_ageing'+'-'+(object.name) + + + \ No newline at end of file diff --git a/addons/stock_ageing_report/static/description/icon.png b/addons/stock_ageing_report/static/description/icon.png new file mode 100644 index 00000000..cd4caac2 Binary files /dev/null and b/addons/stock_ageing_report/static/description/icon.png differ diff --git a/addons/stock_ageing_report/tests/__init__.py b/addons/stock_ageing_report/tests/__init__.py new file mode 100644 index 00000000..ed0b1b9c --- /dev/null +++ b/addons/stock_ageing_report/tests/__init__.py @@ -0,0 +1,3 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from . import test_stock_ageing_report diff --git a/addons/stock_ageing_report/tests/test_stock_ageing_report.py b/addons/stock_ageing_report/tests/test_stock_ageing_report.py new file mode 100644 index 00000000..1caf0bed --- /dev/null +++ b/addons/stock_ageing_report/tests/test_stock_ageing_report.py @@ -0,0 +1,29 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from flectra.tests.common import TransactionCase +from datetime import date, timedelta + + +class TestStockAgeingReport(TransactionCase): + def setUp(self): + super(TestStockAgeingReport, self).setUp() + self.location = self.env['stock.location'] + self.location_barcode = self.env.ref('stock.stock_location_3') + self.barcode = self.location_barcode.barcode + self.warehouse = self.env["stock.warehouse"] + + def test_20_stock_ageing_report(self): + # Print the Stock Ageing Report through the wizard + data_dict = { + 'company_id': [], + 'warehouse_ids': [], + 'location_ids': [], + 'product_category_ids': [(6, 0, [self.env.ref( + 'product.product_category_5').id])], + 'product_ids': [(6, 0, [self.env.ref( + 'product.product_product_5b').id])], + 'period_length': 30, + 'date': date.today() - timedelta(days=30), + } + wizard = self.env['stock.ageing.wizard'].create(data_dict) + wizard.with_context(data_dict).print_report() diff --git a/addons/stock_ageing_report/wizard/__init__.py b/addons/stock_ageing_report/wizard/__init__.py new file mode 100644 index 00000000..c8c4a5ba --- /dev/null +++ b/addons/stock_ageing_report/wizard/__init__.py @@ -0,0 +1,3 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from . import stock_ageing_wizard diff --git a/addons/stock_ageing_report/wizard/stock_ageing_wizard.py b/addons/stock_ageing_report/wizard/stock_ageing_wizard.py new file mode 100644 index 00000000..21c0710c --- /dev/null +++ b/addons/stock_ageing_report/wizard/stock_ageing_wizard.py @@ -0,0 +1,55 @@ +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from flectra import api, models, fields + + +class StockAgeingWizard(models.TransientModel): + + _name = 'stock.ageing.wizard' + _description = 'Wizard that opens the stock ageing' + + company_id = fields.Many2one('res.company', string="Company", + default=lambda self: self.env.user.company_id) + branch_id = fields.Many2one('res.branch', string="Branch", + default=lambda self: + self.env.user.default_branch_id) + warehouse_ids = fields.Many2many("stock.warehouse", string="Warehouse") + location_ids = fields.Many2many("stock.location", string='Location', + domain="[('usage', '=', 'internal')]") + product_category_ids = fields.Many2many("product.category", + string="Product Category") + product_ids = fields.Many2many('product.product', string='Product', + domain="[('type', '=', 'product')]") + period_length = fields.Integer(string='Period Length (days)', default=30) + date = fields.Datetime(string="Date", + help="Choose a date to get the inventory ageing " + "report", + default=fields.Datetime.now()) + + @api.multi + def print_report(self): + """ + To get the Stock Ageing report and print the report + @return : return stock ageing report + """ + datas = {'ids': self._context.get('active_ids', [])} + res = self.read( + ['company_id', 'branch_id', 'warehouse_ids', 'location_ids', + 'product_category_ids', 'product_ids', + 'period_length', 'date']) + for ageing_dict in res: + res = res and res[0] or {} + res['company_id'] = ageing_dict['company_id'] and\ + ageing_dict['company_id'][0] or False + res['branch_id'] = ageing_dict['branch_id'] and \ + ageing_dict['branch_id'][0] or False + res['warehouse_id'] = ageing_dict['warehouse_ids'] + res['location_id'] = ageing_dict['location_ids'] + res['product_category_id'] = ageing_dict['product_category_ids'] + res['product_id'] = ageing_dict['product_ids'] + res['period_length'] = ageing_dict['period_length'] or False + res['date'] = ageing_dict['date'] or False + datas['form'] = res + return self.env.ref( + 'stock_ageing_report.action_stock_ageing_report' + '').report_action(self, data=datas) diff --git a/addons/stock_ageing_report/wizard/stock_ageing_wizard_view.xml b/addons/stock_ageing_report/wizard/stock_ageing_wizard_view.xml new file mode 100644 index 00000000..5da2fe1d --- /dev/null +++ b/addons/stock_ageing_report/wizard/stock_ageing_wizard_view.xml @@ -0,0 +1,50 @@ + + + + + Stock Ageing Wizard Form + stock.ageing.wizard + +
+ + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + Stock Ageing Report + stock.ageing.wizard + form + form + {'company_id': context.get('company_id', False), 'warehouse_id': + context.get('warehouse_ids', False), 'location_id': context.get('location_ids', False), + 'product_category_id': context.get('product_category_ids', False), 'product_id': + context.get('product_ids', False), 'period_length': context.get('period_length', False), 'date': + context.get('date', False)} + + new + + + + +