Files
redmine/docs/redmine_contacts_search_proposals.md
Jason Thistlethwaite 9ee9eb3ec6 Organized
2026-10-17 20:50:35 -04:00

100 lines
5.3 KiB
Markdown

# Contact search proposals
Situations `redmine_contacts.py search` does not cover, as of the current CLI. Do not treat these commands as existing. The working commands are in [redmine_contacts_search.md](redmine_contacts_search.md).
None of these require changing ticket search. They belong on the contacts CLI, with a dry-run default and no write path.
## 1. Exact company or email domain
**Need:** "everyone at gatsbylady.com" or "company is UPS" without fuzzy misses and without a short string scoring unrelated names.
**Today:** company and email are haystack fields. `search gatsbylady.com` works when that string is inside an email. `search UPS` also fuzzy-matches other fields above `0.68`. There is no `--company` or `--domain`.
**Proposal:**
```bash
./redmine_contacts.py --base-url https://rm.ldrprep.com \
search --domain gatsbylady.com --refresh
./redmine_contacts.py --base-url https://rm.ldrprep.com \
search --company UPS --company-exact --refresh
```
`--domain` matches the part after `@`, case-insensitive, across `emails[]`. `--company-exact` matches `company` after trim and case-fold, not a substring of the whole record. If either flag is set, the positional query becomes optional. Print the same text line `search` prints now, plus `--json` from proposal 5.
## 2. List by filter, with no fuzzy query
**Need:** every contact with no tags, or every contact updated since a date, or every `customer` tag, without inventing a query that happens to score.
**Today:** `search` always requires `query`, then drops anyone under `--min-score`. `--no-tags` and the date flags only narrow that fuzzy set. `fetch --no-tags` caches matches and prints a count, not rows.
**Proposal:** a `list` subcommand that reuses `filter_contacts` and does not call `search_contacts`.
```bash
./redmine_contacts.py --base-url https://rm.ldrprep.com \
list --no-tags --updated-after 2026-09-01 --refresh --limit 50
./redmine_contacts.py --base-url https://rm.ldrprep.com \
list --with-tag promotional-spam --refresh
```
Require at least one filter, same guard as `batch-update`, so `list` cannot dump the whole CRM by accident. Default `--limit 50`. Order by `updated_on` descending. Text lines should include id, name, email, and `tag_list`, because a bare fuzzy score is meaningless here.
Do not overload `search` by making `query` optional. Operators already have to know that `search` is fuzzy.
## 3. Tagged customers with an empty Account Number
**Need:** billed or tagged customers who have no NMI account id in custom field 70 (`Account Number`), so the jumpstart can see who is unmatched.
**Today:** a known account number can be fuzzy-searched if it is already stored. There is no empty-field filter. `show` is one id at a time.
**Proposal:**
```bash
./redmine_contacts.py --base-url https://rm.ldrprep.com \
list --with-tag customer --missing-custom-field account-number --refresh
```
Resolve `account-number` with the existing custom-field slug (`slugify_custom_field_name`). Missing means the field is absent, null, or whitespace. Do not treat `"0"` as empty. Read-only. This is the list command from proposal 2 plus one predicate, not a new writer.
## 4. Open tickets from contacts with a tag
**Need:** New Customer Service tickets whose sender is tagged `promotional-spam`, without hand-joining ids.
**Today:** ticket JSON does not store `tag_list`. `bin/rtl search --where 'helpdesk_ticket.contact.tag_list.includes(...)'` matches nothing. The working path is tag search, then `helpdesk_ticket.contact_id == N` per id.
**Proposal:** a read-only join, not a ticket-cache field.
```bash
./redmine_contacts.py --base-url https://rm.ldrprep.com \
tagged-issues --with-tag promotional-spam --issue-status New --open-only --refresh
```
Steps:
1. Resolve contact ids with the list filter from proposal 2, live or `--refresh`.
2. For each id, call the existing `helpdesk-issues` endpoint, or scan the ticket cache for `helpdesk_ticket.contact_id`.
3. Keep issues that are New, open, and in `customer-service`.
4. Print `issue_id contact_id email subject`, and stop after `--limit` issues (default 20).
Do not close anything. Do not add `tag_list` to the ticket cache in this change. A stale contacts cache must be called out in the header line (`cache_refreshed=yes|no`). Refuse to run if the contact cache host does not match `--base-url`, which the current cache reader already does.
## 5. Script output: ids and JSON
**Need:** feed contact ids into `bin/rtl` or a later join without scraping `score=1.00 via email`.
**Today:** `search` prints prose. `show` and `helpdesk-issues` print JSON for one id. There is no `--ids-only` on this CLI. `bin/rtl contacts-search --ids-only` is the other cache.
**Proposal:** `--json` and `--ids-only` on `search` and on `list`.
```bash
./redmine_contacts.py --base-url https://rm.ldrprep.com \
search promotional-spam --with-tag promotional-spam --refresh --ids-only
```
`--json` prints one object per line: `id`, `name`, `email`, `tag_list`, and `score` when the command was fuzzy. `--ids-only` prints one integer per line. Neither flag changes which rows match.
## Out of scope
Duplicate detection (same email or phone on two contacts) needs a separate scan and a human merge step. Do not fold it into `search`. The existing duplicate-merge note stays the place for that design.
Do not make `batch-update` printable as a search. It requires a mutation payload on purpose.