Files
accounting_dev_v2/assets/js/sales-professional.js
T
2026-09-11 16:03:00 +07:00

1033 lines
30 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(function ($) {
"use strict";
var cfg = window.SALES_PAGE,
cart = [],
selectedItem = null,
selectedBars = [],
fileBag = new DataTransfer();
function esc(v) {
return $("<div>")
.text(v == null ? "" : v)
.html();
}
function number(v) {
if (typeof v === "number") return v;
v = String(v || "").replace(/Rp|\s/g, "");
if (v.indexOf(",") >= 0) v = v.replace(/\./g, "").replace(",", ".");
else if (/^\d{1,3}(\.\d{3})+$/.test(v)) v = v.replace(/\./g, "");
return Number(v) || 0;
}
function money(v) {
return (
"Rp " +
new Intl.NumberFormat("id-ID", {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(Number(v) || 0)
);
}
function toast(icon, title) {
if (window.AppAlert && AppAlert.toast) return AppAlert.toast(title, icon);
return Swal.fire({
toast: true,
position: "top-end",
icon: icon,
title: title,
showConfirmButton: false,
timer: 2800,
timerProgressBar: true,
});
}
function request(url, data, files) {
data = data || {};
if (data instanceof FormData) {
if (!data.has(cfg.csrfName)) data.append(cfg.csrfName, cfg.csrfHash);
} else data[cfg.csrfName] = cfg.csrfHash;
return $.ajax({
url: url,
type: "POST",
data: data,
processData: !files,
contentType: files
? false
: "application/x-www-form-urlencoded; charset=UTF-8",
dataType: "json",
});
}
function modal(id) {
return bootstrap.Modal.getOrCreateInstance(document.getElementById(id));
}
function loadCustomers() {
return $.getJSON(cfg.base + "sales/lookup_customers", { q: "" }).done(
function (r) {
$("#customerLookup").html(
'<option value="">Pilih customer</option>' +
r.rows
.map(function (x) {
return (
'<option value="' + x.id + '">' + esc(x.nama) + "</option>"
);
})
.join(""),
);
},
);
}
function loadItems() {
return $.getJSON(cfg.base + "sales/lookup_items", { q: "" }).done(
function (r) {
$("#itemLookup").html(
'<option value="">Cari/pilih barang</option>' +
r.rows
.map(function (x) {
return (
'<option value="' +
x.id +
'" data-row="' +
encodeURIComponent(JSON.stringify(x)) +
'">' +
esc(x.kode_barang + " - " + x.nama_barang) +
"</option>"
);
})
.join(""),
);
},
);
}
function loadWarehouses() {
return $.getJSON(cfg.base + "sales/warehouses").done(function (r) {
$("#warehouseLookup").html(
'<option value="">Pilih gudang</option>' +
r.rows
.map(function (x) {
return (
'<option value="' + x.id + '">' + esc(x.nama) + "</option>"
);
})
.join(""),
);
});
}
$("#newInvoice").on("click", function () {
cart = [];
$("#appendId").val("");
$("#invoiceForm")[0].reset();
$(
"#invoiceForm [name=customer_id],#invoiceForm [name=invoice_type],#invoiceForm [name=recognition_policy],#invoiceForm [name=period_start],#invoiceForm [name=period_end],#invoiceForm [name=due_date]",
).prop("disabled", false);
$(".invoiceModalTitle").text("Buat Invoice");
Promise.all([loadCustomers(), loadItems(), loadWarehouses()])
.then(function () {
renderCart();
modal("invoiceModal").show();
})
.catch(fail);
});
$(document).on("click", ".append-invoice", function () {
cart = [];
var id = $(this).data("id");
$("#appendId").val(id);
Promise.all([loadItems(), loadWarehouses()])
.then(function () {
$(
"#invoiceForm [name=customer_id],#invoiceForm [name=invoice_type],#invoiceForm [name=recognition_policy],#invoiceForm [name=period_start],#invoiceForm [name=period_end],#invoiceForm [name=due_date]",
).prop("disabled", true);
renderCart();
modal("invoiceModal").show();
})
.catch(fail);
});
$("#itemLookup").on("change", function () {
var o = this.options[this.selectedIndex];
selectedItem =
o && o.dataset.row ? JSON.parse(decodeURIComponent(o.dataset.row)) : null;
if (selectedItem) $("#linePrice").val(formatInput(selectedItem.harga_jual));
});
$("#chooseBarcode").on("click", function () {
if (!selectedItem || !$("#warehouseLookup").val())
return toast("warning", "Pilih barang dan gudang terlebih dahulu.");
$.getJSON(cfg.base + "sales/lookup_barcodes", {
item_id: selectedItem.id,
warehouse_id: $("#warehouseLookup").val(),
}).done(function (r) {
selectedBars = [];
$("#barcodeChoices").html(
r.rows.length
? r.rows
.map(function (b) {
var available =
number(b.qty_sisa) -
number(b.reserved_qty) -
number(b.return_reserved_qty);
return (
'<label><input type="checkbox" class="bar-check" data-row="' +
encodeURIComponent(JSON.stringify(b)) +
'"> ' +
esc(b.barcode) +
" <small>(" +
available +
")</small></label>"
);
})
.join("")
: '<span class="text-danger">Tidak ada barcode tersedia.</span>',
);
});
});
$(document).on("change", ".bar-check", function () {
var b = JSON.parse(decodeURIComponent(this.dataset.row));
if (this.checked) {
var qty =
selectedItem && selectedItem.tracking_type === "QTY"
? Math.min(
number(b.qty_sisa) -
number(b.reserved_qty) -
number(b.return_reserved_qty),
Math.max(0, number($("#lineQty").val())),
)
: 1;
selectedBars.push({ id: b.id, barcode: b.barcode, qty: qty });
} else
selectedBars = selectedBars.filter(function (x) {
return Number(x.id) !== Number(b.id);
});
});
$("#addLine").on("click", function () {
var qty = number($("#lineQty").val()),
price = number($("#linePrice").val());
if (!selectedItem || !$("#warehouseLookup").val() || qty <= 0 || price < 0)
return toast("warning", "Lengkapi barang, gudang, qty, dan harga.");
var bqty = selectedBars.reduce(function (s, b) {
return s + number(b.qty);
}, 0);
if (Math.abs(bqty - qty) > 0.0001)
return toast(
"warning",
"Total qty barcode (" +
bqty +
") harus sama dengan qty barang (" +
qty +
").",
);
cart.push({
item_id: selectedItem.id,
item_code: selectedItem.kode_barang,
item_name: selectedItem.nama_barang,
warehouse_id: $("#warehouseLookup").val(),
service_date: $("#invoiceForm [name=date]").val(),
qty: qty,
unit_price: price,
discount_amount: 0,
tax_rate: 0,
specification: "",
barcodes: selectedBars.slice(),
});
selectedBars = [];
$("#barcodeChoices").empty();
renderCart();
});
function renderCart() {
var total = 0;
$("#invoiceCart tbody").html(
cart
.map(function (x, i) {
var sub =
Math.max(0, x.qty * x.unit_price - x.discount_amount) *
(1 + x.tax_rate / 100);
total += sub;
return (
'<tr data-index="' +
i +
'"><td><b>' +
esc(x.item_code + " - " + x.item_name) +
'</b><input class="form-control form-control-sm cart-spec" placeholder="Spesifikasi" value="' +
esc(x.specification) +
'"><small>' +
x.barcodes.length +
' barcode</small></td><td><input type="date" class="form-control form-control-sm cart-date" value="' +
esc(x.service_date) +
'"></td><td>' +
x.qty +
"</td><td>" +
money(x.unit_price) +
'</td><td><input class="form-control form-control-sm cart-discount" inputmode="decimal" value="' +
formatInput(x.discount_amount) +
'"></td><td><input type="number" class="form-control form-control-sm cart-tax" min="0" value="' +
x.tax_rate +
'"></td><td>' +
money(sub) +
'</td><td><button type="button" class="btn btn-sm btn-outline-danger cart-remove">×</button></td></tr>'
);
})
.join(""),
);
$("#cartTotal").text(money(total));
}
$(document).on(
"input change",
".cart-discount,.cart-tax,.cart-date,.cart-spec",
function () {
var tr = $(this).closest("tr"),
x = cart[tr.data("index")];
x.discount_amount = number(tr.find(".cart-discount").val());
x.tax_rate = number(tr.find(".cart-tax").val());
x.service_date = tr.find(".cart-date").val();
x.specification = tr.find(".cart-spec").val();
renderCart();
},
);
$(document).on("click", ".cart-remove", function () {
cart.splice($(this).closest("tr").data("index"), 1);
renderCart();
});
$("#invoiceForm").on("submit", function (e) {
e.preventDefault();
if (!cart.length) return toast("warning", "Tambahkan minimal satu barang.");
var f = new FormData(this),
id = $("#appendId").val();
f.append("rows", JSON.stringify(cart));
var url = id
? cfg.base + "sales/append_invoice/" + id
: cfg.base + "sales/create_invoice";
request(url, f, true)
.done(function (r) {
if (!r.status) return toast("error", r.message);
modal("invoiceModal").hide();
toast("success", r.message);
setTimeout(function () {
location.reload();
}, 600);
})
.fail(fail);
});
function fail(xhr) {
var m = "Transaksi tidak dapat diproses.";
try {
m = JSON.parse(xhr.responseText).message || m;
} catch (e) {}
toast("error", m);
}
$(document).on("click", ".sale-action", function () {
var btn = $(this),
url = btn.data("url");
Swal.fire({
icon: "question",
title: btn.data("confirm"),
showCancelButton: true,
confirmButtonText: "Ya, lanjutkan",
cancelButtonText: "Batal",
}).then(function (r) {
if (!r.isConfirmed) return;
btn.prop("disabled", true);
request(url, {})
.done(function (x) {
if (!x.status) {
btn.prop("disabled", false);
return toast("error", x.message);
}
toast("success", x.message);
setTimeout(function () {
location.reload();
}, 600);
})
.fail(function (x) {
btn.prop("disabled", false);
fail(x);
});
});
});
$(document).on("click", ".reject-invoice", function () {
var id = $(this).data("id");
Swal.fire({
icon: "warning",
title: "Tolak invoice?",
input: "textarea",
inputLabel: "Alasan penolakan",
inputValidator: function (v) {
return !String(v || "").trim() ? "Alasan wajib diisi." : undefined;
},
showCancelButton: true,
confirmButtonText: "Tolak",
}).then(function (r) {
if (r.isConfirmed)
request(cfg.base + "sales/reject_invoice/" + id, { reason: r.value })
.done(function (x) {
if (x.status) location.reload();
else toast("error", x.message);
})
.fail(fail);
});
});
$(document).on("click", ".pdf-open", function () {
$("#pdfModal iframe").attr("src", $(this).data("url"));
modal("pdfModal").show();
});
document
.getElementById("pdfModal")
.addEventListener("hidden.bs.modal", function () {
$("#pdfModal iframe").attr("src", "about:blank");
});
function qty(v) {
v = number(v);
return Math.round(v) === v
? new Intl.NumberFormat("id-ID").format(v)
: new Intl.NumberFormat("id-ID", { maximumFractionDigits: 4 }).format(v);
}
function table(rows, cols) {
return (
'<div class="table-responsive"><table class="table table-sm"><thead><tr>' +
cols
.map(function (c) {
return "<th>" + c[0] + "</th>";
})
.join("") +
"</tr></thead><tbody>" +
rows
.map(function (r) {
return (
"<tr>" +
cols
.map(function (c) {
return "<td>" + c[1](r) + "</td>";
})
.join("") +
"</tr>"
);
})
.join("") +
"</tbody></table></div>"
);
}
$(document).on("click", ".detail-invoice", function () {
$.getJSON(cfg.base + "sales/invoice_detail/" + $(this).data("id"))
.done(function (r) {
if (!r.status) return toast("error", r.message);
var i = r.invoice,
body =
'<div class="detail-grid"><div class="detail-card"><small>Customer</small><h5>' +
esc(i.customer_name) +
"</h5><p>" +
esc(i.customer_address || "-") +
'</p></div><div class="detail-card"><small>Invoice</small><h5>' +
esc(i.no_invoice) +
"</h5><p>" +
esc(i.period_start + " — " + i.period_end) +
" · " +
esc(
i.recognition_policy === "accrual"
? "Akrual"
: "Setelah pembayaran",
) +
'</p></div><div class="detail-card wide"><h6>Ringkasan Barang</h6>' +
table(r.lines, [
[
"Tanggal",
function (x) {
return esc(x.service_date);
},
],
[
"Barang",
function (x) {
return (
"<b>" +
esc(x.item_code + " - " + x.nama_item) +
"</b><small>" +
esc(x.specification || "-") +
"</small>"
);
},
],
[
"Qty",
function (x) {
return qty(x.qty);
},
],
[
"Harga",
function (x) {
return money(x.harga);
},
],
[
"Subtotal",
function (x) {
return money(x.subtotal);
},
],
]) +
'</div><div class="detail-card wide"><h6>Detail Barcode</h6>' +
table(r.barcodes, [
[
"Surat Jalan",
function (x) {
return esc(x.delivery_no || "-");
},
],
[
"Barang",
function (x) {
return esc(x.item_code + " - " + x.nama_barang);
},
],
[
"Barcode / SN",
function (x) {
return (
"<b>" +
esc(x.barcode) +
"</b><small>" +
esc(x.serial_number || "-") +
"</small>"
);
},
],
[
"Qty",
function (x) {
return qty(x.qty);
},
],
[
"Gudang",
function (x) {
return esc(x.warehouse_name || "-");
},
],
]) +
'</div><div class="detail-card"><h6>Pembayaran</h6>' +
table(r.payments, [
[
"Tanggal",
function (x) {
return esc(x.tanggal);
},
],
[
"Nomor",
function (x) {
return esc(x.payment_no);
},
],
[
"Alokasi",
function (x) {
return money(x.allocated);
},
],
]) +
'</div><div class="detail-card"><h6>Surat Jalan</h6>' +
r.deliveries
.map(function (x) {
return (
"<p><b>" +
esc(x.delivery_no) +
"</b> · " +
esc(x.delivery_date) +
" · " +
esc(x.status) +
"</p>"
);
})
.join("") +
"</div></div>";
$("#detailBody").html(body);
modal("detailModal").show();
})
.fail(fail);
});
$(document).on("click", ".detail-delivery", function () {
$.getJSON(cfg.base + "sales/delivery_detail/" + $(this).data("id"))
.done(function (r) {
if (!r.status) return toast("error", r.message);
var d = r.delivery;
$("#detailBody").html(
'<div class="detail-grid"><div class="detail-card"><h5>' +
esc(d.delivery_no) +
"</h5><p>" +
esc(d.customer_name) +
"<br>" +
esc(d.customer_address || "-") +
'</p></div><div class="detail-card"><b>' +
esc(d.no_invoice || "-") +
"</b><p>" +
esc(d.delivery_date) +
" · " +
esc(d.warehouse_name || "-") +
" · " +
esc(d.status) +
'</p></div><div class="detail-card wide">' +
table(r.lines, [
[
"Barang",
function (x) {
return (
"<b>" +
esc(x.description) +
"</b><small>" +
esc(x.specification || "-") +
"</small>"
);
},
],
[
"Qty",
function (x) {
return qty(x.qty) + " " + esc(x.unit || "");
},
],
[
"Dikembalikan",
function (x) {
return qty(x.returned_qty);
},
],
]) +
'</div><div class="detail-card wide"><h6>Barcode / Serial</h6>' +
table(r.barcodes, [
[
"Barcode",
function (x) {
return esc(x.barcode);
},
],
[
"Serial",
function (x) {
return esc(x.serial_number || "-");
},
],
[
"Qty",
function (x) {
return qty(x.qty);
},
],
[
"Status",
function (x) {
return esc(x.status);
},
],
]) +
"</div></div>",
);
modal("detailModal").show();
})
.fail(fail);
});
$(document).on("click", ".detail-return", function () {
$.getJSON(cfg.base + "sales/return_detail/" + $(this).data("id"))
.done(function (r) {
if (!r.status) return toast("error", r.message);
var x = r.return;
$("#detailBody").html(
'<div class="detail-grid"><div class="detail-card"><h5>' +
esc(x.return_no) +
"</h5><p>" +
esc(x.customer_name) +
" · " +
esc(x.no_invoice) +
'</p></div><div class="detail-card"><b>' +
esc(x.status) +
"</b><p>" +
esc(x.reason) +
'</p></div><div class="detail-card wide">' +
table(r.lines, [
[
"Barang",
function (l) {
return esc(l.kode_barang + " - " + l.nama_barang);
},
],
[
"Qty",
function (l) {
return qty(l.qty);
},
],
[
"Kondisi",
function (l) {
return esc(l.physical_condition);
},
],
[
"Nilai",
function (l) {
return money(number(l.net_amount) + number(l.tax_amount));
},
],
]) +
'</div><div class="detail-card wide"><h6>Riwayat</h6>' +
r.history
.map(function (h) {
return (
"<p><b>" +
esc(h.to_status) +
"</b> · " +
esc(h.created_at) +
" · " +
esc(h.user_name || "-") +
"<small>" +
esc(h.notes || "") +
"</small></p>"
);
})
.join("") +
"</div></div>",
);
modal("detailModal").show();
})
.fail(fail);
});
function accountSelect() {
return (
'<select class="form-select pay-account">' +
cfg.accounts
.map(function (a) {
return '<option value="' + a.id + '">' + esc(a.text) + "</option>";
})
.join("") +
"</select>"
);
}
function addSource(amount) {
$("#paymentSources").append(
'<div class="row g-2 pay-source mt-1"><div class="col-7">' +
accountSelect() +
'</div><div class="col-4"><input class="form-control pay-source-amount" inputmode="decimal" value="' +
formatInput(amount || 0) +
'"></div><div class="col-1"><button type="button" class="btn btn-outline-danger remove-source">×</button></div></div>',
);
}
$(document).on("click", ".pay-invoice", function () {
$.getJSON(cfg.base + "sales/invoice_detail/" + $(this).data("id"))
.done(function (r) {
if (!r.status) return toast("error", r.message);
var i = r.invoice;
$("#paymentForm")[0].reset();
fileBag = new DataTransfer();
renderFiles();
$("#paymentForm [name=customer_id]").val(i.customer_id);
$("#paymentOrder").html(
'<div class="detail-card"><small>Customer</small><h5>' +
esc(i.customer_name) +
"</h5><b>" +
esc(i.no_invoice) +
"</b>" +
table(r.lines, [
[
"Barang",
function (x) {
return esc(x.item_code + " - " + x.nama_item);
},
],
[
"Qty",
function (x) {
return qty(x.qty);
},
],
[
"Subtotal",
function (x) {
return money(x.subtotal);
},
],
]) +
'<div class="payment-balance"><div><span>Total invoice</span><b>' +
money(i.total) +
"</b></div><div><span>Sudah dibayar</span><b>" +
money(i.total_bayar) +
"</b></div><div><span>Sisa piutang</span><b>" +
money(i.sisa_piutang) +
'</b></div><label class="mt-2">Nominal dialokasikan</label><input class="form-control allocation" data-id="' +
i.id +
'" value="' +
formatInput(i.sisa_piutang) +
'" inputmode="decimal"></div></div>',
);
$("#paymentSources").empty();
addSource(i.sisa_piutang);
calcPayment();
modal("paymentModal").show();
})
.fail(fail);
});
$("#addPaymentSource").on("click", function () {
addSource(0);
});
$(document).on("click", ".remove-source", function () {
if ($(".pay-source").length > 1) $(this).closest(".pay-source").remove();
else $(this).closest(".pay-source").find("input").val("");
calcPayment();
});
$(document).on("input", ".pay-source-amount,.allocation", calcPayment);
function calcPayment() {
var a = 0,
s = 0;
$(".allocation").each(function () {
a += number(this.value);
});
$(".pay-source-amount").each(function () {
s += number(this.value);
});
$("#payAllocated").text(money(a));
$("#paySources").text(money(s));
$("#payDiff")
.text(money(s - a))
.toggleClass("text-danger", Math.abs(s - a) > 0.001);
}
$("#paymentForm").on("submit", function (e) {
e.preventDefault();
var f = new FormData(this),
sources = [],
alloc = {};
$(".pay-source").each(function () {
sources.push({
account_id: $(this).find(".pay-account").val(),
amount: $(this).find(".pay-source-amount").val(),
});
});
$(".allocation").each(function () {
alloc[$(this).data("id")] = this.value;
});
f.append("sources", JSON.stringify(sources));
f.append("allocations", JSON.stringify(alloc));
request(cfg.base + "sales/payment", f, true)
.done(function (r) {
if (!r.status) return toast("error", r.message);
modal("paymentModal").hide();
Swal.fire({
icon: "success",
title: r.message,
showCancelButton: true,
confirmButtonText: "Lihat Bukti Penerimaan",
cancelButtonText: "Tutup",
}).then(function (x) {
if (x.isConfirmed) {
$("#pdfModal iframe").attr(
"src",
cfg.base + "sales/receipt_pdf/" + r.result.payment_id,
);
modal("pdfModal").show();
} else location.reload();
});
})
.fail(fail);
});
$("#payFiles input").on("change", function () {
Array.from(this.files).forEach(function (f) {
fileBag.items.add(f);
});
this.files = fileBag.files;
renderFiles();
});
function renderFiles() {
$("#payFiles .file-thumb").remove();
Array.from(fileBag.files).forEach(function (f, i) {
var url = f.type.indexOf("image/") === 0 ? URL.createObjectURL(f) : "";
$("#payFiles").append(
'<div class="file-thumb">' +
(url
? '<img src="' + url + '">'
: '<i class="bi bi-file-pdf fs-2 text-danger"></i>') +
'<button type="button" data-file="' +
i +
'">×</button><small>' +
esc(f.name.slice(0, 12)) +
"</small></div>",
);
});
$("#payFiles input")[0].files = fileBag.files;
}
$(document).on("click", "#payFiles .file-thumb button", function () {
var next = new DataTransfer(),
remove = Number(this.dataset.file);
Array.from(fileBag.files).forEach(function (f, i) {
if (i !== remove) next.items.add(f);
});
fileBag = next;
renderFiles();
});
$(document).on("click", ".new-return", function () {
$.getJSON(cfg.base + "sales/delivery_detail/" + $(this).data("id"))
.done(function (r) {
if (!r.status) return toast("error", r.message);
$("#returnForm")[0].reset();
$("#returnForm [name=sales_delivery_id]").val(r.delivery.id);
$("#returnLines").html(
"<h6>Barcode yang dapat diretur</h6>" +
r.barcodes
.filter(function (b) {
return number(b.qty) - number(b.returned_qty) > 0;
})
.map(function (b) {
var left = number(b.qty) - number(b.returned_qty);
return (
'<div class="return-row row g-2 align-items-center"><div class="col-md-4"><label><input type="checkbox" class="return-check" data-id="' +
b.id +
'"> <b>' +
esc(b.barcode) +
"</b><small>" +
esc(b.serial_number || "-") +
'</small></label></div><div class="col-md-2"><input class="form-control return-qty" value="' +
left +
'" max="' +
left +
'" inputmode="decimal"></div><div class="col-md-3"><select class="form-select return-condition"><option value="saleable">Layak jual</option><option value="quarantine">Karantina</option><option value="damaged">Rusak</option><option value="lost">Hilang</option></select></div><div class="col-md-3"><input class="form-control return-note" placeholder="Catatan kondisi"></div></div>'
);
})
.join(""),
);
modal("returnModal").show();
})
.fail(fail);
});
$("#returnForm").on("submit", function (e) {
e.preventDefault();
var rows = [];
$(".return-check:checked").each(function () {
var x = $(this).closest(".return-row");
rows.push({
sales_delivery_barcode_id: $(this).data("id"),
qty: x.find(".return-qty").val(),
physical_condition: x.find(".return-condition").val(),
notes: x.find(".return-note").val(),
});
});
if (!rows.length) return toast("warning", "Pilih minimal satu barcode.");
var f = new FormData(this);
f.append("rows", JSON.stringify(rows));
request(cfg.base + "sales/create_return", f, true)
.done(function (r) {
if (r.status) {
modal("returnModal").hide();
toast("success", r.message);
setTimeout(function () {
location.reload();
}, 600);
} else toast("error", r.message);
})
.fail(fail);
});
$(document).on("click", ".new-return", function () {
if (!$('#returnForm [name="attachments[]"]').length)
$("#returnLines").before(
'<div class="mt-3 return-evidence"><label>Bukti foto/PDF <span class="text-danger">*</span></label><input class="form-control" type="file" name="attachments[]" accept="image/*,.pdf,application/pdf" multiple required><small class="text-muted">Maksimal 10 file, masing-masing 5 MB.</small></div>',
);
});
$(document).on("click", ".detail-delivery", function () {
var id = $(this).data("id");
$.getJSON(cfg.base + "sales/delivery_detail/" + id).done(function (r) {
if (!r.status || r.delivery.status !== "draft") return;
setTimeout(function () {
if ($("#deliveryEditForm").length) return;
var d = r.delivery;
$("#detailBody").append(
'<form id="deliveryEditForm" class="detail-card mt-3" enctype="multipart/form-data"><input type="hidden" name="' +
cfg.csrfName +
'" value="' +
cfg.csrfHash +
'"><h6>Lengkapi Data & Bukti Pengiriman</h6><div class="row g-2"><div class="col-md-3"><label>Tanggal kirim</label><input type="date" name="delivery_date" class="form-control" value="' +
esc(d.delivery_date) +
'"></div><div class="col-md-5"><label>Alamat pengiriman</label><input name="address" class="form-control" value="' +
esc(d.address || d.customer_address || "") +
'"></div><div class="col-md-2"><label>Pengemudi</label><input name="driver_name" class="form-control" value="' +
esc(d.driver_name || "") +
'"></div><div class="col-md-2"><label>Kendaraan</label><input name="vehicle_no" class="form-control" value="' +
esc(d.vehicle_no || "") +
'"></div><div class="col-md-3"><label>Kurir</label><input name="courier" class="form-control" value="' +
esc(d.courier || "") +
'"></div><div class="col-md-3"><label>Nomor resi</label><input name="tracking_no" class="form-control" value="' +
esc(d.tracking_no || "") +
'"></div><div class="col-md-3"><label>Penerima</label><input name="recipient_name" class="form-control" value="' +
esc(d.recipient_name || "") +
'"></div><div class="col-md-3"><label>Bukti kirim</label><input type="file" name="attachments[]" class="form-control" accept="image/*,.pdf" multiple></div><div class="col-12"><label>Catatan</label><textarea name="notes" class="form-control">' +
esc(d.notes || "") +
'</textarea></div><div class="col-12 text-end"><button class="btn btn-primary">Simpan Data Pengiriman</button></div></div></form>',
);
$("#deliveryEditForm").on("submit", function (e) {
e.preventDefault();
request(
cfg.base + "sales/update_delivery/" + id,
new FormData(this),
true,
)
.done(function (x) {
if (x.status) {
toast("success", x.message);
modal("detailModal").hide();
setTimeout(function () {
location.reload();
}, 500);
} else toast("error", x.message);
})
.fail(fail);
});
}, 120);
});
});
function formatInput(v) {
return new Intl.NumberFormat("id-ID", {
minimumFractionDigits: 0,
maximumFractionDigits: 2,
}).format(Number(v) || 0);
}
$(document).on(
"blur",
".money-field,.pay-source-amount,.allocation",
function () {
this.value = formatInput(number(this.value));
},
);
if (cfg.sourceOrder) {
Promise.all([
loadCustomers(),
loadItems(),
loadWarehouses(),
$.getJSON(cfg.base + "salesdocuments/detail/" + cfg.sourceOrder),
])
.then(function (result) {
var source = result[3];
if (!source.status) return toast("error", source.message);
$("#invoiceForm").append(
'<input type="hidden" name="source_sales_order_id" value="' +
cfg.sourceOrder +
'">',
);
$("#customerLookup").val(source.document.customer_id);
$("#invoiceForm [name=customer_id]").prop("disabled", false);
$(".line-builder").prepend(
'<div class="alert alert-info source-order-info"><b>Sumber ' +
esc(source.document.document_no) +
"</b><br>" +
source.lines
.map(function (x) {
return esc(
(x.kode_barang || "") +
" - " +
(x.nama_barang || x.description) +
" · " +
qty(x.qty),
);
})
.join("<br>") +
'<small class="d-block mt-1">Pilih kembali setiap barang, gudang, dan barcode agar stok yang dikirim tervalidasi.</small></div>',
);
modal("invoiceModal").show();
})
.catch(fail);
}
if (cfg.focus) {
setTimeout(function () {
$('.detail-invoice[data-id="' + Number(cfg.focus) + '"]').trigger(
"click",
);
}, 100);
}
})(jQuery);