This is my print format which is created using JS library. I need this same format for sales invoice. If I am writing this same code in custom print format then it is not working.
How do I use this code in ERPNext.
const taxInvoice = () => {
const doc = new jsPDF()
const smallerWidth = 45
const smallerHeight = 45
// Add thumbnail image as full-size cover image on the first page
const logoImg = '/icons/common/pdf/tax-invoice/houseit-simplified-indigo.png'
const invoiceLogo = '/icons/common/pdf/tax-invoice/invoice.png'
const commonSeal = '/icons/common/pdf/tax-invoice/houseit-common-seal.png'
doc.addImage(logoImg, 'PNG', 150, 0, smallerWidth, smallerHeight)
const invoiceTo = [
{
invoiceTo: 'customer name',
toTRN: '00000000000000000',
address: 'xyz addresss',
},
]
const invoiceFrom = [
{
invoiveFrom: 'company name ',
reference: 'HI-00300',
fromTRN: '000000000000000000',
contact: {
email: 'E : account@gmail.com',
tel: 'M : 00000',
mobile: 'M : 00000',
},
},
]
let salePriceValue = 84197.0
let commission = 7135.76
const invoiceDetails = [
{
project: {
project: 'Empire Estate',
unit: '613',
},
size: '440 sq.Ft',
startDate: '-',
salePrice: `AED ${numeral(salePriceValue).format()}`,
rate: '1%',
commissionAmmountExlVAT: `AED ${numeral(commission).format()}`,
},
]
const houseitBankDetails = [
{
accountName: 'company name',
bankName: 'EMIRATES NBD',
accountNumber: '000000000000',
ibanNumber: '000000000000000000000',
branch: 'branch',
},
]
const invoiceDate = moment().format('Do MMM YYYY')
const invoiceNo = 'Hi-009876'
// Calculate the width of the text
const textWidth =
(doc.getStringUnitWidth('Tax Invoice') * doc.internal.getFontSize()) /
doc.internal.scaleFactor
// Calculate the X-coordinate for centering the text
let centerX = (doc.internal.pageSize.width - textWidth) / 2
let yPos = 29
// Set the font size and text
doc.setFontSize(16)
doc.setFont('helvetica', 'bold')
doc.text('Tax Invoice', centerX, 35)
doc.addImage(invoiceLogo, 'PNG', 15, yPos, 25, 24)
yPos = yPos + 30
doc.setFontSize(10)
doc.setFont('helvetica', 'normal')
doc.text('Invoice Date :', 18, yPos - 2)
doc.text(invoiceDate, 40, yPos - 2)
doc.text('Invoice No :', 18, yPos + 3)
doc.text(invoiceNo, 40, yPos + 3)
// Display Invoice To details
doc.text('Invoice To :', 18, yPos + 13)
doc.text(invoiceTo[0].invoiceTo, 40, yPos + 13)
doc.text('TRN :', 18, yPos + 19)
doc.text(invoiceTo[0].toTRN, 40, yPos + 19)
// Manually split the address into three lines
const address = invoiceTo[0].address
const addressLines = address.split(/\s+/)
const maxLineLength = 45 // Maximum characters per line
const addressLine1 = addressLines.slice(0, 5).join(' ') // First 6 words
const addressLine2 = addressLines.slice(5, 9).join(' ') // Next 6 words
const addressLine3 = addressLines.slice(9).join(' ') // Remaining words
// Display each line of the address separately
doc.text('Address :', 18, yPos + 25) // Address label
doc.text(addressLine1, 40, yPos + 25) // First line of the address
doc.text(addressLine2, 40, yPos + 31) // Second line of the address
doc.text(addressLine3, 40, yPos + 37) // Third line of the address
// Display Invoice From details to the right side
doc.text('Invoice From :', 115, yPos + 13) // Adjust X-coordinate
doc.text(invoiceFrom[0].invoiveFrom, 139, yPos + 13) // Adjust X-coordinate
doc.text('Reference No :', 115, yPos + 19) // Adjust X-coordinate
doc.text(invoiceFrom[0].reference, 139, yPos + 19) // Adjust X-coordinate
doc.text('TRN :', 115, yPos + 25) // Adjust X-coordinate
doc.text(invoiceFrom[0].fromTRN, 139, yPos + 25) // Adjust X-coordinate
// Display contact details
doc.text('Contact :', 115, yPos + 31) // Adjust X-coordinate
doc.text(invoiceFrom[0].contact.email, 139, yPos + 31) // Adjust X-coordinate for email
// Split mobile and telephone numbers into two lines
const mobileAndTel = `${invoiceFrom[0].contact.mobile}, ${invoiceFrom[0].contact.tel}`
doc.text(mobileAndTel, 139, yPos + 37) // Adju
yPos = yPos + 45
doc.setFontSize(10)
doc.setFont('helvetica', 'bold')
doc.setTextColor(80, 80, 80)
doc.text(
'Sub : Service Towards Agency Commission for Off-plan Sale in Empire Estate - Arjan Dubai.U.A.E',
18,
yPos + 5,
)
// Define table dimensions and cell padding
const tableX = 18 // X-coordinate of the table
const tableY = yPos + 13 // Y-coordinate of the table
const cellWidths = [31, 25, 25, 27, 19, 49] // Widths of each cell
const cellHeights = 18 // Height of each cell - Adjusted for header
const numRows = invoiceDetails.length // Number of rows in the table
const headerHeight = 20 // Adjusted height of the header row
const vatAmount = (salePriceValue / 100) * 5 // VAT Amount
const totalAmount = salePriceValue + commission + vatAmount // Total Amount Inc. VAT
// Draw table background
doc.setFillColor(240) // Light gray color
doc.rect(
tableX,
tableY,
cellWidths.reduce((a, b) => a + b, 0),
headerHeight + numRows * cellHeights,
'F',
)
// Draw table header
doc.setDrawColor(0)
doc.setFillColor(249, 249, 249)
doc.setFontSize(10)
doc.setFont('helvetica', 'bold')
doc.rect(
tableX,
tableY,
cellWidths.reduce((a, b) => a + b, 0),
headerHeight,
'F',
)
let currentX = tableX
const headers = [
'Project Details',
'Size',
`Sale / Rent\nDate`,
'Sale Price',
'Rate',
'Commission Amount Excl VAT',
] // Adjusted headers without line break
for (let i = 0; i < cellWidths.length; i++) {
// Draw text with wrapping
const textLines = doc.splitTextToSize(headers[i], cellWidths[i])
doc.text(textLines, currentX + 2, tableY + headerHeight / 2) // Adjusted position
currentX += cellWidths[i]
}
// Draw table rows
let currentY = tableY + headerHeight
for (let i = 0; i < numRows; i++) {
// Alternate row colors
if (i % 2 === 0) {
doc.setFillColor(249)
} else {
doc.setFillColor(249)
}
// Draw row background
doc.rect(
tableX,
currentY,
cellWidths.reduce((a, b) => a + b, 0),
cellHeights,
'F',
)
// Draw row content
currentX = tableX
doc.setFont('helvetica', 'normal')
const rowData = Object.values(invoiceDetails[i])
// Adjusted rendering for the project object details
doc.text(
`${rowData[0].project}\n\nUnit: ${rowData[0].unit}`,
currentX + 2,
currentY + 5,
{ align: 'left', valign: 'middle' },
)
currentX += cellWidths[0]
for (let j = 1; j < cellWidths.length; j++) {
doc.text(String(rowData[j]), currentX + 2, currentY + 8, {
align: 'left',
valign: 'middle',
})
currentX += cellWidths[j]
}
// Draw bottom border for the row content
doc.setDrawColor(0)
doc.line(
tableX,
currentY + cellHeights,
tableX + cellWidths.reduce((a, b) => a + b, 0),
currentY + cellHeights,
)
// Move to the next row
currentY += cellHeights
}
// Calculate the end X-coordinate of the upper table
const upperTableEndX =
tableX + cellWidths.slice(0, 5).reduce((a, b) => a + b, 0)
const cellWidth = cellWidths[5] / 2 // Equally divide the width for two cells
// Draw additional rows below the currentY position
for (let i = 0; i < 2; i++) {
const startY = currentY + i * cellHeights // Y-coordinate of the row
// Draw cell for Key
doc.setDrawColor(0)
doc.setFillColor(249, 249, 249)
const keyX = upperTableEndX
doc.rect(keyX, startY, cellWidth, cellHeights, 'F')
doc.setFontSize(9)
doc.text(
i === 0 ? 'VAT 5%\nAmount' : 'Total Amount\nInc.VAT',
keyX + 2,
startY + 8,
{ align: 'left', valign: 'middle' },
)
// Draw cell for Value
doc.setDrawColor(0)
doc.setFillColor(249, 249, 249)
const valueX = keyX + cellWidth
doc.rect(valueX, startY, cellWidth, cellHeights, 'F')
doc.text(
i === 0
? `AED ${numeral(vatAmount).format()}`
: `AED ${numeral(totalAmount).format()}`,
valueX + 20,
startY + 8,
{
align: 'right',
valign: 'middle',
},
)
// Draw left, right, middle, and bottom borders
doc.setDrawColor(0, 0, 0)
doc.line(keyX, startY + cellHeights, keyX + cellWidth, startY + cellHeights) // Bottom border below Key cell
doc.line(
valueX,
startY + cellHeights,
valueX + cellWidth,
startY + cellHeights,
) // Bottom border below Value cell
doc.line(keyX, startY, keyX, startY + cellHeights) // Left border
doc.line(
valueX + cellWidth,
startY,
valueX + cellWidth,
startY + cellHeights,
) // Right border
doc.line(
keyX + cellWidth,
startY + cellHeights,
valueX,
startY + cellHeights - 18,
) // Bottom border
}
// Draw table borders including bottom and right border
doc.setDrawColor(0)
doc.setLineWidth(0.1)
currentX = tableX
currentY = tableY
for (let i = 0; i <= cellWidths.length; i++) {
doc.line(
currentX,
tableY,
currentX,
tableY + headerHeight + numRows * cellHeights,
) // Vertical border
currentX += cellWidths[i]
}
for (let i = 0; i <= numRows; i++) {
doc.line(
tableX,
currentY,
tableX + cellWidths.reduce((a, b) => a + b, 0),
currentY,
) // Horizontal border
currentY += cellHeights
}
yPos = currentY + 10
doc.setFontSize(10)
doc.setFont('helvetica', 'bold')
doc.text(
`Total Amount in Words (AED) :\n${toWords.convert(numeral(totalAmount).format('0.00'))}`,
18,
yPos,
)
yPos = yPos + 15
doc.text(`Company Bank Details :`, 18, yPos)
// Draw bank details
doc.setFontSize(10)
doc.setFont('helvetica', 'normal')
yPos += 8 // Move down slightly for the first line of bank details
houseitBankDetails.forEach((bank, index) => {
const startX = 18
const startY = yPos + index * 25 + 3
// Draw bank details
doc.text(`Account Name : ${bank.accountName}`, startX, startY)
doc.text(`Bank Name : ${bank.bankName}`, startX, startY + 7)
doc.text(`Account Number : ${bank.accountNumber}`, startX, startY + 14)
doc.text(`IBAN Number : ${bank.ibanNumber}`, startX, startY + 21)
doc.text(`Branch : ${bank.branch}`, startX, startY + 28)
})
yPos = yPos + 43
doc.setFontSize(11)
doc.text('for company ', 18, yPos)
doc.addImage(commonSeal, 'PNG', 60, yPos + 1, 50, 32)
doc.text('Authorised Signatory', 18, yPos + 30)
doc.setFontSize(8)
// Define the y-coordinate for the footer
const footerY = yPos + 30
// Set font size and alignment
doc.setFontSize(10)
doc.setTextColor(0, 0, 0) // Black color
doc.setFont('helvetica', 'normal') // Set font and font style
// Define the text for each line
const line1 =
'comapy details'
const line2 =
'company adddress'
const line3 = 'company link.com'
// Calculate the width of the page
const pageWidth = doc.internal.pageSize.getWidth()
// Center and draw each line of text
centerText(doc, line1, footerY + 17)
centerText(doc, line2, footerY + 22)
doc.setFont('helvetica', 'bold')
centerText(doc, line3, footerY + 32)
// Function to center text horizontally
function centerText(doc, text, y) {
const textWidth = doc.getTextWidth(text) // Get the width of the text
const x = (pageWidth - textWidth) / 2 // Calculate the x-coordinate to center the text
doc.text(text, x, y) // Draw the text
}
doc.save('.conmpany-tax-invoice')
}
Output
I need this same format for sales invoice but how to use this code, I did this in print format doctype, but it does not work please guide me how to achieve this.