Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/2097-lead-owner-not-required.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'hotcrm': patch
---

A sales rep can create a lead without first picking themselves as its owner. The **New Lead** form marked **Lead Owner** as required, so clicking **Create** with the field left blank stopped at *"Lead Owner is required"* and nothing was saved. The form no longer requires it. A lead created with the field left blank is owned by the person who created it, as on the **Opportunity**, **Account** and **Contact** New forms. **Lead Owner** stays on the form.
10 changes: 6 additions & 4 deletions src/sales/views/lead.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,12 @@ export const LeadViews = defineView({
},
'lead_source',
'industry',
{
field: 'owner_id',
required: true,
},
// Offered, ⛔ not `required` (#2097): an insert that leaves it empty is
// stamped to the creator by the platform (see `lead.hook.ts`), so a
// rep's new lead is theirs without a pick. `required` blocked that
// save client-side. A pick of another owner on create is currently
// dropped by the console (objectui#12359).
'owner_id',
// `disqualification_reason` is enforced by the
// `disqualification_reason_required` validation on crm_lead, so every
// form that lets a user pick "Unqualified" must also offer the reason
Expand Down
16 changes: 16 additions & 0 deletions test/ownership-model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { InMemoryDriver } from '@objectstack/driver-memory';
import type { VerifyStack } from '@objectstack/verify';
import stack from './helpers/composed-stack';
import { hotcrmStack, signUpPerson, type Person } from './helpers/verify-stack';
import { LeadViews } from '../src/sales/views/lead.view';

/**
* ═══ HotCRM has ONE owner, and it is the platform's (#548) ════════════════
Expand Down Expand Up @@ -162,6 +163,21 @@ describe('one ownership column, and it is `owner_id`', () => {
);
expect(withDefault, 'owner_id must have no schema default').toEqual([]);
});

it('the New Lead form leaves `owner_id` to that stamp — offered, not required (#2097)', () => {
// `LeadViews.form` IS the create dialog (see `case-create-form-narrowing`),
// and a `required` entry there is a client-side submit check. Measured on
// 18.0.0-next.0: a rep's Leads → New stopped at "Lead Owner is required"
// with nothing POSTed, so the stamp never saw the insert. The server half —
// a rep's ownerless insert lands owned by the rep — is pinned end to end by
// `stands down when the middleware already stamped an owner` below.
const entries: unknown[] = ((LeadViews as AnyRec).form?.sections ?? []).flatMap(
(s: AnyRec) => s.fields ?? [],
);
const owner = entries.find((f) => (typeof f === 'string' ? f : (f as AnyRec)?.field) === 'owner_id');
expect(owner, 'owner_id left the New Lead form — this pin would judge nothing').toBeDefined();
expect((owner as AnyRec)?.required === true, 'the New Lead form demands an owner again').toBe(false);
});
});

// ──────────────────────────────────── which writers the gate can see ──
Expand Down
Loading