@sourceloop/ctrl-plane-subscription-service
Version:
Subscription management microservice for SaaS control plane.
212 lines (204 loc) • 6.48 kB
text/typescript
import {BillingComponentBindings, IService} from 'loopback4-billing';
import {inject} from '@loopback/core';
import {Filter, repository} from '@loopback/repository';
import {
del,
get,
getModelSchemaRef,
param,
patch,
post,
requestBody,
} from '@loopback/rest';
import {OPERATION_SECURITY_SPEC, STATUS_CODE} from '@sourceloop/core';
import {authenticate, STRATEGY} from 'loopback4-authentication';
import {authorize} from 'loopback4-authorization';
import {AddressDto} from '../models';
import {BillingCustomer} from '../models/billing-customer.model';
import {CustomerDto} from '../models/dto/customer-dto.model';
import {PermissionKey} from '../permissions';
import {InvoiceRepository} from '../repositories';
import {BillingCustomerRepository} from '../repositories/billing-customer.repository';
const basePath = '/billing-customer';
export class BillingCustomerController {
constructor(
(BillingCustomerRepository)
public billingCustomerRepository: BillingCustomerRepository,
(InvoiceRepository)
public invoiceRepository: InvoiceRepository,
(BillingComponentBindings.BillingProvider)
private readonly billingProvider: IService,
) {}
({
permissions: [PermissionKey.CreateBillingCustomer],
})
(STRATEGY.BEARER, {
passReqToCallback: true,
})
(basePath, {
security: OPERATION_SECURITY_SPEC,
responses: {
[STATUS_CODE.OK]: {
description: 'BillingCustomer model instance',
content: {
'application/json': {
schema: getModelSchemaRef(CustomerDto, {
title: 'NewBillingCustomer',
}),
},
},
},
},
})
async create(
({
content: {
'application/json': {
schema: getModelSchemaRef(CustomerDto, {
title: 'NewCustomer',
exclude: ['id'],
}),
},
},
})
customerDto: Omit<CustomerDto, 'id'>,
.header.string('tenantId') tenantId: string,
): Promise<CustomerDto> {
const customer = await this.billingProvider.createCustomer(customerDto);
await this.billingCustomerRepository.create(
new BillingCustomer({
tenantId,
customerId: customer.id,
}),
);
return new CustomerDto({
id: customer.id,
firstName: customer.firstName,
lastName: customer.lastName,
email: customer.email,
company: customer.company,
phone: customer.phone,
billingAddress: new AddressDto({
firstName: customer.billingAddress?.firstName,
lastName: customer.billingAddress?.lastName,
email: customer.billingAddress?.email,
company: customer.billingAddress?.company,
phone: customer.billingAddress?.phone,
city: customer.billingAddress?.city,
state: customer.billingAddress?.state,
zip: customer.billingAddress?.zip,
country: customer.billingAddress?.country,
}),
});
}
({
permissions: [PermissionKey.GetBillingCustomer],
})
(STRATEGY.BEARER, {
passReqToCallback: true,
})
(basePath, {
security: OPERATION_SECURITY_SPEC,
responses: {
[STATUS_CODE.OK]: {
description: 'BillingCustomer model ',
content: {'application/json': {schema: getModelSchemaRef(CustomerDto)}},
},
},
})
async getCustomer(
.filter(BillingCustomer) filter?: Filter<BillingCustomer>,
): Promise<{customerDetails: CustomerDto; info: BillingCustomer}> {
const customers = await this.billingCustomerRepository.find(filter);
if (customers.length === 0) {
throw new Error('Customer is not present');
}
const customer = await this.billingProvider.getCustomers(
customers[0].customerId,
);
return {
customerDetails: new CustomerDto({
firstName: customer.firstName,
lastName: customer.lastName,
email: customer.email,
company: customer.company,
phone: customer.phone,
billingAddress: new AddressDto({
firstName: customer.billingAddress?.firstName,
lastName: customer.billingAddress?.lastName,
email: customer.billingAddress?.email,
company: customer.billingAddress?.company,
phone: customer.billingAddress?.phone,
city: customer.billingAddress?.city,
state: customer.billingAddress?.state,
zip: customer.billingAddress?.zip,
country: customer.billingAddress?.country,
}),
}),
info: customers[0],
};
}
({
permissions: [PermissionKey.UpdateBillingCustomer],
})
(STRATEGY.BEARER, {
passReqToCallback: true,
})
(`${basePath}/{tenantId}`, {
security: OPERATION_SECURITY_SPEC,
responses: {
[STATUS_CODE.NO_CONTENT]: {
description: 'BillingCustomer PATCH success',
},
},
})
async updateById(
.path.string('tenantId') tenantId: string,
({
content: {
'application/json': {
schema: getModelSchemaRef(CustomerDto, {partial: true}),
},
},
})
customerDto: Partial<CustomerDto>,
): Promise<void> {
const customers = await this.billingCustomerRepository.find({
where: {tenantId: tenantId},
});
if (customers.length === 0) {
throw new Error(`Customer with tenantId ${tenantId} is not present`);
}
await this.billingProvider.updateCustomerById(
customers[0].customerId,
customerDto,
);
}
({
permissions: [PermissionKey.DeleteBillingCustomer],
})
(STRATEGY.BEARER, {
passReqToCallback: true,
})
(`${basePath}/{tenantId}`, {
security: OPERATION_SECURITY_SPEC,
responses: {
[STATUS_CODE.NO_CONTENT]: {
description: 'BillingCustomer DELETE success',
},
},
})
async deleteById(
.path.string('tenantId') tenantId: string,
): Promise<void> {
const customer = await this.billingCustomerRepository.find({
where: {tenantId: tenantId},
});
if (customer.length === 0) {
throw new Error(' Customer with tenantId is not present');
}
await this.billingProvider.deleteCustomer(customer[0].customerId);
await this.invoiceRepository.deleteAll({billingCustomerId: customer[0].id});
await this.billingCustomerRepository.deleteById(customer[0].id);
}
}