137 lines
4.8 KiB
Go
137 lines
4.8 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"apskel-pos-be/internal/entities"
|
|
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type OrderItemRepository interface {
|
|
Create(ctx context.Context, orderItem *entities.OrderItem) error
|
|
GetByID(ctx context.Context, id uuid.UUID) (*entities.OrderItem, error)
|
|
GetByOrderID(ctx context.Context, orderID uuid.UUID) ([]*entities.OrderItem, error)
|
|
Update(ctx context.Context, orderItem *entities.OrderItem) error
|
|
Delete(ctx context.Context, id uuid.UUID) error
|
|
RefundOrderItem(ctx context.Context, id uuid.UUID, refundQuantity int, refundAmount float64, reason string, refundedBy uuid.UUID) error
|
|
VoidOrderItem(ctx context.Context, id uuid.UUID, voidQuantity int, reason string, voidedBy uuid.UUID) error
|
|
UpdateStatus(ctx context.Context, id uuid.UUID, status entities.OrderItemStatus) error
|
|
}
|
|
|
|
type OrderItemRepositoryImpl struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewOrderItemRepositoryImpl(db *gorm.DB) *OrderItemRepositoryImpl {
|
|
return &OrderItemRepositoryImpl{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
func (r *OrderItemRepositoryImpl) Create(ctx context.Context, orderItem *entities.OrderItem) error {
|
|
return r.db.WithContext(ctx).Create(orderItem).Error
|
|
}
|
|
|
|
func (r *OrderItemRepositoryImpl) GetByID(ctx context.Context, id uuid.UUID) (*entities.OrderItem, error) {
|
|
var orderItem entities.OrderItem
|
|
err := r.db.WithContext(ctx).First(&orderItem, "id = ?", id).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &orderItem, nil
|
|
}
|
|
|
|
func (r *OrderItemRepositoryImpl) GetByOrderID(ctx context.Context, orderID uuid.UUID) ([]*entities.OrderItem, error) {
|
|
var orderItems []*entities.OrderItem
|
|
err := r.db.WithContext(ctx).
|
|
Preload("Product").
|
|
Preload("ProductVariant").
|
|
Where("order_id = ?", orderID).
|
|
Find(&orderItems).Error
|
|
return orderItems, err
|
|
}
|
|
|
|
func (r *OrderItemRepositoryImpl) Update(ctx context.Context, orderItem *entities.OrderItem) error {
|
|
return r.db.WithContext(ctx).Save(orderItem).Error
|
|
}
|
|
|
|
func (r *OrderItemRepositoryImpl) Delete(ctx context.Context, id uuid.UUID) error {
|
|
return r.db.WithContext(ctx).Delete(&entities.OrderItem{}, "id = ?", id).Error
|
|
}
|
|
|
|
func (r *OrderItemRepositoryImpl) RefundOrderItem(ctx context.Context, id uuid.UUID, refundQuantity int, refundAmount float64, reason string, refundedBy uuid.UUID) error {
|
|
now := time.Now()
|
|
|
|
// Get current order item
|
|
var orderItem entities.OrderItem
|
|
if err := r.db.WithContext(ctx).First(&orderItem, "id = ?", id).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// Calculate new refund quantities and amounts
|
|
newRefundQuantity := orderItem.RefundQuantity + refundQuantity
|
|
newRefundAmount := orderItem.RefundAmount + refundAmount
|
|
|
|
// Determine if fully or partially refunded
|
|
isFullyRefunded := newRefundQuantity >= orderItem.Quantity
|
|
isPartiallyRefunded := newRefundQuantity > 0 && newRefundQuantity < orderItem.Quantity
|
|
|
|
updates := map[string]interface{}{
|
|
"refund_quantity": newRefundQuantity,
|
|
"refund_amount": newRefundAmount,
|
|
"is_partially_refunded": isPartiallyRefunded,
|
|
"is_fully_refunded": isFullyRefunded,
|
|
"refund_reason": reason,
|
|
"refunded_at": now,
|
|
"refunded_by": refundedBy,
|
|
}
|
|
|
|
return r.db.WithContext(ctx).Model(&entities.OrderItem{}).
|
|
Where("id = ?", id).
|
|
Updates(updates).Error
|
|
}
|
|
|
|
func (r *OrderItemRepositoryImpl) UpdateStatus(ctx context.Context, id uuid.UUID, status entities.OrderItemStatus) error {
|
|
return r.db.WithContext(ctx).Model(&entities.OrderItem{}).
|
|
Where("id = ?", id).
|
|
Update("status", status).Error
|
|
}
|
|
|
|
func (r *OrderItemRepositoryImpl) VoidOrderItem(ctx context.Context, id uuid.UUID, voidQuantity int, reason string, voidedBy uuid.UUID) error {
|
|
now := time.Now()
|
|
|
|
// Get current order item
|
|
var orderItem entities.OrderItem
|
|
if err := r.db.WithContext(ctx).First(&orderItem, "id = ?", id).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// Calculate new voided quantity
|
|
newVoidedQuantity := orderItem.RefundQuantity + voidQuantity // Using refund_quantity field for voided quantity
|
|
|
|
// Determine if fully or partially voided
|
|
isFullyVoided := newVoidedQuantity >= orderItem.Quantity
|
|
isPartiallyVoided := newVoidedQuantity > 0 && newVoidedQuantity < orderItem.Quantity
|
|
|
|
// Calculate voided amount
|
|
voidedAmount := float64(voidQuantity) * orderItem.UnitPrice
|
|
|
|
updates := map[string]interface{}{
|
|
"refund_quantity": newVoidedQuantity, // Reusing refund_quantity field for voided quantity
|
|
"refund_amount": orderItem.RefundAmount + voidedAmount,
|
|
"is_partially_refunded": isPartiallyVoided, // Reusing refunded flags for voided status
|
|
"is_fully_refunded": isFullyVoided,
|
|
"refund_reason": reason,
|
|
"refunded_at": now,
|
|
"refunded_by": voidedBy,
|
|
"status": entities.OrderItemStatusCancelled, // Mark as cancelled when voided
|
|
}
|
|
|
|
return r.db.WithContext(ctx).Model(&entities.OrderItem{}).
|
|
Where("id = ?", id).
|
|
Updates(updates).Error
|
|
}
|