Add manual "Sync Columbia" action and status to powder catalog admin
Phase 3: SuperAdmin-triggered sync. Adds a SyncColumbia POST action that runs a full catalog sync on demand (bypassing the schedule) and reports the result via TempData. The catalog index header gains a "Sync Columbia" button (with a syncing spinner) and a status line showing the scheduled-sync on/off state, last-synced time, and last-run summary, read from the platform settings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using PowderCoating.Application.Constants;
|
||||||
using PowderCoating.Application.DTOs.Common;
|
using PowderCoating.Application.DTOs.Common;
|
||||||
using PowderCoating.Application.DTOs.Inventory;
|
using PowderCoating.Application.DTOs.Inventory;
|
||||||
using PowderCoating.Application.Interfaces;
|
using PowderCoating.Application.Interfaces;
|
||||||
@@ -19,15 +20,21 @@ public class PowderCatalogController : Controller
|
|||||||
|
|
||||||
private readonly IUnitOfWork _unitOfWork;
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
private readonly IInventoryAiLookupService _aiLookupService;
|
private readonly IInventoryAiLookupService _aiLookupService;
|
||||||
|
private readonly IColumbiaCatalogSyncService _columbiaSyncService;
|
||||||
|
private readonly IPlatformSettingsService _platformSettings;
|
||||||
private readonly ILogger<PowderCatalogController> _logger;
|
private readonly ILogger<PowderCatalogController> _logger;
|
||||||
|
|
||||||
public PowderCatalogController(
|
public PowderCatalogController(
|
||||||
IUnitOfWork unitOfWork,
|
IUnitOfWork unitOfWork,
|
||||||
IInventoryAiLookupService aiLookupService,
|
IInventoryAiLookupService aiLookupService,
|
||||||
|
IColumbiaCatalogSyncService columbiaSyncService,
|
||||||
|
IPlatformSettingsService platformSettings,
|
||||||
ILogger<PowderCatalogController> logger)
|
ILogger<PowderCatalogController> logger)
|
||||||
{
|
{
|
||||||
_unitOfWork = unitOfWork;
|
_unitOfWork = unitOfWork;
|
||||||
_aiLookupService = aiLookupService;
|
_aiLookupService = aiLookupService;
|
||||||
|
_columbiaSyncService = columbiaSyncService;
|
||||||
|
_platformSettings = platformSettings;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,6 +142,11 @@ public class PowderCatalogController : Controller
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Columbia sync status for the admin panel (last run + master switch).
|
||||||
|
ViewBag.ColumbiaSyncEnabled = await _platformSettings.GetBoolAsync(ColumbiaIntegrationConstants.SettingEnabled);
|
||||||
|
ViewBag.ColumbiaLastSyncedAt = await _platformSettings.GetAsync(ColumbiaIntegrationConstants.SettingLastSyncedAt);
|
||||||
|
ViewBag.ColumbiaLastResult = await _platformSettings.GetAsync(ColumbiaIntegrationConstants.SettingLastResult);
|
||||||
|
|
||||||
return View(vm);
|
return View(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,6 +434,24 @@ public class PowderCatalogController : Controller
|
|||||||
return Json(results);
|
return Json(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manually triggers a full Columbia Coatings catalog sync (SuperAdmin only). Bypasses the
|
||||||
|
/// scheduled interval. Reports the run outcome via TempData on the catalog index.
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> SyncColumbia(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _columbiaSyncService.RunSyncAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (result.Success)
|
||||||
|
TempData["Success"] = $"Columbia sync complete — {result.Summary}";
|
||||||
|
else
|
||||||
|
TempData["Error"] = $"Columbia sync failed: {result.ErrorMessage}";
|
||||||
|
|
||||||
|
return RedirectToAction(nameof(Index));
|
||||||
|
}
|
||||||
|
|
||||||
// Private helpers
|
// Private helpers
|
||||||
|
|
||||||
private async Task ApplyTdsCureFallbackAsync(InventoryAiLookupResult result, string? colorName)
|
private async Task ApplyTdsCureFallbackAsync(InventoryAiLookupResult result, string? colorName)
|
||||||
|
|||||||
@@ -110,12 +110,42 @@
|
|||||||
<div class="text-muted small">Platform-level lookup library for inventory autofill, SDS/TDS links, and curing specs.</div>
|
<div class="text-muted small">Platform-level lookup library for inventory autofill, SDS/TDS links, and curing specs.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
|
<form asp-action="SyncColumbia" method="post" class="d-inline"
|
||||||
|
onsubmit="this.querySelector('button').disabled=true;this.querySelector('button').innerHTML='<span class=\'spinner-border spinner-border-sm me-1\'></span>Syncing…';">
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
|
<button type="submit" class="btn btn-outline-primary" title="Pull the latest Columbia Coatings catalog now">
|
||||||
|
<i class="bi bi-cloud-download me-1"></i>Sync Columbia
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
<a asp-action="Create" class="btn btn-primary">
|
<a asp-action="Create" class="btn btn-primary">
|
||||||
<i class="bi bi-plus-circle me-1"></i>Add Powder
|
<i class="bi bi-plus-circle me-1"></i>Add Powder
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@{
|
||||||
|
var columbiaLastSynced = ViewBag.ColumbiaLastSyncedAt as string;
|
||||||
|
var columbiaLastResult = ViewBag.ColumbiaLastResult as string;
|
||||||
|
var columbiaEnabled = ViewBag.ColumbiaSyncEnabled is true;
|
||||||
|
}
|
||||||
|
<div class="alert alert-light border d-flex flex-wrap align-items-center gap-2 small mb-4 alert-permanent">
|
||||||
|
<span class="badge @(columbiaEnabled ? "bg-success" : "bg-secondary")">
|
||||||
|
Scheduled sync @(columbiaEnabled ? "on" : "off")
|
||||||
|
</span>
|
||||||
|
@if (!string.IsNullOrWhiteSpace(columbiaLastSynced) && DateTime.TryParse(columbiaLastSynced, out var lastSyncedAt))
|
||||||
|
{
|
||||||
|
<span class="text-muted">Last synced @lastSyncedAt.ToLocalTime().ToString("MMM d, yyyy h:mm tt")</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="text-muted">Never synced</span>
|
||||||
|
}
|
||||||
|
@if (!string.IsNullOrWhiteSpace(columbiaLastResult))
|
||||||
|
{
|
||||||
|
<span class="text-muted">— @columbiaLastResult</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row g-3 mb-4 powder-catalog-summary">
|
<div class="row g-3 mb-4 powder-catalog-summary">
|
||||||
<div class="col-sm-6 col-xl-2">
|
<div class="col-sm-6 col-xl-2">
|
||||||
<div class="card h-100">
|
<div class="card h-100">
|
||||||
|
|||||||
Reference in New Issue
Block a user