Skip to content

feat: add Home Depot provider#77

Open
fnziman wants to merge 1 commit into
eshaffer321:mainfrom
fnziman:feat/homedepot-provider
Open

feat: add Home Depot provider#77
fnziman wants to merge 1 commit into
eshaffer321:mainfrom
fnziman:feat/homedepot-provider

Conversation

@fnziman

@fnziman fnziman commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Adds a new homedepot subcommand that syncs Home Depot purchases into Monarch, mirroring the walmart/costco/amazon providers.

Closes / references #31. Design follows the plan you signed off on in that thread.

Design

  • Companion Go client: github.com/fnziman/homedepot-go — MIT, tagged release v0.1.1 — handles the internal /oms/customer/order/v1/user/{userId}/orderhistory + /orderdetails endpoints via cookie replay (decodes THD_CUSTOMER for the auth token). The client itself is scrubbed-fixtures-only (no real cookies/tokens/PII), 85.6% covered, go 1.25.12 to match this repo's CI pin.
  • Provider package at internal/adapters/providers/homedepot/. Wraps the client's OrderDetail / LineItem types to satisfy providers.Order / providers.OrderItem. Both online and in-store orders supported. Online orders use orderNumber as the dedup ID; in-store use a composite hd-instore-{store}-{transactionId} (since orderNumber is empty for in-store).
  • Wiring: internal/cli/providers.go:NewHomeDepotProvider (mirrors the costco/walmart shape, threads a scoped *slog.Logger via hdgo.Config{Logger: hdLogger} — matches the walmart/costco Config-struct pattern per your ask), new case "homedepot": in cmd/itemize/main.go, HomeDepotConfig in config.go, homedepot: block in config.yaml, env-var fallbacks (HOMEDEPOT_LOOKBACK_DAYS, HOMEDEPOT_MAX_ORDERS, HOMEDEPOT_COOKIE_FILE).
  • Merchant matching: no interface change needed. fetch.go matches on DisplayName() which is "Home Depot" — that case-insensitively substring-matches Monarch's canonical "THE HOME DEPOT".
  • Refunds & Ollama: intentionally out of scope for v1 (per your "keep the PR focused" note). SupportsRefunds() = false; refund handling can go in a follow-up.

Test plan

  • go test ./... -race — all green, provider package at 95.1% coverage, categorizer/adapter packages unchanged
  • go vet ./... — clean
  • golangci-lint run ./... — clean for touched files (two pre-existing QF1012 warnings on categorizer.go:285,290 predate this PR)
  • go build -o itemize ./cmd/itemize/./itemize shows homedepot Sync Home Depot orders in usage and HOMEDEPOT_* env vars in help
  • go.mod stays on go 1.25.12 (verified after go mod tidy)
  • Manual live run on my own account: HOMEDEPOT_COOKIE_FILE=~/.homedepot-api/cookies.json ./itemize homedepot -dry-run -days 14 -verbose — happy to run this and report back once you've had a chance to look at the code

Docs

  • README updated with homedepot row + example usage
  • New docs/homedepot-specifics.md covers cookie export walkthrough (DevTools snippet), the online/in-store distinction, 24-month history cap, MFA re-auth flow, and a troubleshooting table

Deferred / follow-ups (not in this PR per your "keep it focused" note)

  • Refund handling (OrderDetail.returnTotal is available; just not wired)
  • LICENSE file on this repo
  • docs/adding-providers.md refresh (still references the pre-rename module path and internal/providers/)

Happy to iterate — let me know if you'd like any part of this reshaped before merge.

Adds a new `homedepot` subcommand that syncs Home Depot purchases into
Monarch, mirroring the walmart/costco/amazon providers.

Design (per proposal in eshaffer321#31):
- Companion Go client github.com/fnziman/homedepot-go handles the
  internal /oms/customer/order/v1 API via cookie replay (THD_CUSTOMER
  cookie decoded for the auth token). itemize depends on tagged
  release v0.1.1.
- Provider adapter at internal/adapters/providers/homedepot/ wraps
  the client's OrderDetail + LineItem types to satisfy
  providers.Order + providers.OrderItem.
- Both online and in-store schemas supported. Online orders use
  orderNumber as the dedup ID; in-store use a composite
  hd-instore-{store}-{transactionId} since orderNumber is empty.

Registration:
- internal/cli/providers.go: NewHomeDepotProvider — mirrors the
  costco/walmart factory shape, threads a scoped *slog.Logger through
  to homedepot-go.
- cmd/itemize/main.go: `case "homedepot":` in the subcommand switch;
  printUsage rows for the command and the HOMEDEPOT_* env vars.
- internal/infrastructure/config/config.go: HomeDepotConfig struct,
  env-var defaults in LoadFromEnv (HOMEDEPOT_LOOKBACK_DAYS,
  HOMEDEPOT_MAX_ORDERS, HOMEDEPOT_COOKIE_FILE).
- config.yaml: `homedepot:` block.

Merchant matching: no interface change needed. fetch.go matches
against DisplayName(), which is "Home Depot" — case-insensitive
substring-matches Monarch's "THE HOME DEPOT" cleanly.

Tests: 95.1% coverage on the provider package. Mock hdClient
interface; every FetchOrders / GetOrder / HealthCheck / GetItems /
GetSKU / GetQuantity path tested. All Order/OrderItem interface
compliance asserted at compile time.

Docs: README provider row + full walkthrough at
docs/homedepot-specifics.md (cookie export, MFA re-auth, 24-month
history cap, troubleshooting table). Attribution to
joshellissh/homedepot-history in the client's README.

Refs eshaffer321#31

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.87179% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.06%. Comparing base (8cb5ee9) to head (75a2dfb).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/adapters/providers/homedepot/provider.go 93.10% 4 Missing ⚠️
internal/adapters/providers/homedepot/order.go 96.22% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #77      +/-   ##
==========================================
+ Coverage   64.34%   65.06%   +0.71%     
==========================================
  Files          49       51       +2     
  Lines        6575     6761     +186     
==========================================
+ Hits         4231     4399     +168     
- Misses       2037     2046       +9     
- Partials      307      316       +9     
Flag Coverage Δ
unittests 65.06% <94.87%> (+0.71%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
internal/infrastructure/config/config.go 82.05% <100.00%> (+0.97%) ⬆️
internal/adapters/providers/homedepot/order.go 96.22% <96.22%> (ø)
internal/adapters/providers/homedepot/provider.go 93.10% <93.10%> (ø)

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant