|
|
@@ -0,0 +1,153 @@
|
|
|
+import { Repository } from 'typeorm'
|
|
|
+import { FastifyInstance } from 'fastify'
|
|
|
+import { GoodsInfo } from '../entities/goods-info.entity'
|
|
|
+import { QrCodeService } from './qr-code.service'
|
|
|
+import { QrType } from '../entities/qr-code.entity'
|
|
|
+import { PaginationResponse } from '../dto/common.dto'
|
|
|
+import { AdminUpdateGoodsInfoDto } from '../dto/goods-info.dto'
|
|
|
+
|
|
|
+export class GoodsInfoService {
|
|
|
+ private goodsInfoRepository: Repository<GoodsInfo>
|
|
|
+ private qrCodeService: QrCodeService
|
|
|
+
|
|
|
+ constructor(app: FastifyInstance) {
|
|
|
+ this.goodsInfoRepository = app.dataSource.getRepository(GoodsInfo)
|
|
|
+ this.qrCodeService = new QrCodeService(app)
|
|
|
+ }
|
|
|
+
|
|
|
+ async create(qrCode: string, data: Partial<GoodsInfo>): Promise<GoodsInfo> {
|
|
|
+ const qrCodeEntity = await this.qrCodeService.findByQrCode(qrCode)
|
|
|
+ if (!qrCodeEntity) {
|
|
|
+ throw new Error('二维码不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qrCodeEntity.qrType !== QrType.GOODS) {
|
|
|
+ throw new Error('二维码类型不匹配')
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qrCodeEntity.isActivated) {
|
|
|
+ throw new Error('二维码已激活,无法重复填写')
|
|
|
+ }
|
|
|
+
|
|
|
+ const goodsInfo = this.goodsInfoRepository.create({
|
|
|
+ ...data,
|
|
|
+ qrCodeId: qrCodeEntity.id
|
|
|
+ })
|
|
|
+
|
|
|
+ const result = await this.goodsInfoRepository.save(goodsInfo)
|
|
|
+
|
|
|
+ await this.qrCodeService.activateQrCode(qrCodeEntity.id)
|
|
|
+
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ async update(qrCode: string, maintenanceCode: string, data: Partial<GoodsInfo>): Promise<GoodsInfo | null> {
|
|
|
+ const isValid = await this.qrCodeService.verifyMaintenanceCode(qrCode, maintenanceCode)
|
|
|
+ if (!isValid) {
|
|
|
+ throw new Error('维护码错误')
|
|
|
+ }
|
|
|
+
|
|
|
+ const qrCodeEntity = await this.qrCodeService.findByQrCode(qrCode)
|
|
|
+ if (!qrCodeEntity) {
|
|
|
+ throw new Error('二维码不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ const goodsInfo = await this.goodsInfoRepository.findOne({
|
|
|
+ where: { qrCodeId: qrCodeEntity.id }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!goodsInfo) {
|
|
|
+ const created = this.goodsInfoRepository.create({
|
|
|
+ ...data,
|
|
|
+ qrCodeId: qrCodeEntity.id
|
|
|
+ })
|
|
|
+ const result = await this.goodsInfoRepository.save(created)
|
|
|
+ await this.qrCodeService.activateQrCode(qrCodeEntity.id)
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ await this.goodsInfoRepository.update(goodsInfo.id, data)
|
|
|
+
|
|
|
+ const updated = await this.goodsInfoRepository.findOne({ where: { id: goodsInfo.id } })
|
|
|
+ if (!updated) {
|
|
|
+ throw new Error('更新后无法找到物品信息')
|
|
|
+ }
|
|
|
+ return updated
|
|
|
+ }
|
|
|
+
|
|
|
+ async findByQrCodeId(qrCodeId: number): Promise<GoodsInfo | null> {
|
|
|
+ return this.goodsInfoRepository.findOne({ where: { qrCodeId } })
|
|
|
+ }
|
|
|
+
|
|
|
+ async findByQrCode(qrCode: string): Promise<GoodsInfo | null> {
|
|
|
+ const qrCodeEntity = await this.qrCodeService.findByQrCode(qrCode)
|
|
|
+ if (!qrCodeEntity) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ return this.findByQrCodeId(qrCodeEntity.id)
|
|
|
+ }
|
|
|
+
|
|
|
+ async adminUpdate(qrCodeId: number, data: Omit<AdminUpdateGoodsInfoDto, 'qrCodeId'>): Promise<GoodsInfo> {
|
|
|
+ const goodsInfo = await this.goodsInfoRepository.findOne({
|
|
|
+ where: { qrCodeId }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!goodsInfo) {
|
|
|
+ throw new Error('物品信息不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ await this.goodsInfoRepository.update(goodsInfo.id, data)
|
|
|
+ const updated = await this.goodsInfoRepository.findOne({ where: { id: goodsInfo.id } })
|
|
|
+ if (!updated) {
|
|
|
+ throw new Error('更新后无法找到物品信息')
|
|
|
+ }
|
|
|
+ return updated
|
|
|
+ }
|
|
|
+
|
|
|
+ async query(
|
|
|
+ name?: string,
|
|
|
+ contactName?: string,
|
|
|
+ contactPhone?: string,
|
|
|
+ startDate?: string,
|
|
|
+ endDate?: string,
|
|
|
+ page: number = 0,
|
|
|
+ pageSize: number = 20
|
|
|
+ ): Promise<PaginationResponse<GoodsInfo>> {
|
|
|
+ const queryBuilder = this.goodsInfoRepository.createQueryBuilder('goodsInfo')
|
|
|
+
|
|
|
+ if (name) {
|
|
|
+ queryBuilder.andWhere('goodsInfo.name LIKE :name', { name: `%${name}%` })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (contactName) {
|
|
|
+ queryBuilder.andWhere('goodsInfo.contactName LIKE :contactName', { contactName: `%${contactName}%` })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (contactPhone) {
|
|
|
+ queryBuilder.andWhere('goodsInfo.contactPhone LIKE :contactPhone', { contactPhone: `%${contactPhone}%` })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (startDate && endDate) {
|
|
|
+ queryBuilder.andWhere('DATE(goodsInfo.createdAt) BETWEEN :startDate AND :endDate', { startDate, endDate })
|
|
|
+ } else if (startDate) {
|
|
|
+ queryBuilder.andWhere('DATE(goodsInfo.createdAt) >= :startDate', { startDate })
|
|
|
+ } else if (endDate) {
|
|
|
+ queryBuilder.andWhere('DATE(goodsInfo.createdAt) <= :endDate', { endDate })
|
|
|
+ }
|
|
|
+
|
|
|
+ const [content, total] = await queryBuilder
|
|
|
+ .skip(page * pageSize)
|
|
|
+ .take(pageSize)
|
|
|
+ .orderBy('goodsInfo.createdAt', 'DESC')
|
|
|
+ .getManyAndCount()
|
|
|
+
|
|
|
+ return {
|
|
|
+ content,
|
|
|
+ metadata: {
|
|
|
+ total: Number(total),
|
|
|
+ page: Number(page),
|
|
|
+ size: Number(pageSize)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|