feat(dispatch): Shopee 플랫폼 추가 + 받는 사람 정보 저장/출고 엑셀
- 플랫폼 TikTok/Shopee 분리: 업로드 화면이 선택에 따라 파일 안내 변경 (TikTok=Order Export xlsx, Shopee=Packing List xlsx / 라벨 PDF 선택) - TikTok Picking List.pdf 업로드 제거(피킹 요약은 데이터 엑셀로 생성) - 파서 공용화 + 헤더 행 자동탐지(Shopee 제목행 대응), 두 포맷 헤더 별칭 통합 - 받는 사람 이름/전화/주소를 박스 단위로 dispatch_db 에 저장(개인정보) · init SQL 갱신 + 기존 DB용 멱등 마이그레이션 dispatch_add_recipient_columns.sql - 출고 작업 카드: Package 제거, 받는 사람 이름(크게)+주소(여러 줄)+전화 표시 - 배치 다운로드 zip 에 취합 출고 엑셀 포함 파일명 YYYY.MM.DD(Ddd)_tictoc.xlsx / _shopee.xlsx (export.py) - 문서(CLAUDE.md, DISPATCH_MODULE.md) PII 보관·Shopee 반영 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,10 @@
|
||||
.dsp-order { font-size:15px;line-height:1.3;color:#334155;word-break:break-all; }
|
||||
.dsp-order b { display:block;font-size:14px;font-weight:700;color:#475569;letter-spacing:.5px; }
|
||||
.dsp-order span { font-size:27px;font-weight:800;color:#0f172a;letter-spacing:.2px; }
|
||||
.dsp-recipient { border-top:1px dashed #e2e8f0;padding-top:8px; }
|
||||
.dsp-rname { display:block;font-size:22px;font-weight:800;color:#0f172a;line-height:1.2;word-break:break-word; }
|
||||
.dsp-raddr { font-size:14px;line-height:1.45;color:#334155;white-space:normal;word-break:break-word;margin-top:3px; }
|
||||
.dsp-rphone { font-size:13px;color:#475569;margin-top:2px; }
|
||||
.dsp-track-link { color:#2563eb !important;font-size:18px;font-weight:800;
|
||||
text-decoration:underline !important;text-decoration-line:underline !important;
|
||||
text-decoration-thickness:2px;text-underline-offset:3px;cursor:pointer; }
|
||||
@@ -54,7 +58,7 @@
|
||||
<button class="erp-btn erp-btn-outline" data-filter="handed_to_kagayaku" type="button">Kagayaku 전달</button>
|
||||
</div>
|
||||
<input class="erp-input dsp-search" id="dsp-search" type="search"
|
||||
placeholder="검색: Order ID / Tracking ID / Package ID / SKU" />
|
||||
placeholder="검색: Order ID / Tracking ID / 받는 사람 / SKU" />
|
||||
</div>
|
||||
|
||||
<div class="dsp-cards" id="dsp-cards">
|
||||
@@ -64,7 +68,7 @@
|
||||
data-parcel="{{ p.id }}"
|
||||
data-label_attached="{{ p.label_attached|lower }}"
|
||||
data-handed_to_kagayaku="{{ p.handed_to_kagayaku|lower }}"
|
||||
data-search="{{ (p.order_id ~ ' ' ~ p.package_id ~ ' ' ~ p.tracking_id ~ ' ' ~ (p['items']|map(attribute='seller_sku')|join(' ')))|lower }}">
|
||||
data-search="{{ (p.order_id ~ ' ' ~ p.tracking_id ~ ' ' ~ p.recipient_name ~ ' ' ~ (p['items']|map(attribute='seller_sku')|join(' ')))|lower }}">
|
||||
{% set logo = p.shipping_provider | courier_logo %}
|
||||
{% if logo %}
|
||||
<img class="dsp-courier" src="{{ logo }}" alt="{{ p.shipping_provider }}" title="{{ p.shipping_provider }}" />
|
||||
@@ -74,13 +78,17 @@
|
||||
<div class="dsp-no">No. {{ p.seq }}</div>
|
||||
<div class="dsp-order"><b>Order ID</b><span>{{ p.order_id or '—' }}</span></div>
|
||||
<div class="dsp-meta">
|
||||
<div><b>Package</b> {{ p.package_id or '—' }}</div>
|
||||
<div><b>Tracking</b>
|
||||
{% set turl = p.tracking_id | courier_track(p.shipping_provider) %}
|
||||
{% if turl %}<a class="dsp-track-link" href="{{ turl }}" target="_blank" rel="noopener noreferrer">{{ p.tracking_id }}</a>
|
||||
{% else %}{{ p.tracking_id or '—' }}{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="dsp-recipient">
|
||||
<span class="dsp-rname">{{ p.recipient_name or '—' }}</span>
|
||||
{% if p.recipient_address %}<div class="dsp-raddr">{{ p.recipient_address }}</div>{% endif %}
|
||||
{% if p.recipient_phone %}<div class="dsp-rphone">{{ p.recipient_phone }}</div>{% endif %}
|
||||
</div>
|
||||
<ul class="dsp-items">
|
||||
{% for it in p['items'] %}
|
||||
<li>{{ it.seller_sku }} <span class="qty">× {{ it.quantity }}</span></li>
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
{% include "dispatch/_nav.html" %}
|
||||
|
||||
<div class="erp-card" style="max-width:640px;">
|
||||
<div class="cpg-card-head"><h2>TikTok 파일 업로드</h2></div>
|
||||
<p class="erp-muted" style="margin:4px 0 16px;">
|
||||
03_TikTok_Order_Export.xlsx 만 있으면 출고 리스트가 자동 생성됩니다.
|
||||
PDF 2개는 보관용(선택)입니다. 고객 이름/주소/전화는 저장하지 않습니다.
|
||||
</p>
|
||||
<div class="cpg-card-head"><h2>출고 파일 업로드</h2></div>
|
||||
<p class="erp-muted" id="dsp-intro" style="margin:4px 0 16px;"></p>
|
||||
|
||||
<form method="post" action="/dispatch/batches" enctype="multipart/form-data" style="display:flex;flex-direction:column;gap:14px;">
|
||||
<label style="display:flex;flex-direction:column;gap:4px;">
|
||||
@@ -19,29 +16,26 @@
|
||||
|
||||
<label style="display:flex;flex-direction:column;gap:4px;">
|
||||
<span>플랫폼</span>
|
||||
<select class="erp-select" name="platform">
|
||||
<option value="TikTok" selected>TikTok</option>
|
||||
<select class="erp-select" name="platform" id="dsp-platform">
|
||||
{% for pf in platforms %}
|
||||
<option value="{{ pf }}">{{ pf }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label style="display:flex;flex-direction:column;gap:4px;">
|
||||
<span>배치명 <span class="erp-muted">(예: 2026-06-19 TikTok 오전 출고)</span></span>
|
||||
<span>배치명 <span class="erp-muted">(예: 2026-06-19 오전 출고)</span></span>
|
||||
<input class="erp-input" type="text" name="batch_name" placeholder="오전 출고 / 오후 출고 등으로 구분" />
|
||||
</label>
|
||||
|
||||
<label style="display:flex;flex-direction:column;gap:4px;">
|
||||
<span>1️⃣ Picking List.pdf <span class="erp-muted">(선택 · 전체 피킹 참고용)</span></span>
|
||||
<input class="erp-input" type="file" name="picking_pdf" accept="application/pdf" />
|
||||
<span id="dsp-label-lbl"></span>
|
||||
<input class="erp-input" type="file" name="label_pdf" id="dsp-label" accept="application/pdf" />
|
||||
</label>
|
||||
|
||||
<label style="display:flex;flex-direction:column;gap:4px;">
|
||||
<span>2️⃣ Shipping label+Packing slip.pdf <span class="erp-muted">(선택 · 실제 포장/라벨 원본)</span></span>
|
||||
<input class="erp-input" type="file" name="label_pdf" accept="application/pdf" />
|
||||
</label>
|
||||
|
||||
<label style="display:flex;flex-direction:column;gap:4px;">
|
||||
<span>3️⃣ TikTok Order Export.xlsx <span style="color:#dc2626;">*</span> <span class="erp-muted">(자동 출고 리스트 기준)</span></span>
|
||||
<input class="erp-input" type="file" name="order_export"
|
||||
<span id="dsp-data-lbl"></span>
|
||||
<input class="erp-input" type="file" name="data_xlsx" id="dsp-data"
|
||||
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" required />
|
||||
</label>
|
||||
|
||||
@@ -53,3 +47,32 @@
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
(function () {
|
||||
// 플랫폼별 안내/파일 라벨. 데이터 엑셀이 필수, 라벨 PDF 는 선택(보관용).
|
||||
var CFG = {
|
||||
"TikTok": {
|
||||
intro: "TikTok: 03_TikTok_Order_Export.xlsx 만 있으면 출고 리스트가 자동 생성됩니다. 라벨 PDF 는 보관용(선택)입니다.",
|
||||
label: "📄 Shipping label + Packing slip.pdf <span class='erp-muted'>(선택 · 실제 포장/라벨 원본)</span>",
|
||||
data: "📊 TikTok Order Export.xlsx <span style='color:#dc2626;'>*</span> <span class='erp-muted'>(자동 출고 리스트 기준)</span>"
|
||||
},
|
||||
"Shopee": {
|
||||
intro: "Shopee: Packing List.Doorstep Delivery.xlsx 로 출고 리스트가 자동 생성됩니다. Shopee Seller Centre.pdf(택배 송장)는 보관용(선택)입니다.",
|
||||
label: "📄 Shopee Seller Centre.pdf <span class='erp-muted'>(선택 · 택배 송장 원본)</span>",
|
||||
data: "📊 Packing List.Doorstep Delivery.xlsx <span style='color:#dc2626;'>*</span> <span class='erp-muted'>(자동 출고 리스트 기준)</span>"
|
||||
}
|
||||
};
|
||||
var sel = document.getElementById('dsp-platform');
|
||||
function apply() {
|
||||
var c = CFG[sel.value] || CFG["TikTok"];
|
||||
document.getElementById('dsp-intro').textContent = c.intro;
|
||||
document.getElementById('dsp-label-lbl').innerHTML = c.label;
|
||||
document.getElementById('dsp-data-lbl').innerHTML = c.data;
|
||||
}
|
||||
sel.addEventListener('change', apply);
|
||||
apply();
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user