diff --git a/RMuseum/Controllers/GanjoorController.cs b/RMuseum/Controllers/GanjoorController.cs
index 399d4253..79177dc6 100644
--- a/RMuseum/Controllers/GanjoorController.cs
+++ b/RMuseum/Controllers/GanjoorController.cs
@@ -2673,6 +2673,24 @@ namespace RMuseum.Controllers
return Ok(res.Result);
}
+ ///
+ /// start removing category duplicates
+ ///
+ ///
+ ///
+ ///
+ [HttpPut("duplicates/finish/{srcCatId}/{destCatId}")]
+ [Authorize(Policy = RMuseumSecurableItem.GanjoorEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
+ [ProducesResponseType((int)HttpStatusCode.OK)]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
+ public IActionResult StartRemovingCategoryDuplicates(int srcCatId, int destCatId)
+ {
+ var res = _ganjoorService.StartRemovingCategoryDuplicates(srcCatId, destCatId);
+ if (!string.IsNullOrEmpty(res.ExceptionString))
+ return BadRequest(res.ExceptionString);
+ return Ok();
+ }
+
///
/// readonly mode
///
diff --git a/RMuseum/RMuseum.xml b/RMuseum/RMuseum.xml
index 27c08114..cdc933a0 100644
--- a/RMuseum/RMuseum.xml
+++ b/RMuseum/RMuseum.xml
@@ -1648,6 +1648,14 @@
+
+
+ start removing category duplicates
+
+
+
+
+
readonly mode
@@ -11411,6 +11419,14 @@
+
+
+ start removing category duplicates
+
+
+
+
+
translation service implementation
@@ -12860,6 +12876,14 @@
+
+
+ start removing category duplicates
+
+
+
+
+
find category poem rhymes
diff --git a/RMuseum/Services/IGanjoorService.cs b/RMuseum/Services/IGanjoorService.cs
index f202a1c8..5ae1105f 100644
--- a/RMuseum/Services/IGanjoorService.cs
+++ b/RMuseum/Services/IGanjoorService.cs
@@ -869,5 +869,13 @@ namespace RMuseum.Services
///
///
Task> GetCategoryDuplicates(int catId);
+
+ ///
+ /// start removing category duplicates
+ ///
+ ///
+ ///
+ ///
+ RServiceResult StartRemovingCategoryDuplicates(int catId, int destCatId);
}
}
diff --git a/RMuseum/Services/Implementation/GanjoorService-Partials/GanjoorService-DuplicateFinder.cs b/RMuseum/Services/Implementation/GanjoorService-Partials/GanjoorService-DuplicateFinder.cs
index 8932b6b8..5af8b4df 100644
--- a/RMuseum/Services/Implementation/GanjoorService-Partials/GanjoorService-DuplicateFinder.cs
+++ b/RMuseum/Services/Implementation/GanjoorService-Partials/GanjoorService-DuplicateFinder.cs
@@ -53,6 +53,108 @@ namespace RMuseum.Services.Implementation
return new RServiceResult(false, exp.ToString());
}
}
+
+ ///
+ /// start removing category duplicates
+ ///
+ ///
+ ///
+ ///
+ public RServiceResult StartRemovingCategoryDuplicates(int catId, int destCatId)
+ {
+ try
+ {
+ _backgroundTaskQueue.QueueBackgroundWorkItem
+ (
+ async token =>
+ {
+ using (RMuseumDbContext context = new RMuseumDbContext(new DbContextOptions())) //this is long running job, so _context might be already been freed/collected by GC
+ {
+ LongRunningJobProgressServiceEF jobProgressServiceEF = new LongRunningJobProgressServiceEF(context);
+ var job = (await jobProgressServiceEF.NewJob($"RemoveCategoryDuplicates {catId}", "Query data")).Result;
+ try
+ {
+ var dups = await context.GanjoorDuplicates.Where(p => p.SrcCatId == catId && p.DestPoemId != null).OrderBy(p => p.SrcPoemId).ToListAsync();
+ var poems = await context.GanjoorPoems.Where(p => p.CatId == catId).OrderBy(p => p.Id).ToListAsync();
+ if (poems.Count != dups.Count)
+ {
+ await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, "poems.Count != dups.Count");
+ return;
+ }
+
+ foreach (var poem in poems)
+ {
+ if (!dups.Where(d => d.SrcPoemId == poem.Id).Any())
+ {
+ await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, $"poem ID = {poem.Id}, missing destination");
+ return;
+ }
+ }
+
+ foreach (var dup in dups)
+ {
+ var srcPoem = poems.Where(p => p.Id == dup.SrcPoemId).Single();
+
+ var destPage = await context.GanjoorPages.Where(p => p.Id == dup.DestPoemId).SingleAsync();
+ destPage.RedirectFromFullUrl = srcPoem.FullUrl;
+ context.Update(destPage);
+
+ var comments = await context.GanjoorComments.Where(c => c.PoemId == dup.SrcPoemId).ToListAsync();
+ foreach (var comment in comments)
+ {
+ comment.PoemId = (int)dup.DestPoemId;
+ }
+ context.UpdateRange(comments);
+
+ var songs = await context.GanjoorPoemMusicTracks.Where(m => m.PoemId == dup.SrcPoemId).ToListAsync();
+ foreach (var song in songs)
+ {
+ var alreadyAdded = await context.GanjoorPoemMusicTracks.Where(m => m.PoemId == dup.DestPoemId && m.TrackUrl == song.TrackUrl).FirstOrDefaultAsync();
+ if(alreadyAdded != null)
+ {
+ song.PoemId = (int)dup.DestPoemId;
+ }
+ }
+ context.UpdateRange(songs);
+
+ var similars = await context.GanjoorCachedRelatedPoems.Where(s => s.FullUrl == srcPoem.FullUrl).ToListAsync();
+ context.RemoveRange(similars);
+
+ var corrections = await context.GanjoorPoemCorrections.Include(c => c.VerseOrderText).Where(c => c.PoemId == srcPoem.Id).ToListAsync();
+ context.RemoveRange(corrections);
+
+ var page = await context.GanjoorPages.Where(p => p.Id == srcPoem.Id && p.GanjoorPageType == GanjoorPageType.PoemPage).SingleAsync();
+ context.Remove(page);
+
+ await jobProgressServiceEF.UpdateJob(job.Id, 0, srcPoem.FullTitle);
+ }
+ context.RemoveRange(dups);
+ context.RemoveRange(poems);
+
+ await jobProgressServiceEF.UpdateJob(job.Id, 1, "Removing Category and poems");
+
+ var catPage = await context.GanjoorPages.Where(p => p.GanjoorPageType == GanjoorPageType.CatPage && p.CatId == catId).SingleAsync();
+ var destCatPage = await context.GanjoorPages.Where(p => p.GanjoorPageType == GanjoorPageType.CatPage && p.CatId == destCatId).SingleAsync();
+ destCatPage.RedirectFromFullUrl = catPage.FullUrl;
+ context.Update(destCatPage);
+ context.Remove(catPage);
+
+ await jobProgressServiceEF.UpdateJob(job.Id, 100, "", true);
+ }
+ catch (Exception exp)
+ {
+ await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, exp.ToString());
+ }
+
+ }
+ });
+ return new RServiceResult(true);
+ }
+ catch (Exception exp)
+ {
+ return new RServiceResult(false, exp.ToString());
+ }
+ }
private async Task> _FindCategoryPoemsDuplicates(RMuseumDbContext context, int srcCatId, int destCatId)
{
try