178 lines
5.3 KiB
Go
178 lines
5.3 KiB
Go
package repository
|
|
|
|
import (
|
|
"enaklo-pos-be/internal/common/mycontext"
|
|
"enaklo-pos-be/internal/entity"
|
|
"enaklo-pos-be/internal/repository/models"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type CashierSessionRepository interface {
|
|
CreateSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error)
|
|
CloseSession(ctx mycontext.Context, sessionID int64, closingAmount, expectedAmount float64) error
|
|
GetOpenSessionByCashierID(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error)
|
|
GetSessionByID(ctx mycontext.Context, sessionID int64) (*entity.CashierSession, error)
|
|
GetPaymentSummaryBySessionID(ctx mycontext.Context, sessionID int64) ([]entity.PaymentSummary, error)
|
|
GetSessionHistoryByPartnerID(ctx mycontext.Context, partnerID int64, limit, offset int) ([]*entity.CashierSession, int64, error)
|
|
}
|
|
|
|
type cashierSessionRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewCashierSessionRepository(db *gorm.DB) CashierSessionRepository {
|
|
return &cashierSessionRepository{db: db}
|
|
}
|
|
|
|
func (r *cashierSessionRepository) CreateSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error) {
|
|
dbModel := models.CashierSessionDB{
|
|
PartnerID: session.PartnerID,
|
|
CashierID: session.CashierID,
|
|
OpenedAt: time.Now(),
|
|
OpeningAmount: session.OpeningAmount,
|
|
Status: "open",
|
|
CreatedAt: time.Now(),
|
|
}
|
|
|
|
if err := r.db.Create(&dbModel).Error; err != nil {
|
|
return nil, errors.Wrap(err, "failed to create cashier session")
|
|
}
|
|
|
|
session.ID = dbModel.ID
|
|
session.Status = dbModel.Status
|
|
session.OpenedAt = dbModel.OpenedAt
|
|
|
|
return session, nil
|
|
}
|
|
|
|
func (r *cashierSessionRepository) CloseSession(ctx mycontext.Context, sessionID int64, closingAmount, expectedAmount float64) error {
|
|
result := r.db.Model(&models.CashierSessionDB{}).
|
|
Where("id = ?", sessionID).
|
|
Updates(map[string]interface{}{
|
|
"closed_at": time.Now(),
|
|
"closing_amount": closingAmount,
|
|
"expected_amount": expectedAmount,
|
|
"status": "closed",
|
|
})
|
|
|
|
if result.Error != nil {
|
|
return errors.Wrap(result.Error, "failed to close session")
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.New("no session updated")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *cashierSessionRepository) GetOpenSessionByCashierID(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error) {
|
|
var dbModel models.CashierSessionDB
|
|
if err := r.db.Where("cashier_id = ? AND status = 'open'", cashierID).
|
|
Order("opened_at DESC").First(&dbModel).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return nil, errors.Wrap(err, "failed to get open session")
|
|
}
|
|
|
|
return r.toEntity(&dbModel), nil
|
|
}
|
|
|
|
func (r *cashierSessionRepository) GetSessionByID(ctx mycontext.Context, sessionID int64) (*entity.CashierSession, error) {
|
|
var dbModel models.CashierSessionDB
|
|
if err := r.db.First(&dbModel, sessionID).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return nil, errors.Wrap(err, "failed to get session by ID")
|
|
}
|
|
|
|
return r.toEntity(&dbModel), nil
|
|
}
|
|
|
|
func (r *cashierSessionRepository) toEntity(db *models.CashierSessionDB) *entity.CashierSession {
|
|
return &entity.CashierSession{
|
|
ID: db.ID,
|
|
PartnerID: db.PartnerID,
|
|
CashierID: db.CashierID,
|
|
OpenedAt: db.OpenedAt,
|
|
ClosedAt: db.ClosedAt,
|
|
OpeningAmount: db.OpeningAmount,
|
|
ClosingAmount: db.ClosingAmount,
|
|
ExpectedAmount: db.ExpectedAmount,
|
|
Status: db.Status,
|
|
}
|
|
}
|
|
|
|
func (r *cashierSessionRepository) GetPaymentSummaryBySessionID(ctx mycontext.Context, sessionID int64) ([]entity.PaymentSummary, error) {
|
|
type result struct {
|
|
PaymentType string
|
|
PaymentProvider string
|
|
TotalAmount float64
|
|
}
|
|
|
|
var rows []result
|
|
|
|
err := r.db.WithContext(ctx).
|
|
Table("orders").
|
|
Select("payment_type, payment_provider, SUM(total) AS total_amount").
|
|
Where("cashier_session_id = ?", sessionID).
|
|
Group("payment_type, payment_provider").
|
|
Scan(&rows).Error
|
|
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to summarize payments from orders")
|
|
}
|
|
|
|
summary := make([]entity.PaymentSummary, len(rows))
|
|
for i, row := range rows {
|
|
summary[i] = entity.PaymentSummary{
|
|
PaymentType: row.PaymentType,
|
|
PaymentProvider: row.PaymentProvider,
|
|
TotalAmount: row.TotalAmount,
|
|
}
|
|
}
|
|
|
|
return summary, nil
|
|
}
|
|
|
|
func (r *cashierSessionRepository) GetSessionHistoryByPartnerID(ctx mycontext.Context, partnerID int64, limit, offset int) ([]*entity.CashierSession, int64, error) {
|
|
var sessionsDB []models.CashierSessionDB
|
|
var totalCount int64
|
|
|
|
// Count total records
|
|
if err := r.db.Model(&models.CashierSessionDB{}).
|
|
Where("partner_id = ?", partnerID).
|
|
Count(&totalCount).Error; err != nil {
|
|
return nil, 0, errors.Wrap(err, "failed to count cashier sessions")
|
|
}
|
|
|
|
// Get sessions with pagination
|
|
query := r.db.Where("partner_id = ?", partnerID).
|
|
Order("opened_at DESC")
|
|
|
|
if limit > 0 {
|
|
query = query.Limit(limit)
|
|
}
|
|
|
|
if offset > 0 {
|
|
query = query.Offset(offset)
|
|
}
|
|
|
|
if err := query.Find(&sessionsDB).Error; err != nil {
|
|
return nil, 0, errors.Wrap(err, "failed to get cashier session history")
|
|
}
|
|
|
|
// Convert to entity
|
|
sessions := make([]*entity.CashierSession, len(sessionsDB))
|
|
for i, sessionDB := range sessionsDB {
|
|
sessions[i] = r.toEntity(&sessionDB)
|
|
}
|
|
|
|
return sessions, totalCount, nil
|
|
}
|