| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- @page "{id:int}"
- @model Admin.Pages.Store.Shipment.DetailModel
- @using Domain.Entities.Store.ValueObject
- @{
- ViewData["Title"] = "배송 상세";
- }
- <div class="container-fluid">
- <h3>@ViewData["Title"]</h3>
- <hr />
- <partial name="_StatusMessage" />
- @if (Model.Data is null)
- {
- <div class="alert alert-danger">배송 정보를 불러올 수 없습니다.</div>
- }
- else
- {
- var d = Model.Data;
- <div class="card mb-3">
- <div class="card-header"><strong>배송 기본 정보</strong></div>
- <div class="card-body">
- <dl class="row mb-0">
- <dt class="col-sm-2">주문번호</dt><dd class="col-sm-4">
- <a asp-page="/Store/Order/Detail" asp-route-id="@d.OrderID"><code>@d.OrderNumber</code></a>
- </dd>
- <dt class="col-sm-2">구매자</dt><dd class="col-sm-4">@d.BuyerEmail</dd>
- <dt class="col-sm-2">배송 상태</dt><dd class="col-sm-4">@Admin.Pages.Store.Shipment.IndexModel.StatusToText(d.Status)</dd>
- <dt class="col-sm-2">생성일</dt><dd class="col-sm-4">@d.CreatedAt.ToString("yyyy-MM-dd HH:mm")</dd>
- <dt class="col-sm-2">택배사</dt><dd class="col-sm-4">@(d.Carrier ?? "-")</dd>
- <dt class="col-sm-2">송장번호</dt><dd class="col-sm-4">@(d.TrackingNumber ?? "-")</dd>
- <dt class="col-sm-2">출고일</dt><dd class="col-sm-4">@(d.ShippedAt?.ToString("yyyy-MM-dd HH:mm") ?? "-")</dd>
- <dt class="col-sm-2">배송완료</dt><dd class="col-sm-4">@(d.DeliveredAt?.ToString("yyyy-MM-dd HH:mm") ?? "-")</dd>
- <dt class="col-sm-2">배송비</dt><dd class="col-sm-4">@d.ShippingFee.ToString("N0") P</dd>
- <dt class="col-sm-2">관리자 메모</dt><dd class="col-sm-10">@(string.IsNullOrWhiteSpace(d.AdminMemo) ? "-" : d.AdminMemo)</dd>
- </dl>
- </div>
- </div>
- <!-- 수령 주소 (권한 필요) -->
- <div class="card mb-3">
- <div class="card-header d-flex justify-content-between align-items-center">
- <strong>수령 주소</strong>
- @if (!Model.WithAddress)
- {
- <a class="btn btn-sm btn-outline-warning" asp-route-WithAddress="true" asp-route-id="@d.ID">
- <i class="bi bi-eye"></i> 주소 보기 (복호화)
- </a>
- }
- else
- {
- <a class="btn btn-sm btn-outline-secondary" asp-route-id="@d.ID">숨기기</a>
- }
- </div>
- <div class="card-body">
- @if (Model.WithAddress)
- {
- <dl class="row mb-0">
- <dt class="col-sm-2">수령인</dt><dd class="col-sm-10">@d.RecipientName</dd>
- <dt class="col-sm-2">연락처</dt><dd class="col-sm-10">@d.Phone</dd>
- <dt class="col-sm-2">우편번호</dt><dd class="col-sm-10">@d.ZipCode</dd>
- <dt class="col-sm-2">주소</dt><dd class="col-sm-10">@d.Address1</dd>
- <dt class="col-sm-2">상세 주소</dt><dd class="col-sm-10">@d.Address2</dd>
- </dl>
- <p class="small text-muted mb-0 mt-2">
- <i class="bi bi-info-circle"></i> 주소 조회는 감사 로그에 기록됩니다 (S6 적용 예정).
- </p>
- }
- else
- {
- <p class="text-muted mb-0">개인정보 보호를 위해 가려져 있습니다. "주소 보기" 클릭 시 AES-GCM 복호화하여 표시합니다.</p>
- }
- </div>
- </div>
- <!-- 배송비 / 관리자 메모 -->
- <div class="card mb-3">
- <div class="card-header"><strong>배송비 · 관리자 메모</strong></div>
- <div class="card-body">
- <form method="post" asp-page-handler="UpdateBilling" asp-route-id="@d.ID" accept-charset="utf-8">
- @Html.AntiForgeryToken()
- <div class="row mb-2">
- <label asp-for="Billing.ShippingFee" class="col-sm-2 col-form-label">배송비</label>
- <div class="col-sm-10">
- <div class="row">
- <div class="col col-md-auto">
- <div class="input-group">
- <input asp-for="Billing.ShippingFee" class="form-control" type="number" min="0" required />
- <span class="input-group-text">원</span>
- </div>
- </div>
- </div>
- <span asp-validation-for="Billing.ShippingFee" class="text-danger"></span>
- </div>
- </div>
- <div class="row mb-2">
- <label asp-for="Billing.AdminMemo" class="col-sm-2 col-form-label">관리자 메모</label>
- <div class="col-sm-10">
- <textarea asp-for="Billing.AdminMemo" class="form-control" rows="3" maxlength="500" placeholder="운영용 내부 메모 (최대 500자)"></textarea>
- <span asp-validation-for="Billing.AdminMemo" class="text-danger"></span>
- </div>
- </div>
- <div class="text-end">
- <button type="submit" class="btn btn-primary">저장</button>
- </div>
- </form>
- </div>
- </div>
- <!-- 송장 등록 -->
- @if (d.Status == ShipmentStatus.Preparing)
- {
- <div class="card mb-3">
- <div class="card-header"><strong>송장 등록</strong></div>
- <div class="card-body">
- <form method="post" asp-page-handler="RegisterTracking" asp-route-id="@d.ID" accept-charset="utf-8">
- @Html.AntiForgeryToken()
- <div class="row g-2 align-items-end">
- <div class="col-md-3">
- <label asp-for="Tracking.Carrier" class="form-label"></label>
- <input asp-for="Tracking.Carrier" class="form-control" placeholder="예) CJ대한통운" />
- </div>
- <div class="col-md-5">
- <label asp-for="Tracking.TrackingNumber" class="form-label"></label>
- <input asp-for="Tracking.TrackingNumber" class="form-control" />
- </div>
- <div class="col-md-3">
- <button type="submit" class="btn btn-primary w-100">송장 등록 + 출고 준비</button>
- </div>
- </div>
- </form>
- </div>
- </div>
- }
- <!-- 상태 전환 버튼 -->
- <div class="card mb-3">
- <div class="card-header"><strong>상태 변경</strong></div>
- <div class="card-body">
- <div class="d-flex gap-2">
- @if (d.Status is ShipmentStatus.Pickup or ShipmentStatus.Preparing)
- {
- <form method="post" asp-page-handler="Transit" asp-route-id="@d.ID" class="d-inline">
- @Html.AntiForgeryToken()
- <button type="submit" class="btn btn-info">배송중 전환</button>
- </form>
- }
- @if (d.Status == ShipmentStatus.InTransit)
- {
- <form method="post" asp-page-handler="Delivered" asp-route-id="@d.ID" class="d-inline">
- @Html.AntiForgeryToken()
- <button type="submit" class="btn btn-success">배송완료 처리</button>
- </form>
- }
- @if (d.Status is not ShipmentStatus.Delivered and not ShipmentStatus.Failed)
- {
- <form method="post" asp-page-handler="Failed" asp-route-id="@d.ID" class="d-inline">
- @Html.AntiForgeryToken()
- <button type="submit" class="btn btn-outline-danger" onclick="return confirm('배송 실패로 표시하시겠습니까?')">배송 실패</button>
- </form>
- }
- </div>
- </div>
- </div>
- <div class="d-flex justify-content-end gap-2">
- <a class="btn btn-secondary" asp-page="/Store/Shipment/Index">목록</a>
- </div>
- }
- </div>
|