239 lines
8.5 KiB
Python
239 lines
8.5 KiB
Python
from proteus import config, Model
|
|
import psycopg2
|
|
|
|
# XML-RPC Configuration (default connection method)
|
|
HTTPS = 'https://'
|
|
SERVER_URL = 'itsa.open-squared.tech'
|
|
DATABASE_NAME = 'tradon'
|
|
USERNAME = 'admin'
|
|
PASSWORD = 'dsproject'
|
|
|
|
# PostgreSQL Configuration (for direct database inspection)
|
|
DB_HOST = '72.61.163.139'
|
|
DB_PORT = 5433
|
|
DB_USER = 'postgres'
|
|
DB_PASSWORD = 'dsproject'
|
|
|
|
print("="*80)
|
|
print("CUSTOM FIELDS IDENTIFICATION FOR purchase.purchase")
|
|
print("="*80)
|
|
|
|
# Connect to Tryton via XML-RPC
|
|
print(f"\nConnecting via XML-RPC to {SERVER_URL}...")
|
|
config.set_xmlrpc(f'{HTTPS}{USERNAME}:{PASSWORD}@{SERVER_URL}/{DATABASE_NAME}/')
|
|
print("✓ Connected successfully\n")
|
|
|
|
Purchase = Model.get('purchase.purchase')
|
|
|
|
# Get all fields that Proteus sees
|
|
proteus_fields = sorted([key for key in dir(Purchase)
|
|
if not key.startswith('_')
|
|
and key not in ['create', 'delete', 'save', 'find',
|
|
'copy', 'read', 'write', 'search']])
|
|
|
|
print(f"1. FIELDS VISIBLE TO PROTEUS: {len(proteus_fields)} fields")
|
|
print("-"*80)
|
|
|
|
# Standard Tryton purchase.purchase fields (from base module)
|
|
standard_purchase_fields = {
|
|
'id', 'create_date', 'create_uid', 'write_date', 'write_uid',
|
|
'company', 'party', 'invoice_party', 'invoice_address',
|
|
'payment_term', 'warehouse', 'currency', 'description',
|
|
'comment', 'state', 'purchase_date', 'invoice_method',
|
|
'lines', 'invoices', 'invoices_ignored', 'invoices_recreated',
|
|
'invoice_lines', 'invoice_lines_ignored', 'moves',
|
|
'shipment_state', 'invoice_state', 'number', 'reference',
|
|
'shipments', 'shipment_returns', 'rec_name', 'origin',
|
|
'untaxed_amount', 'tax_amount', 'total_amount',
|
|
'untaxed_amount_cache', 'tax_amount_cache', 'total_amount_cache',
|
|
'delivery_date', 'party_lang', 'contact', 'xml_id'
|
|
}
|
|
|
|
# Identify potential custom fields
|
|
potential_custom_fields = [f for f in proteus_fields if f not in standard_purchase_fields]
|
|
|
|
print(f"\n2. POTENTIAL CUSTOM FIELDS: {len(potential_custom_fields)} fields")
|
|
print("-"*80)
|
|
for field in potential_custom_fields:
|
|
print(f" - {field}")
|
|
|
|
# Connect to PostgreSQL to get actual table columns
|
|
print(f"\n3. COLUMNS IN POSTGRESQL TABLE 'purchase_purchase'")
|
|
print("-"*80)
|
|
|
|
try:
|
|
conn = psycopg2.connect(
|
|
dbname=DATABASE_NAME,
|
|
host=DB_HOST,
|
|
port=DB_PORT,
|
|
user=DB_USER,
|
|
password=DB_PASSWORD
|
|
)
|
|
cursor = conn.cursor()
|
|
|
|
# Get all columns from purchase_purchase table
|
|
cursor.execute("""
|
|
SELECT
|
|
column_name,
|
|
data_type,
|
|
character_maximum_length,
|
|
is_nullable,
|
|
column_default
|
|
FROM information_schema.columns
|
|
WHERE table_schema = 'public'
|
|
AND table_name = 'purchase_purchase'
|
|
ORDER BY ordinal_position;
|
|
""")
|
|
|
|
db_columns = cursor.fetchall()
|
|
|
|
print(f"Total columns in database: {len(db_columns)}\n")
|
|
|
|
# Standard columns that typically exist in purchase_purchase
|
|
standard_db_columns = {
|
|
'id', 'create_date', 'create_uid', 'write_date', 'write_uid',
|
|
'company', 'party', 'invoice_party', 'invoice_address',
|
|
'payment_term', 'warehouse', 'currency', 'description',
|
|
'comment', 'state', 'purchase_date', 'invoice_method',
|
|
'number', 'reference', 'delivery_date', 'contact',
|
|
'shipment_state', 'invoice_state', 'origin',
|
|
'untaxed_amount_cache', 'tax_amount_cache', 'total_amount_cache'
|
|
}
|
|
|
|
db_column_names = [col[0] for col in db_columns]
|
|
custom_db_columns = [col for col in db_columns if col[0] not in standard_db_columns]
|
|
|
|
print("Custom columns in database:")
|
|
for col in custom_db_columns:
|
|
col_name, data_type, max_length, nullable, default = col
|
|
length_info = f"({max_length})" if max_length else ""
|
|
print(f" - {col_name:<30} {data_type}{length_info:<15} NULL: {nullable}")
|
|
|
|
# Compare: Fields in Proteus vs Columns in DB
|
|
print(f"\n4. COMPARISON: PROTEUS vs DATABASE")
|
|
print("-"*80)
|
|
|
|
# Fields in Proteus but NOT as direct columns in DB (might be related fields, functions, etc.)
|
|
proteus_only = set(potential_custom_fields) - set(db_column_names)
|
|
if proteus_only:
|
|
print(f"\nFields in Proteus but NOT as columns in DB ({len(proteus_only)}):")
|
|
print("(These might be Many2One, One2Many, Function fields, etc.)")
|
|
for field in sorted(proteus_only):
|
|
print(f" - {field}")
|
|
|
|
# Columns in DB but NOT visible in Proteus (these are the problem!)
|
|
db_only = set([col[0] for col in custom_db_columns]) - set(proteus_fields)
|
|
if db_only:
|
|
print(f"\n⚠️ COLUMNS IN DATABASE BUT NOT VISIBLE IN PROTEUS ({len(db_only)}):")
|
|
print("(These fields MUST be added to the Python model!)")
|
|
for field in sorted(db_only):
|
|
print(f" - {field}")
|
|
|
|
# Fields that exist in BOTH Proteus and DB
|
|
both = set(potential_custom_fields) & set([col[0] for col in custom_db_columns])
|
|
if both:
|
|
print(f"\n✓ Custom fields properly defined in BOTH Proteus and DB ({len(both)}):")
|
|
for field in sorted(both):
|
|
print(f" - {field}")
|
|
|
|
cursor.close()
|
|
conn.close()
|
|
|
|
except Exception as e:
|
|
print(f"Error connecting to PostgreSQL: {e}")
|
|
|
|
# Test persistence of custom fields
|
|
print(f"\n5. TESTING FIELD PERSISTENCE")
|
|
print("-"*80)
|
|
|
|
try:
|
|
# Find a draft purchase to test
|
|
drafts = Purchase.find([('state', '=', 'draft')], limit=1)
|
|
|
|
if drafts:
|
|
test_purchase = drafts[0]
|
|
test_id = test_purchase.id
|
|
|
|
print(f"Testing with purchase ID: {test_id}")
|
|
print("\nTesting custom fields (attempting to set and save):\n")
|
|
|
|
# Test a sample of custom fields
|
|
test_fields = {}
|
|
|
|
# Add fields to test if they exist
|
|
if 'reference' in potential_custom_fields:
|
|
test_fields['reference'] = 'TEST_REF'
|
|
if 'crop' in potential_custom_fields:
|
|
test_fields['crop'] = 'TEST_CROP'
|
|
if 'forex' in potential_custom_fields:
|
|
test_fields['forex'] = 'TEST_FOREX'
|
|
if 'broker' in potential_custom_fields:
|
|
test_fields['broker'] = 'TEST_BROKER'
|
|
if 'certif' in potential_custom_fields:
|
|
test_fields['certif'] = 'TEST_CERT'
|
|
if 'wb' in potential_custom_fields:
|
|
test_fields['wb'] = 'TEST_WB'
|
|
|
|
for field_name, test_value in test_fields.items():
|
|
try:
|
|
original_value = getattr(test_purchase, field_name, None)
|
|
setattr(test_purchase, field_name, test_value)
|
|
test_purchase.save()
|
|
|
|
# Reload
|
|
reloaded = Purchase(test_id)
|
|
new_value = getattr(reloaded, field_name, None)
|
|
|
|
if new_value == test_value:
|
|
print(f" ✓ {field_name}: PERSISTS correctly")
|
|
# Restore original value
|
|
setattr(reloaded, field_name, original_value)
|
|
reloaded.save()
|
|
else:
|
|
print(f" ✗ {field_name}: Does NOT persist (expected: '{test_value}', got: '{new_value}')")
|
|
|
|
except Exception as e:
|
|
print(f" ✗ {field_name}: Error - {str(e)[:60]}")
|
|
else:
|
|
print("No draft purchases found for testing")
|
|
|
|
except Exception as e:
|
|
print(f"Error during persistence testing: {e}")
|
|
|
|
print("\n" + "="*80)
|
|
print("SUMMARY & RECOMMENDATIONS")
|
|
print("="*80)
|
|
print("""
|
|
Next steps for your colleague:
|
|
|
|
1. Review the "⚠️ COLUMNS IN DATABASE BUT NOT VISIBLE IN PROTEUS" section
|
|
→ These fields exist in PostgreSQL but are missing from the Python model
|
|
|
|
2. Review fields that "Does NOT persist" in the testing section
|
|
→ These fields are visible but not working correctly
|
|
|
|
3. Add missing fields to your custom Tryton module:
|
|
|
|
File: modules/your_custom_module/purchase.py
|
|
|
|
from trytond.pool import PoolMeta
|
|
from trytond.model import fields
|
|
|
|
class Purchase(metaclass=PoolMeta):
|
|
__name__ = 'purchase.purchase'
|
|
|
|
# Add each missing field with appropriate type:
|
|
custom_field = fields.Char('Custom Field')
|
|
custom_number = fields.Integer('Custom Number')
|
|
custom_date = fields.Date('Custom Date')
|
|
custom_many2one = fields.Many2One('other.model', 'Reference')
|
|
# etc...
|
|
|
|
4. Increment module version in tryton.cfg
|
|
|
|
5. Update module: trytond-admin -d tradon -u your_custom_module
|
|
|
|
6. Restart Tryton server
|
|
|
|
7. Re-run this script to verify all fields work correctly
|
|
""") |