Subversion Repositories SmartDukaan

Rev

Rev 37543 | Blame | Compare with Previous | Last modification | View Log | RSS feed

$(function() {
        $(document).on('click', "a.view-returns", function() {
                viewReturnStores("main-content");
        });
        $(document).on('click', "a.pending-returns", function() {
                viewPendingReturns("main-content");
        });
        $(document).on('click', "a.approved-returns", function() {
                viewApprovedReturns("main-content");
        });

        $(document).on('click', "a.view-debit-note", function() {
                viewDebitNotes("main-content");
        });

        $(document).on('click', "a.unsettled-purchase-returns", function () {
                doAjaxRequestHandler(context + "/return/unsettled", "GET", function (response) {
                        $('#main-content').html(response);
                });
        });

        $(document).on('click', "a.create-purchase-return", function () {
                doAjaxRequestHandler(context + "/return/unsettled/new", "GET", function (response) {
                        $('#main-content').html(response);
                });
        });

        $(document).on('click', "a.wh-display-name", function() {
                var whId = $(this).closest('tr').data('id');
                $("#approved-returns-container").find("tr.filter").hide().filter('[data-id="' + whId + '"]').show();
                $(this).closest('table').find('tr').removeClass('warning');
                $(this).closest('tr').addClass('warning');
        });

        $(document).on('click', "a.debit-note", function() {
                var debitNoteId = $(this).closest('tr').data('id');
                $("#debit-note-items").find("tr.filter").hide().filter('[data-id="' + debitNoteId + '"]').show();
                $(this).closest('table').find('tr').removeClass('alert-warning');
                $(this).closest('tr').addClass('alert-warning');
        });


        $(document).on('click', "a.request-return", function() {
                if(confirm("Are you sure?")) {
                        createReturnRequest($(this).data("inventoryitemid"), $(this));
                }
        });
        $(document).on('click', "a.approve-return", function() {
                if(confirm("Are you sure to Approve?")) {
                        approveReturnRequest($(this).closest('td').data("returnid"), $(this).closest('td'));
                }
        });
        $(document).on('click', "a.deny-return", function() {
                if(confirm("Are you sure to Deny?")) {
                        denyReturnRequest($(this).closest('td').data("returnid"), $(this).closest('td'));
                }
        });

        $(document).on('click', '#inventory-container a', function (){
                itemId=$(this).data('id');
                if(!fofoId){
                        fofoId =$('select[name="fofo-users"]').val();
                        console.log("fofo Id -"+fofoId);
                }
                doAjaxRequestHandler(context+"/return/inventory/" + fofoId + "/" + itemId, "GET", function(response){
                        returnsTable.rows().remove().rows.add($(response)).draw(false);
                });
        });

        $(document).on('click', '.vendor_return', function () {
                doAjaxRequestHandler(context + "/return/to/vendor", "GET", function (response) {
                        $('#main-content').html(response);
                });
        });

        // Invoice Return
        $(document).on('click', 'a.invoice-return', function () {
                doAjaxRequestHandler(context + "/return/invoice", "GET", function (response) {
                        $('#main-content').html(response);
                });
        });

        // Search by Debit Note Number
        $(document).on('click', '#search-debit-note-btn', function () {
                var debitNoteNumber = $('#debit-note-number-input').val();
                if (!debitNoteNumber) {
                        alert("Please enter a debit note number");
                        return;
                }
                doAjaxRequestHandler(context + "/return/search/debit-note?debitNoteNumber=" + encodeURIComponent(debitNoteNumber), "GET", function (response) {
                        $('#invoice-return-results').html(response);
                });
        });

        $(document).on('click', '#return-invoice-button', function () {
                var invoiceNumber = $('#invoice-number-input').val();
                if (!invoiceNumber) {
                        alert("Please enter an invoice number");
                        return;
                }
                doAjaxRequestHandler(context + "/return/invoice/search?invoiceNumber=" + encodeURIComponent(invoiceNumber), "GET", function (response) {
                        $('#invoice-return-results').html(response);
                });
        });

        // Date-range filter
        $(document).on('click', '#invoice-return-date-apply', function () {
                var fromDate = $('#invoice-return-from-date').val();
                var toDate = $('#invoice-return-to-date').val();
                if (!fromDate || !toDate) {
                        alert("Please pick both From and To dates");
                        return;
                }
                if (fromDate > toDate) {
                        alert("From date must be on or before To date");
                        return;
                }
                doAjaxRequestHandler(context + "/return/invoice?fromDate=" + encodeURIComponent(fromDate)
                                + "&toDate=" + encodeURIComponent(toDate), "GET", function (response) {
                        $('#main-content').html(response);
                });
        });

        // Debit Note Details
        $(document).on('click', '.debit-note-details', function () {
                var debitNoteId = $(this).data("debitnote-id");
                doAjaxRequestHandler(context + "/return/debit-note/details/" + debitNoteId, "GET", function (response) {
                        $('#main-content').html(response);
                });
        });

        // Receive Debit Note
        $(document).on('click', '.receive-debit-note', function () {
                var debitNoteId = $(this).data("debitnote-id");
                doAjaxRequestHandler(context + "/return/debit-note/receive/" + debitNoteId, "GET", function (response) {
                        $('#main-content').html(response);
                        applyDeclaredConditions();
                });
        });

        // Seed every condition dropdown from what the partner declared, then settle the dependent
        // sections. Doing both here keeps one source of truth - the row's data-declared attribute - and
        // guarantees the DOA radios are resolved on load, which a preselected BAD never triggers on its
        // own because no change event fires for it.
        //
        // The markup still renders `selected` server-side as the fallback. If this script fails to load,
        // a declared BAD must not quietly present as GOOD: the server reads any difference from
        // data-declared as the warehouse DISAGREEING with the partner and rejects the whole debit note.
        function applyDeclaredConditions() {
                $('#receive-debit-note-form .return-condition').each(function () {
                        var declared = $(this).data('declared');
                        if (declared) {
                                $(this).val(declared);
                        }
                });
                syncReceiveConditionState();
        }

        // A row whose selected condition differs from what the partner declared is a disagreement,
        // not a correction — the server rejects the whole debit note for it.
        function hasConditionMismatch() {
                var mismatch = false;
                $('#receive-debit-note-form tr[data-item-id]').each(function () {
                        var select = $(this).find('.return-condition');
                        if (select.val() !== select.data('declared')) {
                                mismatch = true;
                        }
                });
                return mismatch;
        }

        // Show/hide the DOA certificate section based on BAD selection on mobile items.
        //
        // Driven by the CURRENT state of the form, never by what the operator just touched, because the
        // form arrives with the partner's declared condition already selected. A partner declaring a
        // mobile as BAD - the ordinary DOA case - renders BAD preselected, so no change event ever
        // fires; leaving this logic in the change handler alone hid the DOA radios on exactly the rows
        // that need them, and the server then refused the receipt for a missing certificate the operator
        // was never shown.
        function syncReceiveConditionState() {
                if (!$('#receive-debit-note-form').length) {
                        return;
                }

                // On a mismatch the receipt never happens, so the DOA certificate is not collected.
                if (hasConditionMismatch()) {
                        $('#condition-mismatch-section').show();
                        $('#doa-certificate-section').hide();
                        $('#submit-receive').removeClass('btn-primary').addClass('btn-danger').text('Reject Return');
                        return;
                }
                $('#condition-mismatch-section').hide();
                $('#submit-receive').removeClass('btn-danger').addClass('btn-primary').text('Confirm Receipt');

                var hasMobileBad = false;
                $('#receive-debit-note-form tr[data-category-id]').each(function () {
                        var categoryId = $(this).data('category-id');
                        var condition = $(this).find('.return-condition').val();
                        if (condition === 'BAD' && categoryId == 10006) {
                                hasMobileBad = true;
                        }
                });
                if (hasMobileBad) {
                        $('#doa-certificate-section').show();
                } else {
                        $('#doa-certificate-section').hide();
                }
        }

        $(document).on('change', '.return-condition', syncReceiveConditionState);

        // Submit receive debit note form
        $(document).on('submit', '#receive-debit-note-form', function (e) {
                e.preventDefault();

                var mismatch = hasConditionMismatch();

                // Validate remarks: mandatory for BAD rows, and for any row whose condition was changed —
                // the remark is what the partner and the escalation chain see as the reason for rejection.
                var valid = true;
                $(this).find('tr[data-item-id]').each(function () {
                        var select = $(this).find('.return-condition');
                        var condition = select.val();
                        var remark = $(this).find('.remark-field').val();
                        if (condition !== select.data('declared') && !remark) {
                                alert("Remark is required when you change the condition — it is sent to the partner as the rejection reason");
                                valid = false;
                                return false;
                        }
                        if (condition === 'BAD' && !remark) {
                                alert("Remark is required for BAD/DOA returns");
                                valid = false;
                                return false;
                        }
                });
                if (!valid) return;

                var debitNoteId = $(this).data('debitnote-id');
                var form = $(this);

                if (mismatch) {
                        if (!confirm("The condition you selected does not match what the partner declared.\n\n"
                                        + "This will REJECT the entire debit note and notify the partner, Logistics, RBM and Sales. "
                                        + "No refund will be raised.\n\nProceed?")) {
                                return;
                        }
                } else {
                        // Check DOA certificate if mobile BAD items exist
                        var hasMobileBad = false;
                        $(this).find('tr[data-category-id]').each(function () {
                                if ($(this).data('category-id') == 10006 && $(this).find('.return-condition').val() === 'BAD') {
                                        hasMobileBad = true;
                                }
                        });
                        if (hasMobileBad && !$('input[name="doaCertificateValid"]:checked').val()) {
                                alert("Please select DOA certificate validity");
                                return;
                        }
                        if (!confirm("Are you sure you want to confirm receipt for this debit note?")) {
                                return;
                        }
                }

                $.ajax({
                        url: context + "/return/debit-note/receive/" + debitNoteId,
                        type: "POST",
                        data: form.serialize(),
                        success: function (response) {
                                if (response === 'true' || response.indexOf('true') >= 0) {
                                        alert(mismatch
                                                ? "Debit note rejected due to condition mismatch. Partner and escalation chain notified."
                                                : "Debit note items received successfully");
                                        doAjaxRequestHandler(context + "/return/invoice", "GET", function (resp) {
                                                $('#main-content').html(resp);
                                        });
                                } else {
                                        alert((mismatch ? "Rejection failed: " : "Receipt failed: ") + response);
                                }
                        },
                        error: function (xhr) {
                                alert("Error: " + xhr.responseText);
                        }
                });
        });

        // Refund Debit Note - opens refund view with receipt details
        $(document).on('click', '.refund-debit-note', function () {
                var debitNoteId = $(this).data("debitnote-id");
                doAjaxRequestHandler(context + "/return/debit-note/refund/" + debitNoteId, "GET", function (response) {
                        $('#main-content').html(response);
                });
        });

        // Confirm refund with finance remark
        $(document).on('click', '.refund-debit-note-confirm', function () {
                var debitNoteId = $(this).data("debitnote-id");
                var financeRemark = $('#finance-remark').val();
                if (confirm("Are you sure you want to process refund for debit note " + debitNoteId + "?")) {
                        doAjaxRequestHandler(context + "/return/debit-note/refund/" + debitNoteId + "?financeRemark=" + encodeURIComponent(financeRemark), "PUT", function (response) {
                                if (response === 'true') {
                                        alert("Debit note refunded successfully");
                                        reloadReturnQueue();
                                } else {
                                        alert("Refund failed: " + response);
                                }
                        }, approvalFailed);
                }
        });

        // Reject debit note return
        $(document).on('click', '.reject-debit-note-confirm', function () {
                var debitNoteId = $(this).data("debitnote-id");
                var rejectRemark = $('#reject-remark').val();
                if (!rejectRemark) {
                        alert("Please enter a reject remark");
                        return;
                }
                if (confirm("Are you sure you want to reject return for debit note " + debitNoteId + "? This will reverse all scans and quantities.")) {
                        doAjaxRequestHandler(context + "/return/debit-note/reject/" + debitNoteId + "?rejectRemark=" + encodeURIComponent(rejectRemark), "PUT", function (response) {
                                if (response === 'true') {
                                        alert("Return rejected successfully");
                                        doAjaxRequestHandler(context + "/return/invoice", "GET", function (resp) {
                                                $('#main-content').html(resp);
                                        });
                                } else {
                                        alert("Rejection failed: " + response);
                                }
                        });
                }
        });

        // Approve Invoice Return (finance approval for shipped invoices)
        $(document).on('click', '.approve-invoice-return', function () {
                var proId = $(this).data("pro-id");
                if (confirm("Are you sure you want to approve and refund this invoice return?")) {
                        doAjaxRequestHandler(context + "/return/invoice/approve/" + proId, "PUT", function (response) {
                                if (response === 'true') {
                                        alert("Invoice return approved and refunded successfully");
                                        reloadReturnQueue();
                                } else {
                                        alert("Approval failed: " + response);
                                }
                        }, approvalFailed);
                }
        });

        // ── Refund as B2C (Finance, same day as a NIC refusal for the buyer's GSTIN) ──

        $(document).on('click', '.b2c-refund', function () {
                var proId = $(this).data("pro-id");
                doAjaxRequestHandler(context + "/return/b2c-refund/" + proId, "GET", function (response) {
                        $('#main-content').html(response);
                });
        });

        // Enable the button only when the typed amount equals the refund amount exactly, a remark is
        // entered and consent is ticked. The server repeats every one of these checks.
        $(document).on('input change', '#b2c-amount, #b2c-remark, #b2c-consent', function () {
                var $amount = $('#b2c-amount');
                var typed = $.trim($amount.val()).replace(/,/g, '');
                var expected = String($amount.data('expected'));
                var matches = typed !== '' && /^\d+$/.test(typed) && typed === expected;
                $('#b2c-amount-error').toggle(typed !== '' && !matches);
                var ready = matches && $.trim($('#b2c-remark').val()) !== '' && $('#b2c-consent').is(':checked');
                $('#b2c-refund-confirm').prop('disabled', !ready);
        });

        $(document).on('click', '.b2c-refund-confirm', function () {
                var $btn = $(this);
                var proId = $btn.data("pro-id");
                var amount = $.trim($('#b2c-amount').val()).replace(/,/g, '');
                var remark = $.trim($('#b2c-remark').val());
                if (!confirm("Refund Rs. " + $btn.data("amount-label") + " to " + $btn.data("partner") + " as B2C?\n"
                                + "Stock comes back to the warehouse and a local credit note is issued.\nThis cannot be undone.")) {
                        return;
                }
                $btn.prop('disabled', true);
                doAjaxRequestHandler(context + "/return/b2c-refund/" + proId + "?amount=" + encodeURIComponent(amount)
                                + "&remark=" + encodeURIComponent(remark) + "&consent=true", "PUT", function (response) {
                        var cnNumber = response;
                        try { cnNumber = JSON.parse(response); } catch (e) { /* already a plain string */ }
                        alert("Refunded Rs. " + $btn.data("amount-label") + ". Credit note " + cnNumber + " issued (B2C, no IRN).");
                        reloadReturnQueue();
                }, function (xhr, msg) {
                        alert("B2C refund failed: " + errorText(msg));
                        $btn.prop('disabled', false);
                });
        });

        $(document).on('click', '.b2c-refund-cancel', function () {
                reloadReturnQueue();
        });

        // Reject Invoice Return — sale stands, no inventory/wallet/GST action
        $(document).on('click', '.reject-invoice-return', function () {
                var proId = $(this).data("pro-id");
                var rejectRemark = prompt("Reason for rejecting this invoice return? (sale will stand, no refund will be issued)");
                if (!rejectRemark) {
                        return;
                }
                if (confirm("Reject invoice return and let the sale stand? This cannot be undone.")) {
                        doAjaxRequestHandler(context + "/return/invoice/reject/" + proId + "?rejectRemark=" + encodeURIComponent(rejectRemark), "PUT", function (response) {
                                if (response === 'true') {
                                        alert("Invoice return rejected");
                                        doAjaxRequestHandler(context + "/return/invoice", "GET", function (resp) {
                                                $('#main-content').html(resp);
                                        });
                                } else {
                                        alert("Rejection failed: " + response);
                                }
                        });
                }
        });

        // Acknowledge rejected return — retailer confirms goods received back
        $(document).on('click', '.acknowledge-rejected-return', function () {
                var debitNoteId = $(this).data("debitnote-id");
                if (confirm("Confirm that you have received the rejected goods back? This will restore your inventory.")) {
                        doAjaxRequestHandler(context + "/return/debit-note/reject/acknowledge/" + debitNoteId, "PUT", function (response) {
                                if (response === 'true') {
                                        alert("Goods acknowledged. Inventory restored.");
                                        doAjaxRequestHandler(context + "/return/invoice", "GET", function (resp) {
                                                $('#main-content').html(resp);
                                        });
                                } else {
                                        alert("Acknowledgment failed: " + response);
                                }
                        });
                }
        });

        // Process Invoice Return (non-GRN'd)
        $(document).on('click', '.process-invoice-return', function () {
                var invoiceNumber = $(this).data("invoice");
                var remark = $('#invoice-return-remark').val();
                if (confirm("Are you sure you want to process return for invoice " + invoiceNumber + "?")) {
                        doAjaxRequestHandler(context + "/return/invoice/process?invoiceNumber=" + encodeURIComponent(invoiceNumber) + "&remark=" + encodeURIComponent(remark), "PUT", function (response) {
                                if (response === 'true') {
                                        alert("Invoice return processed successfully");
                                        doAjaxRequestHandler(context + "/return/invoice", "GET", function (resp) {
                                                $('#main-content').html(resp);
                                        });
                                } else {
                                        alert("Return failed: " + response);
                                }
                        });
                }
        });
});

function viewReturnStores(domId){
        doAjaxRequestHandler(context+"/return/stores", "GET", function(response){
                $('#' + domId).html(response);
        });
}

function viewPendingReturns(domId){
        doAjaxRequestHandler(context+"/return/pending", "GET", function(response){
                $('#' + domId).html(response);
        });
}

function viewApprovedReturns(domId){
        doAjaxRequestHandler(context+"/return/approved", "GET", function(response){
                $('#' + domId).html(response);
                $("#approved-returns").find('a:first').click();
        });
}

function viewDebitNotes(domId){
        doAjaxRequestHandler(context+"/return/debit-note-created", "GET", function(response){
                $('#' + domId).html(response);
                $("#debit-notes").find('a:first').click();
        });
}

function createReturnRequest(inventoryItemId, container){
        doAjaxRequestHandler(context+"/return/inventory/" + inventoryItemId, "PUT", function(response){
                if(response=='true') {
                        container.closest('td').html('Return requested');
                }
        });
}

function approveReturnRequest(inventoryItemId, container){
        doAjaxRequestHandler(context+"/return/inventory/approve/" + inventoryItemId, "PUT", function(response){
                if(response=='true') {
                        container.closest('td').html('Return Approved');
                }
        });
}

function denyReturnRequest(inventoryItemId, container){
        doAjaxRequestHandler(context+"/return/inventory/deny/" + inventoryItemId, "PUT", function(response){
                if(response=='true') {
                        container.closest('td').html('Return denied');
                }
        });
}

function viewDebitNote(warehouseId){
        doAjaxRequestHandler(context+"/return/debit-note/view/" + warehouseId, "GET", function(response){
                //Download PDF code
        });
}

function generateDebitNote(warehouseId){
        doAjaxRequestHandler(context+"/return/debit-note/generate/" + warehouseId, "PUT", function(response){
                if(response=='true') {
                        //Download the pdf
                }
        });
}

function getDebitNote(debitNotedId) {
        doAjaxRequestHandler(context+"/return/debit-note/" + debitNotedId, "GET", function(response){

        });
}

function reloadReturnQueue() {
        doAjaxRequestHandler(context + "/return/invoice", "GET", function (resp) {
                $('#main-content').html(resp);
        });
}

// Pull the human-readable message out of an error body; fall back to the raw text.
function errorText(msg) {
        try {
                var body = JSON.parse(msg);
                var r = body.response || body;
                return r.message || r.code || body.message || body.code || msg;
        } catch (e) {
                return msg;
        }
}

// A refused approval may have just opened the B2C option, so show the reason and reload the
// queue - the row then carries the "Refund as B2C" button without a manual refresh.
function approvalFailed(xhr, msg) {
        alert("Approval failed: " + errorText(msg));
        reloadReturnQueue();
}