- 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>
84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Fix Subscription DocField restrictions so the REST API can update all fields.
|
|
|
|
Frappe's standard PUT /api/resource/Subscription/{name} silently ignores
|
|
fields marked read_only=1, set_only_once=1, etc. These restrictions make
|
|
sense for the desk UI but block our Ops frontend from managing subscriptions.
|
|
|
|
Changes applied (idempotent):
|
|
1. status : read_only 1 -> 0 (so we can cancel/reactivate)
|
|
2. cancelation_date : read_only 1 -> 0 (set when cancelling)
|
|
3. end_date : set_only_once 1 -> 0 (editable for renewals)
|
|
4. start_date : set_only_once 1 -> 0 (editable for corrections)
|
|
5. follow_calendar_months : set_only_once 1 -> 0
|
|
|
|
Also disables follow_calendar_months on all subs (conflicts with annual
|
|
billing unless end_date is set).
|
|
|
|
Run via direct PostgreSQL (no bench CLI needed):
|
|
python3 scripts/migration/setup_subscription_api.py
|
|
"""
|
|
import psycopg2
|
|
|
|
PG = {"host": "db", "port": 5432, "user": "postgres", "password": "123",
|
|
"dbname": "_eb65bdc0c4b1b2d6"}
|
|
|
|
|
|
def main():
|
|
pg = psycopg2.connect(**PG)
|
|
pgc = pg.cursor()
|
|
|
|
# 1. Remove read_only on status and cancelation_date
|
|
pgc.execute("""
|
|
UPDATE "tabDocField"
|
|
SET read_only = 0
|
|
WHERE parent = 'Subscription'
|
|
AND fieldname IN ('status', 'cancelation_date')
|
|
AND read_only = 1
|
|
""")
|
|
n1 = pgc.rowcount
|
|
print(f" read_only removed: {n1} fields")
|
|
|
|
# 2. Remove set_only_once on end_date, start_date, follow_calendar_months
|
|
pgc.execute("""
|
|
UPDATE "tabDocField"
|
|
SET set_only_once = 0
|
|
WHERE parent = 'Subscription'
|
|
AND fieldname IN ('end_date', 'start_date', 'follow_calendar_months')
|
|
AND set_only_once = 1
|
|
""")
|
|
n2 = pgc.rowcount
|
|
print(f" set_only_once removed: {n2} fields")
|
|
|
|
# 3. Disable follow_calendar_months on all subscriptions
|
|
# (it requires end_date + monthly billing; breaks annual subs)
|
|
pgc.execute("""
|
|
UPDATE "tabSubscription"
|
|
SET follow_calendar_months = 0
|
|
WHERE follow_calendar_months = 1
|
|
""")
|
|
n3 = pgc.rowcount
|
|
print(f" follow_calendar_months disabled on {n3} subscriptions")
|
|
|
|
# 4. Fix company name (legacy migration used wrong name)
|
|
pgc.execute("""
|
|
UPDATE "tabSubscription"
|
|
SET company = 'TARGO'
|
|
WHERE company != 'TARGO' OR company IS NULL
|
|
""")
|
|
n4 = pgc.rowcount
|
|
print(f" company fixed to TARGO on {n4} subscriptions")
|
|
|
|
pg.commit()
|
|
pg.close()
|
|
|
|
print()
|
|
print("Done. Clear Frappe cache to apply DocField changes:")
|
|
print(" bench --site <site> clear-cache")
|
|
print(" OR restart the backend container")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|