388 lines
9.9 KiB
JavaScript
388 lines
9.9 KiB
JavaScript
erpnext.setup_einvoice_actions = (doctype) => {
|
|
frappe.ui.form.on(doctype, {
|
|
async refresh(frm) {
|
|
if (frm.doc.docstatus == 2) return;
|
|
|
|
const res = await frappe.call({
|
|
method: 'erpnext.regional.india.e_invoice.utils.validate_eligibility',
|
|
args: { doc: frm.doc }
|
|
});
|
|
const invoice_eligible = res.message;
|
|
|
|
if (!invoice_eligible) return;
|
|
|
|
const { doctype, irn, irn_cancelled, ewaybill, eway_bill_cancelled, name, qrcode_image, __unsaved } = frm.doc;
|
|
|
|
const add_custom_button = (label, action) => {
|
|
if (!frm.custom_buttons[label]) {
|
|
frm.add_custom_button(label, action, __('E Invoicing'));
|
|
}
|
|
};
|
|
|
|
if (!irn && !__unsaved) {
|
|
const action = () => {
|
|
if (frm.doc.__unsaved) {
|
|
frappe.throw(__('Please save the document to generate IRN.'));
|
|
}
|
|
frappe.call({
|
|
method: 'erpnext.regional.india.e_invoice.utils.get_einvoice',
|
|
args: { doctype, docname: name },
|
|
freeze: true,
|
|
callback: (res) => {
|
|
const einvoice = res.message;
|
|
show_einvoice_preview(frm, einvoice);
|
|
}
|
|
});
|
|
};
|
|
|
|
add_custom_button(__("Generate IRN"), action);
|
|
}
|
|
|
|
if (irn && !irn_cancelled && !ewaybill) {
|
|
const fields = [
|
|
{
|
|
"label": "Reason",
|
|
"fieldname": "reason",
|
|
"fieldtype": "Select",
|
|
"reqd": 1,
|
|
"default": "1-Duplicate",
|
|
"options": ["1-Duplicate", "2-Data Entry Error", "3-Order Cancelled", "4-Other"]
|
|
},
|
|
{
|
|
"label": "Remark",
|
|
"fieldname": "remark",
|
|
"fieldtype": "Data",
|
|
"reqd": 1
|
|
}
|
|
];
|
|
const action = () => {
|
|
const d = new frappe.ui.Dialog({
|
|
title: __("Cancel IRN"),
|
|
fields: fields,
|
|
primary_action: function() {
|
|
const data = d.get_values();
|
|
frappe.call({
|
|
method: 'erpnext.regional.india.e_invoice.utils.cancel_irn',
|
|
args: {
|
|
doctype,
|
|
docname: name,
|
|
irn: irn,
|
|
reason: data.reason.split('-')[0],
|
|
remark: data.remark
|
|
},
|
|
freeze: true,
|
|
callback: () => frm.reload_doc() || d.hide(),
|
|
error: () => d.hide()
|
|
});
|
|
},
|
|
primary_action_label: __('Submit')
|
|
});
|
|
d.show();
|
|
};
|
|
add_custom_button(__("Cancel IRN"), action);
|
|
}
|
|
|
|
if (irn && !irn_cancelled && !ewaybill) {
|
|
const action = () => {
|
|
const d = new frappe.ui.Dialog({
|
|
title: __('Generate E-Way Bill'),
|
|
size: "large",
|
|
fields: get_ewaybill_fields(frm),
|
|
primary_action: function() {
|
|
const data = d.get_values();
|
|
frappe.call({
|
|
method: 'erpnext.regional.india.e_invoice.utils.generate_eway_bill',
|
|
args: {
|
|
doctype,
|
|
docname: name,
|
|
irn,
|
|
...data
|
|
},
|
|
freeze: true,
|
|
callback: () => {
|
|
frappe.show_alert({
|
|
message: __('E-Way Bill Generated successfully'),
|
|
indicator: 'green'
|
|
}, 7);
|
|
frm.reload_doc();
|
|
d.hide();
|
|
},
|
|
error: () => {
|
|
frappe.show_alert({
|
|
message: __('E-Way Bill was not Generated'),
|
|
indicator: 'red'
|
|
}, 7);
|
|
d.hide();
|
|
}
|
|
});
|
|
},
|
|
primary_action_label: __('Submit')
|
|
});
|
|
d.fields_dict.transporter.df.onchange = function () {
|
|
const transporter = d.fields_dict.transporter.value;
|
|
if (transporter) {
|
|
frappe.db.get_value('Supplier', transporter, ['gst_transporter_id', 'supplier_name'])
|
|
.then(({ message }) => {
|
|
d.set_value('gst_transporter_id', message.gst_transporter_id);
|
|
d.set_value('transporter_name', message.supplier_name);
|
|
});
|
|
} else {
|
|
d.set_value('gst_transporter_id', '');
|
|
d.set_value('transporter_name', '');
|
|
}
|
|
};
|
|
d.fields_dict.driver.df.onchange = function () {
|
|
const driver = d.fields_dict.driver.value;
|
|
if (driver) {
|
|
frappe.db.get_value('Driver', driver, ['full_name'])
|
|
.then(({ message }) => {
|
|
d.set_value('driver_name', message.full_name);
|
|
});
|
|
} else {
|
|
d.set_value('driver_name', '');
|
|
}
|
|
};
|
|
d.show();
|
|
};
|
|
|
|
add_custom_button(__("Generate E-Way Bill"), action);
|
|
}
|
|
|
|
if (irn && ewaybill && !irn_cancelled && !eway_bill_cancelled) {
|
|
const action = () => {
|
|
// This confirm is added to just reduce unnecesory API calls. All required logic is implemented on server side.
|
|
frappe.confirm(
|
|
__("Have you cancelled e-way bill on the portal?"),
|
|
() => {
|
|
frappe.call({
|
|
method: "erpnext.regional.india.e_invoice.utils.cancel_eway_bill",
|
|
args: { doctype, docname: name },
|
|
freeze: true,
|
|
callback: () => frm.reload_doc(),
|
|
});
|
|
},
|
|
() => {
|
|
frappe.show_alert(
|
|
{
|
|
message: __(
|
|
"Please cancel e-way bill on the portal first."
|
|
),
|
|
indicator: "orange",
|
|
},
|
|
5
|
|
);
|
|
}
|
|
);
|
|
};
|
|
add_custom_button(__("Cancel E-Way Bill"), action);
|
|
}
|
|
|
|
if (irn && !irn_cancelled) {
|
|
let is_qrcode_attached = false;
|
|
if (qrcode_image && frm.attachments) {
|
|
let attachments = frm.attachments.get_attachments();
|
|
if (attachments.length != 0) {
|
|
for (let i = 0; i < attachments.length; i++) {
|
|
if (attachments[i].file_url == qrcode_image) {
|
|
is_qrcode_attached = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!is_qrcode_attached) {
|
|
const action = () => {
|
|
if (frm.doc.__unsaved) {
|
|
frappe.throw(__('Please save the document to generate QRCode.'));
|
|
}
|
|
const dialog = frappe.msgprint({
|
|
title: __("Generate QRCode"),
|
|
message: __("Generate and attach QR Code using IRN?"),
|
|
primary_action: {
|
|
action: function() {
|
|
frappe.call({
|
|
method: 'erpnext.regional.india.e_invoice.utils.generate_qrcode',
|
|
args: { doctype, docname: name },
|
|
freeze: true,
|
|
callback: () => frm.reload_doc() || dialog.hide(),
|
|
error: () => dialog.hide()
|
|
});
|
|
}
|
|
},
|
|
primary_action_label: __('Yes')
|
|
});
|
|
dialog.show();
|
|
};
|
|
add_custom_button(__("Generate QRCode"), action);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
const get_ewaybill_fields = (frm) => {
|
|
return [
|
|
{
|
|
fieldname: "eway_part_a_section_break",
|
|
fieldtype: "Section Break",
|
|
label: "Part A",
|
|
},
|
|
{
|
|
fieldname: "transporter",
|
|
label: "Transporter",
|
|
fieldtype: "Link",
|
|
options: "Supplier",
|
|
default: frm.doc.transporter,
|
|
},
|
|
{
|
|
fieldname: "transporter_name",
|
|
label: "Transporter Name",
|
|
fieldtype: "Data",
|
|
read_only: 1,
|
|
default: frm.doc.transporter_name,
|
|
depends_on: "transporter",
|
|
},
|
|
{
|
|
fieldname: "part_a_column_break",
|
|
fieldtype: "Column Break",
|
|
},
|
|
{
|
|
fieldname: "gst_transporter_id",
|
|
label: "GST Transporter ID",
|
|
fieldtype: "Data",
|
|
default: frm.doc.gst_transporter_id,
|
|
},
|
|
{
|
|
fieldname: "distance",
|
|
label: "Distance (in km)",
|
|
fieldtype: "Float",
|
|
default: frm.doc.distance,
|
|
description: 'Set as zero to auto calculate distance using pin codes',
|
|
},
|
|
{
|
|
fieldname: "eway_part_b_section_break",
|
|
fieldtype: "Section Break",
|
|
label: "Part B",
|
|
},
|
|
{
|
|
fieldname: "mode_of_transport",
|
|
label: "Mode of Transport",
|
|
fieldtype: "Select",
|
|
options: `\nRoad\nAir\nRail\nShip`,
|
|
default: frm.doc.mode_of_transport,
|
|
},
|
|
{
|
|
fieldname: "gst_vehicle_type",
|
|
label: "GST Vehicle Type",
|
|
fieldtype: "Select",
|
|
options: `Regular\nOver Dimensional Cargo (ODC)`,
|
|
depends_on: 'eval:(doc.mode_of_transport === "Road")',
|
|
default: frm.doc.gst_vehicle_type,
|
|
},
|
|
{
|
|
fieldname: "vehicle_no",
|
|
label: "Vehicle No",
|
|
fieldtype: "Data",
|
|
default: frm.doc.vehicle_no,
|
|
},
|
|
{
|
|
fieldname: "part_b_column_break",
|
|
fieldtype: "Column Break",
|
|
},
|
|
{
|
|
fieldname: "lr_date",
|
|
label: "Transport Receipt Date",
|
|
fieldtype: "Date",
|
|
default: frm.doc.lr_date,
|
|
},
|
|
{
|
|
fieldname: "lr_no",
|
|
label: "Transport Receipt No",
|
|
fieldtype: "Data",
|
|
default: frm.doc.lr_no,
|
|
},
|
|
{
|
|
fieldname: "driver",
|
|
label: "Driver",
|
|
fieldtype: "Link",
|
|
options: "Driver",
|
|
default: frm.doc.driver,
|
|
},
|
|
{
|
|
fieldname: "driver_name",
|
|
label: "Driver Name",
|
|
fieldtype: "Data",
|
|
fetch_from: "driver.full_name",
|
|
read_only: 1,
|
|
default: frm.doc.driver_name,
|
|
depends_on: "driver",
|
|
},
|
|
];
|
|
};
|
|
|
|
const request_irn_generation = (frm) => {
|
|
frappe.call({
|
|
method: 'erpnext.regional.india.e_invoice.utils.generate_irn',
|
|
args: { doctype: frm.doc.doctype, docname: frm.doc.name },
|
|
freeze: true,
|
|
callback: () => frm.reload_doc()
|
|
});
|
|
};
|
|
|
|
const get_preview_dialog = (frm, action) => {
|
|
const dialog = new frappe.ui.Dialog({
|
|
title: __("Preview"),
|
|
size: "large",
|
|
fields: [
|
|
{
|
|
"label": "Preview",
|
|
"fieldname": "preview_html",
|
|
"fieldtype": "HTML"
|
|
}
|
|
],
|
|
primary_action: () => action(frm) || dialog.hide(),
|
|
primary_action_label: __('Generate IRN')
|
|
});
|
|
return dialog;
|
|
};
|
|
|
|
const show_einvoice_preview = (frm, einvoice) => {
|
|
const preview_dialog = get_preview_dialog(frm, request_irn_generation);
|
|
|
|
// initialize e-invoice fields
|
|
einvoice["Irn"] = einvoice["AckNo"] = ''; einvoice["AckDt"] = frappe.datetime.nowdate();
|
|
frm.doc.signed_einvoice = JSON.stringify(einvoice);
|
|
|
|
// initialize preview wrapper
|
|
const $preview_wrapper = preview_dialog.get_field("preview_html").$wrapper;
|
|
$preview_wrapper.html(
|
|
`<div>
|
|
<div class="print-preview">
|
|
<div class="print-format"></div>
|
|
</div>
|
|
<div class="page-break-message text-muted text-center text-medium margin-top"></div>
|
|
</div>`
|
|
);
|
|
|
|
frappe.call({
|
|
method: "frappe.www.printview.get_html_and_style",
|
|
args: {
|
|
doc: frm.doc,
|
|
print_format: "GST E-Invoice",
|
|
no_letterhead: 1
|
|
},
|
|
callback: function (r) {
|
|
if (!r.exc) {
|
|
$preview_wrapper.find(".print-format").html(r.message.html);
|
|
const style = `
|
|
.print-format { box-shadow: 0px 0px 5px rgba(0,0,0,0.2); padding: 0.30in; min-height: 80vh; }
|
|
.print-preview { min-height: 0px; }
|
|
.modal-dialog { width: 720px; }`;
|
|
|
|
frappe.dom.set_style(style, "custom-print-style");
|
|
preview_dialog.show();
|
|
}
|
|
}
|
|
});
|
|
};
|