144 lines
4.1 KiB
Go
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("aSeat, &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(¤tQuota)
|
|
|
|
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(¤tQuota)
|
|
|
|
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
|
|
}
|