appointmentbooking

package module
v0.1.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 17, 2026 License: MIT Imports: 10 Imported by: 0

README

appointment-booking

Gestiona la configuración de servicios agendables, calendarios de trabajo del personal (bloques) y reservas de clientes.

Entidades principales

  • employee_service_config: configuración de qué servicios maneja cada profesional (duración, anulación de precio).
  • reservation: la cita programada (fecha/hora, cliente, profesional, servicio) con un estado (status) controlado por máquina de estados finitos (FSM).
  • workcalendar_block: una fila por bloque de tiempo de trabajo — SEMANAL (specific_date == 0, aplica a day_of_week) o DATADO (specific_date > 0, aplica solo a esa fecha y la abre). Varios bloques por día = el descanso para almorzar es el espacio entre ellos.
  • workcalendar_exception: excepciones puntuales (feriados personales, horarios especiales, intervalos bloqueados).
  • workcalendar_config: la zona horaria IANA del calendario de un miembro del personal (heredada por bloques y excepciones).

Documentación

Notas de diseño / desacoplamiento

Sin claves foráneas (FK) físicas hacia otros módulos:

  • reservation.client_id referencia a un cliente (Directorio/Clínica) por ID.
  • reservation.creator_user_id referencia a un usuario de IAM.
  • employee_service_config.service_id referencia a un ítem del módulo de Catálogo.
  • Los campos staff_id referencian al módulo de Personal (Staff).

Las reglas de disponibilidad (bloques + excepciones + la ventana diaria del establecimiento, cruzadas como DayBounds de webtyp.com/time) se aplican en la capa de servicio, no a través de FKs entre módulos. appointment_booking/go.mod mantiene cero dependencias de veltylabs — el límite del establecimiento es un puerto declarado aquí (BoundsReader), satisfecho estructuralmente por veltylabs/business_calendar. El estado de la reserva se controla mediante una FSM en código — sin tabla reservation_status.

Reglas de desarrollo (SKILL)

Restricciones y reglas principales
  • Cambios de estado solo vía FSM: Reservation.Status DEBE cambiar únicamente mediante FSM.Transition(current, event) — excepto al entrar o salir de CONFLICTED, que un recomputo escribe directamente y restaura a través de StatusBeforeConflict. Eventos válidos: CONFIRM, CANCEL, COMPLETE, NO_SHOW_EVENT, EXPIRE, RESCHEDULE, CONFLICT, RESOLVE.
  • RESCHEDULED ≠ CANCELLED: Cuando una reserva es reemplazada por una nueva, la original se marca como RESCHEDULED (no CANCELLED) para preservar la integridad de la traza de auditoría. Estos son estados terminales distintos. CONFLICTED no es terminal.
  • La zona horaria está en WorkCalendarConfig: WorkCalendarBlock y WorkCalendarException NO tienen campo de zona horaria. Siempre carga primero WorkCalendarConfig para obtener la zona horaria IANA. Las horas de los bloques son minutos locales desde la medianoche (p. ej., 540 = 09:00), convertidos a UTC en tiempo de consulta mediante LocalIntToUnixUTC.
  • Instantáneas (Snapshotting): Al crear una reserva, el precio, la moneda, la duración, el staffID y el serviceID se guardan en instantáneas. Nunca mutes los campos de instantánea después de la creación. StaffIdsnapshot/ServiceIdsnapshot usan los nombres de columna históricos staff_idsnapshot/service_idsnapshot — nunca renombrar.
  • Un cambio de agenda reporta sus conflictos: Cada edición profesional (save_day_blocks, save_date_blocks, mark_working_days, unmark_working_days, excepciones) recomputa las reservas futuras en el rango afectado y marca/limpia CONFLICTED. Los cambios a nivel de establecimiento van a través de RecomputeConflicts. Cuando nadie resulta afectado, no se publica nada (CU-19).
  • Sin RBAC aquí: Este módulo confía en actorID como una cadena ya autorizada. La autorización es aplicada por el gateway antes del servicio. Este módulo solo almacena actorID como campo de auditoría.
  • La publicación de eventos es de tipo "dispara y olvida" (fire-and-forget) a través del events.Publisher inyectado (Deps.Publisher). Un publisher nil es seguro.
  • Sin importaciones entre módulos. Las dependencias externas se acceden únicamente mediante interfaces inyectadas: StaffReader, CatalogReader, DirectoryReader, BoundsReader.
Interfaces inyectadas (parámetros del constructor)

El servicio mantiene *orm.DB directamente — sin interfaces de almacenamiento intermedias. Solo se inyectan dependencias entre módulos:

type Deps struct {
    Staff     StaffReader     // provisto por el módulo staff
    Catalog   CatalogReader   // provisto por el módulo catalog
    Directory DirectoryReader // provisto por el módulo directory
    IDs       model.IDGenerator // requerido — nunca se construye dentro del módulo
    Publisher events.Publisher  // nil = eventos deshabilitados
    Bounds    BoundsReader      // nil = sin límites (un profesional independiente sin establecimiento)
}

func New(db *orm.DB, deps Deps) (*Module, error)
Eventos de dominio publicados
Constante de evento Cuándo
appointment.reservation.created Después de que CreateReservation hace commit
appointment.reservation.rescheduled Para la reserva original durante la reprogramación
appointment.reservation.confirmed Después de la transición CONFIRM
appointment.reservation.cancelled Después de la transición CANCEL
appointment.reservation.completed Después de la transición COMPLETE
appointment.reservation.no_show Después de la transición NO_SHOW
appointment.reservation.expired Después de la transición EXPIRE
appointment.schedule.changed Una vez por profesional cuyo cambio de agenda puso ≥1 reserva en conflicto (payload ScheduleChangedPayload{TenantId, StaffId, FromDate, ToDate, ConflictCount})
appointment.reservation.conflicted Por reserva en conflicto, solo cuando el cambio provino de la edición del propio profesional
Errores centinela clave
Error Cuándo
ErrSlotTaken Horario no disponible o carrera de reserva concurrente
ErrConflict Mismatched de concurrencia optimista en actualizaciones de reservas
ErrCalendarConfigNotFound Guardar bloques antes de upsert_calendar_config
ErrInvalidBlock start_min no es < end_min, o fuera de 0..1439
ErrBlocksOverlap Dos bloques del mismo día se solapan
ErrBlockOutsideBusinessHours Un bloque cae fuera de la ventana de apertura del establecimiento
ErrBlockOnClosedDay El establecimiento está cerrado en esa fecha
ErrInvalidTransition La FSM rechaza el evento para el estado actual
Raíz de composición (cómo conectar este módulo)
// La creación del esquema es un paso en tiempo de despliegue (ver subpaquete migrate):
// err := migrate.Migrate(conn, ddlCompiler)

// New / NewRepository asume que el esquema de la base de datos ya existe.
scheduling, _ := appointmentbooking.New(db, appointmentbooking.Deps{
    Staff:     staffmodule.New(db),        // implementa StaffReader
    Catalog:   catalogmodule.New(db),      // implementa CatalogReader
    Directory: directorymodule.New(db),    // implementa DirectoryReader
    IDs:       idGen,                      // model.IDGenerator
    Publisher: eventBus,                   // nil = eventos deshabilitados
    Bounds:    businesscalendarModule,     // implementa BoundsReader; nil = sin límites
})
scheduling.MountOps(opRegistry)            // el transporte recolecta las ops
reservationsView := scheduling.NewView(caller, tenantId, staffId)

La recomputación a nivel de establecimiento es conectada por la aplicación (conoce ambos módulos):

broker.Subscribe(businesscalendar.EventCalendarChanged, func(ev events.Event) {
    var p businesscalendar.CalendarChangedPayload
    // decodificar; abrir más temprano nunca puede invalidar una reserva
    if !p.Closed {
        return
    }
    _, _ = book.RecomputeConflicts(config.TenantID, p.FromDate, p.ToDate)
})
Operaciones disponibles (23 en total)

create_reservation, get_reservation, list_reservations_by_staff, list_reservations_by_client, change_reservation_status, expire_pending_reservations, list_conflicting_reservations, recompute_conflicts, upsert_calendar_config, save_day_blocks, save_date_blocks, mark_working_days, unmark_working_days, list_blocks, get_day_bounds, add_calendar_exception, remove_calendar_exception, list_availability, list_exceptions, create_employee_service_config, get_employee_service_config, list_employee_service_configs_by_staff, update_employee_service_config

expire_pending_reservations es el único disparador para el evento FSM EXPIRE; debe ser llamado por un programador externo — el módulo no tiene procesos en segundo plano internos.

list_blocks y list_exceptions son las lecturas directas que necesita un editor de horarios; la vista orientada al llamador es NewScheduleClient (ver abajo).

ScheduleClient — la cara para el editor de horarios

NewScheduleClient(caller router.Caller, tenantId, staffId string) *ScheduleClient es un cliente tipado del lado del llamador sobre las operaciones de calendario, destinado a ser adaptado por una aplicación a un componente de interfaz scheduleeditor. Importando únicamente router + los tipos de este módulo, se mantiene agnóstico del renderizador:

cl := appointmentbooking.NewScheduleClient(caller, "t1", "s1")
cl.Blocks(func(rows []appointmentbooking.WorkCalendarBlock, err error) { /* … */ })
cl.SaveDayBlocks(dayOfWeek, blocks, func(err error) { /* … */ })
cl.Exceptions(from, to, func(rows []appointmentbooking.WorkCalendarException, err error) { /* … */ })
cl.AddException(exc, func(err error) { /* … */ })
cl.RemoveException(exceptionID, func(err error) { /* … */ })

Una mutación de agenda publica appointment.schedule.changed (con el rango afectado y recuento de conflictos) únicamente cuando realmente puso reservas en conflicto.

NewEmployeeServiceConfigView — la cara para gestionar servicios por profesional

NewEmployeeServiceConfigView(caller router.Caller, tenantId, staffId string) view.Presenter construye un presenter acotado a un profesional para listar y guardar la configuración de sus servicios (employee_service_config).

configView := appointmentbooking.NewEmployeeServiceConfigView(caller, tenantId, staffId)

NewFormView — la cara para pantallas de reserva

NewFormView(caller router.Caller, cfg FormConfig) view.Presenter construye un presenter que tanto lista las reservas de un profesional como crea nuevas. NewView se mantiene como la superficie de solo lista para consumidores de solo lectura.

formView := appointmentbooking.NewFormView(caller, appointmentbooking.FormConfig{
    TenantId:        tenantId,
    StaffId:         staffId,
    ServiceConfigId: serviceConfigId,
    Timezone:        "America/Santiago",
    From:            fromUnixSec,
    To:              toUnixSec,
    ActorId:         actorId,
    LabelFor: func(clientId string) string {
        // Punto de extensión opcional: traducir clientId a un nombre visible en la lista
        return directoryClientName(clientId)
    },
})

FreeSlots(caller, cfg, day) devuelve los horarios reservables para una fecha (p. ej. "2026-09-08") como cadenas "HH:MM" en la zona horaria configurada.

Interfaz de Servicio (SchedulingService)

type SchedulingService interface {
    // Gestión de calendario
    UpsertCalendarConfig(cfg WorkCalendarConfig) error
    SaveDayBlocks(tenantId, staffId string, dayOfWeek int, blocks []WorkCalendarBlock) error
    SaveDateBlocks(tenantId, staffId string, date int64, blocks []WorkCalendarBlock) error
    MarkWorkingDays(tenantId, staffId string, dates []int64, startMin, endMin int) error
    UnmarkWorkingDays(tenantId, staffId string, dates []int64) error
    ListBlocks(tenantId, staffId string) ([]WorkCalendarBlock, error)
    AddException(exc WorkCalendarException) error
    RemoveException(tenantId, exceptionId string) error
    ListExceptions(tenantId, staffId string, from, to int64) ([]WorkCalendarException, error)
    GetDayBounds(date int64) (tinytime.DayBounds, error)

    // Disponibilidad
    ListAvailability(tenantId, staffId, configId string, from, to int64) ([]TimeSlot, error)

    // Reservas
    CreateReservation(cmd CreateReservationCmd) (Reservation, error)
    GetReservation(tenantId, id string) (Reservation, error)
    ListReservationsByStaff(tenantId, staffId string, from, to int64) ([]Reservation, error)
    ListReservationsByClient(tenantId, clientId string) ([]Reservation, error)
    ChangeReservationStatus(cmd ChangeStatusCmd) error
    ExpirePendingReservations(tenantId string, before int64) (int, error)

    // Conflictos
    ListConflictingReservations(tenantId, staffId string, from int64) ([]ConflictingReservation, error)
    RecomputeConflicts(tenantId string, from, to int64) (int, error)
}

Esta interfaz depende de los lectores inyectados:

  • DirectoryReader — valida la existencia del cliente
  • StaffReader — valida la existencia del personal
  • CatalogReader — valida la existencia del servicio
  • BoundsReader — responde "qué minutos de una fecha son utilizables" (opcional)

Documentation

Index

Constants

View Source
const (
	StatusPending     = "PENDING"
	StatusConfirmed   = "CONFIRMED"
	StatusCancelled   = "CANCELLED"
	StatusCompleted   = "COMPLETED"
	StatusNoShow      = "NO_SHOW"
	StatusExpired     = "EXPIRED"     // reserva no pagada que expiró (disparador: scheduler externo vía MCP)
	StatusRescheduled = "RESCHEDULED" // reserva original reemplazada por una nueva (registro de auditoría)
	StatusConflicted  = "CONFLICTED"  // la agenda actual ya no cubre esta reserva — NO es terminal
)

Estados

View Source
const (
	EventConfirm    = "CONFIRM"
	EventCancel     = "CANCEL"
	EventComplete   = "COMPLETE"
	EventNoShow     = "NO_SHOW_EVENT"
	EventExpire     = "EXPIRE"
	EventReschedule = "RESCHEDULE" // marca la original como RESCHEDULED; la nueva reserva se crea atómicamente
	EventConflict   = "CONFLICT"   // una recomputación pone la reserva en conflicto
	EventResolve    = "RESOLVE"    // una recomputación la saca del conflicto
)

Eventos

View Source
const (
	OpCreateReservation                 = "create_reservation"
	OpGetReservation                    = "get_reservation"
	OpListReservationsByStaff           = "list_reservations_by_staff"
	OpListReservationsByClient          = "list_reservations_by_client"
	OpChangeReservationStatus           = "change_reservation_status"
	OpExpirePendingReservations         = "expire_pending_reservations"
	OpUpsertCalendarConfig              = "upsert_calendar_config"
	OpSaveDayBlocks                     = "save_day_blocks"
	OpSaveDateBlocks                    = "save_date_blocks"
	OpMarkWorkingDays                   = "mark_working_days"
	OpUnmarkWorkingDays                 = "unmark_working_days"
	OpListBlocks                        = "list_blocks"
	OpGetDayBounds                      = "get_day_bounds"
	OpAddCalendarException              = "add_calendar_exception"
	OpRemoveCalendarException           = "remove_calendar_exception"
	OpListAvailability                  = "list_availability"
	OpListExceptions                    = "list_exceptions"
	OpListConflictingReservations       = "list_conflicting_reservations"
	OpRecomputeConflicts                = "recompute_conflicts"
	OpCreateEmployeeServiceConfig       = "create_employee_service_config"
	OpGetEmployeeServiceConfig          = "get_employee_service_config"
	OpListEmployeeServiceConfigsByStaff = "list_employee_service_configs_by_staff"
	OpUpdateEmployeeServiceConfig       = "update_employee_service_config"
)
View Source
const (
	ExcHoliday      = "HOLIDAY"
	ExcSpecialHours = "SPECIAL_HOURS"
	ExcBlocked      = "BLOCKED"
)

Tipos de excepción de calendario (valor de WorkCalendarException.ExceptionType).

View Source
const (
	EventReservationCreated     = "appointment.reservation.created"
	EventReservationConfirmed   = "appointment.reservation.confirmed"
	EventReservationCancelled   = "appointment.reservation.cancelled"
	EventReservationCompleted   = "appointment.reservation.completed"
	EventReservationNoShow      = "appointment.reservation.no_show"
	EventReservationExpired     = "appointment.reservation.expired"
	EventReservationRescheduled = "appointment.reservation.rescheduled"
	// EventReservationConflicted se emite UNA VEZ POR reserva cuando un cambio
	// vino de la edición del propio profesional (§8.2) — el notificador llega al
	// paciente sin sondeo. El caso establishment-wide (feriado/cierre que golpea
	// a decenas de profesionales) publica SOLO el summary por staff y el
	// consumidor lee ListConflictingReservations (§8.6).
	EventReservationConflicted = "appointment.reservation.conflicted"
	// EventScheduleChanged se emite al mutar la agenda de un profesional o
	// recomputar conflictos tras un cambio del establecimiento. Un consumidor lo
	// usa para recalcular disponibilidad / notificar (p. ej. reservation recarga
	// sus huecos libres). Solo se emite cuando el cambio PUSO reservas en
	// conflicto (CU-19: sin afectados ⇒ silencio).
	EventScheduleChanged = "appointment.schedule.changed"
)

Eventos de dominio emitidos por este módulo.

View Source
const (
	ConflictReasonOutsideBlocks        = "OUTSIDE_BLOCKS"
	ConflictReasonDayClosed            = "DAY_CLOSED"
	ConflictReasonOutsideBusinessHours = "OUTSIDE_BUSINESS_HOURS"
)

Motivos de ConflictingReservation.Reason — el vocabulario NEUTRO del módulo. Concretamente NO arrastra la razón del establecimiento (por qué un día está cerrado): time.DayBounds lo omite deliberadamente y este módulo lo respeta.

View Source
const ConflictHorizonDays = 370

ConflictHorizonDays es el forward horizon del módulo: cuando no hay rango que acote (un cambio semanal, o to == 0), los conflictos se evalúan hasta aquí.

View Source
const ModelName = "appointment_booking"

ModelName is this module's identity: mcp.HarvestOps qualifies every op above as "appointment_booking.<name>" on the wire — the qualification that makes this module's own "get_day_bounds" distinct from business_calendar's op of the same bare name (the collision this whole mechanism exists to make unrepresentable).

Unlike the other modules in this ecosystem, this package builds its own Lister/Saver implementations directly (lister.go, schedule_client.go, view.go) instead of going through view.NewCallerLister — so it cannot lean on view.Ops.Module to compose the qualified name automatically. qualifiedOp (below) is the single place that composition happens instead; every caller.Call site in this package goes through it.

Variables

View Source
var (
	ErrNotFound = fmt.Err("record", "not", "found")
	ErrConflict = fmt.Err("optimistic", "concurrency", "conflict")
)

Errores sentinela a nivel de paquete

View Source
var (
	ErrCalendarConfigNotFound    = fmt.Err("calendar", "config", "not", "found")
	ErrSlotTaken                 = fmt.Err("slot", "taken")
	ErrInvalidBlock              = fmt.Err("appointment_booking: start_min must be < end_min and both within 0..1439")
	ErrBlocksOverlap             = fmt.Err("appointment_booking: two blocks of the same day overlap")
	ErrBlockOutsideBusinessHours = fmt.Err("appointment_booking: block falls outside the establishment's opening hours")
	ErrBlockOnClosedDay          = fmt.Err("appointment_booking: the establishment is closed on that date")
	ErrNoServiceConfig           = fmt.Err("appointment_booking: FormConfig.ServiceConfigId is required to book — the professional has no service configured")
	ErrIncompleteSlot            = fmt.Err("appointment_booking: a booking needs both a day and an hour")
)
View Source
var AddCalendarExceptionArgsModel = model.Definition{
	Name: "add_calendar_exception_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "specific_date", Type: input.Number()},
		{Name: "exception_type", Type: input.Text()},
		{Name: "start_time", Type: input.Number()},
		{Name: "end_time", Type: input.Number()},
		{Name: "notes", Type: input.Text()},
	},
}
View Source
var ChangeReservationStatusArgsModel = model.Definition{
	Name: "change_reservation_status_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "id", Type: input.Text()},
		{Name: "event", Type: input.Text()},
		{Name: "actor_id", Type: input.Text()},
		{Name: "payment_id", Type: input.Text()},
		{Name: "revision", Type: input.Number()},
	},
}
View Source
var ConflictingReservationModel = model.Definition{
	Name: "conflicting_reservation",
	Fields: model.Fields{
		{Name: "reservation_id", Type: model.Text()},
		{Name: "starts_at", Type: model.Int()},
		{Name: "client_id", Type: model.Text()},
		{Name: "reason", Type: model.Text()},
	},
}

ConflictingReservationModel es transport-only (salida de list_conflicting_reservations / recompute_conflicts) — nunca se renderiza como form editable.

View Source
var CreateEmployeeServiceConfigArgsModel = model.Definition{
	Name: "create_employee_service_config_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "service_id", Type: input.Text()},
		{Name: "duration_min", Type: input.Number()},
		{Name: "buffer_min", Type: input.Number()},
		{Name: "price_override", Type: input.Decimal()},
		{Name: "payment_required", Type: input.Checkbox()},
	},
}
View Source
var CreateReservationArgsModel = model.Definition{
	Name: "create_reservation_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "client_id", Type: input.Text()},
		{Name: "creator_user_id", Type: input.Text()},
		{Name: "employee_service_config_id", Type: input.Text()},
		{Name: "slot_start_utc", Type: input.Number()},
		{Name: "notes", Type: input.Text()},
		{Name: "rescheduled_from_id", Type: input.Text()},
	},
}
View Source
var DayBoundsResultModel = model.Definition{
	Name: "day_bounds_result",
	Fields: model.Fields{
		{Name: "open", Type: model.Bool()},
		{Name: "open_min", Type: model.Int()},
		{Name: "close_min", Type: model.Int()},
	},
}

DayBoundsResultModel es transport-only (salida de get_day_bounds) — la proyección encodable de time.DayBounds para que el editor acote sus controles (§6.2). time.DayBounds NO es model.Encodable, así que se cruza por esta forma.

View Source
var EmployeeServiceConfigModel = model.Definition{
	Name: "employee_service_config",
	Fields: model.Fields{
		{Name: "id", Type: model.Text(), DB: &model.FieldDB{PK: true}, OmitEmpty: true},
		{Name: "tenant_id", Type: model.Text(), NotNull: true},
		{Name: "staff_id", Type: input.Text(), NotNull: true},
		{Name: "service_id", Type: input.Text(), NotNull: true},
		{Name: "duration_min", Type: input.Number()},
		{Name: "buffer_min", Type: input.Number()},
		{Name: "price_override", Type: input.Decimal()},
		{Name: "payment_required", Type: input.Checkbox()},
		{Name: "is_active", Type: input.Checkbox()},
	},
}

EmployeeServiceConfigModel: que servicios realiza un profesional, durante cuanto tiempo y a que precio. La política de widgets es POR ROL, la misma regla que cada modelo de transporte a continuación: input.X() en cada campo que edita una persona. A diferencia de Reservation, esta tabla NO lleva campos solo de auditoría para proteger de convertirse en editable en un formulario — cada columna excepto id/tenant_id es legítimamente orientada al usuario, por lo que los widgets van directamente en el modelo persistido; no hay proyección de formulario separada.

View Source
var EmployeeServiceConfig_ = struct {
	Id              string
	TenantId        string
	StaffId         string
	ServiceId       string
	DurationMin     string
	BufferMin       string
	PriceOverride   string
	PaymentRequired string
	IsActive        string
}{
	Id:              "id",
	TenantId:        "tenant_id",
	StaffId:         "staff_id",
	ServiceId:       "service_id",
	DurationMin:     "duration_min",
	BufferMin:       "buffer_min",
	PriceOverride:   "price_override",
	PaymentRequired: "payment_required",
	IsActive:        "is_active",
}
View Source
var ErrInvalidTransition = fmt.Err("invalid", "transition")

ErrInvalidTransition se devuelve cuando una transición no está permitida.

View Source
var ExpirePendingReservationsArgsModel = model.Definition{
	Name: "expire_pending_reservations_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "before", Type: input.Number()},
	},
}
View Source
var GetDayBoundsArgsModel = model.Definition{
	Name: "get_day_bounds_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "date", Type: input.Number()},
	},
}
View Source
var GetEmployeeServiceConfigArgsModel = model.Definition{
	Name: "get_employee_service_config_args",
	Fields: model.Fields{
		{Name: "id", Type: model.Text()},
	},
}
View Source
var GetReservationArgsModel = model.Definition{
	Name: "get_reservation_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "id", Type: input.Text()},
	},
}
View Source
var ListAvailabilityArgsModel = model.Definition{
	Name: "list_availability_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "config_id", Type: input.Text()},
		{Name: "from", Type: input.Number()},
		{Name: "to", Type: input.Number()},
	},
}
View Source
var ListBlocksArgsModel = model.Definition{
	Name: "list_blocks_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
	},
}
View Source
var ListConflictingReservationsArgsModel = model.Definition{
	Name: "list_conflicting_reservations_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "from", Type: input.Number()},
	},
}
View Source
var ListEmployeeServiceConfigsByStaffArgsModel = model.Definition{
	Name: "list_employee_service_configs_by_staff_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
	},
}
View Source
var ListExceptionsArgsModel = model.Definition{
	Name: "list_exceptions_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "from", Type: input.Number()},
		{Name: "to", Type: input.Number()},
	},
}
View Source
var ListReservationsByClientArgsModel = model.Definition{
	Name: "list_reservations_by_client_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "client_id", Type: input.Text()},
	},
}
View Source
var ListReservationsByStaffArgsModel = model.Definition{
	Name: "list_reservations_by_staff_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "from", Type: input.Number()},
		{Name: "to", Type: input.Number()},
	},
}
View Source
var MarkWorkingDaysArgsModel = model.Definition{
	Name: "mark_working_days_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "dates", Type: model.IntSlice()},
		{Name: "start_min", Type: input.Number()},
		{Name: "end_min", Type: input.Number()},
	},
}
View Source
var RecomputeConflictsArgsModel = model.Definition{
	Name: "recompute_conflicts_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "from", Type: input.Number()},
		{Name: "to", Type: input.Number()},
	},
}
View Source
var RemoveCalendarExceptionArgsModel = model.Definition{
	Name: "remove_calendar_exception_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "exception_id", Type: input.Text()},
	},
}
View Source
var ReservationFormModel = model.Definition{
	Name: "reservation_form",
	Fields: model.Fields{
		{Name: "id", Type: input.Text(), NotNull: true, DB: &model.FieldDB{PK: true}},
		{Name: "client_id", Type: input.Text(), NotNull: true},
		{Name: "day", Type: input.Date(), NotNull: true},
		{Name: "hour", Type: input.Hour(), NotNull: true},
		{Name: "notes", Type: input.Textarea()},
		{Name: "status", Type: model.Text()},
	},
}

ReservationFormModel es la PROYECCIÓN DE FORMULARIO de una reserva: los seis valores que una persona realmente completa o lee al reservar en un mostrador. NO es una tabla — nunca se pasa a migrate.Migrate, y `migrate/migrate.go` crea exactamente cinco tablas, ninguna de ellas esta.

Existe porque los campos de ReservationModel usan tipos base (model.Text() y similares) a propósito: es una fila de BD, y webtyp/form omite cualquier campo cuyo Type no sea input.Input. Un formulario construido sobre Reservation no renderizaría nada. Los dos tipos se mantienen separados en lugar de fusionarse para que los campos de auditoría de una reserva (instantáneas, revisión, status_before_conflict, rescheduled_from_id) nunca emerjan como entradas editables.

La política de widgets es POR ROL, la misma regla que siguen los modelos de transporte: input.X() solo en lo que una persona edita; un tipo base en lo que se muestra y nunca se escribe. Por lo tanto, status es model.Text(): se muestra en la lista y no es accesible desde el formulario, porque status solo cambia a través del FSM (ChangeReservationStatus).

View Source
var ReservationForm_ = struct {
	Id       string
	ClientId string
	Day      string
	Hour     string
	Notes    string
	Status   string
}{
	Id:       "id",
	ClientId: "client_id",
	Day:      "day",
	Hour:     "hour",
	Notes:    "notes",
	Status:   "status",
}
View Source
var ReservationModel = model.Definition{
	Name: "reservation",
	Fields: model.Fields{
		{Name: "id", Type: model.Text(), DB: &model.FieldDB{PK: true}},
		{Name: "tenant_id", Type: model.Text(), NotNull: true},
		{Name: "client_id", Type: model.Text(), NotNull: true},
		{Name: "creator_user_id", Type: model.Text()},
		{Name: "employee_service_config_id", Type: model.Text(), NotNull: true},
		{Name: "staff_idsnapshot", Type: model.Text()},
		{Name: "service_idsnapshot", Type: model.Text()},
		{Name: "duration_min_snapshot", Type: model.Int()},
		{Name: "price_snapshot", Type: model.Float()},
		{Name: "currency_snapshot", Type: model.Text()},
		{Name: "reservation_date", Type: model.Int()},
		{Name: "reservation_time", Type: model.Int()},
		{Name: "local_string_date", Type: model.Text()},
		{Name: "local_string_time", Type: model.Text()},

		{Name: "status", Type: model.Text(), NotNull: true},
		{Name: "rescheduled_from_id", Type: model.Text()},

		{Name: "status_before_conflict", Type: model.Text()},
		{Name: "payment_id", Type: model.Text()},
		{Name: "notes", Type: model.Text()},
		{Name: "updated_at", Type: model.Int()},
		{Name: "updated_by", Type: model.Text()},
		{Name: "revision", Type: model.Int()},
	},
}

NOTA: "staff_idsnapshot" / "service_idsnapshot" preservan EXACTAMENTE el nombre de columna actual (irregularidad histórica, sin guión bajo) — NO renombrar la columna, la tabla ya existe con ese nombre en producción.

View Source
var Reservation_ = struct {
	Id                      string
	TenantId                string
	ClientId                string
	CreatorUserId           string
	EmployeeServiceConfigId string
	StaffIdsnapshot         string
	ServiceIdsnapshot       string
	DurationMinSnapshot     string
	PriceSnapshot           string
	CurrencySnapshot        string
	ReservationDate         string
	ReservationTime         string
	LocalStringDate         string
	LocalStringTime         string
	Status                  string
	RescheduledFromId       string
	StatusBeforeConflict    string
	PaymentId               string
	Notes                   string
	UpdatedAt               string
	UpdatedBy               string
	Revision                string
}{
	Id:                      "id",
	TenantId:                "tenant_id",
	ClientId:                "client_id",
	CreatorUserId:           "creator_user_id",
	EmployeeServiceConfigId: "employee_service_config_id",
	StaffIdsnapshot:         "staff_idsnapshot",
	ServiceIdsnapshot:       "service_idsnapshot",
	DurationMinSnapshot:     "duration_min_snapshot",
	PriceSnapshot:           "price_snapshot",
	CurrencySnapshot:        "currency_snapshot",
	ReservationDate:         "reservation_date",
	ReservationTime:         "reservation_time",
	LocalStringDate:         "local_string_date",
	LocalStringTime:         "local_string_time",
	Status:                  "status",
	RescheduledFromId:       "rescheduled_from_id",
	StatusBeforeConflict:    "status_before_conflict",
	PaymentId:               "payment_id",
	Notes:                   "notes",
	UpdatedAt:               "updated_at",
	UpdatedBy:               "updated_by",
	Revision:                "revision",
}
View Source
var SaveDateBlocksArgsModel = model.Definition{
	Name: "save_date_blocks_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "specific_date", Type: input.Number()},
		{Name: "blocks", Type: model.StructSlice(&WorkCalendarBlockModel)},
	},
}
View Source
var SaveDayBlocksArgsModel = model.Definition{
	Name: "save_day_blocks_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "day_of_week", Type: input.Number()},
		{Name: "blocks", Type: model.StructSlice(&WorkCalendarBlockModel)},
	},
}
View Source
var TimeSlotModel = model.Definition{
	Name: "time_slot",
	Fields: model.Fields{
		{Name: "start_utc", Type: model.Int()},
		{Name: "end_utc", Type: model.Int()},
	},
}
View Source
var UnmarkWorkingDaysArgsModel = model.Definition{
	Name: "unmark_working_days_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "dates", Type: model.IntSlice()},
	},
}
View Source
var UpsertCalendarConfigArgsModel = model.Definition{
	Name: "upsert_calendar_config_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "timezone", Type: input.Text()},
		{Name: "is_active", Type: input.Checkbox()},
	},
}
View Source
var WorkCalendarBlockModel = model.Definition{
	Name: "work_calendar_block",
	Fields: model.Fields{
		{Name: "id", Type: model.Text(), DB: &model.FieldDB{PK: true}},
		{Name: "tenant_id", Type: model.Text(), NotNull: true},
		{Name: "staff_id", Type: model.Text(), NotNull: true},
		{Name: "day_of_week", Type: model.Int(), NotNull: true},
		{Name: "specific_date", Type: model.Int(), NotNull: true},
		{Name: "start_min", Type: model.Int(), NotNull: true},
		{Name: "end_min", Type: model.Int(), NotNull: true},
		{Name: "is_active", Type: model.Bool(), NotNull: true},
	},
}

WorkCalendarBlockModel: one row per block of working time. A day may hold several — "morning 09:00–13:00, afternoon 15:00–19:00" is two rows, and the lunch break is the GAP between them. There is deliberately no break field: a break that is a column can only ever describe one interruption, and the gap describes any number.

specific_date == 0 → the block is WEEKLY and applies to day_of_week. specific_date > 0 → the block is DATED and applies to that date only,

and day_of_week carries no meaning.

A dated block OPENS its day whether or not a weekly block covers that weekday. That is what lets an irregular professional mark the days they work with no weekly template at all.

View Source
var WorkCalendarBlock_ = struct {
	Id           string
	TenantId     string
	StaffId      string
	DayOfWeek    string
	SpecificDate string
	StartMin     string
	EndMin       string
	IsActive     string
}{
	Id:           "id",
	TenantId:     "tenant_id",
	StaffId:      "staff_id",
	DayOfWeek:    "day_of_week",
	SpecificDate: "specific_date",
	StartMin:     "start_min",
	EndMin:       "end_min",
	IsActive:     "is_active",
}
View Source
var WorkCalendarConfigModel = model.Definition{
	Name: "work_calendar_config",
	Fields: model.Fields{
		{Name: "id", Type: model.Text(), DB: &model.FieldDB{PK: true}},
		{Name: "tenant_id", Type: model.Text(), NotNull: true},
		{Name: "staff_id", Type: model.Text(), NotNull: true},
		{Name: "timezone", Type: model.Text(), NotNull: true},
		{Name: "is_active", Type: model.Bool()},
	},
}
View Source
var WorkCalendarConfig_ = struct {
	Id       string
	TenantId string
	StaffId  string
	Timezone string
	IsActive string
}{
	Id:       "id",
	TenantId: "tenant_id",
	StaffId:  "staff_id",
	Timezone: "timezone",
	IsActive: "is_active",
}
View Source
var WorkCalendarExceptionModel = model.Definition{
	Name: "work_calendar_exception",
	Fields: model.Fields{
		{Name: "id", Type: model.Text(), DB: &model.FieldDB{PK: true}},
		{Name: "tenant_id", Type: model.Text(), NotNull: true},
		{Name: "staff_id", Type: model.Text(), NotNull: true},
		{Name: "specific_date", Type: model.Int()},
		{Name: "exception_type", Type: model.Text()},
		{Name: "start_time", Type: model.Int()},
		{Name: "end_time", Type: model.Int()},
		{Name: "notes", Type: model.Text()},
	},
}
View Source
var WorkCalendarException_ = struct {
	Id            string
	TenantId      string
	StaffId       string
	SpecificDate  string
	ExceptionType string
	StartTime     string
	EndTime       string
	Notes         string
}{
	Id:            "id",
	TenantId:      "tenant_id",
	StaffId:       "staff_id",
	SpecificDate:  "specific_date",
	ExceptionType: "exception_type",
	StartTime:     "start_time",
	EndTime:       "end_time",
	Notes:         "notes",
}

Functions

func FreeSlots added in v0.1.7

func FreeSlots(caller router.Caller, cfg FormConfig, day string) ([]string, error)

FreeSlots devuelve los huecos reservables de un día como cadenas "HH:MM" en cfg.Timezone, listos para que un widget de lista los renderice como filas vacías.

day es "YYYY-MM-DD". Devuelve nil (sin error) cuando el alcance está incompleto — sin staff o sin configuración de servicio significa que no hay nada que calcular, no un fallo.

func IsTerminal

func IsTerminal(status string) bool

IsTerminal devuelve true si el estado no tiene transiciones salientes.

func LocalIntToUnixUTC

func LocalIntToUnixUTC(date int64, localInt int, tz string) int64

LocalIntToUnixUTC interpreta localInt como minutos desde la medianoche en la fecha dada (medianoche UTC) en la zona horaria (tz) especificada.

func NewEmployeeServiceConfigView added in v0.1.8

func NewEmployeeServiceConfigView(caller router.Caller, tenantId, staffId string) view.Presenter

NewEmployeeServiceConfigView builds a Presenter scoped to one professional — same shape as NewView(caller, tenantId, staffId) above: there is no "list every service config in the tenant" op, on purpose, mirroring why NewView itself is staff-scoped.

func NewFormView added in v0.1.7

func NewFormView(caller router.Caller, cfg FormConfig) view.Presenter

NewFormView construye un presenter que TANTO LISTA las reservas de un profesional COMO CREA nuevas — la superficie que necesita una pantalla de reservas. NewView, arriba, sigue siendo la superficie solo de lista para un consumidor de solo lectura.

func NewView

func NewView(caller router.Caller, tenantId, staffId string) view.Presenter

NewView construye el Presenter de Reservation — acotado al horario de un solo staff, ya que no existe una operación "listar todas las reservas de un tenant" sin acotar (ver docs/ARCHITECTURE.md §7). Solo lista: sin capacidad Saver/Deleter (las reservas solo mutan vía las transiciones FSM-guardadas de ChangeReservationStatus, y nunca se eliminan físicamente).

func Transition

func Transition(current, event string) (string, error)

Transition devuelve el siguiente estado, o un error si la transición no es válida.

Types

type AddCalendarExceptionArgs

type AddCalendarExceptionArgs struct {
	TenantId      string
	StaffId       string
	SpecificDate  int64
	ExceptionType string
	StartTime     int64
	EndTime       int64
	Notes         string
}

func (*AddCalendarExceptionArgs) DecodeFields

func (m *AddCalendarExceptionArgs) DecodeFields(r model.FieldReader)

func (*AddCalendarExceptionArgs) EncodeFields

func (m *AddCalendarExceptionArgs) EncodeFields(w model.FieldWriter)

func (*AddCalendarExceptionArgs) IsNil

func (m *AddCalendarExceptionArgs) IsNil() bool

func (*AddCalendarExceptionArgs) ModelName

func (m *AddCalendarExceptionArgs) ModelName() string

func (*AddCalendarExceptionArgs) Pointers

func (m *AddCalendarExceptionArgs) Pointers() []any

func (*AddCalendarExceptionArgs) Schema

func (m *AddCalendarExceptionArgs) Schema() []model.Field

func (*AddCalendarExceptionArgs) Validate

func (m *AddCalendarExceptionArgs) Validate(action byte) error

type AddCalendarExceptionArgsList

type AddCalendarExceptionArgsList []*AddCalendarExceptionArgs

func (*AddCalendarExceptionArgsList) Append

func (*AddCalendarExceptionArgsList) At

func (*AddCalendarExceptionArgsList) DecodeFields

func (s *AddCalendarExceptionArgsList) DecodeFields(_ model.FieldReader)

func (*AddCalendarExceptionArgsList) EncodeFields

func (s *AddCalendarExceptionArgsList) EncodeFields(_ model.FieldWriter)

func (*AddCalendarExceptionArgsList) IsNil

func (*AddCalendarExceptionArgsList) Len

type BoundsReader added in v0.1.5

type BoundsReader interface {
	GetDayBounds(date int64) (tinytime.DayBounds, error)
}

BoundsReader answers "which minutes of this date are usable at all".

Declared here, not imported: a booking module must not depend on any particular institutional calendar. Anything that can answer the question satisfies it — veltylabs/business_calendar does, and so would a static config or a different organisation's calendar.

date is midnight UTC in seconds.

type CatalogReader

type CatalogReader interface {
	ServiceExists(tenantId, serviceId string) (bool, error)
}

CatalogReader verifica que un servicio existe y pertenece al tenant.

type ChangeReservationStatusArgs

type ChangeReservationStatusArgs struct {
	TenantId  string
	Id        string
	Event     string
	ActorId   string
	PaymentId string
	Revision  int64
}

func (*ChangeReservationStatusArgs) DecodeFields

func (m *ChangeReservationStatusArgs) DecodeFields(r model.FieldReader)

func (*ChangeReservationStatusArgs) EncodeFields

func (m *ChangeReservationStatusArgs) EncodeFields(w model.FieldWriter)

func (*ChangeReservationStatusArgs) IsNil

func (m *ChangeReservationStatusArgs) IsNil() bool

func (*ChangeReservationStatusArgs) ModelName

func (m *ChangeReservationStatusArgs) ModelName() string

func (*ChangeReservationStatusArgs) Pointers

func (m *ChangeReservationStatusArgs) Pointers() []any

func (*ChangeReservationStatusArgs) Schema

func (m *ChangeReservationStatusArgs) Schema() []model.Field

func (*ChangeReservationStatusArgs) Validate

func (m *ChangeReservationStatusArgs) Validate(action byte) error

type ChangeReservationStatusArgsList

type ChangeReservationStatusArgsList []*ChangeReservationStatusArgs

func (*ChangeReservationStatusArgsList) Append

func (*ChangeReservationStatusArgsList) At

func (*ChangeReservationStatusArgsList) DecodeFields

func (*ChangeReservationStatusArgsList) EncodeFields

func (*ChangeReservationStatusArgsList) IsNil

func (*ChangeReservationStatusArgsList) Len

type ChangeStatusCmd

type ChangeStatusCmd struct {
	TenantId  string
	Id        string
	Event     string
	ActorId   string
	PaymentId string
	Revision  int
}

type ConflictingReservation added in v0.1.5

type ConflictingReservation struct {
	ReservationId string
	StartsAt      int64
	ClientId      string
	Reason        string
}

func (*ConflictingReservation) DecodeFields added in v0.1.5

func (m *ConflictingReservation) DecodeFields(r model.FieldReader)

func (*ConflictingReservation) EncodeFields added in v0.1.5

func (m *ConflictingReservation) EncodeFields(w model.FieldWriter)

func (*ConflictingReservation) IsNil added in v0.1.5

func (m *ConflictingReservation) IsNil() bool

func (*ConflictingReservation) ModelName added in v0.1.5

func (m *ConflictingReservation) ModelName() string

func (*ConflictingReservation) Pointers added in v0.1.5

func (m *ConflictingReservation) Pointers() []any

func (*ConflictingReservation) Schema added in v0.1.5

func (m *ConflictingReservation) Schema() []model.Field

func (*ConflictingReservation) Validate added in v0.1.5

func (m *ConflictingReservation) Validate(action byte) error

type ConflictingReservationList added in v0.1.5

type ConflictingReservationList []*ConflictingReservation

func (*ConflictingReservationList) Append added in v0.1.5

func (*ConflictingReservationList) At added in v0.1.5

func (*ConflictingReservationList) DecodeFields added in v0.1.5

func (s *ConflictingReservationList) DecodeFields(_ model.FieldReader)

func (*ConflictingReservationList) EncodeFields added in v0.1.5

func (s *ConflictingReservationList) EncodeFields(_ model.FieldWriter)

func (*ConflictingReservationList) IsNil added in v0.1.5

func (s *ConflictingReservationList) IsNil() bool

func (*ConflictingReservationList) Len added in v0.1.5

type CreateEmployeeServiceConfigArgs added in v0.1.8

type CreateEmployeeServiceConfigArgs struct {
	TenantId        string
	StaffId         string
	ServiceId       string
	DurationMin     int64
	BufferMin       int64
	PriceOverride   float64
	PaymentRequired bool
}

func (*CreateEmployeeServiceConfigArgs) DecodeFields added in v0.1.8

func (*CreateEmployeeServiceConfigArgs) EncodeFields added in v0.1.8

func (*CreateEmployeeServiceConfigArgs) IsNil added in v0.1.8

func (*CreateEmployeeServiceConfigArgs) ModelName added in v0.1.8

func (m *CreateEmployeeServiceConfigArgs) ModelName() string

func (*CreateEmployeeServiceConfigArgs) Pointers added in v0.1.8

func (m *CreateEmployeeServiceConfigArgs) Pointers() []any

func (*CreateEmployeeServiceConfigArgs) Schema added in v0.1.8

func (*CreateEmployeeServiceConfigArgs) Validate added in v0.1.8

func (m *CreateEmployeeServiceConfigArgs) Validate(action byte) error

type CreateEmployeeServiceConfigArgsList added in v0.1.8

type CreateEmployeeServiceConfigArgsList []*CreateEmployeeServiceConfigArgs

func (*CreateEmployeeServiceConfigArgsList) Append added in v0.1.8

func (*CreateEmployeeServiceConfigArgsList) At added in v0.1.8

func (*CreateEmployeeServiceConfigArgsList) DecodeFields added in v0.1.8

func (*CreateEmployeeServiceConfigArgsList) EncodeFields added in v0.1.8

func (*CreateEmployeeServiceConfigArgsList) IsNil added in v0.1.8

func (*CreateEmployeeServiceConfigArgsList) Len added in v0.1.8

type CreateReservationArgs

type CreateReservationArgs struct {
	TenantId                string
	ClientId                string
	CreatorUserId           string
	EmployeeServiceConfigId string
	SlotStartUtc            int64
	Notes                   string
	RescheduledFromId       string
}

func (*CreateReservationArgs) DecodeFields

func (m *CreateReservationArgs) DecodeFields(r model.FieldReader)

func (*CreateReservationArgs) EncodeFields

func (m *CreateReservationArgs) EncodeFields(w model.FieldWriter)

func (*CreateReservationArgs) IsNil

func (m *CreateReservationArgs) IsNil() bool

func (*CreateReservationArgs) ModelName

func (m *CreateReservationArgs) ModelName() string

func (*CreateReservationArgs) Pointers

func (m *CreateReservationArgs) Pointers() []any

func (*CreateReservationArgs) Schema

func (m *CreateReservationArgs) Schema() []model.Field

func (*CreateReservationArgs) Validate

func (m *CreateReservationArgs) Validate(action byte) error

type CreateReservationArgsList

type CreateReservationArgsList []*CreateReservationArgs

func (*CreateReservationArgsList) Append

func (*CreateReservationArgsList) At

func (*CreateReservationArgsList) DecodeFields

func (s *CreateReservationArgsList) DecodeFields(_ model.FieldReader)

func (*CreateReservationArgsList) EncodeFields

func (s *CreateReservationArgsList) EncodeFields(_ model.FieldWriter)

func (*CreateReservationArgsList) IsNil

func (s *CreateReservationArgsList) IsNil() bool

func (*CreateReservationArgsList) Len

func (s *CreateReservationArgsList) Len() int

type CreateReservationCmd

type CreateReservationCmd struct {
	TenantId                string
	ClientId                string
	CreatorUserId           string
	EmployeeServiceConfigId string
	SlotStartUtc            int64
	Notes                   string
	RescheduledFromId       string
}

type DayBoundsResult added in v0.1.5

type DayBoundsResult struct {
	Open     bool
	OpenMin  int64
	CloseMin int64
}

func (*DayBoundsResult) DecodeFields added in v0.1.5

func (m *DayBoundsResult) DecodeFields(r model.FieldReader)

func (*DayBoundsResult) EncodeFields added in v0.1.5

func (m *DayBoundsResult) EncodeFields(w model.FieldWriter)

func (*DayBoundsResult) IsNil added in v0.1.5

func (m *DayBoundsResult) IsNil() bool

func (*DayBoundsResult) ModelName added in v0.1.5

func (m *DayBoundsResult) ModelName() string

func (*DayBoundsResult) Pointers added in v0.1.5

func (m *DayBoundsResult) Pointers() []any

func (*DayBoundsResult) Schema added in v0.1.5

func (m *DayBoundsResult) Schema() []model.Field

func (*DayBoundsResult) Validate added in v0.1.5

func (m *DayBoundsResult) Validate(action byte) error

type DayBoundsResultList added in v0.1.5

type DayBoundsResultList []*DayBoundsResult

func (*DayBoundsResultList) Append added in v0.1.5

func (s *DayBoundsResultList) Append() model.Fielder

func (*DayBoundsResultList) At added in v0.1.5

func (*DayBoundsResultList) DecodeFields added in v0.1.5

func (s *DayBoundsResultList) DecodeFields(_ model.FieldReader)

func (*DayBoundsResultList) EncodeFields added in v0.1.5

func (s *DayBoundsResultList) EncodeFields(_ model.FieldWriter)

func (*DayBoundsResultList) IsNil added in v0.1.5

func (s *DayBoundsResultList) IsNil() bool

func (*DayBoundsResultList) Len added in v0.1.5

func (s *DayBoundsResultList) Len() int

type Deps

type Deps struct {
	Staff     StaffReader
	Catalog   CatalogReader
	Directory DirectoryReader
	IDs       model.IDGenerator // requerido
	Publisher events.Publisher  // opcional — nil desactiva
	// Bounds constrains every block to the institution's usable window.
	// OPTIONAL: nil means unbounded, which is correct for an app with no
	// institution above the professional (a freelancer's booking page).
	Bounds BoundsReader
}

type DirectoryReader

type DirectoryReader interface {
	ClientExists(tenantId, clientId string) (bool, error)
}

DirectoryReader verifica que un cliente existe y pertenece al tenant.

type EmployeeServiceConfig

type EmployeeServiceConfig struct {
	Id              string
	TenantId        string
	StaffId         string
	ServiceId       string
	DurationMin     int64
	BufferMin       int64
	PriceOverride   float64
	PaymentRequired bool
	IsActive        bool
}

func ReadOneEmployeeServiceConfig

func ReadOneEmployeeServiceConfig(qb *orm.QB, model *EmployeeServiceConfig) (*EmployeeServiceConfig, error)

func (*EmployeeServiceConfig) DecodeFields

func (m *EmployeeServiceConfig) DecodeFields(r model.FieldReader)

func (*EmployeeServiceConfig) EncodeFields

func (m *EmployeeServiceConfig) EncodeFields(w model.FieldWriter)

func (*EmployeeServiceConfig) IsNil

func (m *EmployeeServiceConfig) IsNil() bool

func (*EmployeeServiceConfig) Item added in v0.1.8

func (c *EmployeeServiceConfig) Item() view.Item

Item implements view.Itemizer.

func (*EmployeeServiceConfig) ModelName

func (m *EmployeeServiceConfig) ModelName() string

func (*EmployeeServiceConfig) Pointers

func (m *EmployeeServiceConfig) Pointers() []any

func (*EmployeeServiceConfig) Schema

func (m *EmployeeServiceConfig) Schema() []model.Field

func (*EmployeeServiceConfig) Validate

func (m *EmployeeServiceConfig) Validate(action byte) error

type EmployeeServiceConfigList

type EmployeeServiceConfigList []*EmployeeServiceConfig

func ReadAllEmployeeServiceConfig

func ReadAllEmployeeServiceConfig(qb *orm.QB) (EmployeeServiceConfigList, error)

func (*EmployeeServiceConfigList) Append

func (*EmployeeServiceConfigList) At

func (*EmployeeServiceConfigList) DecodeFields

func (s *EmployeeServiceConfigList) DecodeFields(_ model.FieldReader)

func (*EmployeeServiceConfigList) EncodeFields

func (s *EmployeeServiceConfigList) EncodeFields(_ model.FieldWriter)

func (*EmployeeServiceConfigList) IsNil

func (s *EmployeeServiceConfigList) IsNil() bool

func (*EmployeeServiceConfigList) Len

func (s *EmployeeServiceConfigList) Len() int

type ExpirePendingReservationsArgs

type ExpirePendingReservationsArgs struct {
	TenantId string
	Before   int64
}

func (*ExpirePendingReservationsArgs) DecodeFields

func (m *ExpirePendingReservationsArgs) DecodeFields(r model.FieldReader)

func (*ExpirePendingReservationsArgs) EncodeFields

func (m *ExpirePendingReservationsArgs) EncodeFields(w model.FieldWriter)

func (*ExpirePendingReservationsArgs) IsNil

func (*ExpirePendingReservationsArgs) ModelName

func (m *ExpirePendingReservationsArgs) ModelName() string

func (*ExpirePendingReservationsArgs) Pointers

func (m *ExpirePendingReservationsArgs) Pointers() []any

func (*ExpirePendingReservationsArgs) Schema

func (*ExpirePendingReservationsArgs) Validate

func (m *ExpirePendingReservationsArgs) Validate(action byte) error

type ExpirePendingReservationsArgsList

type ExpirePendingReservationsArgsList []*ExpirePendingReservationsArgs

func (*ExpirePendingReservationsArgsList) Append

func (*ExpirePendingReservationsArgsList) At

func (*ExpirePendingReservationsArgsList) DecodeFields

func (*ExpirePendingReservationsArgsList) EncodeFields

func (*ExpirePendingReservationsArgsList) IsNil

func (*ExpirePendingReservationsArgsList) Len

type FormConfig added in v0.1.7

type FormConfig struct {
	TenantId string // requerido
	StaffId  string // requerido — el profesional cuya agenda se está reservando
	// ServiceConfigId es el employee_service_config al que apunta la reserva.
	// Es lo que fija la duración y el precio; requerido para guardar o listar huecos.
	ServiceConfigId string
	// Timezone es la zona IANA en la que se lee el par día/hora, p. ej.
	// "America/Santiago". Requerido.
	//
	// LIMITACIÓN CONOCIDA: el valor autorizado vive en work_calendar_config.timezone
	// de este módulo, y no existe operación de lectura para él — por lo tanto, el
	// llamador lo proporciona. Agregar get_calendar_config está fuera del alcance
	// de este plan.
	Timezone string
	// From y To delimitan el listado, como segundos a medianoche UTC.
	From, To int64
	// ActorId se graba como creator_user_id. Opcional.
	ActorId string
	// LabelFor convierte un id de cliente en el nombre que se muestra en la lista. Opcional: nil
	// recurre al id sin formato.
	//
	// Es una función, no una dependencia de directorio, a propósito — este módulo
	// resuelve un cliente a través del DirectoryReader inyectado en el SERVIDOR, y
	// no debe adquirir una segunda dependencia en el lado del cliente sobre ninguna
	// implementación particular de directorio.
	LabelFor func(clientId string) string
}

FormConfig es el alcance en el que trabaja un formulario de reserva, más lo único que este módulo no puede saber: cómo nombrar a un cliente.

type GetDayBoundsArgs added in v0.1.5

type GetDayBoundsArgs struct {
	TenantId string
	Date     int64
}

func (*GetDayBoundsArgs) DecodeFields added in v0.1.5

func (m *GetDayBoundsArgs) DecodeFields(r model.FieldReader)

func (*GetDayBoundsArgs) EncodeFields added in v0.1.5

func (m *GetDayBoundsArgs) EncodeFields(w model.FieldWriter)

func (*GetDayBoundsArgs) IsNil added in v0.1.5

func (m *GetDayBoundsArgs) IsNil() bool

func (*GetDayBoundsArgs) ModelName added in v0.1.5

func (m *GetDayBoundsArgs) ModelName() string

func (*GetDayBoundsArgs) Pointers added in v0.1.5

func (m *GetDayBoundsArgs) Pointers() []any

func (*GetDayBoundsArgs) Schema added in v0.1.5

func (m *GetDayBoundsArgs) Schema() []model.Field

func (*GetDayBoundsArgs) Validate added in v0.1.5

func (m *GetDayBoundsArgs) Validate(action byte) error

type GetDayBoundsArgsList added in v0.1.5

type GetDayBoundsArgsList []*GetDayBoundsArgs

func (*GetDayBoundsArgsList) Append added in v0.1.5

func (s *GetDayBoundsArgsList) Append() model.Fielder

func (*GetDayBoundsArgsList) At added in v0.1.5

func (*GetDayBoundsArgsList) DecodeFields added in v0.1.5

func (s *GetDayBoundsArgsList) DecodeFields(_ model.FieldReader)

func (*GetDayBoundsArgsList) EncodeFields added in v0.1.5

func (s *GetDayBoundsArgsList) EncodeFields(_ model.FieldWriter)

func (*GetDayBoundsArgsList) IsNil added in v0.1.5

func (s *GetDayBoundsArgsList) IsNil() bool

func (*GetDayBoundsArgsList) Len added in v0.1.5

func (s *GetDayBoundsArgsList) Len() int

type GetEmployeeServiceConfigArgs added in v0.1.8

type GetEmployeeServiceConfigArgs struct {
	Id string
}

func (*GetEmployeeServiceConfigArgs) DecodeFields added in v0.1.8

func (m *GetEmployeeServiceConfigArgs) DecodeFields(r model.FieldReader)

func (*GetEmployeeServiceConfigArgs) EncodeFields added in v0.1.8

func (m *GetEmployeeServiceConfigArgs) EncodeFields(w model.FieldWriter)

func (*GetEmployeeServiceConfigArgs) IsNil added in v0.1.8

func (*GetEmployeeServiceConfigArgs) ModelName added in v0.1.8

func (m *GetEmployeeServiceConfigArgs) ModelName() string

func (*GetEmployeeServiceConfigArgs) Pointers added in v0.1.8

func (m *GetEmployeeServiceConfigArgs) Pointers() []any

func (*GetEmployeeServiceConfigArgs) Schema added in v0.1.8

func (*GetEmployeeServiceConfigArgs) Validate added in v0.1.8

func (m *GetEmployeeServiceConfigArgs) Validate(action byte) error

type GetEmployeeServiceConfigArgsList added in v0.1.8

type GetEmployeeServiceConfigArgsList []*GetEmployeeServiceConfigArgs

func (*GetEmployeeServiceConfigArgsList) Append added in v0.1.8

func (*GetEmployeeServiceConfigArgsList) At added in v0.1.8

func (*GetEmployeeServiceConfigArgsList) DecodeFields added in v0.1.8

func (*GetEmployeeServiceConfigArgsList) EncodeFields added in v0.1.8

func (*GetEmployeeServiceConfigArgsList) IsNil added in v0.1.8

func (*GetEmployeeServiceConfigArgsList) Len added in v0.1.8

type GetReservationArgs

type GetReservationArgs struct {
	TenantId string
	Id       string
}

func (*GetReservationArgs) DecodeFields

func (m *GetReservationArgs) DecodeFields(r model.FieldReader)

func (*GetReservationArgs) EncodeFields

func (m *GetReservationArgs) EncodeFields(w model.FieldWriter)

func (*GetReservationArgs) IsNil

func (m *GetReservationArgs) IsNil() bool

func (*GetReservationArgs) ModelName

func (m *GetReservationArgs) ModelName() string

func (*GetReservationArgs) Pointers

func (m *GetReservationArgs) Pointers() []any

func (*GetReservationArgs) Schema

func (m *GetReservationArgs) Schema() []model.Field

func (*GetReservationArgs) Validate

func (m *GetReservationArgs) Validate(action byte) error

type GetReservationArgsList

type GetReservationArgsList []*GetReservationArgs

func (*GetReservationArgsList) Append

func (s *GetReservationArgsList) Append() model.Fielder

func (*GetReservationArgsList) At

func (*GetReservationArgsList) DecodeFields

func (s *GetReservationArgsList) DecodeFields(_ model.FieldReader)

func (*GetReservationArgsList) EncodeFields

func (s *GetReservationArgsList) EncodeFields(_ model.FieldWriter)

func (*GetReservationArgsList) IsNil

func (s *GetReservationArgsList) IsNil() bool

func (*GetReservationArgsList) Len

func (s *GetReservationArgsList) Len() int

type ListAvailabilityArgs

type ListAvailabilityArgs struct {
	TenantId string
	StaffId  string
	ConfigId string
	From     int64
	To       int64
}

func (*ListAvailabilityArgs) DecodeFields

func (m *ListAvailabilityArgs) DecodeFields(r model.FieldReader)

func (*ListAvailabilityArgs) EncodeFields

func (m *ListAvailabilityArgs) EncodeFields(w model.FieldWriter)

func (*ListAvailabilityArgs) IsNil

func (m *ListAvailabilityArgs) IsNil() bool

func (*ListAvailabilityArgs) ModelName

func (m *ListAvailabilityArgs) ModelName() string

func (*ListAvailabilityArgs) Pointers

func (m *ListAvailabilityArgs) Pointers() []any

func (*ListAvailabilityArgs) Schema

func (m *ListAvailabilityArgs) Schema() []model.Field

func (*ListAvailabilityArgs) Validate

func (m *ListAvailabilityArgs) Validate(action byte) error

type ListAvailabilityArgsList

type ListAvailabilityArgsList []*ListAvailabilityArgs

func (*ListAvailabilityArgsList) Append

func (*ListAvailabilityArgsList) At

func (*ListAvailabilityArgsList) DecodeFields

func (s *ListAvailabilityArgsList) DecodeFields(_ model.FieldReader)

func (*ListAvailabilityArgsList) EncodeFields

func (s *ListAvailabilityArgsList) EncodeFields(_ model.FieldWriter)

func (*ListAvailabilityArgsList) IsNil

func (s *ListAvailabilityArgsList) IsNil() bool

func (*ListAvailabilityArgsList) Len

func (s *ListAvailabilityArgsList) Len() int

type ListBlocksArgs added in v0.1.5

type ListBlocksArgs struct {
	TenantId string
	StaffId  string
}

func (*ListBlocksArgs) DecodeFields added in v0.1.5

func (m *ListBlocksArgs) DecodeFields(r model.FieldReader)

func (*ListBlocksArgs) EncodeFields added in v0.1.5

func (m *ListBlocksArgs) EncodeFields(w model.FieldWriter)

func (*ListBlocksArgs) IsNil added in v0.1.5

func (m *ListBlocksArgs) IsNil() bool

func (*ListBlocksArgs) ModelName added in v0.1.5

func (m *ListBlocksArgs) ModelName() string

func (*ListBlocksArgs) Pointers added in v0.1.5

func (m *ListBlocksArgs) Pointers() []any

func (*ListBlocksArgs) Schema added in v0.1.5

func (m *ListBlocksArgs) Schema() []model.Field

func (*ListBlocksArgs) Validate added in v0.1.5

func (m *ListBlocksArgs) Validate(action byte) error

type ListBlocksArgsList added in v0.1.5

type ListBlocksArgsList []*ListBlocksArgs

func (*ListBlocksArgsList) Append added in v0.1.5

func (s *ListBlocksArgsList) Append() model.Fielder

func (*ListBlocksArgsList) At added in v0.1.5

func (*ListBlocksArgsList) DecodeFields added in v0.1.5

func (s *ListBlocksArgsList) DecodeFields(_ model.FieldReader)

func (*ListBlocksArgsList) EncodeFields added in v0.1.5

func (s *ListBlocksArgsList) EncodeFields(_ model.FieldWriter)

func (*ListBlocksArgsList) IsNil added in v0.1.5

func (s *ListBlocksArgsList) IsNil() bool

func (*ListBlocksArgsList) Len added in v0.1.5

func (s *ListBlocksArgsList) Len() int

type ListConflictingReservationsArgs added in v0.1.5

type ListConflictingReservationsArgs struct {
	TenantId string
	StaffId  string
	From     int64
}

func (*ListConflictingReservationsArgs) DecodeFields added in v0.1.5

func (*ListConflictingReservationsArgs) EncodeFields added in v0.1.5

func (*ListConflictingReservationsArgs) IsNil added in v0.1.5

func (*ListConflictingReservationsArgs) ModelName added in v0.1.5

func (m *ListConflictingReservationsArgs) ModelName() string

func (*ListConflictingReservationsArgs) Pointers added in v0.1.5

func (m *ListConflictingReservationsArgs) Pointers() []any

func (*ListConflictingReservationsArgs) Schema added in v0.1.5

func (*ListConflictingReservationsArgs) Validate added in v0.1.5

func (m *ListConflictingReservationsArgs) Validate(action byte) error

type ListConflictingReservationsArgsList added in v0.1.5

type ListConflictingReservationsArgsList []*ListConflictingReservationsArgs

func (*ListConflictingReservationsArgsList) Append added in v0.1.5

func (*ListConflictingReservationsArgsList) At added in v0.1.5

func (*ListConflictingReservationsArgsList) DecodeFields added in v0.1.5

func (*ListConflictingReservationsArgsList) EncodeFields added in v0.1.5

func (*ListConflictingReservationsArgsList) IsNil added in v0.1.5

func (*ListConflictingReservationsArgsList) Len added in v0.1.5

type ListEmployeeServiceConfigsByStaffArgs added in v0.1.8

type ListEmployeeServiceConfigsByStaffArgs struct {
	TenantId string
	StaffId  string
}

func (*ListEmployeeServiceConfigsByStaffArgs) DecodeFields added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgs) EncodeFields added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgs) IsNil added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgs) ModelName added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgs) Pointers added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgs) Schema added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgs) Validate added in v0.1.8

func (m *ListEmployeeServiceConfigsByStaffArgs) Validate(action byte) error

type ListEmployeeServiceConfigsByStaffArgsList added in v0.1.8

type ListEmployeeServiceConfigsByStaffArgsList []*ListEmployeeServiceConfigsByStaffArgs

func (*ListEmployeeServiceConfigsByStaffArgsList) Append added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgsList) At added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgsList) DecodeFields added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgsList) EncodeFields added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgsList) IsNil added in v0.1.8

func (*ListEmployeeServiceConfigsByStaffArgsList) Len added in v0.1.8

type ListExceptionsArgs added in v0.1.4

type ListExceptionsArgs struct {
	TenantId string
	StaffId  string
	From     int64
	To       int64
}

func (*ListExceptionsArgs) DecodeFields added in v0.1.4

func (m *ListExceptionsArgs) DecodeFields(r model.FieldReader)

func (*ListExceptionsArgs) EncodeFields added in v0.1.4

func (m *ListExceptionsArgs) EncodeFields(w model.FieldWriter)

func (*ListExceptionsArgs) IsNil added in v0.1.4

func (m *ListExceptionsArgs) IsNil() bool

func (*ListExceptionsArgs) ModelName added in v0.1.4

func (m *ListExceptionsArgs) ModelName() string

func (*ListExceptionsArgs) Pointers added in v0.1.4

func (m *ListExceptionsArgs) Pointers() []any

func (*ListExceptionsArgs) Schema added in v0.1.4

func (m *ListExceptionsArgs) Schema() []model.Field

func (*ListExceptionsArgs) Validate added in v0.1.4

func (m *ListExceptionsArgs) Validate(action byte) error

type ListExceptionsArgsList added in v0.1.4

type ListExceptionsArgsList []*ListExceptionsArgs

func (*ListExceptionsArgsList) Append added in v0.1.4

func (s *ListExceptionsArgsList) Append() model.Fielder

func (*ListExceptionsArgsList) At added in v0.1.4

func (*ListExceptionsArgsList) DecodeFields added in v0.1.4

func (s *ListExceptionsArgsList) DecodeFields(_ model.FieldReader)

func (*ListExceptionsArgsList) EncodeFields added in v0.1.4

func (s *ListExceptionsArgsList) EncodeFields(_ model.FieldWriter)

func (*ListExceptionsArgsList) IsNil added in v0.1.4

func (s *ListExceptionsArgsList) IsNil() bool

func (*ListExceptionsArgsList) Len added in v0.1.4

func (s *ListExceptionsArgsList) Len() int

type ListReservationsByClientArgs

type ListReservationsByClientArgs struct {
	TenantId string
	ClientId string
}

func (*ListReservationsByClientArgs) DecodeFields

func (m *ListReservationsByClientArgs) DecodeFields(r model.FieldReader)

func (*ListReservationsByClientArgs) EncodeFields

func (m *ListReservationsByClientArgs) EncodeFields(w model.FieldWriter)

func (*ListReservationsByClientArgs) IsNil

func (*ListReservationsByClientArgs) ModelName

func (m *ListReservationsByClientArgs) ModelName() string

func (*ListReservationsByClientArgs) Pointers

func (m *ListReservationsByClientArgs) Pointers() []any

func (*ListReservationsByClientArgs) Schema

func (*ListReservationsByClientArgs) Validate

func (m *ListReservationsByClientArgs) Validate(action byte) error

type ListReservationsByClientArgsList

type ListReservationsByClientArgsList []*ListReservationsByClientArgs

func (*ListReservationsByClientArgsList) Append

func (*ListReservationsByClientArgsList) At

func (*ListReservationsByClientArgsList) DecodeFields

func (*ListReservationsByClientArgsList) EncodeFields

func (*ListReservationsByClientArgsList) IsNil

func (*ListReservationsByClientArgsList) Len

type ListReservationsByStaffArgs

type ListReservationsByStaffArgs struct {
	TenantId string
	StaffId  string
	From     int64
	To       int64
}

func (*ListReservationsByStaffArgs) DecodeFields

func (m *ListReservationsByStaffArgs) DecodeFields(r model.FieldReader)

func (*ListReservationsByStaffArgs) EncodeFields

func (m *ListReservationsByStaffArgs) EncodeFields(w model.FieldWriter)

func (*ListReservationsByStaffArgs) IsNil

func (m *ListReservationsByStaffArgs) IsNil() bool

func (*ListReservationsByStaffArgs) ModelName

func (m *ListReservationsByStaffArgs) ModelName() string

func (*ListReservationsByStaffArgs) Pointers

func (m *ListReservationsByStaffArgs) Pointers() []any

func (*ListReservationsByStaffArgs) Schema

func (m *ListReservationsByStaffArgs) Schema() []model.Field

func (*ListReservationsByStaffArgs) Validate

func (m *ListReservationsByStaffArgs) Validate(action byte) error

type ListReservationsByStaffArgsList

type ListReservationsByStaffArgsList []*ListReservationsByStaffArgs

func (*ListReservationsByStaffArgsList) Append

func (*ListReservationsByStaffArgsList) At

func (*ListReservationsByStaffArgsList) DecodeFields

func (*ListReservationsByStaffArgsList) EncodeFields

func (*ListReservationsByStaffArgsList) IsNil

func (*ListReservationsByStaffArgsList) Len

type MarkWorkingDaysArgs added in v0.1.5

type MarkWorkingDaysArgs struct {
	TenantId string
	StaffId  string
	Dates    []int
	StartMin int64
	EndMin   int64
}

func (*MarkWorkingDaysArgs) DecodeFields added in v0.1.5

func (m *MarkWorkingDaysArgs) DecodeFields(r model.FieldReader)

func (*MarkWorkingDaysArgs) EncodeFields added in v0.1.5

func (m *MarkWorkingDaysArgs) EncodeFields(w model.FieldWriter)

func (*MarkWorkingDaysArgs) IsNil added in v0.1.5

func (m *MarkWorkingDaysArgs) IsNil() bool

func (*MarkWorkingDaysArgs) ModelName added in v0.1.5

func (m *MarkWorkingDaysArgs) ModelName() string

func (*MarkWorkingDaysArgs) Pointers added in v0.1.5

func (m *MarkWorkingDaysArgs) Pointers() []any

func (*MarkWorkingDaysArgs) Schema added in v0.1.5

func (m *MarkWorkingDaysArgs) Schema() []model.Field

func (*MarkWorkingDaysArgs) Validate added in v0.1.5

func (m *MarkWorkingDaysArgs) Validate(action byte) error

type MarkWorkingDaysArgsList added in v0.1.5

type MarkWorkingDaysArgsList []*MarkWorkingDaysArgs

func (*MarkWorkingDaysArgsList) Append added in v0.1.5

func (*MarkWorkingDaysArgsList) At added in v0.1.5

func (*MarkWorkingDaysArgsList) DecodeFields added in v0.1.5

func (s *MarkWorkingDaysArgsList) DecodeFields(_ model.FieldReader)

func (*MarkWorkingDaysArgsList) EncodeFields added in v0.1.5

func (s *MarkWorkingDaysArgsList) EncodeFields(_ model.FieldWriter)

func (*MarkWorkingDaysArgsList) IsNil added in v0.1.5

func (s *MarkWorkingDaysArgsList) IsNil() bool

func (*MarkWorkingDaysArgsList) Len added in v0.1.5

func (s *MarkWorkingDaysArgsList) Len() int

type Module

type Module struct {
	// contains filtered or unexported fields
}

func New

func New(db *orm.DB, deps Deps) (*Module, error)

func (*Module) AddException

func (m *Module) AddException(exc WorkCalendarException) error

func (*Module) ChangeReservationStatus

func (m *Module) ChangeReservationStatus(cmd ChangeStatusCmd) error

func (*Module) CreateEmployeeServiceConfig added in v0.1.8

func (m *Module) CreateEmployeeServiceConfig(cfg EmployeeServiceConfig) (EmployeeServiceConfig, error)

CreateEmployeeServiceConfig registers that a professional performs a service, with its own duration/price override.

func (*Module) CreateReservation

func (m *Module) CreateReservation(cmd CreateReservationCmd) (Reservation, error)

func (*Module) ExpirePendingReservations

func (m *Module) ExpirePendingReservations(tenantId string, before int64) (int, error)

func (*Module) GetDayBounds added in v0.1.5

func (m *Module) GetDayBounds(date int64) (tinytime.DayBounds, error)

GetDayBounds proxies Deps.Bounds para que el editor acote sus propios controles llamando a este módulo, no al calendario institucional directamente (§6.2).

func (*Module) GetEmployeeServiceConfig added in v0.1.8

func (m *Module) GetEmployeeServiceConfig(id string) (EmployeeServiceConfig, error)

GetEmployeeServiceConfig reads one by id.

func (*Module) GetReservation

func (m *Module) GetReservation(tenantId, id string) (Reservation, error)

func (*Module) IconSvg

func (m *Module) IconSvg() *sprite.Sprite

IconSvg registra el ícono de marca del módulo. tinywasm/ssr lo extrae durante SSR y assetmin lo inyecta inline en <body> — nunca se llama a mano.

func (*Module) ListAvailability

func (m *Module) ListAvailability(tenantId, staffId, configId string, from, to int64) ([]TimeSlot, error)

func (*Module) ListBlocks added in v0.1.5

func (m *Module) ListBlocks(tenantId, staffId string) ([]WorkCalendarBlock, error)

func (*Module) ListConflictingReservations added in v0.1.5

func (m *Module) ListConflictingReservations(tenantId, staffId string, from int64) ([]ConflictingReservation, error)

ListConflictingReservations returns future reservations that the CURRENT schedule no longer covers. from is normally "now". Son las que una edición de agenda o del establecimiento dejó huérfanas — el worklist de CU-17. Reported, never cancelled: cancelling on the patient's behalf is a decision for a person.

func (*Module) ListEmployeeServiceConfigByStaff added in v0.1.8

func (m *Module) ListEmployeeServiceConfigByStaff(tenantId, staffId string) ([]EmployeeServiceConfig, error)

ListEmployeeServiceConfigByStaff lists every service a professional performs, active or not — the editing screen needs to show and reactivate a disabled one, not just the active set.

func (*Module) ListExceptions added in v0.1.4

func (m *Module) ListExceptions(tenantId, staffId string, from, to int64) ([]WorkCalendarException, error)

func (*Module) ListReservationsByClient

func (m *Module) ListReservationsByClient(tenantId, clientId string) ([]Reservation, error)

func (*Module) ListReservationsByStaff

func (m *Module) ListReservationsByStaff(tenantId, staffId string, from, to int64) ([]Reservation, error)

func (*Module) MarkWorkingDays added in v0.1.5

func (m *Module) MarkWorkingDays(tenantId, staffId string, dates []int64, startMin, endMin int) error

MarkWorkingDays writes ONE dated block per date, all with the same window — the bulk gesture behind "mark the days I work over the next 6 months" (CU-10/CU-11). Re-marking a date replaces its blocks.

func (*Module) ModelName

func (m *Module) ModelName() string

func (*Module) MountOperations added in v0.1.3

func (m *Module) MountOperations(reg router.OperationRegistry)

func (*Module) RecomputeConflicts added in v0.1.5

func (m *Module) RecomputeConflicts(tenantId string, from, to int64) (int, error)

RecomputeConflicts re-evaluates every future reservation in [from, to] against the CURRENT schedule and bounds, marking or clearing CONFLICTED as the answer dictates. Returns how many reservations changed state.

It is idempotent: calling it twice with no intervening change is a no-op and publishes nothing (CU-19/CU-29 depend on that).

tenantId scopes it; from/to are midnight UTC seconds. to == 0 means "the module's full forward horizon", which is what a weekly-hours change needs since it has no bounded date range.

El disparador queda INVERTIDO (§8.4): no hay Subscriber aquí — la aplicación, que legítimamente conoce ambos módulos, se suscribe al calendario del establecimiento y llama a esto.

func (*Module) RemoveException

func (m *Module) RemoveException(tenantId, exceptionId string) error

func (*Module) SaveDateBlocks added in v0.1.5

func (m *Module) SaveDateBlocks(tenantId, staffId string, date int64, blocks []WorkCalendarBlock) error

SaveDateBlocks replaces the dated blocks of ONE date, so a single marked day can diverge from the common window it was created with (CU-11).

func (*Module) SaveDayBlocks added in v0.1.5

func (m *Module) SaveDayBlocks(tenantId, staffId string, dayOfWeek int, blocks []WorkCalendarBlock) error

SaveDayBlocks replaces EVERY weekly block of that weekday with the ones given. A whole-day replace, not a per-row upsert: partial edits are what let the stored set drift out of step with what the editor is showing.

func (*Module) UnmarkWorkingDays added in v0.1.5

func (m *Module) UnmarkWorkingDays(tenantId, staffId string, dates []int64) error

UnmarkWorkingDays deletes every dated block on those dates, returning the days to whatever the weekly template says — or to unworked (CU-15).

func (*Module) UpdateEmployeeServiceConfig added in v0.1.8

func (m *Module) UpdateEmployeeServiceConfig(cfg EmployeeServiceConfig) error

UpdateEmployeeServiceConfig writes the full record.

func (*Module) UpsertCalendarConfig

func (m *Module) UpsertCalendarConfig(cfg WorkCalendarConfig) error

type RecomputeConflictsArgs added in v0.1.5

type RecomputeConflictsArgs struct {
	TenantId string
	From     int64
	To       int64
}

func (*RecomputeConflictsArgs) DecodeFields added in v0.1.5

func (m *RecomputeConflictsArgs) DecodeFields(r model.FieldReader)

func (*RecomputeConflictsArgs) EncodeFields added in v0.1.5

func (m *RecomputeConflictsArgs) EncodeFields(w model.FieldWriter)

func (*RecomputeConflictsArgs) IsNil added in v0.1.5

func (m *RecomputeConflictsArgs) IsNil() bool

func (*RecomputeConflictsArgs) ModelName added in v0.1.5

func (m *RecomputeConflictsArgs) ModelName() string

func (*RecomputeConflictsArgs) Pointers added in v0.1.5

func (m *RecomputeConflictsArgs) Pointers() []any

func (*RecomputeConflictsArgs) Schema added in v0.1.5

func (m *RecomputeConflictsArgs) Schema() []model.Field

func (*RecomputeConflictsArgs) Validate added in v0.1.5

func (m *RecomputeConflictsArgs) Validate(action byte) error

type RecomputeConflictsArgsList added in v0.1.5

type RecomputeConflictsArgsList []*RecomputeConflictsArgs

func (*RecomputeConflictsArgsList) Append added in v0.1.5

func (*RecomputeConflictsArgsList) At added in v0.1.5

func (*RecomputeConflictsArgsList) DecodeFields added in v0.1.5

func (s *RecomputeConflictsArgsList) DecodeFields(_ model.FieldReader)

func (*RecomputeConflictsArgsList) EncodeFields added in v0.1.5

func (s *RecomputeConflictsArgsList) EncodeFields(_ model.FieldWriter)

func (*RecomputeConflictsArgsList) IsNil added in v0.1.5

func (s *RecomputeConflictsArgsList) IsNil() bool

func (*RecomputeConflictsArgsList) Len added in v0.1.5

type RemoveCalendarExceptionArgs

type RemoveCalendarExceptionArgs struct {
	TenantId    string
	ExceptionId string
}

func (*RemoveCalendarExceptionArgs) DecodeFields

func (m *RemoveCalendarExceptionArgs) DecodeFields(r model.FieldReader)

func (*RemoveCalendarExceptionArgs) EncodeFields

func (m *RemoveCalendarExceptionArgs) EncodeFields(w model.FieldWriter)

func (*RemoveCalendarExceptionArgs) IsNil

func (m *RemoveCalendarExceptionArgs) IsNil() bool

func (*RemoveCalendarExceptionArgs) ModelName

func (m *RemoveCalendarExceptionArgs) ModelName() string

func (*RemoveCalendarExceptionArgs) Pointers

func (m *RemoveCalendarExceptionArgs) Pointers() []any

func (*RemoveCalendarExceptionArgs) Schema

func (m *RemoveCalendarExceptionArgs) Schema() []model.Field

func (*RemoveCalendarExceptionArgs) Validate

func (m *RemoveCalendarExceptionArgs) Validate(action byte) error

type RemoveCalendarExceptionArgsList

type RemoveCalendarExceptionArgsList []*RemoveCalendarExceptionArgs

func (*RemoveCalendarExceptionArgsList) Append

func (*RemoveCalendarExceptionArgsList) At

func (*RemoveCalendarExceptionArgsList) DecodeFields

func (*RemoveCalendarExceptionArgsList) EncodeFields

func (*RemoveCalendarExceptionArgsList) IsNil

func (*RemoveCalendarExceptionArgsList) Len

type Repository

type Repository struct {
	// contains filtered or unexported fields
}

Repository provee operaciones CRUD para todas las tablas de appointment-booking.

func NewRepository

func NewRepository(db *orm.DB, ids model.IDGenerator) (*Repository, error)

NewRepository crea un nuevo Repository sobre un *orm.DB ya conectado; el esquema se asume existente — ver el subpaquete migrate.

func (*Repository) DeleteDateBlocks added in v0.1.5

func (r *Repository) DeleteDateBlocks(tenantId, staffId string, date int64) error

DeleteDateBlocks borra todos los bloques datados de esas fechas (CU-15: devuelve el día a lo que diga el template semanal, o a des-trabajado).

func (*Repository) DeleteException

func (r *Repository) DeleteException(tenantId, id string) error

func (*Repository) GetCalendarConfig

func (r *Repository) GetCalendarConfig(tenantId, staffId string) (WorkCalendarConfig, error)

func (*Repository) GetEmployeeServiceConfig

func (r *Repository) GetEmployeeServiceConfig(id string) (EmployeeServiceConfig, error)

func (*Repository) GetException added in v0.1.4

func (r *Repository) GetException(tenantId, id string) (WorkCalendarException, error)

func (*Repository) GetReservation

func (r *Repository) GetReservation(id string) (Reservation, error)

func (*Repository) GetReservationTx

func (r *Repository) GetReservationTx(tx *orm.DB, tenantId, id string) (Reservation, error)

func (*Repository) InsertEmployeeServiceConfig

func (r *Repository) InsertEmployeeServiceConfig(cfg EmployeeServiceConfig) error

func (*Repository) InsertException

func (r *Repository) InsertException(exc WorkCalendarException) error

func (*Repository) InsertReservation

func (r *Repository) InsertReservation(res *Reservation) error

func (*Repository) ListBlocks added in v0.1.5

func (r *Repository) ListBlocks(tenantId, staffId string) ([]WorkCalendarBlock, error)

ListBlocks devuelve todos los bloques de un staff — semanales y datados mezclados; ListAvailability los separa por fecha/weekday con las helpers del servicio.

func (*Repository) ListEmployeeServiceConfigByStaff

func (r *Repository) ListEmployeeServiceConfigByStaff(tenantId, staffId string) ([]EmployeeServiceConfig, error)

func (*Repository) ListExceptions

func (r *Repository) ListExceptions(tenantId, staffId string, from, to int64) ([]WorkCalendarException, error)

func (*Repository) ListReservationsByClient

func (r *Repository) ListReservationsByClient(tenantId, clientId string) ([]Reservation, error)

func (*Repository) ListReservationsByStaff

func (r *Repository) ListReservationsByStaff(tenantId, staffId string, from, to int64) ([]Reservation, error)

func (*Repository) ListReservationsByTenantRange added in v0.1.5

func (r *Repository) ListReservationsByTenantRange(tenantId string, from, to int64) ([]Reservation, error)

ListReservationsByTenantRange lista las reservas de todo un tenant en un rango de fechas — el alcance del recompute del establecimiento (un feriado golpea a todos los profesionales a la vez).

func (*Repository) ReplaceDateBlocks added in v0.1.5

func (r *Repository) ReplaceDateBlocks(tenantId, staffId string, date int64, blocks []WorkCalendarBlock) error

ReplaceDateBlocks pisa los bloques DATADOS de una fecha (CU-11: un día marcado puede divergir de la ventana común con la que se creó).

func (*Repository) ReplaceWeekdayBlocks added in v0.1.5

func (r *Repository) ReplaceWeekdayBlocks(tenantId, staffId string, dayOfWeek int, blocks []WorkCalendarBlock) error

ReplaceWeekdayBlocks pisa todos los bloques semanales del weekday dado — un replace de día completo, no un upsert por fila: los edits parciales son lo que desincroniza el conjunto guardado de lo que muestra el editor (§7).

func (*Repository) UpdateEmployeeServiceConfig

func (r *Repository) UpdateEmployeeServiceConfig(cfg EmployeeServiceConfig) error

func (*Repository) UpdateReservationConflictTx added in v0.1.5

func (r *Repository) UpdateReservationConflictTx(tx *orm.DB, id, tenantId, status, statusBefore, updatedBy string, updatedAt int64, expectedRevision int64) error

UpdateReservationConflictTx escribe el estado CONFLICTED (o su restauración) con optimismo: WHERE revision = N y tenant scope en ambas ramas. statusBefore queda grabado al entrar en conflicto y "" al salir (fuente única de restauración, §8.5).

func (*Repository) UpdateReservationStatus

func (r *Repository) UpdateReservationStatus(id, status, updatedBy string, updatedAt int64, expectedRevision int64) error

func (*Repository) UpdateReservationStatusTx

func (r *Repository) UpdateReservationStatusTx(tx *orm.DB, id, status, updatedBy string, updatedAt int64, expectedRevision int64) error

func (*Repository) UpsertCalendarConfig

func (r *Repository) UpsertCalendarConfig(cfg WorkCalendarConfig) error

type Reservation

type Reservation struct {
	Id                      string
	TenantId                string
	ClientId                string
	CreatorUserId           string
	EmployeeServiceConfigId string
	StaffIdsnapshot         string
	ServiceIdsnapshot       string
	DurationMinSnapshot     int64
	PriceSnapshot           float64
	CurrencySnapshot        string
	ReservationDate         int64
	ReservationTime         int64
	LocalStringDate         string
	LocalStringTime         string
	Status                  string
	RescheduledFromId       string
	StatusBeforeConflict    string
	PaymentId               string
	Notes                   string
	UpdatedAt               int64
	UpdatedBy               string
	Revision                int64
}

func ReadOneReservation

func ReadOneReservation(qb *orm.QB, model *Reservation) (*Reservation, error)

func (*Reservation) DecodeFields

func (m *Reservation) DecodeFields(r model.FieldReader)

func (*Reservation) EncodeFields

func (m *Reservation) EncodeFields(w model.FieldWriter)

func (*Reservation) IsNil

func (m *Reservation) IsNil() bool

func (*Reservation) Item added in v0.1.1

func (r *Reservation) Item() view.Item

Item implementa view.Itemizer — el ÚNICO código específico de view que carga este registro. El Presenter indexa las filas por ID a partir de esto durante Reload; no hay lookup manual byId/WithFill.

func (*Reservation) ModelName

func (m *Reservation) ModelName() string

func (*Reservation) Pointers

func (m *Reservation) Pointers() []any

func (*Reservation) Schema

func (m *Reservation) Schema() []model.Field

func (*Reservation) Validate

func (m *Reservation) Validate(action byte) error

type ReservationForm added in v0.1.7

type ReservationForm struct {
	Id       string
	ClientId string
	Day      string
	Hour     string
	Notes    string
	Status   string
}

func ReadOneReservationForm added in v0.1.7

func ReadOneReservationForm(qb *orm.QB, model *ReservationForm) (*ReservationForm, error)

func (*ReservationForm) DecodeFields added in v0.1.7

func (m *ReservationForm) DecodeFields(r model.FieldReader)

func (*ReservationForm) EncodeFields added in v0.1.7

func (m *ReservationForm) EncodeFields(w model.FieldWriter)

func (*ReservationForm) IsNil added in v0.1.7

func (m *ReservationForm) IsNil() bool

func (*ReservationForm) Item added in v0.1.7

func (r *ReservationForm) Item() view.Item

Item implementa view.Itemizer. LeadMain es la hora porque la lista de reservas se lee hacia abajo en una columna de horas; un widget de lista que encabeza con una hora (webtyp/components targethour) se vincula a este campo.

func (*ReservationForm) ModelName added in v0.1.7

func (m *ReservationForm) ModelName() string

func (*ReservationForm) Pointers added in v0.1.7

func (m *ReservationForm) Pointers() []any

func (*ReservationForm) Schema added in v0.1.7

func (m *ReservationForm) Schema() []model.Field

func (*ReservationForm) Validate added in v0.1.7

func (m *ReservationForm) Validate(action byte) error

type ReservationFormList added in v0.1.7

type ReservationFormList []*ReservationForm

func ReadAllReservationForm added in v0.1.7

func ReadAllReservationForm(qb *orm.QB) (ReservationFormList, error)

func (*ReservationFormList) Append added in v0.1.7

func (s *ReservationFormList) Append() model.Fielder

func (*ReservationFormList) At added in v0.1.7

func (*ReservationFormList) DecodeFields added in v0.1.7

func (s *ReservationFormList) DecodeFields(_ model.FieldReader)

func (*ReservationFormList) EncodeFields added in v0.1.7

func (s *ReservationFormList) EncodeFields(_ model.FieldWriter)

func (*ReservationFormList) IsNil added in v0.1.7

func (s *ReservationFormList) IsNil() bool

func (*ReservationFormList) Len added in v0.1.7

func (s *ReservationFormList) Len() int

type ReservationList

type ReservationList []*Reservation

func ReadAllReservation

func ReadAllReservation(qb *orm.QB) (ReservationList, error)

func (*ReservationList) Append

func (s *ReservationList) Append() model.Fielder

func (*ReservationList) At

func (s *ReservationList) At(i int) model.Fielder

func (*ReservationList) DecodeFields

func (s *ReservationList) DecodeFields(_ model.FieldReader)

func (*ReservationList) EncodeFields

func (s *ReservationList) EncodeFields(_ model.FieldWriter)

func (*ReservationList) IsNil

func (s *ReservationList) IsNil() bool

func (*ReservationList) Len

func (s *ReservationList) Len() int

type SaveDateBlocksArgs added in v0.1.5

type SaveDateBlocksArgs struct {
	TenantId     string
	StaffId      string
	SpecificDate int64
	Blocks       []WorkCalendarBlock
}

func (*SaveDateBlocksArgs) DecodeFields added in v0.1.5

func (m *SaveDateBlocksArgs) DecodeFields(r model.FieldReader)

func (*SaveDateBlocksArgs) EncodeFields added in v0.1.5

func (m *SaveDateBlocksArgs) EncodeFields(w model.FieldWriter)

func (*SaveDateBlocksArgs) IsNil added in v0.1.5

func (m *SaveDateBlocksArgs) IsNil() bool

func (*SaveDateBlocksArgs) ModelName added in v0.1.5

func (m *SaveDateBlocksArgs) ModelName() string

func (*SaveDateBlocksArgs) Pointers added in v0.1.5

func (m *SaveDateBlocksArgs) Pointers() []any

func (*SaveDateBlocksArgs) Schema added in v0.1.5

func (m *SaveDateBlocksArgs) Schema() []model.Field

func (*SaveDateBlocksArgs) Validate added in v0.1.5

func (m *SaveDateBlocksArgs) Validate(action byte) error

type SaveDateBlocksArgsList added in v0.1.5

type SaveDateBlocksArgsList []*SaveDateBlocksArgs

func (*SaveDateBlocksArgsList) Append added in v0.1.5

func (s *SaveDateBlocksArgsList) Append() model.Fielder

func (*SaveDateBlocksArgsList) At added in v0.1.5

func (*SaveDateBlocksArgsList) DecodeFields added in v0.1.5

func (s *SaveDateBlocksArgsList) DecodeFields(_ model.FieldReader)

func (*SaveDateBlocksArgsList) EncodeFields added in v0.1.5

func (s *SaveDateBlocksArgsList) EncodeFields(_ model.FieldWriter)

func (*SaveDateBlocksArgsList) IsNil added in v0.1.5

func (s *SaveDateBlocksArgsList) IsNil() bool

func (*SaveDateBlocksArgsList) Len added in v0.1.5

func (s *SaveDateBlocksArgsList) Len() int

type SaveDayBlocksArgs added in v0.1.5

type SaveDayBlocksArgs struct {
	TenantId  string
	StaffId   string
	DayOfWeek int64
	Blocks    []WorkCalendarBlock
}

func (*SaveDayBlocksArgs) DecodeFields added in v0.1.5

func (m *SaveDayBlocksArgs) DecodeFields(r model.FieldReader)

func (*SaveDayBlocksArgs) EncodeFields added in v0.1.5

func (m *SaveDayBlocksArgs) EncodeFields(w model.FieldWriter)

func (*SaveDayBlocksArgs) IsNil added in v0.1.5

func (m *SaveDayBlocksArgs) IsNil() bool

func (*SaveDayBlocksArgs) ModelName added in v0.1.5

func (m *SaveDayBlocksArgs) ModelName() string

func (*SaveDayBlocksArgs) Pointers added in v0.1.5

func (m *SaveDayBlocksArgs) Pointers() []any

func (*SaveDayBlocksArgs) Schema added in v0.1.5

func (m *SaveDayBlocksArgs) Schema() []model.Field

func (*SaveDayBlocksArgs) Validate added in v0.1.5

func (m *SaveDayBlocksArgs) Validate(action byte) error

type SaveDayBlocksArgsList added in v0.1.5

type SaveDayBlocksArgsList []*SaveDayBlocksArgs

func (*SaveDayBlocksArgsList) Append added in v0.1.5

func (s *SaveDayBlocksArgsList) Append() model.Fielder

func (*SaveDayBlocksArgsList) At added in v0.1.5

func (*SaveDayBlocksArgsList) DecodeFields added in v0.1.5

func (s *SaveDayBlocksArgsList) DecodeFields(_ model.FieldReader)

func (*SaveDayBlocksArgsList) EncodeFields added in v0.1.5

func (s *SaveDayBlocksArgsList) EncodeFields(_ model.FieldWriter)

func (*SaveDayBlocksArgsList) IsNil added in v0.1.5

func (s *SaveDayBlocksArgsList) IsNil() bool

func (*SaveDayBlocksArgsList) Len added in v0.1.5

func (s *SaveDayBlocksArgsList) Len() int

type ScheduleChangedPayload added in v0.1.4

type ScheduleChangedPayload struct {
	TenantId string
	StaffId  string
	// FromDate/ToDate bound what changed, so a consumer recomputes a range
	// instead of everything. 0/0 means "unknown, recompute all".
	FromDate int64
	ToDate   int64
	// ConflictCount is how many reservations the change put in conflict.
	// Zero means nobody needs to be told (CU-19).
	ConflictCount int
}

ScheduleChangedPayload es el payload tipado del evento EventScheduleChanged. Implementa model.Encodable (lo que events.Event.Payload exige) y también model.Decodable, para que un broker que cruza un cable real (webtyp/sse en mjosefa-cms) pueda serializarlo; el broker in-proc de la demo entrega el puntero concreto sin codificar.

func (*ScheduleChangedPayload) DecodeFields added in v0.1.4

func (p *ScheduleChangedPayload) DecodeFields(r model.FieldReader)

func (*ScheduleChangedPayload) EncodeFields added in v0.1.4

func (p *ScheduleChangedPayload) EncodeFields(w model.FieldWriter)

func (*ScheduleChangedPayload) IsNil added in v0.1.4

func (p *ScheduleChangedPayload) IsNil() bool

type ScheduleClient added in v0.1.4

type ScheduleClient struct {
	// contains filtered or unexported fields
}

ScheduleClient es la vista caller-side de la agenda de UN profesional: la contraparte tipada de las ops de calendario, para que una app adapte a scheduleeditor sin importar un transport. Importa solo router + los tipos de este paquete — este módulo no puede importar components/layout (blacklist de renderer).

func NewScheduleClient added in v0.1.4

func NewScheduleClient(caller router.Caller, tenantId, staffId string) *ScheduleClient

NewScheduleClient construye el cliente para la agenda de (tenantId, staffId).

func (*ScheduleClient) AddException added in v0.1.4

func (c *ScheduleClient) AddException(exc WorkCalendarException, done func(error))

AddException da de alta una excepción de calendario.

func (*ScheduleClient) Blocks added in v0.1.5

func (c *ScheduleClient) Blocks(done func([]WorkCalendarBlock, error))

Blocks carga todos los bloques del profesional (semanales y datados).

func (*ScheduleClient) Exceptions added in v0.1.4

func (c *ScheduleClient) Exceptions(from, to int64, done func([]WorkCalendarException, error))

Exceptions carga las excepciones del rango [from, to] (medianoche UTC, inclusive).

func (*ScheduleClient) RemoveException added in v0.1.4

func (c *ScheduleClient) RemoveException(exceptionId string, done func(error))

RemoveException da de baja una excepción por id.

func (*ScheduleClient) SaveDayBlocks added in v0.1.5

func (c *ScheduleClient) SaveDayBlocks(dayOfWeek int, blocks []WorkCalendarBlock, done func(error))

SaveDayBlocks pisa todos los bloques semanales del weekday dado.

type SchedulingService

type SchedulingService interface {
	// Configuración de servicio de empleado
	CreateEmployeeServiceConfig(cfg EmployeeServiceConfig) (EmployeeServiceConfig, error)
	GetEmployeeServiceConfig(id string) (EmployeeServiceConfig, error)
	ListEmployeeServiceConfigByStaff(tenantId, staffId string) ([]EmployeeServiceConfig, error)
	UpdateEmployeeServiceConfig(cfg EmployeeServiceConfig) error

	// Gestión de calendario
	UpsertCalendarConfig(cfg WorkCalendarConfig) error
	SaveDayBlocks(tenantId, staffId string, dayOfWeek int, blocks []WorkCalendarBlock) error
	SaveDateBlocks(tenantId, staffId string, date int64, blocks []WorkCalendarBlock) error
	MarkWorkingDays(tenantId, staffId string, dates []int64, startMin, endMin int) error
	UnmarkWorkingDays(tenantId, staffId string, dates []int64) error
	ListBlocks(tenantId, staffId string) ([]WorkCalendarBlock, error)
	AddException(exc WorkCalendarException) error
	RemoveException(tenantId, exceptionId string) error
	ListExceptions(tenantId, staffId string, from, to int64) ([]WorkCalendarException, error)
	GetDayBounds(date int64) (tinytime.DayBounds, error)

	// Disponibilidad
	ListAvailability(tenantId, staffId, configId string, from, to int64) ([]TimeSlot, error)

	// Reservas
	CreateReservation(cmd CreateReservationCmd) (Reservation, error)
	GetReservation(tenantId, id string) (Reservation, error)
	ListReservationsByStaff(tenantId, staffId string, from, to int64) ([]Reservation, error)
	ListReservationsByClient(tenantId, clientId string) ([]Reservation, error)
	ChangeReservationStatus(cmd ChangeStatusCmd) error
	ExpirePendingReservations(tenantId string, before int64) (int, error)

	// Conflictos
	ListConflictingReservations(tenantId, staffId string, from int64) ([]ConflictingReservation, error)
	RecomputeConflicts(tenantId string, from, to int64) (int, error)
}

type StaffReader

type StaffReader interface {
	StaffExists(tenantId, staffId string) (bool, error)
}

StaffReader verifica que un miembro del staff existe y pertenece al tenant.

type TimeSlot

type TimeSlot struct {
	StartUtc int64
	EndUtc   int64
}

func (*TimeSlot) DecodeFields

func (m *TimeSlot) DecodeFields(r model.FieldReader)

func (*TimeSlot) EncodeFields

func (m *TimeSlot) EncodeFields(w model.FieldWriter)

func (*TimeSlot) IsNil

func (m *TimeSlot) IsNil() bool

func (*TimeSlot) ModelName

func (m *TimeSlot) ModelName() string

func (*TimeSlot) Pointers

func (m *TimeSlot) Pointers() []any

func (*TimeSlot) Schema

func (m *TimeSlot) Schema() []model.Field

func (*TimeSlot) Validate

func (m *TimeSlot) Validate(action byte) error

type TimeSlotList

type TimeSlotList []*TimeSlot

func (*TimeSlotList) Append

func (s *TimeSlotList) Append() model.Fielder

func (*TimeSlotList) At

func (s *TimeSlotList) At(i int) model.Fielder

func (*TimeSlotList) DecodeFields

func (s *TimeSlotList) DecodeFields(_ model.FieldReader)

func (*TimeSlotList) EncodeFields

func (s *TimeSlotList) EncodeFields(_ model.FieldWriter)

func (*TimeSlotList) IsNil

func (s *TimeSlotList) IsNil() bool

func (*TimeSlotList) Len

func (s *TimeSlotList) Len() int

type UnmarkWorkingDaysArgs added in v0.1.5

type UnmarkWorkingDaysArgs struct {
	TenantId string
	StaffId  string
	Dates    []int
}

func (*UnmarkWorkingDaysArgs) DecodeFields added in v0.1.5

func (m *UnmarkWorkingDaysArgs) DecodeFields(r model.FieldReader)

func (*UnmarkWorkingDaysArgs) EncodeFields added in v0.1.5

func (m *UnmarkWorkingDaysArgs) EncodeFields(w model.FieldWriter)

func (*UnmarkWorkingDaysArgs) IsNil added in v0.1.5

func (m *UnmarkWorkingDaysArgs) IsNil() bool

func (*UnmarkWorkingDaysArgs) ModelName added in v0.1.5

func (m *UnmarkWorkingDaysArgs) ModelName() string

func (*UnmarkWorkingDaysArgs) Pointers added in v0.1.5

func (m *UnmarkWorkingDaysArgs) Pointers() []any

func (*UnmarkWorkingDaysArgs) Schema added in v0.1.5

func (m *UnmarkWorkingDaysArgs) Schema() []model.Field

func (*UnmarkWorkingDaysArgs) Validate added in v0.1.5

func (m *UnmarkWorkingDaysArgs) Validate(action byte) error

type UnmarkWorkingDaysArgsList added in v0.1.5

type UnmarkWorkingDaysArgsList []*UnmarkWorkingDaysArgs

func (*UnmarkWorkingDaysArgsList) Append added in v0.1.5

func (*UnmarkWorkingDaysArgsList) At added in v0.1.5

func (*UnmarkWorkingDaysArgsList) DecodeFields added in v0.1.5

func (s *UnmarkWorkingDaysArgsList) DecodeFields(_ model.FieldReader)

func (*UnmarkWorkingDaysArgsList) EncodeFields added in v0.1.5

func (s *UnmarkWorkingDaysArgsList) EncodeFields(_ model.FieldWriter)

func (*UnmarkWorkingDaysArgsList) IsNil added in v0.1.5

func (s *UnmarkWorkingDaysArgsList) IsNil() bool

func (*UnmarkWorkingDaysArgsList) Len added in v0.1.5

func (s *UnmarkWorkingDaysArgsList) Len() int

type UpsertCalendarConfigArgs

type UpsertCalendarConfigArgs struct {
	TenantId string
	StaffId  string
	Timezone string
	IsActive bool
}

func (*UpsertCalendarConfigArgs) DecodeFields

func (m *UpsertCalendarConfigArgs) DecodeFields(r model.FieldReader)

func (*UpsertCalendarConfigArgs) EncodeFields

func (m *UpsertCalendarConfigArgs) EncodeFields(w model.FieldWriter)

func (*UpsertCalendarConfigArgs) IsNil

func (m *UpsertCalendarConfigArgs) IsNil() bool

func (*UpsertCalendarConfigArgs) ModelName

func (m *UpsertCalendarConfigArgs) ModelName() string

func (*UpsertCalendarConfigArgs) Pointers

func (m *UpsertCalendarConfigArgs) Pointers() []any

func (*UpsertCalendarConfigArgs) Schema

func (m *UpsertCalendarConfigArgs) Schema() []model.Field

func (*UpsertCalendarConfigArgs) Validate

func (m *UpsertCalendarConfigArgs) Validate(action byte) error

type UpsertCalendarConfigArgsList

type UpsertCalendarConfigArgsList []*UpsertCalendarConfigArgs

func (*UpsertCalendarConfigArgsList) Append

func (*UpsertCalendarConfigArgsList) At

func (*UpsertCalendarConfigArgsList) DecodeFields

func (s *UpsertCalendarConfigArgsList) DecodeFields(_ model.FieldReader)

func (*UpsertCalendarConfigArgsList) EncodeFields

func (s *UpsertCalendarConfigArgsList) EncodeFields(_ model.FieldWriter)

func (*UpsertCalendarConfigArgsList) IsNil

func (*UpsertCalendarConfigArgsList) Len

type WorkCalendarBlock added in v0.1.5

type WorkCalendarBlock struct {
	Id           string
	TenantId     string
	StaffId      string
	DayOfWeek    int64
	SpecificDate int64
	StartMin     int64
	EndMin       int64
	IsActive     bool
}

func ReadOneWorkCalendarBlock added in v0.1.5

func ReadOneWorkCalendarBlock(qb *orm.QB, model *WorkCalendarBlock) (*WorkCalendarBlock, error)

func (*WorkCalendarBlock) DecodeFields added in v0.1.5

func (m *WorkCalendarBlock) DecodeFields(r model.FieldReader)

func (*WorkCalendarBlock) EncodeFields added in v0.1.5

func (m *WorkCalendarBlock) EncodeFields(w model.FieldWriter)

func (*WorkCalendarBlock) IsNil added in v0.1.5

func (m *WorkCalendarBlock) IsNil() bool

func (*WorkCalendarBlock) ModelName added in v0.1.5

func (m *WorkCalendarBlock) ModelName() string

func (*WorkCalendarBlock) Pointers added in v0.1.5

func (m *WorkCalendarBlock) Pointers() []any

func (*WorkCalendarBlock) Schema added in v0.1.5

func (m *WorkCalendarBlock) Schema() []model.Field

func (*WorkCalendarBlock) Validate added in v0.1.5

func (m *WorkCalendarBlock) Validate(action byte) error

type WorkCalendarBlockList added in v0.1.5

type WorkCalendarBlockList []*WorkCalendarBlock

func ReadAllWorkCalendarBlock added in v0.1.5

func ReadAllWorkCalendarBlock(qb *orm.QB) (WorkCalendarBlockList, error)

func (*WorkCalendarBlockList) Append added in v0.1.5

func (s *WorkCalendarBlockList) Append() model.Fielder

func (*WorkCalendarBlockList) At added in v0.1.5

func (*WorkCalendarBlockList) DecodeFields added in v0.1.5

func (s *WorkCalendarBlockList) DecodeFields(_ model.FieldReader)

func (*WorkCalendarBlockList) EncodeFields added in v0.1.5

func (s *WorkCalendarBlockList) EncodeFields(_ model.FieldWriter)

func (*WorkCalendarBlockList) IsNil added in v0.1.5

func (s *WorkCalendarBlockList) IsNil() bool

func (*WorkCalendarBlockList) Len added in v0.1.5

func (s *WorkCalendarBlockList) Len() int

type WorkCalendarConfig

type WorkCalendarConfig struct {
	Id       string
	TenantId string
	StaffId  string
	Timezone string
	IsActive bool
}

func ReadOneWorkCalendarConfig

func ReadOneWorkCalendarConfig(qb *orm.QB, model *WorkCalendarConfig) (*WorkCalendarConfig, error)

func (*WorkCalendarConfig) DecodeFields

func (m *WorkCalendarConfig) DecodeFields(r model.FieldReader)

func (*WorkCalendarConfig) EncodeFields

func (m *WorkCalendarConfig) EncodeFields(w model.FieldWriter)

func (*WorkCalendarConfig) IsNil

func (m *WorkCalendarConfig) IsNil() bool

func (*WorkCalendarConfig) ModelName

func (m *WorkCalendarConfig) ModelName() string

func (*WorkCalendarConfig) Pointers

func (m *WorkCalendarConfig) Pointers() []any

func (*WorkCalendarConfig) Schema

func (m *WorkCalendarConfig) Schema() []model.Field

func (*WorkCalendarConfig) Validate

func (m *WorkCalendarConfig) Validate(action byte) error

type WorkCalendarConfigList

type WorkCalendarConfigList []*WorkCalendarConfig

func ReadAllWorkCalendarConfig

func ReadAllWorkCalendarConfig(qb *orm.QB) (WorkCalendarConfigList, error)

func (*WorkCalendarConfigList) Append

func (s *WorkCalendarConfigList) Append() model.Fielder

func (*WorkCalendarConfigList) At

func (*WorkCalendarConfigList) DecodeFields

func (s *WorkCalendarConfigList) DecodeFields(_ model.FieldReader)

func (*WorkCalendarConfigList) EncodeFields

func (s *WorkCalendarConfigList) EncodeFields(_ model.FieldWriter)

func (*WorkCalendarConfigList) IsNil

func (s *WorkCalendarConfigList) IsNil() bool

func (*WorkCalendarConfigList) Len

func (s *WorkCalendarConfigList) Len() int

type WorkCalendarException

type WorkCalendarException struct {
	Id            string
	TenantId      string
	StaffId       string
	SpecificDate  int64
	ExceptionType string
	StartTime     int64
	EndTime       int64
	Notes         string
}

func ReadOneWorkCalendarException

func ReadOneWorkCalendarException(qb *orm.QB, model *WorkCalendarException) (*WorkCalendarException, error)

func (*WorkCalendarException) DecodeFields

func (m *WorkCalendarException) DecodeFields(r model.FieldReader)

func (*WorkCalendarException) EncodeFields

func (m *WorkCalendarException) EncodeFields(w model.FieldWriter)

func (*WorkCalendarException) IsNil

func (m *WorkCalendarException) IsNil() bool

func (*WorkCalendarException) ModelName

func (m *WorkCalendarException) ModelName() string

func (*WorkCalendarException) Pointers

func (m *WorkCalendarException) Pointers() []any

func (*WorkCalendarException) Schema

func (m *WorkCalendarException) Schema() []model.Field

func (*WorkCalendarException) Validate

func (m *WorkCalendarException) Validate(action byte) error

type WorkCalendarExceptionList

type WorkCalendarExceptionList []*WorkCalendarException

func ReadAllWorkCalendarException

func ReadAllWorkCalendarException(qb *orm.QB) (WorkCalendarExceptionList, error)

func (*WorkCalendarExceptionList) Append

func (*WorkCalendarExceptionList) At

func (*WorkCalendarExceptionList) DecodeFields

func (s *WorkCalendarExceptionList) DecodeFields(_ model.FieldReader)

func (*WorkCalendarExceptionList) EncodeFields

func (s *WorkCalendarExceptionList) EncodeFields(_ model.FieldWriter)

func (*WorkCalendarExceptionList) IsNil

func (s *WorkCalendarExceptionList) IsNil() bool

func (*WorkCalendarExceptionList) Len

func (s *WorkCalendarExceptionList) Len() int

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL