File size: 3,843 Bytes
d6f631f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package httpdriver

import (
	"errors"
	"fmt"

	"github.com/samber/lo"

	"github.com/openmeterio/openmeter/api"
	productcataloghttp "github.com/openmeterio/openmeter/openmeter/productcatalog/http"
	subscriptionhttp "github.com/openmeterio/openmeter/openmeter/productcatalog/subscription/http"
	"github.com/openmeterio/openmeter/openmeter/subscription"
	subscriptionaddon "github.com/openmeterio/openmeter/openmeter/subscription/addon"
	addondiff "github.com/openmeterio/openmeter/openmeter/subscription/addon/diff"
	subscriptionworkflow "github.com/openmeterio/openmeter/openmeter/subscription/workflow"
	"github.com/openmeterio/openmeter/pkg/clock"
	"github.com/openmeterio/openmeter/pkg/slicesx"
	"github.com/openmeterio/openmeter/pkg/timeutil"
)

func MapCreateSubscriptionAddonRequestToInput(req api.SubscriptionAddonCreate) (subscriptionworkflow.AddAddonWorkflowInput, error) {
	timing, err := subscriptionhttp.MapAPITimingToTiming(req.Timing)
	if err != nil {
		return subscriptionworkflow.AddAddonWorkflowInput{}, fmt.Errorf("failed to cast Timing: %w", err)
	}

	r := subscriptionworkflow.AddAddonWorkflowInput{
		AddonID:         req.Addon.Id,
		InitialQuantity: req.Quantity,
		Timing:          timing,
	}

	if req.Metadata != nil {
		r.MetadataModel.Metadata = lo.FromPtr(req.Metadata)
	}

	return r, nil
}

func MapSubscriptionAddonToResponse(view subscription.SubscriptionView, addon subscriptionaddon.SubscriptionAddon) (api.SubscriptionAddon, error) {
	now := clock.Now()

	// If instance is not found, quantity will be 0
	inst, _ := addon.GetInstanceAt(now)

	pers := lo.Map(addon.GetInstances(), func(i subscriptionaddon.SubscriptionAddonInstance, _ int) timeutil.OpenPeriod {
		return i.AsPeriod()
	})

	if len(pers) == 0 {
		return api.SubscriptionAddon{}, errors.New("no instances found")
	}

	union := lo.Reduce(pers, func(agg timeutil.OpenPeriod, item timeutil.OpenPeriod, _ int) timeutil.OpenPeriod {
		return agg.Union(item)
	}, pers[0])

	affectedMap := addondiff.GetAffectedItemIDs(view, addon)

	rateCards, err := slicesx.MapWithErr(addon.RateCards, func(r subscriptionaddon.SubscriptionAddonRateCard) (api.SubscriptionAddonRateCard, error) {
		rc, err := productcataloghttp.FromRateCard(r.AddonRateCard.RateCard)
		if err != nil {
			return api.SubscriptionAddonRateCard{}, fmt.Errorf("failed to cast RateCard: %w", err)
		}

		ids := affectedMap[r.AddonRateCard.RateCard.Key()]

		return api.SubscriptionAddonRateCard{
			RateCard:                    rc,
			AffectedSubscriptionItemIds: ids,
		}, nil
	})
	if err != nil {
		return api.SubscriptionAddon{}, fmt.Errorf("failed to cast RateCards: %w", err)
	}

	return api.SubscriptionAddon{
		Id:             addon.ID,
		CreatedAt:      addon.CreatedAt,
		UpdatedAt:      addon.UpdatedAt,
		DeletedAt:      addon.DeletedAt,
		Metadata:       lo.EmptyableToPtr(api.Metadata(addon.Metadata)),
		Description:    addon.Description,
		Name:           addon.Name,
		SubscriptionId: addon.SubscriptionID,
		Addon: struct {
			Id           string                "json:\"id\""
			InstanceType api.AddonInstanceType "json:\"instanceType\""
			Key          string                "json:\"key\""
			Version      int                   "json:\"version\""
		}{
			Id:           addon.Addon.ID,
			InstanceType: api.AddonInstanceType(addon.Addon.InstanceType),
			Key:          addon.Addon.Key,
			Version:      addon.Addon.Version,
		},
		ActiveFrom: *union.From,
		ActiveTo:   union.To,
		Quantity:   inst.Quantity,
		QuantityAt: now,
		Timeline: lo.Map(addon.GetInstances(), func(i subscriptionaddon.SubscriptionAddonInstance, _ int) api.SubscriptionAddonTimelineSegment {
			return api.SubscriptionAddonTimelineSegment{
				Quantity:   i.Quantity,
				ActiveFrom: i.CadencedModel.ActiveFrom,
				ActiveTo:   i.CadencedModel.ActiveTo,
			}
		}),
		RateCards: rateCards,
	}, nil
}