appointmentbooking

package module
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2026 License: MIT Imports: 11 Imported by: 0

README

appointment-booking

Manages schedulable service configuration, staff work calendars, and client reservations.

Main entities

  • employee_service_config: configuration of which services each professional handles (duration, price override).
  • reservation: the scheduled appointment (date/time, client, professional, service).
  • workcalendar_weekly: weekly work schedules per staff member.
  • workcalendar_exception: one-off exceptions (personal holidays, special hours, blocked intervals).

Documentation

Design / decoupling notes

No physical FKs to other modules:

  • reservation.client_id references a client (Directory/Clinical) by ID.
  • reservation.creator_user_id references an IAM user.
  • employee_service_config.service_id references an item from the Catalog module.
  • staff_id fields reference the Staff module.

Availability rules (calendar + exceptions) are enforced at the application layer, not via cross-module FKs. Reservation status is enforced by an in-code FSM — no reservation_status table.

Development Rules (SKILL)

Core Constraints & Rules
  • FSM-only status changes: Reservation.Status MUST only change via FSM.Transition(current, event). Never set status directly. Valid events: CONFIRM, CANCEL, COMPLETE, NO_SHOW_EVENT, EXPIRE, RESCHEDULE.
  • RESCHEDULED ≠ CANCELLED: When a reservation is replaced by a new one, the original is marked RESCHEDULED (not CANCELLED) for audit trail integrity. These are different terminal states.
  • Timezone is in WorkCalendarConfig: WorkCalendarWeekly and WorkCalendarException have NO timezone field. Always load WorkCalendarConfig first to get the IANA timezone. Working hours are local integers (e.g., 900 = 09:00), converted to UTC at query time via LocalIntToUnixUTC.
  • Snapshotting: At reservation creation, price, currency, duration, staffID, and serviceID are snapshotted. Never mutate snapshot fields after creation.
  • No RBAC here: This module trusts actorID as an already-authorized string. Authorization is enforced by the MCP gateway before reaching the service. This module only stores actorID as an audit field.
  • EventPublisher is fire-and-forget: After each successful state mutation, publish a domain event via the injected EventPublisher. Publish errors are logged and never fail the operation. nil publisher is safe.
  • MCP is the only external entry point. The service is never called directly except by the MCP handler layer.
  • No cross-module imports. External dependencies are accessed only via injected interfaces: StaffReader, CatalogReader, DirectoryReader.
  • tinywasm packages only for WASM compatibility: use tinywasm/fmt, tinywasm/time, tinywasm/json — never standard library equivalents.
Injected Interfaces (constructor parameters)

The service holds *orm.DB directly — no intermediate store interfaces. Only cross-module dependencies are injected:

type Deps struct {
    Staff     StaffReader     // provided by staff module
    Catalog   CatalogReader   // provided by catalog module
    Directory DirectoryReader // provided by directory module
    Publisher EventPublisher  // nil = events disabled
}

// Constructor: db is *orm.DB passed directly.
func New(db *orm.DB, deps Deps) SchedulingService
Domain Events Published
Event constant When
appointment.reservation.created After CreateReservation commits
appointment.reservation.rescheduled For the original reservation during reschedule
appointment.reservation.confirmed After CONFIRM transition
appointment.reservation.cancelled After CANCEL transition
appointment.reservation.completed After COMPLETE transition
appointment.reservation.no_show After NO_SHOW transition
appointment.reservation.expired After EXPIRE transition
Key Error Sentinels
Error When
ErrSlotTaken Slot not available or concurrent booking race
ErrConflict Optimistic concurrency mismatch on UpdateReservationStatus
ErrCalendarConfigNotFound UpsertWeeklyCalendar called before UpsertCalendarConfig
ErrInvalidTransition FSM rejects the event for the current status
Composition Root (how to wire this module)
scheduling := appointmentbooking.New(db, appointmentbooking.Deps{
    Staff:     staffmodule.New(db),     // implements StaffReader
    Catalog:   catalogmodule.New(db),   // implements CatalogReader
    Directory: directorymodule.New(db), // implements DirectoryReader
    Publisher: eventBus,                // nil = events disabled
})
providers := []mcp.ToolProvider{
    appointmentbooking.NewReservationProvider(scheduling),
    appointmentbooking.NewCalendarProvider(scheduling),
}
// mcp.NewServer(mcp.Config{...}, providers)
Available MCP Tools (13 total)

list_availability, create_reservation, get_reservation, list_reservations_by_staff, list_reservations_by_client, change_reservation_status, upsert_calendar_config, upsert_weekly_calendar, add_calendar_exception, remove_calendar_exception, expire_pending_reservations, list_weekly_calendar, list_exceptions

expire_pending_reservations is the only trigger for the EXPIRE FSM event. It must be called by an external scheduler — the module has no internal background process.

list_weekly_calendar and list_exceptions are the raw reads a schedule editor needs; the caller-side face is NewScheduleClient (see below).

ScheduleClient — the schedule-editor face

NewScheduleClient(caller router.Caller, tenantId, staffId string) *ScheduleClient is a caller-side typed client over the calendar ops, intended to be adapted by an app to a scheduleeditor UI component. Importing only router + this module's types, it stays renderer-agnostic:

cl := appointmentbooking.NewScheduleClient(caller, "t1", "s1")
cl.Weekly(func(rows []appointmentbooking.WorkCalendarWeekly, err error) { /* … */ })
cl.Exceptions(from, to, func(rows []appointmentbooking.WorkCalendarException, err error) { /* … */ })
cl.SaveWeeklyRow(row, func(err error) { /* … */ })
cl.AddException(exc, func(err error) { /* … */ })
cl.RemoveException(exceptionID, func(err error) { /* … */ })

Every successful calendar mutation also publishes the appointment.schedule.changed event (ScheduleChangedPayload{TenantId, StaffId}) so consumers can recompute availability.

Service interface

type SchedulingService interface {
    // Calendar management
    UpsertCalendarConfig(ctx context.Context, cfg WorkCalendarConfig) error
    UpsertWeeklyCalendar(ctx context.Context, cal WorkCalendarWeekly) error
    AddException(ctx context.Context, exc WorkCalendarException) error
    RemoveException(ctx context.Context, tenantID, exceptionID string) error

    // Availability
    ListAvailability(ctx context.Context, tenantID, staffID, configID string, from, to int64) ([]TimeSlot, error)

    // Reservations
    CreateReservation(ctx context.Context, cmd CreateReservationCmd) (Reservation, error)
    GetReservation(ctx context.Context, tenantID, id string) (Reservation, error)
    ListReservationsByStaff(ctx context.Context, tenantID, staffID string, from, to int64) ([]Reservation, error)
    ListReservationsByClient(ctx context.Context, tenantID, clientID string) ([]Reservation, error)
    ChangeReservationStatus(ctx context.Context, cmd ChangeStatusCmd) error
}

This interface depends on injected readers:

  • DirectoryReader — validates client existence
  • StaffReader — validates staff existence
  • CatalogReader — validates service existence

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)
)

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
)

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"
	OpUpsertWeeklyCalendar      = "upsert_weekly_calendar"
	OpAddCalendarException      = "add_calendar_exception"
	OpRemoveCalendarException   = "remove_calendar_exception"
	OpListAvailability          = "list_availability"
	OpListWeeklyCalendar        = "list_weekly_calendar"
	OpListExceptions            = "list_exceptions"
)
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"
	// EventScheduleChanged se emite al mutar la agenda de un profesional
	// (upsert semanal, alta/baja de excepción). Un consumidor lo usa para
	// recalcular disponibilidad (p. ej. reservation recarga sus huecos libres).
	EventScheduleChanged = "appointment.schedule.changed"
)

Eventos de dominio emitidos por este módulo.

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")
)
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 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 EmployeeServiceConfigModel = model.Definition{
	Name: "employee_service_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: "service_id", Type: model.Text(), NotNull: true},
		{Name: "duration_min", Type: model.Int()},
		{Name: "buffer_min", Type: model.Int()},
		{Name: "price_override", Type: model.Float()},
		{Name: "payment_required", Type: model.Bool()},
		{Name: "is_active", Type: model.Bool()},
	},
}
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 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 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 ListWeeklyCalendarArgsModel = model.Definition{
	Name: "list_weekly_calendar_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
	},
}
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 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: "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
	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",
	PaymentId:               "payment_id",
	Notes:                   "notes",
	UpdatedAt:               "updated_at",
	UpdatedBy:               "updated_by",
	Revision:                "revision",
}
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 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 UpsertWeeklyCalendarArgsModel = model.Definition{
	Name: "upsert_weekly_calendar_args",
	Fields: model.Fields{
		{Name: "tenant_id", Type: model.Text()},
		{Name: "staff_id", Type: input.Text()},
		{Name: "day_of_week", Type: input.Number()},
		{Name: "work_start", Type: input.Number()},
		{Name: "work_finish", Type: input.Number()},
		{Name: "break_start", Type: input.Number()},
		{Name: "break_finish", Type: input.Number()},
		{Name: "is_active", Type: input.Checkbox()},
	},
}
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",
}
View Source
var WorkCalendarWeeklyModel = model.Definition{
	Name: "work_calendar_weekly",
	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()},
		{Name: "work_start", Type: model.Int()},
		{Name: "work_finish", Type: model.Int()},
		{Name: "break_start", Type: model.Int()},
		{Name: "break_finish", Type: model.Int()},
		{Name: "is_active", Type: model.Bool()},
	},
}
View Source
var WorkCalendarWeekly_ = struct {
	Id          string
	TenantId    string
	StaffId     string
	DayOfWeek   string
	WorkStart   string
	WorkFinish  string
	BreakStart  string
	BreakFinish string
	IsActive    string
}{
	Id:          "id",
	TenantId:    "tenant_id",
	StaffId:     "staff_id",
	DayOfWeek:   "day_of_week",
	WorkStart:   "work_start",
	WorkFinish:  "work_finish",
	BreakStart:  "break_start",
	BreakFinish: "break_finish",
	IsActive:    "is_active",
}

Functions

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 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

func (*AddCalendarExceptionArgsList) Pointers

func (s *AddCalendarExceptionArgsList) Pointers() []any

func (*AddCalendarExceptionArgsList) Schema

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

func (*ChangeReservationStatusArgsList) Pointers

func (s *ChangeReservationStatusArgsList) Pointers() []any

func (*ChangeReservationStatusArgsList) Schema

type ChangeStatusCmd

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

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

func (*CreateReservationArgsList) Pointers

func (s *CreateReservationArgsList) Pointers() []any

func (*CreateReservationArgsList) Schema

func (s *CreateReservationArgsList) Schema() []model.Field

type CreateReservationCmd

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

type Deps

type Deps struct {
	Staff     StaffReader
	Catalog   CatalogReader
	Directory DirectoryReader
	IDs       model.IDGenerator // requerido
	Publisher events.Publisher  // opcional — nil desactiva
}

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) 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

func (*EmployeeServiceConfigList) Pointers

func (s *EmployeeServiceConfigList) Pointers() []any

func (*EmployeeServiceConfigList) Schema

func (s *EmployeeServiceConfigList) Schema() []model.Field

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

func (*ExpirePendingReservationsArgsList) Pointers

func (s *ExpirePendingReservationsArgsList) Pointers() []any

func (*ExpirePendingReservationsArgsList) Schema

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

func (*GetReservationArgsList) Pointers

func (s *GetReservationArgsList) Pointers() []any

func (*GetReservationArgsList) Schema

func (s *GetReservationArgsList) Schema() []model.Field

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

func (*ListAvailabilityArgsList) Pointers

func (s *ListAvailabilityArgsList) Pointers() []any

func (*ListAvailabilityArgsList) Schema

func (s *ListAvailabilityArgsList) Schema() []model.Field

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

func (*ListExceptionsArgsList) Pointers added in v0.1.4

func (s *ListExceptionsArgsList) Pointers() []any

func (*ListExceptionsArgsList) Schema added in v0.1.4

func (s *ListExceptionsArgsList) Schema() []model.Field

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

func (*ListReservationsByClientArgsList) Pointers

func (s *ListReservationsByClientArgsList) Pointers() []any

func (*ListReservationsByClientArgsList) Schema

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

func (*ListReservationsByStaffArgsList) Pointers

func (s *ListReservationsByStaffArgsList) Pointers() []any

func (*ListReservationsByStaffArgsList) Schema

type ListWeeklyCalendarArgs added in v0.1.4

type ListWeeklyCalendarArgs struct {
	TenantId string
	StaffId  string
}

func (*ListWeeklyCalendarArgs) DecodeFields added in v0.1.4

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

func (*ListWeeklyCalendarArgs) EncodeFields added in v0.1.4

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

func (*ListWeeklyCalendarArgs) IsNil added in v0.1.4

func (m *ListWeeklyCalendarArgs) IsNil() bool

func (*ListWeeklyCalendarArgs) ModelName added in v0.1.4

func (m *ListWeeklyCalendarArgs) ModelName() string

func (*ListWeeklyCalendarArgs) Pointers added in v0.1.4

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

func (*ListWeeklyCalendarArgs) Schema added in v0.1.4

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

func (*ListWeeklyCalendarArgs) Validate added in v0.1.4

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

type ListWeeklyCalendarArgsList added in v0.1.4

type ListWeeklyCalendarArgsList []*ListWeeklyCalendarArgs

func (*ListWeeklyCalendarArgsList) Append added in v0.1.4

func (*ListWeeklyCalendarArgsList) At added in v0.1.4

func (*ListWeeklyCalendarArgsList) DecodeFields added in v0.1.4

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

func (*ListWeeklyCalendarArgsList) EncodeFields added in v0.1.4

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

func (*ListWeeklyCalendarArgsList) IsNil added in v0.1.4

func (s *ListWeeklyCalendarArgsList) IsNil() bool

func (*ListWeeklyCalendarArgsList) Len added in v0.1.4

func (*ListWeeklyCalendarArgsList) Pointers added in v0.1.4

func (s *ListWeeklyCalendarArgsList) Pointers() []any

func (*ListWeeklyCalendarArgsList) Schema added in v0.1.4

func (s *ListWeeklyCalendarArgsList) Schema() []model.Field

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) CreateReservation

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

func (*Module) ExpirePendingReservations

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

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) 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) ListWeeklyCalendar added in v0.1.4

func (m *Module) ListWeeklyCalendar(tenantId, staffId string) ([]WorkCalendarWeekly, error)

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) RemoveException

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

func (*Module) UpsertCalendarConfig

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

func (*Module) UpsertWeeklyCalendar

func (m *Module) UpsertWeeklyCalendar(cal WorkCalendarWeekly) error

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

func (*RemoveCalendarExceptionArgsList) Pointers

func (s *RemoveCalendarExceptionArgsList) Pointers() []any

func (*RemoveCalendarExceptionArgsList) Schema

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 y migra sus 5 tablas propias cuando el backend soporta DDL (no-op contra storage/mem, usado por las pruebas propias de este módulo).

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) 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) ListWeeklyCalendar

func (r *Repository) ListWeeklyCalendar(tenantId, staffId string) ([]WorkCalendarWeekly, error)

func (*Repository) UpdateEmployeeServiceConfig

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

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

func (*Repository) UpsertWeeklyCalendar

func (r *Repository) UpsertWeeklyCalendar(cal WorkCalendarWeekly) 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
	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 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

func (*ReservationList) Pointers

func (s *ReservationList) Pointers() []any

func (*ReservationList) Schema

func (s *ReservationList) Schema() []model.Field

type ScheduleChangedPayload added in v0.1.4

type ScheduleChangedPayload struct {
	TenantId string
	StaffId  string
}

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) 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) SaveWeeklyRow added in v0.1.4

func (c *ScheduleClient) SaveWeeklyRow(row WorkCalendarWeekly, done func(error))

SaveWeeklyRow persiste (upsert) una fila de la plantilla semanal.

func (*ScheduleClient) Weekly added in v0.1.4

func (c *ScheduleClient) Weekly(done func([]WorkCalendarWeekly, error))

Weekly carga la plantilla semanal completa del profesional.

type SchedulingService

type SchedulingService interface {
	// Gestión de calendario
	UpsertCalendarConfig(cfg WorkCalendarConfig) error
	UpsertWeeklyCalendar(cal WorkCalendarWeekly) error
	AddException(exc WorkCalendarException) error
	RemoveException(tenantId, exceptionId string) error
	ListWeeklyCalendar(tenantId, staffId string) ([]WorkCalendarWeekly, error)
	ListExceptions(tenantId, staffId string, from, to int64) ([]WorkCalendarException, 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)
}

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

func (*TimeSlotList) Pointers

func (s *TimeSlotList) Pointers() []any

func (*TimeSlotList) Schema

func (s *TimeSlotList) Schema() []model.Field

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

func (*UpsertCalendarConfigArgsList) Pointers

func (s *UpsertCalendarConfigArgsList) Pointers() []any

func (*UpsertCalendarConfigArgsList) Schema

type UpsertWeeklyCalendarArgs

type UpsertWeeklyCalendarArgs struct {
	TenantId    string
	StaffId     string
	DayOfWeek   int64
	WorkStart   int64
	WorkFinish  int64
	BreakStart  int64
	BreakFinish int64
	IsActive    bool
}

func (*UpsertWeeklyCalendarArgs) DecodeFields

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

func (*UpsertWeeklyCalendarArgs) EncodeFields

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

func (*UpsertWeeklyCalendarArgs) IsNil

func (m *UpsertWeeklyCalendarArgs) IsNil() bool

func (*UpsertWeeklyCalendarArgs) ModelName

func (m *UpsertWeeklyCalendarArgs) ModelName() string

func (*UpsertWeeklyCalendarArgs) Pointers

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

func (*UpsertWeeklyCalendarArgs) Schema

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

func (*UpsertWeeklyCalendarArgs) Validate

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

type UpsertWeeklyCalendarArgsList

type UpsertWeeklyCalendarArgsList []*UpsertWeeklyCalendarArgs

func (*UpsertWeeklyCalendarArgsList) Append

func (*UpsertWeeklyCalendarArgsList) At

func (*UpsertWeeklyCalendarArgsList) DecodeFields

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

func (*UpsertWeeklyCalendarArgsList) EncodeFields

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

func (*UpsertWeeklyCalendarArgsList) IsNil

func (*UpsertWeeklyCalendarArgsList) Len

func (*UpsertWeeklyCalendarArgsList) Pointers

func (s *UpsertWeeklyCalendarArgsList) Pointers() []any

func (*UpsertWeeklyCalendarArgsList) Schema

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

func (*WorkCalendarConfigList) Pointers

func (s *WorkCalendarConfigList) Pointers() []any

func (*WorkCalendarConfigList) Schema

func (s *WorkCalendarConfigList) Schema() []model.Field

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

func (*WorkCalendarExceptionList) Pointers

func (s *WorkCalendarExceptionList) Pointers() []any

func (*WorkCalendarExceptionList) Schema

func (s *WorkCalendarExceptionList) Schema() []model.Field

type WorkCalendarWeekly

type WorkCalendarWeekly struct {
	Id          string
	TenantId    string
	StaffId     string
	DayOfWeek   int64
	WorkStart   int64
	WorkFinish  int64
	BreakStart  int64
	BreakFinish int64
	IsActive    bool
}

func ReadOneWorkCalendarWeekly

func ReadOneWorkCalendarWeekly(qb *orm.QB, model *WorkCalendarWeekly) (*WorkCalendarWeekly, error)

func (*WorkCalendarWeekly) DecodeFields

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

func (*WorkCalendarWeekly) EncodeFields

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

func (*WorkCalendarWeekly) IsNil

func (m *WorkCalendarWeekly) IsNil() bool

func (*WorkCalendarWeekly) ModelName

func (m *WorkCalendarWeekly) ModelName() string

func (*WorkCalendarWeekly) Pointers

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

func (*WorkCalendarWeekly) Schema

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

func (*WorkCalendarWeekly) Validate

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

type WorkCalendarWeeklyList

type WorkCalendarWeeklyList []*WorkCalendarWeekly

func ReadAllWorkCalendarWeekly

func ReadAllWorkCalendarWeekly(qb *orm.QB) (WorkCalendarWeeklyList, error)

func (*WorkCalendarWeeklyList) Append

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

func (*WorkCalendarWeeklyList) At

func (*WorkCalendarWeeklyList) DecodeFields

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

func (*WorkCalendarWeeklyList) EncodeFields

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

func (*WorkCalendarWeeklyList) IsNil

func (s *WorkCalendarWeeklyList) IsNil() bool

func (*WorkCalendarWeeklyList) Len

func (s *WorkCalendarWeeklyList) Len() int

func (*WorkCalendarWeeklyList) Pointers

func (s *WorkCalendarWeeklyList) Pointers() []any

func (*WorkCalendarWeeklyList) Schema

func (s *WorkCalendarWeeklyList) Schema() []model.Field

Jump to

Keyboard shortcuts

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