Subversion Repositories SmartDukaan

Rev

Rev 37750 | Rev 37786 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
32352 amit.gupta 1
$(function () {
2
    $(document).on('click', ".warehouse-create-purchase-order", function () {
3
        loadCreatePurchase("main-content");
4
    });
32145 tejbeer 5
 
32352 amit.gupta 6
    $(document).on('click', ".warehouse-receive-new-invoice", function () {
7
        loadNewReceiveInvoice("main-content");
8
    });
32145 tejbeer 9
 
32192 tejbeer 10
 
32352 amit.gupta 11
    $(document).on('click', ".warehouse-grn-request", function () {
12
        loadGrnRequest("main-content");
13
    });
32192 tejbeer 14
 
32300 tejbeer 15
 
32352 amit.gupta 16
    $(document).on('click', ".warehouse-debit-note", function () {
17
        loadDebitNote("main-content");
18
    });
32192 tejbeer 19
 
20
 
32352 amit.gupta 21
    $(document).on('click', ".warehouse-invoices", function () {
22
        loadWarehouseInvoices("main-content");
23
    });
32256 tejbeer 24
 
37750 ranu 25
    // Sidebar entry for the PO stock-cover approval queue (Niranjan Kala's queue).
26
    // Add this <li> in your sidebar template to expose the entry:
27
    //   <li><a class="warehouse-po-stock-approvals" href="javascript:void(0);">Stock Approvals</a></li>
28
    // Server-side access is gated to APPROVER_EMAILS in PoStockApprovalController.
29
    $(document).on('click', ".warehouse-po-stock-approvals", function () {
30
        loadPoStockApprovals("main-content");
31
    });
32300 tejbeer 32
 
37750 ranu 33
 
32352 amit.gupta 34
    $(document).on('click', '.dateWiseInvoices', function () {
32300 tejbeer 35
 
32352 amit.gupta 36
        var startDate = getDatesFromPicker('input[name="invoice-duration"]').startDate;
37
        var endDate = getDatesFromPicker('input[name="invoice-duration"]').endDate
32300 tejbeer 38
 
32352 amit.gupta 39
        var vendorId = $('#vendorId').val();
32300 tejbeer 40
 
34047 tejus.loha 41
        // doGetAjaxRequestHandler(context + "/getWarehouseInvoicesByVendor?vendorId=" + vendorId + "&startDate=" + startDate + "&endDate=" + endDate, function (response) {
42
        // $('.invoicesviewcontainer').html(response);
43
        doGetAjaxRequestHandler(context + "/getWarehouseInvoicesBydateWise?dateWiseInvoices=" + "&startDate=" + startDate + "&endDate=" + endDate, function (response) {
44
            $('.invoicesviewcontainer').html(response);
45
        });
32300 tejbeer 46
 
33737 ranu 47
    });
32300 tejbeer 48
 
33737 ranu 49
    $(document).on('click', '.generateInvoicesExcel', function () {
32300 tejbeer 50
 
33737 ranu 51
        var startDate = getDatesFromPicker('input[name="invoice-duration"]').startDate;
52
        var endDate = getDatesFromPicker('input[name="invoice-duration"]').endDate;
53
        doAjaxGetDownload(context + "/generateDatewiseInvoiceExcel?startDate=" + startDate + "&endDate=" + endDate, "PurchaseInvoicesReport.xlsx");
32352 amit.gupta 54
    });
32300 tejbeer 55
 
56
 
32352 amit.gupta 57
    $(document)
58
        .on(
59
            'input',
60
            '#invoice',
61
            function () {
62
                if (confirm('Document has been selected, Do you want to upload ?')) {
63
                    var fileSelector = $('#invoice')[0];
64
                    if (fileSelector != undefined
65
                        && fileSelector.files[0] != undefined) {
66
                        var url = context + '/document-upload';
32300 tejbeer 67
 
32352 amit.gupta 68
                        console.log(url);
69
                        var file = this.files[0];
70
                        doAjaxUploadRequestHandler(
71
                            url,
72
                            'POST',
73
                            file,
74
                            function (response) {
75
                                console.log(response);
76
                                var documentId = response.response.document_id;
77
                                console.log("documentId : "
78
                                    + documentId);
79
                                localStorage.setItem("invoiceDocument",
80
                                    documentId);
32192 tejbeer 81
 
32295 tejbeer 82
 
32352 amit.gupta 83
                            });
32300 tejbeer 84
 
32352 amit.gupta 85
                    }
86
                } else {
87
                    // Do nothing!
88
                }
89
            });
32192 tejbeer 90
 
32352 amit.gupta 91
    $(document).on('click', ".createReceiveInvoice", function () {
32192 tejbeer 92
 
32352 amit.gupta 93
        var invoiceDate = $('#actualDate').val();
32192 tejbeer 94
 
32352 amit.gupta 95
        var warehouseId = $('#warehouseMap').val();
32192 tejbeer 96
 
32352 amit.gupta 97
        var numItems = $('#numberofItems').val();
32192 tejbeer 98
 
32352 amit.gupta 99
        var supplierId = $('#vendorId').val();
32192 tejbeer 100
 
32352 amit.gupta 101
        var totalValue = $('#totalValue').val();
32192 tejbeer 102
 
32352 amit.gupta 103
        var invoiceNumber = $('#invoiceNumber').val();
32642 raveendra. 104
        //var invoiceDoc  =  $('#invoiceDoc').val();
32192 tejbeer 105
 
34047 tejus.loha 106
        var invoice = $('#invoice').val();
32642 raveendra. 107
        var invoiceDoc = localStorage
108
            .getItem("invoiceDocument");
34047 tejus.loha 109
        console.log(invoiceDoc)
32192 tejbeer 110
 
32629 amit.gupta 111
        if (invoiceDate === "" && warehouseId === "" && numItems === "" && supplierId === "" && totalValue === "" && invoiceNumber === "" && invoiceDoc === "") {
32352 amit.gupta 112
            alert("Field can't be empty");
113
            return false;
114
        }
32192 tejbeer 115
 
32629 amit.gupta 116
        if (invoiceDate === "") {
32638 raveendra. 117
            alert("Please select date");
32629 amit.gupta 118
            return false;
119
        }
34047 tejus.loha 120
        if (supplierId === "") {
121
            alert("Please choose supplier/Vendor");
122
            return false;
123
        }
32638 raveendra. 124
 
125
        if (invoiceNumber === "") {
126
            alert("Please fill Invoice Number.");
127
            return false;
128
        }
32629 amit.gupta 129
        if (warehouseId === "") {
32638 raveendra. 130
            alert("Please choose warehouse");
32629 amit.gupta 131
            return false;
132
        }
133
 
134
        if (numItems === "") {
32638 raveendra. 135
            alert("Please fill number of items.");
32629 amit.gupta 136
            return false;
137
        }
138
        if (totalValue === "") {
32638 raveendra. 139
            alert("Please fill Total Value.");
32629 amit.gupta 140
            return false;
141
        }
32638 raveendra. 142
        console.log('invoice doc', invoiceDoc);
34047 tejus.loha 143
        if (invoiceDoc === "") {
32638 raveendra. 144
            alert("Please upload invoice.");
32629 amit.gupta 145
            return false;
146
        }
32352 amit.gupta 147
        var newReceiveInvoice = {};
32192 tejbeer 148
 
32352 amit.gupta 149
        newReceiveInvoice['invoiceDate'] = invoiceDate;
32629 amit.gupta 150
        newReceiveInvoice['warehouseId'] = warehouseId;
151
        newReceiveInvoice['numItems'] = numItems;
152
        newReceiveInvoice['supplierId'] = supplierId;
153
        newReceiveInvoice['totalValue'] = totalValue;
154
        newReceiveInvoice['invoiceNumber'] = invoiceNumber;
155
        newReceiveInvoice['invoiceDoc'] = invoiceDoc;
32192 tejbeer 156
 
32629 amit.gupta 157
        if (confirm("Are you sure you want to add new Invoice")) {
32192 tejbeer 158
 
32390 amit.gupta 159
            doPostAjaxRequestWithJsonHandler(`${context}/newReceiveInvoice`, JSON
32352 amit.gupta 160
                .stringify(newReceiveInvoice), function (response) {
161
                if (response == 'true') {
32638 raveendra. 162
                    alert("Successfully added");
32352 amit.gupta 163
                    localStorage.removeItem("invoiceDocument");
164
                    loadNewReceiveInvoice("main-content");
165
                }
166
            });
167
        }
32295 tejbeer 168
 
32192 tejbeer 169
 
32352 amit.gupta 170
    });
32192 tejbeer 171
 
172
 
32352 amit.gupta 173
    var purchaseItemIds;
174
    $(document).on('click', ".purchaseorderitemview", function () {
175
        purchaseItemIds = [];
176
        var vendorId = $('#vendorId').val();
177
        var warehouseId = $('#warehouseMap').val();
32390 amit.gupta 178
        var poDate = $('#poDate').val();
32192 tejbeer 179
 
32352 amit.gupta 180
        console.log(warehouseId);
32192 tejbeer 181
 
32352 amit.gupta 182
        if (warehouseId === null && vendorId === "") {
183
            alert("Field can't be empty");
184
            return;
185
        }
32192 tejbeer 186
 
32390 amit.gupta 187
        if (poDate === '') {
188
            alert("PO Date is required");
189
            return;
190
        }
191
 
192
        if (warehouseId === null && vendorId === "") {
193
            alert("Field can't be empty");
194
            return;
195
        }
196
 
32352 amit.gupta 197
        if (warehouseId === null) {
198
            alert("please select warehouse");
199
            return;
200
        }
201
        if (vendorId === "") {
202
            alert("please select vendor");
203
            return;
204
        }
205
        doGetAjaxRequestHandler(context + "/addPurchaseItemView?warehouseId=" + warehouseId + "&vendorId=" + vendorId, function (response) {
206
            $(".createpurchaseordercontainer").html(response);
207
        });
208
    });
32192 tejbeer 209
 
32145 tejbeer 210
 
36532 amit 211
    $(document).on('change', '#poItemsFile', function () {
212
        var file = this.files[0];
213
        if (!file) return;
214
 
215
        var vendorId = $('#vendorId').val();
216
        var poDate = $('#poDate').val();
217
 
218
        var formData = new FormData();
219
        formData.append("file", file);
220
 
221
        $.ajax({
222
            url: context + '/uploadPurchaseOrderItems?vendorId=' + vendorId + '&poDate=' + poDate,
223
            type: 'POST',
224
            data: formData,
225
            dataType: 'json',
226
            cache: false,
227
            contentType: false,
228
            processData: false,
229
            success: function (items) {
230
                // Clear existing rows
231
                $('#purchase-order-table tbody').empty();
232
                purchaseItemIds = [];
233
 
234
                for (var i = 0; i < items.length; i++) {
235
                    var item = items[i];
236
                    var $row = $('<tr>' +
237
                        '<td><input type="text" class="form-control typeaheaditem" autocomplete="off" value="' + item.modelName + '" readonly/></td>' +
37711 amit 238
                        '<td><div class="mv-qty-cell"><input type="number" class="form-control qty" name="qty" value="' + item.amendedQty + '"/><span class="mv-avail-icon" style="display:none;" tabindex="0">i</span></div><div class="mv-qty-warn" style="display:none;"></div></td>' +
36532 amit 239
                        '<td><input type="number" class="form-control transferPrice" readonly tabindex="-1" value="' + item.transferPrice + '" data-itemid="' + item.itemId + '"/></td>' +
240
                        '<td><input type="number" class="form-control totalValue" tabindex="-1" readonly value="' + item.totalValue + '"/></td>' +
241
                        '<td><input class="form-control btn btn-primary removeInPurchaseOrder" tabindex="-1" type="button" value="Remove"></td>' +
242
                        '</tr>');
243
                    $('#purchase-order-table tbody').append($row);
37711 amit 244
                    // A bulk-uploaded row gets the same breakdown as one picked by hand; absent for outside vendors,
245
                    // in which case this leaves the row alone.
246
                    renderMovementAvailability($row, item.availability);
36532 amit 247
                    purchaseItemIds.push(item.itemId);
248
                }
249
                updateTotalValue();
250
                alert("Uploaded " + items.length + " items successfully");
251
            },
252
            error: function (xhr) {
253
                var msg = "Upload failed";
254
                try {
255
                    var err = JSON.parse(xhr.responseText);
256
                    if (err.message) msg = err.message;
257
                    if (err.code) msg = err.code;
258
                } catch (e) {}
259
                alert(msg);
260
            }
261
        });
262
 
263
        // Reset file input so same file can be re-uploaded
264
        $(this).val('');
265
    });
266
 
32352 amit.gupta 267
    $(document).on('click', ".addRowInPurchaseOrder", function () {
268
        var totalQty = 0;
33727 ranu 269
        var totalValue = 0;
32145 tejbeer 270
 
32358 amit.gupta 271
        $("table > tbody > tr").each(function () {
32352 amit.gupta 272
            var itemId = $(this).find(".transferPrice").data('itemid');
273
            var qty = $(this).find(".qty").val();
33727 ranu 274
            var transferPrice = $(this).find(".transferPrice").val();
32145 tejbeer 275
 
33727 ranu 276
            if (qty !== undefined && qty !== "") {
277
                qty = parseInt(qty);
278
                totalQty += qty;
279
                if (transferPrice !== undefined && transferPrice !== "") {
280
                    transferPrice = parseFloat(transferPrice);
281
                    totalValue += qty * transferPrice;
282
                }
32352 amit.gupta 283
            }
32358 amit.gupta 284
        });
32145 tejbeer 285
 
32603 raveendra. 286
        var $html = $(`<tr>
33727 ranu 287
        <td><input type="text" class="form-control typeaheaditem" autocomplete="off" placeholder="Search Model"/></td>
37697 amit 288
        <td><div class="mv-qty-cell"><input type="number" class="form-control qty" name="qty" placeholder="Quantity"/><span class="mv-avail-icon" style="display:none;" tabindex="0">i</span></div><div class="mv-qty-warn" style="display:none;"></div></td>
33727 ranu 289
        <td><input type="number" class="form-control transferPrice" readonly tabindex="-1" placeholder="Transfer Price"/></td>
290
        <td><input type="number" class="form-control totalValue" tabindex="-1" readonly placeholder="Total Value"/></td>
291
        <td><input class="form-control btn btn-primary removeInPurchaseOrder" tabindex="-1" type="button" value="Remove"></td>
292
    </tr>`);
32192 tejbeer 293
 
32352 amit.gupta 294
        var vendorId = $('#vendorId').val();
32192 tejbeer 295
 
37750 ranu 296
        // Scoped to the PO items table's tbody — bare $('tbody') would also match
297
        // the modal's flagged-items tbody, and jQuery would move $html into the
298
        // modal instead of the visible table, breaking the autocomplete wiring.
299
        $('#purchase-order-table tbody').append($html);
33727 ranu 300
        getVendorItemAheadOptions($html.find('.typeaheaditem'), vendorId, function (selectedItem) {
32488 amit.gupta 301
            let poDate = $('#poDate').val();
32352 amit.gupta 302
            var itemId = selectedItem.itemId;
34047 tejus.loha 303
            var description = selectedItem.itemDescription;
304
            if (itemId) {
32488 amit.gupta 305
                doGetAjaxRequestHandler(`${context}/getPricing?vendorId=${vendorId}&itemId=${itemId}&onDate=${poDate}`, function (response) {
32360 amit.gupta 306
                    if (response !== "null") {
34047 tejus.loha 307
                        if (response !== 'false') {
308
                            var jsonObj = JSON.parse(response);
309
                            $html.find('.transferPrice').val(jsonObj.transferPrice);
37697 amit 310
                            renderMovementAvailability($html, jsonObj);
34047 tejus.loha 311
                            $html.find('input.qty').focus();
33727 ranu 312
 
34047 tejus.loha 313
                            // Update the total value for this row
314
                            let qty = $html.find('.qty').val();
315
                            let transferPrice = jsonObj.transferPrice;
316
                            if (qty && transferPrice) {
317
                                let total = qty * transferPrice;
318
                                $html.find('.totalValue').val(total);
319
                                updateTotalValue();
320
                            }
321
                            addItem($html, itemId);
322
                        } else {
323
                            $html.find('.typeaheaditem').val('');
324
                            alert(`Category not Define(eg- HID, SLOW MOVING, FAST MOVING),First define the category of ${description} and Try again`);
33727 ranu 325
                        }
34047 tejus.loha 326
 
32360 amit.gupta 327
                    } else {
34047 tejus.loha 328
                        $html.find('.typeaheaditem').val('');
37072 amit 329
                        alert(`No approved price for ${description} on ${poDate}. Get the vendor pricing approved first, then try again.`);
32360 amit.gupta 330
                    }
331
                });
332
            } else {
32352 amit.gupta 333
                return false;
334
            }
335
        });
33727 ranu 336
    });
32145 tejbeer 337
 
33727 ranu 338
    $(document).on('input', '.qty', function () {
339
        var $row = $(this).closest('tr');
340
        var qty = parseInt($(this).val());
37697 amit 341
        checkMovableQty($row, qty);
33727 ranu 342
        var transferPrice = parseFloat($row.find('.transferPrice').val());
343
        if (!isNaN(qty) && !isNaN(transferPrice)) {
344
            let total = qty * transferPrice;
345
            $row.find('.totalValue').val(total);
346
        }
347
        updateTotalValue();
32352 amit.gupta 348
    });
32145 tejbeer 349
 
33727 ranu 350
    function updateTotalValue() {
351
        var grandTotal = 0;
36520 amit 352
        var totalQty = 0;
33727 ranu 353
        $('tbody > tr').each(function () {
354
            var rowTotal = parseFloat($(this).find('.totalValue').val());
36520 amit 355
            var rowQty = parseInt($(this).find('.qty').val());
33727 ranu 356
            if (!isNaN(rowTotal)) {
357
                grandTotal += rowTotal;
358
            }
36520 amit 359
            if (!isNaN(rowQty)) {
360
                totalQty += rowQty;
361
            }
33727 ranu 362
        });
36520 amit 363
        $('#totalQuantity').text(totalQty);
33727 ranu 364
        $('#grandTotal').text(grandTotal.toFixed(2));
365
    }
366
 
32355 amit.gupta 367
    function addItem(container, itemId) {
32361 amit.gupta 368
        oldItemId = container.find('.transferPrice').data('itemid');
32360 amit.gupta 369
        if (typeof (oldItemId) === "undefined") {
370
            let itemIndex = purchaseItemIds.indexOf(itemId);
371
            if (itemIndex >= 0) {
372
                alert("Item already added");
32376 amit.gupta 373
                container.find('.typeaheaditem').val("");
32360 amit.gupta 374
                return false;
375
            } else {
376
                purchaseItemIds.push(itemId);
32361 amit.gupta 377
                container.find('.transferPrice').data('itemid', itemId);
32360 amit.gupta 378
                $('.addRowInPurchaseOrder').click();
379
            }
32352 amit.gupta 380
        } else {
32360 amit.gupta 381
            if (oldItemId !== itemId) {
382
                let oldIndex = purchaseItemIds.indexOf(oldItemId);
383
                if (oldIndex > -1) {
384
                    purchaseItemIds.splice(oldIndex, 1);
385
                }
386
                purchaseItemIds.push(itemId);
32361 amit.gupta 387
                container.find('.transferPrice').data('itemid', itemId);
32358 amit.gupta 388
            } else {
32360 amit.gupta 389
                return false;
32352 amit.gupta 390
            }
391
        }
32360 amit.gupta 392
        return true;
32352 amit.gupta 393
    }
32145 tejbeer 394
 
33727 ranu 395
 
32352 amit.gupta 396
    $(document).on('click', '.createSendPurchaseOrder', function () {
32145 tejbeer 397
 
32390 amit.gupta 398
        createPO(true);
32145 tejbeer 399
 
32352 amit.gupta 400
    });
32145 tejbeer 401
 
402
 
32352 amit.gupta 403
    $(document).on('click', '.createPurchaseOrder', function () {
32145 tejbeer 404
 
405
 
32390 amit.gupta 406
        createPO(false);
32352 amit.gupta 407
    });
32145 tejbeer 408
 
409
 
32352 amit.gupta 410
    $(document).on('change', '.qty', function () {
32145 tejbeer 411
 
412
 
32352 amit.gupta 413
        var row = $(this).closest("tr");
414
        var qty = $(row).find(".qty").val();
415
        var transferPrice = $(row).find(".transferPrice").val();
32145 tejbeer 416
 
32352 amit.gupta 417
        var totalVal = transferPrice * qty;
32145 tejbeer 418
 
32352 amit.gupta 419
        var totalValue = $(row).find(".totalValue").val(totalVal);
32145 tejbeer 420
 
32352 amit.gupta 421
        var purchaseOrderValue = 0;
32145 tejbeer 422
 
32352 amit.gupta 423
        $("table > tbody > tr").each(function () {
32145 tejbeer 424
 
32352 amit.gupta 425
            var totalValue = $(this).find(".totalValue").val();
32358 amit.gupta 426
            purchaseOrderValue += totalValue;
32145 tejbeer 427
 
32352 amit.gupta 428
        });
32145 tejbeer 429
 
32352 amit.gupta 430
    });
32145 tejbeer 431
 
432
 
32352 amit.gupta 433
    $(document).on('click', '.warehouse-open-purchase-order', function () {
434
        loadOpenPurchase("main-content");
435
    });
32145 tejbeer 436
 
437
 
32352 amit.gupta 438
    $(document).on('click', '.editViewPurchaseOrder', function () {
439
        var purchaseOrderId = $(this).data('poid');
440
        doGetAjaxRequestHandler(context + "/getEditPOByPurchaseId?purchaseId=" + purchaseOrderId, function (response) {
441
            $('#warehouseEditPurchaseContainer .modal-content').html(response);
442
        });
32145 tejbeer 443
 
32352 amit.gupta 444
    });
32145 tejbeer 445
 
32352 amit.gupta 446
    $(document).on('click', '.editPurchaseOrder', function () {
447
        var purchaseOrderId = $(this).data('poid');
32145 tejbeer 448
 
32352 amit.gupta 449
        editPurchase(false, purchaseOrderId);
32145 tejbeer 450
 
32352 amit.gupta 451
    });
32145 tejbeer 452
 
453
 
32352 amit.gupta 454
    $(document).on('click', '.editSendPurchaseOrder', function () {
455
        var purchaseOrderId = $(this).data('poid');
32145 tejbeer 456
 
457
 
32352 amit.gupta 458
        editPurchase(true, purchaseOrderId);
459
    });
32145 tejbeer 460
 
32352 amit.gupta 461
    $(document).on('click', '.closePurchaseOrder', function () {
462
        var purchaseOrderId = $(this).data('poid');
463
        if (confirm("Are you sure you want to close the PO") == true) {
464
            doPostAjaxRequestHandler(context + "/closePuchaseOrder?purchaseId=" + purchaseOrderId,
465
                function (response) {
32145 tejbeer 466
 
32352 amit.gupta 467
                    console.log(response);
468
                    if (response == 'true') {
469
                        alert("successfully closed");
470
                        loadOpenPurchase("main-content")
471
                    }
472
                });
473
        }
474
    });
32145 tejbeer 475
 
476
 
32352 amit.gupta 477
    $(document).on('click', '.warehouse-view-purchase-order', function () {
478
        doGetAjaxRequestHandler(context + "/viewPurchaseOrder", function (response) {
479
            $('#' + 'main-content').html(response);
480
        });
481
    });
32145 tejbeer 482
 
483
 
32352 amit.gupta 484
    $(document).on('click', '.dateWisePo', function () {
32145 tejbeer 485
 
32352 amit.gupta 486
        var startDate = getDatesFromPicker('input[name="duration"]').startDate;
33729 ranu 487
        var endDate = getDatesFromPicker('input[name="duration"]').endDate;
32145 tejbeer 488
 
489
 
32352 amit.gupta 490
        doGetAjaxRequestHandler(context + "/getPurchaseOrders?startDate=" + startDate + "&endDate=" + endDate, function (response) {
491
            $('.purchaseorderviewcontainer').html(response);
32145 tejbeer 492
 
32352 amit.gupta 493
        });
32145 tejbeer 494
 
495
 
32352 amit.gupta 496
    });
32145 tejbeer 497
 
498
 
32352 amit.gupta 499
    $(document).on('click', '.viewPurchaseOrderlineItem', function () {
500
        var purchaseOrderId = $(this).data('poid');
32145 tejbeer 501
 
32352 amit.gupta 502
        doGetAjaxRequestHandler(context + "/getWarehouseLineItemByPurchaseId?purchaseId=" + purchaseOrderId, function (response) {
503
            $('#warehouseLineItem .modal-content').html(response);
32145 tejbeer 504
 
32352 amit.gupta 505
        });
506
    });
32145 tejbeer 507
 
508
 
32352 amit.gupta 509
    $(document).on("click", '.removeInPurchaseOrder', function () {
510
        var row = $(this).closest("tr");
32361 amit.gupta 511
        let itemId = row.find('.transferPrice').data('itemid');
32360 amit.gupta 512
        let itemIndex = purchaseItemIds.indexOf(itemId);
32352 amit.gupta 513
        if (itemIndex > -1) { // only splice array when item is found
514
            purchaseItemIds.splice(itemIndex, 1); // 2nd parameter means remove one item only
515
        }
516
        row.remove();
517
    });
32192 tejbeer 518
 
519
 
32352 amit.gupta 520
    $(document).on('click', ".addRowForInvoiceItem", function () {
32145 tejbeer 521
 
32352 amit.gupta 522
        var numitems = $(this).data("numitems");
523
        var invoiceId = $(this).data("invoiceid");
524
        var invoiceItemIds = [];
32360 amit.gupta 525
        var totalQty = 0;
32145 tejbeer 526
 
32352 amit.gupta 527
        $("#invoice-order-table > tbody > tr").each(function () {
528
            var itemId = $(this).find(".rate").data('itemid');
529
            var qty = $(this).find(".qty").val();
32145 tejbeer 530
 
32360 amit.gupta 531
            if (qty !== undefined) {
532
                totalQty += qty;
32352 amit.gupta 533
            }
32145 tejbeer 534
 
32360 amit.gupta 535
            if (itemId !== undefined) {
536
                invoiceItemIds.push(itemId);
32352 amit.gupta 537
            }
538
        });
32145 tejbeer 539
 
32352 amit.gupta 540
        var $html = $('<tr>  <td>  <input type="text" class="form-control typeaheaditem"   autocomplete="off"  placeholder="Search Model"/> </td>' +
541
            '<td>  <input type="number" class="form-control qty"  name = "qty" placeholder="Quantity"/> </td>' +
32364 amit.gupta 542
            '<td>  <input type="number" class="form-control rate" placeholder="Rate"/> </td>' +
32352 amit.gupta 543
            '<td> <input class="form-control btn btn-primary removeInInvoiceItem" type="button" value="Remove"></td>  </tr> ');
32145 tejbeer 544
 
545
 
32352 amit.gupta 546
        getItemAheadOptions($html.find('.typeaheaditem'), true, function (
547
            selectedItem) {
548
            var itemId = selectedItem.itemId;
549
            if (invoiceItemIds.indexOf(itemId) > -1) {
550
                alert("Item already added");
551
                $html.find('.typeaheaditem').val("")
32145 tejbeer 552
 
32352 amit.gupta 553
                return false;
554
            }
555
            $html.find('.rate').data('itemid', itemId)
32145 tejbeer 556
 
32352 amit.gupta 557
            $html.find('.removeInInvoiceItem').data('invoiceid', invoiceId)
558
            $html.find('.removeInInvoiceItem').data('itemid', itemId)
32145 tejbeer 559
 
37564 amit 560
        }, true);
32145 tejbeer 561
 
32192 tejbeer 562
 
32352 amit.gupta 563
        if (totalQty < numitems) {
32192 tejbeer 564
 
32352 amit.gupta 565
            $('#invoice-order-table tbody').append($html);
566
        }
32192 tejbeer 567
 
32352 amit.gupta 568
    });
32256 tejbeer 569
 
32192 tejbeer 570
 
32352 amit.gupta 571
    $(document).on('click', '.saveInvoiceDetail', function () {
32192 tejbeer 572
 
32352 amit.gupta 573
        var numItems = $(this).data("numitems");
574
        var invoiceId = $(this).data("invoiceid");
575
        var warehouseId = $(this).data("warehouseid");
576
        var supplierId = $(this).data("supplierid");
577
        getInvoiceItemData(numItems, invoiceId, warehouseId, supplierId, false);
32192 tejbeer 578
 
32352 amit.gupta 579
    });
32192 tejbeer 580
 
581
 
32352 amit.gupta 582
    $(document).on('click', '.validateInvoiceDetail', function () {
583
        var numItems = $(this).data("numitems");
584
        var invoiceId = $(this).data("invoiceid");
585
        var warehouseId = $(this).data("warehouseid");
586
        var supplierId = $(this).data("supplierid");
32192 tejbeer 587
 
32352 amit.gupta 588
        getInvoiceItemData(numItems, invoiceId, warehouseId, supplierId, true);
32192 tejbeer 589
 
32352 amit.gupta 590
    });
32192 tejbeer 591
 
592
 
32352 amit.gupta 593
    $(document).on("click", '.removeInInvoiceItem', function () {
32192 tejbeer 594
 
32352 amit.gupta 595
        var row = $(this).closest("tr");
596
        var invoiceId = $(this).data("invoiceid");
597
        var itemId = $(this).data("itemid");
598
        if (invoiceId != undefined && itemId != undefined) {
599
            doDeleteAjaxRequestHandler(context + "/removeInvoiceItem?invoiceId="
600
                + invoiceId + "&itemId=" + itemId, function (response) {
601
                if (response == "true") {
602
                    alert("Item removed successfully");
32192 tejbeer 603
 
32352 amit.gupta 604
                }
605
            });
606
        }
32192 tejbeer 607
 
32352 amit.gupta 608
        row.remove();
32192 tejbeer 609
 
32352 amit.gupta 610
    });
32192 tejbeer 611
 
612
 
32352 amit.gupta 613
    $(document).on('click', '.purchaseGrn', function () {
32192 tejbeer 614
 
32352 amit.gupta 615
        var grnItemArray = [];
32192 tejbeer 616
 
32352 amit.gupta 617
        var invoiceId = $(this).data("invoiceid");
32192 tejbeer 618
 
32352 amit.gupta 619
        $("#invoice-purchase-validate > tbody > tr").each(function () {
620
            var grnItemJson = {};
32192 tejbeer 621
 
32352 amit.gupta 622
            var itemId = $(this).find(".itemId").text();
623
            var qty = $(this).find(".qty").text();
624
            var poId = $(this).find(".purchaseId").text();
625
            var excessQty = $(this).find(".excessQty").text();
626
            var itemType = $(this).find(".itemType").text();
32192 tejbeer 627
 
32352 amit.gupta 628
            console.log(itemType);
32192 tejbeer 629
 
32352 amit.gupta 630
            if (itemType == "Serialized") {
631
                var serialNumbers = $(this).find(".imeis-to-grn").tagsinput('items');
32366 amit.gupta 632
                grnItemJson['serialNumbers'] = serialNumbers;
32192 tejbeer 633
 
32352 amit.gupta 634
                if (excessQty > 0) {
635
                    var returnSerialNumbers = $(this).find(".imeis-to-grn-return").tagsinput('items');
636
                    grnItemJson['returnSerialNumbers'] = returnSerialNumbers
637
                }
638
            }
32366 amit.gupta 639
            console.log(serialNumbers);
32352 amit.gupta 640
            grnItemJson['itemId'] = itemId;
641
            grnItemJson['serialNumbers'] = serialNumbers
642
            grnItemJson['qty'] = qty
643
            grnItemJson['poId'] = poId
644
            grnItemJson['invoiceId'] = invoiceId
645
            grnItemJson['itemType'] = itemType
646
            grnItemJson['excessQty'] = excessQty
32192 tejbeer 647
 
32352 amit.gupta 648
            grnItemJson['returnSerialNumbers'] = returnSerialNumbers
32192 tejbeer 649
 
32352 amit.gupta 650
            grnItemArray.push(grnItemJson)
32192 tejbeer 651
 
32352 amit.gupta 652
            console.log(grnItemArray)
32192 tejbeer 653
 
32352 amit.gupta 654
        });
32192 tejbeer 655
 
32352 amit.gupta 656
        for (var i = 0; i < grnItemArray.length; i++) {
32366 amit.gupta 657
            var itemType = grnItemArray[i].itemType;
32192 tejbeer 658
 
32352 amit.gupta 659
            if (itemType == "Serialized") {
660
                var excessQty = grnItemArray[i].excessQty
32192 tejbeer 661
 
662
 
32352 amit.gupta 663
                var serialNumbers = grnItemArray[i].serialNumbers.length
664
                var qty = grnItemArray[i].qty
32192 tejbeer 665
 
32352 amit.gupta 666
                if (serialNumbers != qty) {
667
                    alert("serial number is not matched with qty")
668
                    return false;
669
                }
32192 tejbeer 670
 
32352 amit.gupta 671
                if (excessQty > 0) {
32192 tejbeer 672
 
32352 amit.gupta 673
                    var returnSerialNumbers = grnItemArray[i].returnSerialNumbers.length
32192 tejbeer 674
 
32352 amit.gupta 675
                    if (returnSerialNumbers != excessQty) {
676
                        alert("Return serial number is not matched with excess qty")
677
                        return false;
678
                    }
32192 tejbeer 679
 
32352 amit.gupta 680
                }
681
            }
32192 tejbeer 682
 
32352 amit.gupta 683
        }
32192 tejbeer 684
 
685
 
32352 amit.gupta 686
        console.log(JSON.stringify(grnItemArray))
687
        if (confirm("Are you sure you want to grn purchase order") == true) {
32192 tejbeer 688
 
32352 amit.gupta 689
            doPostAjaxRequestWithJsonHandler(context
690
                + "/createGrn", JSON
691
                .stringify(grnItemArray), function (response) {
692
                if (response == 'true') {
693
                    alert("successfully done");
694
                    loadNewReceiveInvoice("main-content");
695
                }
696
            });
697
        }
32192 tejbeer 698
 
699
 
32352 amit.gupta 700
    });
32256 tejbeer 701
 
702
 
32352 amit.gupta 703
    $(document).on('click', '.grnRequest', function () {
32192 tejbeer 704
 
32352 amit.gupta 705
        var grnRequestJson = {};
706
        var grnRequestItemArray = [];
32192 tejbeer 707
 
32352 amit.gupta 708
        var invoiceId = $(this).data("invoiceid");
32192 tejbeer 709
 
710
 
32352 amit.gupta 711
        $("#invoice-purchase-validate > tbody > tr").each(function () {
712
            var grnItemJson = {};
32192 tejbeer 713
 
32352 amit.gupta 714
            var itemId = $.trim($(this).find(".itemId").text());
715
            var poId = $.trim($(this).find(".purchaseId").text());
32192 tejbeer 716
 
32352 amit.gupta 717
            var qty = parseInt($(this).find(".qty").text());
32256 tejbeer 718
 
32352 amit.gupta 719
            var excessQty = parseInt($(this).find(".excessQty").text());
32256 tejbeer 720
 
32352 amit.gupta 721
            var priceMismatch = $.trim($(this).find(".priceMismatch").text());
722
            console.log(priceMismatch)
32256 tejbeer 723
 
724
 
32354 amit.gupta 725
            if (priceMismatch !== "" || excessQty > 0) {
32352 amit.gupta 726
                console.log(typeof priceMismatch)
727
                console.log(excessQty)
728
                grnItemJson['itemId'] = itemId;
729
                grnItemJson['qty'] = qty;
730
                grnItemJson['excessQty'] = excessQty
32376 amit.gupta 731
                if (priceMismatch === '') {
732
                    grnItemJson['mismatch'] = 'QtyMismatch';
733
                } else {
734
                    grnItemJson['mismatch'] = priceMismatch
735
                }
32352 amit.gupta 736
                grnItemJson['poId'] = poId
32192 tejbeer 737
 
32352 amit.gupta 738
                grnRequestItemArray.push(grnItemJson)
739
            }
740
        });
32256 tejbeer 741
 
32352 amit.gupta 742
        console.log(grnRequestItemArray)
32256 tejbeer 743
 
744
 
32352 amit.gupta 745
        grnRequestJson['invoiceId'] = invoiceId;
746
        grnRequestJson['warehousePurchaseModel'] = grnRequestItemArray
32256 tejbeer 747
 
32366 amit.gupta 748
        if (confirm("Are you sure you want to raise grn request")) {
32192 tejbeer 749
 
32352 amit.gupta 750
            doPostAjaxRequestWithJsonHandler(context
751
                + "/grnRequest", JSON
752
                .stringify(grnRequestJson), function (response) {
753
                if (response == 'true') {
754
                    alert("successfully done");
755
                    loadNewReceiveInvoice("main-content");
756
                }
757
            });
758
        }
32192 tejbeer 759
 
760
 
32352 amit.gupta 761
    });
32192 tejbeer 762
 
32256 tejbeer 763
 
32352 amit.gupta 764
    $(document).on('click', '.resolvedPriceMismatchRequest', function () {
765
        var id = $(this).data("id");
32256 tejbeer 766
 
32352 amit.gupta 767
        var invoiceId = $(this).data("invoiceid");
32256 tejbeer 768
 
32352 amit.gupta 769
        var requestId = $(this).data("requestid");
32256 tejbeer 770
 
32352 amit.gupta 771
        var mismatch = $(this).data("mismatch");
32256 tejbeer 772
 
32352 amit.gupta 773
        if (mismatch == "InvoiceMismatch") {
32485 amit.gupta 774
            if (confirm("Are you sure you want to resolve invoice mismatch")) {
32352 amit.gupta 775
                doGetAjaxRequestHandler(context + "/resolvedMismatchRequest?id=" + id, function (response) {
776
                    if (response == 'true') {
777
                        getGrnRequestItems(requestId, invoiceId)
778
                    }
779
                });
32256 tejbeer 780
 
32352 amit.gupta 781
            }
782
        } else if (mismatch == "PoMismatch") {
37707 amit 783
            // Say what the replacement PO is for and what to do if it closes before the stock lands, rather than
784
            // leaving someone to discover that a GRN has quietly stopped matching.
785
            if (confirm("Resolve this price mismatch?\n\nThe current PO line is discarded and a replacement "
786
                    + "purchase order is raised on the invoice date at the corrected price. This invoice is then "
37770 amit 787
                    + "received against that PO.\n\nIt closes automatically after 6 days; if the stock arrives "
788
                    + "later, it needs a fresh PO.") == true) {
32256 tejbeer 789
 
32352 amit.gupta 790
                doGetAjaxRequestHandler(context + "/resolvedMismatchRequest?id=" + id, function (response) {
791
                    if (response == 'true') {
792
                        getGrnRequestItems(requestId, invoiceId)
793
                    }
794
                });
32256 tejbeer 795
 
32352 amit.gupta 796
            }
797
        }
32256 tejbeer 798
 
32352 amit.gupta 799
    });
32256 tejbeer 800
 
801
 
32352 amit.gupta 802
    $(document).on('click', '.resolvedQtyMismatchRequest', function () {
803
        var id = $(this).data("id");
804
        var invoiceId = $(this).data("invoiceid");
805
        var requestId = $(this).data("requestid");
32256 tejbeer 806
 
807
 
32352 amit.gupta 808
        var mismatch = $(this).data("mismatch");
32256 tejbeer 809
 
32352 amit.gupta 810
        var $row = $(this).closest("tr");
811
        var requiredQty = $row.find(".requiredQty").val();
32256 tejbeer 812
 
32352 amit.gupta 813
        console.log(requiredQty);
32256 tejbeer 814
 
32352 amit.gupta 815
        if (mismatch == "QtyMismatch") {
816
            if (confirm("Are you sure you want to resolve qty mismatch") == true) {
32256 tejbeer 817
 
32352 amit.gupta 818
                doGetAjaxRequestHandler(context + "/resolvedMismatchRequest?id=" + id + "&requiredQty=" + requiredQty, function (response) {
819
                    if (response == 'true') {
820
                        getGrnRequestItems(requestId, invoiceId)
821
                    }
822
                });
32256 tejbeer 823
 
32352 amit.gupta 824
            }
825
        }
32256 tejbeer 826
 
32352 amit.gupta 827
    });
32256 tejbeer 828
 
32192 tejbeer 829
 
32145 tejbeer 830
});
831
 
832
function loadCreatePurchase(domId) {
32352 amit.gupta 833
    doGetAjaxRequestHandler(context + "/warehousePurchaseOrder", function (response) {
834
        $('#' + domId).html(response);
835
    });
32145 tejbeer 836
}
837
 
32192 tejbeer 838
 
32145 tejbeer 839
function loadOpenPurchase(domId) {
840
 
32352 amit.gupta 841
    doGetAjaxRequestHandler(context + "/getOpenPurchaseOrder", function (response) {
842
        $('#' + domId).html(response);
843
    });
32145 tejbeer 844
}
845
 
32192 tejbeer 846
function loadNewReceiveInvoice(domId) {
32352 amit.gupta 847
    doGetAjaxRequestHandler(context + "/newReceiveInvoice", function (response) {
848
        $('#' + domId).html(response);
849
    });
32192 tejbeer 850
}
851
 
32256 tejbeer 852
 
853
function loadGrnRequest(domId) {
32352 amit.gupta 854
    doGetAjaxRequestHandler(context + "/grnRequest", function (response) {
855
        $('#' + domId).html(response);
856
    });
32256 tejbeer 857
}
858
 
859
function loadDebitNote(domId) {
32352 amit.gupta 860
    doGetAjaxRequestHandler(context + "/getDebitNote", function (response) {
861
        $('#' + domId).html(response);
862
    });
32256 tejbeer 863
}
864
 
33729 ranu 865
$(document).on('click', '.dateWiseDebitNote', function () {
866
 
867
    var startDate = getDatesFromPicker('input[name="date-duration"]').startDate;
868
    var endDate = getDatesFromPicker('input[name="date-duration"]').endDate;
869
 
870
 
871
    doGetAjaxRequestHandler(context + "/getDateWiseDebitNote?startDate=" + startDate + "&endDate=" + endDate, function (response) {
872
        $('#warehouse-datewise-debitnote-container').html(response);
873
 
874
    });
875
});
876
 
877
$(document).on('click', '.generateVendorDebitNoteExcel', function () {
878
    var startDate = getDatesFromPicker('input[name="date-duration"]').startDate;
879
    var endDate = getDatesFromPicker('input[name="date-duration"]').endDate;
33809 ranu 880
    doAjaxGetDownload(context + "/generateVendorDebitNoteExcel?startDate=" + startDate + "&endDate=" + endDate, "VendorDebitNoteReport.csv");
33729 ranu 881
});
882
 
32300 tejbeer 883
function loadWarehouseInvoices(domId) {
32352 amit.gupta 884
    doGetAjaxRequestHandler(context + "/getWarehouseInvoices", function (response) {
885
        $('#' + domId).html(response);
886
    });
32300 tejbeer 887
}
888
 
37750 ranu 889
// Loads the PO stock-cover approvals queue into the main content pane.
890
// Access is server-gated (403-ish empty view if the caller isn't an approver).
891
function loadPoStockApprovals(domId) {
892
    doGetAjaxRequestHandler(context + "/po/stock-approvals", function (response) {
893
        $('#' + domId).html(response);
894
    });
895
}
896
 
32390 amit.gupta 897
function createPO(sendPo) {
32352 amit.gupta 898
    var purchaseOrder = {};
32145 tejbeer 899
 
32352 amit.gupta 900
    var vendorId = $('#vendorId').val();
32145 tejbeer 901
 
32352 amit.gupta 902
    var warehouseId = $('#warehouseMap').val();
32145 tejbeer 903
 
32390 amit.gupta 904
    var poDate = $('#poDate').val();
32145 tejbeer 905
 
32390 amit.gupta 906
 
32352 amit.gupta 907
    var items = []
908
    $("table > tbody > tr").each(function () {
909
        var purchaseOrderJson = {};
32145 tejbeer 910
 
32352 amit.gupta 911
        var itemId = $(this).find(".transferPrice").data('itemid');
912
        var qty = $(this).find(".qty").val();
913
        var transferPrice = $(this).find(".transferPrice").val();
914
        var totalValue = $(this).find(".totalValue").val();
32145 tejbeer 915
 
916
 
32352 amit.gupta 917
        purchaseOrderJson['itemId'] = itemId;
918
        purchaseOrderJson['amendedQty'] = qty
919
        purchaseOrderJson['totalValue'] = totalValue
920
        purchaseOrderJson['transferPrice'] = transferPrice
32145 tejbeer 921
 
32352 amit.gupta 922
        items.push(purchaseOrderJson)
923
    });
32145 tejbeer 924
 
925
 
32352 amit.gupta 926
    for (var i = 0; i < items.length; i++) {
927
        console.log(items[i])
32145 tejbeer 928
 
32352 amit.gupta 929
        var itemId = items[i].itemId
930
        var qty = items[i].amendedQty
931
        var transferPrice = items[i].transferPrice
932
        var totalValue = items[i].totalValue
32145 tejbeer 933
 
32352 amit.gupta 934
        if (itemId === "" && qty === "" && transferPrice === "" && totalValue === "") {
935
            alert("Field can't be empty");
936
            return false;
937
        }
32145 tejbeer 938
 
939
 
32352 amit.gupta 940
        if (itemId === "") {
941
            alert("please select item");
942
            return false;
943
        }
944
        if (qty === "") {
945
            alert("please choose qty");
946
            return false;
947
        }
32145 tejbeer 948
 
32352 amit.gupta 949
        if (transferPrice === "") {
950
            alert("Transfer Price can't be empty");
951
            return false;
952
        }
953
        if (totalValue === "") {
954
            alert("Total value can't be empty");
955
            return false;
956
        }
32145 tejbeer 957
 
32352 amit.gupta 958
        if (qty <= 0) {
959
            alert("Please fill Qty");
960
            return false;
961
        }
32145 tejbeer 962
 
963
 
32352 amit.gupta 964
    }
32261 tejbeer 965
 
37723 amit 966
    // Rows typed by hand and rows filled from a bulk upload are checked alike: the screen is where the order is made.
967
    var overCap = [];
968
    $("table > tbody > tr").each(function () {
969
        if ($(this).find('.qty').hasClass('mv-over')) {
970
            overCap.push($(this).find('.typeaheaditem').val() + ': ' + $(this).find('.mv-qty-warn').text());
971
        }
972
    });
973
    if (overCap.length > 0) {
974
        alert("Reduce these quantities before creating the PO:\n\n" + overCap.join("\n"));
975
        return false;
976
    }
977
 
32352 amit.gupta 978
    purchaseOrder['vendorId'] = vendorId;
979
    purchaseOrder['warehouseId'] = warehouseId
980
    purchaseOrder['sendPo'] = sendPo
32390 amit.gupta 981
    purchaseOrder['poDate'] = poDate;
32352 amit.gupta 982
    purchaseOrder['items'] = items
32145 tejbeer 983
 
32352 amit.gupta 984
    console.log(purchaseOrder)
32145 tejbeer 985
 
37750 ranu 986
    // Modal 1 (pmscp) replaces the old native `confirm`. Populate the summary
987
    // tiles from what the user actually entered, then hand off to the button
988
    // handler wired in $(document).on('click', '#pmscpConfirmCreate', ...).
989
    openPmscpCreateConfirm(purchaseOrder);
990
}
32145 tejbeer 991
 
37750 ranu 992
// ─────────────────────────────────────────────────────────────────────────────
993
// PO-create modal stack — three sequenced modals replace the old native
994
// confirm/prompt/alert popups:
995
//   1) #pmscpConfirmModal       — "Are you sure you want to create this PO?"
996
//   2) #pmscpReasonModal        — reason textarea + live 50-char counter
997
//                                 (only when preflight says approval is needed)
998
//   3) #pmscpApprovalModal      — final "Sending to Niranjan Kala · L4" confirm
999
// The pending purchaseOrder object rides on window.__pmscpPO between modals.
1000
// ─────────────────────────────────────────────────────────────────────────────
1001
var PMSCP_MIN_REASON = 50;
32145 tejbeer 1002
 
37750 ranu 1003
// Minimal HTML escape for values injected into modal markup (item names from server).
1004
function escapePmscp(s) {
1005
    if (s === null || s === undefined) return '';
1006
    return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
1007
        .replace(/"/g, '&quot;').replace(/'/g, '&#39;');
1008
}
1009
 
1010
function openPmscpCreateConfirm(purchaseOrder) {
1011
    window.__pmscpPO = purchaseOrder;
1012
 
1013
    // Populate summary tiles from the form + purchaseOrder payload.
1014
    var vendorName = $('#vendorId option:selected').text() || purchaseOrder.vendorId;
1015
    var warehouseName = $('#warehouseMap option:selected').text() || purchaseOrder.warehouseId;
1016
    var totalQty = $('#totalQuantity').text() || (purchaseOrder.items || []).length;
1017
    var grandTotal = $('#grandTotal').text() || '';
1018
 
1019
    $('#pmscpSumVendor').text(vendorName);
1020
    $('#pmscpSumWarehouse').text(warehouseName);
1021
    $('#pmscpSumItems').text((purchaseOrder.items || []).length + ' line item(s)');
1022
    $('#pmscpSumQty').text(totalQty);
1023
    $('#pmscpSumTotal').text(grandTotal ? '₹ ' + grandTotal : '—');
1024
 
1025
    $('#pmscpConfirmModal').modal('show');
1026
}
1027
 
1028
// Handlers — bind once (safe with delegated `on`).
1029
$(document).on('click', '#pmscpConfirmCreate', function () {
1030
    $('#pmscpConfirmModal').modal('hide');
1031
    // Give Bootstrap a moment to finish the fade-out before firing the AJAX so
1032
    // the loading overlay renders cleanly.
1033
    setTimeout(function () {
1034
        submitCreatePO(window.__pmscpPO);
1035
    }, 200);
1036
});
1037
 
1038
// Live counter on the reason textarea — gates the Continue button.
1039
$(document).on('input change', '#pmscpReasonText', function () {
1040
    var len = $(this).val().trim().length;
1041
    $('#pmscpReasonCount').text(len);
1042
    var ok = len >= PMSCP_MIN_REASON;
1043
    $('#pmscpReasonCounter').toggleClass('pmscp-ok', ok);
1044
    $('#pmscpReasonContinue').prop('disabled', !ok);
1045
});
1046
 
1047
// Continue from reason modal → open approval-target confirm modal.
1048
$(document).on('click', '#pmscpReasonContinue', function () {
1049
    var reason = $('#pmscpReasonText').val().trim();
1050
    if (reason.length < PMSCP_MIN_REASON) return;   // defensive
1051
    window.__pmscpPO.requesterReason = reason;
1052
    $('#pmscpApprovalReasonPreview').text(reason);
1053
    $('#pmscpReasonModal').modal('hide');
1054
    setTimeout(function () {
1055
        $('#pmscpApprovalModal').modal('show');
1056
    }, 250);
1057
});
1058
 
1059
// Back from approval modal → return to reason modal so user can tweak text.
1060
$(document).on('click', '#pmscpApprovalBack', function () {
1061
    $('#pmscpApprovalModal').modal('hide');
1062
    setTimeout(function () {
1063
        $('#pmscpReasonModal').modal('show');
1064
    }, 250);
1065
});
1066
 
1067
// Final confirm → fire the real create request.
1068
$(document).on('click', '#pmscpApprovalConfirm', function () {
1069
    $('#pmscpApprovalModal').modal('hide');
1070
    setTimeout(function () {
1071
        actuallyCreatePO(window.__pmscpPO);
1072
    }, 200);
1073
});
1074
 
1075
// Reset counter every time reason modal opens so a fresh session starts at 0.
1076
$(document).on('shown.bs.modal', '#pmscpReasonModal', function () {
1077
    // Only reset text if we don't already have a saved reason (e.g. user
1078
    // came back via the "Back" button — preserve what they typed).
1079
    if (!window.__pmscpPO || !window.__pmscpPO.requesterReason) {
1080
        $('#pmscpReasonText').val('');
1081
    } else {
1082
        $('#pmscpReasonText').val(window.__pmscpPO.requesterReason);
1083
    }
1084
    $('#pmscpReasonText').trigger('input').focus();
1085
});
1086
 
1087
// Submits the PO create request. Runs a preflight stock-cover check first
1088
// (single always-200 call, no side effects): if the rule fires, opens the
1089
// reason modal → approval-target modal → hits /createPurchaseOrder once with
1090
// the reason included. This avoids the old "submit → 400 → retry" pattern
1091
// that triggered the global "Error occurred" popup on the first response.
1092
function submitCreatePO(purchaseOrder) {
1093
    $.ajax({
1094
        url: context + "/createPurchaseOrder/preflight-stock-check",
1095
        type: "POST",
1096
        contentType: "application/json",
1097
        data: JSON.stringify(purchaseOrder),
1098
        dataType: "json",
1099
        global: false,   // suppress global handlers just in case preflight fails
1100
        success: function (preflight) {
1101
            // Duplicate-guard: same vendor + item already in a pending approval.
1102
            if (preflight && preflight.alreadyInReview) {
1103
                var lines = [];
1104
                for (var k in preflight.conflicts) {
1105
                    if (Object.prototype.hasOwnProperty.call(preflight.conflicts, k)) {
1106
                        var c = preflight.conflicts[k];
1107
                        // Server sends { itemId: { modelName, poNumber } } — support the
1108
                        // old shape { itemId: poNumber } as fallback in case of stale server.
1109
                        var poNumber = (c && typeof c === 'object') ? c.poNumber : c;
1110
                        var modelName = (c && typeof c === 'object' && c.modelName) ? c.modelName : "";
1111
                        var itemLabel = modelName ? (modelName + " #" + k) : ("Item #" + k);
1112
                        lines.push("  " + itemLabel + " → PO " + poNumber);
1113
                    }
1114
                }
1115
                alert(
1116
                    "Cannot create this PO — one or more items are already under review for the same vendor:\n\n" +
1117
                    lines.join("\n") +
1118
                    "\n\nWait for those POs to be approved or rejected first, then try again."
1119
                );
1120
                return;
1121
            }
1122
            if (preflight && preflight.needsApproval && !purchaseOrder.requesterReason) {
1123
                // Populate the "Items requiring approval" table from preflight.flaggedItems
1124
                // BEFORE opening the modal so the requester sees exactly which SKUs and how
1125
                // much aging vs 15d-sold when they compose their reason. Mixed POs (some
1126
                // clean, some aging) show only the aging items here — clean items are not
1127
                // held and not displayed.
1128
                var flagged = (preflight && preflight.flaggedItems) || [];
1129
                var $rows = $('#pmscpFlaggedRows').empty();
1130
                if (flagged.length > 0) {
1131
                    for (var i = 0; i < flagged.length; i++) {
1132
                        var f = flagged[i];
1133
                        var name = f.modelName || ('#' + f.itemId);
1134
                        // If server left "#itemId" as the model name (item lookup failed),
1135
                        // skip the redundant "#itemId" span since the name already carries it.
1136
                        var idSpan = (name.indexOf('#') === 0) ? '' :
1137
                            ' <span style="color:#7b8199;font-size:11px">#' + f.itemId + '</span>';
1138
                        // Excess turns green only when NO aging anywhere in the network.
1139
                        var hasAgingHere = (f.agingQty || 0) > 0;
1140
                        var hasAgingElsewhere = f.agingBreakdown && f.agingBreakdown.length > 0;
1141
                        var excessColor = (!hasAgingHere && !hasAgingElsewhere) ? '#177a3a' : '#c62828';
1142
                        $rows.append(
1143
                            '<tr>' +
1144
                            '<td style="padding:6px 10px;border-bottom:1px solid #f0f2f7">' + escapePmscp(name) + idSpan + '</td>' +
1145
                            '<td style="padding:6px 10px;text-align:right;border-bottom:1px solid #f0f2f7">' + (f.agingQty || 0) + '</td>' +
1146
                            '<td style="padding:6px 10px;text-align:right;border-bottom:1px solid #f0f2f7">' + (f.sold15dQty || 0) + '</td>' +
1147
                            '<td style="padding:6px 10px;text-align:right;border-bottom:1px solid #f0f2f7">' + (f.poQty || 0) + '</td>' +
1148
                            '<td style="padding:6px 10px;text-align:right;border-bottom:1px solid #f0f2f7;color:' + excessColor + ';font-weight:600">+' + (f.excess || 0) + '</td>' +
1149
                            '</tr>'
1150
                        );
1151
                        // Mirror the detail-modal pattern: when this vendor+warehouse has no
1152
                        // aging AND the item has aging elsewhere, render one amber sub-row per
1153
                        // (warehouse, vendor). Shortens "DL-NSSPL/Delhi/BSB Marketing/G" +
1154
                        // "BSB Marketing Private Limited" to "DL-NSSPL - (BSB)" for readability.
1155
                        if (!hasAgingHere && hasAgingElsewhere) {
1156
                            for (var j = 0; j < f.agingBreakdown.length; j++) {
1157
                                var b = f.agingBreakdown[j];
1158
                                var whFull = b.warehouseName || '';
1159
                                var vFull = b.vendorName || '';
1160
                                var whShort = whFull.indexOf('/') >= 0 ? whFull.substring(0, whFull.indexOf('/')) : whFull;
1161
                                var vShort = vFull.indexOf(' ') >= 0 ? vFull.substring(0, vFull.indexOf(' ')) : vFull;
1162
                                $rows.append(
1163
                                    '<tr style="background:#fff9e6;color:#8a6d3b">' +
1164
                                    '<td style="padding:4px 10px 4px 26px;border-bottom:1px solid #f1e0b0;font-size:11px">' +
1165
                                    '<span style="color:#c19c00">&#8627; aging elsewhere:</span> ' +
1166
                                    escapePmscp(whShort) + ' - (' + escapePmscp(vShort) + ')' +
1167
                                    '</td>' +
1168
                                    '<td style="padding:4px 10px;text-align:right;border-bottom:1px solid #f1e0b0;font-size:11px">' + (b.qty || 0) + '</td>' +
1169
                                    '<td colspan="3" style="border-bottom:1px solid #f1e0b0"></td>' +
1170
                                    '</tr>'
1171
                                );
1172
                            }
1173
                        }
1174
                    }
1175
                    $('#pmscpFlaggedCount').text(flagged.length);
1176
                    $('#pmscpFlaggedBox').show();
1177
                } else {
1178
                    // Empty flaggedItems is unexpected when needsApproval=true, but hide
1179
                    // the table gracefully rather than showing an empty box.
1180
                    $('#pmscpFlaggedBox').hide();
1181
                }
1182
                $('#pmscpReasonModal').modal('show');
1183
                return;
1184
            }
1185
            actuallyCreatePO(purchaseOrder);
1186
        },
1187
        error: function () {
1188
            // Preflight failed for a reason unrelated to the rule — attempt
1189
            // the create anyway; server will still enforce the rule if needed.
1190
            actuallyCreatePO(purchaseOrder);
1191
        }
1192
    });
1193
}
1194
 
1195
// The single, actual create request — fires once whether or not approval is needed.
1196
function actuallyCreatePO(purchaseOrder) {
1197
    doPostAjaxRequestWithJsonHandler(context + "/createPurchaseOrder",
1198
        JSON.stringify(purchaseOrder), function (response) {
32352 amit.gupta 1199
            if (response == 'true') {
37750 ranu 1200
                alert("Successfully created");
32352 amit.gupta 1201
                loadCreatePurchase("main-content");
1202
            }
1203
        });
32145 tejbeer 1204
}
1205
 
1206
 
1207
function editPurchase(sendPo, poid) {
32352 amit.gupta 1208
    var editpurchaseOrder = {}
1209
    var items = []
1210
    $("#purchase-edit-lineitem > tbody > tr").each(function () {
1211
        var purchaseOrderJson = {};
1212
        var itemId = $(this).find("td:eq(0)").text();
32145 tejbeer 1213
 
32352 amit.gupta 1214
        var qty = $(this).find("td:eq(2)").text();
32145 tejbeer 1215
 
32352 amit.gupta 1216
        var amendedQty = $(this).find(".editqty").val();
32256 tejbeer 1217
 
32352 amit.gupta 1218
        var transferPrice = $.trim($(this).find(".transferPrice").html());
32256 tejbeer 1219
 
1220
 
32352 amit.gupta 1221
        purchaseOrderJson['itemId'] = itemId;
1222
        purchaseOrderJson['amendedQty'] = parseInt(amendedQty)
1223
        purchaseOrderJson['qty'] = parseInt(qty)
1224
        purchaseOrderJson['transferPrice'] = transferPrice
32145 tejbeer 1225
 
32352 amit.gupta 1226
        items.push(purchaseOrderJson)
1227
    });
32145 tejbeer 1228
 
1229
 
32352 amit.gupta 1230
    for (var i = 0; i < items.length; i++) {
1231
        console.log(items[i])
32145 tejbeer 1232
 
32352 amit.gupta 1233
        var amendedQty = items[i].amendedQty
1234
        var qty = items[i].qty
32145 tejbeer 1235
 
32256 tejbeer 1236
 
32352 amit.gupta 1237
        if (amendedQty === "") {
1238
            alert("please choose qty");
1239
            return false;
1240
        }
32145 tejbeer 1241
 
32352 amit.gupta 1242
        if (amendedQty < qty) {
1243
            alert("Quantity should be greater than existing qty");
1244
            return false;
1245
        }
32145 tejbeer 1246
 
1247
 
32352 amit.gupta 1248
    }
32145 tejbeer 1249
 
32352 amit.gupta 1250
    editpurchaseOrder['purchaseOrderId'] = poid;
1251
    editpurchaseOrder['sendPo'] = sendPo
1252
    editpurchaseOrder['items'] = items
32145 tejbeer 1253
 
1254
 
32352 amit.gupta 1255
    if (confirm("Are you sure you want to edit purchase order") == true) {
32145 tejbeer 1256
 
32352 amit.gupta 1257
        doPostAjaxRequestWithJsonHandler(context
1258
            + "/editPurchaseOrder", JSON
1259
            .stringify(editpurchaseOrder), function (response) {
1260
            if (response == 'true') {
1261
                alert("successfully created");
1262
                $('#warehouseEditPurchaseContainer').modal('hide');
1263
                $('.modal-backdrop').remove();
32295 tejbeer 1264
 
32352 amit.gupta 1265
                loadOpenPurchase("main-content")
1266
            }
1267
        });
1268
    }
32145 tejbeer 1269
 
1270
}
1271
 
1272
 
32192 tejbeer 1273
function getInvoiceItemData(numItems, invoiceId, warehouseId, supplierId, validate) {
1274
 
32352 amit.gupta 1275
    var invoiceJson = {};
1276
    console.log(numItems)
1277
    var totalQty = 0;
1278
    var invoiceItems = []
1279
    $("#invoice-order-table > tbody > tr").each(function () {
1280
        var invoiceItemJson = {};
1281
        var itemId = $(this).find(".rate").data('itemid');
1282
        var qty = $(this).find(".qty").val();
32192 tejbeer 1283
 
32352 amit.gupta 1284
        if (qty != undefined) {
1285
            totalQty += parseInt(qty)
1286
        }
1287
        var rate = $(this).find(".rate").val();
1288
        invoiceItemJson['itemId'] = itemId;
1289
        invoiceItemJson['qty'] = qty
1290
        invoiceItemJson['rate'] = rate
1291
        invoiceItems.push(invoiceItemJson)
1292
    });
32192 tejbeer 1293
 
1294
 
32352 amit.gupta 1295
    for (var i = 0; i < invoiceItems.length; i++) {
32192 tejbeer 1296
 
32352 amit.gupta 1297
        var itemId = invoiceItems[i].itemId
1298
        var qty = invoiceItems[i].qty
1299
        var rate = invoiceItems[i].rate
1300
        if (itemId === "" && qty === "" && rate === "") {
1301
            alert("Field can't be empty");
1302
            return false;
1303
        }
32192 tejbeer 1304
 
32352 amit.gupta 1305
        if (itemId === "") {
1306
            alert("please select item");
1307
            return false;
1308
        }
1309
        if (qty === "") {
1310
            alert("please choose qty");
1311
            return false;
1312
        }
32192 tejbeer 1313
 
32352 amit.gupta 1314
        if (rate === "") {
1315
            alert("Rate can't be empty");
1316
            return false;
1317
        }
32192 tejbeer 1318
 
32352 amit.gupta 1319
    }
32192 tejbeer 1320
 
32352 amit.gupta 1321
    console.log(totalQty)
32192 tejbeer 1322
 
32352 amit.gupta 1323
    if (totalQty > numItems) {
1324
        alert("Qty Should not be more than  Invoice items");
1325
        return false;
1326
    }
32192 tejbeer 1327
 
32352 amit.gupta 1328
    if (validate) {
32192 tejbeer 1329
 
32352 amit.gupta 1330
        if (totalQty != numItems) {
1331
            alert("Qty Should not match with Invoice items");
1332
            return false;
1333
        }
1334
    }
32192 tejbeer 1335
 
1336
 
32352 amit.gupta 1337
    invoiceJson['invoiceId'] = invoiceId;
1338
    invoiceJson['warehouseId'] = warehouseId;
1339
    invoiceJson['supplierId'] = supplierId;
1340
    invoiceJson['invoiceItems'] = invoiceItems
1341
    if (validate) {
1342
        validateInvoiceItems(invoiceJson);
1343
    } else {
1344
        saveInvoiceItems(invoiceJson)
1345
    }
32192 tejbeer 1346
}
1347
 
1348
 
1349
function saveInvoiceItems(invoiceJson) {
1350
 
1351
 
32352 amit.gupta 1352
    if (confirm("Are you sure you want to save invoice item") == true) {
32192 tejbeer 1353
 
32352 amit.gupta 1354
        doPostAjaxRequestWithJsonHandler(context
1355
            + "/invoiceItemDetail", JSON
1356
            .stringify(invoiceJson), function (response) {
1357
            if (response == 'true') {
1358
                getInvoiceItems(invoiceJson.invoiceId);
1359
            }
1360
        });
1361
    }
32192 tejbeer 1362
 
1363
}
1364
 
1365
 
1366
function validateInvoiceItems(invoiceJson) {
1367
 
1368
 
32352 amit.gupta 1369
    if (confirm("Are you sure you want to validate invoice item") == true) {
32192 tejbeer 1370
 
32352 amit.gupta 1371
        doPostAjaxRequestWithJsonHandler(context
1372
            + "/validateInvoiceItemDetail", JSON
1373
            .stringify(invoiceJson), function (response) {
1374
            $('.invoiceadditemcontainer').html(response);
32192 tejbeer 1375
 
32352 amit.gupta 1376
        });
1377
    }
32192 tejbeer 1378
 
1379
}
1380
 
1381
function getOpenPOFromWarehouse() {
1382
 
32352 amit.gupta 1383
    var warehouseId = $('#warehouseMap').val();
1384
    doGetAjaxRequestHandler(context + "/getOpenPurchaseOrderByWarehouseId?warehouseId=" + warehouseId, function (response) {
1385
        $('#warehouseManagePuchaseContainer').html(response);
1386
    });
32192 tejbeer 1387
 
1388
 
1389
}
1390
 
1391
function getPurchaseLineitem(poId) {
1392
 
1393
 
32352 amit.gupta 1394
    doGetAjaxRequestHandler(context + "/getPurchaseOrderItemByPoId?poId=" + poId, function (response) {
1395
        $('#warehouseManagePuchaseItemContainer').html(response);
1396
        $('#warehousepurchaseitemgrn').hide()
1397
    });
32192 tejbeer 1398
 
1399
 
1400
}
1401
 
1402
 
1403
function getInvoiceItems(invoiceId) {
1404
 
32352 amit.gupta 1405
    doGetAjaxRequestHandler(context + "/getInvoiceItems?invoiceId=" + invoiceId, function (response) {
1406
        $('.invoiceadditemcontainer').html(response);
32192 tejbeer 1407
 
32352 amit.gupta 1408
    });
32192 tejbeer 1409
}
1410
 
1411
 
32256 tejbeer 1412
function getGrnRequestItems(requestId, invoiceId) {
32352 amit.gupta 1413
    doGetAjaxRequestHandler(context + "/grnRequestItem?requestId=" + requestId + "&invoiceId=" + invoiceId, function (response) {
1414
        $('.grnRequestItemContainer').html(response);
32256 tejbeer 1415
 
32352 amit.gupta 1416
    });
32256 tejbeer 1417
}
1418
 
32912 amit.gupta 1419
function removeInvoice(invoiceId) {
34047 tejus.loha 1420
    if (confirm(`Are your sure want to delete invoiceId ${invoiceId}`)) {
32912 amit.gupta 1421
        doGetAjaxRequestHandler(`${context}/removeInvoice?invoiceId=${invoiceId}`, function (response) {
34047 tejus.loha 1422
            $('#open-invoices').DataTable().row("#" + invoiceId).remove().draw();
32912 amit.gupta 1423
            alert("Invoice Removed");
1424
        });
1425
    }
1426
}
32256 tejbeer 1427
 
32912 amit.gupta 1428
function removeGrnRequest(invoiceId) {
34047 tejus.loha 1429
    if (confirm(`Are your sure want to remove grn request for invoiceId ${invoiceId}`)) {
32912 amit.gupta 1430
        doGetAjaxRequestHandler(`${context}/removeGrnRequest?invoiceId=${invoiceId}`, function (response) {
1431
            $('#' + domId).html(response);
1432
            alert("Grn Request Removed");
1433
        });
1434
    }
1435
}
1436
 
1437
 
35806 amit 1438
// ============ GRN Correction ============
1439
 
1440
$(document).on('click', '.warehouse-grn-correction', function () {
1441
    loadGrnCorrection("main-content");
1442
});
1443
 
1444
$(document).on('click', '.warehouse-grn-correction-approval', function () {
1445
    loadGrnCorrectionApproval("main-content");
1446
});
1447
 
1448
$(document).on('click', '.searchCorrectionInvoices', function () {
1449
    var startDate = getDatesFromPicker('input[name="correction-duration"]').startDate;
1450
    var endDate = getDatesFromPicker('input[name="correction-duration"]').endDate;
1451
    doGetAjaxRequestHandler(context + "/grnCorrection?startDate=" + startDate + "&endDate=" + endDate, function (response) {
1452
        $('#main-content').html(response);
1453
    });
1454
});
1455
 
1456
$(document).on('click', '.submitGrnCorrection', function () {
1457
    var invoiceId = $(this).data('invoiceid');
1458
    var remarks = $('#correctionRemarks').val();
1459
 
1460
    if (!remarks || remarks.trim() === '') {
1461
        alert("Please enter remarks explaining the reason for correction");
1462
        return false;
1463
    }
1464
 
1465
    // Collect serial number corrections (old → new)
1466
    var corrections = [];
1467
    $('#serial-corrections-table > tbody > tr').each(function () {
1468
        var oldSerial = $(this).find('.old-serial').val();
1469
        var newSerial = $(this).find('.new-serial').val();
1470
 
1471
        if (oldSerial && newSerial && oldSerial.trim() !== '' && newSerial.trim() !== '') {
1472
            corrections.push({
1473
                oldSerialNumber: oldSerial.trim(),
1474
                newSerialNumber: newSerial.trim()
1475
            });
1476
        }
1477
    });
1478
 
35884 amit 1479
    // Collect item corrections (serialized or non-serialized)
35806 amit 1480
    var qtyCorrections = [];
36206 amit 1481
    var imeiCountError = false;
35806 amit 1482
    $('#qty-corrections-table > tbody > tr').each(function () {
1483
        var oldItemId = $(this).find('.qty-old-itemid').val();
1484
        var newItemId = $(this).find('.qty-new-itemid').val();
35884 amit 1485
        var serial = $(this).find('.qty-serial').val();
35806 amit 1486
        var qty = parseInt($(this).find('.qty-correction-val').val());
1487
 
35884 amit 1488
        if (oldItemId && newItemId && serial && serial.trim() !== '') {
36206 amit 1489
            // Split IMEIs by space, comma, or newline
1490
            var imeis = serial.trim().split(/[\s,]+/).filter(function(s) { return s.length > 0; });
1491
            var imeiCount = imeis.length;
1492
 
1493
            // Auto-set qty from IMEI count, validate if qty was manually entered
1494
            if (qty > 0 && qty !== imeiCount) {
1495
                alert("Row error: Qty (" + qty + ") does not match IMEI count (" + imeiCount + ").\nIMEIs: " + imeis.join(", "));
1496
                imeiCountError = true;
1497
                return false;
1498
            }
1499
 
1500
            // Create one entry per IMEI (each with qty=1)
1501
            for (var i = 0; i < imeis.length; i++) {
1502
                qtyCorrections.push({
1503
                    oldItemId: parseInt(oldItemId),
1504
                    newItemId: parseInt(newItemId),
1505
                    qty: 1,
1506
                    serialNumber: imeis[i].trim()
1507
                });
1508
            }
35884 amit 1509
        } else if (oldItemId && newItemId && qty > 0) {
1510
            qtyCorrections.push({
1511
                oldItemId: parseInt(oldItemId),
1512
                newItemId: parseInt(newItemId),
35806 amit 1513
                qty: qty
1514
            });
1515
        }
1516
    });
1517
 
36206 amit 1518
    if (imeiCountError) return false;
1519
 
35806 amit 1520
    if (corrections.length === 0 && qtyCorrections.length === 0) {
1521
        alert("No corrections specified. Please enter serial number or quantity corrections.");
1522
        return false;
1523
    }
1524
 
1525
    var requestModel = {
1526
        invoiceId: invoiceId,
1527
        remarks: remarks,
1528
        corrections: corrections,
1529
        qtyCorrections: qtyCorrections
1530
    };
1531
 
1532
    if (confirm("Are you sure you want to raise this GRN correction request?")) {
1533
        doPostAjaxRequestWithJsonHandler(context + "/raiseGrnCorrection",
1534
            JSON.stringify(requestModel), function (response) {
36299 amit 1535
                var parsed;
1536
                try { parsed = typeof response === 'string' ? JSON.parse(response) : response; }
1537
                catch (e) { parsed = null; }
1538
                if (parsed && parsed.status === true) {
1539
                    if (parsed.autoApproved) {
1540
                        alert("Correction applied successfully (auto-approved: no model/qty change)");
1541
                    } else {
1542
                        alert("Correction request raised for approval");
1543
                    }
35806 amit 1544
                    loadGrnCorrection("main-content");
1545
                }
1546
            });
1547
    }
1548
});
1549
 
1550
$(document).on('click', '.approveGrnCorrectionBtn', function () {
1551
    var requestId = $(this).data('requestid');
1552
    var remarks = $('#approvalRemarks').val();
1553
 
1554
    if (confirm("Are you sure you want to APPROVE this correction request? This will apply the IMEI/qty changes.")) {
1555
        doPostAjaxRequestHandler(context + "/approveGrnCorrection?requestId=" + requestId + "&remarks=" + encodeURIComponent(remarks),
1556
            function (response) {
1557
                if (response == 'true') {
1558
                    alert("Correction approved and applied successfully");
1559
                    loadGrnCorrectionApproval("main-content");
1560
                }
1561
            });
1562
    }
1563
});
1564
 
1565
$(document).on('click', '.rejectGrnCorrectionBtn', function () {
1566
    var requestId = $(this).data('requestid');
1567
    var remarks = $('#approvalRemarks').val();
1568
 
1569
    if (!remarks || remarks.trim() === '') {
1570
        alert("Please enter remarks explaining the reason for rejection");
1571
        return false;
1572
    }
1573
 
1574
    if (confirm("Are you sure you want to REJECT this correction request?")) {
1575
        doPostAjaxRequestHandler(context + "/rejectGrnCorrection?requestId=" + requestId + "&remarks=" + encodeURIComponent(remarks),
1576
            function (response) {
1577
                if (response == 'true') {
1578
                    alert("Correction request rejected");
1579
                    loadGrnCorrectionApproval("main-content");
1580
                }
1581
            });
1582
    }
1583
});
1584
 
1585
function loadGrnCorrection(domId) {
1586
    doGetAjaxRequestHandler(context + "/grnCorrection", function (response) {
1587
        $('#' + domId).html(response);
1588
    });
1589
}
1590
 
1591
function loadGrnCorrectionApproval(domId) {
1592
    doGetAjaxRequestHandler(context + "/grnCorrectionApproval", function (response) {
1593
        $('#' + domId).html(response);
1594
    });
1595
}
1596
 
1597
function loadGrnCorrectionDetail(invoiceId) {
1598
    doGetAjaxRequestHandler(context + "/grnCorrectionDetail?invoiceId=" + invoiceId, function (response) {
1599
        $('.grnCorrectionDetailContainer').html(response);
1600
    });
1601
}
1602
 
1603
function loadGrnCorrectionRequestDetail(requestId) {
1604
    doGetAjaxRequestHandler(context + "/grnCorrectionRequestDetail?requestId=" + requestId, function (response) {
1605
        $('.grnCorrectionRequestDetailContainer').html(response);
1606
    });
1607
}
1608
 
1609
 
37697 amit 1610
 
1611
/**
1612
 * Shows what the sending warehouse can actually release of an item, on the row where a quantity is being typed.
1613
 *
1614
 * Only our own warehouses answer with this; an outside vendor's pricing response carries no availability, and its row
1615
 * is left exactly as it was. Stock that is entirely promised is shown as zero with the orders holding it named, which
1616
 * is what lets someone chase those orders instead of only seeing a smaller number.
1617
 */
1618
function renderMovementAvailability($row, pricing) {
1619
    var $icon = $row.find('.mv-avail-icon');
1620
    if (!pricing || typeof pricing.movableOnThisPo === 'undefined') {
1621
        $icon.hide();
1622
        $row.removeData('movableOnThisPo');
1623
        return;
1624
    }
1625
 
1626
    var cap = pricing.movableOnThisPo;
1627
    $row.data('movableOnThisPo', cap);
1628
 
37723 amit 1629
    // Reads as a sum - in stock + arriving - promised - so the number that can move is never left unexplained.
37699 amit 1630
    var rows = mvAvailLine('In stock', pricing.inStock, '');
37723 amit 1631
    if (pricing.arrivingTotal > 0) {
1632
        rows += mvAvailLine('Arriving (not yet received)', '+ ' + pricing.arrivingTotal, '');
1633
        $.each(pricing.arriving || [], function (i, po) {
1634
            rows += mvAvailLine(mvEscape(po.poNumber) + ' &middot; ' + mvEscape(po.poDate)
1635
                + (po.destination ? ' &larr; ' + mvEscape(po.destination) : ''), po.qty, ' mv-po');
1636
        });
1637
    }
37697 amit 1638
    if (pricing.promisedTotal > 0) {
37723 amit 1639
        rows += mvAvailLine('Promised on open orders', '&minus; ' + pricing.promisedTotal, '');
37697 amit 1640
        $.each(pricing.promised || [], function (i, po) {
37699 amit 1641
            rows += mvAvailLine(mvEscape(po.poNumber) + ' &middot; ' + mvEscape(po.poDate)
1642
                + (po.destination ? ' &rarr; ' + mvEscape(po.destination) : ''), po.qty, ' mv-po');
37697 amit 1643
        });
1644
    }
37699 amit 1645
    rows += mvAvailLine('Can move on this PO', cap, ' mv-total');
37697 amit 1646
 
1647
    var note = '';
1648
    if (pricing.costSplit) {
1649
        note += '<div class="mv-note">' + (pricing.movableAltogether - cap)
1650
            + ' more came in at a different cost &mdash; raise a separate PO for those.</div>';
1651
    }
1652
    if (cap === 0) {
37699 amit 1653
        note += '<div class="mv-note">' + (pricing.promisedTotal > 0
1654
            ? 'Nothing can move until one of the orders above is completed or closed.'
1655
            : 'Nothing can move from here yet.') + '</div>';
37697 amit 1656
    }
1657
 
37699 amit 1658
    $icon.attr('data-mv-content', '<div class="mv-avail">' + rows + '</div>' + note);
37697 amit 1659
    $icon.removeClass('mv-none mv-part');
1660
    if (cap === 0) {
1661
        $icon.addClass('mv-none');
1662
    } else if (pricing.promisedTotal > 0) {
1663
        $icon.addClass('mv-part');
1664
    }
1665
    $icon.show();
1666
 
1667
    $icon.popover('destroy');
1668
    $icon.popover({
1669
        html: true,
1670
        container: 'body',
1671
        placement: 'left',
1672
        trigger: 'hover focus',
1673
        title: 'Stock at ' + mvEscape(pricing.sourceName),
1674
        content: function () {
1675
            return $(this).attr('data-mv-content');
1676
        }
1677
    });
1678
 
1679
    checkMovableQty($row, parseInt($row.find('.qty').val()));
1680
}
1681
 
1682
/** Flags a quantity that the order cannot take, while it is being typed rather than on submit. */
1683
function checkMovableQty($row, qty) {
1684
    var cap = $row.data('movableOnThisPo');
1685
    var $qty = $row.find('.qty');
1686
    var $warn = $row.find('.mv-qty-warn');
1687
 
1688
    if (typeof cap === 'undefined' || isNaN(qty)) {
1689
        $qty.removeClass('mv-over');
1690
        $warn.hide().empty();
1691
        return;
1692
    }
1693
 
1694
    if (qty > cap) {
1695
        $qty.addClass('mv-over');
1696
        $warn.text(cap === 0 ? 'None can move right now' : 'Only ' + cap + ' can move on this PO').show();
1697
    } else {
1698
        $qty.removeClass('mv-over');
1699
        $warn.hide().empty();
1700
    }
1701
}
1702
 
37699 amit 1703
/**
1704
 * One line of the breakdown.
1705
 *
1706
 * Built from divs and spans on purpose: Bootstrap's popover sanitizer whitelists neither tables nor their rows, and
1707
 * strips a non-whitelisted element together with everything inside it - a table here renders as nothing at all.
1708
 */
1709
function mvAvailLine(label, value, extraClass) {
1710
    return '<div class="mv-row' + extraClass + '"><span class="mv-label">' + label
1711
        + '</span><span class="mv-val">' + value + '</span></div>';
37697 amit 1712
}
1713
 
1714
/** Values here are warehouse and order names out of the database, so they are escaped before going into the popover. */
1715
function mvEscape(value) {
1716
    return $('<div/>').text(value === null || typeof value === 'undefined' ? '' : value).html();
1717
}