update config

This commit is contained in:
aditya.siregar 2025-05-03 10:50:41 +07:00
parent d77f7c7981
commit f0a7c6352f
18 changed files with 438 additions and 55 deletions

View File

@ -2,6 +2,7 @@ package entity
import ( import (
"enaklo-pos-be/internal/constants" "enaklo-pos-be/internal/constants"
"golang.org/x/crypto/bcrypt"
"time" "time"
) )
@ -12,6 +13,16 @@ type MemberRegistrationRequest struct {
BirthDate time.Time `json:"birth_date"` BirthDate time.Time `json:"birth_date"`
BranchID int64 `json:"branch_id" validate:"required"` BranchID int64 `json:"branch_id" validate:"required"`
CashierID int64 `json:"cashier_id" validate:"required"` CashierID int64 `json:"cashier_id" validate:"required"`
Password string `json:"password"`
}
func (m *MemberRegistrationRequest) GetHashPassword() string {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(m.Password), bcrypt.DefaultCost)
if err != nil {
return ""
}
return string(hashedPassword)
} }
type MemberRegistrationResponse struct { type MemberRegistrationResponse struct {
@ -35,6 +46,7 @@ type MemberRegistration struct {
UpdatedAt time.Time `json:"updated_at,omitempty"` UpdatedAt time.Time `json:"updated_at,omitempty"`
BranchID int64 `json:"branch_id"` BranchID int64 `json:"branch_id"`
CashierID int64 `json:"cashier_id"` CashierID int64 `json:"cashier_id"`
Password string `json:"password"`
} }
type MemberVerificationRequest struct { type MemberVerificationRequest struct {
@ -43,6 +55,7 @@ type MemberVerificationRequest struct {
} }
type MemberVerificationResponse struct { type MemberVerificationResponse struct {
Auth *AuthenticateUser
CustomerID int64 `json:"customer_id"` CustomerID int64 `json:"customer_id"`
Name string `json:"name"` Name string `json:"name"`
Email string `json:"email"` Email string `json:"email"`

View File

@ -2,6 +2,7 @@ package auth
import ( import (
"enaklo-pos-be/internal/constants/role" "enaklo-pos-be/internal/constants/role"
"enaklo-pos-be/internal/services/member"
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
@ -15,7 +16,8 @@ import (
) )
type AuthHandler struct { type AuthHandler struct {
service services.Auth service services.Auth
memberSvc member.RegistrationService
} }
func (a *AuthHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) { func (a *AuthHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {

View File

@ -0,0 +1,168 @@
package http
import (
"enaklo-pos-be/internal/common/errors"
"enaklo-pos-be/internal/entity"
"enaklo-pos-be/internal/handlers/request"
"enaklo-pos-be/internal/handlers/response"
"enaklo-pos-be/internal/services/v2/order"
"github.com/gin-gonic/gin"
"net/http"
"strconv"
"time"
)
type CustomerOrderHandler struct {
service order.Service
}
func NewCustomerOrderHandler(service order.Service) *CustomerOrderHandler {
return &CustomerOrderHandler{
service: service,
}
}
func (h *CustomerOrderHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
route := group.Group("/order")
route.GET("/history", jwt, h.GetOrderHistory)
route.GET("/detail/:id", jwt, h.GetOrderID)
}
func (h *CustomerOrderHandler) GetOrderHistory(c *gin.Context) {
ctx := request.GetMyContext(c)
userID := ctx.RequestedBy()
limitStr := c.Query("limit")
offsetStr := c.Query("offset")
status := c.Query("status")
startDateStr := c.Query("start_date")
endDateStr := c.Query("end_date")
searchReq := entity.SearchRequest{}
if status != "" {
searchReq.Status = status
}
limit := 10
if limitStr != "" {
parsedLimit, err := strconv.Atoi(limitStr)
if err == nil && parsedLimit > 0 {
limit = parsedLimit
}
}
if limit > 20 {
limit = 20
}
searchReq.Limit = limit
offset := 0
if offsetStr != "" {
parsedOffset, err := strconv.Atoi(offsetStr)
if err == nil && parsedOffset >= 0 {
offset = parsedOffset
}
}
searchReq.Offset = offset
if startDateStr != "" {
startDate, err := time.Parse(time.RFC3339, startDateStr)
if err == nil {
searchReq.Start = startDate
}
}
if endDateStr != "" {
endDate, err := time.Parse(time.RFC3339, endDateStr)
if err == nil {
searchReq.End = endDate
}
}
orders, total, err := h.service.GetCustomerOrderHistory(ctx, userID, searchReq)
if err != nil {
response.ErrorWrapper(c, err)
return
}
responseData := []response.OrderHistoryResponse{}
for _, order := range orders {
var orderItems []response.OrderItemResponse
for _, item := range order.OrderItems {
orderItems = append(orderItems, response.OrderItemResponse{
ProductID: item.ItemID,
ProductName: item.ItemName,
Price: item.Price,
Quantity: item.Quantity,
Subtotal: item.Price * float64(item.Quantity),
})
}
responseData = append(responseData, response.OrderHistoryResponse{
ID: order.ID,
CustomerName: order.CustomerName,
Status: order.Status,
Amount: order.Amount,
Total: order.Total,
PaymentType: h.formatPayment(order.PaymentType, order.PaymentProvider),
TableNumber: order.TableNumber,
OrderType: order.OrderType,
OrderItems: orderItems,
CreatedAt: order.CreatedAt.Format("2006-01-02T15:04:05Z"),
Tax: order.Tax,
RestaurantName: "Bakso 343",
})
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: responseData,
PagingMeta: &response.PagingMeta{
Page: offset + 1,
Total: int64(total),
Limit: limit,
},
})
}
func (h *CustomerOrderHandler) formatPayment(payment, provider string) string {
if payment == "CASH" {
return payment
}
return payment + " " + provider
}
func (h *CustomerOrderHandler) GetOrderID(c *gin.Context) {
ctx := request.GetMyContext(c)
var req GetOrderParam
if err := c.ShouldBindQuery(&req); err != nil {
response.ErrorWrapper(c, errors.ErrorBadRequest)
return
}
id := c.Param("id")
orderID, err := strconv.ParseInt(id, 10, 64)
if err != nil {
response.ErrorWrapper(c, errors.ErrorBadRequest)
return
}
order, err := h.service.GetOrderByOrderAndCustomerID(ctx, ctx.RequestedBy(), orderID)
if err != nil {
response.ErrorWrapper(c, err)
return
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: MapToOrderCreateResponse(order),
})
}

View File

@ -1,9 +1,11 @@
package customerauth package customerauth
import ( import (
"enaklo-pos-be/internal/entity"
auth2 "enaklo-pos-be/internal/handlers/request" auth2 "enaklo-pos-be/internal/handlers/request"
"enaklo-pos-be/internal/services/member"
"enaklo-pos-be/internal/services/v2/auth" "enaklo-pos-be/internal/services/v2/auth"
"enaklo-pos-be/internal/services/v2/customer" "github.com/go-playground/validator/v10"
"net/http" "net/http"
"strings" "strings"
@ -11,23 +13,24 @@ import (
"enaklo-pos-be/internal/common/errors" "enaklo-pos-be/internal/common/errors"
"enaklo-pos-be/internal/handlers/response" "enaklo-pos-be/internal/handlers/response"
"enaklo-pos-be/internal/services"
) )
type AuthHandler struct { type AuthHandler struct {
service auth.Service service auth.Service
userService services.User memberSvc member.RegistrationService
customerSvc customer.Service
} }
func (a *AuthHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) { func (a *AuthHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
authRoute := group.Group("/auth") authRoute := group.Group("/auth")
authRoute.POST("/login", a.AuthLogin) authRoute.POST("/login", a.AuthLogin)
authRoute.POST("/register", a.Registration)
authRoute.POST("/verify-otp", a.VerifyOTP)
} }
func NewAuthHandler(service auth.Service) *AuthHandler { func NewAuthHandler(service auth.Service, memberSvc member.RegistrationService) *AuthHandler {
return &AuthHandler{ return &AuthHandler{
service: service, service: service,
memberSvc: memberSvc,
} }
} }
@ -60,3 +63,75 @@ func (h *AuthHandler) AuthLogin(c *gin.Context) {
Data: resp, Data: resp,
}) })
} }
func (h *AuthHandler) Registration(c *gin.Context) {
ctx := auth2.GetMyContext(c)
userID := ctx.RequestedBy()
var req auth2.InitiateRegistrationRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.ErrorWrapper(c, errors.ErrorBadRequest)
return
}
validate := validator.New()
if err := validate.Struct(req); err != nil {
response.ErrorWrapper(c, err)
return
}
birthDate, err := req.GetBirthdate()
if err != nil {
response.ErrorWrapper(c, err)
return
}
memberReq := &entity.MemberRegistrationRequest{
Name: req.Name,
Email: req.Email,
Phone: req.Phone,
BirthDate: birthDate,
CashierID: userID,
Password: req.Password,
}
result, err := h.memberSvc.InitiateRegistration(ctx, memberReq)
if err != nil {
response.ErrorWrapper(c, err)
return
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: response.MapToMemberRegistrationResponse(result),
})
}
func (h *AuthHandler) VerifyOTP(c *gin.Context) {
ctx := auth2.GetMyContext(c)
var req auth2.VerifyOTPRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.ErrorWrapper(c, errors.ErrorBadRequest)
return
}
validate := validator.New()
if err := validate.Struct(req); err != nil {
response.ErrorWrapper(c, err)
return
}
result, err := h.memberSvc.VerifyOTP(ctx, req.Token, req.OTP)
if err != nil {
response.ErrorWrapper(c, err)
return
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: response.MapToMemberVerificationResponse(result.Auth),
})
}

View File

@ -99,7 +99,7 @@ func (h *MemberHandler) VerifyOTP(c *gin.Context) {
c.JSON(http.StatusOK, response.BaseResponse{ c.JSON(http.StatusOK, response.BaseResponse{
Success: true, Success: true,
Status: http.StatusOK, Status: http.StatusOK,
Data: response.MapToMemberVerificationResponse(result), Data: response.MapToMemberVerificationResponse(result.Auth),
}) })
} }

View File

@ -5,10 +5,12 @@ import (
) )
type InitiateRegistrationRequest struct { type InitiateRegistrationRequest struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"` Email string `json:"email" validate:"required,email"`
Phone string `json:"phone" validate:"required"` Phone string `json:"phone" validate:"required"`
BirthDate string `json:"birth_date" validate:"required"` BirthDate string `json:"birthDate" validate:"required"`
Password string `json:"password" validate:"required"`
ConfirmPassword string `json:"confirmPassword" validate:"required"`
} }
func (i *InitiateRegistrationRequest) GetBirthdate() (time.Time, error) { func (i *InitiateRegistrationRequest) GetBirthdate() (time.Time, error) {

View File

@ -61,15 +61,15 @@ func MapToMemberRegistrationResponse(entity *entity.MemberRegistrationResponse)
} }
} }
func MapToMemberVerificationResponse(entity *entity.MemberVerificationResponse) MemberVerificationResponse { func MapToMemberVerificationResponse(user *entity.AuthenticateUser) LoginResponseCustoemr {
return MemberVerificationResponse{ resp := LoginResponseCustoemr{
CustomerID: entity.CustomerID, ID: user.ID,
Name: entity.Name, Token: user.Token,
Email: entity.Email, Name: user.Name,
Phone: entity.Phone, ResetPassword: user.ResetPassword,
Points: entity.Points,
Status: entity.Status,
} }
return resp
} }
func MapToMemberRegistrationStatus(entity *entity.MemberRegistrationStatus) MemberRegistrationStatus { func MapToMemberRegistrationStatus(entity *entity.MemberRegistrationStatus) MemberRegistrationStatus {

View File

@ -189,15 +189,16 @@ type OrderDetailItem struct {
} }
type OrderHistoryResponse struct { type OrderHistoryResponse struct {
ID int64 `json:"id"` ID int64 `json:"id"`
CustomerName string `json:"customer_name"` CustomerName string `json:"customer_name"`
Status string `json:"status"` Status string `json:"status"`
Amount float64 `json:"amount"` Amount float64 `json:"amount"`
Total float64 `json:"total"` Total float64 `json:"total"`
PaymentType string `json:"payment_type"` PaymentType string `json:"payment_type"`
TableNumber string `json:"table_number"` TableNumber string `json:"table_number"`
OrderType string `json:"order_type"` OrderType string `json:"order_type"`
OrderItems []OrderItemResponse `json:"order_items"` OrderItems []OrderItemResponse `json:"order_items"`
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
Tax float64 `json:"tax"` Tax float64 `json:"tax"`
RestaurantName string `json:"restaurant_name"`
} }

View File

@ -116,6 +116,7 @@ func (r *memberRepository) toRegistrationDBModel(registration *entity.MemberRegi
UpdatedAt: registration.UpdatedAt, UpdatedAt: registration.UpdatedAt,
BranchID: registration.BranchID, BranchID: registration.BranchID,
CashierID: registration.CashierID, CashierID: registration.CashierID,
Password: registration.Password,
} }
} }

View File

@ -18,6 +18,7 @@ type MemberRegistrationDB struct {
UpdatedAt time.Time `gorm:"column:updated_at"` UpdatedAt time.Time `gorm:"column:updated_at"`
BranchID int64 `gorm:"column:branch_id"` BranchID int64 `gorm:"column:branch_id"`
CashierID int64 `gorm:"column:cashier_id"` CashierID int64 `gorm:"column:cashier_id"`
Password string `gorm:"column:password"`
} }
func (MemberRegistrationDB) TableName() string { func (MemberRegistrationDB) TableName() string {

View File

@ -38,6 +38,8 @@ type OrderRepository interface {
req entity.PopularProductsRequest, req entity.PopularProductsRequest,
) ([]entity.PopularProductItem, error) ) ([]entity.PopularProductItem, error)
FindByIDAndPartnerID(ctx mycontext.Context, id int64, partnerID int64) (*entity.Order, error) 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)
} }
type orderRepository struct { type orderRepository struct {
@ -299,6 +301,10 @@ func (r *orderRepository) toDomainOrderItemModel(dbModel *models.OrderItemDB) *e
CreatedBy: dbModel.CreatedBy, CreatedBy: dbModel.CreatedBy,
CreatedAt: dbModel.CreatedAt, CreatedAt: dbModel.CreatedAt,
ItemName: dbModel.ItemName, ItemName: dbModel.ItemName,
Product: &entity.Product{
ID: dbModel.ItemID,
Name: dbModel.ItemName,
},
} }
} }
@ -416,6 +422,60 @@ func (r *orderRepository) GetOrderHistoryByPartnerID(ctx mycontext.Context, part
return orders, totalCount, nil return orders, totalCount, nil
} }
func (r *orderRepository) GetOrderHistoryByUserID(ctx mycontext.Context, userID int64, req entity.SearchRequest) ([]*entity.Order, int64, error) {
var ordersDB []models.OrderDB
var totalCount int64
baseQuery := r.db.Model(&models.OrderDB{}).Where("customer_id = ?", userID)
if req.Status != "" {
baseQuery = baseQuery.Where("status = ?", req.Status)
}
if !req.Start.IsZero() {
baseQuery = baseQuery.Where("created_at >= ?", req.Start)
}
if !req.End.IsZero() {
baseQuery = baseQuery.Where("created_at <= ?", req.End)
}
if err := baseQuery.Count(&totalCount).Error; err != nil {
return nil, 0, errors.Wrap(err, "failed to count total orders")
}
query := baseQuery.Session(&gorm.Session{})
query = query.Order("created_at DESC")
if req.Limit > 0 {
query = query.Limit(req.Limit)
}
if req.Offset > 0 {
query = query.Offset(req.Offset)
}
if err := query.Preload("OrderItems").Find(&ordersDB).Error; err != nil {
return nil, 0, errors.Wrap(err, "failed to find order history by partner ID")
}
orders := make([]*entity.Order, 0, len(ordersDB))
for _, orderDB := range ordersDB {
order := r.toDomainOrderModel(&orderDB)
order.OrderItems = make([]entity.OrderItem, 0, len(orderDB.OrderItems))
for _, itemDB := range orderDB.OrderItems {
item := r.toDomainOrderItemModel(&itemDB)
order.OrderItems = append(order.OrderItems, *item)
}
orders = append(orders, order)
}
return orders, totalCount, nil
}
func (r *orderRepository) CreateOrUpdate(ctx mycontext.Context, order *entity.Order) (*entity.Order, error) { func (r *orderRepository) CreateOrUpdate(ctx mycontext.Context, order *entity.Order) (*entity.Order, error) {
isUpdate := order.ID != 0 isUpdate := order.ID != 0
@ -856,3 +916,23 @@ func (r *orderRepository) FindByIDAndPartnerID(ctx mycontext.Context, id int64,
return order, nil return order, nil
} }
func (r *orderRepository) FindByIDAndCustomerID(ctx mycontext.Context, id int64, customerID int64) (*entity.Order, error) {
var orderDB models.OrderDB
if err := r.db.Preload("OrderItems").Where("id = ? AND customer_id = ?", id, customerID).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
}

View File

@ -19,8 +19,9 @@ func RegisterCustomerRoutes(app *app.Server, serviceManager *services.ServiceMan
serverRoutes := []HTTPHandlerRoutes{ serverRoutes := []HTTPHandlerRoutes{
discovery.NewHandler(serviceManager.DiscoverService), discovery.NewHandler(serviceManager.DiscoverService),
customerauth.NewAuthHandler(serviceManager.AuthV2Svc), customerauth.NewAuthHandler(serviceManager.AuthV2Svc, serviceManager.MemberRegistrationSvc),
http.NewMenuHandler(serviceManager.ProductV2Svc, serviceManager.InProgressSvc), http.NewMenuHandler(serviceManager.ProductV2Svc, serviceManager.InProgressSvc),
http.NewCustomerOrderHandler(serviceManager.OrderV2Svc),
} }
for _, handler := range serverRoutes { for _, handler := range serverRoutes {

View File

@ -15,10 +15,15 @@ type RegistrationService interface {
ResendOTP(ctx mycontext.Context, token string) (*entity.ResendOTPResponse, error) ResendOTP(ctx mycontext.Context, token string) (*entity.ResendOTPResponse, error)
} }
type CryptoSvc interface {
GenerateJWTCustomer(user *entity.Customer) (string, error)
}
type memberSvc struct { type memberSvc struct {
repo Repository repo Repository
notification NotificationService notification NotificationService
customerSvc CustomerService customerSvc CustomerService
crypt CryptoSvc
} }
type Repository interface { type Repository interface {
@ -42,10 +47,12 @@ func NewMemberRegistrationService(
repo Repository, repo Repository,
notification NotificationService, notification NotificationService,
customerSvc CustomerService, customerSvc CustomerService,
crypt CryptoSvc,
) RegistrationService { ) RegistrationService {
return &memberSvc{ return &memberSvc{
repo: repo, repo: repo,
notification: notification, notification: notification,
customerSvc: customerSvc, customerSvc: customerSvc,
crypt: crypt,
} }
} }

View File

@ -38,11 +38,12 @@ func (s *memberSvc) InitiateRegistration(
BirthDate: request.BirthDate, BirthDate: request.BirthDate,
OTP: otp, OTP: otp,
Status: constants.RegistrationPending, Status: constants.RegistrationPending,
ExpiresAt: constants.TimeNow().Add(10 * time.Minute), // OTP expires in 10 minutes ExpiresAt: constants.TimeNow().Add(10 * time.Minute),
CreatedAt: constants.TimeNow(), CreatedAt: constants.TimeNow(),
UpdatedAt: constants.TimeNow(), UpdatedAt: constants.TimeNow(),
BranchID: request.BranchID, BranchID: request.BranchID,
CashierID: request.CashierID, CashierID: request.CashierID,
Password: request.GetHashPassword(),
} }
savedRegistration, err := s.repo.CreateRegistration(ctx, registration) savedRegistration, err := s.repo.CreateRegistration(ctx, registration)
@ -125,7 +126,14 @@ func (s *memberSvc) VerifyOTP(
logger.ContextLogger(ctx).Warn("failed to send welcome email", zap.Error(err)) logger.ContextLogger(ctx).Warn("failed to send welcome email", zap.Error(err))
} }
signedToken, err := s.crypt.GenerateJWTCustomer(customer)
if err != nil {
return nil, err
}
return &entity.MemberVerificationResponse{ return &entity.MemberVerificationResponse{
Auth: customer.ToUserAuthenticate(signedToken),
CustomerID: customer.ID, CustomerID: customer.ID,
Name: customer.Name, Name: customer.Name,
Email: customer.Email, Email: customer.Email,
@ -200,23 +208,23 @@ func (s *memberSvc) sendRegistrationOTP(
ctx mycontext.Context, ctx mycontext.Context,
registration *entity.MemberRegistration, registration *entity.MemberRegistration,
) error { ) error {
emailData := map[string]interface{}{ //emailData := map[string]interface{}{
"UserName": registration.Name, // "UserName": registration.Name,
"OTPCode": registration.OTP, // "OTPCode": registration.OTP,
} //}
err := s.notification.SendEmailTransactional(ctx, entity.SendEmailNotificationParam{ //err := s.notification.SendEmailTransactional(ctx, entity.SendEmailNotificationParam{
Sender: "noreply@enaklo.co.id", // Sender: "noreply@enaklo.co.id",
Recipient: registration.Email, // Recipient: registration.Email,
Subject: "Enaklo - Registration Verification Code", // Subject: "Enaklo - Registration Verification Code",
TemplateName: "member_registration_otp", // TemplateName: "member_registration_otp",
TemplatePath: "templates/member_registration_otp.html", // TemplatePath: "templates/member_registration_otp.html",
Data: emailData, // Data: emailData,
}) //})
//
if err != nil { //if err != nil {
return err // return err
} //}
//if registration.Phone != "" { //if registration.Phone != "" {
// smsMessage := fmt.Sprintf("Your Enaklo registration code is: %s. Please provide this code to our staff to complete your registration.", registration.OTP) // smsMessage := fmt.Sprintf("Your Enaklo registration code is: %s. Please provide this code to our staff to complete your registration.", registration.OTP)

View File

@ -76,7 +76,7 @@ func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl)
Balance: balance.NewBalanceService(repo.Wallet, repo.Trx, repo.Crypto, &cfg.Withdraw, repo.Transaction), Balance: balance.NewBalanceService(repo.Wallet, repo.Trx, repo.Crypto, &cfg.Withdraw, repo.Transaction),
DiscoverService: discovery.NewDiscoveryService(repo.Site, cfg.Discovery, repo.Product), DiscoverService: discovery.NewDiscoveryService(repo.Site, cfg.Discovery, repo.Product),
OrderV2Svc: orderSvc.New(repo.OrderRepo, productSvcV2, custSvcV2, repo.TransactionRepo, repo.Crypto, &cfg.Order, repo.EmailService, partnerSettings), OrderV2Svc: orderSvc.New(repo.OrderRepo, productSvcV2, custSvcV2, repo.TransactionRepo, repo.Crypto, &cfg.Order, repo.EmailService, partnerSettings),
MemberRegistrationSvc: member.NewMemberRegistrationService(repo.MemberRepository, repo.EmailService, custSvcV2), MemberRegistrationSvc: member.NewMemberRegistrationService(repo.MemberRepository, repo.EmailService, custSvcV2, repo.Crypto),
CustomerV2Svc: custSvcV2, CustomerV2Svc: custSvcV2,
InProgressSvc: inprogressOrder, InProgressSvc: inprogressOrder,
ProductV2Svc: productSvcV2, ProductV2Svc: productSvcV2,

View File

@ -94,7 +94,7 @@ func (s *customerSvc) ResolveCustomer(ctx mycontext.Context, req *entity.Custome
return 0, errors.New("customer name is required to create a new customer") return 0, errors.New("customer name is required to create a new customer")
} }
lastSeq, err := s.repo.FindSequence(ctx, *ctx.GetPartnerID()) lastSeq, err := s.repo.FindSequence(ctx, 1)
if err != nil { if err != nil {
return 0, errors.New("failed to resolve customer sequence") return 0, errors.New("failed to resolve customer sequence")
} }
@ -106,7 +106,7 @@ func (s *customerSvc) ResolveCustomer(ctx mycontext.Context, req *entity.Custome
Points: 0, Points: 0,
CreatedAt: constants.TimeNow(), CreatedAt: constants.TimeNow(),
UpdatedAt: constants.TimeNow(), UpdatedAt: constants.TimeNow(),
CustomerID: utils.GenerateMemberID(ctx, *ctx.GetPartnerID(), lastSeq), CustomerID: utils.GenerateMemberID(ctx, 1, lastSeq),
BirthDate: req.BirthDate, BirthDate: req.BirthDate,
} }
@ -225,7 +225,7 @@ func (s *customerSvc) CustomerCheck(ctx mycontext.Context, req *entity.CustomerR
return &entity.CustomerCheckResponse{ return &entity.CustomerCheckResponse{
Exists: true, Exists: true,
Customer: customer, Customer: customer,
Message: "Customer already exists with this phone number", Message: "Nomor telepon sudah terdaftar. Silakan gunakan nomor lain atau login.",
}, nil }, nil
} }
} }
@ -244,7 +244,7 @@ func (s *customerSvc) CustomerCheck(ctx mycontext.Context, req *entity.CustomerR
return &entity.CustomerCheckResponse{ return &entity.CustomerCheckResponse{
Exists: true, Exists: true,
Customer: customer, Customer: customer,
Message: "Customer already exists with this email", Message: "Email sudah terdaftar. Silakan gunakan email lain atau login.",
}, nil }, nil
} }
} }

View File

@ -30,6 +30,9 @@ type Repository interface {
ctx mycontext.Context, ctx mycontext.Context,
req entity.PopularProductsRequest, req entity.PopularProductsRequest,
) ([]entity.PopularProductItem, error) ) ([]entity.PopularProductItem, error)
GetOrderHistoryByUserID(ctx mycontext.Context, userID int64, req entity.SearchRequest) ([]*entity.Order, int64, error)
FindByIDAndPartnerID(ctx mycontext.Context, id int64, partnerID int64) (*entity.Order, error)
FindByIDAndCustomerID(ctx mycontext.Context, id int64, customerID int64) (*entity.Order, error)
} }
type ProductService interface { type ProductService interface {
@ -96,6 +99,8 @@ type Service interface {
limit int, limit int,
sortBy string, sortBy string,
) ([]entity.PopularProductItem, error) ) ([]entity.PopularProductItem, error)
GetCustomerOrderHistory(ctx mycontext.Context, userID int64, request entity.SearchRequest) ([]*entity.Order, int64, error)
GetOrderByOrderAndCustomerID(ctx mycontext.Context, customerID int64, orderID int64) (*entity.Order, error)
} }
type Config interface { type Config interface {

View File

@ -1,10 +1,29 @@
package order package order
import ( import (
"enaklo-pos-be/internal/common/logger"
"enaklo-pos-be/internal/common/mycontext" "enaklo-pos-be/internal/common/mycontext"
"enaklo-pos-be/internal/entity" "enaklo-pos-be/internal/entity"
"github.com/pkg/errors"
"go.uber.org/zap"
) )
func (s *orderSvc) GetOrderHistory(ctx mycontext.Context, partnerID int64, request entity.SearchRequest) ([]*entity.Order, int64, error) { func (s *orderSvc) GetOrderHistory(ctx mycontext.Context, partnerID int64, request entity.SearchRequest) ([]*entity.Order, int64, error) {
return s.repo.GetOrderHistoryByPartnerID(ctx, partnerID, request) return s.repo.GetOrderHistoryByPartnerID(ctx, partnerID, request)
} }
func (s *orderSvc) GetCustomerOrderHistory(ctx mycontext.Context, userID int64, request entity.SearchRequest) ([]*entity.Order, int64, error) {
return s.repo.GetOrderHistoryByUserID(ctx, userID, request)
}
func (s *orderSvc) GetOrderByOrderAndCustomerID(ctx mycontext.Context, customerID int64, orderID int64) (*entity.Order, error) {
orders, err := s.repo.FindByIDAndCustomerID(ctx, orderID, customerID)
if err != nil {
logger.ContextLogger(ctx).Error("failed to get in-progress orders by partner ID",
zap.Error(err),
zap.Int64("customerID", customerID))
return nil, errors.Wrap(err, "failed to get order")
}
return orders, nil
}