github.com/timoth-y/kicksware-api/order-service@v0.0.0-20201002192818-87b546a7ae5a/usecase/business/orderService.go (about)

     1  package business
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/pkg/errors"
    13  	"github.com/rs/xid"
    14  	"github.com/thoas/go-funk"
    15  	"github.com/timoth-y/kicksware-api/search-service/core/pipe"
    16  	"gopkg.in/dealancer/validate.v2"
    17  
    18  	"github.com/timoth-y/kicksware-api/service-common/core/meta"
    19  	"github.com/timoth-y/kicksware-api/order-service/core/model"
    20  	"github.com/timoth-y/kicksware-api/order-service/core/repo"
    21  	"github.com/timoth-y/kicksware-api/order-service/core/service"
    22  	"github.com/timoth-y/kicksware-api/order-service/env"
    23  )
    24  
    25  var (
    26  	ErrOrderNotFound = errors.New("order Not Found")
    27  	ErrOrderNotValid = errors.New("order Not Valid")
    28  )
    29  
    30  type orderService struct {
    31  	repo repo.OrderRepository
    32  	serviceConfig env.CommonConfig
    33  	pipe pipe.SneakerReferencePipe
    34  }
    35  
    36  func NewOrderService(orderRepo repo.OrderRepository, pipe pipe.SneakerReferencePipe, serviceConfig env.CommonConfig) service.OrderService {
    37  	return &orderService{
    38  		orderRepo,
    39  		serviceConfig,
    40  		pipe,
    41  	}
    42  }
    43  
    44  func (s *orderService) FetchOne(code string, params *meta.RequestParams) (*model.Order, error) {
    45  	return s.repo.FetchOne(code, params)
    46  }
    47  
    48  func (s *orderService) Fetch(codes []string, params *meta.RequestParams) ([]*model.Order, error) {
    49  	return s.repo.Fetch(codes, params)
    50  }
    51  
    52  func (s *orderService) FetchAll(params *meta.RequestParams) ([]*model.Order, error) {
    53  	return s.repo.FetchAll(params)
    54  }
    55  
    56  func (s *orderService) FetchQuery(query meta.RequestQuery, params *meta.RequestParams) (refs []*model.Order, err error) {
    57  	foreignKeys, is := s.handleForeignSubquery(query)
    58  	refs, err = s.repo.FetchQuery(query, params)
    59  	if err == nil && is {
    60  		refs = funk.Filter(refs, func(ref *model.Order) bool {
    61  			return funk.Contains(foreignKeys, ref.UniqueID)
    62  		}).([]*model.Order)
    63  	}
    64  	return
    65  }
    66  
    67  func (s *orderService) StoreOne(order *model.Order) error {
    68  	if err := validate.Validate(order); err != nil {
    69  		return errors.Wrap(ErrOrderNotValid, "service.repo.Store")
    70  	}
    71  	order.UniqueID = xid.New().String()
    72  	if ref, err := s.pipe.FetchOne(order.ReferenceID); err == nil {
    73  		order.Price = ref.Price
    74  		if url := ref.StadiumUrl; len(url) != 0 {
    75  			order.SourceURL = url
    76  		} else if url := ref.GoatUrl; len(url) != 0  {
    77  			order.SourceURL = url
    78  		} else {
    79  			order.SourceURL = fmt.Sprintf("http://kicksware.com/shop/references/%v", ref.UniqueId)
    80  		}
    81  		order.Price = ref.Price
    82  	}
    83  	order.Status = model.Draft
    84  	order.AddedAt = time.Now()
    85  	return s.repo.StoreOne(order)
    86  }
    87  
    88  func (s *orderService) Modify(order *model.Order) error {
    89  	return s.repo.Modify(order)
    90  }
    91  
    92  func (s *orderService) Remove(code string) error {
    93  	return s.repo.Remove(code)
    94  }
    95  
    96  func (s *orderService) CountAll() (int, error) {
    97  	return s.repo.CountAll()
    98  }
    99  
   100  func (s *orderService) Count(query meta.RequestQuery, params *meta.RequestParams) (int, error) {
   101  	foreignKeys, is := s.handleForeignSubquery(query); if is {
   102  		refs, err := s.repo.FetchQuery(query, params)
   103  		if err == nil && is {
   104  			refs = funk.Filter(refs, func(ref *model.Order) bool {
   105  				return funk.Contains(foreignKeys, ref.UniqueID)
   106  			}).([]*model.Order)
   107  		}
   108  		return len(refs), nil
   109  	}
   110  	return s.repo.Count(query, params)
   111  }
   112  
   113  func (s *orderService) handleForeignSubquery(query map[string]interface{}) (foreignKeys []string, is bool) {
   114  	foreignKeys = make([]string, 0)
   115  	for key := range query {
   116  		if strings.Contains(key, "*/") {
   117  			is = true
   118  			res := strings.TrimLeft(key, "*/");
   119  			host := fmt.Sprintf("%s-service", strings.Split(res, "/")[0]);
   120  			service := fmt.Sprintf(s.serviceConfig.InnerServiceFormat, host, res)
   121  			if keys, err := s.postOnForeignService(service, query[key]); err == nil {
   122  				foreignKeys = append(foreignKeys, keys...)
   123  			}
   124  			delete(query, key)
   125  		}
   126  	}
   127  	return
   128  }
   129  
   130  func (s *orderService) postOnForeignService(service string, query interface{}) (keys []string, err error) {
   131  	body, err := json.Marshal(query); if err != nil {
   132  		return
   133  	}
   134  	resp, err := http.Post(service, s.serviceConfig.ContentType, bytes.NewBuffer(body))
   135  	if err != nil {
   136  		return
   137  	}
   138  	defer resp.Body.Close()
   139  
   140  	bytes, err := ioutil.ReadAll(resp.Body); if err != nil {
   141  		return
   142  	}
   143  
   144  	subs := make([]map[string]interface{}, 0)
   145  	err = json.Unmarshal(bytes, &subs); if err != nil {
   146  		return
   147  	}
   148  
   149  	keys = make([]string, 0)
   150  	for _, doc := range subs {
   151  		if key, ok := doc["OrderId"]; ok {
   152  			keys = append(keys, key.(string))
   153  		}
   154  	}
   155  	return
   156  }