Changed the way we point entries. Closes #4.

This commit is contained in:
Alexis Lahouze 2013-01-26 01:15:07 +01:00
parent e4e74eea9f
commit 3cd9304689
8 changed files with 53 additions and 45 deletions

View File

@ -21,8 +21,8 @@ def get_accounts():
Account.name.label("name"), Account.name.label("name"),
Account.authorized_overdraft.label("authorized_overdraft"), 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.pointed, 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.operation_date < func.now(), Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("current")
).outerjoin(Entry).group_by(Account.id).order_by(Account.id) ).outerjoin(Entry).group_by(Account.id).order_by(Account.id)
return json.dumps([{ return json.dumps([{
@ -39,8 +39,8 @@ def get_months(account_id):
session = db.session session = db.session
query = session.query( query = session.query(
distinct(extract("year", Entry.value_date)).label("year"), distinct(extract("year", Entry.operation_date)).label("year"),
extract("month", Entry.value_date).label("month") extract("month", Entry.operation_date).label("month")
).filter(Entry.account_id == account_id).order_by("year", "month") ).filter(Entry.account_id == account_id).order_by("year", "month")
return json.dumps([{ return json.dumps([{

View File

@ -25,17 +25,16 @@ def get_entries(account_id, year, month):
session.query(Entry) session.query(Entry)
.filter(Entry.account_id == account_id) .filter(Entry.account_id == account_id)
.order_by( .order_by(
desc(Entry.value_date),
desc(Entry.operation_date), desc(Entry.operation_date),
Entry.value, Entry.value,
Entry.label, Entry.label,
).subquery() ).subquery()
).filter(func.date_trunc('month', Entry.value_date) == "%s-%s-01" % (year, month)) ).filter(func.date_trunc('month', Entry.operation_date) == "%s-%s-01" % (year, month))
return json.dumps([{ return json.dumps([{
"id": i.id, "id": i.id,
"value_date": i.value_date.strftime("%Y-%m-%d"), "pointed": i.pointed,
"operation_date": i.operation_date.strftime("%Y-%m-%d") if i.operation_date else None, "operation_date": i.operation_date.strftime("%Y-%m-%d"),
"label": i.label, "label": i.label,
"value": str(i.value), "value": str(i.value),
"category": i.category, "category": i.category,
@ -50,8 +49,8 @@ def add_entry():
try: try:
entry = Entry( entry = Entry(
value_date = request.json['value_date'],
operation_date = request.json['operation_date'], operation_date = request.json['operation_date'],
pointed = request.json['pointed'],
label = request.json['label'], label = request.json['label'],
value = request.json['value'], value = request.json['value'],
category = request.json['category'], category = request.json['category'],
@ -74,8 +73,8 @@ def update_entry(entry_id):
entry = session.query(Entry).filter(Entry.id == entry_id).first() entry = session.query(Entry).filter(Entry.id == entry_id).first()
entry.id = entry_id entry.id = entry_id
entry.value_date = request.json['value_date']
entry.operation_date = request.json['operation_date'] entry.operation_date = request.json['operation_date']
entry.pointed = request.json['pointed']
entry.label = request.json['label'] entry.label = request.json['label']
entry.value = request.json['value'] entry.value = request.json['value']
entry.category = request.json['category'] entry.category = request.json['category']

View File

@ -9,8 +9,8 @@ from sqlalchemy.sql import func, select
class Entry(db.Model): class Entry(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
value_date = db.Column(db.Date, nullable = False) pointed = db.Column(db.Boolean, nullable = False, default = False)
operation_date = db.Column(db.Date, nullable = True) operation_date = db.Column(db.Date, nullable = False)
label = db.Column(db.String(500), nullable = False) label = db.Column(db.String(500), nullable = False)
value = db.Column(db.Numeric(15, 2), nullable = False) value = db.Column(db.Numeric(15, 2), nullable = False)
account_id = db.Column(db.Integer, db.ForeignKey('account.id')) account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
@ -18,11 +18,11 @@ class Entry(db.Model):
account = db.relationship(Account, backref = db.backref('entry', lazy="Dynamic")) account = db.relationship(Account, backref = db.backref('entry', lazy="Dynamic"))
category = db.Column(db.String(100), nullable = True) category = db.Column(db.String(100), nullable = True)
sold = column_property(func.sum(value).over(order_by="value_date, operation_date, value desc, label desc")) sold = column_property(func.sum(value).over(order_by="operation_date, value desc, label desc"))
pointedsold = column_property(func.sum(value).over(partition_by="operation_date is not null", order_by="value_date, operation_date, value desc, label desc")) pointedsold = column_property(func.sum(value).over(partition_by="pointed", order_by="operation_date, value desc, label desc"))
def __init__(self, value_date, label, value, account_id, operation_date = None, category = None): def __init__(self, pointed, label, value, account_id, operation_date = None, category = None):
self.value_date = value_date self.pointed = pointed
self.operation_date = operation_date self.operation_date = operation_date
self.label = label self.label = label
self.value = value self.value = value

View File

@ -84,7 +84,7 @@
<thead> <thead>
<tr> <tr>
<th style="width: 100px">Date de valeur</th> <th style="width: 100px">Date de valeur</th>
<th style="width: 100px">Date de l'op.</th> <!--<th style="width: 100px">Date de l'op.</th>-->
<th>Libell&eacute; de l'op&eacute;ration</th> <th>Libell&eacute; de l'op&eacute;ration</th>
<th style="width: 50px">Montant</th> <th style="width: 50px">Montant</th>
<th style="width: 50px">Solde</th> <th style="width: 50px">Solde</th>
@ -179,8 +179,6 @@
<!-- Displayed item template --> <!-- Displayed item template -->
<script id="itemsTmpl" type="text/html"> <script id="itemsTmpl" type="text/html">
<tr data-bind="css: { 'warning': sold() < 0 && sold() >= $root.account().authorized_overdraft(), 'error': sold() < $root.account().authorized_overdraft() }"> <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: operation_date"></td> <td data-bind="text: operation_date"></td>
<td data-bind="text: label"></td> <td data-bind="text: label"></td>
@ -189,7 +187,7 @@
<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: 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-warning': pointedsold() < 0 && pointedsold() >= $root.account().authorized_overdraft(), 'text-error': pointedsold() < $root.account().authorized_overdraft() }"></td> <td data-bind="text: pointed() ? 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>
@ -197,6 +195,7 @@
<div class="btn-group"> <div class="btn-group">
<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>
<a class="btn btn-mini" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-trash"></i></a> <a class="btn btn-mini" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-trash"></i></a>
<a class="btn btn-mini" data-bind="css: {'active': pointed}, click: $root.pointEntry" href="#" title="point"><i class="icon-pencil"></i></a>
</div> </div>
</td> </td>
</tr> </tr>
@ -205,8 +204,6 @@
<!-- New item template --> <!-- New item template -->
<script id="newTmpl" type="text/html"> <script id="newTmpl" type="text/html">
<tr class="form-inline"> <tr class="form-inline">
<td><input type="date" class="input-small" data-bind="value: value_date" data-date-format="yyyy-mm-dd" id="new_value_date" /></td>
<td><input type="date" class="input-small" data-bind="value: operation_date" data-date-format="yyyy-mm-dd" id="new_operation_date" /></td> <td><input type="date" class="input-small" data-bind="value: operation_date" data-date-format="yyyy-mm-dd" id="new_operation_date" /></td>
<td><input type="text" class="input-xxlarge" data-bind="value: label"/></td> <td><input type="text" class="input-xxlarge" data-bind="value: label"/></td>
@ -223,6 +220,7 @@
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-mini btn-success" data-bind="click: $root.save" href="#" title="Add"><i class="icon-plus"></i></a> <a class="btn btn-mini btn-success" data-bind="click: $root.save" href="#" title="Add"><i class="icon-plus"></i></a>
<a class="btn btn-mini" data-bind="click: $root.cancel" href="#" title="Clear"><i class="icon-remove"></i></a> <a class="btn btn-mini" data-bind="click: $root.cancel" href="#" title="Clear"><i class="icon-remove"></i></a>
<a class="btn btn-mini" data-bind="css: {'active': pointed}, click: $root.pointEntry" href="#" title="point"><i class="icon-pencil"></i></a>
</div> </div>
</td> </td>
</tr> </tr>
@ -231,8 +229,6 @@
<!-- Edit item template --> <!-- Edit item template -->
<script id="editTmpl" type="text/html"> <script id="editTmpl" type="text/html">
<tr class="form-inline" data-bind="css: { 'warning': sold() < 0 && sold() >= $root.account().authorized_overdraft(), 'error': sold() < $root.account().authorized_overdraft() }"> <tr class="form-inline" data-bind="css: { 'warning': sold() < 0 && sold() >= $root.account().authorized_overdraft(), 'error': sold() < $root.account().authorized_overdraft() }">
<td><input type="date" class="input-small" data-bind="value: value_date" data-date-format="yyyy-mm-dd" id="value_date" /></td>
<td><input type="date" class="input-small" data-bind="value: operation_date" data-date-format="yyyy-mm-dd" id="operation_date" /></td> <td><input type="date" class="input-small" data-bind="value: operation_date" data-date-format="yyyy-mm-dd" id="operation_date" /></td>
<td><input type="text" class="input-xxlarge" data-bind="value: label"/></td> <td><input type="text" class="input-xxlarge" data-bind="value: label"/></td>
@ -245,10 +241,11 @@
<td><input type="text" class="input-small" data-bind="value: category, typeahead: {source: $root.categories }" /></td> <td><input type="text" class="input-small" data-bind="value: category, typeahead: {source: $root.categories }" /></td>
<td class="btn-group"> <td>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-mini btn-success" data-bind="click: $root.save" href="#" title="Save"><i class="icon-ok"></i></a> <a class="btn btn-mini btn-success" data-bind="click: $root.save" href="#" title="Save"><i class="icon-ok"></i></a>
<a class="btn btn-mini" data-bind="click: $root.cancel" href="#" title="Cancel"><i class="icon-ban-circle"></i></a> <a class="btn btn-mini" data-bind="click: $root.cancel" href="#" title="Cancel"><i class="icon-ban-circle"></i></a>
<a class="btn btn-mini" data-bind="css: {'active': pointed}, click: $root.pointEntry" href="#" title="point"><i class="icon-pencil"></i></a>
</div> </div>
</td> </td>
</tr> </tr>

Binary file not shown.

View File

@ -1,7 +1,7 @@
// Entry object // Entry object
function entry(){ function entry(){
this.id=ko.observable(); this.id=ko.observable();
this.value_date=ko.observable(); this.pointed=ko.observable();
this.operation_date=ko.observable(); this.operation_date=ko.observable();
this.label=ko.observable(); this.label=ko.observable();
this.value=ko.observable(); this.value=ko.observable();
@ -54,7 +54,7 @@ var ListViewModel = function() {
self.selectedItem = ko.observable(); self.selectedItem = ko.observable();
self.newEntry = ko.observable(ko.mapping.fromJS({ self.newEntry = ko.observable(ko.mapping.fromJS({
id: null, id: null,
value_date: null, pointed: false,
operation_date: null, operation_date: null,
label: null, label: null,
value: null, value: null,
@ -209,8 +209,8 @@ var ListViewModel = function() {
// Transform to an array readable by jqplot Line renderer. // Transform to an array readable by jqplot Line renderer.
var chartValues = []; var chartValues = [];
$.each(entries, function(index, entry) { $.each(entries, function(index, entry) {
if(unwrap(entry.value_date) && unwrap(entry.sold)) { if(unwrap(entry.operation_date) && unwrap(entry.sold)) {
chartValues.push([unwrap(entry.value_date), Number(unwrap(entry.sold))]); chartValues.push([unwrap(entry.operation_date), Number(unwrap(entry.sold))]);
} }
}); });
@ -231,11 +231,6 @@ var ListViewModel = function() {
self.entries(entries); self.entries(entries);
// Initialize date picker for value date column.
$("#new_value_date").datepicker().on('changeDate', function(ev){
self.newEntry().value_date(ev.date.format(ev.currentTarget.dataset.dateFormat));
});
// Initialize date picker for operation date column. // Initialize date picker for operation date column.
$("#new_operation_date").datepicker().on('changeDate', function(ev){ $("#new_operation_date").datepicker().on('changeDate', function(ev){
self.newEntry().operation_date(ev.date.format(ev.currentTarget.dataset.dateFormat)); self.newEntry().operation_date(ev.date.format(ev.currentTarget.dataset.dateFormat));
@ -333,11 +328,6 @@ var ListViewModel = function() {
self.savedItem=ko.toJS(item); self.savedItem=ko.toJS(item);
self.selectedItem(item); self.selectedItem(item);
// Initialize date picker for value date column.
$("#value_date").datepicker().on('changeDate', function(ev){
self.selectedItem().value_date(ev.date.format(ev.currentTarget.dataset.dateFormat));
});
// Initialize date picker for operation date column. // Initialize date picker for operation date column.
$("#operation_date").datepicker().on('changeDate', function(ev){ $("#operation_date").datepicker().on('changeDate', function(ev){
self.selectedItem().operation_date(ev.date.format(ev.currentTarget.dataset.dateFormat)); self.selectedItem().operation_date(ev.date.format(ev.currentTarget.dataset.dateFormat));
@ -346,8 +336,8 @@ var ListViewModel = function() {
self.clearNewEntry = function() { self.clearNewEntry = function() {
self.newEntry().id(null); // id should not change, but just in case... self.newEntry().id(null); // id should not change, but just in case...
self.newEntry().pointed(false)
self.newEntry().operation_date(null); self.newEntry().operation_date(null);
self.newEntry().value_date(null);
self.newEntry().label(null); self.newEntry().label(null);
self.newEntry().value(null); self.newEntry().value(null);
self.newEntry().account_id(self.account().id()); // account_id should not change, but just in case... self.newEntry().account_id(self.account().id()); // account_id should not change, but just in case...
@ -359,8 +349,8 @@ var ListViewModel = function() {
// Reset selected item fields to saved item ones. // Reset selected item fields to saved item ones.
if(item === self.selectedItem() && self.savedItem) { if(item === self.selectedItem() && self.savedItem) {
self.selectedItem().id(self.savedItem.id); // id should not change, but just in case... self.selectedItem().id(self.savedItem.id); // id should not change, but just in case...
self.selectedItem().pointed(self.savedItem.pointed);
self.selectedItem().operation_date(self.savedItem.operation_date); self.selectedItem().operation_date(self.savedItem.operation_date);
self.selectedItem().value_date(self.savedItem.value_date);
self.selectedItem().label(self.savedItem.label); self.selectedItem().label(self.savedItem.label);
self.selectedItem().value(self.savedItem.value); self.selectedItem().value(self.savedItem.value);
self.selectedItem().account_id(self.savedItem.account_id); // account_id should not change, but just in case... self.selectedItem().account_id(self.savedItem.account_id); // account_id should not change, but just in case...
@ -377,6 +367,18 @@ var ListViewModel = function() {
self.selectedItem(null); self.selectedItem(null);
}; };
self.pointEntry = function(entry) {
if(entry.pointed()) {
entry.pointed(false);
} else {
entry.pointed(true);
}
if(entry != self.newEntry()) {
self.save(entry);
}
};
// Function to save the current selected entry. // Function to save the current selected entry.
self.save = function(item) { self.save = function(item) {
//var item = self.selectedItem(); //var item = self.selectedItem();

View File

@ -64,13 +64,13 @@ ALTER SEQUENCE account_id_seq OWNED BY account.id;
CREATE TABLE entry ( CREATE TABLE entry (
id bigint NOT NULL, id bigint NOT NULL,
value_date date NOT NULL,
operation_date date, operation_date date,
label character varying(500) NOT NULL, label character varying(500) NOT NULL,
comment character varying(500), comment character varying(500),
value numeric(15,2) NOT NULL, value numeric(15,2) NOT NULL,
account_id integer NOT NULL, account_id integer NOT NULL,
category character varying(100) category character varying(100),
pointed boolean DEFAULT false NOT NULL
); );
@ -131,10 +131,10 @@ CREATE INDEX entry_account_id_idx ON entry USING btree (account_id);
-- --
-- Name: entry_value_date_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: -- Name: entry_operation_date_idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
-- --
CREATE INDEX entry_value_date_idx ON entry USING btree (value_date); CREATE INDEX entry_operation_date_idx ON entry USING btree (operation_date);
-- --

View File

@ -0,0 +1,10 @@
ALTER TABLE entry ADD COLUMN pointed BOOLEAN NOT NULL DEFAULT false;
UPDATE entry SET pointed = operation_date IS NOT NULL;
UPDATE entry SET operation_date = value_date;
ALTER TABLE entry DROP COLUMN value_date;
CREATE INDEX entry_operation_date_idx ON entry USING btree (operation_date);