shoc-backend/SeaHaven.Services/Helpers/WorkOrderNumberNormalizer.cs
Alexandre Brandizzi 4b772c8db3
Some checks are pending
Validate and deploy / Validate deployable source bundle (push) Waiting to run
Validate and deploy / Deploy shoc-backend-dev through Terraform (push) Blocked by required conditions
Validate and deploy / Deploy shoc-backend-staging to Elastic Beanstalk (push) Blocked by required conditions
fix(work-orders): keep SH placeholder WO numbers and block downgrades (#123)
SH-320: the WO number normalizer stripped every non-digit, so a manually
entered SH placeholder (e.g. SH00001) was saved as 00000000001 on both
create and patch. Keep the SH prefix, and reject replacing a saved real
APM number with an SH placeholder.
2026-09-16 15:01:10 -03:00

68 lines
2.2 KiB
C#

using System.Text.RegularExpressions;
namespace SeaHaven.Services.Helpers
{
public static class WorkOrderNumberNormalizer
{
private const int RequiredLength = 11;
private const string ProvisionalPrefix = "SH";
private const int MinimumProvisionalDigits = 5;
public static bool TryNormalize(string? input, out string normalized, out string? error)
{
normalized = "";
error = null;
if (string.IsNullOrWhiteSpace(input))
{
error = "WO number is required.";
return false;
}
var trimmed = input.Trim();
if (WorkOrderNumberRules.IsProvisional(trimmed))
return TryNormalizeProvisional(trimmed, out normalized, out error);
var digits = Regex.Replace(trimmed, @"\D", "");
if (digits.Length == 0)
{
error = "WO number must contain digits.";
return false;
}
if (digits.Length > RequiredLength)
{
error = $"WO number cannot exceed {RequiredLength} digits.";
return false;
}
normalized = digits.PadLeft(RequiredLength, '0');
return true;
}
// SH-320: an SH-prefixed number is the documented placeholder for a WO still
// awaiting its real APM number; keep the prefix instead of stripping it to digits.
private static bool TryNormalizeProvisional(string trimmed, out string normalized, out string? error)
{
normalized = "";
error = null;
var digits = Regex.Replace(trimmed[ProvisionalPrefix.Length..], @"\D", "");
if (digits.Length == 0)
{
error = "WO number must contain digits.";
return false;
}
var candidate = ProvisionalPrefix + digits.PadLeft(MinimumProvisionalDigits, '0');
if (candidate.Length > RequiredLength)
{
error = $"WO number cannot exceed {RequiredLength} characters.";
return false;
}
normalized = candidate;
return true;
}
}
}