dana-medical-site/internal/storage/booking_availability.go
2026-10-22 09:44:04 +00:00

38 lines
1.3 KiB
Go

package storage
import "context"
type BookingDay struct {
Date string `json:"date"`
DoctorIDs []int64 `json:"doctor_ids"`
}
// PublicBookingDays returns only dates and public doctor IDs, never patient data.
// Keep the occupancy rules identical to FreeOnecSlots, including cross-branch reservations.
func (s *Storage) PublicBookingDays(ctx context.Context) ([]BookingDay, error) {
rows, err := s.pool.Query(ctx, `
SELECT to_char(sl.start_at AT TIME ZONE 'Europe/Moscow','YYYY-MM-DD'),
array_agg(DISTINCT d.id ORDER BY d.id)
FROM onec_slots sl JOIN onec_doctors od ON od.onec_id=sl.doctor_onec_id
JOIN doctors d ON d.id=od.doctor_id
WHERE sl.status='free' AND sl.start_at>now() AND od.active
AND d.published AND d.deleted_at IS NULL AND NOT d.absent AND d.booking_provider='native'
AND NOT EXISTS(SELECT 1 FROM onec_appointments a
WHERE a.doctor_onec_id=sl.doctor_onec_id AND a.status IN('pending','booked','arrived')
AND a.start_at<sl.end_at AND COALESCE(a.end_at,a.start_at+interval '30 minutes')>sl.start_at)
GROUP BY 1 ORDER BY 1`)
if err != nil {
return nil, err
}
defer rows.Close()
out := []BookingDay{}
for rows.Next() {
var day BookingDay
if err := rows.Scan(&day.Date, &day.DoctorIDs); err != nil {
return nil, err
}
out = append(out, day)
}
return out, rows.Err()
}