// helper: convert number to Indian-notation words (Crore, Lakh, Thousand, Hundred)
function numberToWords(num) {
const small = [
"",
"One",
"Two",
"Three",
"Four",
"Five",
"Six",
"Seven",
"Eight",
"Nine",
"Ten",
"Eleven",
"Twelve",
"Thirteen",
"Fourteen",
"Fifteen",
"Sixteen",
"Seventeen",
"Eighteen",
"Nineteen",
];
const tens = [
"",
"",
"Twenty",
"Thirty",
"Forty",
"Fifty",
"Sixty",
"Seventy",
"Eighty",
"Ninety",
];
function twoDigit(n) {
if (n < 20) return small[n];
return tens[Math.floor(n / 10)] + (n % 10 ? " " + small[n % 10] : "");
}
let words = "";
const crore = Math.floor(num / 10000000);
num %= 10000000;
if (crore) words += twoDigit(crore) + " Crore ";
const lakh = Math.floor(num / 100000);
num %= 100000;
if (lakh) words += twoDigit(lakh) + " Lakh ";
const thousand = Math.floor(num / 1000);
num %= 1000;
if (thousand) words += twoDigit(thousand) + " Thousand ";
const hundred = Math.floor(num / 100);
num %= 100;
if (hundred) words += small[hundred] + " Hundred ";
if (num) words += (words ? "and " : "") + twoDigit(num) + " ";
return words.trim() || "Zero";
}
if (typeof document !== "undefined") {
document.addEventListener("DOMContentLoaded", function () {
const addItemBtn = document.getElementById("add-item");
const itemsContainer = document.getElementById("items-container");
const form = document.getElementById("quotation-form");
const output = document.getElementById("quotation-output");
const previewContent = document.getElementById("preview-content");
// Add initial empty row
addItemRow();
function generateQuotationHTML(form) {
const data = new FormData(form);
const company = {
name: data.get("company-name"),
address: data.get("company-address"),
phone: data.get("company-phone"),
email: data.get("company-email"),
gstin: data.get("company-gstin"),
};
const customer = {
name: data.get("customer-name"),
address: data.get("customer-address"),
phone: data.get("customer-phone"),
email: data.get("customer-email"),
gstin: data.get("customer-gstin"),
};
const quotationNumber = data.get("quotation-number");
const quotationDate = data.get("quotation-date");
const igstRate = parseFloat(data.get("igst-rate")) || 0;
const freightCharges = parseFloat(data.get("freight-charges")) || 0;
const bank = {
name: data.get("bank-name"),
account: data.get("bank-account"),
ifsc: data.get("bank-ifsc"),
branch: data.get("bank-branch"),
};
const items = [];
itemsContainer.querySelectorAll(".item-card").forEach((card) => {
const desc = card.querySelector(".item-desc").value.trim();
if (desc) {
// Only include cards with description
items.push({
description: desc,
hsn: card.querySelector(".item-hsn").value,
qty:
parseFloat(card.querySelector(".item-qty").value) ||
0,
price:
parseFloat(
card.querySelector(".item-price").value,
) || 0,
discount:
parseFloat(
card.querySelector(".item-discount").value,
) || 0,
amount:
parseFloat(
card
.querySelector(".item-amount")
.textContent.replace("₹", ""),
) || 0,
});
}
});
if (items.length === 0) {
return `
Please add items to generate quotation
`;
}
const { subtotal, igstAmount, _total, rOff, finalTotal } =
calculateQuotation(items, igstRate, freightCharges);
// convert total to words (Rupees and Paise)
const rupeePart = Math.floor(finalTotal);
const paisePart = Math.round((finalTotal - rupeePart) * 100);
const rupeeWords = numberToWords(rupeePart);
const paiseWords = paisePart > 0 ? numberToWords(paisePart) : "";
let html = `
CUSTOMER INFO
${customer.name}
{{cutomer_address}}
GST NO. : ${customer.gstin || ""}
CONTACT NO : ${customer.phone} ${customer.email}
SL NO |
DESCRIPTION |
HSN CODE |
QTY |
UNIT PRICE |
DISCOUNT |
AMOUNT |
`;
items.forEach((item, idx) => {
html += `
${idx + 1} |
${item.description} |
${item.hsn} |
${item.qty} |
${item.price.toFixed(2)} |
${item.discount.toFixed(2)}% |
${item.amount.toFixed(2)} |
`;
});
// Add empty rows to fill the page
for (let i = items.length; i < 20; i++) {
html +=
" | | | | | | |
";
}
html += `
`;
html = html.replace(
"{{address}}",
company.address.replace(/\n/g, "
"),
);
html = html.replace(
"{{cutomer_address}}",
customer.address.replace(/\n/g, "
"),
);
return html;
}
function generateQuotationHTMLForPreview(form) {
const html = generateQuotationHTML(form);
// Remove print button from preview
return html.replace(
/