- InlineField component + useInlineEdit composable for Odoo-style dblclick editing - Client search by name, account ID, and legacy_customer_id (or_filters) - SMS/Email notification panel on ContactCard via n8n webhooks - Ticket reply thread via Communication docs - All migration scripts (51 files) now tracked - Client portal and field tech app added to monorepo - README rewritten with full feature list, migration summary, architecture - CHANGELOG updated with all recent work - ROADMAP updated with current completion status - Removed hardcoded tokens from docs (use $ERP_SERVICE_TOKEN) - .gitignore updated (docker/, .claude/, exports/, .quasar/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Fix the PostgreSQL GROUP BY bug in ERPNext's payment_ledger_entry.py
|
|
on the server via SSH.
|
|
|
|
The bug: update_voucher_outstanding() selects 'account', 'party_type', 'party'
|
|
but doesn't include them in GROUP BY — PostgreSQL requires this, MariaDB doesn't.
|
|
|
|
This script SSH into the server and patches the file in-place.
|
|
"""
|
|
import subprocess
|
|
import sys
|
|
|
|
SERVER = "root@96.125.196.67"
|
|
# Path inside the erpnext docker container
|
|
CONTAINER = "erpnext-backend-1"
|
|
FILE_PATH = "apps/erpnext/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py"
|
|
|
|
# First, let's read the current file to find the exact code to patch
|
|
print("Step 1: Reading current file from server...")
|
|
result = subprocess.run(
|
|
["ssh", SERVER, f"docker exec {CONTAINER} cat /home/frappe/frappe-bench/{FILE_PATH}"],
|
|
capture_output=True, text=True
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
print(f"ERROR reading file: {result.stderr}")
|
|
sys.exit(1)
|
|
|
|
content = result.stdout
|
|
print(f" File size: {len(content)} bytes")
|
|
|
|
# Find the problematic groupby
|
|
# Look for the pattern where groupby has voucher_type and voucher_no but NOT account
|
|
import re
|
|
|
|
# Find the update_voucher_outstanding function and its groupby
|
|
lines = content.split('\n')
|
|
found = False
|
|
for i, line in enumerate(lines):
|
|
if 'def update_voucher_outstanding' in line:
|
|
print(f" Found function at line {i+1}")
|
|
if '.groupby(' in line and 'voucher_type' in line and 'voucher_no' in line:
|
|
# Check surrounding lines for account in groupby
|
|
context = '\n'.join(lines[max(0,i-3):i+5])
|
|
if 'ple.account' not in context or '.groupby' in line:
|
|
print(f" Found groupby at line {i+1}: {line.strip()}")
|
|
found = True
|
|
|
|
if not found:
|
|
print(" Could not find the problematic groupby pattern")
|
|
print(" Dumping function for manual inspection...")
|
|
in_func = False
|
|
for i, line in enumerate(lines):
|
|
if 'def update_voucher_outstanding' in line:
|
|
in_func = True
|
|
if in_func:
|
|
print(f" {i+1}: {line}")
|
|
if in_func and line.strip() and not line.startswith('\t') and not line.startswith(' ') and i > 0:
|
|
if 'def ' in line and 'update_voucher_outstanding' not in line:
|
|
break
|
|
if in_func and i > 250: # safety limit
|
|
break
|
|
|
|
print("\n--- Full file dumped for inspection ---")
|
|
print("Use this output to craft the sed command manually")
|