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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cayaqui.MPS.Helpers" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cayaqui.MPS.Helpers" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Cayaqui.MPS.Helpers" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cayaqui.MPS.Helpers --version 0.1.0
                    
#r "nuget: Cayaqui.MPS.Helpers, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Cayaqui.MPS.Helpers@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cayaqui.MPS.Helpers&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Cayaqui.MPS.Helpers&version=0.1.0
                    
Install as a Cake Tool

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • 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.