Skip to content
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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

turip
Copy link
Contributor

@turip turip commented Nov 12, 2024

Overview

Fixes #(issue)

Notes for reviewer

@turip turip force-pushed the feat/invoice-line-details-calculations branch from 448fadb to b617e83 Compare November 12, 2024 16:34
@@ -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")
Copy link
Contributor

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

Copy link
Contributor Author

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
Copy link
Contributor

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").
Copy link
Contributor

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),
Copy link
Contributor

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?

Copy link
Contributor Author

@turip turip Nov 14, 2024

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),
Copy link
Contributor

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),
Copy link
Contributor

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{
Copy link
Contributor

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{
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants