feat: offer_type (una tantum/retainer), dedup tiers, redesigned Offerte tab

- offer_macros.offer_type ('una_tantum'|'retainer') + editor "Modalità" toggle
  (migration 0012, applied to prod)
- migration 0012 also adds UNIQUE(macro_id, tier_letter) — prevents duplicate
  tiers; ran after a one-time dedup of Web Domination's duplicate A/B/C tiers
- OffersTab redesigned: two-step assign (Offer → Tier cards with price), type
  badge "Una tantum/Ricorrente" instead of misleading "X mesi", no redundant
  "· A" when public_name == tier letter, cleaner active-offers cards
- getProjectFullDetail: availableMicros grouped by macro + defensive dedup;
  projectOffers/availableMicros carry offer_type/category/price
- proposal deck PricingSection shows offer type (fallback to duration for
  pre-existing proposals)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 14:32:59 +02:00
parent 1824cb643f
commit f98828f75e
9 changed files with 333 additions and 132 deletions
+2
View File
@@ -29,6 +29,7 @@ export type AssembledProposal = {
offer: {
macroId: string;
publicName: string;
offerType: string; // una_tantum | retainer
tiers: Array<{
id: string;
tierLetter: string;
@@ -99,6 +100,7 @@ export function assembleProposal(input: AssembleInput): AssembledProposal {
offer: {
macroId: input.offer.macro.id,
publicName: offerTitle,
offerType: input.offer.macro.offer_type ?? "una_tantum",
tiers,
},
};