Создать PDF-файл счета-фактуры с использованием HTML-шаблона
Привет, читатели блога dev-gang! Сегодня я познакомлю вас с процессом создания PDF-файла счета-фактуры для вашего серверного приложения или пользовательского сценария, который можно запустить из командной строки. Давайте начнем! 🎉
Для простоты будет использоваться язык программирования Node.js. Механизм шаблонов Handlebars для отделения данных от презентации.
html2pdf.app для преобразования HTML в PDF, но в качестве альтернативы можно также использовать Puppeteer.
Структура проекта
Предположим, мы создаем новый проект «generate-invoice». Сначала создайте каталог с помощью команды mkdirgenerate-invoice
. Затем инициализируйте проект Node.js, введя команду npm init
, и укажите всю необходимую информацию.
Теперь нам нужно установить зависимости, которые будут использоваться. Для этого запустите команду npm i handlebars axios
.
Имея все необходимые зависимости, давайте создадим файл преобразования с помощью команды mkdir src && touch src/generate.js
.
Теперь нам нужно сохранить шаблон, в котором будет предоставлен HTML-код. Создайте для него каталог шаблонов и файл bill.html
с помощью команды mkdir templates && touch templates/invoice.html
.
Этой простой структуры проекта достаточно, чтобы начать писать код. Ваш проект должен выглядеть как это дерево ниже.
├── package-lock.json
├── package.json
├── node_modules
├── src
│ └── generate.js
└── templates
└── invoice.html
Подготовьте шаблон
Прежде чем приступить к процессу конвертации, вам необходимо создать HTML-шаблон для вашего счета. Этот шаблон будет определять макет, содержание и стиль вашего счета в формате PDF.
В Google можно найти множество HTML-шаблонов счетов. Я собираюсь использовать уже созданный, исходный код которого вы можете найти здесь.
В конечном итоге это должно выглядеть следующим образом:
Не стесняйтесь настраивать HTML-шаблон в соответствии с вашими потребностями в области брендинга и выставления счетов. Вы можете обновить шрифты и цвета, добавить логотип своей компании и включить любую необходимую информацию, такую как номер счета, информацию о клиенте и т. д.
Поместите HTML-код вашего шаблона в файл templates/invoice.html
и приступайте к следующему шагу.
Конвертировать HTML в PDF
Во-первых, нам нужно добавить необходимые зависимости в скрипт преобразования.
import fs from 'fs';
import Handlebars from 'handlebars';
import axios from 'axios';
Теперь мы можем загрузить HTML-код счета-фактуры в шаблон Handlebars.
const invoice = fs.readFileSync('./assets/invoice.html', 'utf8');
const template = Handlebars.compile(invoice);
Также нам нужно задать параметры, которые будут привязаны к шаблону, они могут быть взяты из разных мест вашего реального проекта. Например, база данных, файл Excel, аргументы командной строки и т. д. Для простоты я определю эти параметры непосредственно в скрипте.
const params = {
invoiceNr: 'H2P202307-01711',
billTo: 'Anna Smith',
invoiceDate: (new Date()).toDateString(),
paymentDue: (new Date()).toDateString(),
orderId: 112233,
items: [
{description: 'Domain registration', quantity: 2, price: '$10', total: '$20'},
{description: 'Web hosting', quantity: 1, price: '$15', total: '$15'},
{description: 'Consulting', quantity: 1, price: '$500', total: '$500'},
],
subTotal: '$535',
tax: '$53.5',
total: '$588.5',
};
Теперь мы можем обработать шаблон, передав параметры, и получить результат — окончательный HTML-код, который будет преобразован в PDF-документ.
const html = template(params);
Существует несколько вариантов преобразования HTML в PDF, один из которых может быть с помощью проектов с открытым исходным кодом, таких как Puppeteer или wkhtmltopdf. Сейчас для простоты я собираюсь использовать html2pdf.app. Его бесплатный план дает 100 кредитов в месяц, отлично!
Для регистрации и получения бесплатного API-ключа используйте ссылку: https://dash.html2pdf.app/registration.
Когда у вас есть ключ API, давайте завершим часть преобразования.
const apiKey = '******************'; // API key from https://html2pdf.app
const response = await axios.post('https://api.html2pdf.app/v1/generate', {
html,
apiKey,
}, {responseType: 'arraybuffer'});
Для отправки HTML-кода в API преобразования PDF требуется всего несколько строк кода. Теперь необходимо сохранить ответ. Для этого добавьте в свой скрипт приведенную ниже строку кода.
fs.writeFileSync('./assets/invoice.pdf', response.data);
Полный код сценария преобразования выглядит следующим образом:
import fs from 'fs';
import Handlebars from 'handlebars';
import axios from 'axios';
const invoice = fs.readFileSync('./assets/invoice.html', 'utf8');
const template = Handlebars.compile(invoice);
const params = {
invoiceNr: 'H2P202307-01711',
billTo: 'Anna Smith',
invoiceDate: (new Date()).toDateString(),
paymentDue: (new Date()).toDateString(),
orderId: 112233,
items: [
{description: 'Domain registration', quantity: 2, price: '$10', total: '$20'},
{description: 'Web hosting', quantity: 1, price: '$15', total: '$15'},
{description: 'Consulting', quantity: 1, price: '$500', total: '$500'},
],
subTotal: '$535',
tax: '$53.5',
total: '$588.5',
};
const html = template(params);
const apiKey = 'd3a0264f70864...'; // get api key on https://html2pdf.app
const response = await axios.post('https://api.html2pdf.app/v1/generate', {
html,
apiKey,
}, {responseType: 'arraybuffer'});
fs.writeFileSync('./assets/invoice.pdf', response.data);
Вы также можете найти его на GitHub
Заключение
Мне нравится не смешивать бизнес-логику или данные с уровнем представления, и в настоящее время существует гораздо более понятное решение, когда у нас есть шаблон, отделенный от данных.
Простота API html2pdf.app
и его бесплатный план позволяют нам сэкономить время, и всего лишь с помощью нескольких строк кода мы получаем преобразованный PDF-файл, который вы можете сохранить где-нибудь в облаке или каталоге проекта.
Приятного кодирования!