170 lines
4.6 KiB
Go
170 lines
4.6 KiB
Go
package orderService
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"git.ma-al.com/goc_daniel/b2b/app/actions/orderStatusActions"
|
|
"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/model/enums"
|
|
"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/service/emailService"
|
|
"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
|
|
addressesService *addressesService.AddressesService
|
|
emailService *emailService.EmailService
|
|
actionRegistry *orderStatusActions.ActionRegistry
|
|
}
|
|
|
|
func New() *OrderService {
|
|
return &OrderService{
|
|
ordersRepo: ordersRepo.New(),
|
|
cartsRepo: cartsRepo.New(),
|
|
addressesService: addressesService.New(),
|
|
emailService: emailService.NewEmailService(),
|
|
actionRegistry: &orderStatusActions.GlobalRegistry,
|
|
}
|
|
}
|
|
|
|
var ValidStatuses = map[enums.OrderStatus]bool{
|
|
enums.OrderStatusPending: true,
|
|
enums.OrderStatusConfirmed: true,
|
|
enums.OrderStatusProcessing: true,
|
|
enums.OrderStatusShipped: true,
|
|
enums.OrderStatusOutForDelivery: true,
|
|
enums.OrderStatusDelivered: true,
|
|
enums.OrderStatusCancelled: true,
|
|
enums.OrderStatusReturned: true,
|
|
enums.OrderStatusRefunded: true,
|
|
enums.OrderStatusFailed: true,
|
|
}
|
|
|
|
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)
|
|
// log such errors
|
|
if err != nil {
|
|
fmt.Printf("err: %v\n", err)
|
|
}
|
|
|
|
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, originalUserId uint) 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
|
|
}
|
|
|
|
// all checks passed
|
|
order, err := s.ordersRepo.PlaceNewOrder(cart, name, country_id, address_info, originalUserId)
|
|
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 {
|
|
// Log error but don't fail placing order
|
|
_ = err
|
|
}
|
|
|
|
return s.ChangeOrderStatus(user_id, order.OrderID, enums.OrderStatusPending)
|
|
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
func (s *OrderService) ChangeOrderStatus(userId, orderId uint, newStatus enums.OrderStatus) error {
|
|
order, err := s.ordersRepo.Get(orderId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if order == nil {
|
|
return responseErrors.ErrOrderNotFound
|
|
}
|
|
|
|
if !ValidStatuses[newStatus] {
|
|
return responseErrors.ErrInvalidStatus
|
|
}
|
|
|
|
err = s.ordersRepo.ChangeOrderStatus(order.OrderID, newStatus, userId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
actionCtx := orderStatusActions.ActionContext{
|
|
Order: order,
|
|
UserId: &userId,
|
|
EmailService: s.emailService,
|
|
}
|
|
|
|
go func() {
|
|
_ = s.actionRegistry.ExecuteForStatus(newStatus, actionCtx)
|
|
}()
|
|
|
|
return nil
|
|
}
|