Coverage for modules\crm\services.py: 24%
51 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-05 09:25 +0800
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-05 09:25 +0800
1from datetime import timezone, datetime
2from django.db import transaction
3from core.exceptions import NotFoundException, BadRequestException
4from .models import Company, Contact, Pipeline, DealStage, Deal, Activity
5from modules.authentication.models import User
7class CRMService:
8 @staticmethod
9 def get_or_create_default_pipeline(tenant_id):
10 pipeline = Pipeline.objects.filter(tenant_id=tenant_id, is_default=True).first()
11 if not pipeline:
12 pipeline = Pipeline.objects.create(
13 tenant_id=tenant_id,
14 name="Standard Sales Pipeline",
15 is_default=True
16 )
17 # Default stages
18 stages = [
19 ("Lead In", 10, "#94A3B8"),
20 ("Contact Made", 25, "#60A5FA"),
21 ("Proposal Sent", 50, "#F59E0B"),
22 ("Negotiation", 75, "#8B5CF6"),
23 ("Won", 100, "#10B981"),
24 ]
25 for order, (name, prob, color) in enumerate(stages):
26 DealStage.objects.create(
27 tenant_id=tenant_id,
28 pipeline=pipeline,
29 name=name,
30 order=order,
31 probability=prob,
32 color=color
33 )
34 return pipeline
36 @staticmethod
37 def create_deal(tenant_id, data):
38 stage = DealStage.objects.filter(id=data.stage_id, tenant_id=tenant_id).first()
39 if not stage:
40 raise NotFoundException("Deal stage not found.")
42 contact = Contact.objects.filter(id=data.contact_id, tenant_id=tenant_id).first() if data.contact_id else None
43 company = Company.objects.filter(id=data.company_id, tenant_id=tenant_id).first() if data.company_id else None
44 assigned_to = User.objects.filter(id=data.assigned_to_id).first() if data.assigned_to_id else None
46 return Deal.objects.create(
47 tenant_id=tenant_id,
48 title=data.title,
49 value=data.value,
50 currency=data.currency or 'PHP',
51 pipeline_id=data.pipeline_id,
52 stage=stage,
53 contact=contact,
54 company=company,
55 expected_close_date=data.expected_close_date,
56 assigned_to=assigned_to
57 )
59 @staticmethod
60 def update_deal(tenant_id, deal_id, data):
61 deal = Deal.objects.filter(id=deal_id, tenant_id=tenant_id).first()
62 if not deal:
63 raise NotFoundException("Deal not found.")
65 if data.title is not None:
66 deal.title = data.title
67 if data.value is not None:
68 deal.value = data.value
69 if data.stage_id is not None:
70 stage = DealStage.objects.filter(id=data.stage_id, tenant_id=tenant_id).first()
71 if stage:
72 deal.stage = stage
73 if data.status is not None:
74 deal.status = data.status
75 if data.status in ['WON', 'LOST']:
76 deal.closed_at = datetime.now(timezone.utc)
77 if data.contact_id is not None:
78 deal.contact = Contact.objects.filter(id=data.contact_id, tenant_id=tenant_id).first()
79 if data.company_id is not None:
80 deal.company = Company.objects.filter(id=data.company_id, tenant_id=tenant_id).first()
81 if data.expected_close_date is not None:
82 deal.expected_close_date = data.expected_close_date
83 if data.assigned_to_id is not None:
84 deal.assigned_to = User.objects.filter(id=data.assigned_to_id).first()
86 deal.save()
87 return deal