Added the Clents table to restrict the webapp on allowed clients via 10 yr long cookies and otp for intitial activation.

Added the reconcilable column to ledgers table for future implementation of reconcile account feature.
Purchase return should work now at.
Changed the class of add button in voucher forms to btn-info
Edit in Payment and Receipt should be working now.
JS Code Cleanup including missing ';', etc.
Added 'use strict'; to all js files
Added came_from in login in AngularJS.
Fixed error in purchase where it would look for purchase_ledger instead of ledger of product.
Added 'Clients' permission which is allowed remote logins and to authorize/deauthroize clients
Added JDBC Sqlite provider for use in PyCharm
This commit is contained in:
Tanshu committed 2012-11-04 15:27:46 +05:30
1 parent bccad85099
commit 16bbf37601
57 files changed
+893 -414

No files matched your search

+2 -2
View File
@@ -78,8 +78,8 @@ def main(global_config, **settings):
config.add_route('journal', '/Journal')
config.add_route('purchase_id', '/Purchase/{id}')
config.add_route('purchase', '/Purchase')
config.add_route('purchase_return_id', '/PurchaseReturn/{id}')
config.add_route('purchase_return', '/PurchaseReturn')
config.add_route('purchase_return_id', '/Return/{id}')
config.add_route('purchase_return', '/Return')
config.add_route('payment_id', '/Payment/{id}')
config.add_route('payment', '/Payment')
config.add_route('receipt_id', '/Receipt/{id}')
+50 -10
View File
@@ -1,9 +1,11 @@
import random
import string
import uuid
from sqlalchemy.schema import ForeignKey, Table
from brewman.models.guidtype import GUID
from hashlib import md5
from sqlalchemy import Column, Boolean, Unicode
from sqlalchemy import Column, Boolean, Unicode, Integer
from sqlalchemy.orm import synonym, relationship
@@ -14,12 +16,50 @@ def encrypt(val):
return md5(val.encode('utf-8') + "Salt".encode('utf-8')).hexdigest()
#class UserGroup(Base):
# __tablename__ = 'auth_usergroups'
#
# id = Column('UserGroupID', GUID(), primary_key=True)
# user_id = Column('UserID', GUID(), ForeignKey('auth_users.UserID'))
# group_id = Column('GroupID', GUID(), ForeignKey('auth_groups.GroupID'))
class Client(Base):
__tablename__ = 'auth_clients'
id = Column('ClientID', GUID(), primary_key=True, default=uuid.uuid4)
code = Column('Code', Integer, unique=True, nullable=False)
name = Column('Name', Unicode(255), unique=True, nullable=False)
enabled = Column('Enabled', Boolean, nullable=False)
otp = Column('OTP', Integer)
def __init__(self, code=None, name=None, enabled=False, otp=None):
self.code = code
self.name = name
self.enabled = enabled
self.otp = otp
@classmethod
def by_id(cls, id):
if not isinstance(id, uuid.UUID):
id = uuid.UUID(id)
return DBSession.query(cls).filter(cls.id == id).first()
@classmethod
def by_code(cls, code):
if not isinstance(code, int):
code = int(code)
return DBSession.query(cls).filter(cls.code == code).first()
@classmethod
def list(cls):
return DBSession.query(cls).order_by(cls.name).all()
@classmethod
def enabled_list(cls):
return DBSession.query(cls).filter(cls.enabled == True).order_by(cls.name).all()
@classmethod
def create(cls):
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
user_group = Table(
@@ -27,7 +67,7 @@ user_group = Table(
Column('UserGroupID', GUID(), primary_key=True, default=uuid.uuid4),
Column('UserID', GUID(), ForeignKey('auth_users.UserID')),
Column('GroupID', GUID(), ForeignKey('auth_groups.GroupID'))
)
)
#class RoleGroup(Base):
# __tablename__ = 'auth_rolegroups'
@@ -37,12 +77,12 @@ user_group = Table(
# group_id = Column('GroupID', GUID(), ForeignKey('auth_groups.GroupID'))
role_group = Table (
role_group = Table(
'auth_rolegroups', Base.metadata,
Column('RoleGroupID', GUID(), primary_key=True, default=uuid.uuid4),
Column('RoleID', GUID(), ForeignKey('auth_roles.RoleID')),
Column('GroupID', GUID(), ForeignKey('auth_groups.GroupID'))
)
)
class User(Base):
+9 -6
View File
@@ -160,6 +160,7 @@ class LedgerBase(Base):
type = Column('Type', Integer, nullable=False)
ledger_type = Column('ledger_type', Unicode(50), nullable=False)
is_active = Column('IsActive', Boolean)
is_reconcilable = Column('IsReconcilable', Boolean)
costcenter_id = Column('CostCenterID', GUID(), ForeignKey('entities_costcenters.CostCenterID'))
__mapper_args__ = {'polymorphic_on': ledger_type}
@@ -174,11 +175,12 @@ class LedgerBase(Base):
def type_object(self):
return LedgerType.by_id(self.type)
def __init__(self, code=None, name=None, type=None, is_active=None, costcenter_id=None):
def __init__(self, code=None, name=None, type=None, is_active=None, is_reconcilable=False, costcenter_id=None):
self.code = code
self.name = name
self.type = type
self.is_active = is_active
self.is_reconcilable = is_reconcilable
self.costcenter_id = costcenter_id
@classmethod
@@ -253,7 +255,8 @@ class Employee(LedgerBase):
self.service_points = service_points
self.joining_date = joining_date
self.leaving_date = leaving_date
super().__init__(code, name, 10, is_active, costcenter_id)
super().__init__(code=code, name=name, type=10, is_active=is_active, is_reconcilable=False,
costcenter_id=costcenter_id)
def create(self):
code = DBSession.query(func.max(LedgerBase.code)).filter(LedgerBase.type == self.type).one()[0]
@@ -341,14 +344,14 @@ class LedgerType:
list.append(LedgerType(5, 'Capital', True, False, False, 70, True))
list.append(LedgerType(6, 'Debtors', True, True, True, 30, True))
list.append(LedgerType(7, 'Expenses', False, True, True, 40, True))
# list.append(LedgerType(8, 'Discount', False, False, True, 30, True))
# list.append(LedgerType(8, 'Discount', False, False, True, 30, True))
list.append(LedgerType(9, 'Creditors', True, False, True, 60, True))
list.append(LedgerType(10, 'Salary', True, True, True, 40, False))
list.append(LedgerType(11, 'Liabilities', True, False, True, 50, True))
list.append(LedgerType(12, 'Revenue', False, False, True, 30, True))
# list.append(LedgerType(13, 'Tax', True, False, True, 80, True))
# list.append(LedgerType(14, 'Total', False, False, False, 900, False))
# list.append(LedgerType(15, 'Net', False, False, False, 1000, False))
# list.append(LedgerType(13, 'Tax', True, False, True, 80, True))
# list.append(LedgerType(14, 'Total', False, False, False, 900, False))
# list.append(LedgerType(15, 'Net', False, False, False, 1000, False))
return list
@@ -30,6 +30,9 @@
<label class="checkbox">
<input type="checkbox" ng-model="account.IsActive"> Is Active
</label>
<label class="checkbox">
<input type="checkbox" ng-model="account.IsReconcilable"> Is Reconcilable
</label>
</div>
</div>
@@ -5,6 +5,7 @@
<th>Name</th>
<th>Type</th>
<th>Is Active?</th>
<th>Is Reconcilable?</th>
<th>Cost Center</th>
</tr>
</thead>
@@ -13,6 +14,7 @@
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td>{{item.Type}}</td>
<td>{{item.IsActive}}</td>
<td>{{item.IsReconcilable}}</td>
<td>{{item.CostCenter}}</td>
</tr>
</tbody>
+2 -2
View File
@@ -67,14 +67,14 @@
</div>
</div>
<div class=" control-group" id="add">
<label for="txtBatch" class="control-label">Add</label>
<label for="txtBatch" class="control-label">Product</label>
<div class="controls">
<autobatch id="txtBatch" url="/Services/Batches" selname="name"
batch="batch" ng-model="name"></autobatch>
<input type="text" id="txtQuantity" class="span2" autocomplete="off"
placeholder="Quantity" ng-model="quantity"/>
<button class="btn btn-success" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
<button class="btn btn-info" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
</button>
</div>
</div>
+10 -10
View File
@@ -15,7 +15,7 @@
</div>
</div>
<div class=" control-group" id="add">
<label for="ddlDebitCredit" class="control-label">Add</label>
<label for="ddlDebitCredit" class="control-label">Account</label>
<div class="controls">
<select id="ddlDebitCredit" ng-model="debit">
@@ -28,7 +28,7 @@
<span class="add-on">₹</span><input type="text" id="txtAmount" class="span2" autocomplete="off"
placeholder="Amount" ng-model="amount"/>
</div>
<button class="btn" ng-click="addJournal()">Add</button>
<button class="btn btn-info" ng-click="addJournal()">Add <i class="icon-plus-sign icon-white"></i></button>
</div>
</div>
<div class=" control-group">
@@ -38,18 +38,18 @@
<table id="gvGrid" class="table clean-table">
<thead>
<tr>
<th class="Debit">Debit</th>
<th class="Name">Name</th>
<th class="Amount">Amount</th>
<th class="Delete">Delete</th>
<th>Debit</th>
<th>Name</th>
<th>Amount</th>
<th>Delete</th>
</tr>
</thead>
<tbody id="tbodyMain">
<tr ng-repeat="journal in voucher.Journals">
<td class="Debit">{{journal.Debit | debit}}</td>
<td class="Name">{{journal.Ledger.Name}}</td>
<td data-column="Amount" class="Amount Editable">{{journal.Amount}}</td>
<td class="Delete">
<td>{{journal.Debit | debit}}</td>
<td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td>
<td>
<div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i
class="icon-trash icon-white"></i> Delete</a>
@@ -0,0 +1,23 @@
<form method="post" autocomplete="off">
<div class="modal-header">
<h3 id="myModalLabel">Edit Payment</h3>
</div>
<div class="modal-body">
<div class=" control-group">
<label for="editAccount">Account</label>
<autocomplete id="editAccount" url="/Services/Accounts" selname="edit.Ledger.Name"
selid="edit.Ledger.LedgerID"></autocomplete>
<label for="editAmount">Amount</label>
<div class="input-prepend input-append">
<span class="add-on">₹</span><input type="text" id="editAmount" class="span2" autocomplete="off"
placeholder="Amount" ng-model="edit.Amount"/>
</div>
</div>
<hr>
</div>
<div class="modal-footer">
<button id="cancel" class="btn">Cancel</button>
<button id="action" class="btn btn-primary">Update</button>
</div>
</form>
+15 -6
View File
@@ -27,18 +27,17 @@
</div>
</div>
<div class=" control-group" id="add">
<label for="txtLedger" class="control-label">Add</label>
<label for="txtLedger" class="control-label">Account</label>
<div class="controls">
<autocomplete id="txtLedger" url="/Services/Accounts" selname="name"
selid="id" ng-model="name"></autocomplete>
<autocomplete id="txtLedger" url="/Services/Accounts" selname="ledger.Name"
selid="ledger.LedgerID" ng-model="name"></autocomplete>
<div class=" input-prepend">
<span class="add-on">₹</span>
<input type="text" id="txtAmount" class="span2" autocomplete="off"
placeholder="Amount" ng-model="amount"/>
</div>
<button class="btn btn-success" ng-click="addJournal()">Add <i class="icon-plus-sign icon-white"></i>
</button>
<button class="btn btn-info" ng-click="addJournal()">Add <i class="icon-plus-sign icon-white"></i></button>
</div>
</div>
@@ -59,7 +58,17 @@
<td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td>
<td>
<button class="btn" ng-click="removeJournal(journal)">Delete</button>
<div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i
class="icon-trash icon-white"></i> Delete</a>
<a class="btn btn-danger dropdown-toggle" data-toggle="dropdown" href="#"><span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a ng-confirm url="/partial/payment-modal.html" before="toggleEdit(journal)"
on-action="toggleEdit(journal, true)" on-cancel="toggleEdit(journal, false)"><i
class="icon-pencil"></i> Edit</a></li>
</ul>
</div>
</td>
</tr>
</tbody>
@@ -0,0 +1,104 @@
<form method="post" autocomplete="off" class="form-horizontal">
<legend>Purchase Return Edit / New</legend>
<div class="control-group">
<label for="txtCode" class="control-label">Code</label>
<div class="controls">
<input type="text" id="txtCode" class="non-search-box" disabled="disabled" ng-model="voucher.Code"/>
</div>
</div>
<div class="control-group">
<label for="txtDate" class="control-label">Date</label>
<div class="controls">
<datepicker id="txtDate" model="voucher" prop="Date" ng-model="voucher.Date"></datepicker>
</div>
</div>
<div class="control-group" ng-repeat="journal in voucher.Journals | journalDebit:1">
<label for="txtLedger" class="control-label">Ledger</label>
<div class="controls">
<autocomplete id="txtLedger" url="/Services/Accounts"
selname="journal.Ledger.Name" selid="journal.Ledger.LedgerID"></autocomplete>
<div class="input-prepend">
<span class="add-on">₹</span><input type="text" id="txtLedgerAmount" class="span2"
autocomplete="off" readonly="readonly"
placeholder="Amount" ng-model="journal.Amount"/>
</div>
</div>
</div>
<div class=" control-group" id="add">
<label for="txtBatch" class="control-label">Product</label>
<div class="controls">
<autobatch id="txtBatch" url="/Services/Batches" selname="name"
batch="batch" ng-model="name"></autobatch>
<input type="text" id="txtQuantity" class="span2" autocomplete="off"
placeholder="Quantity" ng-model="quantity"/>
<button class="btn btn-info" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
</button>
</div>
</div>
<div class="control-group">
<label for="gvGrid" class="control-label"></label>
<div class="controls">
<table id="gvGrid" class="table clean-table">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Rate</th>
<th>Tax</th>
<th>Discount</th>
<th>Amount</th>
<th>Delete</th>
</tr>
</thead>
<tbody id="tbodyMain">
<tr ng-repeat="inventory in voucher.Inventories">
<td>{{inventory.Product.Name}}</td>
<td>{{inventory.Quantity}}</td>
<td>{{inventory.Rate}}</td>
<td>{{inventory.Tax}}</td>
<td>{{inventory.Discount}}</td>
<td>{{inventory.Amount}}</td>
<td>
<button class="btn" ng-click="removeInventory(inventory)">Delete</button>
</td>
</tr>
</tbody>
<tfoot id="tfootMain">
</tfoot>
</table>
</div>
</div>
<div class="control-group">
<label for="txtNarration" class="control-label">Narration</label>
<div class="controls">
<textarea rows="2" cols="20" id="txtNarration"
class="non-search-box" ng-model="voucher.Narration"></textarea>
</div>
</div>
<div class="form-actions">
<button class="btn btn-primary" ng-click="save()"
ng-disabled="preventAlteration(voucher)">{{voucher.Code | save_button}}
</button>
<button class="btn btn-inverse" ng-click="post()" ng-hide="voucher.Code == '(Auto)'"
ng-disabled="voucher.Posted || !perms['Post Vouchers']">{{voucher.Posted | posted}}
</button>
<button class="btn btn-danger" ng-hide="voucher.Code == '(Auto)'" ng-disabled="preventAlteration(voucher)"
ng-confirm title="Delete Voucher" action-text="Are you sure? This cannot be undone."
action-button-text="Delete" action-function="delete()"> Delete
</button>
</div>
<div class="row-fluid">
Created on {{voucher.CreationDate}} and Last Edited on {{voucher.LastEditDate}} by {{voucher.User.Name}}.
Posted
by {{voucher.Poster}}
</div>
</form>
+1 -1
View File
@@ -44,7 +44,7 @@
placeholder="Tax" ng-model="tax"/>
<input type="text" id="txtDiscount" autocomplete="off" class="non-search-box inline"
placeholder="Discount" ng-model="discount"/>
<button class="btn btn-success" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
<button class="btn btn-info" ng-click="addInventory()">Add <i class="icon-plus-sign icon-white"></i>
</button>
</div>
</div>
@@ -0,0 +1,23 @@
<form method="post" autocomplete="off">
<div class="modal-header">
<h3 id="myModalLabel">Edit Receipt</h3>
</div>
<div class="modal-body">
<div class=" control-group">
<label for="editAccount">Account</label>
<autocomplete id="editAccount" url="/Services/Accounts" selname="edit.Ledger.Name"
selid="edit.Ledger.LedgerID"></autocomplete>
<label for="editAmount">Amount</label>
<div class="input-prepend input-append">
<span class="add-on">₹</span><input type="text" id="editAmount" class="span2" autocomplete="off"
placeholder="Amount" ng-model="edit.Amount"/>
</div>
</div>
<hr>
</div>
<div class="modal-footer">
<button id="cancel" class="btn">Cancel</button>
<button id="action" class="btn btn-primary">Update</button>
</div>
</form>
+13 -3
View File
@@ -27,7 +27,7 @@
</div>
</div>
<div class=" control-group" id="add">
<label for="txtLedger" class="control-label">Add</label>
<label for="txtLedger" class="control-label">Account</label>
<div class="controls">
<autocomplete id="txtLedger" url="/Services/Accounts" selname="name"
@@ -37,7 +37,7 @@
<input type="text" id="txtAmount" class="span2" autocomplete="off"
placeholder="Amount" ng-model="amount"/>
</div>
<button class="btn btn-success" ng-click="addJournal()">Add <i class="icon-plus-sign icon-white"></i>
<button class="btn btn-info" ng-click="addJournal()">Add <i class="icon-plus-sign icon-white"></i>
</button>
</div>
</div>
@@ -59,7 +59,17 @@
<td>{{journal.Ledger.Name}}</td>
<td>{{journal.Amount}}</td>
<td>
<button class="btn" ng-click="removeJournal(journal)">Delete</button>
<div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i
class="icon-trash icon-white"></i> Delete</a>
<a class="btn btn-danger dropdown-toggle" data-toggle="dropdown" href="#"><span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a ng-confirm url="/partial/receipt-modal.html" before="toggleEdit(journal)"
on-action="toggleEdit(journal, true)" on-cancel="toggleEdit(journal, false)"><i
class="icon-pencil"></i> Edit</a></li>
</ul>
</div>
</td>
</tr>
</tbody>
+6 -4
View File
@@ -1,4 +1,6 @@
function AccountListCtrl($scope, accounts) {
'use strict';
function AccountListCtrl($scope, accounts) {
$scope.info = accounts;
}
AccountListCtrl.resolve = {
@@ -12,10 +14,10 @@ AccountListCtrl.resolve = {
Account.query({}, successCb);
return deferred.promise;
}
}
};
function AccountCtrl($scope, $location, account, account_types, cost_centers) {
$scope.account = account
$scope.account = account;
$scope.account_types = account_types;
$scope.cost_centers = cost_centers;
@@ -73,4 +75,4 @@ AccountCtrl.resolve = {
CostCenter.query({}, successCb);
return deferred.promise;
}
}
};
+46 -11
View File
@@ -1,6 +1,8 @@
'use strict';
var overlord_directive = angular.module('overlord.directive', []);
overlord_directive.directive('autocomplete', function () {
var directiveDefinitionObject = {
return {
restrict:'E',
replace:true,
transclude:true,
@@ -41,11 +43,10 @@ overlord_directive.directive('autocomplete', function () {
});
}
};
return directiveDefinitionObject;
});
overlord_directive.directive('autobatch', function () {
var directiveDefinitionObject = {
return {
restrict:'E',
replace:true,
transclude:true,
@@ -81,11 +82,10 @@ overlord_directive.directive('autobatch', function () {
});
}
};
return directiveDefinitionObject;
});
overlord_directive.directive('datepicker', function () {
var directiveDefinitionObject = {
return {
restrict:'E',
replace:true,
transclude:true,
@@ -102,17 +102,16 @@ overlord_directive.directive('datepicker', function () {
});
}
};
return directiveDefinitionObject;
});
overlord_directive.directive('fadey', function () {
var directiveDefinitionObject = {
return {
restrict:'A',
link:function (scope, element, attrs) {
var duration = 500;
element = jQuery(element);
element.hide();
element.fadeIn(duration)
element.fadeIn(duration);
scope.destroy = function (complete) {
element.fadeOut(duration, function () {
@@ -124,7 +123,6 @@ overlord_directive.directive('fadey', function () {
}
};
return directiveDefinitionObject;
});
overlord_directive.directive('ngConfirm', function (modal, $parse) {
@@ -197,7 +195,7 @@ overlord_directive.directive('ngConfirm', function (modal, $parse) {
overlord_directive.directive('journal-edit', function () {
var directiveDefinitionObject = {
return {
restrict:'A',
replace:true,
transclude:true,
@@ -210,5 +208,42 @@ overlord_directive.directive('journal-edit', function () {
});
}
};
return directiveDefinitionObject;
});
overlord_directive.directive('ngEditRepeat', function (modal, $parse) {
return {
restrict:'E',
template:'' +
'<div class="btn-group">' +
' <a class="btn btn-danger" ng-click="removeJournal(journal)"><i class="icon-trash icon-white"></i> Delete</a>' +
' <a class="btn btn-danger dropdown-toggle" data-toggle="dropdown" href="#"><span class="caret"></span></a>' +
' <ul class="dropdown-menu">' +
' <li><a ng-confirm url="/partial/journal-modal.html" before="toggleEdit(journal)" on-action="toggleEdit(journal, true)" on-cancel="toggleEdit(journal, false)"><i class="icon-pencil"></i> Edit</a></li>' +
' </ul>' +
'</div>',
link:function postLink(scope, element, attrs) {
// Could have custom or boostrap modal options here
var options = {};
if (typeof attrs.url !== 'undefined') {
element.bind("click", function () {
if (typeof attrs.before !== 'undefined') {
var fn = $parse(attrs.before);
scope.$apply(function () {
fn(scope);
});
}
modal.template(attrs.url, attrs.onAction, attrs.onCancel, scope, options);
});
} else {
element.bind("click", function () {
var actionButton = {text:attrs["actionButtonText"], click:attrs["actionFunction"], class:attrs['class']};
var cancelButton = {text:attrs["cancelButtonText"], click:attrs["cancelFunction"]};
modal.confirm(attrs["title"], attrs["actionText"], actionButton, cancelButton, scope, options);
});
}
}
};
});
+2 -1
View File
@@ -1,3 +1,5 @@
'use strict';
var overlord_filter = angular.module('overlord.filter', []);
overlord_filter.filter('debit', function () {
return function (input) {
@@ -8,7 +10,6 @@ overlord_filter.filter('debit', function () {
} else {
return '';
}
;
};
});
+2
View File
@@ -1,3 +1,5 @@
'use strict';
var overlord_service = angular.module('overlord.service', ['ngResource']);
// TODO: Replace hardcoded url with route_url
+4 -2
View File
@@ -1,4 +1,6 @@
function AttendanceCtrl($scope, $location, Attendance, attendance_types, info) {
'use strict';
function AttendanceCtrl($scope, $location, Attendance, attendance_types, info) {
$scope.attendance_types = attendance_types;
$scope.info = info;
$scope.show = function () {
@@ -36,4 +38,4 @@ AttendanceCtrl.resolve = {
AttendanceTypes.query({}, successCb);
return deferred.promise;
}
}
};
+4 -2
View File
@@ -1,4 +1,6 @@
function CashFlowCtrl($scope, $routeParams, $location, cash_flow) {
'use strict';
function CashFlowCtrl($scope, $routeParams, $location, cash_flow) {
$scope.info = cash_flow;
$scope.show = function () {
$location.path('/CashFlow').search({StartDate:$scope.info.StartDate, FinishDate:$scope.info.FinishDate});
@@ -26,4 +28,4 @@ CashFlowCtrl.resolve = {
}
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function ClosingStockCtrl($scope, $location, info) {
'use strict';
function ClosingStockCtrl($scope, $location, info) {
$scope.info = info;
$scope.show = function () {
$location.path('/ClosingStock/' + $scope.info.Date);
@@ -22,4 +24,4 @@ ClosingStockCtrl.resolve = {
}
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function CostCenterListCtrl($scope, cost_centers) {
'use strict';
function CostCenterListCtrl($scope, cost_centers) {
$scope.info = cost_centers;
}
@@ -13,7 +15,7 @@ CostCenterListCtrl.resolve = {
CostCenter.query({}, successCb);
return deferred.promise;
}
}
};
function CostCenterCtrl($scope, $routeParams, $location, cost_center) {
$scope.cost_center = cost_center;
@@ -51,4 +53,4 @@ CostCenterCtrl.resolve = {
CostCenter.get({id:id}, successCb);
return deferred.promise;
}
}
};
+4 -2
View File
@@ -1,4 +1,6 @@
function DaybookCtrl($scope, $location, info) {
'use strict';
function DaybookCtrl($scope, $location, info) {
$scope.info = info;
$scope.show = function () {
$location.path('/Daybook').search({StartDate:$scope.info.StartDate, FinishDate:$scope.info.FinishDate});
@@ -23,4 +25,4 @@ DaybookCtrl.resolve = {
}
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
overlord_service.factory('modal', function ($http, $compile) {
'use strict';
overlord_service.factory('delete-button', function ($http, $compile) {
var modal = {};
modal.get = function (create) {
@@ -7,12 +9,12 @@ overlord_service.factory('modal', function ($http, $compile) {
modal.dialog.appendTo('BODY');
}
return modal.dialog;
}
};
modal.compileAndRun = function (dialog, scope, options) {
$compile(dialog)(scope);
dialog.modal(options);
}
};
modal.alert = function (title, text, button, scope, options) {
text = (text) ? text : "Alert";
@@ -35,7 +37,7 @@ overlord_service.factory('modal', function ($http, $compile) {
modal.close();
});
modal.compileAndRun(dialog, scope, options);
}
};
modal.confirm = function (title, actionText, actionButton, cancelButton, scope, options) {
actionText = (actionText) ? actionText : "Are you sure?";
@@ -68,14 +70,14 @@ overlord_service.factory('modal', function ($http, $compile) {
});
modal.compileAndRun(dialog, scope, options);
}
};
modal.close = function () {
var dialog = modal.get()
var dialog = modal.get();
if (dialog) {
dialog.modal('hide');
}
}
};
return modal;
@@ -1,4 +1,6 @@
function EmployeeAttendanceCtrl($scope, $location, EmployeeAttendance, attendance_types, info) {
'use strict';
function EmployeeAttendanceCtrl($scope, $location, EmployeeAttendance, attendance_types, info) {
$scope.attendance_types = attendance_types;
$scope.info = info;
$scope.show = function () {
@@ -39,4 +41,4 @@ EmployeeAttendanceCtrl.resolve = {
AttendanceTypes.query({}, successCb);
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function EmployeeFunctionsCtrl($scope) {
'use strict';
function EmployeeFunctionsCtrl($scope) {
$scope.creditSalary = function () {
$scope.toasts.push({Type:'Error', Message:'Not Implemented Yet'});
};
+6 -4
View File
@@ -1,4 +1,6 @@
function EmployeeListCtrl($scope, employees) {
'use strict';
function EmployeeListCtrl($scope, employees) {
$scope.info = employees;
}
EmployeeListCtrl.resolve = {
@@ -12,12 +14,12 @@ EmployeeListCtrl.resolve = {
Employee.query({}, successCb);
return deferred.promise;
}
}
};
function EmployeeCtrl($scope, $routeParams, $location, employee, cost_centers) {
$scope.employee = employee;
$scope.cost_centers = cost_centers
$scope.cost_centers = cost_centers;
$scope.save = function () {
$scope.employee.$save(function (u, putResponseHeaders) {
@@ -62,4 +64,4 @@ EmployeeCtrl.resolve = {
CostCenter.query({}, successCb);
return deferred.promise;
}
}
};
+5 -3
View File
@@ -1,4 +1,6 @@
function GroupListCtrl($scope, groups) {
'use strict';
function GroupListCtrl($scope, groups) {
$scope.info = groups;
}
@@ -13,7 +15,7 @@ GroupListCtrl.resolve = {
Group.query({}, successCb);
return deferred.promise;
}
}
};
function GroupCtrl($scope, $location, group) {
$scope.group = group;
@@ -51,4 +53,4 @@ GroupCtrl.resolve = {
Group.get({id:id}, successCb);
return deferred.promise;
}
}
};
+7 -4
View File
@@ -1,4 +1,6 @@
function IssueCtrl($scope, $routeParams, $location, voucher, cost_centers, issue_grid, IssueGrid, Voucher) {
'use strict';
function IssueCtrl($scope, $routeParams, $location, voucher, cost_centers, issue_grid, IssueGrid, Voucher) {
$scope.voucher = voucher;
$scope.cost_centers = cost_centers;
$scope.smallGrid = issue_grid;
@@ -32,8 +34,8 @@
delete $scope.name;
delete $scope.quantity;
$('#txtBatch').val('');
}
$('#txtBatch').focus();
}
};
$scope.removeInventory = function (inventory) {
var index = this.voucher.Inventories.indexOf(inventory);
@@ -79,7 +81,7 @@
if (typeof newInventories === 'undefined' || typeof oldInventories === 'undefined') {
return;
}
var amount = 0
var amount = 0;
for (var i = 0, l = newInventories.length; i < l; i++) {
amount += newInventories[i].Amount;
}
@@ -200,4 +202,5 @@ IssueCtrl.resolve = {
CostCenter.query({}, successCb);
return deferred.promise;
}}
}
};
+5 -4
View File
@@ -1,4 +1,6 @@
function JournalCtrl($scope, $location, voucher) {
'use strict';
function JournalCtrl($scope, $location, voucher) {
$scope.voucher = voucher;
$scope.name = '';
$scope.debit = 1;
@@ -97,7 +99,7 @@
$scope.toggleDebit = function () {
$("#editDebit").button('toggle');
$scope.edit.Debit = ($scope.edit.Debit === 1) ? -1 : 1;
}
};
$scope.toggleEdit = function (journal, update) {
if (typeof update === 'undefined') {
$scope.edit = {};
@@ -137,5 +139,4 @@ JournalCtrl.resolve = {
}
return deferred.promise;
}
}
};
+4 -2
View File
@@ -1,4 +1,6 @@
function LedgerCtrl($scope, $routeParams, $location, ledger) {
'use strict';
function LedgerCtrl($scope, $routeParams, $location, ledger) {
$scope.info = ledger;
$scope.show = function () {
$location.path('/Ledger/' + $scope.info.Ledger.LedgerID).search('StartDate', $scope.info.StartDate).search('FinishDate', $scope.info.FinishDate);
@@ -25,6 +27,6 @@ LedgerCtrl.resolve = {
}
return deferred.promise;
}
}
};
+4 -2
View File
@@ -1,4 +1,6 @@
function LoginCtrl($scope, $http, $location, $route, $routeParams) {
'use strict';
function LoginCtrl($scope, $http, $location, $route, $routeParams) {
$scope.submit = function () {
$http.
post('/login', {username:$scope.username, password:$scope.password}).
@@ -12,7 +14,7 @@
error(function (errorMessage) {
$scope.toasts.push({Type:'Error', Message:errorMessage});
});
}
};
$('#username').focus();
}
@@ -1,3 +1,5 @@
'use strict';
overlord_service.factory('modal', function ($http, $compile) {
var modal = {};
@@ -7,12 +9,12 @@ overlord_service.factory('modal', function ($http, $compile) {
modal.dialog.appendTo('BODY');
}
return modal.dialog;
}
};
modal.compileAndRun = function (dialog, scope, options) {
$compile(dialog)(scope);
dialog.modal(options);
}
};
modal.alert = function (title, text, button, scope, options) {
text = (text) ? text : "Alert";
@@ -35,7 +37,7 @@ overlord_service.factory('modal', function ($http, $compile) {
modal.close();
});
modal.compileAndRun(dialog, scope, options);
}
};
modal.confirm = function (title, actionText, actionButton, cancelButton, scope, options) {
actionText = (actionText) ? actionText : "Are you sure?";
@@ -68,7 +70,7 @@ overlord_service.factory('modal', function ($http, $compile) {
});
modal.compileAndRun(dialog, scope, options);
}
};
modal.template = function (url, onSuccess, onCancel, scope, options) {
$http.get(url).success(function (data) {
@@ -85,20 +87,20 @@ overlord_service.factory('modal', function ($http, $compile) {
if (onCancel) {
scope.$eval(onCancel);
}
})
});
dialog.find("#cancel").click(function () {
modal.close();
});
modal.compileAndRun(dialog, scope, options);
});
}
};
modal.close = function () {
var dialog = modal.get()
var dialog = modal.get();
if (dialog) {
dialog.modal('hide');
}
}
};
return modal;
+8 -2
View File
@@ -19,6 +19,9 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
when('/Purchase', {templateUrl:'/partial/purchase.html', controller:PurchaseCtrl, resolve:PurchaseCtrl.resolve}).
when('/Purchase/:id', {templateUrl:'/partial/purchase.html', controller:PurchaseCtrl, resolve:PurchaseCtrl.resolve}).
when('/Return', {templateUrl:'/partial/purchase-return.html', controller:PurchaseReturnCtrl, resolve:PurchaseReturnCtrl.resolve}).
when('/Return/:id', {templateUrl:'/partial/purchase-return.html', controller:PurchaseReturnCtrl, resolve:PurchaseReturnCtrl.resolve}).
when('/Issue', {templateUrl:'/partial/issue.html', controller:IssueCtrl, resolve:IssueCtrl.resolve}).
when('/Issue/:id', {templateUrl:'/partial/issue.html', controller:IssueCtrl, resolve:IssueCtrl.resolve}).
@@ -123,13 +126,16 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
};
}]);
function BaseCtrl($rootScope, $scope, Auth, $location) {
function BaseCtrl($rootScope, $scope, Auth, $location, $routeParams) {
$rootScope.spinner = {http:0, route:false};
$rootScope.$on('event:loginRequired', function () {
if ($rootScope.auth.isAuthenticated) {
$location.path('/');
} else {
var came_from = $location.path();
var came_from = $routeParams.came_from;
if (typeof came_from === 'undefined' && $location.path() === '/login') {
came_from = $location.path();
}
$location.path('/login').search({came_from:came_from});
}
});
+45 -18
View File
@@ -1,27 +1,33 @@
function PaymentCtrl($scope, $location, voucher, ledgers) {
$scope.voucher = voucher
'use strict';
function PaymentCtrl($scope, $location, voucher, ledgers) {
$scope.voucher = voucher;
$scope.ledgers = ledgers;
function getOldJournal(ledgerID, journals) {
for (var i = 0, l = journals.length; i < l; i++) {
if (journals[i].Ledger.LedgerID === ledgerID) {
return journals[i];
}
}
}
$scope.addJournal = function () {
for (var i = 0, l = this.voucher.Journals.length; i < l; i++) {
if (this.voucher.Journals[i].Ledger.LedgerID === $scope.id) {
var amount = (this.voucher.Journals[i].Debit * this.voucher.Journals[i].Amount) + (parseInt($scope.debit) * Number($scope.amount));
var oldJournal = getOldJournal($scope.ledger.LedgerID, this.voucher.Journals);
if (typeof oldJournal !== 'undefined') {
var amount = (oldJournal.Debit * oldJournal.Amount) + (parseInt($scope.debit) * Number($scope.amount));
if (amount < 0) {
this.voucher.Journals[i].Debit = -1;
this.voucher.Journals[i].Amount = amount * -1;
oldJournal.Debit = -1;
oldJournal.Amount = amount * -1;
} else {
this.voucher.Journals[i].Debit = 1;
this.voucher.Journals[i].Amount = amount;
oldJournal.Debit = 1;
oldJournal.Amount = amount;
}
break;
}
}
if (i >= l) {
this.voucher.Journals.push({Debit:1, Amount:Number($scope.amount), Ledger:{LedgerID:$scope.id, Name:$scope.name}});
} else {
this.voucher.Journals.push({Debit:1, Amount:Number($scope.amount), Ledger:$scope.ledger});
}
delete $scope.ledger;
delete $scope.amount;
delete $scope.id;
delete $scope.name;
$('#txtLedger').focus();
};
@@ -93,6 +99,27 @@
$scope.toasts.push({Type:'Error', Message:data.data});
});
};
$scope.toggleEdit = function (journal, update) {
if (typeof update === 'undefined') {
$scope.edit = {};
angular.copy(journal, $scope.edit);
} else {
if (update === true && typeof $scope.edit !== 'undefined') {
if (journal.Ledger.LedgerID !== $scope.edit.Ledger.LedgerID) {
var oldJournal = getOldJournal($scope.edit.Ledger.LedgerID, $scope.voucher.Journals);
if (typeof oldJournal !== 'undefined') {
return false;
}
}
angular.copy($scope.edit, journal);
$scope.$apply();
return true;
} else if (update === false) {
delete $scope.edit;
}
}
}
}
PaymentCtrl.resolve = {
@@ -117,9 +144,9 @@ PaymentCtrl.resolve = {
var successCb = function (result) {
deferred.resolve(result);
}
};
LedgerService.query({type:1}, successCb);
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function ProductGroupListCtrl($scope, product_groups) {
'use strict';
function ProductGroupListCtrl($scope, product_groups) {
$scope.info = product_groups
}
@@ -13,7 +15,7 @@ ProductGroupListCtrl.resolve = {
ProductGroup.query({}, successCb);
return deferred.promise;
}
}
};
function ProductGroupCtrl($scope, $location, product_group) {
$scope.product_group = product_group;
@@ -51,4 +53,4 @@ ProductGroupCtrl.resolve = {
ProductGroup.get({id:id}, successCb);
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function ProductLedgerCtrl($scope, $routeParams, $location, product_ledger) {
'use strict';
function ProductLedgerCtrl($scope, $routeParams, $location, product_ledger) {
$scope.info = product_ledger;
$scope.show = function () {
$location.path('/ProductLedger/' + $scope.info.Product.ProductID).search('StartDate', $scope.info.StartDate).search('FinishDate', $scope.info.FinishDate);
@@ -24,4 +26,4 @@ ProductLedgerCtrl.resolve = {
}
return deferred.promise;
}
}
};
+6 -4
View File
@@ -1,4 +1,6 @@
function ProductListCtrl($scope, products) {
'use strict';
function ProductListCtrl($scope, products) {
$scope.info = products;
}
@@ -13,10 +15,10 @@ ProductListCtrl.resolve = {
Product.query({}, successCb);
return deferred.promise;
}
}
};
function ProductCtrl($scope, $location, product, product_groups) {
$scope.product = product
$scope.product = product;
$scope.product_groups = product_groups;
$scope.save = function () {
@@ -62,4 +64,4 @@ ProductCtrl.resolve = {
ProductGroup.query({}, successCb);
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function ProfitLossCtrl($scope, $location, profit_loss) {
'use strict';
function ProfitLossCtrl($scope, $location, profit_loss) {
$scope.info = profit_loss;
$scope.show = function () {
$location.path('/ProfitLoss').search({StartDate:$scope.info.StartDate, FinishDate:$scope.info.FinishDate});
@@ -24,4 +26,4 @@ ProfitLossCtrl.resolve = {
}
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function PurchaseEntriesCtrl($scope, $location, purchase_entries) {
'use strict';
function PurchaseEntriesCtrl($scope, $location, purchase_entries) {
$scope.info = purchase_entries;
$scope.show = function () {
@@ -25,6 +27,6 @@ PurchaseEntriesCtrl.resolve = {
}
return deferred.promise;
}
}
};
@@ -0,0 +1,120 @@
'use strict';
function PurchaseReturnCtrl($scope, $location, voucher) {
$scope.voucher = voucher;
$scope.rate = 0;
$scope.addInventory = function () {
for (var i = 0, l = this.voucher.Inventories.length; i < l; i++) {
if (this.voucher.Inventories[i].Product.ProductID === $scope.batch.Product.ProductID) {
break;
}
}
if (i >= l && Number($scope.quantity) <= $scope.batch.QuantityRemaining) {
var amount = Number($scope.quantity) * $scope.batch.Rate * (1 + $scope.batch.Tax) * (1 - $scope.batch.Discount);
this.voucher.Inventories.push(
{
Product:$scope.batch.Product,
Quantity:Number($scope.quantity),
Rate:Number($scope.batch.Rate),
Tax:Number($scope.batch.Tax),
Discount:Number($scope.batch.Discount),
Amount:amount,
Batch:$scope.batch
});
delete $scope.batch;
delete $scope.name;
delete $scope.quantity;
$('#txtBatch').val('');
$('#txtBatch').focus();
}
};
$scope.removeInventory = function (inventory) {
var index = this.voucher.Inventories.indexOf(inventory);
this.voucher.Inventories.splice(index, 1);
};
$scope.$watch('voucher.Inventories', function (inventories, oldValue) {
var amount = 0;
if (typeof inventories !== 'undefined') {
for (var i = 0, l = inventories.length; i < l; i++) {
amount += Number(inventories[i].Amount);
}
}
if (typeof $scope.voucher.Journals !== 'undefined') {
for (var i = 0, l = $scope.voucher.Journals.length; i < l; i++) {
if ($scope.voucher.Journals[i].Debit === 1) {
$scope.voucher.Journals[i].Amount = amount;
break;
}
}
}
}, true);
$scope.preventAlteration = function (voucher) {
if (typeof $scope.perms === 'undefined') {
return false;
} else if (typeof voucher.VoucherID === 'undefined') {
return !$scope.perms['Purchase Return'];
} else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) {
return true;
} else if (voucher.User.UserID != $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) {
return true;
} else {
return false;
}
};
$scope.get = function (voucherid) {
$scope.voucher = Voucher.get({VoucherID:voucherid}, function (u, putResponseHeaders) {
$scope.toasts.push({Type:'Success', Message:u.Code});
}, function (data, status) {
$scope.toasts.push({Type:'Error', Message:data.data});
});
};
$scope.save = function () {
$scope.voucher.$save({type:'Purchase Return'}, function (u, putResponseHeaders) {
$scope.toasts.push({Type:'Success', Message:u.Code});
$location.path('/Return/' + u.VoucherID);
}, function (data, status) {
$scope.toasts.push({Type:'Error', Message:data.data});
});
};
$scope.delete = function () {
$scope.voucher.$delete(function (u, putResponseHeaders) {
$scope.toasts.push({Type:'Success', Message:''});
$location.path('/Return').replace();
}, function (data, status) {
$scope.toasts.push({Type:'Error', Message:data.data});
});
};
$scope.post = function () {
$scope.voucher.$post(function (u, putResponseHeaders) {
$scope.toasts.push({Type:'Success', Message:u.code});
}, function (data, status) {
$scope.toasts.push({Type:'Error', Message:data.data});
});
};
}
PurchaseReturnCtrl.resolve = {
voucher:function ($q, $route, Voucher) {
var deferred = $q.defer();
var id = $route.current.params.id;
var successCb = function (result) {
deferred.resolve(result);
};
if (typeof id === 'undefined') {
Voucher.get({type:'Purchase Return'}, successCb);
} else {
Voucher.get({id:id}, successCb);
}
return deferred.promise;
}
};
+5 -7
View File
@@ -1,5 +1,7 @@
function PurchaseCtrl($scope, $location, voucher) {
$scope.voucher = voucher
'use strict';
function PurchaseCtrl($scope, $location, voucher) {
$scope.voucher = voucher;
$scope.rate = 0;
$scope.addInventory = function () {
@@ -37,10 +39,6 @@
this.voucher.Inventories.splice(index, 1);
};
$scope.ledgerName = function (journal) {
return journal.Ledger.Name;
};
$scope.$watch('voucher.Inventories', function (inventories, oldValue) {
var amount = 0;
if (typeof inventories !== 'undefined') {
@@ -124,4 +122,4 @@ PurchaseCtrl.resolve = {
}
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function RawMaterialCostCtrl($scope, $routeParams, $location, raw_material_cost) {
'use strict';
function RawMaterialCostCtrl($scope, $routeParams, $location, raw_material_cost) {
$scope.info = raw_material_cost;
$scope.show = function () {
$location.path('/RawMaterialCost').search({StartDate:$scope.info.StartDate, FinishDate:$scope.info.FinishDate});
@@ -26,4 +28,4 @@ RawMaterialCostCtrl.resolve = {
}
return deferred.promise;
}
}
};
+45 -18
View File
@@ -1,27 +1,33 @@
function ReceiptCtrl($scope, $routeParams, $location, voucher, ledgers, Voucher) {
$scope.voucher = voucher
'use strict';
function ReceiptCtrl($scope, $routeParams, $location, voucher, ledgers, Voucher) {
$scope.voucher = voucher;
$scope.ledgers = ledgers;
function getOldJournal(ledgerID, journals) {
for (var i = 0, l = journals.length; i < l; i++) {
if (journals[i].Ledger.LedgerID === ledgerID) {
return journals[i];
}
}
}
$scope.addJournal = function () {
for (var i = 0, l = this.voucher.Journals.length; i < l; i++) {
if (this.voucher.Journals[i].Ledger.LedgerID === $scope.id) {
var amount = (this.voucher.Journals[i].Debit * this.voucher.Journals[i].Amount) + (parseInt($scope.debit) * Number($scope.amount));
var oldJournal = getOldJournal($scope.ledger.LedgerID, this.voucher.Journals);
if (typeof oldJournal !== 'undefined') {
var amount = (oldJournal.Debit * oldJournal.Amount) + (parseInt($scope.debit) * Number($scope.amount));
if (amount < 0) {
this.voucher.Journals[i].Debit = -1;
this.voucher.Journals[i].Amount = amount * -1;
oldJournal.Debit = -1;
oldJournal.Amount = amount * -1;
} else {
this.voucher.Journals[i].Debit = 1;
this.voucher.Journals[i].Amount = amount;
oldJournal.Debit = 1;
oldJournal.Amount = amount;
}
break;
}
}
if (i >= l) {
this.voucher.Journals.push({Debit:-1, Amount:Number($scope.amount), Ledger:{LedgerID:$scope.id, Name:$scope.name}});
} else {
this.voucher.Journals.push({Debit:-1, Amount:Number($scope.amount), Ledger:$scope.ledger});
}
delete $scope.ledger;
delete $scope.amount;
delete $scope.id;
delete $scope.name;
$('#txtLedger').focus();
};
@@ -93,6 +99,27 @@
$scope.toasts.push({Type:'Error', Message:data.data});
});
};
$scope.toggleEdit = function (journal, update) {
if (typeof update === 'undefined') {
$scope.edit = {};
angular.copy(journal, $scope.edit);
} else {
if (update === true && typeof $scope.edit !== 'undefined') {
if (journal.Ledger.LedgerID !== $scope.edit.Ledger.LedgerID) {
var oldJournal = getOldJournal($scope.edit.Ledger.LedgerID, $scope.voucher.Journals);
if (typeof oldJournal !== 'undefined') {
return false;
}
}
angular.copy($scope.edit, journal);
$scope.$apply();
return true;
} else if (update === false) {
delete $scope.edit;
}
}
}
}
ReceiptCtrl.resolve = {
@@ -117,9 +144,9 @@ ReceiptCtrl.resolve = {
var successCb = function (result) {
deferred.resolve(result);
}
};
LedgerService.query({type:1}, successCb);
return deferred.promise;
}
}
};
@@ -1,4 +1,6 @@
function TrialBalanceCtrl($scope, $routeParams, $location, trial_balance) {
'use strict';
function TrialBalanceCtrl($scope, $routeParams, $location, trial_balance) {
$scope.info = trial_balance;
$scope.show = function () {
@@ -23,4 +25,4 @@ TrialBalanceCtrl.resolve = {
}
return deferred.promise;
}
}
};
+4 -2
View File
@@ -1,4 +1,6 @@
function UnpostedCtrl($scope, info) {
'use strict';
function UnpostedCtrl($scope, info) {
$scope.info = info;
}
UnpostedCtrl.resolve = {
@@ -12,4 +14,4 @@ UnpostedCtrl.resolve = {
Unposted.query({}, successCb);
return deferred.promise;
}
}
};
+5 -3
View File
@@ -1,4 +1,6 @@
function UserListCtrl($scope, users) {
'use strict';
function UserListCtrl($scope, users) {
$scope.info = users;
}
@@ -13,7 +15,7 @@ UserListCtrl.resolve = {
User.query({}, successCb);
return deferred.promise;
}
}
};
function UserCtrl($scope, $location, user) {
$scope.user = user;
@@ -51,4 +53,4 @@ UserCtrl.resolve = {
User.get({id:id}, successCb);
return deferred.promise;
}
}
};
+2 -1
View File
@@ -37,6 +37,7 @@
<script src="/script/payment.js"> </script>
<script src="/script/receipt.js"> </script>
<script src="/script/purchase.js"> </script>
<script src="/script/purchase-return.js"> </script>
<script src="/script/issue.js"> </script>
<script src="/script/employee-attendance.js"> </script>
@@ -90,7 +91,7 @@
<ul class="dropdown-menu">
<li><a href="/Journal">Journal</a></li>
<li><a href="/Purchase">Purchase</a></li>
<li><a href="/PurchaseReturn">Purchase Return</a></li>
<li><a href="/Return">Purchase Return</a></li>
<li><a href="/Payment">Payment</a></li>
<li><a href="/Receipt">Receipt</a></li>
<li><a href="/Issue">Issue</a></li>
+13 -8
View File
@@ -22,8 +22,9 @@ def save_update(request):
try:
id = request.matchdict.get('id', None)
if id is None:
item = Ledger(0, request.json_body['Name'], int(request.json_body['Type']), request.json_body['IsActive'],
uuid.UUID(request.json_body['CostCenter']['CostCenterID'])).create()
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'],
costcenter_id=uuid.UUID(request.json_body['CostCenter']['CostCenterID'])).create()
else:
new_type = int(request.json_body['Type'])
item = Ledger.by_id(uuid.UUID(id))
@@ -32,6 +33,7 @@ def save_update(request):
item.type = new_type
item.name = request.json_body['Name']
item.is_active = request.json_body['IsActive']
item.is_reconcilable = request.json_body['IsReconcilable']
item.costcenter_id = uuid.UUID(request.json_body['CostCenter']['CostCenterID'])
transaction.commit()
return account_info(item.id)
@@ -65,17 +67,20 @@ def show_blank(request):
return account_info(None)
@view_config(request_method='GET', route_name='account', renderer='json', request_param='list', xhr=True, permission='Authenticated')
@view_config(request_method='GET', route_name='account', renderer='json', request_param='list', xhr=True,
permission='Authenticated')
def show_list(request):
list = Ledger.list()
ledgers = []
for item in list:
ledgers.append({'Name': item.name, 'Type': item.type_object.name, 'IsActive': item.is_active,
'CostCenter': item.costcenter.name, 'Url': request.route_url('account_id', id=item.id)})
ledgers.append({'Name': item.name, 'Type': item.type_object.name, 'IsActive': 'Yes' if item.is_active else 'No',
'IsReconcilable': 'Yes' if item.is_reconcilable else '', 'CostCenter': item.costcenter.name,
'Url': request.route_url('account_id', id=item.id)})
return ledgers
@view_config(request_method='GET', route_name='account_type_list', renderer='json', xhr=True, permission='Authenticated')
@view_config(request_method='GET', route_name='account_type_list', renderer='json', xhr=True,
permission='Authenticated')
def account_type_list(request):
account_types = []
for item in LedgerType.list():
@@ -86,11 +91,11 @@ def account_type_list(request):
def account_info(id):
if id is None:
account = {'Code': '(Auto)', 'Type': LedgerType.by_name('Creditors').id, 'IsActive': True,
'CostCenter': CostCenter.overall()}
'IsReconcilable': False, 'CostCenter': CostCenter.overall()}
else:
account = Ledger.by_id(id)
account = {'LedgerID': account.id, 'Code': account.code, 'Name': account.name, 'Type': account.type,
'IsActive': account.is_active,
'IsActive': account.is_active, 'IsReconcilable':account.is_reconcilable,
'CostCenter': {'CostCenterID': account.costcenter_id, 'Name': account.costcenter.name}}
return account
+58 -5
View File
@@ -1,12 +1,12 @@
from datetime import date, timedelta
import uuid
from pyramid.httpexceptions import HTTPFound
from pyramid.response import Response
from pyramid.security import authenticated_userid, remember
from pyramid.view import view_config
import transaction
from brewman import groupfinder
from brewman.models.auth import Role, User
from brewman.models.auth import Role, User, Client
from brewman.views.transactions import session_current_date
@view_config(route_name='services_session_current_date', renderer='json', xhr=True, permission='Authenticated')
@@ -48,17 +48,70 @@ def user_permission(request):
@view_config(request_method='POST', route_name='login', renderer='json')
def login(request):
username = request.json_body['username']
password = request.json_body['password']
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
else:
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):
@@ -85,7 +85,8 @@ def delete(request):
item.product.name))
item.batch.quantity_remaining -= item.quantity
elif voucher.type == 'Purchase Return':
pass
for item in voucher.inventories:
item.batch.quantity_remaining += item.quantity
DBSession.delete(voucher)
transaction.commit()
return blank_voucher(additionalInfo=json_voucher)
@@ -142,6 +143,8 @@ def blank_voucher(type=None, date=None, additionalInfo=None):
json_voucher['Journals'].append({'Ledger': LedgerBase.cash_in_hand(), 'Amount': 0, 'Debit': 1})
elif type == 'Purchase':
json_voucher['Journals'].append({'Ledger': LedgerBase.local_purchase(), 'Amount': 0, 'Debit': -1})
elif type == 'Purchase Return':
json_voucher['Journals'].append({'Ledger': LedgerBase.local_purchase(), 'Amount': 0, 'Debit': 1})
elif type == 'Issue':
if additionalInfo is None:
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
@@ -30,6 +30,11 @@ class blank_voucher_view(object):
return self.get_blank()
@view_config(request_param='type=Purchase Return', permission='Purchase Return')
def purchase_return(self):
return self.get_blank()
@view_config(request_param='type=Issue', permission='Issue')
def issue(self):
voucher_type = self.request.GET.get('type', None)
@@ -123,7 +123,7 @@ def purchase_update_journals(voucher, journals):
journals = dict()
amount = 0
for item in voucher.inventories:
ledger = Product.by_id(item.product_id).purchase_ledger
ledger = Product.by_id(item.product_id).ledger
amount += item.amount
if ledger.id in journals:
journals[ledger.id].amount += item.amount
@@ -142,7 +142,7 @@ def purchase_update_journals(voucher, journals):
else:
DBSession.delete(item)
voucher.journals.remove(item)
for item in journals:
for item in journals.values():
DBSession.add(item)
voucher.journals.append(item)
@@ -0,0 +1,134 @@
import datetime
from decimal import Decimal
import uuid
from brewman.models import DBSession
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.voucher import Voucher, VoucherType, Batch, Inventory, Journal
__author__ = 'tanshu'
def purchase_return_create_voucher(json, user):
dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id,
type=VoucherType.by_name(json['Type']), posted=False)
create_basic(voucher)
for item in json['Inventories']:
purchase_return_create_inventory(voucher, item)
for item in purchase_return_create_journals(voucher.inventories, json['Journals'][0]['Ledger']['LedgerID']):
DBSession.add(item)
voucher.journals.append(item)
create_purchase_voucher(voucher)
DBSession.flush()
return voucher
def purchase_return_create_inventory(voucher, item):
batch = Batch.by_id(uuid.UUID(item['Batch']['BatchID']))
inventory_id = uuid.UUID(item['InventoryID']) if 'InventoryID' in item else None
quantity = Decimal(item['Quantity'])
if quantity <= 0:
raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name))
if quantity > batch.quantity_remaining:
raise ValidationError("Quantity available is {0} only".format(batch.quantity_remaining))
batch.quantity_remaining -= quantity
item = Inventory(id=inventory_id, product_id=batch.product.id, quantity=quantity, rate=batch.rate, tax=batch.tax,
discount=batch.discount, batch=batch)
DBSession.add(item)
voucher.inventories.append(item)
def purchase_return_create_journals(inventories, ledgerID):
otherLedger = LedgerBase.by_id(uuid.UUID(ledgerID))
journals = dict()
amount = 0
for item in inventories:
ledger = Product.by_id(item.product_id).ledger
amount += item.amount
if ledger.id in journals:
journals[ledger.id].amount += item.amount
else:
journals[ledger.id] = Journal(debit=-1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
amount=item.amount)
journals[otherLedger.id] = Journal(debit=1, cost_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
amount=amount)
return list(journals.values())
def purchase_return_update_voucher(voucher, json, user):
voucher.date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
voucher.narration = json['Narration']
voucher.user_id = user.id
voucher.posted = False
voucher.last_edit_date = datetime.datetime.now()
purchase_return_update_inventory(voucher, json['Inventories'], json['Date'])
purchase_return_update_journals(voucher, json['Journals'])
return voucher
def purchase_return_update_inventory(voucher, newInventories, date):
for it in range(len(voucher.inventories), 0, -1):
item = voucher.inventories[it - 1]
found = False
for j in range(len(newInventories), 0, -1):
i = newInventories[j - 1]
if 'InventoryID' in i and item.id == uuid.UUID(i['InventoryID']):
product = Product.by_id(uuid.UUID(i['Product']['ProductID']))
found = True
if item.product_id != product.id:
raise ValidationError('Product cannot be changed')
quantity = Decimal(i['Quantity'])
if quantity == 0:
raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name))
if quantity - item.quantity > item.batch.quantity_remaining:
raise ValidationError("Maximum quantity available is {0}".format(
item.quantity + item.batch.quantity_remaining))
item.batch.quantity_remaining -= (quantity - item.quantity)
item.quantity = quantity
newInventories.remove(i)
break
if not found:
item.batch.quantity_remaining += item.quantity
DBSession.delete(item)
voucher.inventories.remove(item)
for i in newInventories:
purchase_return_create_inventory(voucher, i)
def purchase_return_update_journals(voucher, journals):
otherLedger = [ff for ff in journals if ff['Debit'] == 1]
otherLedger = LedgerBase.by_id(uuid.UUID(otherLedger[0]['Ledger']['LedgerID']))
journals = dict()
amount = 0
for item in voucher.inventories:
ledger = Product.by_id(item.product_id).ledger
amount += item.amount
if ledger.id in journals:
journals[ledger.id].amount += item.amount
else:
journals[ledger.id] = Journal(debit=-1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
amount=item.amount)
journals[otherLedger.id] = Journal(debit=1, cost_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
amount=amount)
for i in range(len(voucher.journals), 0, -1):
item = voucher.journals[i - 1]
if item.ledger_id in journals:
item.debit = journals[item.ledger_id].debit
item.amount = journals[item.ledger_id].amount
item.cost_center_id = journals[item.ledger_id].cost_center_id
del journals[item.ledger_id]
else:
DBSession.delete(item)
voucher.journals.remove(item)
for item in journals.values():
DBSession.add(item)
voucher.journals.append(item)
@@ -7,6 +7,7 @@ from brewman.models.auth import User
from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import 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
__author__ = 'tanshu'
@@ -36,6 +37,11 @@ class save_voucher(object):
return self.save()
@view_config(request_param='type=Purchase Return', permission='Purchase Return')
def purchase_return(self):
return self.save()
@view_config(request_param='type=Issue', permission='Issue')
def issue(self):
return self.save()
@@ -49,6 +55,8 @@ class save_voucher(object):
voucher = journal_create_voucher(request.json_body, user)
elif request.json_body['Type'] in ['Purchase']:
voucher = purchase_create_voucher(request.json_body, user)
elif request.json_body['Type'] in ['Purchase Return']:
voucher = purchase_return_create_voucher(request.json_body, user)
elif request.json_body['Type'] in ['Issue']:
voucher = issue_create_voucher(request.json_body, user)
transaction.commit()
@@ -8,6 +8,7 @@ from brewman.models.auth import User
from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import 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
__author__ = 'tanshu'
@@ -53,6 +54,11 @@ class update_voucher(object):
return self.update()
@view_config(request_param='type=Purchase Return', permission='Purchase Return')
def purchase_return(self):
return self.update()
@view_config(request_param='type=Issue', permission='Issue')
def issue(self):
return self.update()
@@ -65,6 +71,8 @@ class update_voucher(object):
voucher = journal_update_voucher(self.voucher, self.json, self.user)
elif self.json['Type'] in ['Purchase']:
voucher = purchase_update_voucher(self.voucher, self.json, self.user)
elif self.json['Type'] in ['Purchase Return']:
voucher = purchase_return_update_voucher(self.voucher, self.json, self.user)
elif self.json['Type'] in ['Issue']:
voucher = issue_update_voucher(self.voucher, self.json, self.user)
transaction.commit()
@@ -1,6 +1,7 @@
from datetime import date
from pyramid.view import view_config
__author__ = 'tanshu'
@view_config(request_method='GET', route_name='journal_id', renderer='brewman:templates/angular_base.mako',
permission='Journal')
@@ -18,6 +19,10 @@ from pyramid.view import view_config
permission='Purchase')
@view_config(request_method='GET', route_name='purchase', renderer='brewman:templates/angular_base.mako',
permission='Purchase')
@view_config(request_method='GET', route_name='purchase_return_id', renderer='brewman:templates/angular_base.mako',
permission='Purchase Return')
@view_config(request_method='GET', route_name='purchase_return', renderer='brewman:templates/angular_base.mako',
permission='Purchase Return')
@view_config(request_method='GET', route_name='issue_id', renderer='brewman:templates/angular_base.mako',
permission='Issue')
@view_config(request_method='GET', route_name='issue', renderer='brewman:templates/angular_base.mako',
@@ -1,226 +0,0 @@
import datetime
import transaction
import uuid
from decimal import Decimal
from pyramid.response import Response
from pyramid.security import authenticated_userid
from pyramid.view import view_config
from brewman.models import DBSession
from brewman.models.auth import User
from brewman.models.master import Product, Ledger
from brewman.models.validation_exception import ValidationError
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory, Batch
@view_config(request_method='GET', route_name='purchase_return_id', renderer='brewman:templates/transaction/purchase_return.mako',
permission='Purchase Return Update')
@view_config(request_method='GET', route_name='purchase_return', renderer='brewman:templates/transaction/purchase_return.mako',
permission='Purchase Return Create')
def purchase_get(request):
id = request.matchdict.get('id', None)
if id is None:
currentDate = Literal(
"CurrentDate('#txtDate', '{0}');".format(request.route_url('services_session_current_date')))
voucher_id = ''
posted = ''
code = ''
narration = ''
body = ''
ledger = ''
else:
voucher = Voucher.by_id(uuid.UUID(id))
currentDate = Literal("$('#txtDate').val('{0}');".format(voucher.date.strftime('%d-%b-%Y')))
voucher_id = Literal("$('#VoucherID').val('{0}');".format(voucher.id))
posted = Literal("$('#Posted').val(true);") if voucher.posted else ''
code = Literal("$('#txtCode').val('{0}');".format(voucher.code))
narration = Literal("$('#txtNarration').val('{0}');".format(voucher.narration))
body = Literal(build_body(voucher))
for item in voucher.journals:
if item.debit == 1:
journal = item
break
ledger = Literal("$('#txtLedger').val('{0}');".format(journal.ledger.name))
return {'title': 'Purchase - Hops n Grains',
'pageclass': "page-blogpost page-sidebar-right",
'pagecontentclass': "page-content grid_12",
'page_header': '',
'id': id,
'currentDate': currentDate,
'voucher_id': voucher_id,
'posted': posted,
'code': code,
'narration': narration,
'body': body,
'ledger': ledger}
@view_config(request_method='POST', route_name='purchase_return_id', renderer='json', xhr=True, permission='Purchase Return Update')
@view_config(request_method='POST', route_name='purchase_return', renderer='json', xhr=True, permission='Purchase Return Create')
def purchase_post(request):
try:
id = request.matchdict.get('id', None)
user = User.get_by_id(uuid.UUID(authenticated_userid(request)))
if id == None:
voucher = create_voucher(request.json_body['voucher'], user)
else:
voucher = update_voucher(uuid.UUID(id), request.json_body['voucher'], user)
transaction.commit()
return "Voucher with Code {0} {1}".format(voucher.code, ('Created' if id is None else 'Updated' ))
except ValidationError as ex:
transaction.abort()
response = Response("Failed validation: {0}".format(ex.message))
response.status_int = 500
return response
def build_body(voucher):
body = ''
for item in voucher.inventories:
body += '<tr class="Inventory" id="{0}"><td class="InventoryID hide">{1}</td>'\
'<td class="ProductID hide">{0}</td><td class="Product">{2}</td><td class="Quantity">{3:.5f}</td>'\
'<td class="Rate">{4:.5f}</td><td class="Tax">{5:.5f}</td><td class="Discount">{6:.5f}</td>'\
'<td class="Amount">{7:.5f}</td><td class="BatchID hide">{8}</td><td class="Delete">'\
'<input type="submit" class="subtract" onClick="return DeleteRow(\'{0}\');" value="Delete"/></td></tr>'\
.format(str(item.product_id), str(item.id), item.product.full_name, item.quantity, item. rate, item.tax,
item.discount, item.amount, str(item.batch_id))
return body
def create_voucher(json, user):
dt = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
voucher = Voucher(date=dt, narration=json['Narration'], user_id=user.id,
type=VoucherType.by_name('Purchase Return'), posted=False)
for item in json['Inventories']:
voucher.inventories.append(create_inventory(item, json['Date']))
for item in create_journals(voucher.inventories, json['Journals'][0]['Ledger']['Name']):
voucher.journals.append(item)
voucher.create()
return voucher
def create_inventory(item, date):
product = Product.by_id(uuid.UUID(item['Product']['ProductID']))
inventory_id = uuid.UUID(item['InventoryID'])
if uuid.UUID('00000000-0000-0000-0000-000000000000') == inventory_id:
inventory_id = None
quantity = Decimal(item['Quantity'])
rate = Decimal(item['Rate'])
tax = Decimal(item['Tax'])
discount = Decimal(item['Discount'])
batch = Batch(name=date, product_id=product.id, quantity_remaining=quantity, rate=rate, tax=tax,
discount=discount)
return Inventory(id=inventory_id, product_id=product.id, batch=batch, quantity=quantity, rate=rate, tax=tax,
discount=discount)
def create_journals(inventories, ledgerString):
otherLedger = Ledger.by_name(ledgerString)
journals = dict()
amount = 0
for item in inventories:
ledger = Product.by_id(item.product_id).purchase_ledger
amount += item.amount
if ledger.id in journals:
journals[ledger.id].amount += item.amount
else:
journals[ledger.id] = Journal(debit=1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
amount=item.amount)
journals[otherLedger.id] = Journal(debit=-1, cost_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
amount=amount)
return list(journals.values())
def update_voucher(id, json, user):
voucher = Voucher.by_id(id)
voucher.date = datetime.datetime.strptime(json['Date'], '%d-%b-%Y')
voucher.narration = json['Narration']
voucher.user_id = user.id
voucher.posted = False
voucher.last_edit_date = datetime.datetime.now()
update_inventory(voucher, json['Inventories'], json['Date'])
update_journals(voucher, json['Journals'][0]['Ledger']['Name'])
return voucher
def update_inventory(voucher, newInventories, date):
for item in voucher.inventories:
found = False
for i in newInventories:
if item.id == uuid.UUID(i['InventoryID']):
product = Product.by_id(uuid.UUID(i['Product']['ProductID']))
found = True
if item.product_id != product.id:
raise ValidationError('Product cannot be changed')
quantity = Decimal(i['Quantity'])
if quantity == 0:
raise ValidationError("Quantity of {0} cannot be zero".format(item.product.name))
if item.quantity - quantity > 0 and item.batch.quantity_remaining < (item.quantity - quantity):
raise ValidationError("{0} has been issued, minimum quantity is".format(
item.quantity - item.batch.quantity_remaining))
item.batch.quantity_remaining -= (item.quantity - quantity)
item.quantity = quantity
rate = Decimal(i['Rate'])
discount = Decimal(i['Discount'])
tax = Decimal(i['Tax'])
item.rate = rate
item.batch.rate = rate
item.discount = discount
item.batch.discount = discount
item.tax = tax
item.batch.tax = tax
newInventories.remove(i)
break
if not found:
if item.quantity != item.batch.quantity_remaining:
raise ValidationError("{0} has been issued, it cannot be deleted".format(item.product.name))
else:
DBSession.delete(item.batch)
DBSession.delete(item)
voucher.inventories.remove(item)
for i in newInventories:
product = Product.by_id(uuid.UUID(i['Product']['ProductID']))
quantity = Decimal(i['Quantity'])
rate = Decimal(i['Rate'])
tax = Decimal(i['Tax'])
discount = Decimal(i['Discount'])
batch = Batch(name=date, product_id=product.id, quantity_remaining=quantity, rate=rate, tax=tax,
discount=discount)
inventory = Inventory(id=None, product_id=product.id, batch=batch, quantity=quantity, rate=rate, tax=tax,
discount=discount)
inventory.create(DBSession)
voucher.inventories.append(inventory)
def update_journals(voucher, ledgerString):
otherLedger = Ledger.by_name(ledgerString)
journals = dict()
amount = 0
for item in voucher.inventories:
ledger = Product.by_id(item.product_id).purchase_ledger
amount += item.amount
if ledger.id in journals:
journals[ledger.id].amount += item.amount
else:
journals[ledger.id] = Journal(debit=1, cost_center_id=ledger.costcenter_id, ledger_id=ledger.id,
amount=item.amount)
journals[otherLedger.id] = Journal(debit=-1, cost_center_id=otherLedger.costcenter_id, ledger_id=otherLedger.id,
amount=amount)
for item in voucher.journals:
if item.ledger_id in journals:
item.debit = journals[item.ledger_id].debit
item.amount = journals[item.ledger_id].amount
item.cost_center_id = journals[item.ledger_id].cost_center_id
del journals[item.ledger_id]
else:
DBSession.delete(item)
voucher.journals.remove(item)
for item in journals:
DBSession.add(item)
voucher.journals.append(item)