@@ -1340,69 +1340,118 @@ def get(self, user_id):
13401340
13411341class SendInactiveUserMailReminder (Resource ):
13421342 @admin_required
1343- def post (self ):
1343+ def get (self ):
1344+ user_schema = UserSchema (many = True )
1345+ page = request .args .get ('page' , 1 , type = int )
1346+ per_page = request .args .get ('per_page' , 10 , type = int )
13441347
1345- parser = reqparse .RequestParser ()
1346- parser .add_argument ('value' , type = int , required = True ,
1347- help = 'Time period value is required' )
1348- parser .add_argument ('unit' , type = str , required = True ,
1349- choices = ('hours' , 'days' , 'months' ),
1350- help = 'Time unit must be hours, days, or months' )
1348+ value = request .args .get ('value' , type = int )
1349+ unit = request .args .get ('unit' )
13511350
1352- args = parser .parse_args ()
1353- value = args ['value' ]
1354- unit = args ['unit' ].lower ()
1351+ query = User .query .filter (
1352+ User .verified == True ,
1353+ User .disabled == False ,
1354+ User .admin_disabled == False
1355+ )
1356+
1357+ if value is not None and unit is not None :
1358+ unit = unit .lower ()
1359+ if unit not in ('hours' , 'days' , 'months' ):
1360+ return dict (status = 'fail' , message = "Unit must be hours, days, or months" ), 400
1361+
1362+ now = datetime .now ()
1363+ if unit == 'hours' :
1364+ lower_threshold = now - timedelta (hours = value )
1365+ upper_threshold = now - timedelta (hours = value - 1 )
1366+ elif unit == 'days' :
1367+ lower_threshold = now - timedelta (days = value )
1368+ upper_threshold = now - timedelta (days = value - 1 )
1369+ else :
1370+ lower_threshold = now - timedelta (days = value * 30 )
1371+ upper_threshold = now - timedelta (days = (value - 1 ) * 30 )
1372+
1373+ query = query .filter (
1374+ User .last_seen <= upper_threshold ,
1375+ User .last_seen > lower_threshold
1376+ )
13551377
1356- now = datetime .now ()
1357- if unit == 'hours' :
1358- lower_threshold = now - timedelta (hours = value )
1359- upper_threshold = now - timedelta (hours = value - 1 )
1360- elif unit == 'days' :
1361- lower_threshold = now - timedelta (days = value )
1362- upper_threshold = now - timedelta (days = value - 1 )
1363- else :
1364- lower_threshold = now - timedelta (days = value * 30 )
1365- upper_threshold = now - timedelta (days = (value - 1 ) * 30 )
1378+ query = query .order_by (User .last_seen .desc ())
1379+
1380+ paginated = query .paginate (page = page , per_page = per_page , error_out = False )
1381+ users = paginated .items
1382+
1383+ pagination = {
1384+ 'total' : paginated .total ,
1385+ 'pages' : paginated .pages ,
1386+ 'page' : paginated .page ,
1387+ 'per_page' : paginated .per_page ,
1388+ 'next' : paginated .next_num ,
1389+ 'prev' : paginated .prev_num
1390+ }
1391+ users_data = user_schema .dump (users )
13661392
1367-
1368- inactive_users = User .query .filter (
1369- User .last_seen <= upper_threshold ,
1370- User .last_seen > lower_threshold ,
1393+ return dict (
1394+ status = 'success' ,
1395+ message = f'Found { paginated .total } inactive users' ,
1396+ data = dict (pagination = pagination , users = users_data )
1397+ ), 200
1398+
1399+ @admin_required
1400+ def post (self ):
1401+ user_data = request .get_json ()
1402+
1403+ if not user_data or 'inactive_users' not in user_data :
1404+ return dict (status = 'fail' , message = 'List of user UUIDs not provided' ), 400
13711405
1372- User . verified == True ,
1373- User . disabled == False ,
1374- User . admin_disabled == False
1375- ). all ()
1406+ inactive_users = user_data [ 'inactive_users' ]
1407+
1408+ if not isinstance ( inactive_users , list ):
1409+ return dict ( status = 'fail' , message = 'Invalid format for inactive users' ), 400
13761410
1377- already_notified = set ()
1378-
13791411 emails_sent = 0
13801412 errors = []
1413+ now = datetime .now ()
13811414
1382- for user in inactive_users :
1415+ for user_uuid in inactive_users :
13831416 try :
1384- success = send_inactive_notification_to_user (
1385- email = user .email ,
1386- name = user .name ,
1387- app = current_app ._get_current_object (),
1388- template = "user/inactive_user_reminder.html" ,
1389- subject = "Checking In: Your Crane Cloud Account" ,
1390- date = now .strftime ("%m/%d/%Y" ),
1391- is_success_template = True
1392- )
1393-
1394- if success :
1395- emails_sent += 1
1396- already_notified .add (user .email )
1417+ user = User .query .get (user_uuid )
1418+ if not user :
1419+ errors .append (f"User with UUID { user_uuid } not found" )
1420+ continue
1421+
1422+ if user .last_reminder_sent is None or user .last_reminder_sent < (now - timedelta (days = 30 )):
1423+ success = send_inactive_notification_to_user (
1424+ email = user .email ,
1425+ name = user .name ,
1426+ app = current_app ._get_current_object (),
1427+ template = "user/inactive_user_reminder.html" ,
1428+ subject = "We miss you at Crane Cloud" ,
1429+ date = now .strftime ("%m/%d/%Y" ),
1430+ is_success_template = True
1431+ )
1432+
1433+ if success :
1434+ emails_sent += 1
1435+ user .last_reminder_sent = now
1436+ db .session .add (user )
1437+ else :
1438+ errors .append (f"Failed to send email to { user .email } " )
13971439 else :
1398- errors .append (f"Failed to send email to { user .email } " )
1440+ errors .append (f"Email reminder already sent to { user .email } within the last 30 days " )
13991441
14001442 except Exception as e :
1401- errors .append (f"Error sending email to { user .email } : { str (e )} " )
1402-
1443+ errors .append (f"Error processing user { user_uuid } : { str (e )} " )
1444+
1445+ try :
1446+ db .session .commit ()
1447+ except Exception as e :
1448+ db .session .rollback ()
1449+ return dict (status = 'fail' , message = f'Database error: { str (e )} ' ), 500
1450+
14031451 return dict (
14041452 status = 'success' ,
14051453 message = f'Successfully sent { emails_sent } reminder emails' ,
14061454 total_users_processed = len (inactive_users ),
14071455 errors = errors if errors else None
1408- ), 200
1456+ ), 201
1457+
0 commit comments