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/repos/productsRepo" "git.ma-al.com/goc_daniel/b2b/app/service/addressesService" "git.ma-al.com/goc_daniel/b2b/app/service/emailService" constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data" "git.ma-al.com/goc_daniel/b2b/app/utils/logger" "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 cartsRepo cartsRepo.UICartsRepo productsRepo productsRepo.UIProductsRepo addressesService *addressesService.AddressesService emailService *emailService.EmailService } func New() *OrderService { return &OrderService{ ordersRepo: ordersRepo.New(), cartsRepo: cartsRepo.New(), productsRepo: productsRepo.New(), addressesService: addressesService.New(), emailService: emailService.NewEmailService(), } } func (s *OrderService) Find(user *model.Customer, p find.Paging, filt *filters.FiltersList) (*find.Found[model.CustomerOrder], error) { if !user.HasPermission(perms.OrdersViewAll) { // 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)) } list, err := s.ordersRepo.Find(user.ID, p, filt) if err != nil { return nil, err } for i := 0; i < len(list.Items); i++ { address_unparsed, err := s.addressesService.ValidateAddressJson(list.Items[i].AddressString, list.Items[i].CountryID) if err != nil { logger.Warn("failed to validate address", "service", "orderService", "order_id", list.Items[i].OrderID, "error", err.Error(), ) } list.Items[i].AddressUnparsed = &address_unparsed } return list, nil } func (s *OrderService) PlaceNewOrder(user_id uint, cart_id uint, name string, country_id uint, address_info string) error { _, err := s.addressesService.ValidateAddressJson(address_info, country_id) if err != nil { return err } exists, err := s.cartsRepo.UserHasCart(user_id, cart_id) if err != nil { return err } if !exists { 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 } if name == "" && cart.Name != nil { name = *cart.Name } base_price, tax_incl, tax_excl, err := s.getOrderTotalPrice(user_id, cart_id, country_id) // all checks passed err = s.ordersRepo.PlaceNewOrder(cart, name, country_id, address_info, base_price, tax_incl, tax_excl) if err != nil { return err } // from this point onward we do not cancel this order. // if no error is returned, remove the cart. This should be smooth err = s.cartsRepo.RemoveCart(user_id, cart_id) if err != nil { logger.Warn("failed to remove cart after order placement", "service", "orderService", "user_id", user_id, "cart_id", cart_id, "error", err.Error(), ) } // send email to admin go func(user_id uint) { err := s.emailService.SendNewOrderPlacedNotification(user_id) if err != nil { logger.Warn("failed to send new order notification", "service", "orderService", "user_id", user_id, "error", err.Error(), ) } }(user_id) return nil } func (s *OrderService) ChangeOrderAddress(user *model.Customer, order_id uint, country_id uint, address_info string) error { _, err := s.addressesService.ValidateAddressJson(address_info, country_id) if err != nil { return err } if !user.HasPermission(perms.OrdersModifyAll) { exists, err := s.ordersRepo.UserHasOrder(user.ID, order_id) if err != nil { return err } if !exists { return responseErrors.ErrUserHasNoSuchOrder } } return s.ordersRepo.ChangeOrderAddress(order_id, country_id, address_info) } // This is obiously just an initial version of this function func (s *OrderService) ChangeOrderStatus(user *model.Customer, order_id uint, status string) error { if !user.HasPermission(perms.OrdersModifyAll) { exists, err := s.ordersRepo.UserHasOrder(user.ID, order_id) if err != nil { return err } if !exists { return responseErrors.ErrUserHasNoSuchOrder } } return s.ordersRepo.ChangeOrderStatus(order_id, status) } func (s *OrderService) getOrderTotalPrice(user_id uint, cart_id uint, country_id uint) (float64, float64, float64, error) { cart, err := s.cartsRepo.RetrieveCart(user_id, cart_id) if err != nil { return 0.0, 0.0, 0.0, err } base_price := 0.0 tax_incl := 0.0 tax_excl := 0.0 for _, product := range cart.Products { prices, err := s.productsRepo.GetPrice(product.ProductID, product.ProductAttributeID, constdata.SHOP_ID, user_id, country_id, product.Amount) if err != nil { return 0.0, 0.0, 0.0, err } base_price += prices.Base tax_incl += prices.FinalTaxIncl tax_excl += prices.FinalTaxExcl } return base_price, tax_incl, tax_excl, nil }