medusa-invoice
Version:
Generate invoice from Medusa
295 lines • 27.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const medusa_1 = require("@medusajs/medusa");
const medusa_2 = require("@medusajs/medusa");
const utils_1 = require("@medusajs/utils");
const invoice_1 = require("../models/invoice");
const document_settings_1 = require("../models/document-settings");
const template_kind_1 = require("./types/template-kind");
const invoice_generator_1 = require("./generators/invoice-generator");
const constants_1 = require("./types/constants");
class InvoiceService extends medusa_1.TransactionBaseService {
constructor(container) {
super(container);
this.orderService = container.orderService;
this.documentInvoiceSettingsService =
container.documentInvoiceSettingsService;
}
calculateTemplateKind(documentSettings, documentInvoiceSettings) {
if (documentInvoiceSettings && documentInvoiceSettings.invoice_template) {
return documentInvoiceSettings.invoice_template;
}
// Legacy
if (documentSettings && documentSettings.invoice_template) {
return documentSettings.invoice_template;
}
return template_kind_1.InvoiceTemplateKind.BASIC;
}
calculateFormatNumber(documentSettings, documentInvoiceSettings) {
if (documentInvoiceSettings &&
documentInvoiceSettings.invoice_number_format) {
return documentInvoiceSettings.invoice_number_format;
}
// Legacy
if (documentSettings && documentSettings.invoice_number_format) {
return documentSettings.invoice_number_format;
}
return undefined;
}
async getNextInvoiceNumber(resetForcedNumber) {
const forcedNumber = await this.documentInvoiceSettingsService.getInvoiceForcedNumber();
if (forcedNumber !== undefined) {
if (resetForcedNumber) {
await this.documentInvoiceSettingsService.resetForcedNumberByCreatingNewSettings();
}
return forcedNumber;
}
const lastInvoice = await this.activeManager_
.getRepository(invoice_1.Invoice)
.createQueryBuilder("invoice")
.orderBy("created_at", "DESC")
.getOne();
if (lastInvoice !== null) {
return (parseInt(lastInvoice.number) + 1).toString();
}
return "1";
}
copySettingsIfPossible(newSettings, lastSettings) {
if (lastSettings) {
newSettings.invoice_number_format = lastSettings.invoice_number_format;
newSettings.invoice_template = lastSettings.invoice_template;
newSettings.store_address = lastSettings.store_address;
newSettings.store_logo_source = lastSettings.store_logo_source;
}
}
async getTestDisplayNumber(formatNumber, forcedNumber) {
const nextNumber = forcedNumber !== undefined
? forcedNumber
: await this.getNextInvoiceNumber();
if (nextNumber) {
return formatNumber
? formatNumber.replace(constants_1.INVOICE_NUMBER_PLACEHOLDER, nextNumber)
: nextNumber;
}
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Neither forced number is set or any order present");
}
async getInvoiceTemplate() {
const documentSettingsRepository = this.activeManager_.getRepository(document_settings_1.DocumentSettings);
const lastDocumentSettings = await documentSettingsRepository
.createQueryBuilder("documentSettings")
.orderBy("created_at", "DESC")
.getOne();
if (lastDocumentSettings) {
return lastDocumentSettings.invoice_template;
}
return undefined;
}
async getStoreLogo() {
const documentSettingsRepository = this.activeManager_.getRepository(document_settings_1.DocumentSettings);
const lastDocumentSettings = await documentSettingsRepository
.createQueryBuilder("documentSettings")
.orderBy("created_at", "DESC")
.getOne();
if (lastDocumentSettings) {
return lastDocumentSettings.store_logo_source;
}
return undefined;
}
async updateStoreLogo(newLogoSource) {
const documentSettingsRepository = this.activeManager_.getRepository(document_settings_1.DocumentSettings);
const lastDocumentSettings = await documentSettingsRepository
.createQueryBuilder("documentSettings")
.leftJoinAndSelect("documentSettings.store_address", "store_address")
.orderBy("documentSettings.created_at", "DESC")
.getOne();
const newDocumentSettings = this.activeManager_.create(document_settings_1.DocumentSettings);
this.copySettingsIfPossible(newDocumentSettings, lastDocumentSettings === null ? undefined : lastDocumentSettings);
newDocumentSettings.store_logo_source = newLogoSource;
const result = await documentSettingsRepository.save(newDocumentSettings);
return result;
}
async updateStoreDocumentAddress(newAddress) {
const newEntry = this.activeManager_.create(medusa_1.Address);
newEntry.company = newAddress.company;
newEntry.city = newAddress.city;
newEntry.address_1 = newAddress.address_1;
newEntry.postal_code = newAddress.postal_code;
newEntry.phone = newAddress.phone;
const resultAddress = await this.activeManager_
.getRepository(medusa_1.Address)
.save(newEntry);
const documentSettingsRepository = this.activeManager_.getRepository(document_settings_1.DocumentSettings);
const lastDocumentSettings = await documentSettingsRepository
.createQueryBuilder("documentSettings")
.leftJoinAndSelect("documentSettings.store_address", "store_address")
.orderBy("documentSettings.created_at", "DESC")
.getOne();
const newDocumentSettings = this.activeManager_.create(document_settings_1.DocumentSettings);
this.copySettingsIfPossible(newDocumentSettings, lastDocumentSettings === null ? undefined : lastDocumentSettings);
newDocumentSettings.store_address = resultAddress;
const result = await documentSettingsRepository.save(newDocumentSettings);
return result;
}
async getLastDocumentSettings() {
const documentSettingsRepository = this.activeManager_.getRepository(document_settings_1.DocumentSettings);
const lastDocumentSettings = await documentSettingsRepository
.createQueryBuilder("documentSettings")
.leftJoinAndSelect("documentSettings.store_address", "store_address")
.orderBy("documentSettings.created_at", "DESC")
.getOne();
if (lastDocumentSettings === null) {
return undefined;
}
return lastDocumentSettings;
}
async getInvoice(invoiceId, includeBuffer = false) {
if (includeBuffer) {
const invoice = await this.activeManager_
.getRepository(invoice_1.Invoice)
.createQueryBuilder("invoice")
.leftJoinAndSelect("invoice.document_settings", "document_settings")
.leftJoinAndSelect("document_settings.store_address", "store_address")
.leftJoinAndSelect("invoice.document_invoice_settings", "document_invoice_settings")
.leftJoinAndSelect("invoice.order", "order")
.where("invoice.id = :invoiceId", { invoiceId: invoiceId })
.getOne();
if (invoice && invoice !== null && invoice.document_settings) {
const order = await this.orderService.retrieveWithTotals(invoice.order.id, {
relations: [
"billing_address",
"shipping_address",
"shipping_methods.shipping_option",
],
});
const calculatedTemplateKind = this.calculateTemplateKind(invoice.document_settings, invoice.document_invoice_settings);
const buffer = await (0, invoice_generator_1.generateInvoice)(calculatedTemplateKind, invoice.document_settings, invoice, order);
return {
invoice: invoice,
buffer: buffer,
};
}
}
const invoice = await this.activeManager_
.getRepository(invoice_1.Invoice)
.createQueryBuilder("invoice")
.where("invoice.id = :invoiceId", { invoiceId: invoiceId })
.getOne();
if (invoice && invoice !== null) {
return {
invoice: invoice,
};
}
return {
invoice: undefined,
buffer: undefined,
};
}
async generateInvoiceForOrder(orderId) {
const order = await this.orderService.retrieveWithTotals(orderId, {
relations: [
"billing_address",
"shipping_address",
"shipping_methods.shipping_option",
],
});
if (order) {
const settings = await this.getLastDocumentSettings();
if (settings) {
const invoiceSettings = await this.documentInvoiceSettingsService.getLastDocumentInvoiceSettings();
if (invoiceSettings) {
const calculatedTemplateKind = this.calculateTemplateKind(settings, invoiceSettings);
const [validationPassed, info] = (0, invoice_generator_1.validateInputForProvidedKind)(calculatedTemplateKind, settings);
if (validationPassed) {
const RESET_FORCED_NUMBER = true;
const nextNumber = await this.getNextInvoiceNumber(RESET_FORCED_NUMBER);
const newEntry = this.activeManager_.create(invoice_1.Invoice);
newEntry.number = nextNumber;
const invoiceFormatNumber = this.calculateFormatNumber(settings, invoiceSettings);
newEntry.display_number = invoiceFormatNumber
? invoiceFormatNumber.replace(constants_1.INVOICE_NUMBER_PLACEHOLDER, newEntry.number)
: newEntry.number;
newEntry.order = order;
newEntry.document_settings = settings;
newEntry.document_invoice_settings = invoiceSettings;
const resultInvoice = await this.activeManager_
.getRepository(invoice_1.Invoice)
.save(newEntry);
const metaDataUpdate = (0, medusa_1.setMetadata)(order, {
invoice_id: resultInvoice.id,
});
order.metadata = metaDataUpdate;
await this.activeManager_.getRepository(medusa_2.Order).save(order);
const buffer = await (0, invoice_generator_1.generateInvoice)(calculatedTemplateKind, settings, resultInvoice, order);
return {
invoice: newEntry,
buffer: buffer,
};
}
else {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, info);
}
}
else {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Retrieve invoice settings failed. Please check if they are set.");
}
}
else {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Retrieve document settings failed. Please check if they are set.");
}
}
else {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Cant retrieve order");
}
}
async generateTestInvoice(templateKind) {
const lastOrder = await this.activeManager_.getRepository(medusa_2.Order).find({
skip: 0,
take: 1,
order: { created_at: "DESC" },
});
if (lastOrder && lastOrder.length > 0) {
const lastOrderWithTotals = await this.orderService.retrieveWithTotals(lastOrder[0].id, {
relations: [
"billing_address",
"shipping_address",
"shipping_methods.shipping_option",
],
});
const settings = await this.getLastDocumentSettings();
if (settings) {
const invoiceSettings = await this.documentInvoiceSettingsService.getLastDocumentInvoiceSettings();
if (invoiceSettings) {
const testInvoice = this.activeManager_.create(invoice_1.Invoice);
const nextNumber = await this.getNextInvoiceNumber();
testInvoice.number = nextNumber;
testInvoice.display_number = invoiceSettings.invoice_number_format
? invoiceSettings.invoice_number_format.replace(constants_1.INVOICE_NUMBER_PLACEHOLDER, testInvoice.number)
: testInvoice.number;
testInvoice.created_at = new Date(Date.now());
const [validationPassed, info] = (0, invoice_generator_1.validateInputForProvidedKind)(templateKind, settings);
if (validationPassed) {
const buffer = await (0, invoice_generator_1.generateInvoice)(templateKind, settings, testInvoice, lastOrderWithTotals);
return {
invoice: testInvoice,
buffer: buffer,
};
}
else {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, info);
}
}
else {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Invoice settings are not defined");
}
}
else {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Document settings are not defined");
}
}
else {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "You need to have at least one order to see preview");
}
}
}
exports.default = InvoiceService;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52b2ljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9pbnZvaWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkNBQWdGO0FBQ2hGLDZDQUF1RDtBQUN2RCwyQ0FBOEM7QUFDOUMsK0NBQTRDO0FBQzVDLG1FQUErRDtBQUcvRCx5REFBNEQ7QUFDNUQsc0VBR3dDO0FBQ3hDLGlEQUErRDtBQUcvRCxNQUFxQixjQUFlLFNBQVEsK0JBQXNCO0lBSWhFLFlBQVksU0FBUztRQUNuQixLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDakIsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDO1FBQzNDLElBQUksQ0FBQyw4QkFBOEI7WUFDakMsU0FBUyxDQUFDLDhCQUE4QixDQUFDO0lBQzdDLENBQUM7SUFFTyxxQkFBcUIsQ0FDM0IsZ0JBQWtDLEVBQ2xDLHVCQUFnRDtRQUVoRCxJQUFJLHVCQUF1QixJQUFJLHVCQUF1QixDQUFDLGdCQUFnQixFQUFFO1lBQ3ZFLE9BQU8sdUJBQXVCLENBQUMsZ0JBQXVDLENBQUM7U0FDeEU7UUFDRCxTQUFTO1FBQ1QsSUFBSSxnQkFBZ0IsSUFBSSxnQkFBZ0IsQ0FBQyxnQkFBZ0IsRUFBRTtZQUN6RCxPQUFPLGdCQUFnQixDQUFDLGdCQUF1QyxDQUFDO1NBQ2pFO1FBQ0QsT0FBTyxtQ0FBbUIsQ0FBQyxLQUFLLENBQUM7SUFDbkMsQ0FBQztJQUVPLHFCQUFxQixDQUMzQixnQkFBa0MsRUFDbEMsdUJBQWdEO1FBRWhELElBQ0UsdUJBQXVCO1lBQ3ZCLHVCQUF1QixDQUFDLHFCQUFxQixFQUM3QztZQUNBLE9BQU8sdUJBQXVCLENBQUMscUJBQXFCLENBQUM7U0FDdEQ7UUFDRCxTQUFTO1FBQ1QsSUFBSSxnQkFBZ0IsSUFBSSxnQkFBZ0IsQ0FBQyxxQkFBcUIsRUFBRTtZQUM5RCxPQUFPLGdCQUFnQixDQUFDLHFCQUFxQixDQUFDO1NBQy9DO1FBRUQs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