csb43.aeb43

Parsing and validation utilites for the Spanish standard norm 43 by the “Consejo Superior Bancario” (CSB) / “Asociación Española de Banca” (AEB) for storing bank account transactions.

[es] Herramientas para leer y validar datos almacenados siguiendo la norma 43 del Consejo Superior Bancario (CSB) / Asociación Española de Banca (CSB).

References

[n43_2012] (1,2,3,4,5,6,7,8,9)

Información normalizada de cuenta corriente SEPA (2012), Serie normas y procedimientos bancarios nº 43. Confederación Española de Cajas de Ahorros. Asociación Española de Banca.

@techreport{n43_2012,
    author = {Varios},
    institution = {Confederación Española de Cajas de Ahorros},
    month = 6,
    number = {Serie normas y procedimientos bancarios nº 43},
    publisher = {Asociación Española de Banca},
    title = {{Información normalizada de cuenta corriente (SEPA)}},
    year = {2012}
}
class csb43.aeb43.Account(context: Aeb43Context | None = None, raw: dataclasses.InitVar[AnyBytes | None] = None, bank_code: String = String(field_id=<Field.BANK_CODE: 1>, padding=b'0', trim=<Trim.BOTH_BLANK: 10>, align_left=False, mode=mappingproxy({}), factory=<class 'str'>), branch_code: String = String(field_id=<Field.BRANCH_CODE: 2>, padding=b'0', trim=<Trim.BOTH_BLANK: 10>, align_left=False, mode=mappingproxy({}), factory=<class 'str'>), account_number: String = String(field_id=<Field.ACCOUNT_NUMBER: 3>, padding=b'0', trim=<Trim.BOTH_BLANK: 10>, align_left=False, mode=mappingproxy({}), factory=<class 'str'>), initial_date: Date = Date(field_id=<Field.INITIAL_DATE: 4>, factory=<built-in method today of type object>), final_date: Date = Date(field_id=<Field.FINAL_DATE: 5>, factory=<built-in method today of type object>), initial_balance: Money = Money(value_id=<Field.INITIAL_BALANCE: 7>, mode_id=<Field.EXPENSE_OR_INCOME: 6>, default_mode=b'2', padding=b'0', non_negative=False, factory=<class 'decimal.Decimal'>), currency: Currency = Currency(field_id=<Field.CURRENCY_CODE: 8>, factory=<function euro_currency>), information_mode: InformationModeField = InformationModeField(field_id=<Field.INFORMATION_MODE: 9>, factory=<function InformationModeField.<lambda>>), short_name: String = String(field_id=<Field.SHORT_NAME: 10>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>), padding: String = String(field_id=<Field.PADDING: 11>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>), transactions: NestedCollection[Transaction] = None, summary: SummaryField[ClosingAccount] = None)

COD 11

Account record

[es] Registro de cabecera de cuenta

See [n43_2012] Appendix 1, section 1.1

Fields

bank_codeString[4]

bank code / clave de la entidad

branch_codeString[4]

branch code / clave de oficina

account_numberString[10]

account number / número de cuenta

initial_dateDate

initial date / fecha inicial

final_dateDate

final date / fecha final

initial_balanceMoney[12.2]

initial balance / importe saldo inicial

currencyCurrency

currency / divisa

information_modeInteger[1..3]

information mode / modalidad de información

short_nameString[26]

short name / nombre abreviado

paddingString[3]

padding / libre uso

accepts_nested_codes(record: bytes) bool

return True if the record accepts this nested record

property account_control_key

get the account control key (CC)

append(raw: bytes)

append a bytes record to the collection of dependent records

describe(indent: str = '') str

return a textual summary

is_closed() bool

return True if this account has a final summary

to_dict(translated=True)

return fields as a dict of typed values

validate_summary(summary: ClosingAccount)

validate summary record against the extant nested records

class csb43.aeb43.Batch(context: Aeb43Context | None = None, accounts: NestedCollection[Account] | None = None, summary: SummaryField[EndOfFile] | None = None)

A batch of transactions grouped by accounts

Fields

accountslist[Account]

accounts / cuentas

summaryEndOfFile

summary record / registro de recuento

accepts_nested_codes(record: bytes)

return True if the record accepts this nested record

append(raw: bytes)

append a bytes record to the collection of dependent records

describe(indent: str = '')

user friendly summary

dump() bytes

dump content to bytes

is_closed()

return True if the container is closed

to_dict(translated=True)

return content as a dictionary

validate_summary(summary: EndOfFile)

validate summary against the current content

class csb43.aeb43.ClosingAccount(context: Aeb43Context | None = None, raw: dataclasses.InitVar[AnyBytes | None] = None, _validated: bool = False, bank_code: String = String(field_id=<Field.BANK_CODE: 1>, padding=b'0', trim=<Trim.BOTH_BLANK: 10>, align_left=False, mode=mappingproxy({}), factory=<class 'str'>), branch_code: String = String(field_id=<Field.BRANCH_CODE: 2>, padding=b'0', trim=<Trim.BOTH_BLANK: 10>, align_left=False, mode=mappingproxy({}), factory=<class 'str'>), account_number: String = String(field_id=<Field.ACCOUNT_NUMBER: 3>, padding=b'0', trim=<Trim.BOTH_BLANK: 10>, align_left=False, mode=mappingproxy({}), factory=<class 'str'>), expense_entries: Integer = Integer(field_id=<Field.EXPENSE_ENTRIES: 4>, factory=<class 'int'>), expense: Money = Money(value_id=<Field.EXPENSE_AMOUNT: 5>, mode_id=None, default_mode=b'2', padding=b'0', non_negative=True, factory=<class 'decimal.Decimal'>), income_entries: Integer = Integer(field_id=<Field.INCOME_ENTRIES: 6>, factory=<class 'int'>), income: Money = Money(value_id=<Field.INCOME_AMOUNT: 7>, mode_id=None, default_mode=b'2', padding=b'0', non_negative=True, factory=<class 'decimal.Decimal'>), final_balance: Money = Money(value_id=<Field.FINAL_BALANCE: 9>, mode_id=<Field.FINAL_BALANCE_CODE: 8>, default_mode=b'2', padding=b'0', non_negative=False, factory=<class 'decimal.Decimal'>), currency: Currency = Currency(field_id=<Field.CURRENCY_CODE: 10>, factory=<function euro_currency>), padding: String = String(field_id=<Field.PADDING: 11>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>))

COD 33

Closing account record

[es] Registro de asiento de cuentas

See [n43_2012] Appendix 1, section 1.5

Fields

bank_codeString[4]

bank code / clave de la entidad

branch_codeString[4]

branch code / clave de oficina origen

account_numberString[10]

account number / número de cuenta

expense_entriesInteger

expense entries / número de apuntes en el Debe

expenseMoney[12.2]

expense / total importes en el Debe

income_entriesInteger

income entries / número de apuntes en el Haber

incomeMoney[12.2]

income / total importes en el Haber

paddingString[4]

padding / libre uso

class csb43.aeb43.EndOfFile(context: Aeb43Context | None = None, raw: dataclasses.InitVar[AnyBytes | None] = None, _validated: bool = False, total_records: Integer = Integer(field_id=<Field.TOTAL_RECORDS: 1>, factory=<class 'int'>), padding: String = String(field_id=<Field.PADDING: 2>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>))

COD 88

End of file record

[es] Registro de fin de fichero

See [n43_2012] Appendix 1, section 1.6

Fields

total_recordsInteger

total number of records / número total de registros

paddingString[54]

padding / libre uso

class csb43.aeb43.Exchange(context: Aeb43Context | None = None, raw: dataclasses.InitVar[AnyBytes | None] = None, original_currency: currency.Currency = Currency(field_id=<Field.CURRENCY: 1>, factory=<function euro_currency>), amount: money.Money = Money(value_id=<Field.AMOUNT: 2>, mode_id=None, default_mode=b'2', padding=b'0', non_negative=False, factory=<class 'decimal.Decimal'>), padding: string.String = String(field_id=<Field.PADDING: 3>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>))

COD 24-01

Exchange record

[es] Registro complementario de información de equivalencia de importe del apunte.

See [n43_2012] Appendix 1, section 1.4

Fields

original_currencyCurrency

original currency / divisa origen del movimiento

amountMoney[12.2]

transaction amount in the original currency / import en divisa origen

paddingString[59]

unused space in record / libre

class csb43.aeb43.Item(context: Aeb43Context | None = None, raw: dataclasses.InitVar[AnyBytes | None] = None, record_code: Integer = Integer(field_id=<Field.RECORD: 1>, factory=<function default_record_code>), item1: String = String(field_id=<Field.ITEM1: 2>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>), item2: String = String(field_id=<Field.ITEM2: 3>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>))

COD 23

Complementary item / [es] Registro complementario de concepto.

For SEPA normalization using item records, see:

  • csb43.aeb43.sepa_debit

  • csb43.aeb43.sepa_transfer

See [n43_2012] Appendix 1, section 1.3

Fields

record_codeInteger[1..5]

sequence code for complementary item record / [es] código de registro

item1String[38]

item #1 / [es] concepto 1

item2String[38]

item #2 / [es] concepto 2

classmethod accepts_sequence_code(encoding: str, start: int, code: bytes) bool

return True if the provided code is allowed at the current transaction

Args

encoding

string encoding

start

first item record to check

class csb43.aeb43.SepaDebit(item1: NestedRecord[SepaDebitItem1], item2: NestedRecord[SepaDebitItem2], item3: NestedRecord[SepaDebitItem3], item4: NestedRecord[SepaDebitItem4], item5: NestedRecord[SepaDebitItem5], context: Aeb43Context | None = None)

SEPA direct debit

Set of five 80-bytes records

See [n43_2012] Appendix 4, section 2

as_optional_items() Iterator[Item]

convert to vanilla complementary items

property creditor_id

creditor id [AT-02] / identificador del acreedor [AT-02]

property creditor_name

creditor name [AT-03] / nombre del acreedor [AT-03]

property creditor_reference

creditor reference [AT-10] / referencia del acreedor [AT-10]

property debtor_name

debtor name [AT-14] / último deudor [AT-15]

property mandate_reference

mandate reference [AT-01] / referencia única del mandato [AT-01]

classmethod new(*records: bytes | bytearray, context: Aeb43Context | None = None) SepaDebit

return an empty/default SEPA direct debit object

property scheme_code

scheme code [AT-20] / código de esquema [AT-20]

to_dict(translated: bool = True)

return dict with field values

class csb43.aeb43.SepaTransfer(item1: NestedRecord[SepaTransferItem1], item2: NestedRecord[SepaTransferItem2], item3: NestedRecord[SepaDebitItem3], item4: NestedRecord[SepaDebitItem4], item5: NestedRecord[SepaTransferItem5], context: Aeb43Context | None = None)

SEPA transfer

Set of five 80-bytes records

See [n43_2012] Appendix 4, section 1

property additional_info

additional info / campo de libre uso para información del beneficiario

as_optional_items() Iterator[Item]

convert to conventional vanilla items

classmethod new(*records: bytes | bytearray, context: Aeb43Context | None = None) SepaTransfer

return an empty/default SEPA transfer object

property originator_code

originator code [AT-02] / código del ordenante [AT-02]

property originator_name

originator name [AT-02] / nombre del ordenante [AT-02]

property originator_reference

originator reference [AT-41] / referencia del ordenante [AT-41]

property originator_reference_party

originator reference party [AT-08] & nombre de ‘por cuenta de’ [AT-08]

to_dict(translated: bool = True)

return dict with field values

class csb43.aeb43.Transaction(context: Aeb43Context | None = None, raw: dataclasses.InitVar[AnyBytes | None] = None, padding: String = String(field_id=<Field.PADDING: 1>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>), branch_code: String = BranchCode(field_id=<Field.BRANCH_CODE: 2>, padding=b'0', trim=<Trim.BOTH_BLANK: 10>, align_left=False, mode=mappingproxy({}), factory=<class 'str'>), document_number: String = String(field_id=<Field.DOCUMENT_NUMBER: 9>, padding=b'0', trim=<Trim.BOTH_BLANK: 10>, align_left=False, mode=mappingproxy({}), factory=<class 'str'>), transaction_date: Date = Date(field_id=<Field.TRANSACTION_DATE: 3>, factory=<built-in method today of type object>), value_date: Date = Date(field_id=<Field.VALUE_DATE: 4>, factory=<built-in method today of type object>), shared_item: Integer = Integer(field_id=<Field.SHARED_ITEM: 5>, factory=<class 'int'>), own_item: Integer = Integer(field_id=<Field.OWN_ITEM: 6>, factory=<class 'int'>), amount: Money = Money(value_id=<Field.AMOUNT: 8>, mode_id=<Field.EXPENSE_OR_INCOME: 7>, default_mode=b'2', padding=b'0', non_negative=False, factory=<class 'decimal.Decimal'>), reference1: String = String(field_id=<Field.REFERENCE1: 10>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({<InformationMode.THIRD: 3>: {'padding': b'0', 'trim': <Trim.BOTH_BLANK: 10>, 'align_left': False}}), factory=<class 'str'>), reference2: String = String(field_id=<Field.REFERENCE2: 11>, padding=b' ', trim=<Trim.BOTH: 15>, align_left=True, mode=mappingproxy({}), factory=<class 'str'>), exchange: NestedRecord[Exchange] = None, optional_items: NestedCollection[Item] = None, sepa_transfer: SepaTransferField = None, sepa_debit: SepaDebitField = None)

COD 22

Main transaction record

[es] Registro principal de movimientos

See [n43_2012] Appendix 1, section 1.2

Fields

paddingString[4]

padding / libre uso

branch_codeString[4]

branch code / clave de oficina origen

document_numberString[10]

document number / número de documento

transaction_dateDate

date of transaction / fecha de operación

value_dateDate

effective date / fecha de valor

shared_itemInteger[0..99]

shared item / concepto común

own_itemInteger[0..999]

own item / concepto propio

amountMoney[12.2]

transaction amont / importe

reference1String[12]

reference 1 / referencia 1

reference2String[16]

reference 2 / referencia 2

accepts_nested_codes(record: bytes) bool

return True if the record accepts this nested record

append(raw: bytes)

append a bytes record to the collection of dependent records

iter_optional_items() Iterator[str]

iterate optional items fields

to_dict(translated=True)

return fields as a dict of typed values

to_sepa() None

convert complementary items to a SEPA debit/transfer object

csb43.aeb43.get_current_context() Aeb43Context

get the context for the current scope

csb43.aeb43.read_batch(stream: IO[bytes], context: Aeb43Context | None = None) Batch

read a batch of accounts from a binary stream

Context – [en] Contexto

Context object for reading AEB43 records

class csb43.aeb43.record.context.Aeb43Context(strict: bool = False, silent: bool = False, encoding: str = 'latin1', sepa: bool = True, year_first: bool = True, cache_fields: bool = True, decimals: int = 2, information_mode: InformationMode = InformationMode.THIRD)

settings for encoded AEB43 records

Fields

strictbool

raise exception when a validation fails if strict=True

silentbool

if silent=True, validation warnings are not emitted

encodingstr

string encoding use when transforming from binary files

sepabool

when sepa=True, transactions trie to interpret optional items as SEPA transfer or direct debits

cache_fieldsbool

cache values from setters/getters

decimalint

number of decimal places used in money amounts

information_modeInformationMode

information mode to use in nested records. Accounts will change this value.

emit_validation_error(message: str) None

raise ValidationException if strict or emits a ValidationWarning if not strict and not silent

emit_validation_warning(message: str) None

emit a warning

error_message(message: str) str

get a new error message in a batch context

new_validation_error(message: str) ValidationException

create a new validation error with message

Context line is added to the Exception

scope(**kwargs)

create a scope for this context

to_string(value) str

convert value to string

class csb43.aeb43.record.context.BatchContext(line: int | None = None)

line context

scope()

create a scope for this context

class csb43.aeb43.record.context.Contextual(*args, **kwargs)

protocol for any class that has a context property

class csb43.aeb43.record.context.ContextualMixin

provides a method that always returns a context

get_context() Aeb43Context

get the context for the current scope

class csb43.aeb43.record.context.InformationMode(value)

information mode

[es] modalidad de información

See [n43_2012] Appendix 1

csb43.aeb43.record.context.check_compatible_encoding(encoding: str) bool

returns True if ‘encoding’ is compatible with n43 records

csb43.aeb43.record.context.get_batch_context() BatchContext

get the context for the current scope

csb43.aeb43.record.context.get_current_context() Aeb43Context

get the context for the current scope