update
This commit is contained in:
@@ -2,8 +2,8 @@ package customerauth
|
||||
|
||||
import (
|
||||
auth2 "enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/services/v2/auth"
|
||||
"enaklo-pos-be/internal/services/v2/customer"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
service services.Auth
|
||||
service auth.Service
|
||||
userService services.User
|
||||
customerSvc customer.Service
|
||||
}
|
||||
@@ -23,49 +23,29 @@ type AuthHandler struct {
|
||||
func (a *AuthHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
authRoute := group.Group("/auth")
|
||||
authRoute.POST("/login", a.AuthLogin)
|
||||
authRoute.POST("/forgot-password", a.ForgotPassword)
|
||||
authRoute.POST("/reset-password", jwt, a.ResetPassword)
|
||||
authRoute.POST("/register", a.Register)
|
||||
authRoute.POST("/verify", a.VerifyRegistration)
|
||||
}
|
||||
|
||||
func NewAuthHandler(service services.Auth, userService services.User, customerSvc customer.Service) *AuthHandler {
|
||||
func NewAuthHandler(service auth.Service) *AuthHandler {
|
||||
return &AuthHandler{
|
||||
service: service,
|
||||
userService: userService,
|
||||
customerSvc: customerSvc,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// AuthLogin handles the authentication process for user login.
|
||||
// @Summary User login
|
||||
// @Description Authenticates a user based on the provided credentials and returns a JWT token.
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param bodyParam body auth2.LoginRequest true "User login credentials"
|
||||
// @Success 200 {object} response.BaseResponse{data=response.LoginResponse} "Login successful"
|
||||
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||
// @Router /api/v1/auth/login [post]
|
||||
// @Tags Auth Login API's
|
||||
func (h *AuthHandler) AuthLogin(c *gin.Context) {
|
||||
ctx := auth2.GetMyContext(c)
|
||||
|
||||
var bodyParam auth2.LoginRequest
|
||||
if err := c.ShouldBindJSON(&bodyParam); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
email := strings.ToLower(bodyParam.Email)
|
||||
authUser, err := h.service.AuthenticateUser(c, email, bodyParam.Password)
|
||||
authUser, err := h.service.AuthCustomer(ctx, email, bodyParam.Password)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if authUser.UserType != "CUSTOMER" {
|
||||
response.ErrorWrapper(c, errors.ErrorUserIsNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
resp := response.LoginResponseCustoemr{
|
||||
ID: authUser.ID,
|
||||
Token: authUser.Token,
|
||||
@@ -80,118 +60,3 @@ func (h *AuthHandler) AuthLogin(c *gin.Context) {
|
||||
Data: resp,
|
||||
})
|
||||
}
|
||||
|
||||
// ForgotPassword handles the request for password reset.
|
||||
// @Summary Request password reset
|
||||
// @Description Sends a password reset link to the user's email.
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param bodyParam body auth2.ForgotPasswordRequest true "User email"
|
||||
// @Success 200 {object} response.BaseResponse "Password reset link sent"
|
||||
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||
// @Router /api/v1/auth/forgot-password [post]
|
||||
// @Tags Auth Password API's
|
||||
func (h *AuthHandler) ForgotPassword(c *gin.Context) {
|
||||
var bodyParam auth2.ResetPasswordRequest
|
||||
if err := c.ShouldBindJSON(&bodyParam); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.service.SendPasswordResetLink(c, bodyParam.Email)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Message: "Password reset link sent",
|
||||
})
|
||||
}
|
||||
|
||||
// ResetPassword handles the password reset process.
|
||||
// @Summary Reset user password
|
||||
// @Description Resets the user's password using the provided token.
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param bodyParam body auth2.ResetPasswordRequest true "Reset password details"
|
||||
// @Success 200 {object} response.BaseResponse "Password reset successful"
|
||||
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||
// @Router /api/v1/auth/reset-password [post]
|
||||
// @Tags Auth Password API's
|
||||
func (h *AuthHandler) ResetPassword(c *gin.Context) {
|
||||
ctx := auth2.GetMyContext(c)
|
||||
|
||||
var req auth2.ResetPasswordChangeRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := req.Validate(); err != nil {
|
||||
response.ErrorWrapper(c, errors.NewError(
|
||||
errors.ErrorBadRequest.ErrorType(),
|
||||
fmt.Sprintf("invalid request %v", err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
err := h.service.ResetPassword(ctx, req.OldPassword, req.NewPassword)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Message: "Password reset successful",
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Register(c *gin.Context) {
|
||||
var req auth2.CustomerRegister
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := auth2.GetMyContext(c)
|
||||
customer, err := h.customerSvc.RegistrationMember(ctx, req.ToEntity())
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.CustomerRegistrationResp{
|
||||
EmailVerificationRequired: true,
|
||||
PhoneVerificationRequired: false,
|
||||
VerificationID: customer.VerificationID,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) VerifyRegistration(c *gin.Context) {
|
||||
var req auth2.VerifyEmailRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := auth2.GetMyContext(c)
|
||||
err := h.customerSvc.VerifyOTP(ctx, req.VerificationID, req.OTPCode)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Message: "Email verification successful",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
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/inprogress_order"
|
||||
"enaklo-pos-be/internal/services/v2/product"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type MenuHandler struct {
|
||||
service product.Service
|
||||
orderService inprogress_order.InProgressOrderService
|
||||
}
|
||||
|
||||
func NewMenuHandler(service product.Service, orderService inprogress_order.InProgressOrderService,
|
||||
) *MenuHandler {
|
||||
return &MenuHandler{
|
||||
service: service,
|
||||
orderService: orderService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *MenuHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/menu")
|
||||
|
||||
route.GET("/:partner_id", h.GetProducts)
|
||||
route.POST("/order/create", h.OrderCreate)
|
||||
route.POST("/order/member/create", jwt, h.OrderMemberCreate)
|
||||
route.GET("/order", h.GetOrderID)
|
||||
}
|
||||
|
||||
func (h *MenuHandler) GetProducts(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
partnerIDParam := c.Param("partner_id")
|
||||
partnerID, err := strconv.ParseInt(partnerIDParam, 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if partnerID <= 0 {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req request.ProductParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
searchParam := req.ToEntity()
|
||||
searchParam.PartnerID = partnerID
|
||||
|
||||
products, total, err := h.service.GetProductsByPartnerID(ctx, searchParam)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toProductResponseList(products, int64(total), req),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *MenuHandler) toProductResponseList(resp []*entity.Product, total int64, req request.ProductParam) response.ProductList {
|
||||
var products []response.Product
|
||||
for _, b := range resp {
|
||||
products = append(products, h.toProductResponse(b))
|
||||
}
|
||||
|
||||
return response.ProductList{
|
||||
Products: products,
|
||||
Total: total,
|
||||
Limit: req.Limit,
|
||||
Offset: req.Offset,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *MenuHandler) toProductResponse(resp *entity.Product) response.Product {
|
||||
return response.Product{
|
||||
ID: resp.ID,
|
||||
Name: resp.Name,
|
||||
Type: resp.Type,
|
||||
Price: resp.Price,
|
||||
Status: resp.Status,
|
||||
Description: resp.Description,
|
||||
Image: resp.Image,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *MenuHandler) OrderCreate(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.OrderCustomer
|
||||
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
|
||||
}
|
||||
|
||||
if req.PartnerID == 0 {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
orderRequest := req.ToEntity(req.PartnerID, 0)
|
||||
|
||||
order, err := h.orderService.Save(ctx, orderRequest)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapToOrderCreateResponse(order),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *MenuHandler) OrderMemberCreate(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.OrderCustomer
|
||||
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
|
||||
}
|
||||
|
||||
if req.PartnerID == 0 {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
userID := ctx.RequestedBy()
|
||||
orderRequest := req.ToEntity(req.PartnerID, userID)
|
||||
orderRequest.CustomerID = &userID
|
||||
|
||||
order, err := h.orderService.Save(ctx, orderRequest)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapToOrderCreateResponse(order),
|
||||
})
|
||||
}
|
||||
|
||||
type GetOrderParam struct {
|
||||
PartnerID int64 `form:"partner_id" json:"partner_id"`
|
||||
OrderID int64 `form:"order_id" json:"order_id"`
|
||||
}
|
||||
|
||||
func (h *MenuHandler) GetOrderID(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req GetOrderParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
order, err := h.orderService.GetOrderByOrderAndPartnerID(ctx, req.PartnerID, req.OrderID)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapToOrderCreateResponse(order),
|
||||
})
|
||||
}
|
||||
|
||||
func MapToOrderCreateResponse(result *entity.Order) response.OrderResponse {
|
||||
resp := response.OrderResponse{
|
||||
ID: result.ID,
|
||||
Status: result.Status,
|
||||
Amount: result.Amount,
|
||||
Tax: result.Tax,
|
||||
Total: result.Total,
|
||||
PaymentType: result.PaymentType,
|
||||
CreatedAt: result.CreatedAt,
|
||||
Items: response.MapToOrderItemResponses(result.OrderItems),
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
@@ -22,7 +22,7 @@ type OssHandler struct {
|
||||
func (h *OssHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/file")
|
||||
|
||||
route.POST("/upload", h.UploadFile)
|
||||
route.POST("/upload", jwt, h.UploadFile)
|
||||
}
|
||||
|
||||
func NewOssHandler(ossService services.OSSService) *OssHandler {
|
||||
|
||||
@@ -6,12 +6,10 @@ import (
|
||||
"enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/handlers/response"
|
||||
"enaklo-pos-be/internal/services"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
@@ -275,9 +273,6 @@ func (h *Handler) toProductResponse(resp *entity.Product) response.Product {
|
||||
Price: resp.Price,
|
||||
Status: resp.Status,
|
||||
Description: resp.Description,
|
||||
CreatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||
UpdatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||
PartnerID: resp.PartnerID,
|
||||
Image: resp.Image,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,14 +313,11 @@ func (h *Handler) toProductResponseList(products []entity.Product) []response.Pr
|
||||
for _, product := range products {
|
||||
res = append(res, response.Product{
|
||||
ID: product.ID,
|
||||
PartnerID: product.PartnerID,
|
||||
Name: product.Name,
|
||||
Type: product.Type,
|
||||
Price: product.Price,
|
||||
Status: product.Status,
|
||||
Description: product.Description,
|
||||
CreatedAt: product.CreatedAt.Format(time.RFC3339),
|
||||
UpdatedAt: product.UpdatedAt.Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
return res
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
func GetMyContext(c *gin.Context) mycontext.Context {
|
||||
rawCtx, exists := c.Get("myCtx")
|
||||
if !exists {
|
||||
// handle missing context
|
||||
return mycontext.NewContext(c)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,16 @@ type Order struct {
|
||||
PaymentProvider string `json:"payment_provider"`
|
||||
TableNumber string `json:"table_number"`
|
||||
OrderItems []OrderItem `json:"order_items"`
|
||||
PartnerID int64 `json:"partner_id"`
|
||||
}
|
||||
|
||||
type OrderCustomer struct {
|
||||
CustomerName string `json:"customer_name" validate:"required"`
|
||||
CustomerPhone string `json:"customer_phone"`
|
||||
CustomerEmail string `json:"customer_email"`
|
||||
TableNumber string `json:"table_number" validate:"required"`
|
||||
OrderItems []OrderItem `json:"order_items" validate:"required"`
|
||||
PartnerID int64 `json:"partner_id" validate:"required"`
|
||||
}
|
||||
|
||||
type CustomerOrder struct {
|
||||
@@ -82,8 +92,9 @@ func (o *OrderParam) ToOrderEntity(ctx mycontext.Context) entity.OrderSearch {
|
||||
}
|
||||
|
||||
type OrderItem struct {
|
||||
ProductID int64 `json:"product_id" validate:"required"`
|
||||
Quantity int `json:"quantity" validate:"required"`
|
||||
ProductID int64 `json:"product_id" validate:"required"`
|
||||
Quantity int `json:"quantity" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
func (o *Order) ToEntity(partnerID, createdBy int64) *entity.OrderRequest {
|
||||
@@ -143,3 +154,23 @@ func (o *OrderParamCustomer) ToOrderEntity(ctx mycontext.Context) entity.OrderSe
|
||||
type OrderPrintDetail struct {
|
||||
ID int64 `form:"id" json:"id" example:"10"`
|
||||
}
|
||||
|
||||
func (o *OrderCustomer) ToEntity(partnerID, createdBy int64) *entity.OrderRequest {
|
||||
orderItems := make([]entity.OrderItemRequest, len(o.OrderItems))
|
||||
for i, item := range o.OrderItems {
|
||||
orderItems[i] = entity.OrderItemRequest{
|
||||
ProductID: item.ProductID,
|
||||
Quantity: item.Quantity,
|
||||
Description: item.Description,
|
||||
}
|
||||
}
|
||||
|
||||
return &entity.OrderRequest{
|
||||
PartnerID: partnerID,
|
||||
OrderItems: orderItems,
|
||||
CreatedBy: createdBy,
|
||||
Source: "ONLINE_ORDER",
|
||||
CustomerName: o.CustomerName,
|
||||
TableNumber: o.TableNumber,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,11 @@ package response
|
||||
|
||||
type Product struct {
|
||||
ID int64 `json:"id"`
|
||||
PartnerID int64 `json:"partner_id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Price float64 `json:"price"`
|
||||
Status string `json:"status"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
Image string `json:"image"`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user