Reapply "feat(loyalty): EnakPoint & EnakCoin" (#32)
This reverts commit 4e24f9bbb0.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// CustomerDevice is one install of the customer app that can receive push
|
||||
// notifications.
|
||||
type CustomerDevice struct {
|
||||
CustomerID uuid.UUID
|
||||
DeviceID string
|
||||
Platform *string
|
||||
FCMToken string
|
||||
AppVersion *string
|
||||
}
|
||||
|
||||
// CustomerDeviceRepository keeps the FCM tokens of the customer app.
|
||||
type CustomerDeviceRepository interface {
|
||||
// Register saves the device's current token. A token is only ever one customer's:
|
||||
// registering it takes it away from whoever had it before on that phone, so they
|
||||
// stop getting this customer's notifications.
|
||||
Register(ctx context.Context, device CustomerDevice, now time.Time) error
|
||||
// Unregister forgets a device, for instance on logout. An unknown device is not an error.
|
||||
Unregister(ctx context.Context, customerID uuid.UUID, deviceID string) error
|
||||
ListTokens(ctx context.Context, customerID uuid.UUID) ([]string, error)
|
||||
}
|
||||
|
||||
type customerDeviceRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewCustomerDeviceRepository(db *gorm.DB) CustomerDeviceRepository {
|
||||
return &customerDeviceRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *customerDeviceRepository) Register(ctx context.Context, d CustomerDevice, now time.Time) error {
|
||||
return DBFromContext(ctx, r.db).WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
err := tx.Exec(`DELETE FROM customer_devices WHERE fcm_token = ? AND NOT (customer_id = ? AND device_id = ?)`,
|
||||
d.FCMToken, d.CustomerID, d.DeviceID).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to release FCM token: %w", err)
|
||||
}
|
||||
err = tx.Exec(`INSERT INTO customer_devices (customer_id, device_id, platform, fcm_token, app_version, last_active_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (customer_id, device_id) DO UPDATE SET
|
||||
platform = EXCLUDED.platform,
|
||||
fcm_token = EXCLUDED.fcm_token,
|
||||
app_version = EXCLUDED.app_version,
|
||||
last_active_at = EXCLUDED.last_active_at,
|
||||
updated_at = NOW()`,
|
||||
d.CustomerID, d.DeviceID, d.Platform, d.FCMToken, d.AppVersion, now).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to register customer device: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *customerDeviceRepository) Unregister(ctx context.Context, customerID uuid.UUID, deviceID string) error {
|
||||
err := DBFromContext(ctx, r.db).WithContext(ctx).
|
||||
Exec(`DELETE FROM customer_devices WHERE customer_id = ? AND device_id = ?`, customerID, deviceID).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unregister customer device: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *customerDeviceRepository) ListTokens(ctx context.Context, customerID uuid.UUID) ([]string, error) {
|
||||
var tokens []string
|
||||
err := DBFromContext(ctx, r.db).WithContext(ctx).
|
||||
Table("customer_devices").
|
||||
Where("customer_id = ? AND fcm_token <> ''", customerID).
|
||||
Order("last_active_at DESC NULLS LAST").
|
||||
Pluck("fcm_token", &tokens).Error
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list customer FCM tokens: %w", err)
|
||||
}
|
||||
return tokens, nil
|
||||
}
|
||||
Reference in New Issue
Block a user