using System.Text.Json; using Microsoft.AspNetCore.Mvc; using Nop.Core.Domain.Customers; using Nop.Plugin.Misc.FruitBankPlugin.Models; using Nop.Plugin.Misc.FruitBankPlugin.Services; using Nop.Services.Customers; using Nop.Services.Security; using Nop.Web.Framework; using Nop.Web.Framework.Controllers; using Nop.Web.Framework.Mvc.Filters; namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers; /// /// Inline-save endpoints for the FruitBank "Customer attributes" block on the /// admin customer page (rendered by CustomerCreditWidgetViewComponent). /// Values are stored as store-agnostic (StoreId 0) customer generic attributes /// via . /// [AuthorizeAdmin] [Area(AreaNames.ADMIN)] public class CustomerAttributesController : BasePluginController { private readonly FruitBankAttributeService _attributeService; private readonly ICustomerService _customerService; private readonly IPermissionService _permissionService; public CustomerAttributesController( FruitBankAttributeService attributeService, ICustomerService customerService, IPermissionService permissionService) { _attributeService = attributeService; _customerService = customerService; _permissionService = permissionService; } [HttpPost] [Route("Admin/CustomerAttributes/SetEkaer")] public async Task SetEkaer(int customerId, bool value) { if (!await _permissionService.AuthorizeAsync(StandardPermission.Security.ACCESS_ADMIN_PANEL)) return Json(new { success = false, error = "Access denied" }); var customer = await _customerService.GetCustomerByIdAsync(customerId); if (customer == null) return Json(new { success = false, error = "Customer not found" }); await _attributeService.InsertOrUpdateGenericAttributeAsync( customerId, FruitBankPluginConst.IsEkaerAttribute, value, storeId: 0); return Json(new { success = true, value }); } [HttpPost] [Route("Admin/CustomerAttributes/SaveSites")] public async Task SaveSites(int customerId, int[] siteAddressIds, int defaultAddressId) { if (!await _permissionService.AuthorizeAsync(StandardPermission.Security.ACCESS_ADMIN_PANEL)) return Json(new { success = false, error = "Access denied" }); var customer = await _customerService.GetCustomerByIdAsync(customerId); if (customer == null) return Json(new { success = false, error = "Customer not found" }); // Only keep ids that actually belong to this customer (guards against tampering / stale ids) var validIds = (await _customerService.GetAddressesByCustomerIdAsync(customerId)) .Select(a => a.Id) .ToHashSet(); var selected = (siteAddressIds ?? Array.Empty()) .Where(validIds.Contains) .Distinct() .ToList(); // Default must be one of the selected sites; otherwise no default var effectiveDefault = selected.Contains(defaultAddressId) ? defaultAddressId : 0; var entries = selected .Select(id => new CustomerSiteEntry { AddressId = id, IsDefault = id == effectiveDefault }) .ToList(); var json = JsonSerializer.Serialize(entries); await _attributeService.InsertOrUpdateGenericAttributeAsync( customerId, FruitBankPluginConst.CustomerSitesAttribute, json, storeId: 0); return Json(new { success = true, siteCount = entries.Count, defaultAddressId = effectiveDefault }); } [HttpPost] [Route("Admin/CustomerAttributes/SaveLicensePlates")] public async Task SaveLicensePlates(int customerId, string[] plates, string? defaultPlate) { if (!await _permissionService.AuthorizeAsync(StandardPermission.Security.ACCESS_ADMIN_PANEL)) return Json(new { success = false, error = "Access denied" }); var customer = await _customerService.GetCustomerByIdAsync(customerId); if (customer == null) return Json(new { success = false, error = "Customer not found" }); var cleaned = (plates ?? Array.Empty()) .Select(p => (p ?? string.Empty).Trim().ToUpperInvariant()) .Where(p => p.Length > 0) .Distinct() .ToList(); var def = (defaultPlate ?? string.Empty).Trim().ToUpperInvariant(); var effectiveDefault = cleaned.Contains(def) ? def : null; var entries = cleaned .Select(p => new CustomerLicensePlateEntry { Plate = p, IsDefault = p == effectiveDefault }) .ToList(); var json = JsonSerializer.Serialize(entries); await _attributeService.InsertOrUpdateGenericAttributeAsync( customerId, FruitBankPluginConst.CustomerLicensePlatesAttribute, json, storeId: 0); return Json(new { success = true, plateCount = entries.Count, defaultPlate = effectiveDefault }); } }