mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-17 13:55:08 +00:00
- black: auto-reformatted all 4 Furnitex scripts to PEP 8 style - isort: sorted imports in setup_furnitex.py and delete_streetwok.py - codespell: renamed loop variable `ot` → `opp_type` in create_crm_stages() (codespell flagged `ot` as a misspelling) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
244 lines
8.6 KiB
Python
244 lines
8.6 KiB
Python
"""
|
|
delete_streetwok.py
|
|
Removes all "streetwok (Demo)" company data from Furnitex ERPNext instance.
|
|
Run via: bench --site frontend execute frappe.delete_streetwok.run
|
|
"""
|
|
|
|
import frappe
|
|
|
|
COMPANY = "streetwok (Demo)"
|
|
|
|
|
|
def _sql(q, commit=False):
|
|
frappe.db.sql(q)
|
|
if commit:
|
|
frappe.db.commit()
|
|
|
|
|
|
def run():
|
|
frappe.set_user("Administrator")
|
|
|
|
if not frappe.db.exists("Company", COMPANY):
|
|
print(f" Company '{COMPANY}' not found — nothing to delete.")
|
|
return
|
|
|
|
print(f"\n{'='*54}")
|
|
print(f" DELETING: {COMPANY}")
|
|
print(f"{'='*54}\n")
|
|
|
|
# ── STEP 1: Cancel + delete all submitted documents ──────────
|
|
submitted_doctypes = [
|
|
"Sales Invoice",
|
|
"Purchase Invoice",
|
|
"Payment Entry",
|
|
"Journal Entry",
|
|
"Stock Entry",
|
|
"Delivery Note",
|
|
"Purchase Receipt",
|
|
"Sales Order",
|
|
"Purchase Order",
|
|
"Quotation",
|
|
"Material Request",
|
|
"Stock Reconciliation",
|
|
]
|
|
|
|
for dt in submitted_doctypes:
|
|
# Get submitted docs for this company
|
|
docs = frappe.db.sql(
|
|
f"SELECT name FROM `tab{dt}` WHERE company=%s AND docstatus=1",
|
|
COMPANY,
|
|
as_dict=1,
|
|
)
|
|
if docs:
|
|
print(f" Cancelling {len(docs)} submitted {dt}(s)...")
|
|
for d in docs:
|
|
try:
|
|
doc = frappe.get_doc(dt, d.name)
|
|
doc.flags.ignore_permissions = True
|
|
doc.flags.ignore_links = True
|
|
doc.cancel()
|
|
frappe.db.commit()
|
|
except Exception as e:
|
|
# Force cancel via direct DB update if normal cancel fails
|
|
frappe.db.sql(
|
|
f"UPDATE `tab{dt}` SET docstatus=2 WHERE name=%s", d.name
|
|
)
|
|
frappe.db.commit()
|
|
|
|
# ── STEP 2: Delete all draft + cancelled docs ─────────────────
|
|
all_doctypes = submitted_doctypes + [
|
|
"Landed Cost Voucher",
|
|
"Asset",
|
|
"Salary Slip",
|
|
"Timesheet",
|
|
]
|
|
|
|
for dt in all_doctypes:
|
|
try:
|
|
count = frappe.db.count(dt, {"company": COMPANY})
|
|
if count:
|
|
frappe.db.delete(dt, {"company": COMPANY})
|
|
frappe.db.commit()
|
|
print(f" Deleted {count} {dt}(s)")
|
|
except Exception as e:
|
|
print(f" [WARN] Could not delete {dt}: {e}")
|
|
|
|
# ── STEP 3: Delete GL Entries ─────────────────────────────────
|
|
gl_count = frappe.db.count("GL Entry", {"company": COMPANY})
|
|
if gl_count:
|
|
frappe.db.delete("GL Entry", {"company": COMPANY})
|
|
frappe.db.commit()
|
|
print(f" Deleted {gl_count} GL Entries")
|
|
|
|
# ── STEP 4: Delete Stock Ledger Entries ───────────────────────
|
|
sle_count = frappe.db.count("Stock Ledger Entry", {"company": COMPANY})
|
|
if sle_count:
|
|
frappe.db.delete("Stock Ledger Entry", {"company": COMPANY})
|
|
frappe.db.commit()
|
|
print(f" Deleted {sle_count} Stock Ledger Entries")
|
|
|
|
# ── STEP 5: Delete child tables that reference the company ────
|
|
child_cleanups = [
|
|
("Sales Invoice Item", "company"),
|
|
("Purchase Invoice Item", "company"),
|
|
("Payment Entry Reference", None), # handled via parent delete
|
|
]
|
|
|
|
# ── STEP 6: Delete Warehouses ─────────────────────────────────
|
|
# Disable stock bins first
|
|
wh_list = frappe.db.sql(
|
|
"SELECT name FROM `tabWarehouse` WHERE company=%s", COMPANY, as_dict=1
|
|
)
|
|
if wh_list:
|
|
for wh in wh_list:
|
|
frappe.db.delete("Bin", {"warehouse": wh.name})
|
|
frappe.db.commit()
|
|
|
|
for wh in wh_list:
|
|
try:
|
|
frappe.delete_doc(
|
|
"Warehouse",
|
|
wh.name,
|
|
ignore_permissions=True,
|
|
force=True,
|
|
ignore_on_trash=True,
|
|
)
|
|
except Exception as e:
|
|
frappe.db.sql("DELETE FROM `tabWarehouse` WHERE name=%s", wh.name)
|
|
frappe.db.commit()
|
|
print(f" Deleted {len(wh_list)} Warehouse(s)")
|
|
|
|
# ── STEP 7: Delete Cost Centers ───────────────────────────────
|
|
cc_list = frappe.db.sql(
|
|
"SELECT name FROM `tabCost Center` WHERE company=%s ORDER BY lft DESC",
|
|
COMPANY,
|
|
as_dict=1,
|
|
)
|
|
if cc_list:
|
|
for cc in cc_list:
|
|
try:
|
|
frappe.db.sql("DELETE FROM `tabCost Center` WHERE name=%s", cc.name)
|
|
except Exception:
|
|
pass
|
|
frappe.db.commit()
|
|
print(f" Deleted {len(cc_list)} Cost Center(s)")
|
|
|
|
# ── STEP 8: Delete Accounts ───────────────────────────────────
|
|
acct_count = frappe.db.count("Account", {"company": COMPANY})
|
|
if acct_count:
|
|
# Delete leaf accounts first (is_group=0), then groups
|
|
frappe.db.sql(
|
|
"DELETE FROM `tabAccount` WHERE company=%s AND is_group=0", COMPANY
|
|
)
|
|
frappe.db.sql("DELETE FROM `tabAccount` WHERE company=%s", COMPANY)
|
|
frappe.db.commit()
|
|
print(f" Deleted {acct_count} Account(s)")
|
|
|
|
# ── STEP 9: Delete Fiscal Years linked only to this company ───
|
|
fy_links = frappe.db.sql(
|
|
"""SELECT parent FROM `tabFiscal Year Company`
|
|
WHERE company=%s""",
|
|
COMPANY,
|
|
as_dict=1,
|
|
)
|
|
for fy in fy_links:
|
|
frappe.db.sql(
|
|
"DELETE FROM `tabFiscal Year Company` WHERE company=%s AND parent=%s",
|
|
(COMPANY, fy.parent),
|
|
)
|
|
# If this fiscal year has no other company links, delete it too
|
|
remaining = frappe.db.count("Fiscal Year Company", {"parent": fy.parent})
|
|
if remaining == 0:
|
|
try:
|
|
frappe.db.delete("Fiscal Year", {"name": fy.parent})
|
|
except Exception:
|
|
pass
|
|
frappe.db.commit()
|
|
|
|
# ── STEP 10: Nuke Customers/Suppliers that belong only to ─────
|
|
# streetwok (no transactions in Furnitex)
|
|
# Only delete if they have no Furnitex transactions
|
|
stale_customers = frappe.db.sql(
|
|
"""SELECT c.name FROM `tabCustomer` c
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM `tabSales Invoice`
|
|
WHERE customer=c.name AND company='Furnitex' AND docstatus < 2
|
|
)
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM `tabSales Order`
|
|
WHERE customer=c.name AND company='Furnitex' AND docstatus < 2
|
|
)""",
|
|
as_dict=1,
|
|
)
|
|
if stale_customers:
|
|
for c in stale_customers:
|
|
try:
|
|
frappe.db.delete("Customer", {"name": c.name})
|
|
except Exception:
|
|
pass
|
|
frappe.db.commit()
|
|
print(f" Deleted {len(stale_customers)} orphan Customer(s)")
|
|
|
|
# ── STEP 11: Delete the Company record itself ─────────────────
|
|
try:
|
|
frappe.delete_doc(
|
|
"Company",
|
|
COMPANY,
|
|
ignore_permissions=True,
|
|
force=True,
|
|
ignore_on_trash=True,
|
|
)
|
|
except Exception:
|
|
frappe.db.sql("DELETE FROM `tabCompany` WHERE name=%s", COMPANY)
|
|
frappe.db.commit()
|
|
print(f"\n Company '{COMPANY}' deleted.")
|
|
|
|
# ── STEP 12: Update Default Company if it was streetwok ───────
|
|
default_co = frappe.db.get_default("company")
|
|
if default_co and "streetwok" in default_co.lower():
|
|
frappe.db.set_default("company", "Furnitex")
|
|
frappe.db.commit()
|
|
print(" Default company reset to: Furnitex")
|
|
|
|
# ── STEP 13: Nuke any leftover streetwok items ────────────────
|
|
stale_items = frappe.db.sql(
|
|
"""SELECT name FROM `tabItem`
|
|
WHERE item_name LIKE '%streetwok%'
|
|
OR item_code LIKE '%streetwok%'
|
|
OR description LIKE '%streetwok%'""",
|
|
as_dict=1,
|
|
)
|
|
if stale_items:
|
|
for item in stale_items:
|
|
try:
|
|
frappe.db.delete("Item", {"name": item.name})
|
|
except Exception:
|
|
pass
|
|
frappe.db.commit()
|
|
print(f" Deleted {len(stale_items)} streetwok-tagged Item(s)")
|
|
|
|
frappe.clear_cache()
|
|
|
|
print(f"\n{'='*54}")
|
|
print(" DONE — streetwok removed. Refresh your browser.")
|
|
print(f"{'='*54}\n")
|