feat(statement-branch): 사용자별 거래명세서 공급자 정보 분기 (본사/김포)
Deploy momo-erp / deploy (push) Successful in 1m59s

마이그레이션 027:
- user_info 에 statement_branch VARCHAR(10) DEFAULT 'HQ' 컬럼 추가
- 기존 사용자 일괄 'HQ' 로 채움

라이브러리:
- src/lib/momo-branches.ts 신설 — HQ / KIMPO 두 branch 의 공급자 정보 정의
  · HQ: 기업은행 434-115361-01-016 (이상용) / 010-6369-8443 / momo8443@daum.net
  · KIMPO: 농협 351-1383-7634-13 (모모유통) / 010-5789-9431 / momokimpo@nate.com
- getSupplierByBranch(branch) helper

거래명세표 supplier 분기 (3개 API):
- /api/m/orders/detail: order.STATEMENT_BRANCH 따라 supplier 객체 결정
- /api/m/orders/statement/[id]: xlsx 다운로드도 동일
- /api/m/orders/approve: 메일 발송 stmt 도 동일

사용자 수정 폼:
- /api/admin/users/detail: statement_branch 반환 (default 'HQ')
- /api/admin/users/save: statement_branch 받아 UPDATE
- /admin-panel/user-form: "기준 거래명세서" select 추가 (본사/김포)

흐름: 거래처 사용자의 기준을 김포로 설정 → 그 사용자의 발주에 대한 거래명세표 supplier 가 김포 정보로 표시

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
chpark
2026-05-13 15:29:02 +09:00
parent 75f37d8eaf
commit 6ad57356a0
8 changed files with 79 additions and 24 deletions
@@ -0,0 +1,7 @@
-- 사용자별 거래명세서 기준 지점 (본사 / 김포)
-- 거래명세표 발급 시 공급자(supplier) 정보를 두 가지로 분기하기 위함
ALTER TABLE user_info
ADD COLUMN IF NOT EXISTS statement_branch VARCHAR(10) DEFAULT 'HQ';
-- 기존 사용자는 모두 본사로 default
UPDATE user_info SET statement_branch = 'HQ' WHERE statement_branch IS NULL;
+11
View File
@@ -111,6 +111,17 @@ function UserForm() {
))}
</select>
</div>
<div>
<label className="block text-[11px] font-medium text-gray-500 mb-0.5"> <span className="text-gray-400 font-normal">( )</span></label>
<select
value={form.statement_branch || "HQ"}
onChange={(e) => set("statement_branch", e.target.value)}
className="h-8 w-full rounded border border-gray-300 bg-white px-2 text-[12px]"
>
<option value="HQ"> ( / )</option>
<option value="KIMPO"> ( / )</option>
</select>
</div>
<div>
<label className="block text-[11px] font-medium text-gray-500 mb-0.5"> </label>
<div className="flex gap-2 h-8 items-center">
+1
View File
@@ -17,6 +17,7 @@ export async function POST(request: NextRequest) {
COALESCE(unlimited_qty, 'N') AS "unlimited_qty",
COALESCE(view_hidden, 'N') AS "view_hidden",
default_wh_objid::text AS "default_wh_objid",
COALESCE(statement_branch, 'HQ') AS "statement_branch",
TO_CHAR(regdate, 'YYYY-MM-DD') AS "regdate"
FROM user_info WHERE user_id = $1`,
[body.userId || ""]
+4 -2
View File
@@ -33,6 +33,7 @@ export async function POST(request: NextRequest) {
const viewHidden = body.view_hidden === "Y" ? "Y" : "N";
// 빈 문자열 / undefined → NULL 처리
const defaultWh = body.default_wh_objid && String(body.default_wh_objid).trim() !== "" ? body.default_wh_objid : null;
const stmtBranch = body.statement_branch === "KIMPO" ? "KIMPO" : "HQ";
await client.query(
`UPDATE user_info SET
user_name=$1, sabun=$2, dept_code=$3, dept_name=$4,
@@ -40,14 +41,15 @@ export async function POST(request: NextRequest) {
address=COALESCE($11, address), ceo_name=COALESCE($12, ceo_name),
biz_no=COALESCE($13, biz_no),
unlimited_qty=$14, view_hidden=$15,
default_wh_objid=$16
default_wh_objid=$16,
statement_branch=$17
WHERE user_id=$10`,
[body.user_name || "", body.sabun || "", body.dept_code || "",
body.dept_name || "", body.position_name || "", body.email || "",
body.cell_phone || "", body.user_type || "", body.tel || "",
body.user_id || "",
body.address ?? null, body.ceo_name ?? null, body.biz_no ?? null,
unlimited, viewHidden, defaultWh]
unlimited, viewHidden, defaultWh, stmtBranch]
);
}
return NextResponse.json({ success: true, message: isNew ? "등록되었습니다." : "수정되었습니다." });
+6 -6
View File
@@ -5,6 +5,7 @@ import { createObjectId } from "@/lib/utils";
import { requireMomoAdmin } from "@/lib/momo-guard";
import { buildStatementHtml, buildStatementXlsx } from "@/lib/excel-statement";
import { sendMail } from "@/lib/mailer";
import { getSupplierByBranch } from "@/lib/momo-branches";
export async function POST(req: NextRequest) {
const g = await requireMomoAdmin();
@@ -114,6 +115,7 @@ export async function POST(req: NextRequest) {
`SELECT O.objid, O.order_no, TO_CHAR(O.order_date,'YYYY-MM-DD') AS order_date,
U.user_name AS company_name, U.email,
U.ceo_name, U.biz_no, U.cell_phone AS phone, U.address,
U.statement_branch,
O.total_supply, O.total_vat, O.total_amount,
O.total_taxfree, O.total_taxable
FROM momo_orders O
@@ -137,12 +139,10 @@ export async function POST(req: NextRequest) {
bizNo: order.biz_no as string | undefined,
phone: order.phone as string | undefined,
},
supplier: {
companyName: "모모유통",
bankAccount: process.env.MOMO_BANK_ACCOUNT ?? "기업은행 ____",
phone: process.env.MOMO_PHONE ?? "010-6624-5315",
email: process.env.SMTP_FROM ?? "momo8443@daum.net",
},
supplier: (() => {
const b = getSupplierByBranch(order.statement_branch as string | undefined);
return { companyName: b.NAME, bankAccount: b.BANK_ACCOUNT, phone: b.PHONE, email: b.EMAIL };
})(),
items: items.map((it) => ({
seq: Number(it.seq),
itemName: String(it.item_name_snap),
+5 -10
View File
@@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import { queryOne, queryRows } from "@/lib/db";
import { requireMomoUser } from "@/lib/momo-guard";
import { getSupplierByBranch } from "@/lib/momo-branches";
export async function POST(req: NextRequest) {
const r = await requireMomoUser();
@@ -17,6 +18,7 @@ export async function POST(req: NextRequest) {
U.user_name AS "COMPANY_NAME", U.email AS "EMAIL",
U.ceo_name AS "CEO_NAME", U.biz_no AS "BIZ_NO",
U.cell_phone AS "PHONE", U.address AS "ADDRESS",
U.statement_branch AS "STATEMENT_BRANCH",
O.status AS "STATUS", O.memo AS "MEMO",
O.total_supply AS "TOTAL_SUPPLY", O.total_vat AS "TOTAL_VAT",
O.total_amount AS "TOTAL_AMOUNT",
@@ -75,16 +77,9 @@ export async function POST(req: NextRequest) {
[objid]
);
// 공급자(모모유통) 정보 — 환경변수 또는 기본값
const supplier = {
NAME: process.env.MOMO_COMPANY_NAME || "모모유통",
CEO: process.env.MOMO_COMPANY_CEO || "이상용",
BIZ_NO: process.env.MOMO_COMPANY_BIZNO || "",
BANK_ACCOUNT: process.env.MOMO_BANK_ACCOUNT || "기업은행 434-115361-01-016 (이상용)",
PHONE: process.env.MOMO_PHONE || "010-6369-8443",
EMAIL: process.env.MOMO_EMAIL || "momo8443@daum.net",
ADDRESS: process.env.MOMO_COMPANY_ADDR || "",
};
// 공급자(모모유통) 정보 — 거래처(사용자)의 statement_branch (HQ / KIMPO) 에 따라 분기
const branch = (order as { STATEMENT_BRANCH?: string }).STATEMENT_BRANCH ?? "HQ";
const supplier = getSupplierByBranch(branch);
return NextResponse.json({ success: true, order, items, supplier });
}
+6 -6
View File
@@ -3,6 +3,7 @@ import { NextRequest, NextResponse } from "next/server";
import { queryOne, queryRows } from "@/lib/db";
import { requireMomoUser } from "@/lib/momo-guard";
import { buildStatementXlsx } from "@/lib/excel-statement";
import { getSupplierByBranch } from "@/lib/momo-branches";
export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string }> }) {
const r = await requireMomoUser();
@@ -18,6 +19,7 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
U.cell_phone AS phone,
U.address AS address,
U.email AS email,
U.statement_branch AS statement_branch,
O.total_supply, O.total_vat, O.total_amount,
O.total_taxfree, O.total_taxable,
COALESCE(O.paid_amount, 0) AS paid_amount
@@ -55,12 +57,10 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
bizNo: order.biz_no as string | undefined,
phone: order.phone as string | undefined,
},
supplier: {
companyName: "모모유통",
bankAccount: process.env.MOMO_BANK_ACCOUNT ?? "기업은행 ____",
phone: process.env.MOMO_PHONE ?? "010-6624-5315",
email: process.env.SMTP_FROM ?? "momo8443@daum.net",
},
supplier: (() => {
const b = getSupplierByBranch(order.statement_branch as string | undefined);
return { companyName: b.NAME, bankAccount: b.BANK_ACCOUNT, phone: b.PHONE, email: b.EMAIL };
})(),
items: items.map((it, idx) => {
const isExtra = it.kind === "DELIVERY" || it.kind === "CHARTER";
return {
+39
View File
@@ -0,0 +1,39 @@
// 모모유통 공급자(supplier) 정보 — 거래명세표/계산서 발행 시 사용자별로 분기
// 사용자(user_info.statement_branch) 가 'HQ' / 'KIMPO' 중 어느 값이냐에 따라 적용
export type StatementBranch = "HQ" | "KIMPO";
export interface BranchSupplier {
NAME: string;
CEO: string;
BANK_ACCOUNT: string;
PHONE: string;
EMAIL: string;
BIZ_NO: string;
ADDRESS: string;
}
export const SUPPLIER_BRANCHES: Record<StatementBranch, BranchSupplier> = {
HQ: {
NAME: "모모유통",
CEO: "이상용",
BANK_ACCOUNT: "기업은행 434-115361-01-016 (이상용)",
PHONE: "010-6369-8443",
EMAIL: "momo8443@daum.net",
BIZ_NO: "",
ADDRESS: "",
},
KIMPO: {
NAME: "모모유통",
CEO: "이상용",
BANK_ACCOUNT: "농협 351-1383-7634-13 (모모유통)",
PHONE: "010-5789-9431",
EMAIL: "momokimpo@nate.com",
BIZ_NO: "",
ADDRESS: "",
},
};
export function getSupplierByBranch(branch?: string | null): BranchSupplier {
const key = (branch === "KIMPO" ? "KIMPO" : "HQ") as StatementBranch;
return SUPPLIER_BRANCHES[key];
}