diff --git a/CHANGELOG.md b/CHANGELOG.md index 67ab2e97d..7e4e28b36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -120,6 +120,34 @@ follow semantic versioning; release dates are ISO 8601. ### Templates +- **A violet SaaS invoice preset: `WorkspaceInvoice`.** A brand masthead over a short + accent bar, a half-split issuer and metadata header, two addressed parties on filled + discs, a service-line table whose marks sit on coloured tiles, a settlement row + pairing the bank details against the totals, and a closing band carrying the wordmark. + Ships as `invoice.presets.WorkspaceInvoice` on the existing `StructuredInvoiceData` + model, porting the rendered layout of a published standalone template. Like + `PaymentsInvoice` it flows — the table's header repeats on every page it reaches, a + continuation page reserves a deeper bottom margin, and every page carries its number, + which is a departure from the one-page design and the only way a lost page is + detectable. The sheet's own closing band cannot be page chrome, because a header + footer zone takes only strings and the band holds a wordmark and a link, so it is body + content and the number is the only chrome. Two of the design's own type corrections + are carried as measured constants rather than smoothed away: a cap read off a + screenshot includes half a pixel of antialiasing on each edge, and the body face sets + uppercase about 6% wider than the design's at the same cap height — measured across + three all-caps runs while mixed-case runs at the same sizes matched within 2%. This + design states its currency once per money column and writes the figures under it bare, + carrying the code only on the total, which is the opposite of what `PaymentsInvoice` + does and is why the two presets format money differently. A quantity is written with + what it counts. Both parties print a registration under their address through the pair + `InvoiceRecipient` gained for it, and a party with no number prints no label. Guarded + by a smoke test (including the unknown-mark data error, a line with no mark, the + wordmark fallback, the currency named once and not on every figure, the quantity with + its unit, both registrations and the absent one, the closing address as an annotation, + a missing ship-to, a payment card with no note, an empty document, and a thirty-line + invoice that runs on, repeats its column names and numbers its pages), an exact layout + snapshot and a pixel-parity gate; the examples showcase gains `invoice-workspace-v2`. + - **A paginating invoice preset: `PaymentsInvoice`.** A lavender-and-navy sheet with a diagonal band crossing the masthead, a half-split issuer and metadata header, two addressed parties on discs, a marked service-line table, a settlement row pairing bank diff --git a/assets/readme/examples/invoice-workspace-v2.pdf b/assets/readme/examples/invoice-workspace-v2.pdf new file mode 100644 index 000000000..b12e2f858 Binary files /dev/null and b/assets/readme/examples/invoice-workspace-v2.pdf differ diff --git a/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java b/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java index 54f713e62..6d6d11d08 100644 --- a/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java +++ b/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java @@ -110,6 +110,7 @@ import com.demcha.examples.templates.invoice.ConsultingInvoiceV2Example; import com.demcha.examples.templates.invoice.LumaStudioInvoiceV2Example; import com.demcha.examples.templates.invoice.PaymentsInvoiceV2Example; +import com.demcha.examples.templates.invoice.WorkspaceInvoiceV2Example; import com.demcha.examples.templates.invoice.InvoiceCinematicFileExample; import com.demcha.examples.templates.invoice.ModernInvoiceV2Example; import com.demcha.examples.templates.proposal.CinematicProposalFileExample; @@ -192,6 +193,7 @@ public static void main(String[] args) throws Exception { System.out.println("Generated: " + ConsultingInvoiceV2Example.generate()); System.out.println("Generated: " + LumaStudioInvoiceV2Example.generate()); System.out.println("Generated: " + PaymentsInvoiceV2Example.generate()); + System.out.println("Generated: " + WorkspaceInvoiceV2Example.generate()); // Proposals System.out.println("Generated: " + ProposalCinematicFileExample.generate()); diff --git a/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java b/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java index 98e18d416..236d8d6f7 100644 --- a/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java +++ b/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java @@ -100,6 +100,7 @@ record Entry(String title, String description, List tags, String codeUrl invoice("invoice-consulting-v2", "v2/ConsultingInvoiceV2Example", "Consulting Invoice", "The ConsultingInvoice preset on the structured invoice model — brand lockup with the caller's logo, labelled masthead metadata, priced service lines with service periods, a totals stack and bank payment fields.", "invoice"); invoice("invoice-luma-studio-v2", "v2/LumaStudioInvoiceV2Example", "Luma Studio Invoice", "The LumaStudioInvoice preset on the structured invoice model — a cream sidebar carrying the brand lockup and its ornament, a billed-to / shipped-to pair, priced service lines with a VAT column, and the notes and bank details above a sign-off band.", "invoice"); invoice("invoice-payments-v2", "v2/PaymentsInvoiceV2Example", "Payments Invoice", "The PaymentsInvoice preset on the structured invoice model — a diagonal band crossing the masthead, a half-split issuer and metadata header, two addressed parties, marked service lines that repeat their header across pages, and a settlement row pairing bank details against the totals.", "invoice"); + invoice("invoice-workspace-v2", "v2/WorkspaceInvoiceV2Example", "Workspace Invoice", "The WorkspaceInvoice preset on the structured invoice model — a brand masthead over an accent bar, a half-split issuer and metadata header, two addressed parties on discs, service lines whose marks sit on coloured tiles, and a settlement row above a closing band.", "invoice"); invoice("invoice-modern-v2", "v2/ModernInvoiceV2Example", "Modern Invoice", "The ModernInvoice preset composed straight from an InvoiceDocumentSpec — line items, totals and payment block driven by the BrandTheme rather than per-document styling.", "invoice"); invoice("invoice-classic-v2", "v2/ClassicInvoiceV2Example", "Classic Invoice", "The ClassicInvoice preset — letterhead header band, TOTAL DUE hero strip, BILL TO / FROM columns, and a dedicated Summary table after the line items.", "invoice"); diff --git a/examples/src/main/java/com/demcha/examples/support/WorkspaceInvoiceSampleData.java b/examples/src/main/java/com/demcha/examples/support/WorkspaceInvoiceSampleData.java new file mode 100644 index 000000000..9a569a11e --- /dev/null +++ b/examples/src/main/java/com/demcha/examples/support/WorkspaceInvoiceSampleData.java @@ -0,0 +1,141 @@ +package com.demcha.examples.support; + +import com.demcha.compose.document.templates.data.invoice.InvoiceBrand; +import com.demcha.compose.document.templates.data.invoice.InvoiceContactBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceMasthead; +import com.demcha.compose.document.templates.data.invoice.InvoiceNotesBlock; +import com.demcha.compose.document.templates.data.invoice.InvoicePaymentBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceRecipient; +import com.demcha.compose.document.templates.data.invoice.InvoiceServiceLines; +import com.demcha.compose.document.templates.data.invoice.InvoiceSummaryBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceTotalsBlock; +import com.demcha.compose.document.templates.data.invoice.StructuredInvoiceData; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * Shared sample data for the Workspace invoice example. + * + *

Kept in lockstep with the qa module's {@code WorkspaceInvoiceFixtures} — + * the two modules cannot share a source file, so a content change here belongs + * there too.

+ */ +public final class WorkspaceInvoiceSampleData { + + private WorkspaceInvoiceSampleData() { + } + + /** + * The sample invoice — six metadata rows, two addressed parties, four + * marked service lines, eight payment fields, two summed rows and a closing + * line with an address inside it. + * + * @return the document the example renders + */ + public static StructuredInvoiceData sample() { + return new StructuredInvoiceData( + brand(), supplier(), masthead(), billTo(), shipTo(), + new InvoiceSummaryBlock("", "", ""), + serviceLines(), totals(), payment(), notes(), "USD"); + } + + /** No logo: the wordmark is what a document without one falls back to. */ + private static InvoiceBrand brand() { + return new InvoiceBrand(null, "kestrel", "", "", "", ""); + } + + private static InvoiceContactBlock supplier() { + return new InvoiceContactBlock( + "Kestrel Collaboration, Inc.", + List.of("500 Howard Street, 6th Floor", "San Francisco, CA 94105", + "United States"), + "", "", "kestrel.example", + "", "", + "VAT ID:", "US 77-0560185"); + } + + private static InvoiceMasthead masthead() { + List entries = new ArrayList<>(); + entries.add(new InvoiceMasthead.Entry("Invoice Number:", "INV-2024-0003521", true)); + entries.add(new InvoiceMasthead.Entry("Invoice Date:", "27 May 2024", false)); + entries.add(new InvoiceMasthead.Entry("Billing Period:", "1 - 31 May 2024", false)); + entries.add(new InvoiceMasthead.Entry("Workspace ID:", "T04FQ9L2M", false)); + entries.add(new InvoiceMasthead.Entry("Payment Terms:", "Net 30", false)); + entries.add(new InvoiceMasthead.Entry("Due Date:", "26 June 2024", false)); + return new InvoiceMasthead("INVOICE", entries); + } + + /** The registration is the labelled pair printed under the address. */ + private static InvoiceRecipient billTo() { + return new InvoiceRecipient("BILL TO", "Bright Future Ltd.", "", + List.of("45 King Street", "Manchester M2 7AZ", "United Kingdom"), + "", "", "VAT ID:", "GB 987 6543 21"); + } + + private static InvoiceRecipient shipTo() { + return new InvoiceRecipient("SHIP TO", "Bright Future Ltd.", "", + List.of("Unit 4, Riverside Park", "Leeds LS1 4AP", "United Kingdom"), + "", "", "", ""); + } + + private static InvoiceServiceLines serviceLines() { + // The currency is not in the labels: the preset names it once per money + // column, so a document states the code and nothing else. + InvoiceServiceLines.Columns columns = new InvoiceServiceLines.Columns( + "", "DESCRIPTION", "PLAN / SERVICE", "QTY", "UNIT PRICE", "AMOUNT", ""); + List lines = new ArrayList<>(); + lines.add(line(1, "Kestrel Business+", "Workspace subscription", + "Business+ Annual", "50", "Users", "8.75", "437.50", "grid")); + lines.add(line(2, "Enterprise Key Management", "Customer-managed encryption keys", + "Add-on", "1", "", "100.00", "100.00", "search")); + lines.add(line(3, "Priority Support", "Named engineer and response target", + "Standard", "1", "", "50.00", "50.00", "shield")); + lines.add(line(4, "Workflow Automation", "Templates and scheduled runs", + "Included", "1", "", "0.00", "0.00", "grid")); + return new InvoiceServiceLines(columns, lines); + } + + private static InvoiceServiceLines.Line line(int number, String title, String description, + String plan, String quantity, String unit, + String unitPrice, String amount, String icon) { + return new InvoiceServiceLines.Line(number, title, description, plan, + new BigDecimal(quantity), unit, decimal(unitPrice), decimal(amount), "", icon); + } + + private static InvoiceTotalsBlock totals() { + List rows = new ArrayList<>(); + rows.add(new InvoiceTotalsBlock.Row("Subtotal", decimal("587.50"))); + rows.add(new InvoiceTotalsBlock.Row("Tax (0%)", decimal("0.00"))); + return new InvoiceTotalsBlock(rows, "TOTAL DUE", decimal("587.50")); + } + + private static InvoicePaymentBlock payment() { + List fields = new ArrayList<>(); + fields.add(new InvoicePaymentBlock.Field("Bank Name:", "Bay Union Bank, N.A.")); + fields.add(new InvoicePaymentBlock.Field("Account Name:", "Kestrel Collaboration, Inc.")); + fields.add(new InvoicePaymentBlock.Field("Account Number:", "000000123456789")); + fields.add(new InvoicePaymentBlock.Field("Routing (ABA):", "021000021")); + fields.add(new InvoicePaymentBlock.Field("SWIFT / BIC:", "BAYUUS33")); + fields.add(new InvoicePaymentBlock.Field("Currency:", "USD")); + fields.add(new InvoicePaymentBlock.Field("Reference:", "INV-2024-0003521")); + fields.add(new InvoicePaymentBlock.Field("Bank Address:", "1 Market Plaza, San Francisco")); + return new InvoicePaymentBlock("PAYMENT DETAILS", fields, + "Please include the invoice number in your payment reference.", + "PAYMENT DUE BY", + "26 June 2024", + "", ""); + } + + private static InvoiceNotesBlock notes() { + return new InvoiceNotesBlock("Thank you for using Kestrel.", + List.of("Questions about this invoice? Reach us at billing@kestrel.example " + + "and we will get back to you within one business day."), + "billing@kestrel.example", ""); + } + + private static BigDecimal decimal(String printed) { + return new BigDecimal(printed.replace(",", "")); + } +} diff --git a/examples/src/main/java/com/demcha/examples/templates/invoice/v2/WorkspaceInvoiceV2Example.java b/examples/src/main/java/com/demcha/examples/templates/invoice/v2/WorkspaceInvoiceV2Example.java new file mode 100644 index 000000000..2a18cfb5d --- /dev/null +++ b/examples/src/main/java/com/demcha/examples/templates/invoice/v2/WorkspaceInvoiceV2Example.java @@ -0,0 +1,54 @@ +package com.demcha.examples.templates.invoice; + +import com.demcha.compose.GraphCompose; +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.templates.api.DocumentTemplate; +import com.demcha.compose.document.templates.data.invoice.StructuredInvoiceData; +import com.demcha.compose.document.templates.invoice.presets.WorkspaceInvoice; +import com.demcha.examples.support.ExampleOutputPaths; +import com.demcha.examples.support.WorkspaceInvoiceSampleData; + +import java.nio.file.Path; + +/** + * Renders the layered {@code invoice.v2} Workspace preset against the design + * sample. + * + *

Output: + * {@code examples/target/generated-pdfs/templates/invoice/invoice-workspace-v2.pdf}.

+ * + *

The preset owns its page geometry and its pagination — the table's header + * repeats and a continuation page reserves a deeper bottom margin — so the + * session starts unconfigured. The sample brings no logo, so the lockup box + * beside the title is filled with the brand's name as a wordmark.

+ */ +public final class WorkspaceInvoiceV2Example { + + private WorkspaceInvoiceV2Example() { + } + + /** + * @return absolute path of the rendered PDF + * @throws Exception if rendering fails + */ + public static Path generate() throws Exception { + Path outputFile = ExampleOutputPaths.prepare("templates/invoice", + "invoice-workspace-v2.pdf"); + StructuredInvoiceData data = WorkspaceInvoiceSampleData.sample(); + DocumentTemplate template = WorkspaceInvoice.create(); + + try (DocumentSession document = GraphCompose.document(outputFile).create()) { + template.compose(document, data); + document.buildPdf(); + } + return outputFile; + } + + /** + * @param args ignored + * @throws Exception if rendering fails + */ + public static void main(String[] args) throws Exception { + System.out.println("Generated: " + generate()); + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceFixtures.java b/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceFixtures.java new file mode 100644 index 000000000..28fca8964 --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceFixtures.java @@ -0,0 +1,140 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.templates.data.invoice.InvoiceBrand; +import com.demcha.compose.document.templates.data.invoice.InvoiceContactBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceMasthead; +import com.demcha.compose.document.templates.data.invoice.InvoiceNotesBlock; +import com.demcha.compose.document.templates.data.invoice.InvoicePaymentBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceRecipient; +import com.demcha.compose.document.templates.data.invoice.InvoiceServiceLines; +import com.demcha.compose.document.templates.data.invoice.InvoiceSummaryBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceTotalsBlock; +import com.demcha.compose.document.templates.data.invoice.StructuredInvoiceData; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * Shared fixture data for the {@link WorkspaceInvoice} gates — the SAME + * document feeds the pixel parity test and the layout snapshot test, so a + * geometry shift the pixel budget absorbs still trips the exact snapshot, and + * vice versa. + */ +final class WorkspaceInvoiceFixtures { + + private WorkspaceInvoiceFixtures() { + } + + /** + * The canonical one-page invoice — six metadata rows, two addressed parties + * each printing a registration, four marked service lines, eight payment + * fields, two summed rows and a closing line with an address inside it. + * + * @return the document + */ + static StructuredInvoiceData canonicalInvoice() { + return new StructuredInvoiceData( + brand(), supplier(), masthead(), billTo(), shipTo(), + new InvoiceSummaryBlock("", "", ""), + serviceLines(), totals(), payment(), notes(), "USD"); + } + + /** No logo: the wordmark is what a document without one falls back to. */ + static InvoiceBrand brand() { + return new InvoiceBrand(null, "kestrel", "", "", "", ""); + } + + static InvoiceContactBlock supplier() { + return new InvoiceContactBlock( + "Kestrel Collaboration, Inc.", + List.of("500 Howard Street, 6th Floor", "San Francisco, CA 94105", + "United States"), + "", "", "kestrel.example", + "", "", + "VAT ID:", "US 77-0560185"); + } + + static InvoiceMasthead masthead() { + List entries = new ArrayList<>(); + entries.add(new InvoiceMasthead.Entry("Invoice Number:", "INV-2024-0003521", true)); + entries.add(new InvoiceMasthead.Entry("Invoice Date:", "27 May 2024", false)); + entries.add(new InvoiceMasthead.Entry("Billing Period:", "1 - 31 May 2024", false)); + entries.add(new InvoiceMasthead.Entry("Workspace ID:", "T04FQ9L2M", false)); + entries.add(new InvoiceMasthead.Entry("Payment Terms:", "Net 30", false)); + entries.add(new InvoiceMasthead.Entry("Due Date:", "26 June 2024", false)); + return new InvoiceMasthead("INVOICE", entries); + } + + /** The registration is the labelled pair printed under the address. */ + static InvoiceRecipient billTo() { + return new InvoiceRecipient("BILL TO", "Bright Future Ltd.", "", + List.of("45 King Street", "Manchester M2 7AZ", "United Kingdom"), + "", "", "VAT ID:", "GB 987 6543 21"); + } + + static InvoiceRecipient shipTo() { + return new InvoiceRecipient("SHIP TO", "Bright Future Ltd.", "", + List.of("Unit 4, Riverside Park", "Leeds LS1 4AP", "United Kingdom"), + "", "", "", ""); + } + + static InvoiceServiceLines serviceLines() { + // The currency is not in the labels: the preset names it once per money + // column, so a document states the code and nothing else. + InvoiceServiceLines.Columns columns = new InvoiceServiceLines.Columns( + "", "DESCRIPTION", "PLAN / SERVICE", "QTY", "UNIT PRICE", "AMOUNT", ""); + List lines = new ArrayList<>(); + lines.add(line(1, "Kestrel Business+", "Workspace subscription", + "Business+ Annual", "50", "Users", "8.75", "437.50", "grid")); + lines.add(line(2, "Enterprise Key Management", "Customer-managed encryption keys", + "Add-on", "1", "", "100.00", "100.00", "search")); + lines.add(line(3, "Priority Support", "Named engineer and response target", + "Standard", "1", "", "50.00", "50.00", "shield")); + lines.add(line(4, "Workflow Automation", "Templates and scheduled runs", + "Included", "1", "", "0.00", "0.00", "grid")); + return new InvoiceServiceLines(columns, lines); + } + + private static InvoiceServiceLines.Line line(int number, String title, String description, + String plan, String quantity, String unit, + String unitPrice, String amount, String icon) { + return new InvoiceServiceLines.Line(number, title, description, plan, + new BigDecimal(quantity), unit, decimal(unitPrice), decimal(amount), "", icon); + } + + static InvoiceTotalsBlock totals() { + List rows = new ArrayList<>(); + rows.add(new InvoiceTotalsBlock.Row("Subtotal", decimal("587.50"))); + rows.add(new InvoiceTotalsBlock.Row("Tax (0%)", decimal("0.00"))); + return new InvoiceTotalsBlock(rows, "TOTAL DUE", decimal("587.50")); + } + + static InvoicePaymentBlock payment() { + List fields = new ArrayList<>(); + fields.add(new InvoicePaymentBlock.Field("Bank Name:", "Bay Union Bank, N.A.")); + fields.add(new InvoicePaymentBlock.Field("Account Name:", "Kestrel Collaboration, Inc.")); + fields.add(new InvoicePaymentBlock.Field("Account Number:", "000000123456789")); + fields.add(new InvoicePaymentBlock.Field("Routing (ABA):", "021000021")); + fields.add(new InvoicePaymentBlock.Field("SWIFT / BIC:", "BAYUUS33")); + fields.add(new InvoicePaymentBlock.Field("Currency:", "USD")); + fields.add(new InvoicePaymentBlock.Field("Reference:", "INV-2024-0003521")); + fields.add(new InvoicePaymentBlock.Field("Bank Address:", "1 Market Plaza, San Francisco")); + return new InvoicePaymentBlock("PAYMENT DETAILS", fields, + "Please include the invoice number in your payment reference.", + "PAYMENT DUE BY", + "26 June 2024", + "", ""); + } + + static InvoiceNotesBlock notes() { + return new InvoiceNotesBlock("Thank you for using Kestrel.", + List.of("Questions about this invoice? Reach us at billing@kestrel.example " + + "and we will get back to you within one business day."), + "billing@kestrel.example", ""); + } + + private static BigDecimal decimal(String printed) { + return new BigDecimal(printed.replace(",", "")); + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceLayoutSnapshotTest.java b/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceLayoutSnapshotTest.java new file mode 100644 index 000000000..74c3e25fe --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceLayoutSnapshotTest.java @@ -0,0 +1,33 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.GraphCompose; +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.templates.TemplateTestSupport; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Exact layout snapshot gate for {@link WorkspaceInvoice} — freezes the resolved + * geometry of the canonical one-page invoice, which the pixel budget cannot + * see: a small column or spacing shift stays under the visual-diff budget but + * changes the snapshot. + * + *

The preset owns its page geometry, so the session starts unconfigured.

+ * + *

Refresh with {@code -Dgraphcompose.updateSnapshots=true} after a + * deliberate layout change, and commit the JSON with the change.

+ */ +class WorkspaceInvoiceLayoutSnapshotTest { + + @Test + void canonicalInvoiceMatchesLayoutSnapshot() throws Exception { + try (DocumentSession session = GraphCompose.document().create()) { + WorkspaceInvoice.create().compose(session, + WorkspaceInvoiceFixtures.canonicalInvoice()); + assertThat(session.layoutSnapshot().totalPages()).as("total pages").isEqualTo(1); + TemplateTestSupport.assertCanonicalSnapshot( + session, "workspace_invoice_layout", "invoice"); + } + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceSmokeTest.java b/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceSmokeTest.java new file mode 100644 index 000000000..8dad4bc60 --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceSmokeTest.java @@ -0,0 +1,269 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.GraphCompose; +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.templates.api.DocumentTemplate; +import com.demcha.compose.document.templates.data.invoice.InvoiceBrand; +import com.demcha.compose.document.templates.data.invoice.InvoiceNotesBlock; +import com.demcha.compose.document.templates.data.invoice.InvoicePaymentBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceRecipient; +import com.demcha.compose.document.templates.data.invoice.InvoiceServiceLines; +import com.demcha.compose.document.templates.data.invoice.InvoiceSummaryBlock; +import com.demcha.compose.document.templates.data.invoice.StructuredInvoiceData; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink; +import org.apache.pdfbox.text.PDFTextStripper; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * Smoke test for {@link WorkspaceInvoice} — proves the preset renders a + * {@link StructuredInvoiceData} end-to-end with its packaged marks, names the + * currency once per money column rather than on every figure, writes a quantity + * with what it counts, prints a billed party's registration under its address, + * reports an unknown mark as a data error, repeats the table header when the + * lines run past a page, and carries the closing address as a link annotation, + * which moves no pixel and no layout node so neither gate would notice it going + * missing. + */ +class WorkspaceInvoiceSmokeTest { + + private static byte[] render(StructuredInvoiceData data) throws Exception { + // The preset owns its page geometry, so the session starts unconfigured. + try (DocumentSession session = GraphCompose.document().create()) { + WorkspaceInvoice.create().compose(session, data); + assertThat(session.roots()).isNotEmpty(); + byte[] pdfBytes = session.toPdfBytes(); + assertThat(pdfBytes).isNotEmpty(); + return pdfBytes; + } + } + + private static String textOf(byte[] pdfBytes) throws Exception { + try (PDDocument document = Loader.loadPDF(pdfBytes)) { + return new PDFTextStripper().getText(document); + } + } + + private static int pagesOf(StructuredInvoiceData data) throws Exception { + try (DocumentSession session = GraphCompose.document().create()) { + WorkspaceInvoice.create().compose(session, data); + return session.layoutSnapshot().totalPages(); + } + } + + private static List linkTargets(byte[] pdfBytes) throws Exception { + List targets = new ArrayList<>(); + try (PDDocument document = Loader.loadPDF(pdfBytes)) { + for (PDPage page : document.getPages()) { + for (PDAnnotation annotation : page.getAnnotations()) { + if (annotation instanceof PDAnnotationLink link + && link.getAction() instanceof PDActionURI uri) { + targets.add(uri.getURI()); + } + } + } + } + return targets; + } + + /** The canonical invoice with its service lines replaced. */ + private static StructuredInvoiceData withLines(InvoiceServiceLines lines) { + StructuredInvoiceData base = WorkspaceInvoiceFixtures.canonicalInvoice(); + return new StructuredInvoiceData(base.brand(), base.supplier(), base.masthead(), + base.billTo(), base.shipTo(), base.summary(), lines, base.totals(), + base.payment(), base.notes(), base.currencyCode()); + } + + @Test + void exposesStableIdentity() { + DocumentTemplate template = WorkspaceInvoice.create(); + assertThat(template.id()).isEqualTo(WorkspaceInvoice.ID); + assertThat(template.displayName()).isEqualTo(WorkspaceInvoice.DISPLAY_NAME); + } + + @Test + void rendersCanonicalInvoiceWithPackagedMarks() throws Exception { + render(WorkspaceInvoiceFixtures.canonicalInvoice()); + } + + @Test + void canonicalRenderCarriesEveryBlocksText() throws Exception { + String text = textOf(render(WorkspaceInvoiceFixtures.canonicalInvoice())); + assertThat(text) + .contains("INVOICE") + .contains("Kestrel Collaboration, Inc.") + .contains("Invoice Number:") + .contains("BILL TO") + .contains("SHIP TO") + .contains("Bright Future Ltd.") + .contains("Kestrel Business+") + .contains("PAYMENT DETAILS") + .contains("BAYUUS33") + .contains("TOTAL DUE") + .contains("PAYMENT DUE BY") + .contains("Thank you for using Kestrel."); + } + + @Test + void bothPartiesPrintTheirOwnRegistration() throws Exception { + // The supplier's sits under its address in the header, the billed + // party's under its address in the split — both labelled pairs. + String text = textOf(render(WorkspaceInvoiceFixtures.canonicalInvoice())); + assertThat(text).contains("US 77-0560185").contains("GB 987 6543 21"); + } + + @Test + void aPartyWithNoRegistrationPrintsNoLabel() throws Exception { + // The ship-to has none, and a label over an absence would be worse than + // no row at all — so there is exactly one of each in the split. + String text = textOf(render(WorkspaceInvoiceFixtures.canonicalInvoice())); + assertThat(text.split("VAT ID:", -1)).hasSize(3); + } + + @Test + void theCurrencyIsNamedOncePerColumnAndNotOnEveryFigure() throws Exception { + // This design states the currency in the column head; the figures under + // it are bare, and only the total carries the code. + String text = textOf(render(WorkspaceInvoiceFixtures.canonicalInvoice())); + assertThat(text) + .contains("UNIT PRICE (USD)") + .contains("AMOUNT (USD)") + .contains("USD 587.50") + .doesNotContain("$437.50"); + assertThat(text).contains("437.50"); + } + + @Test + void aQuantityIsWrittenWithWhatItCounts() throws Exception { + String text = textOf(render(WorkspaceInvoiceFixtures.canonicalInvoice())); + assertThat(text).contains("50 Users"); + } + + @Test + void aDocumentWithNoLogoFallsBackToItsName() throws Exception { + // The preset carries no mark of its own, so a document that brings only + // a name still gets a lockup — and the closing band always sets it. + assertThat(textOf(render(WorkspaceInvoiceFixtures.canonicalInvoice()))) + .contains("kestrel"); + } + + @Test + void theClosingAddressIsClickable() throws Exception { + assertThat(linkTargets(render(WorkspaceInvoiceFixtures.canonicalInvoice()))) + .contains("mailto:billing@kestrel.example") + .contains("https://kestrel.example"); + } + + @Test + void anUnknownMarkIsReportedAsADataError() { + InvoiceServiceLines wrong = new InvoiceServiceLines( + WorkspaceInvoiceFixtures.serviceLines().columns(), + List.of(new InvoiceServiceLines.Line(1, "Telepathy", "Reading minds", "Add-on", + BigDecimal.ONE, "", BigDecimal.TEN, BigDecimal.TEN, "", "telescope"))); + + assertThatThrownBy(() -> render(withLines(wrong))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("telescope") + .hasMessageContaining("shield"); + } + + @Test + void aLineWithoutAMarkIsDrawnWithoutOne() throws Exception { + InvoiceServiceLines unmarked = new InvoiceServiceLines( + WorkspaceInvoiceFixtures.serviceLines().columns(), + List.of(new InvoiceServiceLines.Line(1, "Consulting", "A day of it", "Standard", + BigDecimal.ONE, "", new BigDecimal("1200"), new BigDecimal("1200"), ""))); + + assertThat(textOf(render(withLines(unmarked)))).contains("Consulting"); + } + + @Test + void aLongerInvoiceRunsOnAndRepeatsItsTableHeader() throws Exception { + List many = new ArrayList<>(); + for (int index = 1; index <= 30; index++) { + many.add(new InvoiceServiceLines.Line(index, "Service " + index, + "A line of description for it", "Standard", + BigDecimal.ONE, "", new BigDecimal("120"), new BigDecimal("120"), + "", "grid")); + } + StructuredInvoiceData longer = withLines(new InvoiceServiceLines( + WorkspaceInvoiceFixtures.serviceLines().columns(), many)); + + assertThat(pagesOf(longer)).isGreaterThan(1); + byte[] pdfBytes = render(longer); + assertThat(textOf(pdfBytes)).contains("Service 30"); + try (PDDocument document = Loader.loadPDF(pdfBytes)) { + PDFTextStripper stripper = new PDFTextStripper(); + stripper.setStartPage(2); + stripper.setEndPage(2); + assertThat(stripper.getText(document)) + .as("the second page names its columns") + .contains("DESCRIPTION") + .contains("PLAN / SERVICE"); + } + } + + @Test + void everyPageCarriesItsNumber() throws Exception { + List many = new ArrayList<>(); + for (int index = 1; index <= 30; index++) { + many.add(new InvoiceServiceLines.Line(index, "Service " + index, "", "Standard", + BigDecimal.ONE, "", new BigDecimal("120"), new BigDecimal("120"), + "", "grid")); + } + String text = textOf(render(withLines(new InvoiceServiceLines( + WorkspaceInvoiceFixtures.serviceLines().columns(), many)))); + assertThat(text).contains("Page 1 of").contains("Page 2 of"); + } + + @Test + void anInvoiceWithNoShipToDrawsOneParty() throws Exception { + StructuredInvoiceData base = WorkspaceInvoiceFixtures.canonicalInvoice(); + StructuredInvoiceData single = new StructuredInvoiceData(base.brand(), base.supplier(), + base.masthead(), base.billTo(), + new InvoiceRecipient("", "", "", List.of(), "", ""), + base.summary(), base.serviceLines(), base.totals(), base.payment(), + base.notes(), base.currencyCode()); + + String text = textOf(render(single)); + assertThat(text).contains("BILL TO").doesNotContain("SHIP TO"); + } + + @Test + void anInvoiceWithNoNoteDropsTheCardsRuleWithIt() throws Exception { + // The rule exists to separate the fields from the note; with no note it + // would close the card on nothing. + StructuredInvoiceData base = WorkspaceInvoiceFixtures.canonicalInvoice(); + InvoicePaymentBlock quiet = new InvoicePaymentBlock( + base.payment().heading(), base.payment().fields(), "", + base.payment().dueNotice(), base.payment().dueNoticeEmphasis(), "", ""); + StructuredInvoiceData bare = new StructuredInvoiceData(base.brand(), base.supplier(), + base.masthead(), base.billTo(), base.shipTo(), base.summary(), + base.serviceLines(), base.totals(), quiet, base.notes(), base.currencyCode()); + + assertThat(textOf(render(bare))) + .doesNotContain("Please include the invoice number"); + } + + @Test + void anEmptyDocumentStillRenders() throws Exception { + // Every block absent: the preset draws its furniture and nothing else, + // rather than failing on the first missing field. + render(new StructuredInvoiceData(new InvoiceBrand(null, "", "", ""), null, null, + null, null, new InvoiceSummaryBlock("", "", ""), + new InvoiceServiceLines(null, List.of()), null, + new InvoicePaymentBlock("", List.of(), "", "", "", "", ""), + new InvoiceNotesBlock("", List.of(), "", ""), "")); + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceVisualParityTest.java b/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceVisualParityTest.java new file mode 100644 index 000000000..0a72411b1 --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoiceVisualParityTest.java @@ -0,0 +1,41 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.GraphCompose; +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.testing.visual.PdfVisualRegression; +import org.junit.jupiter.api.Test; + +import java.nio.file.Path; + +/** + * Pixel-diff visual parity gate for {@link WorkspaceInvoice} — the canonical + * one-page invoice against a checked-in baseline. + * + *

Re-blessing baselines — after a deliberate visual change, + * re-run with {@code -Dgraphcompose.visual.approve=true} and commit the updated + * PNG with the change.

+ */ +class WorkspaceInvoiceVisualParityTest { + + private static final Path BASELINE_ROOT = Path.of( + "src", "test", "resources", "visual-baselines", "invoice-v2-layered"); + + private static final long PIXEL_DIFF_BUDGET = 50_000L; + private static final int PER_PIXEL_TOLERANCE = 8; + + @Test + void rendersWithinPixelDiffBudget() throws Exception { + byte[] pdfBytes; + try (DocumentSession document = GraphCompose.document().create()) { + WorkspaceInvoice.create().compose(document, + WorkspaceInvoiceFixtures.canonicalInvoice()); + pdfBytes = document.toPdfBytes(); + } + + PdfVisualRegression.standard() + .baselineRoot(BASELINE_ROOT) + .perPixelTolerance(PER_PIXEL_TOLERANCE) + .mismatchedPixelBudget(PIXEL_DIFF_BUDGET) + .assertMatchesBaseline("workspace_invoice", pdfBytes); + } +} diff --git a/qa/src/test/resources/layout-snapshots/canonical-templates/invoice/workspace_invoice_layout.json b/qa/src/test/resources/layout-snapshots/canonical-templates/invoice/workspace_invoice_layout.json new file mode 100644 index 000000000..eec8955b4 --- /dev/null +++ b/qa/src/test/resources/layout-snapshots/canonical-templates/invoice/workspace_invoice_layout.json @@ -0,0 +1,6197 @@ +{ + "formatVersion" : "2.0", + "canvas" : { + "pageWidth" : 595.276, + "pageHeight" : 841.89, + "innerWidth" : 543.365, + "innerHeight" : 800.136, + "margin" : { + "top" : 25.955, + "right" : 26.519, + "bottom" : 15.799, + "left" : 25.391 + } + }, + "totalPages" : 1, + "nodes" : [ { + "path" : "WorkspaceInvoice[0]", + "entityName" : "WorkspaceInvoice", + "entityKind" : "ContainerNode", + "parentPath" : null, + "childIndex" : 0, + "depth" : 1, + "layer" : 1, + "computedX" : 25.391, + "computedY" : 18.885, + "placementX" : 25.391, + "placementY" : 18.885, + "placementWidth" : 543.365, + "placementHeight" : 797.05, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 797.05, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/Masthead[0]", + "entityName" : "Masthead", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 0, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 776.74, + "placementX" : 25.391, + "placementY" : 776.74, + "placementWidth" : 543.365, + "placementHeight" : 39.195, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 39.195, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/Masthead[0]/BrandLockup[0]", + "entityName" : "BrandLockup", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/Masthead[0]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 25.391, + "computedY" : 792.782, + "placementX" : 25.391, + "placementY" : 792.782, + "placementWidth" : 58.595, + "placementHeight" : 23.152, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 58.595, + "contentHeight" : 23.152, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/Masthead[0]/BrandLockup[0]/BrandWordmark[0]", + "entityName" : "BrandWordmark", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/Masthead[0]/BrandLockup[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 25.391, + "computedY" : 792.782, + "placementX" : 25.391, + "placementY" : 792.782, + "placementWidth" : 58.595, + "placementHeight" : 23.152, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 58.595, + "contentHeight" : 23.152, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/Masthead[0]/InvoiceTitle[1]", + "entityName" : "InvoiceTitle", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/Masthead[0]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 145.01, + "computedY" : 776.74, + "placementX" : 145.01, + "placementY" : 776.74, + "placementWidth" : 423.746, + "placementHeight" : 39.195, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 423.746, + "contentHeight" : 39.195, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : -4.119, + "right" : 7.335, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/Masthead[0]/InvoiceTitle[1]/InvoiceTitleText[0]", + "entityName" : "InvoiceTitleText", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/Masthead[0]/InvoiceTitle[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 145.01, + "computedY" : 776.74, + "placementX" : 145.01, + "placementY" : 776.74, + "placementWidth" : 416.411, + "placementHeight" : 43.314, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 416.411, + "contentHeight" : 43.314, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/BrandAccentRule[1]", + "entityName" : "BrandAccentRule", + "entityKind" : "LineNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 1, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 763.46, + "placementX" : 25.391, + "placementY" : 763.46, + "placementWidth" : 23.134, + "placementHeight" : 2.257, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.134, + "contentHeight" : 2.257, + "margin" : { + "top" : 11.023, + "right" : 0.0, + "bottom" : 8.592, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]", + "entityName" : "IssuerMetaRow", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 2, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 641.4, + "placementX" : 25.391, + "placementY" : 641.4, + "placementWidth" : 543.365, + "placementHeight" : 113.468, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 113.468, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]", + "entityName" : "IssuerAddress", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 25.391, + "computedY" : 662.841, + "placementX" : 25.391, + "placementY" : 662.841, + "placementWidth" : 271.683, + "placementHeight" : 92.027, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 271.683, + "contentHeight" : 92.027, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 6.771, + "right" : 0.0, + "bottom" : 0.0, + "left" : 1.128 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerName[0]", + "entityName" : "IssuerName", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 26.519, + "computedY" : 734.805, + "placementX" : 26.519, + "placementY" : 734.805, + "placementWidth" : 127.608, + "placementHeight" : 13.291, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 127.608, + "contentHeight" : 13.291, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerAddressLines[1]", + "entityName" : "IssuerAddressLines", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 26.519, + "computedY" : 684.282, + "placementX" : 26.519, + "placementY" : 684.282, + "placementWidth" : 122.916, + "placementHeight" : 42.373, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 122.916, + "contentHeight" : 42.373, + "margin" : { + "top" : 8.15, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerAddressLines[1]/IssuerAddressLine1[0]", + "entityName" : "IssuerAddressLine1", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerAddressLines[1]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 26.519, + "computedY" : 715.316, + "placementX" : 26.519, + "placementY" : 715.316, + "placementWidth" : 122.916, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 122.916, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerAddressLines[1]/IssuerAddressLine2[1]", + "entityName" : "IssuerAddressLine2", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerAddressLines[1]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 26.519, + "computedY" : 699.799, + "placementX" : 26.519, + "placementY" : 699.799, + "placementWidth" : 104.129, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 104.129, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerAddressLines[1]/IssuerAddressLine3[2]", + "entityName" : "IssuerAddressLine3", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerAddressLines[1]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 26.519, + "computedY" : 684.282, + "placementX" : 26.519, + "placementY" : 684.282, + "placementWidth" : 56.284, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 56.284, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]", + "entityName" : "IssuerTaxLineLayer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 26.519, + "computedY" : 662.841, + "placementX" : 26.519, + "placementY" : 662.841, + "placementWidth" : 270.554, + "placementHeight" : 21.441, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 270.554, + "contentHeight" : 21.441, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]/IssuerTaxLineHolder[0]", + "entityName" : "IssuerTaxLineHolder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 26.519, + "computedY" : 662.841, + "placementX" : 26.519, + "placementY" : 662.841, + "placementWidth" : 270.554, + "placementHeight" : 21.441, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 270.554, + "contentHeight" : 21.441, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]/IssuerTaxLineHolder[0]/IssuerTaxLine[0]", + "entityName" : "IssuerTaxLine", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]/IssuerTaxLineHolder[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 26.519, + "computedY" : 662.841, + "placementX" : 26.519, + "placementY" : 662.841, + "placementWidth" : 270.554, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 270.554, + "contentHeight" : 11.34, + "margin" : { + "top" : 10.101, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]/IssuerTaxLineHolder[0]/IssuerTaxLine[0]/IssuerTaxLabel[0]", + "entityName" : "IssuerTaxLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]/IssuerTaxLineHolder[0]/IssuerTaxLine[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 26.519, + "computedY" : 662.841, + "placementX" : 26.519, + "placementY" : 662.841, + "placementWidth" : 32.999, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 32.999, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]/IssuerTaxLineHolder[0]/IssuerTaxLine[0]/IssuerTaxValue[1]", + "entityName" : "IssuerTaxValue", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/IssuerAddress[0]/IssuerTaxLineLayer[2]/IssuerTaxLineHolder[0]/IssuerTaxLine[0]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 62.067, + "computedY" : 662.841, + "placementX" : 62.067, + "placementY" : 662.841, + "placementWidth" : 67.35, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 67.35, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]", + "entityName" : "InvoiceMeta", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 297.074, + "computedY" : 641.4, + "placementX" : 297.074, + "placementY" : 641.4, + "placementWidth" : 271.683, + "placementHeight" : 113.468, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 271.683, + "contentHeight" : 113.468, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 45.139 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]", + "entityName" : "InvoiceMetaRows", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 342.213, + "computedY" : 641.4, + "placementX" : 342.213, + "placementY" : 641.4, + "placementWidth" : 226.543, + "placementHeight" : 113.468, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 113.468, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]", + "entityName" : "MetaRow1Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 342.213, + "computedY" : 743.528, + "placementX" : 342.213, + "placementY" : 743.528, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]/MetaRow1Holder[0]", + "entityName" : "MetaRow1Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 342.213, + "computedY" : 743.528, + "placementX" : 342.213, + "placementY" : 743.528, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]/MetaRow1Holder[0]/MetaRow1[0]", + "entityName" : "MetaRow1", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]/MetaRow1Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 342.213, + "computedY" : 743.528, + "placementX" : 342.213, + "placementY" : 743.528, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]/MetaRow1Holder[0]/MetaRow1[0]/MetaRow1Label[0]", + "entityName" : "MetaRow1Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]/MetaRow1Holder[0]/MetaRow1[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 342.213, + "computedY" : 744.0, + "placementX" : 342.213, + "placementY" : 744.0, + "placementWidth" : 65.839, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 65.839, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]/MetaRow1Holder[0]/MetaRow1[0]/MetaRow1Value[1]", + "entityName" : "MetaRow1Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow1Layer[0]/MetaRow1Holder[0]/MetaRow1[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 443.777, + "computedY" : 743.528, + "placementX" : 443.777, + "placementY" : 743.528, + "placementWidth" : 84.001, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 84.001, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]", + "entityName" : "MetaRow2Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 342.213, + "computedY" : 723.102, + "placementX" : 342.213, + "placementY" : 723.102, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]/MetaRow2Holder[0]", + "entityName" : "MetaRow2Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 342.213, + "computedY" : 723.102, + "placementX" : 342.213, + "placementY" : 723.102, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]/MetaRow2Holder[0]/MetaRow2[0]", + "entityName" : "MetaRow2", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]/MetaRow2Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 342.213, + "computedY" : 723.102, + "placementX" : 342.213, + "placementY" : 723.102, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]/MetaRow2Holder[0]/MetaRow2[0]/MetaRow2Label[0]", + "entityName" : "MetaRow2Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]/MetaRow2Holder[0]/MetaRow2[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 342.213, + "computedY" : 723.575, + "placementX" : 342.213, + "placementY" : 723.575, + "placementWidth" : 52.689, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 52.689, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]/MetaRow2Holder[0]/MetaRow2[0]/MetaRow2Value[1]", + "entityName" : "MetaRow2Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow2Layer[1]/MetaRow2Holder[0]/MetaRow2[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 443.777, + "computedY" : 723.102, + "placementX" : 443.777, + "placementY" : 723.102, + "placementWidth" : 56.076, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 56.076, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]", + "entityName" : "MetaRow3Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 342.213, + "computedY" : 702.677, + "placementX" : 342.213, + "placementY" : 702.677, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]/MetaRow3Holder[0]", + "entityName" : "MetaRow3Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 342.213, + "computedY" : 702.677, + "placementX" : 342.213, + "placementY" : 702.677, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]/MetaRow3Holder[0]/MetaRow3[0]", + "entityName" : "MetaRow3", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]/MetaRow3Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 342.213, + "computedY" : 702.677, + "placementX" : 342.213, + "placementY" : 702.677, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]/MetaRow3Holder[0]/MetaRow3[0]/MetaRow3Label[0]", + "entityName" : "MetaRow3Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]/MetaRow3Holder[0]/MetaRow3[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 342.213, + "computedY" : 703.149, + "placementX" : 342.213, + "placementY" : 703.149, + "placementWidth" : 54.727, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 54.727, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]/MetaRow3Holder[0]/MetaRow3[0]/MetaRow3Value[1]", + "entityName" : "MetaRow3Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow3Layer[2]/MetaRow3Holder[0]/MetaRow3[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 443.777, + "computedY" : 702.677, + "placementX" : 443.777, + "placementY" : 702.677, + "placementWidth" : 69.911, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 69.911, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]", + "entityName" : "MetaRow4Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]", + "childIndex" : 3, + "depth" : 5, + "layer" : 5, + "computedX" : 342.213, + "computedY" : 682.251, + "placementX" : 342.213, + "placementY" : 682.251, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]/MetaRow4Holder[0]", + "entityName" : "MetaRow4Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 342.213, + "computedY" : 682.251, + "placementX" : 342.213, + "placementY" : 682.251, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]/MetaRow4Holder[0]/MetaRow4[0]", + "entityName" : "MetaRow4", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]/MetaRow4Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 342.213, + "computedY" : 682.251, + "placementX" : 342.213, + "placementY" : 682.251, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]/MetaRow4Holder[0]/MetaRow4[0]/MetaRow4Label[0]", + "entityName" : "MetaRow4Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]/MetaRow4Holder[0]/MetaRow4[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 342.213, + "computedY" : 682.724, + "placementX" : 342.213, + "placementY" : 682.724, + "placementWidth" : 59.038, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 59.038, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]/MetaRow4Holder[0]/MetaRow4[0]/MetaRow4Value[1]", + "entityName" : "MetaRow4Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow4Layer[3]/MetaRow4Holder[0]/MetaRow4[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 443.777, + "computedY" : 682.251, + "placementX" : 443.777, + "placementY" : 682.251, + "placementWidth" : 54.063, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 54.063, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]", + "entityName" : "MetaRow5Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]", + "childIndex" : 4, + "depth" : 5, + "layer" : 5, + "computedX" : 342.213, + "computedY" : 661.825, + "placementX" : 342.213, + "placementY" : 661.825, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]/MetaRow5Holder[0]", + "entityName" : "MetaRow5Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 342.213, + "computedY" : 661.825, + "placementX" : 342.213, + "placementY" : 661.825, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]/MetaRow5Holder[0]/MetaRow5[0]", + "entityName" : "MetaRow5", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]/MetaRow5Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 342.213, + "computedY" : 661.825, + "placementX" : 342.213, + "placementY" : 661.825, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]/MetaRow5Holder[0]/MetaRow5[0]/MetaRow5Label[0]", + "entityName" : "MetaRow5Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]/MetaRow5Holder[0]/MetaRow5[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 342.213, + "computedY" : 662.298, + "placementX" : 342.213, + "placementY" : 662.298, + "placementWidth" : 64.544, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 64.544, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]/MetaRow5Holder[0]/MetaRow5[0]/MetaRow5Value[1]", + "entityName" : "MetaRow5Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow5Layer[4]/MetaRow5Holder[0]/MetaRow5[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 443.777, + "computedY" : 661.825, + "placementX" : 443.777, + "placementY" : 661.825, + "placementWidth" : 28.983, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 28.983, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]", + "entityName" : "MetaRow6Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]", + "childIndex" : 5, + "depth" : 5, + "layer" : 5, + "computedX" : 342.213, + "computedY" : 641.4, + "placementX" : 342.213, + "placementY" : 641.4, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]/MetaRow6Holder[0]", + "entityName" : "MetaRow6Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 342.213, + "computedY" : 641.4, + "placementX" : 342.213, + "placementY" : 641.4, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]/MetaRow6Holder[0]/MetaRow6[0]", + "entityName" : "MetaRow6", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]/MetaRow6Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 342.213, + "computedY" : 641.4, + "placementX" : 342.213, + "placementY" : 641.4, + "placementWidth" : 226.543, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 226.543, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]/MetaRow6Holder[0]/MetaRow6[0]/MetaRow6Label[0]", + "entityName" : "MetaRow6Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]/MetaRow6Holder[0]/MetaRow6[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 342.213, + "computedY" : 641.872, + "placementX" : 342.213, + "placementY" : 641.872, + "placementWidth" : 40.735, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 40.735, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]/MetaRow6Holder[0]/MetaRow6[0]/MetaRow6Value[1]", + "entityName" : "MetaRow6Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/IssuerMetaRow[2]/InvoiceMeta[1]/InvoiceMetaRows[0]/MetaRow6Layer[5]/MetaRow6Holder[0]/MetaRow6[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 443.777, + "computedY" : 641.4, + "placementX" : 443.777, + "placementY" : 641.4, + "placementWidth" : 57.257, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 57.257, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRule[3]", + "entityName" : "PartiesRule", + "entityKind" : "LineNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 3, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 626.667, + "placementX" : 25.391, + "placementY" : 626.667, + "placementWidth" : 543.365, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 1.0, + "margin" : { + "top" : 13.733, + "right" : 0.0, + "bottom" : 13.542, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]", + "entityName" : "PartiesRow", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 4, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 499.093, + "placementX" : 25.391, + "placementY" : 499.093, + "placementWidth" : 543.365, + "placementHeight" : 114.032, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 114.032, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]", + "entityName" : "Party1", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 25.391, + "computedY" : 499.093, + "placementX" : 25.391, + "placementY" : 499.093, + "placementWidth" : 271.683, + "placementHeight" : 114.032, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 271.683, + "contentHeight" : 114.032, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]", + "entityName" : "PartyHeadLayer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 25.391, + "computedY" : 589.427, + "placementX" : 25.391, + "placementY" : 589.427, + "placementWidth" : 271.683, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 271.683, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]", + "entityName" : "PartyHeadHolder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 25.391, + "computedY" : 589.427, + "placementX" : 25.391, + "placementY" : 589.427, + "placementWidth" : 271.683, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 271.683, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]", + "entityName" : "PartyHead", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 25.391, + "computedY" : 589.427, + "placementX" : 25.391, + "placementY" : 589.427, + "placementWidth" : 271.683, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 271.683, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]", + "entityName" : "PartyDisc", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 25.391, + "computedY" : 589.427, + "placementX" : 25.391, + "placementY" : 589.427, + "placementWidth" : 23.698, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.698, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]", + "entityName" : "Discbill-to", + "entityKind" : "ShapeContainerNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 25.391, + "computedY" : 589.427, + "placementX" : 25.391, + "placementY" : 589.427, + "placementWidth" : 23.698, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.698, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]/Glyphbill-to[0]", + "entityName" : "Glyphbill-to", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]", + "childIndex" : 0, + "depth" : 9, + "layer" : 9, + "computedX" : 25.391, + "computedY" : 595.634, + "placementX" : 25.391, + "placementY" : 595.634, + "placementWidth" : 23.698, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.698, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]/Glyphbill-to[0]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]/Glyphbill-to[0]", + "childIndex" : 0, + "depth" : 10, + "layer" : 10, + "computedX" : 25.391, + "computedY" : 595.634, + "placementX" : 25.391, + "placementY" : 595.634, + "placementWidth" : 23.698, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.698, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]/Glyphbill-to[0]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]/Glyphbill-to[0]/Align[0]", + "childIndex" : 0, + "depth" : 11, + "layer" : 11, + "computedX" : 31.598, + "computedY" : 595.634, + "placementX" : 31.598, + "placementY" : 595.634, + "placementWidth" : 11.285, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 11.285, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]/Glyphbill-to[0]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discbill-to[0]/Glyphbill-to[0]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 12, + "layer" : 12, + "computedX" : 31.598, + "computedY" : 595.634, + "placementX" : 31.598, + "placementY" : 595.634, + "placementWidth" : 11.285, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 11.285, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyLabel[1]", + "entityName" : "PartyLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 59.245, + "computedY" : 599.492, + "placementX" : 59.245, + "placementY" : 599.492, + "placementWidth" : 34.464, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 34.464, + "contentHeight" : 11.34, + "margin" : { + "top" : 2.293, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]", + "entityName" : "PartyBody", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 25.391, + "computedY" : 499.093, + "placementX" : 25.391, + "placementY" : 499.093, + "placementWidth" : 271.683, + "placementHeight" : 90.334, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 271.683, + "contentHeight" : 90.334, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 33.855 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyName[0]", + "entityName" : "PartyName", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 59.245, + "computedY" : 575.007, + "placementX" : 59.245, + "placementY" : 575.007, + "placementWidth" : 87.579, + "placementHeight" : 13.291, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 87.579, + "contentHeight" : 13.291, + "margin" : { + "top" : 1.128, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyAddressLines[1]", + "entityName" : "PartyAddressLines", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 59.245, + "computedY" : 525.613, + "placementX" : 59.245, + "placementY" : 525.613, + "placementWidth" : 86.108, + "placementHeight" : 42.938, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 86.108, + "contentHeight" : 42.938, + "margin" : { + "top" : 6.457, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyAddressLines[1]/PartyAddressLine1[0]", + "entityName" : "PartyAddressLine1", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyAddressLines[1]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 59.245, + "computedY" : 557.21, + "placementX" : 59.245, + "placementY" : 557.21, + "placementWidth" : 59.856, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 59.856, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyAddressLines[1]/PartyAddressLine2[1]", + "entityName" : "PartyAddressLine2", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyAddressLines[1]", + "childIndex" : 1, + "depth" : 6, + "layer" : 6, + "computedX" : 59.245, + "computedY" : 541.412, + "placementX" : 59.245, + "placementY" : 541.412, + "placementWidth" : 86.108, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 86.108, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyAddressLines[1]/PartyAddressLine3[2]", + "entityName" : "PartyAddressLine3", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyAddressLines[1]", + "childIndex" : 2, + "depth" : 6, + "layer" : 6, + "computedX" : 59.245, + "computedY" : 525.613, + "placementX" : 59.245, + "placementY" : 525.613, + "placementWidth" : 67.737, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 67.737, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]", + "entityName" : "PartyTaxLineLayer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 59.245, + "computedY" : 499.093, + "placementX" : 59.245, + "placementY" : 499.093, + "placementWidth" : 237.828, + "placementHeight" : 26.519, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 237.828, + "contentHeight" : 26.519, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]/PartyTaxLineHolder[0]", + "entityName" : "PartyTaxLineHolder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 59.245, + "computedY" : 499.093, + "placementX" : 59.245, + "placementY" : 499.093, + "placementWidth" : 237.828, + "placementHeight" : 26.519, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 237.828, + "contentHeight" : 26.519, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]/PartyTaxLineHolder[0]/PartyTaxLine[0]", + "entityName" : "PartyTaxLine", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]/PartyTaxLineHolder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 59.245, + "computedY" : 499.093, + "placementX" : 59.245, + "placementY" : 499.093, + "placementWidth" : 237.828, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 237.828, + "contentHeight" : 11.34, + "margin" : { + "top" : 15.179, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]/PartyTaxLineHolder[0]/PartyTaxLine[0]/PartyTaxLabel[0]", + "entityName" : "PartyTaxLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]/PartyTaxLineHolder[0]/PartyTaxLine[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 59.245, + "computedY" : 499.093, + "placementX" : 59.245, + "placementY" : 499.093, + "placementWidth" : 32.999, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 32.999, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]/PartyTaxLineHolder[0]/PartyTaxLine[0]/PartyTaxValue[1]", + "entityName" : "PartyTaxValue", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party1[0]/PartyBody[1]/PartyTaxLineLayer[2]/PartyTaxLineHolder[0]/PartyTaxLine[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 103.821, + "computedY" : 499.093, + "placementX" : 103.821, + "placementY" : 499.093, + "placementWidth" : 69.609, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 69.609, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]", + "entityName" : "Party2", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 297.074, + "computedY" : 525.613, + "placementX" : 297.074, + "placementY" : 525.613, + "placementWidth" : 271.683, + "placementHeight" : 87.513, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 271.683, + "contentHeight" : 87.513, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 15.799 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]", + "entityName" : "PartyHeadLayer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 312.872, + "computedY" : 589.427, + "placementX" : 312.872, + "placementY" : 589.427, + "placementWidth" : 255.884, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 255.884, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]", + "entityName" : "PartyHeadHolder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 312.872, + "computedY" : 589.427, + "placementX" : 312.872, + "placementY" : 589.427, + "placementWidth" : 255.884, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 255.884, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]", + "entityName" : "PartyHead", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 312.872, + "computedY" : 589.427, + "placementX" : 312.872, + "placementY" : 589.427, + "placementWidth" : 255.884, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 255.884, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]", + "entityName" : "PartyDisc", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 312.872, + "computedY" : 589.427, + "placementX" : 312.872, + "placementY" : 589.427, + "placementWidth" : 23.698, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.698, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]", + "entityName" : "Discship-to", + "entityKind" : "ShapeContainerNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 312.872, + "computedY" : 589.427, + "placementX" : 312.872, + "placementY" : 589.427, + "placementWidth" : 23.698, + "placementHeight" : 23.698, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.698, + "contentHeight" : 23.698, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]/Glyphship-to[0]", + "entityName" : "Glyphship-to", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]", + "childIndex" : 0, + "depth" : 9, + "layer" : 9, + "computedX" : 312.872, + "computedY" : 595.634, + "placementX" : 312.872, + "placementY" : 595.634, + "placementWidth" : 23.698, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.698, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]/Glyphship-to[0]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]/Glyphship-to[0]", + "childIndex" : 0, + "depth" : 10, + "layer" : 10, + "computedX" : 312.872, + "computedY" : 595.634, + "placementX" : 312.872, + "placementY" : 595.634, + "placementWidth" : 23.698, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 23.698, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]/Glyphship-to[0]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]/Glyphship-to[0]/Align[0]", + "childIndex" : 0, + "depth" : 11, + "layer" : 11, + "computedX" : 319.079, + "computedY" : 595.634, + "placementX" : 319.079, + "placementY" : 595.634, + "placementWidth" : 11.285, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 11.285, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]/Glyphship-to[0]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyDisc[0]/Discship-to[0]/Glyphship-to[0]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 12, + "layer" : 12, + "computedX" : 319.079, + "computedY" : 595.634, + "placementX" : 319.079, + "placementY" : 595.634, + "placementWidth" : 11.285, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 11.285, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]/PartyLabel[1]", + "entityName" : "PartyLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyHeadLayer[0]/PartyHeadHolder[0]/PartyHead[0]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 346.727, + "computedY" : 599.492, + "placementX" : 346.727, + "placementY" : 599.492, + "placementWidth" : 36.732, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 36.732, + "contentHeight" : 11.34, + "margin" : { + "top" : 2.293, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]", + "entityName" : "PartyBody", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 312.872, + "computedY" : 525.613, + "placementX" : 312.872, + "placementY" : 525.613, + "placementWidth" : 123.384, + "placementHeight" : 63.815, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 123.384, + "contentHeight" : 63.815, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 33.855 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]/PartyName[0]", + "entityName" : "PartyName", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 346.727, + "computedY" : 575.007, + "placementX" : 346.727, + "placementY" : 575.007, + "placementWidth" : 87.579, + "placementHeight" : 13.291, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 87.579, + "contentHeight" : 13.291, + "margin" : { + "top" : 1.128, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]/PartyAddressLines[1]", + "entityName" : "PartyAddressLines", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 346.727, + "computedY" : 525.613, + "placementX" : 346.727, + "placementY" : 525.613, + "placementWidth" : 89.529, + "placementHeight" : 42.938, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 89.529, + "contentHeight" : 42.938, + "margin" : { + "top" : 6.457, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]/PartyAddressLines[1]/PartyAddressLine1[0]", + "entityName" : "PartyAddressLine1", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]/PartyAddressLines[1]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 346.727, + "computedY" : 557.21, + "placementX" : 346.727, + "placementY" : 557.21, + "placementWidth" : 89.529, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 89.529, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]/PartyAddressLines[1]/PartyAddressLine2[1]", + "entityName" : "PartyAddressLine2", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]/PartyAddressLines[1]", + "childIndex" : 1, + "depth" : 6, + "layer" : 6, + "computedX" : 346.727, + "computedY" : 541.412, + "placementX" : 346.727, + "placementY" : 541.412, + "placementWidth" : 62.086, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 62.086, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]/PartyAddressLines[1]/PartyAddressLine3[2]", + "entityName" : "PartyAddressLine3", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/PartiesRow[4]/Party2[1]/PartyBody[1]/PartyAddressLines[1]", + "childIndex" : 2, + "depth" : 6, + "layer" : 6, + "computedX" : 346.727, + "computedY" : 525.613, + "placementX" : 346.727, + "placementY" : 525.613, + "placementWidth" : 67.737, + "placementHeight" : 11.34, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 67.737, + "contentHeight" : 11.34, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/LineItemsBox[5]", + "entityName" : "LineItemsBox", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 5, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 279.879, + "placementX" : 25.391, + "placementY" : 279.879, + "placementWidth" : 543.365, + "placementHeight" : 196.171, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 196.171, + "margin" : { + "top" : 23.043, + "right" : 0.0, + "bottom" : 15.235, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/LineItemsBox[5]/LineItems[0]", + "entityName" : "LineItems", + "entityKind" : "TableNode", + "parentPath" : "WorkspaceInvoice[0]/LineItemsBox[5]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 25.391, + "computedY" : 279.879, + "placementX" : 25.391, + "placementY" : 279.879, + "placementWidth" : 543.365, + "placementHeight" : 196.171, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 196.171, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]", + "entityName" : "SettlementRow", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 6, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 87.384, + "placementX" : 25.391, + "placementY" : 87.384, + "placementWidth" : 543.365, + "placementHeight" : 177.261, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 177.261, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]", + "entityName" : "PaymentDetails", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 25.391, + "computedY" : 87.384, + "placementX" : 25.391, + "placementY" : 87.384, + "placementWidth" : 236.982, + "placementHeight" : 177.261, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 236.982, + "contentHeight" : 177.261, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 9.592, + "right" : 13.542, + "bottom" : 12.413, + "left" : 13.542 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]", + "entityName" : "CardHeadLayer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 38.933, + "computedY" : 239.818, + "placementX" : 38.933, + "placementY" : 239.818, + "placementWidth" : 209.898, + "placementHeight" : 15.235, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 15.235, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]", + "entityName" : "CardHeadHolder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 239.818, + "placementX" : 38.933, + "placementY" : 239.818, + "placementWidth" : 209.898, + "placementHeight" : 15.235, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 15.235, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]", + "entityName" : "CardHead", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 239.818, + "placementX" : 38.933, + "placementY" : 239.818, + "placementWidth" : 209.898, + "placementHeight" : 15.235, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 15.235, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]", + "entityName" : "CardIcon", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 239.818, + "placementX" : 38.933, + "placementY" : 239.818, + "placementWidth" : 15.235, + "placementHeight" : 15.235, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 15.235, + "contentHeight" : 15.235, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]/Glyphbank[0]", + "entityName" : "Glyphbank", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 239.818, + "placementX" : 38.933, + "placementY" : 239.818, + "placementWidth" : 15.235, + "placementHeight" : 15.235, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 15.235, + "contentHeight" : 15.235, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]/Glyphbank[0]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]/Glyphbank[0]", + "childIndex" : 0, + "depth" : 9, + "layer" : 9, + "computedX" : 38.933, + "computedY" : 239.818, + "placementX" : 38.933, + "placementY" : 239.818, + "placementWidth" : 15.235, + "placementHeight" : 15.235, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 15.235, + "contentHeight" : 15.235, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]/Glyphbank[0]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]/Glyphbank[0]/Align[0]", + "childIndex" : 0, + "depth" : 10, + "layer" : 10, + "computedX" : 38.933, + "computedY" : 239.818, + "placementX" : 38.933, + "placementY" : 239.818, + "placementWidth" : 15.235, + "placementHeight" : 15.235, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 15.235, + "contentHeight" : 15.235, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]/Glyphbank[0]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardIcon[0]/Glyphbank[0]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 11, + "layer" : 11, + "computedX" : 38.933, + "computedY" : 239.818, + "placementX" : 38.933, + "placementY" : 239.818, + "placementWidth" : 15.235, + "placementHeight" : 15.235, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 15.235, + "contentHeight" : 15.235, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]/CardLabel[1]", + "entityName" : "CardLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardHeadLayer[0]/CardHeadHolder[0]/CardHead[0]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 66.016, + "computedY" : 241.195, + "placementX" : 66.016, + "placementY" : 241.195, + "placementWidth" : 77.407, + "placementHeight" : 10.215, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 77.407, + "contentHeight" : 10.215, + "margin" : { + "top" : 3.642, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "entityName" : "CardFields", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 38.933, + "computedY" : 135.216, + "placementX" : 38.933, + "placementY" : 135.216, + "placementWidth" : 209.898, + "placementHeight" : 98.396, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 98.396, + "margin" : { + "top" : 6.207, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]", + "entityName" : "CardField1Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 223.689, + "placementX" : 38.933, + "placementY" : 223.689, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]/CardField1Holder[0]", + "entityName" : "CardField1Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 223.689, + "placementX" : 38.933, + "placementY" : 223.689, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]/CardField1Holder[0]/CardField1[0]", + "entityName" : "CardField1", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]/CardField1Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 223.689, + "placementX" : 38.933, + "placementY" : 223.689, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]/CardField1Holder[0]/CardField1[0]/CardField1Label[0]", + "entityName" : "CardField1Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]/CardField1Holder[0]/CardField1[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 223.689, + "placementX" : 38.933, + "placementY" : 223.689, + "placementWidth" : 44.056, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 44.056, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]/CardField1Holder[0]/CardField1[0]/CardField1Value[1]", + "entityName" : "CardField1Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField1Layer[0]/CardField1Holder[0]/CardField1[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 130.34, + "computedY" : 223.689, + "placementX" : 130.34, + "placementY" : 223.689, + "placementWidth" : 78.032, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 78.032, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]", + "entityName" : "CardField2Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 211.05, + "placementX" : 38.933, + "placementY" : 211.05, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]/CardField2Holder[0]", + "entityName" : "CardField2Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 211.05, + "placementX" : 38.933, + "placementY" : 211.05, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]/CardField2Holder[0]/CardField2[0]", + "entityName" : "CardField2", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]/CardField2Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 211.05, + "placementX" : 38.933, + "placementY" : 211.05, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]/CardField2Holder[0]/CardField2[0]/CardField2Label[0]", + "entityName" : "CardField2Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]/CardField2Holder[0]/CardField2[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 211.05, + "placementX" : 38.933, + "placementY" : 211.05, + "placementWidth" : 56.169, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 56.169, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]/CardField2Holder[0]/CardField2[0]/CardField2Value[1]", + "entityName" : "CardField2Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField2Layer[1]/CardField2Holder[0]/CardField2[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 130.34, + "computedY" : 211.05, + "placementX" : 130.34, + "placementY" : 211.05, + "placementWidth" : 93.585, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 93.585, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]", + "entityName" : "CardField3Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 198.411, + "placementX" : 38.933, + "placementY" : 198.411, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]/CardField3Holder[0]", + "entityName" : "CardField3Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 198.411, + "placementX" : 38.933, + "placementY" : 198.411, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]/CardField3Holder[0]/CardField3[0]", + "entityName" : "CardField3", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]/CardField3Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 198.411, + "placementX" : 38.933, + "placementY" : 198.411, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]/CardField3Holder[0]/CardField3[0]/CardField3Label[0]", + "entityName" : "CardField3Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]/CardField3Holder[0]/CardField3[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 198.411, + "placementX" : 38.933, + "placementY" : 198.411, + "placementWidth" : 64.314, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 64.314, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]/CardField3Holder[0]/CardField3[0]/CardField3Value[1]", + "entityName" : "CardField3Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField3Layer[2]/CardField3Holder[0]/CardField3[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 130.34, + "computedY" : 198.411, + "placementX" : 130.34, + "placementY" : 198.411, + "placementWidth" : 71.938, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 71.938, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]", + "entityName" : "CardField4Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "childIndex" : 3, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 185.772, + "placementX" : 38.933, + "placementY" : 185.772, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]/CardField4Holder[0]", + "entityName" : "CardField4Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 185.772, + "placementX" : 38.933, + "placementY" : 185.772, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]/CardField4Holder[0]/CardField4[0]", + "entityName" : "CardField4", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]/CardField4Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 185.772, + "placementX" : 38.933, + "placementY" : 185.772, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]/CardField4Holder[0]/CardField4[0]/CardField4Label[0]", + "entityName" : "CardField4Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]/CardField4Holder[0]/CardField4[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 185.772, + "placementX" : 38.933, + "placementY" : 185.772, + "placementWidth" : 53.499, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 53.499, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]/CardField4Holder[0]/CardField4[0]/CardField4Value[1]", + "entityName" : "CardField4Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField4Layer[3]/CardField4Holder[0]/CardField4[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 130.34, + "computedY" : 185.772, + "placementX" : 130.34, + "placementY" : 185.772, + "placementWidth" : 43.163, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 43.163, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]", + "entityName" : "CardField5Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "childIndex" : 4, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 173.133, + "placementX" : 38.933, + "placementY" : 173.133, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]/CardField5Holder[0]", + "entityName" : "CardField5Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 173.133, + "placementX" : 38.933, + "placementY" : 173.133, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]/CardField5Holder[0]/CardField5[0]", + "entityName" : "CardField5", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]/CardField5Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 173.133, + "placementX" : 38.933, + "placementY" : 173.133, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]/CardField5Holder[0]/CardField5[0]/CardField5Label[0]", + "entityName" : "CardField5Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]/CardField5Holder[0]/CardField5[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 173.133, + "placementX" : 38.933, + "placementY" : 173.133, + "placementWidth" : 48.165, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 48.165, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]/CardField5Holder[0]/CardField5[0]/CardField5Value[1]", + "entityName" : "CardField5Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField5Layer[4]/CardField5Holder[0]/CardField5[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 130.34, + "computedY" : 173.133, + "placementX" : 130.34, + "placementY" : 173.133, + "placementWidth" : 42.361, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 42.361, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]", + "entityName" : "CardField6Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "childIndex" : 5, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 160.494, + "placementX" : 38.933, + "placementY" : 160.494, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]/CardField6Holder[0]", + "entityName" : "CardField6Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 160.494, + "placementX" : 38.933, + "placementY" : 160.494, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]/CardField6Holder[0]/CardField6[0]", + "entityName" : "CardField6", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]/CardField6Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 160.494, + "placementX" : 38.933, + "placementY" : 160.494, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]/CardField6Holder[0]/CardField6[0]/CardField6Label[0]", + "entityName" : "CardField6Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]/CardField6Holder[0]/CardField6[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 160.494, + "placementX" : 38.933, + "placementY" : 160.494, + "placementWidth" : 35.423, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 35.423, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]/CardField6Holder[0]/CardField6[0]/CardField6Value[1]", + "entityName" : "CardField6Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField6Layer[5]/CardField6Holder[0]/CardField6[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 130.34, + "computedY" : 160.494, + "placementX" : 130.34, + "placementY" : 160.494, + "placementWidth" : 16.868, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 16.868, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]", + "entityName" : "CardField7Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "childIndex" : 6, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 147.855, + "placementX" : 38.933, + "placementY" : 147.855, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]/CardField7Holder[0]", + "entityName" : "CardField7Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 147.855, + "placementX" : 38.933, + "placementY" : 147.855, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]/CardField7Holder[0]/CardField7[0]", + "entityName" : "CardField7", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]/CardField7Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 147.855, + "placementX" : 38.933, + "placementY" : 147.855, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]/CardField7Holder[0]/CardField7[0]/CardField7Label[0]", + "entityName" : "CardField7Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]/CardField7Holder[0]/CardField7[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 147.855, + "placementX" : 38.933, + "placementY" : 147.855, + "placementWidth" : 39.194, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 39.194, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]/CardField7Holder[0]/CardField7[0]/CardField7Value[1]", + "entityName" : "CardField7Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField7Layer[6]/CardField7Holder[0]/CardField7[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 130.34, + "computedY" : 147.855, + "placementX" : 130.34, + "placementY" : 147.855, + "placementWidth" : 73.137, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 73.137, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]", + "entityName" : "CardField8Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]", + "childIndex" : 7, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 135.216, + "placementX" : 38.933, + "placementY" : 135.216, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]/CardField8Holder[0]", + "entityName" : "CardField8Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 135.216, + "placementX" : 38.933, + "placementY" : 135.216, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]/CardField8Holder[0]/CardField8[0]", + "entityName" : "CardField8", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]/CardField8Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 135.216, + "placementX" : 38.933, + "placementY" : 135.216, + "placementWidth" : 209.898, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]/CardField8Holder[0]/CardField8[0]/CardField8Label[0]", + "entityName" : "CardField8Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]/CardField8Holder[0]/CardField8[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 135.216, + "placementX" : 38.933, + "placementY" : 135.216, + "placementWidth" : 51.853, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 51.853, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]/CardField8Holder[0]/CardField8[0]/CardField8Value[1]", + "entityName" : "CardField8Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardFields[1]/CardField8Layer[7]/CardField8Holder[0]/CardField8[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 130.34, + "computedY" : 135.216, + "placementX" : 130.34, + "placementY" : 135.216, + "placementWidth" : 108.138, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 108.138, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardRule[2]", + "entityName" : "CardRule", + "entityKind" : "LineNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 38.933, + "computedY" : 131.161, + "placementX" : 38.933, + "placementY" : 131.161, + "placementWidth" : 209.898, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 1.0, + "margin" : { + "top" : 3.055, + "right" : 0.0, + "bottom" : 9.028, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]", + "entityName" : "CardNoteLayer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]", + "childIndex" : 3, + "depth" : 4, + "layer" : 4, + "computedX" : 38.933, + "computedY" : 99.797, + "placementX" : 38.933, + "placementY" : 99.797, + "placementWidth" : 209.898, + "placementHeight" : 22.336, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 22.336, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]", + "entityName" : "CardNoteHolder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 38.933, + "computedY" : 99.797, + "placementX" : 38.933, + "placementY" : 99.797, + "placementWidth" : 209.898, + "placementHeight" : 22.336, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 22.336, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]", + "entityName" : "CardNote", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 38.933, + "computedY" : 99.797, + "placementX" : 38.933, + "placementY" : 99.797, + "placementWidth" : 209.898, + "placementHeight" : 22.336, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 209.898, + "contentHeight" : 22.336, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]", + "entityName" : "CardNoteIcon", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 38.933, + "computedY" : 110.848, + "placementX" : 38.933, + "placementY" : 110.848, + "placementWidth" : 16.927, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 16.927, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]/Glyphinfo[0]", + "entityName" : "Glyphinfo", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 38.933, + "computedY" : 110.848, + "placementX" : 38.933, + "placementY" : 110.848, + "placementWidth" : 16.927, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 16.927, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]/Glyphinfo[0]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]/Glyphinfo[0]", + "childIndex" : 0, + "depth" : 9, + "layer" : 9, + "computedX" : 38.933, + "computedY" : 110.848, + "placementX" : 38.933, + "placementY" : 110.848, + "placementWidth" : 16.927, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 16.927, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]/Glyphinfo[0]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]/Glyphinfo[0]/Align[0]", + "childIndex" : 0, + "depth" : 10, + "layer" : 10, + "computedX" : 38.933, + "computedY" : 110.848, + "placementX" : 38.933, + "placementY" : 110.848, + "placementWidth" : 11.285, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 11.285, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]/Glyphinfo[0]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteIcon[0]/Glyphinfo[0]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 11, + "layer" : 11, + "computedX" : 38.933, + "computedY" : 110.848, + "placementX" : 38.933, + "placementY" : 110.848, + "placementWidth" : 11.285, + "placementHeight" : 11.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 11.285, + "contentHeight" : 11.285, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]/CardNoteText[1]", + "entityName" : "CardNoteText", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/PaymentDetails[0]/CardNoteLayer[3]/CardNoteHolder[0]/CardNote[0]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 55.86, + "computedY" : 99.797, + "placementX" : 55.86, + "placementY" : 99.797, + "placementWidth" : 185.062, + "placementHeight" : 22.336, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 185.062, + "contentHeight" : 22.336, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]", + "entityName" : "Settlement", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 324.439, + "computedY" : 104.36, + "placementX" : 324.439, + "placementY" : 104.36, + "placementWidth" : 244.317, + "placementHeight" : 160.284, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 244.317, + "contentHeight" : 160.284, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 16.363, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]", + "entityName" : "Totals", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 324.439, + "computedY" : 228.217, + "placementX" : 324.439, + "placementY" : 228.217, + "placementWidth" : 227.954, + "placementHeight" : 30.616, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 227.954, + "contentHeight" : 30.616, + "margin" : { + "top" : 5.812, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 5.642, + "bottom" : 0.0, + "left" : 3.385 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]", + "entityName" : "Total1Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 327.825, + "computedY" : 247.966, + "placementX" : 327.825, + "placementY" : 247.966, + "placementWidth" : 218.926, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]/Total1Holder[0]", + "entityName" : "Total1Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 327.825, + "computedY" : 247.966, + "placementX" : 327.825, + "placementY" : 247.966, + "placementWidth" : 218.926, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]/Total1Holder[0]/Total1[0]", + "entityName" : "Total1", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]/Total1Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 327.825, + "computedY" : 247.966, + "placementX" : 327.825, + "placementY" : 247.966, + "placementWidth" : 218.926, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]/Total1Holder[0]/Total1[0]/Total1Label[0]", + "entityName" : "Total1Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]/Total1Holder[0]/Total1[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 327.825, + "computedY" : 247.966, + "placementX" : 327.825, + "placementY" : 247.966, + "placementWidth" : 33.318, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 33.318, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]/Total1Holder[0]/Total1[0]/Total1Value[1]", + "entityName" : "Total1Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total1Layer[0]/Total1Holder[0]/Total1[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 437.288, + "computedY" : 247.966, + "placementX" : 437.288, + "placementY" : 247.966, + "placementWidth" : 109.463, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 109.463, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]", + "entityName" : "Total2Layer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 327.825, + "computedY" : 228.217, + "placementX" : 327.825, + "placementY" : 228.217, + "placementWidth" : 218.926, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]/Total2Holder[0]", + "entityName" : "Total2Holder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 327.825, + "computedY" : 228.217, + "placementX" : 327.825, + "placementY" : 228.217, + "placementWidth" : 218.926, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]/Total2Holder[0]/Total2[0]", + "entityName" : "Total2", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]/Total2Holder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 327.825, + "computedY" : 228.217, + "placementX" : 327.825, + "placementY" : 228.217, + "placementWidth" : 218.926, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]/Total2Holder[0]/Total2[0]/Total2Label[0]", + "entityName" : "Total2Label", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]/Total2Holder[0]/Total2[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 327.825, + "computedY" : 228.217, + "placementX" : 327.825, + "placementY" : 228.217, + "placementWidth" : 34.033, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 34.033, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]/Total2Holder[0]/Total2[0]/Total2Value[1]", + "entityName" : "Total2Value", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/Totals[0]/Total2Layer[1]/Total2Holder[0]/Total2[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 437.288, + "computedY" : 228.217, + "placementX" : 437.288, + "placementY" : 228.217, + "placementWidth" : 109.463, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 109.463, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalsRule[1]", + "entityName" : "TotalsRule", + "entityKind" : "LineNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 327.825, + "computedY" : 218.336, + "placementX" : 327.825, + "placementY" : 218.336, + "placementWidth" : 224.004, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 224.004, + "contentHeight" : 1.0, + "margin" : { + "top" : 8.881, + "right" : 0.0, + "bottom" : 13.711, + "left" : 3.385 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]", + "entityName" : "TotalDue", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 324.439, + "computedY" : 187.143, + "placementX" : 324.439, + "placementY" : 187.143, + "placementWidth" : 227.954, + "placementHeight" : 17.482, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 227.954, + "contentHeight" : 17.482, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 5.642, + "bottom" : 0.0, + "left" : 3.385 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]", + "entityName" : "TotalDueRowLayer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 327.825, + "computedY" : 187.143, + "placementX" : 327.825, + "placementY" : 187.143, + "placementWidth" : 218.926, + "placementHeight" : 17.482, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 17.482, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]/TotalDueRowHolder[0]", + "entityName" : "TotalDueRowHolder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 327.825, + "computedY" : 187.143, + "placementX" : 327.825, + "placementY" : 187.143, + "placementWidth" : 218.926, + "placementHeight" : 17.482, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 17.482, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]/TotalDueRowHolder[0]/TotalDueRow[0]", + "entityName" : "TotalDueRow", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]/TotalDueRowHolder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 327.825, + "computedY" : 187.143, + "placementX" : 327.825, + "placementY" : 187.143, + "placementWidth" : 218.926, + "placementHeight" : 17.482, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 218.926, + "contentHeight" : 17.482, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]/TotalDueRowHolder[0]/TotalDueRow[0]/TotalDueLabel[0]", + "entityName" : "TotalDueLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]/TotalDueRowHolder[0]/TotalDueRow[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 327.825, + "computedY" : 189.444, + "placementX" : 327.825, + "placementY" : 189.444, + "placementWidth" : 59.518, + "placementHeight" : 12.88, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 59.518, + "contentHeight" : 12.88, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]/TotalDueRowHolder[0]/TotalDueRow[0]/TotalDueValue[1]", + "entityName" : "TotalDueValue", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/TotalDue[2]/TotalDueRowLayer[0]/TotalDueRowHolder[0]/TotalDueRow[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 437.288, + "computedY" : 187.143, + "placementX" : 437.288, + "placementY" : 187.143, + "placementWidth" : 109.463, + "placementHeight" : 17.482, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 109.463, + "contentHeight" : 17.482, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]", + "entityName" : "PaymentDuePanel", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]", + "childIndex" : 3, + "depth" : 4, + "layer" : 4, + "computedX" : 324.439, + "computedY" : 104.36, + "placementX" : 324.439, + "placementY" : 104.36, + "placementWidth" : 227.954, + "placementHeight" : 58.689, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 227.954, + "contentHeight" : 58.689, + "margin" : { + "top" : 24.093, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 14.106, + "right" : 13.542, + "bottom" : 15.799, + "left" : 12.978 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]", + "entityName" : "PaymentDueRowLayer", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 337.417, + "computedY" : 120.159, + "placementX" : 337.417, + "placementY" : 120.159, + "placementWidth" : 201.435, + "placementHeight" : 28.784, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 201.435, + "contentHeight" : 28.784, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]", + "entityName" : "PaymentDueRowHolder", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 337.417, + "computedY" : 120.159, + "placementX" : 337.417, + "placementY" : 120.159, + "placementWidth" : 201.435, + "placementHeight" : 28.784, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 201.435, + "contentHeight" : 28.784, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]", + "entityName" : "PaymentDueRow", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 337.417, + "computedY" : 120.159, + "placementX" : 337.417, + "placementY" : 120.159, + "placementWidth" : 201.435, + "placementHeight" : 28.784, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 201.435, + "contentHeight" : 28.784, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]", + "entityName" : "DueTile", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 337.417, + "computedY" : 127.502, + "placementX" : 337.417, + "placementY" : 127.502, + "placementWidth" : 21.441, + "placementHeight" : 21.441, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 21.441, + "contentHeight" : 21.441, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]", + "entityName" : "DueTileShape", + "entityKind" : "ShapeContainerNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]", + "childIndex" : 0, + "depth" : 9, + "layer" : 9, + "computedX" : 337.417, + "computedY" : 127.502, + "placementX" : 337.417, + "placementY" : 127.502, + "placementWidth" : 21.441, + "placementHeight" : 21.441, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 21.441, + "contentHeight" : 21.441, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]/Glyphcalendar[0]", + "entityName" : "Glyphcalendar", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]", + "childIndex" : 0, + "depth" : 10, + "layer" : 10, + "computedX" : 337.417, + "computedY" : 132.016, + "placementX" : 337.417, + "placementY" : 132.016, + "placementWidth" : 21.441, + "placementHeight" : 12.413, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 21.441, + "contentHeight" : 12.413, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]/Glyphcalendar[0]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]/Glyphcalendar[0]", + "childIndex" : 0, + "depth" : 11, + "layer" : 11, + "computedX" : 337.417, + "computedY" : 132.016, + "placementX" : 337.417, + "placementY" : 132.016, + "placementWidth" : 21.441, + "placementHeight" : 12.413, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 21.441, + "contentHeight" : 12.413, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]/Glyphcalendar[0]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]/Glyphcalendar[0]/Align[0]", + "childIndex" : 0, + "depth" : 12, + "layer" : 12, + "computedX" : 341.931, + "computedY" : 132.016, + "placementX" : 341.931, + "placementY" : 132.016, + "placementWidth" : 12.413, + "placementHeight" : 12.413, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 12.413, + "contentHeight" : 12.413, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]/Glyphcalendar[0]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueTile[0]/DueTileShape[0]/Glyphcalendar[0]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 13, + "layer" : 13, + "computedX" : 341.931, + "computedY" : 132.016, + "placementX" : 341.931, + "placementY" : 132.016, + "placementWidth" : 12.413, + "placementHeight" : 12.413, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 12.413, + "contentHeight" : 12.413, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueText[1]", + "entityName" : "DueText", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 372.4, + "computedY" : 120.159, + "placementX" : 372.4, + "placementY" : 120.159, + "placementWidth" : 73.945, + "placementHeight" : 27.964, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 73.945, + "contentHeight" : 27.964, + "margin" : { + "top" : 0.821, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueText[1]/DueLabel[0]", + "entityName" : "DueLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueText[1]", + "childIndex" : 0, + "depth" : 9, + "layer" : 9, + "computedX" : 372.4, + "computedY" : 137.907, + "placementX" : 372.4, + "placementY" : 137.907, + "placementWidth" : 73.398, + "placementHeight" : 10.215, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 73.398, + "contentHeight" : 10.215, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueText[1]/DueValue[1]", + "entityName" : "DueValue", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/SettlementRow[6]/Settlement[1]/PaymentDuePanel[3]/PaymentDueRowLayer[0]/PaymentDueRowHolder[0]/PaymentDueRow[0]/DueText[1]", + "childIndex" : 1, + "depth" : 9, + "layer" : 9, + "computedX" : 372.4, + "computedY" : 120.159, + "placementX" : 372.4, + "placementY" : 120.159, + "placementWidth" : 73.945, + "placementHeight" : 14.647, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 73.945, + "contentHeight" : 14.647, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ClosingRule[7]", + "entityName" : "ClosingRule", + "entityKind" : "LineNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 7, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 84.465, + "placementX" : 25.391, + "placementY" : 84.465, + "placementWidth" : 543.365, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 1.0, + "margin" : { + "top" : 1.918, + "right" : 0.0, + "bottom" : 8.294, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]", + "entityName" : "ThankYou", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 8, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 53.652, + "placementX" : 25.391, + "placementY" : 53.652, + "placementWidth" : 543.365, + "placementHeight" : 22.519, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 22.519, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 3.385 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]", + "entityName" : "ThankYouRow", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 28.776, + "computedY" : 53.652, + "placementX" : 28.776, + "placementY" : 53.652, + "placementWidth" : 539.98, + "placementHeight" : 22.519, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 539.98, + "contentHeight" : 22.519, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]", + "entityName" : "ThankYouIcon", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 28.776, + "computedY" : 59.244, + "placementX" : 28.776, + "placementY" : 59.244, + "placementWidth" : 25.955, + "placementHeight" : 16.927, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 25.955, + "contentHeight" : 16.927, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]/Glyphinfo[0]", + "entityName" : "Glyphinfo", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 28.776, + "computedY" : 59.244, + "placementX" : 28.776, + "placementY" : 59.244, + "placementWidth" : 25.955, + "placementHeight" : 16.927, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 25.955, + "contentHeight" : 16.927, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]/Glyphinfo[0]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]/Glyphinfo[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 28.776, + "computedY" : 59.244, + "placementX" : 28.776, + "placementY" : 59.244, + "placementWidth" : 25.955, + "placementHeight" : 16.927, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 25.955, + "contentHeight" : 16.927, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]/Glyphinfo[0]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]/Glyphinfo[0]/Align[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 28.776, + "computedY" : 59.244, + "placementX" : 28.776, + "placementY" : 59.244, + "placementWidth" : 16.927, + "placementHeight" : 16.927, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 16.927, + "contentHeight" : 16.927, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]/Glyphinfo[0]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouIcon[0]/Glyphinfo[0]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 28.776, + "computedY" : 59.244, + "placementX" : 28.776, + "placementY" : 59.244, + "placementWidth" : 16.927, + "placementHeight" : 16.927, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 16.927, + "contentHeight" : 16.927, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouText[1]", + "entityName" : "ThankYouText", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 54.732, + "computedY" : 53.652, + "placementX" : 54.732, + "placementY" : 53.652, + "placementWidth" : 389.069, + "placementHeight" : 22.519, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 389.069, + "contentHeight" : 22.519, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouText[1]/ThankYouTitle[0]", + "entityName" : "ThankYouTitle", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouText[1]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 54.732, + "computedY" : 65.303, + "placementX" : 54.732, + "placementY" : 65.303, + "placementWidth" : 113.139, + "placementHeight" : 10.867, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 113.139, + "contentHeight" : 10.867, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouText[1]/ThankYouBody[1]", + "entityName" : "ThankYouBody", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/ThankYou[8]/ThankYouRow[0]/ThankYouText[1]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 54.732, + "computedY" : 53.652, + "placementX" : 54.732, + "placementY" : 53.652, + "placementWidth" : 389.069, + "placementHeight" : 8.977, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 389.069, + "contentHeight" : 8.977, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/FooterRule[9]", + "entityName" : "FooterRule", + "entityKind" : "LineNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 9, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 44.552, + "placementX" : 25.391, + "placementY" : 44.552, + "placementWidth" : 543.365, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 1.0, + "margin" : { + "top" : 8.1, + "right" : 0.0, + "bottom" : 2.514, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/DocumentFooter[10]", + "entityName" : "DocumentFooter", + "entityKind" : "RowNode", + "parentPath" : "WorkspaceInvoice[0]", + "childIndex" : 10, + "depth" : 2, + "layer" : 2, + "computedX" : 25.391, + "computedY" : 18.885, + "placementX" : 25.391, + "placementY" : 18.885, + "placementWidth" : 543.365, + "placementHeight" : 23.152, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 543.365, + "contentHeight" : 23.152, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/DocumentFooter[10]/FooterWordmark[0]", + "entityName" : "FooterWordmark", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/DocumentFooter[10]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 25.391, + "computedY" : 18.885, + "placementX" : 25.391, + "placementY" : 18.885, + "placementWidth" : 58.595, + "placementHeight" : 23.152, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 58.595, + "contentHeight" : 23.152, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/DocumentFooter[10]/FooterAddress[1]", + "entityName" : "FooterAddress", + "entityKind" : "SectionNode", + "parentPath" : "WorkspaceInvoice[0]/DocumentFooter[10]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 106.642, + "computedY" : 19.011, + "placementX" : 106.642, + "placementY" : 19.011, + "placementWidth" : 255.901, + "placementHeight" : 22.9, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 255.901, + "contentHeight" : 22.9, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/DocumentFooter[10]/FooterAddress[1]/FooterName[0]", + "entityName" : "FooterName", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/DocumentFooter[10]/FooterAddress[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 106.642, + "computedY" : 31.989, + "placementX" : 106.642, + "placementY" : 31.989, + "placementWidth" : 95.264, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 95.264, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/DocumentFooter[10]/FooterAddress[1]/FooterAddressLine[1]", + "entityName" : "FooterAddressLine", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/DocumentFooter[10]/FooterAddress[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 106.642, + "computedY" : 19.011, + "placementX" : 106.642, + "placementY" : 19.011, + "placementWidth" : 255.901, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 255.901, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "WorkspaceInvoice[0]/DocumentFooter[10]/FooterSite[2]", + "entityName" : "FooterSite", + "entityKind" : "ParagraphNode", + "parentPath" : "WorkspaceInvoice[0]/DocumentFooter[10]", + "childIndex" : 2, + "depth" : 3, + "layer" : 3, + "computedX" : 484.12, + "computedY" : 25.5, + "placementX" : 484.12, + "placementY" : 25.5, + "placementWidth" : 81.251, + "placementHeight" : 9.922, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 81.251, + "contentHeight" : 9.922, + "margin" : { + "top" : 0.0, + "right" : 1.693, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + } ] +} diff --git a/qa/src/test/resources/visual-baselines/invoice-v2-layered/workspace_invoice-page-0.png b/qa/src/test/resources/visual-baselines/invoice-v2-layered/workspace_invoice-page-0.png new file mode 100644 index 000000000..f55e72757 Binary files /dev/null and b/qa/src/test/resources/visual-baselines/invoice-v2-layered/workspace_invoice-page-0.png differ diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceClosing.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceClosing.java new file mode 100644 index 000000000..8a3af95f4 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceClosing.java @@ -0,0 +1,172 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.dsl.PageFlowBuilder; +import com.demcha.compose.document.node.DocumentLinkOptions; +import com.demcha.compose.document.node.HorizontalAlign; +import com.demcha.compose.document.node.RowVerticalAlign; +import com.demcha.compose.document.node.TextAlign; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentRowColumn; +import com.demcha.compose.document.style.DocumentTextDecoration; +import com.demcha.compose.document.style.DocumentTextStyle; +import com.demcha.compose.document.templates.data.invoice.InvoiceBrand; +import com.demcha.compose.document.templates.data.invoice.InvoiceContactBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceNotesBlock; + +import java.util.List; + +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.BODY; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CLOSING_INNER_LIFT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CLOSING_RULE_LIFT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.FOOTER_LINK_COL; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.FOOTER_MARK_COL; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.FOOTER_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.HAIRLINE_STRONG; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.INK; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.MUTED; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.RULE_THIN; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.THANKS_BODY_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.THANKS_ICON; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.THANKS_ICON_COL; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.THANKS_INDENT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.THANKS_TITLE_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.WORDMARK_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.blockGap; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.gap; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.px; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.style; + +/** + * What closes the sheet: the thank-you block and the brand band under it. + * + *

The band is body content rather than page chrome — it carries a wordmark + * and a reachable address, and a header/footer zone takes only strings. Page + * identity on a continuation page is carried by the page number instead.

+ */ +final class WorkspaceClosing { + + private WorkspaceClosing() { + } + + /** + * Draws the closing blocks. + * + * @param page the page flow + * @param notes the closing words and the address inside them + * @param brand the wordmark the band opens with + * @param supplier who is invoicing, named again under the band + */ + static void render(PageFlowBuilder page, InvoiceNotesBlock notes, InvoiceBrand brand, + InvoiceContactBlock supplier) { + WorkspaceWidgets.fullWidthRule(page, "ClosingRule", HAIRLINE_STRONG, RULE_THIN, + px(12.4) - CLOSING_RULE_LIFT, px(19.2) - CLOSING_INNER_LIFT); + renderThankYou(page, notes); + WorkspaceWidgets.fullWidthRule(page, "FooterRule", HAIRLINE_STRONG, RULE_THIN, + blockGap(22.15, THANKS_BODY_SIZE, 0) - CLOSING_INNER_LIFT, + blockGap(7.9, 0, FOOTER_SIZE)); + renderBand(page, brand, supplier); + } + + /** + * The closing words, opened by a mark in its own column so a wrapped second + * line returns to the text axis rather than to the glyph's. + * + *

The address inside the sentence is a separate run, so it reaches the + * PDF as a real annotation rather than as coloured text.

+ */ + private static void renderThankYou(PageFlowBuilder page, InvoiceNotesBlock notes) { + List paragraphs = notes.paragraphs(); + String title = notes.heading(); + String body = paragraphs.isEmpty() ? "" : paragraphs.get(0); + page.addSection("ThankYou", block -> { + block.spacing(0) + .padding(new DocumentInsets(0, 0, 0, THANKS_INDENT)) + .keepWithNext(); + block.addRow("ThankYouRow", row -> { + row.spacing(0) + .columns(DocumentRowColumn.fixed(THANKS_ICON_COL), + DocumentRowColumn.weight(1)); + row.addSection("ThankYouIcon", glyph -> glyph + .spacing(0) + .add(WorkspaceWidgets.glyph(WorkspaceIcons.INFO, THANKS_ICON, + HorizontalAlign.LEFT))); + row.addSection("ThankYouText", text -> { + text.spacing(gap(24, THANKS_TITLE_SIZE)); + text.addParagraph(p -> p + .name("ThankYouTitle") + .text(title) + .textStyle(style(THANKS_TITLE_SIZE, INK, + DocumentTextDecoration.BOLD))); + text.addParagraph(p -> { + p.name("ThankYouBody"); + DocumentTextStyle plain = style(THANKS_BODY_SIZE, MUTED, + DocumentTextDecoration.DEFAULT); + String email = notes.contactEmail(); + if (email.isBlank() || !body.contains(email)) { + p.inlineText(body, plain); + return; + } + // The address is set apart inside the sentence, so the + // words on either side of it stay one paragraph. + int at = body.indexOf(email); + p.inlineText(body.substring(0, at), plain); + p.inlineText(email, + style(THANKS_BODY_SIZE, ACCENT, DocumentTextDecoration.DEFAULT), + new DocumentLinkOptions("mailto:" + email)); + p.inlineText(body.substring(at + email.length()), plain); + }); + }); + }); + }); + } + + /** The brand band: the wordmark, who is invoicing, and where to find them. */ + private static void renderBand(PageFlowBuilder page, InvoiceBrand brand, + InvoiceContactBlock supplier) { + String website = supplier.website(); + page.addRow("DocumentFooter", row -> { + row.spacing(0) + .verticalAlign(RowVerticalAlign.CENTER) + .columns(DocumentRowColumn.fixed(FOOTER_MARK_COL), + DocumentRowColumn.weight(1), + DocumentRowColumn.fixed(FOOTER_LINK_COL)); + row.addParagraph(p -> p + .name("FooterWordmark") + .text(brand.name()) + .textStyle(style(WORDMARK_SIZE, INK, DocumentTextDecoration.BOLD))); + row.addSection("FooterAddress", text -> { + text.spacing(gap(23, FOOTER_SIZE)); + text.addParagraph(p -> p + .name("FooterName") + .text(supplier.legalName()) + .textStyle(style(FOOTER_SIZE, BODY, DocumentTextDecoration.BOLD))); + text.addParagraph(p -> p + .name("FooterAddressLine") + .text(supplier.addressLines().isEmpty() + ? "" : String.join(", ", supplier.addressLines())) + .textStyle(style(FOOTER_SIZE, MUTED, DocumentTextDecoration.DEFAULT))); + }); + row.addParagraph(p -> { + p.name("FooterSite"); + DocumentTextStyle linkStyle = + style(FOOTER_SIZE, ACCENT, DocumentTextDecoration.DEFAULT); + if (website.isBlank()) { + p.text(""); + } else { + p.inlineText(website, linkStyle, new DocumentLinkOptions(uri(website))); + } + p.align(TextAlign.RIGHT); + p.margin(new DocumentInsets(0, px(3), 0, 0)); + }); + }); + } + + /** A written address as something a reader can follow. */ + private static String uri(String website) { + String trimmed = website.trim(); + return trimmed.startsWith("http://") || trimmed.startsWith("https://") + ? trimmed + : "https://" + trimmed; + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceIcons.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceIcons.java new file mode 100644 index 000000000..da19eb9b0 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceIcons.java @@ -0,0 +1,87 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.svg.SvgIcon; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Map; + +/** + * Classpath loader for the Workspace invoice marks: the two party glyphs, the + * three a service line may take, and the three the preset places itself — the + * bank on the payment card, the information mark on its note, and the calendar + * on the due panel. + * + *

They ship inside the templates artifact under + * {@code templates/invoice/workspace/icons/} as SVG, so they scale with the box + * they are drawn into rather than being resampled. Parsed icons are cached per + * token, so a sheet that repeats a mark reads each file once per JVM.

+ * + *

The set is coloured, not tinted

+ * + *

Each glyph carries its colour in its own markup: white for the marks that + * are knocked out of a filled disc or tile, accent for the ones that stand on + * the page. A token therefore names a glyph and where it is meant to + * sit.

+ * + *

{@link #LINE_TOKENS} is the vocabulary a document names through + * {@code InvoiceServiceLines.Line.icon()}. It is scoped to this preset — + * another preset packages its own set.

+ */ +final class WorkspaceIcons { + + static final String BILL_TO = "bill-to"; + static final String SHIP_TO = "ship-to"; + static final String BANK = "bank"; + static final String INFO = "info"; + static final String CALENDAR = "calendar"; + + private static final String ICON_ROOT = "/templates/invoice/workspace/icons/"; + + /** The marks a document may name on a service line. */ + static final Set LINE_TOKENS = Set.of("search", "grid", "shield"); + + private static final Set TOKENS = Set.of( + BILL_TO, SHIP_TO, BANK, INFO, CALENDAR, "search", "grid", "shield"); + + private static final Map CACHE = new ConcurrentHashMap<>(); + + private WorkspaceIcons() { + } + + /** + * Reads one mark. + * + * @param token one of the packaged tokens + * @return the parsed icon + * @throws IllegalArgumentException when the token names no packaged mark, + * listing the ones a document may choose — an icon token is data, + * so a wrong one is a data error + */ + static SvgIcon icon(String token) { + if (!TOKENS.contains(token)) { + throw new IllegalArgumentException( + "Unknown workspace invoice icon token '" + token + + "'. This preset packages " + LINE_TOKENS.stream().sorted().toList() + + " for a service line's mark."); + } + return CACHE.computeIfAbsent(token, WorkspaceIcons::read); + } + + private static SvgIcon read(String token) { + String resourcePath = ICON_ROOT + token + ".svg"; + try (InputStream input = WorkspaceIcons.class.getResourceAsStream(resourcePath)) { + if (input == null) { + throw new IllegalStateException("Missing workspace invoice icon: " + resourcePath); + } + return SvgIcon.parse(new String(input.readAllBytes(), StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new UncheckedIOException( + "Failed to read workspace invoice icon: " + resourcePath, e); + } + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoice.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoice.java new file mode 100644 index 000000000..7ffd4d03f --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceInvoice.java @@ -0,0 +1,169 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.api.PageMarginRule; +import com.demcha.compose.document.output.DocumentHeaderFooter; +import com.demcha.compose.document.output.DocumentHeaderFooterZone; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.templates.api.DocumentTemplate; +import com.demcha.compose.document.templates.data.invoice.StructuredInvoiceData; + +import java.util.List; +import java.util.Objects; + +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CONTINUATION_MARGIN; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.MUTED; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.PAGE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.PAGE_MARGIN; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.PAGE_NUMBER_BAND; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.PAGE_NUMBER_SIZE; + +/** + * Workspace — a violet-accented SaaS invoice: a brand masthead over an accent + * bar, a half-split issuer and metadata header, two addressed parties on + * discs, a line-item table whose marks sit on coloured tiles, a settlement row + * pairing the bank details against the totals, and a closing band carrying the + * wordmark. + * + *

It flows

+ * + *

The design shows four service lines and real data brings dozens, so the + * table is the region that grows: its header repeats on every page it reaches, + * a continuation page reserves a deeper bottom margin than page one, and every + * page carries its number.

+ * + *

Numbering every page including the first is a departure from the design, + * which is a single sheet and has none. Suppressing page one would match it and + * still make a missing page detectable — a document that opens on "Page 2 of 3" + * is obviously incomplete — but a page without a number cannot be told from a + * page that was lost, so every page carries one.

+ * + *

One column, not five

+ * + *

The table has an outer box and a rule between every row and no interior + * verticals, which is exactly what a single-column table draws: a cell strokes + * all four of its own edges and a one-column table has no interior vertical + * edge. The five columns are a row inside each cell. Built the other way round + * — the box from a stroked section wrapped round the table — every continuation + * page would end in an empty bordered strip, and on page one that strip's + * bottom edge lands on the page number.

+ * + *

The lockup and the wordmark are the caller's

+ * + *

The design opens with a mark and closes with a wordmark. Both come from + * {@code InvoiceBrand}: the masthead draws the logo at the design's measured + * width, or the brand's name when there is no logo, and the closing band always + * sets the name. The templates artifact carries no mark of its own.

+ * + *

What the document says, and what the preset chooses

+ * + *

A service line names its own mark through + * {@code InvoiceServiceLines.Line.icon()}, from this preset's own vocabulary, + * and an unknown token is reported as a data error naming the set. A mark the + * design gives a colour is knocked out of a tile in it; one it does not is drawn + * bare. A line with no token is drawn without a mark. The party discs, the bank + * mark, the information mark and the calendar are the preset's: which glyph + * opens which block is a property of the design rather than of the document.

+ * + *

Figures are written with the locale stated rather than inherited, so the + * same data renders the same sheet on any machine.

+ * + *

Fonts

+ * + *

The sheet is set in Lato throughout, and the face was chosen by + * measurement: its natural widths for eight of the design's strings land within + * 2–5% of the measured ink, where other grotesques are 8–20% out at the same cap + * height. The templates artifact carries no fonts — register the family on the + * session, or the engine substitutes and the measured geometry no longer + * matches the type sitting in it.

+ * + *

Usage:

+ *
{@code
+ * DocumentTemplate template = WorkspaceInvoice.create();
+ * template.compose(session, invoice);
+ * }
+ * + * @since 2.2.3 + */ +public final class WorkspaceInvoice { + + /** Stable identifier of this preset. */ + public static final String ID = "workspace-invoice"; + + /** Human-readable name of this preset. */ + public static final String DISPLAY_NAME = "Workspace Invoice"; + + private WorkspaceInvoice() { + } + + /** + * Creates the template. + * + * @return a template composing a {@link StructuredInvoiceData} + */ + public static DocumentTemplate create() { + return new Template(); + } + + private record Template() implements DocumentTemplate { + + @Override + public String id() { + return ID; + } + + @Override + public String displayName() { + return DISPLAY_NAME; + } + + @Override + public void compose(DocumentSession document, StructuredInvoiceData data) { + Objects.requireNonNull(document, "document"); + Objects.requireNonNull(data, "data"); + + // Every length on the sheet is a share of the design's own grid, so + // the preset sets the page and its margins rather than following + // what the caller configured. + document.pageSize(PAGE); + document.margin(PAGE_MARGIN); + document.pageMargins(List.of(PageMarginRule.from(2, CONTINUATION_MARGIN))); + renderPageNumber(document); + + String currency = data.currencyCode(); + document.pageFlow(page -> { + page.name("WorkspaceInvoice").padding(DocumentInsets.zero()).spacing(0); + WorkspaceMasthead.renderHeader(page, data.brand(), data.supplier(), + data.masthead()); + WorkspaceMasthead.renderParties(page, data.billTo(), data.shipTo()); + WorkspaceLines.render(page, data.serviceLines(), currency); + WorkspaceSettlement.render(page, data.payment(), data.totals(), currency); + WorkspaceClosing.render(page, data.notes(), data.brand(), data.supplier()); + }); + } + + /** + * The only chrome the sheet has. The design's own closing band cannot be + * chrome — a header/footer zone carries left, centre and right strings + * and nothing else, and the band holds a wordmark and a link — so page + * identity is carried by the page number alone. + * + *

The height is stated because a default band is taller than the + * design leaves under its closing block, and a default-height band takes + * that much off the content area and pushes the band onto a second + * page. Sized to the bottom margin it sits inside the margin instead of + * taking content space, and the type is sized to the band rather than + * the other way round.

+ */ + private static void renderPageNumber(DocumentSession document) { + document.footer(DocumentHeaderFooter.builder() + .zone(DocumentHeaderFooterZone.FOOTER) + .centerText("Page {page} of {pages}") + .height((float) PAGE_NUMBER_BAND) + .fontSize((float) PAGE_NUMBER_SIZE) + .textColor(MUTED) + .showSeparator(false) + .build()); + } + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceLines.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceLines.java new file mode 100644 index 000000000..301593ccf --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceLines.java @@ -0,0 +1,200 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.dsl.PageFlowBuilder; +import com.demcha.compose.document.dsl.RowBuilder; +import com.demcha.compose.document.dsl.TableBuilder; +import com.demcha.compose.document.node.DocumentNode; +import com.demcha.compose.document.node.RowVerticalAlign; +import com.demcha.compose.document.node.TextAlign; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentRowColumn; +import com.demcha.compose.document.style.DocumentTextDecoration; +import com.demcha.compose.document.table.DocumentTableCell; +import com.demcha.compose.document.table.DocumentTableColumn; +import com.demcha.compose.document.templates.data.invoice.InvoiceServiceLines; + +import java.util.List; + +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.BODY_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CELL_PAD_L; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CELL_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.COLUMN_SHARES; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CONTENT_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.HEADER_CELL_STYLE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.HEAD_PAD_L; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.INK; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ITEM_CELL_STYLE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ITEM_SUB_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ITEM_TEXT_GAP; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ITEM_TILE_D; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ITEM_TITLE_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.MUTED; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TABLE_HEAD_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.blockGap; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.gap; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.px; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.style; + +/** + * The service lines. + * + *

One column, not five

+ * + *

The design's table has an outer box and a rule between every row and + * no interior verticals — which is exactly the rule topology a + * single-column table draws, because a cell strokes all four of its own edges + * and a one-column table has no interior vertical edge to draw. The five + * columns are a row inside each cell, laid out on shares of the table's width, + * so they stay aligned down the page without the engine drawing a line between + * them.

+ * + *

Reaching the same topology the other way — unstroked cells, separators as + * full-width rule rows, and the outer box from a stroked section wrapped round + * the table — is wrong on a document that paginates: a section's box fills its + * page fragment rather than hugging its rows, so every continuation page would + * end with an empty bordered strip below its last line, and on page one that + * strip's bottom edge lands on the page number.

+ */ +final class WorkspaceLines { + + private WorkspaceLines() { + } + + /** + * Draws the table. + * + * @param page the page flow + * @param serviceLines the columns and the lines + * @param currencyCode the ISO code the figures are stated in + */ + static void render(PageFlowBuilder page, InvoiceServiceLines serviceLines, + String currencyCode) { + page.addSection("LineItemsBox", box -> { + box.spacing(0) + .padding(DocumentInsets.zero()) + .margin(new DocumentInsets(blockGap(45, BODY_SIZE, 0), 0, px(27), 0)); + box.addTable(table -> { + table.name("LineItems") + .width(CONTENT_W) + .columns(DocumentTableColumn.fixed(CONTENT_W)); + renderHeader(table, serviceLines.columns(), currencyCode); + List lines = serviceLines.lines(); + for (int i = 0; i < lines.size(); i++) { + table.rowCells(DocumentTableCell + .node(renderLine(lines.get(i), i)) + .withStyle(ITEM_CELL_STYLE)); + } + }); + }); + } + + /** + * The header repeats on every page its table reaches. It is one cell like + * every other row, so its own stroke draws the table's top edge and the rule + * under the band — in the accent's border step, which is what the design + * tints the band's edges with. + */ + private static void renderHeader(TableBuilder table, InvoiceServiceLines.Columns columns, + String currencyCode) { + RowBuilder row = new RowBuilder(); + row.name("LineItemsHeader").spacing(0).columns(columnWidths()); + row.addParagraph(p -> p + .name("HeadDescription") + .text(columns.description()) + .textStyle(style(TABLE_HEAD_SIZE, ACCENT, DocumentTextDecoration.BOLD)) + .margin(new DocumentInsets(0, 0, 0, HEAD_PAD_L))); + headCell(row, "HeadPlan", columns.servicePeriod()); + headCell(row, "HeadQuantity", columns.quantity()); + // The currency is named once per money column rather than on every + // figure under it, which is where this design states it. + headCell(row, "HeadUnitPrice", + WorkspaceText.labelWithCurrency(columns.unitPrice(), currencyCode)); + headCell(row, "HeadAmount", + WorkspaceText.labelWithCurrency(columns.amount(), currencyCode)); + table.headerCells(DocumentTableCell.node(row.build()).withStyle(HEADER_CELL_STYLE)) + .repeatHeader(); + } + + private static void headCell(RowBuilder row, String name, String label) { + row.addParagraph(p -> p + .name(name) + .text(label) + .textStyle(style(TABLE_HEAD_SIZE, ACCENT, DocumentTextDecoration.BOLD)) + .align(TextAlign.CENTER)); + } + + /** The five columns, as a row inside the row's single cell. */ + private static DocumentNode renderLine(InvoiceServiceLines.Line line, int index) { + int n = index + 1; + RowBuilder row = new RowBuilder(); + row.name("Item" + n) + .spacing(0) + .verticalAlign(RowVerticalAlign.CENTER) + .columns(columnWidths()); + row.addSection("ItemDescription" + n, cell -> { + cell.spacing(0).padding(new DocumentInsets(0, 0, 0, CELL_PAD_L)); + // Mark and text are a horizontal pair inside a row cell, which the + // layout compiler refuses as a bare row. + WorkspaceWidgets.layeredRow(cell, "ItemBody" + n, body -> { + body.spacing(ITEM_TEXT_GAP) + .verticalAlign(RowVerticalAlign.CENTER) + .columns(DocumentRowColumn.fixed(ITEM_TILE_D), + DocumentRowColumn.weight(1)); + body.addSection("ItemGlyph" + n, glyph -> { + glyph.spacing(0); + if (!line.icon().isBlank()) { + glyph.add(WorkspaceWidgets.tile(line.icon())); + } + }); + body.addSection("ItemText" + n, text -> { + text.spacing(gap(25, ITEM_TITLE_SIZE)); + text.addParagraph(p -> p + .name("ItemTitle" + n) + .text(line.title()) + .textStyle(style(ITEM_TITLE_SIZE, INK, + DocumentTextDecoration.BOLD))); + if (!line.description().isBlank()) { + text.addParagraph(p -> p + .name("ItemSubtitle" + n) + .text(line.description()) + .textStyle(style(ITEM_SUB_SIZE, MUTED, + DocumentTextDecoration.DEFAULT))); + } + }); + }); + }); + valueCell(row, "ItemPlan" + n, line.servicePeriod()); + valueCell(row, "ItemQuantity" + n, + WorkspaceText.quantityWithUnit(line.quantity(), line.unit())); + valueCell(row, "ItemUnitPrice" + n, WorkspaceText.money(line.unitPrice())); + valueCell(row, "ItemAmount" + n, WorkspaceText.money(line.amount())); + return row.build(); + } + + private static void valueCell(RowBuilder row, String name, String value) { + row.addParagraph(p -> p + .name(name) + .text(value) + .textStyle(style(CELL_SIZE, MUTED, DocumentTextDecoration.DEFAULT)) + .align(TextAlign.CENTER)); + } + + /** + * The five column widths as shares of the table's own width. The last takes + * whatever the others leave: five independently rounded shares sum to the + * width plus a half-thousandth of a point, and the engine refuses a row + * narrower than its columns. + */ + private static DocumentRowColumn[] columnWidths() { + DocumentRowColumn[] columns = new DocumentRowColumn[COLUMN_SHARES.length]; + double assigned = 0; + for (int i = 0; i < COLUMN_SHARES.length - 1; i++) { + double width = CONTENT_W * COLUMN_SHARES[i]; + assigned += width; + columns[i] = DocumentRowColumn.fixed(width); + } + columns[COLUMN_SHARES.length - 1] = DocumentRowColumn.fixed(CONTENT_W - assigned); + return columns; + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceMasthead.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceMasthead.java new file mode 100644 index 000000000..e3364d569 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceMasthead.java @@ -0,0 +1,304 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.dsl.ImageBuilder; +import com.demcha.compose.document.dsl.PageFlowBuilder; +import com.demcha.compose.document.dsl.SectionBuilder; +import com.demcha.compose.document.node.RowVerticalAlign; +import com.demcha.compose.document.node.TextAlign; +import com.demcha.compose.document.style.DocumentBorders; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentRowColumn; +import com.demcha.compose.document.style.DocumentStroke; +import com.demcha.compose.document.style.DocumentTextDecoration; +import com.demcha.compose.document.templates.data.invoice.InvoiceBrand; +import com.demcha.compose.document.templates.data.invoice.InvoiceContactBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceMasthead; +import com.demcha.compose.document.templates.data.invoice.InvoiceRecipient; + +import java.util.ArrayList; +import java.util.List; + +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT_RULE_T; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT_RULE_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.BODY_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DISC_D; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DISC_GAP; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.HAIRLINE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.HALF; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.INK; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ISSUER_TAX_LABEL_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.LINE_BOX; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.LOCKUP_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.META_CELL_INSET; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.META_LABEL_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.META_LABEL_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.NAME_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.PARTY_TAX_LABEL_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.PARTY_TEXT_INDENT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.RULE_THIN; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.SECTION_LABEL_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TITLE_RIGHT_INSET; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TITLE_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TITLE_TOP_LIFT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.WORDMARK_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.blockGap; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.capOffset; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.gap; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.px; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.style; + +/** + * The header and the two addressed parties: the lockup beside the title, the + * accent bar under it, the issuer against the metadata grid, and the bill-to / + * ship-to split. + * + *

Both splits divide the content box in half: measured, their two vertical + * dividers land on the same x. Neither divider is a node — each is the right + * cell's left border, which is why it begins and ends with that cell's + * content rather than running the row's full height.

+ */ +final class WorkspaceMasthead { + + private WorkspaceMasthead() { + } + + /** + * Draws the header, the accent bar, the issuer/metadata row and the rule + * that closes it. + * + * @param page the page flow + * @param brand the lockup + * @param supplier who is invoicing + * @param masthead the title and the metadata rows + */ + static void renderHeader(PageFlowBuilder page, InvoiceBrand brand, + InvoiceContactBlock supplier, InvoiceMasthead masthead) { + renderLockupRow(page, brand, masthead); + renderAccentBar(page); + page.addRow("IssuerMetaRow", row -> { + row.spacing(0).weights(HALF, HALF); + row.addSection("IssuerAddress", cell -> renderIssuer(cell, supplier)); + row.addSection("InvoiceMeta", cell -> { + cell.spacing(0) + .borders(DocumentBorders.left(DocumentStroke.of(HAIRLINE, RULE_THIN))) + .padding(new DocumentInsets(0, 0, 0, META_CELL_INSET)); + renderMeta(cell, masthead.entries()); + }); + }); + WorkspaceWidgets.fullWidthRule(page, "PartiesRule", HAIRLINE, RULE_THIN, + blockGap(28.5, BODY_SIZE, 0), px(24)); + } + + /** + * TOP, not CENTER: the title's line box is taller than the lockup, so + * centring pushes the lockup down the row it is supposed to set the top edge + * of. + * + *

What fills the lockup column comes from the brand — a logo drawn to the + * design's measured width, or the brand's name set as a wordmark. The + * templates artifact carries no mark of its own.

+ */ + private static void renderLockupRow(PageFlowBuilder page, InvoiceBrand brand, + InvoiceMasthead masthead) { + page.addRow("Masthead", row -> { + row.spacing(0) + .verticalAlign(RowVerticalAlign.TOP) + .columns(DocumentRowColumn.fixed(LOCKUP_W), DocumentRowColumn.weight(1)); + row.addSection("BrandLockup", cell -> { + cell.spacing(0); + if (brand.logo() != null) { + cell.add(new ImageBuilder() + .name("BrandLogo") + .source(brand.logo()) + .width(LOCKUP_W) + .build()); + } else if (!brand.name().isBlank()) { + cell.addParagraph(p -> p + .name("BrandWordmark") + .text(brand.name()) + .textStyle(style(WORDMARK_SIZE, INK, DocumentTextDecoration.BOLD))); + } + }); + row.addSection("InvoiceTitle", cell -> cell + .spacing(0) + .padding(new DocumentInsets(-TITLE_TOP_LIFT, TITLE_RIGHT_INSET, 0, 0)) + .addParagraph(p -> p + .name("InvoiceTitleText") + .text(masthead.title()) + .textStyle(style(TITLE_SIZE, INK, DocumentTextDecoration.BOLD)) + .align(TextAlign.RIGHT))); + }); + } + + /** + * The bar is anchored to the content box's left edge, not to the mark above + * it, so its width derives from the page rather than from the asset. Stating + * its own position rather than a gap keeps the two facts separable when + * either changes. + */ + private static void renderAccentBar(PageFlowBuilder page) { + page.addLine(line -> line + .name("BrandAccentRule") + .horizontal(ACCENT_RULE_W) + .thickness(ACCENT_RULE_T) + .color(ACCENT) + .margin(new DocumentInsets( + px(89) - (LINE_BOX * TITLE_SIZE - TITLE_TOP_LIFT), + 0, + blockGap(19, 0, META_LABEL_SIZE), + 0))); + } + + private static void renderIssuer(SectionBuilder cell, InvoiceContactBlock supplier) { + // The two cells of the split do not share a top edge: the metadata block + // starts above the issuer name, and the divider starts with it. + cell.spacing(0).padding(new DocumentInsets(px(12), 0, 0, px(2))); + cell.addParagraph(p -> p + .name("IssuerName") + .text(supplier.legalName()) + .textStyle(style(NAME_SIZE, INK, DocumentTextDecoration.BOLD))); + cell.addSection("IssuerAddressLines", lines -> { + lines.spacing(gap(27.5, BODY_SIZE)) + .margin(new DocumentInsets(gap(38, NAME_SIZE), 0, 0, 0)); + WorkspaceWidgets.textLines(lines, "IssuerAddressLine", supplier.addressLines(), + BODY_SIZE, INK); + }); + renderLabelledRow(cell, "Issuer", supplier.taxRegistrationLabel(), + supplier.taxRegistrationNumber(), ISSUER_TAX_LABEL_W, gap(38, BODY_SIZE)); + } + + private static void renderMeta(SectionBuilder cell, List entries) { + cell.addSection("InvoiceMetaRows", rows -> { + rows.spacing(gap(36.2, BODY_SIZE)); + int index = 0; + for (InvoiceMasthead.Entry entry : entries) { + String name = "MetaRow" + (++index); + WorkspaceWidgets.layeredRow(rows, name, row -> { + row.spacing(0) + .columns(DocumentRowColumn.fixed(META_LABEL_W), + DocumentRowColumn.weight(1)); + row.addParagraph(p -> p + .name(name + "Label") + .text(entry.label()) + .textStyle(style(META_LABEL_SIZE, INK, + DocumentTextDecoration.DEFAULT))); + row.addParagraph(p -> p + .name(name + "Value") + .text(entry.value()) + .textStyle(style(BODY_SIZE, + entry.emphasized() ? ACCENT : INK, + entry.emphasized() + ? DocumentTextDecoration.BOLD + : DocumentTextDecoration.DEFAULT))); + }); + } + }); + } + + /** + * Draws the two addressed parties. + * + * @param page the page flow + * @param billTo who is billed + * @param shipTo where the work went, or a party with no name when absent + */ + static void renderParties(PageFlowBuilder page, InvoiceRecipient billTo, + InvoiceRecipient shipTo) { + List parties = new ArrayList<>(); + parties.add(billTo); + if (!shipTo.name().isBlank()) { + parties.add(shipTo); + } + List tokens = List.of(WorkspaceIcons.BILL_TO, WorkspaceIcons.SHIP_TO); + + page.addRow("PartiesRow", row -> { + row.spacing(0).weights(WorkspaceWidgets.evenWeights(parties.size())); + for (int i = 0; i < parties.size(); i++) { + InvoiceRecipient party = parties.get(i); + String token = tokens.get(Math.min(i, tokens.size() - 1)); + boolean first = i == 0; + row.addSection("Party" + (i + 1), cell -> { + cell.spacing(0); + if (!first) { + // The divider belongs to the split, so it is the cell's + // own left edge rather than a rule drawn between them. + cell.borders(DocumentBorders.left(DocumentStroke.of(HAIRLINE, RULE_THIN))) + .padding(new DocumentInsets(0, 0, 0, px(28))); + } + renderParty(cell, party, token); + }); + } + }); + } + + /** + * One method for both parties: they are the same component with different + * data, down to the registration only one of them usually prints. + */ + private static void renderParty(SectionBuilder cell, InvoiceRecipient party, String token) { + WorkspaceWidgets.layeredRow(cell, "PartyHead", row -> { + row.spacing(DISC_GAP) + .verticalAlign(RowVerticalAlign.TOP) + .columns(DocumentRowColumn.fixed(DISC_D), DocumentRowColumn.weight(1)); + row.addSection("PartyDisc", disc -> disc + .spacing(0) + .add(WorkspaceWidgets.disc(token))); + row.addParagraph(p -> p + .name("PartyLabel") + .text(party.heading()) + .textStyle(style(SECTION_LABEL_SIZE, ACCENT, DocumentTextDecoration.BOLD)) + .margin(new DocumentInsets(capOffset(8, SECTION_LABEL_SIZE), 0, 0, 0))); + }); + cell.addSection("PartyBody", block -> { + block.spacing(0).padding(new DocumentInsets(0, 0, 0, PARTY_TEXT_INDENT)); + block.addParagraph(p -> p + .name("PartyName") + .text(party.name()) + .textStyle(style(NAME_SIZE, INK, DocumentTextDecoration.BOLD)) + .margin(new DocumentInsets(px(2), 0, 0, 0))); + if (!party.subline().isBlank()) { + block.addParagraph(p -> p + .name("PartySubline") + .text(party.subline()) + .textStyle(style(BODY_SIZE, INK, DocumentTextDecoration.DEFAULT)) + .margin(new DocumentInsets(gap(30, NAME_SIZE), 0, 0, 0))); + } + block.addSection("PartyAddressLines", lines -> { + lines.spacing(gap(28, BODY_SIZE)) + .margin(new DocumentInsets( + gap(35, party.subline().isBlank() ? NAME_SIZE : BODY_SIZE), + 0, 0, 0)); + WorkspaceWidgets.textLines(lines, "PartyAddressLine", party.addressLines(), + BODY_SIZE, INK); + }); + renderLabelledRow(block, "Party", party.registrationLabel(), + party.registrationNumber(), PARTY_TAX_LABEL_W, gap(47, BODY_SIZE)); + }); + } + + /** + * A labelled fact under an address — a registration, printed as a label + * column beside its value. Drawn only when there is a value: a label on its + * own is a heading over an absence. + */ + private static void renderLabelledRow(SectionBuilder parent, String prefix, String label, + String value, double labelWidth, double gapAbove) { + if (value == null || value.isBlank()) { + return; + } + WorkspaceWidgets.layeredRow(parent, prefix + "TaxLine", row -> { + row.spacing(0) + .margin(new DocumentInsets(gapAbove, 0, 0, 0)) + .columns(DocumentRowColumn.fixed(labelWidth), DocumentRowColumn.weight(1)); + row.addParagraph(p -> p + .name(prefix + "TaxLabel") + .text(label) + .textStyle(style(BODY_SIZE, INK, DocumentTextDecoration.DEFAULT))); + row.addParagraph(p -> p + .name(prefix + "TaxValue") + .text(value) + .textStyle(style(BODY_SIZE, INK, DocumentTextDecoration.DEFAULT))); + }); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceSettlement.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceSettlement.java new file mode 100644 index 000000000..1e4a8ed77 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceSettlement.java @@ -0,0 +1,273 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.dsl.PageFlowBuilder; +import com.demcha.compose.document.dsl.SectionBuilder; +import com.demcha.compose.document.dsl.ShapeContainerBuilder; +import com.demcha.compose.document.node.HorizontalAlign; +import com.demcha.compose.document.node.RowVerticalAlign; +import com.demcha.compose.document.node.TextAlign; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentRowColumn; +import com.demcha.compose.document.style.DocumentStroke; +import com.demcha.compose.document.style.DocumentTextDecoration; +import com.demcha.compose.document.templates.data.invoice.InvoicePaymentBlock; +import com.demcha.compose.document.templates.data.invoice.InvoiceTotalsBlock; + +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT_BORDER; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT_SURFACE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.BODY; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CARD_ICON; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CARD_ICON_GAP; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CARD_INNER_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CARD_LABEL_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CARD_PAD; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CARD_RADIUS; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CARD_TEXT_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CARD_TITLE_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DUE_GLYPH; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DUE_LABEL_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DUE_PAD; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DUE_RADIUS; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DUE_TILE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DUE_TILE_GAP; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DUE_TILE_RADIUS; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DUE_VALUE_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.HAIRLINE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.HALF; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.INK; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.MUTED; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.NOTE_ICON; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.NOTE_ICON_COL; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.RULE_MED; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.RULE_THIN; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.SETTLEMENT_GUTTER; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.SETTLEMENT_LEFT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.SETTLEMENT_RIGHT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.SETTLEMENT_RIGHT_INSET; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.SURFACE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TOTALS_PAD_L; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TOTALS_PAD_R; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TOTALS_RULE_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TOTALS_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TOTAL_LABEL_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TOTAL_VALUE_SIZE; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.capOffset; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.gap; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.px; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.style; + +/** + * The settlement row: the payment card against the totals and the panel that + * closes them. + * + *

The split is not the half the two rows above it use — the left cell is + * narrower than the right, with a wide gutter between. That asymmetry is in the + * design.

+ */ +final class WorkspaceSettlement { + + private WorkspaceSettlement() { + } + + /** + * Draws the row. + * + * @param page the page flow + * @param payment the bank details, the note and the due notice + * @param totals the summed rows and the amount due + * @param currencyCode the ISO code the figures are stated in + */ + static void render(PageFlowBuilder page, InvoicePaymentBlock payment, + InvoiceTotalsBlock totals, String currencyCode) { + page.addRow("SettlementRow", row -> { + row.spacing(SETTLEMENT_GUTTER).weights(SETTLEMENT_LEFT, SETTLEMENT_RIGHT); + row.addSection("PaymentDetails", cell -> renderCard(cell, payment)); + row.addSection("Settlement", cell -> { + cell.spacing(0).padding(new DocumentInsets(0, SETTLEMENT_RIGHT_INSET, 0, 0)); + renderTotals(cell, totals, currencyCode); + renderDuePanel(cell, payment); + }); + }); + } + + /** + * An outlined rounded card. Built from a fill, a stroke, a radius and a + * padding rather than a panel helper, which takes one padding value where + * this card's insets are asymmetric. + */ + private static void renderCard(SectionBuilder cell, InvoicePaymentBlock payment) { + cell.spacing(0) + .fillColor(SURFACE) + .stroke(DocumentStroke.of(ACCENT_BORDER, RULE_MED)) + .cornerRadius(CARD_RADIUS) + .padding(CARD_PAD) + .keepTogether(); + + WorkspaceWidgets.layeredRow(cell, "CardHead", row -> { + row.spacing(CARD_ICON_GAP) + .verticalAlign(RowVerticalAlign.TOP) + .columns(DocumentRowColumn.fixed(CARD_ICON), DocumentRowColumn.weight(1)); + row.addSection("CardIcon", glyph -> glyph + .spacing(0) + .add(WorkspaceWidgets.glyph(WorkspaceIcons.BANK, CARD_ICON))); + row.addParagraph(p -> p + .name("CardLabel") + .text(payment.heading()) + .textStyle(style(CARD_TITLE_SIZE, ACCENT, DocumentTextDecoration.BOLD)) + .margin(new DocumentInsets(capOffset(10, CARD_TITLE_SIZE), 0, 0, 0))); + }); + + cell.addSection("CardFields", fields -> { + // The head row is as tall as its glyph, and the first field sits a + // measured distance below the head's top — not below the heading's + // own line box, which is shorter than the glyph. + fields.spacing(gap(22.4, CARD_TEXT_SIZE)) + .margin(new DocumentInsets(px(41 - 27 - 3), 0, 0, 0)); + int index = 0; + for (InvoicePaymentBlock.Field field : payment.fields()) { + String name = "CardField" + (++index); + WorkspaceWidgets.layeredRow(fields, name, row -> { + row.spacing(0) + .columns(DocumentRowColumn.fixed(CARD_LABEL_W), + DocumentRowColumn.weight(1)); + row.addParagraph(p -> p + .name(name + "Label") + .text(field.label()) + .textStyle(style(CARD_TEXT_SIZE, BODY, + DocumentTextDecoration.DEFAULT))); + row.addParagraph(p -> p + .name(name + "Value") + .text(field.value()) + .textStyle(style(CARD_TEXT_SIZE, BODY, + DocumentTextDecoration.DEFAULT))); + }); + } + }); + + if (payment.instruction().isBlank()) { + return; + } + cell.addLine(line -> line + .name("CardRule") + .horizontal(CARD_INNER_W) + .thickness(RULE_THIN) + .color(HAIRLINE) + .margin(new DocumentInsets(gap(23, CARD_TEXT_SIZE), 0, px(16), 0))); + + // Two cells rather than an inline glyph: the design's wrapped second + // line returns to the TEXT axis, not to the glyph's. + WorkspaceWidgets.layeredRow(cell, "CardNote", row -> { + row.spacing(0) + .columns(DocumentRowColumn.fixed(NOTE_ICON_COL), DocumentRowColumn.weight(1)); + row.addSection("CardNoteIcon", glyph -> glyph + .spacing(0) + .add(WorkspaceWidgets.glyph(WorkspaceIcons.INFO, NOTE_ICON, + HorizontalAlign.LEFT))); + row.addParagraph(p -> p + .name("CardNoteText") + .text(payment.instruction()) + .textStyle(style(CARD_TEXT_SIZE, MUTED, DocumentTextDecoration.DEFAULT)) + .lineSpacing(gap(22, CARD_TEXT_SIZE))); + }); + } + + private static void renderTotals(SectionBuilder cell, InvoiceTotalsBlock totals, + String currencyCode) { + cell.addSection("Totals", block -> { + block.spacing(gap(35, TOTALS_SIZE)) + .padding(new DocumentInsets(0, TOTALS_PAD_R, 0, TOTALS_PAD_L)) + .margin(new DocumentInsets(px(10.3), 0, 0, 0)) + .keepTogether(); + int index = 0; + for (InvoiceTotalsBlock.Row entry : totals.rows()) { + String name = "Total" + (++index); + WorkspaceWidgets.layeredRow(block, name, row -> { + row.spacing(0).weights(HALF, HALF); + row.addParagraph(p -> p + .name(name + "Label") + .text(entry.label()) + .textStyle(style(TOTALS_SIZE, INK, DocumentTextDecoration.DEFAULT))); + row.addParagraph(p -> p + .name(name + "Value") + .text(WorkspaceText.money(entry.amount())) + .textStyle(style(TOTALS_SIZE, INK, DocumentTextDecoration.DEFAULT)) + .align(TextAlign.RIGHT)); + }); + } + }); + + // Accent-coloured, not a grey hairline: a colour scan across it returns + // a clear violet hue. + cell.addLine(line -> line + .name("TotalsRule") + .horizontal(TOTALS_RULE_W) + .thickness(RULE_MED) + .color(ACCENT) + .margin(new DocumentInsets(gap(35, TOTALS_SIZE), 0, px(24.3), TOTALS_PAD_L))); + + cell.addSection("TotalDue", block -> { + block.spacing(0) + .padding(new DocumentInsets(0, TOTALS_PAD_R, 0, TOTALS_PAD_L)) + .keepTogether(); + WorkspaceWidgets.layeredRow(block, "TotalDueRow", row -> { + row.spacing(0).verticalAlign(RowVerticalAlign.CENTER).weights(HALF, HALF); + row.addParagraph(p -> p + .name("TotalDueLabel") + .text(totals.totalLabel()) + .textStyle(style(TOTAL_LABEL_SIZE, INK, DocumentTextDecoration.BOLD))); + row.addParagraph(p -> p + .name("TotalDueValue") + .text(WorkspaceText.coded(currencyCode, totals.totalAmount())) + .textStyle(style(TOTAL_VALUE_SIZE, ACCENT, DocumentTextDecoration.BOLD)) + .align(TextAlign.RIGHT)); + }); + }); + } + + /** + * The calendar tile has to be a shape: a bare glyph on the panel would lose + * the white square the design draws behind it, which is the only thing + * separating the glyph from the panel's tint. + */ + private static void renderDuePanel(SectionBuilder cell, InvoicePaymentBlock payment) { + if (payment.dueNotice().isBlank() && payment.dueNoticeEmphasis().isBlank()) { + return; + } + cell.addSection("PaymentDuePanel", panel -> { + panel.spacing(0) + .fillColor(ACCENT_SURFACE) + .stroke(DocumentStroke.of(ACCENT_BORDER, RULE_MED)) + .cornerRadius(DUE_RADIUS) + .padding(DUE_PAD) + .margin(new DocumentInsets(px(42.7), 0, 0, 0)) + .keepTogether(); + WorkspaceWidgets.layeredRow(panel, "PaymentDueRow", row -> { + row.spacing(DUE_TILE_GAP) + .verticalAlign(RowVerticalAlign.TOP) + .columns(DocumentRowColumn.fixed(DUE_TILE), DocumentRowColumn.weight(1)); + row.addSection("DueTile", tile -> tile + .spacing(0) + .add(new ShapeContainerBuilder() + .name("DueTileShape") + .roundedRect(DUE_TILE, DUE_TILE, DUE_TILE_RADIUS) + .fillColor(SURFACE) + .center(WorkspaceWidgets.glyph(WorkspaceIcons.CALENDAR, DUE_GLYPH)) + .build())); + row.addSection("DueText", text -> { + text.spacing(gap(23.6, DUE_LABEL_SIZE)) + .margin(new DocumentInsets(capOffset(5, DUE_LABEL_SIZE), 0, 0, 0)); + text.addParagraph(p -> p + .name("DueLabel") + .text(payment.dueNotice()) + .textStyle(style(DUE_LABEL_SIZE, INK, + DocumentTextDecoration.DEFAULT))); + text.addParagraph(p -> p + .name("DueValue") + .text(payment.dueNoticeEmphasis()) + .textStyle(style(DUE_VALUE_SIZE, INK, DocumentTextDecoration.BOLD))); + }); + }); + }); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceStyles.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceStyles.java new file mode 100644 index 000000000..e0ccf1fa5 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceStyles.java @@ -0,0 +1,344 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.api.DocumentPageSize; +import com.demcha.compose.document.style.DocumentColor; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentStroke; +import com.demcha.compose.document.style.DocumentTextDecoration; +import com.demcha.compose.document.style.DocumentTextStyle; +import com.demcha.compose.document.table.DocumentTableStyle; +import com.demcha.compose.document.table.DocumentTableTextAnchor; +import com.demcha.compose.font.FontName; + +import java.util.Map; + +/** + * Design tokens for {@link WorkspaceInvoice} — the palette, the type scale and + * the geometry every part of the sheet measures against. + * + *

The design was drawn at 1055 px across an A4 page, so {@link #PX} converts + * every length below from that raster to points.

+ * + *

Sizes carry two corrections, both measured

+ * + *

A cap measured on a screenshot includes about half a pixel of antialiasing + * on each edge and the whole of it lands in the size, so {@link #sizeForCap} + * takes it back off. And the body face sets uppercase about 6% wider than the + * design's face at the same cap height — measured across three all-caps runs, + * while mixed-case runs at the same sizes matched within 2% — so + * {@link #sizeForCaps} carries that as a size correction. There is no + * letter-spacing API to take it out with instead.

+ */ +final class WorkspaceStyles { + + private WorkspaceStyles() { + } + + static final DocumentPageSize PAGE = DocumentPageSize.A4; + static final double PAGE_WIDTH = PAGE.width(); + + /** The design's raster is 1055 px wide; every length below came off it. */ + static final double PX = PAGE_WIDTH / 1055.0; + + static final double MARGIN_T = px(46); + static final double MARGIN_R = px(47); + static final double MARGIN_L = px(45); + + /** + * Page one's bottom margin is the page-number band: whatever else is on the + * page, the band has to be reserved, or a paginated invoice runs its last + * line straight through the number. + */ + static final double MARGIN_B_FIRST = px(28); + static final double PAGE_NUMBER_BAND = px(28); + + /** + * How far the closing rule, the thank-you block and the brand band sit above + * the design's own positions. It buys the page number a band to sit in; + * without it there is nowhere on the page for one, because the design's + * closing block runs to within 15 px of the paper. + * + *

Distributed rather than taken in one place, and the distribution is not + * arbitrary: the closing rule sits 17 px under the payment card, so taking + * the whole lift off its top margin would pull it into the card's bottom + * border. Nine px come off the rule — leaving it 8 px clear of the card — + * and the rest out of the two gaps below it. The three shares are not + * independent: a gap inside the block moves everything below it as well, so + * the band's total lift is their sum.

+ */ + static final double CLOSING_LIFT = px(18); + static final double CLOSING_RULE_LIFT = px(9); + static final double CLOSING_INNER_LIFT = (CLOSING_LIFT - CLOSING_RULE_LIFT) / 2.0; + + /** + * A continuation page reserves more: its last row would otherwise end + * against the paper rather than against a margin. + */ + static final double MARGIN_B_LATER = px(58); + + static final DocumentInsets PAGE_MARGIN = + new DocumentInsets(MARGIN_T, MARGIN_R, MARGIN_B_FIRST, MARGIN_L); + static final DocumentInsets CONTINUATION_MARGIN = + new DocumentInsets(MARGIN_T, MARGIN_R, MARGIN_B_LATER, MARGIN_L); + + /** Every width in this preset is a fraction of this. */ + static final double CONTENT_W = PAGE_WIDTH - MARGIN_L - MARGIN_R; + + /** + * The issuer/metadata and bill-to/ship-to rows both split the content box in + * half: measured, both vertical dividers land on the same x. + */ + static final double HALF = 0.5; + + static final DocumentColor ACCENT = DocumentColor.rgb(85, 42, 164); + static final DocumentColor ACCENT_SURFACE = DocumentColor.rgb(245, 242, 253); + static final DocumentColor ACCENT_BORDER = DocumentColor.rgb(199, 184, 236); + static final DocumentColor INK = DocumentColor.rgb(15, 16, 20); + static final DocumentColor BODY = DocumentColor.rgb(45, 47, 53); + static final DocumentColor MUTED = DocumentColor.rgb(100, 102, 108); + static final DocumentColor HAIRLINE = DocumentColor.rgb(232, 234, 238); + static final DocumentColor HAIRLINE_STRONG = DocumentColor.rgb(214, 216, 221); + static final DocumentColor SURFACE = DocumentColor.WHITE; + static final DocumentColor TILE_BLUE = DocumentColor.rgb(45, 90, 242); + static final DocumentColor TILE_GREEN = DocumentColor.rgb(31, 122, 85); + + static final FontName FACE = FontName.LATO; + + /** The face's cap height in ems, read off the TTF. */ + private static final double FACE_CAP_RATIO = 0.7165; + + /** The antialiasing a cap measured on a screenshot carries on each edge. */ + private static final double CAP_INK_BLEED = 0.5; + + /** How far below its own box top a line of text sits. */ + static final double TEXT_TOP_BEARING = 0.235; + + /** + * {@code lineSpacing} is points added between lines over a line box + * of 1.2× the type size, so a measured pitch converts as + * {@code pitch - 1.2 * size}, never as a ratio. + */ + static final double LINE_BOX = 1.2; + + /** + * The one size not taken straight from its cap. At the size its 45 px cap + * implies the title's ink came back 2.9% narrower than the design's with the + * right edges aligned, so it is set 3% larger — which costs 1.4 px of cap + * height to buy back 7 px of width. + */ + static final double TITLE_SIZE = sizeForCap(45) * 1.03; + + /** + * 3% under the size its 15 px cap implies. The two names set at it straddle + * the design — one comes back 1.9% wide and the other 6.9% — so the + * correction halves the larger error rather than making one exact and the + * other worse. + */ + static final double NAME_SIZE = sizeForCap(15) * 0.97; + static final double BODY_SIZE = sizeForCap(12.5); + static final double META_LABEL_SIZE = sizeForCap(12); + + /** + * The party labels keep the uncorrected size: measured against the design + * they come back 5% narrow plain and 11% narrow with the caps correction, so + * they are the one all-caps run the correction does not help. + */ + static final double SECTION_LABEL_SIZE = sizeForCap(12.5); + static final double TABLE_HEAD_SIZE = sizeForCaps(11); + static final double ITEM_TITLE_SIZE = sizeForCap(13); + static final double ITEM_SUB_SIZE = sizeForCap(11); + static final double CELL_SIZE = sizeForCaps(12); + static final double TOTALS_SIZE = sizeForCap(12); + static final double TOTAL_LABEL_SIZE = sizeForCaps(15); + static final double TOTAL_VALUE_SIZE = sizeForCap(19); + static final double CARD_TITLE_SIZE = sizeForCaps(12); + static final double CARD_TEXT_SIZE = sizeForCap(11); + static final double DUE_LABEL_SIZE = sizeForCaps(12); + static final double DUE_VALUE_SIZE = sizeForCap(16); + static final double THANKS_TITLE_SIZE = sizeForCap(12); + static final double THANKS_BODY_SIZE = sizeForCap(10); + static final double FOOTER_SIZE = sizeForCap(11); + static final double WORDMARK_SIZE = sizeForCap(25); + static final double PAGE_NUMBER_SIZE = sizeForCap(8); + + static final double RULE_THIN = px(1.4); + static final double RULE_MED = px(1.6); + static final double ACCENT_RULE_W = px(41); + static final double ACCENT_RULE_T = px(4); + + /** + * The lockup's box, measured off the design's own ink. A caller's logo is + * sized by the width, which is the dimension the design fixes. + */ + static final double LOCKUP_W = px(212); + + /** The title's ink stops short of the content box, not on it. */ + static final double TITLE_RIGHT_INSET = px(13); + + /** + * The lockup sets the row's top edge, so the title's own line box hangs its + * caps below where the design draws them. Nothing else in the row can absorb + * that, so the title is lifted by it. + */ + static final double TITLE_TOP_LIFT = px(7.3); + + static final double DISC_D = px(42); + static final double DISC_GLYPH = px(20); + static final double DISC_GAP = px(18); + + /** The party block's text sits on the label's axis, indented past the disc. */ + static final double PARTY_TEXT_INDENT = DISC_D + DISC_GAP; + static final double ISSUER_TAX_LABEL_W = px(63); + static final double PARTY_TAX_LABEL_W = px(79); + + /** Metadata labels start at the cell's edge and values 180 px along it. */ + static final double META_LABEL_W = px(180); + static final double META_CELL_INSET = px(80); + + /** + * Column shares of the content width, derived from the header labels' + * measured centres rather than from boundaries the design never draws. + */ + static final double[] COLUMN_SHARES = {0.383178, 0.176532, 0.118380, 0.172378, 0.149533}; + + static final double HEAD_PAD_V = px(18.4); + static final double HEAD_PAD_L = px(67); + + /** + * Asymmetric, measured: the design's row content sits 19 px below its top + * rule and 16 px above the next. Symmetric padding centres it and leaves the + * text about 3 px low. + */ + static final double CELL_PAD_T = px(17.0); + static final double CELL_PAD_B = px(14.0); + static final double CELL_PAD_L = px(15); + static final double ITEM_TILE_D = px(33); + static final double ITEM_TILE_RADIUS = px(8); + static final double ITEM_GLYPH = px(19); + static final double ITEM_TEXT_GAP = px(19); + + /** + * Every rule in the table comes from one of these two styles. A cell strokes + * all four of its own edges, and a one-column table has no interior vertical + * edge — so the same stroke that draws the separator between two rows draws + * the table's left and right sides, and nothing else. + */ + static final DocumentTableStyle HEADER_CELL_STYLE = DocumentTableStyle.builder() + .fillColor(ACCENT_SURFACE) + .stroke(DocumentStroke.of(ACCENT_BORDER, RULE_THIN)) + .padding(new DocumentInsets(HEAD_PAD_V, 0, HEAD_PAD_V, 0)) + .textAnchor(DocumentTableTextAnchor.CENTER_LEFT) + .build(); + + static final DocumentTableStyle ITEM_CELL_STYLE = DocumentTableStyle.builder() + .stroke(DocumentStroke.of(HAIRLINE, RULE_THIN)) + .padding(new DocumentInsets(CELL_PAD_T, 0, CELL_PAD_B, 0)) + .textAnchor(DocumentTableTextAnchor.CENTER_LEFT) + .build(); + + /** + * The settlement row is NOT the half split the two rows above it use: its + * left cell is 420 design px, its right 433, with a 110 px gutter. That + * asymmetry is in the design, not in the measurement. + */ + static final double SETTLEMENT_LEFT = px(420); + static final double SETTLEMENT_GUTTER = px(110); + static final double SETTLEMENT_RIGHT = px(433); + static final double SETTLEMENT_RIGHT_INSET = px(29); + + static final double CARD_RADIUS = px(12); + static final DocumentInsets CARD_PAD = new DocumentInsets(px(17), px(24), px(22), px(24)); + static final double CARD_LABEL_W = px(162); + + /** The card's inner width — what its interior rule spans. */ + static final double CARD_INNER_W = SETTLEMENT_LEFT - px(24) - px(24); + static final double CARD_ICON = px(27); + static final double CARD_ICON_GAP = px(21); + static final double NOTE_ICON_COL = px(30); + static final double NOTE_ICON = px(20); + + static final double TOTALS_PAD_L = px(6); + static final double TOTALS_PAD_R = px(10); + static final double TOTALS_RULE_W = px(397); + + static final double DUE_RADIUS = px(12); + static final DocumentInsets DUE_PAD = new DocumentInsets(px(25), px(24), px(28), px(23)); + static final double DUE_TILE = px(38); + static final double DUE_TILE_RADIUS = px(9); + static final double DUE_GLYPH = px(22); + static final double DUE_TILE_GAP = px(24); + + static final double THANKS_INDENT = px(6); + static final double THANKS_ICON_COL = px(46); + static final double THANKS_ICON = px(30); + + static final double FOOTER_MARK_COL = px(144); + static final double FOOTER_LINK_COL = px(150); + + /** + * Which surface a line's glyph is knocked out of. A token with no colour + * here is drawn bare, which is how the design sets a mark that carries its + * own. + */ + static final Map TILE_COLOR = Map.of( + "search", ACCENT, + "grid", TILE_BLUE, + "shield", TILE_GREEN); + + static double px(double designPixels) { + return designPixels * PX; + } + + /** A size named by the cap height it reproduces, in design px. */ + static double sizeForCap(double capPx) { + return px(capPx - CAP_INK_BLEED) / FACE_CAP_RATIO; + } + + /** The same for an all-caps run, which the face sets 6% wide. */ + static double sizeForCaps(double capPx) { + return sizeForCap(capPx) * 0.94; + } + + /** + * Where to start a text box so its caps land {@code capPx} below the top of + * the block it shares a row with — a label beside a glyph, whose design + * position is its own baseline rather than the glyph's centre. + */ + static double capOffset(double capPx, double size) { + return Math.max(0, px(capPx) - TEXT_TOP_BEARING * size); + } + + /** What a text box hangs below its last cap: the rest of the line box. */ + static double bottomBearing(double size) { + return (LINE_BOX - TEXT_TOP_BEARING - FACE_CAP_RATIO) * size; + } + + /** + * A block gap read ink-to-ink on the design, turned into the margin the + * engine wants. Pass 0 for a neighbour that is not text — a rule, a disc, a + * table — which has no bearing to lose. + */ + static double blockGap(double inkGapPx, double sizeAbove, double sizeBelow) { + return Math.max(0, px(inkGapPx) + - (sizeAbove > 0 ? bottomBearing(sizeAbove) : 0) + - (sizeBelow > 0 ? TEXT_TOP_BEARING * sizeBelow : 0)); + } + + /** + * A measured top-to-top pitch turned into the gap the engine wants: the + * first box's own height comes off it, because spacing is between boxes. + */ + static double gap(double pitchPx, double sizeOfFirst) { + return Math.max(0, px(pitchPx) - LINE_BOX * sizeOfFirst); + } + + static DocumentTextStyle style(double size, DocumentColor color, + DocumentTextDecoration decoration) { + return DocumentTextStyle.builder() + .fontName(FACE) + .size(size) + .color(color) + .decoration(decoration) + .build(); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceText.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceText.java new file mode 100644 index 000000000..5111f41aa --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceText.java @@ -0,0 +1,98 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import java.math.BigDecimal; +import java.text.NumberFormat; +import java.util.Currency; +import java.util.Locale; + +/** + * How the Workspace sheet writes its figures. + * + *

The locale is stated, never inherited

+ * + *

Both the grouping of a number and the symbol for a currency code are + * locale-dependent — {@code USD} is {@code $} in English and {@code US$} in the + * root locale, {@code JPY} is {@code ¥} or {@code JP¥} — so a preset that let + * the JVM's default locale decide would render a different sheet on a different + * machine, and its baselines would move with the machine rather than with the + * design. Both helpers below pin {@link Locale#ENGLISH}.

+ */ +final class WorkspaceText { + + private WorkspaceText() { + } + + /** An amount, grouped and always to two places. */ + static String money(BigDecimal value) { + NumberFormat format = NumberFormat.getNumberInstance(Locale.ENGLISH); + format.setGroupingUsed(true); + format.setMinimumFractionDigits(2); + format.setMaximumFractionDigits(2); + return format.format(value); + } + + /** A quantity, written without trailing zeros a whole number does not need. */ + static String quantity(BigDecimal value) { + BigDecimal stripped = value.stripTrailingZeros(); + return stripped.scale() <= 0 ? stripped.toBigInteger().toString() : stripped.toPlainString(); + } + + /** + * The symbol for an ISO currency code, or the code itself when there is no + * symbol for it and the empty string when a document states no currency. + * + * @param currencyCode the ISO code the figures are stated in + * @return what to print before an amount + */ + static String symbol(String currencyCode) { + if (currencyCode == null || currencyCode.isBlank()) { + return ""; + } + try { + return Currency.getInstance(currencyCode.trim()).getSymbol(Locale.ENGLISH); + } catch (IllegalArgumentException notACurrency) { + return currencyCode.trim(); + } + } + + /** + * An amount named by its currency code rather than its symbol — this design + * writes {@code USD 587.50} on the one figure it names at all. + * + * @param currencyCode the ISO code the figures are stated in + * @param value the amount + * @return the amount behind its code, or bare when no currency is stated + */ + static String coded(String currencyCode, BigDecimal value) { + return currencyCode == null || currencyCode.isBlank() + ? money(value) + : currencyCode.trim() + " " + money(value); + } + + /** + * A column label with the currency named after it, which is where this + * design states it for the figures under it. + * + * @param label the column's own words + * @param currencyCode the ISO code the figures are stated in + * @return the label, with the code in brackets when there is one + */ + static String labelWithCurrency(String label, String currencyCode) { + return currencyCode == null || currencyCode.isBlank() + ? label + : label + " (" + currencyCode.trim() + ")"; + } + + /** + * A quantity and what it counts, as the design writes them: one run, so the + * column stays centred on the pair rather than on the number. + * + * @param value the quantity + * @param unit what it counts; blank when the number stands alone + * @return the written quantity + */ + static String quantityWithUnit(BigDecimal value, String unit) { + String written = quantity(value); + return unit == null || unit.isBlank() ? written : written + " " + unit; + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceWidgets.java b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceWidgets.java new file mode 100644 index 000000000..7bb318b4b --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/invoice/presets/WorkspaceWidgets.java @@ -0,0 +1,158 @@ +package com.demcha.compose.document.templates.invoice.presets; + +import com.demcha.compose.document.dsl.PageFlowBuilder; +import com.demcha.compose.document.dsl.RowBuilder; +import com.demcha.compose.document.dsl.SectionBuilder; +import com.demcha.compose.document.dsl.ShapeContainerBuilder; +import com.demcha.compose.document.node.DocumentNode; +import com.demcha.compose.document.node.HorizontalAlign; +import com.demcha.compose.document.node.LayerAlign; +import com.demcha.compose.document.style.DocumentColor; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentTextDecoration; + +import java.util.List; +import java.util.function.Consumer; + +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ACCENT; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.CONTENT_W; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DISC_D; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.DISC_GLYPH; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ITEM_GLYPH; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ITEM_TILE_D; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.ITEM_TILE_RADIUS; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.TILE_COLOR; +import static com.demcha.compose.document.templates.invoice.presets.WorkspaceStyles.style; + +/** + * The pieces more than one part of the Workspace sheet draws: the wrapper every + * horizontal pair inside a cell goes through, the disc and the tile that own + * their glyphs, and the full-width rules that separate the closing blocks. + */ +final class WorkspaceWidgets { + + private WorkspaceWidgets() { + } + + /** + * A row that survives inside a row cell. + * + *

A row nested directly in a row cell is refused by the layout compiler. + * Every horizontal pair that lives inside a cell in this preset goes through + * here, wrapped in a single layer of a stack.

+ * + * @param parent the section to add the row to + * @param name the node name, for review and rollback + * @param spec describes the row + */ + static void layeredRow(SectionBuilder parent, String name, Consumer spec) { + SectionBuilder holder = new SectionBuilder(); + holder.name(name + "Holder"); + holder.addRow(name, spec); + DocumentNode node = holder.build(); + parent.addLayerStack(stack -> stack + .name(name + "Layer") + .layer(node, LayerAlign.TOP_LEFT, 0)); + } + + /** + * A filled disc that owns its glyph: the glyph is knocked out of the accent + * fill, so it is a child of the shape rather than a coloured circle with an + * icon dropped near it. + * + * @param token the packaged mark + * @return the disc node + */ + static DocumentNode disc(String token) { + return new ShapeContainerBuilder() + .name("Disc" + token) + .circle(DISC_D) + .fillColor(ACCENT) + .center(glyph(token, DISC_GLYPH)) + .build(); + } + + /** + * A line's mark on its coloured tile, or bare when the design gives that + * token no tile. + * + * @param token the packaged mark + * @return the tile node + */ + static DocumentNode tile(String token) { + DocumentColor fill = TILE_COLOR.get(token); + if (fill == null) { + return glyph(token, ITEM_TILE_D); + } + return new ShapeContainerBuilder() + .name("ItemTile" + token) + .roundedRect(ITEM_TILE_D, ITEM_TILE_D, ITEM_TILE_RADIUS) + .fillColor(fill) + .center(glyph(token, ITEM_GLYPH)) + .build(); + } + + /** A glyph centred in a box of its own, so a shape can own it. */ + static DocumentNode glyph(String token, double size) { + return glyph(token, size, HorizontalAlign.CENTER); + } + + /** + * The same, aligned. A glyph that leads a text row is left-aligned: its + * column's width is the distance to the text, not a box for the glyph to sit + * in the middle of. + * + * @param token the packaged mark + * @param size the glyph's box + * @param align where the glyph sits in it + * @return the glyph node + */ + static DocumentNode glyph(String token, double size, HorizontalAlign align) { + return new SectionBuilder() + .name("Glyph" + token) + .spacing(0) + .addSvgIcon(WorkspaceIcons.icon(token), size, align) + .build(); + } + + /** One method for all three full-width hairlines; the page uses two weights. */ + static void fullWidthRule(PageFlowBuilder page, String name, DocumentColor color, + double thickness, double gapAbove, double gapBelow) { + page.addLine(line -> line + .name(name) + .horizontal(CONTENT_W) + .thickness(thickness) + .color(color) + .margin(new DocumentInsets(gapAbove, 0, gapBelow, 0))); + } + + /** + * A block of plain lines, one paragraph each. + * + * @param block the section to fill + * @param prefix the node-name prefix, numbered from one + * @param lines the lines + * @param size their type size + * @param color their colour + */ + static void textLines(SectionBuilder block, String prefix, List lines, + double size, DocumentColor color) { + int index = 0; + for (String line : lines) { + String name = prefix + (++index); + block.addParagraph(p -> p + .name(name) + .text(line) + .textStyle(style(size, color, DocumentTextDecoration.DEFAULT))); + } + } + + /** Even weights for a row of {@code count} cells. */ + static double[] evenWeights(int count) { + double[] weights = new double[count]; + for (int i = 0; i < count; i++) { + weights[i] = 1.0 / count; + } + return weights; + } +} diff --git a/templates/src/main/resources/templates/invoice/workspace/icons/bank.svg b/templates/src/main/resources/templates/invoice/workspace/icons/bank.svg new file mode 100644 index 000000000..fbbc8fae9 --- /dev/null +++ b/templates/src/main/resources/templates/invoice/workspace/icons/bank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/invoice/workspace/icons/bill-to.svg b/templates/src/main/resources/templates/invoice/workspace/icons/bill-to.svg new file mode 100644 index 000000000..a91fe98cf --- /dev/null +++ b/templates/src/main/resources/templates/invoice/workspace/icons/bill-to.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/invoice/workspace/icons/calendar.svg b/templates/src/main/resources/templates/invoice/workspace/icons/calendar.svg new file mode 100644 index 000000000..3233ebbb5 --- /dev/null +++ b/templates/src/main/resources/templates/invoice/workspace/icons/calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/invoice/workspace/icons/grid.svg b/templates/src/main/resources/templates/invoice/workspace/icons/grid.svg new file mode 100644 index 000000000..1e92b92da --- /dev/null +++ b/templates/src/main/resources/templates/invoice/workspace/icons/grid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/invoice/workspace/icons/info.svg b/templates/src/main/resources/templates/invoice/workspace/icons/info.svg new file mode 100644 index 000000000..b88a167fa --- /dev/null +++ b/templates/src/main/resources/templates/invoice/workspace/icons/info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/invoice/workspace/icons/search.svg b/templates/src/main/resources/templates/invoice/workspace/icons/search.svg new file mode 100644 index 000000000..d685eadd9 --- /dev/null +++ b/templates/src/main/resources/templates/invoice/workspace/icons/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/invoice/workspace/icons/shield.svg b/templates/src/main/resources/templates/invoice/workspace/icons/shield.svg new file mode 100644 index 000000000..878df61a1 --- /dev/null +++ b/templates/src/main/resources/templates/invoice/workspace/icons/shield.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/invoice/workspace/icons/ship-to.svg b/templates/src/main/resources/templates/invoice/workspace/icons/ship-to.svg new file mode 100644 index 000000000..924aa3b48 --- /dev/null +++ b/templates/src/main/resources/templates/invoice/workspace/icons/ship-to.svg @@ -0,0 +1 @@ + \ No newline at end of file