Spaces:
Sleeping
Sleeping
Commit
Β·
cb7ff7d
1
Parent(s):
aa2cc5f
now saving personal, location and contractor details in the browser local storage correctly π
Browse files- app.py +76 -47
- form/form.py +2 -1
- local_storage/entities.py +21 -15
- local_storage/ls_manager.py +41 -0
- prompts/prompts_manager.py +19 -6
app.py
CHANGED
@@ -1,19 +1,21 @@
|
|
1 |
-
import
|
2 |
|
3 |
import streamlit as st
|
4 |
from streamlit import session_state as ss
|
5 |
-
from streamlit_local_storage import LocalStorage
|
6 |
|
7 |
from form.form import build_form_data_from_answers, write_pdf_form, work_categories
|
8 |
from llm_manager.llm_parser import LlmParser
|
9 |
from local_storage.entities import PersonalDetails, LocationDetails, ContractorDetails
|
|
|
10 |
from prompts.prompts_manager import PromptsManager, Questions as Q
|
11 |
from repository.repository import build_repo_from_environment, get_repository
|
12 |
from repository import ModelRoles, Model
|
13 |
from utils.parsing_utils import check_for_missing_answers
|
14 |
|
15 |
user_msg = "Please describe what you need to do. To get the best results try to answer all the following questions:"
|
16 |
-
|
|
|
|
|
17 |
class UIManager:
|
18 |
def __init__(self):
|
19 |
self.pm: PromptsManager = PromptsManager(work_categories=work_categories)
|
@@ -45,10 +47,14 @@ class UIManager:
|
|
45 |
|
46 |
def build_ui_for_parsing_answers(self):
|
47 |
self._build_base_ui()
|
|
|
|
|
|
|
|
|
48 |
with st.status("initialising LLM"):
|
49 |
self.repository.init()
|
50 |
with st.status("waiting for LLM"):
|
51 |
-
answer = self.repository.send_prompt(self.pm.verify_user_input_prompt(ss["user_input"]))
|
52 |
st.write(f"answers from LLM: {answer['content']}")
|
53 |
with st.status("Checking for missing answers"):
|
54 |
answers = LlmParser.parse_verification_prompt_answers(answer['content'])
|
@@ -80,15 +86,8 @@ class UIManager:
|
|
80 |
with st.status("finding the work categories applicable to your work"):
|
81 |
answer = self.repository.send_prompt(self.pm.get_work_category(ss["answers"][Q.WORK_TO_DO]))
|
82 |
categories = LlmParser.parse_get_categories_answer(answer['content'])
|
83 |
-
|
84 |
-
|
85 |
-
form_data, filename = build_form_data_from_answers(ss["answers"], categories,
|
86 |
-
ss.get("signature"))
|
87 |
-
pdf_form = write_pdf_form(form_data)
|
88 |
-
pdf_form_filename = filename
|
89 |
-
ss["pdf_form"] = pdf_form
|
90 |
-
ss["pdf_form_filename"] = pdf_form_filename
|
91 |
-
ss["step"] = "form_created"
|
92 |
st.rerun()
|
93 |
|
94 |
def build_ui_for_form_created(self):
|
@@ -104,44 +103,44 @@ class UIManager:
|
|
104 |
del ss["signature"]
|
105 |
st.rerun()
|
106 |
|
107 |
-
def
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
|
|
|
|
|
|
117 |
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
if submit_data:
|
128 |
-
for i in range(len(Q)):
|
129 |
-
ss["answers"][Q(i)] = ss[f"fq_{Q(i).name}"]
|
130 |
-
|
131 |
-
for details_key, func in [("your_details", self._get_personal_details),
|
132 |
-
("location_details", self._get_location_details),
|
133 |
-
("contractor_details", self._get_contractor_details)]:
|
134 |
-
details = func(details_key)
|
135 |
-
if details:
|
136 |
-
key = ss[details_key] # get the name under which this data should be saved
|
137 |
-
ls.setItem(key, json.dumps(details.__dict__), key)
|
138 |
-
ss["step"] = "check_category"
|
139 |
st.rerun()
|
140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
@staticmethod
|
142 |
def _get_personal_details(personal_details_key) -> PersonalDetails | None:
|
143 |
-
|
144 |
-
|
|
|
|
|
145 |
return None
|
146 |
|
147 |
@staticmethod
|
@@ -159,6 +158,34 @@ class UIManager:
|
|
159 |
return None
|
160 |
|
161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
def use_streamlit():
|
163 |
|
164 |
um = UIManager()
|
@@ -168,11 +195,13 @@ def use_streamlit():
|
|
168 |
if um.get_current_step() == "parsing_answers":
|
169 |
um.build_ui_for_parsing_answers()
|
170 |
if um.get_current_step() == "parsing_error":
|
171 |
-
um.
|
172 |
if um.get_current_step() == "ask_again":
|
173 |
um.build_ui_for_ask_again()
|
174 |
if um.get_current_step() == "check_category":
|
175 |
um.build_ui_for_check_category()
|
|
|
|
|
176 |
if um.get_current_step() == "form_created":
|
177 |
um.build_ui_for_form_created()
|
178 |
|
|
|
1 |
+
import re
|
2 |
|
3 |
import streamlit as st
|
4 |
from streamlit import session_state as ss
|
|
|
5 |
|
6 |
from form.form import build_form_data_from_answers, write_pdf_form, work_categories
|
7 |
from llm_manager.llm_parser import LlmParser
|
8 |
from local_storage.entities import PersonalDetails, LocationDetails, ContractorDetails
|
9 |
+
from local_storage.ls_manager import save_details, get_detail
|
10 |
from prompts.prompts_manager import PromptsManager, Questions as Q
|
11 |
from repository.repository import build_repo_from_environment, get_repository
|
12 |
from repository import ModelRoles, Model
|
13 |
from utils.parsing_utils import check_for_missing_answers
|
14 |
|
15 |
user_msg = "Please describe what you need to do. To get the best results try to answer all the following questions:"
|
16 |
+
|
17 |
+
find_tags_regex = re.compile(r"(@\S)")
|
18 |
+
|
19 |
class UIManager:
|
20 |
def __init__(self):
|
21 |
self.pm: PromptsManager = PromptsManager(work_categories=work_categories)
|
|
|
47 |
|
48 |
def build_ui_for_parsing_answers(self):
|
49 |
self._build_base_ui()
|
50 |
+
with st.status("parsing user input for tags"):
|
51 |
+
tags = find_tags_regex.findall(ss["user_input"])
|
52 |
+
details = [get_detail(t) for t in tags]
|
53 |
+
ss["details"] = details
|
54 |
with st.status("initialising LLM"):
|
55 |
self.repository.init()
|
56 |
with st.status("waiting for LLM"):
|
57 |
+
answer = self.repository.send_prompt(self.pm.verify_user_input_prompt(ss["user_input"], details))
|
58 |
st.write(f"answers from LLM: {answer['content']}")
|
59 |
with st.status("Checking for missing answers"):
|
60 |
answers = LlmParser.parse_verification_prompt_answers(answer['content'])
|
|
|
86 |
with st.status("finding the work categories applicable to your work"):
|
87 |
answer = self.repository.send_prompt(self.pm.get_work_category(ss["answers"][Q.WORK_TO_DO]))
|
88 |
categories = LlmParser.parse_get_categories_answer(answer['content'])
|
89 |
+
ss["categories"] = categories
|
90 |
+
ss["step"] = "validate_data"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
st.rerun()
|
92 |
|
93 |
def build_ui_for_form_created(self):
|
|
|
103 |
del ss["signature"]
|
104 |
st.rerun()
|
105 |
|
106 |
+
def _integrate_llm_answers_with_user_corrections(self):
|
107 |
+
for i in range(len(Q)):
|
108 |
+
ss["answers"][Q(i)] = ss[f"fq_{Q(i).name}"]
|
109 |
+
|
110 |
+
for details_key, func in [("your_details", self._get_personal_details),
|
111 |
+
("location_details", self._get_location_details),
|
112 |
+
("contractor_details", self._get_contractor_details)]:
|
113 |
+
details = func(details_key)
|
114 |
+
if details:
|
115 |
+
key = ss[details_key] # get the name under which this data should be saved
|
116 |
+
save_details(details, key)
|
117 |
+
ss["step"] = "check_categories"
|
118 |
+
st.rerun()
|
119 |
|
120 |
+
def _create_pdf_form(self):
|
121 |
+
with st.status("categories found, creating PDF form"):
|
122 |
+
form_data, filename = build_form_data_from_answers(ss["answers"], ss["categories"],
|
123 |
+
ss.get("signature"))
|
124 |
+
pdf_form = write_pdf_form(form_data)
|
125 |
+
pdf_form_filename = filename
|
126 |
+
ss["pdf_form"] = pdf_form
|
127 |
+
ss["pdf_form_filename"] = pdf_form_filename
|
128 |
+
ss["step"] = "form_created"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
st.rerun()
|
130 |
|
131 |
+
def build_ui_for_validate_data_after_correction(self):
|
132 |
+
self._build_validation_form(False, self._integrate_llm_answers_with_user_corrections)
|
133 |
+
|
134 |
+
def build_ui_to_confirm_form_data(self):
|
135 |
+
self._build_validation_form(True, self._create_pdf_form)
|
136 |
+
|
137 |
+
|
138 |
@staticmethod
|
139 |
def _get_personal_details(personal_details_key) -> PersonalDetails | None:
|
140 |
+
key_ = ss.get(personal_details_key)
|
141 |
+
if key_:
|
142 |
+
details = PersonalDetails(ss[f"fq_{Q.FULL_NAME.name}"], ss[f"fq_{Q.YOUR_EMAIL.name}"], ss[f"fq_{Q.CONTACT_NUMBER.name}"])
|
143 |
+
return details
|
144 |
return None
|
145 |
|
146 |
@staticmethod
|
|
|
158 |
return None
|
159 |
|
160 |
|
161 |
+
|
162 |
+
def _build_validation_form(self, show_categories:bool, onsubmit):
|
163 |
+
def build_form_fragment(form_, col, title, add_save, *questions):
|
164 |
+
form_.text(title)
|
165 |
+
for user_data in questions:
|
166 |
+
with col:
|
167 |
+
form_.text_input(self.pm.questions_to_field_labels()[user_data], value=ss.get("answers", {})
|
168 |
+
.get(user_data), key=f"fq_{user_data.name}")
|
169 |
+
if add_save:
|
170 |
+
with col:
|
171 |
+
form_.text_input("Save as", key=title.replace(" ", "_"))
|
172 |
+
|
173 |
+
self._build_base_ui()
|
174 |
+
f = st.form("Please check the following information and correct fix any inaccuracies")
|
175 |
+
col1, col2 = f.columns(2)
|
176 |
+
build_form_fragment(f, col1, "your details", True, Q.FULL_NAME, Q.CONTACT_NUMBER, Q.YOUR_EMAIL)
|
177 |
+
build_form_fragment(f, col2, "work details", False, Q.WORK_TO_DO, Q.START_DATE, Q.END_DATE)
|
178 |
+
build_form_fragment(f, col1, "location details", True, Q.COMMUNITY, Q.BUILDING, Q.UNIT_APT_NUMBER,
|
179 |
+
Q.OWNER_OR_TENANT)
|
180 |
+
build_form_fragment(f, col2, "contractor details", True, Q.COMPANY_NAME, Q.COMPANY_NUMBER, Q.COMPANY_EMAIL)
|
181 |
+
if show_categories:
|
182 |
+
for k, wc in work_categories.items():
|
183 |
+
f.checkbox(label=wc, key=k, value=k in ss["categories"])
|
184 |
+
|
185 |
+
submit_data = f.form_submit_button()
|
186 |
+
if submit_data:
|
187 |
+
onsubmit()
|
188 |
+
|
189 |
def use_streamlit():
|
190 |
|
191 |
um = UIManager()
|
|
|
195 |
if um.get_current_step() == "parsing_answers":
|
196 |
um.build_ui_for_parsing_answers()
|
197 |
if um.get_current_step() == "parsing_error":
|
198 |
+
um.build_ui_for_validate_data_after_correction()
|
199 |
if um.get_current_step() == "ask_again":
|
200 |
um.build_ui_for_ask_again()
|
201 |
if um.get_current_step() == "check_category":
|
202 |
um.build_ui_for_check_category()
|
203 |
+
if um.get_current_step() == "validate_form_data":
|
204 |
+
um.build_ui_to_confirm_form_data()
|
205 |
if um.get_current_step() == "form_created":
|
206 |
um.build_ui_for_form_created()
|
207 |
|
form/form.py
CHANGED
@@ -116,4 +116,5 @@ work_categories = {"other_work": "other work", "civil": "Civil work, masonry",
|
|
116 |
"kitchen_refurbish": "kitchen renovation or refurbishment",
|
117 |
"lights_and_sockets": "installation of lights, ceiling lights, power sockets",
|
118 |
"painting_wallpapering": "painting, wallpaper installation",
|
119 |
-
"seating_area_barbecuing_fountain": "installation or renovation of outdoor structures such
|
|
|
|
116 |
"kitchen_refurbish": "kitchen renovation or refurbishment",
|
117 |
"lights_and_sockets": "installation of lights, ceiling lights, power sockets",
|
118 |
"painting_wallpapering": "painting, wallpaper installation",
|
119 |
+
"seating_area_barbecuing_fountain": "installation or renovation of outdoor structures such "
|
120 |
+
"as seating area, barbecuing area or fountains"}
|
local_storage/entities.py
CHANGED
@@ -1,31 +1,37 @@
|
|
1 |
import abc
|
2 |
-
import
|
3 |
|
4 |
-
from streamlit_local_storage import LocalStorage
|
5 |
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
|
9 |
class SavedDetails(abc.ABC):
|
10 |
-
def __init__(self, type_: str):
|
11 |
-
self.type_ = type_
|
12 |
|
13 |
-
|
14 |
-
|
|
|
15 |
|
16 |
@classmethod
|
17 |
-
def load(cls,
|
18 |
-
data = json.loads(json_data)
|
19 |
type_ = data.get("type_")
|
20 |
if not type_ or type_ != cls.type_:
|
21 |
raise ValueError(f"the expected type is {cls.type_} but is actually {type_}")
|
22 |
return cls.__init__(**{k: v for k, v in data if k != "type"})
|
23 |
|
|
|
|
|
24 |
|
25 |
class PersonalDetails(SavedDetails):
|
26 |
-
type_ =
|
27 |
|
28 |
-
def __init__(self, full_name, email, contact_number):
|
29 |
super().__init__(self.type_)
|
30 |
self.full_name = full_name
|
31 |
self.email = email
|
@@ -33,9 +39,9 @@ class PersonalDetails(SavedDetails):
|
|
33 |
|
34 |
|
35 |
class LocationDetails(SavedDetails):
|
36 |
-
type_ =
|
37 |
|
38 |
-
def __init__(self, owner_or_tenant: str, community: str, building: str, unit_number: str):
|
39 |
super().__init__(self.type_)
|
40 |
self.owner_or_tenant = owner_or_tenant
|
41 |
self.community = community
|
@@ -44,9 +50,9 @@ class LocationDetails(SavedDetails):
|
|
44 |
|
45 |
|
46 |
class ContractorDetails(SavedDetails):
|
47 |
-
type_ =
|
48 |
|
49 |
-
def __init__(self, contractor_name:str, contractor_contact_number:str, contractor_email:str):
|
50 |
super().__init__(self.type_)
|
51 |
self.contractor_name = contractor_name
|
52 |
self.contractor_contact_number = contractor_contact_number
|
|
|
1 |
import abc
|
2 |
+
from enum import Enum
|
3 |
|
|
|
4 |
|
5 |
+
class DetailsType(Enum):
|
6 |
+
PERSONAL_DETAILS = 1
|
7 |
+
LOCATION_DETAILS = 2
|
8 |
+
CONTRACTOR_DETAILS = 3
|
9 |
+
|
10 |
+
@classmethod
|
11 |
+
def values(cls):
|
12 |
+
return [cls.PERSONAL_DETAILS, cls.LOCATION_DETAILS, cls.CONTRACTOR_DETAILS]
|
13 |
|
14 |
|
15 |
class SavedDetails(abc.ABC):
|
|
|
|
|
16 |
|
17 |
+
excluded_fields = ["type_"]
|
18 |
+
def __init__(self, type_: DetailsType):
|
19 |
+
self.type_ = type_
|
20 |
|
21 |
@classmethod
|
22 |
+
def load(cls, data: dict):
|
|
|
23 |
type_ = data.get("type_")
|
24 |
if not type_ or type_ != cls.type_:
|
25 |
raise ValueError(f"the expected type is {cls.type_} but is actually {type_}")
|
26 |
return cls.__init__(**{k: v for k, v in data if k != "type"})
|
27 |
|
28 |
+
def to_json(self):
|
29 |
+
return {k:v for k,v in self.__dict__.items() if k not in self.excluded_fields}
|
30 |
|
31 |
class PersonalDetails(SavedDetails):
|
32 |
+
type_ = DetailsType.PERSONAL_DETAILS
|
33 |
|
34 |
+
def __init__(self, full_name, email, contact_number, *_):
|
35 |
super().__init__(self.type_)
|
36 |
self.full_name = full_name
|
37 |
self.email = email
|
|
|
39 |
|
40 |
|
41 |
class LocationDetails(SavedDetails):
|
42 |
+
type_ = DetailsType.LOCATION_DETAILS
|
43 |
|
44 |
+
def __init__(self, owner_or_tenant: str, community: str, building: str, unit_number: str, *_):
|
45 |
super().__init__(self.type_)
|
46 |
self.owner_or_tenant = owner_or_tenant
|
47 |
self.community = community
|
|
|
50 |
|
51 |
|
52 |
class ContractorDetails(SavedDetails):
|
53 |
+
type_ = DetailsType.CONTRACTOR_DETAILS
|
54 |
|
55 |
+
def __init__(self, contractor_name: str, contractor_contact_number: str, contractor_email: str, *_):
|
56 |
super().__init__(self.type_)
|
57 |
self.contractor_name = contractor_name
|
58 |
self.contractor_contact_number = contractor_contact_number
|
local_storage/ls_manager.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
|
3 |
+
from streamlit_local_storage import LocalStorage
|
4 |
+
|
5 |
+
from local_storage.entities import DetailsType, SavedDetails, PersonalDetails, LocationDetails, ContractorDetails
|
6 |
+
|
7 |
+
ls = LocalStorage()
|
8 |
+
|
9 |
+
|
10 |
+
def get_detail(key: str):
|
11 |
+
for detail_type in DetailsType.values():
|
12 |
+
detail = json.loads((ls.getItem(detail_type.name) or {}).get(key))
|
13 |
+
if detail:
|
14 |
+
type_ = detail["type"]
|
15 |
+
if type_ == DetailsType.PERSONAL_DETAILS.name:
|
16 |
+
return PersonalDetails(**detail)
|
17 |
+
elif type_ == DetailsType.LOCATION_DETAILS.name:
|
18 |
+
return LocationDetails(**detail)
|
19 |
+
elif type_ == DetailsType.CONTRACTOR_DETAILS.name:
|
20 |
+
return ContractorDetails(**detail)
|
21 |
+
return None
|
22 |
+
return None
|
23 |
+
|
24 |
+
|
25 |
+
def save_details(details: SavedDetails, key: str):
|
26 |
+
if isinstance(details, PersonalDetails):
|
27 |
+
type_ = DetailsType.PERSONAL_DETAILS
|
28 |
+
elif isinstance(details, LocationDetails):
|
29 |
+
type_ = DetailsType.LOCATION_DETAILS
|
30 |
+
elif isinstance(details, ContractorDetails):
|
31 |
+
type_ = DetailsType.CONTRACTOR_DETAILS
|
32 |
+
else:
|
33 |
+
raise ValueError("Unexpected type: {}", type(details))
|
34 |
+
existing_data = json.loads(ls.getItem(type_.name) or "{}")
|
35 |
+
existing_data[key] = details.to_json()
|
36 |
+
ls.setItem(type_.name, existing_data, type_.name)
|
37 |
+
|
38 |
+
|
39 |
+
def get_details(type_: DetailsType):
|
40 |
+
return json.loads((ls.getItem(type_.name) or "{}"))
|
41 |
+
|
prompts/prompts_manager.py
CHANGED
@@ -2,6 +2,7 @@ import datetime
|
|
2 |
from enum import Enum
|
3 |
from pathlib import Path
|
4 |
|
|
|
5 |
from utils.date_utils import get_today_date_as_dd_mm_yyyy
|
6 |
|
7 |
|
@@ -33,13 +34,18 @@ class PromptsManager:
|
|
33 |
todays_date = get_today_date_as_dd_mm_yyyy()
|
34 |
verification_prompt = verification_prompt.replace("{today}", todays_date)
|
35 |
self.verification_prompt: str = verification_prompt
|
|
|
36 |
|
37 |
-
def verify_user_input_prompt(self, user_prompt) -> str:
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
|
|
|
|
|
|
|
|
43 |
|
44 |
def get_work_category(self, work_description: str) -> str:
|
45 |
return (
|
@@ -57,4 +63,11 @@ class PromptsManager:
|
|
57 |
Questions.COMPANY_NAME: "Contractor company name", Questions.COMPANY_EMAIL: "Contracting company email",
|
58 |
Questions.COMPANY_NUMBER: "Contracting company contact number", Questions.YOUR_EMAIL: "Your email"
|
59 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
|
|
|
2 |
from enum import Enum
|
3 |
from pathlib import Path
|
4 |
|
5 |
+
from local_storage.entities import DetailsType, SavedDetails
|
6 |
from utils.date_utils import get_today_date_as_dd_mm_yyyy
|
7 |
|
8 |
|
|
|
34 |
todays_date = get_today_date_as_dd_mm_yyyy()
|
35 |
verification_prompt = verification_prompt.replace("{today}", todays_date)
|
36 |
self.verification_prompt: str = verification_prompt
|
37 |
+
self.verification_prompt_questions = self.verification_prompt.split("\n")
|
38 |
|
39 |
+
def verify_user_input_prompt(self, user_prompt, exclude_questions_group: list[SavedDetails] = None) -> str:
|
40 |
+
prompt = f"""
|
41 |
+
Using only this information \n {user_prompt} \n answer the following questions, for each question that you cannot answer just answer 'null'.
|
42 |
+
Put each answer in a new line, keep the answer brief
|
43 |
+
and maintain the order in which the questions are asked. Do not add any preamble:
|
44 |
+
"""
|
45 |
+
|
46 |
+
skip_questions = [self.get_questions(d) for d in exclude_questions_group]
|
47 |
+
questions = [q for idx, q in enumerate(self.verification_prompt_questions) if idx not in skip_questions]
|
48 |
+
return prompt + "\n".join(questions)
|
49 |
|
50 |
def get_work_category(self, work_description: str) -> str:
|
51 |
return (
|
|
|
63 |
Questions.COMPANY_NAME: "Contractor company name", Questions.COMPANY_EMAIL: "Contracting company email",
|
64 |
Questions.COMPANY_NUMBER: "Contracting company contact number", Questions.YOUR_EMAIL: "Your email"
|
65 |
}
|
66 |
+
def get_questions(self, type_:DetailsType):
|
67 |
+
if type_ == DetailsType.PERSONAL_DETAILS:
|
68 |
+
return [Questions.FULL_NAME, Questions.CONTACT_NUMBER, Questions.YOUR_EMAIL]
|
69 |
+
if type_ == DetailsType.CONTRACTOR_DETAILS:
|
70 |
+
return [Questions.COMPANY_NAME, Questions.COMPANY_NUMBER, Questions.COMPANY_EMAIL]
|
71 |
+
if type_ == DetailsType.LOCATION_DETAILS:
|
72 |
+
return [Questions.OWNER_OR_TENANT, Questions.COMMUNITY, Questions.BUILDING, Questions.UNIT_APT_NUMBER]
|
73 |
|