refactor(bookings): use computed booking fields and LATERAL joins

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-06-22 00:57:55 +01:00
co-authored by Sisyphus
parent bdee60d34f
commit 0d940e8608
+23 -14
View File
@@ -428,16 +428,19 @@ func GetAllUserBookingsHandler(w http.ResponseWriter, r *http.Request) {
dataQuery := `
SELECT
b.id, b.start_time, b.status, b.notes, b.created_at, b.updated_at, b.created_by,
(SELECT total_amount FROM bookings WHERE id = b.id) AS total_amount,
(SELECT COALESCE(SUM(amount), 0)
FROM payments
WHERE booking_id = b.id AND status = 'completed') AS amount_paid,
(SELECT total_duration_minutes FROM bookings WHERE id = b.id) AS duration_minutes,
b.total_amount,
COALESCE(pt.amount_paid, 0) AS amount_paid,
b.total_duration_minutes AS duration_minutes,
b.deposit_required,
(SELECT COALESCE(SUM(amount), 0)
COALESCE(pt.pre_start_amount_paid, 0) AS pre_start_amount_paid
FROM bookings b
LEFT JOIN LATERAL (
SELECT
COALESCE(SUM(amount) FILTER (WHERE status = 'completed'), 0) AS amount_paid,
COALESCE(SUM(amount) FILTER (WHERE status = 'completed' AND created_at < b.start_time), 0) AS pre_start_amount_paid
FROM payments
WHERE booking_id = b.id AND status = 'completed' AND created_at < b.start_time) AS pre_start_amount_paid
FROM bookings b` + whereClause
WHERE booking_id = b.id
) pt ON true` + whereClause
dataArgs := make([]interface{}, len(whereArgs))
copy(dataArgs, whereArgs)
@@ -662,13 +665,16 @@ func GetAllAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
COALESCE(bt.total_amount, 0) - COALESCE(pt.total_paid, 0) AS amount_due,
b.deposit_required,
COALESCE(bt.service_count, 0) AS service_count,
(SELECT COALESCE(SUM(p2.amount), 0)
FROM payments p2
WHERE p2.booking_id = b.id AND p2.status = 'completed' AND p2.created_at < b.start_time) AS pre_start_amount_paid
COALESCE(pre_pay.pre_start_amount_paid, 0) AS pre_start_amount_paid
FROM bookings b
LEFT JOIN users u ON b.user_id = u.id
LEFT JOIN booking_totals bt ON b.id = bt.booking_id
LEFT JOIN payment_totals pt ON b.id = pt.booking_id
LEFT JOIN LATERAL (
SELECT COALESCE(SUM(amount), 0) AS pre_start_amount_paid
FROM payments
WHERE booking_id = b.id AND status = 'completed' AND created_at < b.start_time
) pre_pay ON true
`
var args []interface{}
@@ -1734,13 +1740,16 @@ func SearchAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
COALESCE(pt.total_paid, 0) AS amount_paid,
COALESCE(bt.total_amount, 0) - COALESCE(pt.total_paid, 0) AS amount_due,
b.deposit_required,
(SELECT COALESCE(SUM(p2.amount), 0)
FROM payments p2
WHERE p2.booking_id = b.id AND p2.status = 'completed' AND p2.created_at < b.start_time) AS pre_start_amount_paid
COALESCE(pre_pay.pre_start_amount_paid, 0) AS pre_start_amount_paid
FROM bookings b
LEFT JOIN users u ON b.user_id = u.id
LEFT JOIN booking_totals bt ON b.id = bt.booking_id
LEFT JOIN payment_totals pt ON b.id = pt.booking_id
LEFT JOIN LATERAL (
SELECT COALESCE(SUM(amount), 0) AS pre_start_amount_paid
FROM payments
WHERE booking_id = b.id AND status = 'completed' AND created_at < b.start_time
) pre_pay ON true
-- NOTE: ILIKE with leading wildcard prevents B-tree index usage.
-- At scale, replace with pg_trgm GIN index: CREATE INDEX idx_bookings_search_trgm ON bookings USING GIN (id gin_trgm_ops, notes gin_trgm_ops);
-- Also consider indexes on users (n_first_name, n_last_name, fn, email, phone) for the joined table.