IDENTITY

title: "TICKET_043: Odoo Module Fix + SSH + Build Verification"
type: ticket
subtype: execution
purpose: "Fix the struxio_iso19650 module using verified v19 model names, establish proper SSH access, fix enterprise_code conflict, push, rebuild, and verify empirically."

GOVERNANCE

status: done
priority: P0
sprint: S001_base_and_mvp1
assignee: "Claude Code (Sonnet 4.6)"
estimated_hours: 2
depends_on: [TICKET_036]
blocks: [TICKET_035, TICKET_037, TICKET_038]
last_updated: "2026-03-16"

TICKET_043: Odoo Module Fix + SSH + Build Verification

Objective

  1. Establish permanent SSH access to Odoo.sh (not just webshell workaround)
  2. Fix documents_data.xml using verified v19 Enterprise model names
  3. Re-enable ALL data files in __manifest__.py
  4. Fix database.enterprise_code duplicate key error in PostgreSQL
  5. Uncheck "Install demo data" in Odoo.sh project settings (known core bug)
  6. Git commit, push, trigger rebuild
  7. Verify build success with empirical proof (log output)

Context

Constraints

Critical Discovery (from previous session)

The documents.folder model DOES NOT EXIST in Odoo v19 Enterprise.
Folders are documents.document records. The 13 actual documents.* models are:
documents.access, documents.access.tracking, documents.account.folder.setting,
documents.document, documents.link_to_record_wizard, documents.mixin,
documents.operation, documents.redirect, documents.request_wizard,
documents.sharing, documents.sharing.access, documents.tag, documents.unlink.mixin

Key fields on documents.document: type (selection), folder_id, name, handler,
tag_ids, owner_id, company_id, children_ids, parent_path

documents.tag exists and has name field — our tag records are correct.

Execution Plan

Task 1: Fix SSH Access (5 min)

The GitHub username for Odoo.sh SSH is shai-samuel, not shais.

# Test with correct username
ssh -o StrictHostKeyChecking=no shai-samuel@struxio-platform-main-29729723.dev.odoo.com "echo SSH_OK && whoami"

If this fails:

  1. Verify SSH key is on GitHub: gh ssh-key list
  2. Check if key sync has completed (may take up to 10 min after adding)
  3. Try verbose: ssh -vvv shai-samuel@struxio-platform-main-29729723.dev.odoo.com
  4. Fallback: Use webshell via curl/browser automation

Update STRUXIO_OS/02_infra/STATE_odoo_sh_access.md with the working username.

Task 2: Verify Folder Type Values (5 min)

Before rewriting the XML, verify the exact type selection values on documents.document:

ssh shai-samuel@struxio-platform-main-29729723.dev.odoo.com "odoo-bin shell <<'PYEOF'
# Get type field selection values
field = env['ir.model.fields'].search([('model', '=', 'documents.document'), ('name', '=', 'type')])
print('TYPE selection:', field.selection_ids.mapped(lambda s: (s.value, s.name)) if field.selection_ids else field.selection)
# Get handler field selection values
field2 = env['ir.model.fields'].search([('model', '=', 'documents.document'), ('name', '=', 'handler')])
print('HANDLER selection:', field2.selection_ids.mapped(lambda s: (s.value, s.name)) if field2.selection_ids else field2.selection)
# Check if folder_id is self-referential
field3 = env['ir.model.fields'].search([('model', '=', 'documents.document'), ('name', '=', 'folder_id')])
print('FOLDER_ID relation:', field3.relation)
# Verify tag fields
for f in env['ir.model.fields'].search([('model', '=', 'documents.tag')]):
    print('TAG FIELD:', f.name, f.ttype, f.relation or '')
exit()
PYEOF"

Record the exact values. Use them in Task 3.

Task 3: Rewrite documents_data.xml (10 min)

Based on Task 2 results, rewrite STRUXIO_App/odoo_erp/struxio_iso19650/data/documents_data.xml.

Expected change: Replace all model="documents.folder" with model="documents.document"
and add the correct type field (likely type = folder or handler = folder).
Also add folder_id as self-referential for sub-folders.

Tags remain model="documents.tag" — confirmed working.

Task 4: Re-enable ALL Data Files in manifest.py (2 min)

Uncomment all data files:

"data": [
    "security/ir.model.access.csv",
    "data/company_data.xml",
    "data/documents_data.xml",
    "data/product_data.xml",
    "data/crm_data.xml",
    "data/quality_data.xml",
    "data/knowledge_data.xml",
],

Task 5: Fix Enterprise Code Duplicate Key (5 min)

ssh shai-samuel@struxio-platform-main-29729723.dev.odoo.com "psql -c \"SELECT key, value FROM ir_config_parameter WHERE key = 'database.enterprise_code';\""

If duplicate exists:

ssh shai-samuel@struxio-platform-main-29729723.dev.odoo.com "psql -c \"DELETE FROM ir_config_parameter WHERE key = 'database.enterprise_code'; INSERT INTO ir_config_parameter (key, value, create_uid, write_uid, create_date, write_date) VALUES ('database.enterprise_code', '<CORRECT_CODE>', 1, 1, now(), now());\""

The correct enterprise code should be in STRUXIO_OS/02_infra/infrastructure_secrets.yaml (SOPS encrypted) or ask Founder.

Task 6: Git Commit and Push (5 min)

cd /Volumes/CORSAIR/STRUXIO_HardDrive/STRUXIO_Workspace/STRUXIO_App
git checkout -b feat/TICKET_043_fix_documents_module
git add odoo_erp/struxio_iso19650/
git commit -m "fix(iso-19650): rewrite documents_data.xml for v19 Enterprise models

- Replace documents.folder (non-existent in v19) with documents.document
- Re-enable all data files: products, quality, knowledge, documents
- Tags use verified documents.tag model
- Folders use documents.document with type=folder and self-referential folder_id

Closes: TICKET_043
Circuit-Breaker: documents.folder failed 3x in TICKET_036"
git push -u origin feat/TICKET_043_fix_documents_module

Task 7: Monitor Build and Verify (15 min)

After push triggers Odoo.sh rebuild:

# Wait 2 minutes for build to start, then check logs
sleep 120
ssh shai-samuel@struxio-platform-main-29729723.dev.odoo.com "grep -i 'struxio_iso19650\|error\|failed' ~/logs/odoo.log | tail -30"

Verification commands (run via odoo-bin shell after build completes):

# V1: Module is installed
print('MODULE:', env['ir.module.module'].search([('name','=','struxio_iso19650')]).state)
# Expected: "installed"

# V2: CDE folders created
folders = env['documents.document'].search([('name','like','%CDE%')])
print('CDE FOLDERS:', len(folders), [f.name for f in folders])
# Expected: >= 1 folder containing "CDE"

# V3: ISO tags created
tags = env['documents.tag'].search([('name','like','%S0%')])
print('ISO TAGS:', len(tags), [t.name for t in tags])
# Expected: >= 1 tag containing "S0"

# V4: Products created
products = env['product.template'].search([('name','like','%ISO 19650%')])
print('PRODUCTS:', len(products), [p.name for p in products])
# Expected: 6 products

# V5: CRM stages created
stages = env['crm.stage'].search([('name','like','%Qualified%')])
print('CRM STAGES:', len(stages))
# Expected: >= 1

# V6: Quality points created
qps = env['quality.point'].search([('name','like','%BEP%')])
print('QUALITY POINTS:', len(qps))
# Expected: >= 1

# V7: Knowledge articles created
articles = env['knowledge.article'].search([('name','like','%ISO 19650%')])
print('KNOWLEDGE ARTICLES:', len(articles))
# Expected: >= 1

# V8: Company name updated
company = env['res.company'].browse(1)
print('COMPANY:', company.name, company.street, company.city)
# Expected: "STRUXIO", "304 S Jones Blvd...", "Las Vegas"

Acceptance Criteria

Rollback Plan

If build fails after push:

  1. git revert HEAD on the feature branch
  2. Push revert to trigger clean rebuild
  3. Analyze error logs before retrying
  4. If 3 consecutive failures → Circuit Breaker → escalate to Architect (Claude Opus in claude.ai)

Affected Files


STRUXIO.ai // Confidential & Proprietary // © 2026