transactions.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. # GPL3 or any later version
  2. import os
  3. import json
  4. import time
  5. import gi
  6. import threading
  7. gi.require_version('Gtk', '3.0')
  8. from gi.repository import Gtk
  9. from gi.repository import Gdk
  10. from gi.repository import GLib
  11. from modules import wallet
  12. from modules import items
  13. from modules import merchants
  14. from modules import ui
  15. from modules import totals
  16. def add(win):
  17. # This is a transaction adder
  18. the_wallet = win.wallet
  19. folder = wallet.save_folder()+"wallets/"+the_wallet+"/transactions/"
  20. try:
  21. os.makedirs(folder)
  22. except:
  23. pass
  24. name = str(int(time.time()))+".json"
  25. editor(win, name)
  26. def editor(win, name):
  27. # This is a transaction editor
  28. the_wallet = win.wallet
  29. folder = wallet.save_folder()+"wallets/"+the_wallet+"/transactions/"
  30. tfile = folder+name
  31. dialogWindow = Gtk.Dialog("Transaction",
  32. buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
  33. Gtk.STOCK_OK, Gtk.ResponseType.OK),
  34. )
  35. dialogWindow.set_size_request(400, 400)
  36. box = dialogWindow.get_content_area()
  37. # Loading transaction data
  38. try:
  39. with open(tfile) as json_file:
  40. data = json.load(json_file)
  41. except:
  42. data = {}
  43. scrl = Gtk.ScrolledWindow()
  44. scrl.set_vexpand(0)
  45. box.pack_start(scrl, 1,1,1)
  46. pack = Gtk.VBox()
  47. scrl.add(pack)
  48. refresh_editor(win, pack, data)
  49. box.show_all()
  50. response = dialogWindow.run()
  51. if response == Gtk.ResponseType.OK:
  52. data["total"] = 0
  53. for i in data.get("items", []):
  54. data["total"] = data["total"] + (i.get("amount",0)*i.get("price"))
  55. with open(tfile, "w") as fp:
  56. json.dump(data, fp, indent=4)
  57. update_transactions(win)
  58. totals.update_totals(win)
  59. dialogWindow.destroy()
  60. def refresh_editor(win, pack, data):
  61. for i in pack.get_children():
  62. i.destroy()
  63. totals = wallet.get_totals(win.wallet)
  64. currancy = totals.get("currancy", "$")
  65. if not data.get("merchant"):
  66. def do_add_merchant(w):
  67. merchant = merchants.select_dialogue(win,mode="transaction_add")
  68. data["merchant"] = merchant
  69. refresh_editor(win, pack, data)
  70. add_merchant = Gtk.Button()
  71. add_merchant.set_relief(Gtk.ReliefStyle.NONE)
  72. add_box = Gtk.HBox()
  73. add_merchant.add(add_box)
  74. add_box.pack_start(ui.icon(win,"list-add"),0,0,0)
  75. add_box.pack_start(Gtk.Label("Add Merchant"),1,1,1)
  76. add_merchant.connect("clicked", do_add_merchant)
  77. pack.pack_start(add_merchant, 0,0,0)
  78. else:
  79. folder = wallet.save_folder()+"merchants/"
  80. mfile = folder+str(data.get("merchant"))
  81. with open(mfile) as json_file:
  82. mdata = json.load(json_file)
  83. merchant_box = Gtk.HBox()
  84. pack.pack_start(merchant_box, 0,1,1)
  85. save_as = mdata.get("image", "")
  86. if os.path.exists(save_as):
  87. image = ui.load(win, ui.net_image_calculation, ui.net_image_render, "", 100 , save_as, False)
  88. else:
  89. image = ui.icon(win, "go-home")
  90. merchant_box.pack_start(image, 0,0,0)
  91. mtext_box = Gtk.VBox()
  92. merchant_box.pack_start(mtext_box, 1,1,1)
  93. def on_delete(w):
  94. try:
  95. del data["merchant"]
  96. except:
  97. pass
  98. refresh_editor(win, pack, data)
  99. delete_button = Gtk.Button()
  100. delete_button.connect("clicked", on_delete)
  101. delete_button.set_relief(Gtk.ReliefStyle.NONE)
  102. delete_button.add(ui.icon(win, "process-stop", size=Gtk.IconSize.SMALL_TOOLBAR))
  103. delete_box = Gtk.HBox()
  104. delete_box.pack_end(delete_button, 0,0,0)
  105. mtext_box.pack_start(delete_box, 0,0,0)
  106. mtext_box.pack_start(Gtk.Label(str(mdata.get("name"))), 0,0,0)
  107. mtext_box.pack_start(Gtk.Label(str(mdata.get("address"))), 0,0,0)
  108. # Items
  109. flowbox = Gtk.FlowBox()
  110. flowbox.set_valign(Gtk.Align.START)
  111. flowbox.set_max_children_per_line(30)
  112. flowbox.set_selection_mode(Gtk.SelectionMode.NONE)
  113. def do_add_item(w):
  114. item = items.select_dialogue(win, mode="transaction_add")
  115. if "items" not in data:
  116. data["items"] = []
  117. if type(item) == dict:
  118. data["items"].append(item)
  119. refresh_editor(win, pack, data)
  120. add_item = Gtk.Button()
  121. add_item.add(ui.icon(win,"list-add"))
  122. add_item.set_relief(Gtk.ReliefStyle.NONE)
  123. flowbox.add(add_item)
  124. add_item.connect("clicked", do_add_item)
  125. folder = wallet.save_folder()+"items/"
  126. total = 0
  127. for n, i in enumerate(data.get("items", [])):
  128. try:
  129. with open(folder+i.get("item")+".json") as json_file:
  130. idata = json.load(json_file)
  131. except:
  132. idata = {}
  133. item_box = Gtk.VBox()
  134. flowbox.add(item_box)
  135. save_as = idata.get("image", "")
  136. if os.path.exists(save_as):
  137. image = ui.load(win, ui.net_image_calculation, ui.net_image_render, "", 100 , save_as, False)
  138. else:
  139. image = ui.icon(win, "package-x-generic")
  140. image_box = Gtk.HBox()
  141. image_box.pack_start(image, 1,1,1)
  142. def on_delete(w, n):
  143. try:
  144. del data["items"][n]
  145. except:
  146. pass
  147. refresh_editor(win, pack, data)
  148. delete_button = Gtk.Button()
  149. delete_button.connect("clicked", on_delete, n)
  150. delete_button.set_relief(Gtk.ReliefStyle.NONE)
  151. delete_button.add(ui.icon(win, "process-stop", size=Gtk.IconSize.SMALL_TOOLBAR))
  152. delete_box = Gtk.VBox()
  153. delete_box.pack_start(delete_button, 0,0,0)
  154. image_box.pack_end(delete_box, 0,0,0)
  155. item_box.pack_start(image_box, 0,0,0)
  156. item_box.pack_start(Gtk.Label(str(idata.get("name", ""))), 0,0,0)
  157. item_box.pack_start(Gtk.Label(str(i.get("amount", ""))+" x "+currancy+str(i.get("price", ""))), 0,0,0)
  158. total = total + (i.get("amount", 0) * i.get("price", 0))
  159. pack.pack_start(flowbox, 1,1,1)
  160. # Description
  161. def on_comment(w):
  162. tb = detext.get_buffer()
  163. data["comment"] = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), True)
  164. descrl = Gtk.ScrolledWindow()
  165. descrl.set_size_request(200,200)
  166. detext = Gtk.TextView()
  167. detext.get_buffer().connect("changed", on_comment)
  168. detext.set_wrap_mode(Gtk.WrapMode.WORD)
  169. detext.get_buffer().set_text(data.get("comment", ""))
  170. descrl.add(detext)
  171. pack.pack_end(descrl, 0,0,5)
  172. pack.pack_end(Gtk.Label("Comment:"), 0,0,5)
  173. # Flip
  174. def do_flip(w):
  175. for i in data.get("items", []):
  176. try:
  177. i["price"] = i["price"] * -1
  178. except:
  179. pass
  180. refresh_editor(win, pack, data)
  181. flip = Gtk.Button()
  182. flip.set_relief(Gtk.ReliefStyle.NONE)
  183. flip_box = Gtk.HBox()
  184. flip_box.pack_start(ui.icon(win, "go-jump"), 0,0,0)
  185. flip_box.pack_start(Gtk.Label("Flip Transaction"), 1,1,5)
  186. flip.add(flip_box)
  187. flip.connect("clicked", do_flip)
  188. pack.pack_end(flip, 0,0,0)
  189. # TOTAL
  190. total_label = Gtk.Label()
  191. total_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
  192. total_label.set_line_wrap(True)
  193. total_label.set_markup('<span size="x-large"> '+currancy+str(round(total, 2))+'</span> ')
  194. total_label.set_selectable(True)
  195. total_label.set_css_name("")
  196. pack.pack_end(total_label, 1,1,10)
  197. pack.show_all()
  198. def update_transactions(win):
  199. t = wallet.get_totals(win.wallet)
  200. box = win.transactions_box
  201. folder = wallet.save_folder()+"wallets/"+win.wallet+"/transactions/"
  202. for i in box.get_children():
  203. i.destroy()
  204. try:
  205. transactions = list(os.walk(folder))[0][2]
  206. transactions = sorted(transactions)
  207. transactions = reversed(transactions)
  208. except:
  209. transactions = []
  210. for i in transactions:
  211. with open(folder+i) as json_file:
  212. tdata = json.load(json_file)
  213. def on_tbutton(w, name):
  214. editor(win, name)
  215. tbutton = Gtk.Button()
  216. tbutton.set_tooltip_text(tdata.get("comment", ""))
  217. tbutton.connect("clicked", on_tbutton, i)
  218. tbutton.set_relief(Gtk.ReliefStyle.NONE)
  219. tbox = Gtk.HBox()
  220. tbutton.add(tbox)
  221. tbox.pack_start(ui.icon(win,"task-past-due"), 0,0,0)
  222. try:
  223. tdate = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(i.replace(".json", ""))))
  224. except Exception as e:
  225. print( e )
  226. tdate = "[Date Unknown]"
  227. try:
  228. mfolder = wallet.save_folder()+"merchants/"
  229. mfile = mfolder+str(tdata.get("merchant"))
  230. with open(mfile) as json_file:
  231. mdata = json.load(json_file)
  232. merchant = mdata.get("name", "")+" "+mdata.get("address", "")
  233. except Exception as e:
  234. print( e )
  235. merchant = "[Private]"
  236. tbox.pack_start(Gtk.Label(tdate), 0,0,10)
  237. tbox.pack_start(Gtk.Label(merchant), 1,1,10)
  238. tbox.pack_end(Gtk.Label(t.get("currancy", "$")+" "+str(round(tdata.get("total", 0), 2))), 0,0,5)
  239. box.pack_start(tbutton, 0,0,0)
  240. box.show_all()