Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/interezante456-pixel/nuevo-proyecto-viernes/llms.txt

Use this file to discover all available pages before exploring further.

The Cliente entity represents a customer who appears on a sale receipt. Every Venta must be linked to a client record; for anonymous walk-in purchases where no customer details are collected, the system automatically assigns the seeded Público General placeholder (ID = 1). Clients with a valid RUC are required when issuing a Factura. The entity is exposed through the AppDbContext.Clientes DbSet and holds a one-to-many relationship with Venta — a single customer may have an unlimited sale history.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Final_proyecto.Models
{
    public class Cliente
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID_Cliente { get; set; }

        [Required, StringLength(50)]
        [RegularExpression(@"^[a-zA-ZáéíóúÁÉÍÓÚñÑüÜ\s]+$",
            ErrorMessage = "Los nombres solo deben contener letras.")]
        public string Nombres { get; set; }

        [Required, StringLength(50)]
        [RegularExpression(@"^[a-zA-ZáéíóúÁÉÍÓÚñÑüÜ\s]+$",
            ErrorMessage = "Los apellidos solo deben contener letras.")]
        public string Apellidos { get; set; }

        [Required, StringLength(10)]
        public string TipoDocumento { get; set; } // DNI o RUC

        [Required, StringLength(11)]
        [RegularExpression(@"^\d{8}$|^(10|20)\d{9}$",
            ErrorMessage = "DNI debe tener 8 dígitos o RUC debe tener 11 dígitos y empezar con 10 o 20")]
        public string NumeroDocumento { get; set; }

        [Required, StringLength(9)]
        [RegularExpression(@"^(?!(\d)\1{8})9\d{8}$",
            ErrorMessage = "El teléfono debe tener 9 dígitos, empezar con 9 y no ser un número repetido como 999999999")]
        public string Telefono { get; set; }

        [StringLength(100)]
        public string? Correo { get; set; }

        [StringLength(200)]
        public string? Direccion { get; set; }

        public ICollection<Venta>? Ventas { get; set; }
    }
}

Properties

ID_Cliente
int
required
Primary key. Auto-generated by the database using DatabaseGeneratedOption.Identity. Annotated with [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]. ID 1 is reserved for the seeded Público General client and must never be deleted.
Nombres
string
required
The customer’s given name(s). Annotated with [Required, StringLength(50)] — maximum 50 characters. Validated against the regex ^[a-zA-ZáéíóúÁÉÍÓÚñÑüÜ\s]+$: only Unicode letters (including Spanish accented characters) and whitespace are allowed; digits and special characters are rejected.
Apellidos
string
required
The customer’s surname(s). Annotated with [Required, StringLength(50)] — maximum 50 characters. Subject to the same letter-only regex as Nombres.
TipoDocumento
string
required
Classifies the identity document number provided. Annotated with [Required, StringLength(10)]. Accepted values are:
  • "DNI" — Peruvian national identity card (8-digit number).
  • "RUC" — Peruvian tax identification number (11-digit number starting with 10 or 20).
The controller uses this field together with NumeroDocumento to enforce the correct format at the UI level.
NumeroDocumento
string
required
The actual document number string. Annotated with [Required, StringLength(11)] and validated by a [RegularExpression] — see Document Type Validation below. Maximum 11 characters (the length of a RUC).
Telefono
string
required
Peruvian mobile phone number. Annotated with [Required, StringLength(9)] and validated by a [RegularExpression] — see Document Type Validation below. Exactly 9 characters in the stored form (no country code, no spaces).
Correo
string?
Optional email address. Annotated with [StringLength(100)] — maximum 100 characters. May be null. Not used as a login credential (that role belongs to Usuario.CorreoUsuario).
Direccion
string?
Optional physical address. Annotated with [StringLength(200)] — maximum 200 characters. May be null. Printed on Factura receipts when present.
Ventas
ICollection<Venta>?
Inverse navigation collection of all Venta records associated with this client. Nullable — not loaded unless .Include(c => c.Ventas) is used. Useful for producing a customer purchase history report.

Document Type Validation

Both identity document and phone number fields are validated using [RegularExpression] data annotations directly on the model, so they are enforced both client-side (via unobtrusive jQuery validation) and server-side (via ModelState.IsValid).

NumeroDocumento

[RegularExpression(@"^\d{8}$|^(10|20)\d{9}$",
    ErrorMessage = "DNI debe tener 8 dígitos o RUC debe tener 11 dígitos y empezar con 10 o 20")]
The pattern accepts two mutually exclusive formats:
FormatPatternExampleDescription
DNI^\d{8}$12345678Exactly 8 decimal digits.
RUC`^(1020)\d$`20512345678Exactly 11 decimal digits, prefix must be 10 or 20.
The TipoDocumento dropdown in the UI is pre-populated with “DNI” or “RUC”. Although the model does not cross-validate TipoDocumento against NumeroDocumento at the annotation level, the regex on NumeroDocumento implicitly enforces the correct length for each type.

Telefono

[RegularExpression(@"^(?!(\d)\1{8})9\d{8}$",
    ErrorMessage = "El teléfono debe tener 9 dígitos, empezar con 9 y no ser un número repetido como 999999999")]
The pattern enforces three rules simultaneously:
  1. Starts with 9 — mandatory for Peruvian mobile numbers.
  2. Exactly 9 digits total9 followed by 8 more decimal digits (9\d{8}).
  3. No all-same-digit strings — the negative lookahead (?!(\d)\1{8}) rejects inputs where all 9 digits are identical (e.g., 999999999, 911111111), preventing placeholder numbers from being accepted.

Default Client

A Público General client is seeded by AppDbContext.OnModelCreating and is always present in the database:
FieldSeeded Value
ID_Cliente1
NombresPúblico
ApellidosGeneral
TipoDocumentoDNI
NumeroDocumento00000000
Telefono900000000
Correopublico@general.com
DireccionTienda Principal
When a cashier processes a Boleta without collecting customer details, VentaController assigns Cliente_ID = 1 automatically. This ensures every Venta row satisfies the non-nullable foreign key constraint without requiring the cashier to register an anonymous customer each time.
The seeded NumeroDocumento = "00000000" bypasses normal DNI uniqueness expectations. Do not allow real customers to be registered with this document number, as doing so would conflict with the seed record and cause ambiguous lookups.

Relationships

Ventas
ICollection<Venta>?
One-to-many relationship configured in AppDbContext.OnModelCreating:
modelBuilder.Entity<Venta>()
    .HasOne(v => v.Cliente)
    .WithMany(c => c.Ventas)
    .HasForeignKey(v => v.Cliente_ID);
A Cliente may appear on zero or more Venta records. Deleting a client that has associated sales is not permitted by default due to the foreign key constraint — deactivate the client or reassign their sales instead.

Build docs developers (and LLMs) love