515 lines
No EOL
38 KiB
JSON
515 lines
No EOL
38 KiB
JSON
[
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 1,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2024-12-11 10:38:15.324777",
|
|
"module": null,
|
|
"name": "Auto-Populating Assigned Addresses",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Pre-Built Routes",
|
|
"script": "# Ensure Area/Zone is selected\r\nif not doc.areazone:\r\n frappe.throw(\"Please select an Area/Zone before saving the route.\")\r\n\r\n# Fetch addresses linked to the selected Area/Zone\r\naddresses = frappe.get_all(\r\n \"Address\", \r\n filters={\"area_zone\": doc.areazone},\r\n fields=[\"name\", \"address_line1\", \"city\"]\r\n)\r\n\r\n# Get existing assigned addresses across all routes to avoid duplicates\r\nexisting_addresses = frappe.get_all(\r\n \"Assigned Addresses\",\r\n fields=[\"address\"],\r\n distinct=True\r\n)\r\nexisting_address_names = [entry[\"address\"] for entry in existing_addresses]\r\n\r\n# Clear the current child table to avoid duplication on re-save\r\ndoc.assigned_addresses = []\r\n\r\n# Populate the child table\r\nfor address in addresses:\r\n if address[\"name\"] not in existing_address_names:\r\n doc.append(\"assigned_addresses\", {\r\n \"address\": address[\"name\"],\r\n \"address_line1\": address[\"address_line1\"],\r\n \"city\": address[\"city\"]\r\n })\r\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2024-12-11 12:59:24.278281",
|
|
"module": null,
|
|
"name": "Connecting Addresses To Route Numbers",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Pre-Built Routes",
|
|
"script": "# Iterate over Assigned Addresses in the Pre-Built Route\r\nfor assigned in doc.assigned_addresses:\r\n # Ensure the address_name field is not empty\r\n if not assigned.address_name:\r\n frappe.throw(f\"Address is missing for an entry in the Assigned Addresses table.\")\r\n \r\n # Fetch the corresponding Address record using address_name\r\n address = frappe.get_doc(\"Address\", assigned.address_name)\r\n \r\n # Update the Service Route (Route Number) in Address\r\n address.custom_service_route = doc.name # Use `doc.name` for the final Route Number\r\n\r\n # Sync the Confirmation Status from Assigned Address to Address\r\n address.custom_confirmation_status = assigned.status\r\n\r\n \r\n\r\n # Save the updated Address record\r\n address.save(ignore_permissions=True)\r\n \r\n # Update the Assigned Address child table with the latest Confirmation Status\r\n assigned.status = address.custom_confirmation_status\r\n\r\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2024-12-12 13:57:00.619063",
|
|
"module": "Programming Module",
|
|
"name": "dig ticket dates",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Locate Log",
|
|
"script": "\r\n\r\n\r\n# Helper function to calculate the legal start date (2 business days after the locate date)\r\ndef calculate_legal_start_date(locate_date):\r\n # Add 2 business days to the locate date (exclude weekends)\r\n current_date = getdate(locate_date)\r\n while True:\r\n current_date = add_days(current_date, 1)\r\n if current_date.weekday() < 5: # Weekdays are 0-4 (Monday to Friday)\r\n if current_date.weekday() == 4: # If it's Friday, skip to Monday\r\n current_date = add_days(current_date, 2)\r\n break\r\n return current_date\r\n\r\n# Helper function to calculate the expiration date based on the state\r\ndef calculate_expiration_date(state, locate_date):\r\n expiration_days = 45 if state == 'Washington' else 28\r\n expiration_date = add_days(locate_date, expiration_days)\r\n return expiration_date\r\n \r\n \r\n\r\n # Calculate the legal start date and expiration date\r\n legal_start_date = calculate_legal_start_date(locate_date)\r\n expiration_date = calculate_expiration_date(state, locate_date)\r\n\r\n ",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 1,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2024-12-18 11:41:19.792616",
|
|
"module": "ERPNext Integrations",
|
|
"name": "Automate Job queue creation",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Sales Order",
|
|
"script": "# Trigger: Before Save\r\nif doc.company == \"Lowe Fencing\":\r\n # Check if a Fencing Job Queue entry already exists for this Sales Order\r\n existing_job = frappe.db.exists(\"Fencing Job Queue\", {\"sales_order\": doc.name})\r\n \r\n if not existing_job:\r\n # Create a new Fencing Job Queue entry\r\n new_job = frappe.get_doc({\r\n \"doctype\": \"Fencing Job Queue\",\r\n \"sales_order\": doc.name,\r\n \"customer\": doc.customer,\r\n \"job_description\": doc.get(\"job_description\", \"No description provided\"), # Modify if necessary\r\n \"status\": \"Pending\"\r\n })\r\n new_job.insert()\r\n frappe.msgprint(f\"Fencing Job Queue entry created for Sales Order {doc.name}.\")\r\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-02-04 03:26:51.295414",
|
|
"module": null,
|
|
"name": "QB Export Generate Entries",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "QB Export",
|
|
"script": "\naccounts = frappe.db.get_list('GL Entry',\n fields=[\n 'account',\n 'sum(debit) as debits',\n 'sum(credit) as credits'\n ],\n group_by='account',\n filters={\n 'company': doc.company,\n 'posting_date': ['between', [doc.start_date, doc.end_date]]\n }\n)\n\nfor account in accounts:\n doc.append('entries', dict(\n doctype = \"QB Export Entry\",\n account = account.account,\n debits = account.debits,\n credits = account.credits\n ))\n \ndoc.save()",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-03-05 06:21:11.448124",
|
|
"module": null,
|
|
"name": "Prevent duplicate customer",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Customer",
|
|
"script": "if frappe.db.exists(\"Customer\", {\"customer_name\": doc.customer_name}):\r\n frappe.throw(f\"Customer with the name '{doc.customer_name}' already exists\")\r\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": "create_deposit",
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-02-26 10:50:57.293076",
|
|
"module": "Accounts",
|
|
"name": "API - Create Deposit",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": null,
|
|
"script": "bank_account_name = frappe.form_dict.bank\ncompany = frappe.form_dict.company\ndate = frappe.form_dict.date\nreference = frappe.form_dict.ref\npayment_entry_names = frappe.form_dict.payment_entries.split(',') if frappe.form_dict.payment_entries is not None else []\npayment_entries = [frappe.get_doc('Payment Entry', name) for name in payment_entry_names]\n\namount = sum([pe.paid_amount for pe in payment_entries])\n\naccounts = frappe.db.get_list(\"Account\", filters={ 'company': company }, fields=['name'])\nundeposited_funds_accounts = [a.name for a in accounts if a.name.startswith('Undeposited Funds -')]\nif len(undeposited_funds_accounts) == 0:\n raise frappe.throw(f\"No Undeposited Funds account for {company}\")\n\nbank_account = frappe.get_doc(\"Bank Account\", bank_account_name)\nif not bank_account or not bank_account.account_name:\n raise frappe.throw(f\"Can't find bank account {bank_account_name}\")\n\nif not bank_account.is_company_account:\n raise frappe.throw(f\"Bank account {bank_account_name} is not a company account\")\n \nif bank_account.company != company:\n raise frappe.throw(f\"Bank account {bank_account_name} company is not {company}\")\n\ntransfer_entry = frappe.get_doc(dict(\n\tdoctype = 'Journal Entry',\n\tvoucher_type = \"Journal Entry\",\n\tcompany = company,\n\tposting_date = date,\n\tcheque_no=reference\n))\ntransfer_entry.append(\"accounts\", dict(\n doctype = \"Journal Entry Account\",\n\taccount = bank_account.account,\n\tdebit_in_account_currency = amount\n))\ntransfer_entry.append(\"accounts\", dict(\n doctype = \"Journal Entry Account\",\n\taccount = undeposited_funds_accounts[0],\n\tcredit_in_account_currency = amount\n))\ntransfer_entry.insert()\n#transfer_entry.submit()\n\n# TODO: for credit card payments, make an additional journal entry to transfer into the fee accounts, based on the fees in the payment entry\n\ntransaction = frappe.get_doc(dict(\n doctype='Bank Transaction',\n date=date,\n status='Pending',\n bank_account=bank_account_name,\n company=company,\n deposit=amount,\n custom_journal_entry=transfer_entry.name,\n reference_number=reference,\n currency=bank_account.currency\n))\nfor pe in payment_entries:\n transaction.append('payment_entries', dict(\n payment_document='Payment Entry',\n payment_entry=pe.name,\n allocated_amount=pe.paid_amount\n ))\ntransaction.insert()\n#transaction.submit()\n\nfrappe.response['message'] = 'Created Bank Transaction & Journal Entry'",
|
|
"script_type": "API"
|
|
},
|
|
{
|
|
"allow_guest": 1,
|
|
"api_method": "quote-action",
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-10 02:56:30.607706",
|
|
"module": null,
|
|
"name": "Quote action from email",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": null,
|
|
"script": "quote = frappe.get_doc(\"Quotation\", frappe.request.args.get('name'))\nif quote.status == 'Open' and frappe.request.args.get('response') is not None:\n quote.flags.ignore_permissions = True\n quote.custom_response = frappe.request.args.get('response')\n quote.save()\n frappe.db.commit()\n frappe.response['success'] = True\nelse:\n raise frappe.ValidationError",
|
|
"script_type": "API"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-08 12:30:28.500389",
|
|
"module": null,
|
|
"name": "Distribute Foreman Time",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Timesheet",
|
|
"script": "for entry in doc.time_logs:\n # We only want to copy today's entries\n if str(frappe.utils.now()).split(' ')[0] != str(entry.from_time).split(' ')[0]:\n continue\n \n if entry.hours is not None and entry.hours > 0 and entry.project is not None:\n employee = frappe.get_doc(\"Employee\", doc.employee)\n if employee.custom_crew is not None and (employee.designation == \"Foreman\" or employee.designation == \"Field Manager\"): # Is crew lead and foreman the same?\n crew_members = frappe.db.get_list(\"Employee\", filters={ 'custom_crew': employee.custom_crew })\n for member in crew_members:\n if member.name == doc.employee:\n continue\n \n new_entry = entry.as_dict()\n del new_entry['name']\n \n # Find or create timesheet to add to\n timesheet_to_add_to = None\n existing_timesheets = frappe.db.get_list(\"Timesheet\", filters={ 'employee': member.name, 'status': 'Draft' }, fields=['name'])\n if len(existing_timesheets) > 0:\n existing = frappe.get_doc(\"Timesheet\", existing_timesheets[0].name)\n \n # If there is already a matching entry (matching on start time), remove it so that we can insert fresh\n for sub_entry in existing.time_logs:\n if str(sub_entry.from_time) == str(entry.from_time):\n existing.remove(sub_entry)\n break\n \n existing.append('time_logs', new_entry)\n existing.save()\n else:\n new_timesheet = frappe.get_doc({\n 'doctype': 'Timesheet',\n 'employee': member.name\n })\n new_timesheet.append('time_logs', new_entry)\n new_timesheet.insert()",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": "snw-foreman-clock-in-out",
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-10 06:45:34.404563",
|
|
"module": "HR",
|
|
"name": "SNW Foreman - Clock In/Out",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": null,
|
|
"script": "employees = frappe.db.get_list(\"Employee\", filters={ 'user_id': frappe.session.user }, fields=['name'])\nif len(employees) == 0:\n frappe.throw(f\"Could not find employee for current user: {frappe.session.user}\")\n\ntimesheets = frappe.db.get_list(\"Timesheet\", filters={ 'employee': employees[0].name, 'status': 'Draft' }, fields=['name'])\n\ntimesheet = None\nis_new = False\nif len(timesheets) > 0:\n timesheet = frappe.get_doc('Timesheet', timesheets[0])\nelse:\n timesheet = frappe.get_doc({\n 'doctype': 'Timesheet',\n 'employee': employees[0].name\n })\n is_new = True\n\nexisting_entry = None\nfor entry in timesheet.time_logs:\n if entry.from_time is not None and entry.to_time is None:\n existing_entry = entry\n break\n \nif frappe.request.method == \"GET\":\n if existing_entry is None:\n frappe.response['running'] = None\n elif existing_entry.project is None:\n frappe.response['running'] = 'driving'\n else:\n frappe.response['running'] = existing_entry.task\n jobs = frappe.db.get_list('Task', filters={ 'custom_foreman': employees[0].name }, order_by='exp_start_date', fields=['name', 'project', 'exp_start_date', 'exp_end_date'])\n for job in jobs:\n job['installation_address'] = frappe.get_doc('Project', job.project).custom_installation_address\n frappe.response['jobs'] = jobs\nelif frappe.request.method == \"POST\":\n frappe.response['running'] = None\n if existing_entry is not None:\n existing_entry.to_time = frappe.utils.now()\n \n if existing_entry is None or existing_entry.project != frappe.form_dict.project:\n timesheet.append('time_logs', {\n 'doctype': 'Timesheet Detail',\n 'from_time': frappe.utils.now(),\n 'activity_type': 'Driving' if frappe.form_dict.project is None else 'Landscaping',\n 'project': frappe.form_dict.project,\n 'task': frappe.form_dict.task,\n })\n frappe.response['running'] = 'driving' if frappe.form_dict.task is None else frappe.form_dict.task\n \n if is_new:\n timesheet.insert()\n else:\n timesheet.save()",
|
|
"script_type": "API"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": "schedule_job",
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-14 10:02:59.043326",
|
|
"module": "Projects",
|
|
"name": "Schedule Project",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": null,
|
|
"script": "task = frappe.get_doc('Task', frappe.form_dict.task)\nif frappe.form_dict.foreman == 'unassigned':\n task.custom_foreman = None\nelse:\n task.custom_foreman = frappe.form_dict.foreman\n\nif frappe.form_dict.type == \"move\": # Reschedule task\n diff = 0 # By default, everything will take one day\n if task.exp_start_date is not None and task.exp_end_date is not None:\n diff = frappe.utils.date_diff(task.exp_end_date, task.exp_start_date)\n task.exp_start_date = frappe.form_dict.date\n task.exp_end_date = frappe.utils.add_to_date(frappe.form_dict.date, days=diff)\nelif frappe.form_dict.type == \"resize\": # Change task duration\n if frappe.utils.date_diff(frappe.form_dict.date, task.exp_start_date) >= 0:\n task.exp_end_date = frappe.form_dict.date\n else: # If they try to move the end date before the start date, just set the end date to the start date\n task.exp_end_date = task.exp_start_date\ntask.save()\n ",
|
|
"script_type": "API"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-04-18 10:37:51.312654",
|
|
"module": null,
|
|
"name": "Change sale order status to \"To Bill\" when project completed",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Project",
|
|
"script": "if doc.status == \"Completed\":\n sales_orders = frappe.db.get_list(\"Sales Order\", filters={ 'project': doc.name }, fields=['name'])\n if len(sales_orders) > 0:\n sale_order = frappe.get_doc(\"Sales Order\", sales_orders[0].name)\n sale_order.custom_project_complete = True\n sale_order.save()\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-07 09:23:35.688555",
|
|
"module": null,
|
|
"name": "Create or link customer to address",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Address",
|
|
"script": "# If there is already a customer linked, update the customer & contact to match the details\n# provided on the contact, if needed\n# This allows the front-office to update all the records using the address only\n# If the address is missing any info that the customer has, pull it onto the address\n# If this customer is referenced on another address, that address will also be updated\n# due to the other server script on Customer that updates all linked addresses\nif doc.custom_customer_to_bill is not None and doc.custom_customer_to_bill != '':\n customer = frappe.get_doc('Customer', doc.custom_customer_to_bill)\n \n if customer.customer_type == \"Individual\":\n address_changed = False\n customer_changed = False\n\n # Customer email_id and mobile_no will be updated automatically by updating the contact\n if customer.customer_primary_contact is not None:\n contact_changed = False\n contact = frappe.get_doc('Contact', customer.customer_primary_contact)\n \n if doc.custom_contact_name is not None and doc.custom_contact_name != '':\n name_parts = doc.custom_contact_name.split(' ')\n first_name = name_parts[0]\n last_name = ' '.join(name_parts[1:]) if len(name_parts) > 1 else None\n if contact.first_name != first_name or contact.last_name != last_name:\n contact.first_name = first_name\n contact.last_name = last_name\n contact_changed = True\n \n if contact.email_id != doc.email_id:\n if doc.email_id is not None and doc.email_id != '':\n for email in contact.email_ids:\n if email.is_primary:\n email.email_id = doc.email_id\n contact_changed = True\n customer_changed = True\n else:\n doc.email_id = contact.email_id\n address_changed = True\n \n if contact.mobile_no != doc.phone:\n if doc.phone is not None and doc.phone != '':\n for phone in contact.phone_nos:\n if phone.is_primary_mobile_no:\n phone.phone = doc.phone\n contact_changed = True\n customer.mobile_no = doc.phone\n customer_changed = True\n else:\n doc.phone = contact.mobile_no\n address_changed = True\n \n if contact_changed:\n contact.save()\n frappe.msgprint(\"Updated contact\")\n \n if customer.customer_name != doc.custom_contact_name:\n if doc.custom_contact_name is not None and doc.custom_contact_name != '':\n customer.customer_name = doc.custom_contact_name\n customer.save()\n frappe.rename_doc('Customer', customer.name, doc.custom_contact_name)\n frappe.msgprint(\"Updated customer\")\n elif customer.customer_name is not None and customer.customer_name != '':\n doc.custom_contact_name = customer.customer_name\n address_changed = True\n elif customer_changed:\n customer.save()\n frappe.msgprint(\"Updated customer\")\n \n if address_changed:\n doc.save()\n frappe.msgprint(\"Pulled details from customer\")\n\nelse:\n if (doc.custom_contact_name is not None and doc.custom_contact_name != '') and (doc.email_id is None or doc.email_id == ''):\n raise frappe.throw(\"If you enter a Contact Name, you must also enter an Email Address\")\n \n # If there is not already a customer linked, try to find one to link\n if doc.email_id is not None and doc.email_id != '':\n potential_customers = frappe.db.get_list('Customer', filters={ 'email_id': doc.email_id }, fields=['name', 'email_id', 'customer_primary_contact'])\n if len(potential_customers) > 0:\n doc.custom_customer_to_bill = potential_customers[0].name;\n doc.save()\n # phone and name will be pulled from customer/contact in next pass\n else:\n # Ok, we'll create a new customer since we couldn't find one\n # See if we can use an existing contact, or if we should create a new contact as well\n potential_contacts = frappe.get_all('Contact Email', filters={'email_id': doc.email_id}, fields=['parent'])\n contact = None\n if len(potential_contacts) > 0:\n contact = frappe.get_doc('Contact', potential_contacts[0].parent)\n \n new_customer = frappe.get_doc({\n 'doctype': 'Customer',\n 'customer_name': doc.custom_contact_name if doc.custom_contact_name is not None else doc.address_title,\n # Customer should auto-create it's primary contact, if we don't link an existing one\n 'customer_primary_contact': contact.name if contact is not None else None,\n 'customer_type': 'Individual',\n 'customer_primary_address': doc.name,\n 'email_id': doc.email_id,\n 'mobile_no': doc.phone\n })\n new_customer.insert()\n \n doc.custom_customer_to_bill = new_customer.name\n doc.save()",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Submit",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-04-25 03:36:27.460012",
|
|
"module": null,
|
|
"name": "Sales Order Status Linked to Payment Entry",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Payment Entry",
|
|
"script": "# Check if this is a Customer payment against a Sales Order\r\nif doc.party_type == \"Customer\" and doc.references:\r\n for ref in doc.references:\r\n if ref.reference_doctype == \"Sales Order\" and ref.reference_name:\r\n sales_order = frappe.get_doc(\"Sales Order\", ref.reference_name)\r\n\r\n # Only act if Sales Order is currently On Hold and requires half-down\r\n if sales_order.status == \"On Hold\" and sales_order.custom_requires_halfdown:\r\n sales_order.db_set(\"status\", \"To Deliver\")\r\n \r\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Submit",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-04-25 03:41:36.948328",
|
|
"module": null,
|
|
"name": "Sales Order Half Down Required Script",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Sales Order",
|
|
"script": "# Set to On Hold if requires_half_down is checked\r\nif doc.custom_requires_halfdown:\r\n doc.status = \"On Hold\"\r\n frappe.db.set_value(\"Sales Order\", doc.name, \"status\", \"On Hold\")\r\n \r\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-02 10:44:23.201852",
|
|
"module": null,
|
|
"name": "Project Creation from Sales Order",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Project",
|
|
"script": "if doc.sales_order:\r\n sales_order = frappe.get_doc(\"Sales Order\", doc.sales_order)\r\n if sales_order.get(\"custom_installation_address\"):\r\n doc.custom_installation_address = sales_order.custom_installation_address\r\n doc.project_name = sales_order.custom_installation_address\r\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-02 10:45:31.652205",
|
|
"module": null,
|
|
"name": "Sales Order Installation Address from Quotation",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Sales Order",
|
|
"script": "if doc.quotation:\r\n quotation = frappe.get_doc(\"Quotation\", doc.quotation)\r\n if quotation.get(\"custom_installation_address\"):\r\n doc.custom_installation_address = quotation.custom_installation_address\r\n",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-07 09:03:15.200325",
|
|
"module": null,
|
|
"name": "Update address contact info",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Customer",
|
|
"script": "if doc.customer_type == \"Individual\":\n addresses = frappe.db.get_list('Address', filters={ 'custom_customer_to_bill': doc.name }, fields=['name'])\n for address_item in addresses:\n address = frappe.get_doc('Address', address_item.name)\n address_changed = False\n if address.custom_contact_name != doc.customer_name:\n address.custom_contact_name = doc.customer_name\n address_changed = True\n \n if address.phone != doc.mobile_no:\n address.phone = doc.mobile_no\n address_changed = True\n \n if address.email_id != doc.email_id:\n address.email_id = doc.email_id\n address_changed = True\n \n if address_changed:\n address.save()",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-30 09:25:42.446239",
|
|
"module": null,
|
|
"name": "Quotation - mark as sent",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Email Queue",
|
|
"script": "if doc.status == \"Sent\" and doc.communication is not None:\n comm = frappe.get_doc(\"Communication\", doc.communication)\n if comm.reference_doctype == \"Quotation\":\n quote = frappe.get_doc(\"Quotation\", comm.reference_name)\n quote.custom_sent = True\n quote.save()",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-10 05:08:17.832989",
|
|
"module": null,
|
|
"name": "Unset task expected dates",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Task",
|
|
"script": "doc.exp_start_date = None\ndoc.exp_end_date = None",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "After Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-15 04:08:51.615310",
|
|
"module": null,
|
|
"name": "Create project close-out tasks when work is complete",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Task",
|
|
"script": "if doc.type == 'Labor' and (doc.status == 'Completed' or doc.status == 'Cancelled'):\n pending_labor_tasks_count = frappe.db.count('Task', { 'project': doc.project, 'type': 'Labor', 'status': ['not in', ['Completed', 'Cancelled']] })\n if pending_labor_tasks_count == 0:\n # If all labor tasks are complete, add the QA and permit close out tasks to the project\n qa_task_template = frappe.get_doc('Task', 'TASK-2025-00007')\n permit_close_task_template = frappe.get_doc('Task', 'TASK-2025-00008')\n \n qa_task_template.name = None\n permit_close_task_template.name = None\n \n qa_task_template.is_template = False\n permit_close_task_template.is_template = False\n \n qa_task_template.project = doc.project\n permit_close_task_template.project = doc.project\n \n qa_task_template.status = \"Open\"\n permit_close_task_template.status = \"Open\"\n \n qa_task_template.insert()\n permit_close_task_template.insert()",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-15 08:30:36.340161",
|
|
"module": null,
|
|
"name": "Lock - New Invoice",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Sales Invoice",
|
|
"script": "current_month = '-'.join(frappe.utils.today().split('-')[:2])\npost_month = '-'.join(doc.posting_date.split('-')[:2])\nif current_month != post_month:\n frappe.throw(\"Cannot post an invoice to a previous month\")",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Cancel",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-15 08:32:11.919798",
|
|
"module": null,
|
|
"name": "Lock - Cancel Invoice",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Sales Invoice",
|
|
"script": "current_month = '-'.join(frappe.utils.today().split('-')[:2])\npost_month = '-'.join(str(doc.posting_date).split('-')[:2])\nif current_month != post_month:\n frappe.throw(\"Cannot cancel an invoice in a previous month\")",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-15 08:44:01.489721",
|
|
"module": null,
|
|
"name": "Lock past month GL Entries",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "GL Entry",
|
|
"script": "current_month = '-'.join(frappe.utils.today().split('-')[:2])\npost_month = '-'.join(doc.posting_date.split('-')[:2])\nif current_month != post_month:\n frappe.throw(\"Cannot modify accounting entries in a previous month\")",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-05-15 12:21:02.649125",
|
|
"module": null,
|
|
"name": "Add coordinates to address",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Address",
|
|
"script": "\nif doc.address_line1 is not None and doc.city is not None and doc.country is not None:\n \n address_components = [\n doc.address_line1,\n doc.address_line2 or '',\n doc.city,\n doc.state or '',\n doc.pincode or '',\n doc.country\n ]\n \n custom_address_for_coordinates = ', '.join([cmp for cmp in address_components if cmp != ''])\n \n # Store custom_address_for_coordinates on doc so that we only re-compute the coordinates if the address changes\n if custom_address_for_coordinates != doc.custom_address_for_coordinates:\n\n api_key = 'AIzaSyCd3ALZe6wjt3xnc7X_rRItfKAEJugfuZ4';\n safe_chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~\"\n encoded_address = ''\n for c in custom_address_for_coordinates:\n if c in safe_chars:\n encoded_address = encoded_address + c\n else:\n encoded_address = encoded_address + '%%%02X' % ord(c)\n geocode_url = f\"https://maps.googleapis.com/maps/api/geocode/json?address={encoded_address}&key={api_key}\"\n \n data = frappe.make_get_request(geocode_url)\n if data['status'] == 'OK' and data['results'][0] is not None:\n location = data['results'][0]['geometry']['location']\n doc.custom_latitude = location['lat']\n doc.custom_longitude = location['lng']\n address_components = data['results'][0]['address_components'];\n for comp in address_components:\n if 'postal_code' in comp['types']:\n doc.pincode = comp['long_name']\n break\n \n doc.custom_address_for_coordinates = custom_address_for_coordinates",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": null,
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Save",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "All",
|
|
"modified": "2025-08-29 17:23:47.107509",
|
|
"module": null,
|
|
"name": "Populate Completed Date",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": "Project",
|
|
"script": "if \"Completed\" in doc.status and doc.custom_completion_date == None:\n doc.custom_completion_date = frappe.utils.today()\n if \"SNW Install\" in doc.project_template and doc.custom_warranty_expiration_date == None:\n doc.custom_warranty_expiration_date = frappe.utils.add_to_date(frappe.utils.today(), days=doc.custom_warranty_duration_days)",
|
|
"script_type": "DocType Event"
|
|
},
|
|
{
|
|
"allow_guest": 0,
|
|
"api_method": "test-followup",
|
|
"cron_format": null,
|
|
"disabled": 0,
|
|
"docstatus": 0,
|
|
"doctype": "Server Script",
|
|
"doctype_event": "Before Insert",
|
|
"enable_rate_limit": 0,
|
|
"event_frequency": "Daily",
|
|
"modified": "2025-04-18 06:47:24.351220",
|
|
"module": null,
|
|
"name": "Quotation - set follow-up needed",
|
|
"rate_limit_count": 5,
|
|
"rate_limit_seconds": 86400,
|
|
"reference_doctype": null,
|
|
"script": "quotes = frappe.db.get_list('Quotation', filters={ 'status': 'Open' }, fields=['name'])\n\nfor quote in quotes:\n communications = frappe.db.get_list(\n \"Communication\",\n filters={\n \"reference_doctype\": \"Quotation\",\n \"reference_name\": quote.name\n },\n fields=[\"communication_date\"]\n )\n if len(communications) > 0:\n latest_date = communications[0].communication_date\n for com in communications:\n if com.communication_date > latest_date:\n latest_date = com.communication_date\n full_quote = frappe.get_doc('Quotation', quote.name)\n full_quote.db_set('custom_followup_needed', frappe.utils.date_diff(frappe.utils.getdate(), latest_date) >= 5)\n frappe.db.commit()",
|
|
"script_type": "Scheduler Event"
|
|
}
|
|
] |