init
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"apskel-pos-be/internal/entities"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type OrderRepository interface {
|
||||
Create(ctx context.Context, order *entities.Order) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*entities.Order, error)
|
||||
GetWithRelations(ctx context.Context, id uuid.UUID) (*entities.Order, error)
|
||||
Update(ctx context.Context, order *entities.Order) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, filters map[string]interface{}, limit, offset int) ([]*entities.Order, int64, error)
|
||||
GetByOrderNumber(ctx context.Context, orderNumber string) (*entities.Order, error)
|
||||
ExistsByOrderNumber(ctx context.Context, orderNumber string) (bool, error)
|
||||
VoidOrder(ctx context.Context, id uuid.UUID, reason string, voidedBy uuid.UUID) error
|
||||
VoidOrderWithStatus(ctx context.Context, id uuid.UUID, status entities.OrderStatus, reason string, voidedBy uuid.UUID) error
|
||||
RefundOrder(ctx context.Context, id uuid.UUID, reason string, refundedBy uuid.UUID) error
|
||||
UpdatePaymentStatus(ctx context.Context, id uuid.UUID, status entities.PaymentStatus) error
|
||||
UpdateStatus(ctx context.Context, id uuid.UUID, status entities.OrderStatus) error
|
||||
GetNextOrderNumber(ctx context.Context, organizationID, outletID uuid.UUID) (string, error)
|
||||
}
|
||||
|
||||
type OrderRepositoryImpl struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewOrderRepositoryImpl(db *gorm.DB) *OrderRepositoryImpl {
|
||||
return &OrderRepositoryImpl{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) Create(ctx context.Context, order *entities.Order) error {
|
||||
return r.db.WithContext(ctx).Create(order).Error
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) GetByID(ctx context.Context, id uuid.UUID) (*entities.Order, error) {
|
||||
var order entities.Order
|
||||
err := r.db.WithContext(ctx).First(&order, "id = ?", id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &order, nil
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) GetWithRelations(ctx context.Context, id uuid.UUID) (*entities.Order, error) {
|
||||
var order entities.Order
|
||||
err := r.db.WithContext(ctx).
|
||||
Preload("Organization").
|
||||
Preload("Outlet").
|
||||
Preload("User").
|
||||
Preload("OrderItems").
|
||||
Preload("OrderItems.Product").
|
||||
Preload("OrderItems.ProductVariant").
|
||||
Preload("Payments").
|
||||
Preload("Payments.PaymentMethod").
|
||||
Preload("Payments.PaymentOrderItems").
|
||||
First(&order, "id = ?", id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &order, nil
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) Update(ctx context.Context, order *entities.Order) error {
|
||||
return r.db.WithContext(ctx).Save(order).Error
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) Delete(ctx context.Context, id uuid.UUID) error {
|
||||
return r.db.WithContext(ctx).Delete(&entities.Order{}, "id = ?", id).Error
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) List(ctx context.Context, filters map[string]interface{}, limit, offset int) ([]*entities.Order, int64, error) {
|
||||
var orders []*entities.Order
|
||||
var total int64
|
||||
|
||||
query := r.db.WithContext(ctx).Model(&entities.Order{}).
|
||||
Preload("Organization").
|
||||
Preload("Outlet").
|
||||
Preload("User").
|
||||
Preload("OrderItems").
|
||||
Preload("OrderItems.Product").
|
||||
Preload("OrderItems.ProductVariant").
|
||||
Preload("Payments").
|
||||
Preload("Payments.PaymentMethod")
|
||||
|
||||
for key, value := range filters {
|
||||
switch key {
|
||||
case "search":
|
||||
searchValue := "%" + value.(string) + "%"
|
||||
query = query.Where("order_number ILIKE ?", searchValue)
|
||||
case "date_from":
|
||||
query = query.Where("created_at >= ?", value)
|
||||
case "date_to":
|
||||
query = query.Where("created_at <= ?", value)
|
||||
default:
|
||||
query = query.Where(key+" = ?", value)
|
||||
}
|
||||
}
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
err := query.Limit(limit).Offset(offset).Order("created_at DESC").Find(&orders).Error
|
||||
return orders, total, err
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) GetByOrderNumber(ctx context.Context, orderNumber string) (*entities.Order, error) {
|
||||
var order entities.Order
|
||||
err := r.db.WithContext(ctx).First(&order, "order_number = ?", orderNumber).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &order, nil
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) ExistsByOrderNumber(ctx context.Context, orderNumber string) (bool, error) {
|
||||
var count int64
|
||||
err := r.db.WithContext(ctx).Model(&entities.Order{}).Where("order_number = ?", orderNumber).Count(&count).Error
|
||||
return count > 0, err
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) VoidOrder(ctx context.Context, id uuid.UUID, reason string, voidedBy uuid.UUID) error {
|
||||
now := time.Now()
|
||||
return r.db.WithContext(ctx).Model(&entities.Order{}).
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"is_void": true,
|
||||
"void_reason": reason,
|
||||
"voided_at": now,
|
||||
"voided_by": voidedBy,
|
||||
}).Error
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) VoidOrderWithStatus(ctx context.Context, id uuid.UUID, status entities.OrderStatus, reason string, voidedBy uuid.UUID) error {
|
||||
now := time.Now()
|
||||
return r.db.WithContext(ctx).Model(&entities.Order{}).
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"status": status,
|
||||
"is_void": true,
|
||||
"void_reason": reason,
|
||||
"voided_at": now,
|
||||
"voided_by": voidedBy,
|
||||
}).Error
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) RefundOrder(ctx context.Context, id uuid.UUID, reason string, refundedBy uuid.UUID) error {
|
||||
now := time.Now()
|
||||
return r.db.WithContext(ctx).Model(&entities.Order{}).
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"is_refund": true,
|
||||
"refund_reason": reason,
|
||||
"refunded_at": now,
|
||||
"refunded_by": refundedBy,
|
||||
}).Error
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) UpdatePaymentStatus(ctx context.Context, id uuid.UUID, status entities.PaymentStatus) error {
|
||||
return r.db.WithContext(ctx).Model(&entities.Order{}).
|
||||
Where("id = ?", id).
|
||||
Update("payment_status", status).Error
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) UpdateStatus(ctx context.Context, id uuid.UUID, status entities.OrderStatus) error {
|
||||
return r.db.WithContext(ctx).Model(&entities.Order{}).
|
||||
Where("id = ?", id).
|
||||
Update("status", status).Error
|
||||
}
|
||||
|
||||
func (r *OrderRepositoryImpl) GetNextOrderNumber(ctx context.Context, organizationID, outletID uuid.UUID) (string, error) {
|
||||
now := time.Now()
|
||||
year := now.Year()
|
||||
month := int(now.Month())
|
||||
|
||||
// Use a transaction to ensure atomic sequence increment
|
||||
tx := r.db.WithContext(ctx).Begin()
|
||||
if tx.Error != nil {
|
||||
return "", tx.Error
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
// Get or create sequence record
|
||||
var sequence entities.OrderSequence
|
||||
err := tx.Where("organization_id = ? AND outlet_id = ? AND year = ? AND month = ?",
|
||||
organizationID, outletID, year, month).
|
||||
First(&sequence).Error
|
||||
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// Create new sequence record
|
||||
sequence = entities.OrderSequence{
|
||||
OrganizationID: organizationID,
|
||||
OutletID: outletID,
|
||||
Year: year,
|
||||
Month: month,
|
||||
SequenceNumber: 0,
|
||||
}
|
||||
if err := tx.Create(&sequence).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
// Increment sequence number
|
||||
sequence.SequenceNumber++
|
||||
if err := tx.Save(&sequence).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Commit transaction
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
orderNumber := fmt.Sprintf("ORD/%04d%02d/%06d", year, month, sequence.SequenceNumber)
|
||||
return orderNumber, nil
|
||||
}
|
||||
Reference in New Issue
Block a user