Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/NicolasMPP/restorante-springboot/llms.txt

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

Restorante models every person in the system — whether an executive chef, a front-of-house server, a manager, or a dining guest — as a subtype of the Persona entity. Using JPA’s JOINED inheritance, the base identity fields (name, ID number, contact details) live in a single normalized personas table, while each role’s specialized data occupies its own joined table. This design avoids sparse columns and keeps identity queries clean, while still allowing each role to carry only the fields that make sense for it.

The Persona Base Class

Persona is the root of the hierarchy. It uses @Inheritance(strategy = InheritanceType.JOINED) — no discriminator column is present at this level, because JOINED inheritance uses the presence of a row in a subtype table to determine the concrete type.
@Entity
@Table(name = "personas")
@Inheritance(strategy = InheritanceType.JOINED)
public class Persona implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Integer id;

    @Column(name = "nombre", nullable = false, length = 100)
    protected String nombre;

    @Column(name = "cedula", nullable = false, unique = true, length = 20)
    protected String cedula;

    @Column(name = "telefono", length = 20)
    protected String telefono;

    @Column(name = "correo", length = 100)
    protected String correo;

    @Column(name = "usuario", length = 50)
    protected String usuario;

    @Column(name = "contrasenia", length = 100)
    protected String contrasenia;
}
FieldTypeConstraints
idIntegerAuto-generated primary key
nombreStringNot null, max 100 characters
cedulaStringNot null, unique, 7–20 characters
telefonoStringOptional, max 20 characters
correoStringOptional, max 100 characters
usuarioStringOptional, max 50 characters
contraseniaStringOptional, max 100 characters
The esValido() method on Persona enforces that nombre is non-blank and within 100 characters, and that cedula is non-blank and between 7 and 20 characters.

The Empleado Class

Empleado extends Persona and is stored in the empleados table, linked to personas by @PrimaryKeyJoinColumn(name = "id"). It introduces employment-specific fields and itself acts as the root of a nested SINGLE_TABLE hierarchy for employee subtypes (Chef and Mesero), using the tipo_empleado discriminator column.
@Entity
@Table(name = "empleados")
@PrimaryKeyJoinColumn(name = "id")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "tipo_empleado", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("EMPLEADO")
public class Empleado extends Persona implements Serializable {

    @Column(name = "fecha_vinculacion")
    protected LocalDate fechaVinculacion;

    @Column(name = "hora_ingreso")
    protected LocalDateTime horaIngreso;

    @Column(name = "hora_salida")
    protected LocalDateTime horaSalida;

    @Column(name = "salario", precision = 10, scale = 2)
    protected BigDecimal salario;

    @JsonIgnore
    @OneToMany(mappedBy = "chef", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Receta> recetas = new ArrayList<>();
}
FieldTypeDescription
fechaVinculacionLocalDateDate the employee joined
horaIngresoLocalDateTimeStart of the employee’s shift
horaSalidaLocalDateTimeEnd of the employee’s shift
salarioBigDecimalMonthly salary (precision 10, scale 2)
recetasList<Receta>Recipes authored by this employee (cascade ALL)
The recetas relationship is defined on Empleado (not just on Chef) because the Receta entity’s chef field is typed as Empleado. This means any employee — including a Mesero, per the model — could technically be assigned a recipe, though in practice the API only assigns recipes through chef records.

Staff Roles at a Glance

RoleDiscriminator / JoinTableSpecial Capabilities
GerenteJOINED (no discriminator)gerentesOwns Menu and Despensa via @OneToMany (cascade ALL)
ChefCHEF in tipo_empleadoempleadosCan be assigned Receta entities; looked up by cédula for recipe assignment
MeseroMESERO in tipo_empleadoempleadosEmployee subtype; no dedicated API operations
ClienteJOINED (no discriminator)clientesExtends Persona only — no salary, schedule, or recipe relationships
Gerente and Cliente both extend Persona directly using JOINED inheritance — they each have their own table (gerentes and clientes) with a @PrimaryKeyJoinColumn(name = "id"). Neither uses a discriminator column. Chef and Mesero, by contrast, extend Empleado and share the empleados table, differentiated only by the tipo_empleado discriminator value.

Seed Data

The InicializadorBD component seeds the following staff and client records on first startup. It checks personaRepository.count() > 0 before inserting, so the seed runs exactly once.
Gerente gerente = new Gerente(
    "Martín Vargas",       // nombre
    "1234567890",          // cedula
    "2615488978",          // telefono
    "martinchef@itu.masterchef.com", // correo
    "MChef55",             // usuario
    "Poo1234"              // contrasenia
);

API Access by Role

Chefs are the only staff role with a dedicated REST endpoint at /api/chefs. This endpoint is used primarily to retrieve chef records for recipe assignment. All other staff roles are managed through their own repositories internally but do not expose a dedicated external endpoint in the current implementation. When a food item is created or updated with a recipe, the API resolves the authoring chef by cédula — the chefCedula field in the request body is looked up against the cedula column in the empleados table (filtered to tipo_empleado = 'CHEF').
The chef’s cédula — not their database id — is the key used in the AlimentoCompletoRequest body when creating or updating a food item with a recipe. For example, to assign Chef Carina Sosa (cédula 3456789012) to a new Pasta Carbonara entry, include "chefCedula": "3456789012" in the request payload.

Build docs developers (and LLMs) love