from datetime import datetime, timedelta import frappe from frappe.query_builder import DocType from crm.demo.utils import ( backdate, build_full_names, fix_auto_records, insert_comment, insert_communication, insert_version, resolve_owners, ) def create_demo_deals(lead_names, demo_users): """Convert seven leads into deals and add deal-specific activity.""" from crm.fcrm.doctype.crm_lead.crm_lead import convert_to_deal session_user, owner_1, owner_2, _ = resolve_owners(demo_users) _full_names = build_full_names(session_user) # leads[0] Alice, [3] David, [7] Henry, [8] Iris, [9] Jack → 5 active/won deals # leads[10] Karen, [11] Leo → 2 lost deals d_alice = convert_to_deal( lead=lead_names[0], deal={"status": "Demo/Making", "deal_value": 120000, "probability": 50, "deal_owner": session_user}, ) d_david = convert_to_deal( lead=lead_names[3], deal={"status": "Proposal/Quotation", "deal_value": 45000, "probability": 70, "deal_owner": owner_1}, ) d_henry = convert_to_deal( lead=lead_names[7], deal={"status": "Negotiation", "deal_value": 85000, "probability": 60, "deal_owner": owner_2}, ) d_iris = convert_to_deal( lead=lead_names[8], deal={"status": "Qualification", "deal_value": 60000, "probability": 35, "deal_owner": session_user}, ) d_jack = convert_to_deal( lead=lead_names[9], deal={"status": "Won", "deal_value": 175000, "probability": 100, "deal_owner": owner_1}, ) d_karen = convert_to_deal( lead=lead_names[10], deal={ "status": "Lost", "deal_value": 95000, "probability": 0, "deal_owner": owner_2, "lost_reason": "Competition", "lost_notes": "Prospect chose a competitor offering deeper BI integrations out of the box. Price was not the issue — feature parity was.", }, ) d_leo = convert_to_deal( lead=lead_names[11], deal={ "status": "Lost", "deal_value": 55000, "probability": 0, "deal_owner": session_user, "lost_reason": "Budget constraints", "lost_notes": "Q2 budget was cut. Leo said they would revisit in Q4 once headcount hiring is complete. Added to nurture sequence.", }, ) deal_names_list = [d_alice, d_david, d_henry, d_iris, d_jack, d_karen, d_leo] # Converted lead indices — must match deal_names_list order _converted_lead_indices = [0, 3, 7, 8, 9, 10, 11] # Days ago each deal was created (always after its lead) _deal_days = [50, 37, 18, 11, 24, 9, 5] _deal_owners = [session_user, owner_1, owner_2, session_user, owner_1, owner_2, session_user] # Organization logos keyed by org name (index order: alice, david, henry, iris, jack, karen, leo) _org_logos = { "Acme Corp": "/assets/crm/images/demo/acme-corp.png", "TechStart Inc": "/assets/crm/images/demo/techstart-inc.png", "PivotTech Solutions": "/assets/crm/images/demo/pivottech-solutions.png", "ScaleUp Labs": "/assets/crm/images/demo/scaleup-labs.png", "Meridian Systems": "/assets/crm/images/demo/meridian-systems.png", "Vertex Analytics": "/assets/crm/images/demo/vertex-analytics.png", "Forge Digital": "/assets/crm/images/demo/forge-digital.png", } now = datetime.now() for d_name, days, d_owner, li in zip( deal_names_list, _deal_days, _deal_owners, _converted_lead_indices, strict=False ): ts = now - timedelta(days=days) backdate("CRM Deal", d_name, d_owner, ts) org = frappe.db.get_value("CRM Deal", d_name, "organization") if org: logo = _org_logos.get(org) if logo: frappe.db.set_value("CRM Organization", org, "organization_logo", logo, update_modified=False) backdate("CRM Organization", org, d_owner, ts) contacts = frappe.get_all( "CRM Contacts", filters={"parent": d_name, "parenttype": "CRM Deal"}, pluck="contact" ) for contact in contacts: if contact: backdate("Contact", contact, d_owner, ts) backdate("CRM Lead", lead_names[li], d_owner, ts, set_creation=False) fix_auto_records("CRM Deal", d_name, d_owner, ts) fix_auto_records("CRM Lead", lead_names[li], d_owner, ts) comment_names = _create_deal_comments(deal_names_list, session_user, owner_1, owner_2, _full_names, now) communication_names = _create_deal_communications( deal_names_list, session_user, owner_1, _full_names, now ) _create_deal_versions(deal_names_list, session_user, owner_1, owner_2, now) # Re-backdate modified to last-activity date so active deals sort to the top of the list. # Index order: alice, david, henry, iris, jack, karen, leo _deal_last_touched_days = [2, 4, 7, 10, 6, 8, 12] for d_name, days, d_owner in zip(deal_names_list, _deal_last_touched_days, _deal_owners, strict=False): backdate("CRM Deal", d_name, d_owner, now - timedelta(days=days), set_creation=False) return { "deals": deal_names_list, "comments": comment_names, "communications": communication_names, } def _create_deal_comments(deal_names, session_user, owner_1, owner_2, full_names, now): comments_data = [ { "deal": deal_names[0], # Alice / Acme Corp "owner": session_user, "content": ( "
Live demo went well — Alice's product team joined and had great questions " "about workflow automation and bulk import. They want a custom sandbox environment " "to evaluate with their own data before signing. Following up to arrange access.
" ), "days_ago": 3, }, { "deal": deal_names[1], # David / TechStart Inc "owner": owner_1, "content": ( "David reviewed the proposal with his co-founder. They're happy with the pricing " "but want a 3-month pilot before committing to annual. Checking with management on " "whether we can offer a pilot discount.
" ), "days_ago": 5, }, { "deal": deal_names[2], # Henry / PivotTech Solutions "owner": owner_2, "content": ( "Negotiation call with Henry went long but productive. He’s pushing for a 15% " "discount on the annual plan citing budget constraints. Legal team is now reviewing " "the contract — decision expected by end of week.
" ), "days_ago": 7, }, { "deal": deal_names[3], # Iris / ScaleUp Labs "owner": session_user, "content": ( "Qualification call completed with Iris and her co-founder. Small but fast-moving " "team of 8 engineers. Main concerns are API depth and self-serve onboarding. " "Sending over the developer docs and scheduling a technical deep-dive.
" ), "days_ago": 10, }, { "deal": deal_names[4], # Jack / Meridian Systems "owner": owner_1, "content": ( "Deal closed — Jack signed the contract this morning. Final value $175k annual. " "Onboarding is scheduled for next Monday. Handoff notes sent to the customer " "success team. Great result for the quarter!
" ), "days_ago": 2, }, { "deal": deal_names[5], # Karen / Vertex Analytics "owner": owner_2, "content": ( "Karen's team went with a competitor — they had deeper BI integrations that we " "currently don't support. Not a pricing issue. Flagged to product team for roadmap " "consideration. Karen asked us to follow up in 6 months.
" ), "days_ago": 8, }, { "deal": deal_names[6], # Leo / Forge Digital "owner": session_user, "content": ( "Budget was cut for the rest of the year — Leo was very apologetic and said the " "product was exactly what they needed. Re-added to nurture sequence for Q4. " "Good candidate for a comeback deal.
" ), "days_ago": 12, }, ] return [ insert_comment( "CRM Deal", data["deal"], data["owner"], data["content"], full_names, now - timedelta(days=data["days_ago"]), ) for data in comments_data ] def _create_deal_communications(deal_names, session_user, owner_1, full_names, now): # Use a placeholder email for recipients where we don't have a real one handy comms_data = [ { "deal": deal_names[0], "owner": session_user, "sent_or_received": "Sent", "subject": "Sandbox access details — Acme Corp CRM Evaluation", "content": ( "Hi Alice,
" "Thanks for joining yesterday's demo — really great session. I've created a " "dedicated sandbox environment pre-loaded with sample data. Login details and " "setup instructions are attached.
" "Our onboarding specialist Sarah will also be available for a walkthrough " "session this week — just let us know a convenient time.
" "Best regards
" ), "sender": session_user, "recipients": "alice.johnson@example.com", "days_ago": 2, }, { "deal": deal_names[1], "owner": owner_1, "sent_or_received": "Received", "subject": "Re: CRM Proposal — Pilot terms query", "content": ( "Hi,
" "We've reviewed the proposal and the pricing looks good. Before we proceed, " "could you clarify what's included in the onboarding package? Specifically, we " "need help migrating ~4,000 contacts from our existing system.
" "Also, is there flexibility on the contract start date?
" "Thanks,
David Lee
CTO, TechStart Inc