1 /*******************************************************
2 Copyright (C) 2014 Gabriele-V
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 ********************************************************/
18 
19 
20 #include "attachmentdialog.h"
21 #include "webapp.h"
22 #include "model/Model_Setting.h"
23 #include "model/Model_Account.h"
24 #include "model/Model_Attachment.h"
25 #include "model/Model_Category.h"
26 #include "model/Model_Payee.h"
27 #include "model/Model_Subcategory.h"
28 #include "paths.h"
29 #include "transdialog.h"
30 #include "util.h"
31 #include <wx/sstream.h>
32 #include <wx/protocol/http.h>
33 
34 //Expected WebAppVersion
35 const wxString WebAppParam::ApiExpectedVersion = "1.0.1";
36 
37 //Internal constants
getUrl()38 const wxString mmWebApp::getUrl()
39 {
40     wxString Url = Model_Infotable::instance().GetStringInfo("WEBAPPURL", "");
41     Url.Replace("https://", "http://");
42     return Url;
43 }
44 
getGuid()45 const wxString mmWebApp::getGuid()
46 {
47     return Model_Infotable::instance().GetStringInfo("WEBAPPGUID", "");
48 }
49 
50 //Parameters used in services.php
51 const wxString WebAppParam::ServicesPage           = "services.php";
52 const wxString WebAppParam::CheckGuid              = "check_guid";
53 const wxString WebAppParam::CheckApiVersion        = "check_api_version";
54 const wxString WebAppParam::DeleteAccount          = "delete_bankaccount";
55 const wxString WebAppParam::ImportAccount          = "import_bankaccount";
56 const wxString WebAppParam::DeletePayee            = "delete_payee";
57 const wxString WebAppParam::ImportPayee            = "import_payee";
58 const wxString WebAppParam::DeleteCategory         = "delete_category";
59 const wxString WebAppParam::ImportCategory         = "import_category";
60 const wxString WebAppParam::DeleteOneTransaction   = "delete_group";
61 const wxString WebAppParam::DownloadNewTransaction = "download_transaction";
62 const wxString WebAppParam::DownloadAttachments    = "download_attachment";
63 const wxString WebAppParam::DeleteAttachment       = "delete_attachment";
64 const wxString WebAppParam::MessageSuccedeed       = "Operation has succeeded";
65 const wxString WebAppParam::MessageWrongGuid       = "Wrong GUID";
66 
67 // Return services page URL with GUID inserted
getServicesPageURL()68 const wxString mmWebApp::getServicesPageURL()
69 {
70     return mmWebApp::getUrl() + "/" + WebAppParam::ServicesPage + "?" + "guid=" + mmWebApp::getGuid();
71 }
72 
73 //Get WebApp Api version
WebApp_getApiVersion()74 const wxString mmWebApp::WebApp_getApiVersion()
75 {
76     wxString outputMessage;
77     site_content(mmWebApp::getServicesPageURL() + "&" + WebAppParam::CheckApiVersion, outputMessage);
78 
79     return outputMessage;
80 }
81 
82 
83 /***************
84 ** Functions  **
85 ***************/
86 //Return function result
returnResult(int & ErrorCode,wxString & outputMessage)87 bool mmWebApp::returnResult(int& ErrorCode, wxString& outputMessage)
88 {
89     if (ErrorCode == 0 && outputMessage == WebAppParam::MessageSuccedeed)
90         return true;
91     else
92         return false;
93 }
94 
95 //Check if WebApp is enabled
WebApp_CheckEnabled()96 bool mmWebApp::WebApp_CheckEnabled()
97 {
98     if (Model_Infotable::instance().GetStringInfo("WEBAPPURL", "") != wxEmptyString
99         && Model_Infotable::instance().GetStringInfo("WEBAPPGUID", "") != wxEmptyString)
100         return true;
101     else
102         return false;
103 }
104 
105 //Check guid
WebApp_CheckGuid()106 bool mmWebApp::WebApp_CheckGuid()
107 {
108     wxString outputMessage;
109     site_content(mmWebApp::getServicesPageURL() + "&" + WebAppParam::CheckGuid, outputMessage);
110 
111     if (outputMessage == WebAppParam::MessageSuccedeed)
112         return true;
113     else if (outputMessage == WebAppParam::MessageWrongGuid)
114     {
115         wxString msgStr = wxString() << _("Wrong WebApp GUID:") << "\n"
116             << _("please check it in network options.") << "\n";
117         wxMessageBox(msgStr, _("Wrong WebApp settings"), wxICON_ERROR);
118         return false;
119     }
120     else
121     {
122         wxString msgStr = wxString() << _("Unable to connect to WebApp:") << "\n"
123             << _("please check settings and / or internet connection.") << "\n\n"
124             << wxString::Format(_("Error: %s"), "\n" + outputMessage + "\n");
125         wxMessageBox(msgStr, _("WebApp connection error"), wxICON_ERROR);
126         return false;
127     }
128 }
129 
130 //Check WebApp Api version
WebApp_CheckApiVersion()131 bool mmWebApp::WebApp_CheckApiVersion()
132 {
133     if (mmWebApp::WebApp_getApiVersion() != WebAppParam::ApiExpectedVersion)
134     {
135         wxString msgStr = _("Wrong WebApp API version:") + "\n"
136             + wxString::Format(_("WebApp   API version -> %s"), mmWebApp::WebApp_getApiVersion()) + "\n"
137             + wxString::Format(_("Expected API version -> %s"), WebAppParam::ApiExpectedVersion) + "\n";
138         wxMessageBox(msgStr, _("Wrong WebApp API version"), wxICON_ERROR);
139         return false;
140     }
141     else
142         return true;
143 }
144 
145 //POST data as JSON
WebApp_SendJson(wxString & Website,const wxString & JsonData,wxString & Output)146 int mmWebApp::WebApp_SendJson(wxString& Website, const wxString& JsonData, wxString& Output)
147 {
148     wxHTTP http;
149     int ErrorCode = 0;
150 
151     //Build string connection
152     Website.Replace("http://", "");
153     wxString BaseServerAddress = Website.SubString(0, Website.Find("/")-1);
154     wxString PagePath = Website.SubString(Website.Find("/"), Website.Length());
155 
156     //Create multipart form
157     wxString Boundary = "Custom_Boundary_MMEX_WebApp";
158     wxString Text = wxEmptyString;
159     Text.Append(wxString::Format("--%s\r\n", Boundary));
160     Text.Append(wxString::Format("Content-Disposition: form-data; name=\"%s\"\r\n\r\n", "MMEX_Post"));
161     Text.Append(wxString::Format("%s\r\n", JsonData));
162     Text.Append(wxString::Format("\r\n--%s--\r\n", Boundary));
163 
164     http.SetPostText("multipart/form-data; boundary=" + Boundary, Text);
165 
166     if (http.Connect(BaseServerAddress))
167     {
168         ErrorCode = http.GetError();
169         if (ErrorCode == wxPROTO_NOERR)
170         {
171             wxInputStream *httpStream = http.GetInputStream(PagePath);
172             if (httpStream)
173             {
174                 wxStringOutputStream out_stream(&Output);
175                 httpStream->Read(out_stream);
176             }
177             else
178                 ErrorCode = -1;
179             wxDELETE(httpStream);
180         }
181         http.Close();
182     }
183     else
184         ErrorCode = http.GetError();
185 
186     if (ErrorCode != wxPROTO_NOERR)
187     {
188         if (ErrorCode == wxPROTO_NETERR) Output = _("A generic network error occurred");
189         else if (ErrorCode == wxPROTO_PROTERR) Output = _("An error occurred during negotiation");
190         else if (ErrorCode == wxPROTO_CONNERR) Output = _("The client failed to connect the server");
191         else if (ErrorCode == wxPROTO_INVVAL) Output = _("Invalid value");
192         else if (ErrorCode == wxPROTO_NOFILE) Output = _("The remote file doesn't exist");
193         else if (ErrorCode == wxPROTO_RCNCT) Output = _("An error occurred during reconnection");
194         else if (ErrorCode == wxPROTO_STREAMING) Output = _("Someone tried to send a command during a transfer");
195         else if (ErrorCode == -1) Output = _("Cannot get data from website");
196         else Output = _("Unknown error");
197     }
198     return ErrorCode;
199 }
200 
201 
202 //Delete all account on WebApp
WebApp_DeleteAllAccount()203 bool mmWebApp::WebApp_DeleteAllAccount()
204 {
205     wxString outputMessage;
206     int ErrorCode = site_content(mmWebApp::getServicesPageURL() + "&" + WebAppParam::DeleteAccount, outputMessage);
207 
208     return mmWebApp::returnResult(ErrorCode, outputMessage);
209 }
210 
211 // Update Account on WebApp
WebApp_UpdateAccount()212 bool mmWebApp::WebApp_UpdateAccount()
213 {
214     int i = 0;
215     json::Object jsonAccountList;
216     std::wstringstream jsonAccountStream;
217     wxString outputMessage;
218 
219     wxString UpdateAccountUrl = mmWebApp::getServicesPageURL() + "&" + WebAppParam::ImportAccount + "=true";
220 
221     mmWebApp::WebApp_DeleteAllAccount();
222 
223     for (const auto &Account : Model_Account::instance().all(Model_Account::COL_ACCOUNTNAME))
224     {
225         if (Model_Account::type(Account) != Model_Account::INVESTMENT)
226             jsonAccountList[L"Accounts"][i][L"AccountName"] = json::String(Account.ACCOUNTNAME.ToStdWstring());
227         i++;
228     }
229 
230     json::Writer::Write(jsonAccountList, jsonAccountStream);
231     wxString AccountList = jsonAccountStream.str();
232 
233     int ErrorCode = mmWebApp::WebApp_SendJson(UpdateAccountUrl, AccountList, outputMessage);
234 
235     return mmWebApp::returnResult(ErrorCode, outputMessage);
236 }
237 
238 //Delete all payee on WebApp
WebApp_DeleteAllPayee()239 bool mmWebApp::WebApp_DeleteAllPayee()
240 {
241     wxString outputMessage;
242     int ErrorCode = site_content(mmWebApp::getServicesPageURL() + "&" + WebAppParam::DeletePayee, outputMessage);
243 
244     return mmWebApp::returnResult(ErrorCode, outputMessage);
245 }
246 
247 //Update payee on WebApp
WebApp_UpdatePayee()248 bool mmWebApp::WebApp_UpdatePayee()
249 {
250     int i = 0;
251     json::Object jsonPayeeList;
252     std::wstringstream jsonPayeeStream;
253     wxString outputMessage, DefCategoryName, DefSubCategoryName;
254 
255     wxString UpdatePayeeUrl = mmWebApp::getServicesPageURL() + "&" + WebAppParam::ImportPayee + "=true";
256 
257     mmWebApp::WebApp_DeleteAllPayee();
258 
259     for (const auto &Payee : Model_Payee::instance().all(Model_Payee::COL_PAYEENAME))
260     {
261         const Model_Category::Data* DefCategory = Model_Category::instance().get(Payee.CATEGID);
262         if (DefCategory != nullptr)
263             DefCategoryName = DefCategory->CATEGNAME;
264         else
265             DefCategoryName = "None";
266 
267         const Model_Subcategory::Data* DefSubCategory = Model_Subcategory::instance().get(Payee.SUBCATEGID);
268         if (DefSubCategory != nullptr)
269             DefSubCategoryName = DefSubCategory->SUBCATEGNAME;
270         else
271             DefSubCategoryName = "None";
272 
273         jsonPayeeList[L"Payees"][i][L"PayeeName"] = json::String(Payee.PAYEENAME.ToStdWstring());
274         jsonPayeeList[L"Payees"][i][L"DefCateg"] = json::String(DefCategoryName.ToStdWstring());
275         jsonPayeeList[L"Payees"][i][L"DefSubCateg"] = json::String(DefSubCategoryName.ToStdWstring());
276 
277         i++;
278     }
279 
280     json::Writer::Write(jsonPayeeList, jsonPayeeStream);
281     wxString PayeesList = jsonPayeeStream.str();
282 
283     int ErrorCode = mmWebApp::WebApp_SendJson(UpdatePayeeUrl, PayeesList, outputMessage);
284 
285     return mmWebApp::returnResult(ErrorCode, outputMessage);
286 }
287 
288 //Delete all category on WebApp
WebApp_DeleteAllCategory()289 bool mmWebApp::WebApp_DeleteAllCategory()
290 {
291     wxString outputMessage;
292     int ErrorCode = site_content(mmWebApp::getServicesPageURL() + "&" + WebAppParam::DeleteCategory, outputMessage);
293 
294     return mmWebApp::returnResult(ErrorCode, outputMessage);
295 }
296 
297 //Update category on WebApp
WebApp_UpdateCategory()298 bool mmWebApp::WebApp_UpdateCategory()
299 {
300     int i = 0;
301     json::Object jsonCategoryList;
302     std::wstringstream jsonCategoryStream;
303     wxString outputMessage, SubCategoryName;
304 
305     wxString UpdateCategoryUrl = mmWebApp::getServicesPageURL() + "&" + WebAppParam::ImportCategory + "=true";
306 
307     mmWebApp::WebApp_DeleteAllCategory();
308 
309     const auto &categories = Model_Category::instance().all();
310     for (const Model_Category::Data& category : categories)
311     {
312         bool FirstCategoryRun = true;
313         bool SubCategoryFound = false;
314         jsonCategoryList[L"Categories"][i][L"CategoryName"] = json::String(category.CATEGNAME.ToStdWstring());
315         for (const auto &sub_category : Model_Category::sub_category(category))
316         {
317             SubCategoryFound = true;
318             if (FirstCategoryRun == true)
319             {
320                 jsonCategoryList[L"Categories"][i][L"SubCategoryName"] = json::String(sub_category.SUBCATEGNAME.ToStdWstring());
321                 i++;
322                 FirstCategoryRun = false;
323             }
324             else
325             {
326                 jsonCategoryList[L"Categories"][i][L"CategoryName"] = json::String(category.CATEGNAME.ToStdWstring());
327                 jsonCategoryList[L"Categories"][i][L"SubCategoryName"] = json::String(sub_category.SUBCATEGNAME.ToStdWstring());
328                 i++;
329                 FirstCategoryRun = false;
330             }
331         }
332 
333         if (SubCategoryFound == false)
334             jsonCategoryList[L"Categories"][i][L"SubCategoryName"] = json::String(L"None");
335         else
336             i--;
337 
338         i++;
339     }
340 
341     json::Writer::Write(jsonCategoryList, jsonCategoryStream);
342     wxString CategoryList = jsonCategoryStream.str();
343 
344     int ErrorCode = mmWebApp::WebApp_SendJson(UpdateCategoryUrl, CategoryList, outputMessage);
345 
346     return mmWebApp::returnResult(ErrorCode, outputMessage);
347 }
348 
349 //Download new transactions
WebApp_DownloadNewTransaction(WebTranVector & WebAppTransactions_,const bool & CheckOnly)350 bool mmWebApp::WebApp_DownloadNewTransaction(WebTranVector& WebAppTransactions_, const bool& CheckOnly)
351 {
352     wxString NewTransactionJSON;
353     int ErrorCode = site_content(mmWebApp::getServicesPageURL() + "&" + WebAppParam::DownloadNewTransaction, NewTransactionJSON);
354 
355     if (NewTransactionJSON == "null" || NewTransactionJSON.IsEmpty() || ErrorCode != 0)
356         return false;
357     else if (CheckOnly)
358         return true;
359     else
360     {
361         json::Object jsonTransaction;
362         std::wstringstream jsonTransactionStream;
363 
364         if (!(NewTransactionJSON.StartsWith("{") && NewTransactionJSON.EndsWith("}"))) return true;
365         jsonTransactionStream << NewTransactionJSON.ToStdWstring();
366         json::Reader::Read(jsonTransaction, jsonTransactionStream);
367 
368         //Define variables
369         webtran_holder WebTran;
370         WebAppTransactions_.clear();
371         std::wstring TrProgrStr;
372         wxDateTime dt;
373         wxString dtStr,Payee,Category,SubCategory;
374 
375         for (int i = 0; i < static_cast<int>(jsonTransaction.Size()); i++)
376         {
377             TrProgrStr = std::to_wstring(i);
378 
379             WebTran.ID = wxAtoi(wxString(json::String(jsonTransaction[TrProgrStr][L"ID"])));
380 
381             dtStr = wxString(json::String(jsonTransaction[TrProgrStr][L"Date"]));
382             mmParseDisplayStringToDate(dt, dtStr, "%Y-%m-%d");
383             WebTran.Date = dt;
384 
385             WebTran.Account = wxString(json::String(jsonTransaction[TrProgrStr][L"Account"]));
386             WebTran.ToAccount = wxString(json::String(jsonTransaction[TrProgrStr][L"ToAccount"]));
387             WebTran.Status = wxString(json::String(jsonTransaction[TrProgrStr][L"Status"]));
388             WebTran.Type = wxString(json::String(jsonTransaction[TrProgrStr][L"Type"]));
389 
390             Payee = wxString(json::String(jsonTransaction[TrProgrStr][L"Payee"]));
391             if (Payee == "None" || Payee.IsEmpty()) Payee = _("Unknown");
392             WebTran.Payee = Payee;
393 
394             Category = wxString(json::String(jsonTransaction[TrProgrStr][L"Category"]));
395             if (Category == "None" || Category.IsEmpty()) Category = _("Unknown");
396             WebTran.Category = Category;
397 
398             SubCategory = wxString(json::String(jsonTransaction[TrProgrStr][L"SubCategory"]));
399             if (SubCategory == "None" || SubCategory.IsEmpty()) SubCategory = wxEmptyString;
400             WebTran.SubCategory = SubCategory;
401 
402             //Amount -> TODO: Test with json::Number
403             wxString jsonAmount = wxString(json::String(jsonTransaction[TrProgrStr][L"Amount"]));
404             double TransactionAmount; jsonAmount.ToDouble(&TransactionAmount);
405             WebTran.Amount = TransactionAmount;
406 
407             WebTran.Notes = wxString(json::String(jsonTransaction[TrProgrStr][L"Notes"]));
408             WebTran.Attachments = wxString(json::String(jsonTransaction[TrProgrStr][L"Attachments"]));
409 
410             WebAppTransactions_.push_back(WebTran);
411         }
412         return true;
413     }
414 }
415 
416 //Insert new transaction
MMEX_InsertNewTransaction(webtran_holder & WebAppTrans)417 int mmWebApp::MMEX_InsertNewTransaction(webtran_holder& WebAppTrans)
418 {
419     int DeskNewTrID = 0;
420     bool bDeleteTrWebApp = false;
421 
422     int AccountID = -1;
423     int ToAccountID = -1;
424     int PayeeID = -1;
425     int CategoryID = -1;
426     int SubCategoryID = -1;
427     wxString TrStatus;
428 
429     //Search Account
430     const Model_Account::Data* Account = Model_Account::instance().get(WebAppTrans.Account);
431     if (Account != nullptr)
432     {
433         AccountID = Account->ACCOUNTID;
434         TrStatus = WebAppTrans.Status;
435     }
436     else
437     {
438         TrStatus = "F";
439         wxString FistAccountName;
440 
441         //Search first bank account
442         for (const auto &FirstAccount : Model_Account::instance().all(Model_Account::COL_ACCOUNTNAME))
443         {
444             if (Model_Account::type(FirstAccount) != Model_Account::INVESTMENT && Model_Account::type(FirstAccount) != Model_Account::TERM)
445             {
446                 FistAccountName = FirstAccount.ACCOUNTNAME;
447                 AccountID = FirstAccount.ACCOUNTID;
448                 break;
449             }
450         }
451 
452         wxString msgStr = wxString::Format(_("Account '%s' not found!"), WebAppTrans.Account)
453             << "\n\n"
454             << wxString::Format(_("Transaction will be inserted with the first bank account:\n'%s' and marked as  'Follow Up'")
455             , FistAccountName) << "\n";
456         wxMessageBox(msgStr, _("Wrong WebApp account"), wxICON_ERROR);
457     }
458 
459     //Search ToAccount
460     if (WebAppTrans.ToAccount != "None")
461     {
462         const Model_Account::Data* ToAccount = Model_Account::instance().get(WebAppTrans.ToAccount);
463         if (ToAccount != nullptr)
464             ToAccountID = ToAccount->ACCOUNTID;
465     }
466 
467     //Search or insert Category
468     const Model_Category::Data* Category = Model_Category::instance().get(WebAppTrans.Category);
469     if (Category != nullptr)
470         CategoryID = Category->CATEGID;
471     else
472     {
473         Model_Category::Data* NewCategory = Model_Category::instance().create();
474         NewCategory->CATEGNAME = WebAppTrans.Category;
475         int NewCategoryID = Model_Category::instance().save(NewCategory);
476         CategoryID = NewCategoryID;
477     }
478 
479     //Search or insert SubCategory
480     if (!WebAppTrans.SubCategory.IsEmpty())
481     {
482         const Model_Subcategory::Data* SubCategory = Model_Subcategory::instance().get(WebAppTrans.SubCategory, CategoryID);
483         if (SubCategory != nullptr)
484             SubCategoryID = SubCategory->SUBCATEGID;
485         else if (CategoryID != -1)
486         {
487             Model_Subcategory::Data* NewSubCategory = Model_Subcategory::instance().create();
488             NewSubCategory->CATEGID = CategoryID;
489             NewSubCategory->SUBCATEGNAME = WebAppTrans.SubCategory;
490             int NewSubCategoryID = Model_Subcategory::instance().save(NewSubCategory);
491             SubCategoryID = NewSubCategoryID;
492         }
493     }
494 
495     //Search or insert Payee
496     const Model_Payee::Data* Payee = Model_Payee::instance().get(WebAppTrans.Payee);
497     if (Payee != nullptr)
498         PayeeID = Payee->PAYEEID;
499     else
500     {
501         Model_Payee::Data* NewPayee = Model_Payee::instance().create();
502         NewPayee->PAYEENAME = WebAppTrans.Payee;
503         NewPayee->CATEGID = CategoryID;
504         NewPayee->SUBCATEGID = SubCategoryID;
505         int NewPayeeID = Model_Payee::instance().save(NewPayee);
506         PayeeID = NewPayeeID;
507     }
508 
509     //Create New Transaction
510     Model_Checking::Data * desktopNewTransaction;
511     desktopNewTransaction = Model_Checking::instance().create();
512     desktopNewTransaction->TRANSDATE = WebAppTrans.Date.FormatISODate();
513     desktopNewTransaction->STATUS = TrStatus;
514     desktopNewTransaction->TRANSCODE = WebAppTrans.Type;
515     desktopNewTransaction->TRANSAMOUNT = WebAppTrans.Amount;
516     desktopNewTransaction->ACCOUNTID = AccountID;
517     desktopNewTransaction->TOACCOUNTID = ToAccountID;
518     desktopNewTransaction->PAYEEID = PayeeID;
519     desktopNewTransaction->CATEGID = CategoryID;
520     desktopNewTransaction->SUBCATEGID = SubCategoryID;
521     desktopNewTransaction->TRANSACTIONNUMBER = "";
522     desktopNewTransaction->NOTES = WebAppTrans.Notes;
523     desktopNewTransaction->FOLLOWUPID = -1;
524     desktopNewTransaction->TOTRANSAMOUNT = WebAppTrans.Amount;
525 
526     DeskNewTrID = Model_Checking::instance().save(desktopNewTransaction);
527 
528     if (DeskNewTrID > 0)
529     {
530         if (!WebAppTrans.Attachments.IsEmpty())
531         {
532             wxString AttachmentsFolder = mmex::getPathAttachment(mmAttachmentManage::InfotablePathSetting());
533             if (AttachmentsFolder == wxEmptyString || !wxDirExists(AttachmentsFolder))
534             {
535                 DeskNewTrID = Model_Checking::instance().remove(DeskNewTrID);
536                 DeskNewTrID = -1;
537 
538                 wxString msgStr = wxString() << _("Unable to download attachments from webapp.") << "\n"
539                     << _("Attachments folder not set or unavailable") << "\n" << "\n"
540                     << _("Transaction not downloaded:") << "\n"
541                     << _("please fix attachments folder or delete attachments from WebApp") << "\n";
542                 wxMessageBox(msgStr, _("Attachment folder error"), wxICON_ERROR);
543             }
544             else
545             {
546                 int AttachmentNr = 0;
547                 wxString WebAppAttachmentName, DesktopAttachmentName;
548                 wxArrayString AttachmentsArray;
549                 wxStringTokenizer tkz1(WebAppTrans.Attachments, (';'), wxTOKEN_RET_EMPTY_ALL);
550                 while (tkz1.HasMoreTokens())
551                     {AttachmentsArray.Add(tkz1.GetNextToken());}
552                 for (size_t i = 0; i < AttachmentsArray.GetCount(); i++)
553                 {
554                     AttachmentNr++;
555                     WebAppAttachmentName = AttachmentsArray.Item(i);
556                     DesktopAttachmentName = WebApp_DownloadOneAttachment(WebAppAttachmentName, DeskNewTrID, AttachmentNr);
557                     if (DesktopAttachmentName != wxEmptyString)
558                     {
559                         Model_Attachment::Data* NewAttachment = Model_Attachment::instance().create();
560                             NewAttachment->REFTYPE = Model_Attachment::reftype_desc(Model_Attachment::TRANSACTION);
561                             NewAttachment->REFID = DeskNewTrID;
562                             NewAttachment->DESCRIPTION = _("Attachment") + "_" << AttachmentNr;
563                             NewAttachment->FILENAME = DesktopAttachmentName;
564                         Model_Attachment::instance().save(NewAttachment);
565                     }
566                     else
567                     {
568                         DeskNewTrID = Model_Checking::instance().remove(DeskNewTrID);
569                         DeskNewTrID = -1;
570 
571                         wxString msgStr = wxString() << _("Unable to download attachments from webapp.") << "\n"
572                             << _("Communication error") << "\n" << "\n"
573                             << _("Transaction not downloaded: please close and open MMEX to try re-download transaction") << "\n";
574                         wxMessageBox(msgStr, _("Attachment download error"), wxICON_ERROR);
575                         break;
576                     }
577 
578                     WebAppAttachmentName = wxEmptyString;
579 
580                 } //End loop throught attachments
581                 bDeleteTrWebApp = true;
582             }
583         }
584         else //Transaction without attachments
585         {
586             bDeleteTrWebApp = true;
587         }
588     }
589 
590     if (bDeleteTrWebApp)
591         WebApp_DeleteOneTransaction(WebAppTrans.ID);
592     return DeskNewTrID;
593 }
594 
595 //Delete one transaction from WebApp
WebApp_DeleteOneTransaction(int WebAppTransactionId)596 bool mmWebApp::WebApp_DeleteOneTransaction(int WebAppTransactionId)
597 {
598     wxString DeleteOneTransactionUrl = mmWebApp::getServicesPageURL() + "&" + WebAppParam::DeleteOneTransaction + "=" << WebAppTransactionId;
599 
600     wxString outputMessage;
601     int ErrorCode = site_content(DeleteOneTransactionUrl, outputMessage);
602 
603     return mmWebApp::returnResult(ErrorCode, outputMessage);
604 }
605 
606 //Download one attachment from WebApp
WebApp_DownloadOneAttachment(const wxString & AttachmentName,int DesktopTransactionID,int AttachmentNr)607 wxString mmWebApp::WebApp_DownloadOneAttachment(const wxString& AttachmentName, int DesktopTransactionID, int AttachmentNr)
608 {
609     wxString FileExtension = wxFileName(AttachmentName).GetExt().MakeLower();
610     wxString FileName = Model_Attachment::reftype_desc(Model_Attachment::TRANSACTION) + "_" + wxString::Format("%i", DesktopTransactionID)
611         + "_Attach" + wxString::Format("%i", AttachmentNr) + "." + FileExtension;
612     wxString FilePath = mmex::getPathAttachment(mmAttachmentManage::InfotablePathSetting()) + wxFileName::GetPathSeparator()
613         + Model_Attachment::reftype_desc(Model_Attachment::TRANSACTION) + wxFileName::GetPathSeparator() + FileName;
614     wxString URL = mmWebApp::getServicesPageURL() + "&" + WebAppParam::DownloadAttachments + "=" + AttachmentName;
615     if (download_file(URL, FilePath))
616         return FileName;
617     else
618         return wxEmptyString;
619 }
620 
621 //Get one attachment from WebApp
WebApp_GetAttachment(const wxString & AttachmentFileName)622 wxString mmWebApp::WebApp_GetAttachment(const wxString& AttachmentFileName)
623 {
624     wxString FileExtension = wxFileName(AttachmentFileName).GetExt().MakeLower();
625     wxString FilePath = mmex::getTempFolder() + "WebAppAttach_" + wxDateTime::Now().Format("%Y%m%d%H%M%S") + "." + FileExtension;
626     wxString URL = mmWebApp::getServicesPageURL() + "&" + WebAppParam::DownloadAttachments + "=" + AttachmentFileName;
627     if (download_file(URL, FilePath))
628         return FilePath;
629     else
630     return wxEmptyString;
631 }
632 
633 
634 //Update account in MMEX
MMEX_WebApp_UpdateAccount()635 bool mmWebApp::MMEX_WebApp_UpdateAccount()
636 {
637     if (mmWebApp::WebApp_CheckEnabled())
638     {
639         if (mmWebApp::WebApp_CheckGuid() && mmWebApp::WebApp_CheckApiVersion())
640             return mmWebApp::WebApp_UpdateAccount();
641         else
642             return false;
643     }
644     else
645         return false;
646 }
647 
648 //Update payee in MMEX
MMEX_WebApp_UpdatePayee()649 bool mmWebApp::MMEX_WebApp_UpdatePayee()
650 {
651     if (mmWebApp::WebApp_CheckEnabled())
652     {
653         if (mmWebApp::WebApp_CheckGuid() && mmWebApp::WebApp_CheckApiVersion())
654             return mmWebApp::WebApp_UpdatePayee();
655         else
656             return false;
657     }
658     else
659         return false;
660 }
661 
662 //Update category in MMEX
MMEX_WebApp_UpdateCategory()663 bool mmWebApp::MMEX_WebApp_UpdateCategory()
664 {
665     if (mmWebApp::WebApp_CheckEnabled())
666     {
667         if (mmWebApp::WebApp_CheckGuid() && mmWebApp::WebApp_CheckApiVersion())
668             return mmWebApp::WebApp_UpdateCategory();
669         else
670             return false;
671     }
672     else
673         return false;
674 }
675