diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/js/rack_parts_dialog.js b/fusion_plating/fusion_plating_shopfloor/static/src/js/rack_parts_dialog.js new file mode 100644 index 00000000..333c81c8 --- /dev/null +++ b/fusion_plating/fusion_plating_shopfloor/static/src/js/rack_parts_dialog.js @@ -0,0 +1,90 @@ +/** @odoo-module */ +/* + * Sub 12b — Rack Parts sub-dialog (OWL). + * + * Mirrors Steelhead screens 7-8. Searchable empty-rack picker, + * QR-scan input, Unit + Amount fields. Save assigns the step → rack; + * Save + Print also opens the rack travel ticket PDF (Sub 12c). + */ + +import { Component, onWillStart, useState } from "@odoo/owl"; +import { Dialog } from "@web/core/dialog/dialog"; +import { rpc } from "@web/core/network/rpc"; +import { useService } from "@web/core/utils/hooks"; +import { _t } from "@web/core/l10n/translation"; + + +export class FpRackPartsDialog extends Component { + static template = "fusion_plating_shopfloor.FpRackPartsDialog"; + static components = { Dialog }; + static props = ["fromStepId", "qty", "onRacked?", "close"]; + + setup() { + this.notification = useService("notification"); + this.state = useState({ + racks: [], + search: "", + selectedRackId: false, + unit: "Count", + amount: this.props.qty || 0, + saving: false, + }); + onWillStart(async () => { + await this.refreshRacks(""); + }); + } + + async refreshRacks(query) { + const data = await rpc("/fp/tablet/rack/list_empty", { query }); + if (data.ok) { + this.state.racks = data.racks; + } + } + + async onSearch(ev) { + this.state.search = ev.target.value; + await this.refreshRacks(this.state.search); + } + + async onScan() { + const code = window.prompt(_t("Scan or type FP-RACK::")); + if (!code) return; + const data = await rpc("/fp/tablet/rack/scan_qr", { qr_code: code }); + if (data.ok) { + this.state.selectedRackId = data.rack_id; + this.notification.add( + _t("Selected %s", data.rack_name), { type: "success" }); + } else { + this.notification.add(data.error, { type: "danger" }); + } + } + + async onSave(printAfter) { + if (!this.state.selectedRackId) return; + this.state.saving = true; + const result = await rpc("/fp/tablet/rack_parts/commit", { + from_step_id: this.props.fromStepId, + rack_id: this.state.selectedRackId, + qty: this.state.amount, + }); + if (result.ok) { + this.notification.add( + _t("Racked onto %s", result.rack_name), + { type: "success" }); + if (this.props.onRacked) { + this.props.onRacked(result); + } + this.props.close(); + if (printAfter) { + // Sub 12c report — until it ships, this returns 404. + window.open( + `/web/report/pdf/fp.rack.travel/${this.state.selectedRackId}`, + "_blank", + ); + } + } else { + this.notification.add(result.error, { type: "danger" }); + this.state.saving = false; + } + } +} diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/xml/rack_parts_dialog.xml b/fusion_plating/fusion_plating_shopfloor/static/src/xml/rack_parts_dialog.xml new file mode 100644 index 00000000..5ee19e07 --- /dev/null +++ b/fusion_plating/fusion_plating_shopfloor/static/src/xml/rack_parts_dialog.xml @@ -0,0 +1,67 @@ + + + + + +
+ +
+ + + +
+ +
+
+ +
+ + + +
+ +
+ + + +
+
+ + + + + + +
+
+ +