reception_index.js 24.3 KB
Newer Older
1 2
var orders = [],
    order = {
3 4
        'id' : null
    },
5
    table_orders = null,
6 7 8
    callback_update = false,
    callback_report = false,
    selection_type = null,
9
    order_groups = {
10
        _id: 'grouped_orders',
11 12 13
        groups: []
    },
    dbc = null,
14 15
    sync = null,
    fingerprint = null;
16

17 18 19

/* UTILS */

20 21
/**
 * Difference between two dates
Damien Moulard committed
22 23
 * @param {Date} date1
 * @param {Date} date2
24 25
 * @returns difference object
 */
Damien Moulard committed
26 27
function dates_diff(date1, date2) {
    var diff = {};
28
    var tmp = date2 - date1;
Damien Moulard committed
29

30 31
    tmp = Math.floor(tmp/1000);
    diff.sec = tmp % 60;
Damien Moulard committed
32

33 34
    tmp = Math.floor((tmp-diff.sec)/60);
    diff.min = tmp % 60;
Damien Moulard committed
35

36 37
    tmp = Math.floor((tmp-diff.min)/60);
    diff.hours = tmp % 24;
Damien Moulard committed
38

39 40
    tmp = Math.floor((tmp-diff.hours)/24);
    diff.days = tmp;
Damien Moulard committed
41

42 43 44
    return diff;
}

45 46 47 48
/**
 * Wait for both ajax callbacks for reloading to avoid a js error
 *   -> reloading when ajax call not answered causes a popup to appear, which can be confusing
 */
49 50 51 52 53
function reload() {
    if (callback_update && callback_report)
        document.location.reload();
}

54 55
/**
 * Check for concurent access to same order before going to reception page.
Damien Moulard committed
56
 * @param {Int} id
57 58 59
 */
function check_before_goto(id) {
    const order_doc_id = 'order_' + id;
Damien Moulard committed
60

61 62
    dbc.get(order_doc_id).then((doc) => {
        if (doc.last_update.fingerprint !== null && doc.last_update.fingerprint !== fingerprint) {
Damien Moulard committed
63 64
            time_diff = dates_diff(new Date(doc.last_update.timestamp), new Date());
            diff_str = ``;
65 66

            if (time_diff.days !== 0) {
Damien Moulard committed
67
                diff_str += `${time_diff.days} jour(s), `;
68 69
            }
            if (time_diff.hours !== 0) {
Damien Moulard committed
70
                diff_str += `${time_diff.hours} heure(s), `;
71 72
            }
            if (time_diff.min !== 0) {
Damien Moulard committed
73
                diff_str += `${time_diff.min} min, `;
74
            }
Damien Moulard committed
75
            diff_str += `${time_diff.sec}s`;
76 77

            let modal_order_access = $('#templates #modal_order_access');
Damien Moulard committed
78

79 80 81 82 83 84 85 86 87 88 89 90 91
            modal_order_access.find(".order_last_update").text(diff_str);

            openModal(
                modal_order_access.html(),
                () => {
                    goto(id);
                },
                'Valider'
            );
        } else {
            goto(id);
        }
    })
Damien Moulard committed
92 93 94
        .catch((err) => {
            console.log(err);
        });
95 96
}

97 98 99 100
function goto(id) {
    document.location.href = "produits/" + id;
}

101
/**
102
 * Go to Products page for an existing group
103
 * @param {int} group_index index of group in groups array
104
 */
105
function group_goto(group_index) {
106 107
    let missing_orders = [];

108 109 110
    // Make sure a couchdb document exists for all group's orders
    for (let i in order_groups.groups[group_index]) {
        let order_data = null;
111
        let order_id = order_groups.groups[group_index][i];
112 113 114

        // Find order data
        for (let order of orders) {
115
            if (order.id == order_id) {
Damien Moulard committed
116
                order_data = order;
117 118 119
            }
        }

120 121 122
        if (order_data != null) {
            create_order_doc(order_data);
        } else {
Damien Moulard committed
123
            missing_orders.push(order_id);
124 125 126 127 128
        }
    }

    if (missing_orders.length > 0) {
        // TODO what to do when orders are missing from group?
129 130
    }

131
    // go to first order
132
    check_before_goto(order_groups.groups[group_index][0]);
133 134
}

135 136
/**
 * Create a couchdb document for an order if it doesn't exist
Damien Moulard committed
137
 * @param {Object} order_data
138
 * @param {Boolean} goto if true, go to order page
139
 */
140 141
function create_order_doc(order_data, go_to_order = false) {
    const order_doc_id = 'order_' + order_data.id;
142

143 144
    dbc.get(order_doc_id).then(() => {
        if (go_to_order === true) {
145
            check_before_goto(order_data.id);
146 147
        }
    })
Damien Moulard committed
148
        .catch(function (err) {
149
        // Create if doesn't exist
Damien Moulard committed
150 151 152 153
            if (err.status === 404) {
                let order_doc = { ...order_data };

                order_doc._id = order_doc_id;
154 155
                order_doc.last_update = {
                    timestamp: Date.now(),
Damien Moulard committed
156
                    fingerprint: fingerprint
157 158 159 160 161
                };

                dbc.put(order_doc).then(() => {
                    if (go_to_order === true) {
                        goto(order_data.id);
162
                    }
Damien Moulard committed
163 164 165 166 167 168 169 170 171 172
                })
                    .catch((err) => {
                        error = {
                            msg: 'Erreur dans la creation de la commande dans couchdb',
                            ctx: 'create_order_doc',
                            details: err
                        };
                        report_JS_error(error, 'reception');
                        console.log(error);
                    });
Damien Moulard committed
173 174
            }
        });
175
}
176 177 178

/* ACTIONS */

179 180 181
/**
 * Validate all prices of an order
 */
Damien Moulard committed
182
function validatePrices() {
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    // Loading on
    openModal();

    var update_data = {
        'update_type' : 'br_valid',
        'orders' : {}
    };

    update_data.orders[order['id']] = { 'po' : [] };

    $.ajax({
        type: "PUT",
        url: "/reception/update_orders",
        dataType: "json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(update_data),
Damien Moulard committed
200
        success: function() {
201 202 203 204
            // Remove order
            dbc.get(`order_${order['id']}`).then((doc) => {
                return dbc.remove(doc);
            })
Damien Moulard committed
205 206 207 208 209
                .then(() => {
                    callback_update = true;
                    reload();
                })
                .catch((err) => {
210
                // No doc found
Damien Moulard committed
211 212 213
                    console.log(err);
                    reload();
                });
214 215 216 217 218 219 220 221 222 223 224 225
        },
        error: function() {
            closeModal();
            alert('Erreur dans la validation des prix');
        }
    });

    // Send changes between BC and BR
    order['updated_products'] = [];

    var updates = {
        'group_amount_total' : order['amount_total'],
226
        'update_type' : 'br_valid',
227 228 229 230 231 232 233 234 235 236 237 238
        'updated_products' : [],
        'user_comments': "",
        'orders' : [order]
    };

    $.ajax({
        type: "POST",
        url: "/reception/save_error_report",
        dataType: "json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(updates),
Damien Moulard committed
239
        success: function() {
240 241 242 243 244 245 246 247 248 249 250 251
            callback_report = true;
            reload();
        },
        error: function() {
            closeModal();
            alert('Erreur dans l\'envoi du rapport.');
            err = {msg: 'Erreur dans l\'envoi du rapport.', ctx: 'validatePrices'};
            report_JS_error(err, 'reception');
        }
    });
}

252 253
/**
 * Action fired when orders are grouped (new group)
Damien Moulard committed
254
 * @returns
255
 */
256
function group_action() {
257
    let pswd = prompt('Merci de demander à un.e salarié.e le mot de passe pour fusionner ces commandes.');
258

259 260 261 262
    // Minimum security level
    if (pswd == merge_orders_pswd) {
        let selected_data = table_orders.rows('.selected').data();
        let group_ids = [];
263

264 265 266
        for (let i = 0; i < selected_data.length; i++) {
            // Select group orders id
            group_ids.push(selected_data[i].id);
267

268 269 270
            // Create doc for each group order if doesn't exist
            create_order_doc(selected_data[i]);
        }
271

272
        group_ids.sort();
Damien Moulard committed
273

274 275 276 277 278 279
        // Save group
        order_groups.groups.push(group_ids);
        dbc.put(order_groups, (err) => {
            if (!err) {
                goto(group_ids[0]);
            } else {
Damien Moulard committed
280
                alert("Une erreur est survenue lors de la création du groupe. Veuillez ré-essayer plus tard svp.");
281 282 283
                console.log(err);
            }
        });
284 285

    } else if (pswd == null) {
286
        return;
287 288 289 290 291
    } else {
        alert('Mauvais mot de passe !');
    }
}

Damien Moulard committed
292 293 294 295 296 297 298 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
/**
 * Remove an orders group.
 * Correctly set orders data so ungrouping goes smoothly.
 *
 * @param {int} group_index index in the groups array
 */
function ungroup(group_index) {
    let group = order_groups.groups[group_index];

    for (let order_id of group) {
        let order_doc_id = 'order_' + order_id;

        // Delete group data in each order
        dbc.get(order_doc_id).then((doc) => {
            if ("updated_products" in doc) {
                for (let i = 0; i < doc.updated_products.length; i++) {
                    delete(doc.updated_products[i].other_orders_data);
                }

                doc.last_update = {
                    timestamp: Date.now(),
                    fingerprint: fingerprint
                };

                dbc.put(doc).then(() => {})
                    .catch((err) => {
                        error = {
                            msg: 'Erreur dans la creation de la commande dans couchdb',
                            ctx: 'create_order_doc',
                            details: err
                        };
                        report_JS_error(error, 'reception');
                        console.log(error);
                    });
            }
        })
            .catch(function (err) {
329 330 331 332 333 334 335
                error = {
                    msg: 'Erreur dans la récupération du doc d\'une commande pour suppression d\'un groupe',
                    ctx: 'ungroup',
                    details: err
                };
                report_JS_error(error, 'reception');
                console.log(error);
Damien Moulard committed
336 337 338 339 340 341 342 343 344 345
            });
    }

    order_groups.groups.splice(group_index, 1);
    dbc.put(order_groups, (err, result) => {
        if (!err) {
            order_groups._rev = result.rev;
            display_orders_table();
            display_grouped_orders();
        } else {
346 347 348 349 350 351 352
            error = {
                msg: 'Erreur dans la mise à jour du doc des groupes pour la suppression',
                ctx: 'ungroup',
                details: err
            };
            report_JS_error(error, 'reception');
            console.log(error);
Damien Moulard committed
353 354 355 356
        }
    });
}

357
/* DISPLAY */
358

359 360
/**
 * Display the order groups.
Damien Moulard committed
361
 * Remove the grouped orders from the order table to prevent grouping in multiple groups.
362 363 364
 */
function display_grouped_orders() {
    if (table_orders !== null) {
365
        var display_something = false;
366

367
        $('#groups_items').empty();
368
        let groups_display_content = "<ul>";
Damien Moulard committed
369

370 371
        for (let group_index in order_groups.groups) {
            let group_orders = [];
Damien Moulard committed
372

373 374 375 376 377 378
            // Extract every order in the groups from the orders table
            for (group_order_id of order_groups.groups[group_index]) {
                // Look for order in datatable"
                for (let i = 0; i < table_orders.rows().data().length; i++) {
                    if (group_order_id == table_orders.rows(i).data()[0].id) {
                        var order = table_orders.rows(i).data()[0];
Damien Moulard committed
379

380
                        group_orders.push(order);
Damien Moulard committed
381

382 383 384 385 386 387
                        // remove table row
                        table_orders.rows(i).remove()
                            .draw();
                    }
                }
            }
388

389 390
            if (group_orders.length > 0) {
                // Display group
391
                display_something = true;
392
                document.getElementById("container_groups").hidden = false;
Damien Moulard committed
393
                let group_row = `<li class="group_line" group_index="${group_index}"><span class="group_line_content"> Commandes de `;
394 395

                for (let i in group_orders) {
Damien Moulard committed
396 397 398
                    group_row += `<b class="group_partner_name">${group_orders[i].partner}</b> du ${group_orders[i].date_order}`;
                    if (i != group_orders.length-1) { // for other elements than last of list
                        group_row += ", ";
399 400
                    }
                }
Damien Moulard committed
401

402
                if (group_orders[0].reception_status == 'False') {
Damien Moulard committed
403 404 405 406
                    group_row += `
                    <button class='btn--primary goto_group_button' onClick='group_goto(${group_index})'>
                        Compter les produits
                    </button>`;
407
                } else {
Damien Moulard committed
408 409 410 411
                    group_row += `
                    <button class='btn--success goto_group_button' onClick='group_goto(${group_index})'>
                        Mettre à jour les prix
                    </button>`;
412
                }
Damien Moulard committed
413

Damien Moulard committed
414 415 416
                group_row += `<i class="fas fa-times fa-lg ungroup_orders_icon"></i>`;

                group_row += "</span></li>";
417
                groups_display_content += group_row;
418 419
            }
        }
Damien Moulard committed
420

421 422 423
        if (display_something === true) {
            $('#container_groups').show();
            $('#groups_items').append(groups_display_content);
Damien Moulard committed
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443

            setTimeout(() => {
                $(".ungroup_orders_icon").off("click");
                $(".ungroup_orders_icon").on("click", function() {
                    let modal_template = $("#modal_delete_group");

                    let group_to_delete_index = $(this).closest(".group_line")
                        .attr("group_index");

                    openModal(
                        modal_template.html(),
                        () => {
                            ungroup(group_to_delete_index);
                        },
                        "Confirmer"
                    );
                });
            }, 100);
        } else {
            $('#container_groups').hide();
444
        }
445 446
    }
}
447

448 449 450 451
/**
 * Display the main orders table
 */
function display_orders_table() {
452 453 454 455
    if (table_orders) {
        table_orders.clear().destroy();
        $('#orders').empty();
    }
456

457
    table_orders = $('#orders').DataTable({
458
        data: orders,
459 460 461 462 463
        columns:[
            {
                data:"id",
                title:"Sélectionner",
                className:"dt-body-center",
Damien Moulard committed
464
                render: function (data) {
465 466 467 468 469 470 471 472 473
                    return '<input type="checkbox" id="select_bc_'+data+'" value="'+data+'">';
                },
                width: "4%",
                orderable: false
            },
            {data:"date_order", "title":"Date Commande", "width": "8%", "className":"dt-body-center"},
            {
                data:"partner",
                title:"Fournisseur",
Damien Moulard committed
474
                render: function (data, type, full) {
475 476 477 478 479 480 481
                    // Add tooltip with PO over partner name
                    return '<div class="tooltip">' + data + ' <span class="tooltiptext">' + full.name + '</span> </div>';
                }
            },
            {
                data:"reception_status",
                className:"dt-body-center",
Damien Moulard committed
482
                render: function (data) {
483 484 485 486 487 488 489 490 491 492 493 494 495
                    if (data == "qty_valid") {
                        return "<span class='btn--danger'>Pas de prix sur le bon de livraison</span>";
                    } else {
                        return "";
                    }
                },
                orderable: false,
                width: "20%"
            },
            {
                data:"reception_status",
                title:"Statut",
                className:"dt-body-center",
Damien Moulard committed
496
                render: function (data) {
497

498
                    switch (data) {
Damien Moulard committed
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
                    case 'qty_valid':
                        return "<span class='btn--success'>Mettre à jour les prix</span>";
                    case 'br_valid':
                        return "<span class='btn'><i class='far fa-check-circle'></i> Réception OK</span>";
                    case 'False':
                        return "<span class='btn--primary'>Compter les produits</span>";

                    case 'done':
                        return "<span class='btn'><i class='far fa-check-circle'></i> Terminé</span>";
                    case 'uprice_valid':
                        return "<span class='btn--primary'>Mise à jour du prix OK</span>";
                    case "valid_pending":
                        return "<span class='btn--info'>En attente de validation</span>";

                    case 'legacy':
                        return "<span class='btn--success'>Legacy</span>";
                    case 'error_pack_op':
                        return "<span class='btn--danger'>Erreur pack operations</span>";

                    case 'error_transfer':
                        return "<span class='btn--danger'>Erreur de transfert</span>";
                    case 'error_picking':
                        return "<span class='btn--danger'>Erreur validation quantité</span>";
                    case '/error_uprice':
                        return "<span class='btn--danger'>Erreur mise à jour du prix</span>";

                    default:
                        return "<span class='btn--warning'>Status inconnu : " + data + "</span>";
527 528 529
                    }
                },
                width: "20%"
530
            } //error_transfert ou error_pack_op
531 532 533 534 535 536 537 538 539
        ],
        dom: 'rtip',
        order: [
            [
                1,
                "asc"
            ]
        ],
        iDisplayLength: 25,
540
        language: {url : '/static/js/datatables/french.json'}
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
    });

    // Set rows event on click
    $('#orders').on('click', 'tbody td', function () {
        var row_data = table_orders.row($(this)).data();

        // Click on row, except cells with button
        if (this.cellIndex < 3 || this.cellIndex == 3 && row_data.reception_status != "qty_valid") {
            // Set row as selected
            $(this.parentElement).toggleClass('selected');
            if (this.parentElement.classList.contains('selected')) {
                document.getElementById("select_bc_"+row_data.id).checked = true;
            } else {
                document.getElementById("select_bc_"+row_data.id).checked = false;
            }

            // Get selected rows
            var selected_data = table_orders.rows('.selected').data();

            // if some rows already selected
            if (selected_data.length > 0) {
                // If one row selected, set selection type
                if (selected_data.length == 1) {
                    // set selection type (in case of first select)
                    selection_type = selected_data[0].reception_status;

                    // Can't group 1 order
                    document.getElementById("group_action").hidden = true;
                } else {
                    // block selection if trying to select a BC with different status
                    if (row_data.reception_status != selection_type) {
                        // unselect
                        $(this.parentElement).toggleClass('selected');
                        document.getElementById("select_bc_"+row_data.id).checked = false;

                        alert('Vous ne pouvez pas grouper des commandes qui ont un statut différent.');
                    } else {
                        //display 'group action' button
                        document.getElementById("group_action").hidden = false;

                        // 'group action' button styling, according to orders status
                        if (selected_data[0].reception_status == 'False') {
                            document.getElementById('group_action').classList.remove('btn--success');
                            document.getElementById('group_action').classList.add('btn--primary');
                            document.getElementById('group_action').innerHTML = 'Compter les produits des commandes sélectionnées';
                        } else {
                            document.getElementById('group_action').classList.remove('btn--primary');
                            document.getElementById('group_action').classList.add('btn--success');
                            document.getElementById('group_action').innerHTML = 'Mettre à jour les prix des commandes sélectionnées';
                        }
                    }
                }

            } else {
                selection_type = null;
                document.getElementById("group_action").hidden = true;
            }
Damien Moulard committed
598
        } else if (this.cellIndex == 4) { // Click on last cell button -> go to products page
599
            // Click action only for specific reception status
600
            if (row_data.reception_status == "qty_valid" || row_data.reception_status == "False") {
601 602
                // Use couchdb to pass order data to next page
                create_order_doc(row_data, true);
603
            }
Damien Moulard committed
604 605
        } else if (this.cellIndex == 3 && row_data.reception_status == "qty_valid") {
            // If 'update prices' step, click on before-last cell -> validate all prices
606 607 608 609 610 611 612 613 614 615 616
            order = row_data;
            openModal($('#modal_no_prices').html(), validatePrices, 'Confirmer', false);
        }
    });

    // Search input
    $('#search_input').on('keyup', function () {
        table_orders
            .search(jQuery.fn.DataTable.ext.type.search.string(this.value))
            .draw();
    });
617 618 619 620 621 622 623
}


$(document).ready(function() {
    openModal();
    $.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });

624
    fingerprint = new Fingerprint({canvas: true}).get();
625

Damien Moulard committed
626
    // Init couchdb
627 628 629 630 631 632
    dbc = new PouchDB(couchdb_dbname),
    sync = PouchDB.sync(couchdb_dbname, couchdb_server, {
        live: true,
        retry: true,
        auto_compaction: false
    });
633

634
    // On distant changes
Damien Moulard committed
635
    sync.on('change', function (info) {
Damien Moulard committed
636
        // If important data changed somewhere else, update local data
637
        let need_to_reload = false;
Damien Moulard committed
638

639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
        if (info.direction === "pull") {
            for (let doc of info.change.docs) {
                if (doc._id === "grouped_orders") {
                    // If groups doc changed, update local groups
                    need_to_reload = true;
                    order_groups = doc;
                } else if ("_deleted" in doc && doc._deleted === true) {
                    // If order was deleted, delete it locally
                    try {
                        const deleted_order_id = parseInt(doc._id.split('_')[1]);
                        let index = orders.findIndex(order => order.id == deleted_order_id);

                        if (index !== -1) {
                            orders.splice(index, 1);
                            need_to_reload = true;
                        }
                    } catch (error) {
                        console.log(error);
                    }
                } else {
                    // Find updated order in local orders & update it if reception status changed
                    let index = orders.findIndex(order => order.id == doc.id);
Damien Moulard committed
661

662 663 664 665 666 667 668 669 670 671 672 673 674
                    if (index !== -1 && orders[index].reception_status !== doc.reception_status) {
                        orders[index] = doc;
                        need_to_reload = true;
                        break;
                    }
                }
            }
        }

        if (need_to_reload) {
            display_orders_table();
            display_grouped_orders();
        }
Damien Moulard committed
675 676 677 678
    }).on('error', function (err) {
        console.log(err);
    });

679 680 681 682
    // Get or create order groups doc
    dbc.get("grouped_orders").then((doc) => {
        order_groups = doc;
    })
Damien Moulard committed
683 684
        .catch(function (err) {
            if (err.status === 404) {
Damien Moulard committed
685
                // Create if doesn't exist
Damien Moulard committed
686 687 688 689 690 691 692 693
                dbc.put(order_groups, (err, result) => {
                    if (!err) {
                        order_groups._rev = result.rev;
                    } else {
                        console.log("document pour les groupes déjà créé");
                        console.log(err);
                    }
                });
Damien Moulard committed
694
            } else {
695 696 697 698 699 700 701
                error = {
                    msg: 'Erreur dans la récupération des groupes dans couchdb',
                    ctx: 'document_init',
                    details: err
                };
                report_JS_error(error, 'reception');
                console.log(error);
Damien Moulard committed
702 703
            }
        });
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726

    // Set date format for DataTable so date ordering can work
    $.fn.dataTable.moment('D/M/Y');

    // Get orders
    $.ajax({
        type: 'GET',
        url: "/reception/get_list_orders",
        dataType:"json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        success: function(data) {
            orders = data.data;
            display_orders_table();
            display_grouped_orders();
            closeModal();
        },
        error: function(data) {
            err = {msg: "erreur serveur lors de la récupération des commandes", ctx: 'get_list_orders'};
            if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
                err.msg += ' : ' + data.responseJSON.error;
            }
            report_JS_error(err, 'orders');
727

728 729 730 731
            closeModal();
            alert('Erreur lors de la récupération des commandes, rechargez la page plus tard.');
        }
    });
732
});