fix: restore S3 error stubs, add CI timeouts, gofmt handlers.go, fix comment
CI / Env docs check (push) Successful in 14s
CI / Docker compose check (push) Successful in 20s
CI / Nginx config check (push) Successful in 20s
CI / Frontend major deps (push) Failing after 30s
CI / Frontend deps check (push) Successful in 31s
CI / Secrets scan (push) Successful in 38s
CI / Go build (push) Successful in 38s
CI / Frontend build (push) Successful in 42s
CI / Knip (push) Successful in 40s
CI / Frontend a11y check (push) Successful in 2m2s
CI / Go vet (prod) (push) Successful in 1m56s
CI / Go vet (dev) (push) Successful in 2m7s
CI / Staticcheck (prod) (push) Successful in 2m51s
CI / Staticcheck (dev) (push) Successful in 3m3s
CI / go mod tidy (push) Successful in 1m17s
CI / Frontend QC (audit) (push) Successful in 1m34s
CI / golangci-lint (push) Successful in 3m44s
CI / Go vulnerabilities (push) Successful in 2m10s
CI / Frontend QC (typecheck) (push) Successful in 1m29s
CI / Security scan (prod) (push) Successful in 4m3s
CI / Security scan (dev) (push) Successful in 4m37s
CI / Frontend QC (lint) (push) Successful in 1m40s
CI / Svelte strict check (push) Successful in 1m22s
CI / Tests (prod) (push) Successful in 3m12s
CI / Tests (dev) (push) Successful in 3m32s
CI / Race (prod) (push) Successful in 7m12s
CI / Race (dev) (push) Successful in 7m22s
CI / Env docs check (push) Successful in 14s
CI / Docker compose check (push) Successful in 20s
CI / Nginx config check (push) Successful in 20s
CI / Frontend major deps (push) Failing after 30s
CI / Frontend deps check (push) Successful in 31s
CI / Secrets scan (push) Successful in 38s
CI / Go build (push) Successful in 38s
CI / Frontend build (push) Successful in 42s
CI / Knip (push) Successful in 40s
CI / Frontend a11y check (push) Successful in 2m2s
CI / Go vet (prod) (push) Successful in 1m56s
CI / Go vet (dev) (push) Successful in 2m7s
CI / Staticcheck (prod) (push) Successful in 2m51s
CI / Staticcheck (dev) (push) Successful in 3m3s
CI / go mod tidy (push) Successful in 1m17s
CI / Frontend QC (audit) (push) Successful in 1m34s
CI / golangci-lint (push) Successful in 3m44s
CI / Go vulnerabilities (push) Successful in 2m10s
CI / Frontend QC (typecheck) (push) Successful in 1m29s
CI / Security scan (prod) (push) Successful in 4m3s
CI / Security scan (dev) (push) Successful in 4m37s
CI / Frontend QC (lint) (push) Successful in 1m40s
CI / Svelte strict check (push) Successful in 1m22s
CI / Tests (prod) (push) Successful in 3m12s
CI / Tests (dev) (push) Successful in 3m32s
CI / Race (prod) (push) Successful in 7m12s
CI / Race (dev) (push) Successful in 7m22s
- s3.go: restore error returns on prod Upload/Download/Delete stubs (silent nil was dangerous — callers would think writes succeeded) - CI: add -timeout 300s to tests, -timeout 480s to race, GO_TESTING to race env - handlers.go: gofmt indentation fix for GetCheckoutStatus struct literal - validators.go: fix comment to include A-F (matched the regex)
This commit is contained in:
@@ -449,7 +449,7 @@ jobs:
|
||||
|
||||
- name: Run tests
|
||||
working-directory: backend
|
||||
run: go test -tags "${{ matrix.gotags }}" -count=1 ${{ matrix.verbose }} ${{ matrix.coverflags }} ./...
|
||||
run: go test -tags "${{ matrix.gotags }}" -count=1 -timeout 300s ${{ matrix.verbose }} ${{ matrix.coverflags }} ./...
|
||||
env:
|
||||
GO_TESTING: "1"
|
||||
POSTGRES_HOST: postgres
|
||||
@@ -531,8 +531,9 @@ jobs:
|
||||
|
||||
- name: Run race detector
|
||||
working-directory: backend
|
||||
run: go test -tags "${{ matrix.gotags }}" -race -count=1 ./...
|
||||
run: go test -tags "${{ matrix.gotags }}" -race -count=1 -timeout 480s ./...
|
||||
env:
|
||||
GO_TESTING: "1"
|
||||
POSTGRES_HOST: postgres
|
||||
TEST_DB_HOST: postgres
|
||||
CGO_ENABLED: "1"
|
||||
|
||||
@@ -141,7 +141,7 @@ func calculateDiscountPreview(ctx context.Context, bookingID string, userID stri
|
||||
}
|
||||
|
||||
var bookingTotal float64
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = db.Conn.QueryRow(ctx, `
|
||||
SELECT total_amount FROM bookings WHERE id = $1
|
||||
`, bookingID).Scan(&bookingTotal)
|
||||
@@ -164,7 +164,7 @@ func calculateDiscountPreview(ctx context.Context, bookingID string, userID stri
|
||||
ORDER BY discount_percent DESC LIMIT 1
|
||||
`).Scan(&campaignID, &campaignPercent, &campaignName); err == nil && campaignID != "" {
|
||||
var exists int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = db.Conn.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND source_id = $2`, bookingID, campaignID).Scan(&exists)
|
||||
if exists == 0 {
|
||||
amount := roundTo2(bookingTotal * campaignPercent / 100)
|
||||
@@ -179,13 +179,13 @@ func calculateDiscountPreview(ctx context.Context, bookingID string, userID stri
|
||||
}
|
||||
|
||||
var userBookingCount int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = db.Conn.QueryRow(ctx, `SELECT COUNT(*) FROM bookings WHERE user_id = $1 AND status = 'completed'`, userID).Scan(&userBookingCount)
|
||||
|
||||
var milestoneCampaignID string
|
||||
var milestonePercent float64
|
||||
var milestoneName string
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = db.Conn.QueryRow(ctx, `
|
||||
SELECT id, discount_percent, name FROM discount_campaigns
|
||||
WHERE status = 'active' AND campaign_type = 'milestone' AND milestone_type = 'per_user_booking_count'
|
||||
@@ -195,7 +195,7 @@ func calculateDiscountPreview(ctx context.Context, bookingID string, userID stri
|
||||
|
||||
if milestoneCampaignID != "" {
|
||||
var exists int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = db.Conn.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND source_id = $2`, bookingID, milestoneCampaignID).Scan(&exists)
|
||||
if exists == 0 {
|
||||
amount := roundTo2(bookingTotal * milestonePercent / 100)
|
||||
@@ -210,7 +210,7 @@ func calculateDiscountPreview(ctx context.Context, bookingID string, userID stri
|
||||
}
|
||||
|
||||
var firstVisitDate time.Time
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = db.Conn.QueryRow(ctx, `SELECT MIN(start_time) FROM bookings WHERE user_id = $1 AND status = 'completed'`, userID).Scan(&firstVisitDate)
|
||||
if !firstVisitDate.IsZero() {
|
||||
type annCamp struct {
|
||||
@@ -237,7 +237,7 @@ func calculateDiscountPreview(ctx context.Context, bookingID string, userID stri
|
||||
|
||||
for _, c := range campaigns {
|
||||
var exists int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = db.Conn.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND source_id = $2`, bookingID, c.id).Scan(&exists)
|
||||
if exists > 0 {
|
||||
continue
|
||||
@@ -274,7 +274,7 @@ func calculateDiscountPreview(ctx context.Context, bookingID string, userID stri
|
||||
LIMIT 1
|
||||
`, userID).Scan(&rdID, &rdPercent); err == nil && rdID != "" {
|
||||
exists := 0
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = db.Conn.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND discount_source = 'referral' AND source_id = $2`, bookingID, rdID).Scan(&exists)
|
||||
if exists == 0 {
|
||||
amount := roundTo2(bookingTotal * rdPercent / 100)
|
||||
@@ -354,7 +354,7 @@ func CreateTerminalPayment(w http.ResponseWriter, r *http.Request) {
|
||||
if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" {
|
||||
slog.Error("failed to rollback transaction", "err", err)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
// Check booking status inside the transaction.
|
||||
var status string
|
||||
@@ -626,7 +626,7 @@ func GetCheckoutStatus(w http.ResponseWriter, r *http.Request) {
|
||||
if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" {
|
||||
slog.Error("failed to rollback transaction", "err", err)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
// Check for existing payment inside the transaction.
|
||||
var existingID string
|
||||
@@ -825,7 +825,7 @@ func CreateBookingPayment(w http.ResponseWriter, r *http.Request) {
|
||||
if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" {
|
||||
slog.Error("failed to rollback transaction", "err", err)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
var status string
|
||||
if err := tx.QueryRow(r.Context(), `SELECT status FROM bookings WHERE id = $1`, bookingID).Scan(&status); err != nil {
|
||||
@@ -1021,7 +1021,7 @@ func CreateBookingPayment(w http.ResponseWriter, r *http.Request) {
|
||||
// Promote deposit to confirmed if total paid meets the 20% threshold.
|
||||
// Check is inside the transaction so it sees the just-inserted payments.
|
||||
var depositMet bool
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = tx.QueryRow(r.Context(), `
|
||||
WITH booking_total AS (
|
||||
SELECT total_amount * 100 AS total_cents FROM bookings WHERE id = $1
|
||||
@@ -1077,7 +1077,7 @@ func CreateBookingPayment(w http.ResponseWriter, r *http.Request) {
|
||||
// would create a credit balance or require a refund.
|
||||
func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingID string, userID string) {
|
||||
var existingPayment int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `
|
||||
SELECT COUNT(*) FROM payments
|
||||
WHERE booking_id = $1 AND status = 'completed' AND payment_method NOT IN ('discount', 'on_the_house')
|
||||
@@ -1110,7 +1110,7 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
ORDER BY discount_percent DESC LIMIT 1
|
||||
`).Scan(&campaignID, &campaignPercent); err == nil && campaignID != "" {
|
||||
var exists int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND source_id = $2`, bookingID, campaignID).Scan(&exists)
|
||||
if exists == 0 {
|
||||
discountAmount := roundTo2(bookingTotal * campaignPercent / 100)
|
||||
@@ -1120,12 +1120,12 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
`, bookingID, userID, campaignID, campaignPercent, bookingTotal, discountAmount); err != nil {
|
||||
log.Printf("Failed to insert time-based campaign discount: %v", err)
|
||||
} else {
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
INSERT INTO payments (booking_id, payment_type, payment_method, amount, status, created_by)
|
||||
VALUES ($1, 'partial', 'discount', $2, 'completed', $3)
|
||||
`, bookingID, discountAmount, userID)
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
UPDATE discount_campaigns SET times_redeemed = times_redeemed + 1 WHERE id = $1
|
||||
`, campaignID)
|
||||
@@ -1134,12 +1134,12 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
}
|
||||
|
||||
var userBookingCount int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `SELECT COUNT(*) FROM bookings WHERE user_id = $1 AND status = 'completed'`, userID).Scan(&userBookingCount)
|
||||
|
||||
var milestoneCampaignID string
|
||||
var milestonePercent float64
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `
|
||||
SELECT id, discount_percent FROM discount_campaigns
|
||||
WHERE status = 'active' AND campaign_type = 'milestone' AND milestone_type = 'per_user_booking_count'
|
||||
@@ -1149,7 +1149,7 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
|
||||
if milestoneCampaignID != "" {
|
||||
var exists int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND source_id = $2`, bookingID, milestoneCampaignID).Scan(&exists)
|
||||
if exists == 0 {
|
||||
discountAmount := roundTo2(bookingTotal * milestonePercent / 100)
|
||||
@@ -1159,12 +1159,12 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
`, bookingID, userID, milestoneCampaignID, milestonePercent, bookingTotal, discountAmount); err != nil {
|
||||
log.Printf("Failed to insert per-user milestone discount: %v", err)
|
||||
} else {
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
INSERT INTO payments (booking_id, payment_type, payment_method, amount, status, created_by)
|
||||
VALUES ($1, 'partial', 'discount', $2, 'completed', $3)
|
||||
`, bookingID, discountAmount, userID)
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
UPDATE discount_campaigns SET times_redeemed = times_redeemed + 1 WHERE id = $1
|
||||
`, milestoneCampaignID)
|
||||
@@ -1173,7 +1173,7 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
}
|
||||
|
||||
var firstVisitDate time.Time
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `SELECT MIN(start_time) FROM bookings WHERE user_id = $1 AND status = 'completed'`, userID).Scan(&firstVisitDate)
|
||||
if !firstVisitDate.IsZero() {
|
||||
annRows, err := q.Query(ctx, `
|
||||
@@ -1199,7 +1199,7 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
|
||||
for _, c := range campaigns {
|
||||
var exists int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND source_id = $2`, bookingID, c.id).Scan(&exists)
|
||||
if exists > 0 {
|
||||
continue
|
||||
@@ -1223,12 +1223,12 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
`, bookingID, userID, c.id, c.pct, bookingTotal, discountAmount); err != nil {
|
||||
log.Printf("Failed to insert anniversary discount: %v", err)
|
||||
} else {
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
INSERT INTO payments (booking_id, payment_type, payment_method, amount, status, created_by)
|
||||
VALUES ($1, 'partial', 'discount', $2, 'completed', $3)
|
||||
`, bookingID, discountAmount, userID)
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
UPDATE discount_campaigns SET times_redeemed = times_redeemed + 1 WHERE id = $1
|
||||
`, c.id)
|
||||
@@ -1246,12 +1246,12 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
SELECT payment_method FROM payments WHERE booking_id = $1 AND payment_method NOT IN ('discount', 'on_the_house') ORDER BY created_at ASC LIMIT 1
|
||||
`, bookingID).Scan(&firstPaymentMethod); err == nil && firstPaymentMethod == "in_person_card" {
|
||||
var globalCount int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `SELECT COUNT(*) FROM bookings WHERE status = 'completed'`).Scan(&globalCount)
|
||||
|
||||
var globalCampaignID string
|
||||
var globalPercent float64
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `
|
||||
SELECT id, discount_percent FROM discount_campaigns
|
||||
WHERE status = 'active' AND campaign_type = 'milestone' AND milestone_type = 'global_booking_count'
|
||||
@@ -1263,7 +1263,7 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
|
||||
if globalCampaignID != "" {
|
||||
var exists int
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND source_id = $2`, bookingID, globalCampaignID).Scan(&exists)
|
||||
if exists == 0 {
|
||||
discountAmount := roundTo2(bookingTotal * globalPercent / 100)
|
||||
@@ -1273,12 +1273,12 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
`, bookingID, userID, globalCampaignID, globalPercent, bookingTotal, discountAmount); err != nil {
|
||||
log.Printf("Failed to insert global milestone discount: %v", err)
|
||||
} else {
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
INSERT INTO payments (booking_id, payment_type, payment_method, amount, status, created_by)
|
||||
VALUES ($1, 'partial', 'discount', $2, 'completed', $3)
|
||||
`, bookingID, discountAmount, userID)
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
UPDATE discount_campaigns SET times_redeemed = times_redeemed + 1 WHERE id = $1
|
||||
`, globalCampaignID)
|
||||
@@ -1297,7 +1297,7 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
LIMIT 1
|
||||
`, userID).Scan(&rdID, &rdPercent); err == nil && rdID != "" {
|
||||
exists := 0
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
//nolint:errcheck // zero value is acceptable fallback on scan failure
|
||||
_ = q.QueryRow(ctx, `SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND discount_source = 'referral' AND source_id = $2`, bookingID, rdID).Scan(&exists)
|
||||
if exists == 0 {
|
||||
discountAmount := roundTo2(bookingTotal * rdPercent / 100)
|
||||
@@ -1305,12 +1305,12 @@ func applyEligibleCampaignsAtPayment(ctx context.Context, q db.Querier, bookingI
|
||||
INSERT INTO booking_discounts (booking_id, user_id, discount_source, source_id, campaign_type, milestone_type, discount_percent, original_total, discount_amount)
|
||||
VALUES ($1, $2, 'referral', $3, NULL, NULL, $4, $5, $6)
|
||||
`, bookingID, userID, rdID, rdPercent, bookingTotal, discountAmount); err == nil {
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
INSERT INTO payments (booking_id, payment_type, payment_method, amount, status, created_by)
|
||||
VALUES ($1, 'partial', 'discount', $2, 'completed', $3)
|
||||
`, bookingID, discountAmount, userID)
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
//nolint:errcheck // exec errors are non-critical; best-effort inserts/updates
|
||||
_, _ = q.Exec(ctx, `
|
||||
UPDATE referral_discounts SET used = TRUE, used_at = NOW() WHERE id = $1
|
||||
`, rdID)
|
||||
@@ -1422,6 +1422,7 @@ func buildSplitRecords(primary PaymentRecord, reqPaymentType string, info *Booki
|
||||
// split payment, following the same rules as the frontend's handlePayFull:
|
||||
// 'balance' when some payment already exists, 'full' when covering everything,
|
||||
// 'partial' when leaving a remainder.
|
||||
//
|
||||
//lint:ignore U1000 reserved for future use
|
||||
func nonDepositPaymentType(reqType string, totalPaidAfterThis float64, thisPortion float64, bookingTotal float64) string {
|
||||
if totalPaidAfterThis >= bookingTotal {
|
||||
@@ -1622,7 +1623,7 @@ func RefundPayment(w http.ResponseWriter, r *http.Request) {
|
||||
if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" {
|
||||
slog.Error("failed to rollback transaction", "err", err)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
refundReq := square.RefundPaymentReq{
|
||||
PaymentID: *payment.SquarePaymentID,
|
||||
@@ -1968,7 +1969,7 @@ func AcquirePaymentLock(w http.ResponseWriter, r *http.Request) {
|
||||
if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" {
|
||||
slog.Error("failed to rollback transaction", "err", err)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
if _, err := tx.Exec(r.Context(), `
|
||||
DELETE FROM time_blockers
|
||||
@@ -2019,7 +2020,7 @@ func ReleasePaymentLock(w http.ResponseWriter, r *http.Request) {
|
||||
if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" {
|
||||
slog.Error("failed to rollback transaction", "err", err)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
if _, err := tx.Exec(r.Context(), `
|
||||
DELETE FROM time_blockers
|
||||
|
||||
@@ -50,19 +50,15 @@ func Connect() error {
|
||||
}
|
||||
|
||||
func (s *S3Client) Upload(ctx context.Context, bucket, key string, body io.Reader, contentType string) error {
|
||||
// TODO: Wire in AWS SDK v2 for production S3 uploads.
|
||||
// Currently only available under //go:build dev via RUSTFS.
|
||||
return nil
|
||||
return fmt.Errorf("not implemented: production S3 upload requires AWS SDK v2 (use RUSTFS in dev)")
|
||||
}
|
||||
|
||||
func (s *S3Client) Download(ctx context.Context, bucket, key string, w io.Writer) error {
|
||||
// TODO: Wire in AWS SDK v2 for production S3 downloads.
|
||||
return nil
|
||||
return fmt.Errorf("not implemented: production S3 download requires AWS SDK v2 (use RUSTFS in dev)")
|
||||
}
|
||||
|
||||
func (s *S3Client) Delete(ctx context.Context, bucket, key string) error {
|
||||
// TODO: Wire in AWS SDK v2 for production S3 deletes.
|
||||
return nil
|
||||
return fmt.Errorf("not implemented: production S3 delete requires AWS SDK v2 (use RUSTFS in dev)")
|
||||
}
|
||||
|
||||
func (s *S3Client) GetURL(ctx context.Context, bucket, key string) (string, error) {
|
||||
|
||||
@@ -27,7 +27,7 @@ func init() {
|
||||
var validIDRegex = regexp.MustCompile(`^[0-9a-fA-F]{12}$`)
|
||||
|
||||
// IsValidID checks if an ID is valid based on the database constraint (CHAR(12) hex string)
|
||||
// Valid IDs are exactly 12 hexadecimal characters (0-9, a-f)
|
||||
// Valid IDs are exactly 12 hexadecimal characters (0-9, a-f, A-F)
|
||||
func IsValidID(id string) bool {
|
||||
if id == "" {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user