화면과 서버를 이을 때 읽는 문서

기능 연결 방식

어떤 요청이 오가고 무엇이 돌아오는지, 무엇이 아직 안 정해졌는지 적었습니다.

29,985자 · 시스템이 만든 그대로입니다

사람이 손댄 곳 3군데
  • · 3단계 ‘화면 목록 다듬기’에서 화면 이름 몇 개를 손봤습니다. 하는 일이 겹쳐 보이는 이름을 갈라 적었을 뿐 문서 본문은 손대지 않았습니다.
  • · 사업계획서 검토에서 받은 지적 여덟 건 중 둘은 반영하지 않기로 하고 그 이유를 적어 남겼습니다. 반영하지 않은 것도 기록에 남아 심사에서 물으면 그대로 답이 됩니다.
  • · 아래 화면은 저장소에 연결되기 전 단계의 것입니다. 기능을 붙이는 작업은 이 사례를 정리하는 시점에 아직 진행 중이라, 동작하는 서비스 화면 대신 이 단계까지만 싣습니다. 없는 것을 있다고 하지 않기 위해 그대로 적어 둡니다.

로컬푸드 직매장 정산 자동화 API 문서

1. 공통 기준

  • 대상: 웹 서비스(Next.js 화면에서 사용)
  • 데이터 형식: application/json
  • 파일 업로드: multipart/form-data
  • 금액: 원 단위 정수(number)로 전달합니다.
  • 날짜: YYYY-MM-DD
  • 날짜·시간: 한국 시간 기준 ISO 형식으로 기록합니다. (NFR-002)
  • 인증: 로그인 후 받은 세션 또는 토큰을 요청에 포함합니다.
  • 권한: 서버가 로그인 사용자 역할을 확인합니다. 화면에서 버튼을 숨겨도 권한 없는 요청은 서버에서 차단합니다. (NFR-004, NFR-005)

공통 오류 응답 예시

{
  "error": {
    "code": "SETTLEMENT_NOT_CLOSABLE",
    "message": "필수 오류 또는 매출 대조 차이가 남아 있어 정산을 마감할 수 없습니다.",
    "details": {
      "errorCount": 2,
      "reconciliationDifference": 1500
    }
  }
}
상태 코드사용자가 이해할 수 있는 상황
400입력값, 파일 형식 또는 날짜가 올바르지 않습니다.
401로그인 정보가 없거나 로그인 시간이 만료되었습니다.
403이 작업을 할 권한이 없습니다.
404요청한 농가, 품목, 정산 주차 또는 정산서를 찾을 수 없습니다.
409이미 등록된 값, 중복 거래, 기간 충돌 또는 마감된 자료의 수정 시도입니다.
422정산 규칙 누락, 상품 미연결 등 계산에 필요한 정보가 부족합니다.

2. 로그인과 계정 권한

운영자 로그인 (FR-001)

항목내용
목적정산 담당자, 점장, 매장 운영자가 로그인하고 역할별 권한을 적용합니다.
인증필요 없음
방식·경로POST /api/auth/operator/login

요청값

{
  "loginId": "manager01",
  "password": "비밀번호"
}

성공 응답

{
  "user": {
    "id": "usr_001",
    "name": "김정산",
    "role": "SETTLEMENT_MANAGER",
    "closingPermission": false
  },
  "sessionExpiresAt": "2026-08-27T18:00:00+09:00"
}

오류 상황

  • 아이디 또는 비밀번호가 맞지 않으면 “로그인 정보가 맞지 않습니다.”라고 안내합니다.
  • 중지된 계정은 로그인할 수 없습니다.
  • 계정 존재 여부는 별도로 알려 주지 않습니다.

운영자 로그아웃 (FR-001)

항목내용
목적운영자 로그인 세션을 종료합니다.
인증운영자
방식·경로POST /api/auth/operator/logout

성공 응답

{
  "message": "로그아웃되었습니다."
}

담당자 계정 목록 조회 (FR-002)

항목내용
목적매장 운영자가 정산 담당자와 마감 권한자의 계정 상태를 확인합니다.
인증매장 운영자
방식·경로GET /api/operator-accounts

성공 응답

{
  "accounts": [
    {
      "id": "usr_001",
      "name": "김정산",
      "loginId": "manager01",
      "role": "SETTLEMENT_MANAGER",
      "closingPermission": false,
      "status": "ACTIVE",
      "updatedAt": "2026-08-27T09:00:00+09:00"
    }
  ]
}

담당자 계정 등록 (FR-002)

항목내용
목적정산 담당자 또는 마감 권한을 가진 담당자 계정을 등록합니다.
인증매장 운영자
방식·경로POST /api/operator-accounts

요청값

{
  "name": "이점장",
  "loginId": "store-chief",
  "initialPassword": "초기비밀번호",
  "role": "STORE_MANAGER",
  "closingPermission": true
}

성공 응답

{
  "account": {
    "id": "usr_002",
    "name": "이점장",
    "role": "STORE_MANAGER",
    "closingPermission": true,
    "status": "ACTIVE"
  }
}

오류 상황

  • 일반 정산 담당자는 다른 사람의 계정이나 마감 권한을 변경할 수 없습니다.
  • 이미 사용하는 로그인 아이디는 등록할 수 없습니다.

담당자 계정 권한·상태 변경 (FR-002)

항목내용
목적담당자 계정의 역할, 마감 권한, 사용 상태를 변경하거나 중지합니다. 변경 이력도 남깁니다.
인증매장 운영자
방식·경로PATCH /api/operator-accounts/{accountId}

요청값

{
  "role": "STORE_MANAGER",
  "closingPermission": true,
  "status": "ACTIVE",
  "changeReason": "점장 변경"
}

성공 응답

{
  "account": {
    "id": "usr_002",
    "role": "STORE_MANAGER",
    "closingPermission": true,
    "status": "ACTIVE"
  },
  "updatedBy": "usr_010",
  "updatedAt": "2026-08-27T10:00:00+09:00"
}

오류 상황

  • 마지막 마감 권한자를 중지하려 하면 대체 마감 권한자를 먼저 지정하도록 안내합니다.
  • 사용 이력이 있는 계정은 삭제하지 않고 중지 상태로만 바꿉니다.

농가 로그인 (FR-003, FR-020)

항목내용
목적농가가 본인 계정으로 로그인해 본인의 정산서만 조회하도록 합니다.
인증필요 없음
방식·경로POST /api/auth/farmer/login

요청값

{
  "loginId": "farmer01",
  "password": "비밀번호"
}

성공 응답

{
  "farmer": {
    "id": "farmer_001",
    "name": "햇살농장"
  },
  "sessionExpiresAt": "2026-08-27T18:00:00+09:00"
}

오류 상황

  • 중지된 농가 계정은 로그인할 수 없습니다.
  • 농가는 다른 농가의 정산서 주소를 직접 입력해도 조회할 수 없습니다.

농가 로그인 계정 연결·상태 변경 (FR-003)

항목내용
목적등록된 농가에 로그인 계정을 연결하고 사용 여부를 관리합니다.
인증정산 담당자
방식·경로PUT /api/farmers/{farmerId}/login-account

요청값

{
  "loginId": "farmer01",
  "initialPassword": "초기비밀번호",
  "status": "ACTIVE"
}

성공 응답

{
  "farmerId": "farmer_001",
  "loginAccount": {
    "id": "farmer-account_001",
    "loginId": "farmer01",
    "status": "ACTIVE"
  }
}

오류 상황

  • 이미 다른 농가에 연결된 계정은 연결할 수 없습니다.
  • 첫 로그인 비밀번호 변경과 비밀번호 복구 방식은 확인 필요입니다.

3. 정산 주차와 기본 정보 관리

정산 주차 목록·상세 조회 (FR-004, FR-015)

항목내용
목적운영자가 현재 정산 주차, 입금 예정일, 정산 진행 상태를 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks

조회값

이름설명
status선택값. 예: PROCESSING, CLOSING_COMPLETED
from, to정산 대상 기간 조회용 날짜

성공 응답

{
  "settlementWeeks": [
    {
      "id": "sw_2026084",
      "salesPeriodStart": "2026-08-17",
      "salesPeriodEnd": "2026-08-23",
      "closingDate": "2026-08-27",
      "expectedDepositDate": "2026-08-31",
      "status": "ERROR_EXISTS",
      "errorCount": 3,
      "reconciliationDifference": 0,
      "statementGenerated": false,
      "closable": false
    }
  ]
}

정산 주차 생성 (FR-004)

항목내용
목적판매 기간, 목요일 마감일, 입금 예정일이 포함된 정산 주차를 만듭니다.
인증정산 담당자
방식·경로POST /api/settlement-weeks

요청값

{
  "salesPeriodStart": "2026-08-17",
  "salesPeriodEnd": "2026-08-23",
  "closingDate": "2026-08-27",
  "expectedDepositDate": "2026-08-31"
}

성공 응답

{
  "settlementWeek": {
    "id": "sw_2026084",
    "status": "PREPARING",
    "salesPeriodStart": "2026-08-17",
    "salesPeriodEnd": "2026-08-23",
    "closingDate": "2026-08-27",
    "expectedDepositDate": "2026-08-31"
  }
}

오류 상황

  • 다른 정산 주차와 판매 기간이 겹치면 생성할 수 없습니다.
  • 종료일이 시작일보다 빠르면 저장할 수 없습니다.

농가·품목·품목군 목록 조회 (FR-005)

항목내용
목적농가, 품목군, 품목, 상품코드 정보를 조회해 판매 항목 연결과 규칙 등록에 사용합니다.
인증운영자
방식·경로GET /api/master-data

성공 응답

{
  "farmers": [
    {
      "id": "farmer_001",
      "name": "햇살농장",
      "status": "ACTIVE"
    }
  ],
  "productGroups": [
    {
      "id": "pg_vegetable",
      "name": "채소"
    }
  ],
  "products": [
    {
      "id": "product_001",
      "name": "무농약 상추 200g",
      "farmerId": "farmer_001",
      "productGroupId": "pg_vegetable",
      "productCode": "880001",
      "status": "ACTIVE"
    }
  ]
}

농가 등록·변경·중지 (FR-005)

항목내용
목적농가 기본 정보와 사용 상태를 관리합니다.
인증정산 담당자
방식·경로POST /api/farmers, PATCH /api/farmers/{farmerId}

등록 요청값

{
  "name": "햇살농장",
  "representativeName": "김농부",
  "phoneNumber": "010-0000-0000",
  "status": "ACTIVE"
}

성공 응답

{
  "farmer": {
    "id": "farmer_001",
    "name": "햇살농장",
    "status": "ACTIVE"
  }
}

오류 상황

  • 정산 이력이 있는 농가는 삭제할 수 없고 사용 중지로 처리합니다.

품목군 등록·변경 (FR-005)

항목내용
목적여러 품목에 공통 정산 규칙을 적용할 수 있도록 품목군을 관리합니다.
인증정산 담당자
방식·경로POST /api/product-groups, PATCH /api/product-groups/{productGroupId}

요청값

{
  "name": "채소",
  "status": "ACTIVE"
}

성공 응답

{
  "productGroup": {
    "id": "pg_vegetable",
    "name": "채소",
    "status": "ACTIVE"
  }
}

품목과 상품코드 등록·변경·중지 (FR-005)

항목내용
목적농가, 품목군, 품목명, 규격, 상품코드를 연결합니다.
인증정산 담당자
방식·경로POST /api/products, PATCH /api/products/{productId}

요청값

{
  "name": "무농약 상추",
  "specification": "200g",
  "farmerId": "farmer_001",
  "productGroupId": "pg_vegetable",
  "productCode": "880001",
  "status": "ACTIVE"
}

성공 응답

{
  "product": {
    "id": "product_001",
    "name": "무농약 상추",
    "farmerId": "farmer_001",
    "productGroupId": "pg_vegetable",
    "productCode": "880001",
    "status": "ACTIVE"
  }
}

오류 상황

  • 하나의 상품코드를 둘 이상의 사용 중인 품목에 연결할 수 없습니다.
  • 정산 이력이 있는 품목은 삭제할 수 없고 사용 중지로 처리합니다.

4. 정산 규칙 관리

정산 규칙 목록·상세 조회 (FR-006)

항목내용
목적수수료율, 할인 수수료, 반품·폐기 부담 기준과 적용 기간을 확인합니다.
인증운영자
방식·경로GET /api/settlement-rules

조회값

이름설명
farmerId특정 농가 규칙만 조회
productId특정 품목 규칙만 조회
productGroupId특정 품목군 규칙만 조회
effectiveDate특정 판매일에 적용되는 규칙 조회

성공 응답

{
  "rules": [
    {
      "id": "rule_001",
      "name": "햇살농장 채소 기본 약정",
      "farmerId": "farmer_001",
      "productGroupId": "pg_vegetable",
      "commissionRate": 10,
      "discountCommissionBasis": "DISCOUNTED_PRICE",
      "returnBurdenParty": "FARMER",
      "disposalBurdenParty": "FARMER",
      "effectiveStartDate": "2026-01-01",
      "effectiveEndDate": null,
      "status": "ACTIVE"
    }
  ]
}

정산 규칙 등록 (FR-006)

항목내용
목적농가별·품목별 약정에 따라 수수료율, 할인 수수료, 반품·폐기 부담 기준을 등록합니다.
인증정산 담당자
방식·경로POST /api/settlement-rules

요청값

{
  "name": "햇살농장 채소 기본 약정",
  "farmerId": "farmer_001",
  "productId": null,
  "productGroupId": "pg_vegetable",
  "commissionRate": 10,
  "discountCommissionBasis": "DISCOUNTED_PRICE",
  "returnBurdenParty": "FARMER",
  "returnCalculationBasis": "RETURN_AMOUNT",
  "disposalBurdenParty": "STORE",
  "disposalCalculationBasis": "RECORDED_AMOUNT",
  "effectiveStartDate": "2026-09-01",
  "effectiveEndDate": null,
  "agreementConfirmed": true
}

성공 응답

{
  "rule": {
    "id": "rule_001",
    "status": "ACTIVE",
    "effectiveStartDate": "2026-09-01"
  }
}

오류 상황

  • 수수료율, 적용 시작일 또는 확정 여부가 없으면 저장할 수 없습니다.
  • 같은 적용 대상과 기간에 규칙이 겹치면 저장할 수 없습니다.
  • 확정되지 않은 약정은 적용 중 규칙으로 저장할 수 없습니다.

정산 규칙 변경 이력 등록 (FR-006)

항목내용
목적기존 규칙을 덮어쓰지 않고 종료일을 설정한 뒤 새 규칙을 등록합니다.
인증정산 담당자
방식·경로POST /api/settlement-rules/{ruleId}/revisions

요청값

{
  "previousRuleEndDate": "2026-08-31",
  "newRule": {
    "name": "햇살농장 채소 변경 약정",
    "farmerId": "farmer_001",
    "productGroupId": "pg_vegetable",
    "commissionRate": 12,
    "discountCommissionBasis": "ORIGINAL_PRICE",
    "returnBurdenParty": "FARMER",
    "disposalBurdenParty": "STORE",
    "effectiveStartDate": "2026-09-01",
    "agreementConfirmed": true
  },
  "changeReason": "농가와 재약정"
}

성공 응답

{
  "previousRule": {
    "id": "rule_001",
    "effectiveEndDate": "2026-08-31"
  },
  "newRule": {
    "id": "rule_002",
    "effectiveStartDate": "2026-09-01"
  }
}

오류 상황

  • 마감 완료된 정산에 적용된 규칙 자체는 수정하거나 삭제할 수 없습니다.
  • 새 규칙은 시작일 이후의 미마감 거래에만 적용합니다.

5. 계산대 판매 파일과 판매 원장

계산대 판매 파일 업로드 (FR-007)

항목내용
목적정산 주차에 해당하는 계산대 판매 파일을 올리고 파일 형식과 행별 데이터를 검사합니다.
인증정산 담당자
방식·경로POST /api/settlement-weeks/{settlementWeekId}/cashier-sales-files
요청 형식multipart/form-data

요청값

이름형식설명
file파일계산대 판매 파일
fileName문자열화면 표시용 파일명

성공 응답

{
  "file": {
    "id": "file_001",
    "fileName": "sales-2026-08-23.csv",
    "uploadedAt": "2026-08-24T09:30:00+09:00",
    "uploadedBy": "usr_001"
  },
  "result": {
    "totalRows": 1250,
    "validRows": 1245,
    "errorRows": 5,
    "status": "PARTIALLY_VALID"
  }
}

오류 상황

  • 지원하지 않는 파일 형식 또는 필수 열이 없으면 파일을 반영하지 않습니다.
  • 판매일이 정산 주차 밖이면 해당 행을 오류로 표시합니다.
  • 동일 파일이 이미 반영되어 있으면 중복 업로드를 막습니다.
  • 일부 오류 행이 있을 때 정상 행만 반영할지 전체를 다시 올릴지는 실제 계산대 판매 파일 형식 확인이 필요합니다.

파일 오류 행과 업로드 이력 조회 (FR-007, FR-024)

항목내용
목적업로드한 계산대 판매 파일의 오류 행, 업로드 담당자, 처리 시점을 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/cashier-sales-files

성공 응답

{
  "files": [
    {
      "id": "file_001",
      "fileName": "sales-2026-08-23.csv",
      "uploadedBy": {
        "id": "usr_001",
        "name": "김정산"
      },
      "uploadedAt": "2026-08-24T09:30:00+09:00",
      "validRows": 1245,
      "errorRows": 5
    }
  ]
}

상품코드 미연결 항목 조회 (FR-008)

항목내용
목적자동 연결되지 않은 상품코드 또는 상품코드가 비어 있는 판매 항목을 확인합니다.
인증정산 담당자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/unlinked-sales-items

성공 응답

{
  "items": [
    {
      "ledgerEntryId": "ledger_001",
      "productCode": "999001",
      "sourceProductName": "친환경 깻잎",
      "saleDate": "2026-08-22",
      "actualSaleAmount": 3000,
      "connectionStatus": "UNLINKED",
      "sourceFileId": "file_001",
      "sourceRowNumber": 48
    }
  ]
}

판매 항목 직접 연결과 상품코드 재사용 등록 (FR-008)

항목내용
목적처음 보는 상품코드 또는 빈 상품코드 판매 항목을 농가와 품목에 연결합니다. 상품코드가 있으면 이후 동일 코드에 재사용합니다.
인증정산 담당자
방식·경로POST /api/sales-ledger/{ledgerEntryId}/product-connection

요청값

{
  "farmerId": "farmer_001",
  "productId": "product_001",
  "reuseForSameProductCode": true
}

성공 응답

{
  "ledgerEntry": {
    "id": "ledger_001",
    "connectionMethod": "MANUAL",
    "farmerId": "farmer_001",
    "productId": "product_001",
    "connectionStatus": "CONNECTED"
  },
  "productCodeMappingSaved": true
}

오류 상황

  • 같은 상품코드가 여러 품목과 충돌하면 자동 연결하지 않고 직접 선택하도록 합니다.
  • 기존 직접 연결을 바꾸더라도 이전 연결 이력은 삭제하지 않습니다.

판매 원장 조회 (FR-009, FR-010)

항목내용
목적판매·할인·반품 거래, 원본 파일 행, 상품 연결 결과, 적용 정산 규칙을 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/sales-ledger

조회값

이름설명
farmerId농가별 조회
productId품목별 조회
transactionTypeSALE, DISCOUNT_SALE, RETURN
statusSETTLABLE, ERROR, DUPLICATE_SUSPECTED

성공 응답

{
  "entries": [
    {
      "id": "ledger_001",
      "transactionId": "pos-20260822-0001",
      "transactionType": "DISCOUNT_SALE",
      "saleDate": "2026-08-22",
      "farmer": {
        "id": "farmer_001",
        "name": "햇살농장"
      },
      "product": {
        "id": "product_001",
        "name": "무농약 상추 200g"
      },
      "originalSaleAmount": 4000,
      "actualSaleAmount": 3000,
      "discountAmount": 1000,
      "appliedRuleId": "rule_001",
      "status": "SETTLABLE",
      "source": {
        "fileId": "file_001",
        "rowNumber": 48
      }
    }
  ]
}

중복 가능 거래 확인 처리 (FR-009)

항목내용
목적시스템이 자동 판별하지 못한 중복 가능 거래를 원본 자료와 비교해 정산 포함 또는 제외로 처리합니다.
인증정산 담당자
방식·경로POST /api/sales-ledger/{ledgerEntryId}/duplicate-review

요청값

{
  "decision": "INCLUDE",
  "reason": "서로 다른 영수증 번호의 정상 판매입니다."
}

성공 응답

{
  "ledgerEntryId": "ledger_001",
  "duplicateReviewStatus": "CONFIRMED_NOT_DUPLICATE",
  "settlementEligibility": "SETTLABLE"
}

오류 상황

  • 거래 고유값이 없는 계산대 판매 파일의 자동 중복 판단 기준은 확인 필요입니다.
  • 확인되지 않은 중복 가능 거래는 정산 계산에서 제외되며 마감을 막습니다.

판매·할인·반품 내역 상세 조회 (FR-010)

항목내용
목적한 거래의 정상 판매금액, 실제 판매금액, 할인금액, 반품 연결 여부와 적용 정산 규칙을 확인합니다.
인증운영자
방식·경로GET /api/sales-ledger/{ledgerEntryId}

성공 응답

{
  "ledgerEntry": {
    "id": "ledger_001",
    "transactionType": "DISCOUNT_SALE",
    "originalSaleAmount": 4000,
    "actualSaleAmount": 3000,
    "discountAmount": 1000,
    "appliedRule": {
      "id": "rule_001",
      "commissionRate": 10,
      "discountCommissionBasis": "DISCOUNTED_PRICE"
    },
    "sourceFile": {
      "id": "file_001",
      "rowNumber": 48
    }
  }
}

오류 상황

  • 할인 전 또는 할인 후 금액이 필요한데 원본 파일에 없으면 확인 필요 오류로 표시합니다.
  • 반품이 원래 판매와 연결되지 않으면 미확인 오류로 표시합니다.
  • 마감된 거래는 조회만 할 수 있습니다.

6. 폐기와 미회수 재고

폐기·미회수 재고 등록 (FR-011)

항목내용
목적유통기한 경과, 미회수 재고 등의 폐기 내역과 정산 부담 금액을 등록합니다.
인증정산 담당자
방식·경로POST /api/settlement-weeks/{settlementWeekId}/disposals

요청값

{
  "farmerId": "farmer_001",
  "productId": "product_001",
  "quantity": 3,
  "disposalReason": "EXPIRED",
  "burdenParty": "FARMER",
  "settlementAmount": 6000,
  "evidenceIds": ["evidence_001"],
  "notifiedFarmerDate": "2026-08-23",
  "notifiedFarmerMethod": "전화"
}

성공 응답

{
  "disposal": {
    "id": "disposal_001",
    "status": "SETTLABLE",
    "burdenParty": "FARMER",
    "settlementAmount": 6000,
    "recordedBy": "usr_001",
    "recordedAt": "2026-08-23T19:00:00+09:00"
  }
}

오류 상황

  • 농가, 품목, 수량, 폐기 사유, 부담 주체가 없으면 확정할 수 없습니다.
  • 적용할 폐기 규칙이 없으면 임의로 계산하지 않고 오류로 남깁니다.
  • 농가 부담인데 농가 안내 기록이 없으면 경고합니다. 마감 필수 조건 여부는 확인 필요입니다.

폐기·미회수 재고 목록·상세 조회 (FR-011, FR-010)

항목내용
목적정산 주차의 폐기와 미회수 재고 내역, 증빙, 부담 주체, 농가 안내 기록을 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/disposals

증빙 사진 업로드 (FR-011, FR-022)

항목내용
목적폐기 내역 또는 농가 이의 제기에 필요한 사진 증빙을 업로드합니다.
인증정산 담당자 또는 농가
방식·경로POST /api/evidence
요청 형식multipart/form-data

요청값

이름설명
file이미지 파일
purposeDISPOSAL 또는 OBJECTION

성공 응답

{
  "evidence": {
    "id": "evidence_001",
    "fileName": "disposal-photo.jpg",
    "contentType": "image/jpeg",
    "uploadedAt": "2026-08-23T19:00:00+09:00"
  }
}

오류 상황

  • 이미지가 아닌 파일 또는 허용 크기를 초과한 파일은 업로드할 수 없습니다.
  • 농가는 본인 이의 제기에만 증빙을 연결할 수 있습니다.

7. 계산, 오류 검사, 매출 대조

정산 금액 계산과 재계산 (FR-012)

항목내용
목적판매일에 유효한 정산 규칙을 적용해 농가별 순 판매액, 수수료, 공제액, 지급액을 계산합니다.
인증정산 담당자
방식·경로POST /api/settlement-weeks/{settlementWeekId}/calculate

성공 응답

{
  "settlementWeekId": "sw_2026084",
  "calculationStatus": "COMPLETED",
  "summary": {
    "farmerCount": 30,
    "netSalesAmount": 2500000,
    "commissionAmount": 285000,
    "farmerBurdenAmount": 18000,
    "storeCompensationAmount": 5000,
    "correctionAmount": 0,
    "totalPayoutAmount": 2202000
  },
  "errorCount": 0
}

오류 상황

  • 적용 가능한 정산 규칙이 없거나 규칙이 충돌하면 계산 완료로 처리하지 않습니다.
  • 할인 수수료 계산에 필요한 금액이 없으면 오류로 처리합니다.
  • 지급액이 음수가 되는 경우의 마감 허용 기준은 확인 필요입니다.

정산 오류 목록과 처리 상태 조회 (FR-013)

항목내용
목적미연결 상품, 규칙 누락·충돌, 중복 가능 거래, 확인되지 않은 할인·반품·폐기 내역을 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/errors

성공 응답

{
  "errors": [
    {
      "id": "error_001",
      "type": "SETTLEMENT_RULE_MISSING",
      "severity": "BLOCKING",
      "message": "판매일에 적용할 정산 규칙이 없습니다.",
      "targetType": "SALES_LEDGER",
      "targetId": "ledger_001",
      "resolutionAction": "정산 규칙을 등록하거나 판매 항목을 확인하세요."
    }
  ],
  "blockingErrorCount": 1
}

매출 대조 결과 조회 (FR-014)

항목내용
목적계산대 판매 파일 순 판매액과 농가 지급액, 수수료, 부담 금액, 수기 조정을 비교합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/reconciliation

성공 응답

{
  "cashierNetSalesAmount": 2500000,
  "manualAdjustmentAmount": 0,
  "adjustedNetSalesAmount": 2500000,
  "farmerPayoutTotalExcludingCorrections": 2202000,
  "commissionTotal": 285000,
  "farmerBurdenTotal": 18000,
  "storeCompensationTotal": 5000,
  "correctionAmountExcluded": 0,
  "currentSettlementAmount": 2500000,
  "difference": 0,
  "reconciled": true
}

오류 상황

  • 차이가 0원이 아니면 정산서를 생성하거나 마감할 수 없습니다.
  • 근거 없는 수동 차액 입력으로 대조 차이를 0원으로 만들 수 없습니다.
  • 수기 조정은 대상 거래와 사유가 연결된 경우에만 반영합니다.

수기 조정 등록 (FR-014, FR-024)

항목내용
목적계산대 판매 파일에 반영되지 않은 조정이 실제로 필요한 경우 대상 거래와 사유를 연결해 기록합니다.
인증정산 담당자
방식·경로POST /api/settlement-weeks/{settlementWeekId}/manual-adjustments

요청값

{
  "amount": -3000,
  "reason": "계산대 취소 내역 누락 확인",
  "relatedLedgerEntryIds": ["ledger_009"]
}

성공 응답

{
  "manualAdjustment": {
    "id": "adjustment_001",
    "amount": -3000,
    "reason": "계산대 취소 내역 누락 확인",
    "recordedBy": "usr_001"
  }
}

8. 정산서 생성과 마감

농가별 정산서 생성 (FR-016)

항목내용
목적필수 오류가 없고 매출 대조 차이가 0원인 정산 주차에서 농가별 정산서를 생성합니다.
인증정산 담당자
방식·경로POST /api/settlement-weeks/{settlementWeekId}/settlement-statements

성공 응답

{
  "settlementWeekId": "sw_2026084",
  "generatedStatementCount": 30,
  "status": "STATEMENTS_GENERATED",
  "statements": [
    {
      "id": "statement_001",
      "farmerId": "farmer_001",
      "payoutAmount": 72500,
      "expectedDepositDate": "2026-08-31"
    }
  ]
}

오류 상황

  • 필수 오류가 남아 있거나 매출 대조 차이가 0원이 아니면 정산서를 생성할 수 없습니다.
  • 생성 후 마감 전에는 오류 처리와 재계산 뒤 정산서를 다시 생성할 수 있습니다.

운영자용 정산서 목록·상세 조회 (FR-016, FR-019)

항목내용
목적농가별 정산서의 판매액, 할인, 반품, 폐기, 수수료, 지급액 및 정정 연결 정보를 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/settlement-statements<br>GET /api/settlement-statements/{statementId}

성공 응답

{
  "statement": {
    "id": "statement_001",
    "farmer": {
      "id": "farmer_001",
      "name": "햇살농장"
    },
    "netSalesAmount": 85000,
    "discountAmount": 5000,
    "returnAmount": 0,
    "disposalAmount": 6000,
    "commissionAmount": 6500,
    "correctionAmount": 0,
    "payoutAmount": 72500,
    "expectedDepositDate": "2026-08-31",
    "status": "GENERATED"
  }
}

운영자용 정산서 내려받기 (FR-016)

항목내용
목적운영자가 농가별 정산서를 인쇄 또는 전달할 수 있는 파일로 내려받습니다.
인증운영자
방식·경로GET /api/settlement-statements/{statementId}/download

성공 응답

  • 정산서 파일을 내려받습니다.
  • 파일에는 농가명, 정산 주차, 판매·할인·반품·폐기 내역, 수수료, 지급액, 입금 예정일을 포함합니다.

정산 마감 (FR-017)

항목내용
목적목요일에 정산 주차를 확정하고 판매·수수료·정산 금액을 서버에서 수정 불가 상태로 잠급니다.
인증마감 권한자
방식·경로POST /api/settlement-weeks/{settlementWeekId}/close

요청값

{
  "closingConfirmation": true
}

성공 응답

{
  "settlementWeek": {
    "id": "sw_2026084",
    "status": "CLOSING_COMPLETED",
    "closedAt": "2026-08-27T16:30:00+09:00",
    "closedBy": {
      "id": "usr_002",
      "name": "이점장"
    }
  }
}

오류 상황

  • 마감 권한이 없는 정산 담당자는 마감할 수 없습니다.
  • 필수 오류가 남아 있거나 매출 대조 차이가 0원이 아니면 마감할 수 없습니다.
  • 정산서가 생성되지 않은 정산 주차는 마감할 수 없습니다.
  • 마감 후 판매 원장, 정산 규칙 적용 결과, 지급액을 직접 수정하려 하면 차단합니다. (NFR-003)

마감·정정 연결 이력 조회 (FR-019, FR-024)

항목내용
목적누가 언제 정산을 마감했는지와 마감 후 정정 항목이 어느 원 정산서 및 다음 정산 주차에 연결되었는지 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/history

성공 응답

{
  "closing": {
    "closedAt": "2026-08-27T16:30:00+09:00",
    "closedBy": "이점장"
  },
  "correctionItems": [
    {
      "id": "correction_001",
      "originalStatementId": "statement_001",
      "targetSettlementWeekId": "sw_2026091",
      "amount": 3000,
      "status": "SCHEDULED"
    }
  ]
}

9. 마감 후 정정

정정 항목 작성 (FR-018)

항목내용
목적마감 후 발견된 오류를 원 정산서를 바꾸지 않고 다음 정산 주차에 증감액으로 반영합니다.
인증정산 담당자
방식·경로POST /api/correction-items

요청값

{
  "originalSettlementStatementId": "statement_001",
  "targetSettlementWeekId": "sw_2026091",
  "farmerId": "farmer_001",
  "amount": 3000,
  "reason": "마감 후 확인된 할인 수수료 차액",
  "relatedLedgerEntryIds": ["ledger_001"]
}

성공 응답

{
  "correctionItem": {
    "id": "correction_001",
    "originalSettlementStatementId": "statement_001",
    "targetSettlementWeekId": "sw_2026091",
    "amount": 3000,
    "status": "SCHEDULED"
  }
}

오류 상황

  • 마감되지 않은 정산서에는 정정 항목을 작성할 수 없습니다.
  • 원 정산서의 농가와 다른 농가에 정정 항목을 반영할 수 없습니다.
  • 다음 정산 주차가 이미 마감되었으면 다른 미마감 정산 주차를 선택해야 합니다.

다음 정산 반영 예정 정정 항목 조회 (FR-018, FR-019)

항목내용
목적다음 정산에 포함될 정정 항목과 원 정산서 연결 관계를 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/correction-items

성공 응답

{
  "correctionItems": [
    {
      "id": "correction_001",
      "farmerId": "farmer_001",
      "amount": 3000,
      "reason": "마감 후 확인된 할인 수수료 차액",
      "originalSettlementWeekId": "sw_2026084",
      "originalStatementId": "statement_001",
      "status": "SCHEDULED"
    }
  ]
}

10. 농가 정산 조회와 이의 제기

농가의 이번 주 정산 요약 조회 (FR-020)

항목내용
목적농가가 스마트폰 첫 화면에서 이번 주 판매금액, 수수료, 받을 금액, 입금 예정일을 큰 글씨로 확인합니다.
인증농가
방식·경로GET /api/farmer/me/current-settlement

성공 응답

{
  "settlementWeek": {
    "id": "sw_2026084",
    "salesPeriod": "2026-08-17 ~ 2026-08-23"
  },
  "summary": {
    "netSalesAmount": 85000,
    "commissionAmount": 6500,
    "payoutAmount": 72500,
    "expectedDepositDate": "2026-08-31"
  },
  "statementId": "statement_001",
  "statementStatus": "CLOSING_COMPLETED"
}

오류 상황

  • 해당 농가의 정산서가 아직 생성되지 않았으면 “이번 주 정산서를 준비 중입니다.”라고 표시합니다.
  • 농가는 본인 정산서만 조회할 수 있습니다.

농가 정산서 목록·상세 조회 (FR-021)

항목내용
목적농가가 자신의 정산서와 판매·할인·반품·폐기·수수료·정정 항목 상세를 조회합니다.
인증농가
방식·경로GET /api/farmer/me/settlement-statements<br>GET /api/farmer/me/settlement-statements/{statementId}

성공 응답

{
  "statement": {
    "id": "statement_001",
    "salesPeriod": "2026-08-17 ~ 2026-08-23",
    "netSalesAmount": 85000,
    "commissionAmount": 6500,
    "returnAmount": 0,
    "disposalAmount": 6000,
    "correctionAmount": 0,
    "payoutAmount": 72500,
    "expectedDepositDate": "2026-08-31",
    "salesDetails": [
      {
        "productName": "무농약 상추 200g",
        "transactionType": "DISCOUNT_SALE",
        "originalSaleAmount": 4000,
        "actualSaleAmount": 3000,
        "commissionAmount": 300
      }
    ]
  }
}

농가 정산서 내려받기 (FR-021)

항목내용
목적농가가 자신의 정산서를 스마트폰에서 파일로 내려받습니다.
인증농가
방식·경로GET /api/farmer/me/settlement-statements/{statementId}/download

오류 상황

  • 다른 농가의 정산서 식별값으로 요청하면 조회할 수 없습니다.

농가 이의 제기 등록 (FR-022)

항목내용
목적농가가 자신의 정산서 또는 상세 거래에 대해 이의 내용과 증빙 사진을 제출합니다.
인증농가
방식·경로POST /api/farmer/me/objections

요청값

{
  "settlementStatementId": "statement_001",
  "ledgerEntryId": "ledger_001",
  "content": "8월 22일 상추 할인 판매 금액을 확인하고 싶습니다.",
  "evidenceIds": ["evidence_002"]
}

성공 응답

{
  "objection": {
    "id": "objection_001",
    "status": "SUBMITTED",
    "submittedAt": "2026-08-28T09:20:00+09:00"
  }
}

오류 상황

  • 본인 정산서가 아닌 경우 이의 제기를 할 수 없습니다.
  • 이의 내용이 없으면 제출할 수 없습니다.
  • 마감 전 정산서에 대한 이의 제기 허용 기준은 화면 정책으로 확인 필요입니다.

운영자용 이의 제기 목록·상세 조회 (FR-023)

항목내용
목적운영자가 제출된 이의 제기, 증빙 사진, 연결된 정산서와 거래 내역을 확인합니다.
인증정산 담당자, 점장, 매장 운영자
방식·경로GET /api/objections<br>GET /api/objections/{objectionId}

성공 응답

{
  "objections": [
    {
      "id": "objection_001",
      "farmerName": "햇살농장",
      "statementId": "statement_001",
      "status": "SUBMITTED",
      "submittedAt": "2026-08-28T09:20:00+09:00"
    }
  ]
}

농가 이의 제기 처리 결과 등록 (FR-023)

항목내용
목적운영자가 이의 처리 결과, 담당자, 처리일, 농가에 알린 날짜와 방법을 기록합니다. 필요하면 정정 항목 작성을 연결합니다.
인증정산 담당자
방식·경로PATCH /api/objections/{objectionId}

요청값

{
  "status": "RESOLVED",
  "result": "할인 수수료 계산 기준을 확인했고 정정 금액 3,000원을 다음 정산에 반영합니다.",
  "processedAt": "2026-08-28",
  "notifiedFarmerDate": "2026-08-28",
  "notifiedFarmerMethod": "전화",
  "correctionItemId": "correction_001"
}

성공 응답

{
  "objection": {
    "id": "objection_001",
    "status": "RESOLVED",
    "processedBy": "usr_001",
    "processedAt": "2026-08-28",
    "notifiedFarmerDate": "2026-08-28",
    "notifiedFarmerMethod": "전화",
    "correctionItemId": "correction_001"
  }
}

오류 상황

  • 처리 결과, 담당자, 처리일이 없으면 처리 완료로 변경할 수 없습니다.
  • 마감 완료된 정산서의 금액을 직접 바꾸지 않습니다. 금액 변경이 필요하면 정정 항목을 연결합니다.

11. 주간 현황과 작업 이력

주간 정산 현황 조회 (FR-015)

항목내용
목적운영자가 한 화면에서 파일 업로드, 상품 연결, 오류, 매출 대조, 정산서 생성, 마감 가능 여부를 확인합니다.
인증운영자
방식·경로GET /api/settlement-weeks/{settlementWeekId}/dashboard

성공 응답

{
  "settlementWeek": {
    "id": "sw_2026084",
    "status": "ERROR_EXISTS",
    "expectedDepositDate": "2026-08-31"
  },
  "progress": {
    "uploadedFileCount": 1,
    "totalSalesRows": 1250,
    "connectedSalesRows": 1240,
    "unlinkedSalesRows": 5,
    "errorCount": 3,
    "reconciliationDifference": 0,
    "statementGenerated": false,
    "closable": false
  },
  "nextActions": [
    {
      "type": "RESOLVE_ERRORS",
      "message": "정산 규칙이 없는 판매 항목 3건을 처리하세요."
    }
  ]
}

주요 작업 이력 조회 (FR-024)

항목내용
목적계정·권한 변경, 파일 업로드, 직접 연결, 규칙 등록·변경, 폐기 등록, 정산서 생성, 마감, 정정, 이의 처리 이력을 확인합니다.
인증매장 운영자
방식·경로GET /api/audit-logs

조회값

이름설명
targetType예: SETTLEMENT_WEEK, SETTLEMENT_RULE, OBJECTION
targetId특정 대상 식별값
actionType예: CREATE, UPDATE, CLOSE, CORRECTION_CREATE
from, to이력 발생 기간

성공 응답

{
  "logs": [
    {
      "id": "log_001",
      "actionType": "SETTLEMENT_CLOSED",
      "targetType": "SETTLEMENT_WEEK",
      "targetId": "sw_2026084",
      "summary": "2026년 8월 4주차 정산을 마감했습니다.",
      "performedBy": {
        "id": "usr_002",
        "name": "이점장"
      },
      "performedAt": "2026-08-27T16:30:00+09:00"
    }
  ]
}

12. 요구사항-API 연결표

요구사항구현 API
FR-001운영자 로그인, 로그아웃
FR-002담당자 계정 목록 조회, 등록, 권한·상태 변경
FR-003농가 로그인, 농가 로그인 계정 연결·상태 변경
FR-004정산 주차 목록·상세 조회, 정산 주차 생성
FR-005농가·품목·품목군 목록 조회, 농가 등록·변경·중지, 품목군 등록·변경, 품목과 상품코드 등록·변경·중지
FR-006정산 규칙 목록·상세 조회, 정산 규칙 등록, 정산 규칙 변경 이력 등록
FR-007계산대 판매 파일 업로드, 파일 오류 행과 업로드 이력 조회
FR-008상품코드 미연결 항목 조회, 판매 항목 직접 연결과 상품코드 재사용 등록
FR-009판매 원장 조회, 중복 가능 거래 확인 처리
FR-010판매 원장 조회, 판매·할인·반품 내역 상세 조회, 폐기·미회수 재고 목록·상세 조회
FR-011폐기·미회수 재고 등록, 목록·상세 조회, 증빙 사진 업로드
FR-012정산 금액 계산과 재계산
FR-013정산 오류 목록과 처리 상태 조회
FR-014매출 대조 결과 조회, 수기 조정 등록
FR-015정산 주차 목록·상세 조회, 주간 정산 현황 조회
FR-016농가별 정산서 생성, 운영자용 정산서 목록·상세 조회, 운영자용 정산서 내려받기
FR-017정산 마감
FR-018정정 항목 작성, 다음 정산 반영 예정 정정 항목 조회
FR-019운영자용 정산서 목록·상세 조회, 마감·정정 연결 이력 조회
FR-020농가의 이번 주 정산 요약 조회
FR-021농가 정산서 목록·상세 조회, 농가 정산서 내려받기
FR-022증빙 사진 업로드, 농가 이의 제기 등록
FR-023운영자용 이의 제기 목록·상세 조회, 농가 이의 제기 처리 결과 등록
FR-024파일 오류 행과 업로드 이력 조회, 수기 조정 등록, 마감·정정 연결 이력 조회, 주요 작업 이력 조회

13. 첫 버전 제외 항목

다음 항목은 SRS의 첫 개발 범위에서 제외합니다.

  • 실제 은행 이체
  • 은행 이체용 지급 파일 생성
  • 문자·카카오톡 알림
  • 여러 로컬푸드 직매장 통합 관리
  • 외부 정보 기반의 자동 상품코드 판별
  • 마감 완료 정산의 재개방 및 직접 수정
  • 별도 모바일 앱과 앱 스토어 배포

다만 개발 인터뷰에는 “농가별 정산 결과를 은행 이체용 파일로 내려받아 운영자가 은행 시스템에 올릴 수 있어야 한다”는 요구가 포함되어 있습니다. SRS의 제외 범위와 충돌하므로, 은행 이체용 지급 파일은 첫 버전 확정 전에 포함 여부를 결정해야 합니다.

기능 연결 방식 — 로컬푸드 직매장 위탁판매·정산 관리 | Prometheon