[IMP] stock_card_report: black, isort

This commit is contained in:
ps-tubtim
2020-03-20 09:54:33 +07:00
parent a6640963a1
commit eb3f0e9002
5 changed files with 364 additions and 340 deletions

View File

@@ -2,23 +2,19 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'Stock Card Report', "name": "Stock Card Report",
'summary': 'Add stock card report on Inventory Reporting.', "summary": "Add stock card report on Inventory Reporting.",
'version': '12.0.1.0.0', "version": "13.0.1.0.0",
'category': 'Warehouse', "category": "Warehouse",
'website': 'https://github.com/OCA/stock-logistics-reporting', "website": "https://github.com/OCA/stock-logistics-reporting",
'author': 'Ecosoft,Odoo Community Association (OCA)', "author": "Ecosoft, Odoo Community Association (OCA)",
'license': 'AGPL-3', "license": "AGPL-3",
'depends': [ "depends": ["stock", "date_range", "report_xlsx_helper"],
'stock', "data": [
'date_range', "data/paper_format.xml",
'report_xlsx_helper', "data/report_data.xml",
"reports/stock_card_report.xml",
"wizard/stock_card_report_wizard_view.xml",
], ],
'data': [ "installable": True,
'data/paper_format.xml',
'data/report_data.xml',
'reports/stock_card_report.xml',
'wizard/stock_card_report_wizard_view.xml',
],
'installable': True,
} }

View File

@@ -5,52 +5,50 @@ from odoo import api, fields, models
class StockCardView(models.TransientModel): class StockCardView(models.TransientModel):
_name = 'stock.card.view' _name = "stock.card.view"
_description = 'Stock Card View' _description = "Stock Card View"
_order = 'date' _order = "date"
date = fields.Datetime() date = fields.Datetime()
product_id = fields.Many2one(comodel_name='product.product') product_id = fields.Many2one(comodel_name="product.product")
product_qty = fields.Float() product_qty = fields.Float()
product_uom_qty = fields.Float() product_uom_qty = fields.Float()
product_uom = fields.Many2one(comodel_name='uom.uom') product_uom = fields.Many2one(comodel_name="uom.uom")
reference = fields.Char() reference = fields.Char()
location_id = fields.Many2one(comodel_name='stock.location') location_id = fields.Many2one(comodel_name="stock.location")
location_dest_id = fields.Many2one(comodel_name='stock.location') location_dest_id = fields.Many2one(comodel_name="stock.location")
is_initial = fields.Boolean() is_initial = fields.Boolean()
product_in = fields.Float() product_in = fields.Float()
product_out = fields.Float() product_out = fields.Float()
class StockCardReport(models.TransientModel): class StockCardReport(models.TransientModel):
_name = 'report.stock.card.report' _name = "report.stock.card.report"
_description = 'Stock Card Report' _description = "Stock Card Report"
# Filters fields, used for data computation # Filters fields, used for data computation
date_from = fields.Date() date_from = fields.Date()
date_to = fields.Date() date_to = fields.Date()
product_ids = fields.Many2many( product_ids = fields.Many2many(comodel_name="product.product")
comodel_name='product.product', location_id = fields.Many2one(comodel_name="stock.location")
)
location_id = fields.Many2one(
comodel_name='stock.location',
)
# Data fields, used to browse report data # Data fields, used to browse report data
results = fields.Many2many( results = fields.Many2many(
comodel_name='stock.card.view', comodel_name="stock.card.view",
compute='_compute_results', compute="_compute_results",
help='Use compute fields, so there is nothing store in database', help="Use compute fields, so there is nothing store in database",
) )
@api.multi @api.multi
def _compute_results(self): def _compute_results(self):
self.ensure_one() self.ensure_one()
date_from = self.date_from or '0001-01-01' date_from = self.date_from or "0001-01-01"
self.date_to = self.date_to or fields.Date.context_today(self) self.date_to = self.date_to or fields.Date.context_today(self)
locations = self.env['stock.location'].search( locations = self.env["stock.location"].search(
[('id', 'child_of', [self.location_id.id])]) [("id", "child_of", [self.location_id.id])]
self._cr.execute(""" )
self._cr.execute(
"""
SELECT move.date, move.product_id, move.product_qty, SELECT move.date, move.product_id, move.product_qty,
move.product_uom_qty, move.product_uom, move.reference, move.product_uom_qty, move.product_uom, move.reference,
move.location_id, move.location_dest_id, move.location_id, move.location_dest_id,
@@ -64,37 +62,46 @@ class StockCardReport(models.TransientModel):
and move.state = 'done' and move.product_id in %s and move.state = 'done' and move.product_id in %s
and CAST(move.date AS date) <= %s and CAST(move.date AS date) <= %s
ORDER BY move.date, move.reference ORDER BY move.date, move.reference
""", ( """,
tuple(locations.ids), tuple(locations.ids), date_from, (
tuple(locations.ids), tuple(locations.ids), tuple(locations.ids),
tuple(self.product_ids.ids), self.date_to)) tuple(locations.ids),
date_from,
tuple(locations.ids),
tuple(locations.ids),
tuple(self.product_ids.ids),
self.date_to,
),
)
stock_card_results = self._cr.dictfetchall() stock_card_results = self._cr.dictfetchall()
ReportLine = self.env['stock.card.view'] ReportLine = self.env["stock.card.view"]
self.results = [ReportLine.new(line).id for line in stock_card_results] self.results = [ReportLine.new(line).id for line in stock_card_results]
@api.multi @api.multi
def _get_initial(self, product_line): def _get_initial(self, product_line):
product_input_qty = sum(product_line.mapped('product_in')) product_input_qty = sum(product_line.mapped("product_in"))
product_output_qty = sum(product_line.mapped('product_out')) product_output_qty = sum(product_line.mapped("product_out"))
return product_input_qty - product_output_qty return product_input_qty - product_output_qty
@api.multi @api.multi
def print_report(self, report_type='qweb'): def print_report(self, report_type="qweb"):
self.ensure_one() self.ensure_one()
action = report_type == 'xlsx' and self.env.ref( action = (
'stock_card_report.action_stock_card_report_xlsx') or \ report_type == "xlsx"
self.env.ref('stock_card_report.action_stock_card_report_pdf') and self.env.ref("stock_card_report.action_stock_card_report_xlsx")
or self.env.ref("stock_card_report.action_stock_card_report_pdf")
)
return action.report_action(self, config=False) return action.report_action(self, config=False)
def _get_html(self): def _get_html(self):
result = {} result = {}
rcontext = {} rcontext = {}
report = self.browse(self._context.get('active_id')) report = self.browse(self._context.get("active_id"))
if report: if report:
rcontext['o'] = report rcontext["o"] = report
result['html'] = self.env.ref( result["html"] = self.env.ref(
'stock_card_report.report_stock_card_report_html').render( "stock_card_report.report_stock_card_report_html"
rcontext) ).render(rcontext)
return result return result
@api.model @api.model

View File

@@ -2,180 +2,179 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging import logging
from odoo import models from odoo import models
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class ReportStockCardReportXlsx(models.AbstractModel): class ReportStockCardReportXlsx(models.AbstractModel):
_name = 'report.stock_card_report.report_stock_card_report_xlsx' _name = "report.stock_card_report.report_stock_card_report_xlsx"
_inherit = 'report.report_xlsx.abstract' _inherit = "report.report_xlsx.abstract"
def generate_xlsx_report(self, workbook, data, objects): def generate_xlsx_report(self, workbook, data, objects):
self._define_formats(workbook) self._define_formats(workbook)
for product in objects.product_ids: for product in objects.product_ids:
for ws_params in self._get_ws_params(workbook, data, product): for ws_params in self._get_ws_params(workbook, data, product):
ws_name = ws_params.get('ws_name') ws_name = ws_params.get("ws_name")
ws_name = self._check_ws_name(ws_name) ws_name = self._check_ws_name(ws_name)
ws = workbook.add_worksheet(ws_name) ws = workbook.add_worksheet(ws_name)
generate_ws_method = getattr( generate_ws_method = getattr(self, ws_params["generate_ws_method"])
self, ws_params['generate_ws_method']) generate_ws_method(workbook, ws, ws_params, data, objects, product)
generate_ws_method(
workbook, ws, ws_params, data, objects, product)
def _get_ws_params(self, wb, data, product): def _get_ws_params(self, wb, data, product):
filter_template = { filter_template = {
'1_date_from': { "1_date_from": {
'header': { "header": {"value": "Date from"},
'value': 'Date from', "data": {
}, "value": self._render("date_from"),
'data': { "format": self.format_tcell_date_center,
'value': self._render('date_from'),
'format': self.format_tcell_date_center,
}, },
}, },
'2_date_to': { "2_date_to": {
'header': { "header": {"value": "Date to"},
'value': 'Date to', "data": {
}, "value": self._render("date_to"),
'data': { "format": self.format_tcell_date_center,
'value': self._render('date_to'),
'format': self.format_tcell_date_center,
}, },
}, },
'3_location': { "3_location": {
'header': { "header": {"value": "Location"},
'value': 'Location', "data": {
}, "value": self._render("location"),
'data': { "format": self.format_tcell_center,
'value': self._render('location'),
'format': self.format_tcell_center,
}, },
}, },
} }
initial_template = { initial_template = {
'1_ref': { "1_ref": {
'data': { "data": {"value": "Initial", "format": self.format_tcell_center},
'value': 'Initial', "colspan": 4,
'format': self.format_tcell_center,
},
'colspan': 4,
},
'2_balance': {
'data': {
'value': self._render('balance'),
'format': self.format_tcell_amount_right,
}, },
"2_balance": {
"data": {
"value": self._render("balance"),
"format": self.format_tcell_amount_right,
}
}, },
} }
stock_card_template = { stock_card_template = {
'1_date': { "1_date": {
'header': { "header": {"value": "Date"},
'value': 'Date', "data": {
"value": self._render("date"),
"format": self.format_tcell_date_left,
}, },
'data': { "width": 25,
'value': self._render('date'),
'format': self.format_tcell_date_left,
}, },
'width': 25, "2_reference": {
"header": {"value": "Reference"},
"data": {
"value": self._render("reference"),
"format": self.format_tcell_left,
}, },
'2_reference': { "width": 25,
'header': {
'value': 'Reference',
}, },
'data': { "3_input": {
'value': self._render('reference'), "header": {"value": "Input"},
'format': self.format_tcell_left, "data": {"value": self._render("input")},
"width": 25,
}, },
'width': 25, "4_output": {
"header": {"value": "Output"},
"data": {"value": self._render("output")},
"width": 25,
}, },
'3_input': { "5_balance": {
'header': { "header": {"value": "Balance"},
'value': 'Input', "data": {"value": self._render("balance")},
}, "width": 25,
'data': {
'value': self._render('input'),
},
'width': 25,
},
'4_output': {
'header': {
'value': 'Output',
},
'data': {
'value': self._render('output'),
},
'width': 25,
},
'5_balance': {
'header': {
'value': 'Balance',
},
'data': {
'value': self._render('balance'),
},
'width': 25,
}, },
} }
ws_params = { ws_params = {
'ws_name': product.name, "ws_name": product.name,
'generate_ws_method': '_stock_card_report', "generate_ws_method": "_stock_card_report",
'title': 'Stock Card - {}'.format(product.name), "title": "Stock Card - {}".format(product.name),
'wanted_list_filter': [k for k in sorted(filter_template.keys())], "wanted_list_filter": [k for k in sorted(filter_template.keys())],
'col_specs_filter': filter_template, "col_specs_filter": filter_template,
'wanted_list_initial': [k for k in sorted(initial_template.keys())], "wanted_list_initial": [k for k in sorted(initial_template.keys())],
'col_specs_initial': initial_template, "col_specs_initial": initial_template,
'wanted_list': [k for k in sorted(stock_card_template.keys())], "wanted_list": [k for k in sorted(stock_card_template.keys())],
'col_specs': stock_card_template, "col_specs": stock_card_template,
} }
return [ws_params] return [ws_params]
def _stock_card_report(self, wb, ws, ws_params, data, objects, product): def _stock_card_report(self, wb, ws, ws_params, data, objects, product):
ws.set_portrait() ws.set_portrait()
ws.fit_to_pages(1, 0) ws.fit_to_pages(1, 0)
ws.set_header(self.xls_headers['standard']) ws.set_header(self.xls_headers["standard"])
ws.set_footer(self.xls_footers['standard']) ws.set_footer(self.xls_footers["standard"])
self._set_column_width(ws, ws_params) self._set_column_width(ws, ws_params)
# Title # Title
row_pos = 0 row_pos = 0
row_pos = self._write_ws_title(ws, row_pos, ws_params, True) row_pos = self._write_ws_title(ws, row_pos, ws_params, True)
# Filter Table # Filter Table
row_pos = self._write_line( row_pos = self._write_line(
ws, row_pos, ws_params, col_specs_section='header', ws,
row_pos,
ws_params,
col_specs_section="header",
default_format=self.format_theader_blue_center, default_format=self.format_theader_blue_center,
col_specs='col_specs_filter', wanted_list='wanted_list_filter') col_specs="col_specs_filter",
wanted_list="wanted_list_filter",
)
row_pos = self._write_line( 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={ render_space={
'date_from': objects.date_from or '', "date_from": objects.date_from or "",
'date_to': objects.date_to or '', "date_to": objects.date_to or "",
'location': objects.location_id.display_name or '', "location": objects.location_id.display_name or "",
}, },
col_specs='col_specs_filter', wanted_list='wanted_list_filter') col_specs="col_specs_filter",
wanted_list="wanted_list_filter",
)
row_pos += 1 row_pos += 1
# Stock Card Table # Stock Card Table
row_pos = self._write_line( row_pos = self._write_line(
ws, row_pos, ws_params, col_specs_section='header', ws,
default_format=self.format_theader_blue_center) row_pos,
ws_params,
col_specs_section="header",
default_format=self.format_theader_blue_center,
)
ws.freeze_panes(row_pos, 0) ws.freeze_panes(row_pos, 0)
balance = objects._get_initial(objects.results.filtered( balance = objects._get_initial(
lambda l: l.product_id == product and l.is_initial)) objects.results.filtered(lambda l: l.product_id == product and l.is_initial)
)
row_pos = self._write_line( row_pos = self._write_line(
ws, row_pos, ws_params, col_specs_section='data', ws,
render_space={'balance': balance}, col_specs='col_specs_initial', row_pos,
wanted_list='wanted_list_initial') ws_params,
col_specs_section="data",
render_space={"balance": balance},
col_specs="col_specs_initial",
wanted_list="wanted_list_initial",
)
product_lines = objects.results.filtered( product_lines = objects.results.filtered(
lambda l: l.product_id == product and not l.is_initial) lambda l: l.product_id == product and not l.is_initial
)
for line in product_lines: for line in product_lines:
balance += line.product_in - line.product_out balance += line.product_in - line.product_out
row_pos = self._write_line( 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={ render_space={
'date': line.date or '', "date": line.date or "",
'reference': line.reference or '', "reference": line.reference or "",
'input': line.product_in or 0, "input": line.product_in or 0,
'output': line.product_out or 0, "output": line.product_out or 0,
'balance': balance, "balance": balance,
}, },
default_format=self.format_tcell_amount_right) default_format=self.format_tcell_amount_right,
)

View File

@@ -1,9 +1,10 @@
# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import time
import logging import logging
import time
from datetime import date from datetime import date
from odoo.tests import common from odoo.tests import common
from odoo.tools import test_reports from odoo.tools import test_reports
@@ -11,213 +12,246 @@ _logger = logging.getLogger(__name__)
class TestStockCard(common.TransactionCase): class TestStockCard(common.TransactionCase):
def setUp(self):
def setUp(cls): super(TestStockCard, self).setUp()
super(TestStockCard, cls).setUp()
# Create uom: # Create uom:
uom_id = cls.ref('uom.product_uom_unit') uom_id = self.ref("uom.product_uom_unit")
# Create products: # Create products:
cls.product_A = cls.env['product.product'].create({ self.product_A = self.env["product.product"].create(
'name': 'Product A', {
'type': 'product', "name": "Product A",
'uom_id': uom_id, "type": "product",
'uom_po_id': uom_id, "uom_id": uom_id,
}) "uom_po_id": uom_id,
}
)
# Create location: # Create location:
cls.location_1 = cls.env.ref('stock.stock_location_stock') self.location_1 = self.env.ref("stock.stock_location_stock")
cls.location_2 = cls.env.ref('stock.stock_location_customers') self.location_2 = self.env.ref("stock.stock_location_customers")
# Create operation type: # Create operation type:
operation_type = cls.env.ref('stock.picking_type_in') operation_type = self.env.ref("stock.picking_type_in")
# Create stock picking: # Create stock picking:
picking = cls.env['stock.picking'].create({ picking = self.env["stock.picking"].create(
'location_id': cls.location_2.id, {
'location_dest_id': cls.location_1.id, "location_id": self.location_2.id,
'picking_type_id': operation_type.id, "location_dest_id": self.location_1.id,
}) "picking_type_id": operation_type.id,
cls.env['stock.move'].create({ }
'name': cls.product_A.name, )
'product_id': cls.product_A.id, self.env["stock.move"].create(
'product_uom_qty': 50.000, {
'product_uom': cls.product_A.uom_id.id, "name": self.product_A.name,
'picking_id': picking.id, "product_id": self.product_A.id,
'location_id': cls.location_2.id, "product_uom_qty": 50.000,
'location_dest_id': cls.location_1.id, "product_uom": self.product_A.uom_id.id,
}) "picking_id": picking.id,
"location_id": self.location_2.id,
"location_dest_id": self.location_1.id,
}
)
picking.action_confirm() picking.action_confirm()
picking.move_ids_without_package.quantity_done = 50.000 picking.move_ids_without_package.quantity_done = 50.000
picking.button_validate() picking.button_validate()
cls.model = cls._getReportModel() self.model = self._getReportModel()
cls.qweb_report_name = cls._getQwebReportName() self.qweb_report_name = self._getQwebReportName()
cls.xlsx_report_name = cls._getXlsxReportName() self.xlsx_report_name = self._getXlsxReportName()
cls.xlsx_action_name = cls._getXlsxReportActionName() self.xlsx_action_name = self._getXlsxReportActionName()
cls.report_title = cls._getReportTitle() self.report_title = self._getReportTitle()
cls.base_filters = cls._getBaseFilters() self.base_filters = self._getBaseFilters()
cls.report = cls.model.create(cls.base_filters) self.report = self.model.create(self.base_filters)
cls.report._compute_results() self.report._compute_results()
def test_html(self): def test_html(self):
test_reports.try_report(self.env.cr, self.env.uid, test_reports.try_report(
self.env.cr,
self.env.uid,
self.qweb_report_name, self.qweb_report_name,
[self.report.id], [self.report.id],
report_type='qweb-html') report_type="qweb-html",
)
def test_qweb(self): def test_qweb(self):
test_reports.try_report(self.env.cr, self.env.uid, test_reports.try_report(
self.env.cr,
self.env.uid,
self.qweb_report_name, self.qweb_report_name,
[self.report.id], [self.report.id],
report_type='qweb-pdf') report_type="qweb-pdf",
)
def test_xlsx(self): def test_xlsx(self):
test_reports.try_report(self.env.cr, self.env.uid, test_reports.try_report(
self.env.cr,
self.env.uid,
self.xlsx_report_name, self.xlsx_report_name,
[self.report.id], [self.report.id],
report_type='xlsx') report_type="xlsx",
)
def test_print(self): def test_print(self):
self.report.print_report('qweb') self.report.print_report("qweb")
self.report.print_report('xlsx') self.report.print_report("xlsx")
def _getReportModel(self): def _getReportModel(self):
return self.env['report.stock.card.report'] return self.env["report.stock.card.report"]
def _getQwebReportName(self): def _getQwebReportName(self):
return 'stock_card_report.report_stock_card_report_pdf' return "stock_card_report.report_stock_card_report_pdf"
def _getXlsxReportName(self): def _getXlsxReportName(self):
return 'stock_card_report.report_stock_card_report_xlsx' return "stock_card_report.report_stock_card_report_xlsx"
def _getXlsxReportActionName(self): def _getXlsxReportActionName(self):
return 'stock_card_report.action_report_stock_card_report_xlsx' return "stock_card_report.action_report_stock_card_report_xlsx"
def _getReportTitle(self): def _getReportTitle(self):
return 'Stock Card Report' return "Stock Card Report"
def _getBaseFilters(self): def _getBaseFilters(self):
return { return {
'product_ids': [(6, 0, [self.product_A.id])], "product_ids": [(6, 0, [self.product_A.id])],
'location_id': self.location_1.id, "location_id": self.location_1.id,
} }
class TestStockCardReport(common.TransactionCase): class TestStockCardReport(common.TransactionCase):
def setUp(self): def setUp(self):
super(TestStockCardReport, self).setUp() super(TestStockCardReport, self).setUp()
# Create uom: # Create uom:
uom_id = self.ref('uom.product_uom_unit') uom_id = self.ref("uom.product_uom_unit")
# Create products: # Create products:
self.product_A = self.env['product.product'].create({ self.product_A = self.env["product.product"].create(
'name': 'Product A', {
'type': 'product', "name": "Product A",
'uom_id': uom_id, "type": "product",
'uom_po_id': uom_id, "uom_id": uom_id,
}) "uom_po_id": uom_id,
self.product_B = self.env['product.product'].create({ }
'name': 'Product B', )
'type': 'product', self.product_B = self.env["product.product"].create(
'uom_id': uom_id, {
'uom_po_id': uom_id, "name": "Product B",
}) "type": "product",
"uom_id": uom_id,
"uom_po_id": uom_id,
}
)
# Create location: # Create location:
self.location_1 = self.env.ref('stock.stock_location_stock') self.location_1 = self.env.ref("stock.stock_location_stock")
self.location_2 = self.env.ref('stock.stock_location_customers') self.location_2 = self.env.ref("stock.stock_location_customers")
# Create operation type: # Create operation type:
operation_type = self.env.ref('stock.picking_type_in') operation_type = self.env.ref("stock.picking_type_in")
# Create stock picking: # Create stock picking:
picking_1 = self.env['stock.picking'].create({ picking_1 = self.env["stock.picking"].create(
'location_id': self.location_2.id, {
'location_dest_id': self.location_1.id, "location_id": self.location_2.id,
'picking_type_id': operation_type.id, "location_dest_id": self.location_1.id,
}) "picking_type_id": operation_type.id,
self.env['stock.move'].create({ }
'name': self.product_A.name, )
'product_id': self.product_A.id, self.env["stock.move"].create(
'product_uom_qty': 50.000, {
'product_uom': self.product_A.uom_id.id, "name": self.product_A.name,
'picking_id': picking_1.id, "product_id": self.product_A.id,
'location_id': self.location_2.id, "product_uom_qty": 50.000,
'location_dest_id': self.location_1.id, "product_uom": self.product_A.uom_id.id,
}) "picking_id": picking_1.id,
"location_id": self.location_2.id,
"location_dest_id": self.location_1.id,
}
)
picking_1.action_confirm() picking_1.action_confirm()
picking_1.move_ids_without_package.quantity_done = 50.000 picking_1.move_ids_without_package.quantity_done = 50.000
picking_1.button_validate() picking_1.button_validate()
picking_2 = self.env['stock.picking'].create({ picking_2 = self.env["stock.picking"].create(
'location_id': self.location_2.id, {
'location_dest_id': self.location_1.id, "location_id": self.location_2.id,
'picking_type_id': operation_type.id, "location_dest_id": self.location_1.id,
}) "picking_type_id": operation_type.id,
self.env['stock.move'].create({ }
'name': self.product_B.name, )
'product_id': self.product_B.id, self.env["stock.move"].create(
'product_uom_qty': 100.000, {
'product_uom': self.product_B.uom_id.id, "name": self.product_B.name,
'picking_id': picking_2.id, "product_id": self.product_B.id,
'location_id': self.location_2.id, "product_uom_qty": 100.000,
'location_dest_id': self.location_1.id, "product_uom": self.product_B.uom_id.id,
}) "picking_id": picking_2.id,
"location_id": self.location_2.id,
"location_dest_id": self.location_1.id,
}
)
picking_2.action_confirm() picking_2.action_confirm()
picking_2.move_ids_without_package.quantity_done = 100.000 picking_2.move_ids_without_package.quantity_done = 100.000
picking_2.button_validate() picking_2.button_validate()
def test_reports(self): def test_reports(self):
report = self.env['report.stock.card.report'].create({ report = self.env["report.stock.card.report"].create(
'product_ids': [(6, 0, [self.product_A.id, self.product_B.id])], {
'location_id': self.location_1.id, "product_ids": [(6, 0, [self.product_A.id, self.product_B.id])],
}) "location_id": self.location_1.id,
}
)
report._compute_results() report._compute_results()
report.print_report('qweb') report.print_report("qweb")
report.print_report('xlsx') report.print_report("xlsx")
def test_get_report_html(self): def test_get_report_html(self):
report = self.env['report.stock.card.report'].create({ report = self.env["report.stock.card.report"].create(
'product_ids': [(6, 0, [self.product_A.id, self.product_B.id])], {
'location_id': self.location_1.id, "product_ids": [(6, 0, [self.product_A.id, self.product_B.id])],
}) "location_id": self.location_1.id,
}
)
report._compute_results() report._compute_results()
report.get_html(given_context={ report.get_html(given_context={"active_id": report.id})
'active_id': report.id
})
def test_wizard_date_range(self): def test_wizard_date_range(self):
date_range = self.env['date.range'] date_range = self.env["date.range"]
self.type = self.env['date.range.type'].create( self.type = self.env["date.range.type"].create(
{'name': 'Month', {"name": "Month", "company_id": False, "allow_overlap": False}
'company_id': False, )
'allow_overlap': False}) dt = date_range.create(
dt = date_range.create({ {
'name': 'FiscalYear', "name": "FiscalYear",
'date_start': time.strftime('%Y-%m-01'), "date_start": time.strftime("%Y-%m-01"),
'date_end': time.strftime('%Y-%m-28'), "date_end": time.strftime("%Y-%m-28"),
'type_id': self.type.id, "type_id": self.type.id,
}) }
wizard = self.env['stock.card.report.wizard'].create( )
{'date_range_id': dt.id, wizard = self.env["stock.card.report.wizard"].create(
'date_from': time.strftime('%Y-%m-28'), {
'date_to': time.strftime('%Y-%m-01'), "date_range_id": dt.id,
'product_ids': [(6, 0, [self.product_A.id, self.product_B.id])], "date_from": time.strftime("%Y-%m-28"),
'location_id': self.location_1.id}) "date_to": time.strftime("%Y-%m-01"),
"product_ids": [(6, 0, [self.product_A.id, self.product_B.id])],
"location_id": self.location_1.id,
}
)
wizard._onchange_date_range_id() wizard._onchange_date_range_id()
self.assertEqual(wizard.date_from, date( self.assertEqual(
date.today().year, date.today().month, 1)) wizard.date_from, date(date.today().year, date.today().month, 1)
self.assertEqual(wizard.date_to, date( )
date.today().year, date.today().month, 28)) self.assertEqual(
wizard._export('qweb-pdf') wizard.date_to, date(date.today().year, date.today().month, 28)
)
wizard._export("qweb-pdf")
wizard.button_export_html() wizard.button_export_html()
wizard.button_export_pdf() wizard.button_export_pdf()
wizard.button_export_xlsx() wizard.button_export_xlsx()

View File

@@ -2,36 +2,25 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models from odoo import api, fields, models
from odoo.tools.safe_eval import safe_eval
from odoo.tools import pycompat from odoo.tools import pycompat
from odoo.tools.safe_eval import safe_eval
class StockCardReportWizard(models.TransientModel): class StockCardReportWizard(models.TransientModel):
_name = 'stock.card.report.wizard' _name = "stock.card.report.wizard"
_description = 'Stock Card Report Wizard' _description = "Stock Card Report Wizard"
date_range_id = fields.Many2one( date_range_id = fields.Many2one(comodel_name="date.range", string="Period")
comodel_name='date.range', date_from = fields.Date(string="Start Date")
string='Period', date_to = fields.Date(string="End Date")
)
date_from = fields.Date(
string='Start Date',
)
date_to = fields.Date(
string='End Date',
)
location_id = fields.Many2one( location_id = fields.Many2one(
comodel_name='stock.location', comodel_name="stock.location", string="Location", required=True
string='Location',
required=True,
) )
product_ids = fields.Many2many( product_ids = fields.Many2many(
comodel_name='product.product', comodel_name="product.product", string="Products", required=True
string='Products',
required=True,
) )
@api.onchange('date_range_id') @api.onchange("date_range_id")
def _onchange_date_range_id(self): def _onchange_date_range_id(self):
self.date_from = self.date_range_id.date_start self.date_from = self.date_range_id.date_start
self.date_to = self.date_range_id.date_end self.date_to = self.date_range_id.date_end
@@ -39,41 +28,40 @@ class StockCardReportWizard(models.TransientModel):
@api.multi @api.multi
def button_export_html(self): def button_export_html(self):
self.ensure_one() self.ensure_one()
action = self.env.ref( action = self.env.ref("stock_card_report.action_report_stock_card_report_html")
'stock_card_report.action_report_stock_card_report_html')
vals = action.read()[0] vals = action.read()[0]
context = vals.get('context', {}) context = vals.get("context", {})
if isinstance(context, pycompat.string_types): if isinstance(context, pycompat.string_types):
context = safe_eval(context) context = safe_eval(context)
model = self.env['report.stock.card.report'] model = self.env["report.stock.card.report"]
report = model.create(self._prepare_stock_card_report()) report = model.create(self._prepare_stock_card_report())
context['active_id'] = report.id context["active_id"] = report.id
context['active_ids'] = report.ids context["active_ids"] = report.ids
vals['context'] = context vals["context"] = context
return vals return vals
@api.multi @api.multi
def button_export_pdf(self): def button_export_pdf(self):
self.ensure_one() self.ensure_one()
report_type = 'qweb-pdf' report_type = "qweb-pdf"
return self._export(report_type) return self._export(report_type)
@api.multi @api.multi
def button_export_xlsx(self): def button_export_xlsx(self):
self.ensure_one() self.ensure_one()
report_type = 'xlsx' report_type = "xlsx"
return self._export(report_type) return self._export(report_type)
def _prepare_stock_card_report(self): def _prepare_stock_card_report(self):
self.ensure_one() self.ensure_one()
return { return {
'date_from': self.date_from, "date_from": self.date_from,
'date_to': self.date_to or fields.Date.context_today(self), "date_to": self.date_to or fields.Date.context_today(self),
'product_ids': [(6, 0, self.product_ids.ids)], "product_ids": [(6, 0, self.product_ids.ids)],
'location_id': self.location_id.id, "location_id": self.location_id.id,
} }
def _export(self, report_type): def _export(self, report_type):
model = self.env['report.stock.card.report'] model = self.env["report.stock.card.report"]
report = model.create(self._prepare_stock_card_report()) report = model.create(self._prepare_stock_card_report())
return report.print_report(report_type) return report.print_report(report_type)