feat: add stock keeping units management
- Created migration to drop `type` column from `stock_keeping_units` table. - Added `Guild` model to Prisma schema. - Implemented `BusinessActivitiesQueryService` for querying business activities. - Developed `GoodsSharedService` for handling goods creation and updates. - Introduced DTOs for creating and updating stock keeping units. - Created controller and service for managing stock keeping units. - Implemented response DTOs for stock keeping units service. - Established module for stock keeping units management.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { BusinessActivitiesQueryService } from '@/common/services/businessActivities/business-activities-query.service'
|
||||
import { PrismaModule } from '@/prisma/prisma.module'
|
||||
import { Module } from '@nestjs/common'
|
||||
import { BusinessActivitiesController } from './business-activities.controller'
|
||||
@@ -12,6 +13,6 @@ import { ConsumerBusinessActivityGoodsModule } from './goods/goods.module'
|
||||
ConsumerBusinessActivityGoodsModule,
|
||||
],
|
||||
controllers: [BusinessActivitiesController],
|
||||
providers: [BusinessActivitiesService],
|
||||
providers: [BusinessActivitiesService, BusinessActivitiesQueryService],
|
||||
})
|
||||
export class ConsumerBusinessActivitiesModule {}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { BusinessActivitiesQueryService } from '@/common/services/businessActivities/business-activities-query.service'
|
||||
import { BusinessActivitySelect } from '@/generated/prisma/models'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { Injectable } from '@nestjs/common'
|
||||
@@ -5,37 +6,28 @@ import { ResponseMapper } from 'common/response/response-mapper'
|
||||
|
||||
@Injectable()
|
||||
export class BusinessActivitiesService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
defaultSelect: BusinessActivitySelect = {
|
||||
id: true,
|
||||
name: true,
|
||||
economic_code: true,
|
||||
created_at: true,
|
||||
partner_token: true,
|
||||
fiscal_id: true,
|
||||
invoice_number_sequence: true,
|
||||
guild: {
|
||||
select: {
|
||||
id: true,
|
||||
code: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
|
||||
license_activation: {
|
||||
select: {
|
||||
id: true,
|
||||
starts_at: true,
|
||||
expires_at: true,
|
||||
license: {
|
||||
select: {
|
||||
activation: {
|
||||
select: {
|
||||
account_allocations: {
|
||||
select: {
|
||||
id: true,
|
||||
account_id: true,
|
||||
defaultSelect: BusinessActivitySelect
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly businessActivitiesQueryService: BusinessActivitiesQueryService,
|
||||
) {
|
||||
this.defaultSelect = {
|
||||
...this.businessActivitiesQueryService.baseSelect,
|
||||
invoice_number_sequence: true,
|
||||
license_activation: {
|
||||
select: {
|
||||
id: true,
|
||||
starts_at: true,
|
||||
expires_at: true,
|
||||
license: {
|
||||
select: {
|
||||
activation: {
|
||||
select: {
|
||||
account_allocations: {
|
||||
select: {
|
||||
id: true,
|
||||
account_id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -43,7 +35,7 @@ export class BusinessActivitiesService {
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
private readonly prepareBusinessActivityResponse = (businessActivity: any) => {
|
||||
@@ -64,22 +56,23 @@ export class BusinessActivitiesService {
|
||||
}
|
||||
|
||||
async findAll(consumer_id: string) {
|
||||
const businessActivities = await this.prisma.businessActivity.findMany({
|
||||
where: {
|
||||
const businessActivities =
|
||||
await this.businessActivitiesQueryService.findAllByConsumer(
|
||||
consumer_id,
|
||||
},
|
||||
select: this.defaultSelect,
|
||||
})
|
||||
this.defaultSelect,
|
||||
)
|
||||
return ResponseMapper.list(
|
||||
businessActivities.map(this.prepareBusinessActivityResponse),
|
||||
)
|
||||
}
|
||||
|
||||
async findOne(consumer_id: string, id: string) {
|
||||
const businessActivity = await this.prisma.businessActivity.findUniqueOrThrow({
|
||||
where: { consumer_id, id },
|
||||
select: this.defaultSelect,
|
||||
})
|
||||
const businessActivity = await this.businessActivitiesQueryService.findOneByConsumer(
|
||||
consumer_id,
|
||||
id,
|
||||
this.defaultSelect,
|
||||
true,
|
||||
)
|
||||
return ResponseMapper.single(this.prepareBusinessActivityResponse(businessActivity))
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -1,7 +1,6 @@
|
||||
import { ApiProperty, PartialType } from '@nestjs/swagger'
|
||||
import { IsEnum, IsNumber, IsObject, IsOptional, IsString } from 'class-validator'
|
||||
import { IsNumber, IsObject, IsOptional, IsString } from 'class-validator'
|
||||
import type { SaleInvoiceType } from 'common/interfaces/sale-invoice-payload'
|
||||
import { UnitType } from 'generated/prisma/enums'
|
||||
|
||||
export class CreateSalesInvoiceItemDto {
|
||||
@IsNumber()
|
||||
@@ -24,9 +23,9 @@ export class CreateSalesInvoiceItemDto {
|
||||
@ApiProperty({ required: true })
|
||||
invoice_id: string
|
||||
|
||||
@IsEnum(UnitType)
|
||||
@ApiProperty({ enum: Object.values(UnitType) })
|
||||
unit_type: UnitType
|
||||
// @IsEnum(UnitType)
|
||||
// @ApiProperty({ enum: Object.values(UnitType) })
|
||||
// unit_type: UnitType
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
import { TokenAccount } from '@/common/decorators/tokenInfo.decorator'
|
||||
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common'
|
||||
import { ApiTags } from '@nestjs/swagger'
|
||||
import { multerImageOptions } from '@/multer.config'
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
Param,
|
||||
Patch,
|
||||
Post,
|
||||
UploadedFile,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common'
|
||||
import { FileInterceptor } from '@nestjs/platform-express'
|
||||
import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger'
|
||||
import { CreateGoodDto, UpdateGoodDto } from './dto/good.dto'
|
||||
import type {
|
||||
ConsumerBusinessActivityGoodsServiceFindAllResponseDto,
|
||||
ConsumerBusinessActivityGoodsServiceFindOneResponseDto,
|
||||
} from './dto/goods-response.dto'
|
||||
import { ConsumerBusinessActivityGoodsService } from './goods.service'
|
||||
import type { ConsumerBusinessActivityGoodsServiceCreateResponseDto, ConsumerBusinessActivityGoodsServiceFindAllResponseDto, ConsumerBusinessActivityGoodsServiceFindOneResponseDto, ConsumerBusinessActivityGoodsServiceUpdateResponseDto } from './dto/goods-response.dto'
|
||||
|
||||
@ApiTags('ConsumerBusinessActivityGoods')
|
||||
@Controller('consumer/business_activities/:businessActivityId/goods')
|
||||
@@ -29,22 +43,44 @@ export class ConsumerBusinessActivityGoodsController {
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(
|
||||
@UseInterceptors(FileInterceptor('image', multerImageOptions))
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@ApiBody({
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
image: { type: 'string', format: 'binary' },
|
||||
},
|
||||
},
|
||||
})
|
||||
create(
|
||||
@Param('businessActivityId') businessActivityId: string,
|
||||
@Body() data: CreateGoodDto,
|
||||
): Promise<ConsumerBusinessActivityGoodsServiceCreateResponseDto> {
|
||||
return this.service.create(businessActivityId, data)
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
) {
|
||||
return this.service.create(businessActivityId, data, file)
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
async update(
|
||||
@UseInterceptors(FileInterceptor('image', multerImageOptions))
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@ApiBody({
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
image: { type: 'string', format: 'binary' },
|
||||
},
|
||||
},
|
||||
})
|
||||
update(
|
||||
@TokenAccount('userId') consumer_id: string,
|
||||
@Param('businessActivityId') businessActivityId: string,
|
||||
|
||||
@Param('id') id: string,
|
||||
@Body() data: UpdateGoodDto,
|
||||
): Promise<ConsumerBusinessActivityGoodsServiceUpdateResponseDto> {
|
||||
return this.service.update(consumer_id, businessActivityId, id, data)
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
) {
|
||||
return this.service.update(consumer_id, businessActivityId, id, data, file)
|
||||
}
|
||||
|
||||
// @Delete(':id')
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { UploaderModule } from '@/modules/uploader/uploader.module'
|
||||
import { PrismaModule } from '@/prisma/prisma.module'
|
||||
import { Module } from '@nestjs/common'
|
||||
import { ConsumerBusinessActivityGoodsController } from './goods.controller'
|
||||
import { ConsumerBusinessActivityGoodsService } from './goods.service'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
imports: [PrismaModule, UploaderModule],
|
||||
controllers: [ConsumerBusinessActivityGoodsController],
|
||||
providers: [ConsumerBusinessActivityGoodsService],
|
||||
exports: [ConsumerBusinessActivityGoodsService],
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { UploadedFileTypes } from '@/common/enums/enums'
|
||||
import { GoodSelect } from '@/generated/prisma/models'
|
||||
import { UploaderService } from '@/modules/uploader/uploader.service'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from 'common/response/response-mapper'
|
||||
@@ -6,7 +8,10 @@ import { CreateGoodDto, UpdateGoodDto } from './dto/good.dto'
|
||||
|
||||
@Injectable()
|
||||
export class ConsumerBusinessActivityGoodsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly uploaderService: UploaderService,
|
||||
) {}
|
||||
|
||||
defaultSelect: GoodSelect = {
|
||||
id: true,
|
||||
@@ -64,12 +69,25 @@ export class ConsumerBusinessActivityGoodsService {
|
||||
return ResponseMapper.single(good)
|
||||
}
|
||||
|
||||
async create(business_activity_id: string, data: CreateGoodDto) {
|
||||
async create(
|
||||
business_activity_id: string,
|
||||
data: CreateGoodDto,
|
||||
file: Express.Multer.File,
|
||||
) {
|
||||
const { category_id, sku_id, measure_unit_id, ...rest } = data
|
||||
let image_url = ''
|
||||
if (file) {
|
||||
const uploadedUrl = await this.uploaderService.uploadFile(
|
||||
file,
|
||||
UploadedFileTypes.GOOD,
|
||||
)
|
||||
image_url = uploadedUrl || ''
|
||||
}
|
||||
|
||||
const good = await this.prisma.good.create({
|
||||
data: {
|
||||
...rest,
|
||||
image_url,
|
||||
business_activity: {
|
||||
connect: {
|
||||
id: business_activity_id,
|
||||
@@ -100,39 +118,61 @@ export class ConsumerBusinessActivityGoodsService {
|
||||
business_activity_id: string,
|
||||
id: string,
|
||||
data: UpdateGoodDto,
|
||||
file: Express.Multer.File,
|
||||
) {
|
||||
const { category_id, sku_id, measure_unit_id, ...rest } = data
|
||||
const good = await this.prisma.good.update({
|
||||
where: {
|
||||
business_activity: {
|
||||
id: business_activity_id,
|
||||
consumer_id,
|
||||
},
|
||||
id,
|
||||
},
|
||||
data: {
|
||||
business_activity: {
|
||||
connect: {
|
||||
const good = await this.prisma.$transaction(async tx => {
|
||||
const { category_id, sku_id, measure_unit_id, ...rest } = data
|
||||
let image_url = ''
|
||||
if (file) {
|
||||
const uploadedUrl = await this.uploaderService.uploadFile(
|
||||
file,
|
||||
UploadedFileTypes.GOOD,
|
||||
)
|
||||
image_url = uploadedUrl || ''
|
||||
}
|
||||
|
||||
const prevImage = await tx.good.findUnique({
|
||||
where: { id },
|
||||
select: { image_url: true },
|
||||
})
|
||||
|
||||
if (image_url && prevImage?.image_url) {
|
||||
this.uploaderService.deleteFile(prevImage.image_url, UploadedFileTypes.GOOD)
|
||||
}
|
||||
|
||||
return await tx.good.update({
|
||||
where: {
|
||||
business_activity: {
|
||||
id: business_activity_id,
|
||||
consumer_id,
|
||||
},
|
||||
id,
|
||||
},
|
||||
category: {
|
||||
connect: {
|
||||
id: category_id,
|
||||
data: {
|
||||
image_url,
|
||||
business_activity: {
|
||||
connect: {
|
||||
id: business_activity_id,
|
||||
},
|
||||
},
|
||||
},
|
||||
sku: {
|
||||
connect: {
|
||||
id: sku_id,
|
||||
category: {
|
||||
connect: {
|
||||
id: category_id,
|
||||
},
|
||||
},
|
||||
},
|
||||
measure_unit: {
|
||||
connect: {
|
||||
id: measure_unit_id,
|
||||
sku: {
|
||||
connect: {
|
||||
id: sku_id,
|
||||
},
|
||||
},
|
||||
measure_unit: {
|
||||
connect: {
|
||||
id: measure_unit_id,
|
||||
},
|
||||
},
|
||||
...rest,
|
||||
},
|
||||
...rest,
|
||||
},
|
||||
})
|
||||
})
|
||||
return ResponseMapper.update(good)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user