Use ngResource for sheduled operations.
This commit is contained in:
parent
61ef6b19af
commit
b8ea699f40
@ -16,42 +16,19 @@
|
|||||||
"""
|
"""
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
|
|
||||||
from flask import json, request
|
|
||||||
from flask.ext.restful import Resource, fields, reqparse, marshal_with_field
|
from flask.ext.restful import Resource, fields, reqparse, marshal_with_field
|
||||||
|
|
||||||
from sqlalchemy.orm.exc import NoResultFound
|
from sqlalchemy.orm.exc import NoResultFound
|
||||||
|
|
||||||
from accountant import session_scope, session_aware
|
from accountant import session_aware
|
||||||
|
|
||||||
from ..models.scheduled_operations import ScheduledOperation
|
from ..models.scheduled_operations import ScheduledOperation
|
||||||
|
|
||||||
from .. import api, api_api
|
from .. import api_api
|
||||||
|
|
||||||
from ..fields import Object
|
from ..fields import Object
|
||||||
|
|
||||||
|
|
||||||
@api.route("/scheduled_operations/<int:account_id>")
|
|
||||||
def get_scheduled_operations(account_id):
|
|
||||||
"""
|
|
||||||
Return entries for an account, year, and month.
|
|
||||||
"""
|
|
||||||
with session_scope() as session:
|
|
||||||
query = ScheduledOperation.get_scheduled_operations_for_account(
|
|
||||||
session, account_id)
|
|
||||||
|
|
||||||
return json.dumps([{
|
|
||||||
"id": i.id,
|
|
||||||
"start_date": i.start_date.strftime("%Y-%m-%d"),
|
|
||||||
"stop_date": i.stop_date.strftime("%Y-%m-%d"),
|
|
||||||
"day": str(i.day),
|
|
||||||
"frequency": str(i.frequency),
|
|
||||||
"label": i.label,
|
|
||||||
"value": str(i.value),
|
|
||||||
"category": i.category,
|
|
||||||
"account_id": i.account_id
|
|
||||||
} for i in query.all()])
|
|
||||||
|
|
||||||
|
|
||||||
resource_fields = {
|
resource_fields = {
|
||||||
'id': fields.Integer,
|
'id': fields.Integer,
|
||||||
'start_date': fields.DateTime(dt_format='iso8601'),
|
'start_date': fields.DateTime(dt_format='iso8601'),
|
||||||
@ -76,10 +53,23 @@ parser.add_argument('category', type=str)
|
|||||||
parser.add_argument('account_id', type=int)
|
parser.add_argument('account_id', type=int)
|
||||||
|
|
||||||
|
|
||||||
|
get_parser = reqparse.RequestParser()
|
||||||
|
get_parser.add_argument('account', type=int)
|
||||||
|
|
||||||
|
|
||||||
class ScheduledOperationListResource(Resource):
|
class ScheduledOperationListResource(Resource):
|
||||||
|
@session_aware
|
||||||
|
@marshal_with_field(fields.List(Object(resource_fields)))
|
||||||
|
def get(self, session):
|
||||||
|
kwargs = get_parser.parse_args()
|
||||||
|
|
||||||
|
return ScheduledOperation.get_scheduled_operations_for_account(
|
||||||
|
session, **kwargs
|
||||||
|
).all()
|
||||||
|
|
||||||
@session_aware
|
@session_aware
|
||||||
@marshal_with_field(Object(resource_fields))
|
@marshal_with_field(Object(resource_fields))
|
||||||
def put(self, session):
|
def post(self, session):
|
||||||
"""
|
"""
|
||||||
Add a new scheduled operation.
|
Add a new scheduled operation.
|
||||||
"""
|
"""
|
||||||
@ -119,7 +109,7 @@ class ScheduledOperationResource(Resource):
|
|||||||
|
|
||||||
@session_aware
|
@session_aware
|
||||||
@marshal_with_field(Object(resource_fields))
|
@marshal_with_field(Object(resource_fields))
|
||||||
def put(self, scheduled_operation_id, session):
|
def post(self, scheduled_operation_id, session):
|
||||||
kwargs = parser.parse_args()
|
kwargs = parser.parse_args()
|
||||||
|
|
||||||
assert (id not in kwargs or kwargs.id is None
|
assert (id not in kwargs or kwargs.id is None
|
||||||
|
@ -14,8 +14,20 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
accountantApp.controller(
|
accountantApp
|
||||||
"SchedulerController", function($scope, $http, $rootScope, $filter, $routeParams) {
|
|
||||||
|
.factory("ScheduledOperations", ["$resource", function($resource) {
|
||||||
|
return $resource(
|
||||||
|
"/api/scheduled_operations/:id", {
|
||||||
|
id: "@id"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}])
|
||||||
|
|
||||||
|
.controller(
|
||||||
|
"SchedulerController", [
|
||||||
|
"$scope", "$http", "$rootScope", "$filter", "$routeParams", "ScheduledOperations",
|
||||||
|
function($scope, $http, $rootScope, $filter, $routeParams, ScheduledOperations) {
|
||||||
// Operations store and selection
|
// Operations store and selection
|
||||||
$scope.operations = [];
|
$scope.operations = [];
|
||||||
$scope.selectedOperation = null;
|
$scope.selectedOperation = null;
|
||||||
@ -23,54 +35,24 @@ accountantApp.controller(
|
|||||||
// Placeholder for saved value to cancel entry edition
|
// Placeholder for saved value to cancel entry edition
|
||||||
$scope.savedOperation = null;
|
$scope.savedOperation = null;
|
||||||
|
|
||||||
|
$scope.categories = [];
|
||||||
|
|
||||||
|
$scope.resetNewOperation = function() {
|
||||||
|
$scope.newOperation = new ScheduledOperations({});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.resetNewOperation();
|
||||||
|
|
||||||
$scope.loadOperations = function(accountId) {
|
$scope.loadOperations = function(accountId) {
|
||||||
// Clean up selected entry.
|
// Clean up selected entry.
|
||||||
$scope.selectedOperation = null;
|
$scope.selectedOperation = null;
|
||||||
$scope.savedOperation = null;
|
$scope.savedOperation = null;
|
||||||
|
|
||||||
$http.get("/api/scheduled_operations/" + accountId).success($scope.loadOperations_success);
|
$scope.operations = ScheduledOperations.query({
|
||||||
};
|
account: $routeParams.accountId
|
||||||
|
}, function(data) {
|
||||||
$scope.loadOperations_success = function(data) {
|
$scope.$emit("operationsLoadedEvent", {operations: data});
|
||||||
var operations = [{
|
});
|
||||||
id: null,
|
|
||||||
start_date: null,
|
|
||||||
stop_date: null,
|
|
||||||
day: null,
|
|
||||||
frequency: null,
|
|
||||||
label: null,
|
|
||||||
account_id: null,
|
|
||||||
category: null,
|
|
||||||
state: "edit"
|
|
||||||
}];
|
|
||||||
|
|
||||||
if(data) {
|
|
||||||
operations = operations.concat(angular.fromJson(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.operations = operations;
|
|
||||||
|
|
||||||
$scope.$emit("operationsLoadedEvent", {operations: operations});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.iconSaveClass = function(operation) {
|
|
||||||
if($scope.isNew(operation)) {
|
|
||||||
return "fa fa-plus";
|
|
||||||
} else if ($scope.isEditing(operation)) {
|
|
||||||
return "fa fa-floppy-o";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.iconCancelClass = function(operation) {
|
|
||||||
if($scope.isNew(operation)) {
|
|
||||||
return "fa fa-times";
|
|
||||||
} else if ($scope.isEditing(operation)) {
|
|
||||||
return "fa fa-ban";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.isNew = function(operation) {
|
|
||||||
return !operation.id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns true if the entry is in editing state.
|
// Returns true if the entry is in editing state.
|
||||||
@ -82,73 +64,45 @@ accountantApp.controller(
|
|||||||
return operation.id && (!operation.state || operation.state === 'display');
|
return operation.id && (!operation.state || operation.state === 'display');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.saveOperation = function(operation) {
|
$scope.createOperation = function(operation) {
|
||||||
if(!operation.account_id) {
|
|
||||||
operation.account_id = $routeParams.accountId;
|
operation.account_id = $routeParams.accountId;
|
||||||
}
|
|
||||||
|
|
||||||
// prepare the Ajax xall to save the sceduled operation.
|
operation.$save(function(data) {
|
||||||
var type;
|
$scope.resetNewOperation();
|
||||||
var url = "/api/scheduled_operations";
|
|
||||||
|
|
||||||
if(!$scope.isNew(operation)) {
|
$scope.$emit("operationCreatedEvent", data);
|
||||||
url += "/" + operation.id;
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
$http.put(url, angular.toJson(operation)).success(function(data) {
|
$scope.$on("operationCreatedEvent", function(e, operation) {
|
||||||
new PNotify({
|
new PNotify({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Save",
|
title: "Save",
|
||||||
text: data
|
text: "Operation #" + operation.id + " created."
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.saveOperation = function(operation) {
|
||||||
|
operation.$save(function(data) {
|
||||||
$scope.$emit("operationSavedEvent", operation);
|
$scope.$emit("operationSavedEvent", operation);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.$on("operationSavedEvent", function(e, operation) {
|
||||||
|
new PNotify({
|
||||||
|
type: "success",
|
||||||
|
title: "Save",
|
||||||
|
text: "Operation #" + operation.id + " saved."
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$scope.editOperation = function(operation) {
|
$scope.editOperation = function(operation) {
|
||||||
// Cancel previous editing.
|
|
||||||
if($scope.selectedOperation) {
|
|
||||||
$scope.cancelEditOperation($scope.selectedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save current entry values.
|
|
||||||
$scope.savedOperation = angular.copy(operation);
|
|
||||||
$scope.selectedOperation = operation;
|
|
||||||
|
|
||||||
// Enter edit state.
|
// Enter edit state.
|
||||||
operation.state='edit';
|
operation.state='edit';
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.cancelEditOperation = function(operation) {
|
$scope.cancelEditOperation = function(operation) {
|
||||||
if ($scope.isNew(operation)) {
|
operation.$get();
|
||||||
operation.id = null;
|
|
||||||
operation.start_date = null;
|
|
||||||
operation.stop_date = null;
|
|
||||||
operation.day = null;
|
|
||||||
operation.frequency = null;
|
|
||||||
operation.label = null;
|
|
||||||
operation.value = null;
|
|
||||||
operation.category = null;
|
|
||||||
operation.account_id = $routeParams.accountId;
|
|
||||||
} else if ($scope.isEditing(operation)) {
|
|
||||||
if($scope.savedOperation) {
|
|
||||||
operation.id = $scope.savedOperation.id;
|
|
||||||
operation.start_date = $scope.savedOperation.start_date;
|
|
||||||
operation.stop_date = $scope.savedOperation.stop_date;
|
|
||||||
operation.day = $scope.savedOperation.day;
|
|
||||||
operation.frequency = $scope.savedOperation.frequency;
|
|
||||||
operation.label = $scope.savedOperation.label;
|
|
||||||
operation.value = $scope.savedOperation.value;
|
|
||||||
operation.category = $scope.savedOperation.category;
|
|
||||||
operation.account_id = $scope.savedOperation.account_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.savedOperation = null;
|
|
||||||
$scope.selectedOperation = null;
|
|
||||||
|
|
||||||
operation.state = 'display';
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.removeOperation = function(operation, modalScope) {
|
$scope.removeOperation = function(operation, modalScope) {
|
||||||
@ -189,4 +143,4 @@ accountantApp.controller(
|
|||||||
});
|
});
|
||||||
|
|
||||||
$scope.loadOperations($routeParams.accountId);
|
$scope.loadOperations($routeParams.accountId);
|
||||||
});
|
}]);
|
||||||
|
@ -34,54 +34,67 @@
|
|||||||
|
|
||||||
<!-- Body of the table containing the entries -->
|
<!-- Body of the table containing the entries -->
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr id="operation_[[operation.id]]" class="form-inline" ng-class="operationRowClass(operation.sold)" ng-repeat="operation in operations">
|
<tr class="form-inline">
|
||||||
<td>
|
<td>
|
||||||
<input ng-show="isEditing(operation)" type="text" class="form-control input-sm" ng-model="operation.start_date" data-date-format="yyyy-mm-dd" bs-datepicker/>
|
<input type="text" class="form-control input-sm" ng-model="newOperation.start_date" data-date-format="yyyy-mm-dd" bs-datepicker/>
|
||||||
<span ng-show="isDisplaying(operation)">[[operation.start_date]]</span>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<input ng-show="isEditing(operation)" type="text" class="form-control input-sm" ng-model="operation.stop_date" data-date-format="yyyy-mm-dd" bs-datepicker/>
|
<input type="text" class="form-control input-sm" ng-model="newOperation.stop_date" data-date-format="yyyy-mm-dd" bs-datepicker/>
|
||||||
<span ng-show="isDisplaying(operation)">[[operation.stop_date]]</span>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<input ng-show="isEditing(operation)" type="text" class="form-control input-sm" ng-model="operation.day"/>
|
<input type="text" class="form-control input-sm" ng-model="newOperation.day"/>
|
||||||
<span ng-show="isDisplaying(operation)">[[operation.day]]</span>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<input ng-show="isEditing(operation)" type="text" class="form-control input-sm" ng-model="operation.frequency"/>
|
<input type="text" class="form-control input-sm" ng-model="newOperation.frequency"/>
|
||||||
<span ng-show="isDisplaying(operation)">[[operation.frequency]]</span>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<input ng-show="isEditing(operation)" type="text" class="form-control input-sm" ng-model="operation.label"/>
|
<input type="text" class="form-control input-sm" ng-model="newOperation.label"/>
|
||||||
<span ng-show="isDisplaying(operation)">[[operation.label]]</span>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<input ng-show="isEditing(operation)" type="text" class="form-control input-sm" ng-model="operation.value"/>
|
<input type="text" class="form-control input-sm" ng-model="newOperation.value"/>
|
||||||
<span ng-show="isDisplaying(operation)">[[operation.value]]</span>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<input ng-show="isEditing(operation)" type="text" class="form-control input-sm" ng-model="operation.category" bs-typeahead="categories"/>
|
<input type="text" class="form-control input-sm" ng-model="newOperation.category" bs-typeahead="categories"/>
|
||||||
<span ng-show="isDisplaying(operation)">[[operation.category]]</span>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-group" ng-show="isEditing(operation)">
|
<div class="btn-group">
|
||||||
<button class="btn btn-xs btn-success" ng-click="saveOperation(operation)" title="Save">
|
<button class="btn btn-xs btn-success" ng-click="createOperation(newOperation)" title="Save">
|
||||||
<span ng-class="iconSaveClass(operation)"></span>
|
<span class="fa fa-plus"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-xs btn-default" ng-click="cancelEditOperation(operation)" title="Cancel">
|
<button class="btn btn-xs btn-default" ng-click="resetNewOperation()" title="Cancel">
|
||||||
<span ng-class="iconCancelClass(operation)"></span>
|
<span class="fa fa-times"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<div class="btn-group" ng-show="isDisplaying(operation)">
|
<tr id="operation_[[operation.id]]" class="form-inline"
|
||||||
|
ng-repeat-start="operation in operations"
|
||||||
|
ng-if="isDisplaying(operation)">
|
||||||
|
<td>[[operation.start_date]]</td>
|
||||||
|
|
||||||
|
<td>[[operation.stop_date]]</td>
|
||||||
|
|
||||||
|
<td>[[operation.day]]</td>
|
||||||
|
|
||||||
|
<td>[[operation.frequency]]</td>
|
||||||
|
|
||||||
|
<td>[[operation.label]]</td>
|
||||||
|
|
||||||
|
<td>[[operation.value]]</td>
|
||||||
|
|
||||||
|
<td>[[operation.category]]</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
<button class="btn btn-xs btn-default" ng-click="editOperation(operation)" title="edit">
|
<button class="btn btn-xs btn-default" ng-click="editOperation(operation)" title="edit">
|
||||||
<span class="fa fa-pencil-square-o"></span>
|
<span class="fa fa-pencil-square-o"></span>
|
||||||
</button>
|
</button>
|
||||||
@ -92,6 +105,50 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr id="operation_[[operation.id]]" class="form-inline"
|
||||||
|
ng-repeat-end
|
||||||
|
ng-if="isEditing(operation)">
|
||||||
|
<td>
|
||||||
|
<input type="text" class="form-control input-sm" ng-model="operation.start_date" data-date-format="yyyy-mm-dd" bs-datepicker/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="text" class="form-control input-sm" ng-model="operation.stop_date" data-date-format="yyyy-mm-dd" bs-datepicker/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="text" class="form-control input-sm" ng-model="operation.day"/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="text" class="form-control input-sm" ng-model="operation.frequency"/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="text" class="form-control input-sm" ng-model="operation.label"/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="text" class="form-control input-sm" ng-model="operation.value"/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="text" class="form-control input-sm" ng-model="operation.category" bs-typeahead="categories"/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-xs btn-success" ng-click="saveOperation(operation)" title="Save">
|
||||||
|
<span class="fa fa-floppy-o"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-xs btn-default" ng-click="cancelEditOperation(operation)" title="Cancel">
|
||||||
|
<span class="fa fa-times"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user