Refine Columbia sync after first live run
Fixes from reviewing the first full sync of the real catalog:
- Exclude non-powder / size-variant listings: physical swatch cards (-SW /
"SWATCH"), 4 oz testers (-04 / "Tester"), and 5 lb sample bags ("Sample (").
These are not standalone powder colors. Filtered before mapping, and a
cleanup step deletes any already synced (so they're removed, not flagged
discontinued). Sample detection keys off the "Sample (" name, not the bare
-S suffix, to avoid catching a real SKU ending in S (verified 0 collisions).
- Tighten RequiresClearCoat: was flagging ~53% of the catalog on any casual
"clear coat" mention. Now only genuine signals (partial-cure schedules, the
Illusion line, explicit "requires a clear" phrasing) trip it.
- Fix literal "—" in the sync success banner (TempData is HTML-encoded).
Tests cover the exclusion patterns and the tightened clear-coat detection.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -121,6 +121,23 @@ public class ColumbiaCatalogMapperTests
|
||||
Assert.False(ColumbiaCatalogMapper.IsAdditive(p));
|
||||
}
|
||||
|
||||
// ── Excluded products (swatches + tester/sample size variants) ────────
|
||||
|
||||
[Theory]
|
||||
[InlineData("T1696049-SW", "**SWATCH** - Copperhead II", true)] // swatch card
|
||||
[InlineData("T1696049-SW", "Copperhead II", true)] // -SW suffix alone
|
||||
[InlineData("X1", "**SWATCH** - Something", true)] // name marker alone
|
||||
[InlineData("T1696049-04", "Copperhead II (4 Ounce Tester)", true)] // tester = size variant
|
||||
[InlineData("XYZ", "Copperhead II (4 Ounce Tester)", true)] // tester by name
|
||||
[InlineData("S1760090-S", "Black Beauty Sample (5 lbs)", true)] // 5lb sample = size variant
|
||||
[InlineData("X5004124", "Blue Wrinkle", false)] // normal powder
|
||||
[InlineData("S5704126", "Smokey Blue", false)] // normal powder, SKU starts with S
|
||||
public void IsExcludedProduct_DetectsSwatchesTestersAndSamples(string sku, string name, bool expected)
|
||||
{
|
||||
var p = new ColumbiaProduct { Sku = sku, Name = name };
|
||||
Assert.Equal(expected, ColumbiaCatalogMapper.IsExcludedProduct(p));
|
||||
}
|
||||
|
||||
// ── Pricing ───────────────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
@@ -219,15 +236,45 @@ public class ColumbiaCatalogMapperTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DetectRequiresClearCoat_IllusionDescription_IsTrue()
|
||||
public void DetectRequiresClearCoat_ExplicitRequirement_IsTrue()
|
||||
{
|
||||
var p = new ColumbiaProduct
|
||||
{
|
||||
Description = "This Illusion powder requires a clear coat to activate the effect.",
|
||||
Description = "This powder requires a clear coat to activate the effect.",
|
||||
};
|
||||
Assert.True(ColumbiaCatalogMapper.DetectRequiresClearCoat(p));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DetectRequiresClearCoat_IllusionLine_IsTrue()
|
||||
{
|
||||
var p = new ColumbiaProduct { Name = "Illusion Cherry", Description = "A translucent red." };
|
||||
Assert.True(ColumbiaCatalogMapper.DetectRequiresClearCoat(p));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DetectRequiresClearCoat_PartialCureSchedule_IsTrue()
|
||||
{
|
||||
var p = new ColumbiaProduct
|
||||
{
|
||||
Name = "Some Base",
|
||||
CureSchedule = "Partial Cure: 15 min total time in oven preheated to 400°F. Then apply clear.",
|
||||
};
|
||||
Assert.True(ColumbiaCatalogMapper.DetectRequiresClearCoat(p));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DetectRequiresClearCoat_CasualMention_IsFalse()
|
||||
{
|
||||
// The over-flagging case: a passing mention is not a requirement.
|
||||
var p = new ColumbiaProduct
|
||||
{
|
||||
Name = "Gloss Black",
|
||||
Description = "Durable gloss black. Apply a clear coat for added protection if desired.",
|
||||
};
|
||||
Assert.False(ColumbiaCatalogMapper.DetectRequiresClearCoat(p));
|
||||
}
|
||||
|
||||
// ── End-to-end mapping invariants ─────────────────────────────────────
|
||||
|
||||
// ── Tolerant image deserialization (WordPress returns [] / false when empty) ──
|
||||
|
||||
Reference in New Issue
Block a user