279 lines
12 KiB
Python
279 lines
12 KiB
Python
import frappe
|
|
|
|
|
|
def fix_indicator_permlevel():
|
|
"""Set actor-visible fields in Progress indicators to permlevel 0 so all roles can read them."""
|
|
visible_fields = ['name1', 'target', 'minimum', 'maximum', 'actual_value', 'cycle_comment', 'cycle_status', 'cycle_date', 'status']
|
|
for f in visible_fields:
|
|
frappe.db.sql(
|
|
"UPDATE `tabDocField` SET permlevel=0 WHERE parent='Progress indicators' AND fieldname=%s",
|
|
f
|
|
)
|
|
print(f' Set permlevel=0: {f}')
|
|
frappe.db.commit()
|
|
frappe.clear_cache(doctype='Progress indicators')
|
|
frappe.clear_cache(doctype='SB Process')
|
|
print('Done.')
|
|
|
|
|
|
def check_process_perms():
|
|
rows = frappe.db.sql(
|
|
'SELECT role, permlevel, `read`, `write`, `create` FROM `tabDocPerm` WHERE parent="SB Process" ORDER BY permlevel, role',
|
|
as_dict=True
|
|
)
|
|
print("=== SB Process Permissions ===")
|
|
for r in rows:
|
|
print(r)
|
|
flds = frappe.db.sql(
|
|
'SELECT fieldname, label, permlevel FROM `tabDocField` WHERE parent="Progress indicators" ORDER BY idx',
|
|
as_dict=True
|
|
)
|
|
print("\n=== Progress indicators field permlevel ===")
|
|
for f in flds:
|
|
print(f)
|
|
|
|
print("\n=== SB Process child table field ===")
|
|
ct = frappe.db.sql(
|
|
'SELECT fieldname, label, options FROM `tabDocField` WHERE parent="SB Process" AND fieldtype="Table"',
|
|
as_dict=True
|
|
)
|
|
for f in ct:
|
|
print(f)
|
|
|
|
|
|
def seed_brd_statuses():
|
|
"""Seed all BRD-specified status master records (idempotent)."""
|
|
brd_statuses = {
|
|
'Idea Statuses': [
|
|
'New', 'Initial Evaluation', 'Rejected',
|
|
'Accept & Under Progress', 'Executed & Closed', 'Moved to Study',
|
|
],
|
|
'Incident Statuses': [
|
|
'New', 'Initial Evaluation', 'Rejected',
|
|
'Accept & Under Progress', 'Executed & Closed',
|
|
],
|
|
'Order Statuses': ['New', 'In Progress', 'Closed'],
|
|
'Process Statuses': ['Pass', 'Fail', 'Unknown', 'Active'],
|
|
}
|
|
for doctype, names in brd_statuses.items():
|
|
for name in names:
|
|
if not frappe.db.exists(doctype, name):
|
|
doc = frappe.new_doc(doctype)
|
|
doc.name1 = name
|
|
doc.insert(ignore_permissions=True)
|
|
print(f'Created {doctype}: {name}')
|
|
else:
|
|
print(f'Already exists {doctype}: {name}')
|
|
frappe.db.commit()
|
|
print('BRD statuses seeded.')
|
|
|
|
|
|
def create_roles():
|
|
roles = ['CEO', 'Ceo', 'SB CEO', 'SB Admin', 'SB Owner', 'SB Manager', 'SB Auditor', 'SB X-Auditor', 'SB Employee']
|
|
for role in roles:
|
|
if not frappe.db.exists('Role', role):
|
|
doc = frappe.new_doc('Role')
|
|
doc.role_name = role
|
|
doc.insert(ignore_permissions=True)
|
|
print(f'Created role: {role}')
|
|
else:
|
|
print(f'Role already exists: {role}')
|
|
frappe.db.commit()
|
|
|
|
def create_test_users():
|
|
users = [
|
|
{'email': 'manager@sidrah.com', 'first_name': 'Sara', 'last_name': 'Manager', 'role': 'SB Manager'},
|
|
{'email': 'auditor@sidrah.com', 'first_name': 'Omar', 'last_name': 'Auditor', 'role': 'SB Auditor'},
|
|
{'email': 'employee@sidrah.com', 'first_name': 'Ali', 'last_name': 'Employee', 'role': 'SB Employee'},
|
|
]
|
|
for u in users:
|
|
if not frappe.db.exists('User', u['email']):
|
|
doc = frappe.new_doc('User')
|
|
doc.email = u['email']
|
|
doc.first_name = u['first_name']
|
|
doc.last_name = u['last_name']
|
|
doc.new_password = 'sidrah123'
|
|
doc.send_welcome_email = 0
|
|
doc.insert(ignore_permissions=True)
|
|
frappe.db.commit()
|
|
user_doc = frappe.get_doc('User', u['email'])
|
|
user_doc.add_roles(u['role'])
|
|
print(f"Created user: {u['email']}")
|
|
else:
|
|
print(f"User already exists: {u['email']}")
|
|
frappe.db.commit()
|
|
|
|
|
|
def check_statuses():
|
|
for dt in ['Incident Statuses', 'Idea Statuses', 'Order Statuses', 'Process Statuses']:
|
|
rows = frappe.db.sql(f'SELECT name, name1 FROM `tab{dt}`', as_dict=True)
|
|
print(f'\n=== {dt} ===')
|
|
for r in rows:
|
|
print(f' name={r.name!r} name1={r.name1!r}')
|
|
|
|
|
|
def cleanup_statuses():
|
|
"""
|
|
Remove all non-BRD status records and migrate documents to the correct BRD values.
|
|
BRD sources: Section 6 (lookup tables), 9.4 (Incident), 10.2 (Idea).
|
|
Run once; safe to re-run (idempotent).
|
|
"""
|
|
|
|
# ── BRD-approved values ───────────────────────────────────────────────────
|
|
BRD = {
|
|
'Incident Statuses': ['New', 'Initial Evaluation', 'Rejected', 'Accept & Under Progress', 'Executed & Closed'],
|
|
'Idea Statuses': ['New', 'Initial Evaluation', 'Rejected', 'Accept & Under Progress', 'Executed & Closed', 'Moved to Study'],
|
|
'Order Statuses': ['Bidding', 'Execution', 'Validation', 'Payment', 'Completion', 'Closed'],
|
|
'Process Statuses': ['Pass', 'Fail', 'Unknown'],
|
|
}
|
|
|
|
# ── Migration maps (old value → BRD value) ────────────────────────────────
|
|
INC_MAP = {
|
|
'Under progress': 'Accept & Under Progress',
|
|
'Executed': 'Executed & Closed',
|
|
'Pending Auditor': 'Initial Evaluation',
|
|
'Pending Manager': 'Accept & Under Progress',
|
|
'Pending Comment': 'Accept & Under Progress',
|
|
'Review': 'Accept & Under Progress',
|
|
'In Study': 'Executed & Closed',
|
|
}
|
|
IDEA_MAP = {
|
|
'Accepted & under progress': 'Accept & Under Progress',
|
|
'Being studied': 'Moved to Study',
|
|
'Executed': 'Executed & Closed',
|
|
'Executed & closed': 'Executed & Closed',
|
|
'Under Progress': 'Accept & Under Progress',
|
|
'Pending Auditor': 'Initial Evaluation',
|
|
'Pending Manager': 'Accept & Under Progress',
|
|
'Pending Comment': 'Accept & Under Progress',
|
|
'Review': 'Accept & Under Progress',
|
|
'In Outsourcing': 'Executed & Closed',
|
|
'Moved to Study': 'Moved to Study',
|
|
}
|
|
ORD_MAP = {
|
|
'New': 'Bidding',
|
|
'Deviation': 'Execution',
|
|
'In Progress':'Execution',
|
|
'Precision': 'Validation',
|
|
}
|
|
PROC_MAP = {
|
|
'Active': 'Unknown',
|
|
'Failures': 'Fail',
|
|
'Success': 'Pass',
|
|
}
|
|
|
|
STAGE_TO_STATUS = {1: 'Bidding', 2: 'Execution', 3: 'Validation', 4: 'Payment', 5: 'Completion'}
|
|
|
|
# ── Step 1: Migrate SB Incident documents ────────────────────────────────
|
|
print('\n--- Migrating SB Incident status ---')
|
|
for old, new in INC_MAP.items():
|
|
count = frappe.db.count('SB Incident', {'status': old})
|
|
if count:
|
|
frappe.db.sql("UPDATE `tabSB Incident` SET status=%s WHERE status=%s", (new, old))
|
|
print(f' Incident: "{old}" → "{new}" ({count} docs)')
|
|
|
|
# ── Step 2: Migrate SB Idea documents ────────────────────────────────────
|
|
print('\n--- Migrating SB Idea status ---')
|
|
for old, new in IDEA_MAP.items():
|
|
count = frappe.db.count('SB Idea', {'status': old})
|
|
if count:
|
|
frappe.db.sql("UPDATE `tabSB Idea` SET status=%s WHERE status=%s", (new, old))
|
|
print(f' Idea: "{old}" → "{new}" ({count} docs)')
|
|
|
|
# ── Step 3: Migrate SB Order — use stage to drive status ────────────────
|
|
print('\n--- Migrating SB Order status (stage-based) ---')
|
|
all_orders = frappe.db.sql(
|
|
"SELECT name, stage, workflow_state, status FROM `tabSB Order`", as_dict=True
|
|
)
|
|
for o in all_orders:
|
|
if o.workflow_state == 'Closed' or o.status == 'Closed':
|
|
correct = 'Closed'
|
|
else:
|
|
correct = STAGE_TO_STATUS.get(int(o.stage or 1), 'Bidding')
|
|
if o.status != correct:
|
|
frappe.db.sql("UPDATE `tabSB Order` SET status=%s WHERE name=%s", (correct, o.name))
|
|
print(f' Order {o.name}: "{o.status}" → "{correct}" (stage={o.stage})')
|
|
# Also handle non-stage-based old mappings for any remaining
|
|
for old, new in ORD_MAP.items():
|
|
count = frappe.db.count('SB Order', {'status': old})
|
|
if count:
|
|
frappe.db.sql("UPDATE `tabSB Order` SET status=%s WHERE status=%s", (new, old))
|
|
print(f' Order: "{old}" → "{new}" ({count} docs)')
|
|
|
|
# ── Step 4: Migrate SB Process documents ─────────────────────────────────
|
|
print('\n--- Migrating SB Process status ---')
|
|
for old, new in PROC_MAP.items():
|
|
count = frappe.db.count('SB Process', {'status': old})
|
|
if count:
|
|
frappe.db.sql("UPDATE `tabSB Process` SET status=%s WHERE status=%s", (new, old))
|
|
print(f' Process: "{old}" → "{new}" ({count} docs)')
|
|
|
|
frappe.db.commit()
|
|
|
|
# ── Step 5: Delete non-BRD master records ────────────────────────────────
|
|
print('\n--- Cleaning status master records ---')
|
|
for dt, allowed in BRD.items():
|
|
existing = frappe.db.sql(f"SELECT name FROM `tab{dt}`", as_dict=True)
|
|
for row in existing:
|
|
if row.name not in allowed:
|
|
frappe.db.sql(f"DELETE FROM `tab{dt}` WHERE name=%s", row.name)
|
|
print(f' Deleted {dt}: "{row.name}"')
|
|
|
|
# ── Step 6: Ensure all BRD records exist (with exact names) ──────────────
|
|
print('\n--- Ensuring BRD statuses exist ---')
|
|
for dt, names in BRD.items():
|
|
for n in names:
|
|
exists = frappe.db.sql(f"SELECT name FROM `tab{dt}` WHERE name=%s", n)
|
|
if not exists:
|
|
frappe.db.sql(f"INSERT INTO `tab{dt}` (name, name1, creation, modified, modified_by, owner, docstatus) VALUES (%s,%s,NOW(),NOW(),'Administrator','Administrator',0)", (n, n))
|
|
print(f' Created {dt}: "{n}"')
|
|
else:
|
|
frappe.db.sql(f"UPDATE `tab{dt}` SET name1=%s WHERE name=%s", (n, n))
|
|
|
|
frappe.db.commit()
|
|
print('\nStatus cleanup complete.')
|
|
|
|
|
|
def sync_workflows():
|
|
"""Sync all Frappe Workflows from workflow.json fixture into Frappe DB."""
|
|
import json
|
|
import os
|
|
fixture_path = frappe.get_app_path('sidrah_business', 'fixtures', 'workflow.json')
|
|
if not os.path.exists(fixture_path):
|
|
print('workflow.json not found')
|
|
return
|
|
|
|
with open(fixture_path, 'r') as f:
|
|
workflows = json.load(f)
|
|
|
|
for wf_data in workflows:
|
|
wf_name = wf_data.get('name')
|
|
if not wf_name:
|
|
continue
|
|
if frappe.db.exists('Workflow', wf_name):
|
|
doc = frappe.get_doc('Workflow', wf_name)
|
|
else:
|
|
doc = frappe.new_doc('Workflow')
|
|
doc.name = wf_name
|
|
|
|
doc.workflow_name = wf_data.get('workflow_name', wf_name)
|
|
doc.document_type = wf_data.get('document_type')
|
|
doc.workflow_state_field = wf_data.get('workflow_state_field', 'workflow_state')
|
|
doc.is_active = wf_data.get('is_active', 1)
|
|
|
|
doc.set('states', [])
|
|
for st in wf_data.get('states', []):
|
|
doc.append('states', st)
|
|
|
|
doc.set('transitions', [])
|
|
for tr in wf_data.get('transitions', []):
|
|
doc.append('transitions', tr)
|
|
|
|
doc.flags.ignore_permissions = True
|
|
doc.save(ignore_permissions=True)
|
|
print(f"Synced Workflow in Frappe DB: {wf_name}")
|
|
|
|
frappe.db.commit()
|
|
print("All Workflows synced to Frappe DB successfully.")
|
|
|