302 lines
9.4 KiB
C#
302 lines
9.4 KiB
C#
|
|
using System.Text.Json;
|
||
|
|
|
||
|
|
namespace PlanTempus.Application.Features.Customers.Components;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Shared catalog for customer detail data.
|
||
|
|
/// Loads from customerDetailMock.json and used by all CustomerDetail* ViewComponents.
|
||
|
|
/// </summary>
|
||
|
|
public static class CustomerDetailCatalog
|
||
|
|
{
|
||
|
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
||
|
|
{
|
||
|
|
PropertyNameCaseInsensitive = true
|
||
|
|
};
|
||
|
|
|
||
|
|
private static Dictionary<string, CustomerDetailRecord>? _customers;
|
||
|
|
|
||
|
|
private static Dictionary<string, CustomerDetailRecord> Customers
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
if (_customers == null)
|
||
|
|
{
|
||
|
|
var jsonPath = Path.Combine(
|
||
|
|
AppDomain.CurrentDomain.BaseDirectory,
|
||
|
|
"Features", "Customers", "Data", "customerDetailMock.json");
|
||
|
|
var json = File.ReadAllText(jsonPath);
|
||
|
|
_customers = JsonSerializer.Deserialize<Dictionary<string, CustomerDetailRecord>>(json, JsonOptions)
|
||
|
|
?? new Dictionary<string, CustomerDetailRecord>();
|
||
|
|
}
|
||
|
|
return _customers;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static CustomerDetailRecord Get(string customerId)
|
||
|
|
{
|
||
|
|
if (!Customers.TryGetValue(customerId, out var customer))
|
||
|
|
throw new KeyNotFoundException($"Customer with id '{customerId}' not found");
|
||
|
|
return customer;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static IEnumerable<string> AllIds => Customers.Keys;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Root record for customer detail
|
||
|
|
public record CustomerDetailRecord
|
||
|
|
{
|
||
|
|
public required string Id { get; init; }
|
||
|
|
public required CustomerHeaderRecord Header { get; init; }
|
||
|
|
public required CustomerContactRecord Contact { get; init; }
|
||
|
|
public List<CustomerProfileItem> Profile { get; init; } = new();
|
||
|
|
public required CustomerMarketingRecord Marketing { get; init; }
|
||
|
|
public required CustomerPaymentRecord Payment { get; init; }
|
||
|
|
public required CustomerPreferencesRecord Preferences { get; init; }
|
||
|
|
public List<CustomerWarningItem> Warnings { get; init; } = new();
|
||
|
|
public required CustomerGroupRecord Group { get; init; }
|
||
|
|
public List<CustomerRelationRecord> Relations { get; init; } = new();
|
||
|
|
public required CustomerStatisticsRecord Statistics { get; init; }
|
||
|
|
public List<CustomerJournalEntry> Journal { get; init; } = new();
|
||
|
|
public required CustomerAppointmentsRecord Appointments { get; init; }
|
||
|
|
public required CustomerGiftcardsRecord Giftcards { get; init; }
|
||
|
|
public List<CustomerActivityEntry> Activity { get; init; } = new();
|
||
|
|
public CustomerEconomyRecord? Economy { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Header section
|
||
|
|
public record CustomerHeaderRecord
|
||
|
|
{
|
||
|
|
public required string Initials { get; init; }
|
||
|
|
public required string Name { get; init; }
|
||
|
|
public required string CustomerSince { get; init; }
|
||
|
|
public List<string> Tags { get; init; } = new();
|
||
|
|
public bool BookingAllowed { get; init; }
|
||
|
|
public required CustomerFactsRecord Facts { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerFactsRecord
|
||
|
|
{
|
||
|
|
public int Visits { get; init; }
|
||
|
|
public int AvgIntervalDays { get; init; }
|
||
|
|
public required string PreferredHairdresser { get; init; }
|
||
|
|
public decimal TotalRevenue { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Contact section
|
||
|
|
public record CustomerContactRecord
|
||
|
|
{
|
||
|
|
public required string Phone { get; init; }
|
||
|
|
public required string Email { get; init; }
|
||
|
|
public required string Address { get; init; }
|
||
|
|
public required string Zip { get; init; }
|
||
|
|
public required string City { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Profile item (flexible)
|
||
|
|
public record CustomerProfileItem
|
||
|
|
{
|
||
|
|
public required string Title { get; init; }
|
||
|
|
public required string Value { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Marketing settings
|
||
|
|
public record CustomerMarketingRecord
|
||
|
|
{
|
||
|
|
public bool EmailOptIn { get; init; }
|
||
|
|
public bool SmsOptIn { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Payment settings
|
||
|
|
public record CustomerPaymentRecord
|
||
|
|
{
|
||
|
|
public bool RequirePrepayment { get; init; }
|
||
|
|
public bool AllowPartialPayment { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Preferences
|
||
|
|
public record CustomerPreferencesRecord
|
||
|
|
{
|
||
|
|
public required string PreferredHairdresser { get; init; }
|
||
|
|
public required string PreferredDays { get; init; }
|
||
|
|
public required string SpecialRequests { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Warning item (flexible)
|
||
|
|
public record CustomerWarningItem
|
||
|
|
{
|
||
|
|
public required string Title { get; init; }
|
||
|
|
public required string Value { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Group
|
||
|
|
public record CustomerGroupRecord
|
||
|
|
{
|
||
|
|
public required string GroupId { get; init; }
|
||
|
|
public required string GroupName { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Relation
|
||
|
|
public record CustomerRelationRecord
|
||
|
|
{
|
||
|
|
public required string Id { get; init; }
|
||
|
|
public required string Name { get; init; }
|
||
|
|
public required string Initials { get; init; }
|
||
|
|
public required string Type { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Statistics
|
||
|
|
public record CustomerStatisticsRecord
|
||
|
|
{
|
||
|
|
public required CustomerAttendanceRecord Attendance { get; init; }
|
||
|
|
public List<CustomerTopItem> TopServices { get; init; } = new();
|
||
|
|
public List<CustomerTopItem> TopProducts { get; init; } = new();
|
||
|
|
public required CustomerBookingBehaviorRecord BookingBehavior { get; init; }
|
||
|
|
public required CustomerLoyaltyRecord Loyalty { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerAttendanceRecord
|
||
|
|
{
|
||
|
|
public int Attended { get; init; }
|
||
|
|
public int Cancelled { get; init; }
|
||
|
|
public int NoShow { get; init; }
|
||
|
|
public int ReliabilityPercent { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerTopItem
|
||
|
|
{
|
||
|
|
public required string Name { get; init; }
|
||
|
|
public int Count { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerBookingBehaviorRecord
|
||
|
|
{
|
||
|
|
public int AvgBookingNoticeDays { get; init; }
|
||
|
|
public required string PreferredDay { get; init; }
|
||
|
|
public required string PreferredTimeSlot { get; init; }
|
||
|
|
public int OnlineBookingRate { get; init; }
|
||
|
|
public int AvgCancellationNoticeDays { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerLoyaltyRecord
|
||
|
|
{
|
||
|
|
public double CustomerSinceYears { get; init; }
|
||
|
|
public int DaysSinceLastVisit { get; init; }
|
||
|
|
public required string ChurnRisk { get; init; }
|
||
|
|
public int AvgIntervalDays { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Journal
|
||
|
|
public record CustomerJournalEntry
|
||
|
|
{
|
||
|
|
public required string Id { get; init; }
|
||
|
|
public required string Type { get; init; }
|
||
|
|
public required string Tag { get; init; }
|
||
|
|
public List<string> Subtags { get; init; } = new();
|
||
|
|
public required string Text { get; init; }
|
||
|
|
public required string Date { get; init; }
|
||
|
|
public required string Author { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Appointments
|
||
|
|
public record CustomerAppointmentsRecord
|
||
|
|
{
|
||
|
|
public List<CustomerUpcomingAppointment> Upcoming { get; init; } = new();
|
||
|
|
public List<CustomerHistoryAppointment> History { get; init; } = new();
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerUpcomingAppointment
|
||
|
|
{
|
||
|
|
public required string Date { get; init; }
|
||
|
|
public required string Time { get; init; }
|
||
|
|
public required string Service { get; init; }
|
||
|
|
public required string Hairdresser { get; init; }
|
||
|
|
public required string Duration { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerHistoryAppointment
|
||
|
|
{
|
||
|
|
public required string Date { get; init; }
|
||
|
|
public required string Service { get; init; }
|
||
|
|
public required string Hairdresser { get; init; }
|
||
|
|
public required string Duration { get; init; }
|
||
|
|
public decimal Price { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Giftcards
|
||
|
|
public record CustomerGiftcardsRecord
|
||
|
|
{
|
||
|
|
public List<CustomerGiftcardItem> Active { get; init; } = new();
|
||
|
|
public List<CustomerGiftcardItem> Expired { get; init; } = new();
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerGiftcardItem
|
||
|
|
{
|
||
|
|
public required string Id { get; init; }
|
||
|
|
public required string Type { get; init; }
|
||
|
|
public required string Label { get; init; }
|
||
|
|
public decimal? OriginalValue { get; init; }
|
||
|
|
public decimal? CurrentBalance { get; init; }
|
||
|
|
public int? TotalPunches { get; init; }
|
||
|
|
public int? UsedPunches { get; init; }
|
||
|
|
public string? ExpiresAt { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Activity
|
||
|
|
public record CustomerActivityEntry
|
||
|
|
{
|
||
|
|
public required string Date { get; init; }
|
||
|
|
public required string Time { get; init; }
|
||
|
|
public required string Type { get; init; }
|
||
|
|
public required string Icon { get; init; }
|
||
|
|
public required string Title { get; init; }
|
||
|
|
public string? Actor { get; init; }
|
||
|
|
public List<string> Badges { get; init; } = new();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Economy
|
||
|
|
public record CustomerEconomyRecord
|
||
|
|
{
|
||
|
|
public required CustomerYearRevenue CurrentYear { get; init; }
|
||
|
|
public required CustomerYearRevenue LastYear { get; init; }
|
||
|
|
public decimal AvgPerVisit { get; init; }
|
||
|
|
public decimal AvgPerMonth { get; init; }
|
||
|
|
public CustomerChartData? ChartData { get; init; }
|
||
|
|
public List<CustomerPurchase> Purchases { get; init; } = new();
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerChartData
|
||
|
|
{
|
||
|
|
public List<string> Categories { get; init; } = new();
|
||
|
|
public List<CustomerChartSeries> Series { get; init; } = new();
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerChartSeries
|
||
|
|
{
|
||
|
|
public required string Name { get; init; }
|
||
|
|
public required string Color { get; init; }
|
||
|
|
public List<CustomerChartDataPoint> Data { get; init; } = new();
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerChartDataPoint
|
||
|
|
{
|
||
|
|
public required string X { get; init; }
|
||
|
|
public decimal Y { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerYearRevenue
|
||
|
|
{
|
||
|
|
public int Year { get; init; }
|
||
|
|
public decimal Total { get; init; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public record CustomerPurchase
|
||
|
|
{
|
||
|
|
public required string Invoice { get; init; }
|
||
|
|
public required string Date { get; init; }
|
||
|
|
public required string Time { get; init; }
|
||
|
|
public required string Employee { get; init; }
|
||
|
|
public required string Services { get; init; }
|
||
|
|
public required string Type { get; init; }
|
||
|
|
public decimal Amount { get; init; }
|
||
|
|
}
|