File size: 10,409 Bytes
cd964f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
import pandas as pd
import os
import logging
from datetime import datetime, date

logger = logging.getLogger(__name__)

def calculate_passenger_type(dob_str):
    """

    Calculate passenger type based on age from date of birth.

    

    Age groups:

    - Infants: 0-1 year (0-11 months)

    - Children: 1-17 years

    - Adults: 18+ years

    

    Returns:

        For Fly Dubai: "Infant", "Child", "Adult"

        For Iraqi/Fly Baghdad: "INF", "CHD", "ADT"

    """
    if not dob_str:
        return "Adult", "ADT"  # Default to adult if no DOB
    
    try:
        # Parse the date (assuming DD/MM/YYYY format)
        dob = datetime.strptime(dob_str, '%d/%m/%Y').date()
        today = date.today()
        
        # Calculate age in years
        age_years = today.year - dob.year
        if today.month < dob.month or (today.month == dob.month and today.day < dob.day):
            age_years -= 1
        
        # Calculate age in months for more accurate infant check
        age_months = (today.year - dob.year) * 12 + (today.month - dob.month)
        if today.day < dob.day:
            age_months -= 1
        
        # Determine passenger type based on age
        if age_months < 12:  # Less than 12 months - Infant
            return "Infant", "INF"
        elif age_years < 18:  # 1-17 years - Child
            return "Child", "CHD"
        else:  # 18+ years - Adult
            return "Adult", "ADT"
            
    except (ValueError, TypeError):
        return "Adult", "ADT"  # Default to adult if date parsing fails

def format_fly_dubai(data_list):
    """

    Formats data for Fly Dubai template (previously Iraqi Airways).

    Columns: TYPE, TITLE, FIRST NAME, LAST NAME, DOB (DD/MM/YYYY), GENDER

    Example: Adult MR FirstNameOne LastNameOne 13/8/2015 Male

    """
    formatted_rows = []
    
    for item in data_list:
        sex = item.get('sex', '').upper()
        # Map Gender to Male/Female
        gender_full = "Male" if sex == 'M' else "Female"
        title = "MR" if sex == 'M' else "MRS"
        
        # Calculate passenger type based on age
        raw_dob = item.get('date_of_birth', '')
        
        # Convert MRZ date (YYMMDD) to DD/MM/YYYY for age calculation
        ddmmyyyy_dob = ''
        if raw_dob and len(raw_dob) == 6:  # YYMMDD format
            try:
                from datetime import datetime
                mrz_date = datetime.strptime(raw_dob, '%y%m%d').date()
                ddmmyyyy_dob = mrz_date.strftime('%d/%m/%Y')
            except:
                ddmmyyyy_dob = raw_dob
        else:
            ddmmyyyy_dob = raw_dob
            
        passenger_type, _ = calculate_passenger_type(ddmmyyyy_dob)
        
        row = {
            "TYPE": passenger_type,
            "TITLE": title,
            "FIRST NAME": item.get('name', ''),
            "LAST NAME": item.get('surname', ''),
            "DOB (DD/MM/YYYY)": ddmmyyyy_dob,
            "GENDER": gender_full
        }
        formatted_rows.append(row)
        
    return pd.DataFrame(formatted_rows)

from datetime import datetime

def _to_ddmmmyy(date_str):
    """Converts DD/MM/YYYY to DDMMMYY format, e.g., 13NOV84."""
    if not date_str:
        return ""
    try:
        # Parse from DD/MM/YYYY
        dt_obj = datetime.strptime(date_str, '%d/%m/%Y')
        # Format to DDMMMYY with strict zero padding for day
        # %d should do it, but to be safe we can use string formatting
        day = dt_obj.strftime('%d')
        month_year = dt_obj.strftime('%b%y').upper()
        return f"{day}{month_year}"
    except ValueError:
        return date_str # Return original if parsing fails

def format_iraqi(data_list):
    """

    Formats data for Iraqi template (previously Flydubai).

    - Date of Birth: DDMMMYY (e.g., 13NOV84)

    - Passport Expiry Date: DDMMMYY (e.g., 13NOV84)

    """
    formatted_rows = []
    
    for item in data_list:
        sex = item.get('sex', '').upper()
        title = "MR" if sex == 'M' else "MRS" 
        
        first_middle = item.get('name', '')
        
        # Get date data for age calculation
        raw_dob = item.get('date_of_birth', '')
        raw_expiry = item.get('expiration_date', '')
        
        # Calculate passenger type based on age
        # The date might be in DDMMMYY format (18NOV16) or YYMMDD format (161118)
        ddmmyyyy_dob = ''
        if raw_dob:
            try:
                # First try YYMMDD format (MRZ raw format) - 6 chars
                if len(raw_dob) == 6:
                    mrz_date = datetime.strptime(raw_dob, '%y%m%d').date()
                    ddmmyyyy_dob = mrz_date.strftime('%d/%m/%Y')
                else:
                    # Try DDMMMYY format (already formatted) - 7+ chars
                    formatted_date = datetime.strptime(raw_dob, '%d%b%y').date()
                    ddmmyyyy_dob = formatted_date.strftime('%d/%m/%Y')
            except:
                ddmmyyyy_dob = raw_dob
        else:
            ddmmyyyy_dob = raw_dob
            
        _, ptc_code = calculate_passenger_type(ddmmyyyy_dob)
        
        # Use the dates as-is since they're already formatted
        dob_formatted = raw_dob
        expiry_formatted = raw_expiry
        
        row = {
            "Last Name": item.get('surname', ''),
            "First Name and Middle Name": first_middle,
            "Title": title,
            "PTC": ptc_code, # Passenger Type Code based on age
            "Gender": sex,
            "Date of Birth": dob_formatted,
            "Passport Last Name": item.get('surname', ''),
            "Passport First Name": first_middle,
            "Passport Middle Name": "",
            "Passport Number": item.get('passport_number', ''),
            "Passport Nationality": item.get('nationality', '')[:3],
            "Passport Issue Country": item.get('country', '')[:3],
            "Passport Expiry Date": expiry_formatted,
            # Empty fields
            "Visa Number": "", "Visa Type": "", "Visa Issue Date": "", "Place of Birth": "",
            "Visa Place of Issue": "", "Visa Country of Application": "", "Address Type": "",
            "Address Country": "", "Address Details": "", "Address City": "",
            "Address State": "", "Address Zip Code": ""
        }
        formatted_rows.append(row)
        
    return pd.DataFrame(formatted_rows)

def format_fly_baghdad(data_list):
    """

    Formats data for Fly Baghdad template.

    Columns: Sequence, Traveling With, Pax Type, Title, First Name, Last Name, Gender, 

             DOB (dd/mm/yyyy), Nationality, Passport Number, Passport Expiry (dd/mm/yyyy), 

             Passport Issued Country

    """
    from config.settings import COUNTRY_CODES
    
    # Create a mapping for quick lookup
    country_map = {c['alpha-3']: c['name'].upper() for c in COUNTRY_CODES}
    
    formatted_rows = []
    
    for i, item in enumerate(data_list):
        sex = item.get('sex', '').upper()
        gender_full = "MALE" if sex == 'M' else "FEMALE"
        title = "MR" if sex == 'M' else "MRS"
        
        # Get and format DOB
        raw_dob = item.get('date_of_birth', '')
        ddmmyyyy_dob = ''
        if raw_dob and len(raw_dob) == 6:
            try:
                mrz_date = datetime.strptime(raw_dob, '%y%m%d').date()
                ddmmyyyy_dob = mrz_date.strftime('%d/%m/%Y')
            except:
                ddmmyyyy_dob = raw_dob
        else:
            ddmmyyyy_dob = raw_dob
            
        # Get and format Expiry
        raw_expiry = item.get('expiration_date', '')
        ddmmyyyy_expiry = ''
        if raw_expiry and len(raw_expiry) == 6:
            try:
                mrz_date = datetime.strptime(raw_expiry, '%y%m%d').date()
                ddmmyyyy_expiry = mrz_date.strftime('%d/%m/%Y')
            except:
                ddmmyyyy_expiry = raw_expiry
        else:
            ddmmyyyy_expiry = raw_expiry
            
        _, ptc_code = calculate_passenger_type(ddmmyyyy_dob)
        
        # Map nationality and country
        nat_code = item.get('nationality', '')[:3].upper()
        country_code = item.get('country', '')[:3].upper()
        
        nationality = country_map.get(nat_code, nat_code)
        issued_country = country_map.get(country_code, country_code)
        
        row = {
            "Sequence": i + 1,
            "Traveling With": "",
            "Pax Type": ptc_code,
            "Title": title,
            "First Name": item.get('name', ''),
            "Last Name": item.get('surname', ''),
            "Gender": gender_full,
            "DOB (dd/mm/yyyy)": ddmmyyyy_dob,
            "Nationality": nationality,
            "Passport Number": item.get('passport_number', ''),
            "Passport Expiry (dd/mm/yyyy)": ddmmyyyy_expiry,
            "Passport Issued Country": issued_country
        }
        formatted_rows.append(row)
        
    return pd.DataFrame(formatted_rows)


def export_to_spreadsheet(data_list, output_file, format='excel'):
    """

    Exports a list of dictionaries to a spreadsheet (Excel or CSV).

    """
    if not data_list:
        logger.warning("No data to export.")
        return False

    try:
        df = pd.DataFrame(data_list)
        
        # Ensure output directory exists
        os.makedirs(os.path.dirname(output_file), exist_ok=True)

        if format.lower() == 'excel' or output_file.endswith('.xlsx'):
            if not output_file.endswith('.xlsx'):
                output_file += '.xlsx'
            df.to_excel(output_file, index=False)
            logger.info(f"Data exported to {output_file}")
            
        elif format.lower() == 'csv' or output_file.endswith('.csv'):
            if not output_file.endswith('.csv'):
                output_file += '.csv'
            df.to_csv(output_file, index=False)
            logger.info(f"Data exported to {output_file}")
            
        else:
            logger.error(f"Unsupported format: {format}")
            return False
            
        return True

    except Exception as e:
        logger.error(f"Failed to export data: {e}")
        return False