diff options
Diffstat (limited to 'src/app/api')
| -rw-r--r-- | src/app/api/location/route.tsx | 9 | ||||
| -rw-r--r-- | src/app/api/product/import/route.tsx | 17 | ||||
| -rw-r--r-- | src/app/api/product/route.tsx | 16 | ||||
| -rw-r--r-- | src/app/api/stock-opname/export/route.tsx | 68 | ||||
| -rw-r--r-- | src/app/api/stock-opname/location/route.tsx | 41 | ||||
| -rw-r--r-- | src/app/api/stock-opname/quantity/route.tsx | 5 | ||||
| -rw-r--r-- | src/app/api/stock-opname/route.tsx | 111 |
7 files changed, 169 insertions, 98 deletions
diff --git a/src/app/api/location/route.tsx b/src/app/api/location/route.tsx index 452a85d..bc4cfff 100644 --- a/src/app/api/location/route.tsx +++ b/src/app/api/location/route.tsx @@ -1,17 +1,14 @@ +import getServerCredential from "@/common/libs/getServerCredential"; import { NextRequest, NextResponse } from "next/server"; import { prisma } from "prisma/client"; -import { Credential } from "@/common/types/auth" export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams; const search = searchParams.get('search'); - const credentialStr = request.cookies.get('credential')?.value - const credential: Credential | null = credentialStr ? JSON.parse(credentialStr) : null + const credential = getServerCredential() - if (!credential) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) - } + if (!credential) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) const { companyId } = credential diff --git a/src/app/api/product/import/route.tsx b/src/app/api/product/import/route.tsx index 7358205..eb87f07 100644 --- a/src/app/api/product/import/route.tsx +++ b/src/app/api/product/import/route.tsx @@ -3,6 +3,12 @@ import { prisma } from "prisma/client"; import * as XLSX from "xlsx"; export async function POST(request: NextRequest) { + const searchParams = request.nextUrl.searchParams + const companyId = searchParams.get('companyId') + + if (!companyId) return NextResponse.json({ error: 'Bad Request. Missing companyId' }, { status: 400 }) + const intCompanyId = parseInt(companyId) + const body = await request.arrayBuffer(); const workbook = XLSX.read(body, { type: 'buffer' }) const worksheetName = workbook.SheetNames[0] @@ -13,14 +19,19 @@ export async function POST(request: NextRequest) { const newProducts = fileData.map(row => ({ id: undefined, isDifferent: false, - name: row[0], - barcode: row[1], - itemCode: row[2], + name: row[0].toString(), + barcode: row[1].toString(), + itemCode: row[2].toString(), onhandQty: row[3], differenceQty: row[4], companyId: row[5], })); + const whereCompany = { companyId: intCompanyId } + + await prisma.stockOpname.deleteMany({ where: whereCompany }) + await prisma.product.deleteMany({ where: whereCompany }) + await prisma.product.createMany({ data: newProducts }) return NextResponse.json(true) diff --git a/src/app/api/product/route.tsx b/src/app/api/product/route.tsx index 1161a4e..07ba9c7 100644 --- a/src/app/api/product/route.tsx +++ b/src/app/api/product/route.tsx @@ -1,24 +1,20 @@ +import getServerCredential from "@/common/libs/getServerCredential"; import { NextRequest, NextResponse } from "next/server"; import { prisma } from "prisma/client"; -import { Credential } from "@/common/types/auth" export async function GET(request: NextRequest) { const PAGE_SIZE = 30; const searchParams = request.nextUrl.searchParams; - const type = searchParams.get('type') const search = searchParams.get('search'); const page = searchParams.get('page'); const intPage: number = page ? parseInt(page) : 1; + const paramCompanyId = searchParams.get('companyId') + const companyId = paramCompanyId ? parseInt(paramCompanyId) : null - const credentialStr = request.cookies.get('credential')?.value - const credential: Credential | null = credentialStr ? JSON.parse(credentialStr) : null + const credential = getServerCredential() - if (!credential) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) - } - - const { companyId } = credential + if (!credential) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) const where = { AND: { @@ -27,7 +23,7 @@ export async function GET(request: NextRequest) { { barcode: { contains: search ?? '' } }, { itemCode: { contains: search ?? '' } }, ], - companyId: type == 'all' ? undefined : companyId + companyId: companyId ?? credential.companyId } } diff --git a/src/app/api/stock-opname/export/route.tsx b/src/app/api/stock-opname/export/route.tsx new file mode 100644 index 0000000..1595f20 --- /dev/null +++ b/src/app/api/stock-opname/export/route.tsx @@ -0,0 +1,68 @@ +import { StockOpnameLocationRes } from "@/common/types/stockOpname"; +import { Product } from "@prisma/client"; +import { NextRequest, NextResponse } from "next/server"; +import { prisma } from "prisma/client"; +import * as XLSX from "xlsx" + +const SELF_HOST = process.env.SELF_HOST as string + +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams + const paramCompanyId = searchParams.get('companyId') + + if (!paramCompanyId) return NextResponse.json({ error: 'Bad Request. Missing companyId' }, { status: 400 }) + + const companyId = parseInt(paramCompanyId) + + const stockOpnames = await prisma.stockOpname.groupBy({ + by: ['productId'], + where: { companyId } + }) + + type SOLocationProduct = (StockOpnameLocationRes & { product: Product | null }) + + const datas: SOLocationProduct[] = [] + + for (const opname of stockOpnames) { + const requestParams = new URLSearchParams({ + productId: opname.productId.toString(), + companyId: companyId.toString() + }) + const detailsFetch = await fetch(`${SELF_HOST}/api/stock-opname/location?${requestParams}`) + const details: StockOpnameLocationRes[] = await detailsFetch.json() + + const product = await prisma.product.findFirst({ where: { id: opname.productId } }) + const mappedData: SOLocationProduct[] = details.map((data) => ({ + ...data, + product + })) + + datas.push(...mappedData) + } + + const dataSheet = datas.map((data) => ({ + location: data.name, + name: data.product?.name, + itemCode: data.product?.itemCode, + barcode: data.product?.barcode, + onhandQty: data.product?.onhandQty, + differenceQty: data.product?.differenceQty, + count1: data.COUNT1.quantity, + count2: data.COUNT2.quantity, + count3: data.COUNT3.quantity, + verification: data.VERIFICATION.quantity, + isDifferent: data.product?.isDifferent + })) + + const worksheet = XLSX.utils.json_to_sheet(dataSheet) + const workbook = XLSX.utils.book_new() + XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1") + const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', 'type': 'buffer' }) + + return new NextResponse(excelBuffer, { + headers: { + 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'Content-Disposition': 'attachment; filename=export.xlsx' + } + }) +}
\ No newline at end of file diff --git a/src/app/api/stock-opname/location/route.tsx b/src/app/api/stock-opname/location/route.tsx index 1009486..e6c20ec 100644 --- a/src/app/api/stock-opname/location/route.tsx +++ b/src/app/api/stock-opname/location/route.tsx @@ -1,28 +1,8 @@ import { DetailTeam, StockOpnameLocationRes } from "@/common/types/stockOpname"; -import { Location, Team } from "@prisma/client"; +import { Team } from "@prisma/client"; import { NextRequest, NextResponse } from "next/server"; import { prisma } from "prisma/client"; - - -const getOpnameQuantity = async (where: { locationId: number, productId: number }) => { - const detailTeam: DetailTeam = { - COUNT1: { quantity: undefined, user: undefined }, - COUNT2: { quantity: undefined, user: undefined }, - VERIFICATION: { quantity: undefined, user: undefined }, - } - for (const team of Object.keys(Team)) { - const opname = await prisma.stockOpname.findFirst({ - where: { ...where, team: team as Team }, - select: { quantity: true, user: true }, - }) - if (!opname) continue - detailTeam[team as Team]['quantity'] = opname?.quantity - detailTeam[team as Team]['user'] = opname?.user - } - return detailTeam -} - export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams; const productId = searchParams.get('productId') ?? ''; @@ -54,4 +34,23 @@ export async function GET(request: NextRequest) { } return NextResponse.json(result) +} + +const getOpnameQuantity = async (where: { locationId: number, productId: number }) => { + const detailTeam: DetailTeam = { + COUNT1: { quantity: undefined, user: undefined }, + COUNT2: { quantity: undefined, user: undefined }, + COUNT3: { quantity: undefined, user: undefined }, + VERIFICATION: { quantity: undefined, user: undefined }, + } + for (const team of Object.keys(Team)) { + const opname = await prisma.stockOpname.findFirst({ + where: { ...where, team: team as Team }, + select: { quantity: true, user: true }, + }) + if (!opname) continue + detailTeam[team as Team]['quantity'] = opname?.quantity + detailTeam[team as Team]['user'] = opname?.user + } + return detailTeam }
\ No newline at end of file diff --git a/src/app/api/stock-opname/quantity/route.tsx b/src/app/api/stock-opname/quantity/route.tsx index 621297f..fe38c0b 100644 --- a/src/app/api/stock-opname/quantity/route.tsx +++ b/src/app/api/stock-opname/quantity/route.tsx @@ -1,10 +1,9 @@ -import { Credential } from "@/common/types/auth"; +import getServerCredential from "@/common/libs/getServerCredential"; import { NextRequest, NextResponse } from "next/server"; import { prisma } from "prisma/client"; export async function GET(request: NextRequest) { - const credentialStr = request.cookies.get('credential')?.value - const credential: Credential | null = credentialStr ? JSON.parse(credentialStr) : null + const credential = getServerCredential() if (!credential) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) diff --git a/src/app/api/stock-opname/route.tsx b/src/app/api/stock-opname/route.tsx index 50feacd..406981b 100644 --- a/src/app/api/stock-opname/route.tsx +++ b/src/app/api/stock-opname/route.tsx @@ -1,44 +1,23 @@ -import { Credential } from "@/common/types/auth"; import { StockOpnameLocationRes, StockOpnameRequest } from "@/common/types/stockOpname"; import { Team } from "@prisma/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 } -const calculateOpnameQuantity = async ( - where: { - productId: number, - companyId: number - } -): Promise<Quantity> => { - const quantity: Quantity = { - COUNT1: null, - COUNT2: 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 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 intPage = page ? parseInt(page) : 1; + 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 }) @@ -48,6 +27,7 @@ export async function GET(request: NextRequest) { AND: { stockOpnames: { some: {} }, companyId: parseInt(companyId), + isDifferent: show ? (show == 'diff' ? true : false) : undefined, OR: [ { name: { contains: search ?? '' } }, { itemCode: { contains: search ?? '' } }, @@ -96,9 +76,28 @@ export async function GET(request: NextRequest) { }) } +const calculateOpnameQuantity = async ( + where: { + productId: number, + companyId: number + } +): Promise<Quantity> => { + 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 credentialStr = request.cookies.get('credential')?.value - const credential: Credential | null = credentialStr ? JSON.parse(credentialStr) : null + const credential = getServerCredential() if (!credential) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) @@ -135,7 +134,7 @@ export async function POST(request: NextRequest) { }) } - computeIsDifferent({ productId: body.product, companyId: companyId }) + await computeIsDifferent({ productId: body.product, companyId: companyId }) return NextResponse.json(newStockOpname) } @@ -152,6 +151,7 @@ const computeIsDifferent = async ({ const totalQty: { [key in keyof typeof Team]: number | null } = { COUNT1: null, COUNT2: null, + COUNT3: null, VERIFICATION: null } @@ -172,43 +172,44 @@ const computeIsDifferent = async ({ let isDifferent: boolean = false for (const opname of stockOpnames) { - let { COUNT1, COUNT2, VERIFICATION } = opname - - if (!totalQty['COUNT1'] && COUNT1.quantity) totalQty['COUNT1'] = 0 - if (!totalQty['COUNT2'] && COUNT2.quantity) totalQty['COUNT2'] = 0 - if (!totalQty['VERIFICATION'] && VERIFICATION.quantity) totalQty['VERIFICATION'] = 0 + let { COUNT1, COUNT2, COUNT3, VERIFICATION } = opname - if (totalQty['COUNT1'] !== null && COUNT1.quantity) totalQty['COUNT1'] += COUNT1.quantity - if (totalQty['COUNT2'] !== null && COUNT2.quantity) totalQty['COUNT2'] += COUNT2.quantity - if (totalQty['VERIFICATION'] !== null && VERIFICATION.quantity) totalQty['VERIFICATION'] += VERIFICATION.quantity + 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 (isCount2Counted && COUNT1.quantity != COUNT2.quantity) { - isDifferent = true - } + 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 } - const product = await prisma.product.findFirst({ - where: { id: productId } - }) + const product = await prisma.product.findFirst({ where: { id: productId } }) if (!product) return const onhandQty = product?.onhandQty || 0 if (!isDifferent) { - if ( - (typeof totalQty['VERIFICATION'] === 'number' && totalQty['VERIFICATION'] > 0) || - totalQty['COUNT2'] == onhandQty || - totalQty['COUNT1'] == onhandQty || - totalQty['COUNT1'] == totalQty['COUNT2'] - ) { - isDifferent = false - } else { - isDifferent = true + const conditional = { + wasVerified: typeof totalQty['VERIFICATION'] === 'number' && totalQty['VERIFICATION'] > 0, + anyCountEqWithOnhand: [totalQty['COUNT1'], totalQty['COUNT2'], totalQty['COUNT3']].includes(onhandQty), + count1EqWithCount2: totalQty['COUNT1'] !== null && totalQty['COUNT2'] !== null && totalQty['COUNT1'] === totalQty['COUNT2'], + count1EqWithCount3: totalQty['COUNT1'] !== null && totalQty['COUNT3'] !== null && totalQty['COUNT1'] === totalQty['COUNT3'], + count2EqWithCount3: totalQty['COUNT2'] !== null && totalQty['COUNT3'] !== null && totalQty['COUNT2'] === totalQty['COUNT3'] } - if (isCount2Counted && totalQty['COUNT1'] != onhandQty) { - isDifferent = true - } + isDifferent = !( + conditional.wasVerified || + conditional.anyCountEqWithOnhand || + conditional.count1EqWithCount2 || + conditional.count1EqWithCount3 || + conditional.count2EqWithCount3 + ) + + // if (isCount2Counted && totalQty['COUNT1'] != onhandQty) { + // isDifferent = true + // } } await prisma.product.update({ |
