16 Commits

Author SHA1 Message Date
db9018722d Merge pull request 'feat: add gitea-tea skill and update AGENTS.md for PR workflow' (#4) from alluring-houseboat into master
Reviewed-on: #4
2026-04-25 20:05:38 -07:00
0e57550b3c stuff 2026-04-25 19:41:40 -07:00
297464c188 Merge branch 'master' of codecommit://integreat 2026-03-30 22:38:34 -07:00
6e3a024f66 adds stuff for dough burger 2026-03-30 22:36:12 -07:00
Bryce
28a755e9a9 fixes invoice date filtering 2026-03-02 23:20:14 -08:00
Bryce
01347ff3f5 fixes balance sheet 2026-03-02 22:53:53 -08:00
53625e4583 Makes invoices use the closed_at date. 2026-02-21 22:53:05 -08:00
8899c643ed Complete code review session - documented findings for auto_ap.permissions, iol-ion.query, and auto_ap.ss.admin.background-jobs 2026-02-08 09:31:26 -08:00
c196723913 ok. 2026-02-08 08:43:53 -08:00
395e445c99 Add test for Bonanza Produce invoice 03882095
Validates existing template correctly parses multi-page invoice with:
- Invoice number 03882095
- Customer identifier NICK THE GREEK
- Account number 600 VISTA WAY
- Total of $946.24
2026-02-08 08:40:40 -08:00
8a0395dc4a Add Bonanza Produce multi-invoice statement template
- Added multi-invoice template for Bonanza Produce with :multi and :multi-match? flags
- Template uses keywords for statement header to identify multi-invoice format
- Extracts invoice-number, date, customer-identifier (from RETURN line), and total
- Parses 4 invoices from statement PDF 13595522.pdf
- All tests pass (29 assertions, 0 failures, 0 errors)

- Added test: parse-bonanza-produce-statement-13595522
- Updated invoice-template-creator skill: emphasized test-first approach
2026-02-08 07:56:14 -08:00
26dbde5bd3 Add invoice-template-creator skill for automated template generation
New repository-based skill at .claude/skills/invoice-template-creator/:
- SKILL.md: Complete guide for creating invoice parsing templates
- references/examples.md: Common patterns and template examples
- Covers vendor identification, regex patterns, field extraction
- Includes testing strategies and common pitfalls

Updated AGENTS.md with reference to the new skill.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-08 07:55:55 -08:00
98a3e0dda6 Extract customer name and address for Bonanza Produce
- customer-identifier field: customer name (e.g., 'NICK THE GREEK')
- account-number field: street address (e.g., '600 VISTA WAY')
- Combined they provide full customer identification with address
- Updated test to verify both fields and their concatenation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-08 07:55:26 -08:00
f4366fe98e Add location extraction for Bonanza Produce invoices
- Extract city/state/zip in location field
- Customer address now split across 3 fields:
  - customer-identifier: customer name
  - account-number: street address
  - location: city, state zip
- All components verified in test

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-08 07:55:12 -08:00
d95e24a1d7 Improve Bonanza Produce customer identifier extraction
- Extract customer name in customer-identifier field
- Extract street address in account-number field
- Use non-greedy regex with lookahead to capture clean values
- Update test to verify both name and address extraction

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-08 07:50:55 -08:00
37351e5f92 Add Bonanza Produce invoice template
- Add new PDF template for Bonanza Produce vendor
- Template uses phone number 530-544-4136 as unique identifier
- Extracts invoice number, date, customer identifier, and total
- Includes passing test for invoice 03881260

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-08 07:50:42 -08:00
12 changed files with 889 additions and 44 deletions

View File

@@ -0,0 +1,174 @@
---
name: clojure-eval
description: Evaluate Clojure code via nREPL using clj-nrepl-eval. Use this when you need to test code, check if edited files compile, verify function behavior, or interact with a running REPL session.
---
# Clojure REPL Evaluation
## When to Use This Skill
Use this skill when you need to:
- **Verify that edited Clojure files compile and load correctly**
- Test function behavior interactively
- Check the current state of the REPL
- Debug code by evaluating expressions
- Require or load namespaces for testing
- Validate that code changes work before committing
## How It Works
The `clj-nrepl-eval` command evaluates Clojure code against an nREPL server. **Session state persists between evaluations**, so you can require a namespace in one evaluation and use it in subsequent calls. Each host:port combination maintains its own session file.
## Instructions
### 0. Discover and select nREPL server
First, discover what nREPL servers are running in the current directory:
```bash
clj-nrepl-eval --discover-ports
```
This will show all nREPL servers (Clojure, Babashka, shadow-cljs, etc.) running in the current project directory.
**Then use the AskUserQuestion tool:**
- **If ports are discovered:** Prompt user to select which nREPL port to use:
- **question:** "Which nREPL port would you like to use?"
- **header:** "nREPL Port"
- **options:** Present each discovered port as an option with:
- **label:** The port number
- **description:** The server type and status (e.g., "Clojure nREPL server in current directory")
- Include up to 4 discovered ports as options
- The user can select "Other" to enter a custom port number
- **If no ports are discovered:** Prompt user how to start an nREPL server:
- **question:** "No nREPL servers found. How would you like to start one?"
- **header:** "Start nREPL"
- **options:**
- **label:** "deps.edn alias", **description:** "Find and use an nREPL alias in deps.edn"
- **label:** "Leiningen", **description:** "Start nREPL using 'lein repl'"
- The user can select "Other" for alternative methods or if they already have a server running on a specific port
IMPORTANT: IF you start a REPL do not supply a port let the nREPL start and return the port that it was started on.
### 1. Evaluate Clojure Code
> Evaluation automatically connects to the given port
Use the `-p` flag to specify the port and pass your Clojure code.
**Recommended: Pass code as a command-line argument:**
```bash
clj-nrepl-eval -p <PORT> "(+ 1 2 3)"
```
**For multiple expressions (single line):**
```bash
clj-nrepl-eval -p <PORT> "(def x 10) (+ x 20)"
```
**Alternative: Using heredoc (may require permission approval for multiline commands):**
```bash
clj-nrepl-eval -p <PORT> <<'EOF'
(def x 10)
(+ x 20)
EOF
```
**Alternative: Via stdin pipe:**
```bash
echo "(+ 1 2 3)" | clj-nrepl-eval -p <PORT>
```
### 2. Display nREPL Sessions
**Discover all nREPL servers in current directory:**
```bash
clj-nrepl-eval --discover-ports
```
Shows all running nREPL servers in the current project directory, including their type (clj/bb/basilisp) and whether they match the current working directory.
**Check previously connected sessions:**
```bash
clj-nrepl-eval --connected-ports
```
Shows only connections you have made before (appears after first evaluation on a port).
### 3. Common Patterns
**Require a namespace (always use :reload to pick up changes):**
```bash
clj-nrepl-eval -p <PORT> "(require '[my.namespace :as ns] :reload)"
```
**Test a function after requiring:**
```bash
clj-nrepl-eval -p <PORT> "(ns/my-function arg1 arg2)"
```
**Check if a file compiles:**
```bash
clj-nrepl-eval -p <PORT> "(require 'my.namespace :reload)"
```
**Multiple expressions:**
```bash
clj-nrepl-eval -p <PORT> "(def x 10) (* x 2) (+ x 5)"
```
**Complex multiline code (using heredoc):**
```bash
clj-nrepl-eval -p <PORT> <<'EOF'
(def x 10)
(* x 2)
(+ x 5)
EOF
```
*Note: Heredoc syntax may require permission approval.*
**With custom timeout (in milliseconds):**
```bash
clj-nrepl-eval -p <PORT> --timeout 5000 "(long-running-fn)"
```
**Reset the session (clears all state):**
```bash
clj-nrepl-eval -p <PORT> --reset-session
clj-nrepl-eval -p <PORT> --reset-session "(def x 1)"
```
## Available Options
- `-p, --port PORT` - nREPL port (required)
- `-H, --host HOST` - nREPL host (default: 127.0.0.1)
- `-t, --timeout MILLISECONDS` - Timeout (default: 120000 = 2 minutes)
- `-r, --reset-session` - Reset the persistent nREPL session
- `-c, --connected-ports` - List previously connected nREPL sessions
- `-d, --discover-ports` - Discover nREPL servers in current directory
- `-h, --help` - Show help message
## Important Notes
- **Prefer command-line arguments:** Pass code as quoted strings: `clj-nrepl-eval -p <PORT> "(+ 1 2 3)"` - works with existing permissions
- **Heredoc for complex code:** Use heredoc (`<<'EOF' ... EOF`) for truly multiline code, but note it may require permission approval
- **Sessions persist:** State (vars, namespaces, loaded libraries) persists across invocations until the nREPL server restarts or `--reset-session` is used
- **Automatic delimiter repair:** The tool automatically repairs missing or mismatched parentheses
- **Always use :reload:** When requiring namespaces, use `:reload` to pick up recent changes
- **Default timeout:** 2 minutes (120000ms) - increase for long-running operations
- **Input precedence:** Command-line arguments take precedence over stdin
## Typical Workflow
1. Discover nREPL servers: `clj-nrepl-eval --discover-ports`
2. Use **AskUserQuestion** tool to prompt user to select a port
3. Require namespace:
```bash
clj-nrepl-eval -p <PORT> "(require '[my.ns :as ns] :reload)"
```
4. Test function:
```bash
clj-nrepl-eval -p <PORT> "(ns/my-fn ...)"
```
5. Iterate: Make changes, re-require with `:reload`, test again

View File

@@ -0,0 +1,82 @@
# clj-nrepl-eval Examples
## Discovery
```bash
clj-nrepl-eval --connected-ports
```
## Heredoc for Multiline Code
```bash
clj-nrepl-eval -p 7888 <<'EOF'
(defn greet [name]
(str "Hello, " name "!"))
(greet "Claude")
EOF
```
### Heredoc Simplifies String Escaping
Heredoc avoids shell escaping issues with quotes, backslashes, and special characters:
```bash
# With heredoc - no escaping needed
clj-nrepl-eval -p 7888 <<'EOF'
(def regex #"\\d{3}-\\d{4}")
(def message "She said \"Hello!\" and waved")
(def path "C:\\Users\\name\\file.txt")
(println message)
EOF
# Without heredoc - requires complex escaping
clj-nrepl-eval -p 7888 "(def message \"She said \\\"Hello!\\\" and waved\")"
```
## Working with Project Namespaces
```bash
# Test a function after requiring
clj-nrepl-eval -p 7888 <<'EOF'
(require '[clojure-mcp-light.delimiter-repair :as dr] :reload)
(dr/delimiter-error? "(defn foo [x]")
EOF
```
## Verify Compilation After Edit
```bash
# If this returns nil, the file compiled successfully
clj-nrepl-eval -p 7888 "(require 'clojure-mcp-light.hook :reload)"
```
## Session Management
```bash
# Reset session if state becomes corrupted
clj-nrepl-eval -p 7888 --reset-session
```
## Common Workflow Patterns
### Load, Test, Iterate
```bash
# After editing a file, reload and test in one command
clj-nrepl-eval -p 7888 <<'EOF'
(require '[my.namespace :as ns] :reload)
(ns/my-function test-data)
EOF
```
### Run Tests After Changes
```bash
clj-nrepl-eval -p 7888 <<'EOF'
(require '[my.project.core :as core] :reload)
(require '[my.project.core-test :as test] :reload)
(clojure.test/run-tests 'my.project.core-test)
EOF
```

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads

View File

@@ -0,0 +1,127 @@
---
name: gitea-tea
description: Use tea CLI to create, manage, and checkout Gitea pull requests. Use this when opening a PR, managing PRs, or checking out PRs on the gitea remote (gitea.story-basking.ts.net).
---
# Gitea Tea CLI Skill
This skill covers using `tea` (Gitea's official CLI) for pull request workflows in this project.
## When to Use This Skill
Use this skill when you need to:
- Create a PR from a working branch to master on the gitea remote
- Open, list, or view PRs
- Checkout a PR locally for review or iteration
- Manage PR state (close, reopen, merge)
## Project Setup
The gitea remote is `gitea.story-basking.ts.net` with repo slug `notid/integreat`. The default push remote is **gitea**, NOT origin and NOT deploy.
In this project's environment:
- Gitea login is pre-configured for `gitea.story-basking.ts.net`
- Repo slug: `notid/integreat`
- Target branch for PRs: `master`
- The git remote named `gitea` points to this instance
## Creating a PR
Use `tea pulls create` to open a PR from the current branch to master. Always specify `-r notid/integreat -b master`:
```bash
tea pulls create -r notid/integreat -b master --title "Title" --description "Body"
```
Common flags:
- `-t, --title` - PR title
- `-d, --description` - PR body/description (use heredoc or file for long descriptions)
- `-a, --assignees` - Comma-separated usernames to assign
- `-L, --labels` - Comma-separated labels to apply
- `-m, --milestone` - Milestone to assign
**Writing a multiline description:**
```bash
tea pulls create -r notid/integreat -b master \
-t "feat: add feature" \
-d "$(cat <<'EOF'
## Summary
- Bullet point one
- Bullet point two
EOF
)"
```
Or write the body to a temp file first and reference it.
## Listing PRs
```bash
tea pulls list -r notid/integreat # List open PRs
tea pulls list -r notid/integreat --state all # All PRs
tea pulls list -r notid/integreat --limit 10 -o simple # Limit output, simple format
```
## Opening a PR in Browser
```bash
tea open pr <number> -r notid/integreat
tea open pr create -r notid/integreat # Open web UI to create a PR
```
## Checking Out a PR Locally
```bash
tea pulls checkout <number> -r notid/integreat
```
This fetches and checks out the PR branch locally.
## Managing PR State
**Close a PR:**
```bash
tea pulls close <number> -r notid/integreat --confirm
```
**Reopen a closed PR:**
```bash
tea pulls reopen <number> -r notid/integreat --confirm
```
**Merge a PR:**
```bash
tea pulls merge <number> -r notid/integreat --confirm
```
**Edit a PR (title, description, etc.):**
```bash
tea pulls edit <number> -r notid/integreat --title "New title" --description "New body"
```
## Full PR Creation Workflow
1. Ensure the branch is pushed to gitea:
```bash
git push gitea <branch-name>
```
2. Create the PR with tea:
```bash
tea pulls create -r notid/integreat -b master \
--title "feat: description of change" \
--description "Detailed PR body here"
```
3. Open the PR in browser to verify:
```bash
tea open pr <number> -r notid/integreat
```
## Tips
- Always use `-r notid/integreat` to specify the repo explicitly
- Use `-b master` to set the target branch (default may differ)
- The `--confirm` flag is required for destructive actions (close, merge)
- Use `-o simple`, `-o json`, `-o table`, etc. to control output format

9
AGENTS.md Normal file
View File

@@ -0,0 +1,9 @@
## Pull Requests on Gitea
This project uses **gitea story-basking.ts net** as the primary remote for PRs. Use `tea` (the Gitea CLI) to create and manage pull requests. The gitea remote is the one you push to, NOT origin and NOT deploy.
**When opening a PR**, load and follow the **gitea-tea** skill. In short:
- Target branch is always `master`
- Use `tea pulls create -r notid/integreat -b master --title "..." --description "..."`
Use 'bd' for task tracking

Binary file not shown.

View File

@@ -0,0 +1,376 @@
---
title: Rebase Invoice Templates, Merge to Master, and Integrate Branches
type: refactor
date: 2026-02-08
---
# Rebase Invoice Templates, Merge to Master, and Integrate Branches
## Overview
This plan outlines a series of git operations to reorganize the branch structure by:
1. Creating a rebase commit with all invoice template changes
2. Applying those changes onto `master`
3. Removing them from the current `clauding` branch
4. Merging `master` back into `clauding`
5. Finally merging `clauding` into `get-transactions2-page-working`
## Current State
### Branch Structure (as of Feb 8, 2026)
```
master (dc021b8c)
├─ deploy/master (dc021b8c)
└─ (other branches)
└─ clauding (0155d91e) - HEAD
├─ 16 commits ahead of master
└─ Contains invoice template work for Bonanza Produce
├─ db1cb194 Add Bonanza Produce invoice template
├─ ec754233 Improve Bonanza Produce customer identifier extraction
├─ af7bc324 Add location extraction for Bonanza Produce invoices
├─ 62107c99 Extract customer name and address for Bonanza Produce
├─ 7ecd569e Add invoice-template-creator skill for automated template generation
└─ 0155d91e Add Bonanza Produce multi-invoice statement template
```
### Merge Base
- **Merge base between `clauding` and `master`**: `dc021b8c`
- **Commits on `clauding` since merge base**: 16 commits
- **Invoice template commits**: 6 commits (db1cb194 through 0155d91e)
## Problem Statement
The current branch structure has:
1. Invoice template work mixed with other feature development in `clauding`
2. No clear separation between invoice template changes and transaction page work
3. A desire to get invoice template changes merged to `master` independently
4. A need to reorganize branches to prepare for merging `get-transactions2-page-working`
## Proposed Solution
Use git rebase and merge operations to create a cleaner branch hierarchy:
1. **Create a new branch** (`invoice-templates-rebased`) with only invoice template commits
2. **Rebase those commits** onto current `master`
3. **Merge** this clean branch to `master`
4. **Remove invoice template commits** from `clauding` branch
5. **Merge `master` into `clauding`** to sync
6. **Merge `clauding` into `get-transactions2-page-working`**
## Implementation Steps
### Phase 1: Extract and Rebase Invoice Templates
#### Step 1.1: Identify Invoice Template Commits
```bash
# From clauding branch, find the range of invoice template commits
git log --oneline --reverse dc021b8c..clauding
```
**Invoice template commits to extract** (6 commits in order):
1. `db1cb194` - Add Bonanza Produce invoice template
2. `ec754233` - Improve Bonanza Produce customer identifier extraction
3. `af7bc324` - Add location extraction for Bonanza Produce invoices
4. `62107c99` - Extract customer name and address for Bonanza Produce
5. `7ecd569e` - Add invoice-template-creator skill for automated template generation
6. `0155d91e` - Add Bonanza Produce multi-invoice statement template
#### Step 1.2: Create Rebased Branch
```bash
# Create a new branch from master with only invoice template commits
git checkout master
git pull origin master # Ensure master is up to date
git checkout -b invoice-templates-rebased
# Cherry-pick the invoice template commits in order
git cherry-pick db1cb194
git cherry-pick ec754233
git cherry-pick af7bc324
git cherry-pick 62107c99
git cherry-pick 7ecd569e
git cherry-pick 0155d91e
# Resolve any conflicts that arise during cherry-pick
# Run tests after each cherry-pick if conflicts occur
```
#### Step 1.3: Verify Rebased Branch
```bash
# Verify the commits are correctly applied
git log --oneline master..invoice-templates-rebased
# Run tests to ensure invoice templates still work
lein test auto-ap.parse.templates-test
```
#### Step 1.4: Merge to Master
```bash
# Merge the clean invoice templates to master
git checkout master
git merge invoice-templates-rebased --no-edit
# Push to remote
git push origin master
```
### Phase 2: Clean Up Clauding Branch
#### Step 2.1: Remove Invoice Template Commits from Clauding
```bash
# From clauding branch, find the commit before the first invoice template
git log --oneline clauding | grep -B1 "db1cb194"
# Suppose that's commit X, rebase clauding to remove invoice templates
git checkout clauding
# Option A: Interactive rebase (recommended for cleanup)
git rebase -i <commit-before-invoice-templates>
# In the editor, delete lines corresponding to invoice template commits:
# db1cb194
# ec754233
# af7bc324
# 62107c99
# 7ecd569e
# 0155d91e
# Save and exit to rebase
# Resolve any conflicts that occur
# Run tests after rebase
```
**OR**
```bash
# Option B: Hard reset to commit before invoice templates
# Identify the commit hash before db1cb194 (let's call it COMMIT_X)
git reset --hard COMMIT_X
# Then add back any non-invoice template commits from clauding
# (commits after the invoice templates that should remain)
git cherry-pick <non-invoice-commits-if-any>
```
#### Step 2.2: Verify Clauding Branch Cleanup
```bash
# Verify invoice template commits are removed
git log --oneline | grep -i "bonanza" # Should be empty
# Verify other commits remain
git log --oneline -20
# Run tests to ensure nothing broke
lein test
```
#### Step 2.3: Force Push Updated Clauding
```bash
# Force push the cleaned branch (use --force-with-lease for safety)
git push --force-with-lease origin clauding
```
### Phase 3: Sync Clauding with Master
#### Step 3.1: Merge Master into Clauding
```bash
git checkout clauding
git merge master --no-edit
# Resolve any conflicts
# Run tests
```
#### Step 3.2: Push Synced Clauding
```bash
git push origin clauding
```
### Phase 4: Final Merge to get-transactions2-page-working
#### Step 4.1: Merge Clauding to get-transactions2-page-working
```bash
git checkout get-transactions2-page-working
git merge clauding --no-edit
# Resolve any conflicts
# Run tests
```
#### Step 4.2: Push Final Branch
```bash
git push origin get-transactions2-page-working
```
## Acceptance Criteria
### Pre-operations Validation
- [ ] All invoice template commits identified correctly (6 commits)
- [ ] Merge base commit (`dc021b8c`) confirmed
- [ ] Current branch state documented
- [ ] Team notified of branch manipulation
### Post-Rebase Validation
- [ ] `invoice-templates-rebased` branch created from `master`
- [ ] All 6 invoice template commits applied correctly
- [ ] All invoice template tests pass
- [ ] No conflicts or unexpected changes during cherry-pick
### Post-Master Validation
- [ ] Invoice templates merged to `master`
- [ ] Changes pushed to remote `master`
- [ ] CI/CD passes on `master`
### Post-Cleanup Validation
- [ ] `clauding` branch has only non-invoice template commits
- [ ] No Bonanza Produce commits remain in `clauding` history
- [ ] All `clauding` tests pass
- [ ] Force push successful
### Post-Sync Validation
- [ ] `clauding` merged with `master`
- [ ] All conflicts resolved
- [ ] Changes pushed to remote
### Final Merge Validation
- [ ] `get-transactions2-page-working` merged with `clauding`
- [ ] All conflicts resolved
- [ ] Final tests pass
- [ ] Changes pushed to remote
## Success Metrics
- **Branch structure**: Invoice templates cleanly separated on `master`
- **Commit history**: Linear, no duplicate invoice template commits
- **Tests passing**: 100% of existing tests pass after each step
- **No data loss**: All work preserved in appropriate branches
- **Branch clarity**: Each branch has a clear, focused purpose
## Dependencies & Risks
### Dependencies
- [ ] All current work on `clauding` should be backed up or committed
- [ ] Team should be aware of branch manipulation to avoid force pushing
- [ ] CI/CD should be monitored during operations
### Risks
1. **Force push risk**: Force pushing `clauding` will rewrite history
- **Mitigation**: Use `--force-with-lease`, notify team beforehand
2. **Conflict resolution**: Multiple merge/conflict resolution points
- **Mitigation**: Test after each step, resolve conflicts carefully
3. **Work loss**: Potential to lose commits if operations go wrong
- **Mitigation**: Create backups, verify each step before proceeding
4. **CI/CD disruption**: Force pushes may affect CI/CD pipelines
- **Mitigation**: Coordinate with team, avoid during active deployments
### Contingency Plan
If something goes wrong:
1. **Recover `clauding` branch**:
```bash
git checkout clauding
git reset --hard origin/clauding # Restore from remote backup
```
2. **Recover master**:
```bash
git checkout master
git reset --hard origin/master # Restore from deploy/master
```
3. **Manual cherry-pick recovery**: If rebasing failed, manually cherry-pick remaining commits
## Alternative Approaches Considered
### Approach 1: Squash and Merge
**Pros**: Single clean commit, simple history
**Cons**: Loses individual commit history and context
**Rejected because**: Team uses merge commits (not squash), and individual commit history is valuable for tracking invoice template development.
### Approach 2: Keep Branches Separate
**Pros**: No branch manipulation needed
**Cons**: Branches remain tangled, harder to track progress
**Rejected because**: Goal is to cleanly separate invoice templates from transaction work.
### Approach 3: Rebase Clauding Onto Master
**Pros**: Linear history
**Cons**: Requires force push, may lose merge context
**Rejected because**: Current team workflow uses merge commits, and merging master into clauding preserves the integration point.
### Approach 4: Create New Branch Instead of Cleanup
**Pros**: Less risky, preserves full history
**Cons**: Accumulates branches, harder to track
**Rejected because**: Goal is cleanup and reorganization, not preservation.
## Related Work
- **Previous invoice template work**: `2026-02-07-feat-add-invoice-template-03881260-plan.md`
- **Current branch structure**: `clauding` has hierarchical relationship with `get-transactions2-page-working`
- **Team git workflow**: Uses merge commits (not rebasing), per repo research
## References & Research
### Internal References
- **Branch management patterns**: Repo research analysis (see `task_id: ses_3c2287be8ffe9icFi5jHEspaqh`)
- **Invoice template location**: `src/clj/auto_ap/parse/templates.clj`
- **Current branch structure**: Git log analysis
### Git Operations Documentation
- **Cherry-pick**: `git cherry-pick <commit>`
- **Interactive rebase**: `git rebase -i <base>`
- **Force push with lease**: `git push --force-with-lease`
- **Merge commits**: `git merge <branch> --no-edit`
### File Locations
- Templates: `src/clj/auto_ap/parse/templates.clj`
- Parser logic: `src/clj/auto_ap/parse.clj`
- Invoice PDF: `dev-resources/INVOICE - 03881260.pdf`
## Testing Plan
### Before Each Major Step
```bash
# Verify current branch state
git branch -vv
git log --oneline -10
# Run all tests
lein test
# Run specific invoice template tests
lein test auto-ap.parse.templates-test
```
### After Each Major Step
- Verify commit count and order
- Run full test suite
- Check for unintended changes
- Verify remote branch state matches local
## Notes
- **Team coordination**: Inform team before force pushing to avoid conflicts
- **Backup strategy**: All commits are preserved in the rebase process
- **Testing**: Verify at each step to catch issues early
- **Safety first**: Use `--force-with-lease` instead of `--force`
- **Documentation**: This plan serves as documentation for the operation

View File

@@ -293,7 +293,9 @@
(condp = (:name (:source order))
"GRUBHUB" :ccp-processor/grubhub
"UBEREATS" :ccp-processor/uber-eats
"Uber Eats" :ccp-processor/uber-eats
"DOORDASH" :ccp-processor/doordash
"DoorDash" :ccp-processor/doordash
"Koala" :ccp-processor/koala
"koala-production" :ccp-processor/koala
:ccp-processor/na))
@@ -349,7 +351,10 @@
(s/reduce conj []))]
[(remove-nils
#:sales-order
{:date (coerce/to-date (time/to-time-zone (coerce/to-date-time (:created_at order)) (time/time-zone-for-id "America/Los_Angeles")))
{:date (if (= "Invoices" (:name (:source order)))
(when (:closed_at order)
(coerce/to-date (time/to-time-zone (coerce/to-date-time (:closed_at order)) (time/time-zone-for-id "America/Los_Angeles"))))
(coerce/to-date (time/to-time-zone (coerce/to-date-time (:created_at order)) (time/time-zone-for-id "America/Los_Angeles"))))
:client (:db/id client)
:location (:square-location/client-location location)
:external-id (str "square/order/" (:client/code client) "-" (:square-location/client-location location) "-" (:id order))
@@ -379,6 +384,9 @@
;; sometimes orders stay open in square. At least one payment
;; is needed to import, in order to avoid importing orders in-progress.
(and
(if (= "Invoices" (:name (:source order)))
(boolean (:closed_at order))
true)
(or (> (count (:tenders order)) 0)
(seq (:returns order)))
(or (= #{} (set (map #(:status (:card_details %)) (:tenders order))))
@@ -862,7 +870,11 @@
#_(comment
(require 'auto-ap.time-reader)
@(let [[c [l]] (get-square-client-and-location "DBFS") ]
(log/peek :x [ c l])
(search c l #clj-time/date-time "2026-03-28" #clj-time/date-time "2026-03-29")
)
@(let [[c [l]] (get-square-client-and-location "NGAK") ]
(log/peek :x [ c l])
@@ -972,13 +984,14 @@
:headers (client-base-headers client)
:as :json})
:body)))
(->>
@(let [[c [l]] (get-square-client-and-location "NGGG")]
(->>
@(let [[c [l]] (get-square-client-and-location "NGGG")]
(search c l (time/plus (time/now))))
(filter (fn [r]
(str/starts-with? (:created_at r) "2024-03-14"))))
(search c l (time/now) (time/plus (time/now) (time/days -1))))
(filter (fn [r]
(str/starts-with? (:created_at r) "2024-03-14"))))
(def refs
(->>
@@ -995,35 +1008,35 @@
(map (fn [r] @(get-payment c (:payment_id r))) refs))
(get-square-client-and-location "NGGB")
(get-square-client-and-location "NGGB")
(def my-results
(let [[c [l]] (get-square-client-and-location "NGFA")]))
(clojure.data.csv/write-csv *out*
(for [c (get-square-clients)
l (:client/square-locations c)
:when (:square-location/client-location l)
bad-row (try (->> @(search c l (coerce/to-date-time #inst "2024-04-01T00:00:00-07:00") (coerce/to-date-time #inst "2024-04-15T23:59:00-07:00"))
(filter #(not (should-import-order? %)))
(map #(first (deref (order->sales-order c l %))))
(filter (fn already-exists [o]
(when (:sales-order/external-id o)
(seq (dc/q '[:find ?i
:in $ ?ei
:where [?i :sales-order/external-id ?ei]]
(dc/db conn)
(:sales-order/external-id o)))))))
(catch Exception e
[]))]
[(:client/code c) (atime/unparse-local (clj-time.coerce/to-date-time (:sales-order/date bad-row)) atime/normal-date) (:sales-order/total bad-row) (:sales-order/tax bad-row) (:sales-order/tip bad-row) (:db/id bad-row)])
:separator \tab)
(for [c (get-square-clients)
l (:client/square-locations c)
:when (:square-location/client-location l)
bad-row (try (->> @(search c l (coerce/to-date-time #inst "2024-04-01T00:00:00-07:00") (coerce/to-date-time #inst "2024-04-15T23:59:00-07:00"))
(filter #(not (should-import-order? %)))
(map #(first (deref (order->sales-order c l %))))
(filter (fn already-exists [o]
(when (:sales-order/external-id o)
(seq (dc/q '[:find ?i
:in $ ?ei
:where [?i :sales-order/external-id ?ei]]
(dc/db conn)
(:sales-order/external-id o)))))))
(catch Exception e
[]))]
[(:client/code c) (atime/unparse-local (clj-time.coerce/to-date-time (:sales-order/date bad-row)) atime/normal-date) (:sales-order/total bad-row) (:sales-order/tax bad-row) (:sales-order/tip bad-row) (:db/id bad-row)])
:separator \tab)
;; =>
(require 'auto-ap.time-reader)
@@ -1035,7 +1048,7 @@
(def z @(search c l #clj-time/date-time "2025-02-23T00:00:00-08:00"
#clj-time/date-time "2025-02-28T00:00:00-08:00"))
#clj-time/date-time "2025-02-28T00:00:00-08:00"))
(take 10 (map #(first (deref (order->sales-order c l %))) z)))
@@ -1051,17 +1064,43 @@
(count)
)
(doseq [c (get-square-clients)]
(println "Upserting" (:client/name c))
@(upsert c))
(doseq [[code] (seq (dc/q '[:find ?code
:in $
:where [?o :sales-order/date ?d]
[(>= ?d #inst "2026-01-01")]
[?o :sales-order/source "Invoices"]
[?o :sales-order/client ?c]
[?c :client/code ?code]]
(dc/db conn)))
:let [[c [l]] (get-square-client-and-location code)
]
order @(search c l #clj-time/date-time "2026-01-01T00:00:00-08:00" (time/now))
:when (= "Invoices" (:name (:source order) ))
:let [[sales-order] @(order->sales-order c l order)]]
(when (should-import-order? order)
(println "DATE IS" (:sales-order/date sales-order))
(when (some-> (:sales-order/date sales-order) coerce/to-date-time (time/after? #clj-time/date-time "2026-2-16T00:00:00-08:00"))
(println "WOULD UPDATE" sales-order)
@(dc/transact auto-ap.datomic/conn [sales-order])
)
#_@(dc/transact )
(println "DONE"))
)
#_(filter (comp #{"OTHER"} :type) (mapcat :tenders z))
(let [[c [l]] (get-square-client-and-location "LFHH")]
(search c l (clj-time.coerce/from-date #inst "2025-02-28") (clj-time.coerce/from-date #inst "2025-03-01"))
@(let [[c [l]] (get-square-client-and-location "NGRY")]
#_(search c l (clj-time.coerce/from-date #inst "2025-02-28") (clj-time.coerce/from-date #inst "2025-03-01"))
(:order (get-order c l "CLjQqkzVfGa82o5hEFUrGtUGO6QZY" ))
)
(order->sales-order c l (:order (get-order c l "KdvwntmfMNTKBu8NOocbxatOs18YY" )))
)
)

View File

@@ -1,11 +1,13 @@
(ns auto-ap.ssr.components.date-range
(:require [auto-ap.ssr.components :as com]
[auto-ap.ssr.components.buttons :as but]
[auto-ap.ssr.svg :as svg]
[auto-ap.time :as atime]
[clj-time.coerce :as c]
[clj-time.core :as t]
[clj-time.periodic :as per]))
(defn date-range-field [{:keys [value id]}]
(defn date-range-field [{:keys [value id apply-button?]}]
[:div {:id id}
(com/field {:label "Date Range"}
[:div.space-y-4
@@ -21,11 +23,17 @@
(atime/unparse-local atime/normal-date))
:placeholder "Date"
:size :small
:class "shrink"})
:class "shrink date-filter-input"})
(com/date-input {:name "end-date"
:value (some-> (:end value)
(atime/unparse-local atime/normal-date))
:placeholder "Date"
:size :small
:class "shrink"})]])])
:class "shrink date-filter-input"})
(when apply-button?
(but/button- {:color :secondary
:size :small
:type "button"
"x-on:click" "$dispatch('datesApplied')"}
"Apply"))]])])

View File

@@ -37,7 +37,7 @@
[auto-ap.ssr.invoice.common :refer [default-read]]
[auto-ap.ssr.invoice.import :as invoice-import]
[auto-ap.ssr.invoice.new-invoice-wizard :as new-invoice-wizard :refer [location-select*]]
[auto-ap.ssr.pos.common :refer [date-range-field*]]
[auto-ap.ssr.components.date-range :as dr]
[auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils
:refer [apply-middleware-to-all-handlers assert-schema
@@ -77,7 +77,7 @@
[:div {:id "exact-match-id-tag"}]))
(defn filters [request]
[:form#invoice-filters {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
[:form#invoice-filters {"hx-trigger" "datesApplied, change delay:500ms from:.filter-trigger, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
::route/table)
"hx-target" "#entity-table"
@@ -92,7 +92,8 @@
:url (bidi/path-for ssr-routes/only-routes :vendor-search)
:value (:vendor (:query-params request))
:value-fn :db/id
:content-fn :vendor/name}))
:content-fn :vendor/name
:class "filter-trigger"}))
(com/field {:label "Account"}
(com/typeahead {:name "account"
:id "account"
@@ -100,8 +101,12 @@
:value (:account (:query-params request))
:value-fn :db/id
:content-fn #(:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read (:db/id %))
(:db/id (:client request))))}))
(date-range-field* request)
(:db/id (:client request))))
:class "filter-trigger"}))
(dr/date-range-field {:value {:start (:start-date (:query-params request))
:end (:end-date (:query-params request))}
:id "date-range"
:apply-button? true})
(com/field {:label "Check #"}
(com/text-input {:name "check-number"
:id "check-number"
@@ -486,7 +491,10 @@
:fetch-page fetch-page
:oob-render
(fn [request]
[(assoc-in (date-range-field* request) [1 :hx-swap-oob] true)
[(assoc-in (dr/date-range-field {:value {:start (:start-date (:query-params request))
:end (:end-date (:query-params request))}
:id "date-range"
:apply-button? true}) [1 :hx-swap-oob] true)
(assoc-in (exact-match-id* request) [1 :hx-swap-oob] true)])
:query-schema query-schema
:parse-query-params (fn [p]

View File

@@ -81,7 +81,7 @@
data (into []
(for [client-id client-ids
d date
[client-id account-id location debits credits balance count] (iol-ion.query/detailed-account-snapshot (dc/db conn) client-id (coerce/to-date (time/plus d (time/days 1))))
[client-id account-id location debits credits balance count] (iol-ion.query/detailed-account-snapshot (dc/db conn) client-id (coerce/to-date d))
:let [account ((or (lookup-account client-id) {}) account-id)]]
{:client-id client-id
:account-id account-id

View File

@@ -51,3 +51,22 @@
(is (= "720.33" (:total (nth results 1))))
(is (= "853.16" (:total (nth results 2))))
(is (= "1066.60" (:total (nth results 3)))))))
(deftest parse-bonanza-produce-invoice-03882095
(testing "Should parse Bonanza Produce invoice 03882095 with customer identifier including address"
(let [pdf-file (io/file "dev-resources/INVOICE - 03882095.pdf")
pdf-text (:out (clojure.java.shell/sh "pdftotext" "-layout" (str pdf-file) "-"))
results (sut/parse pdf-text)
result (first results)]
(is (some? results) "parse should return a result")
(is (some? result) "Template should match and return a result")
(when result
(is (= "Bonanza Produce" (:vendor-code result)))
(is (= "03882095" (:invoice-number result)))
(let [d (:date result)]
(is (= 2026 (time/year d)))
(is (= 1 (time/month d)))
(is (= 23 (time/day d))))
(is (= "NICK THE GREEK" (:customer-identifier result)))
(is (= "600 VISTA WAY" (str/trim (:account-number result))))
(is (= "946.24" (:total result)))))))