diff --git a/docs/commands.md b/docs/commands.md index 85acc01..74a88ed 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1358,6 +1358,14 @@ records that are not prospects. Bulk archive ends mail and keeps list membership it closes open opportunities unless `--no-cascade` is supplied. A positional `prospect_...` ID continues to use the single-prospect operation. +### International Owner + +Property search, count and export accept `international_owner` in the `--body` filters array. Use `true` for foreign mailing addresses, `false` to exclude them, or omit the filter for Any. The source is `MailingForeignAddressInd`: Canada (`C`) and other foreign addresses (`Y`) are international; null values and US territories are excluded. + +```bash +dm properties count --body '{"filters":[{"filter_id":"international_owner","value":true}]}' +``` + ## Archive a mail campaign End the campaign first with `dm mail campaigns end --yes`. Archiving an active, paused, ready or draft campaign returns `409 CAMPAIGN_NOT_ENDED` without changing it. diff --git a/src/index.ts b/src/index.ts index 6e08adb..14ea383 100644 --- a/src/index.ts +++ b/src/index.ts @@ -654,6 +654,12 @@ Examples: // Properties commands // ============================================================================ +const internationalOwnerHelp = ` +International Owner: use international_owner in --body filters. + true: foreign mailing addresses (Canada and other countries). + false: only addresses without a foreign indicator. Omit for Any. + Source: MailingForeignAddressInd; US territories are excluded.`; + const propertiesCmd = program .command('properties') .alias('prop') @@ -679,11 +685,13 @@ propertiesCmd ` Examples: dm properties search --body '{"locations":[{"type":"zip_code","code":"78704"}]}' + dm properties search --body '{"filters":[{"filter_id":"international_owner","value":true}]}' --estimate-cost dm properties search -f search-query.json --estimate-cost dm properties search -f query.json --json Estimate automatically dm properties search -f query.json --json --yes Run after approval cat query.json | dm properties search --json` ) + .addHelpText('after', internationalOwnerHelp) .action(async (options) => { await propertiesSearch(options); }); @@ -706,8 +714,10 @@ propertiesCmd ` Examples: dm properties count --body '{"locations":[{"type":"zip_code","code":"78704"}]}' - dm properties count -f query.json --json` + dm properties count -f query.json --json + dm properties count --body '{"filters":[{"filter_id":"international_owner","value":true}]}'` ) + .addHelpText('after', internationalOwnerHelp) .action(async (options) => { await propertiesCount(options); }); @@ -791,8 +801,10 @@ Examples: dm properties export -f query.json --json dm properties export -f query.json --require-phone --scrub-dnc dm properties export --body '{"locations":[{"type":"state","code":"TX"}]}' --mobile-only - dm properties export -f query.json --anchor property --contact-audience none` + dm properties export -f query.json --anchor property --contact-audience none + dm properties export --body '{"filters":[{"filter_id":"international_owner","value":false}]}'` ) + .addHelpText('after', internationalOwnerHelp) .action(async (options) => { await propertiesExport(options); }); diff --git a/tests/commands/publicApiExtensions.test.ts b/tests/commands/publicApiExtensions.test.ts index b5c8497..d68bbcc 100644 --- a/tests/commands/publicApiExtensions.test.ts +++ b/tests/commands/publicApiExtensions.test.ts @@ -33,7 +33,7 @@ vi.mock('../../src/lib/output.js', () => ({ import { printJson, printKeyValue, printTable } from '../../src/lib/output.js'; import { peopleGet, peopleIds, peopleSearch, peopleExport } from '../../src/commands/people.js'; -import { propertiesGet, propertiesIds, propertiesSearch, propertiesExport } from '../../src/commands/properties.js'; +import { propertiesGet, propertiesIds, propertiesSearch, propertiesExport, propertiesCount } from '../../src/commands/properties.js'; import { enrichAddress, enrichApn, @@ -620,3 +620,11 @@ describe.each([ }); }); }); + + +it.each([true, false])('passes International Owner %s to property counts without changing its meaning', async (value) => { + const filters = [{ filter_id: "international_owner", value }]; + mockParseRequestBody.mockResolvedValue({ filters }); + await propertiesCount({ body: JSON.stringify({ filters }), json: true }); + expect(mockApiRequest).toHaveBeenCalledWith("/properties/search/count", expect.objectContaining({ method: "POST", body: expect.objectContaining({ filters }) })); +});