-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/invoice line details calculations #1834
base: main
Are you sure you want to change the base?
Conversation
448fadb
to
b617e83
Compare
@@ -28,6 +28,8 @@ var ( | |||
ErrInvoiceActionNotAvailable = NewValidationError("invoice_action_not_available", "invoice action not available") | |||
|
|||
ErrInvoiceLineFeatureHasNoMeters = NewValidationError("invoice_line_feature_has_no_meters", "usage based invoice line: feature has no meters") | |||
ErrInvoiceLineGraduatedSplitNotSupported = NewValidationError("invoice_line_graduated_split_not_supported", "graduated tiered pricing is not supported for split periods") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be registered in httpdriver
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these are wrapped into ValidationErrors or whatever error it should be reported as, and that is the thing that the HTTP driver handles.
I can only add a fallback, but regardless the previous logic should ensure proper error codes.
} | ||
} | ||
|
||
// Technically this should not happen, as the last tier should have an upper limit of infinity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return err?
// As entgo doesn't support conditional unique indexes, defaults to ID of the | ||
// line. | ||
// TODO: add hooks | ||
field.String("child_unique_reference_id"). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See apps:
index.Fields("namespace", "type", "is_default").
Annotations(
entsql.IndexWhere("is_default = true"),
).
Unique(),
expect: newDetailedLinesInput{ | ||
{ | ||
Name: "feature: usage in period", | ||
Amount: alpacadecimal.NewFromFloat(10), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be 100?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there was 10 usage, at 10/unit price.
The amount here reflects the unit price. We should rename it to Unit Price. But on a line level this is always per unit amount.
Once the calculations are done there will be a few more fields, such as Sum (Qty * UnitPrice, currency rounding), Total for line total different line total value, most probably based on this: https://docs.gobl.org/draft-0/bill/line
UpToAmount: lo.ToPtr(alpacadecimal.NewFromFloat(5)), | ||
FlatPrice: &plan.PriceTierFlatPrice{ | ||
// 20/unit | ||
Amount: alpacadecimal.NewFromFloat(100), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tiered pricing means units prices on amount see:
https://openmeter.io/blog/tiered-pricing-model#example-comparison
So the unit price will be $100 for for the first 5 items not $20
}), | ||
lineMode: lastInPeriodSplitLineMode, | ||
usage: featureUsageResponse{ | ||
LinePeriodQty: alpacadecimal.NewFromFloat(100), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a test with 14 and 15 qty would be more useful
} | ||
|
||
func TestTieredVolumeCalculation(t *testing.T) { | ||
testTiers := []plan.PriceTier{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On volume based each unit is billed on the highest achieved discount, see:
https://openmeter.io/blog/tiered-pricing-model#example-comparison
usage: featureUsageResponse{ | ||
LinePeriodQty: alpacadecimal.NewFromFloat(22), | ||
}, | ||
expect: newDetailedLinesInput{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on qty 22 we should have only one line item on the highest discount, see:
https://openmeter.io/blog/tiered-pricing-model#example-comparison
Overview
Fixes #(issue)
Notes for reviewer