diff --git a/brewman/__init__.py b/brewman/__init__.py
index 70e00b6a..a0484a65 100644
--- a/brewman/__init__.py
+++ b/brewman/__init__.py
@@ -52,6 +52,7 @@ def main(global_config, **settings):
config.add_route('api_dashboard', '/api/Dashboard')
config.add_route('dashboard', '/Dashboard')
+ config.add_route('api_db_integrity', '/api/DbIntegrity')
config.add_route('api_login', '/api/login')
config.add_route('login', '/login')
config.add_route('logout', '/logout')
diff --git a/brewman/static/partial/settings.html b/brewman/static/partial/settings.html
index 694ae3b2..3965166b 100644
--- a/brewman/static/partial/settings.html
+++ b/brewman/static/partial/settings.html
@@ -128,4 +128,12 @@
class="glyphicon glyphicon-paperclip">
+
diff --git a/brewman/static/scripts/settings.js b/brewman/static/scripts/settings.js
index 9a2092d2..9adc9c9e 100644
--- a/brewman/static/scripts/settings.js
+++ b/brewman/static/scripts/settings.js
@@ -121,6 +121,16 @@ var SettingsController = ['$scope', '$http', 'asDateFilter', '$modal', 'lockInfo
$scope.products = function ($viewValue) {
return Product.autocomplete({term: $viewValue, count: 20}).$promise;
};
+
+ $scope.checkDb = function () {
+ return $http.post('/api/DbIntegrity', {}).
+ success(function (data) {
+ $scope.toasts.push({Type: 'Success', Message: ''});
+ }).
+ error(function (errorMessage) {
+ $scope.toasts.push({Type: 'Danger', Message: errorMessage});
+ });
+ };
}];
SettingsController.resolve = {
diff --git a/brewman/views/Management/db_integrity.py b/brewman/views/Management/db_integrity.py
new file mode 100644
index 00000000..5cb1e1b0
--- /dev/null
+++ b/brewman/views/Management/db_integrity.py
@@ -0,0 +1,35 @@
+from pyramid.view import view_config
+from sqlalchemy import func, distinct, over, desc
+import transaction
+from brewman.models import DBSession
+
+from brewman.models.voucher import Attendance
+
+
+@view_config(request_method='POST', route_name='api_db_integrity', renderer='json', permission='Authenticated')
+def post_check_db(request):
+ info = {}
+
+ duplicate_attendances = get_duplicate_attendances()
+ if duplicate_attendances > 0:
+ fix_duplicate_attendances(duplicate_attendances)
+ info['Duplicate Attendances Fixed'] = duplicate_attendances
+ transaction.commit()
+ return info
+
+
+def get_duplicate_attendances():
+ sub_query = DBSession.query(
+ over(distinct(func.first_value(Attendance.id)), partition_by=[Attendance.employee_id, Attendance.date])
+ ).filter(Attendance.is_valid == True).subquery()
+ query = DBSession.query(func.count(Attendance.id)). \
+ filter(~Attendance.id.in_(sub_query)). \
+ filter(Attendance.is_valid == True)
+ return query.scalar()
+
+
+def fix_duplicate_attendances():
+ sub = DBSession.query(over(distinct(func.first_value(Attendance.id)),
+ partition_by=[Attendance.employee_id, Attendance.date],
+ order_by=desc(Attendance.creation_date))).filter(Attendance.is_valid == True).subquery()
+ DBSession.query(Attendance).filter(~Attendance.id.in_(sub)).filter(Attendance.is_valid == True).delete(False)