GetTransactionByRef retrieves a transaction from the database using the provided reference. It traces the operation using OpenTelemetry and returns the transaction or an error. Parameters: - ctx: Context for managing the request and tracing. - reference: The reference of the transaction to retrieve.
(ctx context.Context, reference string)
| 559 | // Returns: |
| 560 | // - A model.Transaction representing the transaction or an error if the retrieval fails. |
| 561 | func (d Datasource) GetTransactionByRef(ctx context.Context, reference string) (model.Transaction, error) { |
| 562 | // Start a new tracing span for the database operation |
| 563 | ctx, span := otel.Tracer("transaction.database").Start(ctx, "GetTransactionByRef") |
| 564 | defer span.End() |
| 565 | |
| 566 | // Query the transaction by reference |
| 567 | row := d.Conn.QueryRowContext(ctx, ` |
| 568 | SELECT transaction_id, source, reference, amount, precise_amount, currency, destination, description, status, created_at, meta_data, parent_transaction |
| 569 | FROM ledgerforge.transactions |
| 570 | WHERE reference = $1 |
| 571 | `, reference) |
| 572 | |
| 573 | // Initialize the transaction object and scan the query result into it |
| 574 | txn := model.Transaction{} |
| 575 | var metaDataJSON []byte |
| 576 | var preciseAmountStr string |
| 577 | err := row.Scan(&txn.TransactionID, &txn.Source, &txn.Reference, &txn.Amount, &preciseAmountStr, &txn.Currency, &txn.Destination, &txn.Description, &txn.Status, &txn.CreatedAt, &metaDataJSON, &txn.ParentTransaction) |
| 578 | if err != nil { |
| 579 | if err == sql.ErrNoRows { |
| 580 | span.RecordError(err) |
| 581 | return model.Transaction{}, apierror.NewAPIError(apierror.ErrNotFound, fmt.Sprintf("Transaction with reference '%s' not found", reference), err) |
| 582 | } |
| 583 | span.RecordError(err) |
| 584 | return model.Transaction{}, apierror.NewAPIError(apierror.ErrInternalServer, "Failed to retrieve transaction", err) |
| 585 | } |
| 586 | |
| 587 | // Unmarshal the metadata JSON into the transaction's MetaData field |
| 588 | err = json.Unmarshal(metaDataJSON, &txn.MetaData) |
| 589 | if err != nil { |
| 590 | span.RecordError(err) |
| 591 | return model.Transaction{}, apierror.NewAPIError(apierror.ErrInternalServer, "Failed to unmarshal metadata", err) |
| 592 | } |
| 593 | |
| 594 | txn.PreciseAmount, err = parseBigInt(preciseAmountStr) |
| 595 | if err != nil { |
| 596 | span.RecordError(err) |
| 597 | return model.Transaction{}, fmt.Errorf("failed to parse precise_amount: %w", err) |
| 598 | } |
| 599 | |
| 600 | // Log the successful transaction retrieval in the tracing span |
| 601 | span.AddEvent("Transaction retrieved by reference", trace.WithAttributes( |
| 602 | attribute.String("transaction.id", txn.TransactionID), |
| 603 | attribute.String("transaction.reference", txn.Reference), |
| 604 | )) |
| 605 | |
| 606 | return txn, nil |
| 607 | } |
| 608 | |
| 609 | // UpdateTransactionStatus updates the status of a transaction in the database. |
| 610 | // It traces the operation using OpenTelemetry and returns an error if the update fails or if the transaction is not found. |