diff --git a/back/backend/migrations/0008_auto_20190214_1421.py b/back/backend/migrations/0008_auto_20190214_1421.py new file mode 100644 index 0000000..0aff026 --- /dev/null +++ b/back/backend/migrations/0008_auto_20190214_1421.py @@ -0,0 +1,38 @@ +# Generated by Django 2.1.5 on 2019-02-14 22:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('backend', '0007_merge_20190213_2318'), + ] + + operations = [ + migrations.AlterField( + model_name='field', + name='data_decimal', + field=models.DecimalField(decimal_places=2, default=0, max_digits=9), + ), + migrations.AlterField( + model_name='field', + name='number', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='section', + name='auto_submit', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='section', + name='completed', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='section', + name='required', + field=models.BooleanField(default=False), + ), + ] diff --git a/back/backend/models.py b/back/backend/models.py index 0ab711a..e52b763 100644 --- a/back/backend/models.py +++ b/back/backend/models.py @@ -15,9 +15,9 @@ class Report(models.Model): class Section(models.Model): report_id = models.ForeignKey(Report, on_delete=models.CASCADE) - auto_submit = models.BooleanField() - required = models.BooleanField() - completed = models.BooleanField() + auto_submit = models.BooleanField(default=False) + required = models.BooleanField(default=False) + completed = models.BooleanField(default=False) title = models.CharField(max_length=256) html_description = models.TextField() number = models.IntegerField() @@ -29,11 +29,11 @@ class Field(models.Model): section_id = models.ForeignKey(Section, on_delete=models.CASCADE) field_name = models.CharField(max_length=512, default="field") label = models.CharField(max_length=512) - number = models.IntegerField() + number = models.IntegerField(default=0) field_type = models.CharField(max_length=128) completed = models.BooleanField(default=False) data_bool = models.BooleanField(default=False) - data_decimal = models.DecimalField(max_digits=9, decimal_places=2, null=True, blank=True) + data_decimal = models.DecimalField(max_digits=9, decimal_places=2, default=0) data_date = models.DateField(null=True, blank=True) data_file = models.FileField(upload_to='uploads/%Y/%m/%d/', max_length=512, null=True, blank=True) data_string = models.TextField(default='', blank=True) diff --git a/back/backend/policy.py b/back/backend/policy.py index 381405e..7af3281 100644 --- a/back/backend/policy.py +++ b/back/backend/policy.py @@ -45,7 +45,7 @@ general_section = Section( general_section.add_rule( title="Destination city check", - rule=lambda report, section: section.field.destination == "Timbuktu", + rule=lambda report, fields: fields['destination'] == "Timbuktu", rule_break_text="What did the cowboy say about Tim, his wild horse?" ) @@ -68,7 +68,7 @@ flight_section = Section( flight_section.add_rule( title="Airline fare pre-approval check", - rule=lambda report, section: section.fields.fare < 500, + rule=lambda report, fields: fields['fare'] < 500, rule_break_text="Fares cannot be more than $500" ) @@ -88,14 +88,14 @@ lodging_section = Section( } ) -def nightly_rate_check(report, section): - checkin_date = date(section.fields.checkin_date) - checkout_date = date(section.fields.checkout_date) +def nightly_rate_check(report, fields): + checkin_date = date(fields['checkin_date']) + checkout_date = date(fields['checkout_date']) duration = checkout_date - checkin_date - return section.fields.cost <= duration * section.fields.rate + return fields['cost'] <= duration * fields['rate'] lodging_section.add_rule( - title="", + title="Average nightly rate", rule=nightly_rate_check, rule_break_text="The average nightly rate cannot be more than the USGSA rate." ) @@ -108,14 +108,14 @@ transport_section = Section( title="Local Transportation", html_description="
How much did you spend on local transportation, in total?
", fields={ - "duration": {"label": "How many days was your trip?", "field_type": "decimal"}, + "duration": {"label": "How many days was your trip?", "field_type": "integer"}, "cost": {"label": "Total cost", "field_type": "decimal"} } ) transport_section.add_rule( title="Total cost check", - rule=lambda report, section: section.fields.cost <= section.fields.duration * 10, + rule=lambda report, fields: fields['cost'] <= fields['duration'] * 10, rule_break_text="Local transportation costs must be less than $10 per day, on average." ) @@ -136,7 +136,7 @@ per_diem_section = Section( per_diem_section.add_rule( title="Per Diem Cost Check", - rule=lambda report, section: section.fields.cost <= section.fields.duration * section.fields.rate, + rule=lambda report, fields: fields['cost'] <= fields['duration'] * fields['rate'], rule_break_text="The average cost per day for per diem expenses cannot be more than the rate specified by the USGSA." ) diff --git a/back/backend/views.py b/back/backend/views.py index 68b177f..f29d2d6 100644 --- a/back/backend/views.py +++ b/back/backend/views.py @@ -28,15 +28,31 @@ def get_sections(r_id): # create a dict of arrays for section section_set = {"sections": []} queryset = Section.objects.filter(report_id=r_id) - for i in queryset: + for index in range(len(queryset)): + i = queryset[index] data = { "id": i.id, "completed": i.completed, "title": i.title, "html_description": i.html_description, + "rule_violations": [], } # append the fields for corresponding section data.update(get_fields(i.id)) + # process rules from the policy file if the section is completed + if i.completed: + rules = pol.sections[index].rules + for rule in rules: + try: + named_fields = generate_named_fields_for_section(data['fields']) + if not rule['rule'](data, named_fields): + info = { + "label": rule['title'], + "rule_break_text": rule['rule_break_text'], + } + data['rule_violations'].append(info) + except Exception as e: + print('Rule "{}" encountered an error. {}'.format(rule['title'], e)) # append section to the array section_set["sections"].append(data.copy()) @@ -67,6 +83,14 @@ def get_fields(s_id): return field_set +def generate_named_fields_for_section(fields): + result = {} + for field in fields: + key = field['field_name'] + value = field['value'] + result[key] = value + return result + # API Endpoints @api_view(['POST']) def report(request): diff --git a/back/db.sqlite3 b/back/db.sqlite3 index df940de..e74167e 100644 Binary files a/back/db.sqlite3 and b/back/db.sqlite3 differ