Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE `SettlementAccount` ADD COLUMN `business_type` ENUM('PERSONAL', 'CORPORATE') NULL;
8 changes: 7 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,11 @@ enum SellerType {
BUSINESS
}

enum BusinessType {
PERSONAL // κ°œμΈμ‚¬μ—…μž
CORPORATE // λ²•μΈμ‚¬μ—…μž
}

enum ApprovalStatus {
PENDING // 심사 λŒ€κΈ°μ€‘
APPROVED // 승인 μ™„λ£Œ
Expand All @@ -473,7 +478,8 @@ model SettlementAccount {
account_number String @db.VarChar(30)
account_holder String @db.VarChar(100)
seller_type SellerType @default(INDIVIDUAL)
birth_date String? @db.VarChar(10)
business_type BusinessType? // BUSINESS일 λ•Œλ§Œ PERSONAL/CORPORATE μ§€μ •
birth_date String? @db.VarChar(10) // 정책상 λ―Έμ €μž₯ (PII 폐기). Phase 11μ—μ„œ 컬럼 제거 κ²€ν† 
status ApprovalStatus @default(APPROVED) // κ°œμΈμ€ μ¦‰μ‹œ 승인, μ‚¬μ—…μžλŠ” PENDING으둜 생성
is_active Boolean @default(true)
representative_name String? @db.VarChar(100)
Expand Down
84 changes: 66 additions & 18 deletions src/settlements/constants/bank.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,71 @@
// νŽ˜μ΄ν”Œ bank_code_std (KFTC ν‘œμ€€ 3자리 은행 μ½”λ“œ)
// νŽ˜μ΄ν”Œ bank_code_std (KFTC ν‘œμ€€ 3자리 κΈˆμœ΅κΈ°κ΄€ μ½”λ“œ)
// 좜처: Payple μ •μ‚°μ§€κΈ‰λŒ€ν–‰ 곡식 λͺ…μ„Έ
export const PAYPLE_BANKS: Record<string, string> = {
"002": "산업은행",
"003": "기업은행",
"004": "ꡭ민은행",
// 은행
"002": "KDB산업은행",
"003": "IBK기업은행",
"004": "KBꡭ민은행",
"007": "μˆ˜ν˜‘μ€ν–‰",
"008": "μˆ˜μΆœμž…μ€ν–‰",
"011": "λ†ν˜‘μ€ν–‰",
"012": "μ§€μ—­λ†μΆ•ν˜‘",
"011": "NHλ†ν˜‘μ€ν–‰",
"020": "μš°λ¦¬μ€ν–‰",
"023": "SCμ œμΌμ€ν–‰",
"027": "ν•œκ΅­μ”¨ν‹°μ€ν–‰",
"031": "아이엠뱅크(λŒ€κ΅¬)",
"031": "아이엠뱅크 (ꡬ λŒ€κ΅¬μ€ν–‰)",
"032": "뢀산은행",
"034": "광주은행",
"035": "μ œμ£Όμ€ν–‰",
"037": "전뢁은행",
"039": "경남은행",
"045": "μƒˆλ§ˆμ„κΈˆκ³ ",
"048": "μ‹ ν˜‘",
"050": "저좕은행",
"081": "ν•˜λ‚˜μ€ν–‰",
"088": "μ‹ ν•œμ€ν–‰",
"089": "케이뱅크",
"090": "μΉ΄μΉ΄μ˜€λ±…ν¬",
"092": "ν† μŠ€λ±…ν¬",

// μƒν˜ΈκΈˆμœ΅κΈ°κ΄€
"012": "λ†ν˜‘μ€‘μ•™νšŒ(λ‹¨μœ„λ†μΆ•ν˜‘)",
"030": "μˆ˜μ‚°μ—…ν˜‘λ™μ‘°ν•©μ€‘μ•™νšŒ",
"045": "μƒˆλ§ˆμ„κΈˆκ³ μ€‘μ•™νšŒ",
"048": "μ‹ ν˜‘μ€‘μ•™νšŒ",
"050": "μ €μΆ•μ€ν–‰μ€‘μ•™νšŒ",
"064": "μ‚°λ¦Όμ‘°ν•©μ€‘μ•™νšŒ",
"071": "μš°μ •μ‚¬μ—…λ³ΈλΆ€(우체ꡭ)",

// κΈˆμœ΅νˆ¬μžνšŒμ‚¬ (μ¦κΆŒμ‚¬)
"209": "μœ μ•ˆνƒ€μ¦κΆŒ",
"218": "KB증ꢌ",
"227": "λ‹€μ˜¬νˆ¬μžμ¦κΆŒ",
"238": "λ―Έλž˜μ—μ…‹μ¦κΆŒ",
"240": "μ‚Όμ„±μ¦κΆŒ",
"243": "ν•œκ΅­νˆ¬μžμ¦κΆŒ",
"247": "NH투자증ꢌ",
"261": "ꡐ보증ꢌ",
"262": "μ•„μ΄μ— μ¦κΆŒ",
"263": "ν˜„λŒ€μ°¨μ¦κΆŒ",
"264": "ν‚€μ›€μ¦κΆŒ",
"265": "LS증ꢌ",
"266": "SK증ꢌ",
"267": "λŒ€μ‹ μ¦κΆŒ",
"269": "ν•œν™”νˆ¬μžμ¦κΆŒ",
"270": "ν•˜λ‚˜μ¦κΆŒ",
"271": "ν† μŠ€μ¦κΆŒ",
"278": "μ‹ ν•œκΈˆμœ΅νˆ¬μž",
"279": "DB증ꢌ",
"280": "μœ μ§„νˆ¬μžμ¦κΆŒ",
"287": "λ©”λ¦¬μΈ μ¦κΆŒ",

// λ³΄ν—˜μ‚¬
"436": "ꡐ보생λͺ…",
"443": "DBμ†ν•΄λ³΄ν—˜",

// μΊν”Όνƒˆμ‚¬
"304": "ν˜„λŒ€μΊν”Όνƒˆ",
};

// Payple λͺ…μ„Έμ—μ„œ 제거된 μ½”λ“œ β€” κΈ°μ‘΄ 등둝 μ‚¬μš©μž ν˜Έν™˜ 보쑴용.
// μ‹ κ·œ 등둝/μΈμ¦μ—λŠ” μ‚¬μš© κΈˆμ§€. Phase 11 운영 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ ν›„ 제거 μ˜ˆμ •.
export const LEGACY_PAYPLE_BANKS: Record<string, string> = {
"008": "μˆ˜μΆœμž…μ€ν–‰",
"054": "HSBC은행",
"055": "λ„μ΄μΉ˜μ€ν–‰",
"057": "μ œμ΄ν”Όλͺ¨κ°„μ²΄μ΄μŠ€μ€ν–‰",
Expand All @@ -28,14 +75,15 @@ export const PAYPLE_BANKS: Record<string, string> = {
"061": "λΉ„μ—”ν”ΌνŒŒλ¦¬λ°”μ€ν–‰",
"062": "쀑ꡭ곡상은행",
"063": "쀑ꡭ은행",
"064": "μ‚°λ¦Όμ‘°ν•©",
"067": "쀑ꡭ건섀은행",
"071": "우체ꡭ",
"076": "μ‹ μš©λ³΄μ¦κΈ°κΈˆ",
"077": "기술보증기금",
"081": "ν•˜λ‚˜μ€ν–‰",
"088": "μ‹ ν•œμ€ν–‰",
"089": "케이뱅크",
"090": "μΉ΄μΉ΄μ˜€λ±…ν¬",
"092": "ν† μŠ€λ±…ν¬",
};

export const ALL_KNOWN_BANKS: Record<string, string> = { ...PAYPLE_BANKS, ...LEGACY_PAYPLE_BANKS };

export const isValidPaypleBank = (code: string): boolean =>
Object.prototype.hasOwnProperty.call(PAYPLE_BANKS, code);

export const isKnownBank = (code: string): boolean =>
Object.prototype.hasOwnProperty.call(ALL_KNOWN_BANKS, code);
74 changes: 47 additions & 27 deletions src/settlements/controllers/settlement.account.controller.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,57 @@
import { Request, Response } from 'express';
import { verifyAndSaveAccount, getAccountInfo } from '../services/settlement.account.service';
import { VerifyAccountRequestDto, ViewAccountResponseDto} from '../dtos/settlement.dto';
import { verifySellerAccount, getAccountInfo } from '../services/settlement.account.service';
import { VerifyAccountRequestDto, ViewAccountResponseDto } from '../dtos/settlement.dto';

export const verifyAccount = async (req: Request, res: Response) => {
try {
const user = req.user;
const user = req.user;

if (!user) {
return res.status(401).json({
error: "Unauthorized",
message: "둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.",
statusCode: 401
error: 'Unauthorized',
message: '둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.',
statusCode: 401,
});
}

const dto: VerifyAccountRequestDto = req.body;
const userId = (req.user as { user_id: number }).user_id;
const result = await verifyAndSaveAccount(userId, dto);
const result = await verifySellerAccount(userId, dto);

return res.status(200).json({
message: result.message,
statusCode: 200
registerToken: result.registerToken,
expiresIn: result.expiresIn,
statusCode: 200,
});

} catch (error: any) {
const status = error.status || 500;
const errorType = error.type || "InternalServerError";
const message = error.message || "μ•Œ 수 μ—†λŠ” 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.";

if (error.name === 'AccountVerificationError' || error?.name === 'AccountVerificationError') {
return res.status(400).json({
error: 'AccountVerificationError',
subCode: error.subCode,
message: error.message,
statusCode: 400,
});
}
if (error.error === 'ValidationError' || error?.name === 'ValidationError') {
return res.status(400).json({
error: 'ValidationError',
message: error.message,
statusCode: 400,
});
}
if (error.error === 'InvalidAccountInfo') {
return res.status(400).json({
error: 'InvalidAccountInfo',
message: error.message,
statusCode: 400,
});
}
const status = error.statusCode || 500;
return res.status(status).json({
error: errorType,
message: message,
statusCode: status
error: error.error || 'InternalServerError',
message: error.message || 'μ•Œ 수 μ—†λŠ” 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.',
statusCode: status,
});
}
};
Expand All @@ -42,9 +62,9 @@ export const ViewAccount = async (req: Request, res: Response) => {

if (!user) {
return res.status(401).json({
error: "Unauthorized",
message: "둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.",
statusCode: 401
error: 'Unauthorized',
message: '둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.',
statusCode: 401,
});
}

Expand All @@ -53,21 +73,21 @@ export const ViewAccount = async (req: Request, res: Response) => {
const accountData = await getAccountInfo(userId);

const response: ViewAccountResponseDto = {
message: "κ³„μ’Œ 정보 μ‘°νšŒκ°€ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.",
message: 'κ³„μ’Œ 정보 μ‘°νšŒκ°€ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.',
data: accountData,
statusCode: 200
statusCode: 200,
};

return res.status(200).json(response);
} catch (error: any) {
const status = error.statusCode || 500;
const errorType = error.code || "InternalServerError";
const message = error.message || "μ•Œ 수 μ—†λŠ” 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.";
const errorType = error.code || 'InternalServerError';
const message = error.message || 'μ•Œ 수 μ—†λŠ” 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.';

return res.status(status).json({
error: errorType,
message: message,
statusCode: status
message,
statusCode: status,
});
}
}
};
Loading
Loading