129 lines
5.1 KiB
C#
129 lines
5.1 KiB
C#
using System.Text.Json;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Nop.Core.Domain.Common;
|
|
using Nop.Core.Domain.Customers;
|
|
using Nop.Plugin.Misc.FruitBankPlugin.Models;
|
|
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
|
using Nop.Services.Customers;
|
|
using Nop.Web.Areas.Admin.Models.Customers;
|
|
using Nop.Web.Framework.Components;
|
|
|
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Components;
|
|
|
|
[ViewComponent(Name = "CustomerCreditWidget")]
|
|
public class CustomerCreditWidgetViewComponent : NopViewComponent
|
|
{
|
|
private readonly ICustomerCreditService _customerCreditService;
|
|
private readonly FruitBankAttributeService _attributeService;
|
|
private readonly ICustomerService _customerService;
|
|
|
|
public CustomerCreditWidgetViewComponent(
|
|
ICustomerCreditService customerCreditService,
|
|
FruitBankAttributeService attributeService,
|
|
ICustomerService customerService)
|
|
{
|
|
_customerCreditService = customerCreditService;
|
|
_attributeService = attributeService;
|
|
_customerService = customerService;
|
|
}
|
|
|
|
public async Task<IViewComponentResult> InvokeAsync(string widgetZone, object additionalData)
|
|
{
|
|
if (additionalData is not CustomerModel customerModel) return Content("");
|
|
|
|
var customerId = customerModel.Id;
|
|
var credit = await _customerCreditService.GetByCustomerIdAsync(customerId);
|
|
var outstanding = await _customerCreditService.GetOutstandingBalanceAsync(customerId);
|
|
|
|
var isEkaer = await _attributeService
|
|
.GetGenericAttributeValueAsync<Customer, bool>(customerId, FruitBankPluginConst.IsEkaerAttribute, storeId: 0);
|
|
|
|
var model = new CustomerCreditWidgetModel
|
|
{
|
|
CustomerId = customerId,
|
|
HasCreditLimit = credit != null,
|
|
CreditLimit = credit?.CreditLimit ?? 0m,
|
|
OutstandingBalance = outstanding,
|
|
RemainingCredit = credit != null ? credit.CreditLimit - outstanding : (decimal?)null,
|
|
Comment = credit?.Comment,
|
|
IsEkaer = isEkaer
|
|
};
|
|
|
|
await PopulateSitesAsync(model, customerId);
|
|
await PopulatePlatesAsync(model, customerId);
|
|
|
|
return View("~/Plugins/Misc.FruitBankPlugin/Views/CustomerCreditWidget.cshtml", model);
|
|
}
|
|
|
|
private async Task PopulatePlatesAsync(CustomerCreditWidgetModel model, int customerId)
|
|
{
|
|
var json = await _attributeService
|
|
.GetGenericAttributeValueAsync<Customer, string>(customerId, FruitBankPluginConst.CustomerLicensePlatesAttribute, storeId: 0);
|
|
|
|
var entries = ParsePlates(json);
|
|
model.LicensePlates = entries
|
|
.Select(e => new CustomerLicensePlateRow { Plate = e.Plate, IsDefault = e.IsDefault })
|
|
.ToList();
|
|
model.PlateCount = model.LicensePlates.Count;
|
|
model.DefaultPlate = model.LicensePlates.FirstOrDefault(p => p.IsDefault)?.Plate;
|
|
}
|
|
|
|
private static List<CustomerLicensePlateEntry> ParsePlates(string? json)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(json)) return new();
|
|
try { return JsonSerializer.Deserialize<List<CustomerLicensePlateEntry>>(json) ?? new(); }
|
|
catch { return new(); }
|
|
}
|
|
|
|
// Merge the customer's current addresses with the saved site list (orphaned
|
|
// address ids — deleted addresses — are dropped because we iterate addresses).
|
|
private async Task PopulateSitesAsync(CustomerCreditWidgetModel model, int customerId)
|
|
{
|
|
var addresses = await _customerService.GetAddressesByCustomerIdAsync(customerId);
|
|
|
|
var savedJson = await _attributeService
|
|
.GetGenericAttributeValueAsync<Customer, string>(customerId, FruitBankPluginConst.CustomerSitesAttribute, storeId: 0);
|
|
|
|
var saved = ParseSites(savedJson);
|
|
var savedById = saved.ToDictionary(s => s.AddressId);
|
|
|
|
foreach (var addr in addresses)
|
|
{
|
|
savedById.TryGetValue(addr.Id, out var entry);
|
|
model.SiteAddresses.Add(new CustomerSiteAddressRow
|
|
{
|
|
AddressId = addr.Id,
|
|
Display = FormatAddress(addr),
|
|
IsSite = entry != null,
|
|
IsDefault = entry?.IsDefault ?? false
|
|
});
|
|
}
|
|
|
|
var sites = model.SiteAddresses.Where(a => a.IsSite).ToList();
|
|
model.SiteCount = sites.Count;
|
|
model.DefaultSiteDisplay = sites.FirstOrDefault(a => a.IsDefault)?.Display;
|
|
}
|
|
|
|
private static List<CustomerSiteEntry> ParseSites(string? json)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(json)) return new();
|
|
try { return JsonSerializer.Deserialize<List<CustomerSiteEntry>>(json) ?? new(); }
|
|
catch { return new(); }
|
|
}
|
|
|
|
private static string FormatAddress(Address a)
|
|
{
|
|
var name = !string.IsNullOrWhiteSpace(a.Company)
|
|
? a.Company
|
|
: $"{a.FirstName} {a.LastName}".Trim();
|
|
|
|
var locality = $"{a.ZipPostalCode} {a.City}".Trim();
|
|
|
|
var parts = new[] { name, a.Address1, locality }
|
|
.Where(p => !string.IsNullOrWhiteSpace(p));
|
|
|
|
var display = string.Join(", ", parts);
|
|
return string.IsNullOrWhiteSpace(display) ? $"#{a.Id}" : display;
|
|
}
|
|
}
|