Feat: Mailing system

This commit is contained in:
Sallu9007
2025-04-15 21:51:26 +05:30
parent 711d9727fd
commit 411cc7fe03
7 changed files with 580 additions and 0 deletions

View File

@@ -0,0 +1,313 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Models\Publication;
use App\Models\ActivityAttended;
use App\Models\ActivityOrganised;
use App\Models\IVOrganised;
use App\Models\BookPublished;
use App\Models\ExternalEngagement;
use App\Models\OnlineCourse;
use App\Models\PatentCopyright;
use App\Models\User;
use App\Mail\MissingProofsMail;
use App\Models\ActivitiesAttended;
use App\Models\ActivitiesOrganised;
use App\Models\BooksPublished;
use App\Models\Patent;
class MissingProofsController extends Controller
{
public function checkAndSendEmails(Request $request)
{
$selectedCategories = $request->input('categories', []);
if (empty($selectedCategories)) {
return redirect()->back()->with('error', 'Please select at least one category.');
}
// Array to store missing proofs by faculty
$missingProofsByFaculty = [];
// Check each selected category
foreach ($selectedCategories as $category) {
switch ($category) {
case 'publications':
$this->checkPublications($missingProofsByFaculty);
break;
case 'activities_attended':
$this->checkActivitiesAttended($missingProofsByFaculty);
break;
case 'activities_organised':
$this->checkActivitiesOrganised($missingProofsByFaculty);
break;
case 'iv_organised':
$this->checkIVOrganised($missingProofsByFaculty);
break;
case 'books_published':
$this->checkBooksPublished($missingProofsByFaculty);
break;
case 'external_engagement':
$this->checkExternalEngagement($missingProofsByFaculty);
break;
case 'online_courses':
$this->checkOnlineCourses($missingProofsByFaculty);
break;
case 'patents_copyrights':
$this->checkPatentsCopyrights($missingProofsByFaculty);
break;
}
}
// Send emails to faculty members
$this->sendMissingProofEmails($missingProofsByFaculty);
return redirect()->back()->with('success', 'Emails sent successfully to faculty members with missing proofs.');
}
private function checkPublications(&$missingProofsByFaculty)
{
// Find publications with missing proofs (paper_file is null)
$missingProofs = Publication::whereNull('paper_file')->get();
foreach ($missingProofs as $publication) {
$facultyId = $publication->faculty_id;
if (!isset($missingProofsByFaculty[$facultyId])) {
$missingProofsByFaculty[$facultyId] = [
'faculty' => User::find($facultyId),
'items' => []
];
}
$missingProofsByFaculty[$facultyId]['items'][] = [
'type' => 'Publication',
'id' => $publication->id,
'primary_name' => $publication->title,
'details' => [
'Affiliation' => $publication->affiliation,
'Start Date' => $publication->start_date->format('d-m-Y'),
'End Date' => $publication->end_date->format('d-m-Y'),
'First Author' => $publication->first_author_name
]
];
}
}
private function checkActivitiesAttended(&$missingProofsByFaculty)
{
$missingProofs = ActivitiesAttended::whereNull('proof')->get();
foreach ($missingProofs as $activity) {
$facultyId = $activity->faculty_id;
if (!isset($missingProofsByFaculty[$facultyId])) {
$missingProofsByFaculty[$facultyId] = [
'faculty' => User::find($facultyId),
'items' => []
];
}
$missingProofsByFaculty[$facultyId]['items'][] = [
'type' => 'Activity Attended',
'id' => $activity->id,
'primary_name' => $activity->title,
'details' => [
'Organising Institute' => $activity->organising_institute,
'Start Date' => $activity->start_date->format('d-m-Y'),
'End Date' => $activity->end_date->format('d-m-Y')
]
];
}
}
private function checkActivitiesOrganised(&$missingProofsByFaculty)
{
$missingProofs = ActivitiesOrganised::whereNull('proof')->get();
foreach ($missingProofs as $activity) {
$facultyId = $activity->faculty_id;
if (!isset($missingProofsByFaculty[$facultyId])) {
$missingProofsByFaculty[$facultyId] = [
'faculty' => User::find($facultyId),
'items' => []
];
}
$missingProofsByFaculty[$facultyId]['items'][] = [
'type' => 'Activity Organised',
'id' => $activity->id,
'primary_name' => $activity->title,
'details' => [
'Objective' => $activity->objective,
'Outcomes' => $activity->outcomes,
'Start Date' => $activity->start_date->format('d-m-Y'),
'End Date' => $activity->end_date->format('d-m-Y')
]
];
}
}
private function checkIVOrganised(&$missingProofsByFaculty)
{
$missingProofs = IvOrganised::whereNull('proof')->get();
foreach ($missingProofs as $activity) {
$facultyId = $activity->faculty_id;
if (!isset($missingProofsByFaculty[$facultyId])) {
$missingProofsByFaculty[$facultyId] = [
'faculty' => User::find($facultyId),
'items' => []
];
}
$missingProofsByFaculty[$facultyId]['items'][] = [
'type' => 'Industrial Visit Organised',
'id' => $activity->id,
'primary_name' => $activity->company_name,
'details' => [
'Company Address' => $activity->company_address,
'Objective' => $activity->objective,
'Outcomes' => $activity->outcomes,
'Start Date' => $activity->start_date->format('d-m-Y'),
'End Date' => $activity->end_date->format('d-m-Y')
]
];
}
}
private function checkBooksPublished(&$missingProofsByFaculty)
{
$missingProofs = BooksPublished::whereNull('proof')->get();
foreach ($missingProofs as $book) {
$facultyId = $book->faculty_id;
if (!isset($missingProofsByFaculty[$facultyId])) {
$missingProofsByFaculty[$facultyId] = [
'faculty' => User::find($facultyId),
'items' => []
];
}
$missingProofsByFaculty[$facultyId]['items'][] = [
'type' => 'Book Published',
'id' => $book->id,
'primary_name' => $book->title,
'details' => [
'Author' => $book->author,
'Publisher' => $book->publisher,
'ISSN' => $book->issn,
'Date Of Publication' => $book->date_of_publication->format('d-m-Y'),
]
];
}
}
private function checkExternalEngagement(&$missingProofsByFaculty)
{
$missingProofs = ExternalEngagement::whereNull('proof')->get();
foreach ($missingProofs as $engagement) {
$facultyId = $engagement->faculty_id;
if (!isset($missingProofsByFaculty[$facultyId])) {
$missingProofsByFaculty[$facultyId] = [
'faculty' => User::find($facultyId),
'items' => []
];
}
$missingProofsByFaculty[$facultyId]['items'][] = [
'type' => 'External Engagement',
'id' => $engagement->id,
'primary_name' => $engagement->activity,
'details' => [
'Activity Description' => $engagement->activity_description,
'Inviting Organization' => $engagement->inviting_organization,
'Start Date' => $engagement->start_date->format('d-m-Y'),
'End Date' => $engagement->end_date->format('d-m-Y')
]
];
}
}
private function checkOnlineCourses(&$missingProofsByFaculty)
{
$missingProofs = OnlineCourse::whereNull('proof')->get();
foreach ($missingProofs as $course) {
$facultyId = $course->faculty_id;
if (!isset($missingProofsByFaculty[$facultyId])) {
$missingProofsByFaculty[$facultyId] = [
'faculty' => User::find($facultyId),
'items' => []
];
}
$missingProofsByFaculty[$facultyId]['items'][] = [
'type' => 'Online Course',
'id' => $course->id,
'primary_name' => $course->course,
'details' => [
'Offered By' => $course->offered_by,
'Publisher' => $course->publisher,
'Start Date' => $course->start_date->format('d-m-Y'),
'End Date' => $course->end_date->format('d-m-Y')
]
];
}
}
private function checkPatentsCopyrights(&$missingProofsByFaculty)
{
$missingProofs = Patent::whereNull('proof')->get();
foreach ($missingProofs as $patent) {
$facultyId = $patent->faculty_id;
if (!isset($missingProofsByFaculty[$facultyId])) {
$missingProofsByFaculty[$facultyId] = [
'faculty' => User::find($facultyId),
'items' => []
];
}
$missingProofsByFaculty[$facultyId]['items'][] = [
'type' => 'Patent/Copyright',
'id' => $patent->id,
'primary_name' => $patent->title,
'details' => [
'Investigator' => $patent->investigator,
'Application No' => $patent->application_no,
'Status' => $patent->status,
'Date Of Submission' => $patent->date_of_submission->format('d-m-Y'),
'Date Of Filling' => $patent->date_of_filling->format('d-m-Y'),
]
];
}
}
private function sendMissingProofEmails($missingProofsByFaculty)
{
foreach ($missingProofsByFaculty as $facultyData) {
$faculty = $facultyData['faculty'];
$items = $facultyData['items'];
// Send email
try {
Mail::to($faculty->email)->send(new MissingProofsMail($faculty, $items));
} catch (\Exception $e) {
// Handle the exception (log or report)
\Log::error('Failed to send email: ' . $e->getMessage());
// You could flash a message for admin if this is run from an admin panel
}
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
class MissingProofsMail extends Mailable
{
use Queueable, SerializesModels;
public $faculty;
public $items;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(User $faculty, array $items)
{
$this->faculty = $faculty;
$this->items = $items;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
// dd("hehe");
return $this->subject('Missing Proofs Notification')
->view('emails.missing-proofs');
}
}

View File

@@ -24,6 +24,11 @@ class ActivitiesAttended extends Model
'proof', 'proof',
]; ];
protected $casts = [
'start_date' => 'datetime',
'end_date' => 'datetime',
];
// Define the relationship to the User (Faculty) // Define the relationship to the User (Faculty)
public function department() public function department()

View File

@@ -22,6 +22,7 @@ class DatabaseSeeder extends Seeder
ActivitiesAttendedResponsesTableSeeder::class, ActivitiesAttendedResponsesTableSeeder::class,
ActivitiesOrganisedTableSeeder::class, ActivitiesOrganisedTableSeeder::class,
IvOrganisedTableSeeder::class, IvOrganisedTableSeeder::class,
PublicationSeeder::class,
]); ]);
// User::factory()->create([ // User::factory()->create([

View File

@@ -0,0 +1,133 @@
<?php
namespace Database\Seeders;
use App\Models\Publication;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
class PublicationSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// Sample data for publications
$firstAuthorNames = [
'Dr. Sarah Johnson', 'Prof. Michael Chen', 'Dr. Emily Rodriguez',
'Dr. David Kim', 'Prof. Amina Patel', 'Dr. Thomas Wilson',
'Prof. Lisa Wang', 'Dr. Robert Garcia', 'Prof. Olivia Smith',
'Dr. James Lee', 'Prof. Sophia Martinez', 'Dr. Alexander Brown'
];
$coAuthors = [
'Dr. John Smith, Dr. Maria Garcia, Prof. Wei Zhang',
'Prof. Aya Nakamura, Dr. Carlos Mendez',
'Dr. Rebecca Johnson, Prof. Andrew Davis, Dr. Fatima Khan',
'Prof. Samuel Taylor, Dr. Hannah Kim',
'Dr. Jason Miller, Prof. Diana Lewis',
'Prof. Kevin Park, Dr. Natalie Chen, Dr. Omar Hassan',
null, // Some publications might not have co-authors
];
$activityTypes = [
'Journal Article', 'Conference Paper', 'Book Chapter',
'Research Paper', 'Technical Report', 'Review Article'
];
$titles = [
'Advances in Machine Learning for Healthcare Applications',
'Sustainable Energy Systems: A Comprehensive Review',
'Novel Approaches to Quantum Computing',
'The Impact of Climate Change on Marine Ecosystems',
'Artificial Intelligence in Educational Technology',
'Cybersecurity Challenges in IoT Environments',
'Emerging Materials for Next-Generation Batteries',
'Blockchain Applications in Supply Chain Management',
'Genetic Factors in Autoimmune Disorders',
'Urban Planning Strategies for Smart Cities',
'Deep Learning Methods for Natural Language Processing',
'Renewable Energy Integration in Power Grids',
'Ethical Considerations in Biotechnology Research',
'Innovative Techniques in Software Engineering',
'Nanoparticles for Targeted Drug Delivery'
];
$affiliations = [
'International Journal of Computer Science',
'IEEE Transactions on Artificial Intelligence',
'Nature Communications',
'ACM Computing Surveys',
'Journal of Applied Physics',
'Renewable Energy',
'International Conference on Machine Learning',
'IEEE Conference on Computer Vision and Pattern Recognition',
'Annual Conference on Neural Information Processing Systems',
'International Conference on Software Engineering',
'Springer Handbook of Advanced Materials',
'Journal of Educational Technology',
'Environmental Science & Technology',
'Conference on Human Factors in Computing Systems',
'Journal of Biomedical Materials Research'
];
$organizingInstitutes = [
'IEEE', 'ACM', 'Elsevier', 'Springer', 'Nature Publishing Group',
'MIT Press', 'Cambridge University Press', 'Oxford University Press',
'National Science Foundation', 'American Chemical Society',
'Royal Society of Chemistry', 'Institute of Physics',
'Association for Computing Machinery', 'Taylor & Francis Group'
];
$venueAddresses = [
'Harvard University, Cambridge, MA, USA',
'Technical University of Munich, Germany',
'National University of Singapore, Singapore',
'University of Tokyo, Japan',
'ETH Zurich, Switzerland',
'University of California, Berkeley, USA',
'Imperial College London, UK',
'Tsinghua University, Beijing, China',
'University of Toronto, Canada',
'Technical University of Denmark, Copenhagen, Denmark',
'Seoul National University, South Korea',
'University of Melbourne, Australia'
];
$isPeerReviewed = ['yes', 'no'];
// Create 50 sample publication records
for ($i = 0; $i < 10; $i++) {
// Generate random dates
$startDate = now()->subDays(rand(30, 365))->addHours(rand(0, 23))->addMinutes(rand(0, 59));
$endDate = (clone $startDate)->addDays(rand(1, 5))->addHours(rand(0, 23))->addMinutes(rand(0, 59));
$numDays = $startDate->diffInDays($endDate) ?: 1;
// Determine if the publication is indexed
$isPeer = $isPeerReviewed[array_rand($isPeerReviewed)];
$scopusLink = $isPeer === 'yes' && rand(0, 1) ? 'https://www.scopus.com/record/display.uri?eid=2-s2.0-' . rand(10000000000, 99999999999) : null;
$sciLink = $isPeer === 'yes' && rand(0, 1) ? 'https://www.webofscience.com/wos/woscc/full-record/' . rand(100000, 999999) : null;
// Create the publication record
Publication::create([
'department_id' => rand(1, 5),
'first_author_name' => $firstAuthorNames[array_rand($firstAuthorNames)],
'co_authors' => $coAuthors[array_rand($coAuthors)],
'start_date' => $startDate->format('Y-m-d H:i:s'),
'end_date' => $endDate->format('Y-m-d H:i:s'),
'num_days' => $numDays,
'activity_type' => $activityTypes[array_rand($activityTypes)],
'title' => $titles[array_rand($titles)],
'affiliation' => $affiliations[array_rand($affiliations)],
'organizing_institute' => $organizingInstitutes[array_rand($organizingInstitutes)],
'venue_address' => $venueAddresses[array_rand($venueAddresses)],
'is_peer_reviewed' => $isPeer,
'scopus_link' => $scopusLink,
'sci_link' => $sciLink,
'paper_file' => null, // Null for paper file
'faculty_id' => rand(1, 5),
]);
}
}
}

View File

@@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<title>Missing Proofs Notification</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
color: #0056b3;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
margin-bottom: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
.footer {
margin-top: 30px;
font-size: 0.9em;
color: #666;
}
</style>
</head>
<body>
<div class="container">
<h1>Missing Proofs Notification</h1>
<p>Dear {{ $faculty->name }},</p>
<p>Our records indicate that you have missing proofs for the following entries. Please submit the required proofs at your earliest convenience:</p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Name/Title</th>
<th>Details</th>
</tr>
</thead>
<tbody>
@foreach ($items as $item)
<tr>
<td>{{ $item['type'] }}</td>
<td>{{ $item['primary_name'] }}</td>
<td>
<ul style="margin: 0; padding-left: 20px;">
@foreach ($item['details'] as $key => $value)
<li><strong>{{ $key }}:</strong> {{ $value }}</li>
@endforeach
</ul>
</td>
</tr>
@endforeach
</tbody>
</table>
<p>Please log in to the faculty portal to upload the missing proofs. If you have any questions or need assistance, please contact the administrative office.</p>
<p>Thank you for your prompt attention to this matter.</p>
<div class="footer">
<p>This is an automated email. Please do not reply to this message.</p>
</div>
</div>
</body>
</html>

View File

@@ -13,6 +13,7 @@ use App\Http\Controllers\CoordinatorController;
use App\Http\Controllers\ExternalEngagementController; use App\Http\Controllers\ExternalEngagementController;
use App\Http\Controllers\FacultyController; use App\Http\Controllers\FacultyController;
use App\Http\Controllers\IvOrganisedController; use App\Http\Controllers\IvOrganisedController;
use App\Http\Controllers\MissingProofsController;
use App\Http\Controllers\OnlineCoursesController; use App\Http\Controllers\OnlineCoursesController;
use App\Http\Controllers\PatentsController; use App\Http\Controllers\PatentsController;
use App\Http\Controllers\PublicationsController; use App\Http\Controllers\PublicationsController;
@@ -259,6 +260,8 @@ Route::middleware(['auth', CheckRole::class . ':Faculty'])->group(function () {
Route::put('/faculty/Patents/{id}', [PatentsController::class, 'update'])->name('faculty.Patents.update'); Route::put('/faculty/Patents/{id}', [PatentsController::class, 'update'])->name('faculty.Patents.update');
}); });
Route::post('/missing-proofs/check', [MissingProofsController::class, 'checkAndSendEmails'])->name('missing-proofs.check');
// API Resources // API Resources
Route::apiResources([ Route::apiResources([
'roles' => RoleController::class, 'roles' => RoleController::class,