Subversion Repositories SmartDukaan

Rev

Rev 37723 | Rev 37770 | 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
 
37704 amit 461
    // A movement closed before its stock arrived can be reopened, which restarts its auto-close window.
462
    $(document).on('click', '.reopenPurchaseOrder', function () {
463
        var $button = $(this);
464
        var poId = $button.data('poid');
465
        if (!confirm('Reopen this purchase order so the delayed stock can still be received?')) {
466
            return;
467
        }
468
        doPostAjaxRequestHandler(context + '/reopenPurchaseOrder?purchaseId=' + poId, function (response) {
469
            if (response == 'true') {
470
                alert('Purchase order reopened. It can receive stock again.');
471
                $button.closest('tr').find('td').eq(7).text('READY');
472
                $button.remove();
473
            }
474
        });
475
    });
476
 
32352 amit.gupta 477
    $(document).on('click', '.closePurchaseOrder', function () {
478
        var purchaseOrderId = $(this).data('poid');
479
        if (confirm("Are you sure you want to close the PO") == true) {
480
            doPostAjaxRequestHandler(context + "/closePuchaseOrder?purchaseId=" + purchaseOrderId,
481
                function (response) {
32145 tejbeer 482
 
32352 amit.gupta 483
                    console.log(response);
484
                    if (response == 'true') {
485
                        alert("successfully closed");
486
                        loadOpenPurchase("main-content")
487
                    }
488
                });
489
        }
490
    });
32145 tejbeer 491
 
492
 
32352 amit.gupta 493
    $(document).on('click', '.warehouse-view-purchase-order', function () {
494
        doGetAjaxRequestHandler(context + "/viewPurchaseOrder", function (response) {
495
            $('#' + 'main-content').html(response);
496
        });
497
    });
32145 tejbeer 498
 
499
 
32352 amit.gupta 500
    $(document).on('click', '.dateWisePo', function () {
32145 tejbeer 501
 
32352 amit.gupta 502
        var startDate = getDatesFromPicker('input[name="duration"]').startDate;
33729 ranu 503
        var endDate = getDatesFromPicker('input[name="duration"]').endDate;
32145 tejbeer 504
 
505
 
32352 amit.gupta 506
        doGetAjaxRequestHandler(context + "/getPurchaseOrders?startDate=" + startDate + "&endDate=" + endDate, function (response) {
507
            $('.purchaseorderviewcontainer').html(response);
32145 tejbeer 508
 
32352 amit.gupta 509
        });
32145 tejbeer 510
 
511
 
32352 amit.gupta 512
    });
32145 tejbeer 513
 
514
 
32352 amit.gupta 515
    $(document).on('click', '.viewPurchaseOrderlineItem', function () {
516
        var purchaseOrderId = $(this).data('poid');
32145 tejbeer 517
 
32352 amit.gupta 518
        doGetAjaxRequestHandler(context + "/getWarehouseLineItemByPurchaseId?purchaseId=" + purchaseOrderId, function (response) {
519
            $('#warehouseLineItem .modal-content').html(response);
32145 tejbeer 520
 
32352 amit.gupta 521
        });
522
    });
32145 tejbeer 523
 
524
 
32352 amit.gupta 525
    $(document).on("click", '.removeInPurchaseOrder', function () {
526
        var row = $(this).closest("tr");
32361 amit.gupta 527
        let itemId = row.find('.transferPrice').data('itemid');
32360 amit.gupta 528
        let itemIndex = purchaseItemIds.indexOf(itemId);
32352 amit.gupta 529
        if (itemIndex > -1) { // only splice array when item is found
530
            purchaseItemIds.splice(itemIndex, 1); // 2nd parameter means remove one item only
531
        }
532
        row.remove();
533
    });
32192 tejbeer 534
 
535
 
32352 amit.gupta 536
    $(document).on('click', ".addRowForInvoiceItem", function () {
32145 tejbeer 537
 
32352 amit.gupta 538
        var numitems = $(this).data("numitems");
539
        var invoiceId = $(this).data("invoiceid");
540
        var invoiceItemIds = [];
32360 amit.gupta 541
        var totalQty = 0;
32145 tejbeer 542
 
32352 amit.gupta 543
        $("#invoice-order-table > tbody > tr").each(function () {
544
            var itemId = $(this).find(".rate").data('itemid');
545
            var qty = $(this).find(".qty").val();
32145 tejbeer 546
 
32360 amit.gupta 547
            if (qty !== undefined) {
548
                totalQty += qty;
32352 amit.gupta 549
            }
32145 tejbeer 550
 
32360 amit.gupta 551
            if (itemId !== undefined) {
552
                invoiceItemIds.push(itemId);
32352 amit.gupta 553
            }
554
        });
32145 tejbeer 555
 
32352 amit.gupta 556
        var $html = $('<tr>  <td>  <input type="text" class="form-control typeaheaditem"   autocomplete="off"  placeholder="Search Model"/> </td>' +
557
            '<td>  <input type="number" class="form-control qty"  name = "qty" placeholder="Quantity"/> </td>' +
32364 amit.gupta 558
            '<td>  <input type="number" class="form-control rate" placeholder="Rate"/> </td>' +
32352 amit.gupta 559
            '<td> <input class="form-control btn btn-primary removeInInvoiceItem" type="button" value="Remove"></td>  </tr> ');
32145 tejbeer 560
 
561
 
32352 amit.gupta 562
        getItemAheadOptions($html.find('.typeaheaditem'), true, function (
563
            selectedItem) {
564
            var itemId = selectedItem.itemId;
565
            if (invoiceItemIds.indexOf(itemId) > -1) {
566
                alert("Item already added");
567
                $html.find('.typeaheaditem').val("")
32145 tejbeer 568
 
32352 amit.gupta 569
                return false;
570
            }
571
            $html.find('.rate').data('itemid', itemId)
32145 tejbeer 572
 
32352 amit.gupta 573
            $html.find('.removeInInvoiceItem').data('invoiceid', invoiceId)
574
            $html.find('.removeInInvoiceItem').data('itemid', itemId)
32145 tejbeer 575
 
37564 amit 576
        }, true);
32145 tejbeer 577
 
32192 tejbeer 578
 
32352 amit.gupta 579
        if (totalQty < numitems) {
32192 tejbeer 580
 
32352 amit.gupta 581
            $('#invoice-order-table tbody').append($html);
582
        }
32192 tejbeer 583
 
32352 amit.gupta 584
    });
32256 tejbeer 585
 
32192 tejbeer 586
 
32352 amit.gupta 587
    $(document).on('click', '.saveInvoiceDetail', function () {
32192 tejbeer 588
 
32352 amit.gupta 589
        var numItems = $(this).data("numitems");
590
        var invoiceId = $(this).data("invoiceid");
591
        var warehouseId = $(this).data("warehouseid");
592
        var supplierId = $(this).data("supplierid");
593
        getInvoiceItemData(numItems, invoiceId, warehouseId, supplierId, false);
32192 tejbeer 594
 
32352 amit.gupta 595
    });
32192 tejbeer 596
 
597
 
32352 amit.gupta 598
    $(document).on('click', '.validateInvoiceDetail', function () {
599
        var numItems = $(this).data("numitems");
600
        var invoiceId = $(this).data("invoiceid");
601
        var warehouseId = $(this).data("warehouseid");
602
        var supplierId = $(this).data("supplierid");
32192 tejbeer 603
 
32352 amit.gupta 604
        getInvoiceItemData(numItems, invoiceId, warehouseId, supplierId, true);
32192 tejbeer 605
 
32352 amit.gupta 606
    });
32192 tejbeer 607
 
608
 
32352 amit.gupta 609
    $(document).on("click", '.removeInInvoiceItem', function () {
32192 tejbeer 610
 
32352 amit.gupta 611
        var row = $(this).closest("tr");
612
        var invoiceId = $(this).data("invoiceid");
613
        var itemId = $(this).data("itemid");
614
        if (invoiceId != undefined && itemId != undefined) {
615
            doDeleteAjaxRequestHandler(context + "/removeInvoiceItem?invoiceId="
616
                + invoiceId + "&itemId=" + itemId, function (response) {
617
                if (response == "true") {
618
                    alert("Item removed successfully");
32192 tejbeer 619
 
32352 amit.gupta 620
                }
621
            });
622
        }
32192 tejbeer 623
 
32352 amit.gupta 624
        row.remove();
32192 tejbeer 625
 
32352 amit.gupta 626
    });
32192 tejbeer 627
 
628
 
32352 amit.gupta 629
    $(document).on('click', '.purchaseGrn', function () {
32192 tejbeer 630
 
32352 amit.gupta 631
        var grnItemArray = [];
32192 tejbeer 632
 
32352 amit.gupta 633
        var invoiceId = $(this).data("invoiceid");
32192 tejbeer 634
 
32352 amit.gupta 635
        $("#invoice-purchase-validate > tbody > tr").each(function () {
636
            var grnItemJson = {};
32192 tejbeer 637
 
32352 amit.gupta 638
            var itemId = $(this).find(".itemId").text();
639
            var qty = $(this).find(".qty").text();
640
            var poId = $(this).find(".purchaseId").text();
641
            var excessQty = $(this).find(".excessQty").text();
642
            var itemType = $(this).find(".itemType").text();
32192 tejbeer 643
 
32352 amit.gupta 644
            console.log(itemType);
32192 tejbeer 645
 
32352 amit.gupta 646
            if (itemType == "Serialized") {
647
                var serialNumbers = $(this).find(".imeis-to-grn").tagsinput('items');
32366 amit.gupta 648
                grnItemJson['serialNumbers'] = serialNumbers;
32192 tejbeer 649
 
32352 amit.gupta 650
                if (excessQty > 0) {
651
                    var returnSerialNumbers = $(this).find(".imeis-to-grn-return").tagsinput('items');
652
                    grnItemJson['returnSerialNumbers'] = returnSerialNumbers
653
                }
654
            }
32366 amit.gupta 655
            console.log(serialNumbers);
32352 amit.gupta 656
            grnItemJson['itemId'] = itemId;
657
            grnItemJson['serialNumbers'] = serialNumbers
658
            grnItemJson['qty'] = qty
659
            grnItemJson['poId'] = poId
660
            grnItemJson['invoiceId'] = invoiceId
661
            grnItemJson['itemType'] = itemType
662
            grnItemJson['excessQty'] = excessQty
32192 tejbeer 663
 
32352 amit.gupta 664
            grnItemJson['returnSerialNumbers'] = returnSerialNumbers
32192 tejbeer 665
 
32352 amit.gupta 666
            grnItemArray.push(grnItemJson)
32192 tejbeer 667
 
32352 amit.gupta 668
            console.log(grnItemArray)
32192 tejbeer 669
 
32352 amit.gupta 670
        });
32192 tejbeer 671
 
32352 amit.gupta 672
        for (var i = 0; i < grnItemArray.length; i++) {
32366 amit.gupta 673
            var itemType = grnItemArray[i].itemType;
32192 tejbeer 674
 
32352 amit.gupta 675
            if (itemType == "Serialized") {
676
                var excessQty = grnItemArray[i].excessQty
32192 tejbeer 677
 
678
 
32352 amit.gupta 679
                var serialNumbers = grnItemArray[i].serialNumbers.length
680
                var qty = grnItemArray[i].qty
32192 tejbeer 681
 
32352 amit.gupta 682
                if (serialNumbers != qty) {
683
                    alert("serial number is not matched with qty")
684
                    return false;
685
                }
32192 tejbeer 686
 
32352 amit.gupta 687
                if (excessQty > 0) {
32192 tejbeer 688
 
32352 amit.gupta 689
                    var returnSerialNumbers = grnItemArray[i].returnSerialNumbers.length
32192 tejbeer 690
 
32352 amit.gupta 691
                    if (returnSerialNumbers != excessQty) {
692
                        alert("Return serial number is not matched with excess qty")
693
                        return false;
694
                    }
32192 tejbeer 695
 
32352 amit.gupta 696
                }
697
            }
32192 tejbeer 698
 
32352 amit.gupta 699
        }
32192 tejbeer 700
 
701
 
32352 amit.gupta 702
        console.log(JSON.stringify(grnItemArray))
703
        if (confirm("Are you sure you want to grn purchase order") == true) {
32192 tejbeer 704
 
32352 amit.gupta 705
            doPostAjaxRequestWithJsonHandler(context
706
                + "/createGrn", JSON
707
                .stringify(grnItemArray), function (response) {
708
                if (response == 'true') {
709
                    alert("successfully done");
710
                    loadNewReceiveInvoice("main-content");
711
                }
712
            });
713
        }
32192 tejbeer 714
 
715
 
32352 amit.gupta 716
    });
32256 tejbeer 717
 
718
 
32352 amit.gupta 719
    $(document).on('click', '.grnRequest', function () {
32192 tejbeer 720
 
32352 amit.gupta 721
        var grnRequestJson = {};
722
        var grnRequestItemArray = [];
32192 tejbeer 723
 
32352 amit.gupta 724
        var invoiceId = $(this).data("invoiceid");
32192 tejbeer 725
 
726
 
32352 amit.gupta 727
        $("#invoice-purchase-validate > tbody > tr").each(function () {
728
            var grnItemJson = {};
32192 tejbeer 729
 
32352 amit.gupta 730
            var itemId = $.trim($(this).find(".itemId").text());
731
            var poId = $.trim($(this).find(".purchaseId").text());
32192 tejbeer 732
 
32352 amit.gupta 733
            var qty = parseInt($(this).find(".qty").text());
32256 tejbeer 734
 
32352 amit.gupta 735
            var excessQty = parseInt($(this).find(".excessQty").text());
32256 tejbeer 736
 
32352 amit.gupta 737
            var priceMismatch = $.trim($(this).find(".priceMismatch").text());
738
            console.log(priceMismatch)
32256 tejbeer 739
 
740
 
32354 amit.gupta 741
            if (priceMismatch !== "" || excessQty > 0) {
32352 amit.gupta 742
                console.log(typeof priceMismatch)
743
                console.log(excessQty)
744
                grnItemJson['itemId'] = itemId;
745
                grnItemJson['qty'] = qty;
746
                grnItemJson['excessQty'] = excessQty
32376 amit.gupta 747
                if (priceMismatch === '') {
748
                    grnItemJson['mismatch'] = 'QtyMismatch';
749
                } else {
750
                    grnItemJson['mismatch'] = priceMismatch
751
                }
32352 amit.gupta 752
                grnItemJson['poId'] = poId
32192 tejbeer 753
 
32352 amit.gupta 754
                grnRequestItemArray.push(grnItemJson)
755
            }
756
        });
32256 tejbeer 757
 
32352 amit.gupta 758
        console.log(grnRequestItemArray)
32256 tejbeer 759
 
760
 
32352 amit.gupta 761
        grnRequestJson['invoiceId'] = invoiceId;
762
        grnRequestJson['warehousePurchaseModel'] = grnRequestItemArray
32256 tejbeer 763
 
32366 amit.gupta 764
        if (confirm("Are you sure you want to raise grn request")) {
32192 tejbeer 765
 
32352 amit.gupta 766
            doPostAjaxRequestWithJsonHandler(context
767
                + "/grnRequest", JSON
768
                .stringify(grnRequestJson), function (response) {
769
                if (response == 'true') {
770
                    alert("successfully done");
771
                    loadNewReceiveInvoice("main-content");
772
                }
773
            });
774
        }
32192 tejbeer 775
 
776
 
32352 amit.gupta 777
    });
32192 tejbeer 778
 
32256 tejbeer 779
 
32352 amit.gupta 780
    $(document).on('click', '.resolvedPriceMismatchRequest', function () {
781
        var id = $(this).data("id");
32256 tejbeer 782
 
32352 amit.gupta 783
        var invoiceId = $(this).data("invoiceid");
32256 tejbeer 784
 
32352 amit.gupta 785
        var requestId = $(this).data("requestid");
32256 tejbeer 786
 
32352 amit.gupta 787
        var mismatch = $(this).data("mismatch");
32256 tejbeer 788
 
32352 amit.gupta 789
        if (mismatch == "InvoiceMismatch") {
32485 amit.gupta 790
            if (confirm("Are you sure you want to resolve invoice mismatch")) {
32352 amit.gupta 791
                doGetAjaxRequestHandler(context + "/resolvedMismatchRequest?id=" + id, function (response) {
792
                    if (response == 'true') {
793
                        getGrnRequestItems(requestId, invoiceId)
794
                    }
795
                });
32256 tejbeer 796
 
32352 amit.gupta 797
            }
798
        } else if (mismatch == "PoMismatch") {
37707 amit 799
            // Say what the replacement PO is for and what to do if it closes before the stock lands, rather than
800
            // leaving someone to discover that a GRN has quietly stopped matching.
801
            if (confirm("Resolve this price mismatch?\n\nThe current PO line is discarded and a replacement "
802
                    + "purchase order is raised on the invoice date at the corrected price. This invoice is then "
803
                    + "received against that PO.\n\nIt closes automatically after 4 days for a warehouse movement, "
804
                    + "6 for a vendor order. A movement that closes before its stock arrives can be reopened from "
805
                    + "Purchase Orders; a vendor order cannot, and needs a fresh PO.") == true) {
32256 tejbeer 806
 
32352 amit.gupta 807
                doGetAjaxRequestHandler(context + "/resolvedMismatchRequest?id=" + id, function (response) {
808
                    if (response == 'true') {
809
                        getGrnRequestItems(requestId, invoiceId)
810
                    }
811
                });
32256 tejbeer 812
 
32352 amit.gupta 813
            }
814
        }
32256 tejbeer 815
 
32352 amit.gupta 816
    });
32256 tejbeer 817
 
818
 
32352 amit.gupta 819
    $(document).on('click', '.resolvedQtyMismatchRequest', function () {
820
        var id = $(this).data("id");
821
        var invoiceId = $(this).data("invoiceid");
822
        var requestId = $(this).data("requestid");
32256 tejbeer 823
 
824
 
32352 amit.gupta 825
        var mismatch = $(this).data("mismatch");
32256 tejbeer 826
 
32352 amit.gupta 827
        var $row = $(this).closest("tr");
828
        var requiredQty = $row.find(".requiredQty").val();
32256 tejbeer 829
 
32352 amit.gupta 830
        console.log(requiredQty);
32256 tejbeer 831
 
32352 amit.gupta 832
        if (mismatch == "QtyMismatch") {
833
            if (confirm("Are you sure you want to resolve qty mismatch") == true) {
32256 tejbeer 834
 
32352 amit.gupta 835
                doGetAjaxRequestHandler(context + "/resolvedMismatchRequest?id=" + id + "&requiredQty=" + requiredQty, function (response) {
836
                    if (response == 'true') {
837
                        getGrnRequestItems(requestId, invoiceId)
838
                    }
839
                });
32256 tejbeer 840
 
32352 amit.gupta 841
            }
842
        }
32256 tejbeer 843
 
32352 amit.gupta 844
    });
32256 tejbeer 845
 
32192 tejbeer 846
 
32145 tejbeer 847
});
848
 
849
function loadCreatePurchase(domId) {
32352 amit.gupta 850
    doGetAjaxRequestHandler(context + "/warehousePurchaseOrder", function (response) {
851
        $('#' + domId).html(response);
852
    });
32145 tejbeer 853
}
854
 
32192 tejbeer 855
 
32145 tejbeer 856
function loadOpenPurchase(domId) {
857
 
32352 amit.gupta 858
    doGetAjaxRequestHandler(context + "/getOpenPurchaseOrder", function (response) {
859
        $('#' + domId).html(response);
860
    });
32145 tejbeer 861
}
862
 
32192 tejbeer 863
function loadNewReceiveInvoice(domId) {
32352 amit.gupta 864
    doGetAjaxRequestHandler(context + "/newReceiveInvoice", function (response) {
865
        $('#' + domId).html(response);
866
    });
32192 tejbeer 867
}
868
 
32256 tejbeer 869
 
870
function loadGrnRequest(domId) {
32352 amit.gupta 871
    doGetAjaxRequestHandler(context + "/grnRequest", function (response) {
872
        $('#' + domId).html(response);
873
    });
32256 tejbeer 874
}
875
 
876
function loadDebitNote(domId) {
32352 amit.gupta 877
    doGetAjaxRequestHandler(context + "/getDebitNote", function (response) {
878
        $('#' + domId).html(response);
879
    });
32256 tejbeer 880
}
881
 
33729 ranu 882
$(document).on('click', '.dateWiseDebitNote', function () {
883
 
884
    var startDate = getDatesFromPicker('input[name="date-duration"]').startDate;
885
    var endDate = getDatesFromPicker('input[name="date-duration"]').endDate;
886
 
887
 
888
    doGetAjaxRequestHandler(context + "/getDateWiseDebitNote?startDate=" + startDate + "&endDate=" + endDate, function (response) {
889
        $('#warehouse-datewise-debitnote-container').html(response);
890
 
891
    });
892
});
893
 
894
$(document).on('click', '.generateVendorDebitNoteExcel', function () {
895
    var startDate = getDatesFromPicker('input[name="date-duration"]').startDate;
896
    var endDate = getDatesFromPicker('input[name="date-duration"]').endDate;
33809 ranu 897
    doAjaxGetDownload(context + "/generateVendorDebitNoteExcel?startDate=" + startDate + "&endDate=" + endDate, "VendorDebitNoteReport.csv");
33729 ranu 898
});
899
 
32300 tejbeer 900
function loadWarehouseInvoices(domId) {
32352 amit.gupta 901
    doGetAjaxRequestHandler(context + "/getWarehouseInvoices", function (response) {
902
        $('#' + domId).html(response);
903
    });
32300 tejbeer 904
}
905
 
37750 ranu 906
// Loads the PO stock-cover approvals queue into the main content pane.
907
// Access is server-gated (403-ish empty view if the caller isn't an approver).
908
function loadPoStockApprovals(domId) {
909
    doGetAjaxRequestHandler(context + "/po/stock-approvals", function (response) {
910
        $('#' + domId).html(response);
911
    });
912
}
913
 
32390 amit.gupta 914
function createPO(sendPo) {
32352 amit.gupta 915
    var purchaseOrder = {};
32145 tejbeer 916
 
32352 amit.gupta 917
    var vendorId = $('#vendorId').val();
32145 tejbeer 918
 
32352 amit.gupta 919
    var warehouseId = $('#warehouseMap').val();
32145 tejbeer 920
 
32390 amit.gupta 921
    var poDate = $('#poDate').val();
32145 tejbeer 922
 
32390 amit.gupta 923
 
32352 amit.gupta 924
    var items = []
925
    $("table > tbody > tr").each(function () {
926
        var purchaseOrderJson = {};
32145 tejbeer 927
 
32352 amit.gupta 928
        var itemId = $(this).find(".transferPrice").data('itemid');
929
        var qty = $(this).find(".qty").val();
930
        var transferPrice = $(this).find(".transferPrice").val();
931
        var totalValue = $(this).find(".totalValue").val();
32145 tejbeer 932
 
933
 
32352 amit.gupta 934
        purchaseOrderJson['itemId'] = itemId;
935
        purchaseOrderJson['amendedQty'] = qty
936
        purchaseOrderJson['totalValue'] = totalValue
937
        purchaseOrderJson['transferPrice'] = transferPrice
32145 tejbeer 938
 
32352 amit.gupta 939
        items.push(purchaseOrderJson)
940
    });
32145 tejbeer 941
 
942
 
32352 amit.gupta 943
    for (var i = 0; i < items.length; i++) {
944
        console.log(items[i])
32145 tejbeer 945
 
32352 amit.gupta 946
        var itemId = items[i].itemId
947
        var qty = items[i].amendedQty
948
        var transferPrice = items[i].transferPrice
949
        var totalValue = items[i].totalValue
32145 tejbeer 950
 
32352 amit.gupta 951
        if (itemId === "" && qty === "" && transferPrice === "" && totalValue === "") {
952
            alert("Field can't be empty");
953
            return false;
954
        }
32145 tejbeer 955
 
956
 
32352 amit.gupta 957
        if (itemId === "") {
958
            alert("please select item");
959
            return false;
960
        }
961
        if (qty === "") {
962
            alert("please choose qty");
963
            return false;
964
        }
32145 tejbeer 965
 
32352 amit.gupta 966
        if (transferPrice === "") {
967
            alert("Transfer Price can't be empty");
968
            return false;
969
        }
970
        if (totalValue === "") {
971
            alert("Total value can't be empty");
972
            return false;
973
        }
32145 tejbeer 974
 
32352 amit.gupta 975
        if (qty <= 0) {
976
            alert("Please fill Qty");
977
            return false;
978
        }
32145 tejbeer 979
 
980
 
32352 amit.gupta 981
    }
32261 tejbeer 982
 
37723 amit 983
    // Rows typed by hand and rows filled from a bulk upload are checked alike: the screen is where the order is made.
984
    var overCap = [];
985
    $("table > tbody > tr").each(function () {
986
        if ($(this).find('.qty').hasClass('mv-over')) {
987
            overCap.push($(this).find('.typeaheaditem').val() + ': ' + $(this).find('.mv-qty-warn').text());
988
        }
989
    });
990
    if (overCap.length > 0) {
991
        alert("Reduce these quantities before creating the PO:\n\n" + overCap.join("\n"));
992
        return false;
993
    }
994
 
32352 amit.gupta 995
    purchaseOrder['vendorId'] = vendorId;
996
    purchaseOrder['warehouseId'] = warehouseId
997
    purchaseOrder['sendPo'] = sendPo
32390 amit.gupta 998
    purchaseOrder['poDate'] = poDate;
32352 amit.gupta 999
    purchaseOrder['items'] = items
32145 tejbeer 1000
 
32352 amit.gupta 1001
    console.log(purchaseOrder)
32145 tejbeer 1002
 
37750 ranu 1003
    // Modal 1 (pmscp) replaces the old native `confirm`. Populate the summary
1004
    // tiles from what the user actually entered, then hand off to the button
1005
    // handler wired in $(document).on('click', '#pmscpConfirmCreate', ...).
1006
    openPmscpCreateConfirm(purchaseOrder);
1007
}
32145 tejbeer 1008
 
37750 ranu 1009
// ─────────────────────────────────────────────────────────────────────────────
1010
// PO-create modal stack — three sequenced modals replace the old native
1011
// confirm/prompt/alert popups:
1012
//   1) #pmscpConfirmModal       — "Are you sure you want to create this PO?"
1013
//   2) #pmscpReasonModal        — reason textarea + live 50-char counter
1014
//                                 (only when preflight says approval is needed)
1015
//   3) #pmscpApprovalModal      — final "Sending to Niranjan Kala · L4" confirm
1016
// The pending purchaseOrder object rides on window.__pmscpPO between modals.
1017
// ─────────────────────────────────────────────────────────────────────────────
1018
var PMSCP_MIN_REASON = 50;
32145 tejbeer 1019
 
37750 ranu 1020
// Minimal HTML escape for values injected into modal markup (item names from server).
1021
function escapePmscp(s) {
1022
    if (s === null || s === undefined) return '';
1023
    return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
1024
        .replace(/"/g, '&quot;').replace(/'/g, '&#39;');
1025
}
1026
 
1027
function openPmscpCreateConfirm(purchaseOrder) {
1028
    window.__pmscpPO = purchaseOrder;
1029
 
1030
    // Populate summary tiles from the form + purchaseOrder payload.
1031
    var vendorName = $('#vendorId option:selected').text() || purchaseOrder.vendorId;
1032
    var warehouseName = $('#warehouseMap option:selected').text() || purchaseOrder.warehouseId;
1033
    var totalQty = $('#totalQuantity').text() || (purchaseOrder.items || []).length;
1034
    var grandTotal = $('#grandTotal').text() || '';
1035
 
1036
    $('#pmscpSumVendor').text(vendorName);
1037
    $('#pmscpSumWarehouse').text(warehouseName);
1038
    $('#pmscpSumItems').text((purchaseOrder.items || []).length + ' line item(s)');
1039
    $('#pmscpSumQty').text(totalQty);
1040
    $('#pmscpSumTotal').text(grandTotal ? '₹ ' + grandTotal : '—');
1041
 
1042
    $('#pmscpConfirmModal').modal('show');
1043
}
1044
 
1045
// Handlers — bind once (safe with delegated `on`).
1046
$(document).on('click', '#pmscpConfirmCreate', function () {
1047
    $('#pmscpConfirmModal').modal('hide');
1048
    // Give Bootstrap a moment to finish the fade-out before firing the AJAX so
1049
    // the loading overlay renders cleanly.
1050
    setTimeout(function () {
1051
        submitCreatePO(window.__pmscpPO);
1052
    }, 200);
1053
});
1054
 
1055
// Live counter on the reason textarea — gates the Continue button.
1056
$(document).on('input change', '#pmscpReasonText', function () {
1057
    var len = $(this).val().trim().length;
1058
    $('#pmscpReasonCount').text(len);
1059
    var ok = len >= PMSCP_MIN_REASON;
1060
    $('#pmscpReasonCounter').toggleClass('pmscp-ok', ok);
1061
    $('#pmscpReasonContinue').prop('disabled', !ok);
1062
});
1063
 
1064
// Continue from reason modal → open approval-target confirm modal.
1065
$(document).on('click', '#pmscpReasonContinue', function () {
1066
    var reason = $('#pmscpReasonText').val().trim();
1067
    if (reason.length < PMSCP_MIN_REASON) return;   // defensive
1068
    window.__pmscpPO.requesterReason = reason;
1069
    $('#pmscpApprovalReasonPreview').text(reason);
1070
    $('#pmscpReasonModal').modal('hide');
1071
    setTimeout(function () {
1072
        $('#pmscpApprovalModal').modal('show');
1073
    }, 250);
1074
});
1075
 
1076
// Back from approval modal → return to reason modal so user can tweak text.
1077
$(document).on('click', '#pmscpApprovalBack', function () {
1078
    $('#pmscpApprovalModal').modal('hide');
1079
    setTimeout(function () {
1080
        $('#pmscpReasonModal').modal('show');
1081
    }, 250);
1082
});
1083
 
1084
// Final confirm → fire the real create request.
1085
$(document).on('click', '#pmscpApprovalConfirm', function () {
1086
    $('#pmscpApprovalModal').modal('hide');
1087
    setTimeout(function () {
1088
        actuallyCreatePO(window.__pmscpPO);
1089
    }, 200);
1090
});
1091
 
1092
// Reset counter every time reason modal opens so a fresh session starts at 0.
1093
$(document).on('shown.bs.modal', '#pmscpReasonModal', function () {
1094
    // Only reset text if we don't already have a saved reason (e.g. user
1095
    // came back via the "Back" button — preserve what they typed).
1096
    if (!window.__pmscpPO || !window.__pmscpPO.requesterReason) {
1097
        $('#pmscpReasonText').val('');
1098
    } else {
1099
        $('#pmscpReasonText').val(window.__pmscpPO.requesterReason);
1100
    }
1101
    $('#pmscpReasonText').trigger('input').focus();
1102
});
1103
 
1104
// Submits the PO create request. Runs a preflight stock-cover check first
1105
// (single always-200 call, no side effects): if the rule fires, opens the
1106
// reason modal → approval-target modal → hits /createPurchaseOrder once with
1107
// the reason included. This avoids the old "submit → 400 → retry" pattern
1108
// that triggered the global "Error occurred" popup on the first response.
1109
function submitCreatePO(purchaseOrder) {
1110
    $.ajax({
1111
        url: context + "/createPurchaseOrder/preflight-stock-check",
1112
        type: "POST",
1113
        contentType: "application/json",
1114
        data: JSON.stringify(purchaseOrder),
1115
        dataType: "json",
1116
        global: false,   // suppress global handlers just in case preflight fails
1117
        success: function (preflight) {
1118
            // Duplicate-guard: same vendor + item already in a pending approval.
1119
            if (preflight && preflight.alreadyInReview) {
1120
                var lines = [];
1121
                for (var k in preflight.conflicts) {
1122
                    if (Object.prototype.hasOwnProperty.call(preflight.conflicts, k)) {
1123
                        var c = preflight.conflicts[k];
1124
                        // Server sends { itemId: { modelName, poNumber } } — support the
1125
                        // old shape { itemId: poNumber } as fallback in case of stale server.
1126
                        var poNumber = (c && typeof c === 'object') ? c.poNumber : c;
1127
                        var modelName = (c && typeof c === 'object' && c.modelName) ? c.modelName : "";
1128
                        var itemLabel = modelName ? (modelName + " #" + k) : ("Item #" + k);
1129
                        lines.push("  " + itemLabel + " → PO " + poNumber);
1130
                    }
1131
                }
1132
                alert(
1133
                    "Cannot create this PO — one or more items are already under review for the same vendor:\n\n" +
1134
                    lines.join("\n") +
1135
                    "\n\nWait for those POs to be approved or rejected first, then try again."
1136
                );
1137
                return;
1138
            }
1139
            if (preflight && preflight.needsApproval && !purchaseOrder.requesterReason) {
1140
                // Populate the "Items requiring approval" table from preflight.flaggedItems
1141
                // BEFORE opening the modal so the requester sees exactly which SKUs and how
1142
                // much aging vs 15d-sold when they compose their reason. Mixed POs (some
1143
                // clean, some aging) show only the aging items here — clean items are not
1144
                // held and not displayed.
1145
                var flagged = (preflight && preflight.flaggedItems) || [];
1146
                var $rows = $('#pmscpFlaggedRows').empty();
1147
                if (flagged.length > 0) {
1148
                    for (var i = 0; i < flagged.length; i++) {
1149
                        var f = flagged[i];
1150
                        var name = f.modelName || ('#' + f.itemId);
1151
                        // If server left "#itemId" as the model name (item lookup failed),
1152
                        // skip the redundant "#itemId" span since the name already carries it.
1153
                        var idSpan = (name.indexOf('#') === 0) ? '' :
1154
                            ' <span style="color:#7b8199;font-size:11px">#' + f.itemId + '</span>';
1155
                        // Excess turns green only when NO aging anywhere in the network.
1156
                        var hasAgingHere = (f.agingQty || 0) > 0;
1157
                        var hasAgingElsewhere = f.agingBreakdown && f.agingBreakdown.length > 0;
1158
                        var excessColor = (!hasAgingHere && !hasAgingElsewhere) ? '#177a3a' : '#c62828';
1159
                        $rows.append(
1160
                            '<tr>' +
1161
                            '<td style="padding:6px 10px;border-bottom:1px solid #f0f2f7">' + escapePmscp(name) + idSpan + '</td>' +
1162
                            '<td style="padding:6px 10px;text-align:right;border-bottom:1px solid #f0f2f7">' + (f.agingQty || 0) + '</td>' +
1163
                            '<td style="padding:6px 10px;text-align:right;border-bottom:1px solid #f0f2f7">' + (f.sold15dQty || 0) + '</td>' +
1164
                            '<td style="padding:6px 10px;text-align:right;border-bottom:1px solid #f0f2f7">' + (f.poQty || 0) + '</td>' +
1165
                            '<td style="padding:6px 10px;text-align:right;border-bottom:1px solid #f0f2f7;color:' + excessColor + ';font-weight:600">+' + (f.excess || 0) + '</td>' +
1166
                            '</tr>'
1167
                        );
1168
                        // Mirror the detail-modal pattern: when this vendor+warehouse has no
1169
                        // aging AND the item has aging elsewhere, render one amber sub-row per
1170
                        // (warehouse, vendor). Shortens "DL-NSSPL/Delhi/BSB Marketing/G" +
1171
                        // "BSB Marketing Private Limited" to "DL-NSSPL - (BSB)" for readability.
1172
                        if (!hasAgingHere && hasAgingElsewhere) {
1173
                            for (var j = 0; j < f.agingBreakdown.length; j++) {
1174
                                var b = f.agingBreakdown[j];
1175
                                var whFull = b.warehouseName || '';
1176
                                var vFull = b.vendorName || '';
1177
                                var whShort = whFull.indexOf('/') >= 0 ? whFull.substring(0, whFull.indexOf('/')) : whFull;
1178
                                var vShort = vFull.indexOf(' ') >= 0 ? vFull.substring(0, vFull.indexOf(' ')) : vFull;
1179
                                $rows.append(
1180
                                    '<tr style="background:#fff9e6;color:#8a6d3b">' +
1181
                                    '<td style="padding:4px 10px 4px 26px;border-bottom:1px solid #f1e0b0;font-size:11px">' +
1182
                                    '<span style="color:#c19c00">&#8627; aging elsewhere:</span> ' +
1183
                                    escapePmscp(whShort) + ' - (' + escapePmscp(vShort) + ')' +
1184
                                    '</td>' +
1185
                                    '<td style="padding:4px 10px;text-align:right;border-bottom:1px solid #f1e0b0;font-size:11px">' + (b.qty || 0) + '</td>' +
1186
                                    '<td colspan="3" style="border-bottom:1px solid #f1e0b0"></td>' +
1187
                                    '</tr>'
1188
                                );
1189
                            }
1190
                        }
1191
                    }
1192
                    $('#pmscpFlaggedCount').text(flagged.length);
1193
                    $('#pmscpFlaggedBox').show();
1194
                } else {
1195
                    // Empty flaggedItems is unexpected when needsApproval=true, but hide
1196
                    // the table gracefully rather than showing an empty box.
1197
                    $('#pmscpFlaggedBox').hide();
1198
                }
1199
                $('#pmscpReasonModal').modal('show');
1200
                return;
1201
            }
1202
            actuallyCreatePO(purchaseOrder);
1203
        },
1204
        error: function () {
1205
            // Preflight failed for a reason unrelated to the rule — attempt
1206
            // the create anyway; server will still enforce the rule if needed.
1207
            actuallyCreatePO(purchaseOrder);
1208
        }
1209
    });
1210
}
1211
 
1212
// The single, actual create request — fires once whether or not approval is needed.
1213
function actuallyCreatePO(purchaseOrder) {
1214
    doPostAjaxRequestWithJsonHandler(context + "/createPurchaseOrder",
1215
        JSON.stringify(purchaseOrder), function (response) {
32352 amit.gupta 1216
            if (response == 'true') {
37750 ranu 1217
                alert("Successfully created");
32352 amit.gupta 1218
                loadCreatePurchase("main-content");
1219
            }
1220
        });
32145 tejbeer 1221
}
1222
 
1223
 
1224
function editPurchase(sendPo, poid) {
32352 amit.gupta 1225
    var editpurchaseOrder = {}
1226
    var items = []
1227
    $("#purchase-edit-lineitem > tbody > tr").each(function () {
1228
        var purchaseOrderJson = {};
1229
        var itemId = $(this).find("td:eq(0)").text();
32145 tejbeer 1230
 
32352 amit.gupta 1231
        var qty = $(this).find("td:eq(2)").text();
32145 tejbeer 1232
 
32352 amit.gupta 1233
        var amendedQty = $(this).find(".editqty").val();
32256 tejbeer 1234
 
32352 amit.gupta 1235
        var transferPrice = $.trim($(this).find(".transferPrice").html());
32256 tejbeer 1236
 
1237
 
32352 amit.gupta 1238
        purchaseOrderJson['itemId'] = itemId;
1239
        purchaseOrderJson['amendedQty'] = parseInt(amendedQty)
1240
        purchaseOrderJson['qty'] = parseInt(qty)
1241
        purchaseOrderJson['transferPrice'] = transferPrice
32145 tejbeer 1242
 
32352 amit.gupta 1243
        items.push(purchaseOrderJson)
1244
    });
32145 tejbeer 1245
 
1246
 
32352 amit.gupta 1247
    for (var i = 0; i < items.length; i++) {
1248
        console.log(items[i])
32145 tejbeer 1249
 
32352 amit.gupta 1250
        var amendedQty = items[i].amendedQty
1251
        var qty = items[i].qty
32145 tejbeer 1252
 
32256 tejbeer 1253
 
32352 amit.gupta 1254
        if (amendedQty === "") {
1255
            alert("please choose qty");
1256
            return false;
1257
        }
32145 tejbeer 1258
 
32352 amit.gupta 1259
        if (amendedQty < qty) {
1260
            alert("Quantity should be greater than existing qty");
1261
            return false;
1262
        }
32145 tejbeer 1263
 
1264
 
32352 amit.gupta 1265
    }
32145 tejbeer 1266
 
32352 amit.gupta 1267
    editpurchaseOrder['purchaseOrderId'] = poid;
1268
    editpurchaseOrder['sendPo'] = sendPo
1269
    editpurchaseOrder['items'] = items
32145 tejbeer 1270
 
1271
 
32352 amit.gupta 1272
    if (confirm("Are you sure you want to edit purchase order") == true) {
32145 tejbeer 1273
 
32352 amit.gupta 1274
        doPostAjaxRequestWithJsonHandler(context
1275
            + "/editPurchaseOrder", JSON
1276
            .stringify(editpurchaseOrder), function (response) {
1277
            if (response == 'true') {
1278
                alert("successfully created");
1279
                $('#warehouseEditPurchaseContainer').modal('hide');
1280
                $('.modal-backdrop').remove();
32295 tejbeer 1281
 
32352 amit.gupta 1282
                loadOpenPurchase("main-content")
1283
            }
1284
        });
1285
    }
32145 tejbeer 1286
 
1287
}
1288
 
1289
 
32192 tejbeer 1290
function getInvoiceItemData(numItems, invoiceId, warehouseId, supplierId, validate) {
1291
 
32352 amit.gupta 1292
    var invoiceJson = {};
1293
    console.log(numItems)
1294
    var totalQty = 0;
1295
    var invoiceItems = []
1296
    $("#invoice-order-table > tbody > tr").each(function () {
1297
        var invoiceItemJson = {};
1298
        var itemId = $(this).find(".rate").data('itemid');
1299
        var qty = $(this).find(".qty").val();
32192 tejbeer 1300
 
32352 amit.gupta 1301
        if (qty != undefined) {
1302
            totalQty += parseInt(qty)
1303
        }
1304
        var rate = $(this).find(".rate").val();
1305
        invoiceItemJson['itemId'] = itemId;
1306
        invoiceItemJson['qty'] = qty
1307
        invoiceItemJson['rate'] = rate
1308
        invoiceItems.push(invoiceItemJson)
1309
    });
32192 tejbeer 1310
 
1311
 
32352 amit.gupta 1312
    for (var i = 0; i < invoiceItems.length; i++) {
32192 tejbeer 1313
 
32352 amit.gupta 1314
        var itemId = invoiceItems[i].itemId
1315
        var qty = invoiceItems[i].qty
1316
        var rate = invoiceItems[i].rate
1317
        if (itemId === "" && qty === "" && rate === "") {
1318
            alert("Field can't be empty");
1319
            return false;
1320
        }
32192 tejbeer 1321
 
32352 amit.gupta 1322
        if (itemId === "") {
1323
            alert("please select item");
1324
            return false;
1325
        }
1326
        if (qty === "") {
1327
            alert("please choose qty");
1328
            return false;
1329
        }
32192 tejbeer 1330
 
32352 amit.gupta 1331
        if (rate === "") {
1332
            alert("Rate can't be empty");
1333
            return false;
1334
        }
32192 tejbeer 1335
 
32352 amit.gupta 1336
    }
32192 tejbeer 1337
 
32352 amit.gupta 1338
    console.log(totalQty)
32192 tejbeer 1339
 
32352 amit.gupta 1340
    if (totalQty > numItems) {
1341
        alert("Qty Should not be more than  Invoice items");
1342
        return false;
1343
    }
32192 tejbeer 1344
 
32352 amit.gupta 1345
    if (validate) {
32192 tejbeer 1346
 
32352 amit.gupta 1347
        if (totalQty != numItems) {
1348
            alert("Qty Should not match with Invoice items");
1349
            return false;
1350
        }
1351
    }
32192 tejbeer 1352
 
1353
 
32352 amit.gupta 1354
    invoiceJson['invoiceId'] = invoiceId;
1355
    invoiceJson['warehouseId'] = warehouseId;
1356
    invoiceJson['supplierId'] = supplierId;
1357
    invoiceJson['invoiceItems'] = invoiceItems
1358
    if (validate) {
1359
        validateInvoiceItems(invoiceJson);
1360
    } else {
1361
        saveInvoiceItems(invoiceJson)
1362
    }
32192 tejbeer 1363
}
1364
 
1365
 
1366
function saveInvoiceItems(invoiceJson) {
1367
 
1368
 
32352 amit.gupta 1369
    if (confirm("Are you sure you want to save invoice item") == true) {
32192 tejbeer 1370
 
32352 amit.gupta 1371
        doPostAjaxRequestWithJsonHandler(context
1372
            + "/invoiceItemDetail", JSON
1373
            .stringify(invoiceJson), function (response) {
1374
            if (response == 'true') {
1375
                getInvoiceItems(invoiceJson.invoiceId);
1376
            }
1377
        });
1378
    }
32192 tejbeer 1379
 
1380
}
1381
 
1382
 
1383
function validateInvoiceItems(invoiceJson) {
1384
 
1385
 
32352 amit.gupta 1386
    if (confirm("Are you sure you want to validate invoice item") == true) {
32192 tejbeer 1387
 
32352 amit.gupta 1388
        doPostAjaxRequestWithJsonHandler(context
1389
            + "/validateInvoiceItemDetail", JSON
1390
            .stringify(invoiceJson), function (response) {
1391
            $('.invoiceadditemcontainer').html(response);
32192 tejbeer 1392
 
32352 amit.gupta 1393
        });
1394
    }
32192 tejbeer 1395
 
1396
}
1397
 
1398
function getOpenPOFromWarehouse() {
1399
 
32352 amit.gupta 1400
    var warehouseId = $('#warehouseMap').val();
1401
    doGetAjaxRequestHandler(context + "/getOpenPurchaseOrderByWarehouseId?warehouseId=" + warehouseId, function (response) {
1402
        $('#warehouseManagePuchaseContainer').html(response);
1403
    });
32192 tejbeer 1404
 
1405
 
1406
}
1407
 
1408
function getPurchaseLineitem(poId) {
1409
 
1410
 
32352 amit.gupta 1411
    doGetAjaxRequestHandler(context + "/getPurchaseOrderItemByPoId?poId=" + poId, function (response) {
1412
        $('#warehouseManagePuchaseItemContainer').html(response);
1413
        $('#warehousepurchaseitemgrn').hide()
1414
    });
32192 tejbeer 1415
 
1416
 
1417
}
1418
 
1419
 
1420
function getInvoiceItems(invoiceId) {
1421
 
32352 amit.gupta 1422
    doGetAjaxRequestHandler(context + "/getInvoiceItems?invoiceId=" + invoiceId, function (response) {
1423
        $('.invoiceadditemcontainer').html(response);
32192 tejbeer 1424
 
32352 amit.gupta 1425
    });
32192 tejbeer 1426
}
1427
 
1428
 
32256 tejbeer 1429
function getGrnRequestItems(requestId, invoiceId) {
32352 amit.gupta 1430
    doGetAjaxRequestHandler(context + "/grnRequestItem?requestId=" + requestId + "&invoiceId=" + invoiceId, function (response) {
1431
        $('.grnRequestItemContainer').html(response);
32256 tejbeer 1432
 
32352 amit.gupta 1433
    });
32256 tejbeer 1434
}
1435
 
32912 amit.gupta 1436
function removeInvoice(invoiceId) {
34047 tejus.loha 1437
    if (confirm(`Are your sure want to delete invoiceId ${invoiceId}`)) {
32912 amit.gupta 1438
        doGetAjaxRequestHandler(`${context}/removeInvoice?invoiceId=${invoiceId}`, function (response) {
34047 tejus.loha 1439
            $('#open-invoices').DataTable().row("#" + invoiceId).remove().draw();
32912 amit.gupta 1440
            alert("Invoice Removed");
1441
        });
1442
    }
1443
}
32256 tejbeer 1444
 
32912 amit.gupta 1445
function removeGrnRequest(invoiceId) {
34047 tejus.loha 1446
    if (confirm(`Are your sure want to remove grn request for invoiceId ${invoiceId}`)) {
32912 amit.gupta 1447
        doGetAjaxRequestHandler(`${context}/removeGrnRequest?invoiceId=${invoiceId}`, function (response) {
1448
            $('#' + domId).html(response);
1449
            alert("Grn Request Removed");
1450
        });
1451
    }
1452
}
1453
 
1454
 
35806 amit 1455
// ============ GRN Correction ============
1456
 
1457
$(document).on('click', '.warehouse-grn-correction', function () {
1458
    loadGrnCorrection("main-content");
1459
});
1460
 
1461
$(document).on('click', '.warehouse-grn-correction-approval', function () {
1462
    loadGrnCorrectionApproval("main-content");
1463
});
1464
 
1465
$(document).on('click', '.searchCorrectionInvoices', function () {
1466
    var startDate = getDatesFromPicker('input[name="correction-duration"]').startDate;
1467
    var endDate = getDatesFromPicker('input[name="correction-duration"]').endDate;
1468
    doGetAjaxRequestHandler(context + "/grnCorrection?startDate=" + startDate + "&endDate=" + endDate, function (response) {
1469
        $('#main-content').html(response);
1470
    });
1471
});
1472
 
1473
$(document).on('click', '.submitGrnCorrection', function () {
1474
    var invoiceId = $(this).data('invoiceid');
1475
    var remarks = $('#correctionRemarks').val();
1476
 
1477
    if (!remarks || remarks.trim() === '') {
1478
        alert("Please enter remarks explaining the reason for correction");
1479
        return false;
1480
    }
1481
 
1482
    // Collect serial number corrections (old → new)
1483
    var corrections = [];
1484
    $('#serial-corrections-table > tbody > tr').each(function () {
1485
        var oldSerial = $(this).find('.old-serial').val();
1486
        var newSerial = $(this).find('.new-serial').val();
1487
 
1488
        if (oldSerial && newSerial && oldSerial.trim() !== '' && newSerial.trim() !== '') {
1489
            corrections.push({
1490
                oldSerialNumber: oldSerial.trim(),
1491
                newSerialNumber: newSerial.trim()
1492
            });
1493
        }
1494
    });
1495
 
35884 amit 1496
    // Collect item corrections (serialized or non-serialized)
35806 amit 1497
    var qtyCorrections = [];
36206 amit 1498
    var imeiCountError = false;
35806 amit 1499
    $('#qty-corrections-table > tbody > tr').each(function () {
1500
        var oldItemId = $(this).find('.qty-old-itemid').val();
1501
        var newItemId = $(this).find('.qty-new-itemid').val();
35884 amit 1502
        var serial = $(this).find('.qty-serial').val();
35806 amit 1503
        var qty = parseInt($(this).find('.qty-correction-val').val());
1504
 
35884 amit 1505
        if (oldItemId && newItemId && serial && serial.trim() !== '') {
36206 amit 1506
            // Split IMEIs by space, comma, or newline
1507
            var imeis = serial.trim().split(/[\s,]+/).filter(function(s) { return s.length > 0; });
1508
            var imeiCount = imeis.length;
1509
 
1510
            // Auto-set qty from IMEI count, validate if qty was manually entered
1511
            if (qty > 0 && qty !== imeiCount) {
1512
                alert("Row error: Qty (" + qty + ") does not match IMEI count (" + imeiCount + ").\nIMEIs: " + imeis.join(", "));
1513
                imeiCountError = true;
1514
                return false;
1515
            }
1516
 
1517
            // Create one entry per IMEI (each with qty=1)
1518
            for (var i = 0; i < imeis.length; i++) {
1519
                qtyCorrections.push({
1520
                    oldItemId: parseInt(oldItemId),
1521
                    newItemId: parseInt(newItemId),
1522
                    qty: 1,
1523
                    serialNumber: imeis[i].trim()
1524
                });
1525
            }
35884 amit 1526
        } else if (oldItemId && newItemId && qty > 0) {
1527
            qtyCorrections.push({
1528
                oldItemId: parseInt(oldItemId),
1529
                newItemId: parseInt(newItemId),
35806 amit 1530
                qty: qty
1531
            });
1532
        }
1533
    });
1534
 
36206 amit 1535
    if (imeiCountError) return false;
1536
 
35806 amit 1537
    if (corrections.length === 0 && qtyCorrections.length === 0) {
1538
        alert("No corrections specified. Please enter serial number or quantity corrections.");
1539
        return false;
1540
    }
1541
 
1542
    var requestModel = {
1543
        invoiceId: invoiceId,
1544
        remarks: remarks,
1545
        corrections: corrections,
1546
        qtyCorrections: qtyCorrections
1547
    };
1548
 
1549
    if (confirm("Are you sure you want to raise this GRN correction request?")) {
1550
        doPostAjaxRequestWithJsonHandler(context + "/raiseGrnCorrection",
1551
            JSON.stringify(requestModel), function (response) {
36299 amit 1552
                var parsed;
1553
                try { parsed = typeof response === 'string' ? JSON.parse(response) : response; }
1554
                catch (e) { parsed = null; }
1555
                if (parsed && parsed.status === true) {
1556
                    if (parsed.autoApproved) {
1557
                        alert("Correction applied successfully (auto-approved: no model/qty change)");
1558
                    } else {
1559
                        alert("Correction request raised for approval");
1560
                    }
35806 amit 1561
                    loadGrnCorrection("main-content");
1562
                }
1563
            });
1564
    }
1565
});
1566
 
1567
$(document).on('click', '.approveGrnCorrectionBtn', function () {
1568
    var requestId = $(this).data('requestid');
1569
    var remarks = $('#approvalRemarks').val();
1570
 
1571
    if (confirm("Are you sure you want to APPROVE this correction request? This will apply the IMEI/qty changes.")) {
1572
        doPostAjaxRequestHandler(context + "/approveGrnCorrection?requestId=" + requestId + "&remarks=" + encodeURIComponent(remarks),
1573
            function (response) {
1574
                if (response == 'true') {
1575
                    alert("Correction approved and applied successfully");
1576
                    loadGrnCorrectionApproval("main-content");
1577
                }
1578
            });
1579
    }
1580
});
1581
 
1582
$(document).on('click', '.rejectGrnCorrectionBtn', function () {
1583
    var requestId = $(this).data('requestid');
1584
    var remarks = $('#approvalRemarks').val();
1585
 
1586
    if (!remarks || remarks.trim() === '') {
1587
        alert("Please enter remarks explaining the reason for rejection");
1588
        return false;
1589
    }
1590
 
1591
    if (confirm("Are you sure you want to REJECT this correction request?")) {
1592
        doPostAjaxRequestHandler(context + "/rejectGrnCorrection?requestId=" + requestId + "&remarks=" + encodeURIComponent(remarks),
1593
            function (response) {
1594
                if (response == 'true') {
1595
                    alert("Correction request rejected");
1596
                    loadGrnCorrectionApproval("main-content");
1597
                }
1598
            });
1599
    }
1600
});
1601
 
1602
function loadGrnCorrection(domId) {
1603
    doGetAjaxRequestHandler(context + "/grnCorrection", function (response) {
1604
        $('#' + domId).html(response);
1605
    });
1606
}
1607
 
1608
function loadGrnCorrectionApproval(domId) {
1609
    doGetAjaxRequestHandler(context + "/grnCorrectionApproval", function (response) {
1610
        $('#' + domId).html(response);
1611
    });
1612
}
1613
 
1614
function loadGrnCorrectionDetail(invoiceId) {
1615
    doGetAjaxRequestHandler(context + "/grnCorrectionDetail?invoiceId=" + invoiceId, function (response) {
1616
        $('.grnCorrectionDetailContainer').html(response);
1617
    });
1618
}
1619
 
1620
function loadGrnCorrectionRequestDetail(requestId) {
1621
    doGetAjaxRequestHandler(context + "/grnCorrectionRequestDetail?requestId=" + requestId, function (response) {
1622
        $('.grnCorrectionRequestDetailContainer').html(response);
1623
    });
1624
}
1625
 
1626
 
37697 amit 1627
 
1628
/**
1629
 * Shows what the sending warehouse can actually release of an item, on the row where a quantity is being typed.
1630
 *
1631
 * Only our own warehouses answer with this; an outside vendor's pricing response carries no availability, and its row
1632
 * is left exactly as it was. Stock that is entirely promised is shown as zero with the orders holding it named, which
1633
 * is what lets someone chase those orders instead of only seeing a smaller number.
1634
 */
1635
function renderMovementAvailability($row, pricing) {
1636
    var $icon = $row.find('.mv-avail-icon');
1637
    if (!pricing || typeof pricing.movableOnThisPo === 'undefined') {
1638
        $icon.hide();
1639
        $row.removeData('movableOnThisPo');
1640
        return;
1641
    }
1642
 
1643
    var cap = pricing.movableOnThisPo;
1644
    $row.data('movableOnThisPo', cap);
1645
 
37723 amit 1646
    // Reads as a sum - in stock + arriving - promised - so the number that can move is never left unexplained.
37699 amit 1647
    var rows = mvAvailLine('In stock', pricing.inStock, '');
37723 amit 1648
    if (pricing.arrivingTotal > 0) {
1649
        rows += mvAvailLine('Arriving (not yet received)', '+ ' + pricing.arrivingTotal, '');
1650
        $.each(pricing.arriving || [], function (i, po) {
1651
            rows += mvAvailLine(mvEscape(po.poNumber) + ' &middot; ' + mvEscape(po.poDate)
1652
                + (po.destination ? ' &larr; ' + mvEscape(po.destination) : ''), po.qty, ' mv-po');
1653
        });
1654
    }
37697 amit 1655
    if (pricing.promisedTotal > 0) {
37723 amit 1656
        rows += mvAvailLine('Promised on open orders', '&minus; ' + pricing.promisedTotal, '');
37697 amit 1657
        $.each(pricing.promised || [], function (i, po) {
37699 amit 1658
            rows += mvAvailLine(mvEscape(po.poNumber) + ' &middot; ' + mvEscape(po.poDate)
1659
                + (po.destination ? ' &rarr; ' + mvEscape(po.destination) : ''), po.qty, ' mv-po');
37697 amit 1660
        });
1661
    }
37699 amit 1662
    rows += mvAvailLine('Can move on this PO', cap, ' mv-total');
37697 amit 1663
 
1664
    var note = '';
1665
    if (pricing.costSplit) {
1666
        note += '<div class="mv-note">' + (pricing.movableAltogether - cap)
1667
            + ' more came in at a different cost &mdash; raise a separate PO for those.</div>';
1668
    }
1669
    if (cap === 0) {
37699 amit 1670
        note += '<div class="mv-note">' + (pricing.promisedTotal > 0
1671
            ? 'Nothing can move until one of the orders above is completed or closed.'
1672
            : 'Nothing can move from here yet.') + '</div>';
37697 amit 1673
    }
1674
 
37699 amit 1675
    $icon.attr('data-mv-content', '<div class="mv-avail">' + rows + '</div>' + note);
37697 amit 1676
    $icon.removeClass('mv-none mv-part');
1677
    if (cap === 0) {
1678
        $icon.addClass('mv-none');
1679
    } else if (pricing.promisedTotal > 0) {
1680
        $icon.addClass('mv-part');
1681
    }
1682
    $icon.show();
1683
 
1684
    $icon.popover('destroy');
1685
    $icon.popover({
1686
        html: true,
1687
        container: 'body',
1688
        placement: 'left',
1689
        trigger: 'hover focus',
1690
        title: 'Stock at ' + mvEscape(pricing.sourceName),
1691
        content: function () {
1692
            return $(this).attr('data-mv-content');
1693
        }
1694
    });
1695
 
1696
    checkMovableQty($row, parseInt($row.find('.qty').val()));
1697
}
1698
 
1699
/** Flags a quantity that the order cannot take, while it is being typed rather than on submit. */
1700
function checkMovableQty($row, qty) {
1701
    var cap = $row.data('movableOnThisPo');
1702
    var $qty = $row.find('.qty');
1703
    var $warn = $row.find('.mv-qty-warn');
1704
 
1705
    if (typeof cap === 'undefined' || isNaN(qty)) {
1706
        $qty.removeClass('mv-over');
1707
        $warn.hide().empty();
1708
        return;
1709
    }
1710
 
1711
    if (qty > cap) {
1712
        $qty.addClass('mv-over');
1713
        $warn.text(cap === 0 ? 'None can move right now' : 'Only ' + cap + ' can move on this PO').show();
1714
    } else {
1715
        $qty.removeClass('mv-over');
1716
        $warn.hide().empty();
1717
    }
1718
}
1719
 
37699 amit 1720
/**
1721
 * One line of the breakdown.
1722
 *
1723
 * Built from divs and spans on purpose: Bootstrap's popover sanitizer whitelists neither tables nor their rows, and
1724
 * strips a non-whitelisted element together with everything inside it - a table here renders as nothing at all.
1725
 */
1726
function mvAvailLine(label, value, extraClass) {
1727
    return '<div class="mv-row' + extraClass + '"><span class="mv-label">' + label
1728
        + '</span><span class="mv-val">' + value + '</span></div>';
37697 amit 1729
}
1730
 
1731
/** Values here are warehouse and order names out of the database, so they are escaped before going into the popover. */
1732
function mvEscape(value) {
1733
    return $('<div/>').text(value === null || typeof value === 'undefined' ? '' : value).html();
1734
}