summaryrefslogtreecommitdiff
path: root/addons/point_of_sale/static/src/js/Screens/TicketScreen
diff options
context:
space:
mode:
Diffstat (limited to 'addons/point_of_sale/static/src/js/Screens/TicketScreen')
-rw-r--r--addons/point_of_sale/static/src/js/Screens/TicketScreen/TicketScreen.js220
1 files changed, 220 insertions, 0 deletions
diff --git a/addons/point_of_sale/static/src/js/Screens/TicketScreen/TicketScreen.js b/addons/point_of_sale/static/src/js/Screens/TicketScreen/TicketScreen.js
new file mode 100644
index 00000000..f59b72d0
--- /dev/null
+++ b/addons/point_of_sale/static/src/js/Screens/TicketScreen/TicketScreen.js
@@ -0,0 +1,220 @@
+odoo.define('point_of_sale.TicketScreen', function (require) {
+ 'use strict';
+
+ const Registries = require('point_of_sale.Registries');
+ const IndependentToOrderScreen = require('point_of_sale.IndependentToOrderScreen');
+ const { useListener } = require('web.custom_hooks');
+ const { posbus } = require('point_of_sale.utils');
+
+ class TicketScreen extends IndependentToOrderScreen {
+ constructor() {
+ super(...arguments);
+ useListener('close-screen', this.close);
+ useListener('filter-selected', this._onFilterSelected);
+ useListener('search', this._onSearch);
+ this.searchDetails = {};
+ this.filter = null;
+ this._initializeSearchFieldConstants();
+ }
+ mounted() {
+ posbus.on('ticket-button-clicked', this, this.close);
+ this.env.pos.get('orders').on('add remove change', () => this.render(), this);
+ this.env.pos.on('change:selectedOrder', () => this.render(), this);
+ }
+ willUnmount() {
+ posbus.off('ticket-button-clicked', this);
+ this.env.pos.get('orders').off('add remove change', null, this);
+ this.env.pos.off('change:selectedOrder', null, this);
+ }
+ _onFilterSelected(event) {
+ this.filter = event.detail.filter;
+ this.render();
+ }
+ _onSearch(event) {
+ const searchDetails = event.detail;
+ Object.assign(this.searchDetails, searchDetails);
+ this.render();
+ }
+ /**
+ * Override to conditionally show the new ticket button.
+ */
+ get showNewTicketButton() {
+ return true;
+ }
+ get orderList() {
+ return this.env.pos.get_order_list();
+ }
+ get filteredOrderList() {
+ const { AllTickets } = this.getOrderStates();
+ const filterCheck = (order) => {
+ if (this.filter && this.filter !== AllTickets) {
+ const screen = order.get_screen_data();
+ return this.filter === this.constants.screenToStatusMap[screen.name];
+ }
+ return true;
+ };
+ const { fieldValue, searchTerm } = this.searchDetails;
+ const fieldAccessor = this._searchFields[fieldValue];
+ const searchCheck = (order) => {
+ if (!fieldAccessor) return true;
+ const fieldValue = fieldAccessor(order);
+ if (fieldValue === null) return true;
+ if (!searchTerm) return true;
+ return fieldValue && fieldValue.toString().toLowerCase().includes(searchTerm.toLowerCase());
+ };
+ const predicate = (order) => {
+ return filterCheck(order) && searchCheck(order);
+ };
+ return this.orderList.filter(predicate);
+ }
+ selectOrder(order) {
+ this._setOrder(order);
+ if (order === this.env.pos.get_order()) {
+ this.close();
+ }
+ }
+ _setOrder(order) {
+ this.env.pos.set_order(order);
+ }
+ createNewOrder() {
+ this.env.pos.add_new_order();
+ }
+ async deleteOrder(order) {
+ const screen = order.get_screen_data();
+ if (['ProductScreen', 'PaymentScreen'].includes(screen.name) && order.get_orderlines().length > 0) {
+ const { confirmed } = await this.showPopup('ConfirmPopup', {
+ title: 'Existing orderlines',
+ body: `${order.name} has total amount of ${this.getTotal(
+ order
+ )}, are you sure you want delete this order?`,
+ });
+ if (!confirmed) return;
+ }
+ if (order) {
+ await this._canDeleteOrder(order);
+ order.destroy({ reason: 'abandon' });
+ }
+ posbus.trigger('order-deleted');
+ }
+ getDate(order) {
+ return moment(order.creation_date).format('YYYY-MM-DD hh:mm A');
+ }
+ getTotal(order) {
+ return this.env.pos.format_currency(order.get_total_with_tax());
+ }
+ getCustomer(order) {
+ return order.get_client_name();
+ }
+ getCardholderName(order) {
+ return order.get_cardholder_name();
+ }
+ getEmployee(order) {
+ return order.employee ? order.employee.name : '';
+ }
+ getStatus(order) {
+ const screen = order.get_screen_data();
+ return this.constants.screenToStatusMap[screen.name];
+ }
+ /**
+ * Hide the delete button if one of the payments is a 'done' electronic payment.
+ */
+ hideDeleteButton(order) {
+ return order
+ .get_paymentlines()
+ .some((payment) => payment.is_electronic() && payment.get_payment_status() === 'done');
+ }
+ showCardholderName() {
+ return this.env.pos.payment_methods.some(method => method.use_payment_terminal);
+ }
+ get searchBarConfig() {
+ return {
+ searchFields: this.constants.searchFieldNames,
+ filter: { show: true, options: this.filterOptions },
+ };
+ }
+ get filterOptions() {
+ const { AllTickets, Ongoing, Payment, Receipt } = this.getOrderStates();
+ return [AllTickets, Ongoing, Payment, Receipt];
+ }
+ /**
+ * An object with keys containing the search field names which map to functions.
+ * The mapped functions will be used to generate representative string for the order
+ * to match the search term when searching.
+ * E.g. Given 2 orders, search those with `Receipt Number` containing `1111`.
+ * ```
+ * orders = [{
+ * name: '000-1111-222'
+ * total: 10,
+ * }, {
+ * name: '444-5555-666'
+ * total: 15,
+ * }]
+ * ```
+ * `Receipt Number` search field maps to the `name` of the order. So, the orders will be
+ * represented by their name, and the search will result to:
+ * ```
+ * result = [{
+ * name: '000-1111-222',
+ * total: 10,
+ * }]
+ * ```
+ * @returns Record<string, (models.Order) => string>
+ */
+ get _searchFields() {
+ const { ReceiptNumber, Date, Customer, CardholderName } = this.getSearchFieldNames();
+ var fields = {
+ [ReceiptNumber]: (order) => order.name,
+ [Date]: (order) => moment(order.creation_date).format('YYYY-MM-DD hh:mm A'),
+ [Customer]: (order) => order.get_client_name(),
+ };
+
+ if (this.showCardholderName()) {
+ fields[CardholderName] = (order) => order.get_cardholder_name();
+ }
+
+ return fields;
+ }
+ /**
+ * Maps the order screen params to order status.
+ */
+ get _screenToStatusMap() {
+ const { Ongoing, Payment, Receipt } = this.getOrderStates();
+ return {
+ ProductScreen: Ongoing,
+ PaymentScreen: Payment,
+ ReceiptScreen: Receipt,
+ };
+ }
+ _initializeSearchFieldConstants() {
+ this.constants = {};
+ Object.assign(this.constants, {
+ searchFieldNames: Object.keys(this._searchFields),
+ screenToStatusMap: this._screenToStatusMap,
+ });
+ }
+ async _canDeleteOrder(order) {
+ return true;
+ }
+ getOrderStates() {
+ return {
+ AllTickets: this.env._t('All Tickets'),
+ Ongoing: this.env._t('Ongoing'),
+ Payment: this.env._t('Payment'),
+ Receipt: this.env._t('Receipt'),
+ };
+ }
+ getSearchFieldNames() {
+ return {
+ ReceiptNumber: this.env._t('Receipt Number'),
+ Date: this.env._t('Date'),
+ Customer: this.env._t('Customer'),
+ CardholderName: this.env._t('Cardholder Name'),
+ };
+ }
+ }
+ TicketScreen.template = 'TicketScreen';
+
+ Registries.Component.add(TicketScreen);
+
+ return TicketScreen;
+});