Added route for user management
Removed route for user groups and related views / templates User management created. Updated journal to full angular with routes Added User service in angular Added Journal Route. Changed auth in BaseCtrl to use Permission service and do away with function.
This commit is contained in:
@ -61,6 +61,10 @@ def main(global_config, **settings):
|
||||
config.add_route('account', '/Account')
|
||||
config.add_route('account_list', '/Accounts')
|
||||
|
||||
config.add_route('user_id', '/User/{id}')
|
||||
config.add_route('user', '/User')
|
||||
config.add_route('user_list', '/Users')
|
||||
|
||||
config.add_route('product_id', '/Product/{id}')
|
||||
config.add_route('product', '/Product')
|
||||
config.add_route('product_list', '/Products')
|
||||
@ -109,10 +113,6 @@ def main(global_config, **settings):
|
||||
config.add_route('profit_loss', '/Reports/ProfitLoss')
|
||||
config.add_route('trial_balance', '/Reports/TrialBalance')
|
||||
|
||||
config.add_route('user_groups_id', '/Admin/UserGroups/{id}')
|
||||
config.add_route('user_groups', '/Admin/UserGroups')
|
||||
config.add_route('save_user_groups', '/Admin/UserGroupsSave')
|
||||
|
||||
config.add_route('group_roles_id', '/Admin/GroupRoles/{id}')
|
||||
config.add_route('group_roles', '/Admin/GroupRoles')
|
||||
config.add_route('save_group_roles', '/Admin/GroupRolesSave')
|
||||
|
||||
@ -73,6 +73,7 @@ class User(Base):
|
||||
self.name = name
|
||||
if self.password != password:
|
||||
self.password = encrypt(password)
|
||||
self.locked_out = locked_out
|
||||
|
||||
@classmethod
|
||||
def get_by_name(cls, name):
|
||||
|
||||
89
brewman/brewman/static/partial/journal.html
Normal file
89
brewman/brewman/static/partial/journal.html
Normal file
@ -0,0 +1,89 @@
|
||||
<form method="post" autocomplete="off" class="form-horizontal" ng-controller="JournalCtrl">
|
||||
<div class="control-group">
|
||||
<label for="txtCode" class="control-label">Code</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" id="txtCode" class="non-search-box" disabled="disabled" ng-model="voucher.Code"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="txtDate" class="control-label">Date</label>
|
||||
|
||||
<div class="controls">
|
||||
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" control-group" id="add">
|
||||
<label for="ddlDebitCredit" class="control-label">Add</label>
|
||||
|
||||
<div class="controls">
|
||||
<select id="ddlDebitCredit" ng-model="debit">
|
||||
<option value="1">Dr</option>
|
||||
<option value="-1">Cr</option>
|
||||
</select>
|
||||
<autocomplete id="txtLedger" url="/Services/Ledgers" selname="ledger.Name"
|
||||
selid="ledger.LedgerID"></autocomplete>
|
||||
<div class="input-prepend">
|
||||
<span class="add-on">₹</span><input type="text" id="txtAmount" class="span2" autocomplete="off"
|
||||
placeholder="Amount" ng-model="amount"/>
|
||||
</div>
|
||||
<button ng-click="addJournal()">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" control-group">
|
||||
<label for="gvGrid" class="control-label"></label>
|
||||
|
||||
<div class="controls">
|
||||
<table id="gvGrid" class="clean-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="Debit">Debit</th>
|
||||
<th class="Name">Name</th>
|
||||
<th class="Amount">Amount</th>
|
||||
<th class="Delete">Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyMain">
|
||||
<tr ng-repeat="journal in voucher.Journals">
|
||||
<td class="Debit">{{journal.Debit | debit}}</td>
|
||||
<td class="Name">{{journal.Ledger.Name}}</td>
|
||||
<td data-column="Amount" class="Amount Editable">{{journal.Amount}}</td>
|
||||
<td class="Delete">
|
||||
<button ng-click="removeJournal(journal)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot id="tfootMain">
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="txtNarration" class="control-label">Narration</label>
|
||||
|
||||
<div class="controls">
|
||||
<textarea rows="2" cols="20" id="txtNarration"
|
||||
class="non-search-box" ng-model="voucher.Narration"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code != '(Auto)'"
|
||||
ng-disabled="!perms['Journal Create']">Save
|
||||
</button>
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!perms['Journal Update'] || (voucher.Posted && !perms['EditPosted'])">
|
||||
Update
|
||||
</button>
|
||||
<button class="btn btn-inverse" ng-click="post()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="voucher.Posted || !perms['PostTransactions']">{{voucher.Posted | posted}}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="delete()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!perms['Journal Delete'] || (voucher.Posted && !perms['EditPosted'])">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
Created on {{voucher.CreationDate}} and Last Edited on {{voucher.LastEditDate}} by {{voucher.User}}. Posted
|
||||
by {{voucher.Poster}}
|
||||
</div>
|
||||
</form>
|
||||
49
brewman/brewman/static/partial/user-detail.html
Normal file
49
brewman/brewman/static/partial/user-detail.html
Normal file
@ -0,0 +1,49 @@
|
||||
<form method="post" class="form-horizontal" ng-controller="UserCtrl">
|
||||
<legend>User Detail</legend>
|
||||
<div class="control-group">
|
||||
<label for="txtName" class="control-label">Name</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" id="txtName" ng-model="user.Name"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="txtPassword" class="control-label">Password</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="password" id="txtPassword" ng-model="user.Password">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" ng-checked="user.LockedOut"> Locked Out
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="ulGroups" class="control-label">Groups</label>
|
||||
|
||||
<div class="controls">
|
||||
<ul id="ulGroups">
|
||||
<li ng-repeat="group in user.Groups">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" ng-model="group.Enabled"> {{group.Name}}
|
||||
</label>
|
||||
</li>
|
||||
<!--<li ng-repeat="group in user.Groups">{{group}}</li>-->
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class=" control-group" id="add">
|
||||
|
||||
<div class="controls">
|
||||
<button ng-click="save()">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
21
brewman/brewman/static/partial/user-list.html
Normal file
21
brewman/brewman/static/partial/user-list.html
Normal file
@ -0,0 +1,21 @@
|
||||
<legend>Accounts</legend>
|
||||
<table class="clean-table" ng-controller="UserListCtrl">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Locked Out</th>
|
||||
<th>Groups</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="item in info">
|
||||
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
|
||||
<td>{{item.LockedOut}}</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li ng-repeat="group in item.Groups">{{group}}</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -108,3 +108,11 @@ overlord_service.factory('AccountType', ['$resource', function ($resource) {
|
||||
return $resource('/AccountTypes');
|
||||
}]);
|
||||
|
||||
// TODO: Replace hardcoded url with route_url
|
||||
overlord_service.factory('User', ['$resource', function ($resource) {
|
||||
return $resource('/User/:id',
|
||||
{id:'@UserID'}, {
|
||||
query:{method:'GET', params:{list:true}, isArray:true}
|
||||
});
|
||||
}]);
|
||||
|
||||
|
||||
@ -1,8 +1,14 @@
|
||||
var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filter', 'overlord.service']).
|
||||
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
|
||||
$routeProvider.
|
||||
when('/Journal', {templateUrl: '/partial/journal.html', controller: JournalCtrl}).
|
||||
when('/Journal/:id', {templateUrl: '/partial/journal.html', controller: JournalCtrl}).
|
||||
|
||||
when('/Accounts', {templateUrl: '/partial/account-list.html', controller: AccountListCtrl}).
|
||||
when('/Account/:id', {templateUrl: '/partial/account-detail.html', controller: AccountCtrl});
|
||||
when('/Account/:id', {templateUrl: '/partial/account-detail.html', controller: AccountCtrl}).
|
||||
|
||||
when('/Users', {templateUrl: '/partial/user-list.html', controller: UserListCtrl}).
|
||||
when('/User/:id', {templateUrl: '/partial/user-detail.html', controller: UserCtrl});
|
||||
// .otherwise({redirectTo: '/phones'});
|
||||
$locationProvider.html5Mode(true);
|
||||
}]);
|
||||
@ -32,12 +38,7 @@ function AutoComplete(matchFieldName, lookupURL) {
|
||||
|
||||
|
||||
function BaseCtrl($scope, Permission) {
|
||||
$scope.auth = {
|
||||
perms:Permission.query(),
|
||||
isUserInRole:function (role) {
|
||||
return $scope.auth.perms.indexOf(role) !== -1;
|
||||
}
|
||||
};
|
||||
$scope.perms = Permission.get();
|
||||
|
||||
$scope.toasts = [];
|
||||
$scope.clearToast = function(item) {
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
function JournalCtrl($scope, Voucher) {
|
||||
$scope.voucher = new Voucher(voucher);
|
||||
function JournalCtrl($scope, $routeParams, $location, Voucher) {
|
||||
console.log('loading')
|
||||
|
||||
if (typeof $routeParams.id === 'undefined'){
|
||||
$scope.voucher = Voucher.get({type:'Journal'});
|
||||
} else {
|
||||
console.log('getting voucher' + $routeParams.id)
|
||||
$scope.voucher = Voucher.get({id:$routeParams.id});
|
||||
}
|
||||
|
||||
$scope.name = '';
|
||||
$scope.debit = 1;
|
||||
$scope.addJournal = function () {
|
||||
@ -32,8 +40,10 @@
|
||||
|
||||
$scope.$watch('voucher.Journals', function (journals, oldValue) {
|
||||
var amount = 0;
|
||||
for (var i = 0, l = journals.length; i < l; i++) {
|
||||
amount += (journals[i].Amount * journals[i].Debit);
|
||||
if (typeof journals !== 'undefined') {
|
||||
for (var i = 0, l = journals.length; i < l; i++) {
|
||||
amount += (journals[i].Amount * journals[i].Debit);
|
||||
}
|
||||
}
|
||||
$scope.amount = Math.abs(amount);
|
||||
}, true);
|
||||
@ -49,6 +59,7 @@
|
||||
$scope.save = function () {
|
||||
$scope.voucher.$save(function (u, putResponseHeaders) {
|
||||
$scope.toasts.push({Type:'Success', Message:u.Code});
|
||||
$location.path('/Journal/' + u.VoucherID)
|
||||
}, function (data, status) {
|
||||
$scope.toasts.push({Type:'Error', Message:data.data});
|
||||
});
|
||||
@ -57,6 +68,8 @@
|
||||
$scope.delete = function () {
|
||||
$scope.voucher.$delete(function (u, putResponseHeaders) {
|
||||
$scope.toasts.push({Type:'Success', Message:''});
|
||||
$location.path('/Journal')
|
||||
|
||||
}, function (data, status) {
|
||||
$scope.toasts.push({Type:'Error', Message:data.data});
|
||||
});
|
||||
|
||||
25
brewman/brewman/static/scripts/user.js
Normal file
25
brewman/brewman/static/scripts/user.js
Normal file
@ -0,0 +1,25 @@
|
||||
function UserListCtrl($scope, User) {
|
||||
$scope.info = User.query();
|
||||
}
|
||||
|
||||
function UserCtrl($scope, $routeParams, User) {
|
||||
$scope.user = User.get({id: $routeParams.id});
|
||||
|
||||
$scope.save = function () {
|
||||
$scope.user.$save(function (u, putResponseHeaders) {
|
||||
$scope.toasts.push({Type:'Success', Message:u.Code});
|
||||
}, function (data, status) {
|
||||
$scope.toasts.push({Type:'Error', Message:data.data});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.delete = function () {
|
||||
$scope.user.$delete(function (u, putResponseHeaders) {
|
||||
$scope.toasts.push({Type:'Success', Message:''});
|
||||
}, function (data, status) {
|
||||
$scope.toasts.push({Type:'Error', Message:data.data});
|
||||
});
|
||||
};
|
||||
$('#txtName').focus();
|
||||
|
||||
}
|
||||
@ -36,7 +36,11 @@
|
||||
${h.ScriptLink(request, 'angular_filter.js')}
|
||||
${h.ScriptLink(request, 'angular_service.js')}
|
||||
${h.ScriptLink(request, 'session.js')}
|
||||
|
||||
${h.ScriptLink(request, 'journal.js')}
|
||||
|
||||
${h.ScriptLink(request, 'account.js')}
|
||||
${h.ScriptLink(request, 'user.js')}
|
||||
|
||||
<!-- Le fav and touch icons -->
|
||||
<link rel="shortcut icon" href="${request.static_url('brewman:static/img/favicon.ico')}">
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:tal="http://xml.zope.org/namespaces/tal"
|
||||
xmlns:metal="http://xml.zope.org/namespaces/metal"
|
||||
metal:use-macro="base">
|
||||
<tal:block metal:fill-slot="content">
|
||||
${h.JsLink(request, 'voucher.js')}
|
||||
${h.JsLink(request, 'user_groups.js')}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#ddlUser').change(function() { Show($('#ddlUser').val()); });
|
||||
$('#ch_All').click(function () {
|
||||
$('[type=checkbox]').attr('checked', this.checked);
|
||||
});
|
||||
|
||||
$("#btnSave").click(function() { return Save('${request.route_url('save_user_groups')}'); });
|
||||
|
||||
window.onpopstate = function(event) {
|
||||
var state = event.state;
|
||||
if (state != null) {
|
||||
$('#ddlUser').val(state.user_id);
|
||||
Show(state.user_id);
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
<article tal:attributes="class pagecontentclass">
|
||||
<section>
|
||||
<h2 class="ribbon-header">User Roles</h2>
|
||||
<form method="post" autocomplete="off">
|
||||
${h.CsrfToken(request.session)}
|
||||
<p>
|
||||
${user}
|
||||
</p>
|
||||
<p>
|
||||
<table id="gvGrid" class="clean-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="GroupID hide">Date</th>
|
||||
<th class="Name"><input type="checkbox" id="ch_All" value="True" /><label for="ch_All">Name</label></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyMain">
|
||||
${body}
|
||||
</tbody>
|
||||
<tfoot id="tfootMain">
|
||||
${footer}
|
||||
</tfoot>
|
||||
</table>
|
||||
</p>
|
||||
<p>
|
||||
${h.SubmitButton('btnSave', 'Save', 'save')}
|
||||
</p>
|
||||
${h.EndForm()}
|
||||
</section>
|
||||
</article>
|
||||
</tal:block>
|
||||
</html>
|
||||
@ -35,6 +35,8 @@
|
||||
${h.ScriptLink(request, 'angular_filter.js')}
|
||||
${h.ScriptLink(request, 'angular_service.js')}
|
||||
${h.ScriptLink(request, 'session.js')}
|
||||
${h.ScriptLink(request, 'account.js')}
|
||||
${h.ScriptLink(request, 'user.js')}
|
||||
|
||||
<%block name="header" />
|
||||
|
||||
|
||||
@ -3,10 +3,8 @@
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="${request.route_url('logout')}">Logout ${user.name}</a></li>
|
||||
<li><a href="/AccountsTesting/Security/ChangePassword.aspx">Change Password</a></li>
|
||||
<li><a href="${request.route_url('user_groups')}">User Groups</a></li>
|
||||
<li><a href="${request.route_url('group_roles')}">Group Roles</a></li>
|
||||
<li><a href="/AccountsTesting/Security/AddUser.aspx">Add User</a></li>
|
||||
<li><a href="/AccountsTesting/Security/DisableUser.aspx">Disable User</a></li>
|
||||
<li><a href="${request.route_url('user_list')}">Users</a></li>
|
||||
<li><a href="/AccountsTesting/Maintenance/Split.aspx">Split Data</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -15,10 +13,8 @@
|
||||
<li tal:condition="not user" class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-user"></i> User <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="${request.route_url('login')}">Log in</a></li>
|
||||
<li><a href="${request.route_url('user_groups')}">User Groups</a></li>
|
||||
<li><a href="${request.route_url('group_roles')}">Group Roles</a></li>
|
||||
<li><a href="/AccountsTesting/Security/AddUser.aspx">Add User</a></li>
|
||||
<li><a href="/AccountsTesting/Security/DisableUser.aspx">Disable User</a></li>
|
||||
<li><a href="${request.route_url('user_list')}">Users</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@ -28,7 +24,6 @@
|
||||
<ul>
|
||||
<li><a href="${request.route_url('logout')}">Logout ${user.name}</a></li>
|
||||
<li><a href="/AccountsTesting/Security/ChangePassword.aspx">Change Password</a></li>
|
||||
<li><a href="${request.route_url('user_groups')}">User Groups</a></li>
|
||||
<li><a href="${request.route_url('group_roles')}">Group Roles</a></li>
|
||||
<li><a href="/AccountsTesting/Security/AddUser.aspx">Add User</a></li>
|
||||
<li><a href="/AccountsTesting/Security/DisableUser.aspx">Disable User</a></li>
|
||||
@ -39,7 +34,6 @@
|
||||
<li tal:condition="not user"><a href="${request.route_url('home')}">Home</a>
|
||||
<ul>
|
||||
<li><a href="${request.route_url('login')}">Log in</a></li>
|
||||
<li><a href="${request.route_url('user_groups')}">User Groups</a></li>
|
||||
<li><a href="${request.route_url('group_roles')}">Group Roles</a></li>
|
||||
<li><a href="/AccountsTesting/Security/AddUser.aspx">Add User</a></li>
|
||||
<li><a href="/AccountsTesting/Security/DisableUser.aspx">Disable User</a></li>
|
||||
|
||||
@ -135,17 +135,17 @@
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code != '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Issue Create')">Save
|
||||
ng-disabled="!perms['Issue Create']">Save
|
||||
</button>
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Issue Update')">
|
||||
ng-disabled="!perms['Issue Update']">
|
||||
Update
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="resetVoucher(voucher.VoucherID)" ng-hide="voucher.Code == '(Auto)'">
|
||||
New Entry
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="delete()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Issue Delete')">
|
||||
ng-disabled="!perms['Issue Delete']">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
<%inherit file="../base.mako"/>
|
||||
<%block name="header">
|
||||
<script type="text/javascript">
|
||||
const perms = ${perms};
|
||||
const voucher = ${json_voucher};
|
||||
</script>
|
||||
${h.ScriptLink(request, 'journal.js')}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('#txtLedger').focus();
|
||||
});
|
||||
</script>
|
||||
</%block>
|
||||
<%block name="content">
|
||||
<form method="post" autocomplete="off" class="form-horizontal" ng-controller="JournalCtrl">
|
||||
${h.CsrfToken(request.session)}
|
||||
<div class="control-group">
|
||||
<label for="txtCode" class="control-label">Code</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" id="txtCode" class="non-search-box" disabled="disabled" ng-model="voucher.Code"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="txtDate" class="control-label">Date</label>
|
||||
|
||||
<div class="controls">
|
||||
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" control-group" id="add">
|
||||
<label for="ddlDebitCredit" class="control-label">Add</label>
|
||||
|
||||
<div class="controls">
|
||||
<select id="ddlDebitCredit" ng-model="debit">
|
||||
<option value="1">Dr</option>
|
||||
<option value="-1">Cr</option>
|
||||
</select>
|
||||
<autocomplete id="txtLedger" url="${request.route_url('services_ledger_list')}" selname="ledger.Name"
|
||||
selid="ledger.LedgerID"></autocomplete>
|
||||
<div class="input-prepend">
|
||||
<span class="add-on">₹</span><input type="text" id="txtAmount" class="span2" autocomplete="off"
|
||||
placeholder="Amount" ng-model="amount"/>
|
||||
</div>
|
||||
<button ng-click="addJournal()">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" control-group">
|
||||
<label for="gvGrid" class="control-label"></label>
|
||||
|
||||
<div class="controls">
|
||||
<table id="gvGrid" class="clean-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="Debit">Debit</th>
|
||||
<th class="Name">Name</th>
|
||||
<th class="Amount">Amount</th>
|
||||
<th class="Delete">Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyMain">
|
||||
<tr ng-repeat="journal in voucher.Journals">
|
||||
<td class="Debit">{{journal.Debit | debit}}</td>
|
||||
<td class="Name">{{journal.Ledger.Name}}</td>
|
||||
<td data-column="Amount" class="Amount Editable">{{journal.Amount}}</td>
|
||||
<td class="Delete">
|
||||
<button ng-click="removeJournal(journal)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot id="tfootMain">
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="txtNarration" class="control-label">Narration</label>
|
||||
|
||||
<div class="controls">
|
||||
<textarea rows="2" cols="20" id="txtNarration"
|
||||
class="non-search-box" ng-model="voucher.Narration"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code != '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Journal Create')">Save
|
||||
</button>
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Journal Update') || (voucher.Posted && !auth.isUserInRole('EditPosted'))">
|
||||
Update
|
||||
</button>
|
||||
<button class="btn btn-inverse" ng-click="post()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="voucher.Posted || !auth.isUserInRole('PostTransactions')">{{voucher.Posted | posted}}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="delete()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Journal Delete') || (voucher.Posted && !auth.isUserInRole('EditPosted'))">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
Created on {{voucher.CreationDate}} and Last Edited on {{voucher.LastEditDate}} by {{voucher.User}}. Posted
|
||||
by {{voucher.Poster}}
|
||||
</div>
|
||||
</form>
|
||||
</%block>
|
||||
@ -92,17 +92,17 @@
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code != '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Payment Create')">Save
|
||||
ng-disabled="!perms['Payment Create']">Save
|
||||
</button>
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Payment Update') || (voucher.Posted && !auth.isUserInRole('EditPosted'))">
|
||||
ng-disabled="!perms['Payment Update'] || (voucher.Posted && !perms['EditPosted'])">
|
||||
Update
|
||||
</button>
|
||||
<button class="btn btn-inverse" ng-click="post()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="voucher.Posted || !auth.isUserInRole('PostTransactions')">{{voucher.Posted | posted}}
|
||||
ng-disabled="voucher.Posted || !perms['PostTransactions']">{{voucher.Posted | posted}}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="delete()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Payment Delete') || (voucher.Posted && !auth.isUserInRole('EditPosted'))">
|
||||
ng-disabled="!perms['Payment Delete'] || (voucher.Posted && !perms['EditPosted'])">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -107,18 +107,18 @@
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code != '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Purchase Create')">Save
|
||||
ng-disabled="!perms['Purchase Create']">Save
|
||||
</button>
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Purchase Update') || (voucher.Posted && !auth.isUserInRole('EditPosted'))">
|
||||
ng-disabled="!perms['Purchase Update'] || (voucher.Posted && !perms['EditPosted'])">
|
||||
Update
|
||||
</button>
|
||||
<button class="btn btn-inverse" ng-click="post()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="voucher.Posted || !auth.isUserInRole('PostTransactions')">{{voucher.Posted |
|
||||
ng-disabled="voucher.Posted || !perms['PostTransactions']">{{voucher.Posted |
|
||||
posted}}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="delete()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Purchase Delete') || (voucher.Posted && !auth.isUserInRole('EditPosted'))">
|
||||
ng-disabled="!perms['Purchase Delete'] || (voucher.Posted && !perms['EditPosted'])">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -95,17 +95,17 @@
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code != '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Receipt Create')">Save
|
||||
ng-disabled="!perms['Receipt Create']">Save
|
||||
</button>
|
||||
<button class="btn btn-primary" ng-click="save()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Receipt Update') || (voucher.Posted && !auth.isUserInRole('EditPosted'))">
|
||||
ng-disabled="!perms['Receipt Update'] || (voucher.Posted && !perms['EditPosted'])">
|
||||
Update
|
||||
</button>
|
||||
<button class="btn btn-inverse" ng-click="post()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="voucher.Posted || !auth.isUserInRole('PostTransactions')">{{voucher.Posted | posted}}
|
||||
ng-disabled="voucher.Posted || !perms['PostTransactions']">{{voucher.Posted | posted}}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="delete()" ng-hide="voucher.Code == '(Auto)'"
|
||||
ng-disabled="!auth.isUserInRole('Receipt Delete') || (voucher.Posted && !auth.isUserInRole('EditPosted'))">
|
||||
ng-disabled="!perms['Receipt Delete'] || (voucher.Posted && !perms['EditPosted'])">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
|
||||
97
brewman/brewman/views/auth/user.py
Normal file
97
brewman/brewman/views/auth/user.py
Normal file
@ -0,0 +1,97 @@
|
||||
import uuid
|
||||
from pyramid.response import Response
|
||||
|
||||
from pyramid.view import view_config
|
||||
import transaction
|
||||
from brewman.models import DBSession
|
||||
from brewman.models.auth import User, Group
|
||||
|
||||
from brewman.models.validation_exception import ValidationError
|
||||
|
||||
@view_config(route_name='user_list', renderer='brewman:templates/angular_base.mako', permission='ManageRoles')
|
||||
@view_config(request_method='GET', route_name='user_id', renderer='brewman:templates/angular_base.mako',
|
||||
xhr=False, permission='ManageRoles')
|
||||
@view_config(request_method='GET', route_name='user', renderer='brewman:templates/angular_base.mako',
|
||||
xhr=False, permission='ManageRoles')
|
||||
def html(request):
|
||||
return {}
|
||||
|
||||
|
||||
@view_config(request_method='POST', route_name='user_id', renderer='json', xhr=True, permission='CreateUser')
|
||||
@view_config(request_method='POST', route_name='user', renderer='json', xhr=True, permission='CreateUser')
|
||||
def save_update(request):
|
||||
try:
|
||||
id = request.matchdict.get('id', None)
|
||||
if id is None:
|
||||
user = User(request.json_body['Name'], request.json_body['Password'], request.json_body['LockedOut'])
|
||||
DBSession.add(user)
|
||||
else:
|
||||
user = User.get_by_id(uuid.UUID(id))
|
||||
user.name = request.json_body['Name']
|
||||
user.locked_out = request.json_body['LockedOut']
|
||||
if request.json_body['Password'] != '' and request.json_body['Password'] != user.password:
|
||||
user.password = request.json_body['Password']
|
||||
for group in request.json_body['Groups']:
|
||||
print(group)
|
||||
id = uuid.UUID(group['GroupID'])
|
||||
ug = [g for g in user.groups if g.id == id]
|
||||
ug = None if len(ug) == 0 else ug[0]
|
||||
if group['Enabled'] and ug is None:
|
||||
user.groups.append(Group.get_by_id(id))
|
||||
elif not group['Enabled'] and ug:
|
||||
user.groups.remove(ug)
|
||||
transaction.commit()
|
||||
return user_info(user.id)
|
||||
except ValidationError as ex:
|
||||
transaction.abort()
|
||||
response = Response("Failed validation: {0}".format(ex.message))
|
||||
response.status_int = 500
|
||||
return response
|
||||
|
||||
|
||||
@view_config(request_method='DELETE', route_name='user_id', renderer='json', xhr=True, permission='CreateUser')
|
||||
def delete(request):
|
||||
id = request.matchdict.get('id', None)
|
||||
if id is None:
|
||||
response = Response("User is Null")
|
||||
response.status_int = 500
|
||||
return response
|
||||
else:
|
||||
response = Response("User deletion not implemented")
|
||||
response.status_int = 500
|
||||
return response
|
||||
|
||||
|
||||
@view_config(request_method='GET', route_name='user_id', renderer='json', xhr=True, permission='ManageRoles')
|
||||
@view_config(request_method='GET', route_name='user', renderer='json', xhr=True, permission='ManageRoles')
|
||||
def show(request):
|
||||
list = request.GET.get('list', None)
|
||||
|
||||
if list:
|
||||
list = User.list()
|
||||
users = []
|
||||
for item in list:
|
||||
user = {'Name': item.name, 'LockedOut': item.locked_out,
|
||||
'Groups': [], 'Url': request.route_url('user_id', id=item.id)}
|
||||
for group in item.groups:
|
||||
user['Groups'].append(group.name)
|
||||
users.append(user)
|
||||
return users
|
||||
else:
|
||||
id = request.matchdict.get('id', None)
|
||||
id = None if id is None else uuid.UUID(id)
|
||||
return user_info(id)
|
||||
|
||||
|
||||
def user_info(id):
|
||||
if id is None:
|
||||
return {'Name': '', 'LockedOut': False, 'Groups': []}
|
||||
else:
|
||||
user = User.get_by_id(id)
|
||||
account = {'UserID': user.id, 'Name': user.name, 'Password': '', 'LockedOut': user.locked_out, 'Groups': []}
|
||||
for item in Group.list():
|
||||
account['Groups'].append(
|
||||
{'GroupID': item.id, 'Name': item.name, 'Enabled': True if item in user.groups else False})
|
||||
return account
|
||||
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
import uuid
|
||||
|
||||
from pyramid.view import view_config
|
||||
import transaction
|
||||
from brewman.helpers import Literal, SelectInput
|
||||
from brewman.models.auth import User, Group
|
||||
|
||||
@view_config(request_method='GET', route_name='user_groups', permission='ManageRoles',
|
||||
renderer='brewman:templates/auth/user_groups.pt')
|
||||
@view_config(request_method='GET', route_name='user_groups_id', permission='ManageRoles',
|
||||
renderer='brewman:templates/auth/user_groups.pt')
|
||||
def user_groups_get(request):
|
||||
id = request.matchdict.get('id', None)
|
||||
id = None if id is None else uuid.UUID(id)
|
||||
user = SelectInput('ddlUser', list=User.list(), displayField='name', valueField='id', defaultValue=id)
|
||||
body, footer = build_report(request, id)
|
||||
body = Literal(body)
|
||||
footer = Literal(footer)
|
||||
|
||||
return {'title': 'User Groups',
|
||||
'pageclass': "page-blogpost page-sidebar-right",
|
||||
'pagecontentclass': "page-content grid_12",
|
||||
'page_header': '',
|
||||
'user': user,
|
||||
'body': body,
|
||||
'footer': footer}
|
||||
|
||||
|
||||
@view_config(request_method='POST', route_name='user_groups', permission='ManageRoles', renderer='json', xhr=True)
|
||||
@view_config(request_method='POST', route_name='user_groups_id', permission='ManageRoles', renderer='json', xhr=True)
|
||||
def user_groups_post(request):
|
||||
id = request.json_body['user_id']
|
||||
body, footer = build_report(request, uuid.UUID(id))
|
||||
url = request.route_url('user_groups_id', id=id)
|
||||
return {'user_id': id,
|
||||
'url': url,
|
||||
'body': body}
|
||||
|
||||
|
||||
@view_config(request_method='POST', route_name='save_user_groups', permission='ManageRoles', renderer='json', xhr=True)
|
||||
def user_groups_save(request):
|
||||
id = request.json_body['user_id']
|
||||
user = User.get_by_id(uuid.UUID(id))
|
||||
for item in request.json_body['selected_groups']:
|
||||
group = Group.get_by_id(uuid.UUID(item['group_id']))
|
||||
selected = item['selected']
|
||||
if selected and group not in user.groups:
|
||||
user.groups.append(group)
|
||||
elif not selected and group in user.groups:
|
||||
user.groups.remove(group)
|
||||
transaction.commit()
|
||||
return 'Groups Updated'
|
||||
|
||||
|
||||
def build_report(request, id):
|
||||
body = ''
|
||||
if id is None:
|
||||
for item in Group.list():
|
||||
body += '<tr class="Entry"><td class="GroupID hide">{0}</td><td class="Name=">'\
|
||||
'<input type="checkbox" id="ch_{0}" value="True" /><label for="ch_{0}">{1}</label></td></tr>'\
|
||||
.format(str(item.id), item.name)
|
||||
else:
|
||||
user = User.get_by_id(id)
|
||||
for item in Group.list():
|
||||
if item in user.groups:
|
||||
checked = ' checked="checked"'
|
||||
else:
|
||||
checked = ''
|
||||
body += '<tr class="Entry"><td class="GroupID hide">{0}</td><td class="Name=">'\
|
||||
'<input type="checkbox" id="ch_{0}"{2} value="True" /><label for="ch_{0}">{1}</label></td></tr>'\
|
||||
.format(str(item.id), item.name, checked)
|
||||
footer = '<tr><td class="GroupID hide"></td><td class="Name="></td></tr>'
|
||||
return body, footer
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ from datetime import date, timedelta
|
||||
import json
|
||||
|
||||
from pyramid.view import view_config
|
||||
from brewman.models.auth import Role
|
||||
from brewman.views.transactions import session_current_date
|
||||
|
||||
@view_config(route_name='services_session_current_date', renderer='json', xhr=True)
|
||||
@ -47,8 +48,13 @@ def is_user_in_roles(request):
|
||||
|
||||
@view_config(route_name='user_permissions', renderer='json', xhr=True)
|
||||
def user_permission(request):
|
||||
print(json.dumps(request.session['perms']))
|
||||
return request.session['perms']
|
||||
session_perms = request.session['perms']
|
||||
perms = {}
|
||||
|
||||
for item in Role.list():
|
||||
perms[item.name] = True if item.name in session_perms else False
|
||||
|
||||
return perms
|
||||
|
||||
|
||||
def get_first_day(dt, d_years=0, d_months=0):
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import json
|
||||
import uuid
|
||||
from pyramid.response import Response
|
||||
from pyramid.security import authenticated_userid
|
||||
@ -9,10 +8,10 @@ from brewman.models.auth import User
|
||||
from brewman.models.master import LedgerBase, CostCenter
|
||||
from brewman.models.validation_exception import ValidationError
|
||||
from brewman.models.voucher import Voucher, VoucherType
|
||||
from brewman.views import DecimalEncoder
|
||||
from brewman.views.services.voucher.issue import issue_create_voucher, issue_update_voucher
|
||||
from brewman.views.services.voucher.journal import journal_update_voucher, journal_create_voucher
|
||||
from brewman.views.services.voucher.purchase import purchase_create_voucher, purchase_update_voucher
|
||||
from brewman.views.transactions import session_current_date
|
||||
|
||||
__author__ = 'tanshu'
|
||||
|
||||
@ -108,17 +107,14 @@ def delete(request):
|
||||
def get(request):
|
||||
id = request.matchdict.get('id', None)
|
||||
voucher_type = request.GET.get('type', None)
|
||||
if id is None:
|
||||
response = Response("Voucher is Null")
|
||||
if id:
|
||||
return voucher_info(Voucher.by_id(uuid.UUID(id)))
|
||||
elif voucher_type:
|
||||
return blank_voucher(type=voucher_type, date=session_current_date(request))
|
||||
else:
|
||||
response = Response("Voucher ID and Type, both are Null")
|
||||
response.status_int = 500
|
||||
return response
|
||||
else:
|
||||
voucher = voucher_info(Voucher.by_id(uuid.UUID(id)))
|
||||
if voucher_type is None:
|
||||
return voucher
|
||||
else:
|
||||
# voucher = json.dumps(voucher, cls=DecimalEncoder)
|
||||
return blank_voucher(type=voucher_type, additionalInfo=voucher)
|
||||
|
||||
|
||||
def voucher_info(voucher):
|
||||
@ -140,10 +136,10 @@ def voucher_info(voucher):
|
||||
'CostCenter': {'CostCenterID': item.cost_center_id}})
|
||||
for item in voucher.inventories:
|
||||
json_voucher['Inventories'].append(
|
||||
{'InventoryID': item.id, 'Quantity': item.quantity, 'Rate': item.rate,
|
||||
'Tax': item.tax, 'Discount': item.discount, 'Amount': item.amount,
|
||||
'Product': {'ProductID': item.product.id, 'Name': item.product.name, 'Units': item.product.units},
|
||||
'Batch': {'BatchID': item.batch.id, 'QuantityRemaining': item.batch.quantity_remaining}})
|
||||
{'InventoryID': item.id, 'Quantity': item.quantity, 'Rate': item.rate,
|
||||
'Tax': item.tax, 'Discount': item.discount, 'Amount': item.amount,
|
||||
'Product': {'ProductID': item.product.id, 'Name': item.product.name, 'Units': item.product.units},
|
||||
'Batch': {'BatchID': item.batch.id, 'QuantityRemaining': item.batch.quantity_remaining}})
|
||||
return json_voucher
|
||||
|
||||
|
||||
|
||||
@ -10,19 +10,9 @@ from brewman.views import DecimalEncoder
|
||||
from brewman.views.services.voucher import voucher_info, blank_voucher
|
||||
from brewman.views.transactions import session_current_date
|
||||
|
||||
@view_config(request_method='GET', route_name='journal_id', renderer='brewman:templates/transaction/journal.mako',
|
||||
@view_config(request_method='GET', route_name='journal_id', renderer='brewman:templates/angular_base.mako',
|
||||
permission='Journal Update')
|
||||
@view_config(request_method='GET', route_name='journal', renderer='brewman:templates/transaction/journal.mako',
|
||||
@view_config(request_method='GET', route_name='journal', renderer='brewman:templates/angular_base.mako',
|
||||
permission='Journal Create')
|
||||
def journal_get(request):
|
||||
id = request.matchdict.get('id', None)
|
||||
perms = Literal(json.dumps(request.session['perms']))
|
||||
if id is None:
|
||||
json_voucher = Literal(json.dumps(blank_voucher('Journal', session_current_date(request)), cls=DecimalEncoder))
|
||||
else:
|
||||
voucher = Voucher.by_id(uuid.UUID(id))
|
||||
json_voucher = Literal(json.dumps(voucher_info(voucher), cls=DecimalEncoder))
|
||||
return {'title': 'Hops n Grains - Journal Entry',
|
||||
'id': id,
|
||||
'perms': perms,
|
||||
'json_voucher': json_voucher}
|
||||
return {}
|
||||
Reference in New Issue
Block a user