Skip to content

Commit

Permalink
[sprint-1][EA-1] customer: CRUD, overview order
Browse files Browse the repository at this point in the history
  • Loading branch information
Duchieuctk41 committed Jan 14, 2024
1 parent ddbb7f4 commit c12c237
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 53 deletions.
15 changes: 15 additions & 0 deletions api/controllers/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,21 @@ func (h *OrderController) GetOverview(c *gin.Context) {
h.Response(c, http.StatusOK, "success", res)
}

func (h *OrderController) GetBestSeller(c *gin.Context) {
var req erpdto.GetListOrderRequest

if err := c.ShouldBindQuery(&req); err != nil {
h.ResponseValidationError(c, err)
return
}
res, err := h.orderService.GetBestSeller(c, req)
if err != nil {
h.ResponseError(c, err)
return
}
h.Response(c, http.StatusOK, "success", res)
}

func (h *OrderController) validateOrderItem(req []erpdto.OrderItemRequest) (err error) {
if len(req) == 0 {
return errors.New(api_errors.ErrOrderItemRequired)
Expand Down
2 changes: 1 addition & 1 deletion api/controllers/product.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (b *ERPProductController) Create(c *gin.Context) {
b.ResponseError(c, err)
return
}
b.Response(c, http.StatusOK, "success", res)
b.Response(c, http.StatusOK, "success", res.ID)
}

func (b *ERPProductController) Update(c *gin.Context) {
Expand Down
3 changes: 3 additions & 0 deletions dto/erp/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type CreateOrderRequest struct {

Note *string `json:"note"` // note for order
Amount float64 // tổng tiền của toàn bộ sản phẩm
Cost float64 // tổng tiền chi phí
Total float64 `json:"total"` // grand total
Payment float64 `json:"payment"` // COD | Online

Expand Down Expand Up @@ -95,5 +96,7 @@ type UpdateOrderRequest struct {
}

type GetListOrderRequest struct {
StartTime string `form:"start_time"`
EndTime string `form:"end_time"`
request.PageOptions
}
2 changes: 2 additions & 0 deletions dto/erp/product.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type CreateProductRequest struct {
Status bool `json:"status"` // true: active, false: inactive
Quantity *int `json:"quantity"`
StoreId string
Cost float64 `json:"cost" binding:"numeric,gte=0"` // gte: greater than or equal
}

type UpdateProductRequest struct {
Expand All @@ -29,6 +30,7 @@ type ProductResponse struct {
Price float64 `json:"price"`
Status bool `json:"status"`
Quantity int `json:"quantity"`
Cost float64 `json:"cost"`
}

type GetListProductRequest struct {
Expand Down
11 changes: 7 additions & 4 deletions models/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ type Order struct {

PromoteFee *float64 `json:"promote_fee,omitempty"`
PromoteCode *string `json:"promote_code,omitempty"`
Cost float64 `json:"cost"`
//StoreId uuid.UUID `json:"store_id" gorm:"not null"`
OrderItems []*OrderItem `json:"order_item,omitempty" gorm:"foreignkey:OrderId;association_foreignkey:ID"`
}

type OrderOverview struct {
Confirm int `json:"confirm"`
Delivery int `json:"delivery"`
Complete int `json:"complete"`
Cancel int `json:"cancel"`
Revenue float64 `json:"revenue"`
Income float64 `json:"income"`
Confirm int `json:"confirm"`
Delivery int `json:"delivery"`
Complete int `json:"complete"`
Cancel int `json:"cancel"`
}
4 changes: 2 additions & 2 deletions models/order_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import uuid "github.com/satori/go.uuid"

type OrderItem struct {
BaseModel
OrderId uuid.UUID `json:"order_id"`
ProductId uuid.UUID `json:"product_id"`
OrderId uuid.UUID `json:"order_id" gorm:"type:uuid;not null"`
ProductId uuid.UUID `json:"product_id" gorm:"type:uuid;not null"`
Quantity int `json:"quantity"`
Price float64 `json:"price"`
}
17 changes: 17 additions & 0 deletions models/product.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package models

import (
uuid "github.com/satori/go.uuid"
)

type Product struct {
BaseModel
Name string `json:"name" gorm:"column:name;type:varchar(50);not null"`
Expand All @@ -11,6 +15,19 @@ type Product struct {
//StoreId uuid.UUID `json:"store_id" gorm:"column:store_id;type:uuid;not null"`
Sold int `json:"sold" gorm:"column:sold;type:int;default:0;"`
PromotePrice float64 `json:"promote_price" gorm:"column:promote_price;type:float;default:0;"`
Cost float64 `json:"cost" gorm:"column:cost;type:float;default:0;"`
}

type ProductBestSellerResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Image string `json:"image"`
Price float64 `json:"price"`
Status bool `json:"status"`
Quantity int `json:"quantity"`
Cost float64 `json:"cost"`
QuantitySold int `json:"quantity_sold"`
}

func (Product) TableName() string {
Expand Down
22 changes: 19 additions & 3 deletions repository/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type OrderRepo interface {
GetOneById(ctx context.Context, id string) (*models.Order, error)
GetList(ctx context.Context, req erpdto.GetListOrderRequest) (res []*models.Order, total int64, err error)
GetOverview(ctx context.Context, req erpdto.GetListOrderRequest) (res []*models.OrderOverview, err error)
GetBestSeller(ctx context.Context, req erpdto.GetListOrderRequest) (res []*models.ProductBestSellerResponse, err error)
}

type orderRepo struct {
Expand Down Expand Up @@ -61,6 +62,10 @@ func (r *orderRepo) GetList(ctx context.Context, req erpdto.GetListOrderRequest)
query = query.Where("note ilike ?", "%"+req.Search+"%")
}

if req.StartTime != "" && req.EndTime != "" {
query = query.Where("created_at BETWEEN ? AND ?", req.StartTime, req.EndTime)
}

switch req.Sort {
default:
query = query.Order(req.Sort)
Expand All @@ -76,11 +81,14 @@ func (r *orderRepo) GetList(ctx context.Context, req erpdto.GetListOrderRequest)
}

func (r *orderRepo) GetOverview(ctx context.Context, req erpdto.GetListOrderRequest) (res []*models.OrderOverview, err error) {
queryString := `SELECT count(confirm) as confirm, count(delivery) as delivery, count(complete) as complete, count(cancel) as cancel
queryString := `SELECT count(confirm) as confirm, count(delivery) as delivery, count(complete) as complete, count(cancel) as cancel,
sum(revenue) as revenue, sum(income) as income
FROM ( select CASE WHEN status = 'confirm' then 1 else null end as confirm,
CASE WHEN status = 'delivery' then 1 else null end as delivery,
CASE WHEN status = 'complete' then 1 else null end as complete,
CASE WHEN status = 'cancel' then 1 else null end as cancel
CASE WHEN status = 'cancel' then 1 else null end as cancel,
CASE WHEN status != 'cancel' then total else null end revenue,
CASE WHEN status != 'cancel' then "cost" else null end income
FROM orders `

if req.Search != "" {
Expand All @@ -89,6 +97,14 @@ func (r *orderRepo) GetOverview(ctx context.Context, req erpdto.GetListOrderRequ

queryString += `) as t`

err = r.db.Raw(queryString).Find(&res).Error
err = r.db.Debug().Raw(queryString).Find(&res).Error
return res, err
}

func (r *orderRepo) GetBestSeller(ctx context.Context, req erpdto.GetListOrderRequest) (res []*models.ProductBestSellerResponse, err error) {
err = r.db.Table("order_items").Select("products.*, sum(order_items.quantity) as quantity_sold").
Joins("inner join products on order_items.product_id = products.id").Order("quantity_sold desc").
Where("order_items.status != 'cancel'").
Limit(10).Group("products.id").Find(&res).Error
return res, err
}
1 change: 1 addition & 0 deletions route/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func NewRoute(
v1.GET("/order/", middleware.Auth(true), orderController.GetList)
v1.GET("/order/:id", middleware.Auth(true), orderController.GetOne)
v1.GET("/order/overview/", middleware.Auth(true), orderController.GetOverview)
v1.GET("/order/best_seller", middleware.Auth(true), orderController.GetBestSeller)

v1.POST("/promote/", middleware.Auth(true), promoteController.Create)

Expand Down
91 changes: 48 additions & 43 deletions service/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type OrderService interface {
UpdateFlow(ctx context.Context, req erpdto.UpdateOrderRequest) (*models.Order, error)
GetList(ctx context.Context, req erpdto.GetListOrderRequest) ([]*models.Order, int64, error)
GetOverview(ctx context.Context, req erpdto.GetListOrderRequest) ([]*models.OrderOverview, error)
GetBestSeller(ctx context.Context, req erpdto.GetListOrderRequest) ([]*models.ProductBestSellerResponse, error)
GetOne(ctx context.Context, id string) (*models.Order, error)
}

Expand Down Expand Up @@ -87,7 +88,7 @@ func (s *orderService) CreateFlow(ctx context.Context, req erpdto.CreateOrderReq
// check quantity, if quantity is null, only check price
// if promote_price != 0, use promote_price
// calculate amount
req.Amount, err = s.CalculateAmount(ctx, products, mapOrderItem)
req.Amount, req.Cost, err = s.CalculateAmount(ctx, products, mapOrderItem)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -428,17 +429,16 @@ func (s *orderService) calculateTotalAmount(ctx context.Context, amount float64,
return total, nil
}

func (s *orderService) CalculateAmount(ctx context.Context, products []*models.Product, mapOrderItem map[string]erpdto.OrderItemRequest) (float64, error) {
amount := float64(0)
func (s *orderService) CalculateAmount(ctx context.Context, products []*models.Product, mapOrderItem map[string]erpdto.OrderItemRequest) (amount float64, costTotal float64, err error) {
for _, product := range products {
if product.Status != constants.ProductStatusActive {
return 0.0, errors.New(api_errors.ErrProductInvalid)
return 0.0, 0.0, errors.New(api_errors.ErrProductInvalid)
}

// check quantity, if quantity is null, only check price
if product.Quantity != nil {
if utils.ValidInt(product.Quantity) < mapOrderItem[product.ID.String()].Quantity {
return 0.0, errors.New(api_errors.ErrQuantityIsNotEnough)
return 0.0, 0.0, errors.New(api_errors.ErrQuantityIsNotEnough)
}
}

Expand All @@ -448,8 +448,9 @@ func (s *orderService) CalculateAmount(ctx context.Context, products []*models.P
continue
}
amount += product.Price * float64(mapOrderItem[product.ID.String()].Quantity)
costTotal += product.Cost * float64(mapOrderItem[product.ID.String()].Quantity)
}
return amount, nil
return amount, costTotal, nil
}

// UpdateFlow
Expand Down Expand Up @@ -496,6 +497,47 @@ func (s *orderService) UpdateFlow(ctx context.Context, req erpdto.UpdateOrderReq
return order, err
}

func (s *orderService) updateCancelDebtAndRevenue(tx *repository.TX, ctx context.Context, order *models.Order) error {
// get debt
debt, err := s.cashbookRepo.GetDebtByOrderId(tx, ctx, order.ID.String())
if err != nil {
return err
}

// delete debt
if err := s.cashbookService.Delete(ctx, debt.ID.String()); err != nil {
return err
}

// get revenue
revenue, err := s.cashbookRepo.GetCashbookByOrderId(tx, ctx, order.ID.String())
if err != nil {
return err
}

// delete revenue
if err := s.cashbookRepo.Delete(tx, ctx, revenue.ID.String()); err != nil {
return err
}
return nil
}

func (s *orderService) GetList(ctx context.Context, req erpdto.GetListOrderRequest) ([]*models.Order, int64, error) {
return s.erpOrderRepo.GetList(ctx, req)
}

func (s *orderService) GetOverview(ctx context.Context, req erpdto.GetListOrderRequest) ([]*models.OrderOverview, error) {
return s.erpOrderRepo.GetOverview(ctx, req)
}

func (s *orderService) GetBestSeller(ctx context.Context, req erpdto.GetListOrderRequest) ([]*models.ProductBestSellerResponse, error) {
return s.erpOrderRepo.GetBestSeller(ctx, req)
}

func (s *orderService) GetOne(ctx context.Context, id string) (*models.Order, error) {
return s.erpOrderRepo.GetOneById(ctx, id)
}

func (s *orderService) checkOrderStatus(ctx context.Context, order *models.Order, req erpdto.UpdateOrderRequest) error {
switch order.Status {
case constants.Confirm:
Expand Down Expand Up @@ -547,31 +589,6 @@ func (s *orderService) cancelOrder(tx *repository.TX, ctx context.Context, order
return nil
}

func (s *orderService) updateCancelDebtAndRevenue(tx *repository.TX, ctx context.Context, order *models.Order) error {
// get debt
debt, err := s.cashbookRepo.GetDebtByOrderId(tx, ctx, order.ID.String())
if err != nil {
return err
}

// delete debt
if err := s.cashbookService.Delete(ctx, debt.ID.String()); err != nil {
return err
}

// get revenue
revenue, err := s.cashbookRepo.GetCashbookByOrderId(tx, ctx, order.ID.String())
if err != nil {
return err
}

// delete revenue
if err := s.cashbookRepo.Delete(tx, ctx, revenue.ID.String()); err != nil {
return err
}
return nil
}

func (s *orderService) mapCancelOrderItem(orderItems []*models.OrderItem) ([]string, map[string]models.OrderItem) {
productIds := []string{}
mapOrderItem := map[string]models.OrderItem{}
Expand All @@ -598,15 +615,3 @@ func (s *orderService) updateCancelProQuantity(tx *repository.TX, ctx context.Co
}
return nil
}

func (s *orderService) GetList(ctx context.Context, req erpdto.GetListOrderRequest) ([]*models.Order, int64, error) {
return s.erpOrderRepo.GetList(ctx, req)
}

func (s *orderService) GetOverview(ctx context.Context, req erpdto.GetListOrderRequest) ([]*models.OrderOverview, error) {
return s.erpOrderRepo.GetOverview(ctx, req)
}

func (s *orderService) GetOne(ctx context.Context, id string) (*models.Order, error) {
return s.erpOrderRepo.GetOneById(ctx, id)
}

0 comments on commit c12c237

Please sign in to comment.