Added authorized overdraft. Closes #6.
This commit is contained in:
parent
a576a36d3d
commit
9e0a5a2ea1
@ -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()
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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écouvert authorisé</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>
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
--
|
--
|
||||||
|
2
src/sql/update/0.1-0.2/001_authorized_overdraft.sql
Normal file
2
src/sql/update/0.1-0.2/001_authorized_overdraft.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE account ADD COLUMN authorized_overdraft INTEGER NOT NULL DEFAULT 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user