NAME
Business::CAMT - ISO20022 Cash Management (CAMT) messages
SYNOPSIS
my $camt = Business::CAMT->new;
my $msg = $camt->read($file|$xml);
print $msg->toPerl;
print $msg->toJSON;
my $message = $camt->create('053.001.02', $data);
$camt->write('out.xml', $message);
$message->write('out.xml'); # same
DESCRIPTION
Use this module to manage CAMT messages, which are ISO20022 standard "Cash Management" messages as produced in banking. For instance, CAMT.053 is produced by banks and consumed by accountancies, showing transactions in bank-accounts. See https://www.iso20022.org.
At the moment, this module can be used to read and write the XML message files, perfectly validated and predictable. It is intended to also support abstraction in interpreting and constructing the content.
However, I need a sponsor to make that happen. Contact the author for support. Please. I would also like to include a CAMT.053 to CSV and MT-940 converter, v.v. Please hire me.
METHODS
Constructors
- Business::CAMT->new(%options)
-
Create a new CAMT processing object.
Reuse this object to avoid recompilation of the message processor, which is pretty expensive.
-Option --Default big_numbers false long_tagnames false match_schema 'NEWER'
- big_numbers => BOOLEAN
-
Set to a true value when your accounts run into the billions. This will enable Math::BigFloat to be used, which is slower and memory hungry.
- long_tagnames => BOOLEAN
-
The schemas are derived from an UML specifications which uses clear and readible long names for relations and attributes. But, someone with a poor sense of optimization removed most of the vowels from these tags while translating the UML into an XSD. When set to
true
, this option will give you the nice long names in Perl. - match_schema => $rule
-
Sets the default $rule how to handle messages which have namespaces which do not match the schemas contained in the module release.
See matchSchema() for the available $rule values. See the DETAILS section about the namespace versioning horrors.
Accessors
- $obj->schemas()
-
Returns the XML::Compile::Schema object, which collects the compiled message XSDs. The XSDs get automatically loaded when messages are encountered which need them.
Read and Write messages
- $obj->create($type, $data, %options)
-
Create a new message, to be written later. The
$data
is the content of the message, in a structure as can be found in the example templates.The
$type
is either in the formcamt.053.001.02
or053.001.02
.example: of create
my $camt = Business::CAMT->new(...); my $msg = $camt->create('053.001.02', \%data); $msg->write('file.xml');
- $obj->fromHASH(\%data, %options)
-
Create a Business::CAMT::Message object of the given
type
. It is not checked whether the type schema exists until an attempt is made to write the message.-Option--Default type <required>
- $obj->read($file|$xml, %options)
-
Pass a $file name, an $xml document or an $xml element. Returned is a HASH blessed in class 'Business::CAMT::CAMnr', for instance
Business::CAMT::CAMT053
.-Option --Default match_schema new(match_schema)
- $obj->write($file, $message, %options)
-
Write a constructed
$message
(an extension of Business::CAMT::Message) to a file in XML format. The message can also be written as JSON or Perl data-structure, via the message itself.example: writing a message
my $message = $camt->create('053.001.02', $data); $camt->write('out.xml', $message); $message->write('out.xml'); # same
Helper methods
You would rarely (or never) need to use these methods in your programs: they support the reader and writer function.
- $obj->fullname2tagTable()
-
Translates long and understandable names into (silly) abbreviated tags.
- $obj->knownVersions( [$set] )
-
Returns a sorted LIST with all schema versions which are included in this distribution. When the $set is specified (like
053.001
), then only those are reported. - $obj->matchSchema($set, $version, %options)
-
Find the available schema version for the $set (like '053.001') to interpret a message with $version (like '02').
-Option--Default rule new(match_schema)
- rule => 'EXACT'|'NEWER'|'NEWEST'|'ANY'|CODE
-
When
EXACT
, only the precise version is acceptable.NEWER
will fall back to the closest newer version. When no exact match,NEWEST
returns the highest available version, but must be newer. Most generous isANY
, which falls back to the newest available version even when it is older than the message version.You may also pass a CODE reference, which is called with the $set, the requested schema, and a sorted ARRAY of available versions. It must return one of the available versions or
undef
(no compatible version).
- $obj->schemaReader($set, $version, $ns)
-
Produces a CODE which can be called with an XML message, to get it transformed into a Perl data-structure. In this case, the $set and $version have to be known already; method read() figures that out by itself.
- $obj->schemaWriter($set, $version, $ns)
- $obj->tag2fullnameTable()
-
Returns a table which translates the (silly) abbreviations used in the XML tags into readable names. Good names make it easier to understand the handling code and is less error-prone.
DETAILS
In this chapter, you find some background information and implementation tips.
Examples
The release contains a examples/
directory. In that directory, you with find a show
script and some xml files. Run the script with a file, to see what this module has to offer. For example:
cd Business-CAMT-0.01/
examples/show examples/danskeci.com/camt053_dk_example.xml /tmp/a.xml
The script (this module) auto-detects the CAMT type which is found in the XML message. Play with the script to see how changes affect the output.
Templates
In our GitHub repository, you find a templates/
directory which contains a structural dump of each of the Perl data structure which is produced (for read()) or consumed (for write
, to be implemented) by this module.
Be sure you understand anonymous HASHes and ARRAYs in Perl well, when you start playing. Do not forget that code gets more readible when you use practical reference variables.
On GitHub, you will also find a templates-long/
directory full of examples. This demonstrates what option new(long_tagnames) does: it will make the Perl datastructures readible.
Implementation issues
XML namespaces
The idea behind XML namespaces to include schema versioning is fundamentally flawed. The CAMT files form no exception in this broken XML concept. Of course, schema versions are mainly backwards compatible, so why not design your versioning with that in mind?
This module bends the namespace use to hide these design mistakes into flexible code. Without full knowledge about existing and future versions of the schemas, there is a powerfull configuration setting with matchSchema().
Please consider to contribute discovered incompatibility issues to this module, to hide them where possible.
Tag abbreviations
XML is very verbose anyway, so it really does not help to abbreviate tags leaving some vowels out. This makes it harder to read messages and code. It increases the chance on stupid typos in the code.
When you set new(long_tagnames), then your Perl structure will use longer, understandable names: it gets easy to understand the message without reading the documentation. This improves maintenance on the long run.
This option will be applied both on read() and write(). Of course, the templates will show you how it works: see the templates-long/
directory in the github repository.
No common types
Each schema is separate, although their type definitions are overlapping. It is not guaranteed that equal types will stay that way over time. This may cause instable code.
Probably, these issues will not emerge because the schema files are generated from a central UML model. However: small changes in the data structure will cause multiple schemas to change to a new version.
A better setup would be:
a schema for base types, like "Amount"
a schema for more complex (reused) structures
a schema per message, which composes the complex structures
Missed chances on XML
The way these schema's got generated, make them very low in using more powerful XML schema features. Those features would have helped the stability of the "interface" which these messages implement a lot. Done this way, XML is not much better than JSON. To be honest, the schemas are littered by missed chances.
The messages are designed with an UML tool, which means: limited to the features of that tool and hindering the view on the quality of the schema. This leads to structures like:
<Bal>
<Tp>
<CdOrPrtry>
<Cd>OPBD</Cd>
</CdOrPrtry>
</Tp>
<Amt Ccy="SEK">500000</Amt>
<CdtDbtInd>CRDT</CdtDbtInd>
<Dt>
<Dt>2010-10-15</Dt>
</Dt>
</Bal>
In Perl, this leads to (long_tagnames
on)
Balance => {
Type => {
CodeOrProperty => {
Code => 'OPBD',
}
},
Amount => {
_ => '500000',
Currency => 'SEK',
},
CreditDebitInd => 'CRDT',
Date => {
Date => '2010-10-15',
},
}
The XML schema, when designed as XML schema, could have looked like
<OpeningBook Date="2010-10-15CEST">
<Credit Currency="SEK">500000.00</Credit>
</OpeningBook>
The use of group
'ed elements and substitutionGroup
's would have made messages so much clearer and easier. Even simple constructs as extension
and restriction
of complexType
's are not used. It would have reduced the message size much further than by leaving out the vowels from tags, as the example shows.
But more importantly: this hinders backward compatibility in the message evaluation a lot! Using XML features better would result in better maintainable applications. Much better.
SEE ALSO
This module is part of Business-CAMT distribution version 0.13, built on December 02, 2024. Website: http://perl.overmeer.net/CPAN/
LICENSE
Copyrights 2024 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://dev.perl.org/licenses/
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 126:
Deleting unknown formatting code T<>