summaryrefslogtreecommitdiff
path: root/addons/point_of_sale/static/src/js/Screens/OrderManagementScreen/OrderManagementControlPanel.js
blob: 951a09561af6ddd881dfcc928687778c1b0f8ce9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
odoo.define('point_of_sale.OrderManagementControlPanel', function (require) {
    'use strict';

    const { useContext } = owl.hooks;
    const { useAutofocus, useListener } = require('web.custom_hooks');
    const PosComponent = require('point_of_sale.PosComponent');
    const Registries = require('point_of_sale.Registries');
    const OrderFetcher = require('point_of_sale.OrderFetcher');
    const contexts = require('point_of_sale.PosContext');

    // NOTE: These are constants so that they are only instantiated once
    // and they can be used efficiently by the OrderManagementControlPanel.
    const VALID_SEARCH_TAGS = new Set(['date', 'customer', 'client', 'name', 'order']);
    const FIELD_MAP = {
        date: 'date_order',
        customer: 'partner_id.display_name',
        client: 'partner_id.display_name',
        name: 'pos_reference',
        order: 'pos_reference',
    };
    const SEARCH_FIELDS = ['pos_reference', 'partner_id.display_name', 'date_order'];

    function getDomainForSingleCondition(fields, toSearch) {
        const orSymbols = Array(fields.length - 1).fill('|');
        return orSymbols.concat(fields.map((field) => [field, 'ilike', `%${toSearch}%`]));
    }

    /**
     * @emits close-screen
     * @emits prev-page
     * @emits next-page
     * @emits search
     */
    class OrderManagementControlPanel extends PosComponent {
        constructor() {
            super(...arguments);
            // We are using context because we want the `searchString` to be alive
            // even if this component is destroyed (unmounted).
            this.orderManagementContext = useContext(contexts.orderManagement);
            useListener('clear-search', this._onClearSearch);
            useAutofocus({ selector: 'input' });
        }
        onInputKeydown(event) {
            if (event.key === 'Enter') {
                this.trigger('search', this._computeDomain());
            }
        }
        get showPageControls() {
            return OrderFetcher.lastPage > 1;
        }
        get pageNumber() {
            const currentPage = OrderFetcher.currentPage;
            const lastPage = OrderFetcher.lastPage;
            return isNaN(lastPage) ? '' : `(${currentPage}/${lastPage})`;
        }
        get validSearchTags() {
            return VALID_SEARCH_TAGS;
        }
        get fieldMap() {
            return FIELD_MAP;
        }
        get searchFields() {
            return SEARCH_FIELDS;
        }
        /**
         * E.g. 1
         * ```
         *   searchString = 'Customer 1'
         *   result = [
         *      '|',
         *      '|',
         *      ['pos_reference', 'ilike', '%Customer 1%'],
         *      ['partner_id.display_name', 'ilike', '%Customer 1%'],
         *      ['date_order', 'ilike', '%Customer 1%']
         *   ]
         * ```
         *
         * E.g. 2
         * ```
         *   searchString = 'date: 2020-05'
         *   result = [
         *      ['date_order', 'ilike', '%2020-05%']
         *   ]
         * ```
         *
         * E.g. 3
         * ```
         *   searchString = 'customer: Steward, date: 2020-05-01'
         *   result = [
         *      ['partner_id.display_name', 'ilike', '%Steward%'],
         *      ['date_order', 'ilike', '%2020-05-01%']
         *   ]
         * ```
         */
        _computeDomain() {
            const input = this.orderManagementContext.searchString.trim();
            if (!input) return;

            const searchConditions = this.orderManagementContext.searchString.split(/[,&]\s*/);
            if (searchConditions.length === 1) {
                let cond = searchConditions[0].split(/:\s*/);
                if (cond.length === 1) {
                    return getDomainForSingleCondition(this.searchFields, cond[0]);
                }
            }
            const domain = [];
            for (let cond of searchConditions) {
                let [tag, value] = cond.split(/:\s*/);
                if (!this.validSearchTags.has(tag)) continue;
                domain.push([this.fieldMap[tag], 'ilike', `%${value}%`]);
            }
            return domain;
        }
        _onClearSearch() {
            this.orderManagementContext.searchString = '';
            this.onInputKeydown({ key: 'Enter' });
        }
    }
    OrderManagementControlPanel.template = 'OrderManagementControlPanel';

    Registries.Component.add(OrderManagementControlPanel);

    return OrderManagementControlPanel;
});