# Copyright (c) 2022, JINGROW and Contributors # MIT License. See license.txt import click import jingrow from jingrow.custom.pagetype.custom_field.custom_field import create_custom_fields from crm.fcrm.pagetype.crm_dashboard.crm_dashboard import create_default_manager_dashboard from crm.fcrm.pagetype.crm_products.crm_products import create_product_details_script def before_install(): pass def after_install(force=False): add_default_lead_statuses() add_default_deal_statuses() add_default_communication_statuses() add_default_fields_layout(force) add_property_setter() add_email_template_custom_fields() add_default_industries() add_default_lead_sources() add_default_lost_reasons() add_standard_dropdown_items() add_default_scripts() create_default_manager_dashboard(force) create_assignment_rule_custom_fields() add_assignment_rule_property_setters() jingrow.db.commit() def add_default_lead_statuses(): statuses = { "New": { "color": "gray", "position": 1, }, "Contacted": { "color": "orange", "position": 2, }, "Nurture": { "color": "blue", "position": 3, }, "Qualified": { "color": "green", "position": 4, }, "Unqualified": { "color": "red", "position": 5, }, "Junk": { "color": "purple", "position": 6, }, } for status in statuses: if jingrow.db.exists("CRM Lead Status", status): continue pg = jingrow.new_pg("CRM Lead Status") pg.lead_status = status pg.color = statuses[status]["color"] pg.position = statuses[status]["position"] pg.insert() def add_default_deal_statuses(): statuses = { "Qualification": { "color": "gray", "type": "Open", "probability": 10, "position": 1, }, "Demo/Making": { "color": "orange", "type": "Ongoing", "probability": 25, "position": 2, }, "Proposal/Quotation": { "color": "blue", "type": "Ongoing", "probability": 50, "position": 3, }, "Negotiation": { "color": "yellow", "type": "Ongoing", "probability": 70, "position": 4, }, "Ready to Close": { "color": "purple", "type": "Ongoing", "probability": 90, "position": 5, }, "Won": { "color": "green", "type": "Won", "probability": 100, "position": 6, }, "Lost": { "color": "red", "type": "Lost", "probability": 0, "position": 7, }, } for status in statuses: if jingrow.db.exists("CRM Deal Status", status): continue pg = jingrow.new_pg("CRM Deal Status") pg.deal_status = status pg.color = statuses[status]["color"] pg.type = statuses[status]["type"] pg.probability = statuses[status]["probability"] pg.position = statuses[status]["position"] pg.insert() def add_default_communication_statuses(): statuses = ["Open", "Replied"] for status in statuses: if jingrow.db.exists("CRM Communication Status", status): continue pg = jingrow.new_pg("CRM Communication Status") pg.status = status pg.insert() def add_default_fields_layout(force=False): quick_entry_layouts = { "CRM Lead-Quick Entry": { "pagetype": "CRM Lead", "layout": '[{"name": "person_section", "columns": [{"name": "column_5jrk", "fields": ["salutation", "email"]}, {"name": "column_5CPV", "fields": ["first_name", "mobile_no"]}, {"name": "column_gXOy", "fields": ["last_name", "gender"]}]}, {"name": "organization_section", "columns": [{"name": "column_GHfX", "fields": ["organization", "territory"]}, {"name": "column_hXjS", "fields": ["website", "annual_revenue"]}, {"name": "column_RDNA", "fields": ["no_of_employees", "industry"]}]}, {"name": "lead_section", "columns": [{"name": "column_EO1H", "fields": ["status"]}, {"name": "column_RWBe", "fields": ["lead_owner"]}]}]', }, "CRM Deal-Quick Entry": { "pagetype": "CRM Deal", "layout": '[{"name": "organization_section", "hidden": true, "editable": false, "columns": [{"name": "column_GpMP", "fields": ["organization"]}, {"name": "column_FPTn", "fields": []}]}, {"name": "organization_details_section", "editable": false, "columns": [{"name": "column_S3tQ", "fields": ["organization_name", "territory"]}, {"name": "column_KqV1", "fields": ["website", "annual_revenue"]}, {"name": "column_1r67", "fields": ["no_of_employees", "industry"]}]}, {"name": "contact_section", "hidden": true, "editable": false, "columns": [{"name": "column_CeXr", "fields": ["contact"]}, {"name": "column_yHbk", "fields": []}]}, {"name": "contact_details_section", "editable": false, "columns": [{"name": "column_ZTWr", "fields": ["salutation", "email"]}, {"name": "column_tabr", "fields": ["first_name", "mobile_no"]}, {"name": "column_Qjdx", "fields": ["last_name", "gender"]}]}, {"name": "deal_section", "columns": [{"name": "column_mdps", "fields": ["status"]}, {"name": "column_H40H", "fields": ["deal_owner"]}]}]', }, "Contact-Quick Entry": { "pagetype": "Contact", "layout": '[{"name": "salutation_section", "columns": [{"name": "column_eXks", "fields": ["salutation"]}]}, {"name": "full_name_section", "hideBorder": true, "columns": [{"name": "column_cSxf", "fields": ["first_name"]}, {"name": "column_yBc7", "fields": ["last_name"]}]}, {"name": "email_section", "hideBorder": true, "columns": [{"name": "column_tH3L", "fields": ["email_id"]}]}, {"name": "mobile_gender_section", "hideBorder": true, "columns": [{"name": "column_lrfI", "fields": ["mobile_no"]}, {"name": "column_Tx3n", "fields": ["gender"]}]}, {"name": "organization_section", "hideBorder": true, "columns": [{"name": "column_S0J8", "fields": ["company_name"]}]}, {"name": "designation_section", "hideBorder": true, "columns": [{"name": "column_bsO8", "fields": ["designation"]}]}, {"name": "address_section", "hideBorder": true, "columns": [{"name": "column_W3VY", "fields": ["address"]}]}]', }, "CRM Organization-Quick Entry": { "pagetype": "CRM Organization", "layout": '[{"name": "organization_section", "columns": [{"name": "column_zOuv", "fields": ["organization_name"]}]}, {"name": "website_revenue_section", "hideBorder": true, "columns": [{"name": "column_I5Dy", "fields": ["website"]}, {"name": "column_Rgss", "fields": ["annual_revenue"]}]}, {"name": "territory_section", "hideBorder": true, "columns": [{"name": "column_w6ap", "fields": ["territory"]}]}, {"name": "employee_industry_section", "hideBorder": true, "columns": [{"name": "column_u5tZ", "fields": ["no_of_employees"]}, {"name": "column_FFrT", "fields": ["industry"]}]}, {"name": "address_section", "hideBorder": true, "columns": [{"name": "column_O2dk", "fields": ["address"]}]}]', }, "Address-Quick Entry": { "pagetype": "Address", "layout": '[{"name": "details_section", "columns": [{"name": "column_uSSG", "fields": ["address_title", "address_type", "address_line1", "address_line2", "city", "state", "country", "pincode"]}]}]', }, "CRM Call Log-Quick Entry": { "pagetype": "CRM Call Log", "layout": '[{"name":"details_section","columns":[{"name":"column_uMSG","fields":["type","from","duration"]},{"name":"column_wiZT","fields":["to","status","caller","receiver"]}]}]', }, } sidebar_fields_layouts = { "CRM Lead-Side Panel": { "pagetype": "CRM Lead", "layout": '[{"label": "Details", "name": "details_section", "opened": true, "columns": [{"name": "column_kl92", "fields": ["organization", "website", "territory", "industry", "job_title", "source", "lead_owner"]}]}, {"label": "Person", "name": "person_section", "opened": true, "columns": [{"name": "column_XmW2", "fields": ["salutation", "first_name", "last_name", "email", "mobile_no"]}]}]', }, "CRM Deal-Side Panel": { "pagetype": "CRM Deal", "layout": '[{"label": "Contacts", "name": "contacts_section", "opened": true, "editable": false, "contacts": []}, {"label": "Organization Details", "name": "organization_section", "opened": true, "columns": [{"name": "column_na2Q", "fields": ["organization", "website", "territory", "annual_revenue", "close_date", "probability", "next_step", "deal_owner"]}]}]', }, "Contact-Side Panel": { "pagetype": "Contact", "layout": '[{"label": "Details", "name": "details_section", "opened": true, "columns": [{"name": "column_eIWl", "fields": ["salutation", "first_name", "last_name", "email_id", "mobile_no", "gender", "company_name", "designation", "address"]}]}]', }, "CRM Organization-Side Panel": { "pagetype": "CRM Organization", "layout": '[{"label": "Details", "name": "details_section", "opened": true, "columns": [{"name": "column_IJOV", "fields": ["organization_name", "website", "territory", "industry", "no_of_employees", "address"]}]}]', }, } data_fields_layouts = { "CRM Lead-Data Fields": { "pagetype": "CRM Lead", "layout": '[{"label": "Details", "name": "details_section", "opened": true, "columns": [{"name": "column_ZgLG", "fields": ["organization", "industry", "lead_owner"]}, {"name": "column_TbYq", "fields": ["website", "job_title"]}, {"name": "column_OKSX", "fields": ["territory", "source"]}]}, {"label": "Person", "name": "person_section", "opened": true, "columns": [{"name": "column_6c5g", "fields": ["salutation", "email"]}, {"name": "column_1n7Q", "fields": ["first_name", "mobile_no"]}, {"name": "column_cT6C", "fields": ["last_name"]}]}]', }, "CRM Deal-Data Fields": { "pagetype": "CRM Deal", "layout": '[{"name":"first_tab","sections":[{"label":"Details","name":"details_section","opened":true,"columns":[{"name":"column_z9XL","fields":["organization","annual_revenue","next_step"]},{"name":"column_gM4w","fields":["website","closed_date","deal_owner"]},{"name":"column_gWmE","fields":["territory","probability"]}]},{"label":"Products","name":"section_jHhQ","opened":true,"columns":[{"name":"column_xiNF","fields":["products"]}],"editingLabel":false,"hideLabel":true},{"label":"New Section","name":"section_WNOQ","opened":true,"columns":[{"name":"column_ziBW","fields":["total"]},{"label":"","name":"column_wuwA","fields":["net_total"]}],"hideBorder":true,"hideLabel":true}]}]', }, } for layout in quick_entry_layouts: if jingrow.db.exists("CRM Fields Layout", layout): if force: jingrow.delete_pg("CRM Fields Layout", layout) else: continue pg = jingrow.new_pg("CRM Fields Layout") pg.type = "Quick Entry" pg.dt = quick_entry_layouts[layout]["pagetype"] pg.layout = quick_entry_layouts[layout]["layout"] pg.insert() for layout in sidebar_fields_layouts: if jingrow.db.exists("CRM Fields Layout", layout): if force: jingrow.delete_pg("CRM Fields Layout", layout) else: continue pg = jingrow.new_pg("CRM Fields Layout") pg.type = "Side Panel" pg.dt = sidebar_fields_layouts[layout]["pagetype"] pg.layout = sidebar_fields_layouts[layout]["layout"] pg.insert() for layout in data_fields_layouts: if jingrow.db.exists("CRM Fields Layout", layout): if force: jingrow.delete_pg("CRM Fields Layout", layout) else: continue pg = jingrow.new_pg("CRM Fields Layout") pg.type = "Data Fields" pg.dt = data_fields_layouts[layout]["pagetype"] pg.layout = data_fields_layouts[layout]["layout"] pg.insert() def add_property_setter(): if not jingrow.db.exists("Property Setter", {"name": "Contact-main-search_fields"}): pg = jingrow.new_pg("Property Setter") pg.pagetype_or_field = "PageType" pg.pg_type = "Contact" pg.property = "search_fields" pg.property_type = "Data" pg.value = "email_id" pg.insert() def add_email_template_custom_fields(): if not jingrow.get_meta("Email Template").has_field("enabled"): click.secho("* Installing Custom Fields in Email Template") create_custom_fields( { "Email Template": [ { "default": "0", "fieldname": "enabled", "fieldtype": "Check", "label": "Enabled", "insert_after": "", }, { "fieldname": "reference_pagetype", "fieldtype": "Link", "label": "Pagetype", "options": "PageType", "insert_after": "enabled", }, ] } ) jingrow.clear_cache(pagetype="Email Template") def add_default_industries(): industries = [ "Accounting", "Advertising", "Aerospace", "Agriculture", "Airline", "Apparel & Accessories", "Automotive", "Banking", "Biotechnology", "Broadcasting", "Brokerage", "Chemical", "Computer", "Consulting", "Consumer Products", "Cosmetics", "Defense", "Department Stores", "Education", "Electronics", "Energy", "Entertainment & Leisure, Executive Search", "Financial Services", "Food", "Beverage & Tobacco", "Grocery", "Health Care", "Internet Publishing", "Investment Banking", "Legal", "Manufacturing", "Motion Picture & Video", "Music", "Newspaper Publishers", "Online Auctions", "Pension Funds", "Pharmaceuticals", "Private Equity", "Publishing", "Real Estate", "Retail & Wholesale", "Securities & Commodity Exchanges", "Service", "Soap & Detergent", "Software", "Sports", "Technology", "Telecommunications", "Television", "Transportation", "Venture Capital", ] for industry in industries: if jingrow.db.exists("CRM Industry", industry): continue pg = jingrow.new_pg("CRM Industry") pg.industry = industry pg.insert() def add_default_lead_sources(): lead_sources = [ "Existing Customer", "Reference", "Advertisement", "Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing", "Customer's Vendor", "Campaign", "Walk In", ] for source in lead_sources: if jingrow.db.exists("CRM Lead Source", source): continue pg = jingrow.new_pg("CRM Lead Source") pg.source_name = source pg.insert() def add_default_lost_reasons(): lost_reasons = [ { "reason": "Pricing", "description": "The prospect found the pricing to be too high or not competitive.", }, {"reason": "Competition", "description": "The prospect chose a competitor's product or service."}, { "reason": "Budget Constraints", "description": "The prospect did not have the budget to proceed with the purchase.", }, { "reason": "Missing Features", "description": "The prospect felt that the product or service was missing key features they needed.", }, { "reason": "Long Sales Cycle", "description": "The sales process took too long, leading to loss of interest.", }, { "reason": "No Decision-Maker", "description": "The prospect was not the decision-maker and could not proceed.", }, {"reason": "Unresponsive Prospect", "description": "The prospect did not respond to follow-ups."}, {"reason": "Poor Fit", "description": "The prospect was not a good fit for the product or service."}, {"reason": "Other", "description": ""}, ] for reason in lost_reasons: if jingrow.db.exists("CRM Lost Reason", reason["reason"]): continue pg = jingrow.new_pg("CRM Lost Reason") pg.lost_reason = reason["reason"] pg.description = reason["description"] pg.insert() def add_standard_dropdown_items(): crm_settings = jingrow.get_single("FCRM Settings") # don't add dropdown items if they're already present if crm_settings.dropdown_items: return crm_settings.dropdown_items = [] for item in jingrow.get_hooks("standard_dropdown_items"): crm_settings.append("dropdown_items", item) crm_settings.save() def add_default_scripts(): from crm.fcrm.pagetype.fcrm_settings.fcrm_settings import create_forecasting_script for pagetype in ["CRM Lead", "CRM Deal"]: create_product_details_script(pagetype) create_forecasting_script() def add_assignment_rule_property_setters(): """Add a property setter to the Assignment Rule PageType for assign_condition and unassign_condition.""" default_fields = { "pagetype": "Property Setter", "pagetype_or_field": "PageField", "pg_type": "Assignment Rule", "property_type": "Data", "is_system_generated": 1, } if not jingrow.db.exists("Property Setter", {"name": "Assignment Rule-assign_condition-depends_on"}): jingrow.get_pg( { **default_fields, "name": "Assignment Rule-assign_condition-depends_on", "field_name": "assign_condition", "property": "depends_on", "value": "eval: !pg.assign_condition_json", } ).insert() else: jingrow.db.set_value( "Property Setter", {"name": "Assignment Rule-assign_condition-depends_on"}, "value", "eval: !pg.assign_condition_json", ) if not jingrow.db.exists("Property Setter", {"name": "Assignment Rule-unassign_condition-depends_on"}): jingrow.get_pg( { **default_fields, "name": "Assignment Rule-unassign_condition-depends_on", "field_name": "unassign_condition", "property": "depends_on", "value": "eval: !pg.unassign_condition_json", } ).insert() else: jingrow.db.set_value( "Property Setter", {"name": "Assignment Rule-unassign_condition-depends_on"}, "value", "eval: !pg.unassign_condition_json", ) def create_assignment_rule_custom_fields(): if not jingrow.get_meta("Assignment Rule").has_field("assign_condition_json"): click.secho("* Installing Custom Fields in Assignment Rule") create_custom_fields( { "Assignment Rule": [ { "description": "Autogenerated field by CRM App", "fieldname": "assign_condition_json", "fieldtype": "Code", "label": "Assign Condition JSON", "insert_after": "assign_condition", "depends_on": "eval: pg.assign_condition_json", }, { "description": "Autogenerated field by CRM App", "fieldname": "unassign_condition_json", "fieldtype": "Code", "label": "Unassign Condition JSON", "insert_after": "unassign_condition", "depends_on": "eval: pg.unassign_condition_json", }, ], } ) jingrow.clear_cache(pagetype="Assignment Rule")