338 lines
9.3 KiB
Go
338 lines
9.3 KiB
Go
package repository
|
|
|
|
import (
|
|
"enaklo-pos-be/internal/common/logger"
|
|
"enaklo-pos-be/internal/common/mycontext"
|
|
"enaklo-pos-be/internal/entity"
|
|
"enaklo-pos-be/internal/repository/models"
|
|
"enaklo-pos-be/internal/services/v2/inprogress_order"
|
|
time2 "time"
|
|
|
|
"github.com/pkg/errors"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type InProgressOrderRepository interface {
|
|
FindByID(ctx mycontext.Context, id int64) (*entity.Order, error)
|
|
CreateOrder(ctx mycontext.Context, order *entity.Order, tx *gorm.DB) (*entity.Order, error)
|
|
CreateOrderItems(ctx mycontext.Context, orderID int64, items []entity.OrderItem, tx *gorm.DB) error
|
|
GetListByPartnerID(ctx mycontext.Context, partnerID int64, limit, offset int, status string) ([]*entity.Order, error)
|
|
FindByIDAndPartnerID(ctx mycontext.Context, id int64, partnerID int64) (*entity.Order, error)
|
|
FindByIDWithTx(ctx mycontext.Context, id int64, tx *gorm.DB) (*entity.Order, error)
|
|
}
|
|
|
|
type inprogressOrderRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewInProgressOrderRepository(db *gorm.DB) inprogress_order.OrderRepository {
|
|
return &inprogressOrderRepository{db: db}
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) FindByID(ctx mycontext.Context, id int64) (*entity.Order, error) {
|
|
var orderDB models.OrderDB
|
|
|
|
if err := r.db.Preload("OrderItems").First(&orderDB, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, errors.New("order not found")
|
|
}
|
|
return nil, errors.Wrap(err, "failed to find order")
|
|
}
|
|
|
|
order := r.toDomainOrderModel(&orderDB)
|
|
|
|
return order, nil
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) FindByIDWithTx(ctx mycontext.Context, id int64, tx *gorm.DB) (*entity.Order, error) {
|
|
var orderDB models.OrderDB
|
|
|
|
if err := tx.Preload("OrderItems").First(&orderDB, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, errors.New("order not found")
|
|
}
|
|
return nil, errors.Wrap(err, "failed to find order")
|
|
}
|
|
|
|
order := r.toDomainOrderModel(&orderDB)
|
|
|
|
return order, nil
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) CreateOrder(ctx mycontext.Context, order *entity.Order, tx *gorm.DB) (*entity.Order, error) {
|
|
orderDB := r.toOrderDBModel(order)
|
|
|
|
// Use provided transaction or create new one
|
|
var dbTx *gorm.DB
|
|
if tx != nil {
|
|
dbTx = tx
|
|
} else {
|
|
dbTx = r.db.Begin()
|
|
if dbTx.Error != nil {
|
|
return nil, errors.Wrap(dbTx.Error, "failed to begin transaction")
|
|
}
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
dbTx.Rollback()
|
|
}
|
|
}()
|
|
}
|
|
|
|
if err := dbTx.Create(&orderDB).Error; err != nil {
|
|
if tx == nil {
|
|
dbTx.Rollback()
|
|
}
|
|
return nil, errors.Wrap(err, "failed to insert order")
|
|
}
|
|
order.ID = orderDB.ID
|
|
|
|
// Only commit if we created the transaction
|
|
if tx == nil {
|
|
if err := dbTx.Commit().Error; err != nil {
|
|
return nil, errors.Wrap(err, "failed to commit transaction")
|
|
}
|
|
}
|
|
|
|
return order, nil
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) CreateOrderItems(ctx mycontext.Context, orderID int64, items []entity.OrderItem, tx *gorm.DB) error {
|
|
if len(items) == 0 {
|
|
return nil
|
|
}
|
|
|
|
itemsDB := make([]models.OrderItemDB, len(items))
|
|
for i, item := range items {
|
|
itemDB := r.toOrderItemDBModel(&item)
|
|
itemDB.OrderID = orderID
|
|
itemsDB[i] = itemDB
|
|
}
|
|
|
|
if err := tx.Create(&itemsDB).Error; err != nil {
|
|
return errors.Wrap(err, "failed to bulk insert order items")
|
|
}
|
|
|
|
for i := range items {
|
|
items[i].ID = itemsDB[i].ID
|
|
}
|
|
|
|
return nil
|
|
}
|
|
func (r *inprogressOrderRepository) GetListByPartnerID(ctx mycontext.Context, partnerID int64, limit, offset int, status string) ([]*entity.Order, error) {
|
|
var ordersDB []models.OrderDB
|
|
query := r.db.Where("partner_id = ?", partnerID)
|
|
|
|
if status != "" {
|
|
query = query.Where("status = ?", status)
|
|
}
|
|
|
|
query = query.Order("created_at DESC")
|
|
|
|
if limit > 0 {
|
|
query = query.Limit(limit)
|
|
}
|
|
|
|
if offset > 0 {
|
|
query = query.Offset(offset)
|
|
}
|
|
|
|
if err := query.Find(&ordersDB).Error; err != nil {
|
|
return nil, errors.Wrap(err, "failed to find orders by partner ID")
|
|
}
|
|
|
|
orders := make([]*entity.Order, 0, len(ordersDB))
|
|
for _, orderDB := range ordersDB {
|
|
order := r.toDomainOrderModel(&orderDB)
|
|
|
|
var orderItems []models.OrderItemDB
|
|
if err := r.db.Where("order_id = ?", orderDB.ID).Find(&orderItems).Error; err != nil {
|
|
return nil, errors.Wrap(err, "failed to find order items")
|
|
}
|
|
|
|
order.OrderItems = make([]entity.OrderItem, 0, len(orderItems))
|
|
|
|
for _, itemDB := range orderItems {
|
|
item := r.toDomainOrderItemModel(&itemDB)
|
|
|
|
orderItem := entity.OrderItem{
|
|
ID: item.ID,
|
|
ItemID: item.ItemID,
|
|
Quantity: item.Quantity,
|
|
ItemName: item.ItemName,
|
|
}
|
|
|
|
if itemDB.ItemID > 0 {
|
|
var product models.ProductDB
|
|
err := r.db.First(&product, itemDB.ItemID).Error
|
|
|
|
if err == nil {
|
|
productDomain := r.toDomainProductModel(&product)
|
|
orderItem.Product = productDomain
|
|
}
|
|
}
|
|
|
|
order.OrderItems = append(order.OrderItems, orderItem)
|
|
}
|
|
|
|
orders = append(orders, order)
|
|
}
|
|
|
|
return orders, nil
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) FindByIDAndPartnerID(ctx mycontext.Context, id int64, partnerID int64) (*entity.Order, error) {
|
|
var orderDB models.OrderDB
|
|
|
|
if err := r.db.Preload("OrderItems").Where("id = ? AND partner_id = ?", id, partnerID).First(&orderDB).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, errors.New("order not found")
|
|
}
|
|
return nil, errors.Wrap(err, "failed to find order")
|
|
}
|
|
|
|
order := r.toDomainOrderModel(&orderDB)
|
|
|
|
for _, itemDB := range orderDB.OrderItems {
|
|
item := r.toDomainOrderItemModel(&itemDB)
|
|
order.OrderItems = append(order.OrderItems, *item)
|
|
}
|
|
|
|
return order, nil
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) toOrderDBModel(order *entity.Order) models.OrderDB {
|
|
now := time2.Now()
|
|
return models.OrderDB{
|
|
ID: order.ID,
|
|
PartnerID: order.PartnerID,
|
|
CustomerID: order.CustomerID,
|
|
CustomerName: order.CustomerName,
|
|
PaymentType: order.PaymentType,
|
|
PaymentProvider: order.PaymentProvider,
|
|
CreatedBy: order.CreatedBy,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
TableNumber: order.TableNumber,
|
|
OrderType: order.OrderType,
|
|
Status: order.Status,
|
|
Amount: order.Amount,
|
|
Total: order.Total,
|
|
Tax: order.Tax,
|
|
Source: order.Source,
|
|
}
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) toDomainOrderModel(dbModel *models.OrderDB) *entity.Order {
|
|
orderItems := make([]entity.OrderItem, 0, len(dbModel.OrderItems))
|
|
for _, itemDB := range dbModel.OrderItems {
|
|
orderItems = append(orderItems, entity.OrderItem{
|
|
ItemID: itemDB.ItemID,
|
|
ItemType: itemDB.ItemType,
|
|
ItemName: itemDB.ItemName,
|
|
Price: itemDB.Price,
|
|
Quantity: itemDB.Quantity,
|
|
Status: itemDB.Status,
|
|
CreatedBy: itemDB.CreatedBy,
|
|
CreatedAt: itemDB.CreatedAt,
|
|
Notes: itemDB.Notes,
|
|
})
|
|
}
|
|
|
|
return &entity.Order{
|
|
ID: dbModel.ID,
|
|
PartnerID: dbModel.PartnerID,
|
|
CustomerID: dbModel.CustomerID,
|
|
InquiryID: dbModel.InquiryID,
|
|
Status: dbModel.Status,
|
|
Amount: dbModel.Amount,
|
|
Tax: dbModel.Tax,
|
|
Total: dbModel.Total,
|
|
PaymentType: dbModel.PaymentType,
|
|
Source: dbModel.Source,
|
|
CreatedBy: dbModel.CreatedBy,
|
|
CreatedAt: dbModel.CreatedAt,
|
|
UpdatedAt: dbModel.UpdatedAt,
|
|
OrderItems: orderItems,
|
|
CustomerName: dbModel.CustomerName,
|
|
TableNumber: dbModel.TableNumber,
|
|
OrderType: dbModel.OrderType,
|
|
PaymentProvider: dbModel.PaymentProvider,
|
|
}
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) toOrderItemDBModel(item *entity.OrderItem) models.OrderItemDB {
|
|
return models.OrderItemDB{
|
|
ID: item.ID,
|
|
OrderID: item.OrderID,
|
|
ItemID: item.ItemID,
|
|
ItemType: item.ItemType,
|
|
ItemName: item.ItemName,
|
|
Price: item.Price,
|
|
Quantity: item.Quantity,
|
|
Status: item.Status,
|
|
CreatedBy: item.CreatedBy,
|
|
CreatedAt: item.CreatedAt,
|
|
Notes: item.Notes,
|
|
}
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) toDomainOrderItemModel(dbModel *models.OrderItemDB) *entity.OrderItem {
|
|
return &entity.OrderItem{
|
|
ID: dbModel.ID,
|
|
OrderID: dbModel.OrderID,
|
|
ItemID: dbModel.ItemID,
|
|
ItemType: dbModel.ItemType,
|
|
Price: dbModel.Price,
|
|
Quantity: dbModel.Quantity,
|
|
Status: dbModel.Status,
|
|
CreatedBy: dbModel.CreatedBy,
|
|
CreatedAt: dbModel.CreatedAt,
|
|
ItemName: dbModel.ItemName,
|
|
Notes: dbModel.Notes,
|
|
Product: &entity.Product{
|
|
ID: dbModel.ItemID,
|
|
Name: dbModel.ItemName,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) toDomainProductModel(productDB *models.ProductDB) *entity.Product {
|
|
if productDB == nil {
|
|
return nil
|
|
}
|
|
|
|
return &entity.Product{
|
|
ID: productDB.ID,
|
|
Name: productDB.Name,
|
|
Description: productDB.Description,
|
|
Price: productDB.Price,
|
|
CreatedAt: productDB.CreatedAt,
|
|
UpdatedAt: productDB.UpdatedAt,
|
|
Type: productDB.Type,
|
|
Image: productDB.Image,
|
|
}
|
|
}
|
|
|
|
func (r *inprogressOrderRepository) UpdateOrderTotalsWithTx(ctx mycontext.Context, trx *gorm.DB, orderID int64, amount, tax, total float64) error {
|
|
now := time2.Now()
|
|
|
|
result := trx.Model(&models.OrderDB{}).
|
|
Where("id = ?", orderID).
|
|
Updates(map[string]interface{}{
|
|
"amount": amount,
|
|
"tax": tax,
|
|
"total": total,
|
|
"updated_at": now,
|
|
})
|
|
|
|
if result.Error != nil {
|
|
return errors.Wrap(result.Error, "failed to update order totals")
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
logger.ContextLogger(ctx).Warn("no order updated")
|
|
}
|
|
|
|
return nil
|
|
}
|