Initial commit
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
@model PowderCoating.Application.DTOs.Inventory.CreateInventoryItemDto
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Add Inventory Item";
|
||||
ViewData["PageIcon"] = "bi-box-seam";
|
||||
ViewData["PageHelpTitle"] = "Add Inventory Item";
|
||||
ViewData["PageHelpContent"] = "Add a new material to inventory — powder coatings, consumables, or other shop supplies. Select a category first to auto-generate a SKU. Use AI Lookup to fill in manufacturer details from a part number. Set Reorder Point and Reorder Quantity so the system can alert you when stock runs low.";
|
||||
}
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10">
|
||||
<div class="d-flex justify-content-end align-items-center mb-4">
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-arrow-left me-2"></i>Back to List
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<form asp-action="Create" method="post">
|
||||
<partial name="_ValidationSummary" />
|
||||
|
||||
<!-- Basic Information -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex align-items-center gap-2 border-bottom pb-2 mb-3">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-info-circle me-2 text-primary"></i>Basic Information
|
||||
</h5>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Basic Information"
|
||||
data-bs-content="Name and SKU are required. Category drives how the item is filtered and used in quotes — choosing a Powder Coating category shows the Coating Specifications section. SKU is auto-generated from the category prefix but you can edit it. Description is optional free text for internal notes.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label asp-for="InventoryCategoryId" class="form-label">Category <span class="text-danger">*</span></label>
|
||||
<select asp-for="InventoryCategoryId" class="form-select" id="field-category"
|
||||
asp-items="@ViewBag.Categories"
|
||||
data-coating-map="@ViewBag.CategoryIsCoatingJson">
|
||||
<option value="">Select category</option>
|
||||
</select>
|
||||
<span asp-validation-for="InventoryCategoryId" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label asp-for="SKU" class="form-label">SKU <span class="text-danger">*</span></label>
|
||||
<div class="input-group">
|
||||
<input asp-for="SKU" class="form-control" id="field-sku" placeholder="Select a category to auto-generate" />
|
||||
<button type="button" class="btn btn-outline-secondary" id="btn-regen-sku" title="Regenerate SKU" style="display:none;">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
</div>
|
||||
<span asp-validation-for="SKU" class="text-danger"></span>
|
||||
<div class="form-text">Auto-generated when you pick a category. You can edit it.</div>
|
||||
</div>
|
||||
<div class="col-12" id="wrap-name">
|
||||
<label asp-for="Name" class="form-label">Name <span class="text-danger">*</span></label>
|
||||
<input asp-for="Name" class="form-control" id="field-name" placeholder="Enter product name" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-12" id="wrap-description">
|
||||
<label asp-for="Description" class="form-label">Description</label>
|
||||
<textarea asp-for="Description" class="form-control" id="field-description" rows="2"></textarea>
|
||||
<span asp-validation-for="Description" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product Details -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex align-items-center gap-2 border-bottom pb-2 mb-3">
|
||||
<h5 class="mb-0 d-flex align-items-center">
|
||||
<i class="bi bi-palette me-2 text-primary"></i>Product Details
|
||||
@if ((bool)(ViewBag.AiInventoryAssistEnabled ?? true))
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-outline-primary ms-2" id="ai-lookup-btn">
|
||||
<i class="bi bi-stars me-1"></i>AI Lookup
|
||||
</button>
|
||||
}
|
||||
</h5>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Product Details"
|
||||
data-bs-content="Manufacturer, part number, color name, color code, and finish describe the physical product. AI Lookup can auto-fill these fields from a manufacturer name or part number. Coverage is how many sq ft one pound coats at 1 mil thickness (typical: 30). Transfer Efficiency is what percentage of the powder actually sticks (typical: 60–70%). Both values are used to calculate Powder Needed on quotes and jobs.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div id="ai-lookup-status" class="alert alert-info d-none py-2 small mb-3"></div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label asp-for="Manufacturer" class="form-label">Manufacturer</label>
|
||||
<input asp-for="Manufacturer" class="form-control" id="field-manufacturer" placeholder="e.g., Tiger Drylac, Sherwin-Williams" />
|
||||
<span asp-validation-for="Manufacturer" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label asp-for="ManufacturerPartNumber" class="form-label">Manufacturer Part Number</label>
|
||||
<input asp-for="ManufacturerPartNumber" class="form-control" id="field-partnumber" />
|
||||
<span asp-validation-for="ManufacturerPartNumber" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4" id="wrap-colorname">
|
||||
<label asp-for="ColorName" class="form-label">Color Name</label>
|
||||
<input asp-for="ColorName" class="form-control" id="field-colorname" placeholder="e.g., Illusion Malbec" />
|
||||
<span asp-validation-for="ColorName" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4" id="wrap-colorcode">
|
||||
<label asp-for="ColorCode" class="form-label">Color Code</label>
|
||||
<input asp-for="ColorCode" class="form-control" id="field-colorcode" placeholder="e.g., RAL9005" />
|
||||
<span asp-validation-for="ColorCode" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4" id="wrap-finish">
|
||||
<label asp-for="Finish" class="form-label">Finish</label>
|
||||
<input asp-for="Finish" class="form-control" id="field-finish" placeholder="e.g., Gloss, Matte" />
|
||||
<span asp-validation-for="Finish" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-12" id="wrap-specpageurl">
|
||||
<label asp-for="SpecPageUrl" class="form-label">Product URL</label>
|
||||
<div class="input-group">
|
||||
<input asp-for="SpecPageUrl" class="form-control" id="field-specpageurl" placeholder="https://..." />
|
||||
<a id="field-specpageurl-link" href="#" target="_blank" class="btn btn-outline-secondary d-none" title="Open spec page">
|
||||
<i class="bi bi-box-arrow-up-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
<span asp-validation-for="SpecPageUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-6" id="wrap-coverage">
|
||||
<div class="d-flex align-items-center gap-1 mb-1">
|
||||
<label asp-for="CoverageSqFtPerLb" class="form-label mb-0">Coverage (@ViewBag.CoverageUnit)</label>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Coverage"
|
||||
data-bs-content="How many square feet one pound of this powder covers at a standard film thickness. Industry average is about 30 sq ft/lb. Check the manufacturer's technical data sheet for the exact value. This is used together with Transfer Efficiency to calculate how much powder to order for a job.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<input asp-for="CoverageSqFtPerLb" type="number" step="0.01" min="0" value="30" class="form-control" id="field-coverage" placeholder="30" />
|
||||
<span asp-validation-for="CoverageSqFtPerLb" class="text-danger"></span>
|
||||
<small class="form-text text-muted">Surface area coverage per unit of weight (default: 30)</small>
|
||||
</div>
|
||||
<div class="col-md-6" id="wrap-transfer">
|
||||
<div class="d-flex align-items-center gap-1 mb-1">
|
||||
<label asp-for="TransferEfficiency" class="form-label mb-0">Transfer Efficiency (%)</label>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Transfer Efficiency"
|
||||
data-bs-content="The percentage of powder that actually adheres to the part rather than being lost as overspray. Electrostatic spray guns typically achieve 60–70%. A lower efficiency means you need to order more powder per job. The system uses this value in the Powder Needed calculation on quotes.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<input asp-for="TransferEfficiency" type="number" step="0.01" min="0" max="100" value="65" class="form-control" id="field-transfer" placeholder="65" />
|
||||
<span asp-validation-for="TransferEfficiency" class="text-danger"></span>
|
||||
<small class="form-text text-muted">Percentage of coating that sticks to the part (default: 65%)</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Coating Specs (shown for coating-type items) -->
|
||||
<div class="mb-4" id="coating-specs-section">
|
||||
<div class="d-flex align-items-center gap-2 border-bottom pb-2 mb-3">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-thermometer-half text-primary"></i>Coating Specifications
|
||||
</h5>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Coating Specifications"
|
||||
data-bs-content="Cure Temperature and Cure Time come from the manufacturer's tech data sheet — they tell the oven operator the correct bake profile. Requires Clear Coat flags powders that need a clear top coat for durability or finish. Color Families tag this powder for filtering and matching in the quote wizard (e.g., a teal powder would get both Green and Blue).">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label asp-for="CureTemperatureF" class="form-label">Cure Temperature (°F)</label>
|
||||
<input asp-for="CureTemperatureF" type="number" step="1" min="200" max="500" class="form-control" id="field-curetemp" placeholder="e.g., 375" />
|
||||
<span asp-validation-for="CureTemperatureF" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label asp-for="CureTimeMinutes" class="form-label">Cure Time (minutes)</label>
|
||||
<input asp-for="CureTimeMinutes" type="number" step="1" min="1" max="120" class="form-control" id="field-curetime" placeholder="e.g., 15" />
|
||||
<span asp-validation-for="CureTimeMinutes" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4 d-flex align-items-end">
|
||||
<div class="form-check mb-2">
|
||||
<input asp-for="RequiresClearCoat" class="form-check-input" type="checkbox" id="field-clearcoat" />
|
||||
<label asp-for="RequiresClearCoat" class="form-check-label fw-medium">Requires Clear Coat</label>
|
||||
<div class="form-text">Check if this powder needs a clear top coat</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="d-flex align-items-center gap-1 mb-1">
|
||||
<label class="form-label mb-0">Color Families</label>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Color Families"
|
||||
data-bs-content="Click chips to tag which base color families this powder belongs to. A metallic teal would be tagged Green and Blue; a bronze would be tagged Brown and Gold. These tags drive color-match filtering when customers request a specific color in a quote.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<input asp-for="ColorFamilies" type="hidden" id="field-colorfamilies" />
|
||||
<div class="d-flex flex-wrap gap-2 mt-1" id="color-family-chips">
|
||||
@foreach (var fam in new[] { "Red","Orange","Yellow","Green","Blue","Purple","Pink","Brown","Black","White","Gray","Silver","Gold","Bronze","Copper","Clear" })
|
||||
{
|
||||
<span class="badge color-family-chip" data-family="@fam"
|
||||
style="cursor:pointer;font-size:.8rem;padding:.35em .7em;">@fam</span>
|
||||
}
|
||||
</div>
|
||||
<div class="form-text">Click to toggle which primary color families this powder belongs to (e.g., Teal = Green + Blue)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stock Information -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex align-items-center gap-2 border-bottom pb-2 mb-3">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-boxes me-2 text-primary"></i>Stock Information
|
||||
</h5>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Stock Information"
|
||||
data-bs-content="Quantity on Hand is your current starting stock. Reorder Point is the threshold at which the system shows a Low Stock alert — when quantity drops to this level it's time to reorder. Reorder Quantity is how much to order in one batch. Location is the shelf or bin label so staff can find the material quickly.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label asp-for="QuantityOnHand" class="form-label">Quantity on Hand</label>
|
||||
<input asp-for="QuantityOnHand" type="number" step="0.01" min="0" value="0" class="form-control" />
|
||||
<span asp-validation-for="QuantityOnHand" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label asp-for="UnitOfMeasure" class="form-label">Unit of Measure</label>
|
||||
<select asp-for="UnitOfMeasure" class="form-select" asp-items="@ViewBag.UnitsOfMeasure"></select>
|
||||
<span asp-validation-for="UnitOfMeasure" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label asp-for="Location" class="form-label">Location</label>
|
||||
<input asp-for="Location" class="form-control" placeholder="e.g., Shelf A3" />
|
||||
<span asp-validation-for="Location" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex align-items-center gap-1 mb-1">
|
||||
<label asp-for="ReorderPoint" class="form-label mb-0">Reorder Point</label>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Reorder Point"
|
||||
data-bs-content="When Quantity on Hand falls at or below this number a Low Stock warning appears on the item and in the Inventory summary. Set it high enough to cover your lead time — for example if delivery takes a week and you use 2 lb/day, set the reorder point to at least 14 lbs.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<input asp-for="ReorderPoint" type="number" step="0.01" min="0" value="0" class="form-control" />
|
||||
<span asp-validation-for="ReorderPoint" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex align-items-center gap-1 mb-1">
|
||||
<label asp-for="ReorderQuantity" class="form-label mb-0">Reorder Quantity</label>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Reorder Quantity"
|
||||
data-bs-content="The standard quantity to order when restocking — typically a full case or pallet quantity from your supplier. This is informational and appears as a suggested order amount when the item is flagged as low stock.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<input asp-for="ReorderQuantity" type="number" step="0.01" min="0" value="0" class="form-control" />
|
||||
<span asp-validation-for="ReorderQuantity" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing & Vendor -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex align-items-center gap-2 border-bottom pb-2 mb-3">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-currency-dollar me-2 text-primary"></i>Pricing & Vendor
|
||||
</h5>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Pricing & Vendor"
|
||||
data-bs-content="Unit Cost is what you pay per unit (lb, each, etc.) — this is used to calculate total stock value and feeds into job cost calculations. Primary Vendor links to your supplier record for quick reference and purchase ordering.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label asp-for="UnitCost" class="form-label">Unit Cost</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">$</span>
|
||||
<input asp-for="UnitCost" type="number" step="0.01" min="0" value="0" class="form-control" id="field-unitcost" />
|
||||
</div>
|
||||
<span asp-validation-for="UnitCost" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label asp-for="PrimaryVendorId" class="form-label">Primary Vendor</label>
|
||||
<select asp-for="PrimaryVendorId" class="form-select" id="field-vendor" asp-items="@ViewBag.Vendors"
|
||||
data-quick-add-url="/Vendors/Create" data-quick-add-title="Add New Vendor">
|
||||
<option value="">Select vendor</option>
|
||||
<option value="__new__">+ Add New Vendor…</option>
|
||||
</select>
|
||||
<span asp-validation-for="PrimaryVendorId" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Financial Accounts -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex align-items-center gap-2 border-bottom pb-2 mb-3">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-journal-bookmark me-2 text-primary"></i>Financial Accounts
|
||||
</h5>
|
||||
<a tabindex="0" class="help-icon" role="button"
|
||||
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
|
||||
data-bs-title="Financial Accounts"
|
||||
data-bs-content="Inventory Account is the asset account where the value of this stock sits on the balance sheet (e.g., 1200 Inventory — Powder). COGS Account is debited when this material is consumed on a job (e.g., 5000 Cost of Goods Sold). Leave blank to use the company defaults set in your Chart of Accounts.">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</div>
|
||||
<p class="text-muted small mb-3">Map this item to chart-of-account entries for proper balance sheet and cost tracking. Leave blank to use defaults.</p>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label asp-for="InventoryAccountId" class="form-label"></label>
|
||||
<select asp-for="InventoryAccountId" class="form-select" asp-items="ViewBag.InventoryAccounts"
|
||||
data-quick-add-url="/Accounts/Create?preSubType=4" data-quick-add-title="Add Inventory Account">
|
||||
<option value="">(Default inventory account)</option>
|
||||
<option value="__new__">+ Add New Account…</option>
|
||||
</select>
|
||||
<small class="form-text text-muted">Asset account where inventory value is tracked (e.g., 1200 Inventory - Powder).</small>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label asp-for="CogsAccountId" class="form-label"></label>
|
||||
<select asp-for="CogsAccountId" class="form-select" asp-items="ViewBag.CogsAccounts"
|
||||
data-quick-add-url="/Accounts/Create?preSubType=40" data-quick-add-title="Add COGS Account">
|
||||
<option value="">(Default COGS account)</option>
|
||||
<option value="__new__">+ Add New Account…</option>
|
||||
</select>
|
||||
<small class="form-text text-muted">Expense account debited when this material is consumed on a job.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notes -->
|
||||
<div class="mb-4">
|
||||
<h5 class="border-bottom pb-2 mb-3">
|
||||
<i class="bi bi-journal-text me-2 text-primary"></i>Notes
|
||||
</h5>
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<label asp-for="Notes" class="form-label">Additional Notes</label>
|
||||
<textarea asp-for="Notes" class="form-control" rows="3"></textarea>
|
||||
<span asp-validation-for="Notes" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Form Actions -->
|
||||
<div class="d-flex gap-2 justify-content-end pt-3 border-top">
|
||||
<a asp-action="Index" class="btn btn-outline-secondary px-4">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary px-4">
|
||||
<i class="bi bi-check-circle me-2"></i>Create Item
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
<script>const inventoryFormIsCreate = true;</script>
|
||||
<partial name="_InventoryColorFamilyScripts" />
|
||||
}
|
||||
Reference in New Issue
Block a user