import { StockOpnameLocationRes, StockOpnameRequest } from "@/common/types/stockOpname"; import { Prisma, Team } from "prisma/generated/client"; import { NextRequest, NextResponse } from "next/server"; import { prisma } from "prisma/client"; import _ from "lodash" import getServerCredential from "@/common/libs/getServerCredential"; type Quantity = { [key in keyof typeof Team]: number | null } export async function GET(request: NextRequest) { const PAGE_SIZE = 30; const params = request.nextUrl.searchParams const companyId = params.get('companyId') const search = params.get('search') const page = params.get('page') ?? null const show = params.get('show') const intPage = page ? parseInt(page) : 1 if (!companyId) { return NextResponse.json({ error: 'Bad Request. Missing companyId' }, { status: 400 }) } const where: Prisma.ProductWhereInput = { AND: { stockOpnames: { some: {} }, companyId: parseInt(companyId), isDifferent: show ? (show == 'diff' ? true : false) : undefined, OR: [ { name: { mode: 'insensitive', contains: search ?? '' } }, { itemCode: { mode: 'insensitive', contains: search ?? '' } }, { barcode: { mode: 'insensitive', contains: search ?? '' } }, { stockOpnames: { some: { location: { name: { mode: 'insensitive', contains: search ?? '' } } } } }, ] } } const products = await prisma.product.findMany({ skip: (intPage - 1) * PAGE_SIZE, take: PAGE_SIZE, where }) const productCount = await prisma.product.count({ where }) const pagination = { page: intPage, totalPage: Math.ceil(productCount / PAGE_SIZE), } type ProductWithSum = typeof products[0] & { quantity: Quantity } const productsWithSum: ProductWithSum[] = [] for (const product of products) { const quantity = await calculateOpnameQuantity({ productId: product.id, companyId: parseInt(companyId) }) productsWithSum.push({ ...product, quantity }) } return NextResponse.json({ result: productsWithSum, ...pagination }) } const calculateOpnameQuantity = async ( where: { productId: number, companyId: number } ): Promise => { const quantity: Quantity = { COUNT1: null, COUNT2: null, COUNT3: null, VERIFICATION: null } for (const team of Object.values(Team)) { const opnameQty = await prisma.stockOpname.groupBy({ by: ['productId', 'team'], _sum: { quantity: true }, where: { team, ...where } }) if (opnameQty.length === 0) continue quantity[team] = opnameQty[0]._sum.quantity } return quantity } export async function POST(request: NextRequest) { const credential = getServerCredential() if (!credential) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) const body: StockOpnameRequest = await request.json() const { companyId, team } = credential const query = { locationId: body.location, productId: body.product, companyId, team } const stockOpname = await prisma.stockOpname.findFirst({ where: query }) const data = { ...query, userId: credential.id, quantity: body.quantity, isDifferent: false } let newStockOpname = null if (!stockOpname) { newStockOpname = await prisma.stockOpname.create({ data }) } else { newStockOpname = await prisma.stockOpname.update({ where: { id: stockOpname.id }, data }) } await computeIsDifferent({ productId: body.product, companyId: companyId }) return NextResponse.json(newStockOpname) } const SELF_HOST = process.env.SELF_HOST as string const computeIsDifferent = async ({ companyId, productId }: { companyId: number, productId: number }) => { const totalQty: { [key in keyof typeof Team]: number | 0 } = { COUNT1: 0, COUNT2: 0, COUNT3: 0, VERIFICATION: 0 } const searchParams = new URLSearchParams({ companyId: companyId.toString(), productId: productId.toString() }) const stockOpnamesFetch = await fetch(`${SELF_HOST}/api/stock-opname/location?${searchParams}`) const stockOpnames: StockOpnameLocationRes[] = await stockOpnamesFetch.json() let isDifferent: boolean = false let verificationCounter: number = 0 for (const opname of stockOpnames) { let { COUNT1, COUNT2, COUNT3, VERIFICATION } = opname if (totalQty['COUNT1'] === null && _.isNumber(COUNT1.quantity)) totalQty['COUNT1'] = 0 if (totalQty['COUNT2'] === null && _.isNumber(COUNT2.quantity)) totalQty['COUNT2'] = 0 if (totalQty['COUNT3'] === null && _.isNumber(COUNT3.quantity)) totalQty['COUNT3'] = 0 if (totalQty['VERIFICATION'] === null && _.isNumber(VERIFICATION.quantity)) totalQty['VERIFICATION'] = 0 if (_.isNumber(totalQty['COUNT1']) && _.isNumber(COUNT1.quantity)) totalQty['COUNT1'] += COUNT1.quantity if (_.isNumber(totalQty['COUNT2']) && _.isNumber(COUNT2.quantity)) totalQty['COUNT2'] += COUNT2.quantity if (_.isNumber(totalQty['COUNT3']) && _.isNumber(COUNT3.quantity)) totalQty['COUNT3'] += COUNT3.quantity if (_.isNumber(totalQty['VERIFICATION']) && _.isNumber(VERIFICATION.quantity)) totalQty['VERIFICATION'] += VERIFICATION.quantity if (_.isNumber(VERIFICATION.quantity)) verificationCounter++ } const product = await prisma.product.findFirst({ where: { id: productId } }) if (!product) return const onhandQty = product.onhandQty const allQty = totalQty['COUNT1'] + totalQty['COUNT2'] + totalQty['COUNT3'] + totalQty['VERIFICATION'] const differenceQty = onhandQty - allQty // const differenceQty = product.differenceQty // const allQty = onhandQty + differenceQty const conditional = { verificationCheckAll: verificationCounter > 0 && verificationCounter === stockOpnames.length, // anyCountEqWithOnhand: [totalQty['COUNT1'], totalQty['COUNT2'], totalQty['COUNT3']].includes(onhandQty), anyCountEqWithOnhand: totalQty['COUNT1'] === onhandQty || totalQty['COUNT2'] === onhandQty || totalQty['COUNT1'] === onhandQty , anyCountEqWithAllQty: [totalQty['COUNT1'], totalQty['COUNT2'], totalQty['COUNT3']].includes(allQty), count1EqWithCount2: totalQty['COUNT1'] !== null && totalQty['COUNT2'] !== null && totalQty['COUNT1'] === totalQty['COUNT2'] && totalQty['COUNT3'] === null, count1EqWithCount3: totalQty['COUNT1'] !== null && totalQty['COUNT3'] !== null && totalQty['COUNT1'] === totalQty['COUNT3'], count2EqWithCount3: totalQty['COUNT2'] !== null && totalQty['COUNT3'] !== null && totalQty['COUNT2'] === totalQty['COUNT3'], } // isDifferent = !( // conditional.verificationCheckAll || // conditional.anyCountEqWithOnhand || // conditional.anyCountEqWithAllQty || // conditional.count1EqWithCount2 || // conditional.count1EqWithCount3 || // conditional.count2EqWithCount3 // ) if ( conditional.verificationCheckAll || conditional.anyCountEqWithOnhand || conditional.count1EqWithCount2 || conditional.count1EqWithCount3 || conditional.count2EqWithCount3 ) { isDifferent = false; } else { isDifferent = true; } for (const opname of stockOpnames) { let { COUNT1, COUNT2, COUNT3, VERIFICATION } = opname const detailCondition = { verificationCheckAll: _.isNumber(VERIFICATION.quantity), anyCountEqWithOnhand: totalQty['COUNT1'] === onhandQty || totalQty['COUNT2'] === onhandQty || totalQty['COUNT3'] === onhandQty , count1EqWithCount2: totalQty['COUNT3'] === 0 && COUNT1.quantity === COUNT2.quantity, count1EqWithCount3: COUNT1.quantity === COUNT3.quantity, count2EqWithCount3: COUNT2.quantity === COUNT3.quantity && (COUNT2.quantity === 0 && COUNT3.quantity === 0), // count3EqWithCount1_2: (COUNT3.quantity !== COUNT1.quantity) && (COUNT3.quantity !== COUNT2.quantity) && (COUNT1.quantity === COUNT2.quantity) && (COUNT3.quantity !== onhandQty) } if ( detailCondition.verificationCheckAll || detailCondition.anyCountEqWithOnhand || detailCondition.count1EqWithCount2 || detailCondition.count1EqWithCount3 || detailCondition.count2EqWithCount3 ) { isDifferent = false; } else { isDifferent = true; break; } console.log('----------------------------------BATAS SUCI ATAS NEW STOCK ------------------------------'); console.log('Is Different2222:', isDifferent); console.log('Conditions:', detailCondition); } console.log('Total Quantity:', totalQty); console.log('Onhand Quantity:', onhandQty); console.log('Difference Quantity:', differenceQty); console.log('Conditions:', conditional); console.log('Is Different tambah data:', isDifferent); console.log('----------------------------------BATAS SUCI BAWAH NEW STOCK------------------------------'); await prisma.product.update({ where: { id: product.id }, data: { isDifferent } }) }