Merge pull request #59: Implemented policy parsing
Implemented policy parsing!
This commit is contained in:
		
						commit
						21440bf3dc
					
				
					 6 changed files with 87 additions and 98 deletions
				
			
		
							
								
								
									
										18
									
								
								back/backend/migrations/0005_field_field_name.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								back/backend/migrations/0005_field_field_name.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| # Generated by Django 2.1.5 on 2019-02-07 22:02 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('backend', '0004_auto_20190131_1645'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='field', | ||||
|             name='field_name', | ||||
|             field=models.CharField(default='field', max_length=512), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -26,12 +26,13 @@ class Section(models.Model): | |||
| 
 | ||||
| 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() | ||||
|     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, null=True, blank=True) | ||||
|     data_date = models.DateField(default=datetime.date.today) | ||||
|     data_file = models.FileField(upload_to='uploads/%Y/%m/%d/', max_length=512, null=True, blank=True) | ||||
|     data_string = models.TextField(default='', blank=True) | ||||
|  |  | |||
|  | @ -1,10 +1,36 @@ | |||
| # simple_policy.py | ||||
| from datetime import date | ||||
| from policy import Policy, Section | ||||
| 
 | ||||
| # - For the rules, should one refer to fields by 'section.fields.x' | ||||
| # or by the section name eg. 'general_section.fields.x'? | ||||
| #### Classes for policy, sections. | ||||
| 
 | ||||
| class Policy(): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.sections = [] | ||||
| 
 | ||||
|     def add_section(self, section): | ||||
|         self.sections.append(section) | ||||
| 
 | ||||
| class Section(): | ||||
|      | ||||
|     def __init__(self, title="Section", html_description="", required=False, auto_submit=False, fields={}): | ||||
|         self.title = title | ||||
|         self.html_description = html_description | ||||
|         self.required = required | ||||
|         self.auto_submit = auto_submit | ||||
|         self.fields = fields | ||||
|         self.rules = [] | ||||
| 
 | ||||
|     def add_rule(self, title="Rule", rule=None, rule_break_text=""): | ||||
|         rule = { | ||||
|             "title": title, | ||||
|             "rule": rule, | ||||
|             "rule_break_text": rule_break_text, | ||||
|         } | ||||
|         self.rules.append(rule) | ||||
| 
 | ||||
| #### Policy configuration begin here | ||||
| 
 | ||||
| pol = Policy() | ||||
| 
 | ||||
| #### General | ||||
| #### Section 0 | ||||
|  | @ -12,7 +38,7 @@ general_section = Section( | |||
|     title="General Info", | ||||
|     html_description="", | ||||
|     fields={ | ||||
|         "destination": {"label": "Destination City", "type": "string"} | ||||
|         "destination": {"label": "Destination City", "type": "string"}, | ||||
|     } | ||||
| ) | ||||
| 
 | ||||
|  | @ -22,7 +48,7 @@ general_section.add_rule( | |||
|     rule_break_text="What did the cowboy say about Tim, his wild horse?" | ||||
| ) | ||||
| 
 | ||||
| Policy.add_section(general_section) | ||||
| pol.add_section(general_section) | ||||
| 
 | ||||
| #### Flight | ||||
| #### Section 1 | ||||
|  | @ -43,7 +69,7 @@ flight_section.add_rule( | |||
|     rule_break_text="Fares cannot be more than $500" | ||||
| ) | ||||
| 
 | ||||
| Policy.add_section(flight_section) | ||||
| pol.add_section(flight_section) | ||||
| 
 | ||||
| #### Lodging | ||||
| #### Section 2 | ||||
|  | @ -64,13 +90,13 @@ def nightly_rate_check(report, section): | |||
|     duration = checkout_date - checkin_date | ||||
|     return section.fields.cost <= duration * section.fields.rate | ||||
| 
 | ||||
| section.add_rule( | ||||
| lodging_section.add_rule( | ||||
|     title="", | ||||
|     rule=nightly_rate_check, | ||||
|     rule_break_text="The average nightly rate cannot be more than the USGSA rate." | ||||
| ) | ||||
| 
 | ||||
| Policy.add_section(lodging_section) | ||||
| pol.add_section(lodging_section) | ||||
| 
 | ||||
| #### Local Transportation | ||||
| #### Section 3 | ||||
|  | @ -89,7 +115,7 @@ transport_section.add_rule( | |||
|     rule_break_text="Local transportation costs must be less than $10 per day, on average." | ||||
| ) | ||||
| 
 | ||||
| Policy.add_section(transport_section) | ||||
| pol.add_section(transport_section) | ||||
| 
 | ||||
| #### Per Diem | ||||
| #### Section 4 | ||||
|  | @ -109,24 +135,4 @@ per_diem_section.add_rule( | |||
|     rule_break_text="The average cost per day for per diem expenses cannot be more than the rate specified by the USGSA." | ||||
| ) | ||||
| 
 | ||||
| Policy.add_section(per_diem_section) | ||||
| 
 | ||||
| ''' | ||||
| Section( | ||||
|     title="", | ||||
|     html_description="<p></p>", | ||||
|     fields={ | ||||
|         "": {"label": "", "type": ""} | ||||
|     } | ||||
| ) | ||||
| 
 | ||||
| section.add_rule( | ||||
|     title="", | ||||
|     rule=lambda report, section: boolean_statement, | ||||
|     rule_break_text="" | ||||
| ) | ||||
| 
 | ||||
| #// or, for a rule which doesn’t apply to a specific section... | ||||
| #// | ||||
| #// add_general_rule(...) | ||||
| ''' | ||||
| pol.add_section(per_diem_section) | ||||
|  |  | |||
							
								
								
									
										3
									
								
								back/backend/test.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								back/backend/test.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| from policy import pol | ||||
| 
 | ||||
| print(pol) | ||||
|  | @ -1,7 +1,8 @@ | |||
| from rest_framework.decorators import api_view | ||||
| from django.http import JsonResponse | ||||
| from .models import * | ||||
| 
 | ||||
| from .policy import pol | ||||
| import json | ||||
| 
 | ||||
| # function that prints all the reports | ||||
| def get_reports(report_pk): | ||||
|  | @ -47,15 +48,14 @@ def get_sections(r_id): | |||
| def get_fields(s_id): | ||||
|     # create dict of arrays for fields | ||||
|     field_set = {"fields": []} | ||||
|     queryset = Field.objects.filter(section_id=s_id) | ||||
|     # queryset = Field.objects.all() | ||||
|     queryset = Field.objects.filter(section_id=s_id).order_by('number') | ||||
|     for i in queryset: | ||||
|         data = { | ||||
|             "field_name": "TODO", | ||||
|             "field_name": i.field_name, | ||||
|             "label": i.label, | ||||
|             "type": i.type, | ||||
|             "number": i.number, | ||||
|             "value": "get_value", | ||||
|             "value": "i.to_json()", | ||||
|         } | ||||
|         # append the fields to array | ||||
|         # use copy() to avoid overwriting | ||||
|  | @ -70,73 +70,34 @@ def report(request): | |||
|     ''' | ||||
|     Generate a new empty report and return it | ||||
|     ''' | ||||
|     data = { | ||||
|         "title": "2018 Portland trip", | ||||
|         "date_created": "2018-05-22T14:56:28.000Z", | ||||
|         "submitted": False, | ||||
|         "date_submitted": "0000-00-00T00:00:00.000Z", | ||||
|         "sections": [ | ||||
|             { | ||||
|                 "id": 1, | ||||
|                 "completed": True, | ||||
|                 "title": "Flight Info", | ||||
|                 "html_description": "<p>Enter flight details here.</p>", | ||||
|                 "fields": { | ||||
|                     "international": { | ||||
|                         "label": "International flight", | ||||
|                         "type": "boolean", | ||||
|                         "value": True | ||||
|                     }, | ||||
|                     "travel_date": { | ||||
|                         "label": "Travel start date", | ||||
|                         "type": "date", | ||||
|                         "value": "2016-05-22T14:56:28.000Z" | ||||
|                     }, | ||||
|                     "fare": { | ||||
|                         "label": "Fare", | ||||
|                         "type": "decimal", | ||||
|                         "value": "1024.99" | ||||
|                     }, | ||||
|                     "lowest_fare_screenshot": { | ||||
|                         "label": "Lowest fare screenshot", | ||||
|                         "type": "file", | ||||
|                         "value": "e92h842jiu49f8..." | ||||
|                     }, | ||||
|                     "plane_ticket_invoice": { | ||||
|                         "label": "Plane ticket invoice PDF", | ||||
|                         "type": "file", | ||||
|                         "value": "" | ||||
|                     } | ||||
|                 }, | ||||
|                 "rule_violations": [ | ||||
|                     { | ||||
|                         "error_text": "Plane ticket invoice must be submitted." | ||||
|                     } | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 "id": 2, | ||||
|                 "completed": False, | ||||
|                 "title": "Hotel info", | ||||
|                 "html_description": "<p>If you used a hotel, please enter the details.</p>", | ||||
|                 "fields": { | ||||
|                     "total": { | ||||
|                         "label": "Total cost", | ||||
|                         "type": "decimal" | ||||
|                     } | ||||
|                 }, | ||||
|                 "rule_violations": [ | ||||
|                 ] | ||||
|             } | ||||
|         ] | ||||
|     } | ||||
|      | ||||
|     # Create the report | ||||
|     report = Report.objects.create(user_id=request.user, title=request.data['title'], date_created=datetime.date.today()) | ||||
|     report.save() | ||||
| 
 | ||||
|     # Create the sections | ||||
|     for i in range(len(pol.sections)): | ||||
|         section = pol.sections[i] | ||||
|         s = Section.objects.create(report_id=report, auto_submit=section.auto_submit, required=section.required, completed=False, title=section.title, html_description=section.html_description, number=i) | ||||
|         s.save() | ||||
| 
 | ||||
|         # Create the fields | ||||
|         j = 0 | ||||
|         for key in section.fields: | ||||
|             field = section.fields[key] | ||||
|             f = Field.objects.create(section_id=s, field_name=key, label=field['label'], number=j, type=field['type'], completed=False) | ||||
|             f.save() | ||||
|             j = j+1 | ||||
|      | ||||
|     # Return the newly created report | ||||
|     data = get_reports(report.id) | ||||
|     return JsonResponse(data) | ||||
| 
 | ||||
| # List of reports | ||||
| @api_view(['GET']) | ||||
| def reports(request): | ||||
|     report_set = {"reports": []} | ||||
|     queryset = Report.objects.all() | ||||
|     queryset = Report.objects.all().order_by('date_created') | ||||
|     for i in queryset: | ||||
|         data = { | ||||
|             "report_pk": i.id, | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								back/db.sqlite3
									
										
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								back/db.sqlite3
									
										
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Daniel Dupriest
						Daniel Dupriest