You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
7.2 KiB

  1. # -*- encoding: utf-8 -*-
  2. """Classes and definitions used in parsing bank statements."""
  3. ##############################################################################
  4. #
  5. # Copyright (C) 2015 Therp BV <http://therp.nl>.
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. class BankTransaction(dict):
  22. """Single transaction that is part of a bank statement."""
  23. @property
  24. def value_date(self):
  25. """property getter"""
  26. return self['date']
  27. @value_date.setter
  28. def value_date(self, value_date):
  29. """property setter"""
  30. self['date'] = value_date
  31. @property
  32. def name(self):
  33. """property getter"""
  34. return self['name']
  35. @name.setter
  36. def name(self, name):
  37. """property setter"""
  38. self['name'] = name
  39. @property
  40. def transferred_amount(self):
  41. """property getter"""
  42. return self['amount']
  43. @transferred_amount.setter
  44. def transferred_amount(self, transferred_amount):
  45. """property setter"""
  46. self['amount'] = transferred_amount
  47. @property
  48. def eref(self):
  49. """property getter"""
  50. return self['ref']
  51. @eref.setter
  52. def eref(self, eref):
  53. """property setter"""
  54. self['ref'] = eref
  55. if not self.message:
  56. self.name = eref
  57. @property
  58. def message(self):
  59. """property getter"""
  60. return self._message
  61. @message.setter
  62. def message(self, message):
  63. """property setter"""
  64. self._message = message
  65. self.name = message
  66. @property
  67. def remote_owner(self):
  68. """property getter"""
  69. return self['partner_name']
  70. @remote_owner.setter
  71. def remote_owner(self, remote_owner):
  72. """property setter"""
  73. self['partner_name'] = remote_owner
  74. if not (self.message or self.eref):
  75. self.name = remote_owner
  76. @property
  77. def remote_account(self):
  78. """property getter"""
  79. return self['account_number']
  80. @remote_account.setter
  81. def remote_account(self, remote_account):
  82. """property setter"""
  83. self['account_number'] = remote_account
  84. def __init__(self):
  85. """Define and initialize attributes.
  86. Not all attributes are already used in the actual import.
  87. """
  88. super(BankTransaction, self).__init__()
  89. self.transfer_type = False # Action type that initiated this message
  90. self.execution_date = False # The posted date of the action
  91. self.value_date = False # The value date of the action
  92. self.remote_account = False # The account of the other party
  93. self.remote_currency = False # The currency used by the other party
  94. self.exchange_rate = 0.0
  95. # The exchange rate used for conversion of local_currency and
  96. # remote_currency
  97. self.transferred_amount = 0.0 # actual amount transferred
  98. self.name = ''
  99. self._message = False # message from the remote party
  100. self.eref = False # end to end reference for transactions
  101. self.remote_owner = False # name of the other party
  102. self.remote_owner_address = [] # other parties address lines
  103. self.remote_owner_city = False # other parties city name
  104. self.remote_owner_postalcode = False # other parties zip code
  105. self.remote_owner_country_code = False # other parties country code
  106. self.remote_bank_bic = False # bic of other party's bank
  107. self.provision_costs = False # costs charged by bank for transaction
  108. self.provision_costs_currency = False
  109. self.provision_costs_description = False
  110. self.error_message = False # error message for interaction with user
  111. self.storno_retry = False
  112. # If True, make cancelled debit eligible for a next direct debit run
  113. self.data = '' # Raw data from which the transaction has been parsed
  114. class BankStatement(dict):
  115. """A bank statement groups data about several bank transactions."""
  116. @property
  117. def statement_id(self):
  118. """property getter"""
  119. return self['name']
  120. def _set_transaction_ids(self):
  121. """Set transaction ids to statement_id with sequence-number."""
  122. subno = 0
  123. for transaction in self['transactions']:
  124. subno += 1
  125. transaction['unique_import_id'] = (
  126. self.statement_id + str(subno).zfill(4))
  127. @statement_id.setter
  128. def statement_id(self, statement_id):
  129. """property setter"""
  130. self['name'] = statement_id
  131. self._set_transaction_ids()
  132. @property
  133. def local_account(self):
  134. """property getter"""
  135. return self['account_number']
  136. @local_account.setter
  137. def local_account(self, local_account):
  138. """property setter"""
  139. self['account_number'] = local_account
  140. @property
  141. def local_currency(self):
  142. """property getter"""
  143. return self['currency_code']
  144. @local_currency.setter
  145. def local_currency(self, local_currency):
  146. """property setter"""
  147. self['currency_code'] = local_currency
  148. @property
  149. def start_balance(self):
  150. """property getter"""
  151. return self['balance_start']
  152. @start_balance.setter
  153. def start_balance(self, start_balance):
  154. """property setter"""
  155. self['balance_start'] = start_balance
  156. @property
  157. def end_balance(self):
  158. """property getter"""
  159. return self['balance_end']
  160. @end_balance.setter
  161. def end_balance(self, end_balance):
  162. """property setter"""
  163. self['balance_end'] = end_balance
  164. self['balance_end_real'] = end_balance
  165. @property
  166. def date(self):
  167. """property getter"""
  168. return self['date']
  169. @date.setter
  170. def date(self, date):
  171. """property setter"""
  172. self['date'] = date
  173. def create_transaction(self):
  174. """Create and append transaction.
  175. This should only be called after statement_id has been set, because
  176. statement_id will become part of the unique transaction_id.
  177. """
  178. transaction = BankTransaction()
  179. self['transactions'].append(transaction)
  180. # Fill default id, but might be overruled
  181. transaction['unique_import_id'] = (
  182. self.statement_id + str(len(self['transactions'])).zfill(4))
  183. return transaction
  184. def __init__(self):
  185. super(BankStatement, self).__init__()
  186. self['transactions'] = []
  187. self.statement_id = ''
  188. self.local_account = ''
  189. self.local_currency = ''
  190. self.date = ''
  191. self.start_balance = 0.0
  192. self.end_balance = 0.0