brotherton-erpnext/erpnext/setup/demo.py

211 lines
6.2 KiB
Python
Raw Normal View History

2023-06-14 07:24:10 +00:00
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import json
import os
2023-06-19 04:14:57 +00:00
from random import randint
2023-06-14 07:24:10 +00:00
import frappe
from frappe import _
2023-07-29 17:09:07 +00:00
from frappe.utils import add_days, getdate
2023-06-14 07:24:10 +00:00
2023-08-10 16:16:34 +00:00
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
2023-07-29 17:09:07 +00:00
from erpnext.accounts.utils import get_fiscal_year
2023-08-10 16:16:34 +00:00
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_invoice
from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
2023-06-19 08:42:23 +00:00
from erpnext.setup.setup_wizard.operations.install_fixtures import create_bank_account
2023-06-16 08:13:55 +00:00
2023-06-14 07:24:10 +00:00
def setup_demo_data():
from frappe.utils.telemetry import capture
capture("demo_data_creation_started", "erpnext")
try:
company = create_demo_company()
process_masters()
make_transactions(company)
frappe.cache.delete_keys("bootinfo")
frappe.publish_realtime("demo_data_complete")
except Exception:
frappe.log_error("Failed to create demo data")
capture("demo_data_creation_failed", "erpnext", properties={"exception": frappe.get_traceback()})
raise
capture("demo_data_creation_completed", "erpnext")
2023-06-16 08:13:55 +00:00
@frappe.whitelist()
def clear_demo_data():
2023-08-10 12:57:34 +00:00
from frappe.utils.telemetry import capture
frappe.only_for("System Manager")
2023-08-10 12:57:34 +00:00
capture("demo_data_erased", "erpnext")
try:
company = frappe.db.get_single_value("Global Defaults", "demo_company")
create_transaction_deletion_record(company)
clear_masters()
delete_company(company)
default_company = frappe.db.get_single_value("Global Defaults", "default_company")
frappe.db.set_default("company", default_company)
except Exception:
frappe.db.rollback()
frappe.log_error("Failed to erase demo data")
frappe.throw(
_("Failed to erase demo data, please delete the demo company manually."),
title=_("Could Not Delete Demo Data"),
)
2023-06-14 07:24:10 +00:00
def create_demo_company():
company = frappe.db.get_all("Company")[0].name
2023-06-14 07:24:10 +00:00
company_doc = frappe.get_doc("Company", company)
# Make a dummy company
new_company = frappe.new_doc("Company")
new_company.company_name = company_doc.company_name + " (Demo)"
new_company.abbr = company_doc.abbr + "D"
new_company.enable_perpetual_inventory = 1
new_company.default_currency = company_doc.default_currency
new_company.country = company_doc.country
new_company.chart_of_accounts_based_on = "Standard Template"
new_company.chart_of_accounts = company_doc.chart_of_accounts
new_company.insert()
2023-06-17 07:38:18 +00:00
# Set Demo Company as default to
2023-06-19 04:14:57 +00:00
frappe.db.set_single_value("Global Defaults", "demo_company", new_company.name)
frappe.db.set_default("company", new_company.name)
2023-06-19 08:42:23 +00:00
bank_account = create_bank_account({"company_name": new_company.name})
frappe.db.set_value("Company", new_company.name, "default_bank_account", bank_account.name)
2023-06-16 08:13:55 +00:00
return new_company.name
2023-06-14 07:24:10 +00:00
2023-06-16 08:13:55 +00:00
def process_masters():
2023-06-17 07:38:18 +00:00
for doctype in frappe.get_hooks("demo_master_doctypes"):
data = read_data_file_using_hooks(doctype)
if data:
for item in json.loads(data):
create_demo_record(item)
2023-06-14 07:24:10 +00:00
def create_demo_record(doctype):
frappe.get_doc(doctype).insert(ignore_permissions=True)
2023-06-16 08:13:55 +00:00
def make_transactions(company):
2023-06-19 08:42:23 +00:00
frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1)
2023-08-10 16:16:34 +00:00
start_date = get_fiscal_year(date=getdate())[1]
2023-06-19 04:14:57 +00:00
2023-06-17 07:38:18 +00:00
for doctype in frappe.get_hooks("demo_transaction_doctypes"):
data = read_data_file_using_hooks(doctype)
if data:
for item in json.loads(data):
2023-06-19 04:14:57 +00:00
create_transaction(item, company, start_date)
2023-06-16 08:13:55 +00:00
2023-08-10 16:16:34 +00:00
convert_order_to_invoices()
frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 0)
2023-06-16 08:13:55 +00:00
2023-06-19 04:14:57 +00:00
def create_transaction(doctype, company, start_date):
2023-08-10 16:16:34 +00:00
document_type = doctype.get("doctype")
2023-06-19 08:42:23 +00:00
warehouse = get_warehouse(company)
2023-08-10 16:16:34 +00:00
if document_type == "Purchase Order":
posting_date = get_random_date(start_date, 1, 30)
else:
posting_date = get_random_date(start_date, 31, 364)
2023-06-19 08:42:23 +00:00
2023-06-19 04:14:57 +00:00
doctype.update(
{
"company": company,
"set_posting_time": 1,
2023-08-10 16:16:34 +00:00
"transaction_date": posting_date,
"schedule_date": posting_date,
"delivery_date": posting_date,
2023-06-19 08:42:23 +00:00
"set_warehouse": warehouse,
2023-06-19 04:14:57 +00:00
}
)
2023-06-16 08:13:55 +00:00
doc = frappe.get_doc(doctype)
doc.save(ignore_permissions=True)
doc.submit()
2023-08-10 16:16:34 +00:00
def convert_order_to_invoices():
for document in ["Purchase Order", "Sales Order"]:
# Keep some orders intentionally unbilled/unpaid
for i, order in enumerate(
frappe.db.get_all(
document, filters={"docstatus": 1}, fields=["name", "transaction_date"], limit=6
)
):
if document == "Purchase Order":
invoice = make_purchase_invoice(order.name)
elif document == "Sales Order":
invoice = make_sales_invoice(order.name)
2023-08-01 04:40:50 +00:00
2023-08-10 16:16:34 +00:00
invoice.set_posting_time = 1
invoice.posting_date = order.transaction_date
invoice.due_date = order.transaction_date
invoice.update_stock = 1
invoice.submit()
2023-08-01 04:40:50 +00:00
2023-08-10 16:16:34 +00:00
if i % 2 != 0:
payment = get_payment_entry(invoice.doctype, invoice.name)
payment.reference_no = invoice.name
payment.submit()
def get_random_date(start_date, start_range, end_range):
return add_days(start_date, randint(start_range, end_range))
2023-06-19 04:14:57 +00:00
2023-06-16 08:13:55 +00:00
def create_transaction_deletion_record(company):
transaction_deletion_record = frappe.new_doc("Transaction Deletion Record")
transaction_deletion_record.company = company
transaction_deletion_record.save(ignore_permissions=True)
transaction_deletion_record.submit()
2023-06-17 07:38:18 +00:00
def clear_masters():
for doctype in frappe.get_hooks("demo_master_doctypes")[::-1]:
data = read_data_file_using_hooks(doctype)
if data:
for item in json.loads(data):
clear_demo_record(item)
def clear_demo_record(document):
2023-08-10 16:16:34 +00:00
document_type = document.get("doctype")
del document["doctype"]
valid_columns = frappe.get_meta(document_type).get_valid_columns()
filters = document
for key in list(filters):
if key not in valid_columns:
filters.pop(key, None)
doc = frappe.get_doc(document_type, filters)
doc.delete(ignore_permissions=True)
2023-06-17 07:38:18 +00:00
def delete_company(company):
2023-06-19 08:42:23 +00:00
frappe.db.set_single_value("Global Defaults", "demo_company", "")
2023-06-17 07:38:18 +00:00
frappe.delete_doc("Company", company, ignore_permissions=True)
def read_data_file_using_hooks(doctype):
path = os.path.join(os.path.dirname(__file__), "demo_data")
with open(os.path.join(path, doctype + ".json"), "r") as f:
data = f.read()
return data
2023-06-19 08:42:23 +00:00
def get_warehouse(company):
2023-08-10 16:16:34 +00:00
warehouses = frappe.db.get_all("Warehouse", {"company": company, "is_group": 0})
return warehouses[randint(0, 3)].name