orders_helper.js 79.1 KB
Newer Older
1
var suppliers_list = [],
2
    selected_suppliers = [],
3
    products_list = [],
Damien Moulard committed
4
    products = [],
5
    products_table = null,
6
    selected_rows = [],
7 8 9 10 11 12 13 14
    product_orders = [],
    date_format = "dd/mm/yy",
    new_product_supplier_association = {
        package_qty: null,
        price: null
    };

var dbc = null,
15 16 17
    sync = null,
    order_doc = {
        _id: null,
18
        coverage_days: null,
19
        stats_date_period: '',
20
        last_update: {
21
            timestamp: null,
22
            fingerprint: null
23
        },
24 25 26
        products: [],
        selected_suppliers: [],
        selected_rows: []
27
    },
28
    fingerprint = null;
29

30 31
var clicked_order_pill = null;

32

33 34
/* - UTILS */

35 36 37 38
/**
 * Reset data that changes between screens
 */
function reset_data() {
39 40 41 42
    products = [];
    selected_suppliers = [];
    selected_rows = [];
    product_orders = [];
43 44
    order_doc = {
        _id: null,
45
        coverage_days: null,
46
        stats_date_period: '',
47 48
        last_update : {
            timestamp: null,
49
            fingerprint: null
50
        },
51
        products: [],
Damien Moulard committed
52
        selected_suppliers: []
53
    };
54 55 56 57
    new_product_supplier_association = {
        package_qty: null,
        price: null
    };
58
    clicked_order_pill = null;
59 60
}

61 62
/**
 * Difference between two dates
63 64
 * @param {Date} date1
 * @param {Date} date2
65 66 67
 * @returns difference object
 */
function dates_diff(date1, date2) {
68
    var diff = {};
69
    var tmp = date2 - date1;
70

71 72
    tmp = Math.floor(tmp/1000);
    diff.sec = tmp % 60;
73

74 75
    tmp = Math.floor((tmp-diff.sec)/60);
    diff.min = tmp % 60;
76

77 78
    tmp = Math.floor((tmp-diff.min)/60);
    diff.hours = tmp % 24;
79

80 81
    tmp = Math.floor((tmp-diff.hours)/24);
    diff.days = tmp;
82

83 84 85
    return diff;
}

86 87
/**
 * Compute the date from which to calculate stats of sells,
Damien Moulard committed
88 89
 *  depending on the selected parameter.
 *
90 91 92 93
 * @returns String value of the date, ISO format
 */
function _compute_stats_date_from() {
    let val = '';
Damien Moulard committed
94

95 96 97 98
    if (order_doc.stats_date_period !== '') {
        let date = new Date();

        switch (order_doc.stats_date_period) {
Damien Moulard committed
99 100 101 102 103 104 105 106
        case '1week':
            date.setDate(date.getDate() - 7);
            break;
        case '2weeks':
            date.setDate(date.getDate() - 14);
            break;
        default:
            break;
107 108 109 110 111 112 113
        }

        let day = ("0" + date.getDate()).slice(-2);
        let month = ("0" + (date.getMonth() +1)).slice(-2);
        let year = date.getFullYear();

        val = `${year}-${month}-${day}`;
Damien Moulard committed
114
    }
115 116 117 118

    return val;
}

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
/* - PRODUCTS */

/**
 * Add a product.
 *
 * @returns -1 if validation failed, 0 otherwise
 */
function add_product() {
    const user_input = $("#product_input").val();

    // Check if user input is a valid article
    const product = products_list.find(s => s.display_name === user_input);

    if (product === undefined) {
        alert("L'article renseigné n'est pas valide.\n"
        + "Veuillez sélectionner un article dans la liste déroulante.");

        return -1;
    }
Damien Moulard committed
138 139 140 141 142 143 144 145 146 147

    const product_exists = products.findIndex(p => p.name === user_input);

    if (product_exists !== -1) {
        alert("Cet article est déjà dans le tableau.");
        $("#product_input").val('');

        return -1;
    }

148 149 150
    let data = {
        pids: [product.tpl_id],
        stats_from: _compute_stats_date_from()
Damien Moulard committed
151
    };
152

153
    $.ajax({
154 155
        type: 'POST',
        url: '/products/get_product_for_order_helper',
156
        data: JSON.stringify(data),
157 158 159 160
        dataType:"json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        success: function(data) {
161
            let res = data.products[0];
162

163 164 165 166
            if (typeof res.id != "undefined") {
                res.suppliersinfo = [];
                res.default_code = ' ';
                products.unshift(res);
167
                update_main_screen({'sort_order_dir':'desc'});
Damien Moulard committed
168
                update_cdb_order();
169
            } else {
Damien Moulard committed
170
                alert("L'article n'a pas toutes les caractéristiques pour être ajouté.");
171 172 173 174 175 176 177 178 179 180 181 182
            }
            $("#product_input").val('');
        },
        error: function(data) {
            err = {msg: "erreur serveur lors de la récupération des données liées à l'article", ctx: 'get_product_for_help_order_line'};
            if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                err.msg += ' : ' + data.responseJSON.error;
            }
            report_JS_error(err, 'orders');
            alert('Erreur lors de la récupération des informations, réessayer plus tard.');
        }
    });
Damien Moulard committed
183

184 185 186
    return 0;
}

187 188 189 190 191
/**
 * Compute the qty to buy for each product, depending the coverage days.
 * Set the computed qty for the first supplier only.
 */
function compute_products_coverage_qties() {
192 193 194 195 196 197 198
    if (order_doc.coverage_days != null) {
        for (const [
            key,
            product
        ] of Object.entries(products)) {
            if ('suppliersinfo' in product && product.suppliersinfo.length > 0) {
                let purchase_qty_for_coverage = null;
199

200 201 202 203
                // Durée couverture produit = (stock + qté entrante + qté commandée ) / conso quotidienne
                const stock = product.qty_available;
                const incoming_qty = product.incoming_qty;
                const daily_conso = product.daily_conso;
204

205 206
                purchase_qty_for_coverage = order_doc.coverage_days * daily_conso - stock - incoming_qty;
                purchase_qty_for_coverage = (purchase_qty_for_coverage < 0) ? 0 : purchase_qty_for_coverage;
207

208 209
                // Reduce to nb of packages to purchase
                purchase_package_qty_for_coverage = purchase_qty_for_coverage / product.suppliersinfo[0].package_qty;
210

211 212
                // Round up to unit for all products
                purchase_package_qty_for_coverage = Math.ceil(purchase_package_qty_for_coverage);
213

214 215 216
                // Set qty to purchase for first supplier only
                products[key].suppliersinfo[0].qty = purchase_package_qty_for_coverage;
            }
217 218 219 220
        }
    }
}

221 222 223 224
/**
 * Update order products data in case they have changed.
 */
function check_products_data() {
225
    return new Promise((resolve) => {
226
        const suppliers_id = selected_suppliers.map(s => s.id);
227

228
        if (suppliers_id.length > 0) {
Damien Moulard committed
229 230 231 232
            $.notify(
                "Vérfication des informations produits...",
                {
                    globalPosition:"top left",
233
                    className: "info"
Damien Moulard committed
234 235 236
                }
            );

237 238 239 240
            if (clicked_order_pill != null) {
                clicked_order_pill.find('.pill_order_name').empty()
                    .append(`<i class="fas fa-spinner fa-spin"></i>`);
            }
241 242

            $.ajax({
243 244 245
                type: 'GET',
                url: '/orders/get_supplier_products',
                data: {
246 247
                    sids: suppliers_id,
                    stats_from: _compute_stats_date_from()
248
                },
249 250 251 252
                dataType:"json",
                traditional: true,
                contentType: "application/json; charset=utf-8",
                success: function(data) {
253
                    for (let product of data.res.products) {
254 255
                        const p_index = products.findIndex(p => p.id == product.id);

256 257 258 259 260
                        if (p_index === -1) {
                            // Add product if it wasn't fetched before (made available since last access to order)
                            products.push(product);
                        } else {
                            // Save old product suppliersinfo to keep user qty inputs
Damien Moulard committed
261
                            const old_suppliersinfo = [...products[p_index].suppliersinfo];
262 263 264 265 266 267 268

                            // Update product data
                            products[p_index] = product;

                            // Re-set qties
                            for (let psi_index in products[p_index].suppliersinfo) {
                                const old_psi = old_suppliersinfo.find(psi => psi.supplier_id == products[p_index].suppliersinfo[psi_index].supplier_id);
Damien Moulard committed
269

270 271 272
                                if (old_psi !== undefined && old_psi.qty !== undefined) {
                                    products[p_index].suppliersinfo[psi_index].qty = old_psi.qty;
                                }
273
                            }
274
                        }
275 276
                    }

Damien Moulard committed
277
                    $('.notifyjs-wrapper').trigger('notify-hide');
278 279 280 281 282 283 284 285 286 287
                    resolve();
                },
                error: function(data) {
                    err = {msg: "erreur serveur lors de la vérification des données des articles", ctx: 'check_products_data'};
                    if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                        err.msg += ' : ' + data.responseJSON.error;
                    }
                    report_JS_error(err, 'orders');
                    alert(`Erreur lors de la vérification des données des articles. Certaines données peuvent être erronées`);

Damien Moulard committed
288
                    $('.notifyjs-wrapper').trigger('notify-hide');
289 290 291 292 293 294 295 296 297 298
                    // Don't block process if this call fails
                    resolve();
                }
            });
        } else {
            resolve();
        }
    });
}

Damien Moulard committed
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
/**
 * Update the product internal reference ('default_code')
 *
 * @param {HTMLElement} input_el
 * @param {int} p_id
 * @param {int} p_index
 */
function update_product_ref(input_el, p_id, p_index) {
    const val = $(input_el).val();
    const existing_val = products[p_index].default_code.replace("[input]", "");

    products[p_index].default_code = val;

    const row = $(input_el).closest('tr');
    const new_row_data = prepare_datatable_data([p_id])[0];

    products_table.row(row).data(new_row_data)
        .draw();

    $('#products_table')
        .off('blur', 'tbody .product_ref_input')
        .off('keypress', 'tbody .product_ref_input');

    // Update in backend if value changed
    if (existing_val !== val) {
        const data = {
            'product_tmpl_id': p_id,
            'default_code': val
        };

        // Send request to create association
        $.ajax({
            type: "POST",
            url: "/products/update_product_internal_ref",
            dataType: "json",
            traditional: true,
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(data),
            success: () => {
                update_cdb_order();

                $(".actions_buttons_area .right_action_buttons").notify(
                    "Référence sauvegardée !",
                    {
                        elementPosition:"bottom right",
                        className: "success",
                        arrowShow: false
                    }
                );
            },
            error: function(data) {
                let msg = "erreur serveur lors de la sauvegarde de la référence";

                msg += ` (product_tmpl_id: ${product.id}`;

                err = {msg: msg, ctx: 'update_product_ref'};
                if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                    err.msg += ' : ' + data.responseJSON.error;
                }
                report_JS_error(err, 'orders');

                alert('Erreur lors de la sauvegarde de la référence dans Odoo. Veuillez recharger la page et ré-essayer plus tard.');
            }
        });
    }
}

366

367
/* - SUPPLIERS */
368

369 370
/**
 * Add a supplier to the selected suppliers list.
Damien Moulard committed
371 372
 *
 * @returns -1 if validation failed, 0 otherwise
373 374 375 376
 */
function add_supplier() {
    const user_input = $("#supplier_input").val();

377
    let supplier = suppliers_list.find(s => s.display_name === user_input);
Damien Moulard committed
378

Damien Moulard committed
379
    // Check if user input is a valid supplier
380
    if (supplier === undefined) {
Damien Moulard committed
381
        alert("Le fournisseur renseigné n'est pas valide.\n"
382
        + "Veuillez sélectionner un fournisseur dans la liste déroulante.");
Damien Moulard committed
383

384 385 386
        return -1;
    }

Damien Moulard committed
387 388
    const supplier_selected = selected_suppliers.find(s => s.display_name === user_input);

389 390
    if (supplier_selected !== undefined) {
        alert("Ce fournisseur est déjà sélectionné.");
Damien Moulard committed
391

392 393 394 395 396 397 398 399
        return -1;
    }

    openModal();

    // Fetch supplier products
    $.ajax({
        type: 'GET',
400 401 402 403 404
        url: "/orders/get_supplier_products",
        data: {
            sids: [supplier.id],
            stats_from: _compute_stats_date_from()
        },
405 406 407 408
        dataType:"json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        success: function(data) {
Damien Moulard committed
409 410 411 412
            supplier.total_value = 0;
            supplier.total_packages = 0;
            selected_suppliers.push(supplier);

413
            save_supplier_products(supplier, data.res.products);
414
            update_main_screen();
Damien Moulard committed
415
            $("#supplier_input").val("");
416
            update_cdb_order();
417 418 419 420 421 422 423 424 425 426 427 428 429
            closeModal();
        },
        error: function(data) {
            err = {msg: "erreur serveur lors de la récupération des produits", ctx: 'get_supplier_products'};
            if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                err.msg += ' : ' + data.responseJSON.error;
            }
            report_JS_error(err, 'orders');

            closeModal();
            alert('Erreur lors de la récupération des produits, réessayer plus tard.');
        }
    });
Damien Moulard committed
430 431

    return 0;
432
}
433

434 435 436 437 438 439 440 441 442 443 444
/**
 * Remove a supplier from the selected list & its associated products
 *
 * @param {int} supplier_id
 */
function remove_supplier(supplier_id) {
    // Remove from suppliers list
    selected_suppliers = selected_suppliers.filter(supplier => supplier.id != supplier_id);

    // Remove the supplier from the products suppliers list
    for (const i in products) {
445
        products[i].suppliersinfo = products[i].suppliersinfo.filter(supplier => supplier.supplier_id != supplier_id);
446 447 448
    }

    // Remove products only associated to this product
449
    products = products.filter(product => product.suppliersinfo.length > 0);
450

451
    update_main_screen();
452
    update_cdb_order();
453 454 455
}


456 457
/**
 * Send to server the association product-supplier
Damien Moulard committed
458 459 460
 *
 * @param {object} product
 * @param {object} supplier
461 462
 * @param {node} cell product's row in datatable
 */
Damien Moulard committed
463
function save_supplier_product_association(product, supplier, cell) {
464 465
    openModal();

466 467 468 469 470 471 472 473 474
    $('.new_product_supplier_price').off();
    $('.new_product_supplier_package_pty').off();

    const package_qty = parseFloat(new_product_supplier_association.package_qty);
    const price = parseFloat(new_product_supplier_association.price);

    // If value is a number
    if (isNaN(package_qty) || isNaN(price)) {
        closeModal();
Damien Moulard committed
475 476
        alert(`Les champs "Prix" et "Colisage" doivent être remplis et valides. L'association n'a pas été sauvegardée.`);

477 478 479
        return -1;
    }

480 481
    const data = {
        product_tmpl_id: product.id,
482 483
        supplier_id: supplier.id,
        package_qty: package_qty,
Damien Moulard committed
484
        price: price
Damien Moulard committed
485
    };
486

487
    // Send request to create association
488 489 490 491 492 493 494 495
    $.ajax({
        type: "POST",
        url: "/orders/associate_supplier_to_product",
        dataType: "json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(data),
        success: () => {
496
            // Save supplierinfo in product
Damien Moulard committed
497 498
            if (!('suppliersinfo' in product)) {
                product.suppliersinfo = [];
499
            }
Damien Moulard committed
500

501 502 503
            product.suppliersinfo.push({
                supplier_id: supplier.id,
                package_qty: package_qty,
504
                product_code: false,
505
                price: price
Damien Moulard committed
506
            });
507

508
            // Save relation locally
Damien Moulard committed
509
            save_supplier_products(supplier, [product]);
510 511

            // Update table
Damien Moulard committed
512 513 514 515 516 517
            $(cell).removeClass("product_not_from_supplier");
            const row = $(cell).closest("tr");
            const new_row_data = prepare_datatable_data([product.id])[0];

            products_table.row(row).data(new_row_data)
                .draw();
518

519
            update_cdb_order();
520 521 522
            closeModal();
        },
        error: function(data) {
Damien Moulard committed
523 524 525
            let msg = "erreur serveur lors de la sauvegarde de l'association product/supplier";

            msg += ` (product_tmpl_id: ${product.id}; supplier_id: ${supplier.id})`;
Damien Moulard committed
526

527 528 529 530 531 532 533 534 535 536
            err = {msg: msg, ctx: 'save_supplier_product_association'};
            if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                err.msg += ' : ' + data.responseJSON.error;
            }
            report_JS_error(err, 'orders');

            closeModal();
            alert('Erreur lors de la sauvegarde de l\'association. Veuillez ré-essayer plus tard.');
        }
    });
Damien Moulard committed
537 538

    return 0;
539 540
}

541 542 543 544 545 546
/**
 * Send to server the deletion of association product-supplier
 *
 * @param {object} product
 * @param {object} supplier
 */
547
function end_supplier_product_association(product, supplier) {
548 549 550 551 552 553 554 555 556 557
    openModal();

    const data = {
        product_tmpl_id: product.id,
        supplier_id: supplier.id
    };

    // Send request to create association
    $.ajax({
        type: "POST",
558
        url: "/orders/end_supplier_product_association",
559 560 561 562
        dataType: "json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(data),
Damien Moulard committed
563
        success: () => {
564 565 566
            // Remove relation locally
            let p_index = products.findIndex(p => p.id == product.id);
            let psi_index = product.suppliersinfo.findIndex(psi => psi.supplier_id == supplier.id);
Damien Moulard committed
567

568 569 570 571
            products[p_index].suppliersinfo.splice(psi_index, 1);

            // Update table
            display_products();
Damien Moulard committed
572

573 574 575 576 577 578 579
            update_cdb_order();
            closeModal();
        },
        error: function(data) {
            let msg = "erreur serveur lors de la suppression de l'association product/supplier".
                msg += ` (product_tmpl_id: ${product.id}; supplier_id: ${supplier.id})`;

580
            err = {msg: msg, ctx: 'end_supplier_product_association'};
581 582 583 584 585 586 587 588 589 590 591 592 593
            if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                err.msg += ' : ' + data.responseJSON.error;
            }
            report_JS_error(err, 'orders');

            closeModal();
            alert('Erreur lors de la suppression de l\'association. Veuillez ré-essayer plus tard.');
        }
    });

    return 0;
}

594 595 596 597
/**
 * When products are fetched, save them and the relation with the supplier.
 * If product already saved, add the supplier to its suppliers list.
 * Else, add product with supplier.
Damien Moulard committed
598 599 600
 *
 * @param {object} supplier
 * @param {array} new_products
601
 */
602
function save_supplier_products(supplier, new_products) {
603 604 605 606
    for (np of new_products) {
        let index = products.findIndex(p => p.id === np.id);

        if (index === -1) {
Damien Moulard committed
607
            products.push(np);
608
        } else {
609
            // Prevent adding duplicate supplierinfo
Damien Moulard committed
610
            let index_existing_supplierinfo = products[index].suppliersinfo.findIndex(psi => psi.supplier_id == supplier.id);
611 612

            if (index_existing_supplierinfo === -1) {
613 614 615
                // Find the right supplierinfo in new product
                let np_supplierinfo = np.suppliersinfo.find(psi => psi.supplier_id == supplier.id);

616 617
                products[index].suppliersinfo.push(np_supplierinfo);
            }
618 619 620 621 622 623
        }
    }
}

/**
 * Save the quantity set for a product/supplier
Damien Moulard committed
624 625 626 627
 *
 * @param {int} prod_id
 * @param {int} supplier_id
 * @param {float} val
628 629 630 631
 */
function save_product_supplier_qty(prod_id, supplier_id, val) {
    for (const i in products) {
        if (products[i].id == prod_id) {
632 633 634
            for (const j in products[i].suppliersinfo) {
                if (products[i].suppliersinfo[j].supplier_id == supplier_id) {
                    products[i].suppliersinfo[j].qty = val;
635 636 637
                    break;
                }
            }
638 639 640 641 642 643
        }
    }
}

/**
 * Look in the 'suppliers' property of a product
Damien Moulard committed
644 645 646
 *
 * @param {object} product
 * @param {object} supplier
647 648 649
 * @returns boolean
 */
function is_product_related_to_supplier(product, supplier) {
650
    return product.suppliersinfo.find(s => s.supplier_id === supplier.id) !== undefined;
651 652
}

653 654 655 656 657 658 659
/**
 * Calculate the total value purchased for all supplier
 */
function _compute_total_values_by_supplier() {
    // Reinit
    for (let s of selected_suppliers) {
        s.total_value = 0;
660
        s.total_packages = 0;
661 662 663 664 665 666
    }

    for (let p of products) {
        for (let supinfo of p.suppliersinfo) {
            let supplier_index = selected_suppliers.findIndex(s => s.id == supinfo.supplier_id);

667
            // Value
668
            let product_supplier_value = ('qty' in supinfo) ? supinfo.qty * supinfo.package_qty * supinfo.price : 0;
Damien Moulard committed
669

670
            selected_suppliers[supplier_index].total_value += product_supplier_value;
671 672 673

            // Packages
            selected_suppliers[supplier_index].total_packages += ('qty' in supinfo) ? supinfo.qty : 0;
674 675 676 677
        }
    }
}

Damien Moulard committed
678 679 680 681
/* - PRODUCT */

/**
 * Update 'purchase_ok' of a product
Damien Moulard committed
682 683
 *
 * @param {int} p_id product id
Damien Moulard committed
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
 * @param {Boolean} npa value to set purchase_ok to
 */
function set_product_npa(p_id, npa) {
    openModal();

    const data = {
        product_tmpl_id: p_id,
        purchase_ok: !npa
    };

    // Fetch supplier products
    $.ajax({
        type: "POST",
        url: "/products/update_product_purchase_ok",
        dataType: "json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(data),
        success: () => {
            const index = products.findIndex(p => p.id == p_id);
Damien Moulard committed
704

Damien Moulard committed
705 706
            // Give time for modal to fade
            setTimeout(function() {
707
                $(".actions_buttons_area .right_action_buttons").notify(
Damien Moulard committed
708 709
                    "Produit passé en NPA !",
                    {
710
                        elementPosition:"bottom right",
711 712
                        className: "success",
                        arrowShow: false
Damien Moulard committed
713 714 715 716 717 718 719
                    }
                );
            }, 500);

            // Remove NPA products
            products.splice(index, 1);
            update_main_screen();
720
            update_cdb_order();
Damien Moulard committed
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740

            closeModal();
        },
        error: function(data) {
            let msg = "erreur serveur lors de la sauvegarde du NPA".
                msg += ` (product_tmpl_id: ${p_id})`;

            err = {msg: msg, ctx: 'set_product_npa'};
            if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                err.msg += ' : ' + data.responseJSON.error;
            }
            report_JS_error(err, 'orders');

            closeModal();
            alert('Erreur lors de la sauvegarde de la donnée. Veuillez ré-essayer plus tard.');
            update_main_screen();
        }
    });
}

741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
/* - INVENTORY */

/**
 * Create an inventory with the selected lines in the table
 */
function generate_inventory() {
    if (products_table !== null) {
        const selected_data = products_table.rows('.selected').data();

        if (selected_data.length == 0) {
            alert("Veuillez sélectionner les produits à inventorier en cochant les cases sur la gauche du tableau.");
        } else {
            data = {
                lines: [],
                partners_id: [],
                type: 'product_templates'
            };

            for (var i = 0; i < selected_data.length; i++) {
                const product = products.find(p => p.id == selected_data[i].id);

                data.lines.push(product.id);
763 764 765
                for (const supplierinfo of product.suppliersinfo) {
                    if (data.partners_id.indexOf(supplierinfo.supplier_id) === -1) {
                        data.partners_id.push(supplierinfo.supplier_id);
766 767 768 769 770 771 772 773 774 775 776
                    }
                }
            }

            let modal_create_inventory = $('#templates #modal_create_inventory');

            modal_create_inventory.find(".inventory_products_count").text(data.lines.length);

            openModal(
                modal_create_inventory.html(),
                () => {
777
                    if (is_time_to('validate_generate_inventory')) {
778
                        $('#toggle_action_buttons .button_content').empty()
779
                            .append(`<i class="fas fa-spinner fa-spin"></i>`);
780 781 782 783 784 785 786 787 788
                        $.ajax({
                            type: "POST",
                            url: "/inventory/generate_inventory_list",
                            dataType: "json",
                            traditional: true,
                            contentType: "application/json; charset=utf-8",
                            data: JSON.stringify(data),
                            success: () => {
                                unselect_all_rows();
789

790 791
                                // Give time for modal to fade
                                setTimeout(function() {
792 793 794
                                    $('#toggle_action_buttons .button_content').empty()
                                        .append(`Actions`);
                                    $('#toggle_action_buttons').notify(
795 796
                                        "Inventaire créé !",
                                        {
797
                                            elementPosition:"bottom center",
Damien Moulard committed
798
                                            className: "success"
799 800 801 802 803
                                        }
                                    );
                                }, 200);
                            },
                            error: function(data) {
804 805
                                $('#do_inventory').empty()
                                    .append(`Faire un inventaire`);
806 807
                                let msg = "erreur serveur lors de la création de l'inventaire".
                                    err = {msg: msg, ctx: 'generate_inventory'};
808

809 810 811 812
                                if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                                    err.msg += ' : ' + data.responseJSON.error;
                                }
                                report_JS_error(err, 'orders');
813

814
                                alert("Erreur lors de la création de l'inventaire. Réessayez plus tard.");
815
                            }
816 817
                        });
                    }
818 819 820 821 822 823 824
                },
                'Valider'
            );
        }
    }
}

Damien Moulard committed
825 826 827 828 829 830
/* - ORDER */

/**
 * Event fct: on click on an order button
 */
function order_pill_on_click() {
831
    if (is_time_to('order_pill_on_click', 1000)) {
832 833 834
        clicked_order_pill = $(this);
        let order_name_container = clicked_order_pill.find('.pill_order_name');
        let doc_id = $(order_name_container).text();
835

836 837 838 839
        dbc.get(doc_id).then((doc) => {
            if (doc.last_update.fingerprint !== fingerprint) {
                time_diff = dates_diff(new Date(doc.last_update.timestamp), new Date());
                diff_str = ``;
840

841 842 843 844 845 846 847 848 849 850
                if (time_diff.days !== 0) {
                    diff_str += `${time_diff.days} jour(s), `;
                }
                if (time_diff.hours !== 0) {
                    diff_str += `${time_diff.hours} heure(s), `;
                }
                if (time_diff.min !== 0) {
                    diff_str += `${time_diff.min} min, `;
                }
                diff_str += `${time_diff.sec}s`;
851

852
                let modal_order_access = $('#templates #modal_order_access');
853

854
                modal_order_access.find(".order_last_update").text(diff_str);
855

856 857 858
                openModal(
                    modal_order_access.html(),
                    () => {
859 860 861
                        if (is_time_to('validate_access_order')) {
                            goto_main_screen(doc);
                        }
862 863
                    },
                    'Valider'
Damien Moulard committed
864 865
                );
            } else {
866
                goto_main_screen(doc);
Damien Moulard committed
867
            }
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
        })
            .catch(function (err) {
                if (err.status == 404) {
                    $.notify(
                        "Cette commande n'existe plus.",
                        {
                            globalPosition:"top right",
                            className: "error"
                        }
                    );
                    update_order_selection_screen();
                } else {
                    alert('Erreur lors de la récupération de la commande. Si l\'erreur persiste, contactez un administrateur svp.');
                }
                console.log(err);
            });
    }

Damien Moulard committed
886 887 888 889 890
}

/**
 * Create an order in couchdb if the name doesn't exist
 */
891
function create_cdb_order() {
Damien Moulard committed
892 893 894
    const order_name = $("#new_order_name").val();

    order_doc._id = order_name;
895 896 897 898
    order_doc.last_update = {
        timestamp: Date.now(),
        fingerprint: fingerprint
    };
Damien Moulard committed
899 900 901
    dbc.put(order_doc, function callback(err, result) {
        if (!err) {
            order_doc._rev = result.rev;
902
            update_main_screen();
Damien Moulard committed
903 904 905 906 907 908 909 910 911 912 913 914
            switch_screen();
        } else {
            if (err.status == 409) {
                alert("Une commande porte déjà ce nom !");
            }
            console.log(err);
        }
    });
}

/**
 * Update order data of an existing order in couchdb
Damien Moulard committed
915
 *
916
 * @returns Promise resolved after update is complete
Damien Moulard committed
917
 */
918
function update_cdb_order() {
Damien Moulard committed
919 920 921 922 923 924 925 926 927
    order_doc.products = products;
    order_doc.selected_suppliers = selected_suppliers;

    // Save that current user last updated the order
    order_doc.last_update = {
        timestamp: Date.now(),
        fingerprint: fingerprint
    };

928 929 930 931 932 933 934 935 936 937 938 939 940
    return new Promise((resolve) => {
        dbc.put(order_doc, function callback(err, result) {
            if (!err && result !== undefined) {
                order_doc._rev = result.rev;

                resolve();
            } else {
                alert("Erreur lors de la sauvegarde de la commande... Si l'erreur persiste contactez un administrateur svp.");
                console.log(err);

                resolve();
            }
        });
Damien Moulard committed
941 942 943
    });
}

944 945
/**
 * Delete an order in couchdb.
Damien Moulard committed
946
 *
947 948 949 950 951 952 953 954 955 956 957 958 959
 * @returns Promise resolved after delete is complete
 */
function delete_cdb_order() {
    order_doc._deleted = true;

    return new Promise((resolve, reject) => {
        dbc.put(order_doc, function callback(err, result) {
            if (!err && result !== undefined) {
                resolve();
            } else {
                alert("Erreur lors de la suppression de la commande... Si l'erreur persiste contactez un administrateur svp.");
                console.log(err);

François C. committed
960
                reject(new Error("Error while deleting order"));
961 962 963 964 965
            }
        });
    });
}

966 967 968 969 970 971 972 973
/**
 * Create the Product Orders in Odoo
 */
function create_orders() {
    let orders_data = {
        "suppliers_data": {}
    };

974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
    // Get planned delivery date for each supplier before hiding the modal
    for (let supplier of selected_suppliers) {
        // Get planned date from modal
        let supplier_date_planned = $(`#date_planned_supplier_${supplier.id}`).val();
        let formatted_date = null;

        if (supplier_date_planned !== '') {
            if (date_format === "dd/mm/yy") {
                // Change format [dd/mm/yy] to ISO [yy-mm-dd]
                formatted_date = supplier_date_planned
                    .split('/')
                    .reverse()
                    .join('-') + ' 00:00:00';
            } else {
                formatted_date = supplier_date_planned + ' 00:00:00';
            }
        } else {
            // Default date : tomorrow
            let date_object = new Date();
993

994 995 996
            date_object.setDate(date_object.getDate() + 1);

            // Get ISO format bare string
997 998
            formatted_date = date_object.toISOString().replace('T', ' ')
                .split('.')[0];
999 1000 1001 1002 1003 1004
        }

        // Create an entry for this supplier
        orders_data.suppliers_data[supplier.id] = {
            date_planned: formatted_date,
            lines: []
1005
        };
1006 1007 1008 1009
    }

    openModal();

1010 1011 1012 1013
    // Prepare data: get products where a qty is set
    for (let p of products) {
        for (let p_supplierinfo of p.suppliersinfo) {
            // If a qty is set for a supplier for a product
1014
            if ('qty' in p_supplierinfo && p_supplierinfo.qty != 0) {
1015
                const supplier_id = p_supplierinfo.supplier_id;
1016
                const product_code = p_supplierinfo.product_code;
1017

1018
                orders_data.suppliers_data[supplier_id].lines.push({
1019 1020 1021 1022 1023 1024 1025 1026
                    'package_qty': p_supplierinfo.package_qty,
                    'product_id': p.id,
                    'name': p.name,
                    'product_qty_package': p_supplierinfo.qty,
                    'product_qty': p_supplierinfo.qty * p_supplierinfo.package_qty,
                    'product_uom': p.uom_id[0],
                    'price_unit': p_supplierinfo.price,
                    'supplier_taxes_id': p.supplier_taxes_id,
1027 1028
                    'product_variant_ids': p.product_variant_ids,
                    'product_code': product_code
Damien Moulard committed
1029
                });
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
            }
        }
    }

    $.ajax({
        type: "POST",
        url: "/orders/create_orders",
        dataType: "json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(orders_data),
        success: (result) => {
1042 1043
            $('#created_orders_area').empty();

1044 1045 1046 1047
            // Display new orders
            for (let new_order of result.res.created) {
                const supplier_name = suppliers_list.find(s => s.id == new_order.supplier_id).display_name;

1048 1049 1050 1051 1052 1053
                const date_planned = new_order.date_planned
                    .split(' ')[0]
                    .split('-')
                    .reverse()
                    .join('/');

1054 1055 1056 1057
                product_orders.push({
                    'id': new_order.id_po,
                    'supplier_id': new_order.supplier_id,
                    'supplier_name': supplier_name
Damien Moulard committed
1058
                });
1059 1060

                let new_order_template = $("#templates #new_order_item_template");
Damien Moulard committed
1061

1062 1063
                new_order_template.find(".new_order_supplier_name").text(supplier_name);
                new_order_template.find(".new_order_po").text(`PO${new_order.id_po}`);
1064
                new_order_template.find(".new_order_date_planned").text(`Date de livraison prévue: ${date_planned}`);
1065 1066 1067 1068 1069 1070 1071 1072 1073
                new_order_template.find(".download_order_file_button").attr('id', `download_attachment_${new_order.id_po}`);

                $('#created_orders_area').append(new_order_template.html());
            }

            // Prepare buttons to download order attachment
            get_order_attachments();

            // Clear data
1074 1075
            delete_cdb_order().finally(() => {
                // Continue with workflow anyway
1076 1077 1078 1079 1080
                update_order_selection_screen().then(() => {
                    reset_data();
                    switch_screen('orders_created');
                    closeModal();
                });
1081
            });
1082 1083
        },
        error: function(data) {
Damien Moulard committed
1084 1085
            let msg = "erreur serveur lors de la création des product orders";

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
            err = {msg: msg, ctx: 'save_supplier_product_association', data: orders_data};
            if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                err.msg += ' : ' + data.responseJSON.error;
            }
            report_JS_error(err, 'orders');

            closeModal();
            alert('Erreur lors de la création des commandes. Veuillez ré-essayer plus tard.');
        }
    });
Damien Moulard committed
1096 1097

    return 0;
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
}

/**
 * Get the PO attachment id.
 * Display download button when fetch is succesful.
 * The file might not be created soon enough, so try again after 10s if error server
 */
function get_order_attachments() {
    if (product_orders.length > 0) {
        let po_ids = product_orders.map(po => po.id);

        $.ajax({
            type: 'GET',
            url: "/orders/get_orders_attachment",
            data: {
                'po_ids': po_ids
            },
            dataType:"json",
            traditional: true,
            contentType: "application/json; charset=utf-8",
            success: function(data) {
                for (let res_po of data.res) {
Damien Moulard committed
1120
                    $(`#download_attachment_${res_po.id_po}`).attr('href', `${odoo_server}/web/content/${res_po.id_attachment}?download=true`);
1121 1122
                }

Damien Moulard committed
1123 1124
                $('#created_orders_area .download_order_file_loading').hide();
                $('#created_orders_area .download_order_file_button').show();
1125
            },
1126
            error: function() {
1127 1128 1129 1130 1131 1132 1133
                $.notify(
                    "Échec de la récupération du lien de téléchargement des fichiers. Nouvelle tentative dans 10s.",
                    {
                        globalPosition:"top right",
                        className: "error"
                    }
                );
Damien Moulard committed
1134

1135 1136 1137 1138 1139 1140
                setTimeout(get_order_attachments, 10000);
            }
        });
    }
}

Damien Moulard committed
1141

1142 1143
/* - DISPLAY */

1144 1145 1146 1147 1148
function goto_main_screen(doc) {
    order_doc = doc;
    products = order_doc.products;
    selected_suppliers = order_doc.selected_suppliers;

1149 1150 1151 1152 1153
    check_products_data()
        .then(() => {
            update_cdb_order();
            update_main_screen();
            switch_screen();
1154
        });
1155 1156 1157 1158 1159 1160 1161 1162
}

function back() {
    reset_data();
    update_order_selection_screen();
    switch_screen('order_selection');
}

1163 1164 1165 1166
/**
 * Create a string to represent a supplier column in product data
 * @returns String
 */
Damien Moulard committed
1167 1168 1169 1170
function supplier_column_name(supplier) {
    const supplier_id = ('supplier_id' in supplier) ? supplier.supplier_id : supplier.id;


1171
    return `qty_supplier_${supplier_id}`;
1172 1173
}

Damien Moulard committed
1174 1175 1176 1177 1178
/**
 * Display the selected suppliers
 */
function display_suppliers() {
    let supplier_container = $("#suppliers_container");
Damien Moulard committed
1179

Damien Moulard committed
1180
    $("#suppliers_container").empty();
1181
    $(".remove_supplier_icon").off();
Damien Moulard committed
1182

Damien Moulard committed
1183
    for (let supplier of selected_suppliers) {
1184
        let template = $("#templates #supplier_pill_template");
Damien Moulard committed
1185

1186
        template.find(".pill_supplier_name").text(supplier.display_name);
1187
        template.find(".supplier_pill").attr('id', `pill_supplier_${supplier.id}`);
Damien Moulard committed
1188
        template.find(".remove_supplier_icon").attr('id', `remove_supplier_${supplier.id}`);
Damien Moulard committed
1189 1190 1191 1192

        supplier_container.append(template.html());
    }

Damien Moulard committed
1193 1194 1195
    $(".remove_supplier_icon").on("click", function() {
        const el_id = $(this).attr('id')
            .split('_');
1196
        const supplier_id = el_id[el_id.length-1];
Damien Moulard committed
1197
        const clicked_supplier = selected_suppliers.find(s => s.id == supplier_id);
1198 1199

        let modal_remove_supplier = $('#templates #modal_remove_supplier');
1200

Damien Moulard committed
1201
        modal_remove_supplier.find(".supplier_name").text(clicked_supplier.display_name);
1202 1203 1204 1205

        openModal(
            modal_remove_supplier.html(),
            () => {
1206 1207 1208
                if (is_time_to('validate_remove_supplier')) {
                    remove_supplier(supplier_id);
                }
1209
            },
Damien Moulard committed
1210
            'Valider'
1211
        );
Damien Moulard committed
1212
    });
Damien Moulard committed
1213 1214
}

1215 1216 1217 1218
function _compute_product_data(product) {
    let item = {};

    /* Supplier related data */
Damien Moulard committed
1219 1220
    let purchase_qty = 0; // Calculate product's total purchase qty
    let p_package_qties = []; // Look for differences in package qties
1221 1222 1223 1224

    for (let p_supplierinfo of product.suppliersinfo) {
        // Preset qty for input if product related to supplier: existing qty or null (null -> qty to be set, display an empty input)
        let supplier_qty = ("qty" in p_supplierinfo) ? p_supplierinfo.qty : null;
Damien Moulard committed
1225

1226 1227
        item[supplier_column_name(p_supplierinfo)] = supplier_qty;

Damien Moulard committed
1228
        // Update product's total qty to buy if qty set for this supplier
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
        if (supplier_qty !== null) {
            purchase_qty += +parseFloat(supplier_qty * p_supplierinfo.package_qty).toFixed(2);
        }

        // Store temporarily product package qties
        p_package_qties.push(p_supplierinfo.package_qty);
    }

    item.purchase_qty = purchase_qty;

    // If product not related to supplier, set qty for this supplier to false (false -> don't display any input)
    for (supplier of selected_suppliers) {
        if (!is_product_related_to_supplier(product, supplier)) {
            item[supplier_column_name(supplier)] = false;
        }
    }

Damien Moulard committed
1246
    if (p_package_qties.length == 0 || !p_package_qties.every((val, i, arr) => val === arr[0])) {
1247 1248 1249
        // Don't display package qty if no supplierinf or if not all package qties are equals,
        item.package_qty = 'X';
    } else {
1250 1251
        // If all package qties are equals, display it
        item.package_qty = p_package_qties[0];
Damien Moulard committed
1252
    }
1253 1254

    /* Coverage related data */
1255 1256 1257
    const coverage_days = (order_doc.coverage_days !== null) ? order_doc.coverage_days : 0;
    let qty_not_covered = 0;
    let days_covered = 0;
1258

1259 1260 1261 1262
    if (product.daily_conso !== 0) {
        qty_not_covered = product.daily_conso * coverage_days - product.qty_available - product.incoming_qty - purchase_qty;
        qty_not_covered = -Math.ceil(qty_not_covered); // round up: display values that are not fully covered
        qty_not_covered = (qty_not_covered > 0) ? 0 : qty_not_covered; // only display qty not covered (neg value)
1263

1264 1265
        days_covered = (product.qty_available + product.incoming_qty + purchase_qty) / product.daily_conso;
        days_covered = Math.floor(days_covered);
1266
    }
François committed
1267

1268
    item.qty_not_covered = qty_not_covered;
François committed
1269
    item.days_covered = days_covered;
1270

Damien Moulard committed
1271
    return item;
1272 1273
}

1274
/**
1275
 * @param {array} product_ids if set, return formatted data for these products only
1276 1277
 * @returns Array of formatted data for datatable data setup
 */
1278
function prepare_datatable_data(product_ids = []) {
1279
    let data = [];
Damien Moulard committed
1280
    let products_to_format = [];
1281 1282 1283 1284 1285 1286

    if (product_ids.length > 0) {
        products_to_format = products.filter(p => product_ids.includes(p.id));
    } else {
        products_to_format = products;
    }
1287

1288
    for (product of products_to_format) {
1289
        const item = {
1290
            id: product.id,
1291 1292
            name: product.name,
            default_code: product.default_code,
Damien Moulard committed
1293
            incoming_qty: +parseFloat(product.incoming_qty).toFixed(3), // '+' removes unecessary zeroes at the end
1294
            qty_available: +parseFloat(product.qty_available).toFixed(3),
1295
            daily_conso: product.daily_conso,
Damien Moulard committed
1296
            purchase_ok: product.purchase_ok,
1297
            uom: product.uom_id[1],
Damien Moulard committed
1298
            stats: `Ecart type: ${product.sigma} / Jours sans vente: ${Math.round((product.vpc) * 100)}%`
Damien Moulard committed
1299
        };
1300

1301
        const computed_data = _compute_product_data(product);
1302

1303
        const full_item = { ...item, ...computed_data };
1304

1305
        data.push(full_item);
1306 1307 1308 1309 1310 1311 1312 1313 1314
    }

    return data;
}

/**
 * @returns Array of formatted data for datatable columns setup
 */
function prepare_datatable_columns() {
1315
    let columns = [
1316 1317
        {
            data: "id",
Damien Moulard committed
1318 1319 1320 1321
            title: `<div id="table_header_select_all" class="txtcenter">
                        <span class="select_all_text">Sélectionner</span>
                        <label for="select_all_products_cb">- Tout</label>
                        <input type="checkbox" class="select_product_cb" id="select_all_products_cb" name="select_all_products_cb" value="all">
1322
                    </div>`,
Damien Moulard committed
1323
            className: "dt-body-center",
1324 1325 1326 1327
            orderable: false,
            render: function (data) {
                return `<input type="checkbox" class="select_product_cb" id="select_product_${data}" value="${data}">`;
            },
Damien Moulard committed
1328
            width: "4%"
1329 1330 1331
        },
        {
            data: "default_code",
Damien Moulard committed
1332
            title: "Ref",
Damien Moulard committed
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346
            width: "8%",
            render: function (data, type, full) {
                if (data === false) {
                    return "";
                } else if (data.includes("[input]")) {
                    let val = data.replace("[input]", "");


                    return `<div class="custom_cell_content">
                                <input type="text" class="product_ref_input" id="${full.id}_ref_input" value="${val}">
                            </div>`;
                } else {
                    return data;
                }
1347
            }
1348
        },
1349 1350
        {
            data: "name",
Damien Moulard committed
1351
            title: "Produit"
1352 1353 1354 1355
        },
        {
            data: "qty_available",
            title: "Stock",
1356
            className: "dt-body-center",
1357
            width: "4%"
1358 1359 1360 1361
        },
        {
            data: "incoming_qty",
            title: "Quantité entrante",
1362
            className: "dt-body-center",
1363
            width: "4%"
1364 1365 1366 1367
        },
        {
            data: "daily_conso",
            title: "Conso moy /jour",
1368 1369 1370
            render: function (data, type, full) {
                return '<div class="help" title="' + full.stats+ '">' + data + '</div>';
            },
1371 1372
            className: "dt-body-center",
            width: "6%"
Damien Moulard committed
1373
        }
1374 1375
    ];

1376
    for (const supplier of selected_suppliers) {
1377 1378 1379
        columns.push({
            data: supplier_column_name(supplier),
            title: supplier.display_name,
1380
            width: "10%",
1381 1382 1383 1384
            className: `dt-body-center supplier_input_cell`,
            render: (data, type, full) => {
                const base_id = `product_${full.id}_supplier_${supplier.id}`;

1385
                if (data === false) {
1386
                    return `<div id="${base_id}_cell_content" class="custom_cell_content">X</div>`;
1387
                } else {
Damien Moulard committed
1388
                    let content = `<div id="${base_id}_cell_content" class="custom_cell_content">
1389
                                        <input type="number" class="product_qty_input" id="${base_id}_qty_input" min="-1" value=${data}>`;
1390 1391 1392

                    if (full.package_qty === 'X') {
                        let product_data = products.find(p => p.id == full.id);
Damien Moulard committed
1393

1394 1395
                        if (product_data !== undefined) {
                            let supplierinfo = product_data.suppliersinfo.find(psi => psi.supplier_id == supplier.id);
Damien Moulard committed
1396

1397 1398 1399 1400
                            content += `<span class="supplier_package_qty">Colisage : ${supplierinfo.package_qty}</span>`;
                        }
                    }

Damien Moulard committed
1401 1402
                    content += `</div>`;

1403
                    return content;
1404 1405
                }
            }
Damien Moulard committed
1406
        });
1407
    }
1408

1409 1410 1411 1412 1413 1414 1415
    columns.push({
        data: "package_qty",
        title: "Colisage",
        className: "dt-body-center",
        width: "4%"
    });

1416 1417 1418
    columns.push({
        data: "uom",
        title: "UDM",
1419 1420 1421 1422 1423
        className: "dt-body-center",
        width: "4%"
    });

    columns.push({
1424
        data: "purchase_qty",
1425 1426
        title: "Qté Achat",
        className: "dt-body-center",
1427
        width: "4%"
Damien Moulard committed
1428
    });
1429

1430
    columns.push({
1431 1432 1433 1434 1435 1436 1437 1438 1439
        data: "qty_not_covered",
        title: "Besoin non couvert (qté)",
        className: "dt-body-center",
        width: "4%"
    });

    columns.push({
        data: "days_covered",
        title: "Jours de couverture",
1440 1441 1442 1443
        className: "dt-body-center",
        width: "4%"
    });

1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
    columns.push({
        data: "purchase_ok",
        title: `NPA`,
        className: "dt-body-center",
        orderable: false,
        render: function (data) {
            return `<input type="checkbox" class="product_npa_cb" value="purchase_ok" ${data ? '' : 'checked'}>`;
        },
        width: "4%"
    });
1454

1455
    return columns;
1456 1457
}

1458 1459 1460
/**
 * Display the Datatable containing the products
 */
1461
function display_products(params) {
Damien Moulard committed
1462 1463
    if (products.length == 0) {
        $('.main').hide();
1464
        $('#main_content_footer').hide();
1465
        $('#do_inventory').hide();
Damien Moulard committed
1466

Damien Moulard committed
1467 1468 1469
        return -1;
    }

1470
    // If datatable already exists, empty & clear events
1471
    if (products_table) {
Damien Moulard committed
1472
        $(products_table.table().header()).off();
1473 1474
        $('#products_table').off();

1475 1476
        products_table.clear().destroy();
        $('#products_table').empty();
1477 1478
    }

1479 1480
    const data = prepare_datatable_data();
    const columns = prepare_datatable_columns();
1481
    let sort_order_dir = "asc";
Damien Moulard committed
1482

1483 1484 1485
    if (params != undefined && typeof params.sort_order_dir != "undefined") {
        sort_order_dir = params.sort_order_dir;
    }
1486
    products_table = $('#products_table').DataTable({
1487 1488
        data: data,
        columns: columns,
1489 1490
        order: [
            [
1491 1492
                6, // Order by default by first supplier
                sort_order_dir
1493 1494
            ]
        ],
1495
        orderClasses: false,
Damien Moulard committed
1496
        aLengthMenu: [
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
            [
                25,
                50,
                100,
                200,
                -1
            ],
            [
                25,
                50,
                100,
                200,
                "Tout"
            ]
Damien Moulard committed
1511 1512
        ],
        iDisplayLength: -1,
1513
        scrollX: true,
1514
        language: {url : '/static/js/datatables/french.json'},
Damien Moulard committed
1515
        createdRow: function(row) {
Damien Moulard committed
1516 1517
            for (var i = 0; i < row.cells.length; i++) {
                const cell_node = row.cells[i];
1518
                const cell = $(cell_node);
1519

Damien Moulard committed
1520 1521 1522 1523 1524
                if (cell.hasClass("supplier_input_cell") && cell.text() === "X") {
                    cell.addClass('product_not_from_supplier');
                } else if (i === 1) {
                    // Column at index 1 is product reference
                    cell.addClass('product_ref_cell');
1525 1526
                }
            }
Damien Moulard committed
1527
        }
1528 1529 1530
    });

    $('.main').show();
1531
    $('#main_content_footer').show();
1532
    $('#do_inventory').show();
1533

1534 1535 1536
    // Color line on input focus
    $('#products_table').on('focus', 'tbody td .product_qty_input', function () {
        const row = $(this).closest('tr');
Damien Moulard committed
1537

1538 1539 1540
        row.addClass('focused_line');
    });

1541 1542
    // Manage data on inputs blur
    $('#products_table').on('blur', 'tbody td .product_qty_input', function () {
1543 1544
        // Remove line coloring on input blur
        const row = $(this).closest('tr');
Damien Moulard committed
1545

1546 1547
        row.removeClass('focused_line');

1548
        let val = ($(this).val() == '') ? 0 : $(this).val();
Damien Moulard committed
1549

1550 1551 1552 1553
        const id_split = $(this).attr('id')
            .split('_');
        const prod_id = id_split[1];
        const supplier_id = id_split[3];
Damien Moulard committed
1554

1555
        if (val == -1) {
1556
            let modal_end_supplier_product_association = $('#templates #modal_end_supplier_product_association');
Damien Moulard committed
1557

1558
            const product = products.find(p => p.id == prod_id);
Damien Moulard committed
1559

1560
            modal_end_supplier_product_association.find(".product_name").text(product.name);
1561
            const supplier = selected_suppliers.find(s => s.id == supplier_id);
Damien Moulard committed
1562

1563
            modal_end_supplier_product_association.find(".supplier_name").text(supplier.display_name);
Damien Moulard committed
1564

1565
            openModal(
1566
                modal_end_supplier_product_association.html(),
1567
                () => {
1568 1569
                    if (is_time_to('validate_end_supplier_product_association')) {
                        end_supplier_product_association(product, supplier);
1570 1571 1572 1573 1574 1575 1576 1577
                    }
                },
                'Valider',
                false,
                true,
                () => {
                    // Reset value in input on cancel
                    const psi = product.suppliersinfo.find(psi_item => psi_item.supplier_id == supplier_id);
Damien Moulard committed
1578

1579 1580 1581
                    $(this).val(psi.qty);
                }
            );
1582
        } else {
1583
            val = parseFloat(val);
Damien Moulard committed
1584

1585
            // If value is a number
Damien Moulard committed
1586
            if (!isNaN(val)) {
1587 1588
                // Save value
                save_product_supplier_qty(prod_id, supplier_id, val);
Damien Moulard committed
1589

1590 1591 1592
                // Update row
                const product = products.find(p => p.id == prod_id);
                const new_row_data = prepare_datatable_data([product.id])[0];
Damien Moulard committed
1593

1594 1595
                products_table.row($(this).closest('tr')).data(new_row_data)
                    .draw();
Damien Moulard committed
1596

1597 1598 1599 1600 1601
                update_cdb_order();
                display_total_values();
            } else {
                $(this).val('');
            }
1602
        }
1603
    })
Damien Moulard committed
1604
        .on('change', 'tbody td .product_qty_input', function () {
1605
        // Since data change is saved on blur, set focus on change in case of arrows pressed
Damien Moulard committed
1606 1607 1608
            $(this).focus();
        })
        .on('keypress', 'tbody td .product_qty_input', function(e) {
1609
            // Validate on Enter pressed
1610
            if (e.which == 13) {
Damien Moulard committed
1611 1612
                $(this).blur();
            }
1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639
        })
        .on('keydown', 'tbody td .product_qty_input', function(e) {
            if (e.which == 38) {
                e.preventDefault();

                // On arrow up pressed, focus next row input
                let next_input = $(this).closest("tr").prev().find(".product_qty_input");
                next_input.focus();

                // Scroll to a position where the target input is not hidden by the sticky suppliers container
                const suppliers_container_top_offset = 
                    $("#suppliers_container").offset().top
                    - $(window).scrollTop()
                    + $("#suppliers_container").outerHeight();
                    const next_input_top_offset = next_input.offset().top - $(window).scrollTop();

                if (next_input_top_offset < suppliers_container_top_offset) {
                    window.scrollTo({
                        top: $(window).scrollTop() - $("#suppliers_container").outerHeight()
                    });
                }
            } else if (e.which == 40) {
                e.preventDefault();

                // On arrow down pressed, focus previous row input
                $(this).closest("tr").next().find(".product_qty_input").focus();
            } 
Damien Moulard committed
1640
        });
Damien Moulard committed
1641

1642 1643
    // Associate product to supplier on click on 'X' in the table
    $('#products_table').on('click', 'tbody .product_not_from_supplier', function () {
Damien Moulard committed
1644 1645 1646 1647
        // Get supplier & product id
        const el_id = $(this).children()
            .first()
            .attr('id')
1648 1649 1650 1651
            .split('_');
        const product_id = el_id[1];
        const supplier_id = el_id[3];

Damien Moulard committed
1652 1653
        const product = products.find(p => p.id == product_id);
        const supplier = selected_suppliers.find(s => s.id == supplier_id);
1654 1655

        let modal_attach_product_to_supplier = $('#templates #modal_attach_product_to_supplier');
Damien Moulard committed
1656

1657 1658 1659 1660 1661 1662
        modal_attach_product_to_supplier.find(".product_name").text(product.name);
        modal_attach_product_to_supplier.find(".supplier_name").text(supplier.display_name);

        openModal(
            modal_attach_product_to_supplier.html(),
            () => {
1663 1664 1665
                if (is_time_to('validate_save_supplier_product_association')) {
                    save_supplier_product_association(product, supplier, this);
                }
1666 1667 1668 1669 1670
            },
            'Valider',
            false
        );

Damien Moulard committed
1671
        // Find existing price in another supplierinfo
1672
        let default_price = null;
Damien Moulard committed
1673 1674
        let default_package_qty = 1; // Default package qty is 1

1675 1676 1677
        for (let psi of product.suppliersinfo) {
            if ('price' in psi && psi.price !== null) {
                default_price = psi.price;
1678 1679 1680 1681
            }

            if ('package_qty' in psi && psi.package_qty !== null) {
                default_package_qty = psi.package_qty;
1682 1683 1684 1685
            }
        }

        // Set default value for price & package qty for new supplierinfo
Damien Moulard committed
1686 1687
        $(".new_product_supplier_package_pty").val(default_package_qty);
        $(".new_product_supplier_price").val(default_price); // Default price is existing price for other supplier, or none if no other
1688
        new_product_supplier_association = {
1689
            package_qty: default_package_qty,
1690
            price: default_price
Damien Moulard committed
1691 1692
        };

1693 1694 1695 1696 1697 1698 1699
        $('.new_product_supplier_price').on('input', function () {
            new_product_supplier_association.price = $(this).val();
        });
        $('.new_product_supplier_package_pty').on('input', function () {
            new_product_supplier_association.package_qty = $(this).val();
        });
    });
Damien Moulard committed
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734

    // Display input on click on product ref cell
    $('#products_table').on('click', 'tbody .product_ref_cell', function () {
        if ($(this).find('input').length === 0) {
            const row = $(this).closest('tr');
            const p_id = products_table.row(row).data().id;
            const p_index = products.findIndex(p => p.id === p_id);

            const existing_ref = products[p_index].default_code === false ? '' : products[p_index].default_code;

            products[p_index].default_code = "[input]" + existing_ref;

            const new_row_data = prepare_datatable_data([p_id])[0];

            products_table.row(row).data(new_row_data)
                .draw();

            let ref_input = $(`#${p_id}_ref_input`);

            ref_input.focus();
            ref_input.select();

            $('#products_table')
                .on('blur', 'tbody .product_ref_input', function () {
                    update_product_ref(this, p_id, p_index);
                })
                .on('keypress', 'tbody .product_ref_input', function(e) {
                // Validate on Enter pressed
                    if (e.which == 13) {
                        update_product_ref(this, p_id, p_index);
                    }
                });
        }
    });

1735
    // Select row(s) on checkbox change
1736
    $(products_table.table().header()).on('click', 'th #select_all_products_cb', function () {
1737
        if (this.checked) {
Damien Moulard committed
1738
            selected_rows = [];
1739 1740
            products_table.rows().every(function() {
                const node = $(this.node());
Damien Moulard committed
1741

1742
                node.addClass('selected');
Damien Moulard committed
1743 1744
                node.find(".select_product_cb").first()
                    .prop("checked", true);
1745 1746

                // Save selected rows in case the table is updated
Damien Moulard committed
1747 1748 1749
                selected_rows.push(this.data().id);

                return 0;
1750 1751
            });
        } else {
Damien Moulard committed
1752
            unselect_all_rows();
1753 1754 1755
        }
    });
    $('#products_table').on('click', 'tbody td .select_product_cb', function () {
Damien Moulard committed
1756 1757
        $(this).closest('tr')
            .toggleClass('selected');
1758 1759

        // Save / unsave selected row
Damien Moulard committed
1760
        const p_id = products_table.row($(this).closest('tr')).data().id;
Damien Moulard committed
1761

1762
        if (this.checked) {
Damien Moulard committed
1763
            selected_rows.push(p_id);
1764
        } else {
Damien Moulard committed
1765 1766 1767
            const i = selected_rows.findIndex(id => id == p_id);

            selected_rows.splice(i, 1);
1768 1769 1770
        }
    });

Damien Moulard committed
1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786
    // Set product is NPA (Ne Pas Acheter)
    $('#products_table').on('click', 'tbody td .product_npa_cb', function () {
        // Save / unsave selected row
        const p_id = products_table.row($(this).closest('tr')).data().id;
        const npa = this.checked;

        const product = products.find(p => p.id == p_id);

        let modal_product_npa = $('#templates #modal_product_npa');

        modal_product_npa.find(".product_name").text(product.name);
        modal_product_npa.find(".product_npa").text(npa ? 'Ne Pas Acheter' : 'Peut Être Acheté');

        openModal(
            modal_product_npa.html(),
            () => {
1787 1788 1789
                if (is_time_to('validate_set_product_npa')) {
                    set_product_npa(p_id, npa);
                }
Damien Moulard committed
1790 1791 1792 1793 1794 1795 1796 1797 1798 1799
            },
            'Valider',
            false,
            true,
            () => {
                this.checked = !this.checked;
            }
        );
    });

Damien Moulard committed
1800
    return 0;
1801 1802
}

1803 1804 1805 1806
/**
 * Unselect all rows from datatable.
 */
function unselect_all_rows() {
1807
    $("#select_all_products_cb").prop("checked", false);
Damien Moulard committed
1808

1809 1810
    products_table.rows().every(function() {
        const node = $(this.node());
Damien Moulard committed
1811

1812
        node.removeClass('selected');
Damien Moulard committed
1813 1814 1815 1816
        node.find(".select_product_cb").first()
            .prop("checked", false);

        return 0;
1817
    });
Damien Moulard committed
1818 1819

    selected_rows = [];
1820 1821
}

1822 1823 1824 1825 1826 1827 1828
/**
 * Display the total values for each supplier & the global total value
 */
function display_total_values() {
    _compute_total_values_by_supplier();

    let order_total_value = 0;
1829

1830
    for (let supplier of selected_suppliers) {
1831 1832
        $(`#pill_supplier_${supplier.id}`).find('.supplier_total_value')
            .text(parseFloat(supplier.total_value).toFixed(2));
1833
        order_total_value += supplier.total_value;
1834 1835 1836

        $(`#pill_supplier_${supplier.id}`).find('.supplier_total_packages')
            .text(+parseFloat(supplier.total_packages).toFixed(2));
1837
    }
1838 1839 1840

    order_total_value = parseFloat(order_total_value).toFixed(2);
    $('#order_total_value').text(order_total_value);
1841 1842
}

Damien Moulard committed
1843
/**
1844
 * Update DOM display on main screen
Damien Moulard committed
1845
 */
1846
function update_main_screen(params) {
1847
    // Remove listener before recreating them
1848 1849
    $('#products_table').off('focus', 'tbody td .product_qty_input');
    $('#products_table').off('blur', 'tbody td .product_qty_input');
1850
    $('#products_table').off('change', 'tbody td .product_qty_input');
1851
    $('#products_table').off('click', 'tbody .product_not_from_supplier');
Damien Moulard committed
1852
    $('#products_table').off('click', 'tbody .product_ref_cell');
1853 1854
    $('#products_table').off('click', 'thead th #select_all_products_cb');
    $('#products_table').off('click', 'tbody td .select_product_cb');
1855
    $(".remove_supplier_icon").off();
1856

1857
    $(".order_name_container").text(order_doc._id);
Damien Moulard committed
1858
    display_suppliers();
1859
    display_products(params);
1860
    display_total_values();
1861 1862

    // Re-select previously selected rows
Damien Moulard committed
1863
    if (selected_rows.length > 0) {
1864 1865 1866
        products_table.rows().every(function() {
            if (selected_rows.includes(this.data().id)) {
                const node = $(this.node());
Damien Moulard committed
1867

1868
                node.addClass('selected');
Damien Moulard committed
1869 1870
                node.find(".select_product_cb").first()
                    .prop("checked", true);
1871
            }
Damien Moulard committed
1872 1873

            return 0;
1874 1875
        });
    }
1876
    $("#select_all_products_cb").prop("checked", false);
1877

1878 1879 1880 1881 1882
    if (order_doc.coverage_days !== null) {
        $("#coverage_days_input").val(order_doc.coverage_days);
    } else {
        $("#coverage_days_input").val('');
    }
1883 1884 1885 1886 1887 1888

    if (order_doc.stats_date_period !== undefined && order_doc.stats_date_period !== null) {
        $("#stats_date_period_select").val(order_doc.stats_date_period);
    } else {
        $("#stats_date_period_select").val('');
    }
1889 1890
}

1891 1892 1893 1894
/**
 * Update DOM display on the order selection screen
 */
function update_order_selection_screen() {
1895 1896 1897 1898
    return new Promise((resolve) => {
        dbc.allDocs({
            include_docs: true
        })
Damien Moulard committed
1899
            .then(function (result) {
1900
            // Remove listener before recreating them
Damien Moulard committed
1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919
                $(".order_pill").off();

                let existing_orders_container = $("#existing_orders");

                existing_orders_container.empty();
                $('#new_order_name').val('');

                if (result.rows.length === 0) {
                    existing_orders_container.append(`<i>Aucune commande en cours...</i>`);
                } else {
                    for (let row of result.rows) {
                        let template = $("#templates #order_pill_template");

                        template.find(".pill_order_name").text(row.id);

                        existing_orders_container.append(template.html());
                    }

                    $(".order_pill").on("click", order_pill_on_click);
1920 1921 1922 1923 1924
                    $(".remove_order_icon").on("click", function(e) {
                        e.preventDefault();
                        e.stopImmediatePropagation();
                        order_name_container = $(this).prev()[0];
                        let order_id = $(order_name_container).text();
Damien Moulard committed
1925

1926
                        let modal_remove_order = $('#templates #modal_remove_order');
Damien Moulard committed
1927

1928
                        modal_remove_order.find(".remove_order_name").text(order_id);
Damien Moulard committed
1929

1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949
                        openModal(
                            modal_remove_order.html(),
                            () => {
                                if (is_time_to('validate_remove_order')) {
                                    dbc.get(order_id).then((doc) => {
                                        order_doc = doc;
                                        delete_cdb_order().then(() => {
                                            update_order_selection_screen().then(() => {
                                                reset_data();
                                                setTimeout(function() {
                                                    $.notify(
                                                        "Commande supprimée !",
                                                        {
                                                            globalPosition:"top left",
                                                            className: "success"
                                                        }
                                                    );
                                                }, 500);
                                            });
                                        })
Damien Moulard committed
1950 1951 1952
                                            .catch(() => {
                                                console.log("error deleting order");
                                            });
1953 1954 1955 1956 1957 1958
                                    });
                                }
                            },
                            'Valider'
                        );
                    });
1959
                }
Damien Moulard committed
1960

Damien Moulard committed
1961 1962 1963 1964 1965 1966
                resolve();
            })
            .catch(function (err) {
                alert('Erreur lors de la synchronisation des commandes. Vous pouvez créer une nouvelle commande.');
                console.log(err);
            });
1967
    });
1968
}
1969

1970
/**
1971 1972 1973
 * Switch between screens
 * @param {String} direction target screen : order_selection | main_screen | orders_created
 * @param {String} from source screen : order_selection | main_screen | orders_created
1974
 */
1975 1976 1977 1978
function switch_screen(direction = 'main_screen', from = 'main_screen') {
    if (direction === 'orders_created') {
        $('#main_content').hide();
        $('#orders_created').show();
1979
    } else {
1980 1981 1982 1983
        // Animated transition
        let oldBox = null;
        let newBox = null;
        let outerWidth = null;
Damien Moulard committed
1984

1985 1986 1987
        if (direction === 'main_screen') {
            oldBox = $("#select_order_content");
            newBox = $("#main_content");
Damien Moulard committed
1988

1989 1990 1991 1992 1993 1994 1995
            outerWidth = oldBox.outerWidth(true);
        } else {
            if (from === 'orders_created') {
                oldBox = $("#orders_created");
            } else {
                oldBox = $("#main_content");
            }
Damien Moulard committed
1996

1997
            newBox = $("#select_order_content");
Damien Moulard committed
1998

1999 2000
            outerWidth = - oldBox.outerWidth(true);
        }
Damien Moulard committed
2001

2002 2003 2004 2005 2006 2007 2008 2009 2010
        // Display the new box and place it on the right of the screen
        newBox.css({ "left": outerWidth + "px", "right": -outerWidth + "px", "display": "" });
        // Make the old content slide to the left
        oldBox.animate({ "left": -outerWidth + "px", "right": outerWidth + "px" }, 800, function() {
            // Hide old content after animation
            oldBox.css({ "left": "", "right": "", "display": "none" });
        });
        // Slide new box to regular place
        newBox.animate({ "left": "", "right": "" }, 800);
2011
    }
2012 2013 2014
}


2015 2016 2017 2018
/**
 * Init the PouchDB local database & sync
 */
function init_pouchdb_sync() {
2019 2020 2021 2022
    dbc = new PouchDB(couchdb_dbname);
    sync = PouchDB.sync(couchdb_dbname, couchdb_server, {
        live: true,
        retry: true,
2023 2024
        auto_compaction: true,
        revs_limit: 1
2025 2026 2027
    });

    sync.on('change', function (info) {
2028 2029
        if (info.direction === "pull") {
            for (const doc of info.change.docs) {
2030 2031
                if (order_doc._id === doc._id && (order_doc._rev !== doc._rev || doc._deleted === true)) {
                    // If current order was modified somewhere else
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042
                    $.notify(
                        "Un autre navigateur est en train de modifier cette commande !",
                        {
                            globalPosition:"top right",
                            className: "error"
                        }
                    );
                    back();
                    break;
                }
            }
2043 2044

            update_order_selection_screen();
2045
        }
2046
    }).on('error', function (err) {
2047 2048 2049
        if (err.status === 409) {
            alert("Une erreur de synchronisation s'est produite, la commande a sûrement été modifiée sur un autre navigateur. Vous allez être redirigé.e.");
            back();
2050
        }
2051 2052 2053
        console.log('erreur sync');
        console.log(err);
    });
2054 2055 2056 2057
}


$(document).ready(function() {
2058 2059 2060
    if (coop_is_connected()) {
        $('#new_order_form').show();
        $('#existing_orders_area').show();
2061

2062 2063
        fingerprint = new Fingerprint({canvas: true}).get();
        $.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
2064

2065
        openModal();
2066

2067 2068 2069
        init_pouchdb_sync();

        // Main screen
2070 2071 2072 2073
        if (metabase_url !== '') {
            $('#access_metabase').show();
        }

2074 2075 2076 2077
        $("#coverage_form").on("submit", function(e) {
            e.preventDefault();
            if (is_time_to('submit_coverage_form', 1000)) {
                let val = $("#coverage_days_input").val();
2078

2079
                val = parseInt(val);
2080

2081 2082 2083 2084 2085 2086 2087 2088 2089
                if (!isNaN(val)) {
                    order_doc.coverage_days = val;
                    compute_products_coverage_qties();
                    update_cdb_order();
                    update_main_screen();
                } else {
                    $("#coverage_days_input").val(order_doc.coverage_days);
                    alert(`Valeur non valide pour le nombre de jours de couverture !`);
                }
2090
            }
2091
        });
2092

Damien Moulard committed
2093
        $("#toggle_action_buttons").on("click", function() {
2094 2095 2096 2097 2098 2099 2100 2101 2102
            if ($('#actions_buttons_container').is(":visible")) {
                $('#actions_buttons_container').hide();
                $('.toggle_action_buttons_icon').empty()
                    .append('<i class="fas fa-chevron-down"></i>');
            } else {
                $('#actions_buttons_container').show();
                $('.toggle_action_buttons_icon').empty()
                    .append('<i class="fas fa-chevron-up"></i>');
            }
2103 2104 2105
        });

        // Close dropdown menu on click outside
Damien Moulard committed
2106
        $(document).click(function(event) {
2107
            let target = $(event.target);
2108

2109 2110 2111 2112 2113
            if (
                !target.closest('#actions_buttons_wrapper').length
                && $('#actions_buttons_container').is(":visible")
            ) {
                $('#actions_buttons_container').hide();
2114 2115
                $('.toggle_action_buttons_icon').empty()
                    .append('<i class="fas fa-chevron-down"></i>');
Damien Moulard committed
2116
            }
2117
        });
2118

2119 2120 2121 2122 2123 2124
        $("#supplier_form").on("submit", function(e) {
            e.preventDefault();
            if (is_time_to('add_product', 1000)) {
                add_supplier();
            }
        });
2125

2126 2127 2128 2129 2130 2131
        $("#product_form").on("submit", function(e) {
            e.preventDefault();
            if (is_time_to('add_product', 1000)) {
                add_product();
            }
        });
2132

2133 2134 2135 2136 2137 2138 2139 2140 2141
        $("#stats_date_period_select").on("change", function(e) {
            e.preventDefault();
            if (is_time_to('change_stats_date_period', 1000)) {
                openModal();

                order_doc.stats_date_period = $(this).val();

                check_products_data()
                    .then(() => {
2142
                        compute_products_coverage_qties();
2143
                        update_main_screen();
2144
                        update_cdb_order();
2145 2146 2147 2148 2149
                        closeModal();
                    });
            }
        });

2150 2151 2152 2153 2154
        $("#do_inventory").on("click", function() {
            if (is_time_to('generate_inventory', 1000)) {
                generate_inventory();
            }
        });
2155

2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168
        $("#refresh_order").on("click", function() {
            if (is_time_to('refresh_order', 1000)) {
                openModal();
                check_products_data()
                    .then(() => {
                        update_cdb_order();
                        update_main_screen();
                        $("#toggle_action_buttons").click();
                        closeModal();
                    });
            }
        });

Damien Moulard committed
2169
        $("#delete_order_button").on("click", function() {
2170 2171
            if (is_time_to('press_delete_order_button', 1000)) {
                let modal_remove_order = $('#templates #modal_remove_order');
Damien Moulard committed
2172

2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193
                modal_remove_order.find(".remove_order_name").text(order_doc._id);

                openModal(
                    modal_remove_order.html(),
                    () => {
                        if (is_time_to('validate_remove_order')) {
                            delete_cdb_order().then(() => {
                                update_order_selection_screen().then(() => {
                                    reset_data();
                                    switch_screen('order_selection');
                                    setTimeout(function() {
                                        $.notify(
                                            "Commande supprimée !",
                                            {
                                                globalPosition:"top left",
                                                className: "success"
                                            }
                                        );
                                    }, 500);
                                });
                            })
Damien Moulard committed
2194 2195 2196
                                .catch(() => {
                                    console.log("error deleting order");
                                });
2197 2198 2199 2200 2201
                        }
                    },
                    'Valider'
                );
            }
Damien Moulard committed
2202

2203 2204
        });

2205 2206 2207 2208 2209
        $('#back_to_order_selection_from_main').on('click', function() {
            if (is_time_to('back_to_order_selection_from_main', 1000)) {
                back();
            }
        });
2210

2211 2212 2213
        $('#create_orders').on('click', function() {
            if (is_time_to('create_orders', 1000)) {
                let modal_create_order = $('#templates #modal_create_order');
2214

2215
                modal_create_order.find('.suppliers_date_planned_area').empty();
2216

2217 2218
                for (let supplier of selected_suppliers) {
                    let supplier_date_planned_template = $('#templates #modal_create_order__supplier_date_planned');
2219

2220 2221
                    supplier_date_planned_template.find(".supplier_name").text(supplier.display_name);
                    supplier_date_planned_template.find(".modal_input_container").attr('id', `container_date_planned_supplier_${supplier.id}`);
2222

2223 2224
                    modal_create_order.find('.suppliers_date_planned_area').append(supplier_date_planned_template.html());
                }
2225 2226


2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
                openModal(
                    modal_create_order.html(),
                    () => {
                        if (is_time_to('validate_create_orders')) {
                            create_orders();
                        }
                    },
                    'Valider',
                    false
                );
2237

2238 2239
                // Add id to input once modal is displayed
                for (let supplier of selected_suppliers) {
2240 2241
                    $(`#modal #container_date_planned_supplier_${supplier.id}`).find(".supplier_date_planned")
                        .attr('id', `date_planned_supplier_${supplier.id}`);
2242
                }
2243

2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258
                $("#modal .supplier_date_planned")
                    .datepicker({
                        defaultDate: "+1d",
                        minDate: new Date()
                    })
                    .on('change', function() {
                        try {
                            // When date input changes, try to read date
                            $.datepicker.parseDate(date_format, $(this).val());
                        } catch {
                            alert('Date invalide');
                            $(this).val('');
                        }
                    });
            }
2259

2260 2261
            return 0;
        });
2262

2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289
        $.datepicker.regional['fr'] = {
            monthNames: [
                'Janvier',
                'Fevrier',
                'Mars',
                'Avril',
                'Mai',
                'Juin',
                'Juillet',
                'Aout',
                'Septembre',
                'Octobre',
                'Novembre',
                'Decembre'
            ],
            dayNamesMin: [
                'Di',
                'Lu',
                'Ma',
                'Me',
                'Je',
                'Ve',
                'Sa'
            ],
            dateFormat: date_format
        };
        $.datepicker.setDefaults($.datepicker.regional['fr']);
2290

2291 2292
        // Order selection screen
        update_order_selection_screen();
2293

2294 2295 2296 2297 2298 2299
        $("#new_order_form").on("submit", function(e) {
            e.preventDefault();
            if (is_time_to('submit_new_order_form', 1000)) {
                create_cdb_order();
            }
        });
2300

2301 2302 2303 2304 2305 2306
        // Orders created screen
        $('#back_to_order_selection_from_orders_created').on('click', function() {
            if (is_time_to('back_to_order_selection_from_orders_created', 1000)) {
                switch_screen('order_selection', 'orders_created');
            }
        });
2307

2308 2309 2310 2311 2312 2313 2314 2315 2316
        // Get suppliers
        $.ajax({
            type: 'GET',
            url: "/orders/get_suppliers",
            dataType:"json",
            traditional: true,
            contentType: "application/json; charset=utf-8",
            success: function(data) {
                suppliers_list = data.res;
2317

2318 2319 2320 2321
                // Set up autocomplete on supplier input
                $("#supplier_input").autocomplete({
                    source: suppliers_list.map(a => a.display_name)
                });
2322

Damien Moulard committed
2323

2324 2325 2326 2327 2328 2329 2330 2331 2332 2333
            },
            error: function(data) {
                err = {msg: "erreur serveur lors de la récupération des fournisseurs", ctx: 'get_suppliers'};
                if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                    err.msg += ' : ' + data.responseJSON.error;
                }
                report_JS_error(err, 'orders');

                closeModal();
                alert('Erreur lors de la récupération des fournisseurs, rechargez la page plus tard');
2334
            }
2335
        });
2336

2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350
        //Get products
        var accentMap = {
            "á": "a",
            "à": "a",
            "â": "a",
            "é": "e",
            "è": "e",
            "ê": "e",
            "ë": "e",
            "ç": "c",
            "ù": "u",
            "ü": "u",
            "ö": "o"
        };
2351

2352 2353
        var normalize = function(term) {
            var ret = "";
2354

2355 2356 2357
            for (var i = 0; i < term.length; i++) {
                ret += accentMap[ term.charAt(i) ] || term.charAt(i);
            }
Damien Moulard committed
2358

2359 2360
            return ret;
        };
Damien Moulard committed
2361

2362 2363 2364 2365 2366 2367 2368 2369
        $.ajax({
            type: 'GET',
            url: "/products/simple_list",
            dataType:"json",
            traditional: true,
            contentType: "application/json; charset=utf-8",
            success: function(data) {
                products_list = data.list;
2370

2371 2372 2373 2374
                // Set up autocomplete on product input
                $("#product_input").autocomplete({
                    source: function(request, response) {
                        var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
2375

2376 2377
                        response($.grep(products_list.map(a => a.display_name), function(value) {
                            value = value.label || value.value || value;
Damien Moulard committed
2378

2379 2380 2381 2382 2383
                            return matcher.test(value) || matcher.test(normalize(value));
                        }));
                    },
                    position: {collision: "flip" }
                });
Damien Moulard committed
2384

2385 2386 2387 2388 2389 2390 2391 2392
                closeModal();
            },
            error: function(data) {
                err = {msg: "erreur serveur lors de la récupération des articles", ctx: 'get_products'};
                if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                    err.msg += ' : ' + data.responseJSON.error;
                }
                report_JS_error(err, 'orders');
2393

2394 2395
                closeModal();
                alert('Erreur lors de la récupération des articles, rechargez la page plus tard');
2396
            }
2397 2398 2399 2400
        });
    } else {
        $('#not_connected_content').show();
    }
2401
});