40766d805d
증상: 상세페이지를 적용해도 편집기에 수정 전 소스가 보이고 한참 뒤에야 반영됨. 원인은 우리 캐시가 아니라(전부 no-store) 카페24 관리자 API 가 PUT 뒤 한동안 GET 에서 예전 값을 돌려주는 읽기 지연. 예전 코드는 2.4초만 기다린 뒤 GET 값을 그대로 믿어 예전 소스 표시·지문 충돌 오판·예전 값 백업이 생겼다. - 상세설명: 쓰기 성공 시 MANUAL/SCHEDULED revision 을 기준으로, 카페24 값이 유예시간 안의 revision 중 하나와 같으면 지연(pending)으로 보고 마지막 쓰기를 표시·지문 기준으로 쓴다. 모르는 값이면 외부 변경(external). store.resolve_description / db.revision_digests(md5) / 배너 2종. - 적용(apply)은 유효 현재값으로 BACKUP·지문 대조·변경없음 판정. 재조회 확인 결과는 감사로그에만 남긴다. - 스칼라(상품명·가격·이미지·진열/판매): PUT 응답을 cafe24_products. last_write_snapshot(JSONB, 마이그레이션 004)에 남기고 GET 의 updated_date 가 그보다 이전이면 스냅샷으로 덮어씀. 옵션/품목도 섹션별 스냅샷. - 3분할 화면: 목록 | 편집기 | 상품 정보 패널(_side.html, /pane 이 두 조각을 한 응답으로). routes_product_info.py JSON API — 상품명/판매가/공급가/ 소비자가, 대표이미지 업로드(POST /admin/products/images → PUT detail_image + image_upload_type=A), 옵션 생성/이름·썸네일·표시방식 수정/삭제, 품목 자체코드·추가금액·진열·판매 일괄 수정. 화면은 PUT 응답으로 그린다. - client.delete/timeout, products.upload_images·options·variants 래퍼. - 유닛테스트 21건 추가(88 통과), 문서(CAFE24_MODULE 3-3/3-4, DATABASES, .env.example CAFE24_READ_LAG_GRACE_MIN) 갱신. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
141 lines
9.0 KiB
Bash
141 lines
9.0 KiB
Bash
GOOGLE_CLIENT_ID=your-google-oauth-client-id.apps.googleusercontent.com
|
|
GOOGLE_CLIENT_SECRET=your-google-oauth-client-secret
|
|
# OMS(orderlist) 와 SSO 하려면 양쪽 .env 에 동일한 값으로 설정.
|
|
# 미설정 시 컨테이너 기동 실패(fail-fast). openssl rand -hex 32 로 생성 권장.
|
|
SESSION_SECRET_KEY=replace-with-a-long-random-secret
|
|
SESSION_COOKIE_NAME=session
|
|
SESSION_COOKIE_SECURE=true
|
|
# 세션 유효기간(초). OMS(orderlist) 와 동일하게 맞출 것. 28800=8h
|
|
SESSION_MAX_AGE=28800
|
|
|
|
# 포털 접근 허용 이메일. 쉼표로 구분. 비워두면 코드의 기본 목록 사용.
|
|
ALLOWED_EMAILS=king@dbxcorp.co.kr,julie@dbxcorp.co.kr,ellen@dbxcorp.co.kr,bj@dbxcorp.co.kr
|
|
PUBLIC_BASE_URL=https://dbx.no1king.freeddns.org
|
|
# 비워두면 같은 도메인의 /corm/ 경로(NPM 리버스 프록시)로 자동 연결됨
|
|
CS_ORDER_URL=/corm/
|
|
# 비워두면 같은 도메인의 /orderlist/ 경로(NPM 리버스 프록시)로 자동 연결됨
|
|
CUSTOMER_ORDER_LIST_URL=/orderlist/
|
|
|
|
# ─── 개인경비 모듈 (expense_db) ───
|
|
# 설정하면 PostgreSQL 사용, 미설정 시 DATA_DIR/expense.json 사용.
|
|
# DB/역할 생성: scripts/sql/expense_db_init.sql 참고.
|
|
# EXPENSE_DB_URL=postgresql://expense_app:replace-me@postgres-db:5432/expense_db
|
|
|
|
# ─── 쿠팡 밀크런 모듈 (cupang_db) ───
|
|
# 설정해야 모듈이 동작한다(미설정 시 "설정 필요" 안내, JSON 폴백 없음).
|
|
# DB/역할/스키마/센터 seed 생성: scripts/sql/cupang_db_init.sql 참고.
|
|
# CUPANG_DB_URL=postgresql://cupang_app:replace-me@postgres-db:5432/cupang_db
|
|
|
|
# 쿠팡 밀크런 출고리스트를 기록할 Google 스프레드시트 (분배 확정 시 출고일 시트 생성)
|
|
# - 대상 문서는 반드시 "Google 스프레드시트" 형식(업로드한 .xlsx 는 파일>Google 스프레드시트로 저장)
|
|
# - 서비스 계정 이메일(client_email)에 해당 문서를 편집자로 공유해야 한다
|
|
# CUPANG_SHEET_ID=1J74op7lBZOgE27p4R28I3RWsv0EtXdii
|
|
#
|
|
# [방식 A] 사용자 OAuth 리프레시 토큰 — 조직 정책으로 서비스 계정 키를 못 만들 때
|
|
# 토큰 발급: python scripts/google_sheets_authorize.py --client-id .. --client-secret ..
|
|
# (Cloud Console 에서 "데스크톱 앱" 유형 OAuth 클라이언트 ID 발급 후 사용)
|
|
# client id/secret 을 생략하면 로그인용 GOOGLE_CLIENT_ID/SECRET 을 쓴다.
|
|
# GOOGLE_SHEETS_OAUTH_CLIENT_ID=xxx.apps.googleusercontent.com
|
|
# GOOGLE_SHEETS_OAUTH_CLIENT_SECRET=replace-me
|
|
# GOOGLE_SHEETS_OAUTH_REFRESH_TOKEN=replace-me
|
|
#
|
|
# [방식 B] 서비스 계정 JSON (문서를 client_email 에 편집자로 공유해야 함)
|
|
# GOOGLE_SHEETS_CREDENTIALS=/opt/www/main/secrets/google-sheets-sa.json
|
|
# 또는 파일 대신 JSON 본문을 통째로 (한 줄):
|
|
# GOOGLE_SHEETS_CREDENTIALS_JSON={"type":"service_account", ...}
|
|
|
|
# ─── 휴가 관리 모듈 (vacation_db) ───
|
|
# 설정해야 모듈이 동작한다(미설정 시 "설정 필요" 안내, JSON 폴백 없음).
|
|
# DB/역할/스키마/공휴일 seed 생성: scripts/sql/vacation_db_init.sql 참고.
|
|
# 권한키: vacation(접근) / vacation_approver(승인·반려). admin 은 항상 통과.
|
|
# VACATION_DB_URL=postgresql://vacation_app:replace-me@postgres-db:5432/vacation_db
|
|
|
|
# ─── 말레이시아 창고 재고관리 모듈 (malaysia_stock_db) ───
|
|
# 설정해야 모듈이 동작한다(미설정 시 "설정 필요" 안내, JSON 폴백 없음).
|
|
# DB/역할/스키마/창고·아이템 seed 생성: scripts/sql/malaysia_stock_db_init.sql 참고.
|
|
# 권한키: malaysia(접근). admin 은 항상 통과. 상품명은 아래 ITEMCODE_DB_URL 재사용.
|
|
# MALAYSIA_STOCK_DB_URL=postgresql://malaysia_app:replace-me@postgres-db:5432/malaysia_stock_db
|
|
|
|
# ─── 말레이시아 배송 모듈 (dispatch_db) — TikTok 출고관리 ───
|
|
# 설정해야 모듈이 동작한다(미설정 시 "설정 필요" 안내, JSON 폴백 없음).
|
|
# DB/역할/스키마 생성: scripts/sql/dispatch_db_init.sql 참고.
|
|
# 권한키: dispatch(접근). admin 은 항상 통과.
|
|
# 업로드 원본 파일은 DATA_DIR/dispatch/<날짜>/<배치>/ 아래에 저장된다.
|
|
# 개인정보(고객 이름/주소/전화)는 저장하지 않는다.
|
|
# DISPATCH_DB_URL=postgresql://dispatch_app:replace-me@postgres-db:5432/dispatch_db
|
|
|
|
# ─── 프로젝트 관리 모듈 (project_db) — 아사나식 ───
|
|
# 설정해야 모듈이 동작한다(미설정 시 "설정 필요" 안내, JSON 폴백 없음).
|
|
# DB/역할/스키마 생성: scripts/sql/project_db_init.sql 참고.
|
|
# 진입 권한: 로그인한 회사 직원 전원(별도 권한키 없음). 프로젝트 생성/배정은 관리자만.
|
|
# PROJECT_DB_URL=postgresql://project_app:replace-me@postgres-db:5432/project_db
|
|
|
|
# ─── 메일 알림 (SMTP) — 프로젝트 업무 배정/완료 시 관리자 알림 ───
|
|
# SMTP_HOST 가 있어야 발송. 미설정 시 조용히 skip(앱은 정상 동작).
|
|
# SMTP_TLS: true(STARTTLS,587 기본) | ssl(SMTPS,465) | false(평문)
|
|
# SMTP_HOST=smtp.gmail.com
|
|
# SMTP_PORT=587
|
|
# SMTP_USER=alarm@dbxcorp.co.kr
|
|
# SMTP_PASSWORD=app-password-here
|
|
# SMTP_FROM=alarm@dbxcorp.co.kr
|
|
# SMTP_TLS=true
|
|
# 알림 수신자(쉼표구분). 비워두면 ERP 관리자(admin) 전원에게 발송.
|
|
# PROJECT_NOTIFY_EMAIL=king@dbxcorp.co.kr
|
|
|
|
# ─── 카페24 상품 상세페이지 관리 모듈 (cafe24_db) ───
|
|
# 설정해야 모듈이 동작한다(미설정 시 "설정 필요" 안내, JSON 폴백 없음).
|
|
# DB/역할/스키마 생성: scripts/sql/cafe24_db_init.sql 참고.
|
|
# 권한키: cafe24(접근). admin 은 항상 통과. 카페24 연결(OAuth)은 admin 전용.
|
|
# CAFE24_DB_URL=postgresql://cafe24_app:replace-me@postgres-db:5432/cafe24_db
|
|
#
|
|
# 카페24 개발자센터(https://developers.cafe24.com)에서 앱을 만들고 발급받은 값.
|
|
# - Redirect URI 는 아래 CAFE24_REDIRECT_URI 와 반드시 동일하게 앱에 등록.
|
|
# - Scope 는 상품관리에 mall.read_product, mall.write_product 가 필요하다.
|
|
# (향후 주문관리 추가 시 mall.read_order, mall.write_order 를 앱에 추가하고
|
|
# 재인증하면 된다 — 코드는 app/integrations/cafe24/config.py 의 SCOPES)
|
|
# CAFE24_MALL_ID=miraskitchen
|
|
# CAFE24_CLIENT_ID=
|
|
# CAFE24_CLIENT_SECRET=
|
|
# CAFE24_REDIRECT_URI=https://dbx.no1king.freeddns.org/cafe24/oauth/callback
|
|
# CAFE24_API_VERSION=2026-03-01
|
|
#
|
|
# 고객이 보는 쇼핑몰 주소. 상품관리 화면에서 상세페이지 다이렉트 주소를 만들 때 쓴다
|
|
# (예: https://miras.co.kr/product/detail.html?product_no=119).
|
|
# 커스텀 도메인은 mall_id 로 알 수 없어 직접 지정해야 한다.
|
|
# 미설정 시 카페24 기본 도메인(https://<mall_id>.cafe24.com)으로 대체된다.
|
|
# CAFE24_SHOP_URL=https://www.miras.co.kr
|
|
#
|
|
# 카페24 읽기 지연 유예시간(분). 카페24 관리자 API 는 PUT 뒤 한동안 GET 에서 예전
|
|
# 값을 돌려준다. 이 시간 안에 우리가 쓴 값이 있으면, GET 이 그 이전 값을 돌려줘도
|
|
# 마지막 쓰기(revision·스냅샷)를 화면·적용 기준으로 삼는다. 지나면 카페24 값을 믿는다.
|
|
# 미설정 시 360(6시간).
|
|
# CAFE24_READ_LAG_GRACE_MIN=360
|
|
#
|
|
# access/refresh token 을 DB 에 Fernet 암호화해서 저장할 때 쓰는 키.
|
|
# openssl rand -hex 32 로 생성. ⚠️ 값을 바꾸면 기존 토큰을 복호화할 수 없어
|
|
# 카페24 재연결(재인증)이 필요하다.
|
|
# CAFE24_TOKEN_SECRET=
|
|
#
|
|
# ── 디자인 보관함 FTP 편집(모바일 스와이프 / PC·모바일 상품상세 템플릿) ──
|
|
# Admin API(OAuth)로는 스킨 파일을 못 읽는다. 카페24 관리자 → 디자인 →
|
|
# 웹FTP 화면에 표시된 값을 그대로 쓴다(SSL/TLS 미사용, 평문 FTP, 포트 21).
|
|
# 호스트 미설정 시 CAFE24_MALL_ID 기준 기본값({mall_id}.ftp.cafe24.com)을 쓴다.
|
|
# CAFE24_FTP_HOST=miraskitchen.ftp.cafe24.com
|
|
# CAFE24_FTP_PORT=21
|
|
# CAFE24_FTP_USER=
|
|
# CAFE24_FTP_PASSWORD=
|
|
# 편집 대상 파일들의 절대 경로(스킨 번호가 바뀌면 함께 바뀐다). 각각 선택 —
|
|
# 미설정 시 아래 기본값(실물 확인된 미라스키친 mobile11/skin11 스킨)을 쓴다.
|
|
# CAFE24_SWIPER_FTP_PATH=/sde_design/mobile11/product-swiper/product-swiper.js
|
|
# CAFE24_MOBILE_DETAIL_FTP_PATH=/sde_design/mobile11/product/detail.html
|
|
# CAFE24_PC_DETAIL_FTP_PATH=/sde_design/skin11/product/detail.html
|
|
|
|
# ─── 상품 검색 (itemcode_db 읽기 전용) ───
|
|
# cupang 설정 화면에서 제품명을 itemcode_db 에서 검색해 등록한다(읽기만).
|
|
# 미설정 시 검색 비활성 → 수동 등록만 가능.
|
|
# itemcode_db 실제 테이블: single_items(낱개) / set_items(세트)
|
|
# 컬럼: item_code, sabangnet_code, name
|
|
# 읽기 전용 역할 itemcode_ro 를 먼저 생성하고(아래 DSN), 낱개+세트 UNION 검색 SQL 사용:
|
|
# ITEMCODE_DB_URL=postgresql://itemcode_ro:replace-me@postgres-db:5432/itemcode_db
|
|
# ITEMCODE_SEARCH_SQL=SELECT item_code AS code, name AS name, '낱개' AS type FROM single_items WHERE item_code ILIKE %(q)s OR name ILIKE %(q)s UNION ALL SELECT item_code AS code, name AS name, '세트' AS type FROM set_items WHERE item_code ILIKE %(q)s OR name ILIKE %(q)s ORDER BY code ASC LIMIT %(limit)s
|