package merch import ( "context" "errors" "fmt" "github.com/google/uuid" "merch-api/internal/user" "merch-api/pkg/utils" ) const serviceLogHeader string = "[Service]" type service struct { repo Repository utils utils.Utils userProvider user.Provider } func newService(repo Repository, u utils.Utils, up user.Provider) *service { return &service{ repo: repo, utils: u, userProvider: up, } } //origins func (s *service) createOrigin(ctx context.Context, o *newOriginDTO) error { newOrigin := &Origin{ CreatedAt: s.utils.TimeNowUTC(), DeletedAt: s.utils.DeletedNullTime(), Name: o.Name, } logDebug(serviceLogHeader, "create origin success") return s.repo.createOrigin(ctx, newOrigin) } func (s *service) getOrigins(ctx context.Context) (*originsDTO, error) { data, err := s.repo.getOrigins(ctx) if err != nil { logErr(serviceLogHeader, err) return nil, err } var origins []originItem for _, item := range data { origins = append(origins, originItem{ Id: item.Id, Name: item.Name, }) } response := &originsDTO{ Origins: origins, } logDebug(serviceLogHeader, "get origins success") return response, nil } func (s *service) deleteOrigin(ctx context.Context, origin *deleteOriginDTO) error { logDebug(serviceLogHeader, "delete origin success") return s.repo.deleteOriginByName(ctx, origin.Name, s.utils.NullTimeNowUTC()) } // merch func (s *service) createMerch(ctx context.Context, userId int64, payload *newMerchDTO) error { now := s.utils.TimeNowUTC() nullNow := s.utils.NullTimeFromNow(now) empty := s.utils.DeletedNullTime() merchUuid, err := uuid.NewV7() if err != nil { logErr(serviceLogHeader, err) return err } newMerch := &Merch{ CreatedAt: now, UpdatedAt: nullNow, DeletedAt: empty, MerchUuid: merchUuid.String(), UserId: userId, Name: payload.Name, } var merchExtra []ExtraData if payload.Links != nil { originsMap, _, err := s.getOriginsMaps(ctx) if err != nil { logErr(serviceLogHeader, err) return err } for _, item := range payload.Links { merchExtra = append(merchExtra, ExtraData{ CreatedAt: now, UpdatedAt: nullNow, DeletedAt: empty, MerchId: 0, OriginId: originsMap[item.Origin], URL: item.Link, }) } } return s.repo.createMerch(ctx, newMerch, merchExtra) } // getOriginsMaps // first return name:id // second id:name func (s *service) getOriginsMaps(ctx context.Context) (map[string]int64, map[int64]string, error) { origins, err := s.repo.getOrigins(ctx) if err != nil { logErr(serviceLogHeader, err) return nil, nil, err } namesMap := make(map[string]int64, len(origins)) idsMap := make(map[int64]string, len(origins)) for _, origin := range origins { namesMap[origin.Name] = origin.Id idsMap[origin.Id] = origin.Name } return namesMap, idsMap, nil } func (s *service) getMerchUuidMap(ctx context.Context, uuids []string) (map[string]int64, error) { return s.repo.getMerchUuidMap(ctx, uuids) } func (s *service) getMany(ctx context.Context, userId int64) ([]merchDTO, error) { return s.repo.getMany(ctx, userId) } func (s *service) updateMerch(ctx context.Context, userId int64, payload *updateMerchDTO) (*merchDTO, error) { return s.repo.updateMerch(ctx, userId, payload) } func (s *service) updateExtraData(ctx context.Context, userId int64, payload *extraDataDTO) (*extraDataDTO, error) { merchId, err := s.repo.getMerchIdByUuid(ctx, userId, payload.MerchUuid) if err != nil { logErr(serviceLogHeader, err) return nil, err } origins, ids, err := s.getOriginsMaps(ctx) if err != nil { logErr(serviceLogHeader, err) return nil, err } var insertData []ExtraData for _, item := range payload.Links { if _, ok := origins[item.Origin]; !ok { continue } now := s.utils.TimeNowUTC() insertData = append(insertData, ExtraData{ CreatedAt: now, UpdatedAt: s.utils.NullTimeFromNow(now), OriginId: origins[item.Origin], URL: item.Link, }) } result, err := s.repo.updateExtraData(ctx, merchId, insertData) if err != nil { logErr(serviceLogHeader, err) return nil, err } if result == nil || len(result) == 0 { return nil, nil } var ol []originLink for _, item := range result { ol = append(ol, originLink{ Origin: ids[item.OriginId], Link: item.URL, }) } return &extraDataDTO{ MerchUuid: payload.MerchUuid, Links: ol, }, nil } func (s *service) deleteOneMerchRecord(ctx context.Context, userId int64, merchUuid string) error { return s.repo.deleteOneMerchRecord(ctx, userId, merchUuid, s.utils.TimeNowUTC()) } func (s *service) getPrices(ctx context.Context, userId int64, days int) ([]PricesResponse, error) { fmt.Println("Enter service") merchList, err := s.repo.getAllUserMerch(ctx, userId) if err != nil { logErr(serviceLogHeader, err) return nil, err } if len(merchList) == 0 { errMsg := errors.New("no merch found") logErr(serviceLogHeader, errMsg) return nil, errMsg } merchMap := make(map[int64]Merch, len(merchList)) for _, merch := range merchList { merchMap[merch.Id] = merch } var response []PricesResponse for _, item := range merchList { response = append(response, PricesResponse{ MerchUuid: item.MerchUuid, Name: item.Name, Origins: []OriginWithPrices{}, }) } pricesList, err := s.repo.getPricesWithDays(ctx, userId, getPeriod(days)) if err != nil { logErr(serviceLogHeader, err) return nil, err } _, originNamesMap, err := s.getOriginsMaps(ctx) if err != nil { logErr(serviceLogHeader, err) return nil, err } pricesMap := make(map[string]map[string][]PriceEntry) for _, item := range pricesList { merchUuid := merchMap[item.MerchId].MerchUuid if _, ok := pricesMap[merchUuid]; !ok { pricesMap[merchUuid] = make(map[string][]PriceEntry) } originName := originNamesMap[item.OriginId] pricesMap[merchUuid][originName] = append(pricesMap[merchUuid][originName], PriceEntry{ CreatedAt: item.CreatedAt.Unix(), Value: item.Price, }) } for i := range response { for _, name := range originNamesMap { prices := pricesMap[response[i].MerchUuid][name] if prices == nil { continue } response[i].Origins = append(response[i].Origins, OriginWithPrices{ Origin: name, Prices: prices, }) } } return response, nil } func (s *service) getDistinctPrices(ctx context.Context, userId int64, merchUuid string, days int) (*PricesResponse, error) { result, err := s.repo.getDistinctPrices(ctx, userId, merchUuid, getPeriod(days)) if err != nil { logErr(serviceLogHeader, err) return nil, err } if result == nil { return nil, nil } _, originNamesMap, err := s.getOriginsMaps(ctx) if err != nil { logErr(serviceLogHeader, err) return nil, err } response := PricesResponse{ MerchUuid: merchUuid, Origins: []OriginWithPrices{}, } pricesMap := make(map[string][]PriceEntry) for _, item := range result { originName := originNamesMap[item.OriginId] if _, ok := pricesMap[originName]; !ok { pricesMap[originName] = make([]PriceEntry, 0) } pricesMap[originName] = append(pricesMap[originName], PriceEntry{ CreatedAt: item.CreatedAt.Unix(), Value: item.Price, }) } for key, item := range pricesMap { response.Origins = append(response.Origins, OriginWithPrices{ Origin: key, Prices: item, }) } return &response, nil }