Fix issues with date/time format conversions.
The API endpoints will now accept ISO formatted inputs. The frontend needs to do the conversion.
This commit is contained in:
46
app.py
46
app.py
@@ -1357,8 +1357,8 @@ def leave(entry_id):
|
|||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'id': entry.id,
|
'id': entry.id,
|
||||||
'arrival_time': entry.arrival_time.strftime('%Y-%m-%d %H:%M:%S'),
|
'arrival_time': entry.arrival_time.isoformat(),
|
||||||
'departure_time': entry.departure_time.strftime('%Y-%m-%d %H:%M:%S'),
|
'departure_time': entry.departure_time.isoformat(),
|
||||||
'duration': entry.duration,
|
'duration': entry.duration,
|
||||||
'total_break_duration': entry.total_break_duration,
|
'total_break_duration': entry.total_break_duration,
|
||||||
'effective_break_duration': effective_break
|
'effective_break_duration': effective_break
|
||||||
@@ -1449,15 +1449,23 @@ def update_entry(entry_id):
|
|||||||
entry = TimeEntry.query.filter_by(id=entry_id, user_id=session['user_id']).first_or_404()
|
entry = TimeEntry.query.filter_by(id=entry_id, user_id=session['user_id']).first_or_404()
|
||||||
data = request.json
|
data = request.json
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return jsonify({'success': False, 'message': 'No JSON data provided'}), 400
|
||||||
|
|
||||||
if 'arrival_time' in data:
|
if 'arrival_time' in data:
|
||||||
try:
|
try:
|
||||||
entry.arrival_time = datetime.strptime(data['arrival_time'], '%Y-%m-%d %H:%M:%S')
|
# Accept only ISO 8601 format
|
||||||
except ValueError:
|
arrival_time_str = data['arrival_time']
|
||||||
return jsonify({'success': False, 'message': 'Invalid arrival time format'}), 400
|
entry.arrival_time = datetime.fromisoformat(arrival_time_str.replace('Z', '+00:00'))
|
||||||
|
except (ValueError, AttributeError) as e:
|
||||||
|
return jsonify({'success': False, 'message': f'Invalid arrival time format. Expected ISO 8601: {arrival_time_str}'}), 400
|
||||||
|
|
||||||
if 'departure_time' in data and data['departure_time']:
|
if 'departure_time' in data and data['departure_time']:
|
||||||
try:
|
try:
|
||||||
entry.departure_time = datetime.strptime(data['departure_time'], '%Y-%m-%d %H:%M:%S')
|
# Accept only ISO 8601 format
|
||||||
|
departure_time_str = data['departure_time']
|
||||||
|
entry.departure_time = datetime.fromisoformat(departure_time_str.replace('Z', '+00:00'))
|
||||||
|
|
||||||
# Recalculate duration if both times are present
|
# Recalculate duration if both times are present
|
||||||
if entry.arrival_time and entry.departure_time:
|
if entry.arrival_time and entry.departure_time:
|
||||||
# Calculate work duration considering breaks
|
# Calculate work duration considering breaks
|
||||||
@@ -1467,8 +1475,8 @@ def update_entry(entry_id):
|
|||||||
entry.total_break_duration,
|
entry.total_break_duration,
|
||||||
g.user
|
g.user
|
||||||
)
|
)
|
||||||
except ValueError:
|
except (ValueError, AttributeError) as e:
|
||||||
return jsonify({'success': False, 'message': 'Invalid departure time format'}), 400
|
return jsonify({'success': False, 'message': f'Invalid departure time format. Expected ISO 8601: {departure_time_str}'}), 400
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -1476,8 +1484,8 @@ def update_entry(entry_id):
|
|||||||
'message': 'Entry updated successfully',
|
'message': 'Entry updated successfully',
|
||||||
'entry': {
|
'entry': {
|
||||||
'id': entry.id,
|
'id': entry.id,
|
||||||
'arrival_time': entry.arrival_time.strftime('%Y-%m-%d %H:%M:%S'),
|
'arrival_time': entry.arrival_time.isoformat(),
|
||||||
'departure_time': entry.departure_time.strftime('%Y-%m-%d %H:%M:%S') if entry.departure_time else None,
|
'departure_time': entry.departure_time.isoformat() if entry.departure_time else None,
|
||||||
'duration': entry.duration,
|
'duration': entry.duration,
|
||||||
'is_paused': entry.is_paused,
|
'is_paused': entry.is_paused,
|
||||||
'total_break_duration': entry.total_break_duration
|
'total_break_duration': entry.total_break_duration
|
||||||
@@ -1562,7 +1570,7 @@ def resume_entry(entry_id):
|
|||||||
'success': True,
|
'success': True,
|
||||||
'message': 'Work resumed on existing entry',
|
'message': 'Work resumed on existing entry',
|
||||||
'id': entry_to_resume.id,
|
'id': entry_to_resume.id,
|
||||||
'arrival_time': entry_to_resume.arrival_time.strftime('%Y-%m-%d %H:%M:%S'),
|
'arrival_time': entry_to_resume.arrival_time.isoformat(),
|
||||||
'total_break_duration': entry_to_resume.total_break_duration
|
'total_break_duration': entry_to_resume.total_break_duration
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -2900,8 +2908,8 @@ def team_hours_data():
|
|||||||
for entry in entries:
|
for entry in entries:
|
||||||
formatted_entries.append({
|
formatted_entries.append({
|
||||||
'id': entry.id,
|
'id': entry.id,
|
||||||
'arrival_time': entry.arrival_time.strftime('%Y-%m-%d %H:%M:%S'),
|
'arrival_time': entry.arrival_time.isoformat(),
|
||||||
'departure_time': entry.departure_time.strftime('%Y-%m-%d %H:%M:%S') if entry.departure_time else None,
|
'departure_time': entry.departure_time.isoformat() if entry.departure_time else None,
|
||||||
'duration': entry.duration,
|
'duration': entry.duration,
|
||||||
'total_break_duration': entry.total_break_duration
|
'total_break_duration': entry.total_break_duration
|
||||||
})
|
})
|
||||||
@@ -2934,8 +2942,8 @@ def team_hours_data():
|
|||||||
},
|
},
|
||||||
'team_data': team_data,
|
'team_data': team_data,
|
||||||
'date_range': date_range,
|
'date_range': date_range,
|
||||||
'start_date': start_date.strftime('%Y-%m-%d'),
|
'start_date': start_date.isoformat(),
|
||||||
'end_date': end_date.strftime('%Y-%m-%d')
|
'end_date': end_date.isoformat()
|
||||||
})
|
})
|
||||||
|
|
||||||
@app.route('/export')
|
@app.route('/export')
|
||||||
@@ -3455,8 +3463,8 @@ def get_task(task_id):
|
|||||||
'priority': task.priority.value,
|
'priority': task.priority.value,
|
||||||
'estimated_hours': task.estimated_hours,
|
'estimated_hours': task.estimated_hours,
|
||||||
'assigned_to_id': task.assigned_to_id,
|
'assigned_to_id': task.assigned_to_id,
|
||||||
'start_date': task.start_date.strftime('%Y-%m-%d') if task.start_date else None,
|
'start_date': task.start_date.isoformat() if task.start_date else None,
|
||||||
'due_date': task.due_date.strftime('%Y-%m-%d') if task.due_date else None
|
'due_date': task.due_date.isoformat() if task.due_date else None
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonify({'success': True, 'task': task_data})
|
return jsonify({'success': True, 'task': task_data})
|
||||||
@@ -3606,8 +3614,8 @@ def get_subtask(subtask_id):
|
|||||||
'priority': subtask.priority.value,
|
'priority': subtask.priority.value,
|
||||||
'estimated_hours': subtask.estimated_hours,
|
'estimated_hours': subtask.estimated_hours,
|
||||||
'assigned_to_id': subtask.assigned_to_id,
|
'assigned_to_id': subtask.assigned_to_id,
|
||||||
'start_date': subtask.start_date.strftime('%Y-%m-%d') if subtask.start_date else None,
|
'start_date': subtask.start_date.isoformat() if subtask.start_date else None,
|
||||||
'due_date': subtask.due_date.strftime('%Y-%m-%d') if subtask.due_date else None
|
'due_date': subtask.due_date.isoformat() if subtask.due_date else None
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonify({'success': True, 'subtask': subtask_data})
|
return jsonify({'success': True, 'subtask': subtask_data})
|
||||||
|
|||||||
@@ -390,15 +390,15 @@ Please <a href="{{ url_for('login') }}">login</a> or <a href="{{ url_for('regist
|
|||||||
(arrivalTime.split(':').length === 2 ? arrivalTime + ':00' : arrivalTime) :
|
(arrivalTime.split(':').length === 2 ? arrivalTime + ':00' : arrivalTime) :
|
||||||
arrivalTime + ':00:00';
|
arrivalTime + ':00:00';
|
||||||
|
|
||||||
// Format datetime strings for the API (YYYY-MM-DD HH:MM:SS)
|
// Format datetime strings for the API (ISO 8601: YYYY-MM-DDTHH:MM:SS)
|
||||||
const arrivalDateTime = `${arrivalDate} ${arrivalTimeWithSeconds}`;
|
const arrivalDateTime = `${arrivalDate}T${arrivalTimeWithSeconds}`;
|
||||||
let departureDateTime = null;
|
let departureDateTime = null;
|
||||||
|
|
||||||
if (departureDate && departureTime) {
|
if (departureDate && departureTime) {
|
||||||
const departureTimeWithSeconds = departureTime.includes(':') ?
|
const departureTimeWithSeconds = departureTime.includes(':') ?
|
||||||
(departureTime.split(':').length === 2 ? departureTime + ':00' : departureTime) :
|
(departureTime.split(':').length === 2 ? departureTime + ':00' : departureTime) :
|
||||||
departureTime + ':00:00';
|
departureTime + ':00:00';
|
||||||
departureDateTime = `${departureDate} ${departureTimeWithSeconds}`;
|
departureDateTime = `${departureDate}T${departureTimeWithSeconds}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Sending update:', {
|
console.log('Sending update:', {
|
||||||
|
|||||||
@@ -193,12 +193,12 @@
|
|||||||
const departureDate = document.getElementById('edit-departure-date').value;
|
const departureDate = document.getElementById('edit-departure-date').value;
|
||||||
const departureTime = document.getElementById('edit-departure-time').value;
|
const departureTime = document.getElementById('edit-departure-time').value;
|
||||||
|
|
||||||
// Format datetime strings
|
// Format datetime strings as ISO 8601
|
||||||
const arrivalDateTime = `${arrivalDate} ${arrivalTime}:00`;
|
const arrivalDateTime = `${arrivalDate}T${arrivalTime}:00`;
|
||||||
let departureDateTime = null;
|
let departureDateTime = null;
|
||||||
|
|
||||||
if (departureDate && departureTime) {
|
if (departureDate && departureTime) {
|
||||||
departureDateTime = `${departureDate} ${departureTime}:00`;
|
departureDateTime = `${departureDate}T${departureTime}:00`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send update request
|
// Send update request
|
||||||
|
|||||||
Reference in New Issue
Block a user