# Payee Normalization Rules

**Version 2.0** | Last updated: March 2026

These rules define how raw payee names from bank/credit card feeds are normalized into clean, canonical merchant names. They are designed to be replayable on future transaction imports.

Rules are applied in layer order. First match wins for brand rules.

---

## Layer 1: Exact Aliases

User-defined overrides. Checked first, case-insensitive.

| From | To | Notes |
|---|---|---|
| Rancho Meat Market | Mi Rancho | Same restaurant |
| Mi Rancho Mexican Restaurant | Mi Rancho | Same restaurant |
| Mcdonalds? (says "Store") | McDonald's | Quicken display artifact |
| bambi spencer- Fee Amount | Bambi Spencer | Cleanup |
| EB *2025 WASHINGTON RO | Washington Rowing | Eventbrite variant |
| EB 2023 WASHINGTON RO | Washington Rowing | Eventbrite variant |
| EB 2024 WASHINGTON RO | Washington Rowing | Eventbrite variant |
| X8286 - BELLINGHAM INT AI | Bellingham International Airport | Airport code variant |
| CARS Ferndale | CARS Ferndale | Protect from location stripping |

## Layer 2: Prefix Stripping

These prefixes are added by payment processors and carry no merchant info.

| Prefix Pattern | Source |
|---|---|
| `- ...` (leading dash) | Generic |
| `Ext Credit Card Debit/Credit ...` | Credit card processor |
| `TST* ...` | Toast POS |
| `- TST* ...` | Dash + Toast POS |
| `TST ...` (no asterisk) | Toast POS variant |
| `SQ * ...` | Square POS |
| `SQ ...` (no asterisk, caps) | Square POS variant |
| `SQU* ...` | Square POS variant |
| `PY * ...` | PayAnywhere POS |
| `AF* ...` | AF prefix |
| `SP ...` | Shopify POS |
| `Purchase# ...` | Purchase prefix |
| `BILL PAY(xxx) ...` | Bill pay prefix |

## Layer 3: Suffix Stripping

| Suffix Pattern | Example |
|---|---|
| `Card #NNNN` | Card #5988 |
| Country codes (US, USUS, CAUS, JPJP, GBGB, MXMX, etc.) | BELLINGHAM WAUS |

## Layer 3.5: Fee Amount Suffix

Strip `- Fee Amount` suffix from payee names. This is common on Mary's book sale accounts where the payment platform creates separate fee entries.

- Strip pattern: `\s*-?\s*Fee Amount.*$` (case-insensitive)
- Before merging, tag affected transactions with `| Fee` in ZFINOTE
- **CRITICAL**: Use case-INSENSITIVE matching when looking up the base payee (e.g., "Kevin cuddahy" must match "Kevin Cuddahy")

## Layer 4: Brand Rules (99 rules)

These collapse all franchise/store/location variants into one canonical brand name. Matched case-insensitively on the name after prefix/suffix stripping. First match wins.

### Restaurants & Food
| Pattern | Canonical |
|---|---|
| `MCDONALD'S ...` | McDonald's |
| `MC DONALDS ...` | McDonald's |
| `BURGER KING ...` | Burger King |
| `SUBWAY ...` | Subway |
| `CHIPOTLE ...` | Chipotle |
| `JACK IN THE BOX ...` | Jack In The Box |
| `TACO BELL ...` | Taco Bell |
| `TACO TIME ...` | Taco Time |
| `WENDY'S ...` | Wendy's |
| `PORT OF SUBS ...` | Port of Subs |
| `STARBUCKS ...` | Starbucks |
| `EDALEEN DAIRY ...` (incl. FAIRHAVEN) | Edaleen Dairy |
| `BLESSING'S SALON ...` | Blessing's Salon |
| `COMMUNITY FOOD CO-OP ...` | Community Food Co-Op |
| `ALADDIN GYRO ...` | Aladdin Gyro Restaurant |
| `BAGELRY ...` | Bagelry |
| `D'ANNA'S CAFE ITALIA ...` | D'Anna's Cafe Italia |
| `OASIS TEA ZONE ...` | Oasis Tea Zone |
| `SALT & STRAW / SALT AND STRAW ...` | Salt & Straw |
| `WESTSIDE PIZZA ...` | Westside Pizza |
| `IN-N-OUT ...` | In-N-Out Burger |

### Retail & Grocery
| Pattern | Canonical |
|---|---|
| `SAFEWAY FUEL ...` | Safeway Fuel |
| `SAFEWAY ...` (not fuel) | Safeway |
| `WAL-MART / WALMART ...` | Wal-Mart |
| `COSTCO GAS ...` | Costco Gas |
| `COSTCO ...` (not gas) | Costco |
| `HOME DEPOT ...` | Home Depot |
| `LOWE'S / LOWES ...` | Lowe's |
| `FRED MEYER FUEL / FRED M FUEL ...` | Fred Meyer Fuel |
| `FRED MEYER / FRED M ...` (not fuel) | Fred Meyer |
| `RITE AID ...` | Rite Aid |
| `EDDIE BAUER ...` | Eddie Bauer |
| `UNIQLO ...` | Uniqlo |
| `CRUNCHYROLL ...` | Crunchyroll |
| `HOTELS.COM / HOTELCOM ...` | Hotels.com |
| `HARDWARE SALES RENTAL ...` | Hardware Sales Rentals |
| `HARDWARE SALES ...` (not rental) | Hardware Sales |

### Amazon & Streaming
| Pattern | Canonical |
|---|---|
| `AMZN MKTP / AMAZON.COM / AMAZON MARKETPLACE ...` | Amazon |
| `AMAZON KINDLE ...` | Amazon Kindle |
| `AMAZON PRIME ...` | Amazon Prime |
| `PRIME VIDEO ...` | Prime Video |
| `YOUTUBE TV ...` | YouTube TV |
| `YOUTUBE ...` | YouTube |
| `NY TIMES / NYTIMES ...` | NY Times |

### Gas & Auto
| Pattern | Canonical |
|---|---|
| `76 ...` (starting with 76) | 76 Gas Station |
| `ARCO ...` | Arco |
| `SHELL OIL ...` | Shell |
| `UNION 76 ...` | Union 76 |
| `CHEVRON ...` | Chevron |
| `HERTZ RENT-A-CAR ...` | Hertz |

### Airlines & Travel
| Pattern | Canonical |
|---|---|
| `ALASKA AIR ...` | Alaska Air |
| `SOUTHWEST / SOUTHWES ...` | Southwest Airlines |
| `DELTA AIR ...` | Delta Air |
| `UNITED (+ long number) ...` | United Airlines |
| `NWA AIR ...` | Northwest Airlines |
| `ALLEGIANT AIR / ALLEGNT AIR ...` | Allegiant Air |
| `AIR CAN* ...` | Air Canada |
| `FLIX / FLIXBUS ...` | FlixBus |
| `ZIPAIR ...` | Zipair |
| `EASYPARK ...` | EasyPark |

### Construction & Home Services
| Pattern | Canonical |
|---|---|
| `BUILDER'S ALLIANCE / BUILDERS ALLIANC ...` | Builder's Alliance |
| `BUILDERS FIRSTSOURCE ...` | Builders Firstsource |
| `MT. BAKER ROOFING ...` | Mt. Baker Roofing |
| `NOLAN'S ROOFING ...` | Nolan Roofing |
| `MUMM'S ...` | Mumm's HVAC |
| `CLEARWATER ...` | Clearwater Systems |
| `COCHRANE AGENC ...` | Cochrane Agencies |
| `VISTA MATERIALS / SP VISTA MATERIALS ...` | Vista Materials |
| `WINDERMERE PROPE ...` | Windermere Property Management |
| `APPFOLIO ...` | AppFolio |
| `RECYCLING & DISPOSAL ...` | Recycling & Disposal Services |
| `KUBOTA ...` | Kubota |

### Business / Finance
| Pattern | Canonical |
|---|---|
| `FACEBOOK ...` | Facebook Payouts |
| `BANK INT ...` | Bank Interest |
| `LATE FEE ...` | Late Fee |
| `LEMONADE I ...` | Lemonade Insurance |
| `PEARSON EDUCATION / AWL*PEARSON ...` | Pearson Education |
| `CPA VIRTUAL PAY ...` | CPA Virtual Pay |
| `IPHONE CITIZ*PAYMENT ...` | iPhone Payment |
| `KAISER WA PHARMACY / KP BELLINGHAM PHARMA ...` | Kaiser Bellingham Pharmacy |

### Banking / Transfers
| Pattern | Canonical |
|---|---|
| `TRANSFER TO BANK ACCOUNT ...` | Transfer to Bank Account |
| `CHECK (NBR/PAID/#) NNN` | Check (extract number to ZCHECKNUMBER) |
| `ATM WITHDRAWAL ...` | ATM Withdrawal |
| `DEBIT CARD WITHDRAWAL/DEBIT ...` | Debit Card Withdrawal |
| `DEPOSIT : RENT ...` | Deposit: Rent from Westphalen |
| `DEPOSIT GUSTO ...` | Deposit Gusto Payroll |
| `DEPOSIT - TRANSFER FROM DDA NNNN` | Keep as-is (preserve DDA number) |
| `WITHDRAWAL - TRANSFER TO DDA NNNN` | Keep as-is (preserve DDA number) |
| `WITHDRAWAL XXXXXXXX...` | Withdrawal (consolidate masked account variants) |

## Layer 4.5: Gusto Payroll Rules

All Gusto payees with long alphanumeric IDs are consolidated into 3 canonical payees:

| Type Suffix | Canonical |
|---|---|
| `- NET` | Gusto Payroll NET |
| `- TAX` | Gusto Payroll TAX |
| `- FEE` or `ACCTVERIFY` | Gusto Fee |
| `GUSTO NET` (short form) | Gusto Payroll NET |
| `GUSTO TAX` (short form) | Gusto Payroll TAX |
| `GUSTO FEE` (short form) | Gusto Fee |
| `GUSTO PAYROLL ...` | Gusto Payroll NET |

## Layer 5: Location Stripping

Strip trailing city and state info from payee names. Applied after brand rules (so brands aren't affected).

**Exceptions**: Payees starting with "City Of" or "Port Of" are protected — "City Of Bellingham" and "Port of Bellingham" stay as-is.

**42 WA Cities**: Bellingham, Ferndale, Lynden, Seattle, Tacoma, Blaine, Burlington, Mt Vernon, Mount Vernon, Everett, Redmond, Kirkland, Bellevue, Spokane, Olympia, Anacortes, Marysville, Kenmore, Bothell, Lynnwood, Shoreline, Renton, Kent, Auburn, Federal Way, Sumas, Nooksack, Everson, Deming, Maple Falls, Sedro Woolley, Custer, Birch Bay, Bow, SeaTac, Tukwila, Issaquah, Woodinville, Lake Forest Park, Mukilteo, Edmonds, Snohomish

**Formats stripped**: `MERCHANT BELLINGHAM WA`, `MERCHANT BELLINGHAMWA`, `MERCHANT BELLINGHAM`

**Trailing state abbreviations** are also stripped after city removal.

## Layer 6: Cleanup

- Strip trailing store numbers (#1234, STORE 1234, plain 4+ digit numbers)
- **Exception**: Deposit/Withdrawal/Transfer payees keep their numbers
- Normalize curly apostrophes to straight
- Collapse multiple spaces
- Strip trailing punctuation (, . -)

## Layer 7: Check Number Extraction

For payees matching "Check" patterns, extract the check number and populate ZCHECKNUMBER on the transaction.

| Pattern | Example | Extracted |
|---|---|---|
| `Check NNNN` | Check 1002 | 1002 |
| `CHECK # NNNN` | CHECK # 7615 7615 | 7615 |
| `Check Paid - NNNN` | Check Paid - 249 249 | 249 |
| `Check Nbr. NNNN` | Check Nbr. 3020 | 3020 |
| `REMOTE ONLINE DEPOSIT # N` | REMOTE ONLINE DEPOSIT # 1 | 1 |

---

## Provenance: Original Payee → ZFINOTE

Before any payee rename or merge, the original payee name is preserved in the transaction's ZFINOTE (Financial Institution Note) field.

- **Empty ZFINOTE**: Set to original payee name
- **Existing ZFINOTE**: Append ` | orig: [original payee name]`
- **Fee transactions**: Additionally tagged with `| Fee` in ZFINOTE

This ensures you can always trace back to the original bank-imported name.

---

## Consolidation Policies

### NEVER Consolidate (Keep Separate)

| Pair | Reason |
|---|---|
| Costco / Costco Gas | Different categories (groceries vs gas) |
| Fred Meyer / Fred Meyer Fuel | Different categories |
| Safeway / Safeway Fuel | Different categories |
| Amazon / Amazon Kindle | Different services |
| Hardware Sales / Hardware Sales Rentals | Sales vs equipment rental |
| YouTube / YouTube TV | Different services |
| Interest Earned / Interest Charge | Income vs expense |
| Hold placed by / Hold Released By | Different transaction types |

### Deposit Policy

**NEVER** consolidate payees starting with "Deposit". Each deposit variant is distinct and important:
- Deposit - Transfer from *3188
- Deposit GoFundMe PAYOUT
- Deposit VENMO - CASHOUT
- Deposit: Rent from Westphalen
- Deposit Gusto Payroll
- etc.

Same for: Descriptive Deposit, Descriptive Withdrawal, Direct Deposit, External Deposit.

### Withdrawal Policy

Consolidate `Withdrawal XXXXXXXX*` (masked account number variants) into plain "Withdrawal". Keep all named/specific withdrawal variants separate (Transfer to DDA, Transfer to *3188, etc.).

### Interest Policy

Always split into "Interest Earned" (income) and "Interest Charge" (expense). Never merge these together.

### Venmo Rules

| Pattern | Action |
|---|---|
| `Spencer Peters Charged/Paid ...` variants | Merge ALL into single "Spencer Peters". Descriptions already in ZFINOTE. |
| `Ted Peters Paid [Person] [desc]` | Extract person name as new payee. Use ZFINOTE first word to find boundary between person and description. |

---

## Categorization Policies

(To be expanded as categorization proceeds)

### Entity Model
Five separate entities, categorized independently:
1. **Ted Consumption** — checking, savings, credit cards, cash, loans, credit lines (excluding TPC, DB, Mary, Investment, Kagari accounts)
2. **Ted Investment** — brokerage, IRAs, SEPs, CDs-as-brokerage, assets
3. **Mary** — all Mary/Lisa/Aussie/Secret/C-Izzy accounts
4. **TPC** — all TPC/Builders Alliance accounts
5. **DB** — all DB- prefixed accounts

### Specific Category Rules
- **Edaleen Dairy** → Restaurants
- **iPhone Payment** → Stuff >> Hardware
- **Costco Gas**, **Safeway Fuel**, **Fred Meyer Fuel** → Auto >> Gas (separate from parent store)
- **Bank Interest** — no per-institution tracking needed
- **Deposit: Rent from Westphalen** — keep separate from generic Deposit
- **Domestic Wire** — keep company names (Chicago Title, Stewart Title, etc.)
- **Facebook** → Facebook Payouts (not Ads)

### Execution Stats (March 2026)

| Metric | Before | After |
|---|---|---|
| Total payees | 9,703 | 1,836 |
| Orphaned payees (0 txns) | 6,943 | 0 |
| Merge groups applied | — | 264 + 308 consolidation |
| Transactions with ZFINOTE provenance | — | 16,656 |
| Fee transactions tagged | — | 335 |
| Check numbers extracted | — | 48+ |
| Spencer Peters variants merged | 18 | 1 |
| Gusto variants merged | 90 | 3 |
| Fee Amount payees merged | 329 | 0 |
