init project
This commit is contained in:
@@ -0,0 +1 @@
|
||||
package auth
|
||||
@@ -0,0 +1,47 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-be/internal/entity"
|
||||
)
|
||||
|
||||
type AuthRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewAuthRepository(db *gorm.DB) *AuthRepository {
|
||||
return &AuthRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *AuthRepository) CheckExistsUserAccount(ctx context.Context, email string) (*entity.UserDB, error) {
|
||||
var user entity.UserDB
|
||||
|
||||
err := r.db.
|
||||
Table("users").
|
||||
Select("users.*, user_roles.role_id, user_roles.partner_id, roles.role_name, partners.name as partner_name").
|
||||
Where("users.email = ?", email).
|
||||
Joins("left join user_roles on users.id = user_roles.user_id").
|
||||
Joins("left join roles on user_roles.role_id = roles.role_id").
|
||||
Joins("left join partners on user_roles.partner_id = partners.id").
|
||||
First(&user).Error
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fmt.Errorf("user with email %s does not exist", email) // or use a custom error type
|
||||
}
|
||||
|
||||
logger.ContextLogger(ctx).Error(fmt.Sprintf("Failed to get user with email: %s", email), zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package branches
|
||||
|
||||
import (
|
||||
"context"
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-be/internal/entity"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type BranchRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewBranchRepository(db *gorm.DB) *BranchRepository {
|
||||
return &BranchRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BranchRepository) CreateBranch(ctx context.Context, branch *entity.BranchDB) (*entity.BranchDB, error) {
|
||||
err := b.db.Create(branch).Error
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when create branch", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return branch, nil
|
||||
}
|
||||
|
||||
func (b *BranchRepository) UpdateBranch(ctx context.Context, branch *entity.BranchDB) (*entity.BranchDB, error) {
|
||||
if err := b.db.Save(branch).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when update branch", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return branch, nil
|
||||
}
|
||||
|
||||
func (b *BranchRepository) GetBranchByID(ctx context.Context, id int64) (*entity.BranchDB, error) {
|
||||
branch := new(entity.BranchDB)
|
||||
if err := b.db.First(branch, id).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get by id branch", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return branch, nil
|
||||
}
|
||||
|
||||
func (b *BranchRepository) GetAllBranches(ctx context.Context, req entity.BranchSearch) (entity.BranchList, int, error) {
|
||||
var branches []*entity.BranchDB
|
||||
var total int64
|
||||
|
||||
query := b.db
|
||||
query = query.Where("deleted_at is null")
|
||||
|
||||
if req.Search != "" {
|
||||
query = query.Where("name ILIKE ?", "%"+req.Search+"%")
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
query = query.Where("name ILIKE ?", "%"+req.Name+"%")
|
||||
}
|
||||
|
||||
if req.Limit > 0 {
|
||||
query = query.Limit(req.Limit)
|
||||
}
|
||||
|
||||
if req.Offset > 0 {
|
||||
query = query.Offset(req.Offset)
|
||||
}
|
||||
|
||||
if err := query.Find(&branches).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get all branches", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := b.db.Model(&entity.BranchDB{}).Where(query).Count(&total).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when count branches", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return branches, int(total), nil
|
||||
}
|
||||
|
||||
func (b *BranchRepository) DeleteBranch(ctx context.Context, id int64) error {
|
||||
branch := new(entity.BranchDB)
|
||||
branch.ID = id
|
||||
if err := b.db.Delete(branch).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
//go:generate mockery --name Crypto --filename crypto.go --output ./mock --with-expecter
|
||||
|
||||
package crypto
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"furtuna-be/internal/common/errors"
|
||||
"furtuna-be/internal/entity"
|
||||
)
|
||||
|
||||
func NewCrypto(config CryptoConfig) *CryptoImpl {
|
||||
return &CryptoImpl{
|
||||
Config: config,
|
||||
}
|
||||
}
|
||||
|
||||
type CryptoConfig interface {
|
||||
AccessTokenSecret() string
|
||||
AccessTokenExpiresDate() time.Time
|
||||
}
|
||||
|
||||
type CryptoImpl struct {
|
||||
Config CryptoConfig
|
||||
}
|
||||
|
||||
func (c *CryptoImpl) CompareHashAndPassword(hash string, password string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (c *CryptoImpl) ValidateWT(tokenString string) (*jwt.Token, error) {
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return []byte(c.Config.AccessTokenSecret()), nil
|
||||
})
|
||||
|
||||
return token, err
|
||||
}
|
||||
|
||||
func (c *CryptoImpl) GenerateJWT(user *entity.User) (string, error) {
|
||||
branchID := int64(0)
|
||||
if user.PartnerID != nil {
|
||||
branchID = *user.PartnerID
|
||||
}
|
||||
|
||||
claims := &entity.JWTAuthClaims{
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
Subject: strconv.FormatInt(user.ID, 10),
|
||||
ExpiresAt: c.Config.AccessTokenExpiresDate().Unix(),
|
||||
IssuedAt: time.Now().Unix(),
|
||||
NotBefore: time.Now().Unix(),
|
||||
},
|
||||
UserID: user.ID,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Role: int(user.RoleID),
|
||||
BranchID: branchID,
|
||||
}
|
||||
|
||||
token, err := jwt.
|
||||
NewWithClaims(jwt.SigningMethodHS256, claims).
|
||||
SignedString([]byte(c.Config.AccessTokenSecret()))
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (c *CryptoImpl) ParseAndValidateJWT(tokenString string) (*entity.JWTAuthClaims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &entity.JWTAuthClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(c.Config.AccessTokenSecret()), nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(*entity.JWTAuthClaims); ok && token.Valid {
|
||||
return claims, nil
|
||||
} else {
|
||||
return nil, errors.ErrorUnauthorized
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-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,303 @@
|
||||
package orders
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-be/internal/entity"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type OrderRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewOrderRepository(db *gorm.DB) *OrderRepository {
|
||||
return &OrderRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *OrderRepository) CreateOrder(ctx context.Context, order *entity.OrderDB) (*entity.OrderDB, error) {
|
||||
tx := o.db.Begin()
|
||||
|
||||
if err := tx.Select("branch_id", "status", "customer_name", "customer_phone", "pax", "amount", "created_by").Create(order).Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "creating order", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, orditem := range order.OrderItem {
|
||||
orderItem := orditem.ToOrderItemDB()
|
||||
orderItem.OrderID = order.ID
|
||||
|
||||
err := tx.Select("order_id", "item_id", "item_type", "price", "qty", "created_by").Create(orderItem).Error
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when create order item", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
order.OrderItem[i] = *orderItem.ToOrderItem()
|
||||
}
|
||||
|
||||
//insert transaction
|
||||
transaction := order.Transaction.ToTransactionDB()
|
||||
transaction.OrderID = order.ID
|
||||
|
||||
if err := tx.Select("branch_id", "status", "amount", "order_id", "payment_method", "customer_name", "customer_phone", "created_by").Create(transaction).Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "creating transaction", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "committing transaction", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return order, nil
|
||||
}
|
||||
|
||||
func (b *OrderRepository) UpdateOrder(ctx context.Context, order *entity.OrderDB) (*entity.OrderDB, error) {
|
||||
|
||||
if err := b.db.Select("status", "updated_at", "updated_by").Save(order).Error; err != nil {
|
||||
logError(ctx, "update order", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return order, nil
|
||||
}
|
||||
|
||||
func (b *OrderRepository) GetAllOrders(ctx context.Context, req entity.OrderSearch) (entity.OrderList, int, error) {
|
||||
var orders []*entity.OrderDB
|
||||
var total int64
|
||||
|
||||
query := b.db.Table("orders").
|
||||
Select("orders.id, orders.branch_id, b.name as branch_name, orders.status, orders.amount, orders.created_at, orders.updated_at, oi.order_item_id, oi.order_id, oi.item_id, oi.item_type, COALESCE(p.name, s.name, '') as item_name, oi.price, oi.qty, oi.created_at, oi.updated_at, COALESCE(t.payment_method, ''), COALESCE(orders.customer_name, ''), COALESCE(orders.customer_phone, ''), COALESCE(orders.pax, 0)").
|
||||
Joins("LEFT JOIN order_items oi ON orders.id = oi.order_id").
|
||||
Joins("LEFT JOIN transactions t ON orders.id = t.order_id").
|
||||
Joins("LEFT JOIN products p ON oi.item_id = p.id AND oi.item_type ='PRODUCT' ").
|
||||
Joins("LEFT JOIN studios s ON oi.item_id = s.id AND oi.item_type ='STUDIO' ").
|
||||
Joins("LEFT JOIN branches b ON orders.branch_id = b.id")
|
||||
|
||||
if req.Search != "" {
|
||||
query = query.Where("b.name ILIKE ? or orders.status ILIKE ? or oi.item_type ILIKE ? or p.name ILIKE ? or orders.customer_name ILIKE ? ", "%"+req.Search+"%", "%"+req.Search+"%", "%"+req.Search+"%", "%"+req.Search+"%", "%"+req.Search+"%")
|
||||
}
|
||||
|
||||
if req.Status != "" {
|
||||
query = query.Where("orders.status = ?", req.Status)
|
||||
}
|
||||
|
||||
if req.BranchID > 0 {
|
||||
query = query.Where("orders.branch_id = ?", req.BranchID)
|
||||
}
|
||||
|
||||
if req.StatusActive.IsActive() {
|
||||
query = query.Joins("INNER JOIN (SELECT o.id, oi.qty, o.created_at FROM orders o INNER JOIN order_items oi ON o.id = oi.order_id AND oi.item_type = 'STUDIO' where o.status != 'CANCEL' and CURRENT_TIMESTAMP > o.created_at AND CURRENT_TIMESTAMP < (o.created_at + (oi.qty || ' hours')::interval)) order_active on order_active.id=orders.id")
|
||||
}
|
||||
|
||||
if req.Limit > 0 {
|
||||
query = query.Limit(req.Limit)
|
||||
}
|
||||
|
||||
if req.Offset > 0 {
|
||||
query = query.Offset(req.Offset)
|
||||
}
|
||||
|
||||
query.Order("orders.created_at DESC")
|
||||
|
||||
rows, err := query.Rows()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
ordersMap := make(map[int64]*entity.OrderDB) // Map to store orders by ID
|
||||
for rows.Next() {
|
||||
var ordr entity.OrderDB
|
||||
var oi entity.OrderItem
|
||||
|
||||
err := rows.Scan(&ordr.ID, &ordr.BranchID, &ordr.BranchName, &ordr.Status, &ordr.Amount, &ordr.CreatedAt, &ordr.UpdatedAt,
|
||||
&oi.OrderItemID, &oi.OrderID, &oi.ItemID, &oi.ItemType, &oi.ItemName, &oi.Price, &oi.Qty, &oi.CreatedAt, &oi.UpdatedAt,
|
||||
&ordr.Transaction.PaymentMethod, &ordr.CustomerName, &ordr.CustomerPhone, &ordr.Pax)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error scanning rows", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if order, ok := ordersMap[ordr.ID]; ok {
|
||||
// Order already exists in map, append OrderItem to existing order
|
||||
order.OrderItem = append(order.OrderItem, oi)
|
||||
} else {
|
||||
// Order doesn't exist in map, create a new OrderDB
|
||||
newOrder := ordr
|
||||
newOrder.OrderItem = []entity.OrderItem{oi}
|
||||
ordersMap[ordr.ID] = &newOrder
|
||||
|
||||
orders = append(orders, &ordr)
|
||||
}
|
||||
}
|
||||
|
||||
// assign value order item
|
||||
for _, v := range orders {
|
||||
v.OrderItem = ordersMap[v.ID].OrderItem
|
||||
}
|
||||
|
||||
//reset limit for count total data
|
||||
query = query.Offset(-1).Limit(-1)
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when count orders", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return orders, int(total), nil
|
||||
}
|
||||
|
||||
func (b *OrderRepository) GetOrderByID(ctx context.Context, id int64) (*entity.OrderDB, error) {
|
||||
var orders *entity.OrderDB
|
||||
|
||||
query := b.db.Table("orders").
|
||||
Select("orders.id, orders.branch_id, b.name as branch_name, orders.status, orders.amount, orders.created_at, orders.updated_at, oi.order_item_id, oi.order_id, oi.item_id, oi.item_type, COALESCE(p.name, s.name, '') as item_name, oi.price, oi.qty, oi.created_at, oi.updated_at, t.payment_method, orders.customer_name, orders.customer_phone, orders.pax").
|
||||
Joins("LEFT JOIN order_items oi ON orders.id = oi.order_id").
|
||||
Joins("LEFT JOIN transactions t ON orders.id = t.order_id").
|
||||
Joins("LEFT JOIN products p ON oi.item_id = p.id AND oi.item_type ='PRODUCT' ").
|
||||
Joins("LEFT JOIN studios s ON oi.item_id = s.id AND oi.item_type ='STUDIO' ").
|
||||
Joins("LEFT JOIN branches b ON orders.branch_id = b.id").
|
||||
Where("orders.id = ?", id)
|
||||
|
||||
rows, err := query.Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
var ordr entity.OrderDB // Map to store orders by ID
|
||||
for rows.Next() {
|
||||
var oi entity.OrderItem
|
||||
|
||||
err := rows.Scan(&ordr.ID, &ordr.BranchID, &ordr.BranchName, &ordr.Status, &ordr.Amount, &ordr.CreatedAt, &ordr.UpdatedAt,
|
||||
&oi.OrderItemID, &oi.OrderID, &oi.ItemID, &oi.ItemType, &oi.ItemName, &oi.Price, &oi.Qty, &oi.CreatedAt, &oi.UpdatedAt,
|
||||
&ordr.Transaction.PaymentMethod, &ordr.CustomerName, &ordr.CustomerPhone, &ordr.Pax)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error scanning rows", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ordr.OrderItem = append(ordr.OrderItem, oi)
|
||||
}
|
||||
|
||||
orders = &ordr
|
||||
|
||||
if orders == nil {
|
||||
return nil, fmt.Errorf("order not found")
|
||||
}
|
||||
|
||||
return orders, nil
|
||||
}
|
||||
|
||||
func (b *OrderRepository) GetTotalRevenue(ctx context.Context, req entity.OrderTotalRevenueSearch) (float64, int64, error) {
|
||||
var (
|
||||
totalmonthlyRevenue float64
|
||||
totalmonthlyTrans int64
|
||||
)
|
||||
|
||||
query := b.db.Table("orders").
|
||||
Select("COALESCE(sum(amount),0) as total_amount, COALESCE(count(id),0) as total_transaction").
|
||||
Where("status in ('NEW','PAID') ")
|
||||
|
||||
if req.BranchID > 0 {
|
||||
query = query.Where("branch_id = ?", req.BranchID)
|
||||
}
|
||||
|
||||
if req.Month > 0 {
|
||||
query = query.Where("EXTRACT(MONTH FROM created_at) = ? ", req.Month)
|
||||
}
|
||||
|
||||
if req.Year > 0 {
|
||||
query = query.Where("EXTRACT(YEAR FROM created_at) = ? ", req.Year)
|
||||
}
|
||||
|
||||
if req.DateStart != nil {
|
||||
query = query.Where("created_at >= ? ", req.DateStart)
|
||||
}
|
||||
|
||||
if req.DateEnd != nil {
|
||||
query = query.Where("created_at <= ? ", req.DateEnd)
|
||||
}
|
||||
|
||||
rows, err := query.Rows()
|
||||
if err != nil {
|
||||
return totalmonthlyRevenue, totalmonthlyTrans, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&totalmonthlyRevenue, &totalmonthlyTrans)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error scanning rows", zap.Error(err))
|
||||
return totalmonthlyRevenue, totalmonthlyTrans, err
|
||||
}
|
||||
}
|
||||
|
||||
return totalmonthlyRevenue, totalmonthlyTrans, nil
|
||||
}
|
||||
|
||||
func (b *OrderRepository) GetYearlyRevenue(ctx context.Context, year int) (entity.OrderYearlyRevenueList, error) {
|
||||
var result entity.OrderYearlyRevenueList
|
||||
|
||||
err := b.db.Raw(` SELECT
|
||||
oi.item_type,
|
||||
EXTRACT(MONTH FROM o.created_at) AS month_number,
|
||||
SUM(oi.price ) AS total_amount
|
||||
FROM
|
||||
orders o
|
||||
JOIN
|
||||
order_items oi ON o.id = oi.order_id
|
||||
WHERE
|
||||
EXTRACT(YEAR FROM o.created_at) = ?
|
||||
AND o.status IN ('NEW', 'PAID')
|
||||
GROUP BY
|
||||
EXTRACT(MONTH FROM o.created_at),
|
||||
oi.item_type
|
||||
ORDER BY
|
||||
month_number,
|
||||
oi.item_type`, year).Scan(&result).Error
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (b *OrderRepository) GetBranchRevenue(ctx context.Context, req entity.OrderBranchRevenueSearch) (entity.OrderBranchRevenueList, error) {
|
||||
var result entity.OrderBranchRevenueList
|
||||
|
||||
query := b.db.Table("orders o").
|
||||
Joins("JOIN branches ON branches.id = o.branch_id").
|
||||
Select("o.branch_id, branches.name, branches.location, SUM(o.amount) as total_amount, COUNT(o.id) as total_trans").
|
||||
Where("o.status IN ('NEW', 'PAID')").
|
||||
Group("o.branch_id, branches.name, branches.location").
|
||||
Order("total_amount DESC, total_trans DESC")
|
||||
|
||||
if req.DateStart != nil {
|
||||
query = query.Where("o.created_at >= ? ", req.DateStart)
|
||||
}
|
||||
|
||||
if req.DateEnd != nil {
|
||||
query = query.Where("o.created_at <= ? ", req.DateEnd)
|
||||
}
|
||||
|
||||
if err := query.Find(&result).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when GetBranchRevenue", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func logError(ctx context.Context, s string, err error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package oss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
)
|
||||
|
||||
type OSSConfig interface {
|
||||
GetAccessKeyID() string
|
||||
GetAccessKeySecret() string
|
||||
GetEndpoint() string
|
||||
GetBucketName() string
|
||||
GetHostURL() string
|
||||
}
|
||||
|
||||
const _awsRegion = "us-east-1"
|
||||
const _s3ACL = "public-read"
|
||||
|
||||
type OssRepositoryImpl struct {
|
||||
s3 *s3.S3
|
||||
cfg OSSConfig
|
||||
}
|
||||
|
||||
func NewOssRepositoryImpl(ossCfg OSSConfig) *OssRepositoryImpl {
|
||||
sess, err := session.NewSession(&aws.Config{
|
||||
S3ForcePathStyle: aws.Bool(true),
|
||||
Endpoint: aws.String(ossCfg.GetEndpoint()),
|
||||
Region: aws.String(_awsRegion),
|
||||
Credentials: credentials.NewStaticCredentials(ossCfg.GetAccessKeyID(), ossCfg.GetAccessKeySecret(), ""),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Failed to create AWS session:", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return &OssRepositoryImpl{
|
||||
s3: s3.New(sess),
|
||||
cfg: ossCfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *OssRepositoryImpl) UploadFile(ctx context.Context, fileName string, fileContent []byte) (fileUrl string, err error) {
|
||||
reader := bytes.NewReader(fileContent)
|
||||
|
||||
_, err = r.s3.PutObject(&s3.PutObjectInput{
|
||||
Bucket: aws.String(r.cfg.GetBucketName()),
|
||||
Key: aws.String(fileName),
|
||||
Body: reader,
|
||||
ACL: aws.String(_s3ACL),
|
||||
})
|
||||
|
||||
return r.GetPublicURL(fileName), err
|
||||
}
|
||||
|
||||
func (r *OssRepositoryImpl) GetPublicURL(fileName string) string {
|
||||
if fileName == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s/%s%s", r.cfg.GetHostURL(), r.cfg.GetBucketName(), fileName)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package partners
|
||||
|
||||
import (
|
||||
"context"
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-be/internal/entity"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PartnerRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewPartnerRepository(db *gorm.DB) *PartnerRepository {
|
||||
return &PartnerRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *PartnerRepository) Create(ctx context.Context, Partner *entity.PartnerDB) (*entity.PartnerDB, error) {
|
||||
err := b.db.Create(Partner).Error
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when create Partner", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return Partner, nil
|
||||
}
|
||||
|
||||
func (b *PartnerRepository) Update(ctx context.Context, Partner *entity.PartnerDB) (*entity.PartnerDB, error) {
|
||||
if err := b.db.Save(Partner).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when update Partner", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return Partner, nil
|
||||
}
|
||||
|
||||
func (b *PartnerRepository) GetByID(ctx context.Context, id int64) (*entity.PartnerDB, error) {
|
||||
Partner := new(entity.PartnerDB)
|
||||
if err := b.db.First(Partner, id).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get by id Partner", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return Partner, nil
|
||||
}
|
||||
|
||||
func (b *PartnerRepository) GetAll(ctx context.Context, req entity.PartnerSearch) (entity.PartnerList, int, error) {
|
||||
var Partneres []*entity.PartnerDB
|
||||
var total int64
|
||||
|
||||
query := b.db
|
||||
query = query.Where("deleted_at is null")
|
||||
|
||||
if req.Search != "" {
|
||||
query = query.Where("name ILIKE ?", "%"+req.Search+"%")
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
query = query.Where("name ILIKE ?", "%"+req.Name+"%")
|
||||
}
|
||||
|
||||
if req.Limit > 0 {
|
||||
query = query.Limit(req.Limit)
|
||||
}
|
||||
|
||||
if req.Offset > 0 {
|
||||
query = query.Offset(req.Offset)
|
||||
}
|
||||
|
||||
if err := query.Find(&Partneres).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get all Partneres", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := b.db.Model(&entity.PartnerDB{}).Where(query).Count(&total).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when count Partneres", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return Partneres, int(total), nil
|
||||
}
|
||||
|
||||
func (b *PartnerRepository) Delete(ctx context.Context, id int64) error {
|
||||
Partner := new(entity.PartnerDB)
|
||||
Partner.ID = id
|
||||
if err := b.db.Delete(Partner).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package products
|
||||
|
||||
import (
|
||||
"context"
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-be/internal/entity"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ProductRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewProductRepository(db *gorm.DB) *ProductRepository {
|
||||
return &ProductRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ProductRepository) CreateProduct(ctx context.Context, product *entity.ProductDB) (*entity.ProductDB, error) {
|
||||
err := b.db.Create(product).Error
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when create product", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return product, nil
|
||||
}
|
||||
|
||||
func (b *ProductRepository) UpdateProduct(ctx context.Context, product *entity.ProductDB) (*entity.ProductDB, error) {
|
||||
if err := b.db.Save(product).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when update product", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return product, nil
|
||||
}
|
||||
|
||||
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 {
|
||||
logger.ContextLogger(ctx).Error("error when get by id product", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return product, nil
|
||||
}
|
||||
|
||||
func (b *ProductRepository) GetAllProducts(ctx context.Context, req entity.ProductSearch) (entity.ProductList, int, error) {
|
||||
var products []*entity.ProductDB
|
||||
var total int64
|
||||
|
||||
query := b.db
|
||||
query = query.Where("deleted_at is null")
|
||||
|
||||
if req.Search != "" {
|
||||
query = query.Where("name ILIKE ?", "%"+req.Search+"%")
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
query = query.Where("name ILIKE ?", "%"+req.Name+"%")
|
||||
}
|
||||
|
||||
if req.Type != "" {
|
||||
query = query.Where("type = ? ", req.Type)
|
||||
}
|
||||
|
||||
if req.BranchID > 0 {
|
||||
query = query.Where("branch_id = ? ", req.BranchID)
|
||||
}
|
||||
|
||||
if req.Available != "" {
|
||||
if req.Available.IsAvailable() {
|
||||
query = query.Where("stock_qty > 0 ")
|
||||
} else if req.Available.IsUnavailable() {
|
||||
query = query.Where("stock_qty < 1 ")
|
||||
}
|
||||
}
|
||||
|
||||
if req.Limit > 0 {
|
||||
query = query.Limit(req.Limit)
|
||||
}
|
||||
|
||||
if req.Offset > 0 {
|
||||
query = query.Offset(req.Offset)
|
||||
}
|
||||
|
||||
if err := query.Find(&products).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get all products", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := b.db.Model(&entity.ProductDB{}).Where(query).Count(&total).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when count products", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return products, int(total), nil
|
||||
}
|
||||
|
||||
func (b *ProductRepository) DeleteProduct(ctx context.Context, id int64) error {
|
||||
product := new(entity.ProductDB)
|
||||
product.ID = id
|
||||
if err := b.db.Delete(product).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"furtuna-be/internal/repository/branches"
|
||||
"furtuna-be/internal/repository/orders"
|
||||
"furtuna-be/internal/repository/oss"
|
||||
"furtuna-be/internal/repository/partners"
|
||||
"furtuna-be/internal/repository/products"
|
||||
"furtuna-be/internal/repository/studios"
|
||||
"furtuna-be/internal/repository/users"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"furtuna-be/config"
|
||||
"furtuna-be/internal/entity"
|
||||
"furtuna-be/internal/repository/auth"
|
||||
"furtuna-be/internal/repository/crypto"
|
||||
event "furtuna-be/internal/repository/events"
|
||||
)
|
||||
|
||||
type RepoManagerImpl struct {
|
||||
Crypto Crypto
|
||||
Auth Auth
|
||||
Event Event
|
||||
User User
|
||||
Branch Branch
|
||||
Studio Studio
|
||||
Product Product
|
||||
Order Order
|
||||
OSS OSSRepository
|
||||
Partner PartnerRepository
|
||||
}
|
||||
|
||||
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),
|
||||
Branch: branches.NewBranchRepository(db),
|
||||
Studio: studios.NewStudioRepository(db),
|
||||
Product: products.NewProductRepository(db),
|
||||
Order: orders.NewOrderRepository(db),
|
||||
OSS: oss.NewOssRepositoryImpl(cfg.OSSConfig),
|
||||
Partner: partners.NewPartnerRepository(db),
|
||||
}
|
||||
}
|
||||
|
||||
type Auth interface {
|
||||
CheckExistsUserAccount(ctx context.Context, email string) (*entity.UserDB, 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)
|
||||
GenerateJWT(user *entity.User) (string, error)
|
||||
ParseAndValidateJWT(token string) (*entity.JWTAuthClaims, error)
|
||||
}
|
||||
|
||||
type User interface {
|
||||
Create(ctx context.Context, user *entity.UserDB) (*entity.UserDB, error)
|
||||
GetAllUsers(ctx context.Context, req entity.UserSearch) (entity.UserList, int, error)
|
||||
GetUserByID(ctx context.Context, id int64) (*entity.UserDB, error)
|
||||
GetUserByEmail(ctx context.Context, email string) (*entity.UserDB, error)
|
||||
UpdateUser(ctx context.Context, user *entity.UserDB) (*entity.UserDB, error)
|
||||
}
|
||||
|
||||
type Branch interface {
|
||||
CreateBranch(ctx context.Context, branch *entity.BranchDB) (*entity.BranchDB, error)
|
||||
UpdateBranch(ctx context.Context, branch *entity.BranchDB) (*entity.BranchDB, error)
|
||||
GetBranchByID(ctx context.Context, id int64) (*entity.BranchDB, error)
|
||||
GetAllBranches(ctx context.Context, req entity.BranchSearch) (entity.BranchList, int, error)
|
||||
DeleteBranch(ctx context.Context, id int64) error
|
||||
}
|
||||
|
||||
type Studio interface {
|
||||
CreateStudio(ctx context.Context, studio *entity.StudioDB) (*entity.StudioDB, error)
|
||||
UpdateStudio(ctx context.Context, studio *entity.StudioDB) (*entity.StudioDB, error)
|
||||
GetStudioByID(ctx context.Context, id int64) (*entity.StudioDB, error)
|
||||
SearchStudios(ctx context.Context, req entity.StudioSearch) (entity.StudioList, int, error)
|
||||
}
|
||||
|
||||
type Product interface {
|
||||
CreateProduct(ctx context.Context, product *entity.ProductDB) (*entity.ProductDB, error)
|
||||
UpdateProduct(ctx context.Context, product *entity.ProductDB) (*entity.ProductDB, error)
|
||||
GetProductByID(ctx context.Context, id int64) (*entity.ProductDB, error)
|
||||
GetAllProducts(ctx context.Context, req entity.ProductSearch) (entity.ProductList, int, error)
|
||||
DeleteProduct(ctx context.Context, id int64) error
|
||||
}
|
||||
|
||||
type Order interface {
|
||||
CreateOrder(ctx context.Context, order *entity.OrderDB) (*entity.OrderDB, error)
|
||||
UpdateOrder(ctx context.Context, order *entity.OrderDB) (*entity.OrderDB, error)
|
||||
GetOrderByID(ctx context.Context, id int64) (*entity.OrderDB, error)
|
||||
GetAllOrders(ctx context.Context, req entity.OrderSearch) (entity.OrderList, int, error)
|
||||
GetTotalRevenue(ctx context.Context, req entity.OrderTotalRevenueSearch) (float64, int64, error)
|
||||
GetYearlyRevenue(ctx context.Context, year int) (entity.OrderYearlyRevenueList, error)
|
||||
GetBranchRevenue(ctx context.Context, req entity.OrderBranchRevenueSearch) (entity.OrderBranchRevenueList, error)
|
||||
}
|
||||
|
||||
type OSSRepository interface {
|
||||
UploadFile(ctx context.Context, fileName string, fileContent []byte) (fileUrl string, err error)
|
||||
GetPublicURL(fileName string) string
|
||||
}
|
||||
|
||||
type PartnerRepository interface {
|
||||
Create(ctx context.Context, branch *entity.PartnerDB) (*entity.PartnerDB, error)
|
||||
Update(ctx context.Context, branch *entity.PartnerDB) (*entity.PartnerDB, error)
|
||||
GetByID(ctx context.Context, id int64) (*entity.PartnerDB, error)
|
||||
GetAll(ctx context.Context, req entity.PartnerSearch) (entity.PartnerList, int, error)
|
||||
Delete(ctx context.Context, id int64) error
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package studios
|
||||
|
||||
import (
|
||||
"context"
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-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
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"context"
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-be/internal/entity"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type UserRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserRepository(db *gorm.DB) *UserRepository {
|
||||
return &UserRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *UserRepository) Create(ctx context.Context, user *entity.UserDB) (*entity.UserDB, error) {
|
||||
tx := r.db.Begin()
|
||||
|
||||
user.ID = 0
|
||||
if err := tx.Select("name", "email", "password", "status", "created_by", "nik", "user_type", "phone_number").Create(user).Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "creating user", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := tx.First(user, user.ID).Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "retrieving user", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userRole := user.ToUserRoleDB()
|
||||
if err := tx.Create(userRole).Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "creating user role", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "committing transaction", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (b *UserRepository) GetAllUsers(ctx context.Context, req entity.UserSearch) (entity.UserList, int, error) {
|
||||
var users []*entity.UserDB
|
||||
var total int64
|
||||
|
||||
query := b.db.Table("users").
|
||||
Select("users.id, users.email, users.name, users.status, users.created_at, users.updated_at, ur.role_id, r.role_name, ur.partner_id, b.name as partner_name").
|
||||
Joins("LEFT JOIN user_roles ur ON users.id = ur.user_id").
|
||||
Joins("LEFT JOIN roles r ON ur.role_id = r.role_id").
|
||||
Joins("LEFT JOIN partners b ON ur.partner_id = b.id").
|
||||
Where("users.deleted_at is null")
|
||||
|
||||
if req.Search != "" {
|
||||
query = query.Where("users.name ILIKE ? or users.email ILIKE ? or r.role_name ILIKE ? or b.name ILIKE ? ", "%"+req.Search+"%", "%"+req.Search+"%", "%"+req.Search+"%", "%"+req.Search+"%")
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
query = query.Where("users.name ILIKE ?", "%"+req.Name+"%")
|
||||
}
|
||||
|
||||
if req.RoleID > 0 {
|
||||
query = query.Where("ur.role_id = ? ", req.RoleID)
|
||||
}
|
||||
|
||||
if req.PartnerID > 0 {
|
||||
query = query.Where("ur.partner_id = ? ", req.PartnerID)
|
||||
}
|
||||
|
||||
// Get the total count without applying the limit and offset.
|
||||
if err := query.Model(&entity.UserDB{}).Count(&total).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when count users", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Apply pagination.
|
||||
query = query.Offset(req.Offset).Limit(req.Limit)
|
||||
|
||||
if err := query.Scan(&users).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get all users", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return users, int(total), nil
|
||||
}
|
||||
|
||||
func (b *UserRepository) GetUserByID(ctx context.Context, id int64) (*entity.UserDB, error) {
|
||||
var user *entity.UserDB
|
||||
|
||||
query := b.db.Table("users").
|
||||
Select("users.id, users.email, users.name, users.status, users.created_at, users.updated_at, ur.role_id, r.role_name, ur.partner_id, b.name as partner_name").
|
||||
Joins("LEFT JOIN user_roles ur ON users.id = ur.user_id").
|
||||
Joins("LEFT JOIN roles r ON ur.role_id = r.role_id").
|
||||
Joins("LEFT JOIN partners b ON ur.partner_id = b.id").
|
||||
Where("users.id = ?", id)
|
||||
|
||||
if err := query.Scan(&user).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get user", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (b *UserRepository) GetUserByEmail(ctx context.Context, email string) (*entity.UserDB, error) {
|
||||
var user *entity.UserDB
|
||||
|
||||
query := b.db.Table("users").
|
||||
Select("users.id, users.email, users.name, users.status, users.created_at, users.updated_at, ur.role_id, r.role_name, ur.partner_id, b.name as partner_name").
|
||||
Joins("LEFT JOIN user_roles ur ON users.id = ur.user_id").
|
||||
Joins("LEFT JOIN roles r ON ur.role_id = r.role_id").
|
||||
Joins("LEFT JOIN partners b ON ur.partner_id = b.id").
|
||||
Where("users.email = ?", email)
|
||||
|
||||
if err := query.Scan(&user).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get user", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (r *UserRepository) UpdateUser(ctx context.Context, user *entity.UserDB) (*entity.UserDB, error) {
|
||||
tx := r.db.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
if err := tx.Select("name", "email", "password", "status", "deleted_at", "updated_by").Save(user).Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "update user", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userRole := user.ToUserRoleDB()
|
||||
if err := tx.Model(userRole).Where("user_id = ?", user.ID).Updates(userRole).Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "update user role", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
logError(ctx, "committing transaction", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func logError(ctx context.Context, action string, err error) {
|
||||
logger.ContextLogger(ctx).Error("error when "+action, zap.Error(err))
|
||||
}
|
||||
Reference in New Issue
Block a user