First version of global payback

This commit is contained in:
Phyks 2013-09-23 23:08:01 +02:00
parent 05b2a1c929
commit 2134a2c284
7 changed files with 429 additions and 15 deletions

View File

@ -0,0 +1,108 @@
<?php
require_once('data/config.php');
require_once('Storage.class.php');
require_once('UsersInGlobalPayback.class.php');
class GlobalPayback extends Storage {
protected $id = 0, $date, $users_in;
// date is a DateTime object
// buyer is a User object
// users_in is a UsersIn objects
protected $TABLE_NAME = "GlobalPaybacks";
protected $fields = array(
'id'=>'key',
'date'=>'date',
);
public function __construct() {
parent::__construct();
$this->users_in = new UsersInGlobalPayback();
}
// Getters
// =======
public function getId() {
return $this->id;
}
public function getDate($format = "d-m-Y H:i") {
if(!empty($this->date))
return $this->date->format($format);
else
return false;
}
public function getUsersIn() {
return $this->users_in;
}
// Setters
// =======
public function setId($id) {
$this->users_in->setInvoiceId($id);
$this->id = (int) $id;
}
public function setDate($minute, $hour, $day, $month, $year) {
if((int) $minute < 10) $minute = '0'.$minute;
$this->date = DateTime::createFromFormat('Y-n-j G:i', $year.'-'.(int) $month.'-'.(int) $day.' '.(int) $hour.':'.$minute);
}
public function setUsersIn($users_in) {
// Note : users_in in param is an array with users in listed and guests for each user
$this->users_in->set($users_in);
}
// Maps htmlspecialchars on the class before display
// =================================================
public function secureDisplay() {
$this->id = (int) $this->id;
return $this;
}
// Restores object from array
// ==========================
public function sessionRestore($data, $serialized = false) {
if($serialized) {
$data = unserialize($data);
}
$this->setId($data['id']);
$this->date = DateTime::createFromFormat('Y-m-d H:i:s', $data['date']);
}
// Override parent load() method
// =============================
public function load($fields = NULL, $first_only = false) {
$return = parent::load($fields, $first_only); // Execute parent load
if(is_array($return)) {
foreach(array_keys($return) as $key) {
$return[$key]->users_in->load(); // Load users in for each global paybacks
}
}
elseif(is_a($return, 'GlobalPayback')) {
$return->users_in->load();
}
return $return; // Return the loaded elements
}
// Override parent save() method
// ============================
public function save() {
parent::save(); // Save invoice element
$this->users_in->save(); // Save users in
}
// Override parent delete() method
// ===============================
public function delete() {
parent::delete(); // Delete invoice element
$this->users_in->delete(); // Also delete users in
}
}

View File

@ -58,7 +58,7 @@
foreach($this->users_list as $user=>$guests) {
$temp_array[(int) $user] = (int) $guests;
}
$this->users_in = $temp_array;
$this->users_list = $temp_array;
return $this;
}

View File

@ -0,0 +1,132 @@
<?php
require_once('data/config.php');
require_once('Storage.class.php');
class UsersInGlobalPayback extends Storage {
protected $payback_id = 0, $users_list;
//users_list is a 2D array of users_id and amount between them
//user1 owes amount to user2
protected $TABLE_NAME = "Users_in_GlobalPayback";
protected $fields = array(
'global_payback_id'=>'int',
'user1_id'=>'int',
'user2_id'=>'int',
'amount'=>'float'
);
public function __construct() {
parent::__construct();
$users_list = array();
}
// Getters
// =======
public function getPaybackId() {
return $this->payback_id;
}
public function get() {
return $this->users_list;
}
// Setters
// =======
public function setPaybackId($id) {
$this->payback_id = (int) $id;
}
public function set($users_in) {
$this->users_list = $users_in;
}
// Maps htmlspecialchars on the class before display
// =================================================
public function secureDisplay() {
$this->payback_id = (int) $this->payback_id;
$temp_array = array();
foreach($this->users_list as $user1=>$temp) {
foreach($temp as $user2=>$amount) {
$temp_array[(int) $user1][(int) [$user2]] = (float) $amount;
}
}
$this->users_list = $temp_array;
return $this;
}
// Override load() method
// ======================
public function load() {
$query = 'SELECT ';
$i = false;
foreach($this->fields as $field=>$type) {
if($i) { $query .= ','; } else { $i = true; }
$query .= $field;
}
$query .= ' FROM '.MYSQL_PREFIX.$this->TABLE_NAME.' WHERE payback_id=:payback_id';
$query = $this->getConnection()->prepare($query);
$query->bindParam(':payback_id', $this->payback_id);
$query->execute();
$results = $query->fetchAll();
$this->users_list = array();
foreach($results as $result) {
$this->users_list[(int) $result['user1_id']][(int) $result['user2_id']] = (float) $result['amount'];
}
}
// Override save() method
// ======================
public function save() {
// TODO : Optimize ?
$query = 'SELECT COUNT(payback_id) FROM '.MYSQL_PREFIX.$this->TABLE_NAME.' WHERE payback_id=:payback_id';
$query = $this->getConnection()->prepare($query);
$query->bindParam(':payback_id', $this->payback_id);
$query->execute();
$count = $query->fetchColumn(0);
if($count != 0) {
// If there are already some records, delete them first
$query = $this->getConnection()->prepare('DELETE FROM '.MYSQL_PREFIX.$this->TABLE_NAME.' WHERE payback_id=:payback_id');
$query->bindParam(':payback_id', $this->payback_id);
$query->execute();
}
$query = 'INSERT INTO '.MYSQL_PREFIX.$this->TABLE_NAME.'(';
$i = false;
foreach($this->fields as $field=>$type) {
if($i) { $query .= ','; } else { $i = true;}
$query .= $field;
}
$query .= ') VALUES(:payback_id, :user1_id, :user2_id, :amount)';
$query = $this->getConnection()->prepare($query);
$query->bindParam(':payback_id', $this->payback_id);
foreach($this->users_list as $user1=>$temp) {
foreach($temp as $user2=>$amount) {
$query->bindParam(':user1_id', intval($user1));
$query->bindParam(':user2_id', intval($user2));
$query->bindParam(':amount', floatval($amount));
$query->execute();
}
}
}
// Override delete() method
// ========================
public function delete() {
$query = $this->getConnection()->prepare('DELETE FROM '.MYSQL_PREFIX.$this->TABLE_NAME.' WHERE payback_id=:payback_id');
$query->bindParam(':payback_id', $this->payback_id);
$query->execute();
}
}

132
index.php
View File

@ -23,6 +23,7 @@
require_once('inc/User.class.php');
require_once('inc/Invoices.class.php');
require_once('inc/Paybacks.class.php');
require_once('inc/GlobalPaybacks.class.php');
require_once('inc/rain.tpl.class.php');
require_once('inc/functions.php');
require_once('inc/Ban.inc.php');
@ -353,29 +354,29 @@
foreach($config as $line_number=>$line) {
if(strpos(trim($line), "MYSQL_HOST") !== false)
$config[$line_number] = "\tdefine('MYSQL_HOST', '".$_POST['mysql_host']."');\n";
$config[$line_number] = "\tdefine('MYSQL_HOST', '".$_POST['mysql_host']."');";
elseif(strpos(trim($line), "MYSQL_LOGIN") !== false)
$config[$line_number] = "\tdefine('MYSQL_LOGIN', '".$_POST['mysql_login']."');\n";
$config[$line_number] = "\tdefine('MYSQL_LOGIN', '".$_POST['mysql_login']."');";
elseif(strpos(trim($line), "MYSQL_PASSWORD") !== false && !empty($_POST['mysql_password']))
$config[$line_number] = "\tdefine('MYSQL_PASSWORD', '".$_POST['mysql_password']."');\n";
$config[$line_number] = "\tdefine('MYSQL_PASSWORD', '".$_POST['mysql_password']."');";
elseif(strpos(trim($line), "MYSQL_DB") !== false)
$config[$line_number] = "\tdefine('MYSQL_DB', '".$_POST['mysql_db']."');\n";
$config[$line_number] = "\tdefine('MYSQL_DB', '".$_POST['mysql_db']."');";
elseif(strpos(trim($line), "MYSQL_PREFIX") !== false && !empty($_POST['mysql_prefix']))
$config[$line_number] = "\tdefine('MYSQL_PREFIX', '".$_POST['mysql_prefix']."');\n";
$config[$line_number] = "\tdefine('MYSQL_PREFIX', '".$_POST['mysql_prefix']."');";
elseif(strpos(trim($line), "INSTANCE_TITLE") !== false)
$config[$line_number] = "\tdefine('INSTANCE_TITLE', '".$_POST['instance_title']."');\n";
$config[$line_number] = "\tdefine('INSTANCE_TITLE', '".$_POST['instance_title']."');";
elseif(strpos(trim($line), "BASE_URL") !== false)
$config[$line_number] = "\tdefine('BASE_URL', '".$_POST['base_url']."');\n";
$config[$line_number] = "\tdefine('BASE_URL', '".$_POST['base_url']."');";
elseif(strpos(trim($line), "CURRENCY") !== false)
$config[$line_number] = "\tdefine('CURRENCY', '".$_POST['currency']."');\n";
$config[$line_number] = "\tdefine('CURRENCY', '".$_POST['currency']."');";
elseif(strpos(trim($line), "EMAIL_WEBMASTER") !== false)
$config[$line_number] = "\tdefine('EMAIL_WEBMASTER', '".$_POST['email_webmaster']."');\n";
$config[$line_number] = "\tdefine('EMAIL_WEBMASTER', '".$_POST['email_webmaster']."');";
elseif(strpos(trim($line), "TEMPLATE_DIR") !== false)
$config[$line_number] = "\tdefine('TEMPLATE_DIR', 'tpl/".$_POST['template']."/');\n";
$config[$line_number] = "\tdefine('TEMPLATE_DIR', 'tpl/".$_POST['template']."/');";
elseif(strpos(trim($line), "LANG") !== false)
$config[$line_number] = "\tdefine('LANG', '".substr($_POST['template'], -2)."');\n";
$config[$line_number] = "\tdefine('LANG', '".substr($_POST['template'], -2)."');";
elseif(strpos(trim($line), 'date_default_timezone_set') !== false)
$config[$line_number] = "\tdate_default_timezone_set('".$_POST['timezone']."');\n";
$config[$line_number] = "\tdate_default_timezone_set('".$_POST['timezone']."');";
}
if(file_put_contents("data/config.php", $config)) {
@ -675,6 +676,113 @@
}
break;
case "manage_paybacks":
if(empty($_GET['new'])) {
$tpl->assign('list', true);
$tpl->assign('global_paybacks', array(array("id"=>1, "date"=>"now")));
}
else {
if(!empty($_POST['users_in'])) {
$global_payback = new GlobalPayback();
// Backup database
if(!is_dir('db_backup')) {
mkdir('db_backup');
}
system("mysqldump -h ".MYSQL_HOST." -u ".MYSQL_LOGIN." -p ".MYSQL_PASSWORD." ".MYSQL_DB." > db_backup/".date('d-m-Y_H:i'));
$users_in = array();
foreach($_POST['users_in'] as $user1_id) {
$user1_id = intval($user1_id);
foreach($_POST['users_in'] as $user2_id) {
$user2_id = intval($user2_id);
if($user1_id == $user2_id) {
$users_in[$user1_id][$user2_id] = 0;
}
elseif(!empty($users_in[$user2_id][$user1_id])) {
if($users_in[$user2_id][$user1_id] > 0) {
$users_in[$user1_id][$user2_id] = 0;
}
else {
$users_in[$user1_id][$user2_id] = -$users_in[$user1_id][$user2_id];
$users_in[$user2_id][$user1_id] = 0;
}
}
else {
// Get the amount user1 owes to user2
$users_in[$user1_id][$user2_id] = 0;
// Confirm all paybacks when user2 is buyer
$invoices = new Invoice();
$invoices = $invoices->load(array('buyer'=>$user2_id));
if($invoices !== false) {
foreach($invoices as $invoice) {
$paybacks = new Payback();
$paybacks = $paybacks->load(array('invoice_id'=>$invoice->getId(), 'to_user'=>$user2_id, 'from_user'=>$user1_id));
if($paybacks === false) {
$payback = new Payback();
$payback->setTo($user2_id);
$payback->setFrom($user1_id);
$payback->setAmount($invoice->getAmountPerPerson($user1_id));
$payback->setInvoice($invoice->getId());
$payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
$payback->save();
// Add the amount to what user1 owes to user2
$users_in[$user1_id][$user2_id] += $payback->getAmount();
}
}
}
// Confirm all paybacks when from is buyer
$invoices = new Invoice();
$invoices = $invoices->load(array('buyer'=>$user1_id));
if($invoices !== false) {
foreach($invoices as $invoice) {
$paybacks = new Payback();
$paybacks = $paybacks->load(array('invoice_id'=>$invoice->getId(), 'to_user'=>$user1_id, 'from_user'=>$user2_id));
if($paybacks === false) {
$payback = new Payback();
$payback->setTo($user1_id);
$payback->setFrom($user2_id);
$payback->setAmount($invoice->getAmountPerPerson($user2_id));
$payback->setInvoice($invoice->getId());
$payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
$payback->save();
// Substract the amount to what user1 owes to user2
$users_in[$user1_id][$user2_id] -= $payback->getAmount();
}
}
}
}
}
}
$global_payback->setUsersIn($users_in);
$global_payback->setDate(date('i'), date('G'), date('j'), date('n'), date('Y'));
$global_payback->save();
// Clear the cache
($cached_files = glob(raintpl::$cache_dir."*.rtpl.php")) or ($cached_files = array());
array_map("unlink", $cached_files);
header('location: index.php?do=edit_users&'.$get_redir);
exit();
}
$users_list = new User();
$users_list = $users_list->load();
$tpl->assign('users', $users_list);
}
$tpl->draw('manage_paybacks');
break;
default:
if(empty($_GET['all']))

View File

@ -63,6 +63,10 @@ input[type="checkbox"] {
text-align: center;
}
.red {
color: red;
}
.label-block {
display: inline-block;
text-align: right;

View File

@ -10,6 +10,11 @@ body {
margin: 0;
}
body>p, body>ul, body>dl {
margin-left: 1em;
margin-right: 1em;
}
fieldset {
border: 1px solid #999;
margin-bottom: 1em;
@ -55,10 +60,20 @@ h2 {
border-left: none;
}
hr {
width: 33%;
margin-top: 2em;
margin-bottom: 2em;
}
input[type="checkbox"] {
margin-left: 2em;
}
.red {
color: red;
}
.center {
text-align: center;
}
@ -120,12 +135,16 @@ input[type=submit] {
text-align: center
}
#edit_password_form, #edit_user_form, #invoice_form, #notice_form {
#edit_password_form, #edit_user_form, #invoice_form, #notice_form, #global_payback_form {
width: 67%;
margin: auto;
}
#edit_password_form p, #edit_user_form p, #notice_form p {
#global_payback_form fieldset {
margin-top: 2em;
}
#edit_password_form p, #edit_user_form p, #notice_form p, #global_payback_form p {
text-align: center;
}

View File

@ -0,0 +1,43 @@
{include="header"}
{if condition="!empty($list)"}
<h2>Gérer les remboursements globaux</h2>
<p class="center"><a href="?do=manage_paybacks&new=1">Ajouter un remboursement global</a></p>
{if condition="count($global_paybacks) > 0"}
<p>Liste des remboursements globaux précédents :</p>
<dl>
{loop="$global_paybacks"}
<dt>{$value['date']}</dt>
<dd><a href="?do=see_paybacks&id={$value['id']}">Remboursement n°{$value['id']}</a></dd>
{/loop}
</dl>
{/if}
{else}
<h2>Ajouter un remboursement global</h2>
<p>Cette page vous permet d'ajouter un remboursement global. Un tel remboursement permet de simplifier au maximum les remboursements. Ainsi, le tableau de la page d'accueil sera remis à zéro et un nouveau tableau sera créé, tableau qui simplifiera les échanges.</p>
<p>Par exemple, si A doit 5{$currency} à B et B doit 5{$currency} à C, après remboursement global, ces remboursements se simplifieront en A doit 5{$currency} à C.</p>
<p><strong>Note : <span class="red">Cette opération est irréversible sans mettre les mains dans la base de données.</span></strong></p>
<p><strong>Note :</strong> Un backup de votre base de données à l'heure actuelle sera effectué et stocké dans le répertoire backups à la racine de l'instance. Vous pourrez ainsi restaurer la base de données en cas d'erreur de votre part.</p>
<hr/>
<p>Si vous confirmez la création d'un remboursement global, veuillez sélectionner ci-dessous les utilisateurs que vous souhaitez inclure dans le remboursement.</p>
<form method="post" action="?do=manage_paybacks&new=1" id="global_payback_form">
<fieldset>
<legend>Utilisateurs à inclure</legend>
{loop="$users"}
<input type="checkbox" id="users_in_{$value->getId()}" name="users_in[]" value="{$value->getId()}"/>
<label for="users_in_{$value->getId()}">{$value->getDisplayName()}</label><br/>
{/loop}
</fieldset>
<p>
<input type="submit" onclick="confirm('Vous êtes sur le point d\'ajouter un remboursement global incluant les utilisateurs sélectionnés.');" value="Valider"/>
</p>
</form>
{/if}
{include="footer"}