diff --git a/brewman/brewman/__init__.py b/brewman/brewman/__init__.py
index 3aea6723..548c04bd 100644
--- a/brewman/brewman/__init__.py
+++ b/brewman/brewman/__init__.py
@@ -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))"
# 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('assets', 'brewman:static/assets')
@@ -66,6 +67,10 @@ def main(global_config, **settings):
config.add_route('group', '/Group')
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', '/Product')
config.add_route('product_list', '/Products')
@@ -88,6 +93,9 @@ def main(global_config, **settings):
config.add_route('issue', '/Issue')
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', '/Attendance')
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', '/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', '/Ledger')
@@ -124,9 +136,6 @@ def main(global_config, **settings):
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.scan()
diff --git a/brewman/brewman/models/auth.py b/brewman/brewman/models/auth.py
index 8eec623b..2da76140 100644
--- a/brewman/brewman/models/auth.py
+++ b/brewman/brewman/models/auth.py
@@ -56,7 +56,6 @@ class Client(Base):
client_code = random.randint(1000, 9999)
otp = random.randint(1000, 9999)
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)
DBSession.add(client)
return client
@@ -108,18 +107,18 @@ class User(Base):
self.locked_out = locked_out
@classmethod
- def get_by_name(cls, name):
+ def by_name(cls, name):
return DBSession.query(cls).filter(cls.name == name).first()
@classmethod
- def get_by_id(cls, id):
+ def by_id(cls, id):
if not isinstance(id, uuid.UUID):
id = uuid.UUID(id)
return DBSession.query(cls).filter(cls.id == id).one()
@classmethod
def auth(cls, name, password):
- user = cls.get_by_name(name)
+ user = cls.by_name(name)
if not user:
return False, None
if user.password != encrypt(password) or user.locked_out:
@@ -149,7 +148,7 @@ class Group(Base):
self.name = name
@classmethod
- def get_by_id(cls, id):
+ def by_id(cls, id):
return DBSession.query(cls).filter(cls.id == id).one()
@classmethod
@@ -173,6 +172,6 @@ class Role(Base):
return DBSession.query(cls).order_by(cls.name).all()
@classmethod
- def get_by_id(cls, id):
+ def by_id(cls, id):
return DBSession.query(cls).filter(cls.id == id).one()
diff --git a/brewman/brewman/models/master.py b/brewman/brewman/models/master.py
index d8f7b66e..265e28ad 100644
--- a/brewman/brewman/models/master.py
+++ b/brewman/brewman/models/master.py
@@ -223,6 +223,10 @@ class LedgerBase(Base):
def local_purchase(cls):
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):
__tablename__ = 'entities_employees'
diff --git a/brewman/brewman/models/operations.py b/brewman/brewman/models/operations.py
index bdbb28ce..a31ce084 100644
--- a/brewman/brewman/models/operations.py
+++ b/brewman/brewman/models/operations.py
@@ -34,24 +34,13 @@ def update_journal_voucher(voucher):
update_basic(voucher)
-def create_purchase_voucher(voucher):
+def validate_new_purchase_voucher(voucher):
journals_valid(voucher)
for item in voucher.inventories:
batch = item.batch
if not batch.id is None:
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):
journals_valid(voucher)
diff --git a/brewman/brewman/models/voucher.py b/brewman/brewman/models/voucher.py
index 23ead4b5..de5bd197 100644
--- a/brewman/brewman/models/voucher.py
+++ b/brewman/brewman/models/voucher.py
@@ -50,13 +50,13 @@ class Voucher(Base):
def __name__(self):
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.reconcilliation_date = reconcilliation_date
self.narration = narration
self.posted = posted
- self.creation_date = creation_date
- self.last_edit_date = last_edit_date
+ self.creation_date = datetime.now() if creation_date is None else creation_date
+ self.last_edit_date = datetime.now() if last_edit_date is None else last_edit_date
self.type = type
self.user_id = user_id
self.poster_id = poster_id
diff --git a/brewman/brewman/renderers.py b/brewman/brewman/renderers.py
new file mode 100644
index 00000000..37174284
--- /dev/null
+++ b/brewman/brewman/renderers.py
@@ -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)
diff --git a/brewman/brewman/security.py b/brewman/brewman/security.py
index ea53aca3..1a676177 100644
--- a/brewman/brewman/security.py
+++ b/brewman/brewman/security.py
@@ -5,7 +5,7 @@ def groupfinder(user_id, request):
if type(user_id) == str:
user_id = uuid.UUID(user_id)
perms = []
- user = User.get_by_id(user_id)
+ user = User.by_id(user_id)
for item in user.groups:
for perm in item.roles:
perms.append(perm.name)
diff --git a/brewman/brewman/static/css/table.css b/brewman/brewman/static/css/table.css
index 7d2c1cd3..3fe21cb5 100644
--- a/brewman/brewman/static/css/table.css
+++ b/brewman/brewman/static/css/table.css
@@ -1,41 +1,12 @@
/* Table for Issue */
+.no-wrap {
+ white-space: nowrap
+}
.hide
{
display: none;
}
-.clean-table
-{
- 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;
+.table tbody tr.success td {
+ background-color: #1F7A1F;
}
-.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;
-}
diff --git a/brewman/brewman/static/js/angular-cookies-1.0.2.js b/brewman/brewman/static/js/angular-cookies-1.0.2.js
new file mode 100644
index 00000000..955715b1
--- /dev/null
+++ b/brewman/brewman/static/js/angular-cookies-1.0.2.js
@@ -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);
diff --git a/brewman/brewman/static/partial/account-list.html b/brewman/brewman/static/partial/account-list.html
index 5021c777..8e1eec7c 100644
--- a/brewman/brewman/static/partial/account-list.html
+++ b/brewman/brewman/static/partial/account-list.html
@@ -1,5 +1,5 @@
-
+
| Name |
diff --git a/brewman/brewman/static/partial/attendance.html b/brewman/brewman/static/partial/attendance.html
index 7106fcef..c3981772 100644
--- a/brewman/brewman/static/partial/attendance.html
+++ b/brewman/brewman/static/partial/attendance.html
@@ -4,7 +4,7 @@
-
+
@@ -12,7 +12,7 @@
-
+
| Code |
diff --git a/brewman/brewman/static/partial/cash-flow.html b/brewman/brewman/static/partial/cash-flow.html
index 62c7326c..1e4c4775 100644
--- a/brewman/brewman/static/partial/cash-flow.html
+++ b/brewman/brewman/static/partial/cash-flow.html
@@ -4,8 +4,8 @@
-
-
+
+
@@ -13,7 +13,7 @@
-
+
| Name |
diff --git a/brewman/brewman/static/partial/client-list.html b/brewman/brewman/static/partial/client-list.html
new file mode 100644
index 00000000..ec7717b0
--- /dev/null
+++ b/brewman/brewman/static/partial/client-list.html
@@ -0,0 +1,20 @@
+
+
+
+
+ | Code |
+ Name |
+ Enabled |
+ OTP |
+
+
+
+
+ | {{item.Code}} |
+ {{item.Name}} |
+ {{item.Enabled}} |
+ {{item.OTP}} |
+
+
+
+
diff --git a/brewman/brewman/static/partial/closing-stock.html b/brewman/brewman/static/partial/closing-stock.html
index 563236e6..c4f8f74a 100644
--- a/brewman/brewman/static/partial/closing-stock.html
+++ b/brewman/brewman/static/partial/closing-stock.html
@@ -4,7 +4,7 @@
-
+
@@ -12,7 +12,7 @@
-
+
| Product |
diff --git a/brewman/brewman/static/partial/cost-center-list.html b/brewman/brewman/static/partial/cost-center-list.html
index 34ff52fa..8f3d2a0d 100644
--- a/brewman/brewman/static/partial/cost-center-list.html
+++ b/brewman/brewman/static/partial/cost-center-list.html
@@ -1,5 +1,5 @@
-
+
| Name |
diff --git a/brewman/brewman/static/partial/daybook.html b/brewman/brewman/static/partial/daybook.html
index d8d5fb1e..d72ccd2c 100644
--- a/brewman/brewman/static/partial/daybook.html
+++ b/brewman/brewman/static/partial/daybook.html
@@ -4,8 +4,8 @@
-
-
+
+
@@ -13,7 +13,7 @@
-
+
| Date |
@@ -26,7 +26,7 @@
-
+
| {{item.Date}} |
{{item.Type}} |
{{item.Narration}} |
diff --git a/brewman/brewman/static/partial/employee-attendance.html b/brewman/brewman/static/partial/employee-attendance.html
index 6f0e4d1d..e6c69a56 100644
--- a/brewman/brewman/static/partial/employee-attendance.html
+++ b/brewman/brewman/static/partial/employee-attendance.html
@@ -4,8 +4,8 @@
-
-
+
+
@@ -21,21 +21,27 @@
-
+
| Date |
Status |
+ isDirty |
-
+
| {{item.Date}} |
-
|
+
+
+ |
diff --git a/brewman/brewman/static/partial/employee-detail.html b/brewman/brewman/static/partial/employee-detail.html
index 86da0ed9..d1a0f0e3 100644
--- a/brewman/brewman/static/partial/employee-detail.html
+++ b/brewman/brewman/static/partial/employee-detail.html
@@ -56,8 +56,7 @@
-
+
@@ -65,8 +64,7 @@
-
+
diff --git a/brewman/brewman/static/partial/employee-functions.html b/brewman/brewman/static/partial/employee-functions.html
index 0d01583a..c7f113c9 100644
--- a/brewman/brewman/static/partial/employee-functions.html
+++ b/brewman/brewman/static/partial/employee-functions.html
@@ -4,8 +4,18 @@
-
-
+
+
+
+
+
+
@@ -13,7 +23,7 @@
-
+
diff --git a/brewman/brewman/static/partial/employee-list.html b/brewman/brewman/static/partial/employee-list.html
index 9948ca4c..2f65c810 100644
--- a/brewman/brewman/static/partial/employee-list.html
+++ b/brewman/brewman/static/partial/employee-list.html
@@ -1,6 +1,6 @@
-
+
| Code |
diff --git a/brewman/brewman/static/partial/group-list.html b/brewman/brewman/static/partial/group-list.html
index a0888be4..27bfa242 100644
--- a/brewman/brewman/static/partial/group-list.html
+++ b/brewman/brewman/static/partial/group-list.html
@@ -1,5 +1,5 @@
-
+
| Name |
diff --git a/brewman/brewman/static/partial/issue.html b/brewman/brewman/static/partial/issue.html
index c17041e2..0b724102 100644
--- a/brewman/brewman/static/partial/issue.html
+++ b/brewman/brewman/static/partial/issue.html
@@ -4,7 +4,7 @@
-
+
| Amount |
@@ -25,7 +25,7 @@
-
+
@@ -73,7 +73,7 @@
-
+
| Product |
diff --git a/brewman/brewman/static/partial/journal.html b/brewman/brewman/static/partial/journal.html
index 2f672dfa..e49afdaf 100644
--- a/brewman/brewman/static/partial/journal.html
+++ b/brewman/brewman/static/partial/journal.html
@@ -4,7 +4,7 @@
-
+
@@ -27,7 +27,7 @@
-
+
| Debit |
diff --git a/brewman/brewman/static/partial/ledger.html b/brewman/brewman/static/partial/ledger.html
index 73b66704..5a6d3cb9 100644
--- a/brewman/brewman/static/partial/ledger.html
+++ b/brewman/brewman/static/partial/ledger.html
@@ -4,8 +4,8 @@
-
-
+
+
@@ -20,7 +20,7 @@
-
+
| Date |
@@ -33,19 +33,19 @@
-
- | {{item.Date}} |
+
+ | {{item.Date}} |
{{item.Name}} |
- {{item.Type}} |
+ {{item.Type}} |
{{item.Narration}} |
- {{item.Debit}} |
- {{item.Credit}} |
- {{item.Running}} |
+ {{item.Debit}} |
+ {{item.Credit}} |
+ {{item.Running}} |
- | {{info.Footer.Date}} |
+ {{info.Footer.Date}} |
{{info.Footer.Name}} |
{{info.Footer.Type}} |
{{info.Footer.Narration}} |
diff --git a/brewman/brewman/static/partial/login.html b/brewman/brewman/static/partial/login.html
index 753bf476..25de278a 100644
--- a/brewman/brewman/static/partial/login.html
+++ b/brewman/brewman/static/partial/login.html
@@ -14,6 +14,21 @@
+
+
+
diff --git a/brewman/brewman/static/partial/payment.html b/brewman/brewman/static/partial/payment.html
index 0eac6fd5..b65d2704 100644
--- a/brewman/brewman/static/partial/payment.html
+++ b/brewman/brewman/static/partial/payment.html
@@ -3,7 +3,7 @@
-
+
@@ -11,7 +11,7 @@
+ ng-options="l.model.LedgerID as l.label for l in ledgers">