File indexing completed on 2024-06-09 05:01:52

0001 /*
0002     SPDX-FileCopyrightText: 2014 Christian Dávid <christian-david@web.de>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #ifndef PAYEEIDENTIFIER_IBANBIC_H
0007 #define PAYEEIDENTIFIER_IBANBIC_H
0008 
0009 #include "kmm_mymoney_export.h"
0010 
0011 #include <QString>
0012 #include <QChar>
0013 
0014 #include "payeeidentifier/payeeidentifierdata.h"
0015 #include "mymoneyunittestable.h"
0016 
0017 class ibanBicData;
0018 
0019 namespace KMyMoneyPlugin {
0020 class DataPlugin;
0021 }
0022 
0023 namespace payeeIdentifiers
0024 {
0025 /**
0026  * @brief Plugin to handle IBANs and BICs
0027  *
0028  * Can store a pair of an International Bank Account Number (ISO 13616) and Business Identifier Code (ISO 9362).
0029  *
0030  */
0031 class KMM_MYMONEY_EXPORT ibanBic : public payeeIdentifierData
0032 {
0033     KMM_MYMONEY_UNIT_TESTABLE
0034 public:
0035     PAYEEIDENTIFIER_IID(ibanBic, "org.kmymoney.payeeIdentifier.ibanbic");
0036 
0037     enum bicAllocationStatus {
0038         bicAllocated = 0,
0039         bicNotAllocated,
0040         bicAllocationUncertain,
0041     };
0042 
0043     ibanBic();
0044     ibanBic(const ibanBic& other);
0045     ibanBic& operator=(const ibanBic& other) = default;
0046 
0047     ibanBic* clone() const final override;
0048     ibanBic* createFromXml(QXmlStreamReader* reader) const final override;
0049     void writeXML(QXmlStreamWriter* writer) const final override;
0050 
0051     /**
0052      * @brief Set an owner name for this account
0053      */
0054     void setOwnerName(const QString& ownerName) {
0055         m_ownerName  = ownerName;
0056     }
0057     QString ownerName() const {
0058         return m_ownerName;
0059     }
0060 
0061     /**
0062      * @brief Set a IBAN
0063      *
0064      * The IBAN can contain spaces and other special chars.
0065      */
0066     void setIban(const QString& iban);
0067 
0068     /** @copydoc m_iban
0069      * Use this method if you know that iban is in electronic format already. No further checks are done.
0070      */
0071     void setElectronicIban(const QString& iban) {
0072         Q_ASSERT(iban == ibanToElectronic(iban));
0073         m_iban = iban;
0074     }
0075 
0076     /** @copydoc m_iban */
0077     QString electronicIban() const {
0078         return m_iban;
0079     }
0080 
0081     /**
0082      * @brief Returns iban in human readable format
0083      * @see toPaperformatIban()
0084      */
0085     QString paperformatIban(const QString& separator = QLatin1String(" ")) const;
0086 
0087     /**
0088      * @brief Set Business Identifier Code
0089      *
0090      * Call without parameter or QString() to remove bic
0091      *
0092      * @param bic will be normalized
0093      */
0094     void setBic(const QString& bic = QString());
0095 
0096     /**
0097      * @brief Business Identifier Code
0098      * According to ISO 9362
0099      *
0100      * The returned bic is normalized:
0101      * A tailing XXX is omitted, all characters are uppercase.
0102      */
0103     QString storedBic() const {
0104         return m_bic;
0105     }
0106 
0107     /**
0108      * @copydoc storedBic()
0109      *
0110      * Return a stored BIC (if there is any) or try to use the iban to get a BIC.
0111      */
0112     QString bic() const;
0113 
0114     /**
0115      * @brief Business Identifier Code with tailing XXX
0116      *
0117      * Like @a bic() but always 11 characters long (if bic is invalid, it can have another length).
0118      */
0119     QString fullBic() const;
0120 
0121     /**
0122      * @copydoc fullBic()
0123      *
0124      * This method will not try to use the iban to get a bic.
0125      */
0126     QString fullStoredBic() const;
0127 
0128     /**
0129      * @brief Lookup institutions name
0130      *
0131      * Uses any available information to return an institutionName
0132      */
0133     QString institutionName() const;
0134 
0135     bool operator==(const payeeIdentifierData& other) const final override;
0136     bool operator==(const ibanBic& other) const;
0137     bool isValid() const final override;
0138 
0139     /**
0140      * @brief Extends a bic to 11 characters
0141      *
0142      * Also all characters are made upper case.
0143      */
0144     static QString bicToFullFormat(QString bic);
0145 
0146     /**
0147      * @brief Converts an iban to canonical format for machines
0148      *
0149      * Will remove all white spaces.
0150      */
0151     static QString ibanToElectronic(const QString& iban);
0152 
0153     /**
0154      * @brief Converts an iban to human readable format
0155      *
0156      * Grouped in four letters strings separated by a white space.
0157      *
0158      * @param iban an iban, not needed to be canonical, valid or completed
0159      * @param separator Overwrite the default separator (e.g. a smaller space)
0160      */
0161     static QString ibanToPaperformat(const QString& iban, const QString& separator = QLatin1String(" "));
0162 
0163     /**
0164      * @brief Extract Basic Bank Account Number
0165      *
0166      * Returns the Basic Bank Account Number (BBAN) from the IBAN.
0167      * The BBAN is the IBAN without country code and the two digit checksum.
0168      */
0169     static QString bban(const QString& iban);
0170 
0171     static int ibanLengthByCountry(const QString& countryCode);
0172 
0173     static QString institutionNameByBic(const QString& bic);
0174 
0175     static QString bicByIban(const QString& iban);
0176 
0177     static QString localBankCodeByIban(const QString& iban);
0178 
0179     /**
0180      * @brief Check if IBAN is valid
0181      */
0182     bool isIbanValid() const;
0183 
0184     /**
0185      * @brief Check if IBAN can be valid
0186      *
0187      * This method also checks if the given country code is valid.
0188      *
0189      * If also local aware checks are done (e.g. character set and length of BBAN).
0190      *
0191      * @todo Implement local aware checks
0192      */
0193     static bool isIbanValid(const QString& iban);
0194 
0195 
0196     /**
0197      * @brief Check if this BIC is assigned to an bank
0198      *
0199      * This method does not check the given BIC but looks up in the database directly.
0200      * So it might be useful if time consumption is important but isBicAllocated() should
0201      * be your first option.
0202      *
0203      * @param bic BIC to test in canonical format (always 11 characters long, all characters uppercase)
0204      * @see isBicAllocated()
0205      */
0206     static bicAllocationStatus isCanonicalBicAllocated(const QString& bic);
0207 
0208     /** @brief Check if this BIC is assigned to an bank
0209      *
0210      * @param bic BIC to test.
0211      */
0212     static bicAllocationStatus isBicAllocated(const QString& bic);
0213 
0214     /**
0215      * @brief Check the checksum
0216      *
0217      * Test if the ISO 7064 mod 97-10 checksum of the iban is correct.
0218      *
0219      * @param iban An IBAN in electronic format (important!)
0220      */
0221     static bool validateIbanChecksum(const QString& iban);
0222 
0223     static const int ibanMaxLength;
0224 
0225 private:
0226     /**
0227      * @brief Business Identifier Code
0228      * According to ISO 9362
0229      *
0230      * A trailing XXX must be omitted. All characters must be upper case.
0231      */
0232     QString m_bic;
0233 
0234     /**
0235      * @brief  International Bank Account Number
0236      * According to ISO 13616-1:2007 Part 1
0237      * in normalized (electronic) format (no spaces etc.)
0238      */
0239     QString m_iban;
0240 
0241     QString m_ownerName;
0242 
0243     static KMyMoneyPlugin::DataPlugin *getIbanBicData();
0244 
0245     static QString canonizeBic(const QString& bic);
0246 };
0247 
0248 } // namespace payeeIdentifiers
0249 
0250 #endif // PAYEEIDENTIFIER_IBANBIC_H
0251