Organized
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
# Contact search (`redmine_contacts.py`)
|
||||
|
||||
`./redmine_contacts.py search --help` prints three short examples. This page is the situation list. Gaps are in [redmine_contacts_search_proposals.md](redmine_contacts_search_proposals.md).
|
||||
|
||||
This CLI was not changed to write this page. Commands below match the current `search` / `show` / `helpdesk-issues` behavior.
|
||||
|
||||
## What `search` actually does
|
||||
|
||||
1. Load the contact cache, or reload it with `--refresh`.
|
||||
2. Apply exact filters: `--with-tag`, `--without-tag`, `--no-tags`, `--created-after`, `--created-before`, `--updated-after`, `--updated-before`.
|
||||
3. Fuzzy-score the remaining contacts against the required positional query.
|
||||
4. Print text lines, capped by `--limit` (default 20).
|
||||
|
||||
It does not search tickets. It does not print JSON. A normal search still requires `REDMINE_API_KEY` even when it only reads the cache. `--offline-cache` is the exception.
|
||||
|
||||
Default host is the LAN copy, `http://192.168.50.170`. Production:
|
||||
|
||||
```bash
|
||||
cd /home/jason/projects/redmine
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com search "Sahar Daod"
|
||||
```
|
||||
|
||||
Cache file: `.cache/redmine_contacts/<host>_<project>.json`, relative to the current directory. A cache built for one host is rejected for another. This is not `bin/rtl contacts-search`.
|
||||
|
||||
A hit is a substring of a scored field after lowercasing, or a fuzzy score of at least `0.68`. Scored fields: name, email, phone, company, job title, background, website, skype, tags, address, and custom-field values. A phone query is also matched on digits only, so `847-313-1342` hits `8473131342`.
|
||||
|
||||
Output shape: `id: name | company | email | phone | score=1.00 via email`. Use `show <id>` for the record.
|
||||
|
||||
`--refresh` pages through every project contact before scoring. Without it, a tag or field written since the last fetch is invisible.
|
||||
|
||||
## Supported
|
||||
|
||||
### 1. Find a person by name, email, or phone
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com search "Sahar Daod"
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com search sahardaod4@groovinfulfillment.com
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com search 847-313-1342
|
||||
```
|
||||
|
||||
Then the record, including `tag_list`:
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com show 4589
|
||||
```
|
||||
|
||||
`show` prints JSON. `--source api` skips a stale cache. `--source cache` does not call Redmine.
|
||||
|
||||
### 2. Find people at a company, or everyone on one email domain
|
||||
|
||||
Company and email are scored fields, not dedicated filters. A domain that appears in the address scores `1.00`.
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com search gatsbylady.com --refresh
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com search "Cyberstorm" --min-score 0.9
|
||||
```
|
||||
|
||||
Raise `--min-score` when a short company name also fuzzy-matches unrelated contacts. There is no `--company` or `--email-domain` flag. An exact company filter is proposal 1.
|
||||
|
||||
### 3. Exact tag
|
||||
|
||||
`--with-tag` is exact and case-insensitive. The positional query is still required and still fuzzy, so repeat the tag as the query. Otherwise a contact with the tag can be filtered in and then dropped because the name did not fuzzy-match.
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com \
|
||||
search promotional-spam --with-tag promotional-spam --refresh --limit 50
|
||||
```
|
||||
|
||||
Offline, against the cache already on disk for that host:
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com \
|
||||
search promotional-spam --with-tag promotional-spam --offline-cache
|
||||
```
|
||||
|
||||
Repeat `--with-tag` to require every tag. Repeat `--without-tag` to exclude any of those tags.
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com \
|
||||
search customer --with-tag customer --without-tag promotional-spam --limit 20
|
||||
```
|
||||
|
||||
`--no-tags` cannot be combined with `--with-tag`. Listing every untagged contact is not this command. See proposal 2.
|
||||
|
||||
### 4. A tag, narrowed by when the contact was created or updated
|
||||
|
||||
Date flags are exact. The query is still required, so this finds "this text, inside this window," not "everyone touched this week."
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com \
|
||||
search customer --with-tag customer --updated-after 2026-09-01 --refresh
|
||||
```
|
||||
|
||||
Dates are `YYYY-MM-DD` or a full ISO datetime. A date-only `--updated-before` includes that whole UTC day. Listing by date with no text query is proposal 2.
|
||||
|
||||
### 5. A known account number or other custom-field value
|
||||
|
||||
Custom-field values are scored if they are already on the cached contact. Account Number is custom field 70.
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com search 7385Y6 --refresh
|
||||
```
|
||||
|
||||
This finds a value you already know. It cannot list customers whose Account Number is empty. That is proposal 3.
|
||||
|
||||
### 6. Their tickets, once you have the contact id
|
||||
|
||||
`search` stops at the contact. These follow-ups are live reads, not the contact cache.
|
||||
|
||||
```bash
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com helpdesk-issues 4589 --limit 20
|
||||
./redmine_contacts.py --base-url https://rm.ldrprep.com helpdesk-timeline 4589 --limit 20
|
||||
```
|
||||
|
||||
Both print JSON from `/helpdesk_search/contacts/:id/...`.
|
||||
|
||||
Cached Customer Service tickets, any status:
|
||||
|
||||
```bash
|
||||
bin/rtl search --order newest-updated-first --max-tickets 20 \
|
||||
--where 'helpdesk_ticket.contact_id == 4589 AND project.name == "Customer Service"'
|
||||
```
|
||||
|
||||
Open New only:
|
||||
|
||||
```bash
|
||||
bin/rtl search --status New --open-only \
|
||||
--where 'helpdesk_ticket.contact_id == 4589'
|
||||
```
|
||||
|
||||
`bin/rtl search` cannot filter on `tag_list`. The ticket's contact stub is `id`, `name`, `email`, `company`. This returns nothing and does not error:
|
||||
|
||||
```bash
|
||||
bin/rtl search --where 'helpdesk_ticket.contact.tag_list.includes("promotional-spam")'
|
||||
```
|
||||
|
||||
One command that means "New tickets from contacts tagged promotional-spam" is proposal 4. `bin/rtl contacts-search --tag` is a different cache and can lag a live tag.
|
||||
|
||||
## Not a search
|
||||
|
||||
`fetch --with-tag customer` writes a cache and prints a count. It does not list contacts.
|
||||
|
||||
`batch-update` can select by the same tag and date filters, but it requires an update payload and exists to write. Do not use it as a lister.
|
||||
|
||||
`loop-run` is a triage worker, not a search.
|
||||
Reference in New Issue
Block a user