Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
IKycTransform.cs
1using System;
3using System.Linq;
4using System.Threading;
5using System.Threading.Tasks;
6using System.Globalization;
10
12{
16 public interface IKycTransform
17 {
21 string Name { get; }
22
31 Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct);
32 }
33
37 public static class KycTransformRegistry
38 {
39 private static readonly Dictionary<string, IKycTransform> transforms = new(StringComparer.OrdinalIgnoreCase);
40 private static bool initialized;
41
42 private static void EnsureInit()
43 {
44 if (initialized)
45 return;
46
47 initialized = true;
48 // Built-ins
49 Register(new TrimTransform());
50 Register(new UppercaseTransform());
51 Register(new LowercaseTransform());
52 Register(new YearTransform());
53 Register(new MonthTransform());
54 Register(new DayTransform());
55 Register(new PersonalNumberNormalizeTransform());
56 }
57
58 public static void Register(IKycTransform transform)
59 {
60 transforms[transform.Name] = transform;
61 }
62
63 public static bool TryGet(string name, out IKycTransform transform)
64 {
65 EnsureInit();
66 return transforms.TryGetValue(name, out transform!);
67 }
68 }
69
70 #region Built-in transforms
71
72 internal abstract class SimpleFuncTransform : IKycTransform
73 {
74 protected SimpleFuncTransform(string name) => this.Name = name;
75 public string Name { get; }
76 public abstract Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct);
77 }
78
79 internal sealed class TrimTransform : SimpleFuncTransform
80 {
81 public TrimTransform() : base("trim") { }
82 public override Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct) => Task.FromResult(currentValue.Trim());
83 }
84
85 internal sealed class UppercaseTransform : SimpleFuncTransform
86 {
87 public UppercaseTransform() : base("uppercase") { }
88 public override Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct) => Task.FromResult(currentValue.ToUpperInvariant());
89 }
90
91 internal sealed class LowercaseTransform : SimpleFuncTransform
92 {
93 public LowercaseTransform() : base("lowercase") { }
94 public override Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct) => Task.FromResult(currentValue.ToLowerInvariant());
95 }
96
97 internal sealed class YearTransform : SimpleFuncTransform
98 {
99 public YearTransform() : base("year") { }
100 public override Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct)
101 {
102 return Task.FromResult(DateTime.TryParse(currentValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dt) ? dt.Year.ToString(CultureInfo.InvariantCulture) : string.Empty);
103 }
104 }
105
106 internal sealed class MonthTransform : SimpleFuncTransform
107 {
108 public MonthTransform() : base("month") { }
109 public override Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct)
110 {
111 return Task.FromResult(DateTime.TryParse(currentValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dt) ? dt.Month.ToString(CultureInfo.InvariantCulture) : string.Empty);
112 }
113 }
114
115 internal sealed class DayTransform : SimpleFuncTransform
116 {
117 public DayTransform() : base("day") { }
118 public override Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct)
119 {
120 return Task.FromResult(DateTime.TryParse(currentValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dt) ? dt.Day.ToString(CultureInfo.InvariantCulture) : string.Empty);
121 }
122 }
123
124 internal sealed class PersonalNumberNormalizeTransform : SimpleFuncTransform
125 {
126 public PersonalNumberNormalizeTransform() : base("personalNumberNormalize") { }
127 public override async Task<string> ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct)
128 {
129 if (string.IsNullOrWhiteSpace(currentValue))
130 return currentValue;
131
132 string countryCode = string.Empty;
133 try
134 {
135 // Try explicit country field id patterns first
136 string? fromValues = process.Values.Where(kv => kv.Key.Contains("country", StringComparison.OrdinalIgnoreCase))
137 .Select(kv => kv.Value)
138 .FirstOrDefault(v => !string.IsNullOrEmpty(v));
139 if (!string.IsNullOrEmpty(fromValues))
140 countryCode = fromValues!;
141 if (string.IsNullOrEmpty(countryCode))
142 countryCode = ServiceRef.TagProfile.SelectedCountry ?? ServiceRef.TagProfile.LegalIdentity?.GetPersonalInformation().Country ?? string.Empty;
143 }
144 catch (Exception)
145 {
146 countryCode = string.Empty;
147 }
148
149 if (string.IsNullOrEmpty(countryCode))
150 return currentValue;
151
152 try
153 {
154 NumberInformation info = await PersonalNumberSchemes.Validate(countryCode, currentValue);
155 if (info.IsValid == true && !string.IsNullOrEmpty(info.PersonalNumber))
156 return info.PersonalNumber;
157 }
158 catch (Exception ex)
159 {
160 ServiceRef.LogService.LogException(ex);
161 }
162 return currentValue; // fallback
163 }
164 }
165
166 #endregion
167}
bool? IsValid
true = valid: PersonalNumber may be normalized. false = invalid null = scheme not applicable,...
string? PersonalNumber
String representation of the personal number.
Personal Number Schemes available in different countries.
static async Task< NumberInformation > Validate(string CountryCode, string PersonalNumber)
Checks if a personal number is valid, in accordance with registered personal number schemes.
Represents a parsed KYC process with pages, fields, and current values.
Definition: KycProcess.cs:11
IDictionary< string, string?> Values
Gets a modifiable dictionary of field values keyed by field identifier.
Definition: KycProcess.cs:21
Transform registry (static). Register new transforms at startup or via static ctor.
The base KYC field model. Use as-is for generic fields, or subclass for custom logic.
Base class that references services in the app.
Definition: ServiceRef.cs:43
static ILogService LogService
Log service.
Definition: ServiceRef.cs:214
static ITagProfile TagProfile
TAG Profile service.
Definition: ServiceRef.cs:202
Contract for KYC mapping transforms. Transforms can normalize, format or derive new values.
string Name
Unique transform name (case-insensitive in registry).
Task< string > ApplyAsync(ObservableKycField field, KycProcess process, string currentValue, CancellationToken ct)
Applies the transform to the current value.