봉투·LOT·바코드 코드 체계
종량제 물류 시스템에서 사용하는 봉투번호(바코드), LOT 번호, 품목코드 등이 어디서 만들어지고 무엇을 의미하는지 정리한 문서입니다.
구현 기준: app/Controllers/Bag.php, app/Controllers/Admin/BagOrder.php, app/Libraries/BagLotFlowBuilder.php, writable/database/*.sql.
1. 계층 구조 (한눈에 보기)
| 단위 |
예시 |
조회·스캔 용도 |
| LOT |
OQXCKH |
발주 단위, LOT 수불·디스켓 시드 |
| 박스 |
OQXCKH-000008-B001 |
박스 단위 입출고·LOT 수불 |
| 팩 |
OQXCKH-000008-P299 |
팩 단위 (스캔 가능) |
| 낱장 |
OQXCKH-000008-P299-S00125 |
장(매) 단위 판매·반품·LOT 수불 |
참고: 000008은 “8번째 봉투”가 아니라 입고 건 PK(br_idx)를 6자리로 채운 값입니다.
2. 발주 LOT 번호 (bo_lot_no)
생성 시점·위치
- 화면: 관리자 발주 등록·수정 (
Admin\BagOrder::store)
- 테이블:
bag_order.bo_lot_no
생성 규칙
- 신규 발주:
generateLotNo6() — 영문 대문자+숫자 6자리 난수 (0-9, A-Z), DB 중복 시 최대 20회 재시도.
- 실패 시: 타임스탬프 기반 6자리 fallback (
base_convert(time, 10, 36)).
- 발주 수정(재발주): 기존 건의
bo_lot_no를 유지 (새 LOT를 붙이지 않음).
- 입고 시 LOT 미지정: 주문에 LOT가 없으면
bag_code(품목코드)를 LOT 자리에 대체 사용 (createReceivingPackCodes).
의미
- 제작업체·지자체가 한 번의 발주 묶음을 식별하는 번호.
- 입고 후
bag_receiving_pack_code.brpc_lot_no에 복사되어 박스/팩/낱장 코드의 접두어가 됩니다.
- LOT-No 디스켓 불출 (
/bag/order/lot-seed)·바코드 시드 파일명에 사용.
예시
| 값 |
설명 |
OQXCKH |
발주 시 부여된 6자리 LOT (시드 예: writable/barcode-seeds/OQXCKH_v1.seed.json) |
3K9F2A |
다른 발주 건의 LOT |
3. 발주 UUID·버전·해시
| 필드 |
형식 |
의미 |
bo_uuid |
UUID v4 (xxxxxxxx-xxxx-4xxx-...) |
동일 발주의 버전 묶음 식별자 |
bo_version |
정수 (1부터 증가) |
발주 개정 이력 (복합 PK: uuid + version) |
bo_hash |
SHA-256 64자 hex |
발주 헤더+품목 JSON의 무결성 검증용 |
- 수정·재발주 시 새
bo_version 행이 생기고, bo_hash가 갱신됩니다.
- 블록체인 연동 시
SqlLedger에 ORDER_CREATE / ORDER_UPDATE와 함께 기록됩니다.
4. 바코드 시드 파일 (제작업체 연동)
생성 시점
- 발주 저장 시:
Admin\BagOrder::generateBarcodeSeedFile()
- LOT 디스켓 불출 시:
Bag::orderLotSeedGenerate() (동일 포맷)
저장 위치·파일명
- 디렉터리:
writable/barcode-seeds/
- 파일명:
{bo_lot_no}_v{bo_version}.seed.json
예: OQXCKH_v1.seed.json
내용
- 발주·품목 메타를 JSON으로 묶고 AES-256-CBC로 암호화.
- AES 키는 RSA-2048 공개키로 래핑 (
writable/keys/barcode_seed_*.pem).
- 평문에는
lot_no, uuid, version, order, items, order_hash 등이 포함됩니다.
의미 (운영)
- 레거시/요구사항상 제작업체 인쇄용 바코드 원시데이터를 지자체가 발주와 함께 넘기는 용도.
- 현재 웹 입고 바코드(
bag_receiving_pack_code)는 아래 5절처럼 입고 처리 시 서버가 별도 생성합니다.
(README 「바코드 생성/사용 시점」 참고 — 발주 시점 생성 vs 입고 시점 생성 정책 검토 중)
5. 입고 시 박스·팩·낱장 바코드 (bag_receiving_pack_code)
생성 시점·함수
- 함수:
Bag::createReceivingPackCodes()
- 호출: 입고 스캐너·일괄 입고 저장 시 (
receiving/scanner/store, receiving/batch/store 등)
- 조건: 해당
br_idx에 팩 코드가 아직 없을 때만 1회 생성
입력·포장 단위
packaging_unit (pu_pack_per_sheet, pu_total_per_box): 팩당 낱장 수, 박스당 총 낱장 수.
- 입고 낱장 수
qtySheet로 필요 팩 개수 = ceil(qtySheet / pack_per_sheet).
- 박스당 팩 수 =
total_per_box / pack_per_sheet.
코드 포맷 (구현)
$lotNo = 발주 bo_lot_no (없으면 품목코드), $brIdx = bag_receiving.br_idx.
| 구분 |
sprintf 패턴 |
예 (lot=OQXCKH, br_idx=8) |
| 박스 |
{lotNo}-%06d-B%03d |
OQXCKH-000008-B001 |
| 팩 |
{lotNo}-%06d-P%03d |
OQXCKH-000008-P001 … P299 |
| 낱장 시작 |
{packCode}-S%05d |
OQXCKH-000008-P299-S00001 |
| 낱장 끝 |
{packCode}-S%05d |
OQXCKH-000008-P299-S00300 (팩당 300장 예) |
%06d → br_idx 6자리 (000008 = 8번 입고 건).
%03d → 박스·팩 순번 (001~999).
%05d → 팩 내부 낱장 순번 (00001~).
DB 컬럼 의미
| 컬럼 |
설명 |
brpc_lot_no |
발주 LOT |
brpc_box_code |
박스 바코드 |
brpc_pack_code |
팩 바코드 (UNIQUE) |
brpc_sheet_start_code / brpc_sheet_end_code |
해당 팩에 속한 낱장 코드 구간 |
brpc_sheet_qty |
그 팩의 낱장 매수 |
brpc_state |
in_stock / sold 등 재고 상태 |
LOT 수불 조회에서의 해석
- 낱장 번호 입력 → 해당 장의 판매·반품만 + 소속 팩 입고 1건.
- 팩 번호 (
…-P299) → 팩·박스 코드 기준 이력.
- LOT만 (
lot_no 파라미터) → 동일 LOT 전체 팩·입고·발주 요약.
6. 봉투 품목코드 (code_detail, 종류 O)
등록
- 종류:
code_kind.ck_code = 'O' (봉투명/품목)
- 테이블:
code_detail.cd_code, cd_name
- 지자체별 확장:
cd_lg_idx (0이면 공통)
코드 구성 (5자리 숫자 관례)
대구 시드(code_master_init_daegu.sql) 기준:
| 자리 |
연계 종류 |
예 |
| 앞 2자리 |
E 봉투구분 (10=일반, 20=공공, 30=무료, 60=음식물…) |
10 |
| 다음 2자리 |
G 용량 (15=20L, 13=10L…) |
15 |
| 마지막 1자리 |
F 재질 등 |
2 |
예: 10152 = 일반용(10) + 20L(15) + … → 일반용 20L
- 발주·입고·재고·판매 집계는 이 코드(
bs_bag_code, br_bag_code, bi_bag_code 등)로 묶입니다.
- 바코드(LOT·팩·낱장)와는 별개 — 품목 종류 식별용 마스터 코드입니다.
7. 지자체·행정 코드
| 코드 |
필드 |
예 |
의미 |
| 지자체 |
local_government.lg_code |
110204 |
대구 남구 (6자리 관례) |
| 발주 구·군 |
bag_order.bo_gugun_code |
110204 |
발주 시 지자체 lg_code 복사 |
| 발주 동 |
bag_order.bo_dong_code |
(동 코드) |
세부 행정 단위 |
8. 지정판매소 번호 (ds_shop_no)
자동 부여 (주소 기반)
Admin\DesignatedShop::resolveDesignatedShopNumberFromAddress():
- B: 시·도 (
code_kind = B, 주소 매칭)
- C: 구·군 (
C, B 접두 포함)
- D: 동 (
D, C 접두 포함)
- 일련: 동일 지자체 내 기존 번호 끝 3자리 숫자 최댓값 + 1
시드·레거시
- 초기 데이터에
DS-2024-001 형태가 있을 수 있음 (수동/이관 데이터).
- 가상계좌:
ds_va_number / ds_va_bank + ds_va_account
판매 스캔과의 관계
- 판매·반품 시
bssc_ds_idx / brsc_ds_idx로 판매소 연결.
- LOT 수불·판매 대장의 입출고처에
ds_name 표시.
9. 판매·반품 스캔 코드
저장 테이블
| 테이블 |
코드 컬럼 |
생성 시점 |
bag_sale_scan_code |
bssc_code |
지정판매소 판매 (/bag/sale/designated) |
bag_return_scan_code |
brsc_code |
지정판매소 반품 (/bag/sale/designated-return) |
규칙
- 스캔·입력 값 = 입고 시 생성된 바코드 (보통 낱장 또는 팩).
bssc_state: in_stock → 판매 시 sold, 반품 시 다시 in_stock.
- 낱장 판매 시 동일 팩의 다른 낱장을 위해
bag_receiving_pack_code 팩 상태는 유지할 수 있음 (코드 주석 참고).
주문·판매 집계 코드
bag_sale.bs_type: sale / return / cancel
shop_order / shop_order_item: 주문 접수용 (전화·웹 등), 판매소·품목·수량 — LOT 바코드와 별도 흐름.
10. 기타 코드
| 구분 |
예 |
설명 |
| 회원 |
mb_id |
로그인 ID (시스템 부여·가입) |
| 제작업체 |
company.cp_* |
발주 bo_company_idx |
| 판매 대행소 |
sales_agency.sa_* |
발주·입고 bo_agency_idx |
| 무료 불출 |
bag_issue |
불출처·수량 (바코드 LOT 체계와 별도) |
| 반품/파기 시드 |
RET-20260508-DS1-001 |
테스트용 반품 스캔 코드 (bag_dispose_tables.sql) |
| 파기 |
bag_dispose |
입고분 파기 이력 (반품/파기 현황 입고 탭) |
11. 화면별 “어떤 코드를 넣나”
| 화면 |
입력·표시 코드 |
데이터 소스 |
| LOT 수불 조회 |
봉투번호(바코드)·lot_no |
BagLotFlowBuilder |
| 지정판매소 판매/반품 |
스캔 바코드 |
bag_sale_scan_code / bag_return_scan_code |
| 반품/파기 현황 출고 |
(조회만) |
bag_return_scan_code |
| 반품/파기 현황 입고 |
(조회만) |
bag_dispose |
| 기간별 봉투 수불 |
품목코드 O |
집계 (BagFlowReportBuilder) |
| 발주·입고 |
LOT, 품목코드 |
bag_order, bag_receiving |
12. 구현·스키마 참고 파일
| 주제 |
파일 |
| 입고 바코드 생성 |
app/Controllers/Bag.php → createReceivingPackCodes() |
| LOT 6자리 생성 |
app/Controllers/Admin/BagOrder.php → generateLotNo6() |
| LOT 수불 조회 |
app/Libraries/BagLotFlowBuilder.php |
| 팩 코드 테이블 |
writable/database/receiving_pack_code_tables.sql |
| 발주 테이블 |
writable/database/order_tables.sql |
| 품목 마스터 |
writable/database/code_master_init_daegu.sql (종류 O) |
| 바코드 시드 샘플 |
writable/barcode-seeds/*.seed.json |
13. 자주 묻는 혼동
-
OQXCKH-000008-P299와 P300이 비슷해 보이는데 수불이 같다?
- 이전에는 팩·LOT 전체 이력을 함께 가져왔습니다.
- 수정 후 낱장 단위는
…-P299-Sxxxxx 형태로 조회하거나, 팩 단위는 P299/P300 각각 조회해야 판매 이력이 갈립니다.
-
LOT 6자리와 접두 OQXCKH가 다른 길이?
- 발주 LOT는 6자리 규칙이지만, 시드·테스트 데이터에 6자 영문(
OQXCKH)을 쓴 경우가 있습니다. DB VARCHAR(50)에 저장되며, 입고 코드 접두로 그대로 사용됩니다.
-
품목코드 10152와 바코드 OQXCKH-…의 관계?
10152는 종류·용량 마스터.
OQXCKH-…는 물리 단위(팩/장) 추적용 바코드입니다. 같은 품목이라도 LOT·입고 건마다 바코드 접두가 달라집니다.
문서 갱신: 코드 변경 시 createReceivingPackCodes, generateLotNo6, BagLotFlowBuilder를 우선 확인하세요.