Skip to content

Commit

Permalink
Merge pull request #52 from sharpeez/master
Browse files Browse the repository at this point in the history
WLC sprint #2
  • Loading branch information
jawaidm authored Nov 18, 2020
2 parents 6af893d + a8ab0b5 commit 9e427e2
Show file tree
Hide file tree
Showing 25 changed files with 495 additions and 87 deletions.
1 change: 1 addition & 0 deletions cron
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
* * * * * root eval $(grep -v '^#' /etc/.cronenv | xargs -d "\n" -I {} echo export \"{}\" ) && cd /app && python manage_wc.py system_maintenance_check > /dev/null 2>&1
0 2 * * * root eval $(grep -v '^#' /etc/.cronenv | xargs -d "\n" -I {} echo export \"{}\" ) && cd /app && python manage_wc.py cron_tasks > logs/cron_tasks.log 2>&1
10 2 * * * root eval $(grep -v '^#' /etc/.cronenv | xargs -d "\n" -I {} echo export \"{}\" ) && cd /app && python manage_wc.py runcrons > logs/runcrons.log 2>&1
42 changes: 30 additions & 12 deletions wildlifecompliance/components/applications/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,26 @@ def accept_character_check(self, request, *args, **kwargs):
print(traceback.print_exc())
raise serializers.ValidationError(str(e))

@detail_route(methods=['POST', ])
def reset_character_check(self, request, *args, **kwargs):
try:
instance = self.get_object()
instance.reset_character_check(request)

return Response(
{'character_check_status': instance.character_check_status},
status=status.HTTP_200_OK
)
except serializers.ValidationError:
print(traceback.print_exc())
raise
except ValidationError as e:
print(traceback.print_exc())
raise serializers.ValidationError(repr(e.error_dict))
except Exception as e:
print(traceback.print_exc())
raise serializers.ValidationError(str(e))

@detail_route(methods=['POST', ])
def accept_return_check(self, request, *args, **kwargs):
try:
Expand Down Expand Up @@ -1514,20 +1534,18 @@ def assessment_data(self, request, *args, **kwargs):
instance = self.get_object()
with transaction.atomic():

if instance.is_resubmitted:
checkbox = CheckboxAndRadioButtonVisitor(
instance, request.data
)
# Set StandardCondition Fields.
for_condition_fields = StandardConditionFieldElement()
for_condition_fields.accept(checkbox)
checkbox = CheckboxAndRadioButtonVisitor(
instance, request.data
)
# Set StandardCondition Fields.
for_condition_fields = StandardConditionFieldElement()
for_condition_fields.accept(checkbox)

# Set PromptInspection Fields.
for_inspection_fields = PromptInspectionFieldElement()
for_inspection_fields.accept(checkbox)
# Set PromptInspection Fields.
for_inspection_fields = PromptInspectionFieldElement()
for_inspection_fields.accept(checkbox)

instance.is_resubmitted = False
instance.save()
instance.save()

return Response({'success': True})
except MissingFieldsException as e:
Expand Down
76 changes: 66 additions & 10 deletions wildlifecompliance/components/applications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,8 @@ class Application(RevisionedMixin):
choices=SUBMIT_TYPE_CHOICES,
default=SUBMIT_TYPE_ONLINE)
property_cache = JSONField(null=True, blank=True, default={})
is_resubmitted = models.BooleanField(default=False)
# is_resubmitted is not used and can be removed.
# is_resubmitted = models.BooleanField(default=False)

class Meta:
app_label = 'wildlifecompliance'
Expand Down Expand Up @@ -809,6 +810,32 @@ def licence_category(self):
except AttributeError:
return ''

def set_property_cache_licence_fee(self, licence_fee):
'''
Setter for licence fee on the property cache.
NOTE: only used for presentation purposes.
'''
if self.id:
data = str(licence_fee)
self.property_cache['licence_fee'] = data

def get_property_cache_licence_fee(self):
'''
Getter for licence fee on the property cache.
NOTE: only used for presentation purposes.
'''
fee = 0
try:

fee = self.property_cache['licence_fee']

except KeyError:
pass

return fee

def set_activity_processing_status(self, activity_id, processing_status):
if not activity_id:
logger.error("Application: %s cannot update processing status (%s) for an empty activity_id!" %
Expand Down Expand Up @@ -1125,7 +1152,8 @@ def submit(self, request):
# set is_resubmitted to True everytime.
# flag is only used for assessments and conditions and is set
# to false once conditions are processed.
self.is_resubmitted = True
# NOTE: self.is_resubmitted not used.
# self.is_resubmitted = True
# if amendment is submitted change the status of only particular activity
# else if the new application is submitted change the status of
# all the activities
Expand Down Expand Up @@ -1374,6 +1402,30 @@ def accept_character_check(self, request):
ApplicationUserAction.ACTION_ACCEPT_CHARACTER.format(
self.id), request)

def reset_character_check(self, request):
self.character_check_status = \
Application.CHARACTER_CHECK_STATUS_NOT_CHECKED

self.save()
# Create a log entry for the application
self.log_user_action(
ApplicationUserAction.ACTION_RESET_CHARACTER.format(
self.id), request)
# Create a log entry for the applicant (submitter, organisation or
# proxy)
if self.org_applicant:
self.org_applicant.log_user_action(
ApplicationUserAction.ACTION_RESET_CHARACTER.format(
self.id), request)
elif self.proxy_applicant:
self.proxy_applicant.log_user_action(
ApplicationUserAction.ACTION_RESET_CHARACTER.format(
self.id), request)
else:
self.submitter.log_user_action(
ApplicationUserAction.ACTION_RESET_CHARACTER.format(
self.id), request)

def accept_return_check(self, request):
self.return_check_status = Application.RETURN_CHECK_STATUS_ACCEPTED
self.save()
Expand Down Expand Up @@ -5119,8 +5171,8 @@ def store_proposed_attachments(self, proposed_attachments):

def get_activity_from_previous(self):
'''
Gets this Application Selected Activity from the previous Application
Selected Activity application licence.
Return the Application Selected Activity from the previously replaced
Application Selected Activity application licence.
'''
previous = None
prev_app = self.application.previous_application
Expand All @@ -5141,7 +5193,7 @@ def get_activity_from_previous(self):
prev_chain = [
a for a in prev_chain
if a.licence_activity_id == act_id
and a.activity_status in self.ACTIVE
and a.activity_status in status
and a.processing_status in self.PROCESSING_STATUS_ACCEPTED
]
previous = prev_chain[0] # licence has one current activity.
Expand Down Expand Up @@ -5731,7 +5783,7 @@ def reinstate(self):
def get_purpose_from_previous(self):
'''
Gets this Application Selected Activity Purpose from the previous
selected Activity.
replaced selected Activity.
'''
previous = None
prev_app = self.selected_activity.application.previous_application
Expand All @@ -5754,12 +5806,16 @@ def get_purpose_from_previous(self):
prev = [
a for a in activities
if a.licence_activity_id == act_id
and a.activity_status in ApplicationSelectedActivity.ACTIVE
# and a.activity_status in status
and a.processing_status == ACCEPT
and self.purpose in a.issued_purposes
# replaced purposes are no longer issued.
# and self.purpose in a.issued_purposes
]

purposes = prev[0].proposed_purposes.all()
# order by Application Selected Activity ID with Current last.
sorted_prev = sorted(prev, key=lambda x: x.id, reverse=False)
# when multiple Replaced applications only use the last one.
prev_id = len(sorted_prev) - 2 if len(sorted_prev) > 1 else 0
purposes = sorted_prev[prev_id].proposed_purposes.all()
prev = [p for p in purposes if p.purpose_id == self_id]
previous = prev[0]

Expand Down
15 changes: 9 additions & 6 deletions wildlifecompliance/components/applications/payments.py
Original file line number Diff line number Diff line change
Expand Up @@ -1375,17 +1375,20 @@ def set_application_fee_from_attributes(self, attributes):
paid_lic_tot = 0
paid_app_tot = 0
for p in activity.proposed_purposes.all():
fees_lic += p.licence_fee if p.is_payable \
else 0
fees_app += p.application_fee if p.is_payable \
else 0
# fees_lic += p.licence_fee if p.is_payable \
# else 0
# fees_app += p.application_fee if p.is_payable \
# else 0
paid_lic_tot += p.total_paid_adjusted_licence_fee \
if p.is_payable else 0
paid_app_tot += p.total_paid_adjusted_application_fee \
if p.is_payable else 0

fees_app_new = fees_app_adj - paid_app_tot
fees_lic_new = fees_lic_adj - paid_lic_tot
fees_app = fees_app_adj - paid_app_tot
fees_lic = fees_lic_adj - paid_lic_tot

fees_app_new += fees_app
fees_lic_new += fees_lic

else:
fees_app_new += fees_app_adj
Expand Down
27 changes: 6 additions & 21 deletions wildlifecompliance/components/applications/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1195,28 +1195,13 @@ def get_adjusted_paid_amount(self, obj):
"""
Total paid amount adjusted for presentation purposes. Only applicable
for internal officers to enforce refundable payments.
TODO: REDUNDANT
"""
# adjusted = None
# # Include previously paid amounts for amendments.
# adjusted = obj.total_paid_amount + obj.previous_paid_amount

# if obj.processing_status == \
# Application.PROCESSING_STATUS_UNDER_REVIEW:
# # when Under Review, fee for amendment is paid and included in
# # previous paid amount as well as total paid amount. Need to
# # exclude this previous amount.
# adjusted = adjusted - obj.previous_paid_amount

# # licence fee is paid with the application fee. Licence fee needs
# # to be excluded from total paid for application.
# licence_fee_paid = 0
# for activity in obj.activities:
# licence_fee_paid += activity.licence_fee
# adjusted = adjusted - licence_fee_paid

adjusted = 0
import decimal
licence_fee = decimal.Decimal(obj.get_property_cache_licence_fee() * 1)
adjusted = {
'application_fee': obj.application_fee,
'licence_fee': licence_fee
}

return adjusted

Expand Down
4 changes: 3 additions & 1 deletion wildlifecompliance/components/applications/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,8 @@ def reset(self, licence_activity):
for condition in ApplicationCondition.objects.filter(
is_rendered=True,
standard=True,
application=self._application
application=self._application,
licence_activity_id=licence_activity.id
):
condition.delete()

Expand Down Expand Up @@ -1218,6 +1219,7 @@ def do_update_dynamic_attributes(application, fee_exemption=False):
# Update application and licence fees
fees = dynamic_attributes['fees']
application.application_fee = fees['application']
application.set_property_cache_licence_fee(fees['licence'])
application.save()


Expand Down
10 changes: 9 additions & 1 deletion wildlifecompliance/components/main/admin.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
from django.contrib import admin
#from ledger.accounts.models import EmailUser
from wildlifecompliance.components.main import models
from wildlifecompliance.components.main import models, forms
#from reversion.admin import VersionAdmin


@admin.register(models.GlobalSettings)
class GlobalSettingsAdmin(admin.ModelAdmin):
list_display = ['key', 'value']
ordering = ('key',)


@admin.register(models.SystemMaintenance)
class SystemMaintenanceAdmin(admin.ModelAdmin):
list_display = ['name', 'description', 'start_date', 'end_date', 'duration']
ordering = ('start_date',)
readonly_fields = ('duration',)
form = forms.SystemMaintenanceAdminForm
62 changes: 62 additions & 0 deletions wildlifecompliance/components/main/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import pytz

from django import forms
from django.conf import settings
from datetime import datetime, timedelta

from wildlifecompliance.components.main.models import SystemMaintenance


class SystemMaintenanceAdminForm(forms.ModelForm):
class Meta:
model = SystemMaintenance
fields = '__all__'

MSG = 'Start date cannot be before an existing records latest end_date. Start Date must be after'

def clean(self):
cleaned_data = self.cleaned_data
start_date = cleaned_data.get('start_date')
end_date = cleaned_data.get('end_date')
try:
latest_obj = SystemMaintenance.objects.exclude(
id=self.instance.id
).latest('start_date')

except Exception:
latest_obj = SystemMaintenance.objects.none()
tz_local = pytz.timezone(settings.TIME_ZONE) # start_date.tzinfo
# tz_utc = pytz.timezone('utc') # latest_obj.start_date.tzinfo

if latest_obj:
latest_end_date = latest_obj.end_date.astimezone(tz=tz_local)
if self.instance.id:
if start_date < latest_end_date and start_date \
< self.instance.start_date.astimezone(tz_local):

raise forms.ValidationError('{0} {1}'.format(
self.MSG,
latest_end_date.ctime()
))
else:
if start_date < latest_end_date:
raise forms.ValidationError('{0} {1}'.format(
self.MSG,
latest_end_date.ctime()
))

if self.instance.id:
if start_date < datetime.now(tz=tz_local) - timedelta(minutes=5) \
and start_date < self.instance.start_date.astimezone(tz_local):

raise forms.ValidationError('Start date cannot be edited to be further in the past')
else:
if start_date < datetime.now(tz=tz_local) - timedelta(minutes=5):
raise forms.ValidationError('Start date cannot be in the past')

if end_date < start_date:
raise forms.ValidationError('End date cannot be before start date')

super(SystemMaintenanceAdminForm, self).clean()

return cleaned_data
25 changes: 25 additions & 0 deletions wildlifecompliance/components/main/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,31 @@
logger = logging.getLogger(__name__)


@python_2_unicode_compatible
class SystemMaintenance(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
start_date = models.DateTimeField()
end_date = models.DateTimeField()

def duration(self):
""" Duration of system maintenance (in mins) """
return int(
(self.end_date - self.start_date).total_seconds()/60.
) if self.end_date and self.start_date else ''

duration.short_description = 'Duration (mins)'

class Meta:
app_label = 'wildlifecompliance'
verbose_name_plural = "System maintenance"

def __str__(self):
return 'System Maintenance: {} ({}) - starting {}, ending {}'.format(
self.name, self.description, self.start_date, self.end_date
)


@python_2_unicode_compatible
class Sequence(models.Model):

Expand Down
Loading

0 comments on commit 9e427e2

Please sign in to comment.