Added client list, full management pending.

Added limiting of clients via cookies.
Added Attendence report download and credit salary in employee functions.
Renamed get_by_id and get_by_name in User, Group and Role models.
Added salary staff account in LedgerBase.
Voucher validation to be checked.
Added csv renderer for downloading csv files.
Added ngCookies module to process ClientID in login form on client side.
Modified the datepicker directive to process model properly.
Fixed Employee Attendance, was broken.
Allowed batch quantity to increase in multiple entries of same product batch in issue.
Ledger report would not reload data if ledger and dates were not changed, fixed that.
This commit is contained in:
Tanshu committed 2012-11-09 00:13:04 +05:30
1 parent 48c4d79bdf
commit bb820febff
68 files changed
+875 -371

No files matched your search

+13 -4
View File
@@ -29,7 +29,8 @@ def main(global_config, **settings):
) )
# This changes in pyramid 1.4 to something similar to "config.add_renderer('myjson', JSON(indent=4))" # This changes in pyramid 1.4 to something similar to "config.add_renderer('myjson', JSON(indent=4))"
# http://docs.pylonsproject.org/projects/pyramid/en/master/api/renderers.html#pyramid.renderers.JSON # http://docs.pylonsproject.org/projects/pyramid/en/master/api/renderers.html#pyramid.renderers.JSON
config.add_renderer('json', factory='brewman.views.my_json_renderer_factory') config.add_renderer(name='json', factory='brewman.renderers.my_json_renderer_factory')
config.add_renderer(name='csv', factory='brewman.renderers.CSVRenderer')
config.add_static_view('icons', 'brewman:static/icons') config.add_static_view('icons', 'brewman:static/icons')
config.add_static_view('assets', 'brewman:static/assets') config.add_static_view('assets', 'brewman:static/assets')
@@ -66,6 +67,10 @@ def main(global_config, **settings):
config.add_route('group', '/Group') config.add_route('group', '/Group')
config.add_route('group_list', '/Groups') config.add_route('group_list', '/Groups')
config.add_route('client_id', '/Client/{id}')
config.add_route('client', '/Client')
config.add_route('client_list', '/Clients')
config.add_route('product_id', '/Product/{id}') config.add_route('product_id', '/Product/{id}')
config.add_route('product', '/Product') config.add_route('product', '/Product')
config.add_route('product_list', '/Products') config.add_route('product_list', '/Products')
@@ -88,6 +93,9 @@ def main(global_config, **settings):
config.add_route('issue', '/Issue') config.add_route('issue', '/Issue')
config.add_route('issues_grid', '/Issues/Services/{date}') config.add_route('issues_grid', '/Issues/Services/{date}')
config.add_route('voucher', '/Voucher/{id}')
config.add_route('voucher_new', '/Voucher')
config.add_route('attendance_date', '/Attendance/{date}') config.add_route('attendance_date', '/Attendance/{date}')
config.add_route('attendance', '/Attendance') config.add_route('attendance', '/Attendance')
config.add_route('attendance_types', '/AttendanceTypes') config.add_route('attendance_types', '/AttendanceTypes')
@@ -95,6 +103,10 @@ def main(global_config, **settings):
config.add_route('employee_attendance_id', '/EmployeeAttendance/{id}') config.add_route('employee_attendance_id', '/EmployeeAttendance/{id}')
config.add_route('employee_attendance', '/EmployeeAttendance') config.add_route('employee_attendance', '/EmployeeAttendance')
config.add_route('attendance_report', '/AttendanceReport')
config.add_route('credit_salary', '/CreditSalary')
config.add_route('employee_functions', '/EmployeeFunctions')
config.add_route('ledger_id', '/Ledger/{id}') config.add_route('ledger_id', '/Ledger/{id}')
config.add_route('ledger', '/Ledger') config.add_route('ledger', '/Ledger')
@@ -124,9 +136,6 @@ def main(global_config, **settings):
config.add_route('account_type_list', '/AccountTypes') config.add_route('account_type_list', '/AccountTypes')
config.add_route('voucher', '/Voucher/{id}')
config.add_route('voucher_new', '/Voucher')
config.add_route('favicon', '/favicon.ico') config.add_route('favicon', '/favicon.ico')
config.scan() config.scan()
+5 -6
View File
@@ -56,7 +56,6 @@ class Client(Base):
client_code = random.randint(1000, 9999) client_code = random.randint(1000, 9999)
otp = random.randint(1000, 9999) otp = random.randint(1000, 9999)
name = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(6)) name = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(6))
# name = str(client_code)
client = Client(client_code, name, False, otp) client = Client(client_code, name, False, otp)
DBSession.add(client) DBSession.add(client)
return client return client
@@ -108,18 +107,18 @@ class User(Base):
self.locked_out = locked_out self.locked_out = locked_out
@classmethod @classmethod
def get_by_name(cls, name): def by_name(cls, name):
return DBSession.query(cls).filter(cls.name == name).first() return DBSession.query(cls).filter(cls.name == name).first()
@classmethod @classmethod
def get_by_id(cls, id): def by_id(cls, id):
if not isinstance(id, uuid.UUID): if not isinstance(id, uuid.UUID):
id = uuid.UUID(id) id = uuid.UUID(id)
return DBSession.query(cls).filter(cls.id == id).one() return DBSession.query(cls).filter(cls.id == id).one()
@classmethod @classmethod
def auth(cls, name, password): def auth(cls, name, password):
user = cls.get_by_name(name) user = cls.by_name(name)
if not user: if not user:
return False, None return False, None
if user.password != encrypt(password) or user.locked_out: if user.password != encrypt(password) or user.locked_out:
@@ -149,7 +148,7 @@ class Group(Base):
self.name = name self.name = name
@classmethod @classmethod
def get_by_id(cls, id): def by_id(cls, id):
return DBSession.query(cls).filter(cls.id == id).one() return DBSession.query(cls).filter(cls.id == id).one()
@classmethod @classmethod
@@ -173,6 +172,6 @@ class Role(Base):
return DBSession.query(cls).order_by(cls.name).all() return DBSession.query(cls).order_by(cls.name).all()
@classmethod @classmethod
def get_by_id(cls, id): def by_id(cls, id):
return DBSession.query(cls).filter(cls.id == id).one() return DBSession.query(cls).filter(cls.id == id).one()
+4
View File
@@ -223,6 +223,10 @@ class LedgerBase(Base):
def local_purchase(cls): def local_purchase(cls):
return {'LedgerID': 'd2b75912-505f-2548-9093-466dfff6a0f9', 'Name': 'local purchase'} return {'LedgerID': 'd2b75912-505f-2548-9093-466dfff6a0f9', 'Name': 'local purchase'}
@classmethod
def salary(cls):
return {'LedgerID': '5c2b54d0-c174-004d-a0d5-92cdaadcefa7', 'Name': 'salary staff'}
class Employee(LedgerBase): class Employee(LedgerBase):
__tablename__ = 'entities_employees' __tablename__ = 'entities_employees'
+1 -12
View File
@@ -34,24 +34,13 @@ def update_journal_voucher(voucher):
update_basic(voucher) update_basic(voucher)
def create_purchase_voucher(voucher): def validate_new_purchase_voucher(voucher):
journals_valid(voucher) journals_valid(voucher)
for item in voucher.inventories: for item in voucher.inventories:
batch = item.batch batch = item.batch
if not batch.id is None: if not batch.id is None:
raise ValidationError("New Purchase cannot have a Batch") raise ValidationError("New Purchase cannot have a Batch")
create_basic(voucher)
for item in voucher.journals:
item.voucher_id = voucher.id
DBSession.add(item)
for item in voucher.inventories:
item.voucher_id = voucher.id
DBSession.add(item.batch)
item.batch_id = item.batch.id
DBSession.add(item)
DBSession.flush()
def update_purchase_voucher(voucher): def update_purchase_voucher(voucher):
journals_valid(voucher) journals_valid(voucher)
+3 -3
View File
@@ -50,13 +50,13 @@ class Voucher(Base):
def __name__(self): def __name__(self):
return self.name return self.name
def __init__(self, date=None, reconcilliation_date=None, narration=None, posted=None, creation_date=None, last_edit_date=None, type=None, user_id=None, poster_id=None): def __init__(self, date=None, reconcilliation_date=None, narration=None, posted=False, creation_date=None, last_edit_date=None, type=None, user_id=None, poster_id=None):
self.date = date self.date = date
self.reconcilliation_date = reconcilliation_date self.reconcilliation_date = reconcilliation_date
self.narration = narration self.narration = narration
self.posted = posted self.posted = posted
self.creation_date = creation_date self.creation_date = datetime.now() if creation_date is None else creation_date
self.last_edit_date = last_edit_date self.last_edit_date = datetime.now() if last_edit_date is None else last_edit_date
self.type = type self.type = type
self.user_id = user_id self.user_id = user_id
self.poster_id = poster_id self.poster_id = poster_id
+46
View File
@@ -0,0 +1,46 @@
import csv
from io import StringIO
import json
from brewman.views import DecimalEncoder
__author__ = 'tanshu'
class CSVRenderer(object):
def __init__(self, info):
pass
def __call__(self, value, system):
csv_data = StringIO()
writer = csv.writer(csv_data, delimiter=',', quoting=csv.QUOTE_MINIMAL)
if 'header' in value:
writer.writerow(value['header'])
if 'rows' in value:
writer.writerows(value['rows'])
if 'footer' in value:
writer.writerows(value['footer'])
request = system.get('request')
if request is not None:
response = request.response
ct = response.content_type
if ct == response.default_content_type:
response.content_type = 'text/csv'
filename = value['filename'] if 'filename' in value else 'report.csv'
response.content_disposition = 'attachment;filename="{0}"'.format(filename)
return csv_data.getvalue()
class my_json_renderer_factory:
def __init__(self, info):
pass
def __call__(self, value, system):
request = system.get('request')
if request is not None:
response = request.response
ct = response.content_type
if ct == response.default_content_type:
response.content_type = 'application/json'
return json.dumps(value, cls=DecimalEncoder)
+1 -1
View File
@@ -5,7 +5,7 @@ def groupfinder(user_id, request):
if type(user_id) == str: if type(user_id) == str:
user_id = uuid.UUID(user_id) user_id = uuid.UUID(user_id)
perms = [] perms = []
user = User.get_by_id(user_id) user = User.by_id(user_id)
for item in user.groups: for item in user.groups:
for perm in item.roles: for perm in item.roles:
perms.append(perm.name) perms.append(perm.name)
+5 -34
View File
@@ -1,41 +1,12 @@
/* Table for Issue */ /* Table for Issue */
.no-wrap {
white-space: nowrap
}
.hide .hide
{ {
display: none; display: none;
} }
.clean-table .table tbody tr.success td {
{ background-color: #1F7A1F;
background: #fff;
width: 100%;
}
.clean-table th
{
color: #039;
}
.clean-table td:not(.posted)
{
color: #669;
}
.clean-table tbody tr:not(.unposted):hover td
{
color: #339;
background: #d0dafd;
} }
.clean-table tbody tr:nth-child(odd):not(.unposted)
{
background: #e8edff;
}
.clean-table tfoot tr
{
color: #039;
}
.unposted
{
background-color: Pink;
}
.right
{
text-align:right;
}
@@ -0,0 +1,171 @@
/**
* @license AngularJS v1.0.2
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
/**
* @ngdoc overview
* @name ngCookies
*/
angular.module('ngCookies', ['ng']).
/**
* @ngdoc object
* @name ngCookies.$cookies
* @requires $browser
*
* @description
* Provides read/write access to browser's cookies.
*
* Only a simple Object is exposed and by adding or removing properties to/from
* this object, new cookies are created/deleted at the end of current $eval.
*
* @example
*/
factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
var cookies = {},
lastCookies = {},
lastBrowserCookies,
runEval = false,
copy = angular.copy,
isUndefined = angular.isUndefined;
//creates a poller fn that copies all cookies from the $browser to service & inits the service
$browser.addPollFn(function() {
var currentCookies = $browser.cookies();
if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
lastBrowserCookies = currentCookies;
copy(currentCookies, lastCookies);
copy(currentCookies, cookies);
if (runEval) $rootScope.$apply();
}
})();
runEval = true;
//at the end of each eval, push cookies
//TODO: this should happen before the "delayed" watches fire, because if some cookies are not
// strings or browser refuses to store some cookies, we update the model in the push fn.
$rootScope.$watch(push);
return cookies;
/**
* Pushes all the cookies from the service to the browser and verifies if all cookies were stored.
*/
function push() {
var name,
value,
browserCookies,
updated;
//delete any cookies deleted in $cookies
for (name in lastCookies) {
if (isUndefined(cookies[name])) {
$browser.cookies(name, undefined);
}
}
//update all cookies updated in $cookies
for(name in cookies) {
value = cookies[name];
if (!angular.isString(value)) {
if (angular.isDefined(lastCookies[name])) {
cookies[name] = lastCookies[name];
} else {
delete cookies[name];
}
} else if (value !== lastCookies[name]) {
$browser.cookies(name, value);
updated = true;
}
}
//verify what was actually stored
if (updated){
updated = false;
browserCookies = $browser.cookies();
for (name in cookies) {
if (cookies[name] !== browserCookies[name]) {
//delete or reset all cookies that the browser dropped from $cookies
if (isUndefined(browserCookies[name])) {
delete cookies[name];
} else {
cookies[name] = browserCookies[name];
}
updated = true;
}
}
}
}
}]).
/**
* @ngdoc object
* @name ngCookies.$cookieStore
* @requires $cookies
*
* @description
* Provides a key-value (string-object) storage, that is backed by session cookies.
* Objects put or retrieved from this storage are automatically serialized or
* deserialized by angular's toJson/fromJson.
* @example
*/
factory('$cookieStore', ['$cookies', function($cookies) {
return {
/**
* @ngdoc method
* @name ngCookies.$cookieStore#get
* @methodOf ngCookies.$cookieStore
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value.
*/
get: function(key) {
return angular.fromJson($cookies[key]);
},
/**
* @ngdoc method
* @name ngCookies.$cookieStore#put
* @methodOf ngCookies.$cookieStore
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
*/
put: function(key, value) {
$cookies[key] = angular.toJson(value);
},
/**
* @ngdoc method
* @name ngCookies.$cookieStore#remove
* @methodOf ngCookies.$cookieStore
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
*/
remove: function(key) {
delete $cookies[key];
}
};
}]);
})(window, window.angular);
@@ -1,5 +1,5 @@
<legend>Accounts <a href="/Account" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend> <legend>Accounts <a href="/Account" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend>
<table class="table table-bordered clean-table"> <table class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
@@ -4,7 +4,7 @@
<label for="txtDate" class="control-label">Date</label> <label for="txtDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtDate" model="info" prop="Date" ng-model="info.Date"></datepicker> <datepicker id="txtDate" model="info.Date" ng-model="info.Date"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button> <button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div> </div>
</div> </div>
@@ -12,7 +12,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th class="right">Code</th> <th class="right">Code</th>
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button> <button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div> </div>
</div> </div>
@@ -13,7 +13,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
@@ -0,0 +1,20 @@
<legend>Clients</legend>
<table class="table table-condensed table-bordered table-striped">
<thead>
<tr>
<th>Code</th>
<th>Name</th>
<th>Enabled</th>
<th>OTP</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in info">
<td>{{item.Code}}</td>
<td>{{item.Name}}</td>
<td>{{item.Enabled}}</td>
<td>{{item.OTP}}</td>
</tr>
</tbody>
</table>
@@ -4,7 +4,7 @@
<label for="txtDate" class="control-label">Date</label> <label for="txtDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtDate" model="info" prop="Date" ng-model="info.Date"></datepicker> <datepicker id="txtDate" model="info.Date" ng-model="info.Date"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button> <button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div> </div>
</div> </div>
@@ -12,7 +12,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Product</th> <th>Product</th>
@@ -1,5 +1,5 @@
<legend>Cost Centers <a href="/CostCenter" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend> <legend>Cost Centers <a href="/CostCenter" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend>
<table class="table table-bordered clean-table"> <table class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
+4 -4
View File
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button> <button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div> </div>
</div> </div>
@@ -13,7 +13,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Date</th> <th>Date</th>
@@ -26,7 +26,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info.Body" ng-class="{true:'', false:'warning'}[item.Posted]"> <tr ng-repeat="item in info.Body" ng-class="{true:'', false:'error'}[item.Posted]">
<td><a href="{{item.Url}}">{{item.Date}}</a></td> <td><a href="{{item.Url}}">{{item.Date}}</a></td>
<td>{{item.Type}}</td> <td>{{item.Type}}</td>
<td>{{item.Narration}}</td> <td>{{item.Narration}}</td>
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
@@ -21,21 +21,27 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered">
<thead> <thead>
<tr> <tr>
<th>Date</th> <th>Date</th>
<th>Status</th> <th>Status</th>
<th>isDirty</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info.Body"> <tr ng-repeat="item in info.Body"
ng-class="{0:'', 1:'', 2:'info', 3:'error', 4:'error', 5:'', 6:'', 7:'warning', 8:'success'}[item.AttendanceTypeID]"
ng-controller="EmployeeAttendanceSubCtrl">
<td>{{item.Date}}</td> <td>{{item.Date}}</td>
<td> <td>
<select class="select-box" ng-model="item.AttendanceTypeID" <select name="box" class="select-box" ng-model="item.AttendanceTypeID"
ng-options="i.AttendanceTypeID as i.Name for i in attendance_types"> </select> ng-options="i.AttendanceTypeID as i.Name for i in attendance_types"> </select>
</td> </td>
<td>
<button ng-hide="!isDirty()" class="btn btn-primary">Is Dirty</button>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -56,8 +56,7 @@
<label for="txtJoiningDate" class="control-label">Joining Date</label> <label for="txtJoiningDate" class="control-label">Joining Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtJoiningDate" model="employee" prop="JoiningDate" <datepicker id="txtJoiningDate" model="employee.JoiningDate" ng-model="employee.JoiningDate"></datepicker>
ng-model="employee.JoiningDate"></datepicker>
</div> </div>
</div> </div>
@@ -65,8 +64,7 @@
<label for="txtLeavingDate" class="control-label">Leaving Date</label> <label for="txtLeavingDate" class="control-label">Leaving Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtLeavingDate" model="employee" prop="LeavingDate" <datepicker id="txtLeavingDate" model="employee.LeavingDate" ng-model="employee.LeavingDate"></datepicker>
ng-model="employee.LeavingDate"></datepicker>
</div> </div>
</div> </div>
@@ -4,8 +4,18 @@
<label for="txtSalaryMonth" class="control-label">Month</label> <label for="txtSalaryMonth" class="control-label">Month</label>
<div class="controls"> <div class="controls">
<datepicker id="txtSalaryMonth" model="info" prop="SalaryMonth" ng-model="salaryMonth"></datepicker> <datepicker id="txtSalaryMonth" model="salaryMonth" ng-model="salaryMonth"></datepicker>
<button class="btn" ng-click="creditSalary()">Credit</button> <button class="btn btn-info" ng-click="creditSalary()">Credit <i class="icon-leaf icon-white"></i></button>
</div>
</div>
<legend>Attendance Record</legend>
<div class="control-group">
<label for="txtRecordStart" class="control-label">Date</label>
<div class="controls">
<datepicker id="txtRecordStart" model="record.Start" ng-model="record.Start"></datepicker>
<datepicker id="txtRecordFinish" model="record.Finish" ng-model="record.Finish"></datepicker>
<a class="btn btn-info" ng-href="{{attendanceRecordUrl()}}" target="_self">Download <i class="icon-download-alt icon-white"></i></a>
</div> </div>
</div> </div>
<legend>Credit Esi / Pf</legend> <legend>Credit Esi / Pf</legend>
@@ -13,7 +23,7 @@
<label for="txtEsiPfMonth" class="control-label">Month</label> <label for="txtEsiPfMonth" class="control-label">Month</label>
<div class="controls"> <div class="controls">
<datepicker id="txtEsiPfMonth" model="info" prop="EsiPfMonth" ng-model="esiPfMonth"></datepicker> <datepicker id="txtEsiPfMonth" model="esiPfMonth" ng-model="esiPfMonth"></datepicker>
<button class="btn" ng-click="creditEsiPf()">Credit</button> <button class="btn" ng-click="creditEsiPf()">Credit</button>
</div> </div>
</div> </div>
@@ -1,6 +1,6 @@
<legend>Employees <a href="/Employee" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a> <legend>Employees <a href="/Employee" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a>
</legend> </legend>
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Code</th> <th>Code</th>
@@ -1,5 +1,5 @@
<legend>Users <a href="/Group" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend> <legend>Users <a href="/Group" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend>
<table class="table table-bordered clean-table"> <table class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
+3 -3
View File
@@ -4,7 +4,7 @@
<label for="gvSmall" class="control-label"></label> <label for="gvSmall" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvSmall" class="table table-bordered clean-table"> <table id="gvSmall" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Amount</th> <th>Amount</th>
@@ -25,7 +25,7 @@
<label for="txtDate" class="control-label">Date</label> <label for="txtDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker> <datepicker id="txtDate" model="voucher.Date" ng-model="voucher.Date"></datepicker>
</div> </div>
</div> </div>
@@ -73,7 +73,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Product</th> <th>Product</th>
+2 -2
View File
@@ -4,7 +4,7 @@
<label for="txtDate" class="control-label">Date</label> <label for="txtDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker> <datepicker id="txtDate" model="voucher.Date" ng-model="voucher.Date"></datepicker>
</div> </div>
</div> </div>
<div class=" control-group" id="add"> <div class=" control-group" id="add">
@@ -27,7 +27,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Debit</th> <th>Debit</th>
+10 -10
View File
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
@@ -20,7 +20,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Date</th> <th>Date</th>
@@ -33,19 +33,19 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info.Body" ng-class="{true:'', false:'warning'}[item.Posted]"> <tr ng-repeat="item in info.Body" ng-class="{true:'', false:'error'}[item.Posted]">
<td>{{item.Date}}</td> <td class="no-wrap">{{item.Date}}</td>
<td><a href="{{item.Url}}">{{item.Name}}</a></td> <td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td>{{item.Type}}</td> <td class="no-wrap">{{item.Type}}</td>
<td>{{item.Narration}}</td> <td>{{item.Narration}}</td>
<td class="right">{{item.Debit}}</td> <td class="right no-wrap">{{item.Debit}}</td>
<td class="right">{{item.Credit}}</td> <td class="right no-wrap">{{item.Credit}}</td>
<td class="right">{{item.Running}}</td> <td class="right no-wrap">{{item.Running}}</td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
<tr> <tr>
<td>{{info.Footer.Date}}</td> <td class="no-wrap">{{info.Footer.Date}}</td>
<td>{{info.Footer.Name}}</td> <td>{{info.Footer.Name}}</td>
<td>{{info.Footer.Type}}</td> <td>{{info.Footer.Type}}</td>
<td>{{info.Footer.Narration}}</td> <td>{{info.Footer.Narration}}</td>
+15
View File
@@ -14,6 +14,21 @@
<input type="password" ng-model="password" id="password" required placeholder="Password"/> <input type="password" ng-model="password" id="password" required placeholder="Password"/>
</div> </div>
</div> </div>
<legend ng-show="showOTP">ClientID {{clientID}}</legend>
<div class="control-group" ng-show="showOTP">
<label class="control-label" for="otp">OTP</label>
<div class="controls">
<input type="text" ng-model="otp" id="otp" required placeholder="OTP"/>
</div>
</div>
<div class="control-group" ng-show="showOTP">
<label class="control-label" for="name">Client Name</label>
<div class="controls">
<input type="text" ng-model="name" id="name" required placeholder="Client Name"/>
</div>
</div>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="forgot"></label> <label class="control-label" for="forgot"></label>
+3 -3
View File
@@ -3,7 +3,7 @@
<label for="txtDate" class="control-label">Date</label> <label for="txtDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker> <datepicker id="txtDate" model="voucher.Date" ng-model="voucher.Date"></datepicker>
</div> </div>
</div> </div>
<div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:-1"> <div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:-1">
@@ -11,7 +11,7 @@
<div class="controls"> <div class="controls">
<select id="ddlLedger" class="select-box" ng-model="journal.Ledger.LedgerID" <select id="ddlLedger" class="select-box" ng-model="journal.Ledger.LedgerID"
ng-options="l.id as l.label for l in ledgers"> </select> ng-options="l.model.LedgerID as l.label for l in ledgers"> </select>
<div class=" input-prepend"> <div class=" input-prepend">
<span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2" autocomplete="off" <span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2" autocomplete="off"
@@ -37,7 +37,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
@@ -1,5 +1,5 @@
<legend>Product Groups <a href="/ProductGroup" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend> <legend>Product Groups <a href="/ProductGroup" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend>
<table class="table table-bordered clean-table"> <table class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
@@ -21,7 +21,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Date</th> <th>Date</th>
@@ -1,5 +1,5 @@
<legend>Products <a href="/Product" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend> <legend>Products <a href="/Product" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend>
<table class="table table-bordered clean-table"> <table class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Code</th> <th>Code</th>
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button> <button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div> </div>
</div> </div>
@@ -13,7 +13,7 @@
<label for="gvGridProfitLoss" class="control-label"></label> <label for="gvGridProfitLoss" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGridProfitLoss" class="table table-bordered clean-table"> <table id="gvGridProfitLoss" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Group</th> <th>Group</th>
@@ -45,7 +45,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Group</th> <th>Group</th>
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button> <button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div> </div>
</div> </div>
@@ -13,7 +13,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Date</th> <th>Date</th>
@@ -4,7 +4,7 @@
<label for="txtDate" class="control-label">Date</label> <label for="txtDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker> <datepicker id="txtDate" model="voucher.Date" ng-model="voucher.Date"></datepicker>
</div> </div>
</div> </div>
<div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:1"> <div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:1">
@@ -37,7 +37,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Product</th> <th>Product</th>
+2 -2
View File
@@ -4,7 +4,7 @@
<label for="txtDate" class="control-label">Date</label> <label for="txtDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker> <datepicker id="txtDate" model="voucher.Date" ng-model="voucher.Date"></datepicker>
</div> </div>
</div> </div>
<div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:-1"> <div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:-1">
@@ -44,7 +44,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Product</th> <th>Product</th>
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button> <button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div> </div>
</div> </div>
@@ -13,7 +13,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Product</th> <th>Product</th>
@@ -24,7 +24,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="item in info.Body" ng-class="{true:'warning', false:''}[item.Heading]"> <tr ng-repeat="item in info.Body" ng-class="{true:'error', false:''}[item.Heading]">
<td><a href="{{item.Url}}">{{item.Name}}</a></td> <td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td>{{item.Group}}</td> <td>{{item.Group}}</td>
<td class="right">{{item.Quantity}}</td> <td class="right">{{item.Quantity}}</td>
@@ -4,8 +4,8 @@
<label for="txtStartDate" class="control-label">Date</label> <label for="txtStartDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtStartDate" model="info" prop="StartDate" ng-model="info.StartDate"></datepicker> <datepicker id="txtStartDate" model="info.StartDate" ng-model="info.StartDate"></datepicker>
<datepicker id="txtFinishDate" model="info" prop="FinishDate" ng-model="info.FinishDate"></datepicker> <datepicker id="txtFinishDate" model="info.FinishDate" ng-model="info.FinishDate"></datepicker>
<button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button> <button class="btn btn-info" ng-click="show()">Show <i class="icon-eye-open icon-white"></i></button>
</div> </div>
</div> </div>
@@ -13,7 +13,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Cost Center</th> <th>Cost Center</th>
+3 -3
View File
@@ -4,7 +4,7 @@
<label for="txtDate" class="control-label">Date</label> <label for="txtDate" class="control-label">Date</label>
<div class="controls"> <div class="controls">
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker> <datepicker id="txtDate" model="voucher.Date" ng-model="voucher.Date"></datepicker>
</div> </div>
</div> </div>
<div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:1"> <div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:1">
@@ -12,7 +12,7 @@
<div class="controls"> <div class="controls">
<select id="ddlLedger" class="select-box" ng-model="journal.Ledger.LedgerID" <select id="ddlLedger" class="select-box" ng-model="journal.Ledger.LedgerID"
ng-options="l.id as l.label for l in ledgers"> </select> ng-options="l.model.LedgerID as l.label for l in ledgers"> </select>
<div class=" input-prepend"> <div class=" input-prepend">
<span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2" autocomplete="off" <span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2" autocomplete="off"
@@ -39,7 +39,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
@@ -12,7 +12,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Type</th> <th>Type</th>
+1 -1
View File
@@ -4,7 +4,7 @@
<label for="gvGrid" class="control-label"></label> <label for="gvGrid" class="control-label"></label>
<div class="controls"> <div class="controls">
<table id="gvGrid" class="table table-bordered clean-table"> <table id="gvGrid" class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Select</th> <th>Select</th>
@@ -1,5 +1,5 @@
<legend>Users <a href="/User" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend> <legend>Users <a href="/User" class="btn btn-success pull-right">Add <i class="icon-plus icon-white"></i></a></legend>
<table class="table table-bordered clean-table"> <table class="table table-condensed table-bordered table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
+6 -4
View File
@@ -33,7 +33,7 @@ overlord_directive.directive('ngAutocomplete', function ($q, $parse) {
}; };
}); });
overlord_directive.directive('datepicker', function () { overlord_directive.directive('datepicker', function ($parse) {
return { return {
restrict:'E', restrict:'E',
replace:true, replace:true,
@@ -42,12 +42,14 @@ overlord_directive.directive('datepicker', function () {
link:function (scope, element, attrs) { link:function (scope, element, attrs) {
element.datepicker({ element.datepicker({
dateFormat:'dd-M-yy', dateFormat:'dd-M-yy',
showOtherMonths:true,
selectOtherMonths:true,
onSelect:function (dateText, inst) { onSelect:function (dateText, inst) {
if (typeof attrs.model !== 'undefined') { var model = $parse(attrs.model);
scope[attrs.model][attrs.prop] = dateText; var modelSetter = model.assign;
modelSetter(scope, dateText);
scope.$apply(); scope.$apply();
} }
}
}); });
} }
}; };
+7 -27
View File
@@ -2,12 +2,10 @@
var overlord_service = angular.module('overlord.service', ['ngResource']); var overlord_service = angular.module('overlord.service', ['ngResource']);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('IssueGrid', ['$resource', function ($resource) { overlord_service.factory('IssueGrid', ['$resource', function ($resource) {
return $resource('/Issues/Services/:date'); return $resource('/Issues/Services/:date');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Voucher', ['$resource', function ($resource) { overlord_service.factory('Voucher', ['$resource', function ($resource) {
return $resource('/Voucher/:id', return $resource('/Voucher/:id',
{id:'@VoucherID'}, { {id:'@VoucherID'}, {
@@ -15,7 +13,6 @@ overlord_service.factory('Voucher', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Account', ['$resource', function ($resource) { overlord_service.factory('Account', ['$resource', function ($resource) {
return $resource('/Account/:id', return $resource('/Account/:id',
{id:'@LedgerID'}, { {id:'@LedgerID'}, {
@@ -24,7 +21,6 @@ overlord_service.factory('Account', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Employee', ['$resource', function ($resource) { overlord_service.factory('Employee', ['$resource', function ($resource) {
return $resource('/Employee/:id', return $resource('/Employee/:id',
{id:'@LedgerID'}, { {id:'@LedgerID'}, {
@@ -33,17 +29,14 @@ overlord_service.factory('Employee', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Ledger', ['$resource', function ($resource) { overlord_service.factory('Ledger', ['$resource', function ($resource) {
return $resource('/Ledger/:id'); return $resource('/Ledger/:id');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('ProductLedger', ['$resource', function ($resource) { overlord_service.factory('ProductLedger', ['$resource', function ($resource) {
return $resource('/ProductLedger/:id'); return $resource('/ProductLedger/:id');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('CostCenter', ['$resource', function ($resource) { overlord_service.factory('CostCenter', ['$resource', function ($resource) {
return $resource('/CostCenter/:id', return $resource('/CostCenter/:id',
{id:'@CostCenterID'}, { {id:'@CostCenterID'}, {
@@ -51,12 +44,10 @@ overlord_service.factory('CostCenter', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('AccountType', ['$resource', function ($resource) { overlord_service.factory('AccountType', ['$resource', function ($resource) {
return $resource('/AccountTypes'); return $resource('/AccountTypes');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('User', ['$resource', function ($resource) { overlord_service.factory('User', ['$resource', function ($resource) {
return $resource('/User/:id', return $resource('/User/:id',
{id:'@UserID'}, { {id:'@UserID'}, {
@@ -64,7 +55,6 @@ overlord_service.factory('User', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Group', ['$resource', function ($resource) { overlord_service.factory('Group', ['$resource', function ($resource) {
return $resource('/Group/:id', return $resource('/Group/:id',
{id:'@GroupID'}, { {id:'@GroupID'}, {
@@ -72,7 +62,13 @@ overlord_service.factory('Group', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url overlord_service.factory('Client', ['$resource', function ($resource) {
return $resource('/Client/:id',
{id:'@ClientID'}, {
query:{method:'GET', params:{list:true}, isArray:true}
});
}]);
overlord_service.factory('Product', ['$resource', function ($resource) { overlord_service.factory('Product', ['$resource', function ($resource) {
return $resource('/Product/:id', return $resource('/Product/:id',
{id:'@ProductID'}, { {id:'@ProductID'}, {
@@ -81,14 +77,12 @@ overlord_service.factory('Product', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Batch', ['$resource', function ($resource) { overlord_service.factory('Batch', ['$resource', function ($resource) {
return $resource('/Batch', {}, { return $resource('/Batch', {}, {
autocomplete:{method:'GET', params:{term:''}, isArray:true} autocomplete:{method:'GET', params:{term:''}, isArray:true}
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('ProductGroup', ['$resource', function ($resource) { overlord_service.factory('ProductGroup', ['$resource', function ($resource) {
return $resource('/ProductGroup/:id', return $resource('/ProductGroup/:id',
{id:'@ProductGroupID'}, { {id:'@ProductGroupID'}, {
@@ -96,7 +90,6 @@ overlord_service.factory('ProductGroup', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('CostCenter', ['$resource', function ($resource) { overlord_service.factory('CostCenter', ['$resource', function ($resource) {
return $resource('/CostCenter/:id', return $resource('/CostCenter/:id',
{id:'@CostCenterID'}, { {id:'@CostCenterID'}, {
@@ -104,65 +97,52 @@ overlord_service.factory('CostCenter', ['$resource', function ($resource) {
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('TrialBalance', ['$resource', function ($resource) { overlord_service.factory('TrialBalance', ['$resource', function ($resource) {
return $resource('/TrialBalance/:date'); return $resource('/TrialBalance/:date');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('ClosingStock', ['$resource', function ($resource) { overlord_service.factory('ClosingStock', ['$resource', function ($resource) {
return $resource('/ClosingStock/:date'); return $resource('/ClosingStock/:date');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('CashFlow', ['$resource', function ($resource) { overlord_service.factory('CashFlow', ['$resource', function ($resource) {
return $resource('/CashFlow/:id'); return $resource('/CashFlow/:id');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Daybook', ['$resource', function ($resource) { overlord_service.factory('Daybook', ['$resource', function ($resource) {
return $resource('/Daybook'); return $resource('/Daybook');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Unposted', ['$resource', function ($resource) { overlord_service.factory('Unposted', ['$resource', function ($resource) {
return $resource('/Unposted'); return $resource('/Unposted');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('ProfitLoss', ['$resource', function ($resource) { overlord_service.factory('ProfitLoss', ['$resource', function ($resource) {
return $resource('/ProfitLoss'); return $resource('/ProfitLoss');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('PurchaseEntries', ['$resource', function ($resource) { overlord_service.factory('PurchaseEntries', ['$resource', function ($resource) {
return $resource('/PurchaseEntries'); return $resource('/PurchaseEntries');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('RawMaterialCost', ['$resource', function ($resource) { overlord_service.factory('RawMaterialCost', ['$resource', function ($resource) {
return $resource('/RawMaterialCost/:id'); return $resource('/RawMaterialCost/:id');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Auth', ['$resource', function ($resource) { overlord_service.factory('Auth', ['$resource', function ($resource) {
return $resource('/Auth', {}, { return $resource('/Auth', {}, {
login:{method:'GET', params:{list:true}, isArray:true} login:{method:'GET', params:{list:true}, isArray:true}
}); });
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('Attendance', ['$resource', function ($resource) { overlord_service.factory('Attendance', ['$resource', function ($resource) {
return $resource('/Attendance/:date', {date:'@Date'}); return $resource('/Attendance/:date', {date:'@Date'});
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('AttendanceTypes', ['$resource', function ($resource) { overlord_service.factory('AttendanceTypes', ['$resource', function ($resource) {
return $resource('/AttendanceTypes'); return $resource('/AttendanceTypes');
}]); }]);
// TODO: Replace hardcoded url with route_url
overlord_service.factory('EmployeeAttendance', ['$resource', function ($resource) { overlord_service.factory('EmployeeAttendance', ['$resource', function ($resource) {
return $resource('/EmployeeAttendance/:id', {id:'@Employee.LedgerID'}); return $resource('/EmployeeAttendance/:id', {id:'@Employee.LedgerID'});
}]); }]);
+18
View File
@@ -0,0 +1,18 @@
'use strict';
function ClientCtrl($scope, clients) {
$scope.info = clients;
}
ClientCtrl.resolve = {
clients:function ($q, Client) {
var deferred = $q.defer();
var successCb = function (result) {
deferred.resolve(result);
};
Client.query({}, successCb);
return deferred.promise;
}
};
@@ -4,17 +4,36 @@ function EmployeeAttendanceCtrl($scope, $location, EmployeeAttendance, attendanc
$scope.attendance_types = attendance_types; $scope.attendance_types = attendance_types;
$scope.info = info; $scope.info = info;
$scope.show = function () { $scope.show = function () {
var id = $scope.info.Ledger.LedgerID;
var start_date = $scope.info.StartDate;
var finish_date = $scope.info.FinishDate;
if (id == $routeParams.id && start_date == $routeParams.StartDate && finish_date == $routeParams.FinishDate) {
EmployeeAttendance.get({id:id, StartDate:start_date, FinishDate:finish_date}, function (data) {
$scope.info = data;
});
}
else {
$location.path('/EmployeeAttendance/' + $scope.info.Employee.LedgerID).search({StartDate:$scope.info.StartDate, FinishDate:$scope.info.FinishDate}); $location.path('/EmployeeAttendance/' + $scope.info.Employee.LedgerID).search({StartDate:$scope.info.StartDate, FinishDate:$scope.info.FinishDate});
}
}; };
$scope.save = function () { $scope.save = function () {
$scope.info.$save(function (u, putResponseHeaders) { $scope.info.$save(function (u, putResponseHeaders) {
$scope.toasts.push({Type:'Success', Message:u.Code}); $scope.toasts.push({Type:'Success', Message:'Saved!'});
}, function (data, status) { }, function (data, status) {
$scope.toasts.push({Type:'Error', Message:data.data}); $scope.toasts.push({Type:'Error', Message:data.data});
}); });
}; };
$('#txtEmployee').focus(); $('#txtEmployee').focus();
} }
function EmployeeAttendanceSubCtrl($scope) {
$scope.original = {};
angular.copy($scope.item, $scope.original);
$scope.isDirty = function(){
return !angular.equals($scope.original, $scope.item)
}
}
EmployeeAttendanceCtrl.resolve = { EmployeeAttendanceCtrl.resolve = {
info:function ($q, $route, EmployeeAttendance) { info:function ($q, $route, EmployeeAttendance) {
var deferred = $q.defer(); var deferred = $q.defer();
@@ -1,12 +1,24 @@
'use strict'; 'use strict';
function EmployeeFunctionsCtrl($scope) { function EmployeeFunctionsCtrl($scope, $http) {
$scope.record = {};
$scope.creditSalary = function () { $scope.creditSalary = function () {
$scope.toasts.push({Type:'Error', Message:'Not Implemented Yet'}); $http.
post('/CreditSalary', {Month:$scope.salaryMonth}).
success(function (data) {
$scope.toasts.push({Type:'Success', Message:data.message});
}).
error(function (errorMessage) {
$scope.toasts.push({Type:'Error', Message:errorMessage});
});
}; };
$scope.creditEsiPf = function () { $scope.creditEsiPf = function () {
$scope.toasts.push({Type:'Error', Message:'Not Implemented Yet'}); $scope.toasts.push({Type:'Error', Message:'Not Implemented Yet'});
}; };
$scope.attendanceRecordUrl = function () {
var url = '/AttendanceReport?StartDate=' + $scope.record.Start + "&FinishDate=" + $scope.record.Finish;
return url;
};
$scope.uploadFingerprints = function () { $scope.uploadFingerprints = function () {
$scope.toasts.push({Type:'Error', Message:'Not Implemented Yet'}); $scope.toasts.push({Type:'Error', Message:'Not Implemented Yet'});
}; };
+10
View File
@@ -25,6 +25,16 @@ function IssueCtrl($scope, $routeParams, $location, voucher, cost_centers, issue
quantity = Number($scope.quantity), quantity = Number($scope.quantity),
consumption = (getDebitCredit($scope.voucher.Journals, -1) == '7b845f95-dfef-fa4a-897c-f0baf15284a3'); consumption = (getDebitCredit($scope.voucher.Journals, -1) == '7b845f95-dfef-fa4a-897c-f0baf15284a3');
if (typeof oldInventory !== 'undefined' &&
oldInventory.Batch.BatchID === $scope.batch.BatchID &&
(!consumption || oldInventory.Quantity + quantity <= $scope.batch.QuantityRemaining)) {
oldInventory.Quantity += quantity;
delete $scope.batch;
delete $scope.quantity;
$('#txtBatch').val('');
$('#txtBatch').focus();
}
if (typeof oldInventory === 'undefined' && (!consumption || quantity <= $scope.batch.QuantityRemaining)) { if (typeof oldInventory === 'undefined' && (!consumption || quantity <= $scope.batch.QuantityRemaining)) {
this.voucher.Inventories.push( this.voucher.Inventories.push(
{ {
+11 -1
View File
@@ -1,9 +1,19 @@
'use strict'; 'use strict';
function LedgerCtrl($scope, $location, ledger) { function LedgerCtrl($scope, $routeParams, $location, ledger, Ledger) {
$scope.info = ledger; $scope.info = ledger;
$scope.show = function () { $scope.show = function () {
var id = $scope.info.Ledger.LedgerID;
var start_date = $scope.info.StartDate;
var finish_date = $scope.info.FinishDate;
if (id == $routeParams.id && start_date == $routeParams.StartDate && finish_date == $routeParams.FinishDate) {
Ledger.get({id:id, StartDate:start_date, FinishDate:finish_date}, function (data) {
$scope.info = data;
});
}
else {
$location.path('/Ledger/' + $scope.info.Ledger.LedgerID).search('StartDate', $scope.info.StartDate).search('FinishDate', $scope.info.FinishDate); $location.path('/Ledger/' + $scope.info.Ledger.LedgerID).search('StartDate', $scope.info.StartDate).search('FinishDate', $scope.info.FinishDate);
}
}; };
$scope.downloadTable = function () { $scope.downloadTable = function () {
var table = $('#gvGrid'), var table = $('#gvGrid'),
+16 -4
View File
@@ -1,9 +1,17 @@
'use strict'; 'use strict';
function LoginCtrl($scope, $http, $location, $routeParams) { function LoginCtrl($scope, $http, $location, $routeParams, $cookieStore) {
$scope.showOTP = false;
$scope.submit = function () { $scope.submit = function () {
if ($scope.showOTP) {
var data = {username:$scope.username, password:$scope.password, otp:$scope.otp, ClientName:$scope.name};
} else {
var data = {username:$scope.username, password:$scope.password};
}
$http. $http.
post('/login', {username:$scope.username, password:$scope.password}). post('/login', data).
success(function () { success(function () {
var came_from = $routeParams.came_from; var came_from = $routeParams.came_from;
if (typeof came_from === 'undefined' || came_from === "" || came_from === "/login" || came_from === "/logout") { if (typeof came_from === 'undefined' || came_from === "" || came_from === "/login" || came_from === "/logout") {
@@ -11,8 +19,12 @@ function LoginCtrl($scope, $http, $location, $routeParams) {
} }
$location.path(came_from).search({}); $location.path(came_from).search({});
}). }).
error(function (errorMessage) { error(function (data, status, headers, config) {
$scope.toasts.push({Type:'Error', Message:errorMessage}); if (status === 403 && ['Unknown Client', 'OTP not supplied', 'OTP is wrong'].indexOf(data) !== -1) {
$scope.showOTP = true;
$scope.clientID = $cookieStore.get('ClientID');
}
$scope.toasts.push({Type:'Error', Message:data});
}); });
}; };
$('#username').focus(); $('#username').focus();
+3 -1
View File
@@ -1,6 +1,6 @@
'use strict'; 'use strict';
var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filter', 'overlord.service']) var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filter', 'overlord.service', 'ngCookies'])
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) { .config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider. $routeProvider.
when('/', {templateUrl:'/partial/home.html'}). when('/', {templateUrl:'/partial/home.html'}).
@@ -83,6 +83,8 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
when('/Group', {templateUrl:'/partial/group-detail.html', controller:GroupCtrl, resolve:GroupCtrl.resolve}). when('/Group', {templateUrl:'/partial/group-detail.html', controller:GroupCtrl, resolve:GroupCtrl.resolve}).
when('/Group/:id', {templateUrl:'/partial/group-detail.html', controller:GroupCtrl, resolve:GroupCtrl.resolve}). when('/Group/:id', {templateUrl:'/partial/group-detail.html', controller:GroupCtrl, resolve:GroupCtrl.resolve}).
when('/Clients', {templateUrl:'/partial/client-list.html', controller:ClientCtrl, resolve:ClientCtrl.resolve}).
otherwise({templateUrl:'/partial/404.html'}); otherwise({templateUrl:'/partial/404.html'});
$locationProvider.html5Mode(true).hashPrefix('!'); $locationProvider.html5Mode(true).hashPrefix('!');
}]) }])
+4 -4
View File
@@ -25,6 +25,7 @@
<script src="/js/angular-1.0.2.js"> </script> <script src="/js/angular-1.0.2.js"> </script>
<script src="/js/angular-resource-1.0.2.js"> </script> <script src="/js/angular-resource-1.0.2.js"> </script>
<script src="/js/angular-cookies-1.0.2.js"> </script>
<script src="/script/overlord.js"> </script> <script src="/script/overlord.js"> </script>
<script src="/script/angular_directive.js"> </script> <script src="/script/angular_directive.js"> </script>
@@ -58,6 +59,7 @@
<script src="/script/employee.js"> </script> <script src="/script/employee.js"> </script>
<script src="/script/user.js"> </script> <script src="/script/user.js"> </script>
<script src="/script/group.js"> </script> <script src="/script/group.js"> </script>
<script src="/script/client.js"> </script>
<script src="/script/cost-center.js"> </script> <script src="/script/cost-center.js"> </script>
<script src="/script/product.js"> </script> <script src="/script/product.js"> </script>
<script src="/script/product-group.js"> </script> <script src="/script/product-group.js"> </script>
@@ -135,11 +137,8 @@
<li><a href="/Employees">Employees</a></li> <li><a href="/Employees">Employees</a></li>
<li><a href="/Attendance">Attendance</a></li> <li><a href="/Attendance">Attendance</a></li>
<li><a href="/EmployeeAttendance">Employee Attendance</a></li> <li><a href="/EmployeeAttendance">Employee Attendance</a></li>
<li><a href="/AccountsTesting/Employees/AttendanceRecord.aspx">Attendance Record</a></li> <li><a href="/EmployeeFunctions">Employee Functions</a></li>
<li><a href="/AccountsTesting/Employees/SalarySheet.aspx">Salary Sheet</a></li> <li><a href="/AccountsTesting/Employees/SalarySheet.aspx">Salary Sheet</a></li>
<li><a href="/AccountsTesting/Employees/CreditSalary.aspx">Credit Salary</a></li>
<li><a href="/AccountsTesting/Employees/CreditEsiPf.aspx">Credit Esi Pf</a></li>
<li><a href="/AccountsTesting/Employees/ImportFingerprint.aspx">Finger Print</a></li>
<li><a href="/AccountsTesting/Employees/PaymentSheet.aspx">Employee Payment Sheet</a></li> <li><a href="/AccountsTesting/Employees/PaymentSheet.aspx">Employee Payment Sheet</a></li>
<li><a href="/features/elements.html">Display Salary Sheet</a></li> <li><a href="/features/elements.html">Display Salary Sheet</a></li>
</ul> </ul>
@@ -162,6 +161,7 @@
<li><a href="/AccountsTesting/Security/ChangePassword.aspx">Change Password</a></li> <li><a href="/AccountsTesting/Security/ChangePassword.aspx">Change Password</a></li>
<li><a href="/Users">Users</a></li> <li><a href="/Users">Users</a></li>
<li><a href="/Groups">Groups</a></li> <li><a href="/Groups">Groups</a></li>
<li><a href="/Clients">Clients</a></li>
<li><a href="/AccountsTesting/Maintenance/Split.aspx">Split Data</a></li> <li><a href="/AccountsTesting/Maintenance/Split.aspx">Split Data</a></li>
</ul> </ul>
</li> </li>
+1 -26
View File
@@ -2,7 +2,7 @@ from decimal import Decimal
import json import json
import os import os
import uuid import uuid
from pyramid.httpexceptions import HTTPForbidden, HTTPFound, exception_response from pyramid.httpexceptions import HTTPForbidden, HTTPFound
from pyramid.response import FileResponse, Response from pyramid.response import FileResponse, Response
from pyramid.security import forget from pyramid.security import forget
from pyramid.view import view_config from pyramid.view import view_config
@@ -22,13 +22,6 @@ def forbidden(request):
else: else:
return HTTPFound(location=request.route_url('login')) return HTTPFound(location=request.route_url('login'))
@view_config(route_name='logout')
def logout(request):
request.session.invalidate()
headers = forget(request)
return HTTPFound(location=request.route_url('home'), headers=headers)
@view_config(route_name='favicon') @view_config(route_name='favicon')
def favicon(request): def favicon(request):
here = os.path.dirname(__file__) here = os.path.dirname(__file__)
@@ -50,21 +43,3 @@ class DecimalEncoder(json.JSONEncoder):
return str(obj) return str(obj)
return json.JSONEncoder.default(self, obj) return json.JSONEncoder.default(self, obj)
class my_json_renderer_factory:
def __init__(self, info):
""" Constructor: info will be an object having the
following attributes: name (the renderer name), package
(the package that was 'current' at the time the
renderer was registered), type (the renderer type
name), registry (the current application registry) and
settings (the deployment settings dictionary). """
# print(info)
def __call__(self, value, system):
request = system.get('request')
if request is not None:
response = request.response
ct = response.content_type
if ct == response.default_content_type:
response.content_type = 'application/json'
return json.dumps(value, cls=DecimalEncoder)
+14 -6
View File
@@ -16,18 +16,26 @@ def html(request):
return {} return {}
@view_config(request_method='POST', route_name='account_id', renderer='json', xhr=True, permission='Accounts')
@view_config(request_method='POST', route_name='account', renderer='json', xhr=True, permission='Accounts') @view_config(request_method='POST', route_name='account', renderer='json', xhr=True, permission='Accounts')
def save_update(request): def save(request):
try: try:
id = request.matchdict.get('id', None)
if id is None:
item = Ledger(code=0, name=request.json_body['Name'], type=int(request.json_body['Type']), item = Ledger(code=0, name=request.json_body['Name'], type=int(request.json_body['Type']),
is_active=request.json_body['IsActive'], is_reconcilble=request.json_body['IsReconcilable'], is_active=request.json_body['IsActive'], is_reconcilble=request.json_body['IsReconcilable'],
costcenter_id=uuid.UUID(request.json_body['CostCenter']['CostCenterID'])).create() costcenter_id=uuid.UUID(request.json_body['CostCenter']['CostCenterID'])).create()
else: transaction.commit()
return account_info(item.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='POST', route_name='account_id', renderer='json', xhr=True, permission='Accounts')
def update(request):
try:
item = Ledger.by_id(uuid.UUID(request.matchdict['id']))
new_type = int(request.json_body['Type']) new_type = int(request.json_body['Type'])
item = Ledger.by_id(uuid.UUID(id))
if not item.type == new_type: if not item.type == new_type:
item.code = Ledger.get_code(new_type) item.code = Ledger.get_code(new_type)
item.type = new_type item.type = new_type
+10 -2
View File
@@ -102,7 +102,7 @@ def employee_attendance_report(request):
start_date = request.GET.get('StartDate', session_period_start(request)) start_date = request.GET.get('StartDate', session_period_start(request))
finish_date = request.GET.get('FinishDate', session_period_finish(request)) finish_date = request.GET.get('FinishDate', session_period_finish(request))
info = {'StartDate': start_date, 'FinishDate': finish_date, info = {'StartDate': start_date, 'FinishDate': finish_date,
'Employee': {'LedgerID': employee.id, 'Name': employee.name}, 'Body': [], 'Employee': {'LedgerID': employee.id, 'Name': employee.name},
'Body': employee_attendance(employee, start_date, finish_date)} 'Body': employee_attendance(employee, start_date, finish_date)}
return info return info
@@ -129,9 +129,15 @@ def employee_attendance(employee, start_date, finish_date):
permission='Attendance') permission='Attendance')
def save_employee_attendance(request): def save_employee_attendance(request):
try: try:
start_date = None
finish_date = None
user_id = uuid.UUID(authenticated_userid(request)) user_id = uuid.UUID(authenticated_userid(request))
employee = Employee.by_id(uuid.UUID(request.matchdict['id'])) employee = Employee.by_id(uuid.UUID(request.matchdict['id']))
for item in request.json_body['Body']: for item in request.json_body['Body']:
if start_date is None:
start_date = item['Date']
finish_date = item['Date']
attendance_type = item['AttendanceTypeID'] attendance_type = item['AttendanceTypeID']
if attendance_type != 0: if attendance_type != 0:
date = datetime.datetime.strptime(item['Date'], '%d-%b-%Y') date = datetime.datetime.strptime(item['Date'], '%d-%b-%Y')
@@ -139,7 +145,9 @@ def save_employee_attendance(request):
user_id=user_id) user_id=user_id)
attendance.create() attendance.create()
transaction.commit() transaction.commit()
return employee_attendance(employee, request.json_body['StartDate'], request.json_body['FinishDate']) return {'StartDate': start_date, 'FinishDate': finish_date,
'Employee': {'LedgerID': employee.id, 'Name': employee.name},
'Body': employee_attendance(employee, start_date, finish_date)}
except ValidationError as ex: except ValidationError as ex:
transaction.abort() transaction.abort()
response = Response("Failed validation: {0}".format(ex.message)) response = Response("Failed validation: {0}".format(ex.message))
+104
View File
@@ -0,0 +1,104 @@
import calendar
import datetime
import uuid
from pyramid.response import Response
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from sqlalchemy import or_
import transaction
from brewman.models import DBSession
from brewman.models.auth import User
from brewman.models.master import AttendanceType, Employee, Ledger
from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Attendance, Voucher, VoucherType, Journal
from brewman.views.attendance import daterange
from brewman.views.services.session import session_period_start, session_period_finish, get_last_day, get_first_day
__author__ = 'tanshu'
@view_config(route_name='attendance_report', renderer='csv', permission='Attendance')
def get_report(request):
start_date = request.GET.get('StartDate', session_period_start(request))
finish_date = request.GET.get('FinishDate', session_period_finish(request))
start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y')
finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y')
header, report = attendance_record(start_date, finish_date)
return {'header': header, 'rows': report, 'filename': 'Attendance Record.csv'}
def attendance_record(start_date, finish_date):
report = []
header = ["Code", "Name", "Designation", "Department", "Salary", "SC Points"]
for date in daterange(start_date, finish_date, inclusive=True):
header.append(date.strftime('%d-%b'))
not_set = AttendanceType.by_id(0)
employees = DBSession().query(Employee)\
.filter(Employee.joining_date <= finish_date)\
.filter(or_(Employee.is_active, Employee.leaving_date >= start_date))\
.order_by(Employee.costcenter_id).order_by(Employee.designation).order_by(Employee.name).all()
for employee in employees:
row_display = [employee.code, employee.name, employee.designation, employee.costcenter.name, employee.salary,
employee.service_points]
row_value = ['', '', '', '', employee.salary, employee.service_points]
for date in daterange(start_date, finish_date, inclusive=True):
att = DBSession.query(Attendance)\
.filter(Attendance.employee_id == employee.id)\
.filter(Attendance.date == date)\
.filter(Attendance.is_valid == True)\
.first()
att = not_set if att is None else AttendanceType.by_id(att.attendance_type)
row_display.append(att.name)
row_value.append(att.value)
report.extend([tuple(row_display), tuple(row_value)])
return header, report
@view_config(request_method='POST', route_name='credit_salary', renderer='json', xhr=True, permission='Attendance')
def credit_salary(request):
try:
user = User.by_id(uuid.UUID(authenticated_userid(request)))
month = datetime.datetime.strptime(request.json_body['Month'], '%d-%b-%Y')
start_date = get_first_day(month)
finish_date = get_last_day(month)
voucher = Voucher(date=finish_date, narration='Auto Generated Salary Entry', user_id=user.id,
type=VoucherType.by_name('Journal'), posted=True, poster_id=user.id)
DBSession.add(voucher)
for item in salary_journals(start_date, finish_date):
voucher.journals.append(item)
DBSession.add(item)
transaction.commit()
return {'message': 'Salary Entry created'}
except ValidationError as ex:
transaction.abort()
response = Response("Failed validation: {0}".format(ex.message))
response.status_int = 500
return response
def salary_journals(start_date, finish_date):
days = calendar.monthrange(start_date.year, start_date.month)[1]
finish_date = finish_date + datetime.timedelta(1)
amount = 0
journals = []
employees = DBSession().query(Employee)\
.filter(Employee.joining_date <= finish_date)\
.filter(or_(Employee.is_active, Employee.leaving_date >= start_date))\
.order_by(Employee.costcenter_id).order_by(Employee.designation).order_by(Employee.name).all()
for employee in employees:
att = DBSession.query(Attendance)\
.filter(Attendance.employee_id == employee.id)\
.filter(Attendance.date >= start_date)\
.filter(Attendance.date < finish_date)\
.filter(Attendance.is_valid == True)\
.all()
att = sum(map(lambda x: AttendanceType.by_id(x.attendance_type).value, att))
att = round(att * employee.salary / days)
amount += att
journals.append(Journal(amount=att, debit=-1, ledger_id=employee.id, cost_center_id=employee.costcenter_id))
salary = Ledger.salary()
salary = Ledger.by_id(uuid.UUID(salary['LedgerID']))
journals.append(Journal(amount=amount, debit=1, ledger_id=salary.id, cost_center_id=salary.costcenter_id))
return journals
+39
View File
@@ -0,0 +1,39 @@
import uuid
from pyramid.response import Response
from pyramid.view import view_config
import transaction
from brewman.models.auth import Client
from brewman.models.validation_exception import ValidationError
@view_config(request_method='GET', route_name='client_list', renderer='brewman:templates/angular_base.mako',
xhr=False, permission='Clients')
def html(request):
return {}
@view_config(request_method='POST', route_name='client_id', renderer='json', xhr=True, permission='Clients')
def update(request):
try:
item = Client.by_id(uuid.UUID(request.matchdict.get['id']))
item.enabled = request.json_body['Enabled']
transaction.commit()
return {}
except ValidationError as ex:
transaction.abort()
response = Response("Failed validation: {0}".format(ex.message))
response.status_int = 500
return response
@view_config(request_method='GET', route_name='client', request_param='list', renderer='json', xhr=True,
permission='Clients')
def show_list(request):
list = Client.list()
clients = []
for item in list:
clients.append(
{'ClientID': item.id, 'Code': item.code, 'Name': item.name, 'Enabled': item.enabled, 'OTP': item.otp})
return clients
+3 -3
View File
@@ -34,7 +34,7 @@ def save(request):
def update(request): def update(request):
try: try:
id = request.matchdict.get('id', None) id = request.matchdict.get('id', None)
group = Group.get_by_id(uuid.UUID(id)) group = Group.by_id(uuid.UUID(id))
group.name = request.json_body['Name'] group.name = request.json_body['Name']
add_permissions(group, request.json_body['Permissions']) add_permissions(group, request.json_body['Permissions'])
transaction.commit() transaction.commit()
@@ -52,7 +52,7 @@ def add_permissions(group, permissions):
gp = [p for p in group.roles if p.id == id] gp = [p for p in group.roles if p.id == id]
gp = None if len(gp) == 0 else gp[0] gp = None if len(gp) == 0 else gp[0]
if permission['Enabled'] and gp is None: if permission['Enabled'] and gp is None:
group.roles.append(Role.get_by_id(id)) group.roles.append(Role.by_id(id))
elif not permission['Enabled'] and gp: elif not permission['Enabled'] and gp:
group.roles.remove(gp) group.roles.remove(gp)
@@ -98,7 +98,7 @@ def group_info(id):
for item in Role.list(): for item in Role.list():
group['Permissions'].append({'PermissionID': item.id, 'Name': item.name, 'Enabled': False}) group['Permissions'].append({'PermissionID': item.id, 'Name': item.name, 'Enabled': False})
else: else:
group_object = Group.get_by_id(id) group_object = Group.by_id(id)
group = {'GroupID': group_object.id, 'Name': group_object.name, 'Permissions': []} group = {'GroupID': group_object.id, 'Name': group_object.name, 'Permissions': []}
for item in Role.list(): for item in Role.list():
group['Permissions'].append( group['Permissions'].append(
+3 -3
View File
@@ -36,7 +36,7 @@ def save(request):
def update(request): def update(request):
try: try:
id = request.matchdict.get('id', None) id = request.matchdict.get('id', None)
user = User.get_by_id(uuid.UUID(id)) user = User.by_id(uuid.UUID(id))
user.name = request.json_body['Name'] user.name = request.json_body['Name']
user.locked_out = request.json_body['LockedOut'] user.locked_out = request.json_body['LockedOut']
if request.json_body['Password'] != '' and request.json_body['Password'] != user.password: if request.json_body['Password'] != '' and request.json_body['Password'] != user.password:
@@ -57,7 +57,7 @@ def add_groups(user, groups):
ug = [g for g in user.groups if g.id == id] ug = [g for g in user.groups if g.id == id]
ug = None if len(ug) == 0 else ug[0] ug = None if len(ug) == 0 else ug[0]
if group['Enabled'] and ug is None: if group['Enabled'] and ug is None:
user.groups.append(Group.get_by_id(id)) user.groups.append(Group.by_id(id))
elif not group['Enabled'] and ug: elif not group['Enabled'] and ug:
user.groups.remove(ug) user.groups.remove(ug)
@@ -104,7 +104,7 @@ def user_info(id):
for item in Group.list(): for item in Group.list():
account['Groups'].append({'GroupID': item.id, 'Name': item.name, 'Enabled': False}) account['Groups'].append({'GroupID': item.id, 'Name': item.name, 'Enabled': False})
else: else:
user = User.get_by_id(id) user = User.by_id(id)
account = {'UserID': user.id, 'Name': user.name, 'Password': '', 'LockedOut': user.locked_out, 'Groups': []} account = {'UserID': user.id, 'Name': user.name, 'Password': '', 'LockedOut': user.locked_out, 'Groups': []}
for item in Group.list(): for item in Group.list():
account['Groups'].append( account['Groups'].append(
+14 -6
View File
@@ -18,16 +18,24 @@ def html(request):
return {} return {}
@view_config(request_method='POST', route_name='cost_center_id', renderer='json', xhr=True, permission='Cost Centers')
@view_config(request_method='POST', route_name='cost_center', renderer='json', xhr=True, permission='Cost Centers') @view_config(request_method='POST', route_name='cost_center', renderer='json', xhr=True, permission='Cost Centers')
def save_update(request): def save(request):
try: try:
id = request.matchdict.get('id', None)
if id is None:
item = CostCenter(request.json_body['Name']) item = CostCenter(request.json_body['Name'])
DBSession.add(item) DBSession.add(item)
else: transaction.commit()
item = CostCenter.by_id(uuid.UUID(id)) return cost_center_info(item.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='POST', route_name='cost_center_id', renderer='json', xhr=True, permission='Cost Centers')
def update(request):
try:
item = CostCenter.by_id(uuid.UUID(request.matchdict.get['id']))
item.name = request.json_body['Name'] item.name = request.json_body['Name']
transaction.commit() transaction.commit()
return cost_center_info(item.id) return cost_center_info(item.id)
+2
View File
@@ -14,6 +14,8 @@ from brewman.views.account import ledger_list
permission='Employees') permission='Employees')
@view_config(request_method='GET', route_name='employee', renderer='brewman:templates/angular_base.mako', xhr=False, @view_config(request_method='GET', route_name='employee', renderer='brewman:templates/angular_base.mako', xhr=False,
permission='Employees') permission='Employees')
@view_config(request_method='GET', route_name='employee_functions', renderer='brewman:templates/angular_base.mako', xhr=False,
permission='Employees')
def html(request): def html(request):
return {} return {}
+15 -8
View File
@@ -5,9 +5,8 @@ from pyramid.response import Response
from pyramid.view import view_config from pyramid.view import view_config
import transaction import transaction
from brewman.models.master import Product, CostCenter, LedgerType, Ledger, ProductGroup from brewman.models.master import Product, CostCenter, LedgerType, Ledger
from brewman.models.validation_exception import ValidationError from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Batch
@view_config(route_name='product_list', renderer='brewman:templates/angular_base.mako', permission='Authenticated') @view_config(route_name='product_list', renderer='brewman:templates/angular_base.mako', permission='Authenticated')
@view_config(request_method='GET', route_name='product_id', renderer='brewman:templates/angular_base.mako', @view_config(request_method='GET', route_name='product_id', renderer='brewman:templates/angular_base.mako',
@@ -18,19 +17,27 @@ def html(request):
return {} return {}
@view_config(request_method='POST', route_name='product_id', renderer='json', xhr=True, permission='Products')
@view_config(request_method='POST', route_name='product', renderer='json', xhr=True, permission='Products') @view_config(request_method='POST', route_name='product', renderer='json', xhr=True, permission='Products')
def save_update(request): def save(request):
try: try:
id = request.matchdict.get('id', None)
if id is None:
item = Product(0, request.json_body['Name'], request.json_body['Units'], item = Product(0, request.json_body['Name'], request.json_body['Units'],
Decimal(request.json_body['Fraction']), request.json_body['FractionUnits'], Decimal(request.json_body['Fraction']), request.json_body['FractionUnits'],
Decimal(request.json_body['Yeild']), request.json_body['ShowForPurchase'], Decimal(request.json_body['Yeild']), request.json_body['ShowForPurchase'],
uuid.UUID(request.json_body['ProductGroup']['ProductGroupID']), Ledger.all_purchases(), uuid.UUID(request.json_body['ProductGroup']['ProductGroupID']), Ledger.all_purchases(),
Decimal(request.json_body['Price']), request.json_body['Discontinued']).create() Decimal(request.json_body['Price']), request.json_body['Discontinued']).create()
else: transaction.commit()
item = Product.by_id(uuid.UUID(id)) return product_info(item.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='POST', route_name='product_id', renderer='json', xhr=True, permission='Products')
def update(request):
try:
item = Product.by_id(uuid.UUID(request.matchdict.get['id']))
item.name = request.json_body['Name'] item.name = request.json_body['Name']
item.units = request.json_body['Units'] item.units = request.json_body['Units']
item.fraction = Decimal(request.json_body['Fraction']) item.fraction = Decimal(request.json_body['Fraction'])
+15 -7
View File
@@ -5,7 +5,7 @@ from pyramid.view import view_config
import transaction import transaction
from brewman.models import DBSession from brewman.models import DBSession
from brewman.models.master import CostCenter, ProductGroup from brewman.models.master import ProductGroup
from brewman.models.validation_exception import ValidationError from brewman.models.validation_exception import ValidationError
@@ -18,16 +18,24 @@ def html(request):
return {} return {}
@view_config(request_method='POST', route_name='product_group_id', renderer='json', xhr=True, permission='Product Groups')
@view_config(request_method='POST', route_name='product_group', renderer='json', xhr=True, permission='Product Groups') @view_config(request_method='POST', route_name='product_group', renderer='json', xhr=True, permission='Product Groups')
def save_update(request): def save(request):
try: try:
id = request.matchdict.get('id', None)
if id is None:
item = ProductGroup(request.json_body['Name']) item = ProductGroup(request.json_body['Name'])
DBSession.add(item) DBSession.add(item)
else: transaction.commit()
item = ProductGroup.by_id(uuid.UUID(id)) return product_group_info(item.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='POST', route_name='product_group_id', renderer='json', xhr=True, permission='Product Groups')
def update(request):
try:
item = ProductGroup.by_id(uuid.UUID(request.matchdict.get['id']))
item.name = request.json_body['Name'] item.name = request.json_body['Name']
transaction.commit() transaction.commit()
return product_group_info(item.id) return product_group_info(item.id)
+101
View File
@@ -0,0 +1,101 @@
from datetime import date, timedelta
import uuid
from pyramid.httpexceptions import HTTPFound
from pyramid.response import Response
from pyramid.security import authenticated_userid, remember, forget
from pyramid.view import view_config
import transaction
from brewman import groupfinder
from brewman.models.auth import Role, User, Client
@view_config(route_name='logout')
def logout(request):
request.session.invalidate()
headers = forget(request)
return HTTPFound(location=request.route_url('home'), headers=headers)
@view_config(request_method='POST', route_name='login', renderer='json')
def login(request):
username = request.json_body.get('username', None)
password = request.json_body.get('password', None)
found, user = User.auth(username, password)
client = request.cookies.get('ClientID', None)
otp = request.json_body.get('otp', None)
client_name = request.json_body.get('ClientName', None)
allowed, response = check_client(client, otp, client_name, user if found else None)
if found and allowed:
headers = remember(request, str(user.id))
request.response.headers = headers
if allowed and isinstance(response, Client):
request.response.set_cookie('ClientID', value=str(response.code), max_age=10 * 365 * 24 * 60 * 60)
return request.response
elif not found:
response = Response("Login failed")
response.status_int = 403
return response
else:
return response
def check_client(client, otp, client_name, user):
client = None if client is None else Client.by_code(client)
outside_login_allowed = False if user is None else True if 'Clients' in groupfinder(user.id, None) else False
if len(Client.enabled_list()) == 0 and outside_login_allowed:
client = Client.create()
client.otp = None
client.name = 'Created on login by ' + user.name
client.enabled = True
transaction.commit()
return True, client
if client is None:
if outside_login_allowed:
client = Client.create()
transaction.commit()
return True, client
else:
client = Client.create()
response = Response("Unknown Client")
response.status_int = 403
response.set_cookie('ClientID', value=str(client.code), max_age=10 * 365 * 24 * 60 * 60)
transaction.commit()
return False, response
if client.enabled or outside_login_allowed:
return True, None
if client.otp is None:
response = Response("Client is Forbidden")
response.status_int = 403
return False, response
if otp is None:
response = Response("OTP not supplied")
response.status_int = 403
return False, response
elif client.otp != int(otp):
response = Response("OTP is wrong")
response.status_int = 403
return False, response
else:
client.otp = None
client.enabled = True
client.name = client_name
transaction.commit()
return True, None
def get_first_day(dt, d_years=0, d_months=0):
# d_years, d_months are "deltas" to apply to dt
y, m = dt.year + d_years, dt.month + d_months
a, m = divmod(m - 1, 12)
return date(y + a, m + 1, 1)
def get_last_day(dt):
return get_first_day(dt, 0, 1) + timedelta(-1)
+8 -73
View File
@@ -1,12 +1,10 @@
from datetime import date, timedelta from datetime import date, timedelta
import uuid import uuid
from pyramid.response import Response from pyramid.security import authenticated_userid
from pyramid.security import authenticated_userid, remember
from pyramid.view import view_config from pyramid.view import view_config
import transaction
from brewman import groupfinder from brewman import groupfinder
from brewman.models.auth import Role, User, Client from brewman.models.auth import Role, User
def session_current_date(request): def session_current_date(request):
session = request.session session = request.session
@@ -14,6 +12,11 @@ def session_current_date(request):
session['currentDate'] = date.today().strftime('%d-%b-%Y') session['currentDate'] = date.today().strftime('%d-%b-%Y')
return session['currentDate'] return session['currentDate']
def session_current_date_set(request, date):
session = request.session
session['currentDate'] = date
return session['currentDate']
def session_period_start(request): def session_period_start(request):
session = request.session session = request.session
if 'periodStart' not in session: if 'periodStart' not in session:
@@ -34,7 +37,7 @@ def user_permission(request):
if user_id is None: if user_id is None:
auth = {'isAuthenticated': False, 'perms': {}} auth = {'isAuthenticated': False, 'perms': {}}
else: else:
user = User.get_by_id(uuid.UUID(user_id)) user = User.by_id(uuid.UUID(user_id))
auth = {'isAuthenticated': True, 'Name': user.name, 'UserID': user.id} auth = {'isAuthenticated': True, 'Name': user.name, 'UserID': user.id}
session_perms = groupfinder(user.id, request) session_perms = groupfinder(user.id, request)
perms = {} perms = {}
@@ -44,74 +47,6 @@ def user_permission(request):
return auth return auth
@view_config(request_method='POST', route_name='login', renderer='json')
def login(request):
username = request.json_body.get('username', None)
password = request.json_body.get('password', None)
found, user = User.auth(username, password)
# client = request.cookies.get('ClientID', None)
# otp = request.json_body.get('otp', None)
# client_name = request.json_body.get('ClientName', None)
# allowed, response = check_client(client, otp, client_name, user if found else None)
# if found and allowed:
if found:
headers = remember(request, str(user.id))
request.response.headers = headers
# if allowed and isinstance(response, Client):
# request.response.set_cookie('ClientID', value=str(response.code), max_age=10 * 365 * 24 * 60 * 60)
return request.response
elif not found:
response = Response("Login failed")
response.status_int = 500
return response
# else:
# return response
def check_client(client, otp, client_name, user):
client = None if client is None else Client.by_code(client)
if len(Client.enabled_list()) == 0 and user is not None and 'Clients' in groupfinder(user.id, None):
client = Client.create()
client.otp = None
client.name = 'First'
client.enabled = True
transaction.commit()
return True, client
if client is None:
client = Client.create()
response = Response("Unknown Client")
response.status_int = 401
response.set_cookie('ClientID', value=str(client.code), max_age=10 * 365 * 24 * 60 * 60)
return False, response
if client.enabled:
return True, None
if client.otp is None:
response = Response("Client is Forbidden")
response.status_int = 401
return False, response
if otp is None:
response = Response("OTP not supplied")
response.status_int = 401
return False, response
elif client.otp != int(otp):
response = Response("OTP is wrong")
response.status_int = 401
return False, response
else:
client.otp = None
client.enabled = True
client.name = client_name
transaction.commit()
return True, None
def get_first_day(dt, d_years=0, d_months=0): def get_first_day(dt, d_years=0, d_months=0):
# d_years, d_months are "deltas" to apply to dt # d_years, d_months are "deltas" to apply to dt
y, m = dt.year + d_years, dt.month + d_months y, m = dt.year + d_years, dt.month + d_months
@@ -19,7 +19,7 @@ __author__ = 'tanshu'
@view_config(request_method='POST', route_name='voucher', request_param='post', renderer='json', xhr=True, @view_config(request_method='POST', route_name='voucher', request_param='post', renderer='json', xhr=True,
permission='Post Vouchers') permission='Post Vouchers')
def voucher_post(request): def voucher_post(request):
user = User.get_by_id(uuid.UUID(authenticated_userid(request))) user = User.by_id(uuid.UUID(authenticated_userid(request)))
try: try:
voucher = Voucher.by_id(uuid.UUID(request.matchdict['id'])) voucher = Voucher.by_id(uuid.UUID(request.matchdict['id']))
voucher.posted = True voucher.posted = True
@@ -34,7 +34,7 @@ def voucher_post(request):
def check_delete_permissions(request, voucher): def check_delete_permissions(request, voucher):
user = User.get_by_id(uuid.UUID(authenticated_userid(request))) user = User.by_id(uuid.UUID(authenticated_userid(request)))
permissions = groupfinder(user.id, request) permissions = groupfinder(user.id, request)
if voucher.posted and not 'Edit Posted Vouchers' in permissions: if voucher.posted and not 'Edit Posted Vouchers' in permissions:
@@ -53,8 +53,7 @@ def check_delete_permissions(request, voucher):
@view_config(request_method='DELETE', route_name='voucher', renderer='json', xhr=True) @view_config(request_method='DELETE', route_name='voucher', renderer='json', xhr=True)
def delete(request): def delete(request):
id = request.matchdict.get('id', None) voucher = Voucher.by_id(uuid.UUID(request.matchdict['id']))
voucher = Voucher.by_id(uuid.UUID(id))
permission = check_delete_permissions(request, voucher) permission = check_delete_permissions(request, voucher)
if permission is not None: if permission is not None:
return permission return permission
@@ -110,6 +109,8 @@ def voucher_info(voucher):
'LastEditDate': voucher.last_edit_date.strftime('%d-%b-%Y %H:%M'), 'LastEditDate': voucher.last_edit_date.strftime('%d-%b-%Y %H:%M'),
'User': {'UserID': voucher.user.id, 'Name': voucher.user.name}, 'User': {'UserID': voucher.user.id, 'Name': voucher.user.name},
'Poster': voucher.poster.name if voucher.posted else ''} 'Poster': voucher.poster.name if voucher.posted else ''}
if voucher.reconcilliation_date is not None:
json_voucher['ReconcilliationDate'] = voucher.reconcilliation_date.strftime('%d-%b-%Y %H:%M')
for item in voucher.journals: for item in voucher.journals:
json_voucher['Journals'].append({'JournalID': item.id, 'Debit': item.debit, 'Amount': item.amount, json_voucher['Journals'].append({'JournalID': item.id, 'Debit': item.debit, 'Amount': item.amount,
'Ledger': {'LedgerID': item.ledger.id, 'Name': item.ledger.name}, 'Ledger': {'LedgerID': item.ledger.id, 'Name': item.ledger.name},
+12 -16
View File
@@ -3,7 +3,6 @@ from decimal import Decimal
import uuid import uuid
from brewman.models import DBSession from brewman.models import DBSession
from brewman.models.master import Product, CostCenter, LedgerBase from brewman.models.master import Product, CostCenter, LedgerBase
from brewman.models.operations import create_basic
from brewman.models.validation_exception import ValidationError from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal
@@ -11,10 +10,8 @@ __author__ = 'tanshu'
def issue_create_voucher(json, user): def issue_create_voucher(json, user):
dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name('Issue'), voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name('Issue'))
posted=False) DBSession.add(voucher)
create_basic(voucher)
for item in json['Journals']: for item in json['Journals']:
if int(item['Debit']) == 1: if int(item['Debit']) == 1:
@@ -60,10 +57,9 @@ def issue_create_journals(inventories, source, destination):
amount = 0 amount = 0
for item in inventories: for item in inventories:
amount += item.amount amount += item.amount
return [Journal(debit=-1, ledger_id=LedgerBase.all_purchases(), amount=round(amount, 2),
return [Journal(debit=-1, ledger_id=LedgerBase.all_purchases(), amount=round(item.amount, 2),
cost_center_id=source), cost_center_id=source),
Journal(debit=1, ledger_id=LedgerBase.all_purchases(), amount=round(item.amount, 2), Journal(debit=1, ledger_id=LedgerBase.all_purchases(), amount=round(amount, 2),
cost_center_id=destination)] cost_center_id=destination)]
@@ -107,23 +103,23 @@ def issue_update_inventory(voucher, newInventories, batch_consumed):
found = True found = True
if item.product_id != product.id: if item.product_id != product.id:
raise ValidationError('Product cannot be changed') raise ValidationError('Product cannot be changed')
quantity = round(Decimal(i['Quantity']), 2) new_quantity = round(Decimal(i['Quantity']), 2)
item_quantity = round(Decimal(item.quantity), 2) old_quantity = round(Decimal(item.quantity), 2)
quantity_remaining = round(Decimal(item.batch.quantity_remaining), 2) quantity_remaining = round(Decimal(item.batch.quantity_remaining), 2)
if quantity == 0: if new_quantity <= 0:
raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name)) raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name))
if batch_consumed == True and quantity - item_quantity > quantity_remaining: if batch_consumed == True and new_quantity - old_quantity > quantity_remaining:
raise ValidationError("Maximum quantity available for {0} is {1}".format(item.product.full_name, raise ValidationError("Maximum quantity available for {0} is {1}".format(item.product.full_name,
item_quantity + quantity_remaining)) old_quantity + quantity_remaining))
if batch_consumed is None: if batch_consumed is None:
pass pass
elif batch_consumed: elif batch_consumed:
item.batch.quantity_remaining -= (quantity - item_quantity) item.batch.quantity_remaining -= (new_quantity - old_quantity)
else: else:
item.batch.quantity_remaining += (quantity - item_quantity) item.batch.quantity_remaining += (new_quantity - old_quantity)
item.quantity = quantity item.quantity = new_quantity
newInventories.remove(i) newInventories.remove(i)
break break
if not found: if not found:
@@ -3,7 +3,6 @@ from decimal import Decimal
import uuid import uuid
from brewman.models import DBSession from brewman.models import DBSession
from brewman.models.master import Product, LedgerBase from brewman.models.master import Product, LedgerBase
from brewman.models.operations import create_purchase_voucher
from brewman.models.validation_exception import ValidationError from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal
@@ -11,17 +10,19 @@ __author__ = 'tanshu'
def purchase_create_voucher(json, user): def purchase_create_voucher(json, user):
dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name(json['Type']))
type=VoucherType.by_name(json['Type']), posted=False) DBSession.add(voucher)
for item in json['Inventories']: for item in json['Inventories']:
voucher.inventories.append(purchase_create_inventory(item, json['Date'])) voucher.inventories.append(purchase_create_inventory(voucher, item, json['Date']))
for item in purchase_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID']): for item in purchase_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID']):
DBSession.add(item)
voucher.journals.append(item) voucher.journals.append(item)
create_purchase_voucher(voucher) DBSession.flush()
return voucher return voucher
def purchase_create_inventory(item, date): def purchase_create_inventory(voucher, item, date):
product = Product.by_id(uuid.UUID(item['Product']['ProductID'])) product = Product.by_id(uuid.UUID(item['Product']['ProductID']))
inventory_id = uuid.UUID(item['InventoryID']) if 'InventoryID' in item else None inventory_id = uuid.UUID(item['InventoryID']) if 'InventoryID' in item else None
quantity = round(Decimal(item['Quantity']), 2) quantity = round(Decimal(item['Quantity']), 2)
@@ -30,8 +31,12 @@ def purchase_create_inventory(item, date):
discount = round(Decimal(item['Discount']), 5) discount = round(Decimal(item['Discount']), 5)
batch = Batch(name=date, product_id=product.id, quantity_remaining=quantity, rate=rate, tax=tax, batch = Batch(name=date, product_id=product.id, quantity_remaining=quantity, rate=rate, tax=tax,
discount=discount) discount=discount)
return Inventory(id=inventory_id, product_id=product.id, batch=batch, quantity=quantity, rate=rate, tax=tax, DBSession.add(batch)
inventory = Inventory(id=inventory_id, product_id=product.id, batch=batch, quantity=quantity, rate=rate, tax=tax,
discount=discount) discount=discount)
DBSession.add(inventory)
voucher.inventories.append(item)
def purchase_create_journals(inventories, ledgerID): def purchase_create_journals(inventories, ledgerID):
@@ -74,16 +79,16 @@ def purchase_update_inventory(voucher, newInventories, date):
found = True found = True
if item.product_id != product.id: if item.product_id != product.id:
raise ValidationError('Product cannot be changed') raise ValidationError('Product cannot be changed')
quantity = round(Decimal(i['Quantity']), 2) new_quantity = round(Decimal(i['Quantity']), 2)
item_quantity = round(Decimal(item.quantity), 2) old_quantity = round(Decimal(item.quantity), 2)
quantity_remaining = round(Decimal(item.batch.quantity_remaining), 2) quantity_remaining = round(Decimal(item.batch.quantity_remaining), 2)
if quantity == 0: if new_quantity <= 0:
raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name)) raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name))
if item_quantity - quantity > 0 and quantity_remaining < (item_quantity - quantity): if old_quantity > new_quantity and quantity_remaining < (old_quantity - new_quantity):
raise ValidationError("{0} has been issued, minimum quantity is".format( raise ValidationError("{0} has been issued, minimum quantity is".format(
item_quantity - quantity_remaining)) old_quantity - quantity_remaining))
item.batch.quantity_remaining -= (item_quantity - quantity) item.batch.quantity_remaining -= (old_quantity - new_quantity)
item.quantity = quantity item.quantity = new_quantity
rate = round(Decimal(i['Rate']), 2) rate = round(Decimal(i['Rate']), 2)
discount = round(Decimal(i['Discount']), 5) discount = round(Decimal(i['Discount']), 5)
tax = round(Decimal(i['Tax']), 5) tax = round(Decimal(i['Tax']), 5)
@@ -94,8 +99,10 @@ def purchase_update_inventory(voucher, newInventories, date):
item.tax = tax item.tax = tax
item.batch.tax = tax item.batch.tax = tax
newInventories.remove(i) newInventories.remove(i)
#TODO: Update all references of the batch with the new rates
break break
if not found: if not found:
#TODO: Check to see if the batch is issued not just quantity remaining is full
if item.quantity != item.batch.quantity_remaining: if item.quantity != item.batch.quantity_remaining:
raise ValidationError("{0} has been issued, it cannot be deleted".format(item.product.name)) raise ValidationError("{0} has been issued, it cannot be deleted".format(item.product.name))
else: else:
@@ -104,17 +111,17 @@ def purchase_update_inventory(voucher, newInventories, date):
voucher.inventories.remove(item) voucher.inventories.remove(item)
for i in newInventories: for i in newInventories:
product = Product.by_id(uuid.UUID(i['Product']['ProductID'])) product = Product.by_id(uuid.UUID(i['Product']['ProductID']))
quantity = round(Decimal(i['Quantity']), 2) new_quantity = round(Decimal(i['Quantity']), 2)
rate = round(Decimal(i['Rate']), 2) rate = round(Decimal(i['Rate']), 2)
tax = round(Decimal(i['Tax']), 5) tax = round(Decimal(i['Tax']), 5)
discount = round(Decimal(i['Discount']), 5) discount = round(Decimal(i['Discount']), 5)
batch = Batch(name=date, product_id=product.id, quantity_remaining=quantity, rate=rate, tax=tax, batch = Batch(name=date, product_id=product.id, quantity_remaining=new_quantity, rate=rate, tax=tax,
discount=discount) discount=discount)
inventory = Inventory(id=None, product_id=product.id, batch=batch, quantity=quantity, rate=rate, tax=tax, inventory = Inventory(id=None, product_id=product.id, batch=batch, quantity=new_quantity, rate=rate, tax=tax,
discount=discount) discount=discount)
inventory.voucher_id = voucher.id inventory.voucher_id = voucher.id
DBSession.add(inventory.batch) DBSession.add(batch)
inventory.batch_id = inventory.batch.id inventory.batch_id = batch.id
DBSession.add(inventory) DBSession.add(inventory)
voucher.inventories.append(inventory) voucher.inventories.append(inventory)
@@ -145,6 +152,7 @@ def purchase_update_journals(voucher, journals):
DBSession.delete(item) DBSession.delete(item)
voucher.journals.remove(item) voucher.journals.remove(item)
for item in journals.values(): for item in journals.values():
item.amount = round(item.amount, 2)
DBSession.add(item) DBSession.add(item)
voucher.journals.append(item) voucher.journals.append(item)
@@ -3,7 +3,6 @@ from decimal import Decimal
import uuid import uuid
from brewman.models import DBSession from brewman.models import DBSession
from brewman.models.master import Product, LedgerBase from brewman.models.master import Product, LedgerBase
from brewman.models.operations import create_purchase_voucher, create_basic
from brewman.models.validation_exception import ValidationError from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory, Journal
@@ -11,10 +10,8 @@ __author__ = 'tanshu'
def purchase_return_create_voucher(json, user): def purchase_return_create_voucher(json, user):
dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y') dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id, type=VoucherType.by_name(json['Type']))
type=VoucherType.by_name(json['Type']), posted=False) DBSession.add(voucher)
create_basic(voucher)
for item in json['Inventories']: for item in json['Inventories']:
purchase_return_create_inventory(voucher, item) purchase_return_create_inventory(voucher, item)
@@ -49,7 +46,7 @@ def purchase_return_create_journals(inventories, ledgerID):
amount = 0 amount = 0
for item in inventories: for item in inventories:
ledger = Product.by_id(item.product_id).ledger ledger = Product.by_id(item.product_id).ledger
amount += item.amount amount += round(item.amount, 2)
if ledger.id in journals: if ledger.id in journals:
journals[ledger.id].amount += item.amount journals[ledger.id].amount += item.amount
else: else:
@@ -83,7 +80,7 @@ def purchase_return_update_inventory(voucher, newInventories, date):
found = True found = True
if item.product_id != product.id: if item.product_id != product.id:
raise ValidationError('Product cannot be changed') raise ValidationError('Product cannot be changed')
quantity = Decimal(i['Quantity']) quantity = round(Decimal(i['Quantity']), 2)
if quantity == 0: if quantity == 0:
raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name)) raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name))
if quantity - item.quantity > item.batch.quantity_remaining: if quantity - item.quantity > item.batch.quantity_remaining:
@@ -120,13 +117,14 @@ def purchase_return_update_journals(voucher, journals):
item = voucher.journals[i - 1] item = voucher.journals[i - 1]
if item.ledger_id in journals: if item.ledger_id in journals:
item.debit = journals[item.ledger_id].debit item.debit = journals[item.ledger_id].debit
item.amount = journals[item.ledger_id].amount item.amount = round(journals[item.ledger_id].amount, 2)
item.cost_center_id = journals[item.ledger_id].cost_center_id item.cost_center_id = journals[item.ledger_id].cost_center_id
del journals[item.ledger_id] del journals[item.ledger_id]
else: else:
DBSession.delete(item) DBSession.delete(item)
voucher.journals.remove(item) voucher.journals.remove(item)
for item in journals.values(): for item in journals.values():
item.amount = round(item.amount, 2)
DBSession.add(item) DBSession.add(item)
voucher.journals.append(item) voucher.journals.append(item)
@@ -6,6 +6,7 @@ import transaction
from brewman.models.auth import User from brewman.models.auth import User
from brewman.models.validation_exception import ValidationError from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher from brewman.models.voucher import Voucher
from brewman.views.services.session import session_current_date_set
from brewman.views.services.voucher import voucher_info, journal_create_voucher, purchase_create_voucher, issue_create_voucher from brewman.views.services.voucher import voucher_info, journal_create_voucher, purchase_create_voucher, issue_create_voucher
from brewman.views.services.voucher.purchase_return import purchase_return_create_voucher from brewman.views.services.voucher.purchase_return import purchase_return_create_voucher
@@ -16,6 +17,8 @@ __author__ = 'tanshu'
class save_voucher(object): class save_voucher(object):
def __init__(self, request): def __init__(self, request):
self.request = request self.request = request
self.user = User.by_id(uuid.UUID(authenticated_userid(request)))
self.json = request.json_body
@view_config(request_param='type=Journal', permission='Journal') @view_config(request_param='type=Journal', permission='Journal')
def journal(self): def journal(self):
@@ -47,19 +50,17 @@ class save_voucher(object):
return self.save() return self.save()
def save(self): def save(self):
request = self.request
user = User.get_by_id(uuid.UUID(authenticated_userid(request)))
try: try:
""" new voucher """ if self.json['Type'] in ['Journal', 'Payment', 'Receipt']:
if request.json_body['Type'] in ['Journal', 'Payment', 'Receipt']: voucher = journal_create_voucher(self.json, self.user)
voucher = journal_create_voucher(request.json_body, user) elif self.json['Type'] in ['Purchase']:
elif request.json_body['Type'] in ['Purchase']: voucher = purchase_create_voucher(self.json, self.user)
voucher = purchase_create_voucher(request.json_body, user) elif self.json['Type'] in ['Purchase Return']:
elif request.json_body['Type'] in ['Purchase Return']: voucher = purchase_return_create_voucher(self.json, self.user)
voucher = purchase_return_create_voucher(request.json_body, user) elif self.json['Type'] in ['Issue']:
elif request.json_body['Type'] in ['Issue']: voucher = issue_create_voucher(self.json, self.user)
voucher = issue_create_voucher(request.json_body, user)
transaction.commit() transaction.commit()
session_current_date_set(self.request,self.json['Date'])
return voucher_info(Voucher.by_id(voucher.id)) return voucher_info(Voucher.by_id(voucher.id))
except ValidationError as ex: except ValidationError as ex:
transaction.abort() transaction.abort()
@@ -7,6 +7,7 @@ from brewman import groupfinder
from brewman.models.auth import User from brewman.models.auth import User
from brewman.models.validation_exception import ValidationError from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher from brewman.models.voucher import Voucher
from brewman.views.services.session import session_current_date_set
from brewman.views.services.voucher import voucher_info, issue_update_voucher, purchase_update_voucher, journal_update_voucher from brewman.views.services.voucher import voucher_info, issue_update_voucher, purchase_update_voucher, journal_update_voucher
from brewman.views.services.voucher.purchase_return import purchase_return_update_voucher from brewman.views.services.voucher.purchase_return import purchase_return_update_voucher
@@ -17,7 +18,7 @@ __author__ = 'tanshu'
class update_voucher(object): class update_voucher(object):
def __init__(self, request): def __init__(self, request):
self.request = request self.request = request
self.user = User.get_by_id(uuid.UUID(authenticated_userid(request))) self.user = User.by_id(uuid.UUID(authenticated_userid(request)))
self.voucher = Voucher.by_id(uuid.UUID(request.matchdict.get('id', None))) self.voucher = Voucher.by_id(uuid.UUID(request.matchdict.get('id', None)))
self.json = request.json_body self.json = request.json_body
@@ -76,6 +77,7 @@ class update_voucher(object):
elif self.json['Type'] in ['Issue']: elif self.json['Type'] in ['Issue']:
voucher = issue_update_voucher(self.voucher, self.json, self.user) voucher = issue_update_voucher(self.voucher, self.json, self.user)
transaction.commit() transaction.commit()
session_current_date_set(self.request,self.json['Date'])
return voucher_info(Voucher.by_id(voucher.id)) return voucher_info(Voucher.by_id(voucher.id))
except ValidationError as ex: except ValidationError as ex:
transaction.abort() transaction.abort()