diff --git a/internal/entity/member.go b/internal/entity/member.go index ca1113b..af8d68b 100644 --- a/internal/entity/member.go +++ b/internal/entity/member.go @@ -2,6 +2,7 @@ package entity import ( "enaklo-pos-be/internal/constants" + "golang.org/x/crypto/bcrypt" "time" ) @@ -12,6 +13,16 @@ type MemberRegistrationRequest struct { BirthDate time.Time `json:"birth_date"` BranchID int64 `json:"branch_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 { @@ -35,6 +46,7 @@ type MemberRegistration struct { UpdatedAt time.Time `json:"updated_at,omitempty"` BranchID int64 `json:"branch_id"` CashierID int64 `json:"cashier_id"` + Password string `json:"password"` } type MemberVerificationRequest struct { @@ -43,6 +55,7 @@ type MemberVerificationRequest struct { } type MemberVerificationResponse struct { + Auth *AuthenticateUser CustomerID int64 `json:"customer_id"` Name string `json:"name"` Email string `json:"email"` diff --git a/internal/handlers/http/auth/auth.go b/internal/handlers/http/auth/auth.go index 515cc51..18d22b7 100644 --- a/internal/handlers/http/auth/auth.go +++ b/internal/handlers/http/auth/auth.go @@ -2,6 +2,7 @@ package auth import ( "enaklo-pos-be/internal/constants/role" + "enaklo-pos-be/internal/services/member" "fmt" "net/http" "strings" @@ -15,7 +16,8 @@ import ( ) type AuthHandler struct { - service services.Auth + service services.Auth + memberSvc member.RegistrationService } func (a *AuthHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) { diff --git a/internal/handlers/http/customer_order.go b/internal/handlers/http/customer_order.go new file mode 100644 index 0000000..23b418c --- /dev/null +++ b/internal/handlers/http/customer_order.go @@ -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), + }) +} diff --git a/internal/handlers/http/customerauth/auth.go b/internal/handlers/http/customerauth/auth.go index 5f6a736..5eddac7 100644 --- a/internal/handlers/http/customerauth/auth.go +++ b/internal/handlers/http/customerauth/auth.go @@ -1,9 +1,11 @@ package customerauth import ( + "enaklo-pos-be/internal/entity" 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/customer" + "github.com/go-playground/validator/v10" "net/http" "strings" @@ -11,23 +13,24 @@ import ( "enaklo-pos-be/internal/common/errors" "enaklo-pos-be/internal/handlers/response" - "enaklo-pos-be/internal/services" ) type AuthHandler struct { - service auth.Service - userService services.User - customerSvc customer.Service + service auth.Service + memberSvc member.RegistrationService } func (a *AuthHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) { authRoute := group.Group("/auth") 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{ - service: service, + service: service, + memberSvc: memberSvc, } } @@ -60,3 +63,75 @@ func (h *AuthHandler) AuthLogin(c *gin.Context) { 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), + }) +} diff --git a/internal/handlers/http/member.go b/internal/handlers/http/member.go index c309dbb..3e28477 100644 --- a/internal/handlers/http/member.go +++ b/internal/handlers/http/member.go @@ -99,7 +99,7 @@ func (h *MemberHandler) VerifyOTP(c *gin.Context) { c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, - Data: response.MapToMemberVerificationResponse(result), + Data: response.MapToMemberVerificationResponse(result.Auth), }) } diff --git a/internal/handlers/request/member.go b/internal/handlers/request/member.go index 9eca421..ee3198e 100644 --- a/internal/handlers/request/member.go +++ b/internal/handlers/request/member.go @@ -5,10 +5,12 @@ import ( ) type InitiateRegistrationRequest struct { - Name string `json:"name" validate:"required"` - Email string `json:"email" validate:"required,email"` - Phone string `json:"phone" validate:"required"` - BirthDate string `json:"birth_date" validate:"required"` + Name string `json:"name" validate:"required"` + Email string `json:"email" validate:"required,email"` + Phone string `json:"phone" 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) { diff --git a/internal/handlers/response/member.go b/internal/handlers/response/member.go index 9053d46..c0f2b55 100644 --- a/internal/handlers/response/member.go +++ b/internal/handlers/response/member.go @@ -61,15 +61,15 @@ func MapToMemberRegistrationResponse(entity *entity.MemberRegistrationResponse) } } -func MapToMemberVerificationResponse(entity *entity.MemberVerificationResponse) MemberVerificationResponse { - return MemberVerificationResponse{ - CustomerID: entity.CustomerID, - Name: entity.Name, - Email: entity.Email, - Phone: entity.Phone, - Points: entity.Points, - Status: entity.Status, +func MapToMemberVerificationResponse(user *entity.AuthenticateUser) LoginResponseCustoemr { + resp := LoginResponseCustoemr{ + ID: user.ID, + Token: user.Token, + Name: user.Name, + ResetPassword: user.ResetPassword, } + + return resp } func MapToMemberRegistrationStatus(entity *entity.MemberRegistrationStatus) MemberRegistrationStatus { diff --git a/internal/handlers/response/order.go b/internal/handlers/response/order.go index baa04ad..a783569 100644 --- a/internal/handlers/response/order.go +++ b/internal/handlers/response/order.go @@ -189,15 +189,16 @@ type OrderDetailItem struct { } type OrderHistoryResponse struct { - ID int64 `json:"id"` - CustomerName string `json:"customer_name"` - Status string `json:"status"` - Amount float64 `json:"amount"` - Total float64 `json:"total"` - PaymentType string `json:"payment_type"` - TableNumber string `json:"table_number"` - OrderType string `json:"order_type"` - OrderItems []OrderItemResponse `json:"order_items"` - CreatedAt string `json:"created_at"` - Tax float64 `json:"tax"` + ID int64 `json:"id"` + CustomerName string `json:"customer_name"` + Status string `json:"status"` + Amount float64 `json:"amount"` + Total float64 `json:"total"` + PaymentType string `json:"payment_type"` + TableNumber string `json:"table_number"` + OrderType string `json:"order_type"` + OrderItems []OrderItemResponse `json:"order_items"` + CreatedAt string `json:"created_at"` + Tax float64 `json:"tax"` + RestaurantName string `json:"restaurant_name"` } diff --git a/internal/repository/member_repo.go b/internal/repository/member_repo.go index c0de2c8..e247d51 100644 --- a/internal/repository/member_repo.go +++ b/internal/repository/member_repo.go @@ -116,6 +116,7 @@ func (r *memberRepository) toRegistrationDBModel(registration *entity.MemberRegi UpdatedAt: registration.UpdatedAt, BranchID: registration.BranchID, CashierID: registration.CashierID, + Password: registration.Password, } } diff --git a/internal/repository/models/member.go b/internal/repository/models/member.go index 053df3c..82d0d1e 100644 --- a/internal/repository/models/member.go +++ b/internal/repository/models/member.go @@ -18,6 +18,7 @@ type MemberRegistrationDB struct { UpdatedAt time.Time `gorm:"column:updated_at"` BranchID int64 `gorm:"column:branch_id"` CashierID int64 `gorm:"column:cashier_id"` + Password string `gorm:"column:password"` } func (MemberRegistrationDB) TableName() string { diff --git a/internal/repository/orde_repo.go b/internal/repository/orde_repo.go index fde50e3..09c7568 100644 --- a/internal/repository/orde_repo.go +++ b/internal/repository/orde_repo.go @@ -38,6 +38,8 @@ type OrderRepository interface { req entity.PopularProductsRequest, ) ([]entity.PopularProductItem, 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 { @@ -299,6 +301,10 @@ func (r *orderRepository) toDomainOrderItemModel(dbModel *models.OrderItemDB) *e CreatedBy: dbModel.CreatedBy, CreatedAt: dbModel.CreatedAt, 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 } +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) { isUpdate := order.ID != 0 @@ -856,3 +916,23 @@ func (r *orderRepository) FindByIDAndPartnerID(ctx mycontext.Context, id int64, 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 +} diff --git a/internal/routes/customer_routes.go b/internal/routes/customer_routes.go index 155214a..35efa88 100644 --- a/internal/routes/customer_routes.go +++ b/internal/routes/customer_routes.go @@ -19,8 +19,9 @@ func RegisterCustomerRoutes(app *app.Server, serviceManager *services.ServiceMan serverRoutes := []HTTPHandlerRoutes{ discovery.NewHandler(serviceManager.DiscoverService), - customerauth.NewAuthHandler(serviceManager.AuthV2Svc), + customerauth.NewAuthHandler(serviceManager.AuthV2Svc, serviceManager.MemberRegistrationSvc), http.NewMenuHandler(serviceManager.ProductV2Svc, serviceManager.InProgressSvc), + http.NewCustomerOrderHandler(serviceManager.OrderV2Svc), } for _, handler := range serverRoutes { diff --git a/internal/services/member/member.go b/internal/services/member/member.go index 375bda2..c43ffe9 100644 --- a/internal/services/member/member.go +++ b/internal/services/member/member.go @@ -15,10 +15,15 @@ type RegistrationService interface { ResendOTP(ctx mycontext.Context, token string) (*entity.ResendOTPResponse, error) } +type CryptoSvc interface { + GenerateJWTCustomer(user *entity.Customer) (string, error) +} + type memberSvc struct { repo Repository notification NotificationService customerSvc CustomerService + crypt CryptoSvc } type Repository interface { @@ -42,10 +47,12 @@ func NewMemberRegistrationService( repo Repository, notification NotificationService, customerSvc CustomerService, + crypt CryptoSvc, ) RegistrationService { return &memberSvc{ repo: repo, notification: notification, customerSvc: customerSvc, + crypt: crypt, } } diff --git a/internal/services/member/member_registration.go b/internal/services/member/member_registration.go index 6f671e0..96197d2 100644 --- a/internal/services/member/member_registration.go +++ b/internal/services/member/member_registration.go @@ -38,11 +38,12 @@ func (s *memberSvc) InitiateRegistration( BirthDate: request.BirthDate, OTP: otp, 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(), UpdatedAt: constants.TimeNow(), BranchID: request.BranchID, CashierID: request.CashierID, + Password: request.GetHashPassword(), } 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)) } + signedToken, err := s.crypt.GenerateJWTCustomer(customer) + + if err != nil { + return nil, err + } + return &entity.MemberVerificationResponse{ + Auth: customer.ToUserAuthenticate(signedToken), CustomerID: customer.ID, Name: customer.Name, Email: customer.Email, @@ -200,23 +208,23 @@ func (s *memberSvc) sendRegistrationOTP( ctx mycontext.Context, registration *entity.MemberRegistration, ) error { - emailData := map[string]interface{}{ - "UserName": registration.Name, - "OTPCode": registration.OTP, - } + //emailData := map[string]interface{}{ + // "UserName": registration.Name, + // "OTPCode": registration.OTP, + //} - err := s.notification.SendEmailTransactional(ctx, entity.SendEmailNotificationParam{ - Sender: "noreply@enaklo.co.id", - Recipient: registration.Email, - Subject: "Enaklo - Registration Verification Code", - TemplateName: "member_registration_otp", - TemplatePath: "templates/member_registration_otp.html", - Data: emailData, - }) - - if err != nil { - return err - } + //err := s.notification.SendEmailTransactional(ctx, entity.SendEmailNotificationParam{ + // Sender: "noreply@enaklo.co.id", + // Recipient: registration.Email, + // Subject: "Enaklo - Registration Verification Code", + // TemplateName: "member_registration_otp", + // TemplatePath: "templates/member_registration_otp.html", + // Data: emailData, + //}) + // + //if err != nil { + // return err + //} //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) diff --git a/internal/services/service.go b/internal/services/service.go index c4e79c4..b97b7b6 100644 --- a/internal/services/service.go +++ b/internal/services/service.go @@ -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), 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), - MemberRegistrationSvc: member.NewMemberRegistrationService(repo.MemberRepository, repo.EmailService, custSvcV2), + MemberRegistrationSvc: member.NewMemberRegistrationService(repo.MemberRepository, repo.EmailService, custSvcV2, repo.Crypto), CustomerV2Svc: custSvcV2, InProgressSvc: inprogressOrder, ProductV2Svc: productSvcV2, diff --git a/internal/services/v2/customer/customer.go b/internal/services/v2/customer/customer.go index e7de76e..5afc24b 100644 --- a/internal/services/v2/customer/customer.go +++ b/internal/services/v2/customer/customer.go @@ -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") } - lastSeq, err := s.repo.FindSequence(ctx, *ctx.GetPartnerID()) + lastSeq, err := s.repo.FindSequence(ctx, 1) if err != nil { 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, CreatedAt: constants.TimeNow(), UpdatedAt: constants.TimeNow(), - CustomerID: utils.GenerateMemberID(ctx, *ctx.GetPartnerID(), lastSeq), + CustomerID: utils.GenerateMemberID(ctx, 1, lastSeq), BirthDate: req.BirthDate, } @@ -225,7 +225,7 @@ func (s *customerSvc) CustomerCheck(ctx mycontext.Context, req *entity.CustomerR return &entity.CustomerCheckResponse{ Exists: true, Customer: customer, - Message: "Customer already exists with this phone number", + Message: "Nomor telepon sudah terdaftar. Silakan gunakan nomor lain atau login.", }, nil } } @@ -244,7 +244,7 @@ func (s *customerSvc) CustomerCheck(ctx mycontext.Context, req *entity.CustomerR return &entity.CustomerCheckResponse{ Exists: true, Customer: customer, - Message: "Customer already exists with this email", + Message: "Email sudah terdaftar. Silakan gunakan email lain atau login.", }, nil } } diff --git a/internal/services/v2/order/order.go b/internal/services/v2/order/order.go index e568003..ac087da 100644 --- a/internal/services/v2/order/order.go +++ b/internal/services/v2/order/order.go @@ -30,6 +30,9 @@ type Repository interface { ctx mycontext.Context, req entity.PopularProductsRequest, ) ([]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 { @@ -96,6 +99,8 @@ type Service interface { limit int, sortBy string, ) ([]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 { diff --git a/internal/services/v2/order/order_history.go b/internal/services/v2/order/order_history.go index d6b1a55..fa8043e 100644 --- a/internal/services/v2/order/order_history.go +++ b/internal/services/v2/order/order_history.go @@ -1,10 +1,29 @@ package order import ( + "enaklo-pos-be/internal/common/logger" "enaklo-pos-be/internal/common/mycontext" "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) { 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 +}