import { randomUUID } from "crypto"; import { inject, injectable } from "tsyringe"; import Stock from "../domain/entities/stock"; import ItemType from "../domain/entities/vo/itemType.vo"; import ItemRepository from "../domain/repositories/item.repository"; import StockRepository from "../domain/repositories/stock.repository"; import CreateStockService from "../domain/services/createStock"; import { CreateStockAttr, GenerateStockAttr } from "../domain/types/stock.type"; import Result from "../utils/result"; @injectable() export default class CreateStockServiceImpl implements CreateStockService { constructor( @inject("Stock:StockRepository") private repository: StockRepository, @inject("Items:ItemRepository") private itemRepository: ItemRepository, ) { } async run(payload: CreateStockAttr): Promise> { try { const stock = await this.repository.create(payload); return Result.success(stock); } catch (error) { return Result.failure(error); } } async generate(payload: GenerateStockAttr): Promise> { const item = await this.itemRepository.find({ id: payload.itemId }); const coupons = []; for (let index = 0; index < payload.quantity; index++) { coupons.push(this.makeCode()); } let availableStock = await this.repository.allAvailable(payload.itemId); if (availableStock.length < payload.quantity) { if (item!.type === ItemType.UNLIMITED || item!.type === ItemType.LOTTERY) { const lastStock = await this.repository.find({ itemId: payload.itemId }); const stock = coupons.slice(0, payload.quantity - availableStock.length).map(c => { return { code: lastStock?.code || randomUUID(), encodedCode: c, }; }); await this.repository.create({ itemId: payload.itemId, stock }); } else { return Result.failure("Not enough stock available"); } } availableStock = await this.repository.allAvailable(payload.itemId); const resultStock: Stock[] = []; let index = 0; for await (const coupon of coupons) { const updated = await this.repository.update({ id: availableStock[index].id!, data: { itemId: availableStock[index].item.id, code: availableStock[index].code, encodedCode: coupon, } }); index += 1; resultStock.push(updated!); } return Result.success(resultStock); } private makeCode(): string { let result = ""; const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; const charactersLength = characters.length; let counter = 0; while (counter < 8) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); counter += 1; } return result; } }