diff --git a/app/delivery/middleware/perms/permissions.go b/app/delivery/middleware/perms/permissions.go index 7528921..7fa5458 100644 --- a/app/delivery/middleware/perms/permissions.go +++ b/app/delivery/middleware/perms/permissions.go @@ -7,4 +7,5 @@ const ( UserWriteAny Permission = "user.write.any" UserDeleteAny Permission = "user.delete.any" CurrencyWrite Permission = "currency.write" + ViewAllOrders Permission = "orders.view" ) diff --git a/app/delivery/web/api/restricted/orders.go b/app/delivery/web/api/restricted/orders.go index 3c5a180..28e8266 100644 --- a/app/delivery/web/api/restricted/orders.go +++ b/app/delivery/web/api/restricted/orders.go @@ -61,10 +61,10 @@ func (h *OrdersHandler) ListOrders(c fiber.Ctx) error { } var columnMappingListOrders map[string]string = map[string]string{ - "order_id": "co.id", - "user_id": "co.user_id", - "country_id": "co.country_id", - "status": "co.status", + "order_id": "b2b_customer_orders.id", + "user_id": "b2b_customer_orders.user_id", + "country_id": "b2b_customer_orders.country_id", + "status": "b2b_customer_orders.status", } func (h *OrdersHandler) PlaceNewOrder(c fiber.Ctx) error { @@ -81,7 +81,6 @@ func (h *OrdersHandler) PlaceNewOrder(c fiber.Ctx) error { JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute))) } - address_info := c.Query("address_info") country_id_attribute := c.Query("country_id") country_id, err := strconv.Atoi(country_id_attribute) if err != nil { @@ -89,6 +88,8 @@ func (h *OrdersHandler) PlaceNewOrder(c fiber.Ctx) error { JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute))) } + address_info := c.Query("address_info") + err = h.ordersService.PlaceNewOrder(userID, uint(cart_id), uint(country_id), address_info) if err != nil { return c.Status(responseErrors.GetErrorStatus(err)). diff --git a/app/repos/ordersRepo/ordersRepo.go b/app/repos/ordersRepo/ordersRepo.go index e4832e9..d299976 100644 --- a/app/repos/ordersRepo/ordersRepo.go +++ b/app/repos/ordersRepo/ordersRepo.go @@ -1,6 +1,7 @@ package ordersRepo import ( + "git.ma-al.com/goc_daniel/b2b/app/db" "git.ma-al.com/goc_daniel/b2b/app/model" "git.ma-al.com/goc_daniel/b2b/app/utils/query/filters" "git.ma-al.com/goc_daniel/b2b/app/utils/query/find" @@ -20,10 +21,41 @@ func New() UIOrdersRepo { } func (repo *OrdersRepo) Find(user_id uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.CustomerOrder], error) { - return find.Found[model.CustomerOrder]{}, nil + var list []model.CustomerOrder + var total int64 + + query := db.Get(). + Model(&model.CustomerOrder{}). + Preload("Products"). + Order("b2b_customer_orders.id DESC") + + // Apply all filters + if filt != nil { + filt.ApplyAll(query) + } + + // run counter first as query is without limit and offset + err := query.Count(&total).Error + if err != nil { + return find.Found[model.CustomerOrder]{}, err + } + + err = query. + Limit(p.Limit()). + Offset(p.Offset()). + Find(&list).Error + if err != nil { + return find.Found[model.CustomerOrder]{}, err + } + + return find.Found[model.CustomerOrder]{ + Items: list, + Count: uint(total), + }, nil } func (repo *OrdersRepo) PlaceNewOrder(user_id uint, cart_id uint, country_id uint, address_info string) error { + return nil } diff --git a/app/service/addressesService/addressesService.go b/app/service/addressesService/addressesService.go index b077486..48eadc3 100644 --- a/app/service/addressesService/addressesService.go +++ b/app/service/addressesService/addressesService.go @@ -49,7 +49,7 @@ func (s *AddressesService) AddNewAddress(user_id uint, address_info string, coun return responseErrors.ErrMaxAmtOfAddressesReached } - _, err = s.validateAddressJson(address_info, country_id) + _, err = s.ValidateAddressJson(address_info, country_id) if err != nil { return err } @@ -66,7 +66,7 @@ func (s *AddressesService) ModifyAddress(user_id uint, address_id uint, address_ return responseErrors.ErrUserHasNoSuchAddress } - _, err = s.validateAddressJson(address_info, country_id) + _, err = s.ValidateAddressJson(address_info, country_id) if err != nil { return err } @@ -88,7 +88,7 @@ func (s *AddressesService) RetrieveAddressesInfo(user_id uint) (*[]model.Address next_address.CustomerID = (*parsed_addresses)[i].CustomerID next_address.CountryID = (*parsed_addresses)[i].CountryID - next_address.AddressInfo, err = s.validateAddressJson((*parsed_addresses)[i].AddressInfo, next_address.CountryID) + next_address.AddressInfo, err = s.ValidateAddressJson((*parsed_addresses)[i].AddressInfo, next_address.CountryID) // log such errors if err != nil { fmt.Printf("err: %v\n", err) @@ -112,7 +112,7 @@ func (s *AddressesService) DeleteAddress(user_id uint, address_id uint) error { } // validateAddressJson makes sure that the info string represents a valid json of address in given country -func (s *AddressesService) validateAddressJson(info string, country_id uint) (model.AddressField, error) { +func (s *AddressesService) ValidateAddressJson(info string, country_id uint) (model.AddressField, error) { dec := json.NewDecoder(strings.NewReader(info)) dec.DisallowUnknownFields() diff --git a/app/service/orderService/orderService.go b/app/service/orderService/orderService.go index 6b1fb09..ccd46e0 100644 --- a/app/service/orderService/orderService.go +++ b/app/service/orderService/orderService.go @@ -1,28 +1,66 @@ package orderService import ( + "strconv" + + "git.ma-al.com/goc_daniel/b2b/app/delivery/middleware/perms" "git.ma-al.com/goc_daniel/b2b/app/model" + "git.ma-al.com/goc_daniel/b2b/app/repos/cartsRepo" "git.ma-al.com/goc_daniel/b2b/app/repos/ordersRepo" + "git.ma-al.com/goc_daniel/b2b/app/service/addressesService" "git.ma-al.com/goc_daniel/b2b/app/utils/query/filters" "git.ma-al.com/goc_daniel/b2b/app/utils/query/find" + "git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors" ) type OrderService struct { - ordersRepo ordersRepo.UIOrdersRepo + ordersRepo ordersRepo.UIOrdersRepo + cartsRepo cartsRepo.UICartsRepo + addressesService *addressesService.AddressesService } func New() *OrderService { return &OrderService{ - ordersRepo: ordersRepo.New(), + ordersRepo: ordersRepo.New(), + cartsRepo: cartsRepo.New(), + addressesService: addressesService.New(), } } func (s *OrderService) Find(user *model.Customer, p find.Paging, filt *filters.FiltersList) (find.Found[model.CustomerOrder], error) { + if !user.HasPermission(perms.ViewAllOrders) { + // append filter to view only this user's orders + idStr := strconv.FormatUint(uint64(user.ID), 10) + filt.Append(filters.Where("b2b_customer_orders.user_id = " + idStr)) + } + return s.ordersRepo.Find(user.ID, p, filt) } func (s *OrderService) PlaceNewOrder(user_id uint, cart_id uint, country_id uint, address_info string) error { - return nil + _, err := s.addressesService.ValidateAddressJson(address_info, country_id) + if err != nil { + return err + } + + amt, err := s.cartsRepo.UserHasCart(user_id, cart_id) + if err != nil { + return err + } + if amt <= 0 { + return responseErrors.ErrUserHasNoSuchCart + } + + cart, err := s.cartsRepo.RetrieveCart(user_id, cart_id) + if err != nil { + return err + } + if len(cart.Products) == 0 { + return responseErrors.ErrEmptyCart + } + + // all checks passed + return s.ordersRepo.PlaceNewOrder(user_id, cart_id, country_id, address_info) } func (s *OrderService) ChangeOrderAddress(user *model.Customer, order_id uint, country_id uint, address_info string) error { diff --git a/app/utils/responseErrors/responseErrors.go b/app/utils/responseErrors/responseErrors.go index 6b3c548..752e532 100644 --- a/app/utils/responseErrors/responseErrors.go +++ b/app/utils/responseErrors/responseErrors.go @@ -65,6 +65,7 @@ var ( ErrMaxAmtOfCartsReached = errors.New("maximal amount of carts reached") ErrUserHasNoSuchCart = errors.New("user does not have cart with given id") ErrProductOrItsVariationDoesNotExist = errors.New("product or its variation with given ids does not exist") + ErrEmptyCart = errors.New("the cart is empty") // Typed errors for storage ErrAccessDenied = errors.New("access denied!") @@ -195,6 +196,8 @@ func GetErrorCode(c fiber.Ctx, err error) string { return i18n.T_(c, "error.err_user_has_no_such_cart") case errors.Is(err, ErrProductOrItsVariationDoesNotExist): return i18n.T_(c, "error.err_product_or_its_variation_does_not_exist") + case errors.Is(err, ErrEmptyCart): + return i18n.T_(c, "error.err_cart_is_empty") case errors.Is(err, ErrAccessDenied): return i18n.T_(c, "error.err_access_denied") @@ -268,6 +271,7 @@ func GetErrorStatus(err error) int { errors.Is(err, ErrMaxAmtOfCartsReached), errors.Is(err, ErrUserHasNoSuchCart), errors.Is(err, ErrProductOrItsVariationDoesNotExist), + errors.Is(err, ErrEmptyCart), errors.Is(err, ErrAccessDenied), errors.Is(err, ErrFolderDoesNotExist), errors.Is(err, ErrFileDoesNotExist),