Spaces:
Sleeping
Sleeping
| @page | |
| @using BakeryErp.Infrastructure.Database | |
| @using BakeryErp.Infrastructure.Repositories | |
| @model InventoryModel | |
| @{ | |
| ViewData["Title"] = "庫存管理"; | |
| } | |
| <header class="page-header"> | |
| <div> | |
| <p class="eyebrow">庫存管理</p> | |
| <h1>即時庫存與異動審核</h1> | |
| </div> | |
| <a class="button-link" href="/">返回總覽</a> | |
| </header> | |
| @if (!string.IsNullOrWhiteSpace(Model.Message)) | |
| { | |
| <div class="notice success">@Model.Message</div> | |
| } | |
| @if (!string.IsNullOrWhiteSpace(Model.ErrorMessage)) | |
| { | |
| <div class="notice error">@Model.ErrorMessage</div> | |
| } | |
| <section class="metrics compact"> | |
| <article> | |
| <span>庫存品項</span> | |
| <strong>@Model.Report.StockItemCount</strong> | |
| </article> | |
| <article> | |
| <span>低庫存</span> | |
| <strong>@Model.Report.LowStockCount</strong> | |
| </article> | |
| <article> | |
| <span>待審核</span> | |
| <strong>@Model.Report.PendingApprovalCount</strong> | |
| </article> | |
| <article> | |
| <span>已審核異動</span> | |
| <strong>@Model.Report.ApprovedTransactionCount</strong> | |
| </article> | |
| <article> | |
| <span>總庫存數量</span> | |
| <strong>@Model.Report.TotalQuantityOnHand.ToString("N0")</strong> | |
| </article> | |
| </section> | |
| <section class="form-panel"> | |
| <h2>@(Model.Form.Id == Guid.Empty ? "新增庫存異動" : "編輯庫存異動")</h2> | |
| <form method="post" class="data-form"> | |
| <input type="hidden" asp-for="Form.Id" /> | |
| <div class="field"> | |
| <label asp-for="Form.TransactionNumber">異動單號</label> | |
| <input asp-for="Form.TransactionNumber" placeholder="例如 INV-20260525-002" /> | |
| </div> | |
| <div class="field"> | |
| <label asp-for="Form.WarehouseName">倉庫</label> | |
| <input asp-for="Form.WarehouseName" list="warehouseOptions" placeholder="例如 中央廚房主倉" /> | |
| </div> | |
| <div class="field"> | |
| <label asp-for="Form.ItemSku">品項代號</label> | |
| <input asp-for="Form.ItemSku" list="itemSkuOptions" placeholder="例如 RM-FLOUR-001" /> | |
| </div> | |
| <div class="field"> | |
| <label asp-for="Form.ItemName">品項名稱</label> | |
| <input asp-for="Form.ItemName" list="itemNameOptions" placeholder="例如 高筋麵粉" /> | |
| </div> | |
| <div class="field"> | |
| <label asp-for="Form.TransactionType">異動類型</label> | |
| <select asp-for="Form.TransactionType"> | |
| @foreach (var type in Model.TransactionTypeOptions) | |
| { | |
| <option value="@type">@InventoryRepository.GetTransactionTypeName(type)</option> | |
| } | |
| </select> | |
| </div> | |
| <div class="field"> | |
| <label asp-for="Form.Quantity">數量</label> | |
| <input asp-for="Form.Quantity" type="number" step="0.01" /> | |
| </div> | |
| <div class="field"> | |
| <label asp-for="Form.Unit">單位</label> | |
| <input asp-for="Form.Unit" list="unitOptions" placeholder="kg / 個 / 箱" /> | |
| </div> | |
| <div class="field"> | |
| <label asp-for="OccurredDateText">異動日期</label> | |
| <input asp-for="OccurredDateText" type="date" /> | |
| </div> | |
| <div class="field"> | |
| <label asp-for="Form.SourceDocumentNumber">來源單號</label> | |
| <input asp-for="Form.SourceDocumentNumber" placeholder="進貨單 / OCR 單號 / 調撥單" /> | |
| </div> | |
| <div class="field wide"> | |
| <label asp-for="Form.Note">備註</label> | |
| <textarea asp-for="Form.Note" rows="3"></textarea> | |
| </div> | |
| <div class="form-actions"> | |
| <button class="primary-button" type="submit" asp-page-handler="Save">儲存待審核</button> | |
| <a class="secondary-button" href="/Inventory">清空表單</a> | |
| </div> | |
| <datalist id="warehouseOptions"> | |
| @foreach (var warehouse in Model.WarehouseOptions) | |
| { | |
| <option value="@warehouse.Value">@warehouse.Label</option> | |
| } | |
| </datalist> | |
| <datalist id="itemSkuOptions"> | |
| @foreach (var item in Model.ItemOptions) | |
| { | |
| <option value="@item.Sku">@item.Label</option> | |
| } | |
| </datalist> | |
| <datalist id="itemNameOptions"> | |
| @foreach (var item in Model.ItemOptions) | |
| { | |
| <option value="@item.Name">@item.Label</option> | |
| } | |
| </datalist> | |
| <datalist id="unitOptions"> | |
| @foreach (var unit in Model.ItemOptions.Select(item => item.Unit).Distinct()) | |
| { | |
| <option value="@unit"></option> | |
| } | |
| </datalist> | |
| </form> | |
| </section> | |
| <section class="table-panel"> | |
| <div class="section-title"> | |
| <h2>即時庫存清單</h2> | |
| <span>@Model.StockBalances.Count 筆</span> | |
| </div> | |
| <div class="table-wrap"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>狀態</th> | |
| <th>倉庫</th> | |
| <th>品項代號</th> | |
| <th>品項名稱</th> | |
| <th>現有庫存</th> | |
| <th>安全庫存</th> | |
| <th>單位</th> | |
| <th>最後異動</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| @foreach (var stock in Model.StockBalances) | |
| { | |
| var isLowStock = stock.QuantityOnHand <= stock.SafetyStockQuantity; | |
| <tr class="@(isLowStock ? "muted-row" : null)"> | |
| <td> | |
| <span class="badge @(isLowStock ? "warn" : "ok")"> | |
| @(isLowStock ? "低庫存" : "正常") | |
| </span> | |
| </td> | |
| <td>@stock.WarehouseName</td> | |
| <td>@stock.ItemSku</td> | |
| <td>@stock.ItemName</td> | |
| <td>@stock.QuantityOnHand.ToString("N2")</td> | |
| <td>@stock.SafetyStockQuantity.ToString("N2")</td> | |
| <td>@stock.Unit</td> | |
| <td>@stock.LastTransactionAt.ToLocalTime().ToString("yyyy-MM-dd HH:mm")</td> | |
| </tr> | |
| } | |
| </tbody> | |
| </table> | |
| </div> | |
| </section> | |
| <section class="table-panel"> | |
| <div class="section-title"> | |
| <h2>庫存異動清單</h2> | |
| <span>@Model.Transactions.Count 筆</span> | |
| </div> | |
| <div class="table-wrap"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>狀態</th> | |
| <th>異動單號</th> | |
| <th>類型</th> | |
| <th>倉庫</th> | |
| <th>品項</th> | |
| <th>數量</th> | |
| <th>日期</th> | |
| <th>操作</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| @foreach (var transaction in Model.Transactions) | |
| { | |
| <tr> | |
| <td> | |
| <span class="badge @Model.GetStatusClass(transaction.Status)"> | |
| @InventoryRepository.GetStatusName(transaction.Status) | |
| </span> | |
| </td> | |
| <td>@transaction.TransactionNumber</td> | |
| <td>@InventoryRepository.GetTransactionTypeName(transaction.TransactionType)</td> | |
| <td>@transaction.WarehouseName</td> | |
| <td>@transaction.ItemName</td> | |
| <td>@transaction.Quantity.ToString("N2") @transaction.Unit</td> | |
| <td>@transaction.OccurredAt.ToLocalTime().ToString("yyyy-MM-dd")</td> | |
| <td class="row-actions"> | |
| @if (transaction.Status != LocalInventoryTransactionStatus.Approved) | |
| { | |
| <a class="small-link" href="/Inventory?editId=@transaction.Id">編輯</a> | |
| <form method="post"> | |
| <input type="hidden" name="id" value="@transaction.Id" /> | |
| <button class="text-button" type="submit" asp-page-handler="Approve">審核入帳</button> | |
| </form> | |
| <form method="post"> | |
| <input type="hidden" name="id" value="@transaction.Id" /> | |
| <button class="text-button" type="submit" asp-page-handler="Cancel">取消</button> | |
| </form> | |
| } | |
| else | |
| { | |
| <span class="muted-text">已入帳</span> | |
| } | |
| </td> | |
| </tr> | |
| } | |
| </tbody> | |
| </table> | |
| </div> | |
| </section> | |