Update: Changed the Reconcile report so that it shows all the unreconciled entries and also shows the balance according to the reconcile date.
This commit is contained in:
@ -49,8 +49,8 @@
|
|||||||
<th>Reconcile Date</th>
|
<th>Reconcile Date</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody ng-repeat="item in info.Body">
|
<tbody ng-repeat="item in body">
|
||||||
<tr ng-class="{warning:item.IsReconciled}">
|
<tr ng-class="{danger:!item.IsReconciled && $index!=selected, warning:$index==selected}">
|
||||||
<td class="no-wrap">{{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 class="text-right no-wrap">{{item.Debit | currency | clr}}</td>
|
<td class="text-right no-wrap">{{item.Debit | currency | clr}}</td>
|
||||||
@ -70,7 +70,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="6"ng-class="{warning:item.IsReconciled}">
|
<td colspan="6"ng-class="{danger:!item.IsReconciled && $index!=selected, warning:$index==selected}">
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>{{item.Narration}}</p>
|
<p>{{item.Narration}}</p>
|
||||||
<small>{{item.Type}}</small>
|
<small>{{item.Type}}</small>
|
||||||
@ -80,11 +80,11 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="no-wrap">{{info.Footer.Date}}</td>
|
<td class="no-wrap"></td>
|
||||||
<td>{{info.Footer.Name}}</td>
|
<td></td>
|
||||||
<td class="text-right no-wrap">{{info.Footer.Debit | currency}}</td>
|
<td class="text-right no-wrap">{{footer.Debit | currency}}</td>
|
||||||
<td class="text-right no-wrap">{{info.Footer.Credit | currency}}</td>
|
<td class="text-right no-wrap">{{footer.Credit | currency}}</td>
|
||||||
<td class="text-right no-wrap">{{info.Footer.Running | accounting}}</td>
|
<td class="text-right no-wrap">{{footer.Running | accounting}}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
|
|||||||
@ -35,15 +35,7 @@ var LedgerController = ['$scope', '$routeParams', '$location', 'asDateFilter', '
|
|||||||
$scope.selected = index;
|
$scope.selected = index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.$watch(['info', 'hidden'], function () {
|
||||||
// Replace with $watchGroup in AngularJS 1.3+
|
|
||||||
$scope.$watch('hidden', function () {
|
|
||||||
var filtered = $scope.doFilter($scope.hidden, $scope.info.Body);
|
|
||||||
$scope.ledger = filtered.Body;
|
|
||||||
$scope.footer = filtered.Footer;
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
$scope.$watch('info', function () {
|
|
||||||
var filtered = $scope.doFilter($scope.hidden, $scope.info.Body);
|
var filtered = $scope.doFilter($scope.hidden, $scope.info.Body);
|
||||||
$scope.ledger = filtered.Body;
|
$scope.ledger = filtered.Body;
|
||||||
$scope.footer = filtered.Footer;
|
$scope.footer = filtered.Footer;
|
||||||
|
|||||||
@ -14,15 +14,21 @@ var ReconcileController = ['$scope', '$routeParams', '$location', 'asDateFilter'
|
|||||||
$location.path('/Reconcile/' + id).search('StartDate', startDate).search('FinishDate', finishDate);
|
$location.path('/Reconcile/' + id).search('StartDate', startDate).search('FinishDate', finishDate);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.save = function () {
|
$scope.save = function () {
|
||||||
var i, l,
|
var i,
|
||||||
len = $scope.info.Body.length;
|
len = $scope.body.length;
|
||||||
for (i = 0, l = len; i < l; i++) {
|
$scope.info.Body = $scope.body;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
$scope.info.Body[i].ReconcileDate = asDate($scope.info.Body[i].ReconcileDate);
|
$scope.info.Body[i].ReconcileDate = asDate($scope.info.Body[i].ReconcileDate);
|
||||||
}
|
}
|
||||||
$scope.info.$save({StartDate: $routeParams.StartDate, FinishDate: $routeParams.FinishDate}, function (u, putResponseHeaders) {
|
$scope.info.$save({
|
||||||
|
StartDate: $routeParams.StartDate,
|
||||||
|
FinishDate: $routeParams.FinishDate
|
||||||
|
}, function (u, putResponseHeaders) {
|
||||||
$scope.toasts.push({Type: 'Success', Message: ''});
|
$scope.toasts.push({Type: 'Success', Message: ''});
|
||||||
$scope.info = u;
|
$scope.info = u;
|
||||||
|
$scope.doFilter();
|
||||||
}, function (data, status) {
|
}, function (data, status) {
|
||||||
$scope.toasts.push({Type: 'Danger', Message: data.data});
|
$scope.toasts.push({Type: 'Danger', Message: data.data});
|
||||||
});
|
});
|
||||||
@ -46,22 +52,57 @@ var ReconcileController = ['$scope', '$routeParams', '$location', 'asDateFilter'
|
|||||||
$scope.selected = index;
|
$scope.selected = index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.doFilter = function () {
|
||||||
|
var data = angular.copy($scope.info.Body),
|
||||||
|
debit = 0, credit = 0, running = 0;
|
||||||
|
|
||||||
|
data = data.sort(function (a, b) {
|
||||||
|
if (a.IsReconciled !== b.IsReconciled) {
|
||||||
|
return b.IsReconciled - a.IsReconciled;
|
||||||
|
}
|
||||||
|
var aDate = moment(a.ReconcileDate, 'DD-MMM-YYYY');
|
||||||
|
var bDate = moment(b.ReconcileDate, 'DD-MMM-YYYY');
|
||||||
|
return aDate - bDate;
|
||||||
|
});
|
||||||
|
|
||||||
|
_.forEach(data, function (item) {
|
||||||
|
if (item.Type !== 'Opening Balance') {
|
||||||
|
debit += item.Debit;
|
||||||
|
credit += item.Credit;
|
||||||
|
if (item.IsReconciled) {
|
||||||
|
running += item.Debit - item.Credit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
running += item.Debit - item.Credit;
|
||||||
|
}
|
||||||
|
item.Running = running;
|
||||||
|
});
|
||||||
|
$scope.body = data;
|
||||||
|
$scope.footer = {
|
||||||
|
Debit: debit,
|
||||||
|
Credit: credit,
|
||||||
|
Running: running
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.doFilter();
|
||||||
|
|
||||||
$scope.shortcuts = {
|
$scope.shortcuts = {
|
||||||
'up': function (e) {
|
'up': function (e) {
|
||||||
if ($scope.selected > 0) {
|
if ($scope.selected > 0) {
|
||||||
$scope.$apply(function () {
|
$scope.$apply(function () {
|
||||||
$scope.selected = $scope.selected -= 1;
|
$scope.selected = Math.min(Math.max(0, $scope.selected - 1), $scope.ledger.length - 1);
|
||||||
});
|
});
|
||||||
$("#" + $scope.selected).scrollintoview({duration: 'fast'});
|
$("#" + $scope.selected).scrollintoview();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'down': function (e) {
|
'down': function (e) {
|
||||||
if ($scope.selected < $scope.info.Body.length - 1) {
|
if ($scope.selected < $scope.info.Body.length - 1) {
|
||||||
$scope.$apply(function () {
|
$scope.$apply(function () {
|
||||||
$scope.selected = $scope.selected += 1;
|
$scope.selected = Math.min(Math.max(0, $scope.selected + 1), $scope.ledger.length - 1);
|
||||||
});
|
});
|
||||||
$("#" + $scope.selected).scrollintoview({duration: 'fast'});
|
$("#" + $scope.selected).scrollintoview();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -70,6 +111,7 @@ var ReconcileController = ['$scope', '$routeParams', '$location', 'asDateFilter'
|
|||||||
$scope.$apply(function () {
|
$scope.$apply(function () {
|
||||||
$location.path(path).search('StartDate', null).search('FinishDate', null);
|
$location.path(path).search('StartDate', null).search('FinishDate', null);
|
||||||
});
|
});
|
||||||
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -91,5 +133,3 @@ ReconcileController.resolve = {
|
|||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,6 @@ from brewman.models.validation_exception import TryCatchFunction
|
|||||||
from brewman.models.voucher import Journal, Voucher, VoucherType, Batch, Inventory, SalaryDeduction, Fingerprint, \
|
from brewman.models.voucher import Journal, Voucher, VoucherType, Batch, Inventory, SalaryDeduction, Fingerprint, \
|
||||||
Attendance, DbImage
|
Attendance, DbImage
|
||||||
|
|
||||||
|
|
||||||
__author__ = 'tanshu'
|
__author__ = 'tanshu'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -223,7 +223,7 @@ def product_info(id):
|
|||||||
def delete_with_data(product):
|
def delete_with_data(product):
|
||||||
suspense_product = Product.by_id(Product.suspense())
|
suspense_product = Product.by_id(Product.suspense())
|
||||||
suspense_batch = Batch.by_id(Batch.suspense())
|
suspense_batch = Batch.by_id(Batch.suspense())
|
||||||
query = Voucher.query().options(joinedload_all(Voucher.inventories, Inventory.product, innerjoin=True)) \
|
query = Voucher.query().options(joinedload_all(Voucher.inventories, Inventory.product, innerjoin=True) ) \
|
||||||
.filter(Voucher.inventories.any(Inventory.product_id == product.id)) \
|
.filter(Voucher.inventories.any(Inventory.product_id == product.id)) \
|
||||||
.all()
|
.all()
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import datetime
|
|||||||
import pkg_resources
|
import pkg_resources
|
||||||
from pyramid.response import FileResponse
|
from pyramid.response import FileResponse
|
||||||
from sqlalchemy.orm import joinedload_all
|
from sqlalchemy.orm import joinedload_all
|
||||||
from sqlalchemy.sql.expression import func
|
from sqlalchemy.sql.expression import func, or_, and_
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from pyramid.view import view_config
|
from pyramid.view import view_config
|
||||||
@ -28,7 +28,7 @@ def html(request):
|
|||||||
@view_config(request_method='GET', route_name='api_reconcile', renderer='json', permission='Reconcile')
|
@view_config(request_method='GET', route_name='api_reconcile', renderer='json', permission='Reconcile')
|
||||||
def show_blank(request):
|
def show_blank(request):
|
||||||
return {'StartDate': session_period_start(request),
|
return {'StartDate': session_period_start(request),
|
||||||
'FinishDate': session_period_finish(request), 'Ledger': None, 'Body': [], 'Footer': {}}
|
'FinishDate': session_period_finish(request), 'Ledger': None, 'Body': []}
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='GET', route_name='api_reconcile_id', renderer='json', permission='Reconcile')
|
@view_config(request_method='GET', route_name='api_reconcile_id', renderer='json', permission='Reconcile')
|
||||||
@ -39,8 +39,7 @@ def show_data(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,
|
||||||
'Account': {'LedgerID': account.id, 'Name': account.name},
|
'Account': {'LedgerID': account.id, 'Name': account.name}, 'Body': []}
|
||||||
'Body': [], 'Footer': {}}
|
|
||||||
build_report(request, info)
|
build_report(request, info)
|
||||||
return info
|
return info
|
||||||
|
|
||||||
@ -49,15 +48,24 @@ def build_report(request, info):
|
|||||||
ledger_id = info['Account']['LedgerID']
|
ledger_id = info['Account']['LedgerID']
|
||||||
start_date = info['StartDate']
|
start_date = info['StartDate']
|
||||||
finish_date = info['FinishDate']
|
finish_date = info['FinishDate']
|
||||||
total_debit, total_credit, running_total, opening = opening_balance(ledger_id, start_date)
|
opening = opening_balance(ledger_id, start_date)
|
||||||
info['Body'].append(opening)
|
info['Body'].append(opening)
|
||||||
|
|
||||||
query = Voucher.query().options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \
|
query = Voucher.query().options(
|
||||||
.filter(Voucher.journals.any(Journal.ledger_id == ledger_id)) \
|
joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)
|
||||||
.filter(Voucher.date >= datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
|
).filter(
|
||||||
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')) \
|
Voucher.journals.any(Journal.ledger_id == ledger_id)
|
||||||
.filter(Voucher.type != VoucherType.by_name('Issue').id) \
|
).filter(
|
||||||
.order_by(Voucher.reconcile_date).order_by(Voucher.last_edit_date).all()
|
or_(
|
||||||
|
Voucher.is_reconciled == False,
|
||||||
|
and_(
|
||||||
|
Voucher.reconcile_date >= datetime.datetime.strptime(start_date, '%d-%b-%Y'),
|
||||||
|
Voucher.reconcile_date <= datetime.datetime.strptime(finish_date, '%d-%b-%Y')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).filter(
|
||||||
|
Voucher.type != VoucherType.by_name('Issue').id
|
||||||
|
).order_by(Voucher.is_reconciled).order_by(Voucher.reconcile_date).order_by(Voucher.last_edit_date).all()
|
||||||
|
|
||||||
for voucher in query:
|
for voucher in query:
|
||||||
debit = 0
|
debit = 0
|
||||||
@ -66,17 +74,13 @@ def build_report(request, info):
|
|||||||
name = ""
|
name = ""
|
||||||
for journal in voucher.journals:
|
for journal in voucher.journals:
|
||||||
if journal.ledger_id == ledger_id:
|
if journal.ledger_id == ledger_id:
|
||||||
if voucher.posted:
|
|
||||||
running_total += (journal.amount * journal.debit)
|
|
||||||
journal_debit = journal.debit
|
journal_debit = journal.debit
|
||||||
if journal.debit == 1:
|
if journal.debit == 1:
|
||||||
debit = journal.amount
|
debit = journal.amount
|
||||||
total_debit += journal.amount
|
credit = 0
|
||||||
credit = ""
|
|
||||||
else:
|
else:
|
||||||
credit = journal.amount
|
credit = journal.amount
|
||||||
total_credit += journal.amount
|
debit = 0
|
||||||
debit = ""
|
|
||||||
for journal in voucher.journals:
|
for journal in voucher.journals:
|
||||||
if journal.debit != journal_debit:
|
if journal.debit != journal_debit:
|
||||||
name += "{0} / ".format(journal.ledger.name)
|
name += "{0} / ".format(journal.ledger.name)
|
||||||
@ -84,18 +88,15 @@ def build_report(request, info):
|
|||||||
info['Body'].append(
|
info['Body'].append(
|
||||||
{'VoucherID': voucher.id, 'Date': voucher.date.strftime('%d-%b-%Y'), 'Name': name,
|
{'VoucherID': voucher.id, 'Date': voucher.date.strftime('%d-%b-%Y'), 'Name': name,
|
||||||
'Url': get_edit_url(request, voucher), 'Type': VoucherType.by_id(voucher.type).name,
|
'Url': get_edit_url(request, voucher), 'Type': VoucherType.by_id(voucher.type).name,
|
||||||
'Narration': voucher.narration, 'Debit': debit, 'Credit': credit, 'Running': running_total,
|
'Narration': voucher.narration, 'Debit': debit, 'Credit': credit, 'IsReconciled': voucher.is_reconciled,
|
||||||
'ReconcileDate': voucher.reconcile_date.strftime('%d-%b-%Y'), 'IsReconciled': voucher.is_reconciled})
|
'ReconcileDate': voucher.reconcile_date.strftime('%d-%b-%Y')})
|
||||||
|
|
||||||
info['Footer'] = {'Date': finish_date, 'Name': 'Closing Balance', 'Type': 'Closing Balance',
|
|
||||||
'Narration': '', 'Debit': total_debit, 'Credit': total_credit,
|
|
||||||
'Running': running_total, 'Posted': True}
|
|
||||||
|
|
||||||
|
|
||||||
def opening_balance(ledgerID, start_date):
|
def opening_balance(ledgerID, start_date):
|
||||||
opening = DBSession.query(func.sum(Journal.amount * Journal.debit)) \
|
opening = DBSession.query(func.sum(Journal.amount * Journal.debit)) \
|
||||||
.join(Journal.voucher) \
|
.join(Journal.voucher) \
|
||||||
.filter(Voucher.date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
|
.filter(Voucher.reconcile_date < datetime.datetime.strptime(start_date, '%d-%b-%Y')) \
|
||||||
|
.filter(Voucher.is_reconciled == True) \
|
||||||
.filter(Voucher.type != VoucherType.by_name('Issue').id) \
|
.filter(Voucher.type != VoucherType.by_name('Issue').id) \
|
||||||
.filter(Journal.ledger_id == ledgerID) \
|
.filter(Journal.ledger_id == ledgerID) \
|
||||||
.scalar()
|
.scalar()
|
||||||
@ -106,7 +107,7 @@ def opening_balance(ledgerID, start_date):
|
|||||||
else:
|
else:
|
||||||
debit = opening
|
debit = opening
|
||||||
credit = 0
|
credit = 0
|
||||||
return 0, 0, opening, {'Date': start_date, 'Name': 'Opening Balance', 'Type': 'Opening Balance',
|
return {'Date': start_date, 'ID': 'OB', 'Name': 'Opening Balance', 'Type': 'Opening Balance',
|
||||||
'Narration': '', 'Debit': debit, 'Credit': credit, 'Running': opening, 'Posted': True}
|
'Narration': '', 'Debit': debit, 'Credit': credit, 'Running': opening, 'Posted': True}
|
||||||
|
|
||||||
|
|
||||||
@ -131,4 +132,3 @@ def save(request):
|
|||||||
'Body': [], 'Footer': {}}
|
'Body': [], 'Footer': {}}
|
||||||
build_report(request, info)
|
build_report(request, info)
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user