diff --git a/.gitignore b/.gitignore index dd8857c..374e7b1 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,6 @@ publish/ appsettings.Development.json scripts/.env -scripts/.venv \ No newline at end of file +scripts/.venv + +ryan.migrations \ No newline at end of file diff --git a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/ConfigureLocation.razor b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/ConfigureLocation.razor index 7cea837..215697e 100644 --- a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/ConfigureLocation.razor +++ b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/ConfigureLocation.razor @@ -16,6 +16,7 @@ @inject IVendorService VendorService @inject ILocationService LocationService @inject IUnitService UnitService +@inject StorageLocationService StorageLocService @inject IUserContextService UserCtx @inject NavigationManager Nav @inject IConfiguration Config @@ -47,7 +48,7 @@ Back
-

Configure Restaurant

+

Configure Location

@_location.Name · @_location.City, @_location.State
@@ -191,6 +192,103 @@ } + + +
+
+
Storage Locations
+ +
+ +
+ @if (!_storageLocations.Any()) + { +
+ + No storage locations assigned yet. Add one to get started. +
+ } + else + { + + + + + + + + + @foreach (var loc in _storageLocations) + { + + + + + } + +
Name
+ @if (_editingStorageLocationId == loc.Id) + { + + } + else + { + @loc.Name + } + + @if (_editingStorageLocationId == loc.Id) + { + + + } + else + { + + + } +
+ @if (!string.IsNullOrEmpty(_storageLocationDeleteError)) + { +
+ @_storageLocationDeleteError +
+ } + } +
+ + @if (_storageLocations.Any()) + { + + } +
} @@ -366,6 +464,40 @@ } +@if (_showAddStorageLocationModal) +{ + +} + @code { [Parameter] public int LocationId { get; set; } @@ -373,12 +505,22 @@ private List _locationVendors = new(); private List _locationUnits = new(); private List _availableUnitsToAdd = new(); + private List _storageLocations = new(); private bool _hydrated; private bool _showAddVendorModal; private bool _creatingVendor; private bool _showAddUnitModal; private bool _addingUnit; + + // Storage Locations + private bool _showAddStorageLocationModal; + private bool _addingStorageLocation; + private string _newStorageLocationName = ""; + private bool _savingStorageLocation; + private int? _editingStorageLocationId; + private string _editingStorageLocationName = ""; + private string? _storageLocationDeleteError; private int _selectedUnitId; private Vendor _newVendor = new(); @@ -424,6 +566,7 @@ { _locationVendors = await VendorService.GetVendorsByLocationAsync(LocationId); _locationUnits = await UnitService.GetByLocationAsync(LocationId); + _storageLocations = await StorageLocService.GetByLocationAsync(LocationId); } _hydrated = true; @@ -597,4 +740,101 @@ _locationUnits = await UnitService.GetByLocationAsync(LocationId); StateHasChanged(); } + + private void OpenAddStorageLocationModal() + { + _newStorageLocationName = ""; + _storageLocationDeleteError = null; + _showAddStorageLocationModal = true; + } + + private void CloseAddStorageLocationModal() + { + _showAddStorageLocationModal = false; + _newStorageLocationName = ""; + } + + private async Task CreateStorageLocation() + { + if (string.IsNullOrWhiteSpace(_newStorageLocationName)) return; + + _savingStorageLocation = true; + try + { + await StorageLocService.AddAsync(new StorageLocation + { + Name = _newStorageLocationName.Trim(), + LocationId = LocationId + }); + _storageLocations = await StorageLocService.GetByLocationAsync(LocationId); + CloseAddStorageLocationModal(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Failed to create storage location: {ex}"); + } + finally + { + _savingStorageLocation = false; + } + } + + private void StartEditStorageLocation(StorageLocation loc) + { + _editingStorageLocationId = loc.Id; + _editingStorageLocationName = loc.Name ?? ""; + _storageLocationDeleteError = null; + } + + private void CancelStorageLocationEdit() + { + _editingStorageLocationId = null; + _editingStorageLocationName = ""; + } + + private async Task SaveStorageLocationEdit() + { + if (_editingStorageLocationId is null || string.IsNullOrWhiteSpace(_editingStorageLocationName)) return; + + _savingStorageLocation = true; + try + { + var entity = _storageLocations.FirstOrDefault(l => l.Id == _editingStorageLocationId); + if (entity is not null) + { + entity.Name = _editingStorageLocationName.Trim(); + await StorageLocService.UpdateAsync(entity); + _storageLocations = await StorageLocService.GetByLocationAsync(LocationId); + } + CancelStorageLocationEdit(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Failed to update storage location: {ex}"); + } + finally + { + _savingStorageLocation = false; + } + } + + private async Task DeleteStorageLocation(int id) + { + _storageLocationDeleteError = null; + try + { + var inUse = await StorageLocService.IsInUseAsync(id); + if (inUse) + { + _storageLocationDeleteError = "This location is assigned to one or more ingredients. Reassign them first."; + return; + } + await StorageLocService.DeleteAsync(id); + _storageLocations = await StorageLocService.GetByLocationAsync(LocationId); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Failed to delete storage location: {ex}"); + } + } } diff --git a/CulinaryCommandApp/Data/AppDbContext.cs b/CulinaryCommandApp/Data/AppDbContext.cs index c151fd4..9dae148 100644 --- a/CulinaryCommandApp/Data/AppDbContext.cs +++ b/CulinaryCommandApp/Data/AppDbContext.cs @@ -4,6 +4,7 @@ using CulinaryCommandApp.Recipe.Entities; using PO = CulinaryCommand.PurchaseOrder.Entities; using V = CulinaryCommand.Vendor.Entities; +using CulinaryCommand.Models; namespace CulinaryCommand.Data @@ -23,6 +24,7 @@ public AppDbContext(DbContextOptions options) public DbSet TaskListItems => Set(); public DbSet Companies => Set(); public DbSet Ingredients => Set(); + public DbSet StorageLocations => Set(); public DbSet Recipes => Set(); public DbSet RecipeIngredients => Set(); public DbSet RecipeSteps => Set(); diff --git a/CulinaryCommandApp/Data/Enums/Category.cs b/CulinaryCommandApp/Data/Enums/Category.cs index 4fd595a..3c67d50 100644 --- a/CulinaryCommandApp/Data/Enums/Category.cs +++ b/CulinaryCommandApp/Data/Enums/Category.cs @@ -9,11 +9,21 @@ namespace CulinaryCommandApp.Data.Enums public class Category { public const string Produce = "Produce"; - public const string Dairy = "Dairy"; - public const string Meat = "Meat"; + public const string DairyEggs = "Dairy & Eggs"; + public const string Cheese = "Cheese"; + public const string MeatPoultry = "Meat & Poultry"; + public const string Seafood = "Seafood"; + public const string Bakery = "Bakery"; + public const string PastaGrains = "Pasta & Grains"; public const string DryGoods = "Dry Goods"; - public const string Beverages = "Beverages"; - public const string Condiments = "Condiments"; public const string Spices = "Spices"; + public const string Condiments = "Condiments"; + public const string SyrupsMixes = "Syrups & Mixes"; + public const string Desserts = "Desserts"; + public const string Beer = "Beer"; + public const string Wine = "Wine"; + public const string Spirits = "Spirits"; + public const string Beverages = "Beverages"; + public const string Prepared = "Prepared"; } } \ No newline at end of file diff --git a/CulinaryCommandApp/Inventory/DTOs/CreateIngredientDTO.cs b/CulinaryCommandApp/Inventory/DTOs/CreateIngredientDTO.cs index 4443575..8281386 100644 --- a/CulinaryCommandApp/Inventory/DTOs/CreateIngredientDTO.cs +++ b/CulinaryCommandApp/Inventory/DTOs/CreateIngredientDTO.cs @@ -16,5 +16,7 @@ public class CreateIngredientDTO [Range(1, int.MaxValue, ErrorMessage = "LocationId must be a positive integer.")] public int LocationId { get; set; } public int? VendorId { get; set; } + public int? StorageLocationId { get; set; } + public string? StorageLocationName { get; set; } } -} \ No newline at end of file +} diff --git a/CulinaryCommandApp/Inventory/DTOs/InventoryItemDTO.cs b/CulinaryCommandApp/Inventory/DTOs/InventoryItemDTO.cs index a15276f..fdeab55 100644 --- a/CulinaryCommandApp/Inventory/DTOs/InventoryItemDTO.cs +++ b/CulinaryCommandApp/Inventory/DTOs/InventoryItemDTO.cs @@ -20,5 +20,8 @@ public class InventoryItemDTO public int? VendorId { get; set; } public string? VendorName { get; set; } public string? VendorLogoUrl { get; set; } + + public int? StorageLocationId { get; set; } + public string? StorageLocationName { get; set; } } } diff --git a/CulinaryCommandApp/Inventory/Entities/Ingredient.cs b/CulinaryCommandApp/Inventory/Entities/Ingredient.cs index a58d097..fa383b1 100644 --- a/CulinaryCommandApp/Inventory/Entities/Ingredient.cs +++ b/CulinaryCommandApp/Inventory/Entities/Ingredient.cs @@ -5,15 +5,20 @@ namespace CulinaryCommandApp.Inventory.Entities { public class Ingredient { - public int Id {get; set;} + public int Id { get; set; } // display name of the ingredient (ex: "flour", "eggs") public string Name { get; set; } = string.Empty; + // fk to the location this ingredient belongs to public int LocationId { get; set; } public Location? Location { get; set; } + // optional fk to the storage location (sub-location) for this ingredient + public int? StorageLocationId { get; set; } + public StorageLocation? StorageLocation { get; set; } + // optional fk to the vendor that supplies this ingredient public int? VendorId { get; set; } public CulinaryCommand.Vendor.Entities.Vendor? Vendor { get; set; } diff --git a/CulinaryCommandApp/Inventory/Entities/StorageLocation.cs b/CulinaryCommandApp/Inventory/Entities/StorageLocation.cs new file mode 100644 index 0000000..b44d4fd --- /dev/null +++ b/CulinaryCommandApp/Inventory/Entities/StorageLocation.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using CulinaryCommandApp.Inventory.DTOs; + +namespace CulinaryCommandApp.Inventory.Entities +{ + public class StorageLocation + { + public int Id { get; set; } + public int LocationId { get; set; } + public string Name { get; set; } = string.Empty; + public List InventoryItems { get; set; } = new(); + } +} diff --git a/CulinaryCommandApp/Inventory/Pages/Inventory/InventoryCatalog.razor b/CulinaryCommandApp/Inventory/Pages/Inventory/InventoryCatalog.razor index 6e02cab..99a026a 100644 --- a/CulinaryCommandApp/Inventory/Pages/Inventory/InventoryCatalog.razor +++ b/CulinaryCommandApp/Inventory/Pages/Inventory/InventoryCatalog.razor @@ -13,8 +13,10 @@ @inject IUnitService UnitService @inject LocationState LocationState @inject EnumService EnumService +@inject StorageLocationService StorageLocService @inject IUserContextService UserCtx @inject NavigationManager Nav +@inject IJSRuntime JS
@if (!_ready) @@ -29,154 +31,197 @@ } else { -
-
-

Inventory Catalog

-

@(LocationState.CurrentLocation is not null ? $"{LocationState.CurrentLocation.Name} — ingredient catalog" : "Manage your ingredient catalog")

+
+
+

Inventory Catalog

+

@(LocationState.CurrentLocation is not null ? $"{LocationState.CurrentLocation.Name} — ingredient catalog" : "Manage your ingredient catalog")

+
-
- @if (LocationState.CurrentLocation is null) - { - - } - else - { - -
- -
- -
- + @if (LocationState.CurrentLocation is null) + { + + } + else + { +
+ +
+ +
+ +
+ +
- -
-
-
- -
+
+ +
-
- - - - - - - - - - - - - - - @if (isLoading) - { - - - - } - else if (!pagedItems.Any()) - { - - - - } - else - { - @foreach (var item in pagedItems) - { +
+
- - Item Name CategoryUnitCost/Unit Supplier NotesActions
-
- Loading... -
-
-

No items found

-
+ - - - - - - - - + + + + + + + + - } - } - -
- - -
-
@item.Name
-
SKU: @item.SKU
-
-
- @item.Category - @item.Unit$@item.Price.ToString("F2")@(item.VendorName ?? "—")@(string.IsNullOrWhiteSpace(item.Notes) ? "-" : item.Notes) -
- - -
-
+ + Item Name CategoryUnitSupplier LocationNotes
- -
+
+ } - } @* end @if (LocationState.CurrentLocation is not null) *@ + } @* end @if (LocationState.CurrentLocation is not null) *@ } @* end else (_allowed) *@
+@if (showStorageLocationModal) +{ + + +} + @if (showModal) { @@ -198,15 +243,38 @@
-
- - +
+
+
+ + +
+
+
+
+ +
+ + +
+
+
@@ -263,8 +331,35 @@ private List pageButtons = new(); private HashSet selectedIds = new(); private List categories = new(); + private List storageLocations = new(); + + private int? _openMenuId = null; + private double _menuX = 0; + private double _menuY = 0; + + private async Task ToggleMenu(int id, MouseEventArgs e) + { + if (_openMenuId == id) + { + _openMenuId = null; + return; + } + _openMenuId = id; + // Clamp to viewport so the dialog never clips off-screen + var dialogWidth = 190; + var dialogHeight = 110; + var viewportWidth = await JS.InvokeAsync("eval", "window.innerWidth"); + var viewportHeight = await JS.InvokeAsync("eval", "window.innerHeight"); + _menuX = Math.Min(e.ClientX - dialogWidth, viewportWidth - dialogWidth - 8); + _menuY = Math.Min(e.ClientY, viewportHeight - dialogHeight - 8); + } + + private void CloseMenu() => _openMenuId = null; private bool showModal = false; + private bool showStorageLocationModal = false; + private string newStorageLocationName = ""; + private bool _savingStorageLocation = false; private bool _saving = false; private bool _ready = false; private bool _allowed = false; @@ -302,12 +397,15 @@ private void OnLocationChanged() { - _ = InvokeAsync(async () => { - try { + _ = InvokeAsync(async () => + { + try + { await LoadCatalogData(); StateHasChanged(); } - catch (Exception){ + catch (Exception) + { // add some logging later } }); @@ -329,6 +427,7 @@ { itemCatalog = new(); categories = EnumService.GetCategories(); + storageLocations = new List(); _units = await UnitService.GetAllAsync(); FilterItems(); isLoading = false; @@ -345,9 +444,17 @@ .OrderBy(c => c) .ToList(); - _units = await UnitService.GetByLocationAsync(locId.Value); - if (!_units.Any()) - _units = await UnitService.GetAllAsync(); + var locationUnits = await UnitService.GetByLocationAsync(locId.Value); + + var allUnits = await UnitService.GetAllAsync(); + _units = locationUnits + .Union(allUnits) + .DistinctBy(u => u.Id) // requires .NET 6+ + .OrderBy(u => u.Name) + .ToList(); + + var storageLocs = await StorageLocService.GetByLocationAsync(locId.Value); + storageLocations = storageLocs?.Select(sl => sl.Name ?? string.Empty).ToList() ?? new List(); FilterItems(); isLoading = false; @@ -390,21 +497,36 @@ { filteredItems = sortColumn switch { - "name" => sortAscending ? filteredItems.OrderBy(i => i.Name).ToList() : filteredItems.OrderByDescending(i => i.Name).ToList(), - "price" => sortAscending ? filteredItems.OrderBy(i => i.Price).ToList() : filteredItems.OrderByDescending(i => i.Price).ToList(), - "supplier" => sortAscending ? filteredItems.OrderBy(i => i.VendorName).ToList() : filteredItems.OrderByDescending(i => i.VendorName).ToList(), + "name" => sortAscending ? filteredItems.OrderBy(i => i.Name).ToList() : filteredItems.OrderByDescending(i => +i.Name).ToList(), + "price" => sortAscending ? filteredItems.OrderBy(i => i.Price).ToList() : filteredItems.OrderByDescending(i => +i.Price).ToList(), + "supplier" => sortAscending ? filteredItems.OrderBy(i => i.VendorName).ToList() : filteredItems.OrderByDescending(i => +i.VendorName).ToList(), _ => filteredItems }; } private string GetCategoryClass(string? category) => category switch { - "Grains & Pasta" => "category-grains", - "Dairy" => "category-dairy", - "Oils & Sauces" => "category-oils", - "Vegetables" => "category-vegetables", + "Produce" => "category-produce", + "Dairy & Eggs" => "category-dairy-eggs", + "Cheese" => "category-cheese", "Meat & Poultry" => "category-meat", - _ => "category-default" + "Seafood" => "category-seafood", + "Bakery" => "category-bakery", + "Pasta & Grains" => "category-pasta-grains", + "Dry Goods" => "category-dry-goods", + "Spices" => "category-spices", + "Condiments" => "category-condiments", + "Syrups & Mixes" => "category-syrups", + "Desserts" => "category-desserts", + "Beer" => "category-beer", + "Wine" => "category-wine", + "Spirits" => "category-spirits", + "Beverages" => "category-beverages", + "Prepared" => "category-prepared", + _ => "category-default" }; private bool IsPageSelected => pagedItems.Count > 0 && pagedItems.All(i => selectedIds.Contains(i.Id)); @@ -482,6 +604,7 @@ CurrentQuantity = item.CurrentQuantity, ReorderLevel = item.ReorderLevel, LocationId = LocationState.CurrentLocation?.Id ?? 0, + StorageLocationName = item.StorageLocationName, UnitId = item.UnitId, VendorId = item.VendorId }; @@ -490,6 +613,12 @@ private async Task SaveItem() { + if (modalItem.UnitId == 0) + { + @* _saveError = "Please select a unit."; *@ + return; + } + _saving = true; try { @@ -499,6 +628,15 @@ } else { + // Resolve StorageLocationName -> StorageLocationId + int? storageLocId = null; + if (!string.IsNullOrWhiteSpace(modalItem.StorageLocationName)) + { + var allLocs = await StorageLocService.GetByLocationAsync(LocationState.CurrentLocation?.Id ?? 0); + storageLocId = allLocs?.FirstOrDefault(l => + string.Equals(l.Name, modalItem.StorageLocationName, StringComparison.OrdinalIgnoreCase))?.Id; + } + var dto = new InventoryItemDTO { Id = editingItem.Id, @@ -510,6 +648,7 @@ ReorderLevel = modalItem.ReorderLevel, UnitId = modalItem.UnitId, VendorId = modalItem.VendorId, + StorageLocationId = storageLocId, }; await InventoryService.UpdateItemAsync(dto); } @@ -555,4 +694,51 @@ get => selectedCategory; set { selectedCategory = value; FilterItems(); } } -} \ No newline at end of file + + private void OpenStorageLocationModal() + { + showModal = false; + newStorageLocationName = ""; + showStorageLocationModal = true; + } + + private void CloseStorageLocationModal() + { + showStorageLocationModal = false; + newStorageLocationName = ""; + showModal = true; + } + + private async Task SaveStorageLocation() + { + if (string.IsNullOrWhiteSpace(newStorageLocationName)) + return; + + _savingStorageLocation = true; + try + { + var locId = LocationState.CurrentLocation?.Id ?? 0; + var entity = new StorageLocation + { + Name = newStorageLocationName.Trim(), + LocationId = locId + }; + await StorageLocService.AddAsync(entity); + + // Refresh the list and auto-select the new location + var storageLocs = await StorageLocService.GetByLocationAsync(locId); + storageLocations = storageLocs?.Select(sl => sl.Name ?? string.Empty).ToList() ?? new(); + modalItem.StorageLocationName = newStorageLocationName.Trim(); + + CloseStorageLocationModal(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Failed to add storage location: {ex}"); + } + finally + { + _savingStorageLocation = false; + } + } +} diff --git a/CulinaryCommandApp/Inventory/Pages/Inventory/InventoryCatalog.razor.css b/CulinaryCommandApp/Inventory/Pages/Inventory/InventoryCatalog.razor.css index 88288a0..c676ba5 100644 --- a/CulinaryCommandApp/Inventory/Pages/Inventory/InventoryCatalog.razor.css +++ b/CulinaryCommandApp/Inventory/Pages/Inventory/InventoryCatalog.razor.css @@ -28,24 +28,24 @@ } .inventory-header { - background: var(--card); - border-radius: 16px; - padding: 22px 26px; - box-shadow: var(--shadow); - border: 1px solid var(--border); - margin-bottom: 18px; + padding: 8px 0 18px 16px; + border-left: 4px solid #2ca259; + margin-bottom: 20px; } .header-text h1 { font-family: "Space Grotesk", "Source Sans 3", sans-serif; - font-size: 1.6rem; + font-size: 1.5rem; + font-weight: 700; margin: 0 0 4px; + color: #1f2a37; + letter-spacing: -0.01em; } .header-text p { margin: 0; - color: var(--muted); - font-size: 0.95rem; + color: #6b7280; + font-size: 0.88rem; } .inventory-toolbar { @@ -192,7 +192,6 @@ } .inventory-table thead { - background: var(--green); color: var(--ink); } @@ -204,6 +203,7 @@ letter-spacing: 0.02em; text-transform: uppercase; cursor: pointer; + background-color: #2ca259; } .inventory-table thead th i { @@ -230,8 +230,9 @@ text-align: center; } -.actions-col { - width: 100px; +.ellipsis-col { + width: 40px; + text-align: center; } .name-cell .item-name { @@ -245,85 +246,136 @@ margin-top: 2px; } +.unit-col, +.inventory-table thead th.unit-col { + text-align: center; +} + +.unit-badge { + display: inline-block; + padding: 3px 9px; + border-radius: 6px; + border: 1px solid #d1d5db; + font-size: 0.78rem; + font-family: "Source Sans 3", "Segoe UI", sans-serif; + font-weight: 500; + color: #4b5563; + letter-spacing: 0.03em; + background: transparent; +} + .category-pill { display: inline-flex; align-items: center; - padding: 6px 12px; + padding: 4px 10px; border-radius: 999px; font-size: 0.75rem; - font-weight: 700; - background: var(--pill); - color: #1f2a37; -} - -.category-grains { - background: #fbbf24; - color: #78350f; + font-weight: 600; + color: #374151; +} + +.category-produce { background: #dcfce7; } +.category-dairy-eggs { background: #fef9c3; } +.category-cheese { background: #fef3c7; } +.category-meat { background: #ffe4e6; } +.category-seafood { background: #dbeafe; } +.category-bakery { background: #fce7f3; } +.category-pasta-grains { background: #fef08a; } +.category-dry-goods { background: #e5e7eb; } +.category-spices { background: #fde8d8; } +.category-condiments { background: #d1fae5; } +.category-syrups { background: #ede9fe; } +.category-desserts { background: #fce7f3; } +.category-beer { background: #fef3c7; } +.category-wine { background: #f3e8ff; } +.category-spirits { background: #e0e7ff; } +.category-beverages { background: #cffafe; } +.category-prepared { background: #f1f5f9; } +.category-default { background: #e5e7eb; } + +.ellipsis-btn { + width: 28px; + height: 28px; + border-radius: 6px; + border: none; + background: transparent; + color: #9ca3af; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 1rem; + opacity: 0; + transition: opacity 0.15s ease, background 0.15s ease; + cursor: pointer; } -.category-dairy { - background: #a855f7; - color: #fafafa; +.ellipsis-btn:hover { + background: transparent; + color: #1f2a37; } -.category-oils { - background: #eab308; - color: #713f12; +.data-row:hover .ellipsis-btn { + opacity: 1; } -.category-vegetables { - background: #22c55e; - color: #fafafa; +.row-menu-backdrop { + position: fixed; + inset: 0; + z-index: 200; } -.category-meat { - background: #ef4444; - color: #fafafa; +.row-menu-dialog { + position: fixed; + z-index: 201; + background: #ffffff; + border: 1px solid #e5e7eb; + border-radius: 14px; + box-shadow: 0 20px 50px rgba(31, 42, 55, 0.15); + padding: 8px; + min-width: 180px; + display: flex; + flex-direction: column; + gap: 2px; } -.category-default { - background: #6b7280; - color: #ffffff; +.row-menu-label { + font-size: 0.78rem; + font-weight: 600; + color: #9ca3af; + padding: 6px 12px 8px; + letter-spacing: 0.04em; + text-transform: uppercase; + border-bottom: 1px solid #f3f4f6; + margin-bottom: 4px; } -.action-buttons { +.row-menu-action { display: flex; - gap: 8px; -} - -.btn-action { - width: 32px; - height: 32px; - border-radius: 8px; - border: 1px solid #d1d5db; - background: #f3f4f6; - display: inline-flex; align-items: center; - justify-content: center; - color: var(--ink); - transition: all 0.2s ease; - font-weight: 600; + gap: 10px; + padding: 9px 12px; + border: none; + background: transparent; + border-radius: 8px; + font-size: 0.9rem; + color: #1f2a37; + font-family: "Source Sans 3", "Segoe UI", sans-serif; + cursor: pointer; + text-align: left; + transition: background 0.15s ease; + width: 100%; } -.btn-action:hover { - color: var(--ink); - border-color: #9ca3af; - background: #e5e7eb; - transform: translateY(-1px); - box-shadow: 0 6px 12px rgba(107, 114, 128, 0.2); +.row-menu-action:hover { + background: #f9fafb; } -.btn-action.delete { - background: #ef4444; - border-color: #ef4444; - color: var(--ink); +.row-menu-action.delete { + color: #dc2626; } -.btn-action.delete:hover { - color: var(--ink); - border-color: #dc2626; - background: #dc2626; - box-shadow: 0 6px 12px rgba(239, 68, 68, 0.3); +.row-menu-action.delete:hover { + background: #fef2f2; } .table-footer { @@ -355,7 +407,7 @@ display: inline-flex; align-items: center; justify-content: center; - color: var(--green); + color: #2ca259; font-size: 0.85rem; font-weight: 600; transition: all 0.2s ease; @@ -363,15 +415,15 @@ .page-btn:hover, .page-nav:hover { - background: var(--green); + background: #2ca259; color: #ffffff; - border-color: var(--green); + border-color: #2ca259; box-shadow: 0 6px 12px rgba(10, 143, 60, 0.25); } .page-btn.active { - background: var(--green); - border-color: var(--green); + background: #2ca259; + border-color: #2ca259; color: #ffffff; box-shadow: 0 6px 12px rgba(10, 143, 60, 0.25); } diff --git a/CulinaryCommandApp/Inventory/Services/InventoryManagementService.cs b/CulinaryCommandApp/Inventory/Services/InventoryManagementService.cs index d2a4826..ace8bca 100644 --- a/CulinaryCommandApp/Inventory/Services/InventoryManagementService.cs +++ b/CulinaryCommandApp/Inventory/Services/InventoryManagementService.cs @@ -20,6 +20,7 @@ public async Task> GetAllItemsAsync() { return await _db.Ingredients .Include(i => i.Unit) + .Include(i => i.StorageLocation) .Select(ingredient => new InventoryItemDTO { Id = ingredient.Id, @@ -27,13 +28,16 @@ public async Task> GetAllItemsAsync() Category = ingredient.Category, CurrentQuantity = ingredient.StockQuantity, Unit = ingredient.Unit != null ? ingredient.Unit.Name : "count", + UnitId = ingredient.UnitId, SKU = ingredient.Sku ?? "", Price = ingredient.Price ?? 0m, ReorderLevel = ingredient.ReorderLevel, IsLowStock = ingredient.StockQuantity <= ingredient.ReorderLevel && ingredient.StockQuantity > 0, OutOfStockDate = null, LastOrderDate = null, - Notes = ingredient.Notes ?? "" + Notes = ingredient.Notes ?? "", + StorageLocationId = ingredient.StorageLocationId, + StorageLocationName = ingredient.StorageLocation != null ? ingredient.StorageLocation.Name : null }) .ToListAsync(); } @@ -43,6 +47,7 @@ public async Task> GetItemsByLocationAsync(int locationId return await _db.Ingredients .Include(i => i.Unit) .Include(i => i.Vendor) + .Include(i => i.StorageLocation) .Where(i => i.LocationId == locationId) .Select(ingredient => new InventoryItemDTO { @@ -51,6 +56,7 @@ public async Task> GetItemsByLocationAsync(int locationId Category = ingredient.Category, CurrentQuantity = ingredient.StockQuantity, Unit = ingredient.Unit != null ? ingredient.Unit.Name : "count", + UnitId = ingredient.UnitId, SKU = ingredient.Sku ?? "", Price = ingredient.Price ?? 0m, ReorderLevel = ingredient.ReorderLevel, @@ -60,7 +66,9 @@ public async Task> GetItemsByLocationAsync(int locationId Notes = ingredient.Notes ?? "", VendorId = ingredient.VendorId, VendorName = ingredient.Vendor != null ? ingredient.Vendor.Name : null, - VendorLogoUrl = ingredient.Vendor != null ? ingredient.Vendor.LogoUrl : null + VendorLogoUrl = ingredient.Vendor != null ? ingredient.Vendor.LogoUrl : null, + StorageLocationId = ingredient.StorageLocationId, + StorageLocationName = ingredient.StorageLocation != null ? ingredient.StorageLocation.Name : null }) .ToListAsync(); } @@ -75,8 +83,10 @@ public async Task> GetCategoriesByLocationAsync(int locationId) .ToListAsync(); } - public async Task AddItemAsync(CreateIngredientDTO dto) { - var entity = new CulinaryCommandApp.Inventory.Entities.Ingredient { + public async Task AddItemAsync(CreateIngredientDTO dto) + { + var entity = new CulinaryCommandApp.Inventory.Entities.Ingredient + { Name = dto.Name, Sku = dto.SKU, Price = dto.Price, @@ -86,11 +96,13 @@ public async Task AddItemAsync(CreateIngredientDTO dto) { UnitId = dto.UnitId, LocationId = dto.LocationId, VendorId = dto.VendorId, + StorageLocationId = dto.StorageLocationId, CreatedAt = DateTime.UtcNow }; _db.Ingredients.Add(entity); await _db.SaveChangesAsync(); - return new InventoryItemDTO { + return new InventoryItemDTO + { Id = entity.Id, Name = entity.Name, SKU = entity.Sku ?? string.Empty, @@ -102,7 +114,9 @@ public async Task AddItemAsync(CreateIngredientDTO dto) { IsLowStock = entity.StockQuantity <= entity.ReorderLevel, OutOfStockDate = null, LastOrderDate = null, - Notes = entity.Notes ?? string.Empty + Notes = entity.Notes ?? string.Empty, + StorageLocationId = entity.StorageLocationId, + StorageLocationName = entity.StorageLocation != null ? entity.StorageLocation.Name : null }; } @@ -119,7 +133,12 @@ public async Task DeleteItemAsync(int id) public async Task UpdateItemAsync(InventoryItemDTO dto) { - var entity = await _db.Ingredients.FindAsync(dto.Id); + // var entity = await _db.Ingredients.FindAsync(dto.Id); + var entity = await _db.Ingredients + .Include(i => i.Unit) + .Include(i => i.StorageLocation) + .Include(i => i.Vendor) + .FirstOrDefaultAsync(i => i.Id == dto.Id); if (entity == null) return null; @@ -132,6 +151,7 @@ public async Task DeleteItemAsync(int id) entity.Category = dto.Category; entity.UnitId = dto.UnitId; entity.VendorId = dto.VendorId; + entity.StorageLocationId = dto.StorageLocationId; await _db.SaveChangesAsync(); @@ -151,7 +171,9 @@ public async Task DeleteItemAsync(int id) LastOrderDate = null, Notes = entity.Notes ?? string.Empty, VendorId = entity.VendorId, + StorageLocationId = entity.StorageLocationId, + StorageLocationName = entity.StorageLocation != null ? entity.StorageLocation.Name : null }; } - } - } \ No newline at end of file + } +} \ No newline at end of file diff --git a/CulinaryCommandApp/Inventory/Services/StorageLocationService.cs b/CulinaryCommandApp/Inventory/Services/StorageLocationService.cs new file mode 100644 index 0000000..3a12977 --- /dev/null +++ b/CulinaryCommandApp/Inventory/Services/StorageLocationService.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using CulinaryCommandApp.Inventory.Entities; +using CulinaryCommand.Data; + +namespace CulinaryCommandApp.Inventory.Services +{ + public class StorageLocationService + { + private readonly AppDbContext _db; + + public StorageLocationService(AppDbContext db) + { + _db = db; + } + + public async Task> GetByLocationAsync(int locationId) + { + return await _db.StorageLocations + .Where(sl => sl.LocationId == locationId) + .ToListAsync(); + } + + public async Task GetByIdAsync(int id) + { + return await _db.StorageLocations.FindAsync(id); + } + + public async Task AddAsync(StorageLocation storageLocation) + { + _db.StorageLocations.Add(storageLocation); + await _db.SaveChangesAsync(); + return storageLocation; + } + + public async Task UpdateAsync(StorageLocation storageLocation) + { + _db.StorageLocations.Update(storageLocation); + return await _db.SaveChangesAsync() > 0; + } + + public async Task DeleteAsync(int id) + { + var entity = await _db.StorageLocations.FindAsync(id); + if (entity == null) return false; + _db.StorageLocations.Remove(entity); + return await _db.SaveChangesAsync() > 0; + } + + public async Task IsInUseAsync(int id) + { + return await _db.Ingredients.AnyAsync(i => i.StorageLocationId == id); + } + } +} diff --git a/CulinaryCommandApp/Migrations/20260403170549_AddStorageLocationToInventory.Designer.cs b/CulinaryCommandApp/Migrations/20260403170549_AddStorageLocationToInventory.Designer.cs new file mode 100644 index 0000000..0a3dbee --- /dev/null +++ b/CulinaryCommandApp/Migrations/20260403170549_AddStorageLocationToInventory.Designer.cs @@ -0,0 +1,1507 @@ +// +using System; +using CulinaryCommand.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace CulinaryCommand.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260403170549_AddStorageLocationToInventory")] + partial class AddStorageLocationToInventory + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Address") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("City") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CompanyCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("LLCName") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Phone") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("State") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("TaxId") + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ZipCode") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.HasKey("Id"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Feedback", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Device") + .HasColumnType("longtext"); + + b.Property("FeedbackType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Page") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ScreenshotBase64") + .HasColumnType("LONGTEXT"); + + b.Property("SubmittedAt") + .HasColumnType("datetime(6)"); + + b.Property("UserEmail") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserRole") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Feedbacks"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("MarginEdgeKey") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("State") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ZipCode") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.ManagerLocation", b => + { + b.Property("UserId") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.HasKey("UserId", "LocationId"); + + b.HasIndex("LocationId"); + + b.ToTable("ManagerLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("LocationId"); + + b.ToTable("TaskLists"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("TaskListId") + .HasColumnType("int"); + + b.Property("TaskTemplateId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TaskTemplateId"); + + b.HasIndex("TaskListId", "TaskTemplateId") + .IsUnique(); + + b.ToTable("TaskListItems"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("DefaultEstimatedMinutes") + .HasColumnType("int"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Par") + .HasColumnType("int"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("Station") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("IngredientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("RecipeId"); + + b.ToTable("TaskTemplates"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Tasks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Assigner") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DueDate") + .HasColumnType("datetime(6)"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Par") + .HasColumnType("int"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("Station") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("RecipeId"); + + b.HasIndex("UserId"); + + b.ToTable("Tasks"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit(1)"); + + b.Property("InviteToken") + .HasColumnType("longtext"); + + b.Property("InviteTokenExpires") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Password") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Phone") + .HasColumnType("longtext"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("StationsWorked") + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.UserLocation", b => + { + b.Property("UserId") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Role") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.HasKey("UserId", "LocationId"); + + b.HasIndex("LocationId"); + + b.ToTable("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpectedDeliveryDate") + .HasColumnType("datetime(6)"); + + b.Property("IsLocationLocked") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("OrderDate") + .HasColumnType("datetime(6)"); + + b.Property("OrderNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("VendorContact") + .HasColumnType("longtext"); + + b.Property("VendorName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.HasIndex("OrderNumber") + .IsUnique(); + + b.ToTable("PurchaseOrders"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrderLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("PurchaseOrderId") + .HasColumnType("int"); + + b.Property("QuantityOrdered") + .HasPrecision(18, 3) + .HasColumnType("decimal(18,3)"); + + b.Property("QuantityReceived") + .ValueGeneratedOnAdd() + .HasPrecision(18, 3) + .HasColumnType("decimal(18,3)") + .HasDefaultValue(0m); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("PurchaseOrderId"); + + b.HasIndex("UnitId"); + + b.ToTable("PurchaseOrderLines"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.LocationVendor", b => + { + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("LocationId", "VendorId"); + + b.HasIndex("VendorId"); + + b.ToTable("LocationVendors"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("ContactName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("LogoUrl") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Phone") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Website") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Vendors"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.DTOs.InventoryItemDTO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CurrentQuantity") + .HasColumnType("decimal(65,30)"); + + b.Property("IsLowStock") + .HasColumnType("bit(1)"); + + b.Property("LastOrderDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("OutOfStockDate") + .HasColumnType("datetime(6)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("ReorderLevel") + .HasColumnType("decimal(65,30)"); + + b.Property("SKU") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StorageLocationId") + .HasColumnType("int"); + + b.Property("StorageLocationName") + .HasColumnType("longtext"); + + b.Property("Unit") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.Property("VendorLogoUrl") + .HasColumnType("longtext"); + + b.Property("VendorName") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("StorageLocationId"); + + b.ToTable("InventoryItemDTO"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("IngredientId"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("ReorderLevel") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .HasColumnType("longtext"); + + b.Property("StockQuantity") + .HasColumnType("decimal(18, 4)"); + + b.Property("StorageLocationId") + .HasColumnType("int"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("UnitId"); + + b.HasIndex("VendorId"); + + b.ToTable("Ingredients", (string)null); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.InventoryTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StockChange") + .HasColumnType("decimal(65,30)"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("UnitId"); + + b.ToTable("InventoryTransactions"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.LocationUnit", b => + { + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("LocationId", "UnitId"); + + b.HasIndex("UnitId"); + + b.ToTable("LocationUnits"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.StorageLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("StorageLocations"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Unit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Abbreviation") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ConversionFactor") + .HasColumnType("decimal(65,30)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Units"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.Property("RecipeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RecipeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CostPerYield") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsSubRecipe") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("RecipeType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("YieldAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("YieldUnit") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("RecipeId"); + + b.HasIndex("LocationId"); + + b.ToTable("Recipes"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeIngredient", b => + { + b.Property("RecipeIngredientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RecipeIngredientId")); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("PrepNote") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("SubRecipeId") + .HasColumnType("int"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.HasKey("RecipeIngredientId"); + + b.HasIndex("IngredientId"); + + b.HasIndex("RecipeId"); + + b.HasIndex("SubRecipeId"); + + b.HasIndex("UnitId"); + + b.ToTable("RecipeIngredients"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeStep", b => + { + b.Property("StepId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("StepId")); + + b.Property("Duration") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Equipment") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Instructions") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("StepNumber") + .HasColumnType("int"); + + b.Property("Temperature") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("StepId"); + + b.HasIndex("RecipeId"); + + b.ToTable("RecipeSteps"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeSubRecipe", b => + { + b.Property("ParentRecipeId") + .HasColumnType("int"); + + b.Property("ChildRecipeId") + .HasColumnType("int"); + + b.HasKey("ParentRecipeId", "ChildRecipeId"); + + b.HasIndex("ChildRecipeId"); + + b.ToTable("RecipeSubRecipes"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Feedback", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Locations") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.ManagerLocation", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("ManagerLocations") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany("ManagerLocations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskListItem", b => + { + b.HasOne("CulinaryCommand.Data.Entities.TaskList", "TaskList") + .WithMany("Items") + .HasForeignKey("TaskListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.TaskTemplate", "TaskTemplate") + .WithMany("TaskListItems") + .HasForeignKey("TaskTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskList"); + + b.Navigation("TaskTemplate"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId"); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany() + .HasForeignKey("RecipeId"); + + b.Navigation("CreatedByUser"); + + b.Navigation("Ingredient"); + + b.Navigation("Location"); + + b.Navigation("Recipe"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Tasks", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany() + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Ingredient"); + + b.Navigation("Location"); + + b.Navigation("Recipe"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Employees") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.UserLocation", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("UserLocations") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany("UserLocations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrderLine", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany() + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.LocationVendor", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("LocationVendors") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Vendor.Entities.Vendor", "Vendor") + .WithMany("LocationVendors") + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Vendors") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.DTOs.InventoryItemDTO", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.StorageLocation", null) + .WithMany("InventoryItems") + .HasForeignKey("StorageLocationId"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Ingredient", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.StorageLocation", "StorageLocation") + .WithMany() + .HasForeignKey("StorageLocationId"); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("Ingredients") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Vendor.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Location"); + + b.Navigation("StorageLocation"); + + b.Navigation("Unit"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.InventoryTransaction", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("InventoryTransaction") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.LocationUnit", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("LocationUnits") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("LocationUnits") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("Recipes") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeIngredient", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany("RecipeIngredients") + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "SubRecipe") + .WithMany() + .HasForeignKey("SubRecipeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany() + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("Recipe"); + + b.Navigation("SubRecipe"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeStep", b => + { + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany("Steps") + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Recipe"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeSubRecipe", b => + { + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "ChildRecipe") + .WithMany("UsedInRecipes") + .HasForeignKey("ChildRecipeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "ParentRecipe") + .WithMany("SubRecipeUsages") + .HasForeignKey("ParentRecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRecipe"); + + b.Navigation("ParentRecipe"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Company", b => + { + b.Navigation("Employees"); + + b.Navigation("Locations"); + + b.Navigation("Vendors"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.Navigation("LocationUnits"); + + b.Navigation("LocationVendors"); + + b.Navigation("ManagerLocations"); + + b.Navigation("Recipes"); + + b.Navigation("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.Navigation("TaskListItems"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.Navigation("ManagerLocations"); + + b.Navigation("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.Navigation("LocationVendors"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.StorageLocation", b => + { + b.Navigation("InventoryItems"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Unit", b => + { + b.Navigation("Ingredients"); + + b.Navigation("InventoryTransaction"); + + b.Navigation("LocationUnits"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.Navigation("RecipeIngredients"); + + b.Navigation("Steps"); + + b.Navigation("SubRecipeUsages"); + + b.Navigation("UsedInRecipes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/CulinaryCommandApp/Migrations/20260403170549_AddStorageLocationToInventory.cs b/CulinaryCommandApp/Migrations/20260403170549_AddStorageLocationToInventory.cs new file mode 100644 index 0000000..dd3f1e4 --- /dev/null +++ b/CulinaryCommandApp/Migrations/20260403170549_AddStorageLocationToInventory.cs @@ -0,0 +1,232 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace CulinaryCommand.Migrations +{ + /// + public partial class AddStorageLocationToInventory : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "IsActive", + table: "Vendors", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "Users", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "EmailConfirmed", + table: "Users", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "TaskTemplates", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "TaskLists", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsSubRecipe", + table: "Recipes", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsLocationLocked", + table: "PurchaseOrders", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AddColumn( + name: "StorageLocationId", + table: "Ingredients", + type: "int", + nullable: true); + + migrationBuilder.CreateTable( + name: "StorageLocations", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + LocationId = table.Column(type: "int", nullable: false), + Name = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_StorageLocations", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "InventoryItemDTO", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Name = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + SKU = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Category = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CurrentQuantity = table.Column(type: "decimal(65,30)", nullable: false), + Unit = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + UnitId = table.Column(type: "int", nullable: false), + Price = table.Column(type: "decimal(65,30)", nullable: false), + ReorderLevel = table.Column(type: "decimal(65,30)", nullable: false), + IsLowStock = table.Column(type: "bit(1)", nullable: false), + OutOfStockDate = table.Column(type: "datetime(6)", nullable: true), + LastOrderDate = table.Column(type: "datetime(6)", nullable: true), + Notes = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + VendorId = table.Column(type: "int", nullable: true), + VendorName = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + VendorLogoUrl = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + StorageLocationId = table.Column(type: "int", nullable: true), + StorageLocationName = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_InventoryItemDTO", x => x.Id); + table.ForeignKey( + name: "FK_InventoryItemDTO_StorageLocations_StorageLocationId", + column: x => x.StorageLocationId, + principalTable: "StorageLocations", + principalColumn: "Id"); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Ingredients_StorageLocationId", + table: "Ingredients", + column: "StorageLocationId"); + + migrationBuilder.CreateIndex( + name: "IX_InventoryItemDTO_StorageLocationId", + table: "InventoryItemDTO", + column: "StorageLocationId"); + + migrationBuilder.AddForeignKey( + name: "FK_Ingredients_StorageLocations_StorageLocationId", + table: "Ingredients", + column: "StorageLocationId", + principalTable: "StorageLocations", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Ingredients_StorageLocations_StorageLocationId", + table: "Ingredients"); + + migrationBuilder.DropTable( + name: "InventoryItemDTO"); + + migrationBuilder.DropTable( + name: "StorageLocations"); + + migrationBuilder.DropIndex( + name: "IX_Ingredients_StorageLocationId", + table: "Ingredients"); + + migrationBuilder.DropColumn( + name: "StorageLocationId", + table: "Ingredients"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "Vendors", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "Users", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "EmailConfirmed", + table: "Users", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "TaskTemplates", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "TaskLists", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsSubRecipe", + table: "Recipes", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsLocationLocked", + table: "PurchaseOrders", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + } + } +} diff --git a/CulinaryCommandApp/Migrations/20260405213822_FixIngredientUnitRelation.Designer.cs b/CulinaryCommandApp/Migrations/20260405213822_FixIngredientUnitRelation.Designer.cs new file mode 100644 index 0000000..aa0ee31 --- /dev/null +++ b/CulinaryCommandApp/Migrations/20260405213822_FixIngredientUnitRelation.Designer.cs @@ -0,0 +1,1394 @@ +// +using System; +using CulinaryCommand.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace CulinaryCommand.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260405213822_FixIngredientUnitRelation")] + partial class FixIngredientUnitRelation + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Address") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("City") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CompanyCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("LLCName") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Phone") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("State") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("TaxId") + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ZipCode") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.HasKey("Id"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Feedback", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Device") + .HasColumnType("longtext"); + + b.Property("FeedbackType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Page") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ScreenshotBase64") + .HasColumnType("LONGTEXT"); + + b.Property("SubmittedAt") + .HasColumnType("datetime(6)"); + + b.Property("UserEmail") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserRole") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Feedbacks"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("MarginEdgeKey") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("State") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ZipCode") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.ManagerLocation", b => + { + b.Property("UserId") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.HasKey("UserId", "LocationId"); + + b.HasIndex("LocationId"); + + b.ToTable("ManagerLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("LocationId"); + + b.ToTable("TaskLists"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("TaskListId") + .HasColumnType("int"); + + b.Property("TaskTemplateId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TaskTemplateId"); + + b.HasIndex("TaskListId", "TaskTemplateId") + .IsUnique(); + + b.ToTable("TaskListItems"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("DefaultEstimatedMinutes") + .HasColumnType("int"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Par") + .HasColumnType("int"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("Station") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("IngredientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("RecipeId"); + + b.ToTable("TaskTemplates"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Tasks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Assigner") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DueDate") + .HasColumnType("datetime(6)"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Par") + .HasColumnType("int"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("Station") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("RecipeId"); + + b.HasIndex("UserId"); + + b.ToTable("Tasks"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit(1)"); + + b.Property("InviteToken") + .HasColumnType("longtext"); + + b.Property("InviteTokenExpires") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Password") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Phone") + .HasColumnType("longtext"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("StationsWorked") + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.UserLocation", b => + { + b.Property("UserId") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Role") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.HasKey("UserId", "LocationId"); + + b.HasIndex("LocationId"); + + b.ToTable("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpectedDeliveryDate") + .HasColumnType("datetime(6)"); + + b.Property("IsLocationLocked") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("OrderDate") + .HasColumnType("datetime(6)"); + + b.Property("OrderNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("VendorContact") + .HasColumnType("longtext"); + + b.Property("VendorName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.HasIndex("OrderNumber") + .IsUnique(); + + b.ToTable("PurchaseOrders"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrderLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("PurchaseOrderId") + .HasColumnType("int"); + + b.Property("QuantityOrdered") + .HasPrecision(18, 3) + .HasColumnType("decimal(18,3)"); + + b.Property("QuantityReceived") + .ValueGeneratedOnAdd() + .HasPrecision(18, 3) + .HasColumnType("decimal(18,3)") + .HasDefaultValue(0m); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("PurchaseOrderId"); + + b.HasIndex("UnitId"); + + b.ToTable("PurchaseOrderLines"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.LocationVendor", b => + { + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("LocationId", "VendorId"); + + b.HasIndex("VendorId"); + + b.ToTable("LocationVendors"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("ContactName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("LogoUrl") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Phone") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Website") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Vendors"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("IngredientId"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("ReorderLevel") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .HasColumnType("longtext"); + + b.Property("StockQuantity") + .HasColumnType("decimal(18, 4)"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.HasIndex("UnitId"); + + b.HasIndex("VendorId"); + + b.ToTable("Ingredients", (string)null); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.InventoryTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StockChange") + .HasColumnType("decimal(65,30)"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("UnitId"); + + b.ToTable("InventoryTransactions"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.LocationUnit", b => + { + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("LocationId", "UnitId"); + + b.HasIndex("UnitId"); + + b.ToTable("LocationUnits"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Unit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Abbreviation") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ConversionFactor") + .HasColumnType("decimal(65,30)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Units"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.Property("RecipeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RecipeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CostPerYield") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsSubRecipe") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("RecipeType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("YieldAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("YieldUnit") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("RecipeId"); + + b.HasIndex("LocationId"); + + b.ToTable("Recipes"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeIngredient", b => + { + b.Property("RecipeIngredientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RecipeIngredientId")); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("PrepNote") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("SubRecipeId") + .HasColumnType("int"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.HasKey("RecipeIngredientId"); + + b.HasIndex("IngredientId"); + + b.HasIndex("RecipeId"); + + b.HasIndex("SubRecipeId"); + + b.HasIndex("UnitId"); + + b.ToTable("RecipeIngredients"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeStep", b => + { + b.Property("StepId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("StepId")); + + b.Property("Duration") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Equipment") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Instructions") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("StepNumber") + .HasColumnType("int"); + + b.Property("Temperature") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("StepId"); + + b.HasIndex("RecipeId"); + + b.ToTable("RecipeSteps"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeSubRecipe", b => + { + b.Property("ParentRecipeId") + .HasColumnType("int"); + + b.Property("ChildRecipeId") + .HasColumnType("int"); + + b.HasKey("ParentRecipeId", "ChildRecipeId"); + + b.HasIndex("ChildRecipeId"); + + b.ToTable("RecipeSubRecipes"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Feedback", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Locations") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.ManagerLocation", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("ManagerLocations") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany("ManagerLocations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskListItem", b => + { + b.HasOne("CulinaryCommand.Data.Entities.TaskList", "TaskList") + .WithMany("Items") + .HasForeignKey("TaskListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.TaskTemplate", "TaskTemplate") + .WithMany("TaskListItems") + .HasForeignKey("TaskTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskList"); + + b.Navigation("TaskTemplate"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId"); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany() + .HasForeignKey("RecipeId"); + + b.Navigation("CreatedByUser"); + + b.Navigation("Ingredient"); + + b.Navigation("Location"); + + b.Navigation("Recipe"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Tasks", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany() + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Ingredient"); + + b.Navigation("Location"); + + b.Navigation("Recipe"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Employees") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.UserLocation", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("UserLocations") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany("UserLocations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrderLine", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany() + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.LocationVendor", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("LocationVendors") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Vendor.Entities.Vendor", "Vendor") + .WithMany("LocationVendors") + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Vendors") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Ingredient", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("Ingredients") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Vendor.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Location"); + + b.Navigation("Unit"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.InventoryTransaction", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("InventoryTransaction") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.LocationUnit", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("LocationUnits") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("LocationUnits") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("Recipes") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeIngredient", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany("RecipeIngredients") + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "SubRecipe") + .WithMany() + .HasForeignKey("SubRecipeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany() + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("Recipe"); + + b.Navigation("SubRecipe"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeStep", b => + { + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany("Steps") + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Recipe"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeSubRecipe", b => + { + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "ChildRecipe") + .WithMany("UsedInRecipes") + .HasForeignKey("ChildRecipeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "ParentRecipe") + .WithMany("SubRecipeUsages") + .HasForeignKey("ParentRecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRecipe"); + + b.Navigation("ParentRecipe"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Company", b => + { + b.Navigation("Employees"); + + b.Navigation("Locations"); + + b.Navigation("Vendors"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.Navigation("LocationUnits"); + + b.Navigation("LocationVendors"); + + b.Navigation("ManagerLocations"); + + b.Navigation("Recipes"); + + b.Navigation("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.Navigation("TaskListItems"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.Navigation("ManagerLocations"); + + b.Navigation("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.Navigation("LocationVendors"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Unit", b => + { + b.Navigation("Ingredients"); + + b.Navigation("InventoryTransaction"); + + b.Navigation("LocationUnits"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.Navigation("RecipeIngredients"); + + b.Navigation("Steps"); + + b.Navigation("SubRecipeUsages"); + + b.Navigation("UsedInRecipes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/CulinaryCommandApp/Migrations/20260405213822_FixIngredientUnitRelation.cs b/CulinaryCommandApp/Migrations/20260405213822_FixIngredientUnitRelation.cs new file mode 100644 index 0000000..1403267 --- /dev/null +++ b/CulinaryCommandApp/Migrations/20260405213822_FixIngredientUnitRelation.cs @@ -0,0 +1,130 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace CulinaryCommand.Migrations +{ + /// + public partial class FixIngredientUnitRelation : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "IsActive", + table: "Vendors", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "Users", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "EmailConfirmed", + table: "Users", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "TaskTemplates", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "TaskLists", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsSubRecipe", + table: "Recipes", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + + migrationBuilder.AlterColumn( + name: "IsLocationLocked", + table: "PurchaseOrders", + type: "bit(1)", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint(1)"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "IsActive", + table: "Vendors", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "Users", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "EmailConfirmed", + table: "Users", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "TaskTemplates", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsActive", + table: "TaskLists", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsSubRecipe", + table: "Recipes", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + + migrationBuilder.AlterColumn( + name: "IsLocationLocked", + table: "PurchaseOrders", + type: "tinyint(1)", + nullable: false, + oldClrType: typeof(bool), + oldType: "bit(1)"); + } + } +} diff --git a/CulinaryCommandApp/Migrations/20260406031301_RemoveDuplicateUnits.Designer.cs b/CulinaryCommandApp/Migrations/20260406031301_RemoveDuplicateUnits.Designer.cs new file mode 100644 index 0000000..2a99ad9 --- /dev/null +++ b/CulinaryCommandApp/Migrations/20260406031301_RemoveDuplicateUnits.Designer.cs @@ -0,0 +1,1507 @@ +// +using System; +using CulinaryCommand.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace CulinaryCommand.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260406031301_RemoveDuplicateUnits")] + partial class RemoveDuplicateUnits + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Address") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("City") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CompanyCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("LLCName") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Phone") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("State") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("TaxId") + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ZipCode") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.HasKey("Id"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Feedback", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Device") + .HasColumnType("longtext"); + + b.Property("FeedbackType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Page") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ScreenshotBase64") + .HasColumnType("LONGTEXT"); + + b.Property("SubmittedAt") + .HasColumnType("datetime(6)"); + + b.Property("UserEmail") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserRole") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Feedbacks"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("MarginEdgeKey") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("State") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ZipCode") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.ManagerLocation", b => + { + b.Property("UserId") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.HasKey("UserId", "LocationId"); + + b.HasIndex("LocationId"); + + b.ToTable("ManagerLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("LocationId"); + + b.ToTable("TaskLists"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("TaskListId") + .HasColumnType("int"); + + b.Property("TaskTemplateId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TaskTemplateId"); + + b.HasIndex("TaskListId", "TaskTemplateId") + .IsUnique(); + + b.ToTable("TaskListItems"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("DefaultEstimatedMinutes") + .HasColumnType("int"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Par") + .HasColumnType("int"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("Station") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("IngredientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("RecipeId"); + + b.ToTable("TaskTemplates"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Tasks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Assigner") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DueDate") + .HasColumnType("datetime(6)"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Par") + .HasColumnType("int"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("Station") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("LocationId"); + + b.HasIndex("RecipeId"); + + b.HasIndex("UserId"); + + b.ToTable("Tasks"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit(1)"); + + b.Property("InviteToken") + .HasColumnType("longtext"); + + b.Property("InviteTokenExpires") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Password") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Phone") + .HasColumnType("longtext"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("StationsWorked") + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.UserLocation", b => + { + b.Property("UserId") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Role") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.HasKey("UserId", "LocationId"); + + b.HasIndex("LocationId"); + + b.ToTable("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpectedDeliveryDate") + .HasColumnType("datetime(6)"); + + b.Property("IsLocationLocked") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("OrderDate") + .HasColumnType("datetime(6)"); + + b.Property("OrderNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("VendorContact") + .HasColumnType("longtext"); + + b.Property("VendorName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.HasIndex("OrderNumber") + .IsUnique(); + + b.ToTable("PurchaseOrders"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrderLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("PurchaseOrderId") + .HasColumnType("int"); + + b.Property("QuantityOrdered") + .HasPrecision(18, 3) + .HasColumnType("decimal(18,3)"); + + b.Property("QuantityReceived") + .ValueGeneratedOnAdd() + .HasPrecision(18, 3) + .HasColumnType("decimal(18,3)") + .HasDefaultValue(0m); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("PurchaseOrderId"); + + b.HasIndex("UnitId"); + + b.ToTable("PurchaseOrderLines"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.LocationVendor", b => + { + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("LocationId", "VendorId"); + + b.HasIndex("VendorId"); + + b.ToTable("LocationVendors"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CompanyId") + .HasColumnType("int"); + + b.Property("ContactName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("IsActive") + .HasColumnType("bit(1)"); + + b.Property("LogoUrl") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Notes") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Phone") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Website") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Vendors"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.DTOs.InventoryItemDTO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CurrentQuantity") + .HasColumnType("decimal(65,30)"); + + b.Property("IsLowStock") + .HasColumnType("bit(1)"); + + b.Property("LastOrderDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("OutOfStockDate") + .HasColumnType("datetime(6)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("ReorderLevel") + .HasColumnType("decimal(65,30)"); + + b.Property("SKU") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StorageLocationId") + .HasColumnType("int"); + + b.Property("StorageLocationName") + .HasColumnType("longtext"); + + b.Property("Unit") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.Property("VendorLogoUrl") + .HasColumnType("longtext"); + + b.Property("VendorName") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("StorageLocationId"); + + b.ToTable("InventoryItemDTO"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("IngredientId"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("ReorderLevel") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .HasColumnType("longtext"); + + b.Property("StockQuantity") + .HasColumnType("decimal(18, 4)"); + + b.Property("StorageLocationId") + .HasColumnType("int"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("UnitId"); + + b.HasIndex("VendorId"); + + b.ToTable("Ingredients", (string)null); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.InventoryTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StockChange") + .HasColumnType("decimal(65,30)"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IngredientId"); + + b.HasIndex("UnitId"); + + b.ToTable("InventoryTransactions"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.LocationUnit", b => + { + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("LocationId", "UnitId"); + + b.HasIndex("UnitId"); + + b.ToTable("LocationUnits"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.StorageLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("StorageLocations"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Unit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Abbreviation") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ConversionFactor") + .HasColumnType("decimal(65,30)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Units"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.Property("RecipeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RecipeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CostPerYield") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsSubRecipe") + .HasColumnType("bit(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("RecipeType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("YieldAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("YieldUnit") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("RecipeId"); + + b.HasIndex("LocationId"); + + b.ToTable("Recipes"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeIngredient", b => + { + b.Property("RecipeIngredientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RecipeIngredientId")); + + b.Property("IngredientId") + .HasColumnType("int"); + + b.Property("PrepNote") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("SubRecipeId") + .HasColumnType("int"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.HasKey("RecipeIngredientId"); + + b.HasIndex("IngredientId"); + + b.HasIndex("RecipeId"); + + b.HasIndex("SubRecipeId"); + + b.HasIndex("UnitId"); + + b.ToTable("RecipeIngredients"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeStep", b => + { + b.Property("StepId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("StepId")); + + b.Property("Duration") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Equipment") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Instructions") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("RecipeId") + .HasColumnType("int"); + + b.Property("StepNumber") + .HasColumnType("int"); + + b.Property("Temperature") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("StepId"); + + b.HasIndex("RecipeId"); + + b.ToTable("RecipeSteps"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeSubRecipe", b => + { + b.Property("ParentRecipeId") + .HasColumnType("int"); + + b.Property("ChildRecipeId") + .HasColumnType("int"); + + b.HasKey("ParentRecipeId", "ChildRecipeId"); + + b.HasIndex("ChildRecipeId"); + + b.ToTable("RecipeSubRecipes"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Feedback", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Locations") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.ManagerLocation", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("ManagerLocations") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany("ManagerLocations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskListItem", b => + { + b.HasOne("CulinaryCommand.Data.Entities.TaskList", "TaskList") + .WithMany("Items") + .HasForeignKey("TaskListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.TaskTemplate", "TaskTemplate") + .WithMany("TaskListItems") + .HasForeignKey("TaskTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskList"); + + b.Navigation("TaskTemplate"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.HasOne("CulinaryCommand.Data.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId"); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany() + .HasForeignKey("RecipeId"); + + b.Navigation("CreatedByUser"); + + b.Navigation("Ingredient"); + + b.Navigation("Location"); + + b.Navigation("Recipe"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Tasks", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId"); + + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany() + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Ingredient"); + + b.Navigation("Location"); + + b.Navigation("Recipe"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Employees") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.UserLocation", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("UserLocations") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Data.Entities.User", "User") + .WithMany("UserLocations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrderLine", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany() + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.LocationVendor", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("LocationVendors") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Vendor.Entities.Vendor", "Vendor") + .WithMany("LocationVendors") + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Company", "Company") + .WithMany("Vendors") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.DTOs.InventoryItemDTO", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.StorageLocation", null) + .WithMany("InventoryItems") + .HasForeignKey("StorageLocationId"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Ingredient", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.StorageLocation", "StorageLocation") + .WithMany() + .HasForeignKey("StorageLocationId"); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("Ingredients") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommand.Vendor.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Location"); + + b.Navigation("StorageLocation"); + + b.Navigation("Unit"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.InventoryTransaction", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("InventoryTransaction") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.LocationUnit", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("LocationUnits") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany("LocationUnits") + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") + .WithMany("Recipes") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeIngredient", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.Ingredient", "Ingredient") + .WithMany() + .HasForeignKey("IngredientId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany("RecipeIngredients") + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "SubRecipe") + .WithMany() + .HasForeignKey("SubRecipeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") + .WithMany() + .HasForeignKey("UnitId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ingredient"); + + b.Navigation("Recipe"); + + b.Navigation("SubRecipe"); + + b.Navigation("Unit"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeStep", b => + { + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "Recipe") + .WithMany("Steps") + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Recipe"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.RecipeSubRecipe", b => + { + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "ChildRecipe") + .WithMany("UsedInRecipes") + .HasForeignKey("ChildRecipeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("CulinaryCommandApp.Recipe.Entities.Recipe", "ParentRecipe") + .WithMany("SubRecipeUsages") + .HasForeignKey("ParentRecipeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRecipe"); + + b.Navigation("ParentRecipe"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Company", b => + { + b.Navigation("Employees"); + + b.Navigation("Locations"); + + b.Navigation("Vendors"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.Location", b => + { + b.Navigation("LocationUnits"); + + b.Navigation("LocationVendors"); + + b.Navigation("ManagerLocations"); + + b.Navigation("Recipes"); + + b.Navigation("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.TaskTemplate", b => + { + b.Navigation("TaskListItems"); + }); + + modelBuilder.Entity("CulinaryCommand.Data.Entities.User", b => + { + b.Navigation("ManagerLocations"); + + b.Navigation("UserLocations"); + }); + + modelBuilder.Entity("CulinaryCommand.PurchaseOrder.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("CulinaryCommand.Vendor.Entities.Vendor", b => + { + b.Navigation("LocationVendors"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.StorageLocation", b => + { + b.Navigation("InventoryItems"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Unit", b => + { + b.Navigation("Ingredients"); + + b.Navigation("InventoryTransaction"); + + b.Navigation("LocationUnits"); + }); + + modelBuilder.Entity("CulinaryCommandApp.Recipe.Entities.Recipe", b => + { + b.Navigation("RecipeIngredients"); + + b.Navigation("Steps"); + + b.Navigation("SubRecipeUsages"); + + b.Navigation("UsedInRecipes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/CulinaryCommandApp/Migrations/20260406031301_RemoveDuplicateUnits.cs b/CulinaryCommandApp/Migrations/20260406031301_RemoveDuplicateUnits.cs new file mode 100644 index 0000000..5c6a296 --- /dev/null +++ b/CulinaryCommandApp/Migrations/20260406031301_RemoveDuplicateUnits.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace CulinaryCommand.Migrations +{ + /// + public partial class RemoveDuplicateUnits : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "Units", + keyColumn: "Id", + keyValues: new object[] { 1, 2, 3, 4 }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/CulinaryCommandApp/Migrations/AppDbContextModelSnapshot.cs b/CulinaryCommandApp/Migrations/AppDbContextModelSnapshot.cs index 34344bc..f5d4b13 100644 --- a/CulinaryCommandApp/Migrations/AppDbContextModelSnapshot.cs +++ b/CulinaryCommandApp/Migrations/AppDbContextModelSnapshot.cs @@ -209,7 +209,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("varchar(512)"); b.Property("IsActive") - .HasColumnType("tinyint(1)"); + .HasColumnType("bit(1)"); b.Property("LocationId") .HasColumnType("int"); @@ -282,7 +282,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("IsActive") - .HasColumnType("tinyint(1)"); + .HasColumnType("bit(1)"); b.Property("Kind") .HasColumnType("int"); @@ -431,7 +431,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("varchar(256)"); b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); + .HasColumnType("bit(1)"); b.Property("InviteToken") .HasColumnType("longtext"); @@ -440,7 +440,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("datetime(6)"); b.Property("IsActive") - .HasColumnType("tinyint(1)"); + .HasColumnType("bit(1)"); b.Property("Name") .IsRequired() @@ -506,7 +506,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("datetime(6)"); b.Property("IsLocationLocked") - .HasColumnType("tinyint(1)"); + .HasColumnType("bit(1)"); b.Property("LocationId") .HasColumnType("int"); @@ -629,7 +629,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("varchar(256)"); b.Property("IsActive") - .HasColumnType("tinyint(1)"); + .HasColumnType("bit(1)"); b.Property("LogoUrl") .HasMaxLength(512) @@ -662,6 +662,76 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Vendors"); }); + modelBuilder.Entity("CulinaryCommandApp.Inventory.DTOs.InventoryItemDTO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CurrentQuantity") + .HasColumnType("decimal(65,30)"); + + b.Property("IsLowStock") + .HasColumnType("bit(1)"); + + b.Property("LastOrderDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("OutOfStockDate") + .HasColumnType("datetime(6)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("ReorderLevel") + .HasColumnType("decimal(65,30)"); + + b.Property("SKU") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StorageLocationId") + .HasColumnType("int"); + + b.Property("StorageLocationName") + .HasColumnType("longtext"); + + b.Property("Unit") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UnitId") + .HasColumnType("int"); + + b.Property("VendorId") + .HasColumnType("int"); + + b.Property("VendorLogoUrl") + .HasColumnType("longtext"); + + b.Property("VendorName") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("StorageLocationId"); + + b.ToTable("InventoryItemDTO"); + }); + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Ingredient", b => { b.Property("Id") @@ -702,6 +772,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("StockQuantity") .HasColumnType("decimal(18, 4)"); + b.Property("StorageLocationId") + .HasColumnType("int"); + b.Property("UnitId") .HasColumnType("int"); @@ -715,6 +788,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("LocationId"); + b.HasIndex("StorageLocationId"); + b.HasIndex("UnitId"); b.HasIndex("VendorId"); @@ -773,6 +848,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("LocationUnits"); }); + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.StorageLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("StorageLocations"); + }); + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Unit", b => { b.Property("Id") @@ -817,7 +912,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("datetime(6)"); b.Property("IsSubRecipe") - .HasColumnType("tinyint(1)"); + .HasColumnType("bit(1)"); b.Property("LocationId") .HasColumnType("int"); @@ -1179,6 +1274,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Company"); }); + modelBuilder.Entity("CulinaryCommandApp.Inventory.DTOs.InventoryItemDTO", b => + { + b.HasOne("CulinaryCommandApp.Inventory.Entities.StorageLocation", null) + .WithMany("InventoryItems") + .HasForeignKey("StorageLocationId"); + }); + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Ingredient", b => { b.HasOne("CulinaryCommand.Data.Entities.Location", "Location") @@ -1187,6 +1289,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("CulinaryCommandApp.Inventory.Entities.StorageLocation", "StorageLocation") + .WithMany() + .HasForeignKey("StorageLocationId"); + b.HasOne("CulinaryCommandApp.Inventory.Entities.Unit", "Unit") .WithMany("Ingredients") .HasForeignKey("UnitId") @@ -1200,6 +1306,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Location"); + b.Navigation("StorageLocation"); + b.Navigation("Unit"); b.Navigation("Vendor"); @@ -1366,6 +1474,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("LocationVendors"); }); + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.StorageLocation", b => + { + b.Navigation("InventoryItems"); + }); + modelBuilder.Entity("CulinaryCommandApp.Inventory.Entities.Unit", b => { b.Navigation("Ingredients"); diff --git a/CulinaryCommandApp/Program.cs b/CulinaryCommandApp/Program.cs index 3578ae5..e464ed2 100644 --- a/CulinaryCommandApp/Program.cs +++ b/CulinaryCommandApp/Program.cs @@ -23,6 +23,7 @@ using Microsoft.AspNetCore.DataProtection; using CulinaryCommand.Vendor.Services; using System.IO; +using CulinaryCommandApp.Inventory.Entities; @@ -156,6 +157,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/CulinaryCommandApp/Services/EnumService.cs b/CulinaryCommandApp/Services/EnumService.cs index f20f6f0..2596db8 100644 --- a/CulinaryCommandApp/Services/EnumService.cs +++ b/CulinaryCommandApp/Services/EnumService.cs @@ -9,12 +9,22 @@ public List GetCategories() return new List { Category.Produce, - Category.Dairy, - Category.Meat, + Category.DairyEggs, + Category.Cheese, + Category.MeatPoultry, + Category.Seafood, + Category.Bakery, + Category.PastaGrains, Category.DryGoods, - Category.Beverages, + Category.Spices, Category.Condiments, - Category.Spices + Category.SyrupsMixes, + Category.Desserts, + Category.Beer, + Category.Wine, + Category.Spirits, + Category.Beverages, + Category.Prepared }; }