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

808 lines
26 KiB
Go

package transaction
import (
"api-service/internal/config"
"api-service/internal/database"
"api-service/internal/models"
"api-service/internal/models/transaction"
"api-service/pkg/logger"
"context"
"database/sql"
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
"log"
"net/http"
"strconv"
"sync"
"time"
)
var (
db database.Service
once sync.Once
validate *validator.Validate
)
func validated(fl validator.FieldLevel) bool {
return models.IsValidStatus(fl.Field().String())
}
func init() {
once.Do(func() {
db = database.New(config.LoadConfig())
validate = validator.New()
// Register custom validations if needed
validate.RegisterValidation("retribusi_status", validated)
if db == nil {
logger.Fatal("Failed to initialize database connection")
}
})
}
type TiketHandler struct {
db database.Service
}
func NewtiketHandler() *TiketHandler {
return &TiketHandler{
db: db,
}
}
func (h *TiketHandler) respondError(c *gin.Context, message string, err error, statusCode int) {
errorMessage := message
if gin.Mode() == gin.ReleaseMode {
errorMessage = "Internal server error"
}
c.JSON(statusCode, models.ErrorResponse{Error: errorMessage, Code: statusCode, Message: err.Error(), Timestamp: time.Now()})
}
func (h *TiketHandler) Createtiket(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
var req transaction.CreateTicketRequest
if err := c.ShouldBindJSON(&req); err != nil {
h.respondError(c, "Invalid request body", err, http.StatusBadRequest)
return
}
if err := validate.Struct(&req); err != nil {
h.respondError(c, "Validation failed", err, http.StatusBadRequest)
return
}
log.Println(req)
kodeID, err := strconv.Atoi(req.IDLoket)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Kode harus berupa angka"})
return
}
IDKlinik, err := strconv.Atoi(req.IdKlinik)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Kode harus berupa angka"})
return
}
dbConn, err := h.db.GetSQLXDB("postgres_antrean")
if err != nil {
logger.Error("Database connection failed", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database connection failed"})
return
}
newUUID := uuid.New().String()
currentDate := time.Now().Format("2006-01-02")
codeResult, err := h.GetKode(ctx, dbConn, kodeID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
Shift, err := h.GetShift(ctx, dbConn, IDKlinik)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
quotaSeat, usedQuota, err := h.CheckAndLockQuota(ctx, dbConn, kodeID, currentDate)
if err != nil {
if err == sql.ErrNoRows {
c.JSON(http.StatusNotFound, gin.H{"error": "Loket tidak ditemukan"})
return
}
logger.Error("Failed to check quota", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to check quota"})
return
}
availableQuota := quotaSeat - usedQuota
if availableQuota <= 0 {
logger.Warn("Quota loket sudah penuh", map[string]interface{}{
"id_loket": kodeID,
"quota_seat": quotaSeat,
"used_quota": usedQuota,
"available_quota": availableQuota,
})
c.JSON(http.StatusConflict, gin.H{
"error": "Quota loket sudah penuh",
"details": fmt.Sprintf("Quota tersedia: %d", availableQuota),
})
return
}
newUsedQuota, err := h.IncrementUsedQuota(ctx, dbConn, kodeID, currentDate, newUUID)
if err != nil {
logger.Error("Failed to update quota", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update quota"})
return
}
logger.Info("Quota updated successfully", map[string]interface{}{
"id_loket": req.IDLoket,
"new_used_quota": newUsedQuota,
"remaining_quota": quotaSeat - newUsedQuota,
})
barcodeNumber, err := h.GenerateVisitCode(ctx, dbConn.DB)
if err != nil {
logger.Error("Failed to generate barcode", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate barcode: " + err.Error()})
return
}
barcodeData, err := h.insertBarcode(ctx, dbConn.DB, barcodeNumber)
if err != nil {
logger.Error("Failed to insert barcode", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert barcode: " + err.Error()})
return
}
ticketNumber, err := h.generateTicketNumber(ctx, dbConn.DB, codeResult, currentDate)
if err != nil {
logger.Error("Failed to generate ticket", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate ticket: " + err.Error()})
return
}
idtiket, datetimeStart, err := h.insertTicket(ctx, dbConn.DB, barcodeData.IdBarcode, ticketNumber, codeResult, req.IdKlinik, req.IDLoket, req.IDpembayaran)
if err != nil {
logger.Error("Failed to insert ticket", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert ticket: " + err.Error()})
return
}
errVisit := h.insertcalling(ctx, dbConn.DB, req.Idklinikstatus, req.Statuspasien, idtiket)
if errVisit != nil {
logger.Error("Failed to insert calling ", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling: " + err.Error()})
return
}
errVisitservice := h.insertvisit(ctx, dbConn.DB, req.Statuspasien, idtiket)
if errVisitservice != nil {
logger.Error("Failed to insert calling ", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling: " + err.Error()})
return
}
errVisit2 := h.insertcalling(ctx, dbConn.DB, req.Idklinikstatus, req.Statuspasien2, idtiket)
if errVisit2 != nil {
logger.Error("Failed to insert calling ", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling: " + err.Error()})
return
}
errVisitservice2 := h.insertvisit(ctx, dbConn.DB, req.Statuspasien2, idtiket)
if errVisitservice2 != nil {
logger.Error("Failed to insert calling ", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling: " + err.Error()})
return
}
logger.Info("Barcode and ticket generated successfully", map[string]interface{}{
"barcode": barcodeNumber,
"ticket": req.IDLoket + ticketNumber,
"visit_id": barcodeData.IdBarcode,
})
resbarcodeData := &transaction.BarcodeData{
IdBarcode: barcodeData.IdBarcode,
Ticket: codeResult + ticketNumber,
Barcode: barcodeNumber,
NamaKlinik: req.NamaKlinik,
CreatedAt: barcodeData.CreatedAt,
Active: true,
Shift: "shift" + Shift,
Dokter: req.NamaDokter,
DatetimeStart: datetimeStart,
RemainingQuota: strconv.Itoa(quotaSeat - newUsedQuota),
}
c.JSON(http.StatusCreated, transaction.BarcodeResponse{
Message: "Barcode berhasil di-generate",
Data: resbarcodeData,
})
}
func (h *TiketHandler) GetKode(ctx context.Context, dbConn *sqlx.DB, kodeID int) (string, error) {
var code string
query := `SELECT mrc.code FROM master.ms_registration_counter mrc WHERE mrc.id = $1`
err := dbConn.QueryRowContext(ctx, query, kodeID).Scan(&code)
if err != nil {
if err == sql.ErrNoRows {
return "", fmt.Errorf("kode dengan id %d tidak ditemukan", kodeID)
}
return "", fmt.Errorf("failed to get kode: %w", err)
}
return code, nil
}
func (h *TiketHandler) GetShift(ctx context.Context, dbConn *sqlx.DB, IDKlinik int) (string, error) {
var shift string
query := ` select mhss.shift_number from master.ms_healthcare_service mhs
inner join master.ms_healthcare_service_shift mhss on mhss.fk_ms_healthcare_service_id = mhs.id
where mhs.id = $1`
err := dbConn.QueryRowContext(ctx, query, IDKlinik).Scan(&shift)
if err != nil {
if err == sql.ErrNoRows {
return "", fmt.Errorf("kode dengan id %d tidak ditemukan", IDKlinik)
}
return "", fmt.Errorf("failed to get kode: %w", err)
}
return shift, nil
}
func (h *TiketHandler) GenerateVisitCode(ctx context.Context, dbConn *sql.DB) (string, error) {
today := time.Now().Format("060102") // Format: YYMMDD
query := `
SELECT tpv.visit_code::TEXT
FROM transaction.tr_patient_visit tpv
WHERE tpv.visit_code::TEXT LIKE $1 || '%'
AND tpv.registration_datetime >= CURRENT_DATE
AND tpv.registration_datetime < CURRENT_DATE + INTERVAL '1 day'
ORDER BY tpv.visit_code DESC
LIMIT 1
`
var lastVisitCode string
err := dbConn.QueryRowContext(ctx, query, today).Scan(&lastVisitCode)
var newNumber int
if err == sql.ErrNoRows {
newNumber = 1
} else if err != nil {
return "", fmt.Errorf("failed to get last visit code: %w", err)
} else {
if len(lastVisitCode) >= 11 {
lastNumberStr := lastVisitCode[6:] // Ambil 5 digit terakhir
lastNumber, _ := strconv.Atoi(lastNumberStr)
newNumber = lastNumber + 1
} else {
newNumber = 1
}
}
// Format: YYMMDD + 5 digit dengan leading zero
newVisitCode := fmt.Sprintf("%s%05d", today, newNumber)
return newVisitCode, nil
}
func (h *TiketHandler) insertBarcode(ctx context.Context, dbConn *sql.DB, barcode string) (*transaction.BarcodeData, error) {
barcodeInt, err := strconv.ParseInt(barcode, 10, 64)
if err != nil {
return nil, fmt.Errorf("failed to convert barcode to integer: %w", err)
}
query := `
INSERT INTO transaction.tr_patient_visit
(visit_code, registration_datetime,active)
VALUES
($1, NOW(),true)
RETURNING id,visit_code, registration_datetime, active
`
var barcodeData transaction.BarcodeData
var visitCodeInt int64
err = dbConn.QueryRowContext(ctx, query, barcodeInt).Scan(
&barcodeData.IdBarcode,
&visitCodeInt,
&barcodeData.CreatedAt,
&barcodeData.Active,
)
if err != nil {
return nil, fmt.Errorf("failed to insert barcode: %w", err)
}
barcodeData.Barcode = strconv.FormatInt(visitCodeInt, 10)
return &barcodeData, nil
}
// func (h *TiketHandler) generateTicketNumber(ctx context.Context, dbConn *sql.DB, healthcareServiceCode string, currentDate string) (string, error) {
// query := `
// SELECT ticket
// FROM transaction.tr_patient_visit_healthcare_service tpvhs
// WHERE tpvhs.healtcare_service_code = $1
// AND DATE(tpvhs.datetime_start) = $2
// ORDER BY tpvhs.datetime_start DESC, tpvhs.id DESC
// LIMIT 1
// `
//
// var lastTicket string
// err := dbConn.QueryRowContext(ctx, query, healthcareServiceCode, currentDate).Scan(&lastTicket)
//
// var nextNumber int
//
// if err == sql.ErrNoRows {
// nextNumber = 1
// logger.Info("No ticket found for today, starting from 001", map[string]interface{}{
// "code": healthcareServiceCode,
// })
// } else if err != nil {
// return "", fmt.Errorf("failed to query last ticket: %w", err)
// } else {
// lastNumber, err := strconv.Atoi(lastTicket)
// if err != nil {
// nextNumber = 1
// logger.Warn("Failed to parse ticket number, resetting to 001", map[string]interface{}{
// "last_ticket": lastTicket,
// "error": err.Error(),
// })
// } else {
// nextNumber = lastNumber + 1
// }
//
// logger.Info("Found last ticket", map[string]interface{}{
// "last_ticket": lastTicket,
// "next_number": nextNumber,
// })
// }
//
// if nextNumber > 999 {
// return "", fmt.Errorf("maximum ticket limit reached for today (999)")
// }
//
// ticketNumber := fmt.Sprintf("%03d", nextNumber)
//
// return ticketNumber, nil
// }
func (h *TiketHandler) generateTicketNumber(ctx context.Context, dbConn *sql.DB, healthcareServiceCode string, currentDate string) (string, error) {
query := `
SELECT COALESCE(MAX(CAST(ticket AS INTEGER)), 0) as max_ticket
FROM transaction.tr_patient_visit_healthcare_service tpvhs
WHERE tpvhs.healtcare_service_code = $1
AND DATE(tpvhs.datetime_start) = $2
`
var maxTicket int
err := dbConn.QueryRowContext(ctx, query, healthcareServiceCode, currentDate).Scan(&maxTicket)
if err != nil {
return "", fmt.Errorf("failed to query max ticket: %w", err)
}
nextNumber := maxTicket + 1
logger.Info("Generating next ticket number", map[string]interface{}{
"code": healthcareServiceCode,
"date": currentDate,
"max_ticket": maxTicket,
"next_number": nextNumber,
})
if nextNumber > 999 {
return "", fmt.Errorf("maximum ticket limit reached for today (999)")
}
ticketNumber := fmt.Sprintf("%03d", nextNumber)
return ticketNumber, nil
}
func (h *TiketHandler) inserttiket(ctx context.Context, dbcoon *sql.DB, idticket int64, idklinik string) error {
query := `
INSERT INTO "transaction".tr_patient_visit_healthcare_service_healthcare_service
(fk_tr_patient_visit_healthcare_service_id, fk_ms_healthcare_service_id)
VALUES
($1, $2)
`
_, err := dbcoon.ExecContext(ctx, query, idticket, idklinik)
if err != nil {
return fmt.Errorf("failed to insert ticket relation: %w", err)
}
return nil
}
func (h *TiketHandler) insertcalling(ctx context.Context, dbcoon *sql.DB, IdHealthcarestatus string, IdVisitstatus string, idtiket int64) error {
query := `
INSERT INTO "transaction".tr_patient_visit_healthcare_service_calling
(fk_ref_healthcare_status_id, fk_ref_visit_status_id,fk_ref_healthcare_type_id,fk_tr_patient_visit_healthcare_service_id,active,datetime)
VALUES
($1,$2,$3,$4,TRUE,NOW())
`
_, err := dbcoon.ExecContext(ctx, query, IdHealthcarestatus, IdVisitstatus, IdHealthcarestatus, idtiket)
if err != nil {
return fmt.Errorf("failed to insert ticket relation: %w", err)
}
return nil
}
func (h *TiketHandler) insertvisit(ctx context.Context, dbcoon *sql.DB, IdVisitstatus string, idtiket int64) error {
query := `
INSERT INTO "transaction".tr_patient_visit_healthcare_service_visit_status
(fk_ref_visit_status_id,fk_tr_patient_visit_healthcare_service_id,datetime)
VALUES
($1,$2,NOW())
`
_, err := dbcoon.ExecContext(ctx, query, IdVisitstatus, idtiket)
if err != nil {
return fmt.Errorf("failed to insert ticket relation: %w", err)
}
return nil
}
func (h *TiketHandler) insertTicket(ctx context.Context, dbcoon *sql.DB, visitID string, ticket string, healthcareServiceCode string, idKlinik string, idloket string, idpembayaran string) (int64, time.Time, error) {
query := `
INSERT INTO transaction.tr_patient_visit_healthcare_service
(ticket, healtcare_service_code, fk_tr_patient_visit_id,fk_ms_healthcare_service_id,fk_ms_registration_counter_id,fk_ref_payment_type_id,datetime_start,active)
VALUES
($1,$2,$3,$4,$5,$6,NOW(),true)
RETURNING id, datetime_start
`
var id int64
var datetimeStart time.Time
err := dbcoon.QueryRowContext(ctx, query, ticket, healthcareServiceCode, visitID, idKlinik, idloket, idpembayaran).Scan(&id, &datetimeStart)
if err != nil {
return 0, time.Time{}, fmt.Errorf("failed to insert ticket: %w", err)
}
return id, datetimeStart, nil
}
func (h *TiketHandler) Updatecekin(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
var req transaction.Checkin
if err := c.ShouldBindJSON(&req); err != nil {
h.respondError(c, "Invalid request body", err, http.StatusBadRequest)
return
}
if err := validate.Struct(&req); err != nil {
h.respondError(c, "Validation failed", err, http.StatusBadRequest)
return
}
log.Println(req)
dbConn, err := h.db.GetSQLXDB("postgres_antrean")
if err != nil {
logger.Error("Database connection failed", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database connection failed"})
return
}
ticketID, err := h.GetTicketIDByVisitCode(ctx, dbConn, req.Visitcode)
if err != nil {
if err == sql.ErrNoRows {
c.JSON(http.StatusNotFound, gin.H{
"error": "Ticket tidak ditemukan",
"visit_code": req.Visitcode,
})
return
}
logger.Error("Failed to get ticket", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve ticket"})
return
}
log.Println(ticketID)
errVisit := h.insertcalling2(ctx, dbConn.DB, req.Idklinikstatus, req.Statuspasien, ticketID)
if errVisit != nil {
logger.Error("Failed to insert calling", map[string]interface{}{"error": errVisit.Error()}) // PERBAIKAN: errVisit bukan err
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling: " + errVisit.Error()}) // PERBAIKAN
return
}
errVisitservice := h.insertvisit2(ctx, dbConn.DB, req.Statuspasien, ticketID)
if errVisitservice != nil {
logger.Error("Failed to insert visit service", map[string]interface{}{"error": errVisitservice.Error()}) // PERBAIKAN
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert visit service: " + errVisitservice.Error()}) // PERBAIKAN
return
}
errVisit2 := h.insertcalling2(ctx, dbConn.DB, req.Idklinikstatus2, req.Statuspasien2, ticketID)
if errVisit2 != nil {
logger.Error("Failed to insert calling 2", map[string]interface{}{"error": errVisit2.Error()}) // PERBAIKAN
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling 2: " + errVisit2.Error()}) // PERBAIKAN
return
}
errVisitservice2 := h.insertvisit2(ctx, dbConn.DB, req.Statuspasien2, ticketID)
if errVisitservice2 != nil {
logger.Error("Failed to insert visit service 2", map[string]interface{}{"error": errVisitservice2.Error()}) // PERBAIKAN
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert visit service 2: " + errVisitservice2.Error()}) // PERBAIKAN
return
}
err = h.UpdateCheckin(ctx, dbConn, &req)
if err != nil {
logger.Error("Failed to update check-in", map[string]interface{}{
"error": err.Error(),
"visitCode": req.Visitcode,
})
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to update check-in",
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Check-in berhasil",
"data": req.Visitcode,
})
}
func (h *TiketHandler) UpdateCheckin(ctx context.Context, dbConn *sqlx.DB, req *transaction.Checkin) error {
query := `
UPDATE "transaction".tr_patient_visit_healthcare_service tpvhs
SET check_in = true, check_in_datetime = NOW()
WHERE fk_tr_patient_visit_id = (
SELECT id
FROM "transaction".tr_patient_visit tpv
WHERE tpv.visit_code = $1
)
`
result, err := dbConn.ExecContext(ctx, query, req.Visitcode)
if err != nil {
return fmt.Errorf("failed to execute update query: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("failed to get rows affected: %w", err)
}
if rowsAffected == 0 {
return fmt.Errorf("visit code tidak ditemukan: %s", req.Visitcode)
}
logger.Info("Check-in updated successfully", map[string]interface{}{
"visitCode": req.Visitcode,
"rowsAffected": rowsAffected,
})
return nil
}
func (h *TiketHandler) GetTicketIDByVisitCode(ctx context.Context, dbConn *sqlx.DB, visitCode string) (*transaction.TicketID, error) {
query := `
SELECT tpvhs.id
FROM "transaction".tr_patient_visit tpv
INNER JOIN "transaction".tr_patient_visit_healthcare_service tpvhs
ON tpvhs.fk_tr_patient_visit_id = tpv.id
WHERE tpv.visit_code = $1
and tpvhs.active = true
`
var ticketID transaction.TicketID
err := dbConn.QueryRowContext(ctx, query, visitCode).Scan(&ticketID.ID)
if err != nil {
if err == sql.ErrNoRows {
return nil, sql.ErrNoRows
}
return nil, fmt.Errorf("failed to get ticket ID: %w", err)
}
logger.Info("Ticket ID retrieved successfully", map[string]interface{}{
"visitCode": visitCode,
"ticketID": ticketID.ID,
})
return &ticketID, nil
}
func (h *TiketHandler) insertcalling2(ctx context.Context, dbcoon *sql.DB, IdHealthcarestatus string, IdVisitstatus string, idtiket *transaction.TicketID) error {
query := `
INSERT INTO "transaction".tr_patient_visit_healthcare_service_calling
(fk_ref_healthcare_status_id, fk_ref_visit_status_id, fk_ref_healthcare_type_id, fk_tr_patient_visit_healthcare_service_id, active, datetime)
VALUES
($1, $2, $3, $4, TRUE, NOW())
`
_, err := dbcoon.ExecContext(ctx, query, IdHealthcarestatus, IdVisitstatus, IdHealthcarestatus, idtiket.ID)
if err != nil {
return fmt.Errorf("failed to insert calling: %w", err)
}
return nil
}
func (h *TiketHandler) insertvisit2(ctx context.Context, dbcoon *sql.DB, IdVisitstatus string, idtiket *transaction.TicketID) error {
query := `
INSERT INTO "transaction".tr_patient_visit_healthcare_service_visit_status
(fk_ref_visit_status_id, fk_tr_patient_visit_healthcare_service_id, datetime)
VALUES
($1, $2, NOW())
`
_, err := dbcoon.ExecContext(ctx, query, IdVisitstatus, idtiket.ID)
if err != nil {
return fmt.Errorf("failed to insert visit status: %w", err)
}
return nil
}
func (h *TiketHandler) CreateStatus(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
var req transaction.UpdateTiket
if err := c.ShouldBindJSON(&req); err != nil {
h.respondError(c, "Invalid request body", err, http.StatusBadRequest)
return
}
if err := validate.Struct(&req); err != nil {
h.respondError(c, "Validation failed", err, http.StatusBadRequest)
return
}
log.Println(req)
dbConn, err := h.db.GetSQLXDB("postgres_antrean")
if err != nil {
logger.Error("Database connection failed", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database connection failed"})
return
}
ticketID, err := h.GetTicketIDByVisitCode(ctx, dbConn, req.Visitcode)
if err != nil {
if err == sql.ErrNoRows {
c.JSON(http.StatusNotFound, gin.H{
"error": "Ticket tidak ditemukan",
"visit_code": req.Visitcode,
})
return
}
logger.Error("Failed to get ticket", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve ticket"})
return
}
errVisit := h.insertcalling2(ctx, dbConn.DB, req.Idklinikstatus, req.Statuspasien, ticketID)
if errVisit != nil {
logger.Error("Failed to insert calling", map[string]interface{}{"error": errVisit.Error()}) // PERBAIKAN: errVisit bukan err
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling: " + errVisit.Error()}) // PERBAIKAN
return
}
errVisitservice := h.insertvisit2(ctx, dbConn.DB, req.Statuspasien, ticketID)
if errVisitservice != nil {
logger.Error("Failed to insert visit service", map[string]interface{}{"error": errVisitservice.Error()}) // PERBAIKAN
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert visit service: " + errVisitservice.Error()}) // PERBAIKAN
return
}
errVisit2 := h.insertcalling2(ctx, dbConn.DB, req.Idklinikstatus2, req.Statuspasien2, ticketID)
if errVisit2 != nil {
logger.Error("Failed to insert calling 2", map[string]interface{}{"error": errVisit2.Error()}) // PERBAIKAN
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling 2: " + errVisit2.Error()}) // PERBAIKAN
return
}
errVisitservice2 := h.insertvisit2(ctx, dbConn.DB, req.Statuspasien2, ticketID)
if errVisitservice2 != nil {
logger.Error("Failed to insert visit service 2", map[string]interface{}{"error": errVisitservice2.Error()}) // PERBAIKAN
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert visit service 2: " + errVisitservice2.Error()}) // PERBAIKAN
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Update berhasil",
"data": req.Visitcode,
})
}
func (h *TiketHandler) SelesaiStatus(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
var req transaction.TiketSelesai
if err := c.ShouldBindJSON(&req); err != nil {
h.respondError(c, "Invalid request body", err, http.StatusBadRequest)
return
}
if err := validate.Struct(&req); err != nil {
h.respondError(c, "Validation failed", err, http.StatusBadRequest)
return
}
log.Println(req)
loketID, err := strconv.Atoi(req.IDLoket)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "ID Loket harus berupa angka"})
return
}
dbConn, err := h.db.GetSQLXDB("postgres_antrean")
if err != nil {
logger.Error("Database connection failed", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Database connection failed"})
return
}
ticketID, err := h.GetTicketIDByVisitCode(ctx, dbConn, req.Visitcode)
if err != nil {
if err == sql.ErrNoRows {
c.JSON(http.StatusNotFound, gin.H{
"error": "Ticket tidak ditemukan",
"visit_code": req.Visitcode,
})
return
}
logger.Error("Failed to get ticket", map[string]interface{}{"error": err.Error()})
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve ticket"})
return
}
errVisit := h.insertcalling2(ctx, dbConn.DB, req.Idklinikstatus, req.Statuspasien, ticketID)
if errVisit != nil {
logger.Error("Failed to insert calling", map[string]interface{}{"error": errVisit.Error()}) // PERBAIKAN: errVisit bukan err
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert calling: " + errVisit.Error()}) // PERBAIKAN
return
}
errVisitservice := h.insertvisit2(ctx, dbConn.DB, req.Statuspasien, ticketID)
if errVisitservice != nil {
logger.Error("Failed to insert visit service", map[string]interface{}{"error": errVisitservice.Error()}) // PERBAIKAN
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to insert visit service: " + errVisitservice.Error()}) // PERBAIKAN
return
}
currentDate := time.Now().Format("2006-01-02")
newUsedQuota, err := h.MinQuota(ctx, dbConn, loketID, currentDate)
if err != nil {
logger.Error("Failed to return quota", map[string]interface{}{
"error": err.Error(),
"loket_id": loketID,
"ticket_id": ticketID,
"visit_code": req.Visitcode,
})
} else {
logger.Info("Quota returned successfully", map[string]interface{}{
"loket_id": loketID,
"new_used_quota": newUsedQuota,
"ticket_id": ticketID,
"visit_code": req.Visitcode,
})
}
c.JSON(http.StatusOK, gin.H{
"message": "Update status selesai berhasil",
"data": req.Visitcode,
"Quota": newUsedQuota,
})
}