146 lines
6.0 KiB
Markdown
146 lines
6.0 KiB
Markdown
# 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.
|