diff --git a/datafetcher/handlers/accounts.go b/datafetcher/handlers/accounts.go index 6b8b884..0418aba 100644 --- a/datafetcher/handlers/accounts.go +++ b/datafetcher/handlers/accounts.go @@ -6,6 +6,7 @@ import ( "log" "net/http" + "github.com/a-h/templ" "github.com/esteanes/expense-manager/datafetcher/templates" "github.com/esteanes/expense-manager/datafetcher/upclient" ) @@ -17,27 +18,72 @@ type AccountHandler struct { func NewAccountHandler(log *log.Logger, upclient *upclient.APIClient, auth context.Context) *AccountHandler { handler := &AccountHandler{} handler.BaseHandler = &BaseHandler{ - Uri: "/accounts", - Log: log, - UpClient: upclient, - UpAuth: auth, - Handler: handler, // Set the Handler interface to the specific handler + Uri: "/accounts", + Log: log, + UpClient: upclient, + UpAuth: auth, + Handler: handler, // Set the Handler interface to the specific handler + MaxPageSize: int32(100), } return handler } func (h *AccountHandler) Post(w http.ResponseWriter, r *http.Request) {} func (h *AccountHandler) Get(w http.ResponseWriter, r *http.Request) { - pageSize := int32(30) filterOwnershipType := upclient.OwnershipTypeEnum("INDIVIDUAL") - resp, r2, err := h.UpClient.AccountsAPI.AccountsGet(h.UpAuth).PageSize(pageSize).FilterOwnershipType(filterOwnershipType).Execute() - h.Log.Println(resp) + accountChannel := make(chan upclient.AccountResource, 10) + clonedChannels := Clone(accountChannel, 2) + accountChannel1 := <-clonedChannels + accountChannel2 := <-clonedChannels + go h.GetAccounts(accountChannel, filterOwnershipType) + + templ.Handler(templates.Accounts(accountChannel1, accountChannel2), templ.WithStreaming()).ServeHTTP(w, r) +} + +func (h *AccountHandler) GetAccounts(accountChannel chan upclient.AccountResource, ownershipType upclient.OwnershipTypeEnum) { + defer close(accountChannel) + resp, r2, err := h.UpClient.AccountsAPI.AccountsGet(h.UpAuth).PageSize(h.MaxPageSize).FilterOwnershipType(ownershipType).Execute() if err != nil { - fmt.Fprintf(w, "Error when calling `AccountsAPI.AccountsGet``: %v\n", err) - fmt.Fprintf(w, "Full HTTP response: %v\n", r2) + h.Log.Println(fmt.Sprintf("Error when calling `AccountsAPI.AccountsGet`: %s\n", err)) + h.Log.Println(fmt.Sprintf("Full HTTP response: %v\n", r2)) h.Log.Println("Unable to get account information") } - // fmt.Fprintf(w, "Response from `AccountsAPI.AccountsGet`: %v\n", resp) - templates.Accounts(resp.Data).Render(r.Context(), w) + for _, account := range resp.Data { + accountChannel <- account + } +} +func Clone[T any](inCh chan T, size int) <-chan <-chan T { + // The channel of channels to return at the end of this function call + ret := make(chan (<-chan T), size) + + // This slice keeps track of all the output channels this function will be creating below. + outChs := make([]chan T, size) + + // Create channels, keep track of them in the slice and send them on the return channel + for i := 0; i < size; i++ { + // The buffer size of the newly created channel is the same as the input channel + outChs[i] = make(chan T, cap(inCh)) + ret <- outChs[i] + } + + // Start a goroutine to manage receiving message from the input channels and sending out to the output channels + // Close the output channels if the input channel has been closed. + go func() { + for { + msg, more := <-inCh + if more { + for _, ch := range outChs { + ch <- msg + } + } else { + for _, ch := range outChs { + close(ch) + } + return + } + } + }() + + return ret } diff --git a/datafetcher/handlers/basehandler.go b/datafetcher/handlers/basehandler.go index 70c2a52..bc8ce54 100644 --- a/datafetcher/handlers/basehandler.go +++ b/datafetcher/handlers/basehandler.go @@ -2,6 +2,7 @@ package handlers import ( "context" + "fmt" "log" "net/http" @@ -14,14 +15,16 @@ type Handler interface { } type BaseHandler struct { - Uri string - Log *log.Logger - UpClient *upclient.APIClient - UpAuth context.Context - Handler Handler // Embed the Handler interface + Uri string + Log *log.Logger + UpClient *upclient.APIClient + UpAuth context.Context + Handler Handler // Embed the Handler interface + MaxPageSize int32 } func (h *BaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + h.Log.Println(fmt.Sprintf("%s %s params: %s", r.Method, h.Uri, r.URL.Query())) switch r.Method { case http.MethodPost: h.Handler.Post(w, r) diff --git a/datafetcher/handlers/transactions.go b/datafetcher/handlers/transactions.go index f7e0deb..66141fc 100644 --- a/datafetcher/handlers/transactions.go +++ b/datafetcher/handlers/transactions.go @@ -5,37 +5,95 @@ import ( "fmt" "log" "net/http" + "net/url" + "strconv" + "github.com/a-h/templ" "github.com/esteanes/expense-manager/datafetcher/templates" - "github.com/esteanes/expense-manager/datafetcher/upclient" ) type TransactionsHandler struct { *BaseHandler + *AccountHandler } -func NewTransactionHandler(log *log.Logger, upclient *upclient.APIClient, auth context.Context) *TransactionsHandler { +func NewTransactionHandler(log *log.Logger, upclient *upclient.APIClient, auth context.Context, accountHandler *AccountHandler) *TransactionsHandler { handler := &TransactionsHandler{} handler.BaseHandler = &BaseHandler{ - Uri: "/transactions", - Log: log, - UpClient: upclient, - UpAuth: auth, - Handler: handler, // Set the Handler interface to the specific handler + Uri: "/transactions", + Log: log, + UpClient: upclient, + UpAuth: auth, + Handler: handler, // Set the Handler interface to the specific handler + MaxPageSize: int32(100), } + handler.AccountHandler = accountHandler return handler } func (h *TransactionsHandler) Post(w http.ResponseWriter, r *http.Request) {} func (h *TransactionsHandler) Get(w http.ResponseWriter, r *http.Request) { - pageSize := int32(30) // int32 | The number of records to return in each page. (optional) - resp, r2, err := h.UpClient.TransactionsAPI.TransactionsGet(h.UpAuth).PageSize(pageSize).Execute() + queryParams := r.URL.Query() + numTransactions, err := strconv.ParseInt(queryParams.Get("numTransactions"), 10, 32) if err != nil { - fmt.Fprintf(w, "Error when calling `TransactionsAPI.TransactionsGet``: %v\n", err) - fmt.Fprintf(w, "Full HTTP response: %v\n", r2.Body) - h.Log.Println(r2.Body) + numTransactions = int64(10) + } + accountId := queryParams.Get("accountId") + transactionsChannel := make(chan upclient.TransactionResource, numTransactions) + go h.getTransactions(transactionsChannel, int32(numTransactions), accountId) + accountsChannel := make(chan upclient.AccountResource) + go h.AccountHandler.GetAccounts(accountsChannel, upclient.OwnershipTypeEnum("INDIVIDUAL")) + templ.Handler(templates.Transactions(transactionsChannel, accountsChannel), templ.WithStreaming()).ServeHTTP(w, r) + +} +func (h *TransactionsHandler) getTransactions(transactionsChannel chan upclient.TransactionResource, numTransactions int32, accountId string) { + defer close(transactionsChannel) + getRequest := h.UpClient.TransactionsAPI.AccountsAccountIdTransactionsGet(h.UpAuth, accountId).PageSize(h.MaxPageSize) + var pageAfter *string + pageAfter = nil + countTransactions := int32(0) + for countTransactions < numTransactions { + if pageAfter != nil { + pageKeyParsed, _ := ExtractPageAfter(*pageAfter) + getRequest = getRequest.PageAfter(pageKeyParsed) + h.Log.Println(fmt.Sprintf("setting pageAfter to %s", pageKeyParsed)) + } + h.Log.Println(fmt.Sprintf("request struct is %+v", getRequest)) + resp, r2, err := getRequest.Execute() + if err != nil { + h.Log.Println(fmt.Sprintf("Error when calling `TransactionsAPI.TransactionsGet``: %s\n", err)) + h.Log.Println(fmt.Sprintf("Full HTTP response: %s\n", r2.Body)) + h.Log.Println(r2.Body) + return + } + // h.Log.Println(fmt.Sprintf("resp object is %#v", resp)) + pageAfter = resp.Links.Next.Get() + h.Log.Println(fmt.Sprintf("pageAfter is %p", pageAfter)) + if pageAfter != nil { + h.Log.Println(fmt.Sprintf("page after link is: %s", *pageAfter)) + } + for _, transaction := range resp.Data { + if countTransactions < numTransactions { + transactionsChannel <- transaction + countTransactions++ + } + } } - // response from `TransactionsGet`: ListTransactionsResponse - templates.Transactions(resp.Data).Render(r.Context(), w) +} + +func ExtractPageAfter(inputURL string) (string, error) { + // Parse the URL + parsedURL, err := url.Parse(inputURL) + if err != nil { + return "", err + } + + // Extract the query parameters + queryParams := parsedURL.Query() + + // Get the value of "page[before]" + pageAfter := queryParams.Get("page[after]") + + return pageAfter, nil } diff --git a/datafetcher/server.go b/datafetcher/server.go index 975aadf..80457ac 100644 --- a/datafetcher/server.go +++ b/datafetcher/server.go @@ -86,7 +86,7 @@ func HandleRequests(upBankToken string, log *log.Logger) { // Creating individual handlers accountHandler := handlers.NewAccountHandler(log, apiClient, auth) - transactionsHandler := handlers.NewTransactionHandler(log, apiClient, auth) + transactionsHandler := handlers.NewTransactionHandler(log, apiClient, auth, accountHandler) transactionsCsvHandler := handlers.NewTransactionCsvHandler(log, apiClient, auth) mux := http.NewServeMux() mux.HandleFunc(accountHandler.Uri, accountHandler.ServeHTTP) diff --git a/datafetcher/templates/accounts.templ b/datafetcher/templates/accounts.templ index 4d33a8f..4bb44ee 100644 --- a/datafetcher/templates/accounts.templ +++ b/datafetcher/templates/accounts.templ @@ -5,7 +5,36 @@ import ( "strings" ) -templ Accounts(accounts []upclient.AccountResource) { +templ AccountDetails(accounts <-chan upclient.AccountResource) { +

Accounts

+ +} + +templ AccountButtons(accounts <-chan upclient.AccountResource) { +

Accounts

+ +} + +templ Accounts(accounts1 <-chan upclient.AccountResource, accounts2 <-chan upclient.AccountResource) { @@ -14,18 +43,8 @@ templ Accounts(accounts []upclient.AccountResource) { Accounts -

Accounts

- + @AccountButtons(accounts2) + @AccountDetails(accounts1) } diff --git a/datafetcher/templates/accounts_templ.go b/datafetcher/templates/accounts_templ.go index cc86fc3..9d0eb77 100644 --- a/datafetcher/templates/accounts_templ.go +++ b/datafetcher/templates/accounts_templ.go @@ -13,7 +13,7 @@ import ( "strings" ) -func Accounts(accounts []upclient.AccountResource) templ.Component { +func AccountDetails(accounts <-chan upclient.AccountResource) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) @@ -31,82 +31,257 @@ func Accounts(accounts []upclient.AccountResource) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Accounts

Accounts

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func Accounts(accounts1 <-chan upclient.AccountResource, accounts2 <-chan upclient.AccountResource) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var15 := templ.GetChildren(ctx) + if templ_7745c5c3_Var15 == nil { + templ_7745c5c3_Var15 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Accounts") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = AccountButtons(accounts2).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = AccountDetails(accounts1).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/datafetcher/templates/transactions.templ b/datafetcher/templates/transactions.templ index a229676..5230d7a 100644 --- a/datafetcher/templates/transactions.templ +++ b/datafetcher/templates/transactions.templ @@ -30,7 +30,50 @@ func getCardPurchaseNumber(transaction upclient.TransactionResource) string { return *maybePurchaseNumber } -templ Transactions(transactions []upclient.TransactionResource) { +func getCategory(transaction upclient.TransactionResource) string { + maybeCategory := transaction.GetRelationships().Category.Data.Get() + if maybeCategory == nil { + return "" + } + return maybeCategory.Id + +} + +templ TransactionsTable(transactions chan upclient.TransactionResource) { +

Transactions

+ + + + + + + + + + + + + + + for transaction := range(transactions) { + @templ.Flush() { + + + + + + + + + + + } + } + +
Transaction AmountDescriptionStatusTimeMessageCategoryPurchase MethodCard Number
{ transaction.Attributes.Amount.Value }{ transaction.Attributes.Description }{ string(transaction.Attributes.Status) }{ transaction.Attributes.CreatedAt.String() }{ getMessage(transaction) }{ getCategory(transaction) }{ getCardPurchase(transaction) }{ getCardPurchaseNumber(transaction) }
+} + +templ Transactions(transactions chan upclient.TransactionResource, accounts chan upclient.AccountResource) { @@ -53,33 +96,8 @@ templ Transactions(transactions []upclient.TransactionResource) { -

Transactions

- - - - - - - - - - - - - - for _, transaction := range(transactions) { - - - - - - - - - - } - -
Transaction AmountDescriptionStatusTimeMessagePurchase MethodCard Number
{ transaction.Attributes.Amount.Value }{ transaction.Attributes.Description }{ string(transaction.Attributes.Status) }{ transaction.Attributes.CreatedAt.String() }{ getMessage(transaction) }{ getCardPurchase(transaction) }{ getCardPurchaseNumber(transaction) }
+ @AccountButtons(accounts) + @TransactionsTable(transactions) } diff --git a/datafetcher/templates/transactions_templ.go b/datafetcher/templates/transactions_templ.go index 1ea1a5b..94a33b2 100644 --- a/datafetcher/templates/transactions_templ.go +++ b/datafetcher/templates/transactions_templ.go @@ -38,7 +38,16 @@ func getCardPurchaseNumber(transaction upclient.TransactionResource) string { return *maybePurchaseNumber } -func Transactions(transactions []upclient.TransactionResource) templ.Component { +func getCategory(transaction upclient.TransactionResource) string { + maybeCategory := transaction.GetRelationships().Category.Data.Get() + if maybeCategory == nil { + return "" + } + return maybeCategory.Id + +} + +func TransactionsTable(transactions chan upclient.TransactionResource) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) @@ -56,108 +65,177 @@ func Transactions(transactions []upclient.TransactionResource) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Transactions

Transactions

") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

Transactions

Transaction AmountDescriptionStatusTimeMessagePurchase MethodCard Number
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - for _, transaction := range transactions { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + }) + templ_7745c5c3_Err = templ.Flush().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Transaction AmountDescriptionStatusTimeMessageCategoryPurchase MethodCard Number
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.Amount.Value) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 72, Col: 48} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.Description) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 73, Col: 47} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(string(transaction.Attributes.Status)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 74, Col: 50} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.CreatedAt.String()) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 75, Col: 54} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(getMessage(transaction)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 76, Col: 36} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(getCardPurchase(transaction)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 77, Col: 41} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(getCardPurchaseNumber(transaction)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 78, Col: 47} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) - if templ_7745c5c3_Err != nil { + for transaction := range transactions { + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.Amount.Value) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 61, Col: 47} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.Description) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 62, Col: 46} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(string(transaction.Attributes.Status)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 63, Col: 49} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var6 string + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.CreatedAt.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 64, Col: 53} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(getMessage(transaction)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 65, Col: 35} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(getCategory(transaction)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 66, Col: 36} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(getCardPurchase(transaction)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 67, Col: 40} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(getCardPurchaseNumber(transaction)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 68, Col: 46} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func Transactions(transactions chan upclient.TransactionResource, accounts chan upclient.AccountResource) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var11 := templ.GetChildren(ctx) + if templ_7745c5c3_Var11 == nil { + templ_7745c5c3_Var11 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Transactions") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = AccountButtons(accounts).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = TransactionsTable(transactions).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/datafetcher/upclient/api/openapi.yaml b/datafetcher/upclient/api/openapi.yaml index 7788436..85b7b92 100644 --- a/datafetcher/upclient/api/openapi.yaml +++ b/datafetcher/upclient/api/openapi.yaml @@ -682,6 +682,26 @@ paths: schema: type: integer style: form + - description: | + To view a page before a specific transaction. + example: WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D + explode: true + in: query + name: "page[before]" + required: false + schema: + type: string + style: form + - description: | + Where to continue paginating across + example: WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D + explode: true + in: query + name: "page[after]" + required: false + schema: + type: string + style: form - description: | The transaction status for which to return records. This can be used to filter `HELD` transactions from those @@ -921,6 +941,26 @@ paths: schema: type: integer style: form + - description: | + To view a page before a specific transaction. + example: WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D + explode: true + in: query + name: "page[before]" + required: false + schema: + type: string + style: form + - description: | + Where to continue paginating across + example: WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D + explode: true + in: query + name: "page[after]" + required: false + schema: + type: string + style: form - description: | The transaction status for which to return records. This can be used to filter `HELD` transactions from those diff --git a/datafetcher/upclient/api_transactions.go b/datafetcher/upclient/api_transactions.go index 61e1de4..a06ffc6 100644 --- a/datafetcher/upclient/api_transactions.go +++ b/datafetcher/upclient/api_transactions.go @@ -28,6 +28,8 @@ type ApiAccountsAccountIdTransactionsGetRequest struct { ApiService *TransactionsAPIService accountId string pageSize *int32 + pageBefore *string + pageAfter *string filterStatus *TransactionStatusEnum filterSince *time.Time filterUntil *time.Time @@ -41,6 +43,18 @@ func (r ApiAccountsAccountIdTransactionsGetRequest) PageSize(pageSize int32) Api return r } +// To view a page before a specific transaction. +func (r ApiAccountsAccountIdTransactionsGetRequest) PageBefore(pageBefore string) ApiAccountsAccountIdTransactionsGetRequest { + r.pageBefore = &pageBefore + return r +} + +// Where to continue paginating across +func (r ApiAccountsAccountIdTransactionsGetRequest) PageAfter(pageAfter string) ApiAccountsAccountIdTransactionsGetRequest { + r.pageAfter = &pageAfter + return r +} + // The transaction status for which to return records. This can be used to filter `HELD` transactions from those that are `SETTLED`. func (r ApiAccountsAccountIdTransactionsGetRequest) FilterStatus(filterStatus TransactionStatusEnum) ApiAccountsAccountIdTransactionsGetRequest { r.filterStatus = &filterStatus @@ -124,6 +138,12 @@ func (a *TransactionsAPIService) AccountsAccountIdTransactionsGetExecute(r ApiAc if r.pageSize != nil { parameterAddToHeaderOrQuery(localVarQueryParams, "page[size]", r.pageSize, "") } + if r.pageBefore != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "page[before]", r.pageBefore, "") + } + if r.pageAfter != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "page[after]", r.pageAfter, "") + } if r.filterStatus != nil { parameterAddToHeaderOrQuery(localVarQueryParams, "filter[status]", r.filterStatus, "") } @@ -197,6 +217,8 @@ type ApiTransactionsGetRequest struct { ctx context.Context ApiService *TransactionsAPIService pageSize *int32 + pageBefore *string + pageAfter *string filterStatus *TransactionStatusEnum filterSince *time.Time filterUntil *time.Time @@ -210,6 +232,18 @@ func (r ApiTransactionsGetRequest) PageSize(pageSize int32) ApiTransactionsGetRe return r } +// To view a page before a specific transaction. +func (r ApiTransactionsGetRequest) PageBefore(pageBefore string) ApiTransactionsGetRequest { + r.pageBefore = &pageBefore + return r +} + +// Where to continue paginating across +func (r ApiTransactionsGetRequest) PageAfter(pageAfter string) ApiTransactionsGetRequest { + r.pageAfter = &pageAfter + return r +} + // The transaction status for which to return records. This can be used to filter `HELD` transactions from those that are `SETTLED`. func (r ApiTransactionsGetRequest) FilterStatus(filterStatus TransactionStatusEnum) ApiTransactionsGetRequest { r.filterStatus = &filterStatus @@ -290,6 +324,12 @@ func (a *TransactionsAPIService) TransactionsGetExecute(r ApiTransactionsGetRequ if r.pageSize != nil { parameterAddToHeaderOrQuery(localVarQueryParams, "page[size]", r.pageSize, "") } + if r.pageBefore != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "page[before]", r.pageBefore, "") + } + if r.pageAfter != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "page[after]", r.pageAfter, "") + } if r.filterStatus != nil { parameterAddToHeaderOrQuery(localVarQueryParams, "filter[status]", r.filterStatus, "") } diff --git a/datafetcher/upclient/docs/TransactionsAPI.md b/datafetcher/upclient/docs/TransactionsAPI.md index da3c962..8838345 100644 --- a/datafetcher/upclient/docs/TransactionsAPI.md +++ b/datafetcher/upclient/docs/TransactionsAPI.md @@ -12,7 +12,7 @@ Method | HTTP request | Description ## AccountsAccountIdTransactionsGet -> ListTransactionsResponse AccountsAccountIdTransactionsGet(ctx, accountId).PageSize(pageSize).FilterStatus(filterStatus).FilterSince(filterSince).FilterUntil(filterUntil).FilterCategory(filterCategory).FilterTag(filterTag).Execute() +> ListTransactionsResponse AccountsAccountIdTransactionsGet(ctx, accountId).PageSize(pageSize).PageBefore(pageBefore).PageAfter(pageAfter).FilterStatus(filterStatus).FilterSince(filterSince).FilterUntil(filterUntil).FilterCategory(filterCategory).FilterTag(filterTag).Execute() List transactions by account @@ -34,6 +34,8 @@ import ( func main() { accountId := "689a08de-fa65-4f2d-8b58-e49b17117dc7" // string | The unique identifier for the account. pageSize := int32(30) // int32 | The number of records to return in each page. (optional) + pageBefore := "WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D" // string | To view a page before a specific transaction. (optional) + pageAfter := "WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D" // string | Where to continue paginating across (optional) filterStatus := openapiclient.TransactionStatusEnum("HELD") // TransactionStatusEnum | The transaction status for which to return records. This can be used to filter `HELD` transactions from those that are `SETTLED`. (optional) filterSince := time.Now() // time.Time | The start date-time from which to return records, formatted according to rfc-3339. Not to be used for pagination purposes. (optional) filterUntil := time.Now() // time.Time | The end date-time up to which to return records, formatted according to rfc-3339. Not to be used for pagination purposes. (optional) @@ -42,7 +44,7 @@ func main() { configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.TransactionsAPI.AccountsAccountIdTransactionsGet(context.Background(), accountId).PageSize(pageSize).FilterStatus(filterStatus).FilterSince(filterSince).FilterUntil(filterUntil).FilterCategory(filterCategory).FilterTag(filterTag).Execute() + resp, r, err := apiClient.TransactionsAPI.AccountsAccountIdTransactionsGet(context.Background(), accountId).PageSize(pageSize).PageBefore(pageBefore).PageAfter(pageAfter).FilterStatus(filterStatus).FilterSince(filterSince).FilterUntil(filterUntil).FilterCategory(filterCategory).FilterTag(filterTag).Execute() if err != nil { fmt.Fprintf(os.Stderr, "Error when calling `TransactionsAPI.AccountsAccountIdTransactionsGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) @@ -69,6 +71,8 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **pageSize** | **int32** | The number of records to return in each page. | + **pageBefore** | **string** | To view a page before a specific transaction. | + **pageAfter** | **string** | Where to continue paginating across | **filterStatus** | [**TransactionStatusEnum**](TransactionStatusEnum.md) | The transaction status for which to return records. This can be used to filter `HELD` transactions from those that are `SETTLED`. | **filterSince** | **time.Time** | The start date-time from which to return records, formatted according to rfc-3339. Not to be used for pagination purposes. | **filterUntil** | **time.Time** | The end date-time up to which to return records, formatted according to rfc-3339. Not to be used for pagination purposes. | @@ -95,7 +99,7 @@ Name | Type | Description | Notes ## TransactionsGet -> ListTransactionsResponse TransactionsGet(ctx).PageSize(pageSize).FilterStatus(filterStatus).FilterSince(filterSince).FilterUntil(filterUntil).FilterCategory(filterCategory).FilterTag(filterTag).Execute() +> ListTransactionsResponse TransactionsGet(ctx).PageSize(pageSize).PageBefore(pageBefore).PageAfter(pageAfter).FilterStatus(filterStatus).FilterSince(filterSince).FilterUntil(filterUntil).FilterCategory(filterCategory).FilterTag(filterTag).Execute() List transactions @@ -116,6 +120,8 @@ import ( func main() { pageSize := int32(30) // int32 | The number of records to return in each page. (optional) + pageBefore := "WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D" // string | To view a page before a specific transaction. (optional) + pageAfter := "WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D" // string | Where to continue paginating across (optional) filterStatus := openapiclient.TransactionStatusEnum("HELD") // TransactionStatusEnum | The transaction status for which to return records. This can be used to filter `HELD` transactions from those that are `SETTLED`. (optional) filterSince := time.Now() // time.Time | The start date-time from which to return records, formatted according to rfc-3339. Not to be used for pagination purposes. (optional) filterUntil := time.Now() // time.Time | The end date-time up to which to return records, formatted according to rfc-3339. Not to be used for pagination purposes. (optional) @@ -124,7 +130,7 @@ func main() { configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.TransactionsAPI.TransactionsGet(context.Background()).PageSize(pageSize).FilterStatus(filterStatus).FilterSince(filterSince).FilterUntil(filterUntil).FilterCategory(filterCategory).FilterTag(filterTag).Execute() + resp, r, err := apiClient.TransactionsAPI.TransactionsGet(context.Background()).PageSize(pageSize).PageBefore(pageBefore).PageAfter(pageAfter).FilterStatus(filterStatus).FilterSince(filterSince).FilterUntil(filterUntil).FilterCategory(filterCategory).FilterTag(filterTag).Execute() if err != nil { fmt.Fprintf(os.Stderr, "Error when calling `TransactionsAPI.TransactionsGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) @@ -146,6 +152,8 @@ Other parameters are passed through a pointer to a apiTransactionsGetRequest str Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **pageSize** | **int32** | The number of records to return in each page. | + **pageBefore** | **string** | To view a page before a specific transaction. | + **pageAfter** | **string** | Where to continue paginating across | **filterStatus** | [**TransactionStatusEnum**](TransactionStatusEnum.md) | The transaction status for which to return records. This can be used to filter `HELD` transactions from those that are `SETTLED`. | **filterSince** | **time.Time** | The start date-time from which to return records, formatted according to rfc-3339. Not to be used for pagination purposes. | **filterUntil** | **time.Time** | The end date-time up to which to return records, formatted according to rfc-3339. Not to be used for pagination purposes. | diff --git a/openapi.json b/openapi.json index 5feb667..eaa0e16 100644 --- a/openapi.json +++ b/openapi.json @@ -2467,6 +2467,26 @@ "example": 30, "description": "The number of records to return in each page.\n" }, + { + "name": "page[before]", + "in": "query", + "schema": { + "type": "string" + }, + "required": false, + "example":"WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D", + "description": "To view a page before a specific transaction.\n" + }, + { + "name": "page[after]", + "in": "query", + "schema": { + "type": "string" + }, + "required": false, + "example":"WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D", + "description": "Where to continue paginating across\n" + }, { "name": "filter[status]", "in": "query", @@ -2781,6 +2801,26 @@ "example": 30, "description": "The number of records to return in each page.\n" }, + { + "name": "page[before]", + "in": "query", + "schema": { + "type": "string" + }, + "required": false, + "example":"WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D", + "description": "To view a page before a specific transaction.\n" + }, + { + "name": "page[after]", + "in": "query", + "schema": { + "type": "string" + }, + "required": false, + "example":"WyIyMDI0LTA5LTA2VDEwOjEyOjA2Ljg2MDQ2MzAwMFoiLCJjYjc1ZjI5ZS1lY2M1LTQ5NzYtYWEyOC0KJlkjsdfkA5ZDIiXQ%3D%3D", + "description": "Where to continue paginating across\n" + }, { "name": "filter[status]", "in": "query",