Files
hamkadr/src/JobsMedical.Web/Pages/Admin/Ingested.cshtml.cs
T

68 lines
3.1 KiB
C#
Raw Normal View History

using JobsMedical.Web.Data;
using JobsMedical.Web.Models;
using JobsMedical.Web.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
namespace JobsMedical.Web.Pages.Admin;
/// <summary>Every crawled item with its outcome (queued / published / flagged / discarded),
/// filterable by status and source — the full audit trail of ingestion.</summary>
[Authorize(Roles = "Admin")]
public class IngestedModel : PageModel
{
private readonly AppDbContext _db;
public IngestedModel(AppDbContext db) => _db = db;
public List<RawListing> Items { get; private set; } = new();
public int Total { get; private set; }
public Dictionary<RawListingStatus, int> Counts { get; private set; } = new();
[TempData] public string? Message { get; set; }
[BindProperty(SupportsGet = true)] public string? Status { get; set; } // new|flagged|published|discarded|all
[BindProperty(SupportsGet = true)] public string? Source { get; set; }
public async Task OnGetAsync()
{
Counts = await _db.RawListings.GroupBy(r => r.Status)
.Select(g => new { g.Key, C = g.Count() }).ToDictionaryAsync(x => x.Key, x => x.C);
var q = _db.RawListings.AsNoTracking().AsQueryable();
var st = Status?.ToLowerInvariant() switch
{
"new" => (RawListingStatus?)RawListingStatus.New,
"flagged" => RawListingStatus.Flagged,
"published" => RawListingStatus.Normalized,
"discarded" => RawListingStatus.Discarded,
_ => null,
};
if (st is not null) q = q.Where(r => r.Status == st);
if (!string.IsNullOrWhiteSpace(Source)) q = q.Where(r => r.SourceChannel.Contains(Source));
Total = await q.CountAsync();
Items = await q.OrderByDescending(r => r.FetchedAt).Take(200).ToListAsync();
}
/// <summary>
/// Bulk-delete everything that was published from ingestion: the aggregated Shift/Job/Talent
/// posts on the site AND the approved (Normalized) raw items that produced them. Done in a
/// transaction; the linked raw rows are removed first since they hold FKs to the posts.
/// </summary>
public async Task<IActionResult> OnPostDeletePublishedAsync()
{
await using var tx = await _db.Database.BeginTransactionAsync();
var raws = await _db.RawListings.Where(r => r.Status == RawListingStatus.Normalized).ExecuteDeleteAsync();
var shifts = await _db.Shifts.Where(s => s.Source == ShiftSource.Aggregated).ExecuteDeleteAsync();
var jobs = await _db.JobOpenings.Where(j => j.Source == ShiftSource.Aggregated).ExecuteDeleteAsync();
var talent = await _db.TalentListings.Where(t => t.Source == ShiftSource.Aggregated).ExecuteDeleteAsync();
await tx.CommitAsync();
string P(int n) => JalaliDate.ToPersianDigits(n.ToString());
Message = $"حذف شد: {P(shifts)} شیفت، {P(jobs)} استخدام، {P(talent)} آماده‌به‌کار و {P(raws)} آیتم جمع‌آوری.";
return RedirectToPage(new { Status });
}
}