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 { UploaderModule } from "./modules/uploader/uploader.module";
|
||||||
import { UsersModule } from "./modules/users/users.module";
|
import { UsersModule } from "./modules/users/users.module";
|
||||||
import { UtilsModule } from "./modules/utils/utils.module";
|
import { UtilsModule } from "./modules/utils/utils.module";
|
||||||
|
import { BarnameModule } from "./modules/barname/barname.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -67,6 +68,7 @@ import { UtilsModule } from "./modules/utils/utils.module";
|
|||||||
ChatbotModule,
|
ChatbotModule,
|
||||||
SearchModule,
|
SearchModule,
|
||||||
BillsModule,
|
BillsModule,
|
||||||
|
BarnameModule
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule implements NestModule {
|
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