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

@@ -289,6 +289,8 @@ type operationSnapshot struct {
GatewayService string
OperationRef string
PaymentRef string
ClientName string
ClientAddress string
OperationCode string
OperationLabel string
OperationState string
@@ -306,6 +308,8 @@ func operationSnapshotFromRequest(req *documentsv1.GetOperationDocumentRequest)
GatewayService: strings.TrimSpace(req.GetGatewayService()),
OperationRef: strings.TrimSpace(req.GetOperationRef()),
PaymentRef: strings.TrimSpace(req.GetPaymentRef()),
ClientName: strings.TrimSpace(req.GetClientName()),
ClientAddress: strings.TrimSpace(req.GetClientAddress()),
OperationCode: strings.TrimSpace(req.GetOperationCode()),
OperationLabel: strings.TrimSpace(req.GetOperationLabel()),
OperationState: strings.TrimSpace(req.GetOperationState()),
@@ -328,21 +332,6 @@ func operationSnapshotFromRequest(req *documentsv1.GetOperationDocumentRequest)
func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block {
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{
{
Tag: renderer.TagTitle,
@@ -355,30 +344,115 @@ func buildOperationBlocks(snapshot operationSnapshot) []renderer.Block {
{
Tag: renderer.TagMeta,
Lines: []string{
documentCopy.MetaDocumentType,
fmt.Sprintf("%s: %s", documentCopy.MetaCertificateNumberLabel, certificateNumber(snapshot)),
fmt.Sprintf("%s: %s", documentCopy.MetaDateLabel, formatCertificateDate(certificateDate(snapshot))),
},
},
{
Tag: renderer.TagSection,
Lines: []string{documentCopy.SectionOperation},
Lines: []string{documentCopy.SectionParties},
},
{
Tag: renderer.TagKV,
Rows: rows,
Tag: renderer.TagText,
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 != "" {
blocks = append(blocks,
renderer.Block{Tag: renderer.TagSection, Lines: []string{documentCopy.SectionFailure}},
renderer.Block{
Tag: renderer.TagKV,
Rows: [][]string{
{documentCopy.RowFailureCode, safeValue(snapshot.FailureCode)},
{documentCopy.RowFailureReason, safeValue(snapshot.FailureReason)},
},
blocks = append(blocks, renderer.Block{
Tag: renderer.TagKV,
Rows: [][]string{
{documentCopy.RowFailureCode, safeValue(snapshot.FailureCode)},
{documentCopy.RowFailureReason, safeValue(snapshot.FailureReason)},
},
)
})
}
return blocks
@@ -392,6 +466,80 @@ func formatSnapshotTime(value time.Time) string {
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 {
trimmed := strings.TrimSpace(value)
if trimmed == "" {

View File

@@ -3,6 +3,7 @@ package documents
import (
"bytes"
"context"
"strings"
"testing"
"time"
@@ -191,3 +192,92 @@ func TestGetOperationDocument_RequiresOperationRef(t *testing.T) {
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
}