This repository has been archived on 2026-08-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
summernote-editor-override/editor_override/public/js/payment_request.js
T
dirga 705e6f20e9
CI / Server (push) Failing after 46s
summernote
2025-08-28 16:06:15 +07:00

214 lines
9.4 KiB
JavaScript

// helper: format currency (Indonesia style) - untuk fallback client-side rendering
function fmtMoney(n) {
n = Number(n) || 0;
var parts = n.toFixed(2).split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return parts[0] + ',' + parts[1];
}
// Function: build HTML client-side (same logic as template) - dipakai ketika doc belum disimpan
function build_message_html_client(doc, ref_doc) {
var amount = Number(doc.grand_total || doc.amount || 0);
var netto = amount ? (amount / 1.11) : 0;
var ppn = amount - netto;
var qty = 0;
if (ref_doc) {
qty = Number(ref_doc.total_qty || 0);
if (!qty && ref_doc.items) {
for (var i = 0; i < ref_doc.items.length; i++) {
qty += Number(ref_doc.items[i].qty || 0);
}
}
}
if (!qty) qty = 1;
var per_unit = netto / qty;
var html = '';
html += '<div style="font-family: Arial, sans-serif; font-size: 13px; line-height: 1.6;">';
html += '<table border="1" cellspacing="0" cellpadding="6" width="100%" style="border-collapse: collapse;">';
html += '<thead style="background:#f2f2f2;"><tr><th style="width:5%">No</th><th style="width:55%">Nama Barang</th><th style="width:10%;text-align:center">Banyaknya</th><th style="text-align:right;width:15%">Harga Satuan</th><th style="text-align:right;width:15%">Jumlah Satuan</th></tr></thead>';
html += '<tbody>';
html += '<tr>';
html += '<td style="text-align:center;">1</td>';
var name = (ref_doc && ref_doc.items && ref_doc.items.length>0) ? (ref_doc.items[0].item_name || "Nama Barang / Uraian") : "Nama Barang / Uraian";
html += '<td>' + name + '</td>';
html += '<td style="text-align:center;">' + (qty.toFixed(2)) + '</td>';
html += '<td style="text-align:right;">Rp ' + fmtMoney(per_unit) + '</td>';
html += '<td style="text-align:right;">Rp ' + fmtMoney(netto) + '</td>';
html += '</tr>';
html += '<tr><td colspan="4" style="text-align:right;">Diskon</td><td style="text-align:right;">Rp ' + fmtMoney(0) + '</td></tr>';
html += '<tr><td colspan="4" style="text-align:right;">PPN 11%</td><td style="text-align:right;">Rp ' + fmtMoney(ppn) + '</td></tr>';
html += '<tr><td colspan="4" style="text-align:right;font-weight:bold;">Total</td><td style="text-align:right;font-weight:bold;">Rp ' + fmtMoney(amount) + '</td></tr>';
html += '</tbody></table>';
html += '<p style="margin-top:10px;">Terbilang : <b>' + ( (typeof frappe !== 'undefined' && frappe.utils && frappe.utils.money_in_words) ? frappe.utils.money_in_words(amount, (doc.currency || "IDR")) : "") + '</b></p>';
html += '<p style="margin-top:30px; text-align:right;">Jakarta, ' + ((doc.transaction_date) ? doc.transaction_date : ( (typeof frappe !== 'undefined' && frappe.utils && frappe.utils.nowdate) ? frappe.utils.nowdate() : "" )) + '<br>Hormat kami,</p>';
html += '</div>';
return html;
}
// Function: update message - uses server render if docname exists, otherwise client-side render
function update_message(frm) {
// If there's a reference document, fetch it (for client-side rendering)
var ref_doctype = frm.doc.reference_doctype;
var ref_name = frm.doc.reference_name;
var do_server_render = !!frm.doc.name; // prefer server render when doc saved (has name)
if (ref_doctype && ref_name) {
frappe.call({
method: "frappe.client.get",
args: { doctype: ref_doctype, name: ref_name },
callback: function(r) {
var ref_doc = r.message || null;
if (do_server_render) {
// server render (uses api.get_payment_message)
frappe.call({
method: "editor_override.api.get_payment_message",
args: { docname: frm.doc.name },
callback: function(res) {
if (res.message) {
frm.set_value("message", res.message);
frm.refresh_field("message");
}
}
});
} else {
// client-side render for unsaved doc
var html = build_message_html_client(frm.doc, ref_doc);
frm.set_value("message", html);
frm.refresh_field("message");
}
}
});
} else {
// no reference doc
if (do_server_render) {
frappe.call({
method: "editor_override.api.get_payment_message",
args: { docname: frm.doc.name },
callback: function(res) {
if (res.message) {
frm.set_value("message", res.message);
frm.refresh_field("message");
}
}
});
} else {
var html = build_message_html_client(frm.doc, null);
frm.set_value("message", html);
frm.refresh_field("message");
}
}
}
// ===========================
// Payment Term logic (existing) + tie to update_message
// ===========================
frappe.ui.form.on("Payment Request", {
onload: function(frm) {
// set default or initial behaviours if needed
// e.g. df property toggles, default percent, etc. (adapt from your original code)
if (!frm.doc.custom_payment_term_percentage) {
frm.set_value("custom_payment_term_percentage", 100);
}
},
refresh: function(frm) {
// always update message UI on refresh (safe)
update_message(frm);
},
reference_name: function(frm) {
// when reference changes, fetch base amount and refresh message
if (frm.doc.reference_doctype === "Sales Order" && frm.doc.reference_name) {
// fetch SO grand_total and set as amount (default 100% portion)
frappe.call({
method: "frappe.client.get",
args: { doctype: "Sales Order", name: frm.doc.reference_name },
callback: function(r) {
if (r.message && r.message.grand_total) {
// if no custom percent set, set amount to full SO
var portion = frm.doc.custom_payment_term_percentage || 100;
var final_amount = (r.message.grand_total * portion) / 100;
frm.set_value("grand_total", final_amount);
frm.refresh_field("grand_total");
// now update message
update_message(frm);
}
}
});
} else {
update_message(frm);
}
},
custom_payment_term: function(frm) {
var value = frm.doc.custom_payment_term;
if (!value) {
frm.set_value("custom_payment_term_percentage", 100);
// get original amount from SO and refresh message
if (frm.doc.reference_doctype === "Sales Order" && frm.doc.reference_name) {
frappe.call({
method: "frappe.client.get",
args: { doctype: "Sales Order", name: frm.doc.reference_name },
callback: function(r) {
if (r.message && r.message.grand_total) {
frm.set_value("grand_total", r.message.grand_total);
frm.refresh_field("grand_total");
update_message(frm);
}
}
});
} else {
update_message(frm);
}
} else {
// fetch selected Payment Term invoice_portion
frappe.call({
method: "frappe.client.get",
args: {
doctype: "Payment Term",
name: value
},
callback: function(r) {
if (r.message && r.message.invoice_portion !== undefined) {
var portion = r.message.invoice_portion;
frm.set_value("custom_payment_term_percentage", portion);
// calc final amount based on sales order base
if (frm.doc.reference_doctype === "Sales Order" && frm.doc.reference_name) {
frappe.call({
method: "frappe.client.get",
args: { doctype: "Sales Order", name: frm.doc.reference_name },
callback: function(rr) {
if (rr.message && rr.message.grand_total) {
var final_amount = (rr.message.grand_total * portion) / 100;
frm.set_value("grand_total", final_amount);
frm.refresh_field("grand_total");
// Immediately update message to reflect new grand_total
update_message(frm);
}
}
});
} else {
update_message(frm);
}
}
}
});
}
},
// in case grand_total is edited manually
grand_total: function(frm) {
update_message(frm);
}
});