Merge pull request #78 from danieldupriest/implement-rules

Implement rules for GET report
This commit is contained in:
hui2018 2019-02-14 16:35:26 -08:00 committed by GitHub
commit a4bf17ee71
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 16 deletions

View file

@ -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),
),
]

View file

@ -15,9 +15,9 @@ class Report(models.Model):
class Section(models.Model): class Section(models.Model):
report_id = models.ForeignKey(Report, on_delete=models.CASCADE) report_id = models.ForeignKey(Report, on_delete=models.CASCADE)
auto_submit = models.BooleanField() auto_submit = models.BooleanField(default=False)
required = models.BooleanField() required = models.BooleanField(default=False)
completed = models.BooleanField() completed = models.BooleanField(default=False)
title = models.CharField(max_length=256) title = models.CharField(max_length=256)
html_description = models.TextField() html_description = models.TextField()
number = models.IntegerField() number = models.IntegerField()
@ -29,11 +29,11 @@ class Field(models.Model):
section_id = models.ForeignKey(Section, on_delete=models.CASCADE) section_id = models.ForeignKey(Section, on_delete=models.CASCADE)
field_name = models.CharField(max_length=512, default="field") field_name = models.CharField(max_length=512, default="field")
label = models.CharField(max_length=512) label = models.CharField(max_length=512)
number = models.IntegerField() number = models.IntegerField(default=0)
field_type = models.CharField(max_length=128) field_type = models.CharField(max_length=128)
completed = models.BooleanField(default=False) completed = models.BooleanField(default=False)
data_bool = 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_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_file = models.FileField(upload_to='uploads/%Y/%m/%d/', max_length=512, null=True, blank=True)
data_string = models.TextField(default='', blank=True) data_string = models.TextField(default='', blank=True)

View file

@ -45,7 +45,7 @@ general_section = Section(
general_section.add_rule( general_section.add_rule(
title="Destination city check", 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?" rule_break_text="What did the cowboy say about Tim, his wild horse?"
) )
@ -68,7 +68,7 @@ flight_section = Section(
flight_section.add_rule( flight_section.add_rule(
title="Airline fare pre-approval check", 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" rule_break_text="Fares cannot be more than $500"
) )
@ -88,14 +88,14 @@ lodging_section = Section(
} }
) )
def nightly_rate_check(report, section): def nightly_rate_check(report, fields):
checkin_date = date(section.fields.checkin_date) checkin_date = date(fields['checkin_date'])
checkout_date = date(section.fields.checkout_date) checkout_date = date(fields['checkout_date'])
duration = checkout_date - checkin_date duration = checkout_date - checkin_date
return section.fields.cost <= duration * section.fields.rate return fields['cost'] <= duration * fields['rate']
lodging_section.add_rule( lodging_section.add_rule(
title="", title="Average nightly rate",
rule=nightly_rate_check, rule=nightly_rate_check,
rule_break_text="The average nightly rate cannot be more than the USGSA rate." rule_break_text="The average nightly rate cannot be more than the USGSA rate."
) )
@ -108,14 +108,14 @@ transport_section = Section(
title="Local Transportation", title="Local Transportation",
html_description="<p>How much did you spend on local transportation, in total?</p>", html_description="<p>How much did you spend on local transportation, in total?</p>",
fields={ 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"} "cost": {"label": "Total cost", "field_type": "decimal"}
} }
) )
transport_section.add_rule( transport_section.add_rule(
title="Total cost check", 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." 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( per_diem_section.add_rule(
title="Per Diem Cost Check", 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." rule_break_text="The average cost per day for per diem expenses cannot be more than the rate specified by the USGSA."
) )

View file

@ -28,15 +28,31 @@ def get_sections(r_id):
# create a dict of arrays for section # create a dict of arrays for section
section_set = {"sections": []} section_set = {"sections": []}
queryset = Section.objects.filter(report_id=r_id) queryset = Section.objects.filter(report_id=r_id)
for i in queryset: for index in range(len(queryset)):
i = queryset[index]
data = { data = {
"id": i.id, "id": i.id,
"completed": i.completed, "completed": i.completed,
"title": i.title, "title": i.title,
"html_description": i.html_description, "html_description": i.html_description,
"rule_violations": [],
} }
# append the fields for corresponding section # append the fields for corresponding section
data.update(get_fields(i.id)) 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 # append section to the array
section_set["sections"].append(data.copy()) section_set["sections"].append(data.copy())
@ -67,6 +83,14 @@ def get_fields(s_id):
return field_set 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 Endpoints
@api_view(['POST']) @api_view(['POST'])
def report(request): def report(request):

Binary file not shown.