feat: implement demo candidate 1.0.0-rc.1
This commit is contained in:
118
src/service/goods.ts
Normal file
118
src/service/goods.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { Inject, Provide } from '@midwayjs/core';
|
||||
import {
|
||||
InjectSaasCrud,
|
||||
SaasAction,
|
||||
SaasActionContext,
|
||||
SaasBusinessReject,
|
||||
SaasCrudCaller,
|
||||
SaasCrudService,
|
||||
SaasCrudServiceBase,
|
||||
} from '@cool-midway/module-runtime';
|
||||
import {
|
||||
Actions,
|
||||
Crud,
|
||||
Events,
|
||||
type GoodsBatchInfoInput,
|
||||
type GoodsBatchInfoOutput,
|
||||
type GoodsInfoOutput,
|
||||
type GoodsReleaseStockInput,
|
||||
type GoodsReleaseStockOutput,
|
||||
type GoodsReserveStockInput,
|
||||
type GoodsReserveStockOutput,
|
||||
} from '../saas/generated';
|
||||
|
||||
@Provide()
|
||||
@SaasCrudService(Crud.Goods)
|
||||
export class GoodsService extends SaasCrudServiceBase<typeof Crud.Goods> {
|
||||
@InjectSaasCrud(Crud.Goods)
|
||||
private readonly goods!: SaasCrudCaller<typeof Crud.Goods>;
|
||||
|
||||
@Inject()
|
||||
private readonly saasActionContext!: SaasActionContext;
|
||||
|
||||
@SaasAction(Actions.GoodsBatchInfo)
|
||||
async batchInfo(
|
||||
input: GoodsBatchInfoInput
|
||||
): Promise<GoodsBatchInfoOutput> {
|
||||
const list: GoodsInfoOutput[] = [];
|
||||
for (const id of input.ids) {
|
||||
const goods = await this.findGoods(id);
|
||||
if (goods) list.push(goods);
|
||||
}
|
||||
return { list };
|
||||
}
|
||||
|
||||
@SaasAction(Actions.GoodsReserveStock)
|
||||
async reserveStock(
|
||||
input: GoodsReserveStockInput
|
||||
): Promise<GoodsReserveStockOutput> {
|
||||
const goods = await this.requireGoods(input.goodsId);
|
||||
if (goods.status !== 1) {
|
||||
throw new SaasBusinessReject(
|
||||
'GOODS_UNAVAILABLE',
|
||||
`商品 ${input.goodsId} 当前不可售`
|
||||
);
|
||||
}
|
||||
if (goods.stock < input.quantity) {
|
||||
throw new SaasBusinessReject(
|
||||
'INSUFFICIENT_STOCK',
|
||||
`商品 ${input.goodsId} 库存不足`,
|
||||
{ available: goods.stock, requested: input.quantity }
|
||||
);
|
||||
}
|
||||
|
||||
const remainingStock = goods.stock - input.quantity;
|
||||
this.saasActionContext.raise(Events.DemoGoodsStockReserved, {
|
||||
goodsId: input.goodsId,
|
||||
quantity: input.quantity,
|
||||
remainingStock,
|
||||
});
|
||||
await this.updateStock(input.goodsId, remainingStock);
|
||||
return { goodsId: input.goodsId, remainingStock };
|
||||
}
|
||||
|
||||
@SaasAction(Actions.GoodsReleaseStock)
|
||||
async releaseStock(
|
||||
input: GoodsReleaseStockInput
|
||||
): Promise<GoodsReleaseStockOutput> {
|
||||
const goods = await this.requireGoods(input.goodsId);
|
||||
const currentStock = goods.stock + input.quantity;
|
||||
|
||||
this.saasActionContext.raise(Events.DemoGoodsStockReserved, {
|
||||
goodsId: input.goodsId,
|
||||
quantity: input.quantity,
|
||||
remainingStock: currentStock,
|
||||
});
|
||||
await this.updateStock(input.goodsId, currentStock);
|
||||
return { goodsId: input.goodsId, currentStock };
|
||||
}
|
||||
|
||||
private async findGoods(goodsId: number): Promise<GoodsInfoOutput | null> {
|
||||
const rows = await this.goods.list({
|
||||
where: { id: String(goodsId) },
|
||||
take: 1,
|
||||
});
|
||||
return rows[0] || null;
|
||||
}
|
||||
|
||||
private async requireGoods(goodsId: number): Promise<GoodsInfoOutput> {
|
||||
const goods = await this.findGoods(goodsId);
|
||||
if (!goods) {
|
||||
throw new SaasBusinessReject(
|
||||
'GOODS_NOT_FOUND',
|
||||
`商品 ${goodsId} 不存在`
|
||||
);
|
||||
}
|
||||
return goods;
|
||||
}
|
||||
|
||||
private async updateStock(goodsId: number, stock: number): Promise<void> {
|
||||
const result = await this.goods.update({ id: String(goodsId), stock });
|
||||
if (result.affected !== 1) {
|
||||
throw new SaasBusinessReject(
|
||||
'GOODS_STOCK_UPDATE_FAILED',
|
||||
`商品 ${goodsId} 库存更新失败`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user