Add refund order

This commit is contained in:
aditya.siregar
2025-06-14 21:17:13 +07:00
parent 58d3b32c40
commit ebb33186b8
42 changed files with 1152 additions and 2094 deletions
+137
View File
@@ -0,0 +1,137 @@
package repository
import (
"enaklo-pos-be/internal/common/mycontext"
"enaklo-pos-be/internal/entity"
"enaklo-pos-be/internal/repository/models"
"github.com/pkg/errors"
"gorm.io/gorm"
"time"
)
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)
}
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{
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,
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
}
+94
View File
@@ -0,0 +1,94 @@
package repository
import (
"enaklo-pos-be/internal/common/mycontext"
"enaklo-pos-be/internal/entity"
"enaklo-pos-be/internal/repository/models"
"github.com/pkg/errors"
"gorm.io/gorm"
"time"
)
type CategoryRepository interface {
Create(ctx mycontext.Context, category *entity.Category) (*entity.Category, error)
GetByPartnerID(ctx mycontext.Context, partnerID int64) ([]*entity.Category, error)
GetByID(ctx mycontext.Context, id int64) (*entity.Category, error)
Update(ctx mycontext.Context, category *entity.Category) error
Delete(ctx mycontext.Context, id int64) error
}
type categoryRepository struct {
db *gorm.DB
}
func NewCategoryRepository(db *gorm.DB) CategoryRepository {
return &categoryRepository{db: db}
}
func (r *categoryRepository) Create(ctx mycontext.Context, category *entity.Category) (*entity.Category, error) {
dbModel := &models.CategoryDB{
PartnerID: category.PartnerID,
Name: category.Name,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if err := r.db.WithContext(ctx).Create(dbModel).Error; err != nil {
return nil, errors.Wrap(err, "failed to create category")
}
category.ID = dbModel.ID
return category, nil
}
func (r *categoryRepository) GetByPartnerID(ctx mycontext.Context, partnerID int64) ([]*entity.Category, error) {
var dbModels []models.CategoryDB
if err := r.db.WithContext(ctx).
Where("partner_id = ? AND deleted_at IS NULL", partnerID).
Find(&dbModels).Error; err != nil {
return nil, errors.Wrap(err, "failed to fetch categories by partner ID")
}
var result []*entity.Category
for _, db := range dbModels {
result = append(result, r.toEntity(&db))
}
return result, nil
}
func (r *categoryRepository) GetByID(ctx mycontext.Context, id int64) (*entity.Category, error) {
var db models.CategoryDB
if err := r.db.WithContext(ctx).
Where("id = ? AND deleted_at IS NULL", id).
First(&db).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, errors.Wrap(err, "failed to get category by ID")
}
return r.toEntity(&db), nil
}
func (r *categoryRepository) Update(ctx mycontext.Context, category *entity.Category) error {
return r.db.WithContext(ctx).Model(&models.CategoryDB{}).
Where("id = ?", category.ID).
Updates(map[string]interface{}{
"name": category.Name,
"updated_at": time.Now(),
}).Error
}
func (r *categoryRepository) Delete(ctx mycontext.Context, id int64) error {
return r.db.WithContext(ctx).
Model(&models.CategoryDB{}).
Where("id = ?", id).
Update("deleted_at", time.Now()).Error
}
func (r *categoryRepository) toEntity(db *models.CategoryDB) *entity.Category {
return &entity.Category{
ID: db.ID,
PartnerID: db.PartnerID,
Name: db.Name,
CreatedAt: db.CreatedAt.Unix(),
UpdatedAt: db.UpdatedAt.Unix(),
}
}
-86
View File
@@ -1,86 +0,0 @@
package event
import (
"context"
"go.uber.org/zap"
"gorm.io/gorm"
"enaklo-pos-be/internal/common/logger"
"enaklo-pos-be/internal/entity"
)
type EventRepoImpl struct {
DB *gorm.DB
}
func NewEventRepo(db *gorm.DB) *EventRepoImpl {
return &EventRepoImpl{DB: db}
}
func (e *EventRepoImpl) CreateEvent(ctx context.Context, event *entity.EventDB) (*entity.EventDB, error) {
err := e.DB.Create(event).Error
if err != nil {
logger.ContextLogger(ctx).Error("error when create event", zap.Error(err))
return nil, err
}
return event, nil
}
func (e *EventRepoImpl) UpdateEvent(ctx context.Context, event *entity.EventDB) (*entity.EventDB, error) {
if err := e.DB.Save(event).Error; err != nil {
logger.ContextLogger(ctx).Error("error when update event", zap.Error(err))
return nil, err
}
return event, nil
}
func (e *EventRepoImpl) GetEventByID(ctx context.Context, id int64) (*entity.EventDB, error) {
event := new(entity.EventDB)
if err := e.DB.First(event, id).Error; err != nil {
logger.ContextLogger(ctx).Error("error when get event by id", zap.Error(err))
return nil, err
}
return event, nil
}
func (e *EventRepoImpl) GetAllEvents(ctx context.Context, nameFilter string, limit, offset int) (entity.EventList, int, error) {
var events []*entity.EventDB
var total int64
query := e.DB
query = query.Where("deleted_at is null")
if nameFilter != "" {
query = query.Where("name LIKE ?", "%"+nameFilter+"%")
}
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
if err := query.Find(&events).Error; err != nil {
logger.ContextLogger(ctx).Error("error when get all events", zap.Error(err))
return nil, 0, err
}
if err := e.DB.Model(&entity.EventDB{}).Where(query).Count(&total).Error; err != nil {
logger.ContextLogger(ctx).Error("error when count event", zap.Error(err))
return nil, 0, err
}
return events, int(total), nil
}
func (e *EventRepoImpl) DeleteEvent(ctx context.Context, id int64) error {
event := new(entity.EventDB)
event.ID = id
if err := e.DB.Delete(event).Error; err != nil {
logger.ContextLogger(ctx).Error("error when get all events", zap.Error(err))
return err
}
return nil
}
@@ -0,0 +1,20 @@
package models
import "time"
type CashierSessionDB struct {
ID int64 `gorm:"primaryKey"`
CashierID int64 `gorm:"not null"`
OpenedAt time.Time `gorm:"not null"`
ClosedAt *time.Time
OpeningAmount float64 `gorm:"not null"`
ClosingAmount *float64
ExpectedAmount *float64
Notes *string
Status string `gorm:"not null"`
CreatedAt time.Time
}
func (CashierSessionDB) TableName() string {
return "cashier_sessions"
}
+16
View File
@@ -0,0 +1,16 @@
package models
import "time"
type CategoryDB struct {
ID int64 `gorm:"primaryKey;autoIncrement"`
PartnerID int64 `gorm:"not null"`
Name string `gorm:"type:varchar(255);not null"`
CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"`
DeletedAt *time.Time
}
func (CategoryDB) TableName() string {
return "categories"
}
+21 -18
View File
@@ -5,24 +5,26 @@ import (
)
type OrderDB struct {
ID int64 `gorm:"primaryKey;column:id"`
PartnerID int64 `gorm:"column:partner_id"`
CustomerID *int64 `gorm:"column:customer_id"`
InquiryID *string `gorm:"column:inquiry_id"`
Status string `gorm:"column:status"`
Amount float64 `gorm:"column:amount"`
Tax float64 `gorm:"column:tax"`
Total float64 `gorm:"column:total"`
PaymentType string `gorm:"column:payment_type"`
Source string `gorm:"column:source"`
CreatedBy int64 `gorm:"column:created_by"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
OrderItems []OrderItemDB `gorm:"foreignKey:OrderID"`
OrderType string `gorm:"column:order_type"`
TableNumber string `gorm:"column:table_number"`
PaymentProvider string `gorm:"column:payment_provider"`
CustomerName string `gorm:"column:customer_name"`
ID int64 `gorm:"primaryKey;column:id"`
PartnerID int64 `gorm:"column:partner_id"`
CustomerID *int64 `gorm:"column:customer_id"`
InquiryID *string `gorm:"column:inquiry_id"`
Status string `gorm:"column:status"`
Amount float64 `gorm:"column:amount"`
Tax float64 `gorm:"column:tax"`
Total float64 `gorm:"column:total"`
PaymentType string `gorm:"column:payment_type"`
Source string `gorm:"column:source"`
CreatedBy int64 `gorm:"column:created_by"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
OrderItems []OrderItemDB `gorm:"foreignKey:OrderID"`
OrderType string `gorm:"column:order_type"`
TableNumber string `gorm:"column:table_number"`
PaymentProvider string `gorm:"column:payment_provider"`
CustomerName string `gorm:"column:customer_name"`
CashierSessionID int64 `gorm:"column:cashier_session_id"`
Description string `gorm:"column:description"`
}
func (OrderDB) TableName() string {
@@ -68,6 +70,7 @@ type OrderInquiryDB struct {
PaymentProvider string `gorm:"column:payment_provider"`
TableNumber string `gorm:"column:table_number"`
OrderType string `gorm:"column:order_type"`
CashierSessionID int64 `gorm:"column:cashier_session_id"`
}
func (OrderInquiryDB) TableName() string {
+60 -34
View File
@@ -40,6 +40,7 @@ type OrderRepository interface {
FindByIDAndPartnerID(ctx mycontext.Context, id int64, partnerID int64) (*entity.Order, error)
GetOrderHistoryByUserID(ctx mycontext.Context, userID int64, req entity.SearchRequest) ([]*entity.Order, int64, error)
FindByIDAndCustomerID(ctx mycontext.Context, id int64, customerID int64) (*entity.Order, error)
UpdateOrder(ctx mycontext.Context, id int64, status string, description string) error
}
type orderRepository struct {
@@ -232,25 +233,48 @@ func (r *orderRepository) UpdateInquiryStatus(ctx mycontext.Context, id string,
return nil
}
func (r *orderRepository) UpdateOrder(ctx mycontext.Context, id int64, status string, description string) error {
now := time.Now()
result := r.db.Model(&models.OrderDB{}).
Where("id = ?", id).
Updates(map[string]interface{}{
"status": status,
"updated_at": now,
"description": description,
})
if result.Error != nil {
return errors.Wrap(result.Error, "failed to update order status")
}
if result.RowsAffected == 0 {
logger.ContextLogger(ctx).Warn("no order updated")
}
return nil
}
func (r *orderRepository) toOrderDBModel(order *entity.Order) models.OrderDB {
return models.OrderDB{
ID: order.ID,
PartnerID: order.PartnerID,
CustomerID: order.CustomerID,
InquiryID: order.InquiryID,
Status: order.Status,
Amount: order.Amount,
Tax: order.Tax,
Total: order.Total,
PaymentType: order.PaymentType,
Source: order.Source,
CreatedBy: order.CreatedBy,
CreatedAt: order.CreatedAt,
UpdatedAt: order.UpdatedAt,
OrderType: order.OrderType,
TableNumber: order.TableNumber,
PaymentProvider: order.PaymentProvider,
CustomerName: order.CustomerName,
ID: order.ID,
PartnerID: order.PartnerID,
CustomerID: order.CustomerID,
InquiryID: order.InquiryID,
Status: order.Status,
Amount: order.Amount,
Tax: order.Tax,
Total: order.Total,
PaymentType: order.PaymentType,
Source: order.Source,
CreatedBy: order.CreatedBy,
CreatedAt: order.CreatedAt,
UpdatedAt: order.UpdatedAt,
OrderType: order.OrderType,
TableNumber: order.TableNumber,
PaymentProvider: order.PaymentProvider,
CustomerName: order.CustomerName,
CashierSessionID: order.CashierSessionID,
}
}
@@ -346,27 +370,29 @@ func (r *orderRepository) toOrderInquiryDBModel(inquiry *entity.OrderInquiry) mo
PaymentProvider: inquiry.PaymentProvider,
OrderType: inquiry.OrderType,
TableNumber: inquiry.TableNumber,
CashierSessionID: inquiry.CashierSessionID,
}
}
func (r *orderRepository) toDomainOrderInquiryModel(dbModel *models.OrderInquiryDB) *entity.OrderInquiry {
inquiry := &entity.OrderInquiry{
ID: dbModel.ID,
PartnerID: dbModel.PartnerID,
Status: dbModel.Status,
Amount: dbModel.Amount,
Tax: dbModel.Tax,
Total: dbModel.Total,
PaymentType: dbModel.PaymentType,
Source: dbModel.Source,
CreatedBy: dbModel.CreatedBy,
CreatedAt: dbModel.CreatedAt,
ExpiresAt: dbModel.ExpiresAt,
OrderItems: []entity.OrderItem{},
OrderType: dbModel.OrderType,
CustomerName: dbModel.CustomerName,
PaymentProvider: dbModel.PaymentProvider,
TableNumber: dbModel.TableNumber,
ID: dbModel.ID,
PartnerID: dbModel.PartnerID,
Status: dbModel.Status,
Amount: dbModel.Amount,
Tax: dbModel.Tax,
Total: dbModel.Total,
PaymentType: dbModel.PaymentType,
Source: dbModel.Source,
CreatedBy: dbModel.CreatedBy,
CreatedAt: dbModel.CreatedAt,
ExpiresAt: dbModel.ExpiresAt,
OrderItems: []entity.OrderItem{},
OrderType: dbModel.OrderType,
CustomerName: dbModel.CustomerName,
PaymentProvider: dbModel.PaymentProvider,
TableNumber: dbModel.TableNumber,
CashierSessionID: dbModel.CashierSessionID,
}
if dbModel.CustomerID != nil {
@@ -718,7 +744,7 @@ func (r *orderRepository) GetRevenueOverview(
ctx mycontext.Context,
req entity.RevenueOverviewRequest,
) ([]entity.RevenueOverviewItem, error) {
var overview []entity.RevenueOverviewItem
overview := []entity.RevenueOverviewItem{}
baseQuery := r.db.Model(&models.OrderDB{}).
Where("partner_id = ?", req.PartnerID).
+8 -4
View File
@@ -38,7 +38,7 @@ func (b *ProductRepository) UpdateProduct(ctx context.Context, product *entity.P
func (b *ProductRepository) GetProductByID(ctx context.Context, id int64) (*entity.ProductDB, error) {
product := new(entity.ProductDB)
if err := b.db.First(product, id).Error; err != nil {
if err := b.db.Preload("Category").First(product, id).Error; err != nil {
logger.ContextLogger(ctx).Error("error when get by id product", zap.Error(err))
return nil, err
}
@@ -84,8 +84,12 @@ func (b *ProductRepository) GetAllProducts(ctx context.Context, req entity.Produ
query = query.Where("type = ? ", req.Type)
}
if req.BranchID > 0 {
query = query.Where("branch_id = ? ", req.BranchID)
if req.CategoryID > 0 {
query = query.Where("category_id = ? ", req.CategoryID)
}
if req.PartnerID > 0 {
query = query.Where("partner_id = ? ", req.PartnerID)
}
if req.Limit > 0 {
@@ -96,7 +100,7 @@ func (b *ProductRepository) GetAllProducts(ctx context.Context, req entity.Produ
query = query.Offset(req.Offset)
}
if err := query.Find(&products).Error; err != nil {
if err := query.Preload("Category").Find(&products).Order("id ASC").Error; err != nil {
logger.ContextLogger(ctx).Error("error when get all products", zap.Error(err))
return nil, 0, err
}
+4 -14
View File
@@ -15,7 +15,6 @@ import (
pg "enaklo-pos-be/internal/repository/payment_gateway"
"enaklo-pos-be/internal/repository/products"
"enaklo-pos-be/internal/repository/sites"
"enaklo-pos-be/internal/repository/studios"
transactions "enaklo-pos-be/internal/repository/transaction"
"enaklo-pos-be/internal/repository/trx"
"enaklo-pos-be/internal/repository/users"
@@ -28,15 +27,12 @@ import (
"enaklo-pos-be/internal/entity"
"enaklo-pos-be/internal/repository/auth"
"enaklo-pos-be/internal/repository/crypto"
event "enaklo-pos-be/internal/repository/events"
)
type RepoManagerImpl struct {
Crypto Crypto
Auth Auth
Event Event
User User
Studio Studio
Product Product
Order Order
OSS OSSRepository
@@ -60,15 +56,15 @@ type RepoManagerImpl struct {
MemberRepository MemberRepository
PartnerSetting PartnerSettingsRepository
UndianRepository UndianRepo
CashierSeasionRepo CashierSessionRepository
CategoryRepository CategoryRepository
}
func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
return &RepoManagerImpl{
Crypto: crypto.NewCrypto(cfg.Auth()),
Auth: auth.NewAuthRepository(db),
Event: event.NewEventRepo(db),
User: users.NewUserRepository(db),
Studio: studios.NewStudioRepository(db),
Product: products.NewProductRepository(db),
Order: orders.NewOrderRepository(db),
OSS: oss.NewOssRepositoryImpl(cfg.OSSConfig),
@@ -92,6 +88,8 @@ func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
InProgressOrderRepo: NewInProgressOrderRepository(db),
PartnerSetting: NewPartnerSettingsRepository(db),
UndianRepository: NewUndianRepository(db),
CashierSeasionRepo: NewCashierSessionRepository(db),
CategoryRepository: NewCategoryRepository(db),
}
}
@@ -101,14 +99,6 @@ type Auth interface {
UpdatePassword(ctx context.Context, trx *gorm.DB, newHashedPassword string, userID int64, resetPassword bool) error
}
type Event interface {
CreateEvent(ctx context.Context, event *entity.EventDB) (*entity.EventDB, error)
UpdateEvent(ctx context.Context, event *entity.EventDB) (*entity.EventDB, error)
GetEventByID(ctx context.Context, id int64) (*entity.EventDB, error)
GetAllEvents(ctx context.Context, nameFilter string, limit, offset int) (entity.EventList, int, error)
DeleteEvent(ctx context.Context, id int64) error
}
type Crypto interface {
CompareHashAndPassword(hash string, password string) bool
ValidateWT(tokenString string) (*jwt.Token, error)
-89
View File
@@ -1,89 +0,0 @@
package studios
import (
"context"
"enaklo-pos-be/internal/common/logger"
"enaklo-pos-be/internal/entity"
"go.uber.org/zap"
"gorm.io/gorm"
)
type StudioRepository struct {
db *gorm.DB
}
func NewStudioRepository(db *gorm.DB) *StudioRepository {
return &StudioRepository{
db: db,
}
}
func (s *StudioRepository) CreateStudio(ctx context.Context, studio *entity.StudioDB) (*entity.StudioDB, error) {
err := s.db.Omit("ID").Create(studio).Error
if err != nil {
logger.ContextLogger(ctx).Error("error when creating studio", zap.Error(err))
return nil, err
}
return studio, nil
}
func (s *StudioRepository) UpdateStudio(ctx context.Context, studio *entity.StudioDB) (*entity.StudioDB, error) {
if err := s.db.Save(studio).Error; err != nil {
logger.ContextLogger(ctx).Error("error when updating studio", zap.Error(err))
return nil, err
}
return studio, nil
}
func (s *StudioRepository) GetStudioByID(ctx context.Context, id int64) (*entity.StudioDB, error) {
studio := new(entity.StudioDB)
if err := s.db.First(studio, id).Error; err != nil {
logger.ContextLogger(ctx).Error("error when getting studio by ID", zap.Error(err))
return nil, err
}
return studio, nil
}
func (s *StudioRepository) SearchStudios(ctx context.Context, req entity.StudioSearch) (entity.StudioList, int, error) {
var studios []*entity.StudioDB
var total int64
query := s.db
if req.Id > 0 {
query = query.Where("id = ?", req.Id)
}
if req.Name != "" {
query = query.Where("name ILIKE ?", "%"+req.Name+"%")
}
if req.Status != "" {
query = query.Where("status = ?", req.Status)
}
if req.BranchId > 0 {
query = query.Where("branch_id = ?", req.BranchId)
}
if req.Limit > 0 {
query = query.Limit(req.Limit)
}
if req.Offset > 0 {
query = query.Offset(req.Offset)
}
if err := query.Find(&studios).Error; err != nil {
logger.ContextLogger(ctx).Error("error when getting all studios", zap.Error(err))
return nil, 0, err
}
if err := s.db.Model(&entity.StudioDB{}).Where(query).Count(&total).Error; err != nil {
logger.ContextLogger(ctx).Error("error when counting studios", zap.Error(err))
return nil, 0, err
}
return studios, int(total), nil
}