1 /*
2  * This file is part of KMyMoney, A Personal Finance Manager by KDE
3  * Copyright (C) 2014 Christian Dávid <christian-david@web.de>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef PAYEEIDENTIFIER_IBANBIC_H
20 #define PAYEEIDENTIFIER_IBANBIC_H
21 
22 #include "kmm_mymoney_export.h"
23 
24 #include <QString>
25 #include <QChar>
26 
27 #include "payeeidentifier/payeeidentifierdata.h"
28 #include "mymoneyunittestable.h"
29 
30 class ibanBicData;
31 
32 namespace KMyMoneyPlugin { class DataPlugin; }
33 
34 namespace payeeIdentifiers
35 {
36 /**
37  * @brief Plugin to handle IBANs and BICs
38  *
39  * Can store a pair of an International Bank Account Number (ISO 13616) and Business Identifier Code (ISO 9362).
40  *
41  */
42 class KMM_MYMONEY_EXPORT ibanBic : public payeeIdentifierData
43 {
44   KMM_MYMONEY_UNIT_TESTABLE
45 public:
46   PAYEEIDENTIFIER_IID(ibanBic, "org.kmymoney.payeeIdentifier.ibanbic");
47 
48   enum bicAllocationStatus {
49     bicAllocated = 0,
50     bicNotAllocated,
51     bicAllocationUncertain
52   };
53 
54   ibanBic();
55   ibanBic(const ibanBic& other);
56   ibanBic& operator=(const ibanBic& other) = default;
57 
58   ibanBic* clone() const final override;
59   ibanBic* createFromXml(const QDomElement& element) const final override;
60   void writeXML(QDomDocument& document, QDomElement& parent) const final override;
61 
62   /**
63    * @brief Set an owner name for this account
64    */
setOwnerName(const QString & ownerName)65   void setOwnerName(const QString& ownerName) {
66     m_ownerName  = ownerName;
67   }
ownerName()68   QString ownerName() const {
69     return m_ownerName;
70   }
71 
72   /**
73    * @brief Set a IBAN
74    *
75    * The IBAN can contain spaces and other special chars.
76    */
77   void setIban(const QString& iban);
78 
79   /** @copydoc m_iban
80    * Use this method if you know that iban is in electronic format already. No futher checks are done.
81    */
setElectronicIban(const QString & iban)82   void setElectronicIban(const QString& iban) {
83     Q_ASSERT(iban == ibanToElectronic(iban));
84     m_iban = iban;
85   }
86 
87   /** @copydoc m_iban */
electronicIban()88   QString electronicIban() const {
89     return m_iban;
90   }
91 
92   /**
93    * @brief Returns iban in human readable format
94    * @see toPaperformatIban()
95    */
96   QString paperformatIban(const QString& separator = QLatin1String(" ")) const;
97 
98   /**
99    * @brief Set Business Identifier Code
100    *
101    * Call without parameter or QString() to remove bic
102    *
103    * @param bic will be normalized
104    */
105   void setBic(const QString& bic = QString());
106 
107   /**
108    * @brief Business Identifier Code
109    * According to ISO 9362
110    *
111    * The returned bic is normalized:
112    * A tailing XXX is omitted, all characters are uppercase.
113    */
storedBic()114   QString storedBic() const {
115     return m_bic;
116   }
117 
118   /**
119    * @copydoc storedBic()
120    *
121    * Return a stored BIC (if there is any) or try to use the iban to get a BIC.
122    */
123   QString bic() const;
124 
125   /**
126    * @brief Business Identifier Code with tailing XXX
127    *
128    * Like @a bic() but always 11 characters long (if bic is invalid, it can have another length).
129    */
130   QString fullBic() const;
131 
132   /**
133    * @copydoc fullBic()
134    *
135    * This method will not try to use the iban to get a bic.
136    */
137   QString fullStoredBic() const;
138 
139   /**
140    * @brief Lookup institutions name
141    *
142    * Uses any available information to return an institutionName
143    */
144   QString institutionName() const;
145 
146   bool operator==(const payeeIdentifierData& other) const final override;
147   bool operator==(const ibanBic& other) const;
148   bool isValid() const final override;
149 
150   /**
151    * @brief Extends a bic to 11 characters
152    *
153    * Also all characters are made upper case.
154    */
155   static QString bicToFullFormat(QString bic);
156 
157   /**
158    * @brief Converts an iban to canonical format for machines
159    *
160    * Will remove all white spaces.
161    */
162   static QString ibanToElectronic(const QString& iban);
163 
164   /**
165    * @brief Converts an iban to human readable format
166    *
167    * Grouped in four letters strings separated by a white space.
168    *
169    * @param iban an iban, not needed to be canonical, valid or completed
170    * @param separator Overwrite the default separator (e.g. a smaller space)
171    */
172   static QString ibanToPaperformat(const QString& iban, const QString& separator = QLatin1String(" "));
173 
174   /**
175    * @brief Extract Basic Bank Account Number
176    *
177    * Returns the Basic Bank Account Number (BBAN) from the IBAN.
178    * The BBAN is the IBAN without country code and the two digit checksum.
179    */
180   static QString bban(const QString& iban);
181 
182   static int ibanLengthByCountry(const QString& countryCode);
183 
184   static QString institutionNameByBic(const QString& bic);
185 
186   static QString bicByIban(const QString& iban);
187 
188   static QString localBankCodeByIban(const QString& iban);
189 
190   /**
191    * @brief Chech if IBAN is valid
192    */
193   bool isIbanValid() const;
194 
195   /**
196    * @brief Check if IBAN can be valid
197    *
198    * This method also checks if the given country code is valid.
199    *
200    * If also local aware checks are done (e.g. character set and length of BBAN).
201    *
202    * @todo Implement local aware checks
203    */
204   static bool isIbanValid(const QString& iban);
205 
206 
207   /**
208    * @brief Check if this BIC is assigned to an bank
209    *
210    * This method does not check the given BIC but looks up in the database directly.
211    * So it might be useful if time consumption is important but isBicAllocated() should
212    * be your first option.
213    *
214    * @param bic BIC to test in canonical format (always 11 characters long, all characters uppercase)
215    * @see isBicAllocated()
216    */
217   static bicAllocationStatus isCanonicalBicAllocated(const QString& bic);
218 
219   /** @brief Check if this BIC is assigned to an bank
220    *
221    * @param bic BIC to test.
222    */
223   static bicAllocationStatus isBicAllocated(const QString& bic);
224 
225   /**
226    * @brief Check the checksum
227    *
228    * Test if the ISO 7064 mod 97-10 checksum of the iban is correct.
229    *
230    * @param iban An IBAN in electronic format (important!)
231    */
232   static bool validateIbanChecksum(const QString& iban);
233 
234   static const int ibanMaxLength;
235 
236 private:
237   /**
238    * @brief Business Identifier Code
239    * According to ISO 9362
240    *
241    * A trailing XXX must be ommitted. All characters must be upper case.
242    */
243   QString m_bic;
244 
245   /**
246    * @brief  International Bank Account Number
247    * According to ISO 13616-1:2007 Part 1
248    * in normalized (electronic) format (no spaces etc.)
249    */
250   QString m_iban;
251 
252   QString m_ownerName;
253 
254   static KMyMoneyPlugin::DataPlugin *getIbanBicData();
255 
256   static QString canonizeBic(const QString& bic);
257 };
258 
259 } // namespace payeeIdentifiers
260 
261 #endif // PAYEEIDENTIFIER_IBANBIC_H
262 
263