site, license plate

This commit is contained in:
Adam 2026-06-27 01:56:58 +02:00
parent ab912a4ab9
commit 0638c89989
7 changed files with 105 additions and 8 deletions

View File

@ -76,6 +76,22 @@ public class OrderDto : MgOrderDto<OrderItemDto, ProductDto>, IOrderDto
[ToonDescription(BusinessRule = "get => GenericAttributes.GetValueOrNull<DateTime>('DateOfReceipt')")]
public DateTime? DateOfReceipt => GenericAttributes.GetValueOrNull<DateTime>(nameof(IOrderDto.DateOfReceipt));
[NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
[ToonDescription(BusinessRule = "get => GenericAttributes single 'LicensePlate' value (raw, NAV mapper normalizes)")]
public string? LicensePlate =>
GenericAttributes.SingleOrDefault(x => x.Key == nameof(IOrderDto.LicensePlate))?.Value;
[NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
[ToonDescription(BusinessRule = "get => deserialize GenericAttributes single 'Site' JSON value to OrderSiteSnapshot")]
public OrderSiteSnapshot? Site
{
get
{
var json = GenericAttributes.SingleOrDefault(x => x.Key == nameof(IOrderDto.Site))?.Value;
return string.IsNullOrWhiteSpace(json) ? null : JsonConvert.DeserializeObject<OrderSiteSnapshot>(json);
}
}
[NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
[ToonDescription(BusinessRule = "get => GenericAttributes.GetValueOrDefault('RevisorId', 0)")]
public int RevisorId => GenericAttributes.GetValueOrDefault(nameof(IOrderDto.RevisorId), 0);
@ -87,7 +103,7 @@ public class OrderDto : MgOrderDto<OrderItemDto, ProductDto>, IOrderDto
[NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
[ToonDescription(BusinessRule = "get => OrderItemDtos.Count > 0 && OrderItemDtos.All(oi => oi.IsAudited)")]
public bool IsAllOrderItemAudited => OrderItemDtos.Count > 0 && OrderItemDtos.All(oi => oi.IsAudited);
[NotColumn, NotMapped, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
[ToonDescription(BusinessRule = "get => OrderItemDtos.All(oi => oi.AverageWeightIsValid)")]
public bool IsAllOrderItemAvgWeightValid => OrderItemDtos.All(oi => oi.AverageWeightIsValid);
@ -106,7 +122,7 @@ public class OrderDto : MgOrderDto<OrderItemDto, ProductDto>, IOrderDto
//if (GenericAttributes.TryGetValue<DateTime>(nameof(IOrderDto.DateOfReceipt), out var value)) return value;
//var dateOfReceipt = GenericAttributes.SingleOrDefault(x => x.Key == nameof(IOrderDto.DateOfReceipt))?.Value ?? string.Empty;
//return dateOfReceipt.IsNullOrWhiteSpace() ? null : CommonHelper.To<DateTime>(dateOfReceipt);
public OrderDto() :base()
public OrderDto() : base()
{ }
public OrderDto(int orderId) : base(orderId)
{ }

View File

@ -0,0 +1,22 @@
namespace FruitBank.Common.Dtos;
/// <summary>
/// Frozen snapshot of the customer site (telephely) selected for an order, stored
/// as JSON in the order's "Site" generic attribute. Shaped to the NAV EKÁER
/// LocationType (UnloadLocation) so the outgoing trade card can use it directly.
/// </summary>
public class OrderSiteSnapshot
{
/// <summary>The customer Address this snapshot was taken from (reference only; data is frozen).</summary>
public int SourceAddressId { get; set; }
public string? Name { get; set; } // LocationType.Name (Company or person name)
public string? VatNumber { get; set; } // LocationType.VatNumber (customer's VAT)
public string? CountryCode { get; set; } // LocationType.Country (ISO, e.g. "HU")
public string? ZipCode { get; set; } // LocationType.ZipCode
public string? City { get; set; } // LocationType.City
public string? Street { get; set; } // LocationType.Street (Address1 [+ Address2])
/// <summary>Pre-formatted one-line display for UI.</summary>
public string? Display { get; set; }
}

View File

@ -16,6 +16,9 @@ public interface IOrderDto : IMgOrderDto<OrderItemDto, ProductDto>, IMeasured, I
int RevisorId { get; }
int MeasurementOwnerId { get; }
string? LicensePlate { get; }
OrderSiteSnapshot? Site { get; }
bool IsComplete { get; }
bool HasMeasuringAccess(int? customerId, bool isRevisorUser = false);

View File

@ -0,0 +1,7 @@
# Loggers
SignalR client-to-server log writer.
## Key Files
- **`SignaRClientLogItemWriter.cs`** — Routes client logs to `{BaseUrl}/loggerHub` via SignalR. Configurable by AppType and LogLevel.

View File

@ -0,0 +1,17 @@
using AyCode.Core.Enums;
using AyCode.Core.Loggers;
using AyCode.Services.Loggers;
namespace FruitBank.Common.Loggers
{
public class SignaRClientLogItemWriter : AcSignaRClientLogItemWriter
{
public SignaRClientLogItemWriter() : this(AppType.Web, LogLevel.Detail, null)
{
}
public SignaRClientLogItemWriter(AppType appType, LogLevel logLevel, string? categoryName = null) : base($"{FruitBankConstClient.BaseUrl}/{FruitBankConstClient.LoggerHubName}", appType, logLevel, categoryName)
{
}
}
}

View File

@ -145,13 +145,14 @@ public sealed class ShippingToEkaerMapper : IShippingToEkaerMapper
Seller = CompanyEndpoint(company),
Buyer = CustomerEndpoint(customer),
LoadLocation = company.Site,
UnloadLocation = BuildCustomerLocation(customer),
// A lerakodási hely az orderre választott telephely (snapshot); ha nincs beállítva,
// fallback a vevő fő címére (a korábbi viselkedés).
UnloadLocation = BuildSiteLocation(order.Site) ?? BuildCustomerLocation(customer),
Lines = lines,
// Kimenőnél NEM töltjük a szállítmányozót: a vevő maga viszi el, és a vevő MÁR a címzett (destinationName) —
// külön fuvarozót nem tartunk nyilván; a carrierText opcionális (a NAV nem követeli) → üresen hagyjuk.
// Kimenőnél nincs külön szállítmányozó: a vevő maga viszi el → carrierText üres (a NAV nem követeli).
CarrierName = null,
// A vonó jármű (rendszám) a customer-hez még nincs bekötve → üresen marad, a felrakodás megkezdéséig pótolandó
// (a validátor warningolja). Amint bekötik, a Vehicle is innen jön.
// A vonó jármű rendszáma az orderre mentett LicensePlate-ből (a customer adja meg, ill. az auto-hozzárendelés).
Vehicle = BuildVehicleFromPlate(order.LicensePlate),
};
}
@ -279,6 +280,37 @@ public sealed class ShippingToEkaerMapper : IShippingToEkaerMapper
};
}
/// <summary>Lerakodási hely az orderre választott telephely-snapshotból (kimenő). A snapshot már a rendelés
/// pillanatában befagyott LocationType-mezőket hordoz (név, adószám, irsz., város, utca, ország).</summary>
private static LocationType? BuildSiteLocation(OrderSiteSnapshot? site)
{
if (site is null) return null;
return new LocationType
{
Name = site.Name,
VatNumber = NormalizeVatNumber(site.VatNumber),
Country = NormalizeCountryCode(site.CountryCode, 2),
ZipCode = NormalizeZipCode(site.ZipCode),
City = site.City,
Street = site.Street,
};
}
/// <summary>A vonó jármű az orderre mentett rendszámból (kimenő). Ország jelenleg belföld (HU); a rendszámot
/// a meglévő NAV-pattern szerint normalizáljuk. Üres/érvénytelen rendszám → nincs jármű (a validátor jelzi).</summary>
private static BasicVehicleDetailType? BuildVehicleFromPlate(string? plateNumber)
{
var plate = NormalizePlateNumber(plateNumber);
if (plate is null) return null;
return new BasicVehicleDetailType
{
PlateNumber = plate,
Country = NormalizeCountryCode(HomeCountry, 3),
};
}
/// <summary>A számla-pénznem → HUF szorzó, NEM dobó változat (a kapu külföldinél küszöb nélkül jelent, ott az érték
/// nem kell): HUF → 1; külföldi + érvényes árfolyam → árfolyam; külföldi + hiányzó árfolyam → 0 (a tétel-érték null lesz).
/// Generáláskor a service config-kapuja (TryConfigError) előbb elvágja a hiányzó-árfolyamos külföldi esetet.</summary>

View File

@ -7,7 +7,7 @@
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
<RunAOTCompilation>true</RunAOTCompilation>
<RunAOTCompilation>false</RunAOTCompilation>
<WasmStripILAfterAOT>true</WasmStripILAfterAOT>
<OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>