Cayaqui.MPS.Helpers
0.1.0
dotnet add package Cayaqui.MPS.Helpers --version 0.1.0
NuGet\Install-Package Cayaqui.MPS.Helpers -Version 0.1.0
<PackageReference Include="Cayaqui.MPS.Helpers" Version="0.1.0" />
<PackageVersion Include="Cayaqui.MPS.Helpers" Version="0.1.0" />
<PackageReference Include="Cayaqui.MPS.Helpers" />
paket add Cayaqui.MPS.Helpers --version 0.1.0
#r "nuget: Cayaqui.MPS.Helpers, 0.1.0"
#:package Cayaqui.MPS.Helpers@0.1.0
#addin nuget:?package=Cayaqui.MPS.Helpers&version=0.1.0
#tool nuget:?package=Cayaqui.MPS.Helpers&version=0.1.0
Cayaqui.MPS.Helpers
Utilities zero-dependency para .NET 10 usadas transversalmente en los módulos MPS.
Contenido
| Archivo | Tipos / métodos |
|---|---|
Guard.cs |
Guard.Against.* — Null, NullOrWhiteSpace, EmptyGuid, Negative, NegativeOrZero, OutOfRange, NullOrEmpty, ExceedsMaxLength, BelowMinLength, NotDefault, MatchesPattern, Email, FutureDate, PastDate, InvalidOperation |
Result.cs |
Result<T> / Result con Success/Failure, Map, Match |
PaginatedList.cs |
Metadata de paginación (TotalCount, PageNumber, HasNext, FirstItemIndex, …) |
DateRange.cs |
Record struct inclusiva con Contains, Overlaps, IntersectWith, EnumerateDays, DurationDays |
Money.cs |
Record struct con Amount + ISO 4217 Currency; arithmetic con validación de moneda, compact string (10.4M / 1.2K) |
IClock.cs |
Abstracción IClock + SystemClock + FakeClock (testeo determinista) |
JsonDefaults.cs |
JsonSerializerOptions preconfigurado (camelCase, enums string, ignore null, tolerant reader) |
Extensions/StringExtensions.cs |
Truncate, ToDisplayLabel, ToTitleCase, FormatCode, IsValidEmail, RemoveAccents, Slugify, NormalizeWhitespace, MaskLast, MaskEmail, ToSnakeCase, ToKebabCase |
Extensions/DateTimeExtensions.cs |
ToShortDisplay, WeekNumber (ISO 8601), WorkingDaysUntil, StartOfMonth/EndOfMonth, ToRelativeTime, IsWeekend/IsWeekday, Quarter, FiscalYear, NextBusinessDay, AddBusinessDays, ToUtc(tz)/ToLocal(tz) |
Extensions/DecimalExtensions.cs |
EVM: CpiOf, SpiOf, PfOf, CvOf, SvOf, EacByCpi, EtcOf, VacOf, TcpiBac, TcpiEac, ScheduleAtCompletion, VacPercent; formatting: ToPercentString, ToCurrencyString, ToIndexString, ToAccountingString; utils: Clamp, RoundToCents, WithinTolerance; status: CpiStatus, SpiStatus, PfStatus, ToStatusColor (enum EvmStatus) |
Extensions/EnumExtensions.cs |
GetDescription ([Description]), GetDisplayName ([Display]), TryParseEnum, GetValues |
Extensions/CollectionExtensions.cs |
IsNullOrEmpty, WithIndex, Batch, AddIfNotNull, IndexOf(predicate), ToOrdinalDictionary |
Distribución propietaria — requiere contrato comercial con Cayaqui. Ver
LICENSE.txt.
Instalación
dotnet add package Cayaqui.MPS.Helpers
Ejemplos rápidos
Guard clauses
using MPS.Helpers;
public void CreateProject(string code, decimal budget, string email)
{
Guard.Against.NullOrWhiteSpace(code, nameof(code));
Guard.Against.BelowMinLength(code, 3, nameof(code));
Guard.Against.MatchesPattern(code, @"^[A-Z]{2,3}-\d{3,5}$", nameof(code));
Guard.Against.NegativeOrZero(budget, nameof(budget));
Guard.Against.Email(email, nameof(email));
}
Result pattern
using MPS.Helpers;
public Result<Project> FindProject(Guid id) =>
_repo.Get(id) is { } p
? Result<Project>.Success(p)
: Result<Project>.Failure("PROJECT_NOT_FOUND", $"Project {id} does not exist.");
EVM
using MPS.Helpers.Extensions;
decimal ev = 80_000, ac = 95_000, pv = 100_000, bac = 500_000, eac = 625_000;
decimal? cpi = ev.CpiOf(ac); // 0.8421
decimal? spi = ev.SpiOf(pv); // 0.80
decimal eac2 = bac.EacByCpi(cpi); // 593_750
decimal? tcpi = bac.TcpiEac(eac, ev, ac); // future efficiency needed vs EAC
decimal sac = 12m.ScheduleAtCompletion(spi); // PD 12m, SPI 0.8 → 15m
EvmStatus status = cpi.CpiStatus(); // Critical (< 0.85)
string display = cpi.ToIndexString(); // "0.84" (InvariantCulture default)
Money
using MPS.Helpers;
var budget = new Money(500_000m, "USD");
var actual = new Money(435_000m, "USD");
var variance = budget - actual; // USD 65,000.00
var withVat = budget * 1.19m; // USD 595,000.00
budget.ToCompactString(); // "USD 500.0K"
budget.ToString(); // "USD 500,000.00"
// Currency mismatch → InvalidOperationException al operar
// var mixed = budget + new Money(100m, "EUR"); // throws
DateRange
using MPS.Helpers;
var projectWindow = new DateRange(new DateTime(2025, 1, 1), new DateTime(2025, 12, 31));
projectWindow.Contains(DateTime.Today); // true si dentro
projectWindow.DurationDays; // 365
var phase = new DateRange(new DateTime(2025, 3, 1), new DateTime(2025, 6, 30));
projectWindow.Overlaps(phase); // true
projectWindow.IntersectWith(phase); // [2025-03-01, 2025-06-30]
IClock (testeo determinista)
public class ExpiryService(IClock clock)
{
public bool IsExpired(DateTime expiresAt) => clock.UtcNow > expiresAt;
}
// Producción
builder.Services.AddSingleton<IClock>(SystemClock.Instance);
// Tests
var fake = new FakeClock(new DateTime(2025, 6, 15, 10, 0, 0, DateTimeKind.Utc));
var service = new ExpiryService(fake);
fake.Advance(TimeSpan.FromHours(2)); // avanza el reloj sin tocar DateTime.UtcNow
JSON defaults
using MPS.Helpers;
using System.Text.Json;
var json = JsonSerializer.Serialize(dto, JsonDefaults.Web);
// camelCase ✓ · enums como strings ✓ · null ignored ✓ · tolerant reader ✓
Strings y dates
using MPS.Helpers.Extensions;
"Control Account 01 — Diseño Eléctrico".Slugify(); // "control-account-01-diseno-electrico"
"alejandro@cayaqui.com".MaskEmail(); // "a********@cayaqui.com"
"acción".RemoveAccents(); // "accion"
" hello\t\nworld ".NormalizeWhitespace(); // "hello world"
new DateTime(2025, 6, 15).Quarter(); // 2
new DateTime(2025, 8, 1).FiscalYear(fiscalStartMonth: 7); // 2026 (FY empieza en julio)
new DateTime(2025, 6, 6).NextBusinessDay(); // viernes → lunes
new DateTime(2025, 6, 2).AddBusinessDays(5); // suma 5 días hábiles
Requisitos
- .NET 10.0 o superior
- Sin dependencias externas — pure C# / BCL only.
Formato y cultura
Los formatters (ToShortDisplay, ToIndexString, ToCurrencyString, ToPercentString, ToAccountingString) usan InvariantCulture por default para salidas deterministas (APIs, reports, logs). Para UI localizada pasar CultureInfo explícita:
var es = new CultureInfo("es-CL");
value.ToPercentString(decimals: 2, culture: es); // "75,60%"
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 106 | 4/24/2026 |
Initial release. Guard, Result, PaginatedList, DateRange, Money, IClock (+FakeClock), JsonDefaults, Enum/Collection/String/DateTime/Decimal extensions with EVM indicators per ANSI-EIA-748.