feat(berths): website auto-promote toggle + manual-override soft-pin priority
- website_berth_autopromote_enabled (default OFF): a website registration for a specific, currently-available berth auto-creates a prospect (client + optional yacht + interest) and links the berth is_specific_interest=true, flipping the public map to Under Offer; general/residence/contact submissions stay capture-only. Marks the submission converted so a rep never double-creates it. - derivePublicStatus now honours a manual pin (soft pin): a manually-set status wins over the interest-derived Under Offer, but a real permanent tenancy or an explicit sold still override it. - berth rules engine respects a manual pin EXCEPT for sale triggers (-> sold), so a confirmed sale still wins but soft auto-changes never stomp a pin. - Reset-to-automatic action (service + API POST /berths/[id]/status/reset + UI) to drop a manual pin; lock badge on every manual override (list + detail); divergence banner prompting reset when a pinned-Available berth has a deal. - migration stage map updated to the §4b signed-off mapping: GQI -> enquiry unless it named a berth/size marker (-> qualified); SQI -> qualified. Tests: +public-berths soft-pin cases, +website-intake-promote helpers, +migration GQI marker rule. 1582 unit/integration green; tsc clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -117,6 +117,31 @@ describe('derivePublicStatus', () => {
|
||||
expect(derivePublicStatus('available', true)).toBe('Under Offer');
|
||||
});
|
||||
});
|
||||
|
||||
describe('manual override (soft pin)', () => {
|
||||
it('a manual "available" pin wins over an active specific-interest link', () => {
|
||||
// The key behaviour: a rep deliberately keeping a berth Available is NOT
|
||||
// overridden by an interest-derived "Under Offer".
|
||||
expect(derivePublicStatus('available', true, false, 'manual')).toBe('Available');
|
||||
});
|
||||
it('a manual "under_offer" pin shows Under Offer', () => {
|
||||
expect(derivePublicStatus('under_offer', false, false, 'manual')).toBe('Under Offer');
|
||||
});
|
||||
it('a manual "sold" pin shows Sold', () => {
|
||||
expect(derivePublicStatus('sold', false, false, 'manual')).toBe('Sold');
|
||||
});
|
||||
it('a real permanent tenancy still overrides a manual "available" pin (soft pin)', () => {
|
||||
expect(derivePublicStatus('available', false, true, 'manual')).toBe('Sold');
|
||||
expect(derivePublicStatus('available', true, true, 'manual')).toBe('Sold');
|
||||
});
|
||||
it('"automated" override mode falls through to normal derivation (interest promotes)', () => {
|
||||
expect(derivePublicStatus('available', true, false, 'automated')).toBe('Under Offer');
|
||||
});
|
||||
it('null/omitted override mode preserves pre-pin behaviour', () => {
|
||||
expect(derivePublicStatus('available', true, false, null)).toBe('Under Offer');
|
||||
expect(derivePublicStatus('available', true, false)).toBe('Under Offer');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPermanentTenureType', () => {
|
||||
|
||||
Reference in New Issue
Block a user