diff --git a/RMuseum/Services/Implementation/GanjoorService.cs b/RMuseum/Services/Implementation/GanjoorService.cs index 9c7b7ab7..83828355 100644 --- a/RMuseum/Services/Implementation/GanjoorService.cs +++ b/RMuseum/Services/Implementation/GanjoorService.cs @@ -2102,6 +2102,11 @@ namespace RMuseum.Services.Implementation if (correction.GeoDateTags != null) { + // already-approved tags for this poem, used below to reject suggestions that just + // repeat what's already tagged on the same couplet - no extra service call needed, + // GetPoemById above always loads this + var approvedGeoDateTags = poem.GeoDateTags ?? Array.Empty(); + foreach (var geoDateTag in correction.GeoDateTags) { if (!geoDateTag.MarkForDelete) @@ -2113,6 +2118,34 @@ namespace RMuseum.Services.Implementation { return new RServiceResult(null, "برچسب جغرافیایی/تاریخی باید حداقل شامل مکان یا تاریخ باشد."); } + + // PoemGeoDateTag.CoupletIndex uses 0 for "whole poem", matching a null CoupletIndex here + int effectiveCoupletIndex = geoDateTag.CoupletIndex ?? 0; + var approvedForCouplet = approvedGeoDateTags.Where(t => t.CoupletIndex == effectiveCoupletIndex); + + if (hasLocation) + { + bool locationAlreadyTagged = geoDateTag.LocationId != null + ? approvedForCouplet.Any(t => t.LocationId == geoDateTag.LocationId) + : approvedForCouplet.Any(t => t.Location != null && + string.Equals(t.Location.Name?.Trim(), geoDateTag.SuggestedLocationName.Trim(), StringComparison.OrdinalIgnoreCase)); + if (locationAlreadyTagged) + { + return new RServiceResult(null, "این مکان از قبل برای همین بیت ثبت شده است."); + } + } + + if (hasDate) + { + bool dateAlreadyTagged = approvedForCouplet.Any(t => + t.LunarYear == geoDateTag.LunarYear && + t.LunarMonth == geoDateTag.LunarMonth && + t.LunarDay == geoDateTag.LunarDay); + if (dateAlreadyTagged) + { + return new RServiceResult(null, "این تاریخ از قبل برای همین بیت ثبت شده است."); + } + } } } }