# Feature Specification: General CRM Backlog Fixes

**Feature Branch**: `fix/general-backlog`

**Created**: 2026-08-21

**Status**: Draft

**Input**: User description: "Spec a bundle of 5 backlog items: (1) non-effective Interações must be saved even without a Profissional indication, (2) in the Profissional form, add 'não sei' options to radio groups and add a number-of-children field with related dynamic fields, (3) partial term search on system-wide selects, (4) fix infinite loading when an ajax call returns empty data, (5) create a qualification status on Canais to be considered in the Profissional qualification index, and prioritize cellphone numbers over landline numbers when displaying/editing phone data."

**Scope note**: The Canal-qualification-status-in-the-index half of item (5) was explicitly descoped by the user during clarification and is deferred to a future spec; only the cellphone-vs-landline display-order half is covered here (User Story 5).

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Log a non-effective interaction without a Profissional (Priority: P1)

A salesperson tries to log an interaction that did not reach anyone at the company (e.g., a call that went unanswered) and marks it as "Não Efetivo". Today the form still forces them to pick at least one Profissional before it can be saved, which does not reflect reality — there was no one to pick. The salesperson needs to save the record of the attempt anyway.

**Why this priority**: This is a data-loss bug — unreachable-contact attempts are currently impossible to log at all, which undercounts real sales activity and effort.

**Independent Test**: Open the interaction form, mark "Não Efetivo", leave "Profissionais" empty, and save. The interaction is created successfully and appears in the company's interaction history with no Profissional linked.

**Acceptance Scenarios**:

1. **Given** a new interaction marked "Não Efetivo", **When** the user saves it without selecting any Profissional, **Then** the interaction is saved successfully and linked to zero Profissionais.
2. **Given** a new interaction marked "Efetivo", **When** the user tries to save it without selecting any Profissional, **Then** the system still blocks the save and asks for at least one Profissional (existing behavior is preserved for effective interactions).
3. **Given** an interaction saved as "Não Efetivo" with no Profissional, **When** it is later viewed in the company's interaction history, **Then** it displays correctly without errors, showing no Profissional associated.

---

### User Story 2 - See a clear empty state instead of an endless spinner (Priority: P2)

A user searches or filters a list (professionals, interactions, or any other record table in the system) and the search legitimately has no matches. Instead of a "no results" message, the loading indicator spins forever, making the user think the system is frozen or broken.

**Why this priority**: This is a broadly reproducible bug that affects any list/table in the system whenever a query returns zero rows, blocking users from continuing their work without a page reload.

**Independent Test**: Filter any record list by a term guaranteed to match nothing. The loading indicator clears and an empty-state message is shown instead of spinning indefinitely.

**Acceptance Scenarios**:

1. **Given** a list/table anywhere in the system, **When** the underlying query returns zero results, **Then** the loading indicator is removed and a clear "no results" state is shown instead of an indefinite spinner.
2. **Given** a list/table that previously showed an empty state, **When** the user changes the search/filter to one that matches records, **Then** the normal populated table is shown again with loading behaving normally.

---

### User Story 3 - Find options by typing any part of their name (Priority: P3)

A user starts typing part of a name into any of the system's searchable dropdowns (e.g., selecting a Profissional, a produto, an empresa) but the term they remember is in the middle or end of the name rather than the beginning. Today the dropdown fails to find it, forcing the user to guess the exact start of the label.

**Why this priority**: This is a systemic usability gap affecting every searchable select across the system, slowing down data entry and lookups system-wide.

**Independent Test**: Open any searchable select in the system and type a substring taken from the middle of a known option's label. The option appears in the results.

**Acceptance Scenarios**:

1. **Given** any searchable select in the system, **When** the user types a substring that appears anywhere within an option's label (not only at the start), **Then** that option appears in the filtered results.
2. **Given** a searchable select with a server-side (type-ahead) search, **When** the user types a partial term, **Then** matching options are returned regardless of where the term appears in the label.

---

### User Story 4 - Record "não sei" and multiple children on a Profissional (Priority: P4)

A user filling out or updating a Profissional's personal data often doesn't know the answer to certain personal questions (e.g., sex, marital status) and is currently forced to pick one of the definite options, silently recording incorrect data. Separately, when a Profissional has more than one child, the form only lets the user record a single child's details, even though it asks "does this person have children" as if it could support more.

**Why this priority**: Forcing a guess on unknown personal data pollutes the database with incorrect information used elsewhere (e.g., qualification scoring), and undercounting children misrepresents the Profissional's profile — both matter, but are lower urgency than the two bugs above.

**Independent Test**: Open the Profissional form, select "não sei" on a personal-data question that previously had no such option, and save — the choice is preserved. Separately, enter a number of children greater than one and fill in each child's own name/sex/birth year, then save and reopen the record to confirm all children were kept.

**Acceptance Scenarios**:

1. **Given** the Profissional form, **When** the user opens a personal-data radio group that today only offers definite options (e.g., sex, marital status), **Then** a "Não sei" option is available and can be selected and saved.
2. **Given** a Profissional marked as having children, **When** the user enters a number of children greater than one, **Then** the form presents one set of child fields (name, sex, birth year) per child.
3. **Given** a Profissional with multiple children already saved, **When** the record is reopened for editing, **Then** all previously saved children are shown with their individual data.
4. **Given** a Profissional's number of children is reduced on an edit, **When** the change is saved, **Then** only the remaining children's data is kept and the removed children's data is no longer associated with the Profissional.

---

### User Story 5 - Show the cellphone number first (Priority: P5)

A user viewing or editing a Profissional's phone numbers wants to see the number they'd actually call — the cellphone — front and center, instead of having to scan past landline numbers that happen to have been entered first.

**Why this priority**: A display-ordering refinement that improves usability but changes no data and blocks no workflow.

**Independent Test**: Add a landline number first and a cellphone number second to a Profissional's record. Reopen the record — the cellphone number is shown before the landline number everywhere phone numbers are listed.

**Acceptance Scenarios**:

1. **Given** a Profissional with both a cellphone and a landline number saved, **When** their phone data is displayed in any list, panel, or edit form, **Then** the cellphone number is shown before the landline number.
2. **Given** a Profissional with only landline numbers, **When** their phone data is displayed, **Then** the existing order among landline numbers is preserved.

---

### Edge Cases

- If an interaction is changed from "Não Efetivo" to "Efetivo" (at creation or on a later edit) while no Profissional is selected, the save is blocked until at least one Profissional is chosen, consistent with the existing rule for effective interactions.
- A list/table's empty state must be distinguishable from a failed request (e.g., a network or server error still surfaces an error, rather than silently showing "no results").
- Selecting "Não sei" on a field that is also read by the qualification-completeness calculation is treated as "not answered" (does not count as filled), the same as leaving the field blank today.
- Reducing a Profissional's number of children on an edit permanently discards the data of the removed children — this is a destructive action and should be treated accordingly by the implementation.
- A Profissional with two or more cellphone numbers keeps their relative order among themselves; only the cellphone-vs-landline grouping is reordered.

## Requirements *(mandatory)*

### Functional Requirements

**Interação save behavior**

- **FR-001**: System MUST allow a non-effective ("Não Efetivo") interaction to be saved with zero Profissionais linked.
- **FR-002**: System MUST continue to require at least one Profissional before an effective ("Efetivo") interaction can be saved.
- **FR-003**: System MUST correctly display and report on interactions that have no Profissional linked, without errors.

**List/table loading behavior**

- **FR-004**: System MUST clear the loading indicator for any list/table view once its query completes, regardless of whether the query returned any rows.
- **FR-005**: System MUST show a clear "no results" state when a list/table query returns zero rows.
- **FR-006**: This behavior MUST apply consistently to every list/table in the system that shares the current loading/pagination behavior, not only to the table(s) where the bug was first observed.

**System-wide select search**

- **FR-007**: System MUST match a typed search term against any part of an option's label, not only its beginning, in every searchable select across the system.
- **FR-008**: This behavior MUST apply consistently to both client-side-filtered selects and selects backed by server-side (type-ahead) search.

**Profissional form fields**

- **FR-009**: System MUST offer a "Não sei" choice on Profissional radio-group questions that currently force a definite answer with no neutral/unknown option (at minimum: sex, and marital status).
- **FR-010**: System MUST let the user record a number of children for a Profissional, rather than only a yes/no "has children" flag.
- **FR-011**: System MUST present one set of child fields (name, sex, birth year) for each child indicated by the number of children.
- **FR-012**: System MUST persist and redisplay each child's individual data when the Profissional record is reopened.
- **FR-013**: System MUST update the set of saved children when the number of children is changed on an edit, discarding data for children that no longer exist.

**Phone number display order**

- **FR-014**: System MUST classify each stored phone number as a cellphone or a landline number.
- **FR-015**: System MUST display a Profissional's cellphone numbers before their landline numbers in every place phone numbers are listed, viewed, or edited.

### Key Entities

- **Interação**: A logged contact event with a company, with an effectiveness flag (Efetivo/Não Efetivo), a channel, a status, and zero or more linked Profissionais.
- **Profissional**: An individual contact person at a company, holding personal/demographic data (sex, marital status, children, decision power, etc.), contact data (emails, phone numbers), and a qualification completeness score.
- **Filho (Child)**: A dependent record belonging to a Profissional (name, sex, birth year); a Profissional can have zero or more.
- **Telefone (Phone number)**: A phone number belonging to a Profissional, classified as cellphone or landline for display ordering purposes.

## Success Criteria *(mandatory)*

### Measurable Outcomes

- **SC-001**: 100% of non-effective interaction attempts can be saved without a Profissional selected, down from being fully blocked today.
- **SC-002**: A search or filter that returns zero results shows a "no results" state within the same time a populated result would have appeared, in place of an indefinite spinner, across all record lists in the system.
- **SC-003**: Users successfully locate an option in a searchable select by typing any substring of its label, not only its first characters, across all system selects.
- **SC-004**: Users can record "não sei" instead of guessing on the personal-data questions identified in FR-009, and can register more than one child per Profissional with individual details for each.
- **SC-005**: When viewing or editing any Profissional that has at least one cellphone number on file, that number is the first phone number shown, 100% of the time.

## Assumptions

- "Profissional" refers to the system's existing Profissional entity (an individual contact at a company); this is the entity the Interação, radio-group, and phone-ordering items in this spec all operate on.
- Effective interactions keep requiring at least one Profissional; only the non-effective case changes.
- "Não sei" is added to the radio groups that today force a binary/definite answer with no neutral option (sex, marital status, and the equivalent spouse/child sex groups); it is not necessarily added to every radio group in the form (e.g., "Poder de decisão" already has a neutral "Neutro" option).
- Cellphone-vs-landline classification is derived by the system from the stored number itself rather than requiring users to manually tag each phone number, since no such classification is captured today.
- The partial-term search change applies to selects that already support typed search; it does not add search capability to selects that don't already have it.
- Adding a qualification status to Canais and factoring it into the Profissional qualification index is out of scope for this spec (explicitly deferred by the user) and will be specified separately.
