docs format updated

This commit is contained in:
Stephan D
2026-03-13 01:28:51 +01:00
parent b4eb1437f6
commit f1840690e1
54 changed files with 677 additions and 195 deletions

View File

@@ -8,7 +8,7 @@ require (
github.com/aws/aws-sdk-go-v2 v1.41.3 github.com/aws/aws-sdk-go-v2 v1.41.3
github.com/aws/aws-sdk-go-v2/config v1.32.11 github.com/aws/aws-sdk-go-v2/config v1.32.11
github.com/aws/aws-sdk-go-v2/credentials v1.19.11 github.com/aws/aws-sdk-go-v2/credentials v1.19.11
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4 github.com/aws/aws-sdk-go-v2/service/s3 v1.97.0
github.com/jung-kurt/gofpdf v1.16.2 github.com/jung-kurt/gofpdf v1.16.2
github.com/prometheus/client_golang v1.23.2 github.com/prometheus/client_golang v1.23.2
github.com/shopspring/decimal v1.4.0 github.com/shopspring/decimal v1.4.0
@@ -61,7 +61,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -30,8 +30,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7su
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19 h1:JnQeStZvPHFHeyky/7LbMlyQjUa+jIBj36OlWm0pzIk= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19 h1:JnQeStZvPHFHeyky/7LbMlyQjUa+jIBj36OlWm0pzIk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19/go.mod h1:HGyasyHvYdFQeJhvDHfH7HXkHh57htcJGKDZ+7z+I24= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19/go.mod h1:HGyasyHvYdFQeJhvDHfH7HXkHh57htcJGKDZ+7z+I24=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4 h1:4ExZyubQ6LQQVuF2Qp9OsfEvsTdAWh5Gfwf6PgIdLdk= github.com/aws/aws-sdk-go-v2/service/s3 v1.97.0 h1:zyKY4OxzUImu+DigelJI9o49QQv8CjREs5E1CywjtIA=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4/go.mod h1:NF3JcMGOiARAss1ld3WGORCw71+4ExDD2cbbdKS5PpA= github.com/aws/aws-sdk-go-v2/service/s3 v1.97.0/go.mod h1:NF3JcMGOiARAss1ld3WGORCw71+4ExDD2cbbdKS5PpA=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias= github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias=
@@ -229,8 +229,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -3,7 +3,8 @@ package content
// Issuer details are intentionally centralized to avoid document text drift. // Issuer details are intentionally centralized to avoid document text drift.
const ( const (
IssuerLegalName = "SMX Operations Limited" IssuerLegalName = "SMX Operations Limited"
IssuerLegalAddress = "Room 607, 12/F., Block C, Hong Kong Industrial Centre, 489-491 Castle Peak Road, Lai Chi Kok, Hong Kong" IssuerLegalAddress = "Room 607, 12/F., Block C, Hong Kong Industrial Centre, 489-491 Castle Peak Road, Lai Chi Kok, HongKong"
IssuerEmail = "contact@sendico.io"
) )
const ( const (
@@ -74,43 +75,77 @@ var AcceptanceTemplate = AcceptanceTemplateContent{
// OperationDocumentContent contains all static copy for operation documents. // OperationDocumentContent contains all static copy for operation documents.
type OperationDocumentContent struct { type OperationDocumentContent struct {
Title string Title string
Subtitle string Subtitle string
MetaDocumentType string MetaCertificateNumberLabel string
SectionOperation string MetaDateLabel string
SectionFailure string SectionParties string
RowOrganization string PartiesIntro string
RowGatewayService string RowServiceProvider string
RowOperationRef string RowServiceProviderAddress string
RowPaymentRef string RowServiceProviderEmail string
RowCode string RowClient string
RowState string RowClientAddress string
RowLabel string RowClientReference string
RowStartedAtUTC string SectionSubject string
RowCompletedAtUTC string SubjectIntro string
RowAmount string SectionServicePeriod string
RowFailureCode string RowPeriodFrom string
RowFailureReason string RowPeriodTo string
MissingValuePlaceholder string SectionTotalAmount string
RowTotalAmount string
SectionClientConfirmation string
ConfirmationLine1 string
ConfirmationLine2 string
ConfirmationLine3 string
SectionSignatures string
SignatureServiceProviderLine string
SignatureClientNamePrefix string
SignatureClientTitleLine string
SignatureClientLine string
SectionOperationStatus string
RowOperationStatus string
RowOperationCode string
RowOperationLabel string
RowFailureCode string
RowFailureReason string
MissingValuePlaceholder string
} }
var OperationDocument = OperationDocumentContent{ var OperationDocument = OperationDocumentContent{
Title: "OPERATION BILLING DOCUMENT", Title: "CERTIFICATE OF SERVICES RENDERED",
Subtitle: "Gateway operation statement", Subtitle: "Payment operation completion and acceptance statement",
MetaDocumentType: "Document Type: Operation", MetaCertificateNumberLabel: "Certificate No.",
SectionOperation: "OPERATION DETAILS", MetaDateLabel: "Date",
SectionFailure: "FAILURE DETAILS", SectionParties: "PARTIES",
RowOrganization: "Organization", PartiesIntro: "This Certificate is made between:",
RowGatewayService: "Gateway Service", RowServiceProvider: "Service Provider",
RowOperationRef: "Operation Ref", RowServiceProviderAddress: "Service Provider Address",
RowPaymentRef: "Payment Ref", RowServiceProviderEmail: "Service Provider Email",
RowCode: "Code", RowClient: "Client",
RowState: "State", RowClientAddress: "Client Address",
RowLabel: "Label", RowClientReference: "Client Reference",
RowStartedAtUTC: "Started At (UTC)", SectionSubject: "SUBJECT OF THE CERTIFICATE",
RowCompletedAtUTC: "Completed At (UTC)", SubjectIntro: "The Service Provider confirms that the following services have been fully rendered to the Client:",
RowAmount: "Amount", SectionServicePeriod: "SERVICE PERIOD",
RowFailureCode: "Failure Code", RowPeriodFrom: "From",
RowFailureReason: "Failure Reason", RowPeriodTo: "To",
MissingValuePlaceholder: "n/a", SectionTotalAmount: "TOTAL AMOUNT",
RowTotalAmount: "Amount",
SectionClientConfirmation: "CLIENT CONFIRMATION",
ConfirmationLine1: "- the services were rendered in full;",
ConfirmationLine2: "- the services were rendered properly and within the agreed scope;",
ConfirmationLine3: "- the Client has no claims regarding the quality, quantity, or timing of the services rendered.",
SectionSignatures: "SIGNATURES",
SignatureServiceProviderLine: "Service Provider: Name: SMX Operations Limited | Signature: __________________",
SignatureClientNamePrefix: "Client: Name:",
SignatureClientTitleLine: "Title: Authorized Representative",
SignatureClientLine: "Signature: __________________",
SectionOperationStatus: "OPERATION STATUS",
RowOperationStatus: "Operation Status",
RowOperationCode: "Operation Code",
RowOperationLabel: "Operation Label",
RowFailureCode: "Failure Code",
RowFailureReason: "Failure Reason",
MissingValuePlaceholder: "n/a",
} }

View File

@@ -289,6 +289,8 @@ type operationSnapshot struct {
GatewayService string GatewayService string
OperationRef string OperationRef string
PaymentRef string PaymentRef string
ClientName string
ClientAddress string
OperationCode string OperationCode string
OperationLabel string OperationLabel string
OperationState string OperationState string
@@ -306,6 +308,8 @@ func operationSnapshotFromRequest(req *documentsv1.GetOperationDocumentRequest)
GatewayService: strings.TrimSpace(req.GetGatewayService()), GatewayService: strings.TrimSpace(req.GetGatewayService()),
OperationRef: strings.TrimSpace(req.GetOperationRef()), OperationRef: strings.TrimSpace(req.GetOperationRef()),
PaymentRef: strings.TrimSpace(req.GetPaymentRef()), PaymentRef: strings.TrimSpace(req.GetPaymentRef()),
ClientName: strings.TrimSpace(req.GetClientName()),
ClientAddress: strings.TrimSpace(req.GetClientAddress()),
OperationCode: strings.TrimSpace(req.GetOperationCode()), OperationCode: strings.TrimSpace(req.GetOperationCode()),
OperationLabel: strings.TrimSpace(req.GetOperationLabel()), OperationLabel: strings.TrimSpace(req.GetOperationLabel()),
OperationState: strings.TrimSpace(req.GetOperationState()), OperationState: strings.TrimSpace(req.GetOperationState()),
@@ -328,21 +332,6 @@ func operationSnapshotFromRequest(req *documentsv1.GetOperationDocumentRequest)
func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block { func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block {
documentCopy := content.OperationDocument documentCopy := content.OperationDocument
rows := [][]string{
{documentCopy.RowOrganization, snapshot.OrganizationRef},
{documentCopy.RowGatewayService, snapshot.GatewayService},
{documentCopy.RowOperationRef, snapshot.OperationRef},
{documentCopy.RowPaymentRef, safeValue(snapshot.PaymentRef)},
{documentCopy.RowCode, safeValue(snapshot.OperationCode)},
{documentCopy.RowState, safeValue(snapshot.OperationState)},
{documentCopy.RowLabel, safeValue(snapshot.OperationLabel)},
{documentCopy.RowStartedAtUTC, formatSnapshotTime(snapshot.StartedAt)},
{documentCopy.RowCompletedAtUTC, formatSnapshotTime(snapshot.CompletedAt)},
}
if snapshot.Amount != "" || snapshot.Currency != "" {
rows = append(rows, []string{documentCopy.RowAmount, strings.TrimSpace(strings.TrimSpace(snapshot.Amount) + " " + strings.TrimSpace(snapshot.Currency))})
}
blocks := []renderer.Block{ blocks := []renderer.Block{
{ {
Tag: renderer.TagTitle, Tag: renderer.TagTitle,
@@ -355,30 +344,115 @@ func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block {
{ {
Tag: renderer.TagMeta, Tag: renderer.TagMeta,
Lines: []string{ Lines: []string{
documentCopy.MetaDocumentType, fmt.Sprintf("%s: %s", documentCopy.MetaCertificateNumberLabel, certificateNumber(snapshot)),
fmt.Sprintf("%s: %s", documentCopy.MetaDateLabel, formatCertificateDate(certificateDate(snapshot))),
}, },
}, },
{ {
Tag: renderer.TagSection, Tag: renderer.TagSection,
Lines: []string{documentCopy.SectionOperation}, Lines: []string{documentCopy.SectionParties},
}, },
{ {
Tag: renderer.TagKV, Tag: renderer.TagText,
Rows: rows, Lines: []string{documentCopy.PartiesIntro},
},
{
Tag: renderer.TagKV,
Rows: [][]string{
{documentCopy.RowServiceProvider, content.IssuerLegalName},
{documentCopy.RowServiceProviderAddress, content.IssuerLegalAddress},
{documentCopy.RowServiceProviderEmail, content.IssuerEmail},
{documentCopy.RowClient, certificateClientName(snapshot)},
{documentCopy.RowClientAddress, certificateClientAddress(snapshot)},
{documentCopy.RowClientReference, safeValue(snapshot.PaymentRef)},
},
},
{
Tag: renderer.TagSection,
Lines: []string{documentCopy.SectionSubject},
},
{
Tag: renderer.TagText,
Lines: []string{
documentCopy.SubjectIntro,
"",
"- Payment execution and orchestration services for payment reference " + safeValue(snapshot.PaymentRef) + ".",
"- Gateway service: " + safeValue(snapshot.GatewayService) + ".",
"- Operation reference: " + safeValue(snapshot.OperationRef) + ".",
"- Operation descriptor: " + operationDescriptor(snapshot) + ".",
},
},
{
Tag: renderer.TagSection,
Lines: []string{documentCopy.SectionServicePeriod},
},
{
Tag: renderer.TagKV,
Rows: [][]string{
{documentCopy.RowPeriodFrom, formatSnapshotTime(snapshot.StartedAt)},
{documentCopy.RowPeriodTo, formatSnapshotTime(snapshot.CompletedAt)},
},
},
{
Tag: renderer.TagSection,
Lines: []string{documentCopy.SectionTotalAmount},
},
{
Tag: renderer.TagKV,
Rows: [][]string{
{documentCopy.RowTotalAmount, operationAmount(snapshot)},
},
},
{
Tag: renderer.TagSection,
Lines: []string{documentCopy.SectionClientConfirmation},
},
{
Tag: renderer.TagText,
Lines: []string{
documentCopy.ConfirmationLine1,
documentCopy.ConfirmationLine2,
documentCopy.ConfirmationLine3,
"",
"This Certificate serves as confirmation of the completion and acceptance of the services.",
},
},
{
Tag: renderer.TagSection,
Lines: []string{documentCopy.SectionSignatures},
},
{
Tag: renderer.TagSign,
Lines: []string{
documentCopy.SignatureServiceProviderLine,
"",
documentCopy.SignatureClientNamePrefix + " " + certificateClientName(snapshot),
documentCopy.SignatureClientTitleLine,
documentCopy.SignatureClientLine,
},
},
{
Tag: renderer.TagSection,
Lines: []string{documentCopy.SectionOperationStatus},
},
{
Tag: renderer.TagKV,
Rows: [][]string{
{documentCopy.RowOperationStatus, safeValue(snapshot.OperationState)},
{documentCopy.RowOperationCode, safeValue(snapshot.OperationCode)},
{documentCopy.RowOperationLabel, safeValue(snapshot.OperationLabel)},
},
}, },
} }
if snapshot.FailureCode != "" || snapshot.FailureReason != "" { if snapshot.FailureCode != "" || snapshot.FailureReason != "" {
blocks = append(blocks, blocks = append(blocks, renderer.Block{
renderer.Block{Tag: renderer.TagSection, Lines: []string{documentCopy.SectionFailure}}, Tag: renderer.TagKV,
renderer.Block{ Rows: [][]string{
Tag: renderer.TagKV, {documentCopy.RowFailureCode, safeValue(snapshot.FailureCode)},
Rows: [][]string{ {documentCopy.RowFailureReason, safeValue(snapshot.FailureReason)},
{documentCopy.RowFailureCode, safeValue(snapshot.FailureCode)},
{documentCopy.RowFailureReason, safeValue(snapshot.FailureReason)},
},
}, },
) })
} }
return blocks return blocks
@@ -392,6 +466,80 @@ func formatSnapshotTime(value time.Time) string {
return value.UTC().Format(time.RFC3339) return value.UTC().Format(time.RFC3339)
} }
func certificateNumber(snapshot operationSnapshot) string {
if paymentRef := strings.TrimSpace(snapshot.PaymentRef); paymentRef != "" {
return paymentRef
}
if operationRef := strings.TrimSpace(snapshot.OperationRef); operationRef != "" {
return operationRef
}
return content.OperationDocument.MissingValuePlaceholder
}
func certificateDate(snapshot operationSnapshot) time.Time {
if !snapshot.CompletedAt.IsZero() {
return snapshot.CompletedAt.UTC()
}
if !snapshot.StartedAt.IsZero() {
return snapshot.StartedAt.UTC()
}
return time.Now().UTC()
}
func formatCertificateDate(value time.Time) string {
if value.IsZero() {
return content.OperationDocument.MissingValuePlaceholder
}
return value.UTC().Format("January 2, 2006")
}
func operationAmount(snapshot operationSnapshot) string {
amount := strings.TrimSpace(snapshot.Amount)
currency := strings.TrimSpace(snapshot.Currency)
if amount == "" && currency == "" {
return content.OperationDocument.MissingValuePlaceholder
}
return strings.TrimSpace(amount + " " + currency)
}
func operationDescriptor(snapshot operationSnapshot) string {
label := strings.TrimSpace(snapshot.OperationLabel)
code := strings.TrimSpace(snapshot.OperationCode)
switch {
case label != "" && code != "":
return fmt.Sprintf("%s (%s)", label, code)
case label != "":
return label
case code != "":
return code
default:
return content.OperationDocument.MissingValuePlaceholder
}
}
func certificateClientName(snapshot operationSnapshot) string {
if name := strings.TrimSpace(snapshot.ClientName); name != "" {
return name
}
return "John Doe"
}
func certificateClientAddress(snapshot operationSnapshot) string {
if address := strings.TrimSpace(snapshot.ClientAddress); address != "" {
return address
}
return content.OperationDocument.MissingValuePlaceholder
}
func safeValue(value string) string { func safeValue(value string) string {
trimmed := strings.TrimSpace(value) trimmed := strings.TrimSpace(value)
if trimmed == "" { if trimmed == "" {

View File

@@ -3,6 +3,7 @@ package documents
import ( import (
"bytes" "bytes"
"context" "context"
"strings"
"testing" "testing"
"time" "time"
@@ -191,3 +192,92 @@ func TestGetOperationDocument_RequiresOperationRef(t *testing.T) {
t.Fatalf("expected InvalidArgument, got=%v err=%v", status.Code(err), err) t.Fatalf("expected InvalidArgument, got=%v err=%v", status.Code(err), err)
} }
} }
func TestBuildOperationBlocks_CertificateIncludesPaymentData(t *testing.T) {
snapshot := operationSnapshot{
OrganizationRef: "org-1",
GatewayService: "chain_gateway",
OperationRef: "op-123",
PaymentRef: "pay-123",
ClientName: "Jane Customer",
ClientAddress: "Main Street 1, City",
OperationCode: "transfer",
OperationLabel: "Outbound transfer",
OperationState: "completed",
Amount: "100.50",
Currency: "USDT",
StartedAt: time.Date(2026, 3, 1, 10, 0, 0, 0, time.UTC),
CompletedAt: time.Date(2026, 3, 2, 12, 0, 0, 0, time.UTC),
}
blocks := buildOperationBlocks(snapshot)
if len(blocks) == 0 {
t.Fatalf("expected blocks")
}
if got := blocks[0].Lines[0]; got != content.OperationDocument.Title {
t.Fatalf("title mismatch: got=%q want=%q", got, content.OperationDocument.Title)
}
meta := findTaggedBlock(blocks, renderer.TagMeta)
if meta == nil {
t.Fatalf("expected meta block")
}
metaText := strings.Join(meta.Lines, "\n")
if !strings.Contains(metaText, "Certificate No.: pay-123") {
t.Fatalf("meta should include certificate number, got=%q", metaText)
}
if !strings.Contains(metaText, "Date: March 2, 2026") {
t.Fatalf("meta should include certificate date, got=%q", metaText)
}
amountFound := false
clientFound := false
for _, block := range blocks {
if block.Tag != renderer.TagKV {
continue
}
for _, row := range block.Rows {
if len(row) >= 2 && row[0] == content.OperationDocument.RowTotalAmount && row[1] == "100.50 USDT" {
amountFound = true
}
if len(row) >= 2 && row[0] == content.OperationDocument.RowClient && row[1] == "Jane Customer" {
clientFound = true
}
}
}
if !amountFound {
t.Fatalf("expected total amount row with payment amount")
}
if !clientFound {
t.Fatalf("expected client row with customer name")
}
}
func TestCertificateNumber_FallsBackToOperationRef(t *testing.T) {
got := certificateNumber(operationSnapshot{
OperationRef: "op-777",
})
if got != "op-777" {
t.Fatalf("certificateNumber fallback mismatch: got=%q want=%q", got, "op-777")
}
}
func TestCertificateClientName_Fallback(t *testing.T) {
if got := certificateClientName(operationSnapshot{}); got != "John Doe" {
t.Fatalf("certificateClientName fallback mismatch: got=%q want=%q", got, "John Doe")
}
}
func findTaggedBlock(blocks []renderer.Block, tag renderer.Tag) *renderer.Block {
for i := range blocks {
if blocks[i].Tag == tag {
return &blocks[i]
}
}
return nil
}

View File

@@ -46,7 +46,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -39,7 +39,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -18,7 +18,7 @@ require (
github.com/aws/aws-sdk-go-v2 v1.41.3 github.com/aws/aws-sdk-go-v2 v1.41.3
github.com/aws/aws-sdk-go-v2/config v1.32.11 github.com/aws/aws-sdk-go-v2/config v1.32.11
github.com/aws/aws-sdk-go-v2/credentials v1.19.11 github.com/aws/aws-sdk-go-v2/credentials v1.19.11
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4 github.com/aws/aws-sdk-go-v2/service/s3 v1.97.0
github.com/go-chi/chi/v5 v5.2.5 github.com/go-chi/chi/v5 v5.2.5
github.com/go-chi/cors v1.2.2 github.com/go-chi/cors v1.2.2
github.com/go-chi/jwtauth/v5 v5.4.0 github.com/go-chi/jwtauth/v5 v5.4.0
@@ -37,7 +37,7 @@ require (
github.com/testcontainers/testcontainers-go/modules/mongodb v0.33.0 github.com/testcontainers/testcontainers-go/modules/mongodb v0.33.0
go.mongodb.org/mongo-driver/v2 v2.5.0 go.mongodb.org/mongo-driver/v2 v2.5.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
golang.org/x/net v0.51.0 golang.org/x/net v0.52.0
google.golang.org/grpc v1.79.2 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@@ -88,7 +88,7 @@ require (
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-json v0.10.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect

View File

@@ -32,8 +32,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7su
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19 h1:JnQeStZvPHFHeyky/7LbMlyQjUa+jIBj36OlWm0pzIk= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19 h1:JnQeStZvPHFHeyky/7LbMlyQjUa+jIBj36OlWm0pzIk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19/go.mod h1:HGyasyHvYdFQeJhvDHfH7HXkHh57htcJGKDZ+7z+I24= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.19/go.mod h1:HGyasyHvYdFQeJhvDHfH7HXkHh57htcJGKDZ+7z+I24=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4 h1:4ExZyubQ6LQQVuF2Qp9OsfEvsTdAWh5Gfwf6PgIdLdk= github.com/aws/aws-sdk-go-v2/service/s3 v1.97.0 h1:zyKY4OxzUImu+DigelJI9o49QQv8CjREs5E1CywjtIA=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.4/go.mod h1:NF3JcMGOiARAss1ld3WGORCw71+4ExDD2cbbdKS5PpA= github.com/aws/aws-sdk-go-v2/service/s3 v1.97.0/go.mod h1:NF3JcMGOiARAss1ld3WGORCw71+4ExDD2cbbdKS5PpA=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias= github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias=
@@ -112,8 +112,8 @@ github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
@@ -346,8 +346,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View File

@@ -16,6 +16,8 @@ import (
"github.com/tech/sendico/pkg/mutil/mzap" "github.com/tech/sendico/pkg/mutil/mzap"
documentsv1 "github.com/tech/sendico/pkg/proto/billing/documents/v1" documentsv1 "github.com/tech/sendico/pkg/proto/billing/documents/v1"
connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1" connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1"
endpointv1 "github.com/tech/sendico/pkg/proto/payments/endpoint/v1"
orchestrationv2 "github.com/tech/sendico/pkg/proto/payments/orchestration/v2"
"github.com/tech/sendico/server/interface/api/sresponse" "github.com/tech/sendico/server/interface/api/sresponse"
mutil "github.com/tech/sendico/server/internal/mutil/param" mutil "github.com/tech/sendico/server/internal/mutil/param"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
@@ -24,7 +26,6 @@ import (
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb"
) )
const ( const (
@@ -61,6 +62,10 @@ func (a *PaymentAPI) getOperationDocument(r *http.Request, account *model.Accoun
if operationRef == "" { if operationRef == "" {
return response.BadRequest(a.logger, a.Name(), "missing_parameter", "operation_ref is required") return response.BadRequest(a.logger, a.Name(), "missing_parameter", "operation_ref is required")
} }
paymentRef := strings.TrimSpace(query.Get("payment_ref"))
if paymentRef == "" {
return response.BadRequest(a.logger, a.Name(), "missing_parameter", "payment_ref is required")
}
service, gateway, h := a.resolveOperationDocumentDeps(r.Context(), gatewayService) service, gateway, h := a.resolveOperationDocumentDeps(r.Context(), gatewayService)
if h != nil { if h != nil {
@@ -73,7 +78,18 @@ func (a *PaymentAPI) getOperationDocument(r *http.Request, account *model.Accoun
return documentErrorResponse(a.logger, a.Name(), err) return documentErrorResponse(a.logger, a.Name(), err)
} }
req := operationDocumentRequest(orgRef.Hex(), gatewayService, operationRef, op) req := operationDocumentRequest(orgRef.Hex(), gatewayService, operationRef, paymentRef, op)
if payment, paymentErr := a.fetchPayment(r.Context(), orgRef.Hex(), paymentRef); paymentErr != nil {
a.logger.Warn(
"Failed to fetch payment snapshot for operation document",
zap.Error(paymentErr),
mzap.ObjRef("organization_ref", orgRef),
zap.String("payment_ref", paymentRef),
zap.String("operation_ref", operationRef),
)
} else {
enrichOperationDocumentRequestFromPayment(req, payment)
}
docResp, err := a.fetchOperationDocument(r.Context(), service.InvokeURI, req) docResp, err := a.fetchOperationDocument(r.Context(), service.InvokeURI, req)
if err != nil { if err != nil {
@@ -263,6 +279,28 @@ func (a *PaymentAPI) fetchGatewayOperation(ctx context.Context, invokeURI, opera
return op, nil return op, nil
} }
func (a *PaymentAPI) fetchPayment(ctx context.Context, organizationRef, paymentRef string) (*orchestrationv2.Payment, error) {
if a.execution == nil {
return nil, merrors.Internal("payment execution client is not configured")
}
resp, err := a.execution.GetPayment(ctx, &orchestrationv2.GetPaymentRequest{
Meta: requestMeta(organizationRef, ""),
PaymentRef: strings.TrimSpace(paymentRef),
})
if err != nil {
return nil, err
}
if resp == nil {
return nil, merrors.NoData("payment orchestrator returned empty response")
}
if resp.GetPayment() == nil {
return nil, merrors.NoData("payment orchestrator returned empty payment")
}
return resp.GetPayment(), nil
}
func findGatewayForService(gateways []discovery.GatewaySummary, gatewayService mservice.Type) *discovery.GatewaySummary { func findGatewayForService(gateways []discovery.GatewaySummary, gatewayService mservice.Type) *discovery.GatewaySummary {
candidates := make([]discovery.GatewaySummary, 0, len(gateways)) candidates := make([]discovery.GatewaySummary, 0, len(gateways))
for _, gw := range gateways { for _, gw := range gateways {
@@ -313,13 +351,14 @@ func findGatewayForService(gateways []discovery.GatewaySummary, gatewayService m
return &best return &best
} }
func operationDocumentRequest(organizationRef string, gatewayService mservice.Type, requestedOperationRef string, op *connectorv1.Operation) *documentsv1.GetOperationDocumentRequest { func operationDocumentRequest(organizationRef string, gatewayService mservice.Type, requestedOperationRef string, paymentRef string, op *connectorv1.Operation) *documentsv1.GetOperationDocumentRequest {
req := &documentsv1.GetOperationDocumentRequest{ req := &documentsv1.GetOperationDocumentRequest{
OrganizationRef: strings.TrimSpace(organizationRef), OrganizationRef: strings.TrimSpace(organizationRef),
GatewayService: gatewayService, GatewayService: gatewayService,
OperationRef: firstNonEmpty(strings.TrimSpace(op.GetOperationRef()), strings.TrimSpace(requestedOperationRef)), OperationRef: firstNonEmpty(strings.TrimSpace(op.GetOperationRef()), strings.TrimSpace(requestedOperationRef)),
PaymentRef: strings.TrimSpace(paymentRef),
OperationCode: strings.TrimSpace(op.GetType().String()), OperationCode: strings.TrimSpace(op.GetType().String()),
OperationLabel: operationLabel(op.GetType()), OperationLabel: strings.TrimSpace(op.GetType().String()),
OperationState: strings.TrimSpace(op.GetStatus().String()), OperationState: strings.TrimSpace(op.GetStatus().String()),
Amount: strings.TrimSpace(op.GetMoney().GetAmount()), Amount: strings.TrimSpace(op.GetMoney().GetAmount()),
Currency: strings.TrimSpace(op.GetMoney().GetCurrency()), Currency: strings.TrimSpace(op.GetMoney().GetCurrency()),
@@ -332,63 +371,94 @@ func operationDocumentRequest(organizationRef string, gatewayService mservice.Ty
req.CompletedAtUnixMs = ts.AsTime().UnixMilli() req.CompletedAtUnixMs = ts.AsTime().UnixMilli()
} }
req.PaymentRef = operationParamValue(op.GetParams(), "payment_ref", "parent_payment_ref", "paymentRef", "parentPaymentRef") if isFailedOperationStatus(op.GetStatus()) {
req.FailureCode = firstNonEmpty( req.FailureCode = strings.TrimSpace(op.GetStatus().String())
operationParamValue(op.GetParams(), "failure_code", "provider_code", "error_code"), }
failureCodeFromStatus(op.GetStatus()),
)
req.FailureReason = operationParamValue(op.GetParams(), "failure_reason", "provider_message", "error", "message")
return req return req
} }
func operationLabel(opType connectorv1.OperationType) string { func isFailedOperationStatus(status connectorv1.OperationStatus) bool {
switch opType { return status == connectorv1.OperationStatus_OPERATION_FAILED || status == connectorv1.OperationStatus_OPERATION_CANCELLED
case connectorv1.OperationType_CREDIT:
return "Credit"
case connectorv1.OperationType_DEBIT:
return "Debit"
case connectorv1.OperationType_TRANSFER:
return "Transfer"
case connectorv1.OperationType_PAYOUT:
return "Payout"
case connectorv1.OperationType_FEE_ESTIMATE:
return "Fee Estimate"
case connectorv1.OperationType_FX:
return "FX"
case connectorv1.OperationType_GAS_TOPUP:
return "Gas Top Up"
default:
return strings.TrimSpace(opType.String())
}
} }
func failureCodeFromStatus(status connectorv1.OperationStatus) string { func enrichOperationDocumentRequestFromPayment(req *documentsv1.GetOperationDocumentRequest, payment *orchestrationv2.Payment) {
switch status { if req == nil || payment == nil {
case connectorv1.OperationStatus_OPERATION_FAILED, connectorv1.OperationStatus_OPERATION_CANCELLED: return
return strings.TrimSpace(status.String())
default:
return ""
} }
req.PaymentRef = firstNonEmpty(strings.TrimSpace(req.GetPaymentRef()), strings.TrimSpace(payment.GetPaymentRef()))
req.ClientName = firstNonEmpty(strings.TrimSpace(req.GetClientName()), paymentClientName(payment))
} }
func operationParamValue(params *structpb.Struct, keys ...string) string { func paymentClientName(payment *orchestrationv2.Payment) string {
if params == nil { if payment == nil {
return "" return ""
} }
values := params.AsMap() intent := payment.GetIntentSnapshot()
for _, key := range keys { if intent == nil {
raw, ok := values[key] return ""
if !ok {
continue
}
if text := strings.TrimSpace(fmt.Sprint(raw)); text != "" && text != "<nil>" {
return text
}
} }
return "" if customerDescription := strings.TrimSpace(intent.GetComment()); customerDescription != "" {
return customerDescription
}
return firstNonEmpty(
paymentEndpointClientName(intent.GetDestination()),
paymentEndpointClientName(intent.GetSource()),
)
}
func paymentEndpointClientName(endpoint *endpointv1.PaymentEndpoint) string {
if endpoint == nil {
return ""
}
method := endpoint.GetPaymentMethod()
if method == nil {
return ""
}
switch method.GetType() {
case endpointv1.PaymentMethodType_PAYMENT_METHOD_TYPE_CARD:
type cardMethodData struct {
FirstName string `bson:"firstName"`
LastName string `bson:"lastName"`
}
var payload cardMethodData
if err := bson.Unmarshal(method.GetData(), &payload); err != nil {
return ""
}
return strings.TrimSpace(strings.Join([]string{
strings.TrimSpace(payload.FirstName),
strings.TrimSpace(payload.LastName),
}, " "))
case endpointv1.PaymentMethodType_PAYMENT_METHOD_TYPE_BANK_ACCOUNT:
type bankMethodData struct {
RecipientName string `bson:"recipientName"`
}
var payload bankMethodData
if err := bson.Unmarshal(method.GetData(), &payload); err != nil {
return ""
}
return strings.TrimSpace(payload.RecipientName)
case endpointv1.PaymentMethodType_PAYMENT_METHOD_TYPE_IBAN:
type ibanMethodData struct {
AccountHolder string `bson:"accountHolder"`
}
var payload ibanMethodData
if err := bson.Unmarshal(method.GetData(), &payload); err != nil {
return ""
}
return strings.TrimSpace(payload.AccountHolder)
default:
return ""
}
} }
func findDocumentsService(services []discovery.ServiceSummary) *discovery.ServiceSummary { func findDocumentsService(services []discovery.ServiceSummary) *discovery.ServiceSummary {

View File

@@ -0,0 +1,120 @@
package paymentapiimp
import (
"testing"
"github.com/tech/sendico/pkg/mservice"
documentsv1 "github.com/tech/sendico/pkg/proto/billing/documents/v1"
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1"
endpointv1 "github.com/tech/sendico/pkg/proto/payments/endpoint/v1"
orchestrationv2 "github.com/tech/sendico/pkg/proto/payments/orchestration/v2"
quotationv2 "github.com/tech/sendico/pkg/proto/payments/quotation/v2"
"go.mongodb.org/mongo-driver/v2/bson"
)
func TestOperationDocumentRequest_UsesStructuredOperationFieldsOnly(t *testing.T) {
op := &connectorv1.Operation{
OperationRef: "pay-123:hop_1",
Type: connectorv1.OperationType_TRANSFER,
Status: connectorv1.OperationStatus_OPERATION_SUCCESS,
Money: &moneyv1.Money{
Amount: "100.50",
Currency: "USDT",
},
}
req := operationDocumentRequest("org-1", mservice.ChainGateway, "requested-op", "pay-123", op)
if req == nil {
t.Fatalf("expected request")
}
if got, want := req.GetPaymentRef(), "pay-123"; got != want {
t.Fatalf("payment_ref mismatch: got=%q want=%q", got, want)
}
if got := req.GetClientName(); got != "" {
t.Fatalf("expected empty client_name from operation-only request, got=%q", got)
}
if got := req.GetClientAddress(); got != "" {
t.Fatalf("expected empty client_address from operation-only request, got=%q", got)
}
}
func TestOperationDocumentRequest_FailureCodeFromStructuredStatus(t *testing.T) {
req := operationDocumentRequest("org-1", mservice.ChainGateway, "op", "pay-123", &connectorv1.Operation{
OperationRef: "pay-123:hop_1",
Type: connectorv1.OperationType_TRANSFER,
Status: connectorv1.OperationStatus_OPERATION_FAILED,
})
if req == nil {
t.Fatalf("expected request")
}
if got, want := req.GetFailureCode(), "OPERATION_FAILED"; got != want {
t.Fatalf("failure_code mismatch: got=%q want=%q", got, want)
}
}
func TestPaymentClientName_FromIntentComment(t *testing.T) {
payment := &orchestrationv2.Payment{
IntentSnapshot: &quotationv2.QuoteIntent{
Comment: "Jane Customer",
},
}
if got, want := paymentClientName(payment), "Jane Customer"; got != want {
t.Fatalf("paymentClientName mismatch: got=%q want=%q", got, want)
}
}
func TestPaymentClientName_FromStructuredCardEndpoint(t *testing.T) {
raw, err := bson.Marshal(map[string]string{
"firstName": "Jane",
"lastName": "Doe",
})
if err != nil {
t.Fatalf("Marshal: %v", err)
}
payment := &orchestrationv2.Payment{
IntentSnapshot: &quotationv2.QuoteIntent{
Destination: &endpointv1.PaymentEndpoint{
Source: &endpointv1.PaymentEndpoint_PaymentMethod{
PaymentMethod: &endpointv1.PaymentMethod{
Type: endpointv1.PaymentMethodType_PAYMENT_METHOD_TYPE_CARD,
Data: raw,
},
},
},
},
}
if got, want := paymentClientName(payment), "Jane Doe"; got != want {
t.Fatalf("paymentClientName mismatch: got=%q want=%q", got, want)
}
}
func TestEnrichOperationDocumentRequestFromPayment_SetsClientName(t *testing.T) {
req := &documentsv1.GetOperationDocumentRequest{
OperationRef: "pay-123:hop_1",
}
payment := &orchestrationv2.Payment{
PaymentRef: "pay-123",
IntentSnapshot: &quotationv2.QuoteIntent{
Comment: "Client Name",
},
}
enrichOperationDocumentRequestFromPayment(req, payment)
if got, want := req.GetPaymentRef(), "pay-123"; got != want {
t.Fatalf("payment_ref mismatch: got=%q want=%q", got, want)
}
if got, want := req.GetClientName(), "Client Name"; got != want {
t.Fatalf("client_name mismatch: got=%q want=%q", got, want)
}
}
func TestOperationDocumentRequest_Compatibility(t *testing.T) {
var _ *documentsv1.GetOperationDocumentRequest = operationDocumentRequest("org-1", mservice.ChainGateway, "op", "pay-1", &connectorv1.Operation{})
}

View File

@@ -165,6 +165,10 @@ func (*fakeExecutionClientForBatch) ListPayments(context.Context, *orchestration
return &orchestrationv2.ListPaymentsResponse{}, nil return &orchestrationv2.ListPaymentsResponse{}, nil
} }
func (*fakeExecutionClientForBatch) GetPayment(context.Context, *orchestrationv2.GetPaymentRequest) (*orchestrationv2.GetPaymentResponse, error) {
return &orchestrationv2.GetPaymentResponse{}, nil
}
func (*fakeExecutionClientForBatch) Close() error { return nil } func (*fakeExecutionClientForBatch) Close() error { return nil }
type fakeEnforcerForBatch struct { type fakeEnforcerForBatch struct {

View File

@@ -32,6 +32,7 @@ import (
type executionClient interface { type executionClient interface {
ExecutePayment(ctx context.Context, req *orchestrationv2.ExecutePaymentRequest) (*orchestrationv2.ExecutePaymentResponse, error) ExecutePayment(ctx context.Context, req *orchestrationv2.ExecutePaymentRequest) (*orchestrationv2.ExecutePaymentResponse, error)
ExecuteBatchPayment(ctx context.Context, req *orchestrationv2.ExecuteBatchPaymentRequest) (*orchestrationv2.ExecuteBatchPaymentResponse, error) ExecuteBatchPayment(ctx context.Context, req *orchestrationv2.ExecuteBatchPaymentRequest) (*orchestrationv2.ExecuteBatchPaymentResponse, error)
GetPayment(ctx context.Context, req *orchestrationv2.GetPaymentRequest) (*orchestrationv2.GetPaymentResponse, error)
ListPayments(ctx context.Context, req *orchestrationv2.ListPaymentsRequest) (*orchestrationv2.ListPaymentsResponse, error) ListPayments(ctx context.Context, req *orchestrationv2.ListPaymentsRequest) (*orchestrationv2.ListPaymentsResponse, error)
Close() error Close() error
} }

View File

@@ -53,7 +53,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -212,8 +212,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -13,7 +13,7 @@ require (
github.com/tech/sendico/fx/storage v0.0.0 github.com/tech/sendico/fx/storage v0.0.0
github.com/tech/sendico/pkg v0.1.0 github.com/tech/sendico/pkg v0.1.0
go.uber.org/zap v1.27.1 go.uber.org/zap v1.27.1
golang.org/x/net v0.51.0 golang.org/x/net v0.52.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

View File

@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -44,7 +44,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -47,7 +47,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -181,8 +181,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -86,7 +86,7 @@ require (
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -322,8 +322,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -44,7 +44,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -47,7 +47,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -181,8 +181,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -44,7 +44,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -94,7 +94,7 @@ require (
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -337,8 +337,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -45,7 +45,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -181,8 +181,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -47,7 +47,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect

View File

@@ -196,8 +196,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -45,7 +45,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -181,8 +181,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -60,7 +60,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -182,8 +182,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -59,7 +59,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -182,8 +182,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=

View File

@@ -108,7 +108,7 @@ require (
go.opentelemetry.io/otel/trace v1.39.0 // indirect go.opentelemetry.io/otel/trace v1.39.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect

View File

@@ -289,8 +289,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View File

@@ -48,4 +48,6 @@ message GetOperationDocumentRequest {
int64 started_at_unix_ms = 12; int64 started_at_unix_ms = 12;
int64 completed_at_unix_ms = 13; int64 completed_at_unix_ms = 13;
string client_name = 14;
string client_address = 15;
} }

View File

@@ -13,10 +13,12 @@ class PaymentDocumentsService {
String organizationRef, String organizationRef,
String gatewayService, String gatewayService,
String operationRef, String operationRef,
String paymentRef,
) async { ) async {
final query = <String, String>{ final query = <String, String>{
'gateway_service': gatewayService, 'gateway_service': gatewayService,
'operation_ref': operationRef, 'operation_ref': operationRef,
'payment_ref': paymentRef,
}; };
final queryString = Uri(queryParameters: query).query; final queryString = Uri(queryParameters: query).query;
final url = '/documents/operation/$organizationRef?$queryString'; final url = '/documents/operation/$organizationRef?$queryString';

View File

@@ -348,7 +348,7 @@ RouteBase payoutShellRoute() => ShellRoute(
path: PayoutRoutes.reportPaymentPath, path: PayoutRoutes.reportPaymentPath,
pageBuilder: (_, state) => NoTransitionPage( pageBuilder: (_, state) => NoTransitionPage(
child: PaymentDetailsPage( child: PaymentDetailsPage(
paymentId: paymentRef:
state.uri.queryParameters[PayoutRoutes.reportPaymentIdQuery] ?? state.uri.queryParameters[PayoutRoutes.reportPaymentIdQuery] ??
'', '',
), ),

View File

@@ -9,14 +9,14 @@ import 'package:pweb/utils/report/operations/document_rule.dart';
class PaymentDetailsController extends ChangeNotifier { class PaymentDetailsController extends ChangeNotifier {
PaymentDetailsController({required String paymentId}) PaymentDetailsController({required String paymentRef})
: _paymentId = paymentId; : _paymentRef = paymentRef;
PaymentsProvider? _payments; PaymentsProvider? _payments;
String _paymentId; String _paymentRef;
Payment? _payment; Payment? _payment;
String get paymentId => _paymentId; String get paymentId => _paymentRef;
Payment? get payment => _payment; Payment? get payment => _payment;
bool get isLoading => _payments?.isLoading ?? false; bool get isLoading => _payments?.isLoading ?? false;
Exception? get error => _payments?.error; Exception? get error => _payments?.error;
@@ -44,8 +44,8 @@ class PaymentDetailsController extends ChangeNotifier {
operationDocumentRequest(operation) != null; operationDocumentRequest(operation) != null;
void update(PaymentsProvider provider, String paymentId) { void update(PaymentsProvider provider, String paymentId) {
if (_paymentId != paymentId) { if (_paymentRef != paymentId) {
_paymentId = paymentId; _paymentRef = paymentId;
} }
if (!identical(_payments, provider)) { if (!identical(_payments, provider)) {
@@ -60,7 +60,7 @@ class PaymentDetailsController extends ChangeNotifier {
} }
void _rebuild() { void _rebuild() {
_payment = _findPayment(_payments?.payments ?? const [], _paymentId); _payment = _findPayment(_payments?.payments ?? const [], _paymentRef);
notifyListeners(); notifyListeners();
} }

View File

@@ -17,9 +17,9 @@ import 'package:pweb/generated/i18n/app_localizations.dart';
class PaymentDetailsPage extends StatelessWidget { class PaymentDetailsPage extends StatelessWidget {
final String paymentId; final String paymentRef;
const PaymentDetailsPage({super.key, required this.paymentId}); const PaymentDetailsPage({super.key, required this.paymentRef});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -27,16 +27,18 @@ class PaymentDetailsPage extends StatelessWidget {
PaymentsProvider, PaymentsProvider,
PaymentDetailsController PaymentDetailsController
>( >(
create: (_) => PaymentDetailsController(paymentId: paymentId), create: (_) => PaymentDetailsController(paymentRef: paymentRef),
update: (_, payments, controller) => update: (_, payments, controller) =>
controller!..update(payments, paymentId), controller!..update(payments, paymentRef),
child: const _PaymentDetailsView(), child: _PaymentDetailsView(paymentRef: paymentRef),
); );
} }
} }
class _PaymentDetailsView extends StatelessWidget { class _PaymentDetailsView extends StatelessWidget {
const _PaymentDetailsView(); final String paymentRef;
const _PaymentDetailsView({required this.paymentRef});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -73,6 +75,7 @@ class _PaymentDetailsView extends StatelessWidget {
context, context,
gatewayService: request.gatewayService, gatewayService: request.gatewayService,
operationRef: request.operationRef, operationRef: request.operationRef,
paymentRef: paymentRef,
); );
}, },
); );

View File

@@ -13,7 +13,7 @@ import 'package:pweb/generated/i18n/app_localizations.dart';
class OperationRow { class OperationRow {
static DataRow build(OperationItem op, BuildContext context) { static DataRow build(String paymentRef, OperationItem op, BuildContext context) {
final isUnknownDate = op.date.millisecondsSinceEpoch == 0; final isUnknownDate = op.date.millisecondsSinceEpoch == 0;
final localDate = op.date.toLocal(); final localDate = op.date.toLocal();
final loc = AppLocalizations.of(context)!; final loc = AppLocalizations.of(context)!;
@@ -33,6 +33,7 @@ class OperationRow {
context, context,
gatewayService: op.gatewayService ?? '', gatewayService: op.gatewayService ?? '',
operationRef: op.operationRef ?? '', operationRef: op.operationRef ?? '',
paymentRef: paymentRef,
), ),
icon: const Icon(Icons.download), icon: const Icon(Icons.download),
label: Text(loc.downloadAct), label: Text(loc.downloadAct),

View File

@@ -6,11 +6,13 @@ import 'package:pweb/pages/report/table/row.dart';
class OperationsTable extends StatelessWidget { class OperationsTable extends StatelessWidget {
final String paymentRef;
final List<OperationItem> operations; final List<OperationItem> operations;
final bool showFileNameColumn; final bool showFileNameColumn;
const OperationsTable({ const OperationsTable({
super.key, super.key,
required this.paymentRef,
required this.operations, required this.operations,
required this.showFileNameColumn, required this.showFileNameColumn,
}); });
@@ -49,7 +51,7 @@ class OperationsTable extends StatelessWidget {
}); });
// Use the DataRow built by OperationRow and extract its cells // Use the DataRow built by OperationRow and extract its cells
final row = OperationRow.build(op, context); final row = OperationRow.build(paymentRef, op, context);
return DataRow.byIndex( return DataRow.byIndex(
index: index, index: index,
color: color, color: color,

View File

@@ -10,10 +10,12 @@ import 'package:pweb/utils/error/snackbar.dart';
import 'package:pweb/generated/i18n/app_localizations.dart'; import 'package:pweb/generated/i18n/app_localizations.dart';
Future<void> downloadPaymentAct( Future<void> downloadPaymentAct(
BuildContext context, { BuildContext context, {
required String gatewayService, required String gatewayService,
required String operationRef, required String operationRef,
required String paymentRef,
}) async { }) async {
final organizations = context.read<OrganizationsProvider>(); final organizations = context.read<OrganizationsProvider>();
if (!organizations.isOrganizationSet) { if (!organizations.isOrganizationSet) {
@@ -21,7 +23,8 @@ Future<void> downloadPaymentAct(
} }
final gateway = gatewayService.trim(); final gateway = gatewayService.trim();
final operation = operationRef.trim(); final operation = operationRef.trim();
if (gateway.isEmpty || operation.isEmpty) { final payment = paymentRef.trim();
if (gateway.isEmpty || operation.isEmpty || payment.isEmpty) {
return; return;
} }
@@ -33,6 +36,7 @@ Future<void> downloadPaymentAct(
organizations.current.id, organizations.current.id,
gateway, gateway,
operation, operation,
payment,
); );
await downloadFile(file); await downloadFile(file);
}, },

0
t.json
View File