dmolinari created pull request dmolinari/SIG-CM2.0#60

dmolinari
Tue, 21 Apr 2026 16:28:23 +0000

60#chore(prc-001): followups #54 #55 #57 #58 + cierre #52 #53#

Resumen

Resuelve los 6 followups post-archive de PRC-001 (excepto #56 que queda para FAC-001).

# | Decisión/Fix | Cierre
#52 R1.7 hyphens | Confirmado: default = 2 palabras (coincide con impl actual) | Cerrado sin código
#53 GC-24 all-specials | Confirmado: TotalWords=0 + conteo por categoría es correcto | Cerrado sin código
#54 Seeds demo per-ProductType | V025 con overrides ficticios idempotentes (Clasificado/Notables/Fúnebres) | ✅ Código
#55 Emoji en Symbol | No se permiten (decisión negocio). Validator usa WordCounterService.ContainsEmoji | ✅ Código
#57 FluentValidation opt-in | PricePerUnit >= 0 (alineado con CK_Price_NonNegative de V023) | ✅ Código
#58 tsconfig + MSW | ignoreDeprecations: "6.0" agregado (MSW handler ya existente, sin cambios necesarios) | ✅ Código

Cambios técnicos

Backend

src/api/SIGCM2.Domain/Pricing/WordCounter/WordCounterService.cs: nuevo método público ContainsEmoji(string?) que reutiliza IsEmojiRune para detección de emoji en cualquier string. Permite reuso desde validators.

src/api/SIGCM2.Application/Pricing/ChargeableChars/Create/CreateChargeableCharConfigCommandValidator.cs:

Symbol: nueva regla .Must(s => !WordCounterService.ContainsEmoji(s)) con mensaje claro.

PricePerUnit: GreaterThan(0m) → GreaterThanOrEqualTo(0m) con mensaje que documenta la semántica "0 = desactiva cobro (opt-in billing)".

BD

database/migrations/V025__seed_chargeable_char_overrides_demo.sql: MERGE idempotente. Para cada uno de los 3 ProductTypes (Clasificado/Notables/Fúnebres), si existe activo, inserta overrides con precios ficticios. Si el tipo no existe, bloque correspondiente es no-op.

V025_ROLLBACK.sql: elimina overrides demo preservando globales.

Aplicado en las 3 DBs (SIGCM2 + Test_App + Test_Api).

database/README.md: V025 agregada al índice de migraciones.

Frontend

src/web/tsconfig.json: "ignoreDeprecations": "6.0" para silenciar warning TS5101 (baseUrl deprecation en TS 6.x).

Tests

tests/SIGCM2.Application.Tests/Pricing/ChargeableChars/CreateChargeableCharConfigCommandValidatorTests.cs:

PricePerUnit_Zero_Passes_OptInBilling (antes _FailsValidation, ahora documenta la intención opt-in)

Symbol_WithEmoji_FailsValidation — [Theory] con 5 emojis (😀 🚗 🔥 ❤️ ☀️)

Symbol_WithoutEmoji_Passes — [Theory] con 8 plain symbols

tests/SIGCM2.Api.Tests/Pricing/ChargeableChars/ChargeableCharConfigControllerTests.cs:

Post_InvalidPrice_Returns400ValidationFailure: usa -1 en lugar de 0 (ya que 0 es válido)

Post_WithEmojiSymbol_Returns400 (antes _Returns201_BecauseEmojiRejectionIsDeferred)

Verify

dotnet test: 1659/1659 green (1310 Application + 349 Api)

cd src/web && npx vitest run: 510/510 green

cd src/web && npx tsc --noEmit: 0 errors, 0 warnings (TS5101 silenciado)

Issues cerrados

Closes #52, #53, #54, #55, #57, #58.

Quedan abiertos:

#56 — FAC-001 guards (heredado, se cierra cuando se implemente FAC-001; recordatorio en callout [!important] del UDT doc + label followup).