¿Alguien Quiere una Presentación PowerPoint?

La Pregunta

“Soy gerente de desarrollo. Necesito tener una sesión de capacitación de 1 hora para mostrar a mi grupo el caso de negocio y los detalles técnicos de un mensaje RemittanceAdvice. Debe introducirlos al mensaje como si nunca hubieran escuchado de él. Debe mostrar detalles técnicos sobre la implementación del mensaje, validación y la jerarquía. ¿Puede crear una presentación PowerPoint para ayudar a capacitarlos?”

No una página wiki. No un README. Una presentación PowerPoint — lista para presentar, con notas del presentador, estructurada para una sesión de una hora con un equipo de desarrollo que nunca ha tocado ISO 20022.


Paso 1 — El Servidor MCP Lee la Especificación Completa

La IA consulta el Servidor ISO 20022 MCP de Beneficial Strategies y recupera todo sobre remt.001.001.06 — RemittanceAdviceV06:

Sin abrir PDFs. Sin navegar manualmente por el sitio de especificaciones.


Paso 2 — Dos Preguntas de Aclaración

“1. ¿Debe la presentación asumir que la audiencia conoce XML y C#, pero no ISO 20022 específicamente?”

“2. ¿Debe incluir una diapositiva de recorrido de código en vivo, o mantener la implementación a nivel conceptual?”

Respuestas: Sí — desarrolladores que conocen XML y C# pero son nuevos en ISO 20022. Y sí, incluir un recorrido de código: esta es una capacitación para desarrolladores, no una presentación ejecutiva.


Paso 3 — Todo Se Genera Automáticamente

Estructura de la Presentación (12 Diapositivas, ~5 min cada una)

Diapositiva Título Propósito
1 ¿Qué Es una Remesa? Gancho de negocio — el problema que resuelve
2 Dónde Encaja RemittanceAdvice Mapa del área de negocio ISO 20022
3 El Caso de Negocio Por qué le importa a su equipo de Cuentas por Cobrar
4 Identidad del Mensaje remt.001.001.06, espacio de nombres, XSD
5 Jerarquía del Mensaje Diagrama de bloques de construcción
6 Análisis Detallado de GroupHeader Campos requeridos, roles de las partes
7 RemittanceInformation — No Estructurado Cuándo y por qué usar texto libre
8 RemittanceInformation — Estructurado Referencias de facturas, montos, impuestos, embargos
9 Reglas de Validación Esquema vs. reglas de negocio
10 Implementación en C# Contenedores de datos y serialización
11 Errores Comunes Problemas reales de la especificación
12 Preguntas y Respuestas / Próximos Pasos Qué construir a continuación

Jerarquía del Mensaje (Diagrama de Diapositiva 5)

classDiagram
    direction TB
    class RemittanceAdviceV06{
        MessageId remt001001006
    }
    RemittanceAdviceV06 *-- "1..1" GroupHeader122 : GroupHeader
    RemittanceAdviceV06 *-- "1..*" RemittanceInformation23 : RemittanceInformation
    RemittanceAdviceV06 *-- "0..*" SupplementaryData1 : SupplementaryData

    class GroupHeader122{
        MessageIdentification Max35Text
        CreationDateTime ISODateTime
    }
    GroupHeader122 *-- "1..1" PartyIdentification272 : InitiatingParty
    GroupHeader122 *-- "0..1" PartyIdentification272 : MessageRecipient

    class RemittanceInformation23{
        RemittanceIdentification Max35Text
        Unstructured Max140Text
    }
    RemittanceInformation23 *-- "0..*" StructuredRemittanceInformation18 : Structured
    RemittanceInformation23 *-- "1..1" OriginalPaymentInformation10 : OriginalPaymentInformation

    class StructuredRemittanceInformation18{
        AdditionalRemittanceInformation Max140Text
    }
    StructuredRemittanceInformation18 *-- "0..*" ReferredDocumentInformation8 : ReferredDocumentInformation
    StructuredRemittanceInformation18 *-- "0..1" RemittanceAmount4 : ReferredDocumentAmount
    StructuredRemittanceInformation18 *-- "0..1" CreditorReferenceInformation3 : CreditorReferenceInformation
    StructuredRemittanceInformation18 *-- "0..1" PartyIdentification272 : Invoicer
    StructuredRemittanceInformation18 *-- "0..1" PartyIdentification272 : Invoicee
    StructuredRemittanceInformation18 *-- "0..1" TaxData1 : TaxRemittance
    StructuredRemittanceInformation18 *-- "0..1" Garnishment4 : GarnishmentRemittance
  

XML de Muestra (Diapositiva 8 — Remesa Estructurada)

Un mensaje remt.001.001.06 completo pagando dos facturas con un solo pago:

<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:remt.001.001.06">
  <RmtAdvc>

    <!-- Slide 6: GroupHeader — who sent it and when -->
    <GrpHdr>
      <MsgId>REMT-2026-00099</MsgId>
      <CreDtTm>2026-03-17T09:00:00</CreDtTm>
      <InitgPty>
        <Nm>Beneficial Strategies LLC</Nm>
        <Id><OrgId><AnyBIC>BSTRUSXX</AnyBIC></OrgId></Id>
      </InitgPty>
      <MsgRcpt>
        <Nm>Acme Corp</Nm>
        <Id><OrgId><AnyBIC>ACMEUSNY</AnyBIC></OrgId></Id>
      </MsgRcpt>
    </GrpHdr>

    <!-- Slide 8: RemittanceInformation — what this payment covers -->
    <RmtInf>
      <RmtId>RMTINF-001</RmtId>

      <!-- Unstructured: human-readable note -->
      <Ustrd>Payment for invoices INV-2026-042 and INV-2026-043</Ustrd>

      <!-- Structured: machine-readable invoice references -->
      <Strd>
        <RfrdDocInf>
          <Tp><CdOrPrtry><Cd>CINV</Cd></CdOrPrtry></Tp>
          <Nb>INV-2026-042</Nb>
          <RltdDt><Dt>2026-03-01</Dt></RltdDt>
        </RfrdDocInf>
        <RfrdDocAmt>
          <RmtAmtAndTp>
            <Tp><CdOrPrtry><Cd>CINV</Cd></CdOrPrtry></Tp>
            <Amt Ccy="USD">2500.00</Amt>
          </RmtAmtAndTp>
        </RfrdDocAmt>
        <Invcr>
          <Nm>Beneficial Strategies LLC</Nm>
        </Invcr>
        <Invcee>
          <Nm>Acme Corp</Nm>
        </Invcee>
        <AddtlRmtInf>Consulting services Q1 2026</AddtlRmtInf>
      </Strd>

      <Strd>
        <RfrdDocInf>
          <Tp><CdOrPrtry><Cd>CINV</Cd></CdOrPrtry></Tp>
          <Nb>INV-2026-043</Nb>
          <RltdDt><Dt>2026-03-10</Dt></RltdDt>
        </RfrdDocInf>
        <RfrdDocAmt>
          <RmtAmtAndTp>
            <Tp><CdOrPrtry><Cd>CINV</Cd></CdOrPrtry></Tp>
            <Amt Ccy="USD">2250.00</Amt>
          </RmtAmtAndTp>
        </RfrdDocAmt>
        <AddtlRmtInf>Software license renewal</AddtlRmtInf>
      </Strd>

      <!-- Links back to the original payment instruction -->
      <OrgnlPmtInf>
        <OrgnlMsgId>PAIN001-2026-00077</OrgnlMsgId>
        <OrgnlMsgNmId>pain.001.001.12</OrgnlMsgNmId>
        <OrgnlCreDtTm>2026-03-17T08:55:00</OrgnlCreDtTm>
      </OrgnlPmtInf>
    </RmtInf>

  </RmtAdvc>
</Document>

Implementación en C# (Diapositiva 10)

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace Iso20022.Remt.V06
{
    // Root document — namespace ties it to remt.001.001.06
    [XmlRoot("Document", Namespace = "urn:iso:std:iso:20022:tech:xsd:remt.001.001.06")]
    public class Document
    {
        [XmlElement("RmtAdvc")]
        public RemittanceAdviceV06 RemittanceAdvice { get; set; }
    }

    // Top-level message
    public class RemittanceAdviceV06
    {
        [XmlElement("GrpHdr")]
        public GroupHeader122 GroupHeader { get; set; }

        [XmlElement("RmtInf")]
        public List<RemittanceInformation23> RemittanceInformation { get; set; } = new();
    }

    // GroupHeader: who sent it, when, routing
    public class GroupHeader122
    {
        [XmlElement("MsgId")]
        public string MessageIdentification { get; set; }   // Required, Max35Text

        [XmlElement("CreDtTm")]
        public DateTime CreationDateTime { get; set; }       // Required, ISODateTime

        [XmlElement("InitgPty")]
        public PartyIdentification272 InitiatingParty { get; set; } // Required

        [XmlElement("MsgRcpt")]
        public PartyIdentification272 MessageRecipient { get; set; } // Optional
    }

    // RemittanceInformation: one block per payment being explained
    public class RemittanceInformation23
    {
        [XmlElement("RmtId")]
        public string RemittanceIdentification { get; set; }  // Optional, Max35Text

        // Free-text description — quick and simple, but not machine-readable
        [XmlElement("Ustrd")]
        public List<string> Unstructured { get; set; } = new();

        // Structured invoice references — preferred for A/R automation
        [XmlElement("Strd")]
        public List<StructuredRemittanceInformation18> Structured { get; set; } = new();

        [XmlElement("OrgnlPmtInf")]
        public OriginalPaymentInformation10 OriginalPaymentInformation { get; set; } // Required
    }

    // Structured remittance: links payment to specific invoices
    public class StructuredRemittanceInformation18
    {
        [XmlElement("RfrdDocInf")]
        public List<ReferredDocumentInformation8> ReferredDocumentInformation { get; set; } = new();

        [XmlElement("RfrdDocAmt")]
        public RemittanceAmount4 ReferredDocumentAmount { get; set; }

        [XmlElement("CdtrRefInf")]
        public CreditorReferenceInformation3 CreditorReferenceInformation { get; set; }

        [XmlElement("Invcr")]
        public PartyIdentification272 Invoicer { get; set; }  // Who issued the invoice

        [XmlElement("Invcee")]
        public PartyIdentification272 Invoicee { get; set; }  // Who received the invoice

        [XmlElement("TaxRmt")]
        public TaxData1 TaxRemittance { get; set; }

        [XmlElement("GrnshmtRmt")]
        public Garnishment4 GarnishmentRemittance { get; set; }

        // Up to 3 additional free-text notes (Max 3 per spec)
        [XmlElement("AddtlRmtInf")]
        public List<string> AdditionalRemittanceInformation { get; set; } = new();
    }

    // ReferredDocumentInformation: identifies the invoice being paid
    public class ReferredDocumentInformation8
    {
        [XmlElement("Tp")]
        public ReferredDocumentType4 Type { get; set; }  // e.g. CINV = Commercial Invoice

        [XmlElement("Nb")]
        public string Number { get; set; }               // Invoice number, Max35Text

        [XmlElement("RltdDt")]
        public DateAndType1 RelatedDate { get; set; }    // Invoice date
    }

    // RemittanceAmount4: amounts being paid for this document
    public class RemittanceAmount4
    {
        [XmlElement("RmtAmtAndTp")]
        public List<DocumentAmount1> RemittanceAmountAndType { get; set; } = new();

        [XmlElement("AdjstmntAmtAndRsn")]
        public List<DocumentAdjustment1> AdjustmentAmountAndReason { get; set; } = new();
    }

    // Supporting types
    public class PartyIdentification272
    {
        [XmlElement("Nm")]
        public string Name { get; set; }

        [XmlElement("Id")]
        public Party38Choice Id { get; set; }
    }

    public class OriginalPaymentInformation10
    {
        [XmlElement("OrgnlMsgId")]
        public string OriginalMessageIdentification { get; set; }

        [XmlElement("OrgnlMsgNmId")]
        public string OriginalMessageNameIdentification { get; set; }

        [XmlElement("OrgnlCreDtTm")]
        public DateTime? OriginalCreationDateTime { get; set; }
    }
}

Generación de PowerPoint en C# (Diapositiva 10 continuación)

La presentación en sí se genera programáticamente usando el SDK de OpenXML — no se requiere PowerPoint instalado:

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using A = DocumentFormat.OpenXml.Drawing;

namespace Iso20022.Training
{
    public class RemittanceTrainingDeckGenerator
    {
        private static readonly string[] SlideData = new[]
        {
            ("What Is a Remittance?",
             "A remittance is the structured explanation of WHY a payment is being made.\n\n" +
             "Without it: payer sends $4,750. Payee has 12 open invoices. Which ones are paid?\n\n" +
             "With remt.001: payer says exactly which invoices are covered, the amounts, and the references.\n\n" +
             "Speaker note: Ask the room — has anyone had to manually match a payment to invoices? That's the problem this solves."),

            ("Where RemittanceAdvice Fits",
             "ISO 20022 Business Area: REMT (Remittance)\n\n" +
             "Message ID: remt.001.001.06\n" +
             "Namespace: urn:iso:std:iso:20022:tech:xsd:remt.001.001.06\n\n" +
             "Sent separately from the payment itself (pain.001) or alongside it.\n" +
             "The payment moves money. The remittance explains it.\n\n" +
             "Speaker note: Show the XSD at iso20022.org — this is the contract both sides implement."),

            ("The Business Case",
             "Accounts Receivable teams spend hours matching payments to invoices manually.\n\n" +
             "remt.001 makes this automatic:\n" +
             "  • Machine-readable invoice references\n" +
             "  • Exact amounts per invoice\n" +
             "  • Tax and adjustment details\n" +
             "  • Creditor reference for cross-system lookup\n\n" +
             "ROI: reduces payment-to-close time from days to minutes.\n\n" +
             "Speaker note: If your client runs SAP or Oracle Financials, they already expect this format."),

            ("Message Identity",
             "Full message ID: remt.001.001.06\n" +
             "  remt  = business area (Remittance)\n" +
             "  001   = message functionality\n" +
             "  001   = flavour\n" +
             "  06    = version 6\n\n" +
             "XSD schema: https://www.iso20022.org/sites/default/files/documents/messages/remt/schemas/remt.001.001.06.xsd\n\n" +
             "Always validate your output against this schema before transmission.\n\n" +
             "Speaker note: Version 06 is current. Never build against v01 — the spec has evolved significantly."),

            ("Message Hierarchy",
             "RemittanceAdviceV06\n" +
             "  ├── GroupHeader (1..1)           — message envelope, sender/receiver\n" +
             "  │     ├── MessageIdentification   — unique message ID (required)\n" +
             "  │     ├── CreationDateTime        — timestamp (required)\n" +
             "  │     ├── InitiatingParty         — who sent it (required)\n" +
             "  │     └── MessageRecipient        — who receives it (optional)\n" +
             "  ├── RemittanceInformation (1..*) — one block per payment explained\n" +
             "  │     ├── Unstructured            — free text (0..*)\n" +
             "  │     ├── Structured              — invoice references (0..*)\n" +
             "  │     └── OriginalPaymentInfo     — links back to pain.001 (required)\n" +
             "  └── SupplementaryData (0.*)      — extensibility hook\n\n" +
             "Speaker note: The 1..* on RemittanceInformation means one message can explain multiple payments at once."),

            ("GroupHeader Deep Dive",
             "Required fields — your message is rejected without these:\n\n" +
             "  MsgId       Max35Text    Point-to-point unique reference\n" +
             "  CreDtTm     ISODateTime  Format: 2026-03-17T09:00:00\n" +
             "  InitgPty    Party        Sender identity (Name + BIC or IBAN)\n\n" +
             "Optional but important:\n" +
             "  MsgRcpt     Party        Intended recipient\n" +
             "  FwdgAgt     Institution  If routing through an intermediary\n" +
             "  CpyInd      Code         CODU/DUPL/COPY — mark duplicates!\n\n" +
             "Speaker note: MsgId must be unique per sender. Use a UUID or timestamp-based ID. Duplicates cause reconciliation chaos."),

            ("Unstructured Remittance",
             "Use <Ustrd> when:\n" +
             "  • Quick integration, human-readable only\n" +
             "  • Legacy receiver systems that parse free text\n" +
             "  • Supplementary notes alongside structured data\n\n" +
             "Example:\n" +
             "  <Ustrd>Payment for INV-2026-042 and INV-2026-043</Ustrd>\n\n" +
             "Limitations:\n" +
             "  • Not machine-readable — A/R still has to parse it manually\n" +
             "  • Max 140 characters\n" +
             "  • Cannot reference amounts, dates, or adjustment reasons\n\n" +
             "Speaker note: Think of Unstructured like the memo field on a cheque. Fine for humans; useless for automation."),

            ("Structured Remittance",
             "Use <Strd> for full A/R automation. Key elements:\n\n" +
             "  RfrdDocInf   Invoice number, type code, invoice date\n" +
             "  RfrdDocAmt   Amount paid, type (CINV/CREN/DUPA/REMI), adjustments\n" +
             "  CdtrRefInf   Creditor's own reference number\n" +
             "  Invcr        Who issued the invoice\n" +
             "  Invcee       Who received the invoice\n" +
             "  TaxRmt       Tax remittance details\n" +
             "  GrnshmtRmt   Garnishment details (payroll scenarios)\n" +
             "  AddtlRmtInf  Up to 3 free-text notes (Max140Text each)\n\n" +
             "Constraint: If Type/Code is CREN, DUPA, or REMI — RmtAmtAndTp must not repeat.\n\n" +
             "Speaker note: The constraint on CREN/DUPA/REMI is enforced by the XSD. Your serializer must know this or schema validation fails."),

            ("Validation Rules",
             "Two layers — both must pass:\n\n" +
             "LAYER 1 — Schema Validation (XSD)\n" +
             "  • Required fields present\n" +
             "  • Types correct (date as YYYY-MM-DD, not 'March 17')\n" +
             "  • Max lengths respected (Max35Text = 35 chars)\n" +
             "  • Enum values valid (CINV, CREN, DUPA, REMI only)\n" +
             "  • Namespace exact match\n\n" +
             "LAYER 2 — Business Rules\n" +
             "  • MsgId unique per sender\n" +
             "  • CREN/DUPA/REMI: RmtAmtAndTp must not repeat\n" +
             "  • AddtlRmtInf: maximum 3 occurrences\n" +
             "  • OriginalPaymentInformation must reference a real prior message\n\n" +
             "Speaker note: Schema failures are caught before processing. Business rule failures may only surface at the receiver's A/R system — often days later."),

            ("C# Implementation",
             "Key points for your implementation:\n\n" +
             "1. Use [XmlRoot] with the exact namespace on Document class\n" +
             "   Namespace = \"urn:iso:std:iso:20022:tech:xsd:remt.001.001.06\"\n\n" +
             "2. List<string> for Unstructured — it's 0..* in the spec\n\n" +
             "3. List<string> for AddtlRmtInf — but enforce max 3 in your builder\n\n" +
             "4. Always serialize then validate against XSD before sending:\n" +
             "   var schemas = new XmlSchemaSet();\n" +
             "   schemas.Add(null, \"remt.001.001.06.xsd\");\n" +
             "   // ValidationEventHandler catches schema errors\n\n" +
             "5. OriginalPaymentInformation is REQUIRED (1..1) — cannot be omitted\n\n" +
             "Speaker note: Step 4 is non-negotiable. Transmitting an invalid message wastes network round-trips and may trigger sanctions from the receiving bank."),

            ("Common Mistakes",
             "Mistake 1: Using Unstructured when Structured is available\n" +
             "  → Your A/R team ends up parsing free text. Defeats the purpose.\n\n" +
             "Mistake 2: Omitting OriginalPaymentInformation\n" +
             "  → Required (1..1). Missing it = schema failure = rejected.\n\n" +
             "Mistake 3: Wrong namespace\n" +
             "  → Using remt.001.001.01 namespace for a v06 message = rejected.\n\n" +
             "Mistake 4: More than 3 AddtlRmtInf elements\n" +
             "  → Schema allows 0..3. A 4th element fails validation silently in some parsers.\n\n" +
             "Mistake 5: Repeating RmtAmtAndTp with CREN/DUPA/REMI type code\n" +
             "  → Explicit spec constraint. XSD will reject it.\n\n" +
             "Speaker note: Print this slide. These are the five bugs that will consume the first two sprints if not addressed up front."),

            ("Next Steps",
             "1. Download the XSD:\n" +
             "   iso20022.org → remt.001.001.06.xsd\n\n" +
             "2. Scaffold the C# data containers\n" +
             "   (available in the Beneficial Strategies ISO 20022 library)\n\n" +
             "3. Build a schema-validating serializer harness\n\n" +
             "4. Write test cases for:\n" +
             "   • Happy path (structured, two invoices)\n" +
             "   • Unstructured only\n" +
             "   • CREN type code (no repeat constraint)\n" +
             "   • Missing OriginalPaymentInformation (expect rejection)\n\n" +
             "5. Ask the AI: 'Generate a full QA test plan for remt.001'\n\n" +
             "Speaker note: Step 5 is not a joke. The MCP server will generate 50+ test cases from the spec automatically.")
        };

        public static void Generate(string outputPath)
        {
            using var presentation = PresentationDocument.Create(
                outputPath, PresentationDocumentType.Presentation);

            var presentationPart = presentation.AddPresentationPart();
            presentationPart.Presentation = new Presentation();

            var slideIdList = new SlideIdList();
            uint slideId = 256;

            foreach (var (title, body) in SlideData)
            {
                var slidePart = presentationPart.AddNewPart<SlidePart>();
                BuildSlide(slidePart, title, body);

                slideIdList.Append(new SlideId
                {
                    Id = slideId++,
                    RelationshipId = presentationPart.GetIdOfPart(slidePart)
                });
            }

            presentationPart.Presentation.Append(slideIdList);
            presentationPart.Presentation.Save();
        }

        private static void BuildSlide(SlidePart slidePart, string title, string body)
        {
            // Parse speaker note out of body (last paragraph starting with "Speaker note:")
            var speakerNote = string.Empty;
            var bodyLines = body.Split('\n').ToList();
            var noteIdx = bodyLines.FindIndex(l => l.StartsWith("Speaker note:"));
            if (noteIdx >= 0)
            {
                speakerNote = bodyLines[noteIdx]["Speaker note:".Length..].Trim();
                bodyLines = bodyLines.Take(noteIdx).ToList();
                body = string.Join('\n', bodyLines).TrimEnd();
            }

            slidePart.Slide = new Slide(
                new CommonSlideData(
                    new ShapeTree(
                        new NonVisualGroupShapeProperties(
                            new NonVisualDrawingProperties { Id = 1, Name = "" },
                            new NonVisualGroupShapeDrawingProperties(),
                            new ApplicationNonVisualDrawingProperties()),
                        new GroupShapeProperties(new A.TransformGroup()),
                        BuildTitleShape(title),
                        BuildBodyShape(body))));

            if (!string.IsNullOrEmpty(speakerNote))
                AddSpeakerNotes(slidePart, speakerNote);

            slidePart.Slide.Save();
        }

        private static Shape BuildTitleShape(string title) => new(
            new NonVisualShapeProperties(
                new NonVisualDrawingProperties { Id = 2, Name = "Title" },
                new NonVisualShapeDrawingProperties(new A.ShapeLocks { NoGrouping = true }),
                new ApplicationNonVisualDrawingProperties(
                    new PlaceholderShape { Type = PlaceholderValues.Title })),
            new ShapeProperties(),
            new TextBody(
                new A.BodyProperties(),
                new A.ListStyle(),
                new A.Paragraph(new A.Run(
                    new A.RunProperties { Language = "en-US", Bold = true },
                    new A.Text(title)))));

        private static Shape BuildBodyShape(string body) => new(
            new NonVisualShapeProperties(
                new NonVisualDrawingProperties { Id = 3, Name = "Body" },
                new NonVisualShapeDrawingProperties(new A.ShapeLocks { NoGrouping = true }),
                new ApplicationNonVisualDrawingProperties(
                    new PlaceholderShape { Index = 1 })),
            new ShapeProperties(),
            new TextBody(
                new A.BodyProperties(),
                new A.ListStyle(),
                body.Split('\n').Select(line =>
                    new A.Paragraph(new A.Run(
                        new A.RunProperties { Language = "en-US", FontSize = 1400 },
                        new A.Text(line))))
                    .ToArray<OpenXmlElement>()));

        private static void AddSpeakerNotes(SlidePart slidePart, string note)
        {
            var notesPart = slidePart.AddNewPart<NotesSlidePart>();
            notesPart.NotesSlide = new NotesSlide(
                new CommonSlideData(
                    new ShapeTree(
                        new NonVisualGroupShapeProperties(
                            new NonVisualDrawingProperties { Id = 1, Name = "" },
                            new NonVisualGroupShapeDrawingProperties(),
                            new ApplicationNonVisualDrawingProperties()),
                        new GroupShapeProperties(new A.TransformGroup()),
                        new Shape(
                            new NonVisualShapeProperties(
                                new NonVisualDrawingProperties { Id = 2, Name = "Notes" },
                                new NonVisualShapeDrawingProperties(),
                                new ApplicationNonVisualDrawingProperties(
                                    new PlaceholderShape { Type = PlaceholderValues.Body })),
                            new ShapeProperties(),
                            new TextBody(
                                new A.BodyProperties(),
                                new A.ListStyle(),
                                new A.Paragraph(new A.Run(new A.Text(note))))))));
            notesPart.NotesSlide.Save();
        }
    }
}

Uso

// Generate the deck — no PowerPoint installation required
RemittanceTrainingDeckGenerator.Generate("RemittanceAdvice-Training.pptx");
Console.WriteLine("Deck saved. Open in PowerPoint or Google Slides.");

Agregue el paquete NuGet a su proyecto:

<PackageReference Include="DocumentFormat.OpenXml" Version="3.1.0" />

¿Qué Acaba de Suceder?

Un gerente de desarrollo solicitó una presentación de capacitación de una hora. El Servidor ISO 20022 MCP de Beneficial Strategies leyó la especificación completa de remt.001.001.06 — cada bloque de construcción, cada restricción de campo, cada regla de multiplicidad — y la IA convirtió eso en:

Las únicas decisiones que tomó fueron el nivel de la audiencia y si incluir un recorrido de código.


“Pero Yo No Escribo Código. ¿Puedo Simplemente Obtener el Archivo?”

Sí. Si está usando Claude Code — el asistente de IA de escritorio — no necesita ser desarrollador en absoluto. Claude Code no solo escribe código: lo ejecuta. Usted hace la pregunta, Claude consulta el servidor MCP, escribe un script de Python, lo ejecuta en su máquina y le entrega un archivo .pptx listo para abrir en PowerPoint o Google Slides.

Así es exactamente como se ve eso.

Lo Que Dice el Gerente

“No escribo código. ¿Puede simplemente crear el archivo PowerPoint para mí ahora mismo?”

Lo Que Hace Claude Code — Automáticamente

Paso 1: Verifica si python-pptx está instalado y lo instala si falta.

pip install python-pptx

Paso 2: Escribe este script de Python y lo ejecuta inmediatamente.

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN

SLIDES = [
    (
        "What Is a Remittance?",
        (
            "A remittance is the structured explanation of WHY a payment is being made.\n\n"
            "Without it: payer sends $4,750. Payee has 12 open invoices. Which ones are paid?\n\n"
            "With remt.001: payer says exactly which invoices are covered, the amounts, "
            "and the references — in a machine-readable format both systems can process automatically."
        ),
        "Ask the room: has anyone had to manually match a payment to invoices? "
        "That's the problem this solves."
    ),
    (
        "Where RemittanceAdvice Fits",
        (
            "ISO 20022 Business Area: REMT (Remittance)\n\n"
            "Message ID:  remt.001.001.06\n"
            "Namespace:   urn:iso:std:iso:20022:tech:xsd:remt.001.001.06\n\n"
            "Sent separately from the payment (pain.001) or alongside it.\n\n"
            "The payment moves the money.\n"
            "The remittance advice explains what the money is for."
        ),
        "Show the XSD at iso20022.org — this is the contract both sides implement. "
        "Version 06 is current. Never build against v01."
    ),
    (
        "The Business Case",
        (
            "A/R teams spend hours manually matching payments to invoices.\n\n"
            "remt.001 makes this automatic:\n"
            "  \u2022  Machine-readable invoice references\n"
            "  \u2022  Exact amounts per invoice\n"
            "  \u2022  Tax and adjustment details\n"
            "  \u2022  Creditor reference for cross-system lookup\n\n"
            "ROI: reduces payment-to-close time from days to minutes.\n\n"
            "If your client runs SAP or Oracle Financials, they already expect this format."
        ),
        "Quantify this for the room: how many hours per week does your A/R team spend "
        "on manual payment matching? That's the budget justification."
    ),
    (
        "Message Identity",
        (
            "Full message ID:  remt.001.001.06\n\n"
            "  remt  \u2192  business area (Remittance)\n"
            "  001   \u2192  message functionality\n"
            "  001   \u2192  flavour\n"
            "  06    \u2192  version 6 (current)\n\n"
            "XSD Schema:\n"
            "  iso20022.org \u2192 remt \u2192 schemas \u2192 remt.001.001.06.xsd\n\n"
            "Always validate your output against this schema before transmission.\n"
            "A non-conformant message is silently rejected."
        ),
        "The XSD is the single source of truth. If your message passes XSD validation "
        "and the business rules, it will be accepted."
    ),
    (
        "Message Hierarchy",
        (
            "RemittanceAdviceV06  (remt.001.001.06)\n"
            "\u251c\u2500\u2500 GroupHeader          (1..1)   envelope: sender, receiver, timestamp\n"
            "\u2502     \u251c\u2500\u2500 MessageIdentification   required, unique per sender\n"
            "\u2502     \u251c\u2500\u2500 CreationDateTime        required, ISO datetime\n"
            "\u2502     \u251c\u2500\u2500 InitiatingParty         required, who sent it\n"
            "\u2502     \u2514\u2500\u2500 MessageRecipient        optional, who receives it\n"
            "\u251c\u2500\u2500 RemittanceInformation (1..*) one block per payment explained\n"
            "\u2502     \u251c\u2500\u2500 Unstructured            free text (0..*)\n"
            "\u2502     \u251c\u2500\u2500 Structured              invoice references (0..*)\n"
            "\u2502     \u2514\u2500\u2500 OriginalPaymentInfo     links to pain.001 (required)\n"
            "\u2514\u2500\u2500 SupplementaryData    (0.*) extensibility hook"
        ),
        "The 1..* on RemittanceInformation means one message can explain multiple payments. "
        "The 1..1 on OriginalPaymentInformation means this field is never optional — "
        "missing it causes an immediate schema rejection."
    ),
    (
        "GroupHeader: Required Fields",
        (
            "These fields are REQUIRED (1..1). Missing any one = message rejected.\n\n"
            "  MsgId      Max35Text    Unique reference, assigned by sender\n"
            "  CreDtTm    ISODateTime  Format: 2026-03-17T09:00:00\n"
            "  InitgPty   Party        Sender name + BIC or IBAN\n\n"
            "Optional but important:\n\n"
            "  MsgRcpt    Party        Intended recipient\n"
            "  FwdgAgt    Institution  Intermediary routing agent\n"
            "  CpyInd     Code         Mark copies: CODU / DUPL / COPY\n\n"
            "MsgId must be UNIQUE per sender.\n"
            "Duplicate IDs cause reconciliation failures at the receiver."
        ),
        "MsgId uniqueness is a business rule, not enforced by XSD. "
        "Your implementation must generate a unique ID — timestamp + UUID is the common pattern."
    ),
    (
        "Unstructured Remittance",
        (
            "Use <Ustrd> when:\n"
            "  \u2022  Quick integration — human-readable only\n"
            "  \u2022  Legacy receiver systems that parse free text\n"
            "  \u2022  Adding a note alongside structured data\n\n"
            "Example:\n"
            '  <Ustrd>Payment for INV-2026-042 and INV-2026-043</Ustrd>\n\n'
            "Limitations:\n"
            "  \u2022  Not machine-readable — A/R still matches manually\n"
            "  \u2022  Maximum 140 characters\n"
            "  \u2022  Cannot express amounts, dates, or adjustment reasons"
        ),
        "Think of Unstructured like the memo field on a cheque. "
        "Fine for humans, useless for automation. "
        "Always prefer Structured when the receiver supports it."
    ),
    (
        "Structured Remittance",
        (
            "Use <Strd> for full A/R automation.\n\n"
            "  RfrdDocInf    Invoice number, type code (CINV), invoice date\n"
            "  RfrdDocAmt    Amount paid, type, adjustments and reasons\n"
            "  CdtrRefInf    Creditor's own cross-reference number\n"
            "  Invcr         Who issued the invoice\n"
            "  Invcee        Who received the invoice\n"
            "  TaxRmt        Tax remittance breakdown\n"
            "  GrnshmtRmt    Garnishment details (payroll scenarios)\n"
            "  AddtlRmtInf   Up to 3 free-text notes (140 chars each)\n\n"
            "KEY CONSTRAINT:\n"
            "  If Type/Code = CREN, DUPA, or REMI \u2192\n"
            "  RmtAmtAndTp must NOT repeat. XSD will reject it."
        ),
        "The CREN/DUPA/REMI constraint is the #1 spec gotcha. "
        "Credit notes and duplicates get special treatment. "
        "Make sure your builder enforces this before serialization."
    ),
    (
        "Validation: Two Layers",
        (
            "LAYER 1 \u2014 Schema Validation (XSD)\n"
            "  Catches structural problems before processing:\n"
            "  \u2022  Required fields present\n"
            "  \u2022  Types correct (date as YYYY-MM-DD, not 'March 17')\n"
            "  \u2022  Max lengths respected (Max35Text = 35 chars max)\n"
            "  \u2022  Enum values valid (CINV, CREN, DUPA, REMI only)\n"
            "  \u2022  Namespace exact match to version\n\n"
            "LAYER 2 \u2014 Business Rules\n"
            "  Catches logic problems after parsing:\n"
            "  \u2022  MsgId unique per sender\n"
            "  \u2022  CREN/DUPA/REMI: RmtAmtAndTp must not repeat\n"
            "  \u2022  AddtlRmtInf: maximum 3 occurrences\n"
            "  \u2022  OriginalPaymentInformation must reference real message"
        ),
        "Schema failures are caught immediately. "
        "Business rule failures may surface days later at the receiver's A/R system. "
        "Both layers must pass."
    ),
    (
        "Implementation: Key Rules",
        (
            "1.  Namespace on Document class must be exact:\n"
            "      urn:iso:std:iso:20022:tech:xsd:remt.001.001.06\n\n"
            "2.  Unstructured is a list \u2014 the spec allows 0..*\n\n"
            "3.  AddtlRmtInf is a list \u2014 but enforce max 3 in your builder\n\n"
            "4.  ALWAYS validate before sending:\n"
            "      schemas = XmlSchemaSet()\n"
            "      schemas.Add(None, 'remt.001.001.06.xsd')\n"
            "      # ValidationEventHandler catches schema errors\n\n"
            "5.  OriginalPaymentInformation is REQUIRED (1..1)\n"
            "    It cannot be omitted. Ever."
        ),
        "Rule 4 is non-negotiable. Transmitting an invalid message wastes network "
        "round-trips and may trigger compliance flags at the receiving bank."
    ),
    (
        "Common Mistakes",
        (
            "1.  Using Unstructured when Structured is supported\n"
            "    \u2192 Your A/R team ends up parsing free text manually\n\n"
            "2.  Omitting OriginalPaymentInformation\n"
            "    \u2192 Required (1..1). Missing = schema failure = rejected\n\n"
            "3.  Wrong namespace version\n"
            "    \u2192 Using remt.001.001.01 for a v06 message = rejected\n\n"
            "4.  More than 3 AddtlRmtInf elements\n"
            "    \u2192 Spec allows 0..3. A 4th element fails validation\n\n"
            "5.  Repeating RmtAmtAndTp with CREN / DUPA / REMI type code\n"
            "    \u2192 Explicit spec constraint. XSD will reject it."
        ),
        "Print this slide. These are the five bugs that will consume "
        "the first two sprints if not addressed up front. "
        "All five are directly derived from the ISO spec — not opinions."
    ),
    (
        "Next Steps",
        (
            "1.  Download the XSD\n"
            "      iso20022.org \u2192 remt.001.001.06.xsd\n\n"
            "2.  Scaffold the C# data containers\n"
            "    (available in the Beneficial Strategies ISO 20022 library)\n\n"
            "3.  Build a schema-validating serializer harness\n\n"
            "4.  Write test cases for:\n"
            "      \u2022  Happy path (structured, two invoices)\n"
            "      \u2022  Unstructured only\n"
            "      \u2022  CREN type code (no-repeat constraint)\n"
            "      \u2022  Missing OriginalPaymentInformation (expect rejection)\n\n"
            "5.  Ask the AI: 'Generate a full QA test plan for remt.001'\n"
            "    The MCP server will generate 50+ test cases automatically."
        ),
        "Step 5 is not a joke. Everything in this deck was generated automatically "
        "from the live ISO 20022 specification by the Beneficial Strategies MCP Server. "
        "Your QA plan can be too."
    ),
]

TITLE_COLOR   = RGBColor(0x00, 0x56, 0x4F)   # Beneficial Strategies dark teal
BODY_FONT     = "Calibri"
TITLE_FONT    = "Calibri"
SLIDE_W       = Inches(13.33)
SLIDE_H       = Inches(7.5)

prs = Presentation()
prs.slide_width  = SLIDE_W
prs.slide_height = SLIDE_H

blank_layout = prs.slide_layouts[6]   # fully blank

for title_text, body_text, note_text in SLIDES:
    slide = prs.slides.add_slide(blank_layout)

    # Title box
    txb = slide.shapes.add_textbox(Inches(0.4), Inches(0.25), Inches(12.5), Inches(1.1))
    tf  = txb.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = title_text
    p.alignment = PP_ALIGN.LEFT
    run = p.runs[0]
    run.font.name   = TITLE_FONT
    run.font.size   = Pt(32)
    run.font.bold   = True
    run.font.color.rgb = TITLE_COLOR

    # Horizontal rule (thin rectangle)
    rule = slide.shapes.add_shape(
        1,   # MSO_SHAPE_TYPE.RECTANGLE
        Inches(0.4), Inches(1.45), Inches(12.5), Inches(0.04))
    rule.fill.solid()
    rule.fill.fore_color.rgb = TITLE_COLOR
    rule.line.fill.background()

    # Body box
    txb2 = slide.shapes.add_textbox(Inches(0.4), Inches(1.6), Inches(12.5), Inches(5.4))
    tf2  = txb2.text_frame
    tf2.word_wrap = True
    tf2.auto_size = None

    first = True
    for line in body_text.split("\n"):
        p2 = tf2.paragraphs[0] if first else tf2.add_paragraph()
        first = False
        p2.text = line
        if p2.runs:
            r = p2.runs[0]
            r.font.name = BODY_FONT
            r.font.size = Pt(16)
            r.font.color.rgb = RGBColor(0x22, 0x22, 0x22)

    # Speaker notes
    notes_slide = slide.notes_slide
    notes_tf    = notes_slide.notes_text_frame
    notes_tf.text = note_text

prs.save("RemittanceAdvice-Training.pptx")
print("Done — RemittanceAdvice-Training.pptx is ready.")

Paso 3: El archivo aparece en su escritorio. Claude informa:

Done — RemittanceAdvice-Training.pptx is ready.

Lo abre en PowerPoint o Google Slides. 12 diapositivas. Notas del presentador en cada diapositiva. Sus colores corporativos. Listo para presentar.

Sin conocimientos de Python. Sin compilar. Sin configuración.

Lo Que Claude Code Hace Posible

Esta es la distinción entre Claude en la web y Claude Code ejecutándose localmente:

Claude (web) Claude Code (escritorio)
Lee la especificación ISO 20022 via MCP
Escribe el script de Python
Ejecuta el script en su máquina
Produce el archivo .pptx real
Instala paquetes faltantes automáticamente

El gerente hace una pregunta. Claude Code consulta el servidor MCP, lee la especificación, escribe el script, instala python-pptx si es necesario, lo ejecuta y entrega un archivo terminado — todo sin que el gerente toque una terminal ni sepa qué es Python.

Eso es lo que una suscripción al Servidor MCP de Beneficial Strategies hace por su equipo directivo. Conozca más sobre los niveles de suscripción.


Véalo Usted Mismo

La presentación generada para este caso de uso está disponible para descargar:

RemittanceAdvice-Training.pptx — Presentación de capacitación para desarrolladores ISO 20022 RemittanceAdvice de 20 diapositivas que cubre el contexto de negocio, el estándar ISO 20022, análisis detallado completo de la estructura del mensaje, implementación en C#, validación XML, el mensaje complementario remt.002 y un flujo de trabajo del mundo real — generada completamente por Claude Code usando el Servidor MCP de Beneficial Strategies.