Added authorized overdraft. Closes #6.

This commit is contained in:
Alexis Lahouze 2013-01-24 20:44:09 +01:00
parent a576a36d3d
commit 9e0a5a2ea1
6 changed files with 79 additions and 31 deletions

View File

@ -19,6 +19,7 @@ def get_accounts():
query = session.query( query = session.query(
Account.id.label("id"), Account.id.label("id"),
Account.name.label("name"), Account.name.label("name"),
Account.authorized_overdraft.label("authorized_overdraft"),
func.sum(Entry.value).label("future"), func.sum(Entry.value).label("future"),
func.sum(case([(Entry.operation_date != None, Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("pointed"), func.sum(case([(Entry.operation_date != None, Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("pointed"),
func.sum(case([(Entry.value_date < func.now(), Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("current") func.sum(case([(Entry.value_date < func.now(), Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("current")
@ -27,6 +28,7 @@ def get_accounts():
return json.dumps([{ return json.dumps([{
"id": i.id, "id": i.id,
"name": i.name, "name": i.name,
"authorized_overdraft": i.authorized_overdraft,
"current": str(i.current), "current": str(i.current),
"pointed": str(i.pointed), "pointed": str(i.pointed),
"future": str(i.future) "future": str(i.future)
@ -51,7 +53,7 @@ def add_account():
session = db.create_scoped_session() session = db.create_scoped_session()
try: try:
account = Account(request.json['name']) account = Account(request.json['name'], request.json['authorized_overdraft'])
session.add(account) session.add(account)
session.commit() session.commit()
@ -70,6 +72,7 @@ def update_account(account_id):
account = session.query(Account).filter(Account.id == account_id).first() account = session.query(Account).filter(Account.id == account_id).first()
account.name = request.json['name'] account.name = request.json['name']
account.authorized_overdraft = request.json['authorized_overdraft']
session.merge(account) session.merge(account)
session.commit() session.commit()

View File

@ -4,7 +4,9 @@ from app import db
class Account(db.Model): class Account(db.Model):
id = db.Column(db.Integer, primary_key = True) id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(200), nullable = False) name = db.Column(db.String(200), nullable = False)
authorized_overdraft = db.Column(db.Integer, nullable = True, default = 0)
def __init__(self, name): def __init__(self, name, authorized_overdraft):
self.name = name self.name = name
self.authorized_overdraft = authorized_overdraft

View File

@ -120,6 +120,10 @@
<div class="controls"> <div class="controls">
<input type="text" id="inputName" data-bind="value: name"></input> <input type="text" id="inputName" data-bind="value: name"></input>
</div> </div>
<label class="control-label" for="inputAuthorizedOverdraft">D&eacute;couvert authoris&eacute;</label>
<div class="controls">
<input type="text" id="inputAuthorizedOverdraft" data-bind="value: authorized_overdraft"></input>
</div>
</div> </div>
</form> </form>
</div> </div>
@ -130,13 +134,13 @@
</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: { 'warning': sold() < 0 && sold() >= $root.account().authorized_overdraft(), 'error': sold() < $root.account().authorized_overdraft() }">
<td data-bind="text: value_date"></td> <td data-bind="text: value_date"></td>
<td data-bind="text: operation_date"></td> <td data-bind="text: operation_date"></td>
<td data-bind="text: label"></td> <td data-bind="text: label"></td>
<td data-bind="text: value, css: {'text-error': value() < 0 }"></td> <td data-bind="text: value, css: {'text-error': value() < 0 }"></td>
<td data-bind="text: sold, css: {'text-error': sold() < 0 }"></td> <td data-bind="text: sold, css: {'text-warning': sold() < 0 && sold() >= $root.account().authorized_overdraft(), 'text-error': sold() < $root.account().authorized_overdraft() }"></td>
<td data-bind="text: operation_date() ? pointedsold : '', css: {'text-error': operation_date() && pointedsold() < 0 }"></td> <td data-bind="text: operation_date() ? pointedsold : '', css: {'text-warning': pointedsold() < 0 && pointedsold() >= $root.account().authorized_overdraft(), 'text-error': pointedsold() < $root.account().authorized_overdraft() }"></td>
<td data-bind="text: category"></td> <td data-bind="text: category"></td>
<td class="buttons"> <td class="buttons">
<a class="btn btn-mini" data-bind="click: $root.edit" href="#" title="edit"><i class="icon-edit"></i></a> <a class="btn btn-mini" data-bind="click: $root.edit" href="#" title="edit"><i class="icon-edit"></i></a>

View File

@ -15,6 +15,7 @@ function entry(){
function account() { function account() {
this.id=ko.observable(); this.id=ko.observable();
this.name=ko.observable(); this.name=ko.observable();
this.authorized_overdraft=ko.observable();
this.future=ko.observable(); this.future=ko.observable();
this.current=ko.observable(); this.current=ko.observable();
this.pointed=ko.observable(); this.pointed=ko.observable();
@ -72,7 +73,8 @@ var ListViewModel = function() {
self.addAccount = function() { self.addAccount = function() {
self.editingAccount(ko.mapping.fromJS({ self.editingAccount(ko.mapping.fromJS({
id: null, id: null,
name: null name: null,
authorized_overdraft: null
})); }));
$("#edit-account").modal(); $("#edit-account").modal();
@ -88,6 +90,7 @@ var ListViewModel = function() {
self.cancelEditAccount = function() { self.cancelEditAccount = function() {
if(self.editingAccount() && self.savedAccount) { if(self.editingAccount() && self.savedAccount) {
self.editingAccount().name(self.savedAccount.name); self.editingAccount().name(self.savedAccount.name);
self.editingAccount().authorized_overdraft(self.savedAccount.authorized_overdraft);
} }
self.editingAccount(null); self.editingAccount(null);
@ -195,7 +198,7 @@ var ListViewModel = function() {
} }
}); });
return chartValues; return {account: self.account(), entries: chartValues};
}, self); }, self);
// Function to load entries from server for a specific account and month. // Function to load entries from server for a specific account and month.
@ -224,26 +227,26 @@ var ListViewModel = function() {
// Update accounts // Update accounts
self.accounts(ko.utils.arrayMap($.parseJSON(data), ko.mapping.fromJS)); self.accounts(ko.utils.arrayMap($.parseJSON(data), ko.mapping.fromJS));
var accountToSelect = null
// Reset selected account to the new instance corresponding to the old one. // Reset selected account to the new instance corresponding to the old one.
if(self.account()) { if(self.account()) {
var oldId = self.account().id();
// Reset to null
self.account(null);
// Find the new instance of the previously selected account. // Find the new instance of the previously selected account.
$.each(self.accounts(), function(index, account) { $.each(self.accounts(), function(index, account) {
if(account.id() == oldId) { if(account.id() == self.account().id()) {
self.account(account); accountToSelect = account;
} }
}); });
} }
// Set selected account to first one if not yet selected // Set selected account to first one if not yet selected
if(!self.account() && self.accounts().length > 0){ if(!accountToSelect && self.accounts().length > 0){
self.account(self.accounts()[0]); accountToSelect = self.accounts()[0];
} }
// Reset to account to select
self.account(accountToSelect);
// Load months if there is any account, or remove months. // Load months if there is any account, or remove months.
if(self.account()) { if(self.account()) {
self.loadMonths(self.account()); self.loadMonths(self.account());
@ -259,27 +262,26 @@ var ListViewModel = function() {
// Update months // Update months
self.months(ko.utils.arrayMap($.parseJSON(data), ko.mapping.fromJS)); self.months(ko.utils.arrayMap($.parseJSON(data), ko.mapping.fromJS));
var monthToSelect = null;
// Reset selected month to the new instance corresponding to the old one // Reset selected month to the new instance corresponding to the old one
if(self.month()) { if(self.month()) {
var oldYear = self.month().year();
var oldMonth = self.month().month();
// Reset to null
self.month(null);
// Find the new instance of the previously selected month. // Find the new instance of the previously selected month.
$.each(self.months(), function(index, month) { $.each(self.months(), function(index, month) {
if(month.year() == oldYear && month.month() == oldMonth) { if(month.year() === self.month().year() && month.month() === self.month().month()) {
self.month(month); monthToSelect = month;
} }
}); });
} }
// 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() && self.months().length > 0) { if(!monthToSelect && self.months().length > 0) {
self.month(self.months()[self.months().length - 1]); monthToSelect = self.months()[self.months().length - 1];
} }
// Reset to month to select
self.month(monthToSelect);
// Load entries if there is a month or remove entries. // Load entries if there is a month or remove entries.
if(self.month) { if(self.month) {
self.loadEntries(self.account(), self.month()); self.loadEntries(self.account(), self.month());
@ -430,10 +432,12 @@ var ListViewModel = function() {
}; };
// Function to draw the sold evolution chart. // Function to draw the sold evolution chart.
drawChart = function(entries, element) { drawChart = function(data, element) {
// Clear previous chart // Clear previous chart
$(element).html(""); $(element).html("");
var entries = data.entries;
if(entries && entries.length > 0) { if(entries && entries.length > 0) {
// Prepare for today vertical line. // Prepare for today vertical line.
var today = new Date(); var today = new Date();
@ -494,11 +498,19 @@ drawChart = function(entries, element) {
canvasOverlay: { canvasOverlay: {
show: true, show: true,
objects: [ objects: [
// Red horizontal line for 0 limit // Orange horizontal line for 0 limit
{dashedHorizontalLine: { {dashedHorizontalLine: {
name: "zero", name: "zero",
y: 0, y: 0,
lineWidth: 1, lineWidth: 1,
color: "orange",
shadow: false
}},
// Red horizontal line for authorized overdraft limit
{dashedHorizontalLine: {
name: "overdraft",
y: data.account.authorized_overdraft(),
lineWidth: 1,
color: "red", color: "red",
shadow: false shadow: false
}}, }},
@ -573,8 +585,8 @@ ko.bindingHandlers.chart = {
var unwrap = ko.utils.unwrapObservable; var unwrap = ko.utils.unwrapObservable;
var dataSource = valueAccessor(); var dataSource = valueAccessor();
var entries = dataSource ? unwrap(dataSource) : null; var data = dataSource ? unwrap(dataSource) : null;
drawChart(entries, element); drawChart(data, element);
} }
}; };

View File

@ -8,6 +8,20 @@ SET standard_conforming_strings = on;
SET check_function_bodies = false; SET check_function_bodies = false;
SET client_min_messages = warning; SET client_min_messages = warning;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
SET search_path = public, pg_catalog; SET search_path = public, pg_catalog;
SET default_tablespace = ''; SET default_tablespace = '';
@ -20,7 +34,8 @@ SET default_with_oids = false;
CREATE TABLE account ( CREATE TABLE account (
id integer NOT NULL, id integer NOT NULL,
name character varying(200) NOT NULL name character varying(200) NOT NULL,
authorized_overdraft integer DEFAULT 0 NOT NULL
); );
@ -130,6 +145,16 @@ ALTER TABLE ONLY entry
ADD CONSTRAINT entry_account_id_fkey FOREIGN KEY (account_id) REFERENCES account(id); ADD CONSTRAINT entry_account_id_fkey FOREIGN KEY (account_id) REFERENCES account(id);
--
-- Name: public; Type: ACL; Schema: -; Owner: -
--
REVOKE ALL ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM postgres;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO PUBLIC;
-- --
-- PostgreSQL database dump complete -- PostgreSQL database dump complete
-- --

View File

@ -0,0 +1,2 @@
ALTER TABLE account ADD COLUMN authorized_overdraft INTEGER NOT NULL DEFAULT 0;