# lbx-invoice
This packages aims to take care of most of your invoicing concerns, including:
- Generation of continuous invoice numbers by saving the amount of created invoices through one year
- Generation of invoice pdf files in the format PDF-A from a invoice model instance

This library was built with customization in mind, so most things can easily be modified.

# Usage
## Register the component

The minimum required code changes to use the library to its full extend is simply registering it in the `application.ts`:
```typescript
import { BaseInvoiceRepository, LbxInvoiceComponent, NumberInvoicesRepository } from 'lbx-invoice';

export class MyApplication extends BootMixin(ServiceMixin(RepositoryMixin(RestApplication))) {
    constructor(options: ApplicationConfig = {}) {
        // ...
        this.component(LbxInvoiceComponent);
        this.repository(BaseInvoiceRepository);
        this.repository(NumberInvoicesRepository);
        // ...
    }
}
```

If you don't want to use the predefined repositories you can create your own and bind them to the corresponding key in `LbxInvoiceBindings`.

Almost everything above comes from the library out of the box. You only need to create your own PdfService for generating the files.

## Create your own PdfService

```typescript
import { BaseCompanyInfo, BaseInvoice, BasePdfService } from 'lbx-invoice';

const invoicePath: string = path.join(__dirname, '..', '../src/services/invoices');

@injectable({ scope: BindingScope.TRANSIENT })
export class InvoicePdfService extends BasePdfService<BaseInvoice, BaseCompanyInfo> {
    protected readonly TAX_OFFICE?: string = undefined;
    protected readonly TAX_NUMBER?: string = undefined;
    protected readonly IBAN?: string = undefined;
    protected readonly BIC?: string = undefined;
    protected readonly BANK_NAME?: string = undefined;
    protected readonly BANK_CODE?: string = undefined;
    protected readonly BANK_ACCOUNT_NUMBER?: string = undefined;
    protected readonly companyInfo: BaseCompanyInfo = {
        name: 'Example Company',
        fullName: 'Example Company LLC',
        email: 'info@example-company.com',
        phone: '12345 67890123',
        address: {
            street: 'Example street',
            number: '1b',
            postcode: '12345',
            city: 'Example city'
        }
    };

    protected async handleFinishedInvoicePdf(pdfData: string, invoice: BaseInvoice): Promise<void> {
        writeFileSync(path.join(invoicePath, `${invoice.number}.pdf`), pdfData, 'base64');
    }
}
```

## Enjoy!
That's it, now you can use it inside your code:
```typescript
import { BaseInvoice, BaseInvoiceRepository, InvoiceNumberService, LbxInvoiceBindings } from 'lbx-invoice';
// ...
export class ExampleInvoiceController {
    constructor(
        @inject(LbxInvoiceBindings.INVOICE_REPOSITORY)
        private readonly baseInvoiceRepository: BaseInvoiceRepository,
        @service(InvoicePdfService)
        private readonly pdfService: InvoicePdfService,
        @inject(LbxInvoiceBindings.INVOICE_NUMBER_SERVICE)
        private readonly invoiceNumberService: InvoiceNumberService,
        @inject('datasources.db')
        private readonly dataSource: DbDataSource
    ) {}

    @post('/invoices')
    async create(
        @requestBody({
            content: {
                'application/json': {
                    schema: getModelSchemaRef(BaseInvoice, {
                        exclude: ['id', 'number']
                    })
                }
            }
        })
        invoice: Omit<BaseInvoice, 'id'>
    ): Promise<void> {
        const transaction: juggler.Transaction = await this.dataSource.beginTransaction(IsolationLevel.READ_COMMITTED);
        try {
            invoice.number = await this.invoiceNumberService.generateInvoiceNumber(invoice.customerAddressData, transaction);
            const finishedInvoice: BaseInvoice = await this.baseInvoiceRepository.create(invoice, { transaction: transaction });
            await this.pdfService.createInvoicePdf(finishedInvoice);
            await transaction.commit();
        }
        catch (error) {
            await transaction.rollback();
            throw error;
        }
    }
}
```

# Customization
The library is highly customizable through the usage of Bindings.

Almost everything can be overriden by you when you provide a value for the specific Binding:

```typescript
import { LbxInvoiceBindings } from 'lbx-invoice';
// ...
this.bind(LbxInvoiceBindings.INVOICE_REPOSITORY).toClass(MyCustomInvoiceRepository);
// ...
```

All bindings can be accessed under `LbxInvoiceBindings`.