Added account management (add, edit, remove).
This commit is contained in:
parent
afc2ccd0ca
commit
6b6c54a048
@ -4,16 +4,19 @@ require_once('Slim/Slim.php');
|
|||||||
|
|
||||||
$app=new \Slim\Slim();
|
$app=new \Slim\Slim();
|
||||||
|
|
||||||
$app->get('/entries/:account_id/:year/:month', 'get_entries');
|
$app->get('/entries/:account_id/:year/:month', 'getEntries');
|
||||||
$app->get('/accounts', 'get_accounts');
|
$app->get('/accounts', 'getAccounts');
|
||||||
$app->get('/accounts/:account_id/months', 'get_months');
|
$app->get('/accounts/:account_id/months', 'getMonths');
|
||||||
$app->delete('/entries/:id', 'remove_entry');
|
$app->delete('/entries/:id', 'removeEntry');
|
||||||
$app->post('/entries/add', 'add_entry');
|
$app->post('/entries/add', 'addEntry');
|
||||||
$app->put('/entries/save/:id', 'save_entry');
|
$app->put('/entries/save/:id', 'saveEntry');
|
||||||
|
$app->post('/accounts/add','addAccount');
|
||||||
|
$app->put('/accounts/save/:id','saveAccount');
|
||||||
|
$app->delete('/accounts/:id', 'removeAccount');
|
||||||
|
|
||||||
$app->run();
|
$app->run();
|
||||||
|
|
||||||
function get_connection() {
|
function getConnection() {
|
||||||
$db=new PDO("pgsql:host=localhost;dbname=accountant", "accountant", "accountant");
|
$db=new PDO("pgsql:host=localhost;dbname=accountant", "accountant", "accountant");
|
||||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
@ -21,14 +24,14 @@ function get_connection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the entries
|
// Return the entries
|
||||||
function get_entries($account_id, $year, $month) {
|
function getEntries($account_id, $year, $month) {
|
||||||
|
|
||||||
$day=$year."-".$month."-01";
|
$day=$year."-".$month."-01";
|
||||||
|
|
||||||
$connection=get_connection();
|
$connection=getConnection();
|
||||||
|
|
||||||
$sql = <<<EOF
|
$sql = <<<EOF
|
||||||
select
|
select
|
||||||
id,
|
id,
|
||||||
value_date,
|
value_date,
|
||||||
operation_date,
|
operation_date,
|
||||||
@ -40,7 +43,7 @@ select
|
|||||||
category
|
category
|
||||||
from (
|
from (
|
||||||
select
|
select
|
||||||
*,
|
*,
|
||||||
sum(value) over(order by value_date, operation_date, label desc, value desc) as sold,
|
sum(value) over(order by value_date, operation_date, label desc, value desc) as sold,
|
||||||
sum(value) over(partition by operation_date is not null order by value_date, operation_date, label desc, value desc) as pointedSold
|
sum(value) over(partition by operation_date is not null order by value_date, operation_date, label desc, value desc) as pointedSold
|
||||||
from entry
|
from entry
|
||||||
@ -60,11 +63,11 @@ EOF;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add an entry
|
// Add an entry
|
||||||
function add_entry() {
|
function addEntry() {
|
||||||
$request = \Slim\Slim::getInstance()->request();
|
$request = \Slim\Slim::getInstance()->request();
|
||||||
$entry = json_decode($request->getBody(), true);
|
$entry = json_decode($request->getBody(), true);
|
||||||
|
|
||||||
$connection=get_connection();
|
$connection=getConnection();
|
||||||
|
|
||||||
$statement=$connection->prepare("insert into entry (value_date, operation_date, label, value, account_id, category) values (:value_date, :operation_date, :label, :value, :account_id, :category)");
|
$statement=$connection->prepare("insert into entry (value_date, operation_date, label, value, account_id, category) values (:value_date, :operation_date, :label, :value, :account_id, :category)");
|
||||||
|
|
||||||
@ -77,15 +80,15 @@ function add_entry() {
|
|||||||
|
|
||||||
$return=$statement->execute();
|
$return=$statement->execute();
|
||||||
|
|
||||||
echo("Entry saved.");
|
echo("Entry saved.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saves an entry
|
// Saves an entry
|
||||||
function save_entry($id) {
|
function saveEntry($id) {
|
||||||
$request = \Slim\Slim::getInstance()->request();
|
$request = \Slim\Slim::getInstance()->request();
|
||||||
$entry = json_decode($request->getBody(), true);
|
$entry = json_decode($request->getBody(), true);
|
||||||
|
|
||||||
$connection=get_connection();
|
$connection=getConnection();
|
||||||
|
|
||||||
$statement=$connection->prepare("update entry set value_date=:value_date, operation_date=:operation_date, label=:label, value=:value, account_id=:account_id, category=:category where id=:id");
|
$statement=$connection->prepare("update entry set value_date=:value_date, operation_date=:operation_date, label=:label, value=:value, account_id=:account_id, category=:category where id=:id");
|
||||||
|
|
||||||
@ -99,12 +102,12 @@ function save_entry($id) {
|
|||||||
|
|
||||||
$return=$statement->execute();
|
$return=$statement->execute();
|
||||||
|
|
||||||
echo($entry['id'] . " saved.");
|
echo($entry['id'] . " saved.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove an entry
|
// Remove an entry
|
||||||
function remove_entry($id) {
|
function removeEntry($id) {
|
||||||
$connection=get_connection();
|
$connection=getConnection();
|
||||||
|
|
||||||
$statement=$connection->prepare("delete from entry where id=:id");
|
$statement=$connection->prepare("delete from entry where id=:id");
|
||||||
$statement->bindParam("id", $id);
|
$statement->bindParam("id", $id);
|
||||||
@ -115,8 +118,8 @@ function remove_entry($id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the accounts with their solds.
|
// Return the accounts with their solds.
|
||||||
function get_accounts() {
|
function getAccounts() {
|
||||||
$connection=get_connection();
|
$connection=getConnection();
|
||||||
|
|
||||||
$sql = <<<EOF
|
$sql = <<<EOF
|
||||||
select
|
select
|
||||||
@ -127,7 +130,7 @@ select
|
|||||||
sum(case when entry.value_date <= now() then entry.value else cast(0 as numeric) end) as current
|
sum(case when entry.value_date <= now() then entry.value else cast(0 as numeric) end) as current
|
||||||
from
|
from
|
||||||
account
|
account
|
||||||
join entry on (account.id = entry.account_id)
|
left outer join entry on (account.id = entry.account_id)
|
||||||
group by
|
group by
|
||||||
account.id
|
account.id
|
||||||
order by
|
order by
|
||||||
@ -142,8 +145,8 @@ EOF;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the months for an account.
|
// Returns the months for an account.
|
||||||
function get_months($account_id) {
|
function getMonths($account_id) {
|
||||||
$connection=get_connection();
|
$connection=getConnection();
|
||||||
|
|
||||||
$sql = <<<EOF
|
$sql = <<<EOF
|
||||||
select
|
select
|
||||||
@ -165,5 +168,49 @@ EOF;
|
|||||||
|
|
||||||
echo(json_encode($statement->fetchAll(PDO::FETCH_ASSOC)));
|
echo(json_encode($statement->fetchAll(PDO::FETCH_ASSOC)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addAccount() {
|
||||||
|
$request = \Slim\Slim::getInstance()->request();
|
||||||
|
$account = json_decode($request->getBody(), true);
|
||||||
|
|
||||||
|
$connection=getConnection();
|
||||||
|
|
||||||
|
$statement=$connection->prepare("insert into account (name) values (:name)");
|
||||||
|
|
||||||
|
$statement->bindParam("name", $account['name']);
|
||||||
|
|
||||||
|
$return=$statement->execute();
|
||||||
|
|
||||||
|
echo("Account saved.");
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveAccount($id) {
|
||||||
|
$request = \Slim\Slim::getInstance()->request();
|
||||||
|
$account = json_decode($request->getBody(), true);
|
||||||
|
|
||||||
|
$connection=getConnection();
|
||||||
|
|
||||||
|
$statement=$connection->prepare("update account set name=:name where id=:id");
|
||||||
|
|
||||||
|
$statement->bindParam("name", $account['name']);
|
||||||
|
$statement->bindParam("id", $id);
|
||||||
|
|
||||||
|
$return=$statement->execute();
|
||||||
|
|
||||||
|
echo("Account #$id saved.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove an account
|
||||||
|
function removeAccount($id) {
|
||||||
|
$connection=getConnection();
|
||||||
|
|
||||||
|
$statement=$connection->prepare("delete from account where id=:id");
|
||||||
|
$statement->bindParam("id", $id);
|
||||||
|
|
||||||
|
$return=$statement->execute();
|
||||||
|
|
||||||
|
echo("Account #$id removed.");
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
<button class="btn btn-nav dropdown-toggle" data-toggle="dropdown"><b class="caret"></b></button>
|
<button class="btn btn-nav dropdown-toggle" data-toggle="dropdown"><b class="caret"></b></button>
|
||||||
|
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="#">Modifier</a></li>
|
<li><a href="#" data-bind="click: $root.editAccount">Modifier</a></li>
|
||||||
<li><a href="#">Supprimer</a></li>
|
<li><a href="#" data-bind="click: $root.removeAccount">Supprimer</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -101,6 +101,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="remove-account-confirm" class="modal hide fade">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>Confirmer la suppression</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Confirmez-vous la suppression de ce compte ?</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a href="#" class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Non</a>
|
||||||
|
<a href="#" class="btn" data-bind="click: confirmAccountRemove">Oui</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="edit-account" class="modal hide fade">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>Éditer le compte</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="form-horizontal" data-bind="with: editingAccount">
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label" for="inputName">Nom du compte</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="inputName" data-bind="value: name"></input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a href="#" class="btn btn-primary" data-bind="click: saveAccount">OK</a>
|
||||||
|
<a href="#" class="btn" data-bind="click: cancelEditAccount">Annuler</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script id="itemsTmpl" type="text/html">
|
<script id="itemsTmpl" type="text/html">
|
||||||
<tr data-bind="css: { 'error': sold() < 0 }">
|
<tr data-bind="css: { 'error': sold() < 0 }">
|
||||||
<td data-bind="text: value_date"></td>
|
<td data-bind="text: value_date"></td>
|
||||||
|
@ -40,6 +40,10 @@ var ListViewModel = function() {
|
|||||||
self.account = ko.observable();
|
self.account = ko.observable();
|
||||||
self.accounts = ko.observableArray([]);
|
self.accounts = ko.observableArray([]);
|
||||||
|
|
||||||
|
self.savedAccount = null;
|
||||||
|
self.editingAccount = ko.observable();
|
||||||
|
self.removedAccount = null;
|
||||||
|
|
||||||
// Month store and selection
|
// Month store and selection
|
||||||
self.months = ko.observableArray();
|
self.months = ko.observableArray();
|
||||||
self.month = ko.observable();
|
self.month = ko.observable();
|
||||||
@ -52,7 +56,84 @@ var ListViewModel = function() {
|
|||||||
self.savedItem = null;
|
self.savedItem = null;
|
||||||
|
|
||||||
// Placeholder for entry to remove to be available in modal function "yes" click callback
|
// Placeholder for entry to remove to be available in modal function "yes" click callback
|
||||||
self.itemToRemove = ko.observable();
|
self.removedItem = null;
|
||||||
|
|
||||||
|
self.addAccount = function() {
|
||||||
|
self.editingAccount(ko.mapping.fromJS({
|
||||||
|
id: null,
|
||||||
|
name: null
|
||||||
|
}));
|
||||||
|
|
||||||
|
$("#edit-account").modal();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.editAccount = function(account) {
|
||||||
|
self.editingAccount(account);
|
||||||
|
self.savedAccount = ko.toJS(account);
|
||||||
|
|
||||||
|
$("#edit-account").modal();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cancelEditAccount = function() {
|
||||||
|
if(self.editingAccount() && self.savedAccount) {
|
||||||
|
self.editingAccount().name(self.savedAccount.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.editingAccount(null);
|
||||||
|
self.savedAccount = null;
|
||||||
|
|
||||||
|
$("#edit-account").modal('hide');
|
||||||
|
};
|
||||||
|
|
||||||
|
self.saveAccount = function() {
|
||||||
|
var account = self.editingAccount();
|
||||||
|
|
||||||
|
// Ajax call to save the entry.
|
||||||
|
var type;
|
||||||
|
var url = "api/accounts/";
|
||||||
|
|
||||||
|
if(account.id()) {
|
||||||
|
type = "PUT";
|
||||||
|
url += "save/" + account.id();
|
||||||
|
} else {
|
||||||
|
type = "POST";
|
||||||
|
url += "add";
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({url: url, type: type, data:ko.toJSON(account)}).success(function(data) {
|
||||||
|
message("success", "Save", data);
|
||||||
|
|
||||||
|
self.editingAccount(null);
|
||||||
|
self.savedAccount = null;
|
||||||
|
|
||||||
|
$("#edit-account").modal('hide');
|
||||||
|
|
||||||
|
// Reload accounts to update solds.
|
||||||
|
self.loadAccounts();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.removeAccount = function(account) {
|
||||||
|
// Cancel current editing.
|
||||||
|
self.removedAccount = account;
|
||||||
|
$('#remove-account-confirm').modal();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to confirm the removal of an entry.
|
||||||
|
self.confirmAccountRemove = function() {
|
||||||
|
var account = self.removedAccount;
|
||||||
|
|
||||||
|
$.ajax("api/accounts/" + ko.utils.unwrapObservable(account.id), {type: "DELETE"}).success(function (data) {
|
||||||
|
message("success", "Save", data);
|
||||||
|
|
||||||
|
// Reload accounts to update solds.
|
||||||
|
self.loadAccounts();
|
||||||
|
}).complete(function (data) {
|
||||||
|
// Reset removed item to null and hide the modal dialog.
|
||||||
|
self.removedAccount = null;
|
||||||
|
$('#remove-account-confirm').modal('hide');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Returns the data for the categories by summing values with same category
|
// Returns the data for the categories by summing values with same category
|
||||||
self.expenseCategoriesChart = ko.computed(function() {
|
self.expenseCategoriesChart = ko.computed(function() {
|
||||||
@ -140,13 +221,19 @@ var ListViewModel = function() {
|
|||||||
|
|
||||||
// Function to load entries from server for a specific account and month.
|
// Function to load entries from server for a specific account and month.
|
||||||
self.loadEntries = function(account, month) {
|
self.loadEntries = function(account, month) {
|
||||||
$.get("api/entries/" + account.id() + "/" + month.year() + "/" + month.month()).success(function(data) {
|
// An account may not have any month (new account)
|
||||||
|
if(month) {
|
||||||
|
$.get("api/entries/" + account.id() + "/" + month.year() + "/" + month.month()).success(function(data) {
|
||||||
// Clean up selected entry.
|
// Clean up selected entry.
|
||||||
self.selectedItem(null);
|
self.selectedItem(null);
|
||||||
|
|
||||||
// Update entries
|
// Update entries
|
||||||
self.entries(ko.utils.arrayMap($.parseJSON(data), ko.mapping.fromJS));
|
self.entries(ko.utils.arrayMap($.parseJSON(data), ko.mapping.fromJS));
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
// If no month, just remove all entries.
|
||||||
|
self.entries.removeAll();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to load accounts
|
// Function to load accounts
|
||||||
@ -171,12 +258,16 @@ var ListViewModel = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set selected account to first one if not yet selected
|
// Set selected account to first one if not yet selected
|
||||||
if(!self.account()){
|
if(!self.account() && self.accounts().length > 0){
|
||||||
self.account(self.accounts()[0]);
|
self.account(self.accounts()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load months
|
// Load months if there is any account, or remove months.
|
||||||
self.loadMonths(self.account());
|
if(self.account()) {
|
||||||
|
self.loadMonths(self.account());
|
||||||
|
} else {
|
||||||
|
self.months.removeAll();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -203,12 +294,16 @@ var ListViewModel = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set selected month to the last one if not yet selected.
|
// Set selected month to the last one if not yet selected.
|
||||||
if(!self.month()) {
|
if(!self.month() && self.months().length > 0) {
|
||||||
self.month(self.months()[self.months().length - 1]);
|
self.month(self.months()[self.months().length - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load entries
|
// Load entries if there is a month or remove entries.
|
||||||
self.loadEntries(self.account(), self.month());
|
if(self.month) {
|
||||||
|
self.loadEntries(self.account(), self.month());
|
||||||
|
} else {
|
||||||
|
self.entries.removeAll();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user