Files
dmolinari 3e7c4bfde9 chore(prc-001): followups #54 #55 #57 #58 — emoji validator + opt-in pricing + demo seed + tsconfig
Resuelve 4 de los followups creados post-archive de PRC-001:

#55 — Decisión de negocio (2026-04-21): emojis NO se permiten en Symbol config.
  - WordCounterService.ContainsEmoji(string): helper publico que reutiliza los
    rangos Unicode de IsEmojiRune (Emoticons, Pictographs, Dingbats, VS-16, ZWJ).
  - CreateChargeableCharConfigCommandValidator: regla .Must que rechaza emoji
    en Symbol con mensaje claro. Defensiva: cubre clientes directos al API
    (Postman, adversariales) mas alla del SymbolInput blocker del frontend.
  - Tests: 5 emojis positivos (smile/car/fire/heart VS-16/sun) + 8 plain symbols
    ($, %, !, ¡, @, €, ##, ABCD) + actualizacion del Api test E2E (Post_WithEmojiSymbol).

#57 — Alineacion FluentValidation con opt-in billing (CK_Price_NonNegative >= 0).
  - CreateChargeableCharConfigCommandValidator.PricePerUnit: GreaterThan(0)
    -> GreaterThanOrEqualTo(0). Mensaje explica el significado: 0 = no cobra.
  - Tests actualizados: PricePerUnit_Zero ahora Passes (era Fails). Negative
    sigue fallando. Api e2e usa -1 para el caso de rechazo.

#58 — tsconfig ignoreDeprecations + MSW handler (parte a).
  - src/web/tsconfig.json: agrega "ignoreDeprecations": "6.0" para silenciar
    el warning TS5101 del baseUrl deprecated en TS 6.x.
  - (El MSW handler de /api/v1/admin/product-types no aplica — los tests ya
    mockean ProductTypeSelect directamente; warning residual no existe.)

#54 — Seeder demo de overrides ficticios per-ProductType (V025).
  - database/migrations/V025__seed_chargeable_char_overrides_demo.sql:
    MERGE idempotente que crea overrides de ChargeableCharConfig para
    ProductTypes Clasificado/Notables/Fúnebres si existen en la DB.
    Precios ficticios ($ 5-8, % 3-5, ! 2-4, ¡ 2-4). No-op si los tipos no
    estan seedados (sera cuando PRD-008 haga seed de los 12 legacy).
  - V025_ROLLBACK.sql: elimina overrides demo preservando globales.
  - Aplicado en SIGCM2, SIGCM2_Test_App, SIGCM2_Test_Api.
  - database/README.md: V025 agregada al indice.

Tests: 1659 .NET (1310 Application + 349 Api) + 510 vitest — todos GREEN.

Closes #54, #55, #57, #58.
2026-04-21 13:27:54 -03:00
..

database/ — SIG-CM 2.0

Todo el DDL del sistema vive acá: migraciones versionadas, stored procedures, functions, seeds.

Estructura

database/
├── migrations/        # Migraciones versionadas V0XX__<descripcion>.sql (SQL puro, idempotentes)
├── procedures/        # Stored procedures — creados/alterados por UDTs específicas
├── functions/         # User-defined functions
├── seeds/             # Data de referencia no-versionada
└── schemas/           # Extracciones de schema (referencia)

Migraciones aplicadas (orden obligatorio)

Versión Archivo UDT Descripción
V001 V001__create_usuario.sql UDT-001 Tabla Usuario + IX_Usuario_Username_Activo
V002 V002__create_refresh_token.sql UDT-002 Tabla RefreshToken
V003 V003__create_rol.sql UDT-004 Tabla Rol + 8 roles canónicos
V004 V004__alter_usuario_rol_fk.sql UDT-004 FK Usuario.Rol → Rol.Codigo
V005 V005__create_permiso.sql UDT-005 Tabla Permiso + 18 permisos canónicos
V006 V006__create_rol_permiso.sql UDT-005 Tabla RolPermiso + seed 36 rows
V007 V007__add_admin_permissions_udt006.sql UDT-006 3 permisos administrativos RBAC
V008 V008__add_mustchangepassword_and_indexes.sql UDT-008 Usuario.MustChangePassword + IX_Usuario_Activo_Rol
V009 V009__activate_permisos_overrides.sql UDT-009 Migración shape PermisosJson {grant, deny}
V010 V010__audit_infrastructure.sql UDT-010 Infra de auditoría + Temporal Tables. Ver nota abajo.
V011 V011__create_medio_seccion.sql ADM-001 Medio + Seccion (temporal, retention 10y) + permiso administracion:secciones:gestionar
V012 V012__seed_medios.sql ADM-001 Seed idempotente de Medios ELDIA y ELPLATA
V013 V013__create_puntos_de_venta.sql ADM-008 PuntosDeVenta (temporal, retention 10y) + permiso administracion:puntos_de_venta:gestionar
V014 V014__create_tablas_fiscales.sql ADM-009 TiposDeIva + IngresosBrutos (versioning por cadena) + permisos fiscales
V015 V015__create_local_timezone_views.sql UDT-011 Vistas admin con OccurredAt convertido a hora Argentina
V016 V016__create_rubro.sql CAT-001 Rubro (adjacency list, temporal 10y) + permiso catalogo:rubros:gestionar
V017 V017__create_product_type.sql PRD-001 ProductType (flags + multimedia limits, temporal 10y) + permiso catalogo:tipos:gestionar
V018 V018__create_product.sql PRD-002 Product (temporal 10y) + permiso catalogo:productos:gestionar + índices
V019 V019__create_product_prices.sql PRD-003 ProductPrices (temporal 10y, forward-only) + SP sp_ProductPrices_InsertWithClose + permiso implícito
V020 V020__add_chargeable_chars_permission.sql PRC-001 Permiso tasacion:caracteres_especiales:gestionar + asignación a admin
V021 V021__create_chargeable_char_config.sql PRC-001 ChargeableCharConfig + ChargeableCharConfig_History (temporal 10y) + 2 SPs (InsertWithClose, GetActiveForProductType) + 2 índices
V022 V022__seed_chargeable_char_config.sql PRC-001 Seed 4 filas globales ($, %, !, ¡) con PricePerUnit=1.0000
V023 V023__refactor_chargeable_char_config_to_product_type.sql PRC-001 (scope delta) Refactor MedioId→ProductTypeId + nuevo SP ReactivateWithGuard + CK_Price_NonNegative (>= 0)
V024 V024__reseed_global_with_zero_price.sql PRC-001 (scope delta) Reseed 4 globales a PricePerUnit=0.0000 (opt-in billing)
V025 V025__seed_chargeable_char_overrides_demo.sql PRC-001 (followup #54) Seed demo de overrides ficticios per-ProductType (Clasificado/Notables/Fúnebres). Idempotente: no-op si los tipos no existen

Convenciones

  • SQL puro ejecutado manualmente (no hay runner automático; decisión arquitectónica).
  • Idempotentes: cada migración usa IF NOT EXISTS / MERGE / IF NOT EXISTS (SELECT 1 FROM sys....). Re-ejecutarlas es seguro.
  • Boilerplate inicial: SET QUOTED_IDENTIFIER ON; SET ANSI_NULLS ON; SET NOCOUNT ON; GO.
  • Naming: PK_*, UQ_*, FK_*, DF_*, CK_*, IX_*.
  • Se aplican a TRES bases: SIGCM2 (dev), SIGCM2_Test_App (Application.Tests) y SIGCM2_Test_Api (Api.Tests). El orden debe ser idéntico en las tres.

Cómo aplicar migraciones

En dev (manual)

# Con sqlcmd (aplicar a las tres bases en orden):
sqlcmd -S TECNICA3 -d SIGCM2           -U desarrollo -P desarrollo2026 -i database/migrations/V010__audit_infrastructure.sql
sqlcmd -S TECNICA3 -d SIGCM2_Test_App  -U desarrollo -P desarrollo2026 -i database/migrations/V010__audit_infrastructure.sql
sqlcmd -S TECNICA3 -d SIGCM2_Test_Api  -U desarrollo -P desarrollo2026 -i database/migrations/V010__audit_infrastructure.sql

O desde SSMS: abrir el archivo, conectar a cada base, F5.

En integration tests

tests/SIGCM2.TestSupport/SqlTestFixture.cs aplica automáticamente el schema necesario en SIGCM2_Test_App al inicializar el fixture (EnsureV008SchemaAsync, EnsureV009SchemaAsync, EnsureV010SchemaAsync…). TestWebAppFactory hace lo mismo contra SIGCM2_Test_Api. NO hace falta correr los scripts manualmente si el fixture ya lo cubre.

En producción (roadmap futuro)

  1. Backup completo de la base.
  2. Revisar notas específicas de la migración (ver abajo).
  3. Ventana de mantenimiento si la migración lo requiere.
  4. sqlcmd + script + verify que los PRINT salieron esperados.
  5. Smoke test post-migración.

⚠️ Notas especiales por migración

V010 — Infraestructura de Auditoría

Riesgos específicos:

  • Activa SYSTEM_VERSIONING en Usuario, Rol, Permiso, RolPermiso. Tablas con datos. ALTER TABLE ADD PERIOD FOR SYSTEM_TIME toma Sch-M lock (schema modification). En dev con pocos usuarios el lock es milisegundos; en prod con conexiones activas puede generar espera.
  • Crea filegroups AUDIT_HOT y AUDIT_COLD con archivos físicos <DB>_AUDIT_HOT.ndf y <DB>_AUDIT_COLD.ndf en el default data path del server.
  • Crea 2 partition functions + schemes mensuales (boundaries 2026-01..2027-02). El job AuditPartitionManagerJob (B11) extiende la ventana mes a mes.

Para aplicar en prod:

  1. Backup completo previo (no negociable).
  2. Ventana de mantenimiento ≥ 10 min (los ALTER de SYSTEM_VERSIONING son rápidos pero pueden caer en timeouts si hay transacciones largas).
  3. Ejecutar el script + verificar todos los PRINT "created/applied".
  4. Smoke test post: SELECT TOP 1 * FROM dbo.AuditEvent (vacío OK); SELECT temporal_type FROM sys.tables WHERE name = 'Usuario' (debe devolver 2 = system-versioned).
  5. Si algo falla → V010_ROLLBACK.sql (pierde toda la historia) o restore de backup.

Catálogo de entidades auditables (source of truth): Obsidian/02-ARQUITECTURA-y-TECH-STACK/2.5 📋 Auditoría.md. Cada UDT nueva que introduzca entidades de negocio debe agregar esas tablas al catálogo y activar SYSTEM_VERSIONING en su migración.

V011/V012 — ADM-001 Medios y Secciones

Alcance: crea dbo.Medio y dbo.Seccion con Temporal Tables (retention 10 años), el permiso administracion:secciones:gestionar (y lo asigna a rol admin), y siembra los dos Medios fundacionales ELDIA y ELPLATA.

Notas:

  • administracion:medios:gestionar ya existía desde V005 — no se toca.
  • PlataformaEmpresaId es INT NULL sin FK; la FK se agrega en INT-003 cuando se cree la tabla PlataformaEmpresa.
  • Seccion.Tipo acepta 'clasificados' | 'notables' | 'suplementos' (CHECK constraint). Config avanzada (par/impar, suplementos, cupos) se introduce en ADM-003.
  • Rollback: V012_ROLLBACK.sql (falla si hay Secciones vivas) → V011_ROLLBACK.sql. Rollback en prod NO soportado si ADM-008/009 o PRC-* ya aplicados.

Bases de datos de integration tests

Base Propósito Usada por
SIGCM2_Test_App Tests de repositorios y Application layer SIGCM2.Application.Tests vía SqlTestFixture (parameterless ctor)
SIGCM2_Test_Api Tests de endpoints HTTP / WebApplicationFactory SIGCM2.Api.Tests vía TestWebAppFactory

Script de creación inicial (idempotente): database/init/create-test-api-db.sql

Ambas bases deben tener todas las migraciones V001V015 aplicadas en orden. Al crear una base nueva o al agregar un desarrollador:

  1. Crear las bases con create-test-api-db.sql
  2. Aplicar V001V015 en orden (ver tabla de arriba) contra cada base de test
  3. Las EnsureV0XX del fixture validan presencia; no aplican migraciones pesadas

Fuente única de connection strings: tests/SIGCM2.TestSupport/TestConnectionStrings.cs

Recursos

  • Design autoritativo: Obsidian/02-ARQUITECTURA-y-TECH-STACK/2.5 📋 Auditoría.md
  • Decisión persistida (engram): sig-cm2/audit-architecture
  • SDD artifacts UDT-010 (engram): sdd/udt-010-auditoria-trazabilidad/{explore,proposal,spec,design,tasks,apply-progress}