using FruitBank.Common.Enums; using LinqToDB; using Microsoft.AspNetCore.Mvc; using Nop.Core; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Services.Customers; using Nop.Web.Framework.Controllers; namespace Nop.Plugin.Misc.FruitBankPlugin.Controllers; public class CustomerPreorderController : BasePluginController { private readonly IWorkContext _workContext; private readonly ICustomerService _customerService; private readonly PreorderDbContext _preorderDbContext; private readonly FruitBankDbContext _dbContext; public CustomerPreorderController( IWorkContext workContext, ICustomerService customerService, PreorderDbContext preorderDbContext, FruitBankDbContext dbContext) { _workContext = workContext; _customerService = customerService; _preorderDbContext = preorderDbContext; _dbContext = dbContext; } [HttpGet] public async Task List() { var customer = await _workContext.GetCurrentCustomerAsync(); if (await _customerService.IsGuestAsync(customer)) return Challenge(); // Load this customer's preorders, newest first var preorders = await _preorderDbContext.Preorders .GetAllByCustomerIdAsync(customer.Id, false) .OrderByDescending(p => p.CreatedOnUtc) .ToListAsync(); var allItems = await _preorderDbContext.PreorderItems.GetAll() .Where(i => preorders.Select(p => p.Id).Contains(i.PreorderId)) .ToListAsync(); // Resolve product names var productIds = allItems.Select(i => i.ProductId).Distinct().ToList(); var productDtos = await _dbContext.ProductDtos .GetAll(false) .Where(p => productIds.Contains(p.Id)) .ToListAsync(); var productById = productDtos.ToDictionary(p => p.Id); var rows = preorders.Select(p => { var items = allItems.Where(i => i.PreorderId == p.Id).ToList(); // Derive status from quantities (enum reads unreliable in LinqToDB) var allFulfilled = items.Any() && items.All(i => i.FulfilledQuantity >= i.RequestedQuantity); var anyFulfilled = items.Any(i => i.FulfilledQuantity > 0); var allDropped = items.Any() && items.All(i => i.FulfilledQuantity == 0 && i.RequestedQuantity > 0); var effectiveStatus = (int)p.Status != 0 ? p.Status : allFulfilled ? PreorderStatus.Confirmed : anyFulfilled ? PreorderStatus.PartiallyFulfilled : PreorderStatus.Pending; return new CustomerPreorderRow { PreorderId = p.Id, OrderId = p.OrderId, DateOfReceipt = p.DateOfReceipt, CreatedOnUtc = p.CreatedOnUtc, Status = effectiveStatus, CustomerNote = p.CustomerNote, Items = items.Select(i => { productById.TryGetValue(i.ProductId, out var dto); return new CustomerPreorderItemRow { ProductName = dto?.Name ?? $"Termék #{i.ProductId}", IsMeasurable = dto?.IsMeasurable ?? false, RequestedQuantity = i.RequestedQuantity, FulfilledQuantity = i.FulfilledQuantity, UnitPriceInclTax = i.UnitPriceInclTax, Status = i.FulfilledQuantity == 0 ? PreorderItemStatus.Pending : i.FulfilledQuantity >= i.RequestedQuantity ? PreorderItemStatus.Fulfilled : PreorderItemStatus.PartiallyFulfilled }; }).ToList() }; }).ToList(); return View("~/Plugins/Misc.FruitBankPlugin/Views/CustomerPreorder/List.cshtml", rows); } // ── Inner models ────────────────────────────────────────────────────────── public class CustomerPreorderRow { public int PreorderId { get; set; } public int? OrderId { get; set; } public DateTime DateOfReceipt { get; set; } public DateTime CreatedOnUtc { get; set; } public PreorderStatus Status { get; set; } public string? CustomerNote { get; set; } public List Items { get; set; } = new(); } public class CustomerPreorderItemRow { public string ProductName { get; set; } = string.Empty; public bool IsMeasurable { get; set; } public int RequestedQuantity { get; set; } public int FulfilledQuantity { get; set; } public decimal UnitPriceInclTax { get; set; } public PreorderItemStatus Status { get; set; } } }