Skip to content

Commit

Permalink
Merge pull request #2 from COMP-1640-GRE/cuongphgch210011
Browse files Browse the repository at this point in the history
Cuongphgch210011 - update job + fix bug -infinity
  • Loading branch information
cuongphgch210011 authored Apr 9, 2024
2 parents e63391c + 0546af9 commit 8a55d90
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 9 deletions.
9 changes: 7 additions & 2 deletions DotnetGRPC/AppDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

public DbSet<Faculty> Faculty { get; set; }
public DbSet<Template> Template { get; set; }
public DbSet<Notification> Notification { get; set; }
public DbSet<User> User { get; set; }

public DbSet<Contribution> Contribution { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name }, LogLevel.Information);
base.OnConfiguring(optionsBuilder);
}
}
2 changes: 2 additions & 0 deletions DotnetGRPC/DotnetGRPC.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
<PackageReference Include="Grpc.AspNetCore" Version="2.61.0" />
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.61.0" />
<PackageReference Include="Grpc.AspNetCore.Server.Reflection" Version="2.61.0" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.12" />
<PackageReference Include="Hangfire.PostgreSql" Version="1.20.8" />
<PackageReference Include="Microsoft.AspNetCore.Grpc.Swagger" Version="0.8.3" />
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.7.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
Expand Down
48 changes: 48 additions & 0 deletions DotnetGRPC/Model/Contribution.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace DotnetGRPC.Model
{
[Table("contribution")]
public class Contribution
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("id")]
public long Id { get; set; }

[Column("created_at")]
public DateTime CreatedAt { get; set; }

[Column("updated_at")]
public DateTime UpdatedAt { get; set; }

[Column("db_author_id")]
public long DbAuthorId { get; set; }

[Column("title")]
public string Title { get; set; }

[Column("description")]
public string? Description { get; set; }

[Column("evaluation")]
public string? Evaluation { get; set; }

[Column("view_count")]
public long ViewCount { get; set; }

[Column("semester_id")]
public long SemesterId { get; set; }

[Column("selected")]
public bool? Selected { get; set; }

[Column("is_anonymous")]
public bool? IsAnonymous { get; set; }

[Column("status")]
public string Status { get; set; }
}
}
18 changes: 18 additions & 0 deletions DotnetGRPC/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
using DotnetGRPC.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Hangfire;
using Hangfire.PostgreSql;

using Microsoft.Extensions.Azure;
using Azure.Identity;
using Azure.Core;
Expand All @@ -23,10 +26,20 @@
builder.Services.AddScoped<UserRepository>();
builder.Services.AddScoped<TemplateRepository>();
builder.Services.AddScoped<NotificationRepository>();
builder.Services.AddScoped<FacultyRepository>();
builder.Services.AddScoped<ContributionRepository>();

// Add services
builder.Services.AddScoped<NotificationService>();

// Add email service
builder.Services.Configure<EmailSettings>(builder.Configuration.GetSection("EmailSettings"));

// Add Hangfire services
builder.Services.AddHangfire(config =>
config.UsePostgreSqlStorage(c =>
c.UseNpgsqlConnection(builder.Configuration.GetConnectionString("DefaultConnection"))));
builder.Services.AddHangfireServer();

builder.Services.AddGrpcSwagger();
builder.Services.AddSwaggerGen(c =>
Expand Down Expand Up @@ -65,6 +78,11 @@
DotnetGRPC.GlobalVariables.Blob.Secret = builder.Configuration["SPACES_SECRET"];

Check warning on line 78 in DotnetGRPC/Program.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference assignment.

Check warning on line 78 in DotnetGRPC/Program.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference assignment.
}

app.UseHangfireDashboard();
app.UseHangfireServer();

Check warning on line 82 in DotnetGRPC/Program.cs

View workflow job for this annotation

GitHub Actions / build

'HangfireApplicationBuilderExtensions.UseHangfireServer(IApplicationBuilder, BackgroundJobServerOptions, IEnumerable<IBackgroundProcess>, JobStorage)' is obsolete: 'Please use IServiceCollection.AddHangfireServer extension method instead in the ConfigureServices method. Will be removed in 2.0.0.'

Check warning on line 82 in DotnetGRPC/Program.cs

View workflow job for this annotation

GitHub Actions / build

'HangfireApplicationBuilderExtensions.UseHangfireServer(IApplicationBuilder, BackgroundJobServerOptions, IEnumerable<IBackgroundProcess>, JobStorage)' is obsolete: 'Please use IServiceCollection.AddHangfireServer extension method instead in the ConfigureServices method. Will be removed in 2.0.0.'

RecurringJob.AddOrUpdate<NotificationService>(service => service.SendNotifyPendingContribution(), Cron.Daily);

Check warning on line 84 in DotnetGRPC/Program.cs

View workflow job for this annotation

GitHub Actions / build

'RecurringJob.AddOrUpdate<T>(Expression<Func<T, Task>>, Func<string>, TimeZoneInfo, string)' is obsolete: 'Please use an overload with the explicit recurringJobId parameter and RecurringJobOptions instead. Will be removed in 2.0.0.'

Check warning on line 84 in DotnetGRPC/Program.cs

View workflow job for this annotation

GitHub Actions / build

'RecurringJob.AddOrUpdate<T>(Expression<Func<T, Task>>, Func<string>, TimeZoneInfo, string)' is obsolete: 'Please use an overload with the explicit recurringJobId parameter and RecurringJobOptions instead. Will be removed in 2.0.0.'

// Configure the HTTP request pipeline.
app.MapGrpcService<GreeterService>();
app.MapGrpcService<FileTransferService>();
Expand Down
22 changes: 22 additions & 0 deletions DotnetGRPC/Repository/ContributionRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using DotnetGRPC.Model;
using Microsoft.EntityFrameworkCore;

public class ContributionRepository
{
private readonly AppDbContext _context;

public ContributionRepository(AppDbContext context)
{
_context = context;
}

public async Task<List<Contribution>> FindPendingContributions14DaysAgo()
{
var fourteenDaysAgo = DateTime.UtcNow.AddDays(-14);

return await _context.Contribution
.Where(c => c.UpdatedAt < fourteenDaysAgo && c.Status == "pending")
.ToListAsync();
}

}
17 changes: 17 additions & 0 deletions DotnetGRPC/Repository/FacultyRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using DotnetGRPC.Model;
using Microsoft.EntityFrameworkCore;

public class FacultyRepository
{
private readonly AppDbContext _context;

public FacultyRepository(AppDbContext context)
{
_context = context;
}

public async Task<Faculty> FindByIdAsync(long id)
{
return await _context.Faculty.FindAsync(id);

Check warning on line 15 in DotnetGRPC/Repository/FacultyRepository.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.

Check warning on line 15 in DotnetGRPC/Repository/FacultyRepository.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.
}
}
2 changes: 1 addition & 1 deletion DotnetGRPC/Repository/NotificationRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public async Task<Notification> FindByIdAsync(long id)

public async Task SaveAsync(Notification notification)
{
notification.CreatedAt = notification.CreatedAt.ToUniversalTime();
notification.CreatedAt = DateTime.UtcNow;
_context.Notification.Add(notification);
await _context.SaveChangesAsync();
}
Expand Down
7 changes: 7 additions & 0 deletions DotnetGRPC/Repository/UserRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ public async Task<User> FindByIdAsync(long id)
{
return await _context.User.SingleOrDefaultAsync(user => user.Id == id);

Check warning on line 15 in DotnetGRPC/Repository/UserRepository.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.

Check warning on line 15 in DotnetGRPC/Repository/UserRepository.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.
}

public async Task<List<User>> FindFacultyCoordinators(long facultyId)
{
return await _context.User
.Where(user => user.FacultyId == facultyId && user.Role != "student")
.ToListAsync();
}
}
67 changes: 62 additions & 5 deletions DotnetGRPC/Services/NotificationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,34 @@ public class NotificationService : Notification.NotificationBase
private readonly UserRepository _userRepository;
private readonly TemplateRepository _templateRepository;
private readonly NotificationRepository _notificationRepository;
private readonly ContributionRepository _contributionRepository;
private readonly FacultyRepository _facultyRepository;


public NotificationService(AppDbContext dbContext, IOptions<EmailSettings> emailSettings, UserRepository userRepository, TemplateRepository templateRepository, NotificationRepository notificationRepository)
public NotificationService(AppDbContext dbContext, IOptions<EmailSettings> emailSettings, UserRepository userRepository, TemplateRepository templateRepository, NotificationRepository notificationRepository, ContributionRepository contributionRepository, FacultyRepository facultyRepository)
{
_dbContext = dbContext;
_emailSettings = emailSettings.Value;
_userRepository = userRepository;
_templateRepository = templateRepository;
_notificationRepository = notificationRepository;
_contributionRepository = contributionRepository;
_facultyRepository = facultyRepository;
}

public async Task SendEmailAsync(long studentUserId, string templateCode, string option)
public async Task SendEmailAsync(long userId, string templateCode, string option)
{
if (studentUserId == 0)
if (userId == 0)
{
throw new ArgumentException("Student is null");
}

var student = await _userRepository.FindByIdAsync(studentUserId) ?? throw new ArgumentException("Student not found");
var student = await _userRepository.FindByIdAsync(userId) ?? throw new ArgumentException("Student not found");
var template = await _templateRepository.FindByTemplateCodeAsync(templateCode) ?? throw new ArgumentException("Template not found");
using (var mailMessage = new MailMessage())
{
mailMessage.To.Add(new MailAddress(student.Email));
mailMessage.From = new MailAddress("[email protected]");
mailMessage.From = new MailAddress(_emailSettings.Username);
mailMessage.Subject = template.TemplateName;
mailMessage.Body = template.TemplateContent
.Replace("[Student Name]", $"{student.FirstName} {student.LastName}")
Expand Down Expand Up @@ -106,6 +110,59 @@ public override async Task getListNotifications(ListNotificationRequest request,
await responseStream.WriteAsync(notificationResponse);
}
}

public async Task SendNotifyPendingContribution()
{
Console.WriteLine("Sending notification to faculty coordinators for pending contributions");
var contributions = await _contributionRepository.FindPendingContributions14DaysAgo();
if (contributions.Count == 0)
{
Console.WriteLine("No pending contributions");
}
foreach (var contribution in contributions)
{
var templateNotification = await _templateRepository.FindByTemplateCodeAsync("fac01_noti");
var templateEmail = await _templateRepository.FindByTemplateCodeAsync("fac01_email");
var student = await _userRepository.FindByIdAsync(contribution.DbAuthorId);
if (student.FacultyId == null)
{
throw new Exception("Student has no faculty");
}
var faculty = await _facultyRepository.FindByIdAsync(student.FacultyId.Value);
var users = await _userRepository.FindFacultyCoordinators(student.FacultyId.Value);
foreach (var user in users)
{
var notification = new Model.Notification
{
Content = templateNotification.TemplateContent,
Seen = false,
UserId = user.Id,
WithEmail = true
};
await _notificationRepository.SaveAsync(notification);

using (var mailMessage = new MailMessage())
{
mailMessage.To.Add(new MailAddress(user.Email));
mailMessage.From = new MailAddress(_emailSettings.Username);
mailMessage.Subject = templateEmail.TemplateName;
mailMessage.Body = templateEmail.TemplateContent
.Replace("[Student Name]", $"{student.FirstName} {student.LastName}")
.Replace("[Title of Contribution]", contribution.Title)
.Replace("[Date of Submission]", contribution.UpdatedAt.ToString("dd/MM/yyyy"))
.Replace("[Faculty Name]", faculty.Name);
mailMessage.IsBodyHtml = true;
using (var smtpClient = new SmtpClient(_emailSettings.Host, _emailSettings.Port))
{
smtpClient.Credentials = new NetworkCredential(_emailSettings.Username, _emailSettings.Password);
smtpClient.EnableSsl = _emailSettings.EnableSsl;
await smtpClient.SendMailAsync(mailMessage);
}
}
Console.WriteLine("Email sent to " + faculty.Name + " faculty coordinator");
}
}
}
}
}

2 changes: 1 addition & 1 deletion DotnetGRPC/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
}
},
"ConnectionStrings": {
"DefaultConnection": "Host=comp1640.postgres.database.azure.com;Database=development;Username=comp_1640_admin;Password=NpQT7m8dDr!FuWoG#&$xTpNS*enLPpbywhcJCCeB#7$JvYAsU&5#aWr6&9st&%^&HovS!3dV@rgBV&gU%p&8$h8#2Lp&eN@pv^^biaPVrBCCct6!FrPMfkmWa^&totVx"
"DefaultConnection": "Host=comp1640.postgres.database.azure.com;Database=development;Username=comp_1640_admin;Password=NpQT7m8dDr!FuWoG#&$xTpNS*enLPpbywhcJCCeB#7$JvYAsU&5#aWr6&9st&%^&HovS!3dV@rgBV&gU%p&8$h8#2Lp&eN@pv^^biaPVrBCCct6!FrPMfkmWa^&totVx;Pooling=true;MaxPoolSize=30;MinPoolSize=10;"
},
"EmailSettings": {
"Host": "smtp.gmail.com",
Expand Down

0 comments on commit 8a55d90

Please sign in to comment.