@@ -10,20 +10,26 @@ import (
1010
1111 "github.com/openmeterio/openmeter/openmeter/billing"
1212 "github.com/openmeterio/openmeter/pkg/clock"
13+ "github.com/openmeterio/openmeter/pkg/entitydiff"
1314 "github.com/openmeterio/openmeter/pkg/models"
1415)
1516
16- type idDiff = diff [string ]
17+ type idDiff struct {
18+ ToCreate []string
19+ ToUpdate []string
20+ ToDelete []string
21+ }
1722
1823type lineDiffExpectation struct {
19- LineBase idDiff
20- FlatFee idDiff
21- UsageBased idDiff
24+ Line idDiff
2225
2326 AmountDiscounts idDiff
2427
25- AffectedLineIDs []string
26- ChildrenDiff * lineDiffExpectation
28+ DetailedLine idDiff
29+ DetailedLineAmountDiscounts idDiff
30+
31+ AffectedLineIDs []string
32+ DetailedLineAffectedLineIDs []string
2733}
2834
2935func TestInvoiceLineDiffing (t * testing.T ) {
@@ -33,9 +39,9 @@ func TestInvoiceLineDiffing(t *testing.T) {
3339 ManagedResource : models .NewManagedResource (models.ManagedResourceInput {
3440 ID : "1" ,
3541 }),
36- Type : billing .InvoiceLineTypeFee ,
42+ Type : billing .InvoiceLineTypeUsageBased ,
3743 },
38- FlatFee : & billing.FlatFeeLine {},
44+ UsageBased : & billing.UsageBasedLine {},
3945 },
4046 {
4147 LineBase : billing.LineBase {
@@ -76,25 +82,14 @@ func TestInvoiceLineDiffing(t *testing.T) {
7682 require .NoError (t , err )
7783
7884 requireDiff (t , lineDiffExpectation {
79- LineBase : idDiff {
85+ Line : idDiff {
8086 ToCreate : []string {"1" , "2" },
8187 },
82- FlatFee : idDiff {
83- ToCreate : []string {"1 " },
88+ DetailedLine : idDiff {
89+ ToCreate : []string {"2.1" , "2.2 " },
8490 },
85- UsageBased : idDiff {
86- ToCreate : []string {"2" },
87- },
88- ChildrenDiff : & lineDiffExpectation {
89- LineBase : idDiff {
90- ToCreate : []string {"2.1" , "2.2" },
91- },
92- FlatFee : idDiff {
93- ToCreate : []string {"2.1" , "2.2" },
94- },
95- AmountDiscounts : idDiff {
96- ToCreate : []string {"D2.1.1" },
97- },
91+ DetailedLineAmountDiscounts : idDiff {
92+ ToCreate : []string {"D2.1.1" },
9893 },
9994 }, lineDiff )
10095 })
@@ -120,16 +115,11 @@ func TestInvoiceLineDiffing(t *testing.T) {
120115
121116 requireDiff (t , lineDiffExpectation {
122117 AffectedLineIDs : []string {"2" },
123- ChildrenDiff : & lineDiffExpectation {
124- LineBase : idDiff {
125- ToDelete : []string {"2.1" },
126- },
127- // Flat fee is not deleted as it does not have soft delete, so it's enough to mark the line as deleted
128- FlatFee : idDiff {},
129- AmountDiscounts : idDiff {
130- // Discounts also get deleted
131- ToDelete : []string {"D2.1.1" },
132- },
118+ DetailedLine : idDiff {
119+ ToDelete : []string {"2.1" },
120+ },
121+ DetailedLineAmountDiscounts : idDiff {
122+ ToDelete : []string {"D2.1.1" },
133123 },
134124 }, lineDiff )
135125 })
@@ -145,13 +135,8 @@ func TestInvoiceLineDiffing(t *testing.T) {
145135
146136 requireDiff (t , lineDiffExpectation {
147137 AffectedLineIDs : []string {"2" },
148- ChildrenDiff : & lineDiffExpectation {
149- LineBase : idDiff {
150- ToUpdate : []string {"2.1" },
151- },
152- FlatFee : idDiff {
153- ToUpdate : []string {"2.1" },
154- },
138+ DetailedLine : idDiff {
139+ ToUpdate : []string {"2.1" },
155140 },
156141 }, lineDiff )
157142 })
@@ -166,10 +151,7 @@ func TestInvoiceLineDiffing(t *testing.T) {
166151 require .NoError (t , err )
167152
168153 requireDiff (t , lineDiffExpectation {
169- LineBase : idDiff {
170- ToUpdate : []string {"2" },
171- },
172- UsageBased : idDiff {
154+ Line : idDiff {
173155 ToUpdate : []string {"2" },
174156 },
175157 }, lineDiff )
@@ -191,19 +173,14 @@ func TestInvoiceLineDiffing(t *testing.T) {
191173
192174 requireDiff (t , lineDiffExpectation {
193175 AffectedLineIDs : []string {"2" },
194- ChildrenDiff : & lineDiffExpectation {
195- LineBase : idDiff {
196- ToDelete : []string {"2.1" },
197- ToCreate : []string {"2.3" },
198- },
199- FlatFee : idDiff {
200- ToCreate : []string {"2.3" },
201- },
202- AmountDiscounts : idDiff {
203- // The discount gets deleted + created
204- ToCreate : []string {"D2.1.3" },
205- ToDelete : []string {"D2.1.1" },
206- },
176+ DetailedLine : idDiff {
177+ ToDelete : []string {"2.1" },
178+ ToCreate : []string {"2.3" },
179+ },
180+ DetailedLineAmountDiscounts : idDiff {
181+ // The discount gets deleted + created
182+ ToCreate : []string {"D2.1.3" },
183+ ToDelete : []string {"D2.1.1" },
207184 },
208185 }, lineDiff )
209186 })
@@ -219,11 +196,10 @@ func TestInvoiceLineDiffing(t *testing.T) {
219196 require .NoError (t , err )
220197
221198 requireDiff (t , lineDiffExpectation {
222- AffectedLineIDs : []string {"2" , "2.1" },
223- ChildrenDiff : & lineDiffExpectation {
224- AmountDiscounts : idDiff {
225- ToDelete : []string {"D2.1.1" },
226- },
199+ AffectedLineIDs : []string {"2" },
200+ DetailedLineAffectedLineIDs : []string {"2.1" },
201+ DetailedLineAmountDiscounts : idDiff {
202+ ToDelete : []string {"D2.1.1" },
227203 },
228204 }, lineDiff )
229205 })
@@ -238,11 +214,10 @@ func TestInvoiceLineDiffing(t *testing.T) {
238214 require .NoError (t , err )
239215
240216 requireDiff (t , lineDiffExpectation {
241- AffectedLineIDs : []string {"2" , "2.1" },
242- ChildrenDiff : & lineDiffExpectation {
243- AmountDiscounts : idDiff {
244- ToUpdate : []string {"D2.1.1" },
245- },
217+ AffectedLineIDs : []string {"2" },
218+ DetailedLineAffectedLineIDs : []string {"2.1" },
219+ DetailedLineAmountDiscounts : idDiff {
220+ ToUpdate : []string {"D2.1.1" },
246221 },
247222 }, lineDiff )
248223 })
@@ -260,12 +235,11 @@ func TestInvoiceLineDiffing(t *testing.T) {
260235 require .NoError (t , err )
261236
262237 requireDiff (t , lineDiffExpectation {
263- AffectedLineIDs : []string {"2" , "2.1" },
264- ChildrenDiff : & lineDiffExpectation {
265- AmountDiscounts : idDiff {
266- ToCreate : []string {"D2.1.2" },
267- ToDelete : []string {"D2.1.1" },
268- },
238+ AffectedLineIDs : []string {"2" },
239+ DetailedLineAffectedLineIDs : []string {"2.1" },
240+ DetailedLineAmountDiscounts : idDiff {
241+ ToCreate : []string {"D2.1.2" },
242+ ToDelete : []string {"D2.1.1" },
269243 },
270244 }, lineDiff )
271245 })
@@ -282,13 +256,11 @@ func TestInvoiceLineDiffing(t *testing.T) {
282256
283257 requireDiff (t , lineDiffExpectation {
284258 AffectedLineIDs : []string {"2" },
285- ChildrenDiff : & lineDiffExpectation {
286- LineBase : idDiff {
287- ToDelete : []string {"2.1" },
288- },
289- AmountDiscounts : idDiff {
290- ToDelete : []string {"D2.1.1" },
291- },
259+ DetailedLine : idDiff {
260+ ToDelete : []string {"2.1" },
261+ },
262+ DetailedLineAmountDiscounts : idDiff {
263+ ToDelete : []string {"D2.1.1" },
292264 },
293265 }, lineDiff )
294266 })
@@ -303,16 +275,14 @@ func TestInvoiceLineDiffing(t *testing.T) {
303275 require .NoError (t , err )
304276
305277 requireDiff (t , lineDiffExpectation {
306- LineBase : idDiff {
278+ Line : idDiff {
307279 ToDelete : []string {"2" },
308280 },
309- ChildrenDiff : & lineDiffExpectation {
310- LineBase : idDiff {
311- ToDelete : []string {"2.1" , "2.2" },
312- },
313- AmountDiscounts : idDiff {
314- ToDelete : []string {"D2.1.1" },
315- },
281+ DetailedLine : idDiff {
282+ ToDelete : []string {"2.1" , "2.2" },
283+ },
284+ DetailedLineAmountDiscounts : idDiff {
285+ ToDelete : []string {"D2.1.1" },
316286 },
317287 }, lineDiff )
318288 })
@@ -327,7 +297,7 @@ func TestInvoiceLineDiffing(t *testing.T) {
327297 require .NoError (t , err )
328298
329299 requireDiff (t , lineDiffExpectation {
330- LineBase : idDiff {
300+ Line : idDiff {
331301 ToDelete : []string {"1" },
332302 },
333303 }, lineDiff )
@@ -344,66 +314,19 @@ func TestInvoiceLineDiffing(t *testing.T) {
344314
345315 requireDiff (t , lineDiffExpectation {}, lineDiff )
346316 })
347-
348- t .Run ("deleted, changed lines are not triggering updates" , func (t * testing.T ) {
349- base := cloneLines (template )
350- base [1 ].DeletedAt = lo .ToPtr (clock .Now ())
351- base [1 ].Children .GetByID ("2.1" ).DeletedAt = lo .ToPtr (clock .Now ())
352-
353- snapshotAsDBState (base )
354- base [1 ].DeletedAt = nil
355- base [1 ].Children .GetByID ("2.1" ).DeletedAt = nil
356-
357- lineDiff , err := diffInvoiceLines (base )
358- require .NoError (t , err )
359-
360- requireDiff (t , lineDiffExpectation {
361- LineBase : idDiff {
362- ToUpdate : []string {"2" },
363- },
364- ChildrenDiff : & lineDiffExpectation {
365- LineBase : idDiff {
366- ToUpdate : []string {"2.1" },
367- },
368- },
369- }, lineDiff )
370- })
371- }
372-
373- func mapLinesToIDs (lines []* billing.Line ) []string {
374- return lo .Map (lines , func (line * billing.Line , _ int ) string {
375- // Use description as ID if it's set, so that we can predict the new line's ID for new
376- // line testcases
377- if line .Description != nil {
378- return * line .Description
379- }
380- return line .ID
381- })
382- }
383-
384- func mapLineDiffToIDs (in diff [* billing.Line ]) idDiff {
385- return idDiff {
386- ToCreate : mapLinesToIDs (in .ToCreate ),
387- ToUpdate : mapLinesToIDs (in .ToUpdate ),
388- ToDelete : mapLinesToIDs (in .ToDelete ),
389- }
390- }
391-
392- func mapLineDiscountsToIDs (t * testing.T , discounts []withParent [billing.AmountLineDiscountManaged , * billing.Line ]) []string {
393- return lo .Map (discounts , func (d withParent [billing.AmountLineDiscountManaged , * billing.Line ], _ int ) string {
394- if d .Entity .Description != nil {
395- return * d .Entity .Description
396- }
397-
398- return d .Entity .GetID ()
399- })
400317}
401318
402- func mapLineDiscountDiffToIDs ( t * testing. T , in diff [ withParent [billing. AmountLineDiscountManaged , * billing. Line ]] ) idDiff {
319+ func mapDiffToIDs [ T entitydiff. Entity ]( in entitydiff. Diff [ T ], getDescription func ( T ) * string ) idDiff {
403320 return idDiff {
404- ToCreate : mapLineDiscountsToIDs (t , in .ToCreate ),
405- ToUpdate : mapLineDiscountsToIDs (t , in .ToUpdate ),
406- ToDelete : mapLineDiscountsToIDs (t , in .ToDelete ),
321+ ToCreate : lo .Map (in .Create , func (item T , _ int ) string {
322+ return lo .FromPtrOr (getDescription (item ), item .GetID ())
323+ }),
324+ ToUpdate : lo .Map (in .Update , func (item entitydiff.DiffUpdate [T ], _ int ) string {
325+ return lo .FromPtrOr (getDescription (item .PersistedState ), item .PersistedState .GetID ())
326+ }),
327+ ToDelete : lo .Map (in .Delete , func (item T , _ int ) string {
328+ return lo .FromPtrOr (getDescription (item ), item .GetID ())
329+ }),
407330 }
408331}
409332
@@ -420,35 +343,27 @@ func msgPrefix(prefix string, in ...interface{}) []interface{} {
420343 return in
421344}
422345
423- func requireIdDiffMatches (t * testing.T , a , b idDiff , msgAndArgs ... interface {}) {
424- t .Helper ()
425-
426- require .ElementsMatch (t , a .ToCreate , b .ToCreate , msgPrefix ("ToCreate" , msgAndArgs ... ))
427- require .ElementsMatch (t , a .ToUpdate , b .ToUpdate , msgPrefix ("ToUpdate" , msgAndArgs ... ))
428- require .ElementsMatch (t , a .ToDelete , b .ToDelete , msgPrefix ("ToDelete" , msgAndArgs ... ))
429- }
430-
431- func requireDiffWithoutChildren (t * testing.T , expected lineDiffExpectation , actual * invoiceLineDiff , prefix string ) {
346+ func requireIdDiffMatches [T entitydiff.Entity ](t * testing.T , a idDiff , b entitydiff.Diff [T ], getDescription func (T ) * string , msgAndArgs ... interface {}) {
432347 t .Helper ()
433348
434- requireIdDiffMatches (t , expected .LineBase , mapLineDiffToIDs (actual .LineBase ), prefix + ": LineBase" )
435- requireIdDiffMatches (t , expected .FlatFee , mapLineDiffToIDs (actual .FlatFee ), prefix + ": FlatFee" )
436- requireIdDiffMatches (t , expected .UsageBased , mapLineDiffToIDs (actual .UsageBased ), prefix + ": UsageBased" )
349+ idDiffB := mapDiffToIDs (b , getDescription )
437350
438- requireIdDiffMatches (t , expected .AmountDiscounts , mapLineDiscountDiffToIDs (t , actual .AmountDiscounts ), prefix + ": AmountDiscounts" )
351+ require .ElementsMatch (t , a .ToCreate , idDiffB .ToCreate , msgPrefix ("ToCreate" , msgAndArgs ... ))
352+ require .ElementsMatch (t , a .ToUpdate , idDiffB .ToUpdate , msgPrefix ("ToUpdate" , msgAndArgs ... ))
353+ require .ElementsMatch (t , a .ToDelete , idDiffB .ToDelete , msgPrefix ("ToDelete" , msgAndArgs ... ))
439354}
440355
441- func requireDiff (t * testing.T , expected lineDiffExpectation , actual * invoiceLineDiff ) {
356+ func requireDiff (t * testing.T , expected lineDiffExpectation , actual invoiceLineDiff ) {
442357 t .Helper ()
443- requireDiffWithoutChildren (t , expected , actual , "root diff" )
444- require .ElementsMatch (t , expected .AffectedLineIDs , actual .AffectedLineIDs .AsSlice (), "affectedLineIDs" )
445358
446- childrenExpectation := expected .ChildrenDiff
447- if childrenExpectation == nil {
448- childrenExpectation = & lineDiffExpectation {}
449- }
359+ requireIdDiffMatches (t , expected .Line , actual .Line , func (line * billing.Line ) * string { return line .GetDescription () }, "line diff" )
360+ requireIdDiffMatches (t , expected .AmountDiscounts , actual .AmountDiscounts , func (discount amountLineDiscountManagedWithLine ) * string { return discount .Entity .Description }, "amount discounts" )
361+
362+ requireIdDiffMatches (t , expected .DetailedLine , actual .DetailedLine , func (line detailedLineWithParent ) * string { return line .Entity .GetDescription () }, "detailed line diff" )
363+ requireIdDiffMatches (t , expected .DetailedLineAmountDiscounts , actual .DetailedLineAmountDiscounts , func (discount amountLineDiscountManagedWithLine ) * string { return discount .Entity .Description }, "detailed line amount discounts" )
450364
451- requireDiffWithoutChildren (t , * childrenExpectation , actual .ChildrenDiff , "children diff" )
365+ require .ElementsMatch (t , expected .AffectedLineIDs , actual .AffectedLineIDs .AsSlice (), "affected line IDs" )
366+ require .ElementsMatch (t , expected .DetailedLineAffectedLineIDs , actual .DetailedLineAffectedLineIDs .AsSlice (), "detailed line affected line IDs" )
452367}
453368
454369func cloneLines (lines []* billing.Line ) []* billing.Line {
0 commit comments