odoo18/addons/event/static/src/client_action/event_barcode.js

150 lines
5.4 KiB
JavaScript

/** @odoo-module **/
import { _t } from "@web/core/l10n/translation";
import { BarcodeScanner } from "@barcodes/components/barcode_scanner";
import { Component, onWillStart } from "@odoo/owl";
import { isDisplayStandalone } from "@web/core/browser/feature_detection";
import { rpc } from "@web/core/network/rpc";
import { registry } from "@web/core/registry";
import { useBus, useService } from "@web/core/utils/hooks";
import { url } from '@web/core/utils/urls';
import { EventRegistrationSummaryDialog } from "./event_registration_summary_dialog";
import { scanBarcode } from "@web/core/barcode/barcode_dialog";
import { standardActionServiceProps } from "@web/webclient/actions/action_service";
export class EventScanView extends Component {
static template = "event.EventScanView";
static components = { BarcodeScanner };
static props = { ...standardActionServiceProps };
setup() {
this.actionService = useService("action");
this.dialog = useService("dialog");
this.notification = useService("notification");
this.orm = useService("orm");
const { default_event_id, active_model, active_id } = this.props.action.context;
this.eventId = default_event_id || (active_model === "event.event" && active_id);
this.isMultiEvent = !this.eventId;
this.isDisplayStandalone = isDisplayStandalone();
const barcode = useService("barcode");
useBus(barcode.bus, "barcode_scanned", (ev) => this.onBarcodeScanned(ev.detail.barcode));
onWillStart(this.onWillStart);
}
/**
* @override
* Fetch barcode init information. Notably eventId triggers mono- or multi-
* event mode (Registration Desk in multi event allow to manage attendees
* from several events and tickets without reloading / changing event in UX.
*/
async onWillStart() {
this.data = await rpc("/event/init_barcode_interface", {
event_id: this.eventId,
});
const fileExtension = new Audio().canPlayType("audio/ogg") ? "ogg" : "mp3";
this.sounds = {
error: new Audio(url(`/barcodes/static/src/audio/error.${fileExtension}`)),
notify: new Audio(url(`/mail/static/src/audio/ting.${fileExtension}`)),
};
this.sounds.error.load();
this.sounds.notify.load();
}
playSound(type) {
type = type || "notify";
this.sounds[type].currentTime = 0;
this.sounds[type].play();
}
/**
* When scanning a barcode, call Registration.register_attendee() to get
* formatted registration information, notably its status or event-related
* information. Open a confirmation / choice Dialog to confirm attendee.
*/
async onBarcodeScanned(barcode) {
const result = await this.orm.call("event.registration", "register_attendee", [], {
barcode: barcode,
event_id: this.eventId,
});
if (result.error && result.error === "invalid_ticket") {
this.playSound("error");
this.notification.add(_t("Invalid ticket"), {
title: _t("Warning"),
type: "danger",
});
} else {
this.registrationId = result.id;
this.closeLastDialog?.();
this.closeLastDialog = this.dialog.add(
EventRegistrationSummaryDialog,
{
playSound: (type) => this.playSound(type),
doNextScan: () => this.doNextScan(),
registration: result
}
);
}
}
/**
* Duplication of the openMobileScanner() method from BarcodeScanner component
* to avoid using the component in the template and to be able to call it directly
* from the dialog.
*/
async doNextScan() {
let error = null;
let barcode = null;
try {
barcode = await scanBarcode(this.env, this.facingMode);
} catch (err) {
error = err.message;
}
if (barcode) {
await this.onBarcodeScanned(barcode);
if ("vibrate" in window.navigator) {
window.navigator.vibrate(100);
}
} else {
this.notification.add(error || _t("Please, Scan again!"), {
type: "warning",
});
}
}
onClickSelectAttendee() {
if (this.isMultiEvent) {
this.actionService.doAction("event.event_registration_action", {
additionalContext: {
is_registration_desk_view: true, // To remove in master
},
});
} else {
this.actionService.doAction("event.event_registration_action_kanban", {
additionalContext: {
active_id: this.eventId,
is_registration_desk_view: true, // To remove in master
search_default_unconfirmed: true,
search_default_confirmed: true,
},
});
}
}
onClickBackToEvents() {
if (this.isMultiEvent) {
// define action from scratch instead of using existing 'action_event_view' to avoid
// messing with menu bar
this.actionService.doAction("event.action_event_view", { clearBreadcrumbs: true });
} else {
this.actionService.restore();
}
}
}
registry.category("actions").add("event.event_barcode_scan_view", EventScanView);