2019-01-30 00:39:35 +00:00
|
|
|
from datetime import date
|
|
|
|
|
2019-02-16 20:11:37 +00:00
|
|
|
#### Classes for policy, sections. Do not edit these.
|
|
|
|
#####################################################
|
2019-01-30 00:39:35 +00:00
|
|
|
|
2019-02-07 23:32:21 +00:00
|
|
|
class Policy():
|
2019-02-16 20:11:37 +00:00
|
|
|
"""
|
|
|
|
Represents the policy for the company/organization.
|
|
|
|
"""
|
2019-02-07 23:32:21 +00:00
|
|
|
def __init__(self):
|
2019-02-16 20:11:37 +00:00
|
|
|
"""
|
|
|
|
Creates a new Policy object.
|
|
|
|
"""
|
2019-02-07 23:32:21 +00:00
|
|
|
self.sections = []
|
|
|
|
|
|
|
|
def add_section(self, section):
|
2019-02-16 20:11:37 +00:00
|
|
|
"""
|
|
|
|
Appends the specified section to the policy in order.
|
|
|
|
|
|
|
|
section -- Section object to append.
|
|
|
|
"""
|
2019-02-07 23:32:21 +00:00
|
|
|
self.sections.append(section)
|
|
|
|
|
|
|
|
class Section():
|
2019-02-16 20:11:37 +00:00
|
|
|
"""
|
|
|
|
Represents a logical division of te policy, containing
|
|
|
|
data fields for users to enter, and rules which
|
|
|
|
apply to those fields.
|
|
|
|
"""
|
|
|
|
def __init__(self, title="Section", html_description="", required=False, auto_submit=False, fields={}):
|
|
|
|
"""
|
|
|
|
Creates a new Section object.
|
|
|
|
|
|
|
|
title -- This is the name for the section the user sees.
|
|
|
|
html_description -- This is html displayed beneath the title.
|
|
|
|
required -- If True, user must complete before submitting.
|
|
|
|
auto_submit -- Completing this section notifies the administrator.
|
|
|
|
fields -- A python object of fields the user should enter.
|
|
|
|
"""
|
2019-02-07 23:32:21 +00:00
|
|
|
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=""):
|
2019-02-16 20:11:37 +00:00
|
|
|
"""
|
|
|
|
Assigns a new rule to the section.
|
|
|
|
|
|
|
|
title -- Administrative title for the rule.
|
|
|
|
rule -- lambda expression which must evaluate true to pass the rule.
|
|
|
|
rule_break_text -- Error message to show the user when rule is broken.
|
|
|
|
"""
|
2019-02-07 23:32:21 +00:00
|
|
|
rule = {
|
|
|
|
"title": title,
|
|
|
|
"rule": rule,
|
|
|
|
"rule_break_text": rule_break_text,
|
|
|
|
}
|
|
|
|
self.rules.append(rule)
|
|
|
|
|
|
|
|
pol = Policy()
|
2019-01-30 00:39:35 +00:00
|
|
|
|
2019-02-16 20:11:37 +00:00
|
|
|
#### Policy configuration begins here. Edit below this line.
|
|
|
|
############################################################
|
|
|
|
|
2019-01-30 00:39:35 +00:00
|
|
|
#### General
|
|
|
|
#### Section 0
|
|
|
|
general_section = Section(
|
|
|
|
title="General Info",
|
|
|
|
html_description="",
|
|
|
|
fields={
|
2019-02-15 22:59:42 +00:00
|
|
|
"destination": {"number": 0, "label": "Destination City", "field_type": "string"},
|
2019-01-30 00:39:35 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
general_section.add_rule(
|
|
|
|
title="Destination city check",
|
2019-02-14 22:19:15 +00:00
|
|
|
rule=lambda report, fields: fields['destination'] == "Timbuktu",
|
2019-01-30 00:39:35 +00:00
|
|
|
rule_break_text="What did the cowboy say about Tim, his wild horse?"
|
|
|
|
)
|
|
|
|
|
2019-02-07 23:32:21 +00:00
|
|
|
pol.add_section(general_section)
|
2019-01-30 00:39:35 +00:00
|
|
|
|
|
|
|
#### Flight
|
|
|
|
#### Section 1
|
|
|
|
flight_section = Section(
|
|
|
|
title="Flight Info",
|
|
|
|
html_description="<p>Enter flight details here.</p>",
|
|
|
|
fields={
|
2019-02-15 22:59:42 +00:00
|
|
|
"international": {"number": 0, "label": "Is this an international flight?", "field_type": "boolean"},
|
|
|
|
"departure_date": {"number": 1, "label": "Departure date", "field_type": "date"},
|
|
|
|
"return_date": {"number": 2, "label": "Return date", "field_type": "date"},
|
|
|
|
"fare": {"number": 3, "label": "Fare", "field_type": "decimal"},
|
|
|
|
"layovers": {"number": 4, "label": "Transit wait", "field_type": "integer"},
|
|
|
|
"fare_search_screenshot": {"number": 5, "label": "Screenshot of fare search", "field_type": "file"},
|
2019-01-30 00:39:35 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
flight_section.add_rule(
|
|
|
|
title="Airline fare pre-approval check",
|
2019-02-14 22:19:15 +00:00
|
|
|
rule=lambda report, fields: fields['fare'] < 500,
|
2019-01-30 00:39:35 +00:00
|
|
|
rule_break_text="Fares cannot be more than $500"
|
|
|
|
)
|
|
|
|
|
2019-02-07 23:32:21 +00:00
|
|
|
pol.add_section(flight_section)
|
2019-01-30 00:39:35 +00:00
|
|
|
|
|
|
|
#### Lodging
|
|
|
|
#### Section 2
|
|
|
|
lodging_section = Section(
|
|
|
|
title="Hotel Info",
|
2019-02-08 01:13:43 +00:00
|
|
|
html_description="<p>Enter hotel info here.\nPer diem rates can be found at "
|
2019-02-15 23:18:02 +00:00
|
|
|
"<a href='https://www.gsa.gov/travel/plan-book/per-diem-rates' target='_blank'>this link</a></p>",
|
2019-01-30 00:39:35 +00:00
|
|
|
fields={
|
2019-02-15 22:59:42 +00:00
|
|
|
"check-in_date": {"number": 0, "label": "Check-in date", "field_type": "date"},
|
|
|
|
"check-out_date": {"number": 1, "label": "Check-out date", "field_type": "date"},
|
|
|
|
"rate": {"number": 2, "label": "Per diem nightly rate", "field_type": "decimal"},
|
|
|
|
"cost": {"number": 3, "label": "Total Cost", "field_type": "decimal"}
|
2019-01-30 00:39:35 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2019-02-14 22:19:15 +00:00
|
|
|
def nightly_rate_check(report, fields):
|
|
|
|
checkin_date = date(fields['checkin_date'])
|
|
|
|
checkout_date = date(fields['checkout_date'])
|
2019-01-30 00:39:35 +00:00
|
|
|
duration = checkout_date - checkin_date
|
2019-02-14 22:19:15 +00:00
|
|
|
return fields['cost'] <= duration * fields['rate']
|
2019-01-30 00:39:35 +00:00
|
|
|
|
2019-02-07 23:32:21 +00:00
|
|
|
lodging_section.add_rule(
|
2019-02-14 22:19:15 +00:00
|
|
|
title="Average nightly rate",
|
2019-01-30 00:39:35 +00:00
|
|
|
rule=nightly_rate_check,
|
|
|
|
rule_break_text="The average nightly rate cannot be more than the USGSA rate."
|
|
|
|
)
|
|
|
|
|
2019-02-07 23:32:21 +00:00
|
|
|
pol.add_section(lodging_section)
|
2019-01-30 00:39:35 +00:00
|
|
|
|
|
|
|
#### Local Transportation
|
|
|
|
#### Section 3
|
|
|
|
transport_section = Section(
|
|
|
|
title="Local Transportation",
|
|
|
|
html_description="<p>How much did you spend on local transportation, in total?</p>",
|
|
|
|
fields={
|
2019-02-15 22:59:42 +00:00
|
|
|
"duration": {"number":0, "label": "How many days was your trip?", "field_type": "integer"},
|
|
|
|
"cost": {"number":1, "label": "Total cost", "field_type": "decimal"}
|
2019-01-30 00:39:35 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
transport_section.add_rule(
|
|
|
|
title="Total cost check",
|
2019-02-14 22:19:15 +00:00
|
|
|
rule=lambda report, fields: fields['cost'] <= fields['duration'] * 10,
|
2019-01-30 00:39:35 +00:00
|
|
|
rule_break_text="Local transportation costs must be less than $10 per day, on average."
|
|
|
|
)
|
|
|
|
|
2019-02-07 23:32:21 +00:00
|
|
|
pol.add_section(transport_section)
|
2019-01-30 00:39:35 +00:00
|
|
|
|
|
|
|
#### Per Diem
|
|
|
|
#### Section 4
|
|
|
|
per_diem_section = Section(
|
|
|
|
title="Per Diem",
|
2019-02-10 20:44:26 +00:00
|
|
|
html_description="<p>Enter info about meals and incidentals here.\nPer diem rates can be found at "
|
2019-02-15 23:18:02 +00:00
|
|
|
"<a href='https://www.gsa.gov/travel/plan-book/per-diem-rates' target='_blank'>this link</a></p>",
|
2019-01-30 00:39:35 +00:00
|
|
|
fields={
|
2019-02-15 22:59:42 +00:00
|
|
|
"duration": {"number":0, "label": "How many days was your trip?", "field_type": "integer"},
|
|
|
|
"rate": {"number":1, "label": "What is the per diem rate for your destination?", "field_type": "decimal"},
|
|
|
|
"cost": {"number":2,"label": "Total Cost for meals and incidentals", "field_type": "decimal"}
|
2019-01-30 00:39:35 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
per_diem_section.add_rule(
|
|
|
|
title="Per Diem Cost Check",
|
2019-02-14 22:19:15 +00:00
|
|
|
rule=lambda report, fields: fields['cost'] <= fields['duration'] * fields['rate'],
|
2019-01-30 00:39:35 +00:00
|
|
|
rule_break_text="The average cost per day for per diem expenses cannot be more than the rate specified by the USGSA."
|
|
|
|
)
|
|
|
|
|
2019-02-07 23:32:21 +00:00
|
|
|
pol.add_section(per_diem_section)
|