#!/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")