barname
This commit is contained in:
@@ -31,6 +31,7 @@ import { TicketsModule } from "./modules/tickets/tickets.module";
|
||||
import { UploaderModule } from "./modules/uploader/uploader.module";
|
||||
import { UsersModule } from "./modules/users/users.module";
|
||||
import { UtilsModule } from "./modules/utils/utils.module";
|
||||
import { BarnameModule } from "./modules/barname/barname.module";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -67,6 +68,7 @@ import { UtilsModule } from "./modules/utils/utils.module";
|
||||
ChatbotModule,
|
||||
SearchModule,
|
||||
BillsModule,
|
||||
BarnameModule
|
||||
],
|
||||
})
|
||||
export class AppModule implements NestModule {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import {
|
||||
Body, Controller, Delete, Get, Param, Post,
|
||||
Query, UseInterceptors
|
||||
} from "@nestjs/common";
|
||||
import { ApiHeader, ApiOperation } from "@nestjs/swagger";
|
||||
|
||||
import { BarnameService } from "./barname.service";
|
||||
import { BillListQueryDto } from "./dto/bill-list-query.dto";
|
||||
import { CreateBarnameDto } from "./dto/create-barname.dto";
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { BusinessDec } from "../../common/decorators/business.decorator";
|
||||
import { ParamDto } from "../../common/DTO/param.dto";
|
||||
import { BusinessInterceptor } from "../../core/interceptors/business.interceptor";
|
||||
import { Business } from "../businesses/entities/business.entity";
|
||||
import { UserDec } from "../../common/decorators/user.decorator";
|
||||
|
||||
@Controller("barname")
|
||||
@UseInterceptors(BusinessInterceptor)
|
||||
@AuthGuards()
|
||||
export class BarnameController {
|
||||
constructor(private readonly billsService: BarnameService) { }
|
||||
|
||||
@ApiOperation({ summary: "Create water bill" })
|
||||
@Post("water")
|
||||
@ApiHeader({ name: "x-business-id" })
|
||||
createWaterBill(@Body() dto: CreateBarnameDto, @BusinessDec() business: Business, @UserDec("id") userId: string,) {
|
||||
return this.billsService.createBarname(dto, business, userId);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation({ summary: "Create" })
|
||||
@ApiHeader({ name: "x-business-id" })
|
||||
@Post("charge")
|
||||
create(@Body() dto: CreateBarnameDto, @BusinessDec() business: Business, @UserDec("id") userId: string) {
|
||||
return this.billsService.createBarname(dto, business,userId);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Get all bills with filters and pagination" })
|
||||
@Get()
|
||||
@ApiHeader({ name: "x-business-id" })
|
||||
findAll(@Query() queryDto: BillListQueryDto, @BusinessDec("id") businessId: string) {
|
||||
return this.billsService.findAll(queryDto, businessId);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Get a bill by id" })
|
||||
@Get(":id")
|
||||
findOne(@Param() paramDto: ParamDto, @BusinessDec("id") businessId: string) {
|
||||
return this.billsService.findOne(paramDto.id, businessId);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Remove a bill" })
|
||||
@Delete(":id")
|
||||
remove(@Param() paramDto: ParamDto, @BusinessDec("id") businessId: string) {
|
||||
return this.billsService.remove(paramDto.id, businessId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { MikroOrmModule } from "@mikro-orm/nestjs";
|
||||
import { BullModule } from "@nestjs/bullmq";
|
||||
import { Module } from "@nestjs/common";
|
||||
|
||||
import { BarnameController } from "./barname.controller";
|
||||
import { BarnameService } from "./barname.service";
|
||||
import { Barname } from "./entities/barname.entity";
|
||||
import { BusinessesModule } from "../businesses/businesses.module";
|
||||
import { CompaniesModule } from "../companies/companies.module";
|
||||
import { INVOICE } from "../invoices/constants";
|
||||
import { InvoicesModule } from "../invoices/invoices.module";
|
||||
import { NotificationModule } from "../notifications/notifications.module";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
BullModule.registerQueue({ name: INVOICE.QUEUE_NAME }),
|
||||
MikroOrmModule.forFeature([Barname]),
|
||||
CompaniesModule,
|
||||
BusinessesModule,
|
||||
NotificationModule,
|
||||
InvoicesModule,
|
||||
],
|
||||
controllers: [BarnameController],
|
||||
providers: [BarnameService],
|
||||
})
|
||||
export class BarnameModule {}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { EntityManager } from "@mikro-orm/postgresql";
|
||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||
|
||||
import { BillListQueryDto } from "./dto/bill-list-query.dto";
|
||||
import { CreateBarnameDto } from "./dto/create-barname.dto";
|
||||
import { Barname } from "./entities/barname.entity";
|
||||
import { BarnameRepository } from "./repositories/barname.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";
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class BarnameService {
|
||||
readonly SEWAGE_RATE = 0.3;
|
||||
readonly TAX_RATE = 0.1;
|
||||
|
||||
constructor(
|
||||
private readonly em: EntityManager,
|
||||
// private readonly companiesService: CompaniesService,
|
||||
private readonly billRepository: BarnameRepository,
|
||||
) { }
|
||||
|
||||
async createBarname(dto: CreateBarnameDto, business: Business, userId: string) {
|
||||
const { description, driverName, driverPhone, carType, exitAt, origin, plaque, weight,attachments } = dto;
|
||||
|
||||
const company = await this.em.findOne(Company, { business, user: { id: userId }, deletedAt: null });
|
||||
if (!company) throw new BadRequestException(CompanyMessage.COMPANY_NOT_FOUND);
|
||||
|
||||
const bill = this.em.create(Barname,
|
||||
{ carType, exitAt, origin, plaque, weight, business, description, driverName, driverPhone, company,attachments });
|
||||
|
||||
await this.em.persistAndFlush(bill);
|
||||
|
||||
return bill
|
||||
}
|
||||
|
||||
|
||||
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: [] });
|
||||
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 } }, { populate: [] });
|
||||
if (!bill) {
|
||||
throw new BadRequestException("Bill not found");
|
||||
}
|
||||
await this.em.removeAndFlush(bill);
|
||||
return { deleted: true };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsDateString, IsEnum, IsOptional } from "class-validator";
|
||||
|
||||
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||
import { BarnameStatus } from "../enums/bill-type.enum";
|
||||
|
||||
export class BillListQueryDto extends PaginationDto {
|
||||
@IsOptional()
|
||||
@IsEnum(BarnameStatus)
|
||||
@ApiPropertyOptional({ enum: BarnameStatus, description: "Filter by bill type" })
|
||||
status?: BarnameStatus;
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
@ApiPropertyOptional({ description: "Filter bills created since this date", example: "2025-01-01" })
|
||||
since?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
@ApiPropertyOptional({ description: "Filter bills created until this date", example: "2025-12-31" })
|
||||
to?: string;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsArray, IsDateString, IsNotEmpty, IsOptional, IsString, } from "class-validator";
|
||||
|
||||
|
||||
export class CreateBarnameDto {
|
||||
@ApiProperty({ description: "Barname title" })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
plaque: string;
|
||||
|
||||
@ApiProperty({ description: "Barname description" })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
description: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
driverName: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
driverPhone: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
origin: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
weight: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
carType: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsString({each:true})
|
||||
@IsArray()
|
||||
attachments: string[];
|
||||
|
||||
|
||||
@ApiProperty()
|
||||
@IsDateString()
|
||||
exitAt: string;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { PartialType } from "@nestjs/swagger";
|
||||
|
||||
import { CreateBarnameDto } from "./create-barname.dto";
|
||||
|
||||
export class UpdateBillDto extends PartialType(CreateBarnameDto) {}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Entity, EntityRepositoryType, ManyToOne, Opt, Property } from "@mikro-orm/core";
|
||||
|
||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||
import { Business } from "../../businesses/entities/business.entity";
|
||||
import { BarnameRepository } from "../repositories/barname.repository";
|
||||
import { Company } from "../../companies/entities/company.entity";
|
||||
import { BarnameStatus } from "../enums/bill-type.enum";
|
||||
|
||||
@Entity({ repository: () => BarnameRepository })
|
||||
export class Barname extends BaseEntity {
|
||||
@ManyToOne(() => Business, { nullable: false, deleteRule: "cascade" })
|
||||
business!: Business;
|
||||
|
||||
@ManyToOne(() => Company, { nullable: false, deleteRule: "cascade" })
|
||||
company!: Company;
|
||||
|
||||
@Property({ type: 'numeric', autoincrement: true })
|
||||
number!: number & Opt;
|
||||
|
||||
@Property({ type: 'string' })
|
||||
driverName: string;
|
||||
|
||||
@Property({ type: 'string' })
|
||||
driverPhone: string;
|
||||
|
||||
@Property({ type: 'string' })
|
||||
origin: string;
|
||||
|
||||
@Property({ type: 'string' })
|
||||
weight: string;
|
||||
|
||||
@Property({ type: 'string' })
|
||||
carType: string;
|
||||
|
||||
@Property({ type: 'string' })
|
||||
plaque: string;
|
||||
|
||||
@Property({ type: 'string' })
|
||||
description: string;
|
||||
|
||||
|
||||
@Property({ type: 'json' })
|
||||
attachments: string[];
|
||||
|
||||
@Property({ nullable: true })
|
||||
exitAt?: Date;
|
||||
|
||||
@Property()
|
||||
status: BarnameStatus & Opt
|
||||
|
||||
[EntityRepositoryType]?: BarnameRepository;
|
||||
}
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
export enum BarnameStatus {
|
||||
PENDING='pending',
|
||||
COMPLETED='completed'
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import { EntityRepository } from "@mikro-orm/postgresql";
|
||||
|
||||
import { PaginationUtils } from "../../utils/providers/pagination.utils";
|
||||
import { BillListQueryDto } from "../dto/bill-list-query.dto";
|
||||
import { Barname } from "../entities/barname.entity";
|
||||
|
||||
export class BarnameRepository extends EntityRepository<Barname> {
|
||||
async getBillsList(queryDto: BillListQueryDto, businessId: string) {
|
||||
const { limit, skip } = PaginationUtils(queryDto);
|
||||
|
||||
const knex = this.em.getKnex();
|
||||
const query = knex
|
||||
.select("b.*")
|
||||
.select(knex.raw("COUNT(i.id) as invoice_count"))
|
||||
.from("bill as b")
|
||||
.leftJoin("invoice as i", "i.bill_id", "b.id")
|
||||
.where("b.business_id", businessId)
|
||||
.groupBy("b.id")
|
||||
.orderBy("b.created_at", "desc")
|
||||
.limit(limit)
|
||||
.offset(skip);
|
||||
|
||||
// Add filters
|
||||
if (queryDto.status) {
|
||||
query.andWhere("b.status", queryDto.status);
|
||||
}
|
||||
|
||||
if (queryDto.since) {
|
||||
query.andWhere("b.created_at", ">=", new Date(queryDto.since));
|
||||
}
|
||||
|
||||
if (queryDto.to) {
|
||||
query.andWhere("b.created_at", "<=", new Date(queryDto.to));
|
||||
}
|
||||
|
||||
// Execute the query
|
||||
const barname = await query;
|
||||
|
||||
// Get total count for pagination
|
||||
const countQuery = knex("bill").count("* as total").where("business_id", businessId);
|
||||
|
||||
|
||||
if (queryDto.since) {
|
||||
countQuery.andWhere("created_at", ">=", new Date(queryDto.since));
|
||||
}
|
||||
|
||||
if (queryDto.to) {
|
||||
countQuery.andWhere("created_at", "<=", new Date(queryDto.to));
|
||||
}
|
||||
|
||||
const totalResult = await countQuery;
|
||||
const total = Number(totalResult[0].total);
|
||||
|
||||
|
||||
|
||||
return [barname, total];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user