Skip to content

fix: tax Indiana seller-billed shipping#650

Open
Blb3D wants to merge 2 commits into
mainfrom
fix/taxable-shipping-policy
Open

fix: tax Indiana seller-billed shipping#650
Blb3D wants to merge 2 commits into
mainfrom
fix/taxable-shipping-policy

Conversation

@Blb3D
Copy link
Copy Markdown
Owner

@Blb3D Blb3D commented Jun 6, 2026

Summary

  • add a Core-owned, provider-neutral tax calculation helper for state-aware taxable shipping
  • tax Indiana seller-billed delivery on manual sales orders and manual quotes, including company-state fallback for local/no-destination entry
  • preserve non-Indiana behavior and model non-taxable USPS/third-party shipping semantics for future UI/provider wiring
  • clean up pre-existing unused test locals/import that blocked per-file ruff validation

Validation

  • DB_NAME=filaops_test, DATABASE_URL cleared before DB-backed tests
  • python -m pytest backend/tests/services/test_tax_calculation_service.py backend/tests/services/test_sales_order_service.py backend/tests/services/test_quote_service.py -q -> 210 passed, 1 skipped
  • python -m ruff check backend/app/services/tax_calculation_service.py backend/app/services/sales_order_service.py backend/app/services/quote_service.py backend/tests/services/test_tax_calculation_service.py backend/tests/services/test_sales_order_service.py backend/tests/services/test_quote_service.py -> All checks passed
  • python -m compileall backend/app/services/tax_calculation_service.py backend/app/services/sales_order_service.py backend/app/services/quote_service.py backend/tests/services/test_tax_calculation_service.py backend/tests/services/test_sales_order_service.py backend/tests/services/test_quote_service.py
  • git diff --check

Notes

This does not add a QuickBooks/Avalara/TaxJar dependency. It gives Core a conservative built-in policy point so a later provider can replace or enrich the calculation without coupling Core to PRO.

AI attribution

Co-authored-by: Codex Codex@anthropic.com
Agent-Session: codex-taxable-shipping-policy-20260606-001

Summary by CodeRabbit

  • New Features

    • Tax calculations now include shipping where appropriate and use seller/destination state for more accurate quote and order totals.
    • Quote/order flows persist shipping state and automatically recompute tax/total on relevant create/update actions, respecting apply-tax toggles.
  • Bug Fixes

    • Fixed incorrect tax and total computations that previously omitted shipping or used stale tax resolution.
  • Tests

    • Added state-aware tax tests covering Indiana shipping, non-taxable postage, and recalculation scenarios.

Co-authored-by: Codex <Codex@anthropic.com>

Agent-Session: codex-taxable-shipping-policy-20260606-001
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 6, 2026

Complex PR? Review this PR in Change Stack to move by importance, not file order.

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5714c507-d5d5-4efa-a2dc-23a606c0b9ba

📥 Commits

Reviewing files that changed from the base of the PR and between e734bac and 3b5a70d.

📒 Files selected for processing (4)
  • backend/app/services/quote_service.py
  • backend/app/services/sales_order_service.py
  • backend/tests/services/test_quote_service.py
  • backend/tests/services/test_sales_order_service.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • backend/app/services/sales_order_service.py
  • backend/tests/services/test_quote_service.py
  • backend/app/services/quote_service.py

Walkthrough

Adds a provider-neutral tax calculation service and integrates it into quote and sales order flows to compute state-aware taxable bases and tax amounts (including Indiana shipping rules), and updates tests to validate the new behavior.

Changes

Tax Calculation and Service Integration

Layer / File(s) Summary
Tax calculation service foundation
backend/app/services/tax_calculation_service.py
New service module with ShippingChargeType enum (SELLER_BILLED_DELIVERY, USPS_POSTAGE, THIRD_PARTY_FREIGHT), SalesTaxResult dataclass (taxable_base, tax_amount, shipping_taxable), and functions is_shipping_taxable() and calculate_sales_tax() that implement state-aware tax base computation with Indiana seller-billed shipping inclusion, USPS postage exclusion, and cent-precision quantization.
Sales order service integration
backend/app/services/sales_order_service.py
get_company_tax_settings() updated to accept optional pre-fetched CompanySettings via keyword-only parameter with explicit is not None checks; create_sales_order() and _recalculate_order_totals() tax computation replaced with calculate_sales_tax() calls passing subtotal, tax rate, shipping cost, ship-to state, and seller state from company settings; removed old auto-copy shipping block.
Quote service integration
backend/app/services/quote_service.py
New _calculate_quote_tax_amount() helper wraps calculate_sales_tax(); quote creation persists shipping_state and sets total_price = subtotal + tax + shipping; update paths conditionally load CompanySettings and recompute/clear tax fields via the helper based on apply_tax and shipping changes.
Tax calculation service tests
backend/tests/services/test_tax_calculation_service.py
Unit tests validate Indiana seller-billed shipping inclusion in taxable base (shipping_taxable=true), non-Indiana state shipping exclusion (shipping_taxable=false), and Indiana USPS postage non-taxability (shipping_taxable=false) with quantized decimal assertions.
Quote service tests
backend/tests/services/test_quote_service.py
Integration tests verify Indiana tax behavior: quote creation includes shipping cost in taxable base with updated tax_amount and total_price; quote shipping_cost/shipping_state updates trigger taxable base recalculation and updated tax/total; added default TaxRate handling for apply_tax updates.
Sales order service tests and cleanup
backend/tests/services/test_sales_order_service.py
Test helper _set_company_tax() now persists optional company_state to CompanySettings; new integration tests verify Indiana shipping tax behavior when shipping_state provided and fallback to company_state when destination unspecified; edits preserve taxable shipping; minor test cleanups remove unused locals/imports.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

Indiana's postage finds its place in tax,
Small decimals marched, rounded to a cent,
Services aligned to measure base and fact,
Quotes and orders now respect state intent,
A tidy suite of tests confirms the act.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers all required sections: Summary (4 bullet points), Validation (test results, linting, compilation checks), and Notes. However, it does not follow the provided template structure with the standard sections (Related Issues, Changes, Testing checklist). Consider restructuring the description to match the repository template with Related Issues, Changes list, and Testing checklist sections for consistency with team standards.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: implementing Indiana seller-billed shipping tax treatment, which aligns with the core objective of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/taxable-shipping-policy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/app/services/quote_service.py`:
- Around line 286-292: The tax calculation uses request.shipping_state via
_calculate_quote_tax_amount but create_quote never persists that destination;
update the create_quote implementation to assign the incoming shipping state to
the Quote (e.g., set quote.shipping_state = getattr(request, "shipping_state",
None) or the equivalent request field) before saving so subsequent tax
recalculations and order conversion read the true destination; modify
create_quote (and any save/commit path for the Quote) to persist this value
whenever you call _calculate_quote_tax_amount with a request shipping_state.
- Around line 548-559: The single-item apply_tax=True branch bypasses the shared
resolver and can drop or stale tax fields; update that branch in the quote
update flow to call the existing _resolve_tax(...) (the same used by
create_quote/create/update paths) to obtain the resolved tax_rate, tax_amount,
tax_name and tax_rate_id using company_settings and any incoming tax_rate_id,
then set quote.tax_rate, quote.tax_amount, quote.tax_name, quote.tax_rate_id
accordingly and recompute quote.total_price (subtotal + tax_amount + shipping);
this ensures consistency with create_quote() and respects get_default_tax_rate()
fallback.
- Around line 436-442: The recalculation gate (should_recalculate) misses
changes to the shipping state so tax and totals stay stale; detect when the
quote's shipping_state is changed (e.g., compute shipping_state_updated by
comparing request.shipping_state to the existing quote.shipping_state or the
current shipping_state var) and include that flag in the should_recalculate
condition (or fold it into shipping_cost_updated) so changes to shipping_state
trigger tax and total recomputation (affecting tax_amount and total_price).

In `@backend/app/services/sales_order_service.py`:
- Around line 768-780: The header recompute path currently uses a naive
line_total * order.tax_rate in _recalculate_order_totals which ignores taxable
shipping and diverges from calculate_sales_tax used at creation; update
_recalculate_order_totals to call the same helper used during creation
(calculate_sales_tax, with company settings from
get_company_tax_settings/CompanySettings) and use the returned
tax_result.tax_amount (taking shipping_cost and ship_to_state into account)
instead of multiplying by order.tax_rate so persisted totals remain consistent
after edits/removals.
- Around line 768-779: The tax call uses shipping_state too early; before
calling calculate_sales_tax resolve ship_to_state by backfilling shipping_state
from the customer's saved shipping address (the same logic currently applied
later when populating the order from the customer record) so that shipping_state
is not None when passed in. Update the code around
company_settings/get_company_tax_settings/calculate_sales_tax to first set
shipping_state = shipping_state or customer.saved_shipping_state (or the
existing helper that loads the customer's saved address), then call
calculate_sales_tax with that resolved ship_to_state (keeping
seller_state=company_settings.company_state fallback).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2e5662b3-8614-4c64-9863-773aa19f8d50

📥 Commits

Reviewing files that changed from the base of the PR and between 0455782 and e734bac.

📒 Files selected for processing (6)
  • backend/app/services/quote_service.py
  • backend/app/services/sales_order_service.py
  • backend/app/services/tax_calculation_service.py
  • backend/tests/services/test_quote_service.py
  • backend/tests/services/test_sales_order_service.py
  • backend/tests/services/test_tax_calculation_service.py

Comment thread backend/app/services/quote_service.py
Comment thread backend/app/services/quote_service.py
Comment thread backend/app/services/quote_service.py Outdated
Comment thread backend/app/services/sales_order_service.py
Comment thread backend/app/services/sales_order_service.py
Co-authored-by: Codex <Codex@anthropic.com>

Agent-Session: codex-pr650-coderabbit-20260606-001
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