|
9 | 9 | "github.com/alpacahq/alpacadecimal" |
10 | 10 | "github.com/samber/lo" |
11 | 11 |
|
| 12 | + "github.com/openmeterio/openmeter/openmeter/billing/charges" |
| 13 | + "github.com/openmeterio/openmeter/openmeter/billing/charges/meta" |
12 | 14 | "github.com/openmeterio/openmeter/openmeter/customer" |
13 | 15 | "github.com/openmeterio/openmeter/openmeter/ledger" |
14 | 16 | ledgeraccount "github.com/openmeterio/openmeter/openmeter/ledger/account" |
@@ -77,6 +79,7 @@ type CreditTransaction struct { |
77 | 79 | Amount alpacadecimal.Decimal |
78 | 80 | Balance CreditTransactionBalance |
79 | 81 | Name string |
| 82 | + Description *string |
80 | 83 | Annotations models.Annotations |
81 | 84 | } |
82 | 85 |
|
@@ -124,6 +127,8 @@ func (s *Service) ListCreditTransactions(ctx context.Context, input ListCreditTr |
124 | 127 | return ListCreditTransactionsResult{}, err |
125 | 128 | } |
126 | 129 |
|
| 130 | + s.applyChargeMetadataToCreditTransactions(ctx, input.CustomerID.Namespace, items) |
| 131 | + |
127 | 132 | if len(items) > 0 { |
128 | 133 | runningBalance, err := s.GetBalance(ctx, input.CustomerID, routeFilter(items[0].Currency), lo.ToPtr(result.Items[0].Cursor())) |
129 | 134 | if err != nil { |
@@ -212,7 +217,7 @@ func creditTransactionFromLedgerTransaction(tx ledger.Transaction) (CreditTransa |
212 | 217 | Type: creditTransactionType(amount), |
213 | 218 | Currency: entry.PostingAddress().Route().Route().Currency, |
214 | 219 | Amount: amount, |
215 | | - Name: creditTransactionName(tx), |
| 220 | + Name: "", |
216 | 221 | Annotations: tx.Annotations(), |
217 | 222 | }, nil |
218 | 223 | } |
@@ -251,11 +256,107 @@ func creditTransactionType(fboImpact alpacadecimal.Decimal) CreditTransactionTyp |
251 | 256 | return CreditTransactionTypeAdjusted |
252 | 257 | } |
253 | 258 |
|
254 | | -func creditTransactionName(tx ledger.Transaction) string { |
255 | | - templateName, _ := ledger.TransactionTemplateNameFromAnnotations(tx.Annotations()) |
256 | | - if templateName != "" { |
257 | | - return templateName |
| 259 | +type chargeDisplayMetadata struct { |
| 260 | + Name string |
| 261 | + Description *string |
| 262 | +} |
| 263 | + |
| 264 | +func (s *Service) applyChargeMetadataToCreditTransactions(ctx context.Context, namespace string, items []CreditTransaction) { |
| 265 | + chargeIDs := lo.Uniq(lo.FilterMap(items, func(item CreditTransaction, _ int) (string, bool) { |
| 266 | + id := chargeIDFromAnnotations(item.Annotations) |
| 267 | + return id, id != "" |
| 268 | + })) |
| 269 | + |
| 270 | + if len(chargeIDs) == 0 { |
| 271 | + return |
| 272 | + } |
| 273 | + |
| 274 | + chargeEntities, err := s.ChargesService.GetByIDs(ctx, charges.GetByIDsInput{ |
| 275 | + Namespace: namespace, |
| 276 | + IDs: chargeIDs, |
| 277 | + }) |
| 278 | + if err != nil { |
| 279 | + return |
| 280 | + } |
| 281 | + |
| 282 | + chargeDisplayByID := make(map[string]chargeDisplayMetadata, len(chargeEntities)) |
| 283 | + for _, chargeEntity := range chargeEntities { |
| 284 | + chargeID, err := chargeEntity.GetChargeID() |
| 285 | + if err != nil { |
| 286 | + continue |
| 287 | + } |
| 288 | + |
| 289 | + metadata, err := chargeDisplayMetadataFromCharge(chargeEntity) |
| 290 | + if err != nil { |
| 291 | + continue |
| 292 | + } |
| 293 | + |
| 294 | + chargeDisplayByID[chargeID.ID] = metadata |
| 295 | + } |
| 296 | + |
| 297 | + for i := range items { |
| 298 | + chargeID := chargeIDFromAnnotations(items[i].Annotations) |
| 299 | + if chargeID == "" { |
| 300 | + continue |
| 301 | + } |
| 302 | + |
| 303 | + metadata, ok := chargeDisplayByID[chargeID] |
| 304 | + if !ok { |
| 305 | + continue |
| 306 | + } |
| 307 | + |
| 308 | + items[i].Name = metadata.Name |
| 309 | + items[i].Description = metadata.Description |
| 310 | + } |
| 311 | +} |
| 312 | + |
| 313 | +func chargeDisplayMetadataFromCharge(charge charges.Charge) (chargeDisplayMetadata, error) { |
| 314 | + switch charge.Type() { |
| 315 | + case meta.ChargeTypeFlatFee: |
| 316 | + flatFeeCharge, err := charge.AsFlatFeeCharge() |
| 317 | + if err != nil { |
| 318 | + return chargeDisplayMetadata{}, fmt.Errorf("map flat fee charge: %w", err) |
| 319 | + } |
| 320 | + |
| 321 | + return chargeDisplayMetadata{ |
| 322 | + Name: flatFeeCharge.Intent.Name, |
| 323 | + Description: flatFeeCharge.Intent.Description, |
| 324 | + }, nil |
| 325 | + case meta.ChargeTypeUsageBased: |
| 326 | + usageBasedCharge, err := charge.AsUsageBasedCharge() |
| 327 | + if err != nil { |
| 328 | + return chargeDisplayMetadata{}, fmt.Errorf("map usage based charge: %w", err) |
| 329 | + } |
| 330 | + |
| 331 | + return chargeDisplayMetadata{ |
| 332 | + Name: usageBasedCharge.Intent.Name, |
| 333 | + Description: usageBasedCharge.Intent.Description, |
| 334 | + }, nil |
| 335 | + case meta.ChargeTypeCreditPurchase: |
| 336 | + creditPurchaseCharge, err := charge.AsCreditPurchaseCharge() |
| 337 | + if err != nil { |
| 338 | + return chargeDisplayMetadata{}, fmt.Errorf("map credit purchase charge: %w", err) |
| 339 | + } |
| 340 | + |
| 341 | + return chargeDisplayMetadata{ |
| 342 | + Name: creditPurchaseCharge.Intent.Name, |
| 343 | + Description: creditPurchaseCharge.Intent.Description, |
| 344 | + }, nil |
| 345 | + default: |
| 346 | + return chargeDisplayMetadata{}, fmt.Errorf("unsupported charge type %s", charge.Type()) |
| 347 | + } |
| 348 | +} |
| 349 | + |
| 350 | +func chargeIDFromAnnotations(annotations models.Annotations) string { |
| 351 | + raw, ok := annotations[ledger.AnnotationChargeID] |
| 352 | + if !ok { |
| 353 | + return "" |
| 354 | + } |
| 355 | + |
| 356 | + value, ok := raw.(string) |
| 357 | + if !ok { |
| 358 | + return "" |
258 | 359 | } |
259 | 360 |
|
260 | | - return "credit_transaction" |
| 361 | + return value |
261 | 362 | } |
0 commit comments