add: bill module
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import dayjs from 'dayjs';
|
||||
import Decimal from 'decimal.js';
|
||||
|
||||
import { BillListQueryDto } from './dto/bill-list-query.dto';
|
||||
import { CreateChargeBillDto } from './dto/create-charge-bill.dto';
|
||||
import { CreateWaterBillDto } from './dto/create-water-bill.dto';
|
||||
import { Bill } from './entities/bill.entity';
|
||||
import { BillType } from './enums/bill-type.enum';
|
||||
import { BillsRepository } from './repositories/bill.repository';
|
||||
import { CompanyMessage } from '../../common/enums/message.enum';
|
||||
import { Business } from '../businesses/entities/business.entity';
|
||||
import { Company } from '../companies/entities/company.entity';
|
||||
import { CompaniesService } from '../companies/services/companies.service';
|
||||
import { InvoiceItem } from '../invoices/entities/invoice-item.entity';
|
||||
import { Invoice } from '../invoices/entities/invoice.entity';
|
||||
|
||||
@Injectable()
|
||||
export class BillsService {
|
||||
constructor(
|
||||
private readonly em: EntityManager,
|
||||
private readonly companiesService: CompaniesService,
|
||||
private readonly billRepository: BillsRepository,
|
||||
) {}
|
||||
|
||||
async createWaterBill(dto: CreateWaterBillDto, business: Business) {
|
||||
const { values, waterRate, dueDays } = dto;
|
||||
const em = this.em.fork();
|
||||
|
||||
try {
|
||||
await em.begin();
|
||||
|
||||
const bill = em.create(Bill, { type: BillType.WATER_BILL, business });
|
||||
em.persist(bill);
|
||||
const dueDate = dayjs().add(dueDays, 'day').toDate();
|
||||
|
||||
const uniqueCompanyIds = [...new Set(values.map((v) => v.companyId))];
|
||||
const companies = await this.companiesService.findByIds(uniqueCompanyIds, em);
|
||||
const companyMap = new Map<string, Company>(companies.map((c) => [c.id, c]));
|
||||
|
||||
for (const value of values) {
|
||||
const subtotal = new Decimal(waterRate).mul(value.waterUsage);
|
||||
const tax = subtotal.mul(0.1);
|
||||
const totalPrice = subtotal.add(tax);
|
||||
const company = companyMap.get(value.companyId);
|
||||
if (!company) {
|
||||
throw new BadRequestException(CompanyMessage.COMPANY_NOT_FOUND);
|
||||
}
|
||||
|
||||
const invoice = em.create(Invoice, {
|
||||
company,
|
||||
totalPrice,
|
||||
originalPrice: totalPrice,
|
||||
dueDate,
|
||||
tax,
|
||||
business,
|
||||
bill,
|
||||
});
|
||||
|
||||
const invoiceItem = em.create(InvoiceItem, {
|
||||
name: 'قبض آب',
|
||||
count: value.waterUsage,
|
||||
unitPrice: new Decimal(waterRate),
|
||||
discount: new Decimal(0),
|
||||
totalPrice,
|
||||
invoice,
|
||||
});
|
||||
invoice.items.add(invoiceItem);
|
||||
|
||||
em.persist(invoice);
|
||||
}
|
||||
|
||||
await em.flush();
|
||||
await em.commit();
|
||||
|
||||
return bill;
|
||||
} catch (error) {
|
||||
await em.rollback();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async createChargeBill(dto: CreateChargeBillDto, business: Business) {
|
||||
const { chargeRate, dueDays } = dto;
|
||||
const em = this.em.fork();
|
||||
|
||||
try {
|
||||
await em.begin();
|
||||
|
||||
const bill = em.create(Bill, { type: BillType.MONTHLY_CHARGE, business });
|
||||
em.persist(bill);
|
||||
const dueDate = dayjs().add(dueDays, 'day').toDate();
|
||||
|
||||
const companies = await this.companiesService.findAllBybusinessId(business.id, em);
|
||||
|
||||
for (const company of companies) {
|
||||
const subtotal = new Decimal(chargeRate);
|
||||
const tax = subtotal.mul(0.1);
|
||||
const totalPrice = subtotal.add(tax);
|
||||
|
||||
const invoice = em.create(Invoice, {
|
||||
company,
|
||||
totalPrice,
|
||||
originalPrice: totalPrice,
|
||||
dueDate,
|
||||
tax,
|
||||
business,
|
||||
bill,
|
||||
});
|
||||
|
||||
const invoiceItem = em.create(InvoiceItem, {
|
||||
name: 'قبض شارژ',
|
||||
count: 1,
|
||||
unitPrice: subtotal,
|
||||
discount: new Decimal(0),
|
||||
totalPrice,
|
||||
invoice,
|
||||
});
|
||||
invoice.items.add(invoiceItem);
|
||||
|
||||
em.persist(invoice);
|
||||
}
|
||||
|
||||
await em.flush();
|
||||
await em.commit();
|
||||
|
||||
return bill;
|
||||
} catch (error) {
|
||||
await em.rollback();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(queryDto: BillListQueryDto, businessId: string) {
|
||||
const [bills, count] = await this.billRepository.getBillsList(queryDto, businessId);
|
||||
return {
|
||||
bills,
|
||||
count,
|
||||
paginate: true,
|
||||
};
|
||||
}
|
||||
|
||||
async findOne(id: string, businessId: string) {
|
||||
const bill = await this.billRepository.findOne(
|
||||
{ id, business: { id: businessId } },
|
||||
{ populate: ["invoices"] },
|
||||
);
|
||||
if (!bill) {
|
||||
throw new BadRequestException("Bill not found");
|
||||
}
|
||||
return { bill };
|
||||
}
|
||||
|
||||
async remove(id: string, businessId: string) {
|
||||
const bill = await this.billRepository.findOne({
|
||||
id,
|
||||
business: { id: businessId },
|
||||
});
|
||||
if (!bill) {
|
||||
throw new BadRequestException("Bill not found");
|
||||
}
|
||||
await this.em.removeAndFlush(bill);
|
||||
return { deleted: true };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user