Files
sam-docs/front/[API-2025-12-08] pricing-api-enhancement-request.md
hskwon 5d1190a0d3 docs: plans 폴더 추가 및 HR API 규칙 문서 정리
- plans/ 폴더 신규 생성 (개발 계획 임시 문서용)
- hr-api-react-sync-plan.md를 specs → plans로 이동
- INDEX.md 업데이트 (폴더 구조, 워크플로우)
- rules/ HR API 규칙 문서 추가 (employee, attendance, department-tree)
- pricing API 요청 문서 업데이트
2025-12-09 14:44:39 +09:00

9.9 KiB
Raw Blame History

단가관리 API 분석 및 구현 현황

작성일: 2025-12-08 최종 업데이트: 2025-12-08 상태: 백엔드 API 구현 완료


1. 구현 현황 요약

현재 API 구조 (구현 완료)

Method Endpoint 설명 상태
GET /api/v1/pricing 목록 조회 (페이지네이션, 필터) 완료
GET /api/v1/pricing/{id} 단건 조회 완료
POST /api/v1/pricing 등록 완료
PUT /api/v1/pricing/{id} 수정 완료
DELETE /api/v1/pricing/{id} 삭제 (soft delete) 완료
POST /api/v1/pricing/{id}/finalize 확정 완료
GET /api/v1/pricing/{id}/revisions 변경이력 조회 완료
POST /api/v1/pricing/by-items 품목별 단가 현황 (다건) 완료
GET /api/v1/pricing/cost 원가 조회 (수입검사 > 표준원가) 완료

완료된 사항

  • 새 테이블 구조: prices, price_revisions 테이블 생성
  • 기존 테이블 마이그레이션: price_historiesprices 데이터 이관
  • 모든 요청 필드: 원가 계산, 마진 관리, 리비전 관리 기능 구현

2. 테이블 스키마 (구현 완료)

2.1 prices 테이블 (신규 생성)

CREATE TABLE prices (
    id                  BIGINT PRIMARY KEY AUTO_INCREMENT,
    tenant_id           BIGINT NOT NULL,

    -- 품목 연결
    item_type_code      VARCHAR(20) NOT NULL,     -- 'PRODUCT' | 'MATERIAL'
    item_id             BIGINT NOT NULL,
    client_group_id     BIGINT NULL,              -- NULL=기본가

    -- 원가 정보
    purchase_price      DECIMAL(15,4) NULL,       -- 매입단가
    processing_cost     DECIMAL(15,4) NULL,       -- 가공비
    loss_rate           DECIMAL(5,2) NULL,        -- LOSS율 (%)

    -- 판매가 정보
    margin_rate         DECIMAL(5,2) NULL,        -- 마진율 (%)
    sales_price         DECIMAL(15,4) NULL,       -- 판매단가
    rounding_rule       ENUM('round','ceil','floor') DEFAULT 'round',
    rounding_unit       INT DEFAULT 1,            -- 1, 10, 100, 1000

    -- 메타 정보
    supplier            VARCHAR(255) NULL,
    effective_from      DATE NOT NULL,
    effective_to        DATE NULL,
    note                TEXT NULL,

    -- 상태 관리
    status              ENUM('draft','active','inactive','finalized') DEFAULT 'draft',
    is_final            BOOLEAN DEFAULT FALSE,
    finalized_at        DATETIME NULL,
    finalized_by        BIGINT NULL,

    -- 감사 컬럼
    created_by, updated_by, deleted_by, timestamps, soft_deletes
);

2.2 price_revisions 테이블 (변경 이력)

CREATE TABLE price_revisions (
    id                  BIGINT PRIMARY KEY,
    tenant_id           BIGINT NOT NULL,
    price_id            BIGINT NOT NULL,
    revision_number     INT NOT NULL,
    changed_at          DATETIME NOT NULL,
    changed_by          BIGINT NOT NULL,
    change_reason       VARCHAR(500) NULL,
    before_snapshot     JSON NULL,
    after_snapshot      JSON NOT NULL
);

2.3 기존 price_histories 테이블 처리

  • prices 테이블로 데이터 마이그레이션 완료
  • price_histories 테이블 삭제됨

3. API 엔드포인트 상세 (구현 완료)

3.1 단가 등록 POST /api/v1/pricing

Request Body:

{
  "item_type_code": "MATERIAL",
  "item_id": 123,
  "client_group_id": null,

  "purchase_price": 1000,
  "processing_cost": 100,
  "loss_rate": 5,
  "margin_rate": 20,
  "rounding_rule": "round",
  "rounding_unit": 10,

  "supplier": "ABC상사",
  "effective_from": "2025-01-01",
  "effective_to": null,
  "note": "2025년 1분기 단가",
  "status": "active"
}

자동 처리:

  • sales_price 자동 계산 (입력 안해도 됨)
  • 기존 무기한 단가의 effective_to 자동 설정
  • 최초 리비전 자동 생성

3.2 목록 조회 GET /api/v1/pricing

Query Parameters:

파라미터 타입 설명
page int 페이지 번호
size int 페이지당 개수 (max 100)
q string 검색어 (공급업체, 비고)
item_type_code string PRODUCT / MATERIAL
item_id int 품목 ID
client_group_id int/null 고객그룹 ID
status string draft, active, inactive, finalized
valid_at date 특정 일자에 유효한 단가

Response:

{
  "success": true,
  "message": "message.fetched",
  "data": {
    "current_page": 1,
    "data": [
      {
        "id": 1,
        "item_type_code": "MATERIAL",
        "item_id": 123,
        "client_group_id": null,
        "purchase_price": "1000.0000",
        "processing_cost": "100.0000",
        "loss_rate": "5.00",
        "margin_rate": "20.00",
        "sales_price": "1386.0000",
        "rounding_rule": "round",
        "rounding_unit": 10,
        "supplier": "ABC상사",
        "effective_from": "2025-01-01",
        "effective_to": null,
        "status": "active",
        "is_final": false,
        "client_group": null
      }
    ],
    "total": 1
  }
}

4. 추가 API 엔드포인트 (구현 완료)

4.1 품목별 단가 현황 POST /api/v1/pricing/by-items

용도: 여러 품목의 현재 유효한 단가를 한번에 조회

Request Body:

{
  "items": [
    { "item_type_code": "MATERIAL", "item_id": 123 },
    { "item_type_code": "MATERIAL", "item_id": 124 },
    { "item_type_code": "PRODUCT", "item_id": 10 }
  ],
  "client_group_id": 1,
  "date": "2025-12-08"
}

조회 우선순위:

  1. 고객그룹별 단가 (client_group_id 지정 시)
  2. 기본 단가 (client_group_id = NULL)

Response:

{
  "success": true,
  "data": [
    {
      "item_type_code": "MATERIAL",
      "item_id": 123,
      "price": { ... },
      "has_price": true
    },
    {
      "item_type_code": "MATERIAL",
      "item_id": 124,
      "price": null,
      "has_price": false
    }
  ]
}

4.2 변경 이력 조회 GET /api/v1/pricing/{id}/revisions

Response:

{
  "success": true,
  "data": {
    "data": [
      {
        "id": 2,
        "revision_number": 2,
        "changed_at": "2025-12-08T11:00:00.000000Z",
        "changed_by": 1,
        "change_reason": "마진율 조정",
        "before_snapshot": {
          "purchase_price": "1000.0000",
          "margin_rate": "15.00",
          "sales_price": "1265.0000"
        },
        "after_snapshot": {
          "purchase_price": "1000.0000",
          "margin_rate": "20.00",
          "sales_price": "1386.0000"
        },
        "changed_by_user": { "id": 1, "name": "홍길동" }
      }
    ]
  }
}

4.3 단가 확정 POST /api/v1/pricing/{id}/finalize

동작:

  • is_finaltrue
  • statusfinalized
  • 확정 후 수정/삭제 불가

Response:

{
  "success": true,
  "message": "message.pricing.finalized",
  "data": {
    "id": 5,
    "is_final": true,
    "finalized_at": "2025-12-08T14:30:00.000000Z",
    "finalized_by": 1,
    "status": "finalized"
  }
}

4.4 원가 조회 GET /api/v1/pricing/cost

용도: 수입검사 입고단가 > 표준원가 우선순위로 원가 조회

Query Parameters:

파라미터 타입 필수 설명
item_type_code string PRODUCT / MATERIAL
item_id int 품목 ID
date date 조회 기준일 (기본: 오늘)

Response:

{
  "success": true,
  "data": {
    "item_type_code": "MATERIAL",
    "item_id": 123,
    "date": "2025-12-08",
    "cost_source": "receipt",
    "purchase_price": 1050.00,
    "receipt_id": 45,
    "receipt_date": "2025-12-01",
    "price_id": null
  }
}
cost_source 설명
receipt 수입검사 입고단가
standard 표준원가 (prices 테이블)
not_found 단가 미등록

5. 비즈니스 로직

5.1 판매단가 자동 계산

총원가 = (매입단가 + 가공비) × (1 + LOSS율/100)
판매단가 = 반올림(총원가 × (1 + 마진율/100), 반올림단위, 반올림규칙)

5.2 상태 흐름

draft → active → finalized
         ↓
      inactive

5.3 주요 검증 규칙

  • 동일 품목+고객그룹+시작일 조합 중복 불가
  • 확정된 단가는 수정/삭제 불가
  • 마진율/LOSS율은 0~100% 범위
  • 반올림단위는 1, 10, 100, 1000 중 하나

6. 프론트엔드 작업 현황

작업 상태 비고
usePricingList 훅 생성 미완료
타입 정의 미완료
단가 목록 페이지 미완료
단가 등록/수정 페이지 미완료
단가 상세 페이지 (이력 포함) 미완료
품목별 단가 현황 컴포넌트 미완료

7. 백엔드 참고 파일

컨트롤러/서비스

  • api/app/Http/Controllers/Api/V1/PricingController.php
  • api/app/Services/PricingService.php

모델

  • api/app/Models/Products/Price.php
  • api/app/Models/Products/PriceRevision.php

요청 클래스

  • api/app/Http/Requests/Pricing/PriceIndexRequest.php
  • api/app/Http/Requests/Pricing/PriceStoreRequest.php
  • api/app/Http/Requests/Pricing/PriceUpdateRequest.php
  • api/app/Http/Requests/Pricing/PriceByItemsRequest.php
  • api/app/Http/Requests/Pricing/PriceCostRequest.php

마이그레이션

  • api/database/migrations/2025_12_08_154633_create_prices_table.php
  • api/database/migrations/2025_12_08_154634_create_price_revisions_table.php
  • api/database/migrations/2025_12_08_154635_migrate_price_histories_to_prices.php
  • api/database/migrations/2025_12_08_154636_drop_price_histories_table.php

라우트

  • api/routes/api.php (Line 368-379)

8. 관련 문서


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