mrfirdauss commited on
Commit
2883543
·
1 Parent(s): 71ec80a

feat done all docs gen

Browse files
README.md CHANGED
@@ -36,6 +36,9 @@ It currently supports:
36
  | `/generate/<doc-type>` | POST | Generate a document |
37
  | `/generate/schengen` | POST | Generate a Schengen visa cover letter for a group/family trip |
38
  | `/generate/japan-multientry` | POST | Generate a Japan multi-entry visa support letter |
 
 
 
39
 
40
  ---
41
 
@@ -56,7 +59,6 @@ curl -X POST http://localhost:5000/generate/schengen \
56
  -d '{
57
  "country": "Germany",
58
  "city": "Jakarta",
59
- "date": "18th July 2024",
60
  "purpose": "tourism",
61
  "main_destination": "Germany",
62
  "event": "personal vacation",
@@ -87,7 +89,6 @@ curl -X POST http://localhost:5000/generate/schengen/group \
87
  -d '{
88
  "country": "Germany",
89
  "city": "Jakarta",
90
- "date": "18th July 2024",
91
  "purpose": "family visit",
92
  "main_destination": "Germany",
93
  "event": "family gathering",
@@ -133,12 +134,12 @@ curl -X POST http://localhost:5000/generate/schengen/group \
133
  ### Endpoint
134
 
135
  ```
136
- POST /generate/japan-multientry
137
  ```
138
 
139
  #### Sample Requests
140
  ```bash
141
- curl -X POST http://localhost:5000/generate/japan-multientry \
142
  -H "Content-Type: application/json" \
143
  -d '{
144
  "name": "John Doe",
@@ -157,5 +158,134 @@ curl -X POST http://localhost:5000/generate/japan-multientry \
157
 
158
  ```
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  ---
161
 
 
36
  | `/generate/<doc-type>` | POST | Generate a document |
37
  | `/generate/schengen` | POST | Generate a Schengen visa cover letter for a group/family trip |
38
  | `/generate/japan-multientry` | POST | Generate a Japan multi-entry visa support letter |
39
+ | `/generate/sponsorship` | POST | Generate sponsorship letter |
40
+ | `/generate/housewife-statement` | POST | Generate housewife statement letter |
41
+ | `/generate/passport-collection | POST | Generate passport collection consent letter |
42
 
43
  ---
44
 
 
59
  -d '{
60
  "country": "Germany",
61
  "city": "Jakarta",
 
62
  "purpose": "tourism",
63
  "main_destination": "Germany",
64
  "event": "personal vacation",
 
89
  -d '{
90
  "country": "Germany",
91
  "city": "Jakarta",
 
92
  "purpose": "family visit",
93
  "main_destination": "Germany",
94
  "event": "family gathering",
 
134
  ### Endpoint
135
 
136
  ```
137
+ POST /generate/japan-multientry-tourist
138
  ```
139
 
140
  #### Sample Requests
141
  ```bash
142
+ curl -X POST http://localhost:5000/generate/japan-multientry-tourist \
143
  -H "Content-Type: application/json" \
144
  -d '{
145
  "name": "John Doe",
 
158
 
159
  ```
160
 
161
+ ## Sponsorshi Letter
162
+
163
+ ### **Endpoint**
164
+ ```
165
+ POST /generate/sponsorship
166
+ ```
167
+
168
+
169
+ ### **Sample Request**
170
+
171
+ ```bash
172
+ curl -X POST http://localhost:5000/generate/sponsorship \
173
+ -H "Content-Type: application/json" \
174
+ -d '{
175
+ "sponsor_name": "Mr. John Sponsor",
176
+ "sponsor_address": "123 Sponsor St, Appt 4B",
177
+ "sponsor_postal_code": "New York, NY 10001",
178
+ "sponsor_email": "john.sponsor@email.com",
179
+ "sponsor_contact_number": "+1 (555) 123-4567",
180
+
181
+ "officer_title": "Visa Officer",
182
+ "embassy_name": "Embassy of [Country]",
183
+ "embassy_address": "456 Embassy Row",
184
+ "embassy_city_state_postal": "Washington, D.C. 20008",
185
+
186
+ "applicant_name": "Ms. Jane Applicant",
187
+ "applicant_dob": "January 15, 1995",
188
+ "applicant_passport_no": "X12345678",
189
+
190
+ "visa_name": "B-2 Visitor Visa",
191
+ "sponsor_relationship": "friend",
192
+ "visit_reason": "attend my wedding and for tourism",
193
+ "destination_country": "the United States",
194
+ "visit_start_date": "December 1, 2024",
195
+ "visit_end_date": "December 20, 2024",
196
+ "visit_purpose_details": "a personal visit to attend my wedding ceremony on December 5th and to tour New York City"
197
+ }' -- output document.pdf
198
+ ```
199
+
200
+ ## Housewife Statement Letter
201
+
202
+ ### **Endpoint**
203
+ ```
204
+ POST /generate/housewife-statement
205
+ ```
206
+
207
+
208
+ ### **Sample Request**
209
+
210
+ ```bash
211
+ curl -X POST http://localhost:5000/generate/housewife-statement \
212
+ -H "Content-Type: application/json" \
213
+ -d '{
214
+ "applicant_name": "Mrs. Sarah Wijaya",
215
+ "applicant_dob": "Jakarta, April 10, 1985",
216
+ "applicant_passport": "B1234567",
217
+ "sponsor_name": "Mr. Budi Wijaya",
218
+ "sponsor_bank_details": "Bank Central Asia (BCA): 123-456-7890",
219
+ "destination_country": "Japan",
220
+ "visa_type": "tourism",
221
+ "visit_end_date": "November 20, 2024",
222
+ "travel_companions": "my husband, Budi Wijaya, and my son, Putra Wijaya",
223
+ "letter_location": "Jakarta",
224
+ "letter_date": "October 28, 2024"
225
+ }' -- output Schengen_Visa_Cover_Letter.pdf
226
+ ```
227
+
228
+ ## Sponsorshi Letter
229
+
230
+ ### **Endpoint**
231
+ ```
232
+ POST /generate/sponsorship
233
+ ```
234
+
235
+
236
+ ### **Sample Request**
237
+
238
+ ```bash
239
+ curl -X POST http://localhost:5000/generate/sponsorship \
240
+ -H "Content-Type: application/json" \
241
+ -d '{
242
+ "sponsor_name": "Mr. John Sponsor",
243
+ "sponsor_address": "123 Sponsor St, Appt 4B",
244
+ "sponsor_postal_code": "New York, NY 10001",
245
+ "sponsor_email": "john.sponsor@email.com",
246
+ "sponsor_contact_number": "+1 (555) 123-4567",
247
+
248
+ "officer_title": "Visa Officer",
249
+ "embassy_name": "Embassy of [Country]",
250
+ "embassy_address": "456 Embassy Row",
251
+ "embassy_city_state_postal": "Washington, D.C. 20008",
252
+
253
+ "applicant_name": "Ms. Jane Applicant",
254
+ "applicant_dob": "January 15, 1995",
255
+ "applicant_passport_no": "X12345678",
256
+
257
+ "visa_name": "B-2 Visitor Visa",
258
+ "sponsor_relationship": "friend",
259
+ "visit_reason": "attend my wedding and for tourism",
260
+ "destination_country": "the United States",
261
+ "visit_start_date": "December 1, 2024",
262
+ "visit_end_date": "December 20, 2024",
263
+ "visit_purpose_details": "a personal visit to attend my wedding ceremony on December 5th and to tour New York City"
264
+ }' -- output document.pdf
265
+ ```
266
+
267
+ ## Passport Collection Consent Letter
268
+ ```
269
+ POST /generate/passport-collection
270
+ ```
271
+
272
+ ### **Sample Request**
273
+
274
+ ```bash
275
+ curl -X POST http://localhost:5000/generate/passport-collection \
276
+ -H "Content-Type: application/json" \
277
+ -d ' {
278
+ "applicant_name": "Budi Hartono",
279
+ "applicant_nik": "3171234567890001",
280
+ "applicant_address": "Jl. Kemerdekaan No. 17, akarta Pusat",
281
+ "agent_name": "Citra Lestari",
282
+ "agent_nik": "3171098765432100",
283
+ "agent_address": "Jl. Melati No. 8, akarta Selatan",
284
+ "passport_no": "C1234567",
285
+ "letter_location": "Jakarta",
286
+ "letter_date": "18th July 2024"
287
+ }' -- output document.pdf
288
+ ```
289
+
290
  ---
291
 
app/util/housewife_statement_letter_generator.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from fpdf import FPDF
3
+ import datetime
4
+ from .pdf_document_generator import PDFDocumentGenerator
5
+ class HousewifeStatementLetterGenerator(PDFDocumentGenerator):
6
+ """
7
+ Generates a specific PDF for a Housewife's Statement Letter
8
+ for a visa application.
9
+ """
10
+ def build_document(self, pdf: FPDF):
11
+ """
12
+ Creates the full PDF document for the statement letter
13
+ by adding content to the FPDF object.
14
+ """
15
+
16
+ # --- Extract data with fallbacks ---
17
+ applicant_name = self.data.get("applicant_name", "[Your Full Name]")
18
+ applicant_dob = self.data.get("applicant_dob", "[Place and Date of Birth]")
19
+ applicant_passport = self.data.get("applicant_passport", "[Your Passport Number]")
20
+
21
+ sponsor_name = self.data.get("sponsor_name", "[husband name]")
22
+ sponsor_bank_details = self.data.get("sponsor_bank_details", "[Name of Bank: Bank Account Number]")
23
+
24
+ destination_country = self.data.get("destination_country", "[Destination Country]")
25
+ visa_type = self.data.get("visa_type", "[visitor/tourism]")
26
+ visit_end_date = self.data.get("visit_end_date", "[Date ended of the trip]")
27
+ travel_companions = self.data.get("travel_companions", "[people who join the trip]")
28
+
29
+ today = datetime.date.today()
30
+ letter_location = self.data.get("letter_location", "[City]")
31
+ letter_date = self.data.get("letter_date", today.strftime("%B %d, %Y"))
32
+
33
+ # --- Build the PDF Document ---
34
+ pdf.set_font('Times', 'BU', 12)
35
+ pdf.set_left_margin(25)
36
+ pdf.set_right_margin(25)
37
+ pdf.set_y(25)
38
+
39
+ # Title
40
+ pdf.cell(0, 6, "HOUSEWIFE'S STATEMENT LETTER", 0, 1, 'C')
41
+ pdf.ln(10)
42
+
43
+ # Applicant Details
44
+ pdf.set_font('Times', '', 11)
45
+ pdf.cell(0, 5, "I, the undersigned below:")
46
+ pdf.ln(5)
47
+
48
+ # Aligned key-value pairs
49
+ pdf.cell(50, 5, "Name")
50
+ pdf.cell(0, 5, f": {applicant_name}")
51
+ pdf.ln(5)
52
+ pdf.cell(50, 5, "Place and Date of Birth")
53
+ pdf.cell(0, 5, f": {applicant_dob}")
54
+ pdf.ln(5)
55
+ pdf.cell(50, 5, "Passport Number")
56
+ pdf.cell(0, 5, f": {applicant_passport}")
57
+ pdf.ln(10)
58
+
59
+ # Body Paragraph 1
60
+ body_p1 = (
61
+ f"I am a housewife, and my daily expenses are fully covered by my husband {sponsor_name}. "
62
+ f"During this visit to {destination_country}, all expenses, including travel, "
63
+ "accommodation, and daily necessities, will be fully sponsored by my husband "
64
+ f"from his savings account ({sponsor_bank_details})."
65
+ )
66
+ pdf.multi_cell(0, 5, body_p1)
67
+ pdf.ln(5)
68
+
69
+ # Body Paragraph 2
70
+ body_p2 = (
71
+ f"I am applying for a {destination_country} {visa_type} visa and will comply with "
72
+ "applicable regulations. I declare that I will return to Indonesia by the end of "
73
+ f"the trip on {visit_end_date}. I guarantee that I intend to spend "
74
+ f"holidays with {travel_companions}, and not look for a job "
75
+ "during my stay."
76
+ )
77
+ pdf.multi_cell(0, 5, body_p2)
78
+ pdf.ln(5)
79
+
80
+ # Body Paragraph 3
81
+ body_p3 = (
82
+ "I respectfully request that my visa application be processed at your earliest "
83
+ "convenience."
84
+ )
85
+ pdf.multi_cell(0, 5, body_p3)
86
+ pdf.ln(10)
87
+
88
+ # Body Paragraph 4
89
+ body_p4 = "Thus, I have made this statement in all honesty."
90
+ pdf.multi_cell(0, 5, body_p4)
91
+ pdf.ln(15)
92
+
93
+ # Closing
94
+ pdf.cell(0, 5, f"{letter_location}, {letter_date}")
95
+ pdf.ln(25) # Space for signature
96
+ pdf.set_font('Times', 'B', 11)
97
+ pdf.cell(0, 5, applicant_name)
app/util/passport_collection_letter_generator.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fpdf import FPDF
2
+ import datetime
3
+ from .pdf_document_generator import PDFDocumentGenerator
4
+ class PassportCollectionLetterGenerator(PDFDocumentGenerator):
5
+ """
6
+ Generates a specific PDF for a Passport Collection Letter (Surat Kuasa)
7
+ based on the provided Indonesian template.
8
+ """
9
+ def build_document(self, pdf: FPDF):
10
+ """
11
+ Creates the full PDF document for the statement letter
12
+ by adding content to the FPDF object.
13
+ """
14
+
15
+ # --- Extract data with fallbacks ---
16
+ applicant_name = self.data.get("applicant_name", "[Applicant's name]")
17
+ applicant_nik = self.data.get("applicant_nik", "[NIK]")
18
+ applicant_address = self.data.get("applicant_address", "[Applicant's address]")
19
+
20
+ agent_name = self.data.get("agent_name", "[Agent's name]")
21
+ agent_nik = self.data.get("agent_nik", "[NIK]")
22
+ agent_address = self.data.get("agent_address", "[Agent's address]")
23
+
24
+ passport_no = self.data.get("passport_no", "[Passport No.]")
25
+
26
+ today = datetime.date.today()
27
+ letter_location = self.data.get("letter_location", "[City]")
28
+ letter_date = self.data.get("letter_date", today.strftime("%d %B %Y"))
29
+
30
+ # --- Build the PDF Document ---
31
+ pdf.set_left_margin(25)
32
+ pdf.set_right_margin(25)
33
+ pdf.set_y(25)
34
+
35
+ # Title
36
+ pdf.set_font('Arial', 'BU', 12)
37
+ pdf.cell(0, 6, "SURAT KUASA", 0, 1, 'C')
38
+ pdf.ln(10)
39
+
40
+ # Pemberi Kuasa (Pihak Pertama)
41
+ pdf.set_font('Arial', '', 11)
42
+ pdf.cell(0, 5, "Saya yang bertanda tangan di bawah ini:")
43
+ pdf.ln(5)
44
+
45
+ pdf.cell(20, 5, "Nama")
46
+ pdf.cell(0, 5, f": {applicant_name}")
47
+ pdf.ln(5)
48
+ pdf.cell(20, 5, "NIK")
49
+ pdf.cell(0, 5, f": {applicant_nik}")
50
+ pdf.ln(5)
51
+ pdf.cell(20, 5, "Alamat")
52
+ pdf.multi_cell(0, 5, f": {applicant_address}") # Use multi_cell for long addresses
53
+ pdf.ln(5)
54
+ pdf.cell(0, 5, "Selanjutnya disebut sebagai Pihak Pertama, memberikan kuasa penuh kepada:")
55
+ pdf.ln(10)
56
+
57
+ # Penerima Kuasa
58
+ pdf.cell(20, 5, "Nama")
59
+ pdf.cell(0, 5, f": {agent_name}")
60
+ pdf.ln(5)
61
+ pdf.cell(20, 5, "NIK")
62
+ pdf.cell(0, 5, f": {agent_nik}")
63
+ pdf.ln(5)
64
+ pdf.cell(20, 5, "Alamat")
65
+ pdf.multi_cell(0, 5, f": {agent_address}") # Use multi_cell for long addresses
66
+ pdf.ln(5)
67
+ pdf.cell(0, 5, "Selanjutnya disebut sebagai Penerima Kuasa.")
68
+ pdf.ln(10)
69
+
70
+ # Purpose
71
+ body_p1 = (
72
+ f"Untuk mengambil dokumen dengan nomor Paspor {passport_no} atas nama {applicant_name}, "
73
+ "serta menandatangani semua dokumen yang berkaitan dengan pengambilan paspor di "
74
+ "kantor pengurusan aplikasi visa."
75
+ )
76
+ pdf.multi_cell(0, 5, body_p1)
77
+ pdf.ln(5)
78
+
79
+ # Disclaimer
80
+ body_p2 = (
81
+ "Segala akibat dan hal-hal yang diakibatkan oleh pelimpahan wewenang ini menjadi "
82
+ "tanggung jawab saya sepenuhnya sebagai pemberi kuasa. Demikian surat kuasa ini saya "
83
+ "perbuat dengan sebenar-benarnya, dalam keadaan sehat jasmani dan Rohani, serta "
84
+ "tanpa adanya unsur paksaan dari siapapun, untuk bisa dipergunakan sebagaimana mestinya."
85
+ )
86
+ pdf.multi_cell(0, 5, body_p2)
87
+ pdf.ln(10)
88
+
89
+ # Closing
90
+ pdf.cell(0, 5, f"{letter_location}, {letter_date}")
91
+ pdf.ln(10)
92
+
93
+ # Signatures
94
+ # Calculate positions
95
+ page_width = pdf.w - pdf.l_margin - pdf.r_margin
96
+ col_width = page_width / 2
97
+
98
+ start_y = pdf.get_y()
99
+
100
+ # Pemberi Kuasa
101
+ pdf.cell(col_width, 5, "Pemberi Kuasa,", 0, 0, 'C')
102
+ # Penerima Kuasa
103
+ pdf.cell(col_width, 5, "Penerima Kuasa,", 0, 1, 'C')
104
+
105
+ pdf.set_y(pdf.get_y() + 10) # Move down 15 for Materai
106
+
107
+ # Materai text in the middle of the first column
108
+ pdf.set_font('Arial', 'I', 9)
109
+ pdf.set_x(pdf.l_margin + (col_width / 2) - 5) # Centered in first column
110
+ pdf.cell(10, 5, "Materai")
111
+ pdf.ln(15) # Space for signatures
112
+
113
+ start_y_names = pdf.get_y()
114
+
115
+ # Applicant Name
116
+ pdf.set_font('Arial', '', 11)
117
+ pdf.set_x(pdf.l_margin)
118
+ pdf.cell(col_width, 5, f"({applicant_name})", 0, 0, 'C')
119
+
120
+ # Agent Name
121
+ pdf.set_x(pdf.l_margin + col_width)
122
+ pdf.cell(col_width, 5, f"({agent_name})", 0, 1, 'C')
123
+
app/util/pdf_document_generator.py CHANGED
@@ -28,6 +28,13 @@ class PDFDocumentGenerator(ABC):
28
  """
29
  pass
30
 
 
 
 
 
 
 
 
31
  def compile_pdf(self, tempdir: str) -> (str, str):
32
  """
33
  Generates the PDF document using fpdf2 and saves it in tempdir.
 
28
  """
29
  pass
30
 
31
+ def _get_day_suffix(self, day):
32
+ """Returns the ordinal suffix (st, nd, rd, th) for a given day."""
33
+ if 11 <= day <= 13:
34
+ return 'th'
35
+ suffix = {1: 'st', 2: 'nd', 3: 'rd'}.get(day % 10, 'th')
36
+ return suffix
37
+
38
  def compile_pdf(self, tempdir: str) -> (str, str):
39
  """
40
  Generates the PDF document using fpdf2 and saves it in tempdir.
app/util/schengen_visa_letter_generator.py CHANGED
@@ -14,7 +14,7 @@ class SchengenVisaLetterGenerator(PDFDocumentGenerator):
14
  members = data.get("group_members", [])
15
  self.trip_type = "group" if members and len(members) > 0 else "individual"
16
 
17
- def build_document(self, pdf):
18
  """
19
  Builds the formatted PDF content.
20
  This method is called by the base class `compile_pdf()`.
@@ -22,9 +22,12 @@ class SchengenVisaLetterGenerator(PDFDocumentGenerator):
22
  personal = self.data.get("personal_details", {})
23
  members = self.data.get("group_members", [])
24
 
 
 
 
25
  # --- Extract fields ---
26
  city = self.data.get("city", "Jakarta")
27
- date = self.data.get("date", "18th July 2024")
28
  country = self.data.get("country", "[Schengen Country Name]")
29
  purpose = self.data.get("purpose", "[tourism/family visit]")
30
  main_dest = self.data.get("main_destination", "[country]")
@@ -114,6 +117,8 @@ class SchengenVisaLetterGenerator(PDFDocumentGenerator):
114
  pdf.set_font("Times", "B", 12)
115
  pdf.cell(0, 10, "We will also provide the following supporting documents:", ln=True)
116
  pdf.set_font("Times", "", 12)
 
 
117
  pdf.multi_cell(
118
  0,
119
  8,
@@ -128,6 +133,7 @@ class SchengenVisaLetterGenerator(PDFDocumentGenerator):
128
  "- Copy of family documents or marriage certificate\n"
129
  "- Copy of passport",
130
  )
 
131
  pdf.ln(6)
132
 
133
  # --- Commitment & Return ---
 
14
  members = data.get("group_members", [])
15
  self.trip_type = "group" if members and len(members) > 0 else "individual"
16
 
17
+ def build_document(self, pdf: FPDF):
18
  """
19
  Builds the formatted PDF content.
20
  This method is called by the base class `compile_pdf()`.
 
22
  personal = self.data.get("personal_details", {})
23
  members = self.data.get("group_members", [])
24
 
25
+ today = datetime.date.today()
26
+ suffix = self._get_day_suffix(today.day)
27
+ date = today.strftime(f"%d{suffix} %B %Y")
28
  # --- Extract fields ---
29
  city = self.data.get("city", "Jakarta")
30
+ # date = self.data.get("date", "18th July 2024")
31
  country = self.data.get("country", "[Schengen Country Name]")
32
  purpose = self.data.get("purpose", "[tourism/family visit]")
33
  main_dest = self.data.get("main_destination", "[country]")
 
117
  pdf.set_font("Times", "B", 12)
118
  pdf.cell(0, 10, "We will also provide the following supporting documents:", ln=True)
119
  pdf.set_font("Times", "", 12)
120
+ standard_l_margin = pdf.l_margin
121
+ pdf.set_left_margin(standard_l_margin+10)
122
  pdf.multi_cell(
123
  0,
124
  8,
 
133
  "- Copy of family documents or marriage certificate\n"
134
  "- Copy of passport",
135
  )
136
+ pdf.set_left_margin(standard_l_margin)
137
  pdf.ln(6)
138
 
139
  # --- Commitment & Return ---
app/util/sponsorship_letter_generator.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ from fpdf import FPDF
3
+
4
+ from .pdf_document_generator import PDFDocumentGenerator
5
+
6
+ class SponsorshipLetterGenerator(PDFDocumentGenerator):
7
+ """
8
+ Generates a specific PDF for a Visa Sponsorship Letter based on
9
+ the provided template.
10
+ """
11
+ def build_document(self, pdf: FPDF):
12
+ """
13
+ Creates the full PDF document for the sponsorship letter
14
+ by adding content to the FPDF object.
15
+ """
16
+
17
+ # --- Extract data with fallbacks ---
18
+ # Sponsor details
19
+ sponsor_name = self.data.get("sponsor_name", "[Name of the Sponsor]")
20
+ sponsor_address = self.data.get("sponsor_address", "[Address]")
21
+ sponsor_postal = self.data.get("sponsor_postal_code", "[Postal Code]")
22
+ sponsor_email = self.data.get("sponsor_email", "[your email]")
23
+ sponsor_phone = self.data.get("sponsor_contact_number", "[your contact number]")
24
+
25
+ # Letter date (defaults to today)
26
+ letter_date = self.data.get("letter_date", datetime.date.today().strftime("%B %d, %Y"))
27
+
28
+ # Embassy details
29
+ officer_title = self.data.get("officer_title", "[Title of the Officer]")
30
+ embassy_name = self.data.get("embassy_name", "[Name of the Embassy/High Commission]")
31
+ embassy_address = self.data.get("embassy_address", "[Street Address]")
32
+ embassy_city_state_postal = self.data.get("embassy_city_state_postal", "[City, State/Region, Postal Code]")
33
+
34
+ # Applicant details
35
+ applicant_name = self.data.get("applicant_name", "[Name of the Applicant]")
36
+ applicant_dob = self.data.get("applicant_dob", "[Date of Birth]")
37
+ applicant_passport = self.data.get("applicant_passport_no", "[Passport No.]")
38
+
39
+ # Visit details
40
+ visa_name = self.data.get("visa_name", "[Visa Name]")
41
+ relationship = self.data.get("sponsor_relationship", "[mention your relationship]")
42
+ visit_reason = self.data.get("visit_reason", "[mention the reason for the visit]")
43
+ destination_country = self.data.get("destination_country", "[destination country]")
44
+ start_date = self.data.get("visit_start_date", "[start date]")
45
+ end_date = self.data.get("visit_end_date", "[end date]")
46
+ purpose_details = self.data.get("visit_purpose_details", "[personal reason / professional reason]")
47
+
48
+ pdf.set_font('Arial', '', 11)
49
+ pdf.set_left_margin(25)
50
+ pdf.set_right_margin(25)
51
+ pdf.set_y(25)
52
+
53
+ # Sponsor Info
54
+ pdf.multi_cell(0, 5, f"{sponsor_name}\n{sponsor_address}\n{sponsor_postal}")
55
+ pdf.ln(5)
56
+ pdf.cell(0, 5, letter_date)
57
+ pdf.ln(10)
58
+
59
+ # Embassy Info
60
+ pdf.multi_cell(0, 5, f"{officer_title}\n{embassy_name}\n{embassy_address}\n{embassy_city_state_postal}")
61
+ pdf.ln(10)
62
+
63
+ # Subject Line
64
+ pdf.set_font('Arial', 'B', 11)
65
+ pdf.cell(0, 5, f"Subject: Sponsorship Letter for {visa_name} Application - {applicant_name}")
66
+ pdf.ln(10)
67
+
68
+ # Salutation
69
+ pdf.set_font('Arial', '', 11)
70
+ pdf.cell(0, 5, "Dear Sir/Mam,")
71
+ pdf.ln(10)
72
+
73
+ # Body Paragraph 1
74
+ body_p1 = (
75
+ f"I am writing this letter on behalf of {applicant_name}, born on {applicant_dob}, "
76
+ f"holding Passport No. {applicant_passport}. I am his/her {relationship}. "
77
+ f"I would like to sponsor him/her to {visit_reason} in {destination_country} "
78
+ f"from {start_date} to {end_date}. The purpose of his/her visit is "
79
+ f"{purpose_details}."
80
+ )
81
+ pdf.multi_cell(0, 5, body_p1)
82
+ pdf.ln(5)
83
+
84
+ # Body Paragraph 2
85
+ body_p2 = (
86
+ f"I will also be supporting {applicant_name} during his/her stay in the {destination_country} "
87
+ "and will provide him/her with the required accommodation. Please find enclosed the "
88
+ "following documents as verification proof that I am financially able to support him/her:"
89
+ )
90
+ pdf.multi_cell(0, 5, body_p2)
91
+ pdf.ln(5)
92
+
93
+ # Note: You would typically list the documents here.
94
+ # For a real implementation, you might pass a list of documents in the data.
95
+ pdf.set_left_margin(35)
96
+ pdf.multi_cell(0, 5, "- Proof of income (Pay Slips, Bank Statements)\n- Proof of accommodation (Utility Bill, Tenancy Agreement)\n- Copy of my Passport / Residence Permit")
97
+ pdf.set_left_margin(25)
98
+ pdf.ln(5)
99
+
100
+ # Body Paragraph 3
101
+ body_p3 = (
102
+ f"If you have any questions, please feel free to contact me at {sponsor_email} "
103
+ f"or {sponsor_phone}."
104
+ )
105
+ pdf.multi_cell(0, 5, body_p3)
106
+ pdf.ln(10)
107
+
108
+ # Closing
109
+ pdf.cell(0, 5, "Thank you.")
110
+ pdf.ln(5)
111
+ pdf.cell(0, 5, "Sincerely,")
112
+ pdf.ln(15) # Space for signature
113
+ pdf.cell(0, 5, sponsor_name)
114
+ pdf.ln(5)
115
+ pdf.cell(0, 5, sponsor_phone)
server.py CHANGED
@@ -120,6 +120,8 @@ def create_app() -> Flask:
120
  Example:
121
  POST /generate/schengen
122
  POST /generate/japan-multientry-tourist
 
 
123
  """
124
  try:
125
  data = request.get_json()
@@ -136,6 +138,18 @@ def create_app() -> Flask:
136
  "app.util.schengen_visa_letter_generator",
137
  "SchengenVisaLetterGenerator",
138
  ),
 
 
 
 
 
 
 
 
 
 
 
 
139
  }
140
 
141
  if visa_type.lower() not in generator_map:
 
120
  Example:
121
  POST /generate/schengen
122
  POST /generate/japan-multientry-tourist
123
+ POST /generate/sponsorship
124
+ POST /generate/housewife-statement
125
  """
126
  try:
127
  data = request.get_json()
 
138
  "app.util.schengen_visa_letter_generator",
139
  "SchengenVisaLetterGenerator",
140
  ),
141
+ "sponsorship": (
142
+ "app.util.sponsorship_letter_generator",
143
+ "SponsorshipLetterGenerator"
144
+ ),
145
+ "housewife-statement": (
146
+ "app.util.housewife_statement_letter_generator",
147
+ "HousewifeStatementLetterGenerator"
148
+ ),
149
+ "passport-collection": (
150
+ "app.util.passport_collection_letter_generator",
151
+ "PassportCollectionLetterGenerator"
152
+ )
153
  }
154
 
155
  if visa_type.lower() not in generator_map: