@sourceloop/ctrl-plane-subscription-service
Version:
Subscription management microservice for SaaS control plane.
105 lines (95 loc) • 3.87 kB
text/typescript
import {BindingScope, inject, injectable} from '@loopback/context';
import {AddressDto, ChargeDto, InvoiceDto} from '../models';
import {BillingComponentBindings, IService} from 'loopback4-billing';
import {repository} from '@loopback/repository';
import {InvoiceRepository, BillingCustomerRepository} from '../repositories';
import {TransactionDto} from '../models/dto/transaction-dto.model';
({scope: BindingScope.TRANSIENT})
export class BillingInvoiceService {
constructor(
(BillingCustomerRepository)
private readonly billingCustomerRepository: BillingCustomerRepository,
(InvoiceRepository)
private readonly invoiceRepository: InvoiceRepository,
(BillingComponentBindings.BillingProvider)
private readonly billingProvider: IService,
) {}
async createInvoice(invoiceDto: Omit<InvoiceDto, 'id' | 'status'>) {
const customer = await this.billingCustomerRepository.find({
where: {customerId: invoiceDto.customerId},
});
if (customer.length === 0) {
throw new Error('Customer with tenantId is not present');
}
const invoice = await this.billingProvider.createInvoice(invoiceDto);
const charges = invoice.charges?.map(
charge =>
new ChargeDto({amount: charge.amount, description: charge.description}),
);
const invoiceInfo = await this.invoiceRepository.create({
invoiceId: invoice.id,
invoiceStatus: invoice.status,
billingCustomerId: customer[0].id,
});
return new InvoiceDto({
id: invoiceInfo.id,
customerId: invoice.customerId,
charges: charges,
status: invoice.status,
shippingAddress: new AddressDto({
firstName: invoice.shippingAddress?.firstName ?? '',
lastName: invoice.shippingAddress?.lastName ?? '',
email: invoice.shippingAddress?.email ?? '',
company: invoice.shippingAddress?.company,
phone: invoice.shippingAddress?.phone,
city: invoice.shippingAddress?.city ?? '',
state: invoice.shippingAddress?.state ?? '',
zip: invoice.shippingAddress?.zip ?? '',
country: invoice.shippingAddress?.country ?? '',
}),
options: invoice.options,
currencyCode: invoice.currencyCode,
});
}
async getInvoice(invoiceId: string) {
const invoice = await this.billingProvider.retrieveInvoice(invoiceId);
const charges = invoice.charges?.map(
charge =>
new ChargeDto({amount: charge.amount, description: charge.description}),
);
return new InvoiceDto({
customerId: invoice.customerId,
charges: charges,
status: invoice.status,
shippingAddress: new AddressDto({
firstName: invoice.shippingAddress?.firstName ?? '',
lastName: invoice.shippingAddress?.lastName ?? '',
email: invoice.shippingAddress?.email ?? '',
company: invoice.shippingAddress?.company,
phone: invoice.shippingAddress?.phone,
city: invoice.shippingAddress?.city ?? '',
state: invoice.shippingAddress?.state ?? '',
zip: invoice.shippingAddress?.zip ?? '',
country: invoice.shippingAddress?.country ?? '',
}),
options: invoice.options,
});
}
async applyPayment(invoiceId: string, transactionDto: TransactionDto) {
const invoiceInfo = await this.invoiceRepository.findById(invoiceId);
await this.billingProvider.applyPaymentSourceForInvoice(
invoiceInfo.invoiceId,
transactionDto,
);
}
async deleteInvoice(invoiceId: string) {
const invoice = await this.invoiceRepository.find({
where: {invoiceId: invoiceId},
});
if (invoice.length === 0) {
throw new Error('Invoice with invoiceId is not present');
}
await this.billingProvider.deleteInvoice(invoiceId);
await this.invoiceRepository.deleteById(invoice[0].id);
}
}