Skip to content

Change Log — Dan's Code Changes

Nisarg: Check this file before starting work each day. Newest entries at the top.


2026-04-13

Documentation — Stale content sweep + RFP scraper build prompt

  • What changed:
  • docs/developer/architecture.md synchronized with the reconciled SR-Odoo/ARCHITECTURE.md — all stale sr_attendance references marked as DEAD, sr_ewaste_compliance added to tree/matrix/inheritance, sr_dashboards dep fixed (was wrongly listed as depending on sr_attendance; actually depends on sr_management_fixes), sr_reports dep list fixed (was missing sr_inventory_processing), weighted-materials section rewritten to reflect inlined-in-sr_management reality.
  • docs/developer/changelog.md backfilled with the 2026-04-05, 2026-04-10, and 2026-04-12 entries that were missed during regular deploys.
  • Build prompt for sr_rfp_scraper written to ~/Desktop/sr_rfp_scraper-BUILD-PROMPT.md — 474-line self-contained spec for delegating the module build to another LLM. Covers safety rules, environment, full module spec (3 models, adapter pattern, SAM.gov as first adapter), test requirements, commit protocol, success criteria.
  • Files: docs/developer/architecture.md, docs/developer/changelog.md (this file)
  • Why: Yesterday's 2026-04-12 audit found ~95 stale references across sr-docs, concentrated in strategy docs and architecture.md. The strategy docs were fixed inline; the architecture copy needed this sync. The changelog backfill is a separate item — sr-docs was ~10 days behind SR-Odoo's CHANGES.md.
  • Watch out: The sr-docs copy of architecture.md is now a verbatim mirror of SR-Odoo/ARCHITECTURE.md. If they diverge in the future, SR-Odoo is the source of truth. Consider automating the sync.

2026-04-12

sr_ewaste_compliance v17.0.1.0.0 — Installed on EXP + packaging fix

  • What changed: Installed the previously-written sr_ewaste_compliance module on EXP sr_live_jan19_backup for the first time. Also fixed a packaging bug that blocked the first install attempt.
  • Packaging fix (commit d62a6a77): Added sr_ewaste_compliance/static/description/index.html placeholder. Without this file, Odoo's ir_module_module._get_desc() falls back to rendering the manifest's RST description via docutils, which does a CWD-relative lookup for html4css1.css. On EXP the odoo service user has no stat permission on the default CWD, triggering PermissionError and a CRITICAL registry-load abort. The placeholder HTML short-circuits docutils entirely.
  • mail.activity.mixin fix (commit 051f0a32): compliance.vendor.certification inherited only mail.thread, but its daily cron_check_expiring_certs calls activity_schedule() — only available with mail.activity.mixin. Would have crashed daily once any cert entered the 30-day expiry window. Found by the functional test suite's first run.
  • EXP install: Created 9 tables (compliance_intake, compliance_intake_line, compliance_data_destruction, compliance_focus_material, compliance_downstream_vendor, compliance_certificate, compliance_vendor_certification, compliance_diversion, compliance_nwipe_import_log), 3 cron jobs (Focus Material Storage Alerts daily, Expiring Vendor Certifications daily, nwipe/ShredOS Log Import every 30 min), 3 sequences.
  • ARCHITECTURE.md — added module to tree, matrix, hr.employee inheritance chain, then separately swept all stale sr_attendance references (commit 766fcad3).
  • Files: sr_ewaste_compliance/static/description/index.html (new), sr_ewaste_compliance/models/compliance_vendor_certification.py (fix), FUNCTIONAL_TESTS_EWASTE_COMPLIANCE.md (new — 35 tests across 10 suites), sr_ewaste_compliance/HANDOFF.md (new), ARCHITECTURE.md
  • Why: The SR Enterprise Master Plan (Section 16) flagged 4 compliance items as PARTIAL because the module existed but wasn't installed. Installing it closes all 4 gaps and is a prerequisite for R2 certification work.
  • Watch out:
  • Localhost 1818 test1 already has the module installed at v17.0.1.0.0 — don't be surprised to find the tables pre-populated with test data there.
  • Pre-install backup lives at /opt/backups/odoo/sr_live_jan19_backup_pre_ewaste_install_20260412_1808.sql.gz on EXP. Remove in a few days once stable.
  • 3 new daily/30-min crons run on EXP. Benign with zero records. Monitor log volume during first week.
  • Results: Install succeeded with exit code 0. All 9 tables created. All 3 crons active. HTTP 200 on port 1819. No errors in journalctl. Functional tests 33/33 PASS after the mail.activity.mixin fix (2 intentional skips for full-registry upgrade tests that can't run against dirty tree).
  • Tests Nisarg should run on promotion (1820 → staging → production):
  • Pull jan: git -C /path/to/Dan-Odoo pull origin jan — must include commit 051f0a32
  • Verify fix: grep "mail.activity.mixin" sr_ewaste_compliance/models/compliance_vendor_certification.py — must show both mail.thread and mail.activity.mixin
  • Install: sudo -u <odoo_user> bash -c 'cd /tmp && <venv_python> <odoo-bin> -c <conf> -d <target_db> -i sr_ewaste_compliance --stop-after-init --logfile=/tmp/ew_install.log'
  • Check log: grep -iE "ERROR|CRITICAL|Traceback" /tmp/ew_install.log | tail -20
  • Verify state: SELECT state FROM ir_module_module WHERE name='sr_ewaste_compliance'installed
  • Verify tables: \dt compliance_* → 9 tables
  • Verify crons: 3 active crons matching %compliance%
  • Restart, HTTP health check 200
  • Run FUNCTIONAL_TESTS_EWASTE_COMPLIANCE.md — 33/33 expected
  • Upgrade cmd (on EXP): sudo -u odoo bash -c 'cd /tmp && /opt/odoo/odoo17-venv/bin/python3 /opt/odoo/odoo17/odoo-bin -c /etc/odoo/odoo.conf -d sr_live_jan19_backup -i sr_ewaste_compliance --stop-after-init --logfile=/tmp/ew_install.log'
  • Related: sr_ewaste_compliance/HANDOFF.md, FUNCTIONAL_TESTS_EWASTE_COMPLIANCE.md, release notes at /releases/sr_ewaste_compliance/v1.0.0/

EXP Infrastructure — Automated backups, monitoring, DB maintenance

  • What changed: Three infrastructure improvements on EXP closing master plan items A9 (backups), D2 (monitoring), D3 (database maintenance).
  • Automated nightly Odoo backups/opt/backups/odoo/backup.sh runs nightly at 2:00 AM via dan's crontab. pg_dump sr_live_jan19_backup | gzip with 14-day retention. Test backup compressed 1.7 GB → 114 MB. Logs to /opt/backups/odoo/backup.log. This was the single biggest risk item — no automated backup existed for sr_live before today.
  • System monitoring/opt/monitoring/health-check.sh runs hourly. Checks disk (>85% alert), memory (>90% alert), load (>4× CPU alert), services (odoo, postgresql, nginx), Odoo HTTP 1819, DB connectivity, high-frequency cron staleness, backup freshness (>36h alert). Ad-hoc status: /opt/monitoring/status.sh.
  • mail_message vacuum — table hadn't been autovacuumed since 2026-01-21 (2.5 months stale). Manually ran VACUUM (VERBOSE, ANALYZE) — reclaimed 29,790 dead IDs across 6,082 pages (15.76% of table). Post-vacuum: 0 dead tuples.
  • Files: (all on EXP, not in git) /opt/backups/odoo/backup.sh, /opt/monitoring/health-check.sh, /opt/monitoring/status.sh, dan's crontab (2 new entries)
  • Watch out:
  • Backup retention is 14 days. Older files auto-deleted. Consider a weekly offsite copy later.
  • Monitoring alerts write to log only — no email/SMS notification yet. Grep for >>> ALERT: in /opt/monitoring/health.log.
  • mail_message autovacuum may go stale again — root cause unknown. Check autovacuum settings if it recurs.
  • EXP Odoo is odoo.service (not odoo17.service) — monitoring script checks both names for portability between dev and prod.

Documentation — Strategy & Planning section + HR procedures + Daily checklists

  • What changed: Added foundational strategy documents and several missing compliance/operations docs to sr-docs.
  • docs/strategy/ section (NEW) — Operating Playbook, Enterprise Master Plan (18-section framework), Operational Master Plan (workstream action plan). These close the business-planning gap — sr-docs had SOPs and training but no strategic docs.
  • docs/compliance/emergency-response.md (NEW) — medical, fire, spill, weather, active-threat procedures. Has TO BE FILLED markers for facility-specific phone numbers.
  • docs/compliance/record-retention.md (NEW) — full retention schedule by record type (customer, financial, HR, DOT, HIPAA, environmental, IT, legal).
  • docs/knowledge-base/material-acceptance.md (NEW) — Tier 1/2/3 materials with decision tree. Print-and-post ready.
  • docs/knowledge-base/daily-checklists.md (NEW) — opening/closing checklists for warehouse, office, fleet roles. Includes a "Customization — What Each Facility Must Verify" section.
  • docs/knowledge-base/aged-inventory-management.md (NEW) — markdown schedule and cycle-out rules by category.
  • docs/policies/disciplinary-procedures.md (NEW) — progressive discipline steps, immediate termination criteria.
  • docs/policies/exit-procedures.md (NEW) — offboarding checklist including TN-specific final paycheck rules.
  • deploy.sh (NEW) — one-command build + rsync from local clone to /var/www/docs/ on EXP.
  • Files: docs/strategy/ (4 files), docs/compliance/emergency-response.md, docs/compliance/record-retention.md, docs/knowledge-base/material-acceptance.md, docs/knowledge-base/daily-checklists.md, docs/knowledge-base/aged-inventory-management.md, docs/policies/disciplinary-procedures.md, docs/policies/exit-procedures.md, docs/releases/sr_ewaste_compliance/v1.0.0.md, mkdocs.yml, deploy.sh
  • Why: Audit of the 180-page sr-docs site found that while SOPs, training, compliance, and role guides were strong (86% substantive), the site had zero strategy documents. Master plan workstream items B1-B10, F1-F2, and H4.
  • Watch out:
  • TO BE FILLED markers in emergency-response.md (phone numbers) must be filled in by Dan before the doc is genuinely useful. Drafts for Dan's input live at ~/Desktop/sr-drafts/.
  • Three draft release notes for sr_social_media v3.1.0, sr_operations_kpi v3.1.0, sr_inventory_processing v4.5.0 exist in docs/releases/ but are NOT in mkdocs.yml nav — Dan's review pending before publishing.

2026-04-10

sr_pickup_blast v17.0.2.2.0 — Base URL override + qweb body rendering fix

  • What changed: Two independent bugs that together caused a production pickup blast to deliver dead links and record zero responses.
  • Base URL override + localhost guard (commit 399824a0). New system parameter sr_pickup_blast.public_base_url is read first by MassEmailWizard._get_pickup_base_url() with fallback to web.base.url. Helper raises UserError if the resolved URL contains localhost, 127.0.0.1, or 0.0.0.0.
  • qweb rendering of per-recipient body fields (commit 354650f7). The wizard previously emitted __PICKUP_TOKEN__ / __PARTNER_NAME__ placeholders that a send-time override swapped for Jinja {{ }} expressions. Odoo 17 mass mailing renders body_html via qweb, which outputs {{ }} literally — so customers received emails with a literal {{object.name}} in place of their name and literal curly-brace text inside the response URLs. Fixed by emitting qweb syntax directly: <strong t-out="object.name"></strong> and <a t-attf-href="{base_url}/pickup/response/{{ object.get_pickup_token() }}/need">.
  • Files: sr_pickup_blast/__manifest__.py (17.0.2.0.0 → 17.0.2.2.0), sr_pickup_blast/models/mass_email_wizard.py
  • Why: A 2026-04-09 production blast from app1 delivered emails with URLs pointing at localhost:1818 (Odoo silently rewrote web.base.url because web.base.url.freeze=True was not set). Investigating surfaced the qweb rendering bug hiding behind it.
  • Watch out:
  • App1 production needs three system parameters set: web.base.url, web.base.url.freeze=True, and sr_pickup_blast.public_base_url. The freeze=True is critical — without it, Odoo rewrites web.base.url on every admin login. See ~/Desktop/PRODUCTION_FIX_pickup_blast_app1.md for full deploy procedure.
  • Wizard-generated body is no longer editable in the drag-and-drop editor (may strip t-attf-href attributes). Send immediately after wizard creation without editing.
  • Also discovered a latent sr_management fresh-install load-order bug: sr_management/__manifest__.py has data/geoengine_customer_map.xml before views/menus.xml, but the geoengine file references sr_menu_customers_sales defined in menus.xml. Breaks -i sr_management on empty database. Does NOT break upgrades. Not fixed in this commit — patched ephemerally on EXP for test, then reverted. Coordinate with Nisarg for permanent fix.
  • Results: Verified end-to-end on fresh EXP database. Real SMTP to two inboxes, partner name rendered, UUID tokens working, YES/NO click-through confirmed, queue updates correct, CRM lead + note created.
  • Tests Nisarg should run on promotion:
  • python3 ~/SR-Odoo/scripts/run_functional_tests.py sr_pickup_blast <target_db> — must end with ALL TESTS PASSED
  • Verify the three system parameters on target DB
  • Verify sending user's email domain matches SMTP from_filter
  • Run scripts/suite7_preflight.py — must print READY_TO_BLAST
  • Self-test: one-recipient blast, click YES and NO, verify queue changes. Then dispatch real recipients in batches of ≤50.
  • Upgrade cmd: sudo -u odoo17 /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_pickup_blast --stop-after-init

2026-04-05

sr_scheduling + sr_management — Service Window Separation + Scheduling Algorithm Fixes

  • What changed:
  • Service window separated from HOO. New fields has_service_window / service_window_start / service_window_end on res.partner and customer.pickups. HOO is now just informational business hours; service window is the optional tighter pickup constraint.
  • Customer form view: HOO + Service Window shown in side-by-side boxes (purple / teal). Verified toggle moved inside HOO box. Service window toggle hides/shows time fields.
  • 0/0 HOO validation relaxed: writing hoo_start_time=0 + hoo_end_time=0 no longer raises ValidationError (treated as "not set yet").
  • Direction checking removed: routing_utils.directions_are_compatible() now always returns True. Route optimizer handles stop ordering; weight/time/box constraints prevent overloaded routes.
  • TSP-based route time estimation: new truck.schedule.estimate_optimized_route_hours() uses nearest-neighbor TSP with haversine × 1.3 circuity × 50 mph. Replaces broken total_trip_time sum that treated each pickup as independent round-trip (was showing 43h for 2 pickups).
  • Automatic stop sequencing: _optimize_schedule_sequence() runs on every pickup add/assign, writing sequence field to each pickup via nearest-neighbor.
  • Scheduling skip reasons: when suggested date is 3+ days out, wizard message shows which earlier dates were skipped and why.
  • Wizard truck selection: _return_valid_schedules now searches across ALL trucks in the region, not just the customer's default truck. Auto-updates truck_assigned_id.
  • ORS direction calculation fix: uses straight-line bearing from origin→destination instead of first-polyline-segment bearing.
  • Test harness added: sr_scheduling/tests/run_scenarios.py runs end-to-end scheduling scenarios from CSV, generates HTML report.
  • Files: sr_management/models/res_partner.py, sr_management/models/customer_pickups.py, sr_management/views/res_partner_view.xml, sr_scheduling/models/res_partner.py, sr_scheduling/models/customer_pickups.py, sr_scheduling/models/truck_schedule.py, sr_scheduling/models/routing_utils.py, sr_scheduling/models/ors_routing.py, sr_scheduling/wizard/add_note.py, sr_scheduling/wizard/add_note.xml, sr_scheduling/wizard/reschedule_pickup_date.py, sr_scheduling/tests/run_scenarios.py (new), sr_scheduling/tests/scenarios/scheduling_scenarios.csv (new), FUNCTIONAL_TESTS_SCHEDULING.md
  • Why: CSR reports of scheduling picking illogical dates (pushing 500lb Collins pickup to April 29 when April 6 had space). Root causes: total_trip_time computed as sum of per-pickup round-trips, direction checking blocking valid same-region consolidations, wizard only searching one truck's schedules, service window and HOO conflated into one set of fields.
  • Watch out:
  • Existing pickups keep their direction field value but it doesn't affect scheduling anymore.
  • total_trip_time stored field still exists — only the scheduling algorithm uses the new TSP method for capacity checks.
  • 50 mph average calibrated for East TN; adjust constant in truck_schedule.py::estimate_optimized_route_hours if deploying to flatter terrain.
  • Service window fields default to False/0 — must be set explicitly for customers who want a tight window.
  • Results: 19/19 functional tests pass, 10/10 scenario tests pass. Manually verified with Collins (Cookeville, 45mi) + Clarksville route: algorithm correctly schedules Collins on Apr 7 Clarksville route at 8.7h / 9h available.
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_management,sr_scheduling --stop-after-init

2026-04-02

sr_management_fixes + sr_management — Merge staging-2: prospect queue, activity status, attendance fix

  • What changed: Merged Nisarg's staging-2 changes into jan. (1) Queue system uses in_queue_a/b/c/d booleans with Queue A/B logic (missed_cycles, frequency-based). (2) Warehouse distance calculations via OSRM. (3) Prospect workflow with stage action buttons. (4) customer_activity_status computed field (new/active/warm/cold/dormant/dnd). (5) OOR customer type. (6) hr.attendance create() override auto-closes open check-ins. (7) Batched cron jobs with savepoints.
  • Files: sr_management_fixes/ (10 files), sr_management/models/res_partner.py, sr_management/models/hr_attendance.py, sr_management/views/res_partner_view.xml
  • Watch out: Cross-module dependency: sr_management._onchange_category_id references warehouse_distances from sr_management_fixes. Debug print() statements in staging-2 code. cr.commit() in cron methods.
  • Upgrade cmd: -u sr_management,sr_management_fixes --stop-after-init

sr_scheduling v1.1.0 + sr_truck_schedule + sr_management — Scheduling Fixes, Service Windows, Staging-2 Merge

  • What changed: Fixed 5 scheduling issues from 4/1 meeting: underweight routes, map tab, calendar nav, direction bugs, lunch ETA. Added service window indicators. HOO toggle in wizard, HOO optional. Merged staging-2 engine (VROOM, ORS, window checks, activity status).
  • Files: 16 files across sr_scheduling, sr_truck_schedule, sr_management
  • Watch out: Merged staging-2 code — discuss before deploying to test/staging servers. VROOM needs pyvroom (optional).
  • Upgrade cmd: -u sr_scheduling,sr_truck_schedule,sr_management --stop-after-init

2026-03-31

sr_general_sales v6.0.0 — eBay REST API, OAuth 2.0, Full Marketplace Integration

  • What changed: (1) eBay REST API (Sell Inventory API) — full implementation of create inventory item, create offer, publish offer flow via OAuth 2.0. (2) OAuth 2.0 consent flow — generate authorization URL, exchange auth code for tokens, auto-refresh. New fields on sr.api.settings: refresh_token, auth_code, ru_name, oauth_status. (3) Business policies — auto-detects and caches seller's payment/return/shipping profile IDs from eBay account. (4) Trading API fixes — uses SellerProfiles (business policies) instead of inline shipping/return XML which was rejected. Auto-includes Brand/Model/Type as item specifics. Condition IDs use safe universally-supported values (1000/1500/3000/7000). Category map updated to leaf categories only. (5) API Settings UI rebuilt — connection test buttons (app token + full), OAuth consent flow with instructions, credential auto-sync to system parameters. (6) Cleaned up duplicate code — marketplace_connector.py consolidated into marketplace/ subdirectory, ebay_rest_client.py now imported. (7) Smart posting fallback — tries REST API first if OAuth configured, falls back to Trading API. (8) 52 functional tests all passing, 21 unit tests passing.
  • Files: models/api_settings.py, models/marketplace/__init__.py, models/marketplace/ebay_rest_client.py, models/marketplace/ebay_connector.py, models/marketplace/general_sale_item_actions.py, models/marketplace_connector.py, models/__init__.py, views/api_settings_views.xml, __manifest__.py, FUNCTIONAL_TESTS_GENERAL_SALES.md (new), sr_general_sales/HANDOFF.md (new)
  • Why: Make eBay posting fully functional end-to-end. Previous version had REST API stubs and Trading API that failed on accounts with business policies.
  • Watch out:
  • eBay account (internationalrecyclers) has business policies — profile IDs cached in system params. If policies change on eBay, clear ebay_payment_profile_id, ebay_return_profile_id, ebay_shipping_profile_id.
  • Photos must be 500px+ or eBay rejects them.
  • Amazon and Walmart connectors are still honest stubs (raise clear UserError).
  • Downstream modules (sr_inventory_processing, sr_multichannel_ecommerce, sr_operations_kpi, sr_shipping) all depend on this.
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_general_sales --stop-after-init

2026-03-30

sr_seo_locations — Final: Data Population, Deliverables, Manifest Fix

  • What changed: (1) Fixed manifest load order — menu_views.xml must load before seo_state_views.xml (caused fresh install failure on EXP). (2) Added static/description/index.html to sr_seo_blog (required by EXP Odoo install). (3) Ran batch AI content generation — all 87 locations (local) and 117 locations (EXP) now have unique, AI-generated intro/main/why-choose content via Claude Haiku. (4) Populated review data: 4.8/5 rating, 47 reviews, GBP URL on all locations. (5) Generated 7 state-specific blog posts via AI, linked to state hubs. (6) Updated FUNCTIONAL_TESTS_SEO_LOCATIONS.md — 10 suites, 94 tests, covering all new features. (7) Updated HANDOFF.md with all new features, dependencies, production checklist. (8) Updated ARCHITECTURE.md with new deps (crm, scott_ai) and sr_seo_blog module. 36/36 unit tests, 93/94 functional tests passing (1 false negative on star character encoding).
  • Files: sr_seo_locations/__manifest__.py, sr_seo_blog/static/description/index.html (new), FUNCTIONAL_TESTS_SEO_LOCATIONS.md, sr_seo_locations/HANDOFF.md, ARCHITECTURE.md, CHANGES.md
  • Why: Complete project wrap-up — fix EXP install blockers, populate all data, update all deliverable docs per CLAUDE.md requirements.
  • Watch out:
  • Data (AI content, reviews, blog posts) is in the database, not git. Each server needs its own batch run.
  • EXP required API key to be copied from local to scott_ai provider
  • EXP batch generation ran in 3 batches (XML-RPC timeout on 117 locations)
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_seo_locations --stop-after-init

2026-03-29

sr_seo_locations — Phases 3-4: AI Content, Chatbot Context, Blog, Tracking

  • What changed: (1) AI content generation: replaced manual copy-paste ChatGPT wizard with direct scott_ai API integration. "Generate with AI" and "Generate & Apply" buttons on the wizard. Batch generation server action processes up to N locations (configurable via seo.ai_batch_limit system parameter). Added scott_ai dependency. (2) Chatbot location context: new JSON API endpoints /chat/context and /chat/locations that expose location/service data for the chat widget. Modified sr_website_chat's chat_widget.js to detect the current page, fetch context from the API, and include it in WebSocket messages to the external backend. (3) Blog bridge module: new sr_seo_blog module linking sr_seo_locations + website_blog. M2M fields between blog posts and locations/states. "Related Articles" sections auto-inject into location and state pages. Backend form tabs for managing linked posts. (4) Image optimization: hero_image_alt field auto-generated from city/state, get_hero_image() prefers uploaded binary over Unsplash, get_card_image() serves resized version. (5) Conversion tracking: new Odoo 17 tracking JS (replaced disabled Odoo 16 version) with GA gtag + dataLayer events for page views, phone clicks, form submissions, CTA clicks. UTM parameter extraction from URLs, injection into forms as hidden fields, and resolution to Odoo UTM records on CRM lead creation. 49/49 tests passing.
  • Files: sr_seo_locations/__manifest__.py, controllers/main.py, models/seo_location.py, wizard/seo_content_wizard.py, wizard/seo_wizard_views.xml, views/seo_location_views.xml, views/website_location_templates.xml, static/src/js/location_tracking.js (new). sr_website_chat/static/src/js/chat_widget.js. New module: sr_seo_blog/ (7 files).
  • Why: Phases 3-4 of SEO enhancement initiative — automate content at scale, make chatbot location-aware, add blog content marketing, optimize images, measure conversions.
  • Watch out:
  • scott_ai must be installed and have an active LLM provider configured before using AI generation
  • Batch generation commits after each location — if interrupted, partial progress is saved
  • Chat context API is public/read-only — the external WebSocket backend at ai.scottrecycling.com needs to be updated to consume the context field in messages
  • sr_seo_blog must be installed separately (-i sr_seo_blog) — it's not auto-installed
  • Tracking JS requires GA/GTM to be configured on the website for events to fire
  • UTM params are auto-resolved to Odoo utm.source/medium/campaign records (created if they don't exist)
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_seo_locations,sr_website_chat -i sr_seo_blog --stop-after-init

sr_item_barcode — NEW MODULE: Barcode Assignment, Labels, and Scanner

  • What changed: New module adds barcode support to processed inventory items. (1) Auto-generates unique Code 128 barcodes (SR0000001 format) on item creation via ir.sequence. (2) PDF label report (57x32mm stickers) with barcode, manufacturer, model, serial. (3) Web scanner at /inventory/scan — scan barcode to look up item details, or scan serial to create new item with device type selection. (4) Barcode field injected into all 13 device form views (laptop, desktop, phone, tablet, server, monitor, chromebook, AIO, printer, scanner, docking, toner, medical). (5) Bulk server actions: "Print Barcode Labels" and "Regenerate Barcodes" available from list view.
  • Files: New module sr_item_barcode/ — models/processed_inventory_item.py, controllers/scanner.py, views/processed_inventory_item_views.xml, views/scanner_templates.xml, reports/barcode_label_report.xml, reports/barcode_label_template.xml, static/src/js/scanner.js, static/src/css/scanner.css, data/sequence_data.xml, security/ir.model.access.csv. Also: ARCHITECTURE.md, FUNCTIONAL_TESTS_ITEM_BARCODE.md.
  • Why: No barcode system existed for individual inventory items. Items were tracked only by serial number with no scannable identifier for warehouse operations or label printing.
  • Watch out:
  • Existing items will have NULL barcode until saved or bulk-regenerated via server action
  • Field is item_barcode (not barcode) to avoid Odoo product barcode conflict
  • Scanner page requires Odoo login — not public
  • Depends on barcodes (Odoo core) — should already be available
  • Install cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -i sr_item_barcode --stop-after-init

sr_multichannel_ecommerce — Bug Fixes & Improvements + ecommerce_enterprise Removal

  • What changed: Seven fixes to sr_multichannel_ecommerce: (1) Cross-channel oversell prevention — when an order is marked paid, inventory is zeroed on the other marketplace channels via the sync service. (2) Added missing marketplace.order.refund.wizard with form view, access rights, and chatter logging. (3) Moved repricing competition price cache from in-memory dict (lost on worker restart) to DB-backed ir.config_parameter JSON storage. (4) Weekly cleanup cron now NULLs raw_data on delivered/cancelled/refunded orders >90 days old to prevent DB bloat. (5) action_mark_paid now returns True for XML-RPC compatibility. (6) Inventory sync methods (_sync_ebay/amazon/walmart_quantity) accept optional quantity kwarg for explicit zero-out. (7) Rewrote unit tests — old tests were testing unimplemented negative-price constraints; new tests cover marketplace fields, order lifecycle, and refund wizard (13/13 pass). Also removed ecommerce_enterprise module (own-website shop) — unproductive without audience, and updated ARCHITECTURE.md.
  • Files: sr_multichannel_ecommerce/models/marketplace/orders/marketplace_order.py, sr_multichannel_ecommerce/models/marketplace/inventory_sync_service.py, sr_multichannel_ecommerce/models/marketplace/repricing_service.py, sr_multichannel_ecommerce/data/cron_jobs.xml, sr_multichannel_ecommerce/__manifest__.py, sr_multichannel_ecommerce/wizard/refund_wizard.py (new), sr_multichannel_ecommerce/wizard/refund_wizard_views.xml (new), sr_multichannel_ecommerce/security/ir.model.access.csv, sr_multichannel_ecommerce/tests/test_price_constraints.py, ARCHITECTURE.md. Deleted: ecommerce_enterprise/ directory.
  • Why: Module audit identified oversell risk, missing refund workflow, volatile cache, and DB bloat. ecommerce_enterprise provided no value without organic web traffic.
  • Watch out:
  • Cross-channel zero-out depends on API credentials being configured — without them it logs a warning but doesn't block
  • Repricing cache key is multichannel.repricing_price_cache in ir.config_parameter — if corrupted, set to {}
  • If ecommerce_enterprise was installed in any database, it must be uninstalled before removing the addon path
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_multichannel_ecommerce --stop-after-init

sr_seo_locations — Phase 1 SEO Enhancements

  • What changed: (1) Added email notifications for recycling service request form — customer confirmation + internal notification to dan@scottcomputers.com, matching the pickup form pattern. Added crm to module dependencies. (2) Main site cleanup: added "Recycling Services" nav menu item linking to /recycling, added 301 redirects for legacy /schedule -> /locations/schedule-pickup and /services -> /recycling, updated robots.txt Disallow rules for internal pages. (3) Added Google Business Profile integration: gbp_url field on locations, "Leave Us a Review on Google" CTA on location detail pages, sameAs in JSON-LD schema. (4) Added review/rating system: average_rating, review_count, reviews (JSON) fields, star rating display on location pages, aggregateRating in schema markup for Google rich results. All 36 unit tests pass.
  • Files: sr_seo_locations/__manifest__.py, controllers/main.py, models/seo_location.py, data/email_templates.xml, views/menu_views.xml, views/seo_location_views.xml, views/website_location_templates.xml, hooks.py
  • Why: Phase 1 of SEO enhancement initiative — fix email notification gap, improve site navigation/crawlability, enable Google rich results via review schema.
  • Watch out:
  • GBP URLs and review data must be entered per location in backend (Website > SEO Locations > Google & Reviews tab)
  • Legacy /schedule and /services URLs now 301 redirect — any bookmarks will still work
  • crm module is now a hard dependency (was already used but not declared)
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_seo_locations --stop-after-init

sr_seo_locations — Code Review Cleanup

  • What changed: Six fixes from code review: (1) Deleted 7 stale .backup_* files from controllers/, models/, and module root. (2) Removed duplicate form_error template ID from website_location_templates.xml — was conflicting with the proper version in form_response_templates.xml. (3) Made page view and form submission counters atomic using SELECT FOR UPDATE + ORM write instead of the old read-then-write pattern that had a race condition under concurrent requests. Applies to SEOLocation.increment_page_view, SEOLocation.increment_form_submission, and SEOService.increment_page_view. (4) Replaced 3 hardcoded phone numbers in form_response_templates.xml with website.company_id.phone so they stay in sync with company settings. (5) Consolidated SEOLocationContentExtension and SEOLocationRemoteSync (two _inherit = 'seo.location' classes) into the main SEOLocation class — all fields and methods now in one place. (6) Added functional test file and handoff doc.
  • Files: sr_seo_locations/models/seo_location.py, sr_seo_locations/views/form_response_templates.xml, sr_seo_locations/views/website_location_templates.xml, FUNCTIONAL_TESTS_SEO_LOCATIONS.md, sr_seo_locations/HANDOFF.md. Deleted: 7 .backup_* files.
  • Why: Code review identified race condition in counters, duplicate template IDs causing unpredictable rendering, hardcoded phone numbers that wouldn't update with company changes, and unnecessary model class fragmentation.
  • Watch out:
  • Company phone number must be set on the company record for error/thank-you pages to display it
  • The atomic increment uses SELECT FOR UPDATE — no behavior change for end users, but the row lock pattern differs from before
  • All 36 unit tests pass after changes
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_seo_locations --stop-after-init

2026-03-28

Staging Sync — sr_management, sr_management_fixes, sr_pickup_blast, sr_product_customization, sr_reports, sr_scheduling

  • What changed: Merged 17 commits from ScottRecycling/staging into jan to sync branches. Key changes: (1) Removed sr_attendance and sr_attendance_improvements modules — attendance code now lives inside sr_management to match staging architecture. Code preserved on spare-code branch. (2) Merged Nisarg's staging work: pricing approval fields + term condition lines on res.partner, warehouse distance widget in sr_management_fixes, prospect workflow stages, pickup blast response tracking updates, certificate reports + drive serial scanner in sr_reports, portal inventory wizards in sr_product_customization, geoengine map data. (3) Resolved 42 merge conflicts across all modules. (4) Uninstalled sr_attendance from test1 and exp databases.
  • Files: 79 files deleted (sr_attendance/, sr_attendance_improvements/), 26 attendance files restored into sr_management/, manifests updated in sr_management + sr_dashboards + sr_management_fixes + sr_scheduling + sr_reports + sr_product_customization, init.py imports updated, requirements.txt merged.
  • Why: jan and staging had diverged since Dec 2025. Staging had 17 commits with production features not on jan. Needed to sync before deploying jan to staging server.
  • Watch out:
  • Must uninstall sr_attendance in database before upgrading: UPDATE ir_module_module SET state = 'uninstalled' WHERE name IN ('sr_attendance', 'sr_attendance_improvements') AND state = 'installed';
  • New pip packages required: pycairo, fuzzywuzzy, python-Levenshtein, shapely, geojson
  • Attendance code moved: Any references to sr_attendance. (template XML IDs, imports) must now use sr_management.
  • spare-code branch on ScottRecycling remote preserves the original extracted attendance module for future re-extraction
  • All 24 functional tests passed (Suites 0-9 from FUNCTIONAL_TESTS.md)
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_management,sr_management_fixes,sr_pickup_blast,sr_product_customization,sr_reports,sr_scheduling --stop-after-init

sr_pickup_blast

  • What changed: Module ready for testing/production. Email blast system with pickup response tracking — customers click "Need Pickup" or "Not right now" from email, responses auto-create CRM leads and notes. Includes A/B testing, response analytics, re-engagement automation, response rate alerts, customer segmentation, bot detection, and CAN-SPAM unsubscribe.
  • Files: Full module at sr_pickup_blast/ — models, controllers, views, data, security. Also added FUNCTIONAL_TESTS_PICKUP_BLAST.md at repo root and sr_pickup_blast/HANDOFF.md with deploy/test instructions.
  • Why: Replaces manual email outreach. Customers can respond directly from email without logging in. Tracks response rates per campaign.
  • Watch out:
  • Uninstall sr_mass_email_from_filter first if it's installed — they share the mass.email.wizard model name
  • web.base.url must be set to the correct production URL or all email links will break
  • Outgoing mail server on prod must point to real SMTP, not Mailpit (localhost:1025)
  • Two cron jobs (response rate alerts, re-engagement) are created but inactive by default — enable manually if desired
  • Token expiration defaults to 90 days, configurable via system parameter sr_pickup_blast.token_expiration_days
  • See sr_pickup_blast/HANDOFF.md for full production checklist and manual test steps
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_pickup_blast --stop-after-init

sr_scheduling (commit 618fb81)

  • What changed: 12h AM/PM time display with timezone labels in all scheduling messages. Added _float_to_12h() and _get_tz_label() helpers. Scheduling explanations now show "9 AM CT-11 AM CT, est. arrival 10:14 AM CT" instead of "9:00-11:00, est. arrival 10:14". Early start warnings also use 12h format. Timezone cron added to sr_management to populate cust_tz on customers using Google Maps Timezone API (200/hour).
  • Files: sr_scheduling/wizard/add_note.py, sr_management/models/res_partner.py, sr_management/data/ir_crons.xml
  • Why: Military time was confusing for CSRs. Customers span Eastern and Central time zones.
  • Watch out: cust_tz must be populated for timezone labels to show. Cron runs hourly, 200 customers per batch. Google Maps API key must be set. On exp, 153 missing res_partner columns were created manually — this won't be needed on databases that have been upgraded properly.

sr_scheduling (commit 9a13753)

  • What changed: Scheduling explanation message now shows WHY a date was chosen. When the wizard finds a date, the suggested_pickup_date_msg displays: existing route vs new, number of stops, capacity after adding, route time vs available hours, service window with estimated arrival, region name.
  • Files: sr_scheduling/wizard/add_note.py
  • Why: CSRs had no visibility into why the system chose a particular date.

2026-03-27

sr_management

  • What changed: Added morning_prep_minutes and evening_unload_minutes fields to customer.region model. Added Route Timing group to region form view.
  • Files: sr_management/models/customer_region.py, sr_management/views/customer_region.xml
  • Why: Driver prep time (30 min morning) and unload time (region-specific) now reduce available route hours.
  • Watch out: After upgrade, set region values: Sunbright=30min unload, Morristown/Pulaski=60min. All regions default to 30min prep.
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_management --stop-after-init

sr_scheduling

  • What changed: Major update — service window enforcement, prep/unload time support, early start warnings, Nisarg code merge.
  • Files: models/truck_schedule.py, models/customer_pickups.py, models/res_partner.py, wizard/add_note.py, wizard/add_note.xml, wizard/pickup_best_date.py (new), wizard/__init__.py, security/ir.model.access.csv
  • Why: Service windows were stored but never enforced. Now pickups outside their window are rejected (find next day) or flagged. Driver prep/unload time reduces available route hours. Early start warning lets CSR adjust departure for early-window customers.
  • Watch out:
  • warehouse_bearing and route_sector columns need to exist on res_partner (auto-created on upgrade, or run: ALTER TABLE res_partner ADD COLUMN IF NOT EXISTS warehouse_bearing double precision DEFAULT 0; ALTER TABLE res_partner ADD COLUMN IF NOT EXISTS route_sector varchar;)
  • Windows under 6 hours are treated as "tight" constraints. 6+ hours = flexible.
  • _compute_is_over_hours now uses available hours (total - prep - unload), so existing routes may newly show as "over hours"
  • Merged Nisarg's pickup_best_date.py wizard and warehouse_bearing/route_sector from staging-2
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_scheduling --stop-after-init

2026-03-25

sr_example_module

  • What changed: Added new_field to res.partner, updated compute method _compute_example
  • Files: sr_example_module/models/res_partner.py, sr_example_module/views/partner_views.xml
  • Why: Needed for the heat map feature
  • Watch out: You'll need to upgrade this module before sr_other_module or it will error
  • Upgrade cmd: /opt/odoo17/odoo17-venv/bin/python3 /opt/odoo17/odoo17/odoo-bin -c /etc/odoo17.conf -d test1 -u sr_example_module --stop-after-init