Files
api_antrean/internal/handlers/transaction/quota.go
T
2026-02-13 15:57:28 +07:00

144 lines
4.1 KiB
Go

package transaction
import (
"api-service/pkg/logger"
"context"
"database/sql"
"fmt"
"github.com/jmoiron/sqlx"
)
func (h *TiketHandler) CheckAndLockQuota(ctx context.Context, dbConn *sqlx.DB, loketID int, date string) (quotaSeat int, usedQuota int, err error) {
query := `
SELECT mrc.quota,
COALESCE(tmrcsq.seat_quota, 0) as used_quota
FROM master.ms_registration_counter mrc
LEFT JOIN temporary.tm_registration_counter_seat_quota tmrcsq
ON tmrcsq.fk_ms_registration_counter_id = mrc.id
AND tmrcsq.date = $1
WHERE mrc.id = $2
FOR UPDATE OF mrc
`
err = dbConn.QueryRowContext(ctx, query, date, loketID).Scan(&quotaSeat, &usedQuota)
return quotaSeat, usedQuota, err
}
func (h *TiketHandler) IncrementUsedQuota(ctx context.Context, dbConn *sqlx.DB, loketID int, date string, newUUID string) (newUsedQuota int, err error) {
checkQuery := `
SELECT seat_quota
FROM temporary.tm_registration_counter_seat_quota
WHERE fk_ms_registration_counter_id = $1
AND date = $2
`
var currentQuota int
err = dbConn.QueryRowContext(ctx, checkQuery, loketID, date).Scan(&currentQuota)
if err == sql.ErrNoRows {
insertQuery := `
INSERT INTO temporary.tm_registration_counter_seat_quota
(id, fk_ms_registration_counter_id, date, seat_quota)
VALUES ($1, $2, $3, 1)
RETURNING seat_quota
`
err = dbConn.QueryRowContext(ctx, insertQuery, newUUID, loketID, date).Scan(&newUsedQuota)
if err != nil {
return 0, fmt.Errorf("failed to insert quota: %w", err)
}
return newUsedQuota, nil
} else if err != nil {
// Error lain
return 0, fmt.Errorf("failed to check existing quota: %w", err)
}
updateQuery := `
UPDATE temporary.tm_registration_counter_seat_quota
SET seat_quota = seat_quota + 1
WHERE fk_ms_registration_counter_id = $1
AND date = $2
RETURNING seat_quota
`
err = dbConn.QueryRowContext(ctx, updateQuery, loketID, date).Scan(&newUsedQuota)
if err != nil {
return 0, fmt.Errorf("failed to update quota: %w", err)
}
return newUsedQuota, nil
}
func (h *TiketHandler) MinQuota(ctx context.Context, dbConn *sqlx.DB, loketID int, date string) (newUsedQuota int, err error) {
// Step 1: Cek quota saat ini
checkQuery := `
SELECT seat_quota
FROM temporary.tm_registration_counter_seat_quota
WHERE fk_ms_registration_counter_id = $1
AND date = $2
`
var currentQuota int
err = dbConn.QueryRowContext(ctx, checkQuery, loketID, date).Scan(&currentQuota)
if err == sql.ErrNoRows {
// Tidak ada record, berarti quota belum pernah dipakai
logger.Warn("No quota record found, nothing to decrement", map[string]interface{}{
"loket_id": loketID,
"date": date,
})
return 0, fmt.Errorf("no quota record found for this loket and date")
} else if err != nil {
return 0, fmt.Errorf("failed to check existing quota: %w", err)
}
// Step 2: Validasi quota tidak boleh negatif
if currentQuota <= 0 {
logger.Warn("Quota already at zero, cannot decrement", map[string]interface{}{
"loket_id": loketID,
"current_quota": currentQuota,
})
return 0, fmt.Errorf("quota already at zero")
}
// Step 3: Kurangi quota
updateQuery := `
UPDATE temporary.tm_registration_counter_seat_quota
SET seat_quota = seat_quota - 1
WHERE fk_ms_registration_counter_id = $1
AND date = $2
AND seat_quota > 0
RETURNING seat_quota
`
err = dbConn.QueryRowContext(ctx, updateQuery, loketID, date).Scan(&newUsedQuota)
if err != nil {
return 0, fmt.Errorf("failed to decrement quota: %w", err)
}
logger.Info("Quota decremented successfully", map[string]interface{}{
"loket_id": loketID,
"new_used_quota": newUsedQuota,
})
return newUsedQuota, nil
}
func (h *TiketHandler) GetLoketIDByTicketID(ctx context.Context, dbConn *sqlx.DB, ticketID int64) (loketID int, err error) {
query := `
SELECT fk_ms_registration_counter_id
FROM "transaction".tr_patient_visit_healthcare_service
WHERE id = $1
`
err = dbConn.QueryRowContext(ctx, query, ticketID).Scan(&loketID)
if err != nil {
if err == sql.ErrNoRows {
return 0, fmt.Errorf("ticket not found")
}
return 0, fmt.Errorf("failed to get loket ID: %w", err)
}
return loketID, nil
}