An application in PHP with a web front-end to manage your food shopping with your friends easily. Deprecated, use https://github.com/spiral-project/ihatemoney instead.

index.php 58KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  1. <?php
  2. // Include necessary files
  3. if(!file_exists('data/config.php')) { header('location: install.php'); exit(); }
  4. require_once('data/config.php');
  5. require_once('inc/User.class.php');
  6. require_once('inc/Invoices.class.php');
  7. require_once('inc/Paybacks.class.php');
  8. require_once('inc/GlobalPaybacks.class.php');
  9. require_once('inc/rain.tpl.class.php');
  10. require_once('inc/functions.php');
  11. require_once('inc/Ban.inc.php');
  12. require_once('inc/CSRF.inc.php');
  13. session_start();
  14. $i18n = array();
  15. require_once(LANG);
  16. // Long lasting session inspired by the work from sbgodin for shaarli
  17. define('WEB_PATH', substr($_SERVER["REQUEST_URI"], 0, 1+strrpos($_SERVER["REQUEST_URI"], '/', 0)));
  18. if(!empty($_GET['json'])) {
  19. raintpl::$tpl_dir = 'tpl/json/';
  20. $get_redir = 'json=1';
  21. }
  22. else {
  23. raintpl::$tpl_dir = TEMPLATE_DIR;
  24. $get_redir = '';
  25. }
  26. raintpl::$cache_dir = 'tmp/';
  27. // Define raintpl instance
  28. $tpl = new raintpl();
  29. $tpl->assign('instance_title', htmlspecialchars(INSTANCE_TITLE));
  30. $tpl->assign('connection', false);
  31. $tpl->assign('notice', nl2br(getNotice()));
  32. $tpl->assign('error', '');
  33. $tpl->assign('base_url', htmlspecialchars(BASE_URL));
  34. $tpl->assign('currency', htmlspecialchars(CURRENCY));
  35. $tpl->assign('email_webmaster', htmlspecialchars(EMAIL_WEBMASTER));
  36. $tpl->assign('i18n', $i18n);
  37. $current_user = new User();
  38. if(isset($_SESSION['current_user'])) {
  39. $current_user->sessionRestore($_SESSION['current_user'], true);
  40. }
  41. else {
  42. if(!empty($_COOKIE['bouffeatulm_staySignedIn']) && !empty($_COOKIE['bouffeatulm_login'])) {
  43. // Connect back
  44. $user = new User();
  45. $user->setLogin($_COOKIE['bouffeatulm_login']);
  46. if(ban_canLogin() == false) {
  47. setcookie('bouffeatulm_login', 0, 0, WEB_PATH);
  48. setcookie('bouffeatulm_staySignedIn', 0, 0, WEB_PATH);
  49. exit($errors['unknown_username_password']);
  50. }
  51. else {
  52. $user = $user->exists($_COOKIE['bouffeatulm_login']);
  53. if($_COOKIE['bouffeatulm_staySignedIn'] === md5($user->getStaySignedInToken().$_SERVER['REMOTE_ADDR'])) {
  54. ban_loginOk();
  55. $_SESSION['current_user'] = $user->sessionStore();
  56. $_SESSION['ip'] = user_ip();
  57. setcookie('bouffeatulm_login', $_COOKIE['bouffeatulm_login'], time()+31536000, WEB_PATH);
  58. setcookie('bouffeatulm_staySignedIn', $_COOKIE['bouffeatulm_staySignedIn'], time()+31536000, WEB_PATH);
  59. header('location: index.php?'.$get_redir);
  60. exit();
  61. }
  62. else {
  63. ban_loginFailed();
  64. setcookie('bouffeatulm_login', 0, 0, WEB_PATH);
  65. setcookie('bouffeatulm_staySignedIn', 0, 0, WEB_PATH);
  66. exit($errors['unknown_username_password']);
  67. }
  68. }
  69. }
  70. else {
  71. $current_user = false;
  72. }
  73. }
  74. $tpl->assign('current_user', secureDisplay($current_user));
  75. if(!empty($_GET['json_token'])) {
  76. $current_user = new User();
  77. if($current_user->load(array('json_token'=>$_GET['json_token'], true)) === false) {
  78. header('location: index.php?do=connect'.$get_redir);
  79. exit();
  80. }
  81. else {
  82. if(!empty($get_redir))
  83. $get_redir .= '&';
  84. $get_redir .= 'json_token='.$_GET['json_token'];
  85. }
  86. }
  87. else {
  88. //If json token not available
  89. // If not connected, redirect to connection page
  90. if($current_user === false && (empty($_GET['do']) OR $_GET['do'] != 'connect')) {
  91. header('location: index.php?do=connect&'.$get_redir);
  92. exit();
  93. }
  94. // If IP has changed, logout
  95. if($current_user !== false && user_ip() != $_SESSION['ip']) {
  96. logout();
  97. header('location: index.php?do=connect&'.$get_redir);
  98. exit();
  99. }
  100. }
  101. // Initialize empty $_GET['do'] if required to avoid error
  102. if(empty($_GET['do'])) {
  103. $_GET['do'] = '';
  104. }
  105. // Check what to do
  106. switch($_GET['do']) {
  107. case 'connect':
  108. if($current_user !== false) {
  109. header('location: index.php?'.$get_redir);
  110. exit();
  111. }
  112. if(!empty($_POST['login']) && !empty($_POST['password']) && check_token(600, 'connection')) {
  113. $user = new User();
  114. $user->setLogin($_POST['login']);
  115. if(ban_canLogin() == false) {
  116. $error = $errors['unknown_username_password'];
  117. }
  118. else {
  119. $user = $user->exists($_POST['login']);
  120. if($user !== false && $user->checkPassword($_POST['password'])) {
  121. ban_loginOk();
  122. $_SESSION['current_user'] = $user->sessionStore();
  123. $_SESSION['ip'] = user_ip();
  124. if(!empty($_POST['remember_me'])) { // Handle remember me cookie
  125. $token = md5(uniqid(mt_rand(), true));
  126. $user->setStaySignedInToken($token);
  127. $user->save();
  128. setcookie('bouffeatulm_login', $_POST['login'], time()+31536000, WEB_PATH);
  129. setcookie('bouffeatulm_staySignedIn', md5($token.$_SERVER['REMOTE_ADDR']), time()+31536000, WEB_PATH);
  130. }
  131. header('location: index.php?'.$get_redir);
  132. exit();
  133. }
  134. else {
  135. ban_loginFailed();
  136. $error = $errors['unknown_username_password'];
  137. }
  138. }
  139. }
  140. $tpl->assign('connection', true);
  141. $tpl->assign('user_post', (!empty($_POST['login'])) ? htmlspecialchars($_POST['login']) : '');
  142. if(!empty($error))
  143. $tpl->assign('error', $error);
  144. $tpl->assign('token', generate_token('connection'));
  145. $tpl->draw('connection');
  146. break;
  147. case 'disconnect':
  148. $current_user = false;
  149. logout();
  150. header('location: index.php?do=connect&'.$get_redir);
  151. exit();
  152. break;
  153. case 'password':
  154. if(!empty($_POST['email']) && !empty($_POST['notifications'])) {
  155. if(check_token(600, 'password')) {
  156. if(!empty($_POST['password']) && !empty($_POST['password_confirm'])) {
  157. if($_POST['password'] == $_POST['password_confirm']) {
  158. $current_user->setPassword($current_user->encrypt($_POST['password']));
  159. }
  160. else {
  161. $error = true;
  162. $tpl->assign('error', $errors['password_mismatch']);
  163. }
  164. }
  165. if($current_user->setEmail($_POST['email']) === false) {
  166. $error = true;
  167. $tpl->assign('error', $errors['email_invalid']);
  168. }
  169. $current_user->setNotifications($_POST['notifications']);
  170. $current_user->save();
  171. if(!empty($error)) {
  172. header('location: index.php?'.$get_redir);
  173. exit();
  174. }
  175. }
  176. else {
  177. $tpl->assign('error', $errors['token_error']);
  178. }
  179. }
  180. $tpl->assign('view', 'password');
  181. $tpl->assign('json_token', htmlspecialchars($current_user->getJsonToken()));
  182. $tpl->assign('token', generate_token('password'));
  183. $tpl->draw('edit_users');
  184. break;
  185. case 'edit_users':
  186. case 'add_user':
  187. if(!$current_user->getAdmin()) {
  188. header('location: index.php?'.$get_redir);
  189. exit();
  190. }
  191. if(!empty($_POST['login']) && (!empty($_POST['password']) || !empty($_POST['user_id'])) && !empty($_POST['notifications']) && isset($_POST['admin'])) {
  192. if(check_token(600, 'edit_users')) {
  193. $user = new User();
  194. if(!empty($_POST['user_id'])) {
  195. $user = $user->load(array('id' => $_POST['user_id']), true);
  196. }
  197. else {
  198. $user->newJsonToken();
  199. }
  200. $user->setLogin($_POST['login']);
  201. $user->setDisplayName(!empty($_POST['display_name']) ? $_POST['display_name'] : '');
  202. if(!empty($_POST['password'])) {
  203. $user->setPassword($user->encrypt($_POST['password']));
  204. }
  205. $user->setAdmin($_POST['admin']);
  206. $user->setStaySignedInToken(NULL);
  207. if($user->setEmail($_POST['email']) !== false) {
  208. if(!empty($_POST['user_id']) || $user->isUnique()) {
  209. $user->setNotifications($_POST['notifications']);
  210. $user->save();
  211. // Clear the cache
  212. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  213. array_map("unlink", $cached_files);
  214. header('location: index.php?do=edit_users&'.$get_redir);
  215. exit();
  216. }
  217. else {
  218. $tpl->assign('error', $errors['user_already_exists']);
  219. }
  220. }
  221. else {
  222. $tpl->assign('error', $errors['email_invalid']);
  223. }
  224. }
  225. else {
  226. $tpl->assign('error', $errors['token_error']);
  227. }
  228. }
  229. if(!empty($_GET['user_id']) || $_GET['do'] == 'add_user') {
  230. if(!empty($_GET['user_id'])) {
  231. $user_id = (int) $_GET['user_id'];
  232. $user = new User();
  233. $user = $user->load(array('id'=>$user_id), true);
  234. $tpl->assign('user_data', $user->secureDisplay());
  235. }
  236. $tpl->assign('user_id', (!empty($user_id) ? (int) $user_id : -1));
  237. $tpl->assign('view', 'edit_user');
  238. }
  239. else {
  240. $users_list = new User();
  241. $users_list = $users_list->load();
  242. $tpl->assign('users', secureDisplay($users_list));
  243. $tpl->assign('view', 'list_users');
  244. }
  245. $tpl->assign('login_post', (!empty($_POST['login']) ? htmlspecialchars($_POST['login']) : ''));
  246. $tpl->assign('email_post', (!empty($_POST['email']) ? htmlspecialchars($_POST['email']) : ''));
  247. $tpl->assign('display_name_post', (!empty($_POST['display_name']) ? htmlspecialchars($_POST['display_name']) : ''));
  248. $tpl->assign('admin_post', (isset($_POST['admin']) ? (int) $_POST['admin'] : -1));
  249. $tpl->assign('token', generate_token('edit_users'));
  250. $tpl->draw('edit_users');
  251. break;
  252. case 'new_token':
  253. if(!empty($_GET['user_id']) && $current_user->getAdmin()) {
  254. $user_id = (int) $_GET['user_id'];
  255. }
  256. else {
  257. $user_id = $current_user->getId();
  258. }
  259. if(check_token(600, 'password') || check_token(600, 'edit_users')) {
  260. $user = new User();
  261. $user = $user->load(array('id'=>$user_id), true);
  262. $user->newJsonToken();
  263. $user->save();
  264. if(empty($_GET['user_id']))
  265. $_SESSION['current_user'] = $user->sessionStore();
  266. if(!empty($_GET['user_id']))
  267. header('location: index.php?do=edit_users&user_id='.$user_id);
  268. else
  269. header('location: index.php?do=password&'.$get_redir);
  270. exit();
  271. }
  272. else {
  273. $tpl->assign('error', $errors['token_error']);
  274. $tpl->assign('block_error', true);
  275. $tpl->draw('index');
  276. exit();
  277. }
  278. break;
  279. case 'delete_user':
  280. if($_GET['user_id'] != $current_user->getId()) {
  281. if(check_token(600, 'edit_users')) {
  282. $user = new User();
  283. $user->setId($_GET['user_id']);
  284. $user->delete();
  285. // Update concerned invoices
  286. $invoices = new Invoice();
  287. $invoices = $invoices->load();
  288. if($invoices !== FALSE) {
  289. foreach($invoices as $invoice) {
  290. if($invoice->getBuyer() == $_GET['user_id']) {
  291. $invoice->delete();
  292. }
  293. if($invoice->getUsersIn()->inUsersIn($_GET['user_id'])) {
  294. $users_in = $invoice->getUsersIn()->get();
  295. unset($users_in[$_GET['user_id']]);
  296. if(empty($users_in) || array_keys($users_in) == array($invoice->getBuyer()))
  297. $invoice->delete();
  298. else {
  299. $invoice->setUsersIn($users_in);
  300. $invoice->save();
  301. }
  302. }
  303. }
  304. }
  305. // Update paybacks
  306. $paybacks = new Payback();
  307. $paybacks = $paybacks->load(array('from_user'=>(int) $_GET['user_id']));
  308. if($paybacks !== FALSE) {
  309. foreach($paybacks as $payback) {
  310. $payback->delete();
  311. }
  312. }
  313. $paybacks = new Payback();
  314. $paybacks = $paybacks->load(array('to_user'=>(int) $_GET['user_id']));
  315. if($paybacks !== FALSE) {
  316. foreach($paybacks as $payback) {
  317. $payback->delete();
  318. }
  319. }
  320. // Clear the cache
  321. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  322. array_map("unlink", $cached_files);
  323. header('location: index.php?do=edit_users&'.$get_redir);
  324. exit();
  325. }
  326. else {
  327. $tpl->assign('error', $errors['token_error']);
  328. $tpl->assign('block_error', 'true');
  329. $tpl->draw('index');
  330. exit();
  331. }
  332. }
  333. break;
  334. case 'edit_notice':
  335. if(isset($_POST['notice'])) {
  336. $tpl->assign('notice', htmlspecialchars($_POST['notice']));
  337. if(check_token(600, 'settings')) {
  338. setNotice($_POST['notice']);
  339. // Clear the cache
  340. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  341. array_map("unlink", $cached_files);
  342. header('location: index.php?'.$get_redir);
  343. exit();
  344. }
  345. else {
  346. $tpl->assign('error', $errors['token_error']);
  347. }
  348. }
  349. $tpl->assign('show_settings', false);
  350. $tpl->assign('token', generate_token('settings'));
  351. $tpl->draw('settings');
  352. break;
  353. case 'settings':
  354. if(!empty($_POST['mysql_host']) && !empty($_POST['mysql_login']) && !empty($_POST['mysql_db']) && !empty($_POST['instance_title']) && !empty($_POST['base_url']) && !empty($_POST['currency']) && !empty($_POST['timezone']) && !empty($_POST['template'])) {
  355. if(check_token(600, 'settings')) {
  356. if(!is_writable('data/')) {
  357. $tpl>assign('error', $errors['write_error_data']);
  358. }
  359. else {
  360. if(!is_dir('tpl/'.$_POST['template'])) {
  361. $tpl->assign('error', $errors['template_error']);
  362. }
  363. else {
  364. $config = file('data/config.php');
  365. foreach($config as $line_number=>$line) {
  366. if(strpos(trim($line), "MYSQL_HOST") !== false)
  367. $config[$line_number] = "\tdefine('MYSQL_HOST', '".$_POST['mysql_host']."');\n";
  368. elseif(strpos(trim($line), "MYSQL_LOGIN") !== false)
  369. $config[$line_number] = "\tdefine('MYSQL_LOGIN', '".$_POST['mysql_login']."');\n";
  370. elseif(strpos(trim($line), "MYSQL_PASSWORD") !== false && !empty($_POST['mysql_password']))
  371. $config[$line_number] = "\tdefine('MYSQL_PASSWORD', '".$_POST['mysql_password']."');\n";
  372. elseif(strpos(trim($line), "MYSQL_DB") !== false)
  373. $config[$line_number] = "\tdefine('MYSQL_DB', '".$_POST['mysql_db']."');\n";
  374. elseif(strpos(trim($line), "MYSQL_PREFIX") !== false && !empty($_POST['mysql_prefix']))
  375. $config[$line_number] = "\tdefine('MYSQL_PREFIX', '".$_POST['mysql_prefix']."');\n";
  376. elseif(strpos(trim($line), "INSTANCE_TITLE") !== false)
  377. $config[$line_number] = "\tdefine('INSTANCE_TITLE', '".$_POST['instance_title']."');\n";
  378. elseif(strpos(trim($line), "BASE_URL") !== false)
  379. $config[$line_number] = "\tdefine('BASE_URL', '".$_POST['base_url']."');\n";
  380. elseif(strpos(trim($line), "CURRENCY") !== false)
  381. $config[$line_number] = "\tdefine('CURRENCY', '".$_POST['currency']."');\n";
  382. elseif(strpos(trim($line), "EMAIL_WEBMASTER") !== false)
  383. $config[$line_number] = "\tdefine('EMAIL_WEBMASTER', '".$_POST['email_webmaster']."');\n";
  384. elseif(strpos(trim($line), "TEMPLATE_DIR") !== false)
  385. $config[$line_number] = "\tdefine('TEMPLATE_DIR', 'tpl/".$_POST['template']."/');\n";
  386. elseif(strpos(trim($line), "LANG") !== false)
  387. $config[$line_number] = "\tdefine('LANG', 'i18n/".$_POST['lang']."');\n";
  388. elseif(strpos(trim($line), 'date_default_timezone_set') !== false)
  389. $config[$line_number] = "\tdate_default_timezone_set('".$_POST['timezone']."');\n";
  390. }
  391. if(file_put_contents("data/config.php", $config)) {
  392. // Clear the cache
  393. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  394. array_map("unlink", $cached_files);
  395. header('location: index.php?'.$get_redir);
  396. exit();
  397. }
  398. else {
  399. $tpl->assign('error', $errors['unable_write_config']);
  400. }
  401. }
  402. }
  403. }
  404. else {
  405. $tpl->assign('error', $errors['token_error']);
  406. }
  407. }
  408. $tpl->assign('mysql_host', htmlspecialchars(MYSQL_HOST));
  409. $tpl->assign('mysql_login', htmlspecialchars(MYSQL_LOGIN));
  410. $tpl->assign('mysql_db', htmlspecialchars(MYSQL_DB));
  411. $tpl->assign('mysql_prefix', htmlspecialchars(MYSQL_PREFIX));
  412. $tpl->assign('timezone', @date_default_timezone_get());
  413. $tpl->assign('show_settings', true);
  414. $tpl->assign('token', generate_token('settings'));
  415. $tpl->assign('templates', secureDisplay(listTemplates('tpl/')));
  416. $tpl->assign('current_template', htmlspecialchars(trim(substr(TEMPLATE_DIR, 4), '/')));
  417. $tpl->assign('current_lang', htmlspecialchars(LANG));
  418. $tpl->assign('available_lang', secureDisplay(listLangs()));
  419. $tpl->draw('settings');
  420. break;
  421. case 'new_invoice':
  422. case 'edit_invoice':
  423. $users_list = new User();
  424. $users_list = $users_list->load();
  425. if(!empty($_GET['id'])) {
  426. $invoice = new Invoice();
  427. $invoice = $invoice->load(array('id'=>(int) $_GET['id']), true);
  428. $date_hour = $invoice->getDate('a');
  429. $date_day = $invoice->getDate('d');
  430. $date_month = $invoice->getDate('m');
  431. $date_year = $invoice->getDate('Y');
  432. $amount = $invoice->getAmount();
  433. $what = $invoice->getWhat();
  434. $users_in = $invoice->getUsersIn()->get();
  435. }
  436. if(!empty($_POST['what'])) $what = $_POST['what'];
  437. if(!empty($_POST['amount'])) $amount = $_POST['amount'];
  438. if(!empty($_POST['date_day'])) $date_day = $_POST['date_day'];
  439. if(!empty($_POST['date_month'])) $date_month = $_POST['date_month'];
  440. if(!empty($_POST['date_year'])) $date_year = $_POST['date_year'];
  441. if(!empty($_POST['users_in'])) {
  442. $users_in = array();
  443. foreach($_POST['users_in'] as $user) {
  444. $users_in[(int) $user] = (int) $_POST['guest_user_'.$user];
  445. }
  446. }
  447. if(!empty($_POST['what']) && !empty($_POST['amount']) && (float) $_POST['amount'] != 0 && isset($_POST['date_hour']) && !empty($_POST['date_day']) && !empty($_POST['date_month']) && !empty($_POST['date_year']) && !empty($_POST['users_in'])) {
  448. if(check_token(600, 'new_invoice')) {
  449. if($_POST['amount'] <= 0) {
  450. $tpl->assign('error', $errors['negative_amount']);
  451. }
  452. else {
  453. if(array_keys($users_in) == array($current_user->getId())) {
  454. $tpl->assign('error', $errors['no_users']);
  455. }
  456. else {
  457. $invoice = new Invoice();
  458. if(!empty($_POST['id'])) {
  459. $invoice->setId($_POST['id']);
  460. }
  461. $invoice->setWhat($_POST['what']);
  462. $invoice->setAmount($_POST['amount']);
  463. if(empty($_POST['id'])) {
  464. $invoice->setBuyer($current_user->getId());
  465. }
  466. $invoice->setDate(0, int2ampm($_POST['date_hour']), $_POST['date_day'], $_POST['date_month'], $_POST['date_year']);
  467. $invoice->setUsersIn($users_in);
  468. $invoice->save();
  469. // Send notifications
  470. if (!empty($_POST['id'])) {
  471. $invoice = new Invoice();
  472. $invoice = $invoice->load(array('id'=>$_POST['id']), true);
  473. $buyer = $invoice->getBuyer();
  474. }
  475. else {
  476. $buyer = $current_user->getId();
  477. }
  478. foreach ($users_in as $user_in=>$guest) {
  479. if (empty($_POST['id']) && $user_in == $buyer) {
  480. continue;
  481. }
  482. $user_in_details = new User();
  483. $user_in_details = $user_in_details->load(array('id'=>$user_in), true);
  484. if (!empty($user_in_details->getEmail()) && $user_in_details->getNotifications() === 3) {
  485. sendmail($user_in_details, $subject, $msg, $from); // TODO notifs
  486. }
  487. }
  488. // Clear the cache
  489. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  490. array_map("unlink", $cached_files);
  491. header('location: index.php?'.$get_redir);
  492. exit();
  493. }
  494. }
  495. }
  496. else {
  497. $tpl->assign('error', $errors['token_error']);
  498. }
  499. }
  500. $tpl->assign('days', range(1,31));
  501. $tpl->assign('months', range(1, 12));
  502. $tpl->assign('years', range(date('Y') - 1, date('Y') + 1));
  503. $tpl->assign('hour_post', (!empty($date_hour) ? (int) ampm2int($date_hour) : (int) ampm2int(date('a'))));
  504. $tpl->assign('day_post', (!empty($date_day) ? (int) $date_day : (int) date('d')));
  505. $tpl->assign('month_post', (!empty($date_month) ? (int) $date_month : (int) date('m')));
  506. $tpl->assign('year_post', (!empty($date_year) ? (int) $date_year : (int) date('Y')));
  507. $tpl->assign('amount_post', (!empty($amount) ? (float) $amount : 0));
  508. $tpl->assign('what_post', (!empty($what) ? htmlspecialchars($what) : ''));
  509. $tpl->assign('users', secureDisplay($users_list));
  510. if(isset($_POST['what']) && empty($_POST['what']))
  511. $tpl->assign('error', $errors['what_unknown']);
  512. if(!empty($_POST['amount']) && (float) $_POST['amount'] == 0)
  513. $tpl->assign('error', $errors['incorrect_amount']);
  514. $tpl->assign('users_in', (!empty($users_in) ? $users_in : array()));
  515. $tpl->assign('id', (!empty($_GET['id']) ? (int) $_GET['id'] : 0));
  516. $tpl->assign('token', generate_token('new_invoice'));
  517. $tpl->draw('new_invoice');
  518. break;
  519. case 'delete_invoice':
  520. if(!empty($_GET['id'])) {
  521. if(check_token(600, 'invoice')) {
  522. $invoice = new Invoice();
  523. $invoice = $invoice->load(array('id'=>(int) $_GET['id']), true);
  524. if($current_user->getAdmin() || $invoice->getBuyer() == $current_user->getId()) {
  525. $invoice->delete();
  526. // Delete related paybacks
  527. $paybacks = new Payback();
  528. $paybacks = $paybacks->load(array('invoice_id'=>(int) $_GET['id']));
  529. if($paybacks !== false) {
  530. foreach($paybacks as $payback) {
  531. $payback->delete();
  532. }
  533. }
  534. // Clear the cache
  535. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  536. array_map("unlink", $cached_files);
  537. header('location: index.php?'.$get_redir);
  538. exit();
  539. }
  540. else {
  541. $tpl->assign('error', $errors['unauthorized']);
  542. $tpl->assign('block_error', true);
  543. $tpl->draw('index');
  544. exit();
  545. }
  546. }
  547. else {
  548. $tpl->assign('error', $errors['token_error']);
  549. $tpl->assign('block_error', true);
  550. $tpl->draw('index');
  551. exit();
  552. }
  553. }
  554. else {
  555. header('location: index.php?'.$get_redir);
  556. exit();
  557. }
  558. break;
  559. case 'confirm_payback':
  560. if(!empty($_GET['from']) && !empty($_GET['to']) && !empty($_GET['invoice_id']) && $_GET['from'] != $_GET['to']) {
  561. if($_GET['to'] == $current_user->getId() || $current_user->getAdmin()) {
  562. if(check_token(600, 'invoice')) {
  563. $invoice = new Invoice();
  564. $invoice = $invoice->load(array('id'=>(int) $_GET['invoice_id']), true);
  565. $payback = new Payback();
  566. if(!empty($_GET['payback_id'])) {
  567. $payback = $payback->load(array('id'=>(int) $_GET['payback_id']), true);
  568. if($payback->getFrom() != $_GET['from'] || $payback->getTo() != $_GET['to']) {
  569. $payback = new Payback();
  570. }
  571. }
  572. else {
  573. $payback = $payback->load(array('invoice_id'=>(int) $_GET['invoice_id'], 'to_user'=>(int) $_GET['to'], 'from_user'=>(int) $_GET['from']), true);
  574. if($payback == false)
  575. $payback = new Payback();
  576. }
  577. $payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
  578. $payback->setInvoice($_GET['invoice_id']);
  579. $payback->setAmount($invoice->getAmountPerPerson($_GET['from']));
  580. $payback->setFrom($_GET['from']);
  581. $payback->setTo($_GET['to']);
  582. $payback->save();
  583. // Clear the cache
  584. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  585. array_map("unlink", $cached_files);
  586. header('location: index.php');
  587. exit();
  588. }
  589. else {
  590. $tpl->assign('error', $errors['token_error']);
  591. $tpl->assign('block_error', true);
  592. $tpl->draw('index');
  593. exit();
  594. }
  595. }
  596. else {
  597. $tpl->assign('error', $errors['unauthorized']);
  598. $tpl->assign('block_error', true);
  599. $tpl->draw('index');
  600. exit();
  601. }
  602. }
  603. else {
  604. header('location: index.php?'.$get_redir);
  605. }
  606. break;
  607. case 'delete_payback':
  608. if(!empty($_GET['from']) && !empty($_GET['to']) && !empty($_GET['invoice_id'])) {
  609. if($_GET['to'] == $current_user->getId() || $current_user->getAdmin()) {
  610. if(check_token(600, 'invoice')) {
  611. $paybacks = new Payback();
  612. $paybacks = $paybacks->load(array('to_user'=>(int) $_GET['to'], 'from_user'=> (int) $_GET['from'], 'invoice_id'=> (int) $_GET['invoice_id']));
  613. if($paybacks !== false) {
  614. foreach($paybacks as $payback) {
  615. $payback->delete();
  616. }
  617. }
  618. // Clear the cache
  619. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  620. array_map("unlink", $cached_files);
  621. header('location: index.php');
  622. exit();
  623. }
  624. else {
  625. $tpl->assign('error', $errors['token_error']);
  626. $tpl->assign('block_error', true);
  627. $tpl->draw('index');
  628. exit();
  629. }
  630. }
  631. else {
  632. header('location: index.php');
  633. exit();
  634. }
  635. }
  636. else {
  637. header('location: index.php');
  638. exit();
  639. }
  640. break;
  641. case 'payall':
  642. if(!empty($_GET['from']) && !empty($_GET['to'])) {
  643. if($_GET['to'] == $current_user->getId() || $current_user->getAdmin()) {
  644. if(check_token(600, 'invoice')) {
  645. // Confirm all paybacks when to is buyer
  646. $invoices = new Invoice();
  647. $invoices = $invoices->load(array('buyer'=>(int) $_GET['to']));
  648. if($invoices !== false) {
  649. foreach($invoices as $invoice) {
  650. $paybacks = new Payback();
  651. $paybacks = $paybacks->load(array('invoice_id'=>$invoice->getId(), 'to_user'=>(int) $_GET['to'], 'from_user'=>(int) $_GET['from']));
  652. if($paybacks === false) {
  653. $payback = new Payback();
  654. $payback->setTo($_GET['to']);
  655. $payback->setFrom($_GET['from']);
  656. $payback->setAmount($invoice->getAmountPerPerson($_GET['from']));
  657. $payback->setInvoice($invoice->getId());
  658. $payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
  659. $payback->save();
  660. }
  661. }
  662. }
  663. // Confirm all paybacks when from is buyer
  664. $invoices = new Invoice();
  665. $invoices = $invoices->load(array('buyer'=>(int) $_GET['from']));
  666. if($invoices !== false) {
  667. foreach($invoices as $invoice) {
  668. $paybacks = new Payback();
  669. $paybacks = $paybacks->load(array('invoice_id'=>$invoice->getId(), 'to_user'=>(int) $_GET['from'], 'from_user'=>(int) $_GET['to']));
  670. if($paybacks === false) {
  671. $payback = new Payback();
  672. $payback->setTo($_GET['from']);
  673. $payback->setFrom($_GET['to']);
  674. $payback->setAmount($invoice->getAmountPerPerson($_GET['to']));
  675. $payback->setInvoice($invoice->getId());
  676. $payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
  677. $payback->save();
  678. }
  679. }
  680. }
  681. // Clear the cache
  682. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  683. array_map("unlink", $cached_files);
  684. header('location: index.php');
  685. exit();
  686. }
  687. else {
  688. $tpl->assign('error', $errors['token_error']);
  689. $tpl->assign('block_error', true);
  690. $tpl->draw('index');
  691. exit();
  692. }
  693. }
  694. else {
  695. header('location: index.php');
  696. exit();
  697. }
  698. }
  699. else {
  700. header('location: index.php');
  701. exit();
  702. }
  703. break;
  704. case "see_paybacks":
  705. $global_paybacks = new GlobalPayback();
  706. if(empty($_GET['id'])) {
  707. $global_paybacks = $global_paybacks->load();
  708. if($global_paybacks !== false) {
  709. $sort_keys = array();
  710. foreach($global_paybacks as $key=>$entry) {
  711. $sort_keys[$key] = $entry->getId();
  712. }
  713. array_multisort($sort_keys, SORT_DESC, $global_paybacks);
  714. }
  715. }
  716. else {
  717. $global_paybacks = $global_paybacks->load(array('id'=>(int) $_GET['id']), true);
  718. $tpl->assign('id', (int) $_GET['id']);
  719. $users_list = new User();
  720. $users_list = $users_list->load();
  721. $tpl->assign('users', $users_list);
  722. }
  723. $tpl->assign('list', true);
  724. $tpl->assign('global_paybacks', $global_paybacks);
  725. $tpl->assign('token', generate_token('global_payback'));
  726. $tpl->draw('see_paybacks');
  727. break;
  728. case "confirm_global_paybacks":
  729. if(!empty($_GET['from']) && !empty($_GET['to']) && !empty($_GET['payback_id']) && $_GET['from'] != $_GET['to']) {
  730. if($_GET['to'] == $current_user->getId() || $current_user->getAdmin()) {
  731. if(check_token(600, 'global_payback')) {
  732. $global_payback = new GlobalPayback();
  733. $global_payback = $global_payback->load(array('id'=>(int) $_GET['payback_id']), true);
  734. $users_in = $global_payback->getUsersIn()->get();
  735. $users_in[(int) $_GET['from']][(int) $_GET['to']] = 0;
  736. $users_in[(int) $_GET['to']][(int) $_GET['from']] = 0;
  737. $global_payback->setUsersIn($users_in);
  738. if($global_payback->getUsersIn()->isEmpty()) {
  739. $global_payback->setClosed(true);
  740. }
  741. else {
  742. $global_payback->setClosed(false);
  743. }
  744. $global_payback->save();
  745. // Clear the cache
  746. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  747. array_map("unlink", $cached_files);
  748. header('location: ?do=see_paybacks&id='.(int)$_GET['payback_id']);
  749. exit();
  750. }
  751. else {
  752. header('location: index.php');
  753. exit();
  754. }
  755. }
  756. else {
  757. $tpl->assign('error', $errors['token_error']);
  758. $tpl->assign('block_error', true);
  759. $tpl->draw('index');
  760. exit();
  761. }
  762. }
  763. else {
  764. header('location: index.php?'.$get_redir);
  765. }
  766. break;
  767. case "manage_paybacks":
  768. if(empty($_GET['new'])) {
  769. $global_paybacks = new GlobalPayback();
  770. $global_paybacks = $global_paybacks->load();
  771. // Sort paybacks by id DESC
  772. if($global_paybacks !== false) {
  773. $sort_keys = array();
  774. foreach($global_paybacks as $key=>$entry) {
  775. $sort_keys[$key] = $entry->getId();
  776. }
  777. array_multisort($sort_keys, SORT_DESC, $global_paybacks);
  778. }
  779. $tpl->assign('list', true);
  780. $tpl->assign('global_paybacks', $global_paybacks);
  781. }
  782. else {
  783. if(!empty($_POST['users_in']) && count($_POST['users_in']) > 1) {
  784. if(check_token(600, 'global_payback')) {
  785. $global_payback = new GlobalPayback();
  786. // Backup database
  787. if(!is_dir('db_backups')) {
  788. mkdir('db_backups');
  789. }
  790. if(!is_writeable('db_backups')) {
  791. $tpl->assign('error', $errors['write_error_db_backups']);
  792. $tpl->assign('block_error', true);
  793. $tpl->draw('index');
  794. exit();
  795. }
  796. else {
  797. if(system(escapeshellcmd("mysqldump -q -h \"".MYSQL_HOST."\" -u \"".MYSQL_LOGIN."\" -p\"".MYSQL_PASSWORD."\" \"".MYSQL_DB."\" > db_backups/".date('d-m-Y_H:i'))) === FALSE) {
  798. $tpl->assign('error', $errors['db_dump_failed']);
  799. $tpl->assign('block_error', true);
  800. $tpl->draw('index');
  801. exit();
  802. }
  803. else {
  804. $users_in = array();
  805. foreach($_POST['users_in'] as $user1_id) {
  806. $user1_id = intval($user1_id);
  807. foreach($_POST['users_in'] as $user2_id) {
  808. $user2_id = intval($user2_id);
  809. if($user1_id == $user2_id) {
  810. $users_in[$user1_id][$user2_id] = 0;
  811. }
  812. elseif(!empty($users_in[$user2_id][$user1_id])) {
  813. if($users_in[$user2_id][$user1_id] > 0) {
  814. $users_in[$user1_id][$user2_id] = 0;
  815. }
  816. else {
  817. $users_in[$user1_id][$user2_id] = -$users_in[$user2_id][$user1_id];
  818. $users_in[$user2_id][$user1_id] = 0;
  819. }
  820. }
  821. else {
  822. // Get the amount user1 owes to user2
  823. $users_in[$user1_id][$user2_id] = 0;
  824. // Confirm all paybacks when user2 is buyer
  825. $invoices = new Invoice();
  826. $invoices = $invoices->load(array('buyer'=>$user2_id));
  827. if($invoices !== false) {
  828. foreach($invoices as $invoice) {
  829. if($invoice->getAmountPerPerson($user1_id) !== false) {
  830. $paybacks = new Payback();
  831. $paybacks = $paybacks->load(array('invoice_id'=>$invoice->getId(), 'to_user'=>$user2_id, 'from_user'=>$user1_id));
  832. if($paybacks === false) {
  833. $payback = new Payback();
  834. $payback->setTo($user2_id);
  835. $payback->setFrom($user1_id);
  836. $payback->setAmount($invoice->getAmountPerPerson($user1_id));
  837. $payback->setInvoice($invoice->getId());
  838. $payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
  839. $payback->save();
  840. // Add the amount to what user1 owes to user2
  841. $users_in[$user1_id][$user2_id] += $payback->getAmount();
  842. }
  843. }
  844. }
  845. }
  846. // Confirm all paybacks when from is buyer
  847. $invoices = new Invoice();
  848. $invoices = $invoices->load(array('buyer'=>$user1_id));
  849. if($invoices !== false) {
  850. foreach($invoices as $invoice) {
  851. if($invoice->getAmountPerPerson($user2_id) !== false) {
  852. $paybacks = new Payback();
  853. $paybacks = $paybacks->load(array('invoice_id'=>$invoice->getId(), 'to_user'=>$user1_id, 'from_user'=>$user2_id));
  854. if($paybacks === false) {
  855. $payback = new Payback();
  856. $payback->setTo($user1_id);
  857. $payback->setFrom($user2_id);
  858. $payback->setAmount($invoice->getAmountPerPerson($user2_id));
  859. $payback->setInvoice($invoice->getId());
  860. $payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
  861. $payback->save();
  862. // Substract the amount to what user1 owes to user2
  863. $users_in[$user1_id][$user2_id] -= $payback->getAmount();
  864. }
  865. }
  866. }
  867. }
  868. }
  869. }
  870. }
  871. // Now, let's simplify the matrix ! :)
  872. // First, get the total balance by user (gains - debts)
  873. $balances = array();
  874. $simplified_balances = array();
  875. foreach($_POST['users_in'] as $user) {
  876. $balances[$user] = 0;
  877. foreach($_POST['users_in'] as $user2) {
  878. if(!empty($users_in[$user][$user2])) {
  879. $balances[$user] -= $users_in[$user][$user2];
  880. }
  881. if(!empty($users_in[$user2][$user])) {
  882. $balances[$user] += $users_in[$user2][$user];
  883. }
  884. $simplified_balances[$user][$user2] = 0;
  885. }
  886. }
  887. // Round at 0.01 currency
  888. foreach($balances as $key=>$balance) {
  889. $balances[$key] = round($balance, 2);
  890. }
  891. // Do while $balances is not identically filled with zeros
  892. $i = 0;
  893. while(count(array_unique($balances)) != 1 or $balances[key($balances)] != 0) {
  894. // Sort balances in abs values, desc
  895. uasort($balances, "sort_array_abs");
  896. // Get the largest one in abs
  897. // The following largest with opposite sign must pay him back the max
  898. reset($balances);
  899. $user1 = key($balances);
  900. foreach($balances as $user2=>$value) {
  901. if($value * $balances[$user1] < 0) {
  902. if($balances[$user1] > 0) {
  903. $simplified_balances[$user2][$user1] = round(abs($value), 2);
  904. $balances[$user1] = round($balances[$user1] - abs($value), 2);
  905. $balances[$user2] = round($balances[$user2] + abs($value), 2);
  906. }
  907. else {
  908. $simplified_balances[$user1][$user2] = round(abs($value), 2);
  909. $balances[$user1] = round($balances[$user1] + abs($value), 2);
  910. $balances[$user2] = round($balances[$user2] - abs($value), 2);
  911. }
  912. break;
  913. }
  914. }
  915. }
  916. $global_payback->setUsersIn($simplified_balances);
  917. if($global_payback->getUsersIn()->isEmpty()) {
  918. $global_payback->setClosed(true);
  919. }
  920. else {
  921. $global_payback->setClosed(false);
  922. }
  923. $global_payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
  924. $global_payback->save();
  925. // Clear the cache
  926. ($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
  927. array_map("unlink", $cached_files);
  928. header('location: index.php?do=manage_paybacks&'.$get_redir);
  929. exit();
  930. }
  931. }
  932. }
  933. else {
  934. $tpl->assign('error', $errors['token_error']);
  935. $tpl->assign('block_error', true);
  936. $tpl->draw('index');
  937. exit();
  938. }
  939. }
  940. $users_list = new User();
  941. $users_list = $users_list->load();
  942. $tpl->assign('users', $users_list);
  943. }
  944. $tpl->assign('token', generate_token('global_payback'));
  945. $tpl->draw('manage_paybacks');
  946. break;
  947. default:
  948. if(empty($_GET['all']))
  949. $_GET['all'] = 0;
  950. // Display cached page in priority
  951. if($cache = $tpl->cache('index', $expire_time = 600, $cache_id = $current_user->getLogin().$_GET['all'])) {
  952. echo $cache;
  953. }
  954. else {
  955. $users_list = new User();
  956. $users_list = $users_list->load();
  957. $invoices_list = new Invoice();
  958. if(empty($_GET['all'])) {
  959. $invoices_list = $invoices_list->load(array('date'=>array('>='.date('Y-m').'-01 00:00:00', 'AND', '<='.date('Y-m').'-31 23:59:59')));
  960. $tpl->assign('all', 0);
  961. }
  962. else {
  963. $invoices_list = $invoices_list->load();
  964. $tpl->assign('all', 1);
  965. }
  966. // Only keep the invoices which concern the user (as buyer or user in) (only if user != admin)
  967. // TODO : Optimize ?
  968. if(!$current_user->getAdmin() && $invoices_list !== false) {
  969. foreach($invoices_list as $key=>$invoice) {
  970. if($invoice->getBuyer() != $current_user->getId() && !$invoice->getUsersIn()->inUsersIn($current_user->getId())) {
  971. unset($invoices_list[$key]);
  972. }
  973. }
  974. }
  975. if($invoices_list === false) $invoices_list = array();
  976. else {
  977. $sort_keys = array();
  978. foreach($invoices_list as $key=>$entry) {
  979. $sort_keys[$key] = $entry->getDate();
  980. }
  981. array_multisort($sort_keys, SORT_DESC, $invoices_list);
  982. }
  983. $paybacks = array();
  984. foreach($invoices_list as $invoice) {
  985. $paybacks[$invoice->getId()] = new Payback();
  986. $paybacks[$invoice->getId()] = $paybacks[$invoice->getId()]->load(array('invoice_id'=>$invoice->getId()), false, 'from_user');
  987. }
  988. $balances = array();
  989. foreach($users_list as $user1) {
  990. foreach($users_list as $user2) {
  991. if($user1->getId() == $user2->getId()) {
  992. $balances[$user1->getId()][$user2->getId()] = 'X';
  993. }
  994. if(!empty($balances[$user2->getId()][$user1->getId()])) {
  995. // If the opposed element in the matrix exists
  996. if(is_float($balances[$user2->getId()][$user1->getId()])) {
  997. if($balances[$user2->getId()][$user1->getId()] >= 0) {
  998. $balances[$user1->getId()][$user2->getId()] = '-';
  999. }
  1000. else {
  1001. $balances[$user1->getId()][$user2->getId()] = -$balances[$user2->getId()][$user1->getId()];
  1002. $balances[$user2->getId()][$user1->getId()] = '-';
  1003. }
  1004. }
  1005. }
  1006. else {
  1007. // TODO : Optimize ?
  1008. $balances[$user1->getId()][$user2->getId()] = 0;
  1009. // First, get a list of all invoices paid by user2 and check if user1 was in
  1010. $invoices_list_balances = new Invoice();
  1011. $invoices_list_balances = $invoices_list_balances->load(array('buyer'=>$user2->getId()));
  1012. if($invoices_list_balances !== false) {
  1013. foreach($invoices_list_balances as $invoice) {
  1014. if($invoice->getUsersIn()->inUsersIn($user1->getId())) {
  1015. $balances[$user1->getId()][$user2->getId()] = $balances[$user1->getId()][$user2->getId()] + $invoice->getAmountPerPerson($user1->getId(), false);
  1016. $payback_balance = new Payback();
  1017. $payback_balance = $payback_balance->load(array('invoice_id'=>$invoice->getId(), 'from_user'=>$user1->getId(), 'to_user'=>$user2->getId()), true);
  1018. if($payback_balance !== false)
  1019. $balances[$user1->getId()][$user2->getId()] = $balances[$user1->getId()][$user2->getId()] - $payback_balance->getAmount();
  1020. }
  1021. }
  1022. }
  1023. // Then search for all invoices paid by 1 and check if user2 was in
  1024. $invoices_list_balances = new Invoice();
  1025. $invoices_list_balances = $invoices_list_balances->load(array('buyer'=>$user1->getId()));
  1026. if($invoices_list_balances !== false) {
  1027. foreach($invoices_list_balances as $invoice) {
  1028. if($invoice->getUsersIn()->inUsersIn($user2->getId())) {
  1029. $balances[$user1->getId()][$user2->getId()] = $balances[$user1->getId()][$user2->getId()] - $invoice->getAmountPerPerson($user2->getId(), false);
  1030. $payback_balance = new Payback();
  1031. $payback_balance = $payback_balance->load(array('invoice_id'=>$invoice->getId(), 'from_user'=>$user2->getId(), 'to_user'=>$user1->getId()), true);
  1032. if($payback_balance !== false)
  1033. $balances[$user1->getId()][$user2->getId()] = $balances[$user1->getId()][$user2->getId()] + $payback_balance->getAmount();
  1034. }
  1035. }
  1036. }
  1037. if(abs($balances[$user1->getId()][$user2->getId()]) < 0.01) {
  1038. $balances[$user1->getId()][$user2->getId()] = '-';
  1039. $balances[$user2->getId()][$user1->getId()] = '-';
  1040. }
  1041. }
  1042. }
  1043. }
  1044. foreach($users_list as $user1) {
  1045. foreach($users_list as $user2) {
  1046. if($balances[$user1->getId()][$user2->getId()] != '-' && $balances[$user1->getId()][$user2->getId()] != 'X')
  1047. $balances[$user1->getId()][$user2->getId()] = round($balances[$user1->getId()][$user2->getId()], 2);
  1048. }
  1049. }
  1050. if(!$current_user->getAdmin()) {
  1051. $user_balance = 0;
  1052. foreach($users_list as $user1) {
  1053. $user_balance = $user_balance - $balances[$current_user->getId()][$user1->getId()];
  1054. $user_balance = $user_balance + $balances[$user1->getId()][$current_user->getId()];
  1055. }
  1056. $tpl->assign('user_balance', round($user_balance, 2));
  1057. }
  1058. $tpl->assign('users', secureDisplay($users_list));
  1059. $tpl->assign('invoices', secureDisplay($invoices_list));
  1060. $tpl->assign('paybacks', secureDisplay($paybacks));
  1061. $tpl->assign('balances', secureDisplay($balances));
  1062. $tpl->assign('token', generate_token('invoice'));
  1063. // Cache the page (1 month to make it almost permanent and only regenerate it upon new invoice)
  1064. $tpl->cache('index', 108000, $current_user->getLogin().$_GET['all']);
  1065. $tpl->draw('index');
  1066. break;
  1067. }
  1068. }