fix: use Contains for status matching - catches Complete/Completed/etc, add Dismiss support
This commit is contained in:
@@ -90,7 +90,6 @@ namespace Disco.Plugins.ServiceTracker.Services
|
||||
for (int j = 0; j < fields.Count; j++) if (!string.IsNullOrWhiteSpace(fields[j])) { allEmpty = false; break; }
|
||||
if (allEmpty) continue;
|
||||
|
||||
// Get RAW cell values for stable hashing (before any parsing)
|
||||
var rawTimestamp = RawGet(fields, _config.ColTimestamp);
|
||||
var rawEmail = RawGet(fields, _config.ColEmail);
|
||||
var rawTask = RawGet(fields, _config.ColTask);
|
||||
@@ -113,15 +112,16 @@ namespace Disco.Plugins.ServiceTracker.Services
|
||||
SheetNotes = SafeGet(fields, _config.ColNotes)
|
||||
};
|
||||
|
||||
// Hash uses RAW strings - never changes regardless of date parsing
|
||||
var stableHash = GenerateStableHash(rawTimestamp, rawEmail, rawTask, rawIssue);
|
||||
ticket.InternalId = StableIdFromHash(stableHash, usedIds);
|
||||
ticket.ExternalId = "NTT" + ticket.InternalId.ToString();
|
||||
usedIds.Add(ticket.InternalId);
|
||||
|
||||
// Use Contains for flexible status matching
|
||||
var status = (ticket.RawStatus ?? "").ToLower().Trim();
|
||||
ticket.IsOpen = status != "completed" && status != "closed"
|
||||
&& status != "resolved" && status != "done" && status != "cancelled";
|
||||
ticket.IsOpen = !status.Contains("complete") && !status.Contains("closed")
|
||||
&& !status.Contains("resolved") && !status.Contains("done")
|
||||
&& !status.Contains("cancel") && !status.Contains("finished");
|
||||
|
||||
if (ticket.IsOpen && (!string.IsNullOrWhiteSpace(ticket.TaskTitle) || !string.IsNullOrWhiteSpace(ticket.IssueDescription)))
|
||||
tickets.Add(ticket);
|
||||
@@ -129,36 +129,16 @@ namespace Disco.Plugins.ServiceTracker.Services
|
||||
return tickets;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash from RAW cell text - same spreadsheet cells always produce the same number.
|
||||
/// Uses raw strings, never parsed values, so DateTime.Now never contaminates the hash.
|
||||
/// </summary>
|
||||
private int GenerateStableHash(string rawTimestamp, string rawEmail, string rawTask, string rawIssue)
|
||||
{
|
||||
var key = (rawTimestamp ?? "").Trim().ToLower() + "|"
|
||||
+ (rawEmail ?? "").Trim().ToLower() + "|"
|
||||
+ (rawTask ?? "").Trim().ToLower() + "|"
|
||||
+ (rawIssue ?? "").Trim().ToLower();
|
||||
|
||||
var key = (rawTimestamp ?? "").Trim().ToLower() + "|" + (rawEmail ?? "").Trim().ToLower() + "|" + (rawTask ?? "").Trim().ToLower() + "|" + (rawIssue ?? "").Trim().ToLower();
|
||||
uint hash = 5381;
|
||||
for (int i = 0; i < key.Length; i++)
|
||||
hash = ((hash << 5) + hash) + (uint)key[i];
|
||||
for (int i = 0; i < key.Length; i++) hash = ((hash << 5) + hash) + (uint)key[i];
|
||||
return (int)(hash % 800000) + 100000;
|
||||
}
|
||||
|
||||
private int StableIdFromHash(int baseId, HashSet<int> used)
|
||||
{
|
||||
int id = baseId;
|
||||
while (used.Contains(id)) id++;
|
||||
return id;
|
||||
}
|
||||
|
||||
/// <summary>Returns raw untrimmed cell value for hashing. Never returns null - returns empty string.</summary>
|
||||
private string RawGet(List<string> fields, int index)
|
||||
{
|
||||
if (index < 0 || index >= fields.Count) return "";
|
||||
return fields[index] ?? "";
|
||||
}
|
||||
private int StableIdFromHash(int baseId, HashSet<int> used) { int id = baseId; while (used.Contains(id)) id++; return id; }
|
||||
private string RawGet(List<string> fields, int index) { if (index < 0 || index >= fields.Count) return ""; return fields[index] ?? ""; }
|
||||
|
||||
public static string MapPriority(string raw)
|
||||
{
|
||||
@@ -172,45 +152,15 @@ namespace Disco.Plugins.ServiceTracker.Services
|
||||
return "medium";
|
||||
}
|
||||
|
||||
private string SafeGet(List<string> fields, int index)
|
||||
{
|
||||
if (index < 0 || index >= fields.Count) return null;
|
||||
var val = fields[index].Trim();
|
||||
return string.IsNullOrEmpty(val) ? null : val;
|
||||
}
|
||||
|
||||
private DateTime SafeGetDate(List<string> fields, int index)
|
||||
{
|
||||
var val = SafeGet(fields, index);
|
||||
if (val == null) return DateTime.MinValue;
|
||||
DateTime dt;
|
||||
if (DateTime.TryParse(val, out dt)) return dt;
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
|
||||
private DateTime? SafeGetDateNullable(List<string> fields, int index)
|
||||
{
|
||||
var val = SafeGet(fields, index);
|
||||
if (val == null) return null;
|
||||
DateTime dt;
|
||||
if (DateTime.TryParse(val, out dt)) return dt;
|
||||
return null;
|
||||
}
|
||||
private string SafeGet(List<string> fields, int index) { if (index < 0 || index >= fields.Count) return null; var val = fields[index].Trim(); return string.IsNullOrEmpty(val) ? null : val; }
|
||||
private DateTime SafeGetDate(List<string> fields, int index) { var val = SafeGet(fields, index); if (val == null) return DateTime.MinValue; DateTime dt; if (DateTime.TryParse(val, out dt)) return dt; return DateTime.MinValue; }
|
||||
private DateTime? SafeGetDateNullable(List<string> fields, int index) { var val = SafeGet(fields, index); if (val == null) return null; DateTime dt; if (DateTime.TryParse(val, out dt)) return dt; return null; }
|
||||
|
||||
private List<string> ParseCsvLine(string line)
|
||||
{
|
||||
var fields = new List<string>();
|
||||
bool inQuotes = false;
|
||||
var current = new StringBuilder();
|
||||
for (int i = 0; i < line.Length; i++)
|
||||
{
|
||||
char c = line[i];
|
||||
if (c == '"') { if (inQuotes && i + 1 < line.Length && line[i + 1] == '"') { current.Append('"'); i++; } else inQuotes = !inQuotes; }
|
||||
else if (c == ',' && !inQuotes) { fields.Add(current.ToString()); current.Clear(); }
|
||||
else if (c != '\r') current.Append(c);
|
||||
}
|
||||
fields.Add(current.ToString());
|
||||
return fields;
|
||||
var fields = new List<string>(); bool inQuotes = false; var current = new StringBuilder();
|
||||
for (int i = 0; i < line.Length; i++) { char c = line[i]; if (c == '"') { if (inQuotes && i + 1 < line.Length && line[i + 1] == '"') { current.Append('"'); i++; } else inQuotes = !inQuotes; } else if (c == ',' && !inQuotes) { fields.Add(current.ToString()); current.Clear(); } else if (c != '\r') current.Append(c); }
|
||||
fields.Add(current.ToString()); return fields;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user