@ryanforever/invoice-generator
Version:
invoice-generator API wrapper
222 lines (152 loc) • 4.88 kB
JavaScript
const Logger = require("@ryanforever/logger").v4
const fs = require("fs")
const path = require("path")
const kindof = require("kind-of")
const _ = require("underscore")
const dayjs = require("dayjs")
const Axios = require("axios")
const util = require("util")
const inflection = require("inflection")
const logger = new Logger(__filename, {debug: true})
const label = input => inflection.titleize(inflection.underscore(input))
let timetamp1 = `YYMMDD`
function InvoiceGenerator(config = {}) {
const logger = new Logger(__filename, {debug: config.debug ?? false})
const key = config.key
const defaultName = config.name
const defaultAddress = config.address
const defaultPhone = config.phone
const defaultPaymentTerm = config.paymentTerm || 30
const defaultNotes = config.notes
const defaultLogo = config.logo
if (!key) throw new Error(`missing api key`)
this.defaults = {
name: defaultName,
address: defaultAddress,
phone: defaultPhone,
paymentTerm: defaultPaymentTerm,
logo: defaultLogo,
notes: defaultNotes
}
const axios = Axios.create({
baseURL: "https://invoice-generator.com",
headers: {
Authorization: `Bearer ${key}`
}
})
this.generate = async function(input = {}, save) {
logger.debug(`generate`)
input.fromName = input.fromName || defaultName
input.fromAddress = input.fromAddress || defaultAddress
input.fromPhone = input.fromPhone || defaultPhone
input.dueIn = input.dueIn || defaultPaymentTerm
input.notes = input.notes || defaultNotes
input.logo = input.logo || defaultLogo
let invoice = new Invoice(input)
// logger.log(invoice)
let res = await axios.post("/", invoice, {
responseType: 'arraybuffer',
reponseEncoding: 'binary',
}).catch(err => {
logger.error(err.response.data)
throw new Error(err)
})
// logger.log(res)
let data = res.data
// const byteArray = new TextEncoder().encode(data)
// const buffer = Buffer.from(byteArray.buffer, "utf8")
if (save) fs.writeFileSync("../output/test.pdf", data, "binary")
return {invoice, data}
}
}
function Invoice(data = {}) {
let dateFormat1 = "DD MMM YYYY"
// to/from
let fromName = data.fromName
let fromAddress = data.fromAddress
let fromPhone = data.fromPhone
let fromEmail = data.fromEmail
let toName = data.toName || data.clientName
let toAddress = data.toAddress || data.clientAddress
let toPhone = data.toPhone || data.clientPhone
let toEmail = data.toEmail || data.clientEmail
let title = data.title
let from = concat(fromName, fromAddress, fromPhone, fromEmail)
let to = concat(toName, toAddress, toPhone, toEmail)
let items = []
let inputItems = data.items || data.item
if (inputItems) {
if (kindof(inputItems) == "array") items = inputItems.map(x => new Item(x))
else if (kindof(inputItems) == "object") items.push(new Item(inputItems))
}
// DATE STUFF
let date
if (data.date) date = dayjs(data.date).format(dateFormat1)
else date = date = dayjs().format(dateFormat1)
let dueDate
let dueIn = data.dueIn
if (data.dueIn) {
if (kindof(dueIn) !== "number") throw new Error(`dueIn must be a number that represents # of days from invoice date`)
dueDate = dayjs(date).add(dueIn, "days").format(dateFormat1)
}
// SET CUSTOM FIELDS
let customFields = {
// title: data.title,
"#": data.invoiceNumber || data.number
// invoiceNumber: data.invoiceNumber,
}
let custom_fields = []
for (let [name, value] of Object.entries(customFields)) {
if (!value) continue
custom_fields.push({name: label(name), value})
}
if (data.fields && kindof(data.fields) == "object") {
for (let [name, value] of Object.entries(data.fields)) {
if (!value) continue
custom_fields.push({name: label(name), value})
}
}
// SET MAIN FIELDS
let fields = {
// number: data.title,
logo: data.logo,
from,
to,
ship_to: data.ship_to || data.shipTo,
date,
due_date: dueDate,
notes: undefined,
terms: undefined,
payment_terms: undefined,
custom_fields,
}
for (let [key, val] of Object.entries(data)) {
if (fields.hasOwnProperty(key)) fields[key] = val
}
this.logo = data.logo
this.from = from || data.from
this.to = to || data.to
this.ship_to = data.shipTo || data.ship_to
this.date = date
this.due_date = dueDate
this.number = data.title
this.notes = undefined
this.terms = undefined
this.payment_terms = undefined
this.custom_fields = custom_fields
this.invoice_number_title = ""
fields.items = items
Object.assign(this, fields)
}
function Item(input = {}) {
this.name = input.name
this.quantity = input.quantity || input.qty
this.unit_cost = input.unitCost || input.cost || input.rate
this.description = input.description || input.comment
}
function concat(...args) {
args = args.filter(x => x)
if (!args.length) return undefined
else return args.join("\n")
}
module.exports = InvoiceGenerator