[REF] stock: reception_report into WOWL

Converts the legacy reception report into WOWL.
Fixes 'Assign All' buttons disappearing from the report until it is
reloaded when clicking on them.
Removes references to 'report_type == html' from xml since it is only
used as PDF now.

Part of the global conversion of stock to WOWL.

Task-2885757

closes odoo/odoo#102687

X-original-commit: f310d8f16b57c776ad92406bd52daa707ad45a88
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
This commit is contained in:
clesgow
2022-10-07 18:48:13 +02:00
parent 106602f7e0
commit dd9220459c
9 changed files with 500 additions and 262 deletions
@@ -11,6 +11,16 @@ class ReceptionReport(models.AbstractModel):
_name = 'report.stock.report_reception'
_description = "Stock Reception Report"
@api.model
def get_report_data(self, docids, data):
report_values = self._get_report_values(docids, data)
report_values['docs'] = self._format_html_docs(report_values.get('docs', False))
report_values['sources_info'] = self._format_html_sources_info(report_values.get('sources_to_lines', {}))
report_values['sources_to_lines'] = self._format_html_sources_to_lines(report_values.get('sources_to_lines', {}))
report_values['sources_to_formatted_scheduled_date'] = self._format_html_sources_to_date(report_values.get('sources_to_formatted_scheduled_date', {}))
report_values['show_uom'] = self.env.user.has_group('uom.group_uom')
return report_values
@api.model
def _get_report_values(self, docids, data=None):
''' This report is flexibly designed to work with both individual and batch pickings.
@@ -325,3 +335,42 @@ class ReceptionReport(models.AbstractModel):
def _action_unassign(self, in_move, out_move):
""" For extension purposes only """
return
def _format_html_docs(self, docs):
""" Format docs to be sent in an html request. """
return [{
'id': doc.id,
'name': doc.display_name,
'state': doc.state,
'display_state': dict(doc._fields['state']._description_selection(self.env)).get(doc.state),
} for doc in docs] if docs else docs
def _format_html_sources_to_date(self, sources_to_dates):
""" Format sources_to_formatted_scheduled_date to be sent in an html request. """
return {str(source): date for (source, date) in sources_to_dates.items()}
def _format_html_sources_to_lines(self, sources_to_lines):
""" Format sources_to_lines to be sent in an html request, while adding an index for OWL's t-foreach. """
return {
str(source): [{**line, 'index': i, 'move_out_id': line['move_out'].id} for i, line in enumerate(lines)]
for source, lines in sources_to_lines.items()
}
def _format_html_sources_info(self, sources_to_lines):
""" Format used info from sources of sources_to_lines to be sent in an html request. """
return {str(source): [self._format_html_source(s, index == 0) for index, s in enumerate(source)] for source in sources_to_lines.keys()}
def _format_html_source(self, source, is_picking=False):
""" Format used info from a single source to be sent in an html request. """
formatted = {
'id': source.id,
'model': source._name,
'name': source.display_name,
}
if is_picking:
formatted.update({
'priority': source.priority,
'partner_id': source.partner_id.id if source.partner_id else False,
'partner_name': source.partner_id.name if source.partner_id else False,
})
return formatted
+5 -60
View File
@@ -59,9 +59,9 @@
</t>
</h3>
</div>
<div><table t-if="sources_to_lines" class="o_report_reception_table table table-sm">
<table t-if="sources_to_lines" class="o_report_reception_table table table-sm">
<t t-foreach="sources_to_lines" t-as="source">
<thead t-if="report_type == 'html' or any(line['is_assigned'] for line in sources_to_lines[source])">
<thead t-if="any(line['is_assigned'] for line in sources_to_lines[source])">
<tr class="bg-light">
<th>
<i t-if="source[0].priority == '1'" class="o_priority o_priority_star fa fa-star"/>
@@ -78,71 +78,19 @@
</span>
</th>
<th>Expected Delivery: <t t-esc="sources_to_formatted_scheduled_date[source]"/></th>
<th t-if="report_type == 'html' and any(s['move_ins'] for s in sources_to_lines[source])">
<button t-if="any(not s['is_assigned'] and s['is_qty_assignable'] for s in sources_to_lines[source])"
class="btn btn-sm btn-primary o_report_reception_assign o_assign_all"
name="assign_source_link">
Assign All
</button>
</th>
<th t-if="report_type == 'html'">
<button t-if="any(s['move_ins'] for s in sources_to_lines[source])"
class="btn btn-sm btn-primary o_print_label o_print_label_all"
t-att-disabled="not any(s['is_assigned'] for s in sources_to_lines[source])"
name="print_labels">
<span class="d-none d-sm-block o_print_label_text">Print Labels</span>
<span class="d-block d-sm-none fa fa-print"/>
</button>
</th>
</tr>
</thead>
<tbody>
<t t-set="possible_moves" t-value="sources_to_lines[source]"/>
<t t-foreach="possible_moves" t-as="line">
<!-- don't print non-assigned lines when printing pdf -->
<tr t-if="report_type == 'html' or line['is_assigned']">
<tr t-if="line['is_assigned']">
<td>
<t t-esc="line['product']['display_name']"/>
</td>
<td>
<t t-esc="line['quantity']"/>
<t groups="uom.group_uom" t-esc="line['uom']"/>
<button t-if="report_type == 'html'"
class="o_report_reception_forecasted btn btn-link fa fa-area-chart"
t-att-move-id="line['move_out'].id"
name="forecasted_report_link">
</button>
</td>
<td t-if="report_type == 'html' and line['is_qty_assignable']">
<button t-if="not line['is_assigned']"
class="btn btn-sm btn-primary o_report_reception_assign"
t-attf-model="stock.move"
t-att-move-id="line['move_out'].id"
t-att-move-ins-ids="line['move_ins']"
t-att-qty="line['quantity']"
name="assign_link">
Assign
</button>
<button t-if="line['is_assigned']"
class="btn btn-sm btn-primary o_report_reception_unassign"
t-attf-model="stock.move"
t-att-move-id="line['move_out'].id"
t-att-move-ins-ids="line['move_ins']"
t-att-qty="line['quantity']"
name="unassign_link">
Unassign
</button>
</td>
<td t-if="report_type == 'html'">
<button t-if="line['is_qty_assignable'] and line['source']"
t-att-move-id="line['move_out'].id"
t-att-qty="line['quantity']"
t-attf-class="btn btn-sm btn-primary o_print_label"
t-att-disabled="not line['is_assigned']"
name="print_label">
<span class="d-none d-sm-block o_print_label_text">Print Label</span>
<span class="d-block d-sm-none fa fa-print"/>
</button>
</td>
</tr>
</t>
@@ -151,16 +99,13 @@
</table>
<p t-else="">
No allocation need found.
</p></div>
</p>
</div>
</template>
<template id="report_reception">
<t t-call="web.html_container">
<t t-if="report_type == 'pdf'" t-call="web.internal_layout">
<t t-call="stock.report_reception_body"/>
</t>
<t t-else="">
<t t-call="web.internal_layout">
<t t-call="stock.report_reception_body"/>
</t>
</t>
@@ -0,0 +1,75 @@
/** @odoo-module **/
import { useService } from "@web/core/utils/hooks";
import { formatFloat } from "@web/views/fields/formatters";
const { Component } = owl;
export class ReceptionReportLine extends Component {
setup() {
this.ormService = useService("orm");
this.actionService = useService("action");
this.formatFloat = (val) => formatFloat(val, { digits: [false, this.props.precision] });
}
//---- Handlers ----
async onClickForecast() {
const action = await this.ormService.call(
"stock.move",
"action_product_forecast_report",
[[this.data.move_out_id]],
);
return this.actionService.doAction(action);
}
async onClickPrint() {
if (!this.data.move_out_id) {
return;
}
const reportFile = 'stock.report_reception_report_label';
const modelIds = [this.data.move_out_id];
const productQtys = [Math.ceil(this.data.quantity) || '1'];
return this.actionService.doAction({
type: "ir.actions.report",
report_type: "qweb-pdf",
report_name: `${reportFile}?docids=${modelIds}&quantity=${productQtys}`,
report_file: reportFile,
});
}
async onClickAssign() {
await this.ormService.call(
"report.stock.report_reception",
"action_assign",
[false, [this.data.move_out_id], [this.data.quantity], [this.data.move_ins]],
);
this.env.bus.trigger("update-assign-state", { isAssigned: true, tableIndex: this.props.parentIndex, lineIndex: this.data.index });
}
async onClickUnassign() {
const done = await this.ormService.call(
"report.stock.report_reception",
"action_unassign",
[false, this.data.move_out_id, this.data.quantity, this.data.move_ins]
)
if (done) {
this.env.bus.trigger("update-assign-state", { isAssigned: false, tableIndex: this.props.parentIndex, lineIndex: this.data.index });
}
}
//---- Getters ----
get data() {
return this.props.data;
}
}
ReceptionReportLine.template = "stock.ReceptionReportLine";
ReceptionReportLine.props = {
data: Object,
parentIndex: String,
showUom: Boolean,
precision: Number,
};
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<tr t-name="stock.ReceptionReportLine" class="align-middle" owl="1">
<td t-esc="data.product.display_name"/>
<td>
<t t-esc="formatFloat(data.quantity)"/> <t t-if="props.showUom" t-esc="data.uom"/>
<button class="btn btn-link fa fa-area-chart" t-on-click="onClickForecast" name="forecasted_report_link"/>
</td>
<td t-if="data.is_qty_assignable">
<button t-if="!data.is_assigned"
t-on-click="onClickAssign"
class="btn btn-sm btn-primary"
name="assign_link">
Assign
</button>
<button t-else=""
t-on-click="onClickUnassign"
class="btn btn-sm btn-primary"
name="unassign_link">
Unassign
</button>
</td>
<td>
<button t-if="data.is_qty_assignable &amp;&amp; data.source"
class="btn btn-sm btn-primary"
t-attf-disabled="{{ !data.is_assigned }}"
name="print_label"
t-on-click="onClickPrint">
<span class="d-sm-block">Print Label</span>
</button>
</td>
</tr>
</templates>
@@ -0,0 +1,150 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { useBus, useService } from "@web/core/utils/hooks";
import { ControlPanel } from "@web/search/control_panel/control_panel";
import { ReceptionReportTable } from "../reception_report_table/stock_reception_report_table";
const { Component, onWillStart, useState } = owl;
export class ReceptionReportMain extends Component {
setup() {
this.controlPanelDisplay = {
"top-right": false,
"bottom-right": false,
};
this.ormService = useService("orm");
this.actionService = useService("action");
this.reportName = "stock.report_reception";
this.state = useState({
sourcesToLines: {},
});
useBus(this.env.bus, "update-assign-state", (ev) => this._changeAssignedState(ev.detail));
onWillStart(async () => {
this.data = await this.getReportData();
this.state.sourcesToLines = this.data.sources_to_lines;
});
}
async getReportData() {
const args = [
this.context.default_picking_ids,
{ context: this.context, report_type: "html" },
];
return this.ormService.call(
"report.stock.report_reception",
"get_report_data",
args,
{ context: this.context }
);
}
//---- Handlers ----
async onClickAssignAll() {
const moveIds = [];
const quantities = [];
const inIds = [];
for (const lines of Object.values(this.state.sourcesToLines)) {
for (const line of lines) {
if (line.is_assigned) continue;
moveIds.push(line.move_out_id);
quantities.push(line.quantity);
inIds.push(line.move_ins);
}
}
await this.ormService.call(
"report.stock.report_reception",
"action_assign",
[false, moveIds, quantities, inIds],
);
this._changeAssignedState({ isAssigned: true });
}
async onClickTitle(docId) {
return this.actionService.doAction({
type: "ir.actions.act_window",
res_model: this.data.doc_model,
res_id: docId,
views: [[false, "form"]],
target: "current",
});
}
onClickPrint() {
return this.actionService.doAction({
type: "ir.actions.report",
report_type: "qweb-pdf",
report_name: `${this.reportName}/${this.context.default_picking_ids.join(",")}`,
report_file: this.reportName,
});
}
onClickPrintLabels() {
const reportFile = 'stock.report_reception_report_label';
const modelIds = [];
const quantities = [];
for (const lines of Object.values(this.state.sourcesToLines)) {
for (const line of lines) {
if (!line.is_assigned) continue;
modelIds.push(line.move_out_id);
quantities.push(line.quantity || 1);
}
}
if (!modelIds.length) {
return;
}
return this.actionService.doAction({
type: "ir.actions.report",
report_type: "qweb-pdf",
report_name: `${reportFile}?docids=${modelIds}&quantity=${quantities}`,
report_file: reportFile,
});
}
//---- Utils ----
_changeAssignedState(options) {
const { isAssigned, tableIndex, lineIndex } = options;
for (const [tabIndex, lines] of Object.entries(this.state.sourcesToLines)) {
if (tableIndex && tableIndex != tabIndex) continue;
lines.forEach(line => {
if (isNaN(lineIndex) || lineIndex == line.index) {
line.is_assigned = isAssigned;
}
});
}
}
//---- Getters ----
get context() {
return this.props.action.context;
}
get hasContent() {
return this.data.sources_to_lines && Object.keys(this.data.sources_to_lines).length > 0;
}
get isAssignAllDisabled() {
return Object.values(this.state.sourcesToLines).every(lines => lines.every(line => line.is_assigned));
}
get isPrintLabelDisabled() {
return Object.values(this.state.sourcesToLines).every(lines => lines.every(line => !line.is_assigned));
}
}
ReceptionReportMain.components = {
ControlPanel,
ReceptionReportTable,
};
ReceptionReportMain.template = "stock.ReceptionReportMain";
registry.category("actions").add("reception_report", ReceptionReportMain);
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<div t-name="stock.ReceptionReportMain" class="o_action" owl="1">
<ControlPanel display="controlPanelDisplay">
<t t-set-slot="control-panel-bottom-left-buttons">
<div class="o_cp_buttons" role="toolbar" aria-label="Control panel buttons">
<div class="d-inline-block">
<button t-on-click="onClickPrint" type="button" class="btn btn-primary" title="Print">Print</button>
<button t-on-click="onClickAssignAll" class="btn btn-secondary ms-1" t-att-disabled="isAssignAllDisabled">Assign All</button>
<button t-on-click="onClickPrintLabels" class="btn btn-secondary ms-1" t-att-disabled="isPrintLabelDisabled">Print Labels</button>
</div>
</div>
</t>
</ControlPanel>
<div class="o_report_reception container-fluid justify-content-between">
<div class="o_report_reception_header my-4">
<h1>
<t t-if="data.docs">
<div t-foreach="data.docs" t-as="doc" t-key="doc.id">
<a href="#" t-on-click.prevent="() => this.onClickTitle(doc.id)" view-type="form" t-esc="doc.name"/>
<span t-esc="doc.display_state" t-attf-class="ms-1 align-text-top badge rounded-pill bg-opacity-50 {{ doc.state == 'done' ? 'bg-success' : 'bg-info' }}"/>
</div>
</t>
<t t-else="">
<span t-esc="data.reason"/>
</t>
</h1>
</div>
<t t-if="hasContent">
<table class="table table-sm">
<ReceptionReportTable
t-foreach="state.sourcesToLines" t-as="source" t-key="source"
index="source"
scheduledDate="data.sources_to_formatted_scheduled_date[source]"
lines="state.sourcesToLines[source]"
source="data.sources_info[source]"
showUom="data.show_uom"
precision="data.precision"/>
</table>
</t>
<p t-else="">
No allocation need found.
</p>
</div>
</div>
</templates>
@@ -0,0 +1,96 @@
/** @odoo-module **/
import { useService } from "@web/core/utils/hooks";
import { ReceptionReportLine } from "../reception_report_line/stock_reception_report_line";
const { Component } = owl;
export class ReceptionReportTable extends Component {
setup() {
this.actionService = useService("action");
this.ormService = useService("orm");
}
//---- Handlers ----
async onClickAssignAll() {
const moveIds = [];
const quantities = [];
const inIds = [];
for (const line of this.props.lines) {
if (line.is_assigned) continue;
moveIds.push(line.move_out_id);
quantities.push(line.quantity);
inIds.push(line.move_ins);
}
await this.ormService.call(
"report.stock.report_reception",
"action_assign",
[false, moveIds, quantities, inIds],
);
this.env.bus.trigger("update-assign-state", { isAssigned: true, tableIndex: this.props.index });
}
async onClickLink(resModel, resId, viewType) {
return this.actionService.doAction({
type: "ir.actions.act_window",
res_model: resModel,
res_id: resId,
views: [[false, viewType]],
target: "current",
});
}
async onClickPrintLabels() {
const reportFile = 'stock.report_reception_report_label';
const modelIds = [];
const quantities = [];
for (const line of this.props.lines) {
if (!line.is_assigned) continue;
modelIds.push(line.move_out_id);
quantities.push(line.quantity || 1);
}
if (!modelIds.length) {
return;
}
return this.actionService.doAction({
type: "ir.actions.report",
report_type: "qweb-pdf",
report_name: `${reportFile}?docids=${modelIds}&quantity=${quantities}`,
report_file: reportFile,
});
}
//---- Getters ----
get hasMovesIn() {
return this.props.lines.some(line => line.move_ins && line.move_ins.length > 0);
}
get hasAssignAllButton() {
return this.props.lines.some(line => line.is_qty_assignable);
}
get isAssignAllDisabled() {
return this.props.lines.every(line => line.is_assigned);
}
get isPrintLabelDisabled() {
return this.props.lines.every(line => !line.is_assigned);
}
}
ReceptionReportTable.template = "stock.ReceptionReportTable";
ReceptionReportTable.components = {
ReceptionReportLine,
};
ReceptionReportTable.props = {
index: String,
scheduledDate: { type: String, optional: true },
lines: Array,
source: Array,
showUom: Boolean,
precision: Number,
};
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="stock.ReceptionReportTable" owl="1">
<thead>
<tr class="bg-light">
<th>
<i t-if="props.source[0].priority == '1'" class="o_priority o_priority_star fa fa-star"/>
<a href="#" t-on-click.prevent="() => this.onClickLink(props.source[0].model, props.source[0].id, 'form')" t-out="props.source[0].name"/>
<span t-if="props.source.length > 1">
(<a href="#" t-on-click.prevent="() => this.onClickLink(props.source[1].model, props.source[1].id, 'form')" t-out="props.source[1].name"/>)
</span>
<span t-if="props.source[0].model == 'stock.picking' and props.source[0].partner_id">:
<a href="#" t-on-click.prevent="() => this.onClickLink('res.partner', props.source[0].partner_id, 'form')" t-out="props.source[0].partner_name"/>
</span>
</th>
<th>Expected Delivery: <t t-esc="props.scheduledDate"/></th>
<th t-if="hasMovesIn">
<button t-if="hasAssignAllButton" t-on-click="onClickAssignAll" class="btn btn-sm btn-primary" t-att-disabled="isAssignAllDisabled" name="assign_source_link">
Assign All
</button>
</th>
<th>
<button t-if="hasMovesIn" t-on-click="onClickPrintLabels" class="btn btn-sm btn-primary" t-att-disabled="isPrintLabelDisabled" name="print_labels">
<span class="d-none d-sm-block">Print Labels</span>
<span class="d-block d-sm-none fa fa-print"/>
</button>
</th>
</tr>
</thead>
<tbody>
<t t-foreach="props.lines" t-as="line" t-key="line.index">
<ReceptionReportLine
data="line"
parentIndex="props.index"
showUom="props.showUom"
precision="props.precision"/>
</t>
</tbody>
</t>
</templates>
@@ -1,202 +0,0 @@
/** @odoo-module **/
import clientAction from 'report.client_action';
import core from 'web.core';
const qweb = core.qweb;
const _t = core._t;
const ReceptionReport = clientAction.extend({
/**
* @override
*/
init: function (parent, action, options) {
this._super(...arguments);
this.context = Object.assign(action.context || {}, {
active_ids: action.context.default_picking_ids,
});
this.report_name = `stock.report_reception`;
this.report_url = `/report/html/${this.report_name}/?context=${JSON.stringify(this.context)}`;
this._title = action.name;
},
/**
* @override
*/
start: function () {
return Promise.all([
this._super(...arguments),
]).then(() => {
this._renderButtons();
});
},
/**
* @override
*/
on_attach_callback: function () {
this._super();
this.iframe.addEventListener("load",
() => this._bindAdditionalActionHandlers(),
{ once: true }
);
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Renders extra report buttons in control panel
*/
_renderButtons: function () {
this.$buttons.append(qweb.render('reception_report_buttons', {}));
this.$buttons.on('click', '.o_report_reception_assign', this._onClickAssign.bind(this));
this.$buttons.on('click', '.o_print_label', this._onClickPrintLabel.bind(this));
this.controlPanelProps.cp_content = {
$buttons: this.$buttons,
};
},
/**
* Bind additional <button> action handlers
*/
_bindAdditionalActionHandlers: function () {
const rr = $(this.iframe).contents().find('.o_report_reception');
rr.on('click', '.o_report_reception_assign', this._onClickAssign.bind(this));
rr.on('click', '.o_report_reception_unassign', this._onClickUnassign.bind(this));
rr.on('click', '.o_report_reception_forecasted', this._onClickForecastReport.bind(this));
rr.on('click', '.o_print_label', this._onClickPrintLabel.bind(this));
},
_switchButton: function (button) {
button.innerText = button.innerText.includes(_t("Unassign")) ? _t("Assign") : _t("Unassign");
button.name = button.name === 'assign_link' ? 'unassign_link' : 'assign_link';
button.classList.toggle("o_report_reception_assign");
button.classList.toggle("o_report_reception_unassign");
},
/**
* Assign the specified move(s)
*
* @returns {Promise}
*/
_onClickAssign: function (ev) {
const el = ev.currentTarget;
const quantities = []; // incoming qty amounts to assign
const moveIds = [];
const inIds = [];
let nodeToAssign = [];
if (el.name === 'assign_link') { // One line "Assign"
nodeToAssign = [el];
el.closest('tbody').previousElementSibling.querySelectorAll('.o_print_label_all').forEach(button => button.removeAttribute('disabled'));
} else {
el.style.display = 'none';
if (el.name === "assign_all_link") { // Global "Assign All"
const iframe = this.iframe.contentDocument;
iframe.querySelectorAll('.o_assign_all').forEach(button => button.style.display = 'none');
iframe.querySelectorAll('.o_print_label_all').forEach(button => button.removeAttribute('disabled'));
nodeToAssign = iframe.querySelectorAll('.o_report_reception_assign:not(.o_assign_all)');
} else { // Local assign all
nodeToAssign = el.closest('thead').nextElementSibling.querySelectorAll('.o_report_reception_assign:not(.o_assign_all)');
const thead = el.closest('thead');
thead.querySelector('.o_print_label_all').removeAttribute('disabled');
thead.nextElementSibling.querySelectorAll('.o_print_label_all').forEach(button => button.removeAttribute('disabled'));
}
}
nodeToAssign.forEach(node => {
node.closest('td').nextElementSibling.querySelectorAll('.o_print_label').forEach(button => button.removeAttribute('disabled'));
moveIds.push(parseInt(node.getAttribute('move-id')));
quantities.push(parseFloat(node.getAttribute('qty')));
inIds.push(JSON.parse(node.getAttribute('move-ins-ids')));
this._switchButton(node);
});
return this._rpc({
model: 'report.stock.report_reception',
args: [false, moveIds, quantities, inIds],
method: 'action_assign'
});
},
/**
* Unassign the specified move
*
* @returns {Promise}
*/
_onClickUnassign: function (ev) {
const el = ev.currentTarget;
const quantity = parseFloat(el.getAttribute('qty'));
const modelId = parseInt(el.getAttribute('move-id'));
const inIds = JSON.parse("[" + el.getAttribute('move-ins-ids') + "]");
return this._rpc({
model: 'report.stock.report_reception',
args: [false, modelId, quantity, inIds[0]],
method: 'action_unassign'
}).then(() => {
// only switch buttons if successful
this._switchButton(el);
el.closest('td').nextElementSibling.querySelectorAll('.o_print_label').forEach(button => button.setAttribute('disabled', true));
});
},
/**
* Open the forecast report for the product of the selected move.
*
* @returns {Promise}
*/
_onClickForecastReport: function (ev) {
const modelId = parseInt(ev.currentTarget.getAttribute('move-id'));
return this._rpc({
model: 'stock.move',
args: [[modelId]],
method: 'action_product_forecast_report'
}).then((action) => {
return this.do_action(action);
});
},
/**
* Print the corresponding source label
*/
_onClickPrintLabel: function (ev) {
const el = ev.currentTarget;
const modelIds = [];
const productQtys = [];
const report_file = 'stock.report_reception_report_label';
let nodeToPrint = [];
if (el.name === 'print_label') { // One line print
nodeToPrint = [el];
} else {
if (el.name === "print_all_labels") { // Global "Print Labels"
nodeToPrint = this.iframe.contentDocument.querySelectorAll('.o_print_label:not(.o_print_label_all):not(:disabled)');
} else { // Local "Print Labels"
nodeToPrint = el.closest('thead').nextElementSibling.querySelectorAll('.o_print_label:not(.o_print_label_all):not(:disabled)');
}
}
nodeToPrint.forEach(node => {
modelIds.push(parseInt(node.getAttribute('move-id')));
productQtys.push(Math.ceil(node.getAttribute('qty')) || '1');
});
if (!modelIds.length) { // Nothing to print for this model.
return Promise.resolve();
}
const report_name = `${report_file}?docids=${modelIds}&report_type=qweb-pdf&quantity=${productQtys}`;
const action = {
type: 'ir.actions.report',
report_type: 'qweb-pdf',
report_name,
report_file,
};
return this.do_action(action);
}
});
core.action_registry.add('reception_report', ReceptionReport);
export default ReceptionReport;