From 78245b7a94305ea03bafe744fd7fcf9a7a9bc90b Mon Sep 17 00:00:00 2001 From: rouggy Date: Tue, 10 Aug 2021 01:05:52 +0700 Subject: [PATCH] first commit --- accounts/HSBC_ATM_VND/TransactionHistory.csv | 20 + .../TransactionHistory.csv | 6 + .../Export_00051040831_03012021_02072021.csv | 69 ++ api.py | 137 ++++ app.py | 50 ++ data/master.json | 734 ++++++++++++++++++ db.py | 0 models/__init__.py | 0 models/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 174 bytes ...eg002@hotmail.com 2021-04-20-20-07-04).pyc | Bin 0 -> 1112 bytes .../__pycache__/transactions.cpython-39.pyc | Bin 0 -> 1386 bytes models/transactions.py | 32 + .../import_config_2021-04-20.json | 41 + .../import_config_2021-04-23.json | 41 + .../SG_Greg_EUR/import_config_2021-04-21.json | 39 + transaction.py | 161 ++++ 16 files changed, 1330 insertions(+) create mode 100644 accounts/HSBC_ATM_VND/TransactionHistory.csv create mode 100644 accounts/HSBC_CreditCard_VND/TransactionHistory.csv create mode 100644 accounts/SG_Greg_EUR/Export_00051040831_03012021_02072021.csv create mode 100644 api.py create mode 100644 app.py create mode 100644 data/master.json create mode 100644 db.py create mode 100644 models/__init__.py create mode 100644 models/__pycache__/__init__.cpython-39.pyc create mode 100644 models/__pycache__/transactions.cpython-39 (SFConflict legreg002@hotmail.com 2021-04-20-20-07-04).pyc create mode 100644 models/__pycache__/transactions.cpython-39.pyc create mode 100644 models/transactions.py create mode 100644 output/HSBC_ATM_VND/import_config_2021-04-20.json create mode 100644 output/HSBC_CreditCard_VND/import_config_2021-04-23.json create mode 100644 output/SG_Greg_EUR/import_config_2021-04-21.json create mode 100644 transaction.py diff --git a/accounts/HSBC_ATM_VND/TransactionHistory.csv b/accounts/HSBC_ATM_VND/TransactionHistory.csv new file mode 100644 index 0000000..725f2f8 --- /dev/null +++ b/accounts/HSBC_ATM_VND/TransactionHistory.csv @@ -0,0 +1,20 @@ +27/07/2021,ATM 23JUL21 ELECTRO 16:25:56 VN219492VND 727000.00 PHARMACITY A89501804 ATM,"-727,000.00","102,101,988.00" +27/07/2021,ATM 23JUL21 ELECTRO 16:12:06 VN318526VND 3383010.00 PAYOO-LESQUARE A89500909 ATM,"-3,383,010.00","102,828,988.00" +26/07/2021,TRANSFER 090-480781-041 Commande Raclette IB0100417 INTERNET BANKING,"-1,790,000.00","106,211,998.00" +23/07/2021,TRANSFER 091-846345-141 Greg IB0206975 INTERNET BANKING,"91,700,000.00","108,001,998.00" +23/07/2021,"TRANSFER PAYOO BILL PMT/TT HOADON 235795X269505 23JUL2021 13""43:06 IB0108619 INTERNET BANKING","-13,173,586.00","16,301,998.00" +21/07/2021,ATM 19JUL21 ELECTRO 17:34:34 VN115710VND 2761416.00 AN NAM GOURMET - TD A89501911 ATM,"-2,761,416.00","29,475,584.00" +20/07/2021,ATM 14JUL21 ELECTRO 14:58:53 VN400724VND 4106000.00 NAM AN MARKET NTMK A89500839 ATM,"-4,106,000.00","32,237,000.00" +19/07/2021,ATM 14JUL21 ELECTRO 15:41:23 VN110257VND 2551000.00 CC 77 QHUONG HCM A89502242 ATM,"-2,551,000.00","36,343,000.00" +16/07/2021,ATM 14JUL21 ELECTRO 14:32:17 VN309416VND 2396000.00 CT TNHH VIET PHAP HAI SA A89501455 ATM,"-2,396,000.00","38,894,000.00" +16/07/2021,ATM 14JUL21 ELECTRO 15:11:40 VN210474VND 2452000.00 SAI GON PET A89501188 ATM,"-2,452,000.00","41,290,000.00" +16/07/2021,ATM 14JUL21 ELECTRO 15:14:32 VN110226VND 1774000.00 SAI GON PET A89501187 ATM,"-1,774,000.00","43,742,000.00" +15/07/2021,TRANSFER LP VNM10NMT4 QC earbuds CONG TY TNHH TM DV DO NET CAO 98854769 QC earbuds 20 Nguyen U Di Thao dien IB0107796 INTERNET BANKING,"-8,690,000.00","45,516,000.00" +15/07/2021,TRANSFER 091-846345-141 Greg IB0402177 INTERNET BANKING,"25,223,000.00","54,206,000.00" +15/07/2021,ATM 11JUL21 ELECTRO 09:44:44 VN106399VND 2975000.00 MEAT WORKS AN PHU A89500467 ATM,"-2,975,000.00","28,983,000.00" +14/07/2021,ATM 11JUL21 ELECTRO 09:34:00 VN106390VND 781000.00 SIEU THI AN PHU A89503223 ATM,"-781,000.00","31,958,000.00" +14/07/2021,ATM 12JUL21 ELECTRO 17:15:32 VN307354VND 2851000.00 CT TNHH VIET PHAP HAI SA A89502572 ATM,"-2,851,000.00","32,739,000.00" +14/07/2021,ATM 11JUL21 ELECTRO 10:07:06 VN206688VND 2074300.00 NAM AN MARKET NTMK A89501126 ATM,"-2,074,300.00","35,590,000.00" +13/07/2021,ATM 08JUL21 ELECTRO 12:43:11 VN493204VND 5019000.00 SIEU THI AN PHU A89504772 ATM,"-5,019,000.00","37,664,300.00" +12/07/2021,ATM 12JUL21 ATMA837 17:13:05 A83700190 ATM,"-4,000,000.00","42,683,300.00" +09/07/2021,TRANSFER 090-480781-041 BRETON STEPHANIE BOOTLEG IB0301485 INTERNET BANKING,"-1,795,000.00","46,683,300.00" diff --git a/accounts/HSBC_CreditCard_VND/TransactionHistory.csv b/accounts/HSBC_CreditCard_VND/TransactionHistory.csv new file mode 100644 index 0000000..a2ea748 --- /dev/null +++ b/accounts/HSBC_CreditCard_VND/TransactionHistory.csv @@ -0,0 +1,6 @@ +"21/07/2021","20/07/2021",PAYPAL *WHATBOX INC 5199622726 ON PAYPAL *WHATBOX INC 5199622726 CAN,"-2,590,087.00","-2,590,087.00" +"21/07/2021","20/07/2021",PAYPAL *NETFLIX 35314369001 FRA PAYPAL *NETFLIX 35314369001 FRA,"-453,390.00","-453,390.00" +"19/07/2021","16/07/2021",PAYPAL *YOUSSEF 4029357733 SGP PAYPAL *YOUSSEF 4029357733 SGP,"-284,039.00","-284,039.00" +"19/07/2021","16/07/2021",PAYPAL *YOUSSEF 4029357733 SGP PAYPAL *YOUSSEF 4029357733 SGP,"-823,714.00","-823,714.00" +"19/07/2021","16/07/2021",PAYPAL *VETVER PHOTOMA 4029357733 SGP PAYPAL *VETVER PHOTOMA 4029357733 SGP,"-1,278,177.00","-1,278,177.00" +"09/07/2021","08/07/2021",GOOGLE YouTube Member Mountain View CA GOOGLE YouTube Member Mountain View USA,"-10,000.00","-10,000.00" diff --git a/accounts/SG_Greg_EUR/Export_00051040831_03012021_02072021.csv b/accounts/SG_Greg_EUR/Export_00051040831_03012021_02072021.csv new file mode 100644 index 0000000..e6a289f --- /dev/null +++ b/accounts/SG_Greg_EUR/Export_00051040831_03012021_02072021.csv @@ -0,0 +1,69 @@ +01/07/2021;PRLV EUROPEEN ACC 0113690088 DE: SOGECAP ID: FR04ZZZ110906 MOTIF: 00610504154900214330804854SOGECEPIC EA AD000000/00610/5041549;-150,00;EUR; +30/06/2021;CARTE X1533 27/06 Molotov COMMERCE ELECTRONIQUE 110118101367830IOPD;-3,99;EUR; +30/06/2021;PRELEVEMENT EUROPEEN 9013994551 DE: FREE MOBILE ID: FR07ZZZ591778 REF: fmpmt-1382247416 MANDAT ++FM-11309168-1;-29,99;EUR; +29/06/2021;CARTE X1533 28/06 PAYPAL COMMERCE ELECTRONIQUE 110118000044989IOPD;-12,99;EUR; +29/06/2021;CARTE X1533 28/06 PAYPAL COMMERCE ELECTRONIQUE 110118000057230IOPD;-39,99;EUR; +25/06/2021;FRAIS PAIEMENT HORS ZONE EURO CARTE X1533 23/06 8,99 EUR ROYAUME-UNI;-0,24;EUR; +24/06/2021;CARTE X1533 23/06 PLAYSTATIONNETWORK 8,99 EUR ROYAUME-UNI COMMERCE ELECTRONIQUE 230117500254301IOPD;-8,99;EUR; +22/06/2021;CARTE X1533 21/06 PAYPAL COMMERCE ELECTRONIQUE 110117300092728IOPD;-6,99;EUR; +08/06/2021;PRELEVEMENT EUROPEEN 6510642872 DE: ProRealTime SARL ID: FR69ZZZ528388 MOTIF: PROREALTIMEJUNE REF: OI616555;-57,55;EUR; +04/06/2021;CARTE X1533 02/06 PAYPAL COMMERCE ELECTRONIQUE 110115500288622IOPD;-12,00;EUR; +01/06/2021;CARTE X1533 30/05 PAYPAL COMMERCE ELECTRONIQUE 110115200171704IOPD;-8,99;EUR; +01/06/2021;PRLV EUROPEEN ACC 6208945251 DE: SOGECAP ID: FR04ZZZ110906 MOTIF: 00610504154900213330762178SOGECEPIC EA AD000000/00610/5041549;-150,00;EUR; +31/05/2021;CARTE X1533 27/05 Molotov COMMERCE ELECTRONIQUE 110115106313480IOPD;-3,99;EUR; +31/05/2021;PRELEVEMENT EUROPEEN 5818830333 DE: FREE MOBILE ID: FR07ZZZ591778 REF: fmpmt-1366416977 MANDAT ++FM-11309168-1;-11,99;EUR; +26/05/2021;PRELEVEMENT EUROPEEN 5514430914 DE: FREE MOBILE ID: FR07ZZZ591778 REF: fmpmt-1365181238 MANDAT ++FM-11309168-1;-14,42;EUR; +25/05/2021;CARTE X1533 23/05 PAYPAL COMMERCE ELECTRONIQUE;-2,69;EUR; +25/05/2021;CARTE X1533 21/05 PAYPAL COMMERCE ELECTRONIQUE;-6,99;EUR; +25/05/2021;CARTE X1533 23/05 Playstation COMMERCE ELECTRONIQUE;-8,99;EUR; +11/05/2021;CARTE X1533 10/05 WEB AMENDE.GOUV COMMERCE ELECTRONIQUE;-45,00;EUR; +11/05/2021;PRELEVEMENT EUROPEEN 4000194397 DE: ProRealTime SARL ID: FR69ZZZ528388 MOTIF: PROREALTIMEMAY REF: OI613706;-56,56;EUR; +07/05/2021;VIR RECU 3684897119S DE: APRIL INTERNATIONAL CARE FRANCE REF: 10897113;686,00;EUR; +07/05/2021;VIR RECU 3684984702S DE: APRIL INTERNATIONAL CARE FRANCE REF: 10897114;880,10;EUR; +04/05/2021;CARTE X1533 03/05 PAYPAL COMMERCE ELECTRONIQUE;-25,08;EUR; +03/05/2021;CARTE X1533 30/04 PAYPAL COMMERCE ELECTRONIQUE;-8,99;EUR; +03/05/2021;PRLV EUROPEEN ACC 3319917619 DE: SOGECAP ID: FR04ZZZ110906 MOTIF: 00610504154900212330721940SOGECEPIC EA AD000000/00610/5041549;-150,00;EUR; +30/04/2021;CARTE X1533 27/04 MolotovTV COMMERCE ELECTRONIQUE;-3,99;EUR; +29/04/2021;VIR RECU 2886790790S DE: APRIL INTERNATIONAL CARE FRANCE REF: 10883740;286,46;EUR; +29/04/2021;VIR RECU 2886790978S DE: APRIL INTERNATIONAL CARE FRANCE REF: 10883741;464,74;EUR; +29/04/2021;VIR RECU 2886771560S DE: APRIL INTERNATIONAL CARE FRANCE REF: 10883739;504,68;EUR; +26/04/2021;CARTE X1533 24/04 WP SONY COMMERCE ELECTRONIQUE;-7,49;EUR; +26/04/2021;CARTE X1533 24/04 WP SONY COMMERCE ELECTRONIQUE;-39,99;EUR; +26/04/2021;PRELEVEMENT EUROPEEN 2307495459 DE: FREE MOBILE ID: FR07ZZZ591778 REF: fmpmt-1348650381 MANDAT ++FM-11309168-1;-57,22;EUR; +26/04/2021;CARTE X1533 25/04 WP SONY COMMERCE ELECTRONIQUE;-99,99;EUR; +22/04/2021;CARTE X1533 21/04 PAYPAL COMMERCE ELECTRONIQUE;-6,99;EUR; +21/04/2021;COTISATION ANNUELLE CARTE Visa X1533;-45,00;EUR; +19/04/2021;CARTE X1533 16/04 PAYPAL COMMERCE ELECTRONIQUE;-19,59;EUR; +19/04/2021;CARTE X1533 18/04 Sony COMMERCE ELECTRONIQUE;-99,99;EUR; +13/04/2021;CARTE X1533 12/04 PAYPAL COMMERCE ELECTRONIQUE;-7,60;EUR; +13/04/2021;PRELEVEMENT EUROPEEN 0900266516 DE: ProRealTime SARL ID: FR69ZZZ528388 MOTIF: PROREALTIMEAPRIL REF: OI602509;-56,56;EUR; +07/04/2021;CARTE X1533 04/04 MolotovTV COMMERCE ELECTRONIQUE;-9,99;EUR; +06/04/2021;VIR RECU 0691380381S DE: M SALAUN OU MME BRETON M SALAUN OU M ME BRETON DE: M/M M SALAUN OU MME BRETON REF: GREG;600,00;EUR; +02/04/2021;ARRETE 01.01/31.03 MINIMUM FORFAITAIRE NOMBRE JOURS DEBITEURS : 45;-7,00;EUR; +01/04/2021;PRLV EUROPEEN ACC 0114854765 DE: SOGECAP ID: FR04ZZZ110906 MOTIF: 00610504154900211330678941SOGECEPIC EA AD000000/00610/5041549;-150,00;EUR; +31/03/2021;CARTE X1533 30/03 PAYPAL COMMERCE ELECTRONIQUE;-4,49;EUR; +30/03/2021;CARTE X1533 27/03 MolotovTV COMMERCE ELECTRONIQUE;-3,99;EUR; +24/03/2021;PRELEVEMENT EUROPEEN 8205715880 DE: FREE MOBILE ID: FR07ZZZ591778 REF: fmpmt-1333038936 MANDAT ++FM-11309168-1;-29,51;EUR; +22/03/2021;CARTE X1533 19/03 PAYPAL COMMERCE ELECTRONIQUE;-2,00;EUR; +22/03/2021;CARTE X1533 21/03 PAYPAL COMMERCE ELECTRONIQUE;-6,99;EUR; +15/03/2021;CARTE X1533 12/03 PAYPAL COMMERCE ELECTRONIQUE;-12,00;EUR; +15/03/2021;CARTE X1533 13/03 PAYPAL COMMERCE ELECTRONIQUE;-69,99;EUR; +09/03/2021;PRELEVEMENT EUROPEEN 6715206132 DE: ProRealTime SARL ID: FR69ZZZ528388 MOTIF: PROREALTIMEMARCH REF: OI594560;-57,55;EUR; +02/03/2021;CARTE X1533 27/02 MolotovTV COMMERCE ELECTRONIQUE;-3,99;EUR; +02/03/2021;PRLV EUROPEEN ACC 6011218416 DE: SOGECAP ID: FR04ZZZ110906 MOTIF: 00610504154900210330634962SOGECEPIC EA AD000000/00610/5041549;-150,00;EUR; +24/02/2021;PRELEVEMENT EUROPEEN 5405711261 DE: FREE MOBILE ID: FR07ZZZ591778 REF: fmpmt-1318936201 MANDAT ++FM-11309168-1;-19,99;EUR; +22/02/2021;CARTE X1533 21/02 PAYPAL COMMERCE ELECTRONIQUE;-6,99;EUR; +15/02/2021;CARTE X1533 13/02 PAYPAL COMMERCE ELECTRONIQUE;-5,49;EUR; +08/02/2021;PRELEVEMENT EUROPEEN 3602154980 DE: ProRealTime SARL ID: FR69ZZZ528388 MOTIF: PROREALTIMEFEBRU REF: OI581624;-50,56;EUR; +02/02/2021;PRLV EUROPEEN ACC 3211687689 DE: SOGECAP ID: FR04ZZZ110906 MOTIF: 00610504154900209330597203SOGECEPIC EA AD000000/00610/5041549;-150,00;EUR; +01/02/2021;CARTE X1533 27/01 MolotovTV COMMERCE ELECTRONIQUE;-3,99;EUR; +25/01/2021;PRELEVEMENT EUROPEEN 2211094675 DE: FREE MOBILE ID: FR07ZZZ591778 REF: fmpmt-1303516258 MANDAT ++FM-11309168-1;-22,39;EUR; +22/01/2021;CARTE X1533 21/01 PAYPAL COMMERCE ELECTRONIQUE;-6,99;EUR; +13/01/2021;VIR RECU 1384935648S DE: AMERICAN EXPRESS CARTE FRANCE MOTIF: Remboursement de Solde Crediteur REF: 302-394424-421;115,72;EUR; +12/01/2021;TENUE DE COMPTE;-6,00;EUR; +11/01/2021;CARTE X1533 09/01 PAYPAL COMMERCE ELECTRONIQUE;-5,49;EUR; +11/01/2021;CARTE X1533 10/01 PAYPAL COMMERCE ELECTRONIQUE;-38,45;EUR; +08/01/2021;CARTE X1533 07/01 REF UNION COMMERCE ELECTRONIQUE;-55,00;EUR; +07/01/2021;VIR INST REC 150724200949 DE: Mintos Marketplace AS DATE: 07/01/2021 09:38 MOTIF: Withdrawal from Investor account No 30097106;91,48;EUR; +06/01/2021;PRELEVEMENT EUROPEEN 0500336419 DE: ProRealTime SARL ID: FR69ZZZ528388 MOTIF: PROREALTIMEJANUA REF: OI580415;-47,45;EUR; +04/01/2021;PRLV EUROPEEN ACC 0432056413 DE: SOGECAP ID: FR04ZZZ110906 MOTIF: 00610504154900207330559117SOGECEPIC EA AD000000/00610/5041549;-150,00;EUR; diff --git a/api.py b/api.py new file mode 100644 index 0000000..c11033a --- /dev/null +++ b/api.py @@ -0,0 +1,137 @@ +import requests +import math +from models.transactions import * + +token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIyMyIsImp0aSI6IjU1NjM3NTAzMTBhMzU0OGEwODY0NTc2NGM4MTMyZTQxYmIzZWY2ODI0ZTM1YjZmNWQ3NWYwNjZjMjE1OWZkOTIwY2ZkNjQ0NTUyN2I1MWIyIiwiaWF0IjoxNjI1MDM0NDE3Ljc0OTA4NSwibmJmIjoxNjI1MDM0NDE3Ljc0OTA4NywiZXhwIjoxNjU2NTcwNDE3LjczOTMyMiwic3ViIjoiMSIsInNjb3BlcyI6W119.U8CaPuvjw_ZTrEevH6Qhi_O9Mu7eQcDhzwXrLw8lR1tC_NBm2i6JOmRK_uRSA4xt4-J_AJtsBv7PnWE-p8FznsbS6gABGmzrU2GX6u0ByiwcawbkmkPhN28gdBxf-wwvFevsUbFtT71xt3n4xOzpuD91uxKsHDOBz3Hw0X0dsqiw1s-MuHfRNBNoG1qKwtv3lGoBIuAyiqqxyDG53hDdrx7_A23Jop7XtSktWLfdhLNXG4rquK24ETDwtdfwEqdneL1QWf8Q-fcJGne-j5Rar9x8aupSM7rcNe-Tzw4iYzRk6fzB6ERYj4nfRbPTmIGfjw5Km3aysTvOjVvS3fL_poEay4dD7X_TQj-k5g4ZfRiGq6aPhoN4IEq0DMVAC17Za9uhjbOq_Fn-MfMAaOlX6bP-1bMZoclqsw8x1IQIyAbkPvFORS4wsx7QqrmYjTTsXGbUudfWbvaSLPLhF6h50BvHoVV719qulsq69yLBAkDs8ZIuiJ8VtH5-vHTmHVfvQUjg0WZKi6ZiQXEZvydyaJ6Hk8Fscg6e-tz3xcGUAwzIqrIRYggGkhiGRHa49JmgVf8-MMqFUb6rak4N5xhMZVX9cWt4S7vDuCQcyfHryV-wZ4qp0kLueon_abu_zgmEUu-nn1FBtCRY3h8ODK_aFIgD0N3UQtYebfbJx34yoAg" +baseUrl = "https://accounts.rouggy.com" +endPoint = "api/v1/transactions" + +url = baseUrl + "/" + endPoint +my_headers = {'Authorization': f"Bearer {token}", 'accept': 'application/json', 'Content-Type': 'application/json'} + + +def uploadTransaction(t): + global data + + transaction = Transactions() + + # Get last id in the database and increment it. + try: + transaction = Transactions.select().order_by(Transactions.id.desc()).get() + t.id = transaction.id + 1 + except: + t.id = 1 + + if t.amount < 0: + t.amount = abs(t.amount) + + if t.type == "withdrawal": + + data = { + "error_if_duplicate_hash": "false", + "apply_rules": "true", + "transactions": [ + { + "type": "withdrawal", + "date": t.payment_date, + "amount": t.amount, + "description": t.description, + "currency_code": t.currency, + "category_name": t.category, + "source_name": t.asset_account, + "destination_name": t.opposing_account, + "tags": t.tag, + "external_id": t.id + } + ] + } + + + elif t.type == "transfer": + + if t.opposing_account == "HSBC Vietnam [Shared] Credit Card (VND)" or t.opposing_account == "HSBC Vietnam [Shared] Current Account (VND)": + t.foreign_currency_code = "VND" + elif t.opposing_account == "Societe Generale [Perso] Gregory Current Account (EUR)": + t.foreign_currency_code = "EUR" + elif t.opposing_account == "HSBC Vietnam [Shared] Savings Account (USD)" or t.opposing_account == "HSBC Vietnam [Perso] Gregory Savings Account (USD)": + t.foreign_currency_code = "USD" + + if t.asset_account == "HSBC Vietnam [Shared] Savings Account (USD)" and t.opposing_account == "HSBC Vietnam [Shared] Credit Card (VND)" or t.opposing_account == "HSBC Vietnam [Shared] Current Account (VND)": + t.save(force_insert=True) + return + + if t.currency != t.foreign_currency_code and t.foreign_currency_code is not None: + if t.currency == "VND" and t.foreign_currency_code == "USD": + + t.foreign_currency_amount = t.amount / 23100 + t.foreign_currency_amount = (math.ceil(t.amount / 100) * 100) + + data = { + "error_if_duplicate_hash": "false", + "apply_rules": "true", + "transactions": [ + { + "type": "transfer", + "date": t.payment_date, + "amount": t.amount, + "description": t.description, + "currency_code": t.currency, + "category_name": t.category, + "foreign_amount": t.foreign_currency_amount, + "foreign_currency_code": t.foreign_currency_code, + "source_name": t.asset_account, + "destination_name": t.opposing_account, + "tags": t.tag, + "external_id": t.id + } + ] + } + + else: + + data = { + "error_if_duplicate_hash": "false", + "apply_rules": "true", + "transactions": [ + { + "type": "transfer", + "date": t.payment_date, + "amount": t.amount, + "description": t.description, + "currency_code": t.currency, + "category_name": t.category, + "source_name": t.asset_account, + "destination_name": t.opposing_account, + "tags": t.tag, + "external_id": t.id + } + ] + } + + elif t.type == "deposit": + + data = { + "error_if_duplicate_hash": "false", + "apply_rules": "true", + "transactions": [ + { + "type": "deposit", + "date": t.payment_date, + "amount": t.amount, + "description": t.description, + "currency_code": t.currency, + "category_name": t.category, + "source_name": t.asset_account, + "destination_name": t.opposing_account, + "tags": t.tag, + "external_id": t.id + } + ] + } + + post = requests.post(url, headers=my_headers, json=data) + print(f"Imported into Firefly the transaction {t.description} for an amount of: {t.currency}{t.amount} from " + f"{t.asset_account} to {t.opposing_account}") + print(f"Results: {post.text}") + + t.save(force_insert=True) \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..d5cb33c --- /dev/null +++ b/app.py @@ -0,0 +1,50 @@ +import os, codecs, sys +from transaction import * +from models.transactions import * + +#create_tables() + +# delete csv output files if already exists +for root, dirs, files in os.walk('output'): + for file in files: + if file.endswith(".csv"): + os.remove(f"{root}/{file}") + +for root, dirs, files in os.walk('accounts'): + for file in files: + file_name = f"{root}/{file}" + with codecs.open(file_name, 'r', encoding='utf-8-sig') as f: + for line in f: + line = line.strip() + # check if transaction already exists in the db which means it has been updated in Firefly 3 already + transaction = Transactions.get_or_none(Transactions.raw_line.contains(line)) + # transaction = Transactions.select().where(Transactions.raw_line==line.strip()) + if transaction is None: + + # if does not exist create new transaction + t = Transactions() + t.raw_line = line + t.tag = "" + + if root == "accounts\\HSBC_ATM_VND": + t.account_name = Accounts.HSBC_ATM_VND.value + t.asset_account = Accounts.HSBC_ATM_VND.value + t.currency = "VND" + t.account_short_name = Accounts.HSBC_ATM_VND.name + createTransactionCurrentVND(t) + elif root == "accounts\\HSBC_CreditCard_VND": + t.account_name = Accounts.HSBC_CreditCard_VND.value + t.asset_account = Accounts.HSBC_CreditCard_VND.value + t.currency = "VND" + t.account_short_name = Accounts.HSBC_CreditCard_VND.name + createTransactionCreditCardVND(t) + elif root == "accounts\\SG_Greg_EUR": + t.account_name = Accounts.SG_Greg_EUR.value + t.asset_account = Accounts.SG_Greg_EUR.value + t.currency = "EUR" + t.account_short_name = Accounts.SG_Greg_EUR.name + createTransactionSGEUR(t) + + else: + print("This bank account does not exist...") + diff --git a/data/master.json b/data/master.json new file mode 100644 index 0000000..0ef380d --- /dev/null +++ b/data/master.json @@ -0,0 +1,734 @@ +[ { + "regex": "PIZZA 4PS", + "type": "withdrawal", + "description": "4P's Restaurant", + "asset_account": "", + "opposing_account": "4P's Restaurant", + "default_category": "Lunch Restaurant", + "tag": "" + }, + { + "regex": "(ANNAM GOURMET MARKET|AN NAM GOURMET)", + "type": "withdrawal", + "description": "Annam Gourmet Market", + "asset_account": "", + "opposing_account": "Annam Gourmet Market", + "default_category": "Food", + "tag": "" + }, + { + "regex": "MPOS WILDTHYME", + "type": "withdrawal", + "description": "Wildthyme Restaurant", + "asset_account": "", + "opposing_account": "Wildthyme Restaurant", + "default_category": "Entertainment Restaurant", + "tag": "" + }, + + { + "regex": "ESTL-EP-OVS", + "type": "withdrawal", + "description": "OVS", + "asset_account": "", + "opposing_account": "OVS Shop", + "default_category": "Kids", + "tag": "" + }, + { + "regex": "NH CA PHE PV BACOULOS", + "type": "withdrawal", + "description": "Bacoulos Restaurant", + "asset_account": "", + "opposing_account": "Bacoulos Restaurant", + "default_category": "Lunch Restaurant", + "tag": "" + }, + { + "regex": "SIEU THI AN PHU", + "type": "withdrawal", + "description": "An Phu Supermarket", + "asset_account": "", + "opposing_account": "An Phu Supermarket", + "default_category": "Food", + "tag": "" + }, + + { + "regex": "SAI GON PET", + "type": "withdrawal", + "description": "Saigon Pet", + "asset_account": "", + "opposing_account": "Saigon Pet", + "default_category": "Pets", + "tag": "" + }, + + { + "regex": "MEAT WORKS", + "type": "withdrawal", + "description": "Meat Works", + "asset_account": "", + "opposing_account": "Meat Works", + "default_category": "Food", + "tag": "Meat" + }, + + { + "regex": "THU NGUYEN SHOP", + "type": "withdrawal", + "description": "Albetta", + "asset_account": "", + "opposing_account": "Albetta", + "default_category": "Kids", + "tag": "Toys" + }, + { + "regex": "BOOTLEGGERS|BOOTLEG", + "type": "withdrawal", + "description": "Bootleggers", + "asset_account": "", + "opposing_account": "Bootleggers", + "default_category": "Food", + "tag": "" + }, + { + "regex": "A CUT ABOVE", + "type": "withdrawal", + "description": "A Cut Above", + "asset_account": "", + "opposing_account": "A Cut Above", + "default_category": "Daily Expense", + "tag": "Hair" + }, + { + "regex": "PHAP HAI SA", + "type": "withdrawal", + "description": "La Poissonnerie", + "asset_account": "", + "opposing_account": "La Poissonnerie", + "default_category": "Food", + "tag": "" + }, + { + "regex": "CTTNHH TV THIET KE POTS", + "type": "withdrawal", + "description": "Herve Dining Restaurant", + "asset_account": "", + "opposing_account": "Herve Dining Restaurant", + "default_category": "Entertainment Restaurant", + "tag": "" + }, + { + "regex": "(CMI VIETNAM|Centre Medical International)", + "type": "withdrawal", + "description": "Centre Medical International", + "asset_account": "", + "opposing_account": "Centre Medical International", + "default_category": "Medical", + "tag": "" + }, + { + "regex": "FAME NAILS THAO DIEN", + "type": "withdrawal", + "description": "Fame Nails", + "asset_account": "", + "opposing_account": "Fame Nails", + "default_category": "Daily Expense", + "tag": "Nails" + }, + { + "regex": "FAR EAST MEDICAL", + "type": "withdrawal", + "description": "FV Hospital", + "asset_account": "", + "opposing_account": "FV Hospital", + "default_category": "Medical", + "tag": "" + }, + { + "regex": "CHOPP, INC", + "type": "withdrawal", + "description": "Chopp", + "asset_account": "", + "opposing_account": "Chopp", + "default_category": "Food", + "tag": "" + }, + { + "regex": "AU PARC REST", + "type": "withdrawal", + "description": "Au Parc Restaurant", + "asset_account": "", + "opposing_account": "Au Parc Restaurant", + "default_category": "Lunch Restaurant", + "tag": "" + }, + { + "regex": "THE WAREHOUSE", + "type": "withdrawal", + "description": "The Warehouse", + "asset_account": "", + "opposing_account": "The Warehouse", + "default_category": "Alcool", + "tag": "" + }, + { + "regex": "PAYOO-LESQUARE", + "type": "withdrawal", + "description": "Le Square", + "asset_account": "", + "opposing_account": "Le Square", + "default_category": "Food", + "tag": "" + }, + { + "regex": "NAM AN MARKET", + "type": "withdrawal", + "description": "Nam An", + "asset_account": "", + "opposing_account": "Nam An", + "default_category": "Food", + "tag": "" + }, + { + "regex": "HUE - CORNER", + "type": "withdrawal", + "description": "Hue Corner Restaurant", + "asset_account": "", + "opposing_account": "Hue Corner Restaurant", + "default_category": "Lunch Restaurant", + "tag": "" + }, + { + "regex": "MAMA SENS REST", + "type": "withdrawal", + "description": "Mama Sens Restaurant", + "asset_account": "", + "opposing_account": "Mama Sens Restaurant", + "default_category": "Entertainment Restaurant", + "tag": "" + }, + { + "regex": "SUN SEA RESORT", + "type": "withdrawal", + "description": "Sun Sea Resort", + "asset_account": "", + "opposing_account": "Sun Sea Resort", + "default_category": "Holidays", + "tag": "" + }, + { + "regex": "PHARMACITY", + "type": "withdrawal", + "description": "Pharmacity", + "asset_account": "", + "opposing_account": "Pharmacity", + "default_category": "Medical", + "tag": "" + }, + { + "regex": "ATMA837", + "type": "transfer", + "description": "Cash Withdrawal", + "asset_account": "", + "opposing_account": "Cash Wallet", + "default_category": "Cash", + "tag": "" + }, + { + "regex": "PK ESTELLA", + "type": "withdrawal", + "description": "Estella Mall", + "asset_account": "", + "opposing_account": "Estella Mall", + "default_category": "Medical", + "tag": "" + }, + { + "regex": "(AA Stop|VU Ngoc Thu|VU NGOC THU)", + "type": "withdrawal", + "description": "Coco's Milk", + "asset_account": "", + "opposing_account": "AA Stop Shop", + "default_category": "Kids", + "tag": "Milk" + }, + { + "regex": "PLUS", + "type": "withdrawal", + "description": "Cash Withdrawal", + "asset_account": "", + "opposing_account": "Cash Wallet", + "default_category": "Cash", + "tag": "" + }, + { + "regex": "THUC PHAM SACH LEGUMES", + "type": "withdrawal", + "description": "Legumes Shop", + "asset_account": "", + "opposing_account": "Legumes Shop", + "default_category": "Food", + "tag": "Vegetables,Bio" + }, + { + "regex": "(TRANSFER 091-846345-141 Greg)", + "type": "transfer", + "description": "Bank Transfer from Savings USD to Current VND", + "asset_account": "HSBC Vietnam [Shared] Savings Account (USD)", + "opposing_account": "HSBC Vietnam [Shared] Current Account (VND)", + "default_category": "Bank Transfer", + "tag": "" + }, + { + "regex": "(091-844902-141 Greg Savings)", + "type": "transfer", + "description": "Bank Transfer from Savings USD to Greg Savings", + "asset_account": "HSBC Vietnam [Shared] Savings Account (USD)", + "opposing_account": "HSBC Vietnam [Perso] Gregory Savings Account (USD)", + "default_category": "Bank Transfer", + "tag": "" + }, + { + "regex": "(091-846345-001 Greg)", + "type": "transfer", + "description": "Bank Transfer from Savings USD to Current VND", + "asset_account": "HSBC Vietnam [Shared] Savings Account (USD)", + "opposing_account": "HSBC Vietnam [Shared] Current Account (VND)", + "default_category": "Bank Transfer", + "tag": "" + }, + { + "regex": "(MSC VIET NAM SALARY)", + "type": "deposit", + "description": "Salary & Bonus", + "asset_account": "MSC Vietnam", + "opposing_account": "HSBC Vietnam [Shared] Savings Account (USD)", + "default_category": "Salary & Bonus", + "tag": "" + }, + { + "regex": "BILLED FINANCE CHARGES", + "type": "withdrawal", + "description": "Bank Charges (Interest)", + "asset_account": "", + "opposing_account": "HSBC Bank", + "default_category": "Bank Charges", + "tag": "" + }, + { + "regex": "OVHSINGAPOR", + "type": "withdrawal", + "description": "OVH Singapore", + "asset_account": "", + "opposing_account": "OVH Singapore", + "default_category": "Entertainment Internet", + "tag": "" + }, + { + "regex": "NordVPNcom", + "type": "withdrawal", + "description": "NordVPN", + "asset_account": "", + "opposing_account": "NordVPN", + "default_category": "Entertainment Internet", + "tag": "" + }, + { + "regex": "FASTUSENET", + "type": "withdrawal", + "description": "Usenet Fast Usenet", + "asset_account": "", + "opposing_account": "Fast Usenet", + "default_category": "Entertainment Internet", + "tag": "" + }, + { + "regex": "EXPRESSVPN", + "type": "withdrawal", + "description": "Express VPN", + "asset_account": "", + "opposing_account": "Express VPN", + "default_category": "Entertainment Internet", + "tag": "VPN" + }, + { + "regex": "EDUARDOANDI", + "type": "withdrawal", + "description": "Eduardo Andi", + "asset_account": "", + "opposing_account": "Eduardo Andi", + "default_category": "Entertainment Television", + "tag": "Plex" + }, + { + "regex": "WHATBOX INC", + "type": "withdrawal", + "description": "Whatbox Seedbox", + "asset_account": "", + "opposing_account": "Whatbox", + "default_category": "Entertainment Internet", + "tag": "Seedbox" + }, + { + "regex": "NETFLIX", + "type": "withdrawal", + "description": "Netflix", + "asset_account": "", + "opposing_account": "Netflix", + "default_category": "Entertainment Television", + "tag": "" + }, + { + "regex": "AMZN Mktp US", + "type": "withdrawal", + "description": "Amazon US", + "asset_account": "", + "opposing_account": "Amazon US", + "default_category": "Entertainment", + "tag": "" + }, + { + "regex": "(PAY BY 091-846345-141 TO 5460 2200 0036 8361|5460 2200 0036 8361 Greg)", + "type": "transfer", + "description": "Bank Transfer to Credit Card", + "asset_account": "HSBC Vietnam [Shared] Savings Account (USD)", + "opposing_account": "HSBC Vietnam [Shared] Credit Card (VND)", + "default_category": "Bank Transfer", + "tag": "" + }, + { + "regex": "BIG C THAO DIEN", + "type": "withdrawal", + "description": "BigC", + "asset_account": "", + "opposing_account": "BigC", + "default_category": "Food", + "tag": "" + }, + { + "regex": "CC 77 QHUONG HCM", + "type": "withdrawal", + "description": "Cong Cung", + "asset_account": "", + "opposing_account": "Cong Cung", + "default_category": "Food", + "tag": "" + }, + { + "regex": "YERSIN CLINIC", + "type": "withdrawal", + "description": "Yersin Clinic", + "asset_account": "", + "opposing_account": "Yersin Clinic", + "default_category": "Medical", + "tag": "" + }, + { + "regex": "PAYPAL COMMERCE ELECTRONIQUE", + "type": "withdrawal", + "description": "Paypal", + "asset_account": "", + "opposing_account": "Paypal", + "default_category": "Entertainment", + "tag": "" + }, + { + "regex": "FREE MOBILE", + "type": "withdrawal", + "description": "Free", + "asset_account": "", + "opposing_account": "Free", + "default_category": "Phone", + "tag": "" + }, + { + "regex": "(MolotovTV|Molotov)", + "type": "withdrawal", + "description": "Molotov TV", + "asset_account": "", + "opposing_account": "MolotovTV", + "default_category": "Entertainment Television", + "tag": "" + }, + { + "regex": "SOGECAP", + "type": "transfer", + "description": "PERP Retirement", + "asset_account": "", + "opposing_account": "Societe Generale [Perso] Gregory Current PERP (EUR)", + "default_category": "Savings", + "tag": "" + }, + { + "regex": "ProRealTime", + "type": "withdrawal", + "description": "Pro Real Time", + "asset_account": "", + "opposing_account": "Pro Real Time", + "default_category": "Stock Exchange", + "tag": "" + }, + { + "regex": "(Sony COMMERCE ELECTRONIQUE|Playstation COMMERCE ELECTRONIQUE|PLAYSTATIONNETWORK)", + "type": "withdrawal", + "description": "Sony Games PS4", + "asset_account": "", + "opposing_account": "Sony", + "default_category": "Entertainment Games", + "tag": "PS4" + }, + { + "regex": "(MINIMUM FORFAITAIRE|FRAIS PAIEMENT HORS ZONE EURO)", + "type": "withdrawal", + "description": "Bank Charges", + "asset_account": "", + "opposing_account": "Societe Generale", + "default_category": "Bank Charges", + "tag": "" + }, + { + "regex": "UNISURE LIMITED-EUR", + "type": "withdrawal", + "description": "Unilife Insurance", + "asset_account": "", + "opposing_account": "Unilife Insurance", + "default_category": "Life Insurance", + "tag": "" + }, + { + "regex": "AMERICAN EXPRESS CARTE FRANCE MOTIF: Remboursement", + "type": "deposit", + "description": "American Express Refund", + "asset_account": "American Express", + "opposing_account": "Societe Generale [Perso] Gregory Current Account (EUR)", + "default_category": "Income", + "tag": "" + }, + { + "regex": "SALAUN OU MME BRETON", + "type": "deposit", + "description": "Bank Transfer from HSBC France", + "asset_account": "HSBC France", + "opposing_account": "Societe Generale [Perso] Gregory Current Account (EUR)", + "default_category": "Income", + "tag": "" + }, + { + "regex": "(VIR INS.*Mintos Marketplace)", + "type": "deposit", + "description": "Mintos", + "asset_account": "Mintos", + "opposing_account": "Societe Generale [Perso] Gregory Current Account (EUR)", + "default_category": "Income", + "tag": "" + }, + { + "regex": "(VIR RECU.*MME VIOLETTE ANDRE)", + "type": "deposit", + "description": "Bank Transfer From Violette", + "asset_account": "Violette", + "opposing_account": "Societe Generale [Perso] Gregory Current Account (EUR)", + "default_category": "Income", + "tag": "" + }, + { + "regex": "(VIR EUROPEEN EMIS.*Melody)", + "type": "deposit", + "description": "Transfer to Melody", + "asset_account": "", + "opposing_account": "Melody", + "default_category": "Entertainment", + "tag": "" + }, + { + "regex": "TENUE DE COMPTE", + "type": "withdrawal", + "description": "Bank Charges", + "asset_account": "", + "opposing_account": "Societe Generale", + "default_category": "Bank Charges", + "tag": "" + }, + { + "regex": "REF UNION", + "type": "withdrawal", + "description": "Ref Union Fees", + "asset_account": "", + "opposing_account": "REF Union", + "default_category": "Entertainment", + "tag": "Ham Radio" + }, + { + "regex": "AMENDE.GOUV", + "type": "withdrawal", + "description": "Government Fines", + "asset_account": "", + "opposing_account": "French Government", + "default_category": "Other", + "tag": "" + }, + { + "regex": "PAYOO BILL PMT/TT HOADON", + "type": "withdrawal", + "description": "Electricity Bill", + "asset_account": "", + "opposing_account": "EVN HCMC", + "default_category": "Utilities", + "tag": "Electricity" + }, + { + "regex": "UNCLE BILLS", + "type": "withdrawal", + "description": "Uncle Bills", + "asset_account": "", + "opposing_account": "Uncle Bills", + "default_category": "Kids", + "tag": "" + }, + { + "regex": "COTISATION ANNUELLE CARTE Visa X1533", + "type": "withdrawal", + "description": "Visa Card Fees", + "asset_account": "", + "opposing_account": "Societe Generale", + "default_category": "Bank Charges", + "tag": "" + }, + { + "regex": "MAD HOUSE RESTAURANT", + "type": "withdrawal", + "description": "Mad House Restaurant", + "asset_account": "", + "opposing_account": "Mad House", + "default_category": "Entertainment Restaurant", + "tag": "" + }, + { + "regex": "FAHASA TAN DINH 1", + "type": "withdrawal", + "description": "Fahasa Library", + "asset_account": "", + "opposing_account": "Fahasa Library", + "default_category": "Entertainment Kids", + "tag": "" + }, + { + "regex": "LA ROSA BISTRO", + "type": "withdrawal", + "description": "La Rosa Bistro", + "asset_account": "", + "opposing_account": "La Rosa Bistro", + "default_category": "Lunch Restaurant", + "tag": "" + }, + { + "regex": "THEGIOIDIDONG.COM", + "type": "withdrawal", + "description": "Thegioididong", + "asset_account": "", + "opposing_account": "Thegioididong", + "default_category": "Entertainment Computer", + "tag": "" + }, + { + "regex": "NH BEIRUT", + "type": "withdrawal", + "description": "Beirut Restaurant", + "asset_account": "", + "opposing_account": "Beirut Restaurant", + "default_category": "Entertainment Restaurant", + "tag": "" + }, + { + "regex": "PHT SAIGON TRADING LIMIT", + "type": "withdrawal", + "description": "In The Mood", + "asset_account": "", + "opposing_account": "In The Mood", + "default_category": "Entertainment", + "tag": "" + }, + { + "regex": "GUARDIAN SHOP 99", + "type": "withdrawal", + "description": "Guardian Shop", + "asset_account": "", + "opposing_account": "Guardian Shop", + "default_category": "Daily Expense", + "tag": "" + }, + { + "regex": "APRIL INTERNATIONAL CARE", + "type": "deposit", + "description": "April International", + "asset_account": "", + "opposing_account": "April International", + "default_category": "Medical", + "tag": "" + }, + { + "regex": "DECOSY", + "type": "withdrawal", + "description": "Decosy", + "asset_account": "", + "opposing_account": "Decosy", + "default_category": "Daily Expense", + "tag": "" + }, + { + "regex": "RUSTICO", + "type": "withdrawal", + "description": "Pasta Fresca", + "asset_account": "", + "opposing_account": "Pasta Fresca", + "default_category": "Lunch Restaurant", + "tag": "" + }, + { + "regex": "INNOCENCE PARIS", + "type": "withdrawal", + "description": "Innocence Paris", + "asset_account": "", + "opposing_account": "Innocence Paris", + "default_category": "Other", + "tag": "" + }, + { + "regex": "RAFFLES MEDICAL CLINIC", + "type": "withdrawal", + "description": "Raffles Medical Clinic", + "asset_account": "", + "opposing_account": "Raffles Medical Clinic", + "default_category": "Medical", + "tag": "" + }, + { + "regex": "NGUYEN KIM", + "type": "withdrawal", + "description": "Nguyen Kim", + "asset_account": "", + "opposing_account": "Nguyen Kim", + "default_category": "Appliances", + "tag": "" + }, + { + "regex": "NHA KHOA MINH KHAI HCM VNM", + "type": "withdrawal", + "description": "Starlight Dentist", + "asset_account": "", + "opposing_account": "Starlight", + "default_category": "Medical", + "tag": "" + }, + { + "regex": "SOCOLA MAROU", + "type": "withdrawal", + "description": "Maison Marou", + "asset_account": "", + "opposing_account": "Maison Marou", + "default_category": "Entertainment Restaurant", + "tag": "" + } +] \ No newline at end of file diff --git a/db.py b/db.py new file mode 100644 index 0000000..e69de29 diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/models/__pycache__/__init__.cpython-39.pyc b/models/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..52522f462464c726c5ef53365120ea0826c0e6ef GIT binary patch literal 174 zcmYe~<>g`kg0(X%6F~H15P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;x_;vsFw$YEf~1 zOmJ#qT4qivlowExpI(%ho10jYnV%OEP+5`zq@07pob&U_Qj1Dbi`+7cQqyuOjbn22 jQ&Mw^W8&j8^D;}~qSGcMRt>d6$W#hme3nH@lg@S+nZ(t& z-GlH1yi0Dmf=A#6j@@=tY>xcJ=l}SeW7cjr39ilFmyh3Tg#6IN>Z&8Li(Bp>aKf#W zj0sr0#%=C!mwUW^<<}} zR8Ev&nPibxm)%)eIXXulV@d2b@h#E9->~BdSI74>=$0GyzntbLJt@LL&>Bm7P2Z^5 zb>ZKmbXjmqUSz6rR5=6M7@RUOm-vF6hiQ@l4PIvoVp#AW zoa6$MI18gf2*{!`WK-ke{tZEdb+1|+WF(TAE_<~m^Fl-rE~9RsP$ijZ;gU%kdrZMR ziD1UcDP$_d>43^xMDin~;#`!Ktyp|(Yw&>(z2!p$-}3Nl8q}xdC$z?}<56!0a1KD* thvn$)8w_tIQRvyAu6YWk*GB)gaFzdZKH59_g-AUdzU^DiAJ1NQ{{m<86LkOp literal 0 HcmV?d00001 diff --git a/models/__pycache__/transactions.cpython-39.pyc b/models/__pycache__/transactions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d5ed3e55c778873428b8209c170ec08b86271f6 GIT binary patch literal 1386 zcmZuxUys{F5Z|>O$4Q)PxKfZ1@Q4&1qNb(LtE#FZ)%Aso4&8}At01%IojO(>ue)n= zO<%9#?Zj7rN50aEH(n?offtxvClGOG%fH>3otd54`K|eI*eCe(zxnO^AALf8x5Dnz zMd2}i`Vc`7K?`z9fC^9eA`l%Bitc5Hc~6OmMDH~bJ@7Al7NFc01C$34pxhC$7``Sf z6niIReB%wqB4cXk$1I+md^MBh51?vLEL5_|vNenEA3S-QWp@s4-~H_1RXjboGnsyR ze=?m+@8y5S=o^@z(dZCWTp8b%^BW!26sXH^KaeD;%dTJr+5Qz!f`4s$4k+2?60o3c*y63ON|Y~roXcGU#+x&qdlExBr4 zBE`>>A}_%V1n5-dm2HC=B6*=sHoj>4iv;%(fcVd%|mIL&RrNKDTSg6)