Correction de l'usage de transaction dans K-Psul

This commit is contained in:
Aurélien Delobelle 2016-08-08 03:32:48 +02:00
parent 726f42c469
commit 4c8b23e999

View file

@ -418,6 +418,7 @@ def kpsul_perform_operations(request):
cof_grant_divisor = 1 + cof_grant / 100 cof_grant_divisor = 1 + cof_grant / 100
is_addcost = (addcost_for and addcost_amount is_addcost = (addcost_for and addcost_amount
and addcost_for != operationgroup.on_acc) and addcost_for != operationgroup.on_acc)
addcost_total = 0
# 1. Calculating amount of each PURCHASE operations # 1. Calculating amount of each PURCHASE operations
# 1.1 Standard price for n articles # 1.1 Standard price for n articles
@ -437,7 +438,7 @@ def kpsul_perform_operations(request):
operation.addcost_amount = addcost_amount * operation.article_nb operation.addcost_amount = addcost_amount * operation.article_nb
operation.amount -= operation.addcost_amount operation.amount -= operation.addcost_amount
# 5 # 5
addcost_for.balance += operation.addcost_amount addcost_total += operation.addcost_amount
operation.addcost_for = addcost_for operation.addcost_for = addcost_for
# 1.3 # 1.3
if operationgroup.on_acc.is_cof: if operationgroup.on_acc.is_cof:
@ -450,47 +451,40 @@ def kpsul_perform_operations(request):
if operation.type == Operation.DEPOSIT: if operation.type == Operation.DEPOSIT:
required_perms.append('kfet.can_perform_deposit') required_perms.append('kfet.can_perform_deposit')
# Starting transaction to ensure data consistency
# Adding required permissions to perform operation group # Using select_for_update where it is critical
opegroup_perms = operationgroup.on_acc.perms_to_perform_operation(
amount = operationgroup.amount)
required_perms += opegroup_perms
# Checking authenticated user has all perms
if not request.user.has_perms(required_perms):
# Sending BAD_REQUEST with missing perms
missing_perms = \
[ Permission.objects.get(codename=codename).name for codename in (
(perm.split('.'))[1] for perm in
required_perms if not request.user.has_perm(perm)
)]
data['errors'].append({'missing_perms': missing_perms })
return JsonResponse(data, status=403)
# If 1 perm is required, saving who perform the operations
if len(required_perms) > 0:
operationgroup.valid_by = request.user.profile.account_kfet
# Filling cof status for statistics
operationgroup.is_cof = operationgroup.on_acc.is_cof
# Updating (no commit) account's balance
operationgroup.on_acc.balance += operationgroup.amount
# Saving in a transaction to ensure database integrity
try: try:
with transaction.atomic(): with transaction.atomic():
on_acc = operationgroup.on_acc
on_acc = Account.objects.select_for_update().get(pk=on_acc.pk)
# Adding required permissions to perform operation group
opegroup_perms = on_acc.perms_to_perform_operation(
amount = operationgroup.amount)
required_perms += opegroup_perms
# Checking authenticated user has all perms
if not request.user.has_perms(required_perms):
raise PermissionDenied
# If 1 perm is required, saving who perform the operations
if len(required_perms) > 0:
operationgroup.valid_by = request.user.profile.account_kfet
# Filling cof status for statistics
operationgroup.is_cof = on_acc.is_cof
# Saving account's balance
on_acc.balance += operationgroup.amount
on_acc.save()
# Saving addcost_for with new balance if there is one
if is_addcost:
addcost_for += addcost_total
addcost_for.save()
# Saving operation group # Saving operation group
operationgroup.save() operationgroup.save()
data['operationgroup'] = operationgroup.pk data['operationgroup'] = operationgroup.pk
# Saving account with new balance
operationgroup.on_acc.save()
# Saving addcost_for with new balance if there is one
if is_addcost:
addcost_for.save()
# Filling operationgroup id for each operations and saving # Filling operationgroup id for each operations and saving
# Saving articles with new stock # Saving articles with new stock
for operation in operations: for operation in operations:
@ -499,7 +493,17 @@ def kpsul_perform_operations(request):
if operation.type == Operation.PURCHASE: if operation.type == Operation.PURCHASE:
operation.article.save() operation.article.save()
data['operations'].append(operation.pk) data['operations'].append(operation.pk)
except PermissionDenied:
# Sending BAD_REQUEST with missing perms
missing_perms = \
[ Permission.objects.get(codename=codename).name for codename in (
(perm.split('.'))[1] for perm in
required_perms if not request.user.has_perm(perm)
)]
data['errors'].append({'missing_perms': missing_perms })
return JsonResponse(data, status=403)
except IntegrityError: except IntegrityError:
data['errors'].append('DB error') data['errors'].append('DB error')
return JsonResponse(data, status=500)
return JsonResponse(data) return JsonResponse(data)