fix: companies

This commit is contained in:
2026-02-17 09:19:11 +03:30
parent f9f397e92a
commit 42d78e15ff
11 changed files with 79 additions and 80 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ import { rateLimitConfig } from "./configs/rateLimit.config";
import { HTTPLogger } from "./core/middlewares/logger.middleware"; import { HTTPLogger } from "./core/middlewares/logger.middleware";
import { AnnouncementsModule } from "./modules/announcements/announcement.module"; import { AnnouncementsModule } from "./modules/announcements/announcement.module";
import { AuthModule } from "./modules/auth/auth.module"; import { AuthModule } from "./modules/auth/auth.module";
import { BillsModule } from './modules/bills/bills.module'; import { BillsModule } from "./modules/bills/bills.module";
import { BusinessesModule } from "./modules/businesses/businesses.module"; import { BusinessesModule } from "./modules/businesses/businesses.module";
import { ChatbotModule } from "./modules/chatbot/chatbot.module"; import { ChatbotModule } from "./modules/chatbot/chatbot.module";
import { CompaniesModule } from "./modules/companies/companies.module"; import { CompaniesModule } from "./modules/companies/companies.module";
+6 -1
View File
@@ -20,5 +20,10 @@ export function getSwaggerDocument(app: NestFastifyApplication) {
.build(); .build();
const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig); const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig);
SwaggerModule.setup("api-docs", app, swaggerDocument); SwaggerModule.setup("api-docs", app, swaggerDocument, {
swaggerOptions: {
docExpansion: "none",
defaultModelsExpandDepth: -1,
},
});
} }
+1 -10
View File
@@ -1,13 +1,4 @@
import { import { Body, Controller, Delete, Get, Param, Post, Query, UseInterceptors } from "@nestjs/common";
Body,
Controller,
Delete,
Get,
Param,
Post,
Query,
UseInterceptors,
} from "@nestjs/common";
import { ApiOperation } from "@nestjs/swagger"; import { ApiOperation } from "@nestjs/swagger";
import { BillsService } from "./bills.service"; import { BillsService } from "./bills.service";
+1 -5
View File
@@ -8,11 +8,7 @@ import { BusinessesModule } from "../businesses/businesses.module";
import { CompaniesModule } from "../companies/companies.module"; import { CompaniesModule } from "../companies/companies.module";
@Module({ @Module({
imports: [ imports: [MikroOrmModule.forFeature([Bill]), CompaniesModule, BusinessesModule],
MikroOrmModule.forFeature([Bill]),
CompaniesModule,
BusinessesModule,
],
controllers: [BillsController], controllers: [BillsController],
providers: [BillsService], providers: [BillsService],
}) })
+21 -24
View File
@@ -1,20 +1,20 @@
import { EntityManager } from '@mikro-orm/postgresql'; import { EntityManager } from "@mikro-orm/postgresql";
import { BadRequestException, Injectable } from '@nestjs/common'; import { BadRequestException, Injectable } from "@nestjs/common";
import dayjs from 'dayjs'; import dayjs from "dayjs";
import Decimal from 'decimal.js'; import Decimal from "decimal.js";
import { BillListQueryDto } from './dto/bill-list-query.dto'; import { BillListQueryDto } from "./dto/bill-list-query.dto";
import { CreateChargeBillDto } from './dto/create-charge-bill.dto'; import { CreateChargeBillDto } from "./dto/create-charge-bill.dto";
import { CreateWaterBillDto } from './dto/create-water-bill.dto'; import { CreateWaterBillDto } from "./dto/create-water-bill.dto";
import { Bill } from './entities/bill.entity'; import { Bill } from "./entities/bill.entity";
import { BillType } from './enums/bill-type.enum'; import { BillType } from "./enums/bill-type.enum";
import { BillsRepository } from './repositories/bill.repository'; import { BillsRepository } from "./repositories/bill.repository";
import { CompanyMessage } from '../../common/enums/message.enum'; import { CompanyMessage } from "../../common/enums/message.enum";
import { Business } from '../businesses/entities/business.entity'; import { Business } from "../businesses/entities/business.entity";
import { Company } from '../companies/entities/company.entity'; import { Company } from "../companies/entities/company.entity";
import { CompaniesService } from '../companies/services/companies.service'; import { CompaniesService } from "../companies/services/companies.service";
import { InvoiceItem } from '../invoices/entities/invoice-item.entity'; import { InvoiceItem } from "../invoices/entities/invoice-item.entity";
import { Invoice } from '../invoices/entities/invoice.entity'; import { Invoice } from "../invoices/entities/invoice.entity";
@Injectable() @Injectable()
export class BillsService { export class BillsService {
@@ -33,7 +33,7 @@ export class BillsService {
const bill = em.create(Bill, { type: BillType.WATER_BILL, business }); const bill = em.create(Bill, { type: BillType.WATER_BILL, business });
em.persist(bill); em.persist(bill);
const dueDate = dayjs().add(dueDays, 'day').toDate(); const dueDate = dayjs().add(dueDays, "day").toDate();
const uniqueCompanyIds = [...new Set(values.map((v) => v.companyId))]; const uniqueCompanyIds = [...new Set(values.map((v) => v.companyId))];
const companies = await this.companiesService.findByIds(uniqueCompanyIds, em); const companies = await this.companiesService.findByIds(uniqueCompanyIds, em);
@@ -59,7 +59,7 @@ export class BillsService {
}); });
const invoiceItem = em.create(InvoiceItem, { const invoiceItem = em.create(InvoiceItem, {
name: 'قبض آب', name: "قبض آب",
count: value.waterUsage, count: value.waterUsage,
unitPrice: new Decimal(waterRate), unitPrice: new Decimal(waterRate),
discount: new Decimal(0), discount: new Decimal(0),
@@ -90,7 +90,7 @@ export class BillsService {
const bill = em.create(Bill, { type: BillType.MONTHLY_CHARGE, business }); const bill = em.create(Bill, { type: BillType.MONTHLY_CHARGE, business });
em.persist(bill); em.persist(bill);
const dueDate = dayjs().add(dueDays, 'day').toDate(); const dueDate = dayjs().add(dueDays, "day").toDate();
const companies = await this.companiesService.findAllBybusinessId(business.id, em); const companies = await this.companiesService.findAllBybusinessId(business.id, em);
@@ -110,7 +110,7 @@ export class BillsService {
}); });
const invoiceItem = em.create(InvoiceItem, { const invoiceItem = em.create(InvoiceItem, {
name: 'قبض شارژ', name: "قبض شارژ",
count: 1, count: 1,
unitPrice: subtotal, unitPrice: subtotal,
discount: new Decimal(0), discount: new Decimal(0),
@@ -142,10 +142,7 @@ export class BillsService {
} }
async findOne(id: string, businessId: string) { async findOne(id: string, businessId: string) {
const bill = await this.billRepository.findOne( const bill = await this.billRepository.findOne({ id, business: { id: businessId } }, { populate: ["invoices"] });
{ id, business: { id: businessId } },
{ populate: ["invoices"] },
);
if (!bill) { if (!bill) {
throw new BadRequestException("Bill not found"); throw new BadRequestException("Bill not found");
} }
@@ -2,12 +2,11 @@ import { ApiProperty } from "@nestjs/swagger";
import { IsInt } from "class-validator"; import { IsInt } from "class-validator";
export class CreateChargeBillDto { export class CreateChargeBillDto {
@ApiProperty() @ApiProperty()
@IsInt() @IsInt()
chargeRate: number; chargeRate: number;
@ApiProperty()
@IsInt()
dueDays:number;
@ApiProperty()
@IsInt()
dueDays: number;
} }
+21 -20
View File
@@ -3,30 +3,31 @@ import { Type } from "class-transformer";
import { ArrayMinSize, IsArray, IsInt, IsNotEmpty, IsUUID, ValidateNested } from "class-validator"; import { ArrayMinSize, IsArray, IsInt, IsNotEmpty, IsUUID, ValidateNested } from "class-validator";
export class ValueDto { export class ValueDto {
@IsNotEmpty({ message: ' BillMessage.COMPANY_ID_REQUIRED' }) @IsNotEmpty({ message: " BillMessage.COMPANY_ID_REQUIRED" })
@ApiProperty({ description: "شناسه شرکت", }) @ApiProperty({ description: "شناسه شرکت" })
@IsUUID("7") @IsUUID("7")
companyId: string; companyId: string;
@ApiProperty() @ApiProperty()
@IsNotEmpty({ message: 'BillMessage.WATER_USAGE_REQUIRED' }) @IsNotEmpty({ message: "BillMessage.WATER_USAGE_REQUIRED" })
@IsInt() @IsInt()
@ApiProperty({ description: "مصرف آب", example: 100 }) @ApiProperty({ description: "مصرف آب", example: 100 })
waterUsage: number; waterUsage: number;
} }
export class CreateWaterBillDto { export class CreateWaterBillDto {
@ApiProperty() @ApiProperty()
@IsInt() @IsInt()
waterRate:number; waterRate: number;
@ApiProperty() @ApiProperty()
@IsInt() @IsInt()
dueDays:number; dueDays: number;
@Type(() => ValueDto) @ApiProperty({ example: [{ companyId: "", waterUsage: 100 }] })
@IsArray() @Type(() => ValueDto)
@ArrayMinSize(1) @IsArray()
@ValidateNested({ each: true }) @ArrayMinSize(1)
values: ValueDto[]; @ValidateNested({ each: true })
values: ValueDto[];
} }
+2 -2
View File
@@ -1,5 +1,5 @@
import { PartialType } from '@nestjs/swagger'; import { PartialType } from "@nestjs/swagger";
import { CreateWaterBillDto } from './create-water-bill.dto'; import { CreateWaterBillDto } from "./create-water-bill.dto";
export class UpdateBillDto extends PartialType(CreateWaterBillDto) {} export class UpdateBillDto extends PartialType(CreateWaterBillDto) {}
+7 -8
View File
@@ -8,15 +8,14 @@ import { BillsRepository } from "../repositories/bill.repository";
@Entity({ repository: () => BillsRepository }) @Entity({ repository: () => BillsRepository })
export class Bill extends BaseEntity { export class Bill extends BaseEntity {
@Enum({ items: () => BillType })
type: BillType;
@Enum({ items: () => BillType }) @ManyToOne(() => Business, { nullable: false, deleteRule: "cascade" })
type: BillType; business!: Business;
@ManyToOne(() => Business, { nullable: false, deleteRule: "cascade" }) @OneToMany(() => Invoice, (invoice) => invoice.bill, { cascade: [Cascade.PERSIST, Cascade.REMOVE], orphanRemoval: true })
business!: Business; invoices = new Collection<Invoice>(this);
@OneToMany(() => Invoice, (invoice) => invoice.bill, { cascade: [Cascade.PERSIST, Cascade.REMOVE], orphanRemoval: true }) [EntityRepositoryType]?: BillsRepository;
invoices = new Collection<Invoice>(this);
[EntityRepositoryType]?: BillsRepository;
} }
@@ -47,6 +47,13 @@ export class CompaniesController {
return this.companiesService.getCompaniesList(query, businessId); return this.companiesService.getCompaniesList(query, businessId);
} }
@Get("list/all")
@AuthGuards()
@ApiOperation({ summary: "get companies list without pagination (admin)" })
getAllCompanies(@BusinessDec("id") businessId: string) {
return this.companiesService.findAllBybusinessId2(businessId);
}
@Get("list/public") @Get("list/public")
@ApiOperation({ summary: "get companies list (public)" }) @ApiOperation({ summary: "get companies list (public)" })
getCompaniesListPublic(@Query() queryDto: CompanyListPublicQueryDto, @BusinessDec("id") businessId: string) { getCompaniesListPublic(@Query() queryDto: CompanyListPublicQueryDto, @BusinessDec("id") businessId: string) {
@@ -29,7 +29,7 @@ export class CompaniesService {
private readonly passwordService: PasswordService, private readonly passwordService: PasswordService,
private readonly em: EntityManager, private readonly em: EntityManager,
private readonly companyRequestRepository: CompanyRequestRepository, private readonly companyRequestRepository: CompanyRequestRepository,
) { } ) {}
async create(createDto: CreateCompanyDto, business: Business) { async create(createDto: CreateCompanyDto, business: Business) {
const em = this.em.fork(); const em = this.em.fork();
@@ -461,7 +461,7 @@ export class CompaniesService {
async findByIds(comapnyIds: string[], em: EntityManager) { async findByIds(comapnyIds: string[], em: EntityManager) {
const companies = await em.find(Company, { const companies = await em.find(Company, {
id: { $in: comapnyIds } id: { $in: comapnyIds },
}); });
if (companies.length !== comapnyIds.length) throw new BadRequestException(CompanyMessage.COMPANY_NOT_FOUND); if (companies.length !== comapnyIds.length) throw new BadRequestException(CompanyMessage.COMPANY_NOT_FOUND);
return companies; return companies;
@@ -471,4 +471,8 @@ export class CompaniesService {
const companies = await em.find(Company, { business: { id: businessId } }); const companies = await em.find(Company, { business: { id: businessId } });
return companies; return companies;
} }
async findAllBybusinessId2(businessId: string) {
const companies = await this.em.find(Company, { business: { id: businessId } });
return companies;
}
} }