생산관리>M-BOM 관리 — PR-A1 그리드/검색 (mBomMgmtGridList 1:1 이식)
운영 wace productionplanning/mBomMgmtList.jsp + productionplanning.xml:2874-3119 mBomMgmtGridList 매퍼 1:1 이식. PROJECT_MGMT × CONTRACT_ITEM 펼침 그리드 + M-BOM 헤더/히스토리/구매리스트 상태 표시 + 9 검색 필터. 백엔드 (3 파일 + app.ts 마운트): - services/mbomService.ts — list() : 9 검색 필터 + 30+ 컬럼 SELECT · 주문유형/제품구분/국내해외(CODE_NAME 비교)/고객사(C_ 3-way)/유무상/SN(EXISTS) · 품번/품명(PM·CI 양쪽 LIKE)/접수일·요청납기 범위 · WRITER_NAME/MBOM_EDITOR : user_name() PL/pgSQL (PR-A0 신설) · MBOM_STATUS/MBOM_PART_NO/MBOM_REGDATE/MBOM_VERSION : mbom_header+history 서브쿼리 · PURCHASE_LIST_OBJID/_DATE : sales_request_master.mbom_header_objid 매칭 · CUSTOMER_NAME : CASE C_% → client_mng / ELSE → supply_mng - controllers/mbomController.ts — getList - routes/productionMbomRoutes.ts — GET /list - app.ts — /api/production/mbom 마운트 (productionRoutes 다음) 프론트 (3 파일): - lib/api/mbom.ts — MbomListFilter / MbomRow / mbomApi.list - app/(main)/COMPANY_16/production/mbom/page.tsx — 검색 폼 2행(12 필드) + 16 컬럼 DataGrid · comm_code 옵션 로드: /api/sales/codes/0000167 (주문유형) /0000001 (제품구분) /0001782 (유무상) · 고객사: /api/sales/customers 재사용 (customer_mng) · 국내/해외 + 유상/무상 raw 옵션 - app/(main)/COMPANY_16/purchase/mbom/page.tsx — production/mbom 페이지 re-export (사용자 요청: 구매관리 메뉴 트리에도 동일 화면 노출) 메뉴 (data-sync): - 03_mbom_menu_dedup.sql — menu_info 100016(purchase/mbom) + 100032(production/mbom) 양쪽 active 보장 (이미 DB에 등록되어 있던 entry) PR-A2 이후 분리: - 단건 상세 다이얼로그, read-only mbom_detail 트리 표시 - BOM 복사 (E-BOM→M-BOM 트리 복사) - 구매리스트 생성 액션 (M-BOM→PURCHASE) - M-BOM 본 편집 (4프레임 팝업) 검증: - backend nodemon hot-load OK (401 TOKEN_MISSING 응답으로 라우터 등록 확인) - 매퍼 SQL 직접 실행: PROJECT_MGMT × CONTRACT_ITEM 5건 + CUSTOMER/M-BOM 매칭 정상 - typecheck: 신규 코드 0 에러 (pre-existing 에러만 잔존) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -119,6 +119,7 @@ import workHistoryRoutes from "./routes/workHistoryRoutes"; // 작업 이력 관
|
||||
import tableHistoryRoutes from "./routes/tableHistoryRoutes"; // 테이블 변경 이력 조회
|
||||
import bomRoutes from "./routes/bomRoutes"; // BOM 이력/버전 관리
|
||||
import productionRoutes from "./routes/productionRoutes"; // 생산계획 관리
|
||||
import productionMbomRoutes from "./routes/productionMbomRoutes"; // 생산관리>M-BOM 관리 (wace_plm 도메인)
|
||||
import itemInspectionRoutes from "./routes/itemInspectionRoutes"; // 품목검사정보
|
||||
import crawlRoutes from "./routes/crawlRoutes"; // 웹 크롤링
|
||||
import roleRoutes from "./routes/roleRoutes"; // 권한 그룹 관리
|
||||
@@ -380,6 +381,7 @@ app.use("/api/work-history", workHistoryRoutes); // 작업 이력 관리
|
||||
app.use("/api/table-history", tableHistoryRoutes); // 테이블 변경 이력 조회
|
||||
app.use("/api/bom", bomRoutes); // BOM 이력/버전 관리
|
||||
app.use("/api/production", productionRoutes); // 생산계획 관리
|
||||
app.use("/api/production/mbom", productionMbomRoutes); // 생산관리>M-BOM 관리 (wace_plm 도메인)
|
||||
app.use("/api/item-inspection", itemInspectionRoutes); // 품목검사정보 (그룹 페이징)
|
||||
app.use("/api/crawl", crawlRoutes); // 웹 크롤링
|
||||
app.use("/api/material-status", materialStatusRoutes); // 자재현황
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// ============================================================
|
||||
// 생산관리 > M-BOM 관리 (PR-A1) — wace productionplanning.xml 1:1 이식.
|
||||
// 라우트:
|
||||
// GET /api/production/mbom/list M-BOM 관리 그리드 (PROJECT_MGMT × CONTRACT_ITEM 펼침)
|
||||
// ============================================================
|
||||
|
||||
import { Response } from "express";
|
||||
import { AuthenticatedRequest } from "../types/auth";
|
||||
import * as svc from "../services/mbomService";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
function parseFilter(q: Record<string, any>): svc.MbomListFilter {
|
||||
const filter: svc.MbomListFilter = { ...q };
|
||||
if (q.page) filter.page = Number(q.page);
|
||||
if (q.page_size) filter.page_size = Number(q.page_size);
|
||||
return filter;
|
||||
}
|
||||
|
||||
export async function getList(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const data = await svc.list(parseFilter(req.query as Record<string, any>));
|
||||
return res.json({ success: true, data });
|
||||
} catch (e: any) {
|
||||
logger.error("M-BOM 관리 목록 실패", { error: e.message });
|
||||
return res.status(500).json({ success: false, message: e.message });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// ============================================================
|
||||
// 생산관리 > M-BOM 관리 (PR-A1) 라우트.
|
||||
// app.ts: app.use("/api/production/mbom", productionMbomRoutes)
|
||||
// ============================================================
|
||||
|
||||
import { Router } from "express";
|
||||
import { authenticateToken } from "../middleware/authMiddleware";
|
||||
import * as ctrl from "../controllers/mbomController";
|
||||
|
||||
const router = Router();
|
||||
router.use(authenticateToken);
|
||||
|
||||
router.get("/list", ctrl.getList);
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,277 @@
|
||||
// ============================================================
|
||||
// 생산관리 > M-BOM 관리 (PR-A1) — wace productionplanning.xml 1:1 이식.
|
||||
//
|
||||
// 매퍼 매핑 (원본: wace_plm/src/com/pms/mapper/productionplanning.xml):
|
||||
// mBomMgmtGridList → list() (라인 2874~3119, PROJECT_MGMT × CONTRACT_ITEM 펼침)
|
||||
//
|
||||
// 그리드 베이스: PROJECT_MGMT × CONTRACT_ITEM 펼침 (1 프로젝트 = 1+ 행).
|
||||
// 9 검색 필터 + 30+ 출력 컬럼 (M-BOM 상태/저장일/작성자 + 구매리스트 매칭).
|
||||
// vexplor_rps 의존: project_mgmt / contract_mgmt / contract_item / contract_item_serial
|
||||
// / mbom_header (PR-A0) / mbom_history / sales_request_master / client_mng
|
||||
// / supply_mng / part_bom_report / comm_code / user_info / user_name() fn
|
||||
// ============================================================
|
||||
|
||||
import { getPool } from "../database/db";
|
||||
|
||||
// ─── 필터/페이지 타입 ──────────────────────────────────────────
|
||||
|
||||
export interface MbomListFilter {
|
||||
search_category_cd?: string;
|
||||
search_product_cd?: string;
|
||||
search_area_cd?: string;
|
||||
search_customer_objid?: string;
|
||||
search_paid_type?: string;
|
||||
search_serial_no?: string;
|
||||
search_part_no?: string;
|
||||
search_part_name?: string;
|
||||
search_receipt_date_from?: string;
|
||||
search_receipt_date_to?: string;
|
||||
search_req_del_date_from?: string;
|
||||
search_req_del_date_to?: string;
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
}
|
||||
|
||||
function paginate(filter: { page?: number; page_size?: number }) {
|
||||
const page = Math.max(1, Number(filter.page) || 1);
|
||||
const pageSize = Math.min(500, Math.max(1, Number(filter.page_size) || 50));
|
||||
return { limit: pageSize, offset: (page - 1) * pageSize, page, pageSize };
|
||||
}
|
||||
|
||||
// ─── WHERE 절 빌더 (매퍼 mBomMgmtGridList <if> 조건 1:1) ──────
|
||||
|
||||
function buildWhere(filter: MbomListFilter, startIdx: number) {
|
||||
const params: any[] = [];
|
||||
const conds: string[] = [];
|
||||
let idx = startIdx;
|
||||
|
||||
if (filter.search_category_cd) {
|
||||
conds.push(`CM.CATEGORY_CD = $${idx++}`);
|
||||
params.push(filter.search_category_cd);
|
||||
}
|
||||
if (filter.search_product_cd) {
|
||||
conds.push(`CM.PRODUCT = $${idx++}`);
|
||||
params.push(filter.search_product_cd);
|
||||
}
|
||||
if (filter.search_area_cd) {
|
||||
// 운영판: CODE_NAME(CM.AREA_CD) = '국내'/'해외' (사람이 보는 값으로 검색)
|
||||
conds.push(`(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.AREA_CD LIMIT 1) = $${idx++}`);
|
||||
params.push(filter.search_area_cd);
|
||||
}
|
||||
if (filter.search_receipt_date_from) {
|
||||
conds.push(`PM.REGDATE >= TO_DATE($${idx++}, 'YYYY-MM-DD')`);
|
||||
params.push(filter.search_receipt_date_from);
|
||||
}
|
||||
if (filter.search_receipt_date_to) {
|
||||
conds.push(`PM.REGDATE < TO_DATE($${idx++}, 'YYYY-MM-DD') + INTERVAL '1 day'`);
|
||||
params.push(filter.search_receipt_date_to);
|
||||
}
|
||||
if (filter.search_customer_objid) {
|
||||
// 운영판 3-way 매칭 (C_xxx 양방향) 1:1
|
||||
conds.push(
|
||||
`(CM.CUSTOMER_OBJID = $${idx} OR CM.CUSTOMER_OBJID = REPLACE($${idx}, 'C_', '') OR 'C_' || CM.CUSTOMER_OBJID = $${idx})`
|
||||
);
|
||||
params.push(filter.search_customer_objid);
|
||||
idx++;
|
||||
}
|
||||
if (filter.search_paid_type) {
|
||||
conds.push(`CM.PAID_TYPE = $${idx++}`);
|
||||
params.push(filter.search_paid_type);
|
||||
}
|
||||
if (filter.search_serial_no) {
|
||||
conds.push(
|
||||
`EXISTS (SELECT 1 FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID::VARCHAR = PM.CONTRACT_ITEM_OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND UPPER(CIS.SERIAL_NO) LIKE '%' || UPPER($${idx++}) || '%')`
|
||||
);
|
||||
params.push(filter.search_serial_no);
|
||||
}
|
||||
if (filter.search_req_del_date_from) {
|
||||
conds.push(`COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) >= $${idx++}`);
|
||||
params.push(filter.search_req_del_date_from);
|
||||
}
|
||||
if (filter.search_req_del_date_to) {
|
||||
conds.push(`COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) <= $${idx++}`);
|
||||
params.push(filter.search_req_del_date_to);
|
||||
}
|
||||
if (filter.search_part_no) {
|
||||
conds.push(
|
||||
`(UPPER(PM.PART_NO) LIKE '%' || UPPER($${idx}) || '%' OR UPPER(CI.PART_NO) LIKE '%' || UPPER($${idx}) || '%')`
|
||||
);
|
||||
params.push(filter.search_part_no);
|
||||
idx++;
|
||||
}
|
||||
if (filter.search_part_name) {
|
||||
conds.push(
|
||||
`(UPPER(PM.PART_NAME) LIKE '%' || UPPER($${idx}) || '%' OR UPPER(CI.PART_NAME) LIKE '%' || UPPER($${idx}) || '%')`
|
||||
);
|
||||
params.push(filter.search_part_name);
|
||||
idx++;
|
||||
}
|
||||
|
||||
return { sql: conds.length ? "AND " + conds.join(" AND ") : "", params };
|
||||
}
|
||||
|
||||
// ─── M-BOM 관리 그리드 ──────────────────────────────────────────
|
||||
//
|
||||
// 매퍼 productionplanning.xml mBomMgmtGridList (라인 2874~3119) 1:1 이식.
|
||||
|
||||
export async function list(filter: MbomListFilter) {
|
||||
const { limit, offset, page, pageSize } = paginate(filter);
|
||||
const where = buildWhere(filter, 1);
|
||||
const pool = getPool();
|
||||
|
||||
const baseSql = `
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT OUTER JOIN CONTRACT_ITEM CI ON (
|
||||
CASE
|
||||
WHEN PM.CONTRACT_ITEM_OBJID IS NOT NULL THEN CI.OBJID::VARCHAR = PM.CONTRACT_ITEM_OBJID
|
||||
ELSE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID AND CI.PART_OBJID = PM.PART_OBJID
|
||||
END
|
||||
)
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE 1=1
|
||||
AND PM.PROJECT_NO IS NOT NULL
|
||||
AND PM.PROJECT_NO != ''
|
||||
${where.sql}
|
||||
`;
|
||||
|
||||
const dataSql = `
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.CONTRACT_OBJID,
|
||||
PM.PROJECT_NO,
|
||||
CM.CATEGORY_CD,
|
||||
COALESCE((SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.CATEGORY_CD LIMIT 1), '') AS CATEGORY_NAME,
|
||||
CM.PRODUCT,
|
||||
COALESCE((SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1), '') AS PRODUCT_NAME,
|
||||
CM.AREA_CD,
|
||||
COALESCE((SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.AREA_CD LIMIT 1), '') AS AREA_NAME,
|
||||
TO_CHAR(PM.REGDATE, 'YYYY-MM-DD') AS RECEIPT_DATE,
|
||||
(SELECT user_name(MH.WRITER)
|
||||
FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR
|
||||
AND MH.STATUS = 'Y'
|
||||
ORDER BY MH.REGDATE DESC
|
||||
LIMIT 1) AS WRITER_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
CASE WHEN CM.CUSTOMER_OBJID LIKE 'C_%'
|
||||
THEN (SELECT CLIENT_NM FROM CLIENT_MNG AS C
|
||||
WHERE 'C_' || C.OBJID::VARCHAR = CM.CUSTOMER_OBJID LIMIT 1)
|
||||
ELSE (SELECT SUPPLY_NAME FROM SUPPLY_MNG
|
||||
WHERE OBJID::VARCHAR = CM.CUSTOMER_OBJID::VARCHAR LIMIT 1) END,
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
CM.PAID_TYPE,
|
||||
COALESCE((SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PAID_TYPE LIMIT 1),
|
||||
CASE
|
||||
WHEN CM.PAID_TYPE = 'paid' THEN '유상'
|
||||
WHEN CM.PAID_TYPE = 'free' THEN '무상'
|
||||
ELSE '' END
|
||||
) AS PAID_TYPE_NAME,
|
||||
-- 품목 정보: CONTRACT_ITEM 우선, 없으면 PM
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
CI.PART_OBJID,
|
||||
-- S/N 표시: "첫S/N 외 N건"
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건' END
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID::VARCHAR = PM.CONTRACT_ITEM_OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL
|
||||
AND CIS.SERIAL_NO != ''
|
||||
) AS SERIAL_NO,
|
||||
-- S/N 전체 (콤마 리스트) — 팝업용
|
||||
(SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID::VARCHAR = PM.CONTRACT_ITEM_OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL
|
||||
AND CIS.SERIAL_NO != ''
|
||||
) AS SERIAL_NO_LIST,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, NULLIF(CI.ORDER_QUANTITY, '')::numeric, 0) AS QUANTITY,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
-- E-BOM 정보
|
||||
COALESCE(CI.PART_OBJID, PM.PART_OBJID) AS BOM_REPORT_OBJID,
|
||||
COALESCE((SELECT PBR.STATUS FROM PART_BOM_REPORT PBR
|
||||
WHERE PBR.OBJID::VARCHAR = COALESCE(CI.PART_OBJID, PM.PART_OBJID) LIMIT 1), '') AS EBOM_STATUS,
|
||||
COALESCE((SELECT TO_CHAR(PBR.REGDATE, 'YYYY-MM-DD') FROM PART_BOM_REPORT PBR
|
||||
WHERE PBR.OBJID::VARCHAR = COALESCE(CI.PART_OBJID, PM.PART_OBJID) LIMIT 1), '') AS EBOM_REGDATE,
|
||||
-- M-BOM HEADER OBJID
|
||||
(SELECT MH.OBJID::VARCHAR FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR AND MH.STATUS = 'Y'
|
||||
ORDER BY MH.REGDATE DESC LIMIT 1) AS MBOM_HEADER_OBJID,
|
||||
-- 구매리스트 OBJID + 생성일
|
||||
(SELECT SRM.OBJID::VARCHAR FROM SALES_REQUEST_MASTER SRM
|
||||
WHERE SRM.MBOM_HEADER_OBJID = (
|
||||
SELECT MH.OBJID::VARCHAR FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR AND MH.STATUS = 'Y'
|
||||
ORDER BY MH.REGDATE DESC LIMIT 1
|
||||
) LIMIT 1) AS PURCHASE_LIST_OBJID,
|
||||
(SELECT TO_CHAR(SRM.REGDATE, 'YYYY-MM-DD') FROM SALES_REQUEST_MASTER SRM
|
||||
WHERE SRM.MBOM_HEADER_OBJID = (
|
||||
SELECT MH.OBJID::VARCHAR FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR AND MH.STATUS = 'Y'
|
||||
ORDER BY MH.REGDATE DESC LIMIT 1
|
||||
) LIMIT 1) AS PURCHASE_LIST_DATE,
|
||||
-- M-BOM 상태 ('Y' 있으면 Y, 아니면 PM.mbom_status raw)
|
||||
COALESCE(
|
||||
(SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE COALESCE(PM.MBOM_STATUS, '') END
|
||||
FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR AND MH.STATUS = 'Y' LIMIT 1),
|
||||
COALESCE(PM.MBOM_STATUS, '')
|
||||
) AS MBOM_STATUS,
|
||||
-- M-BOM 품번
|
||||
COALESCE(
|
||||
(SELECT MH.MBOM_NO FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR AND MH.STATUS = 'Y'
|
||||
ORDER BY MH.REGDATE DESC LIMIT 1), ''
|
||||
) AS MBOM_PART_NO,
|
||||
-- M-BOM 저장일 (수정일 우선, 없으면 등록일)
|
||||
(SELECT TO_CHAR(COALESCE(MH.EDIT_DATE, MH.REGDATE), 'YYYY-MM-DD')
|
||||
FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR AND MH.STATUS = 'Y'
|
||||
ORDER BY COALESCE(MH.EDIT_DATE, MH.REGDATE) DESC LIMIT 1) AS MBOM_REGDATE,
|
||||
-- M-BOM 작성자/수정자
|
||||
(SELECT user_name(COALESCE(MH.EDITER, MH.WRITER))
|
||||
FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR AND MH.STATUS = 'Y'
|
||||
ORDER BY COALESCE(MH.EDITER, MH.WRITER) DESC LIMIT 1) AS MBOM_EDITOR,
|
||||
-- M-BOM 변경이력 카운트 (0이면 NULL)
|
||||
NULLIF(
|
||||
(SELECT COUNT(1)::INTEGER FROM MBOM_HISTORY MHI
|
||||
WHERE MHI.MBOM_HEADER_OBJID = (
|
||||
SELECT MH.OBJID::VARCHAR FROM MBOM_HEADER MH
|
||||
WHERE MH.PROJECT_OBJID = PM.OBJID::VARCHAR AND MH.STATUS = 'Y'
|
||||
ORDER BY MH.REGDATE DESC LIMIT 1
|
||||
)), 0
|
||||
) AS MBOM_VERSION
|
||||
${baseSql}
|
||||
ORDER BY PM.REGDATE DESC, CI.PART_NO
|
||||
LIMIT $${where.params.length + 1} OFFSET $${where.params.length + 2}
|
||||
`;
|
||||
|
||||
const countSql = `SELECT COUNT(*)::int AS cnt ${baseSql}`;
|
||||
|
||||
const dataParams = [...where.params, limit, offset];
|
||||
|
||||
const [dataRes, countRes] = await Promise.all([
|
||||
pool.query(dataSql, dataParams),
|
||||
pool.query(countSql, where.params),
|
||||
]);
|
||||
|
||||
return {
|
||||
rows: dataRes.rows,
|
||||
totalCount: countRes.rows[0]?.cnt ?? 0,
|
||||
page,
|
||||
pageSize,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user