Files
sam-docs/rules/client-policy.md
hskwon 914667738b docs: clients is_active Boolean 변경 반영
- client-policy.md: TINYINT(1), true/false 상태값 반영, Hard Delete 명시
- client-api-analysis.md: 스키마/타입 Boolean 업데이트, Soft Delete → Hard Delete 수정
2025-12-08 20:26:01 +09:00

19 KiB
Raw Permalink Blame History

거래처 관리 정책 (Client Management Policy)

작성일: 2025-12-08 상태: 설계 확정 관련 요청: docs/front/[API-2025-12-04] client-api-analysis.md


1. 개요

1.1 목적

  • 거래처 마스터 통합 관리 (매입처/매출처/매입매출)
  • 고객그룹 기반 단가 정책 연계
  • 세금계산서 합의 및 불량 채권 관리
  • 주문/발주 연동을 위한 거래처 기반 시스템

1.2 핵심 원칙

원칙 설명
거래처 유형 분류 매입, 매출, 매입매출로 구분 관리
코드 유일성 tenant 내 client_code 중복 불가
그룹 기반 단가 고객그룹별 차등 판매가 적용
연관 데이터 보호 주문 존재 시 삭제 불가

2. 테이블 구조

2.1 ERD 개요

┌─────────────────┐       ┌─────────────────────┐
│  client_groups  │──────<│      clients        │
│   (고객 그룹)    │       │     (거래처)        │
└────────┬────────┘       └─────────┬───────────┘
         │                          │
         │ price_rate               │ client_id
         │                          │
         ▼                          ▼
┌─────────────────┐       ┌─────────────────────┐
│     prices      │       │      orders         │
│    (차등 단가)   │       │      (주문)         │
└─────────────────┘       └─────────────────────┘

2.2 clients 테이블 (거래처 마스터)

CREATE TABLE clients (
    id                      BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id               BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
    client_group_id         BIGINT UNSIGNED NULL COMMENT '고객그룹 ID',

    -- 기본 정보 --
    client_code             VARCHAR(50) NOT NULL COMMENT '거래처 코드',
    name                    VARCHAR(100) NOT NULL COMMENT '거래처명',
    client_type             VARCHAR(20) NULL COMMENT '거래처 유형 (매입/매출/매입매출)',
    is_active               TINYINT(1) DEFAULT 1 COMMENT '활성여부(1=활성,0=비활성)',

    -- 사업자 정보 --
    business_no             VARCHAR(20) NULL COMMENT '사업자등록번호',
    business_type           VARCHAR(50) NULL COMMENT '업태',
    business_item           VARCHAR(100) NULL COMMENT '업종',

    -- 연락처 정보 --
    contact_person          VARCHAR(50) NULL COMMENT '담당자명',
    phone                   VARCHAR(30) NULL COMMENT '전화번호',
    mobile                  VARCHAR(20) NULL COMMENT '휴대폰',
    fax                     VARCHAR(20) NULL COMMENT '팩스',
    email                   VARCHAR(80) NULL COMMENT '이메일',
    address                 VARCHAR(255) NULL COMMENT '주소',

    -- 담당자 정보 --
    manager_name            VARCHAR(50) NULL COMMENT '당사 담당자명',
    manager_tel             VARCHAR(20) NULL COMMENT '당사 담당자 연락처',
    system_manager          VARCHAR(50) NULL COMMENT '시스템 담당자',

    -- 계정 정보 --
    account_id              VARCHAR(50) NULL COMMENT '계정 ID',
    account_password        VARCHAR(255) NULL COMMENT '계정 비밀번호 (hidden)',

    -- 발주/결제 설정 --
    purchase_payment_day    VARCHAR(20) NULL COMMENT '매입 결제일',
    sales_payment_day       VARCHAR(20) NULL COMMENT '매출 결제일',

    -- 세금계산서 합의 --
    tax_agreement           BOOLEAN DEFAULT FALSE COMMENT '세금계산서 합의 여부',
    tax_amount              DECIMAL(15,2) NULL COMMENT '합의 금액',
    tax_start_date          DATE NULL COMMENT '합의 시작일',
    tax_end_date            DATE NULL COMMENT '합의 종료일',

    -- 불량 채권 관리 --
    bad_debt                BOOLEAN DEFAULT FALSE COMMENT '불량 채권 여부',
    bad_debt_amount         DECIMAL(15,2) NULL COMMENT '불량 채권 금액',
    bad_debt_receive_date   DATE NULL COMMENT '채권 발생일',
    bad_debt_end_date       DATE NULL COMMENT '채권 종료일',
    bad_debt_progress       VARCHAR(20) NULL COMMENT '진행 상태',

    -- 기타 --
    memo                    TEXT NULL COMMENT '메모',

    -- 감사 컬럼 --
    created_by              BIGINT UNSIGNED NULL COMMENT '생성자 ID',
    updated_by              BIGINT UNSIGNED NULL COMMENT '수정자 ID',
    created_at              TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at              TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    -- 인덱스 --
    INDEX idx_clients_tenant (tenant_id),
    INDEX idx_clients_code (tenant_id, client_code),
    INDEX idx_clients_group (tenant_id, client_group_id),
    INDEX idx_clients_type (tenant_id, client_type),
    INDEX idx_clients_active (tenant_id, is_active),
    UNIQUE idx_clients_unique (tenant_id, client_code),

    FOREIGN KEY (client_group_id) REFERENCES client_groups(id) ON DELETE SET NULL
) COMMENT='거래처 마스터';

2.3 client_groups 테이블 (고객 그룹)

CREATE TABLE client_groups (
    id                  BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id           BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',

    -- 그룹 정보 --
    group_code          VARCHAR(50) NOT NULL COMMENT '그룹 코드',
    group_name          VARCHAR(100) NOT NULL COMMENT '그룹명',
    price_rate          DECIMAL(5,4) DEFAULT 1.0000 COMMENT '단가 비율 (1.0 = 100%)',
    is_active           BOOLEAN DEFAULT TRUE COMMENT '활성 상태',

    -- 감사 컬럼 --
    created_by          BIGINT UNSIGNED NULL COMMENT '생성자 ID',
    updated_by          BIGINT UNSIGNED NULL COMMENT '수정자 ID',
    deleted_by          BIGINT UNSIGNED NULL COMMENT '삭제자 ID',
    created_at          TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at          TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at          TIMESTAMP NULL COMMENT 'Soft Delete',

    -- 인덱스 --
    INDEX idx_groups_tenant (tenant_id),
    INDEX idx_groups_code (tenant_id, group_code),
    INDEX idx_groups_active (tenant_id, is_active),
    UNIQUE idx_groups_unique (tenant_id, group_code, deleted_at)
) COMMENT='고객 그룹';

3. 거래처 유형 정책

3.1 거래처 유형 (client_type)

유형 설명 용도
매입 자재/상품 구매처 발주, 입고, 매입 관리
매출 제품/상품 판매처 주문, 출고, 매출 관리
매입매출 양방향 거래처 매입+매출 모두 가능

3.2 유형별 업무 흐름

┌───────────────────────────────────────────────────────────────┐
│                        매입 거래처                              │
├───────────────────────────────────────────────────────────────┤
│  발주요청 → 발주서 → 입고 → 수입검사 → 매입확정 → 대금지급    │
└───────────────────────────────────────────────────────────────┘

┌───────────────────────────────────────────────────────────────┐
│                        매출 거래처                              │
├───────────────────────────────────────────────────────────────┤
│  견적 → 수주 → 생산 → 출고 → 매출확정 → 대금수금              │
└───────────────────────────────────────────────────────────────┘

4. 고객그룹과 단가 연계

4.1 단가 적용 우선순위

┌─────────────────────────────────────────────────────────┐
│                  판매가 조회 로직                        │
├─────────────────────────────────────────────────────────┤
│  1순위: 고객그룹별 특별 단가                            │
│         prices WHERE client_group_id = [거래처.그룹ID]  │
│                                                         │
│  2순위: 기본 판매가                                     │
│         prices WHERE client_group_id IS NULL            │
└─────────────────────────────────────────────────────────┘

4.2 단가 비율 적용 (price_rate)

최종 판매가 = 기본 판매가 × price_rate

예시:
- 기본 판매가: 10,000원
- VIP 그룹 price_rate: 0.90 (10% 할인)
- 최종 판매가: 10,000 × 0.90 = 9,000원

4.3 그룹 활용 예시

그룹 코드 그룹명 price_rate 설명
DEFAULT 일반 고객 1.0000 정가 적용
VIP VIP 고객 0.9000 10% 할인
WHOLESALE 도매 거래처 0.8000 20% 할인
PARTNER 협력 업체 0.8500 15% 할인

5. 세금계산서 합의 관리

5.1 합의 정보 구조

필드 설명 용도
tax_agreement 합의 여부 세금계산서 발행 방식 결정
tax_amount 합의 금액 월정액 또는 고정 금액
tax_start_date 시작일 합의 유효 기간 시작
tax_end_date 종료일 합의 유효 기간 종료

5.2 합의 유형

┌─────────────────────────────────────────────────────────┐
│   tax_agreement = FALSE                                 │
│   → 실제 거래 금액으로 세금계산서 발행                   │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│   tax_agreement = TRUE                                  │
│   → 합의 금액(tax_amount)으로 세금계산서 발행           │
│   → 유효 기간: tax_start_date ~ tax_end_date            │
└─────────────────────────────────────────────────────────┘

6. 불량 채권 관리

6.1 불량 채권 정보 구조

필드 설명
bad_debt 불량 채권 여부
bad_debt_amount 불량 채권 금액
bad_debt_receive_date 채권 발생일
bad_debt_end_date 채권 종료(해결)일
bad_debt_progress 진행 상태

6.2 진행 상태 (bad_debt_progress)

┌──────────┐     협의     ┌──────────┐     법적조치   ┌──────────┐
│  협의중  │ ──────────> │  소송중  │ ─────────── │ 회수완료 │
└──────────┘              └────┬─────┘              └──────────┘
                               │
                               │ 회수 불가
                               ▼
                          ┌──────────┐
                          │ 대손처리 │
                          └──────────┘

6.3 불량 채권 상태값

상태 설명 후속 조치
협의중 채권 회수 협의 진행 정기 연락, 분할 상환 협의
소송중 법적 절차 진행 법무팀 연계, 소송 진행
회수완료 채권 전액 회수 bad_debt_end_date 기록
대손처리 회수 불가 판정 회계 처리, 거래 중단 검토

7. 상태 관리

7.1 활성 상태 (is_active)

┌──────────────┐     비활성화     ┌──────────────┐
│  true (활성)  │ ───────────── │  false (비활성)│
│   거래가능    │     <───────── │  거래중단      │
└──────────────┘     재활성화     └──────────────┘

7.2 상태별 제약

상태 주문 생성 발주 생성 조회 수정
true (활성)
false (비활성)

7.3 비활성화 고려 사항

  • 불량 채권 거래처: bad_debt = true 시 비활성화 검토
  • 장기 미거래: 12개월 이상 거래 없을 시 비활성화 검토
  • 사업자 폐업: 사업자등록 말소 확인 시 비활성화

8. API 엔드포인트

8.1 엔드포인트 목록

Method Endpoint 설명 우선순위
GET /api/v1/clients 거래처 목록 조회 🔴 필수
GET /api/v1/clients/{id} 거래처 상세 조회 🔴 필수
POST /api/v1/clients 거래처 등록 🔴 필수
PUT /api/v1/clients/{id} 거래처 수정 🔴 필수
DELETE /api/v1/clients/{id} 거래처 삭제 🔴 필수
POST /api/v1/clients/{id}/toggle 활성/비활성 토글 🟡 중요
GET /api/v1/client-groups 고객그룹 목록 🟡 중요
POST /api/v1/client-groups 고객그룹 등록 🟢 권장

8.2 목록 조회 API

GET /api/v1/clients?page=1&size=20&q=검색어&only_active=true

Query Parameters:

파라미터 타입 설명
page int 페이지 번호 (기본: 1)
size int 페이지당 개수 (기본: 20)
q string 검색어 (거래처명, 코드, 담당자)
only_active bool 활성 거래처만 조회

Response:

{
  "success": true,
  "message": "message.fetched",
  "data": {
    "current_page": 1,
    "data": [
      {
        "id": 1,
        "client_code": "C001",
        "name": "ABC 상사",
        "client_type": "매입매출",
        "business_no": "123-45-67890",
        "contact_person": "홍길동",
        "is_active": true,
        "client_group": {
          "id": 1,
          "group_name": "VIP"
        }
      }
    ],
    "total": 100
  }
}

9. 비즈니스 규칙

9.1 검증 규칙

규칙 설명
R1 client_code는 tenant 내 유일해야 함
R2 client_code, name은 필수 값
R3 client_type은 '매입', '매출', '매입매출' 중 하나
R4 주문이 존재하는 거래처는 삭제 불가
R5 email 형식 검증
R6 bad_debt_progress는 지정된 값만 허용
R7 tax_start_date ≤ tax_end_date

9.2 코드 중복 처리

신규 등록 시:
└─ tenant_id + client_code 조합 중복 검사
└─ 중복 시 error.duplicate_code 반환

수정 시:
└─ client_code 변경 시에만 중복 검사 수행
└─ 자기 자신 제외하고 검사

9.3 삭제 정책

테이블 삭제 방식 설명
clients Hard Delete 연관 주문이 없는 경우만 삭제 가능
client_groups Soft Delete deleted_at 컬럼 사용
  • 연관 데이터 보호: orders 존재 시 error.has_orders 반환
  • 주문 있는 거래처: 비활성화(is_active = false)로 처리 권장

9.4 비밀번호 보호

protected $hidden = ['account_password'];
  • account_password는 API 응답에서 자동 제외
  • 저장 시 평문 저장 (필요시 암호화 적용 검토)

10. 필드 분류

10.1 기본 정보 (4개)

필드 타입 필수 설명
client_code string(50) 거래처 코드
name string(100) 거래처명
client_type enum 매입/매출/매입매출
is_active boolean 활성 상태 (기본: true)

10.2 사업자 정보 (3개)

필드 타입 필수 설명
business_no string(20) 사업자등록번호
business_type string(50) 업태
business_item string(100) 업종

10.3 연락처 정보 (6개)

필드 타입 필수 설명
contact_person string(50) 담당자명
phone string(30) 전화번호
mobile string(20) 휴대폰
fax string(20) 팩스
email string(80) 이메일
address string(255) 주소

10.4 담당자 정보 (3개)

필드 타입 필수 설명
manager_name string(50) 당사 담당자명
manager_tel string(20) 당사 담당자 연락처
system_manager string(50) 시스템 담당자

10.5 계정/발주 정보 (4개)

필드 타입 필수 설명
account_id string(50) 계정 ID
account_password string(255) 계정 비밀번호 (hidden)
purchase_payment_day string(20) 매입 결제일
sales_payment_day string(20) 매출 결제일

10.6 세금계산서 합의 (4개)

필드 타입 필수 설명
tax_agreement boolean 합의 여부
tax_amount decimal(15,2) 합의 금액
tax_start_date date 합의 시작일
tax_end_date date 합의 종료일

10.7 불량 채권 (5개)

필드 타입 필수 설명
bad_debt boolean 불량 채권 여부
bad_debt_amount decimal(15,2) 불량 채권 금액
bad_debt_receive_date date 채권 발생일
bad_debt_end_date date 채권 종료일
bad_debt_progress enum 진행 상태

10.8 기타 (2개)

필드 타입 필수 설명
client_group_id bigint 고객그룹 ID
memo text 메모

11. 관련 문서


최종 업데이트: 2025-12-08