summaryrefslogtreecommitdiff
path: root/src/app/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/api')
-rw-r--r--src/app/api/location/route.tsx9
-rw-r--r--src/app/api/product/import/route.tsx17
-rw-r--r--src/app/api/product/route.tsx16
-rw-r--r--src/app/api/stock-opname/export/route.tsx68
-rw-r--r--src/app/api/stock-opname/location/route.tsx41
-rw-r--r--src/app/api/stock-opname/quantity/route.tsx5
-rw-r--r--src/app/api/stock-opname/route.tsx111
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({