CRM domain model
Οι έννοιες, οι σχέσεις και οι αποφάσεις ονοματοδοσίας του CRM όπως υλοποιούνται σήμερα.
Βασικές έννοιες
Η σημερινή ιεραρχία των models:
Organization
-> OrganizationMembership -> User
-> OrganizationSettings
-> EmailAccount
-> OrganizationInvitation
-> Company
-> Contact
-> Deal
-> Task
-> Automation
-> AutomationRun
User
-> UserProfileOrganization
Το Organization αντιστοιχεί σε έναν πελάτη Bubllio CRM και αποτελεί το workspace ή tenant του. Κάθε Organization απομονώνει τα CRM data του:
- Companies
- Contacts
- Deals και sales pipeline
- Tasks και follow-ups
- Automations
- Users και role-based permissions μέσω memberships
- Pending invitations για χρήστες που δεν είναι ακόμη μέλη
- Organization settings και κρυπτογραφημένα SMTP email accounts
Τα Organization settings περιλαμβάνουν επίσης την επιχειρηματική ταυτότητα, τις regional preferences και τα ERP defaults του workspace. Η επιχειρηματική ταυτότητα περιλαμβάνει legal/trading names, φορολογικά και μητρώου στοιχεία, στοιχεία επικοινωνίας και ταχυδρομική διεύθυνση. Τα ERP defaults ορίζουν νόμισμα, έναρξη οικονομικού έτους, φορολογικό συντελεστή, όρους πληρωμής και αρίθμηση εγγράφων. Δεν δημιουργούν από μόνα τους λογιστικά παραστατικά.
Ο χρήστης μπορεί να δημιουργήσει ένα ιδιωτικό personal workspace από τον workspace picker. Αυτό είναι κανονικό tenant για τις δικές του Companies, Contacts και Automations, αλλά έχει is_personal=true και έναν Owner. Personal workspaces δεν διαγράφονται, δεν δέχονται invitations και δεν προσθέτουν μέλη. Shared/team workspaces είναι κανονικά Organizations: ο χρήστης τα βλέπει αφού αποδεχτεί invitation ή δημιουργήσει workspace για τον εαυτό του. Workspace που περιμένει τον προτεινόμενο Owner του παραμένει κρυφό από τα κανονικά CRM endpoints. Μετά το provisioning, η πρόσβαση ελέγχεται από τα membership roles.
Company
Το Company είναι εξωτερική επιχείρηση καταχωρισμένη στο CRM, με την οποία συνεργάζεται ή θέλει να συνεργαστεί η ομάδα. Χρησιμοποιούμε Company αντί για Customer, επειδή μια επιχείρηση μπορεί να καταχωριστεί πριν γίνει πελάτης.
Το Company.lifecycle_stage παίρνει μία από τις τιμές:
leadprospectcustomerinactive
Η εγγραφή Company περιλαμβάνει το επιχειρηματικό προφίλ που χρειάζεται στις πωλήσεις και στην εξυπηρέτηση: tax/VAT reference, κλάδο, στοιχεία επικοινωνίας, ταχυδρομική διεύθυνση, country code και εσωτερικές σημειώσεις. Τα δεδομένα ανήκουν στο Organization που έχει την εγγραφή και περιλαμβάνονται στο tenant-scoped search.
Κάθε Company λαμβάνει customer code περιορισμένο στο Organization, όπως CUS-00001, CUS-00002 κ.ο.κ. Μπορεί να ανατεθεί σε ένα μέλος του workspace ως account owner. Τα tax/VAT IDs και τα email addresses ελέγχονται για ακριβή duplicates χωρίς διάκριση πεζών/κεφαλαίων, μέσα στο ίδιο Organization.
Τα customer-facing Company URLs χρησιμοποιούν αυτόν τον σύντομο κωδικό ως public reference. Τα detail και action routes του API δέχονται ακόμη το αρχικό UUID, ώστε να παραμείνουν συμβατά τα υπάρχοντα bookmarks και integrations.
Οι Companies μπορούν να αρχειοθετηθούν και να επανέλθουν. Οι ενεργές λίστες κρύβουν τις archived εγγραφές από προεπιλογή· φίλτρα επιτρέπουν την προβολή archived ή όλων των records. Η μόνιμη διαγραφή διατίθεται μόνο ως API operation και μόνο για κενές εγγραφές. Company με Contacts δεν διαγράφεται.
Το CompanyActivity καταγράφει ποιος δημιούργησε, ενημέρωσε, ανέθεσε, αρχειοθέτησε ή επανέφερε μια Company. Καταγράφει επίσης την προσθήκη Contact. Τα activity entries αποθηκεύουν ασφαλή metadata, όπως τα ονόματα των πεδίων που άλλαξαν, όχι τις προηγούμενες τιμές τους.
Contact
Το Contact είναι άτομο που εργάζεται σε μία από τις Companies του CRM. Κάθε Contact ανήκει σε ένα Organization και μία Company.
Ο serializer επιβεβαιώνει ότι η επιλεγμένη Company ανήκει στο επιλεγμένο Organization. Τα email addresses των Contacts ελέγχονται για ακριβή duplicates χωρίς διάκριση πεζών/κεφαλαίων, μέσα στο ίδιο Organization. Τα Contacts αναζητούνται με όνομα, στοιχεία επικοινωνίας, τμήμα ή job title και φιλτράρονται ανά Company.
Το Contact μπορεί επίσης να έχει προαιρετικό workspace owner, status active ή former, primary contact (ένα ενεργό ανά Company), archived status και tenant-scoped activity log. Για την καθημερινή χρήση, δείτε τον οδηγό Contacts και Companies.
Deal
Το Deal είναι sales opportunity που ανήκει σε ένα tenant. Συνδέεται με μία Company και προαιρετικά με ένα Contact και workspace owner. Περνά από τα stages lead, qualified, proposal, negotiation, won ή lost και περιλαμβάνει value, currency, probability και expected close date.
Κατά την καταχώριση του ποσού δηλώνεται αν είναι net ή περιλαμβάνει ΦΠΑ. Το API υπολογίζει net value, VAT amount και gross value· οι sales forecasts δεν περιλαμβάνουν τον φόρο στα έσοδα. Κάθε Deal διατηρεί τη θέση του μέσα στο pipeline stage, ώστε η σειρά drag and drop να αποθηκεύεται. Το API απορρίπτει Company, Contact ή owner references που ανήκουν σε άλλο tenant. Δείτε τον οδηγό Sales pipeline.
Γιατί Company και όχι Customer;
Ο όρος Customer υπονοεί ότι η επιχείρηση έχει ήδη αγοράσει κάτι. Σε ένα CRM θέλουμε να καταχωρίζουμε επιχειρήσεις πριν γίνουν πελάτες.
Company = η εξωτερική επιχείρηση
Contact = άτομο που εργάζεται σε αυτή την επιχείρηση
Company.lifecycle_stage = lead, prospect, customer ή inactiveΈτσι καλύπτεται ολόκληρος ο CRM lifecycle χωρίς να χρειαστεί μετονομασία των models αργότερα.
Μελλοντική έννοια Account
Έχουμε συζητήσει το Account, αλλά προς το παρόν τον αντίστοιχο ρόλο έχει το Company. Αν το προϊόν χρειαστεί πιο σύνθετη διαχείριση accounts, μπορούμε να προσθέσουμε αυτή την έννοια αργότερα. Η πρόωρη προσθήκη της θα δημιουργούσε σύγχυση στην ονοματοδοσία.
Σχέσεις models
Organization 1 -> many Companies
Organization 1 -> many Contacts
Organization 1 -> many Deals
Organization 1 -> many Tasks
Organization 1 -> many ServiceCatalogItems
Organization 1 -> many CustomerSubscriptions
Organization 1 -> many Charges
Organization 1 -> many Payments
Organization 1 -> many OrganizationMemberships
User 1 -> many OrganizationMemberships
Company 1 -> many Contacts
Company 1 -> many CompanyActivities
Company 1 -> many Deals
Company 1 -> many Tasks
Company 1 -> many CustomerSubscriptions
User 1 -> many assigned Companies
Organization 1 -> many Automations
Automation 1 -> many AutomationRuns
Organization 1 -> 1 OrganizationSettings
Organization 1 -> many EmailAccounts
User 1 -> 0 or 1 personal Organization
CustomerSubscription 1 -> many Charges
Charge 1 -> many PaymentsTasks και next actions
Το Task είναι follow-up που ανήκει σε ένα Organization και συνδέεται υποχρεωτικά με μία Company. Μπορεί επίσης να συνδεθεί με Contact ή Deal της ίδιας Company. Καταγράφει ενέργεια τύπου task, call, email ή meeting, μαζί με owner, priority, due time, προαιρετικό reminder και σημειώσεις. Το Organization προκύπτει πάντα από το authorized URL. Τα related records και ο assignee επικυρώνονται έναντι του ίδιου Organization.
Το workflow status αποθηκεύεται ως todo, in_progress, waiting ή completed. Η ολοκλήρωση καταγράφεται στα completed_at και completed_by. Μετάβαση σε completed συμπληρώνει αυτά τα audit metadata· επαναφορά σε άλλο status τα καθαρίζει. Οι ενέργειες move, complete και reopen χρησιμοποιούν το ίδιο row-locking service, ώστε τα metadata να μην αποκλίνουν. Το overdue είναι derived status για incomplete Task του οποίου το due time έχει περάσει· δεν είναι μεταβλητό database flag.
Το παλαιότερο incomplete Task που συνδέεται με Deal εμφανίζεται στο frontend ως next action. Reminder delivery και unified customer timeline δεν έχουν υλοποιηθεί ακόμη.
Services και billing
Το ServiceCatalogItem αποθηκεύει επαναχρησιμοποιήσιμες εμπορικές προεπιλογές, όπως service name, net price, VAT rate και billing cycle. Το CustomerSubscription είναι η πραγματική συμφωνία με μία Company και κρατά αντίγραφο αυτών των τιμών, ώστε μελλοντικές αλλαγές του catalog να μην αλλοιώνουν το ιστορικό του πελάτη.
Η δημιουργία subscription δημιουργεί την πρώτη Charge. Κάθε Charge κρατά snapshot των net, VAT και gross amounts για μία περίοδο κάλυψης. Μπορούν να συνδεθούν ένα ή περισσότερα Payment records. Το payment status προκύπτει από τα ποσά που εισπράχθηκαν και το υπόλοιπο· δεν διατηρείται με χειροκίνητο boolean.
Όταν εξοφληθεί πλήρως ενεργή recurring subscription με auto-renew, το service δημιουργεί ακριβώς μία επόμενη Charge. Ο unique database constraint σε subscription και due date κάνει την ενέργεια idempotent. Pause ή cancel subscription δεν διαγράφει Charges ή Payments. Η κανονική ακύρωση θέτει status cancelling έως το τέλος της τρέχουσας περιόδου κάλυψης, ακυρώνει μόνο τις επόμενες ανοιχτές Charges και εμποδίζει τη δημιουργία νέας Charge μετά από πληρωμή. Η subscription μπορεί να επανενεργοποιηθεί πριν από την ημερομηνία ακύρωσης, χωρίς duplicate Charge. Η άμεση ακύρωση είναι ρητή ενέργεια για εξαιρετικές περιπτώσεις.
Επιχειρησιακή λογική
Επιχειρησιακή λογική είναι οι κανόνες του domain, όχι μόνο η διαχείριση HTTP requests. Παραδείγματα:
- Το Contact μιας Company πρέπει να ανήκει στο ίδιο Organization.
- Η δημιουργία Company μπορεί να ενεργοποιήσει Automation.
- Κάθε Automation εκτελείται μέσα στο Organization στο οποίο ανήκει.
- Email account χρησιμοποιείται μόνο μέσω των settings endpoints του Organization στο οποίο ανήκει. Τα Automation emails δεν χρησιμοποιούν ακόμη αυτά τα accounts.
- Authenticated χρήστης αποκτά πρόσβαση σε REST resources μόνο μέσω
OrganizationMembershipκαι των capabilities του role του.
Για τους πλήρεις κανόνες πρόσβασης, δείτε το Authentication, Organizations και ρόλοι.
Τοποθετήστε τη λογική στο κατάλληλο επίπεδο:
serializers.py (or api/*_serializers.py) -> API input validation
services/*.py -> reusable domain behavior
models.py -> core data constraints and simple model behavior
api/*.py -> HTTP request/response coordinationΤα views δεν πρέπει να γίνουν το σημείο όπου συγκεντρώνονται όλοι οι product rules.
Για τη ροή από event σε action, δείτε τα Automations. Μελλοντικό action Create contact θα δημιουργεί CRM record· trigger Contact created θα αντιδρά σε αυτή τη δημιουργία. Κανένα από τα δύο δεν υποστηρίζεται σήμερα από το automation system. Το Automation Roadmap εξηγεί τη διάκριση.
Τρέχον όριο πρόσβασης
Authenticated χρήστης αποκτά πρόσβαση σε κανονικά REST resources μόνο σε Organizations όπου έχει OrganizationMembership με το απαιτούμενο capability. Το Django staff ή superuser status δεν παρακάμπτει αυτό το REST όριο. Ωστόσο, Django superuser έχει ευρεία πρόσβαση μέσω του /admin/. Η διαχείριση εγκατάστασης γίνεται από ξεχωριστά endpoints.
Μια συνηθισμένη pending invitation δεν δημιουργεί membership. Το provisioning δημιουργεί προσωρινό Owner membership για τον creator, αλλά κρατά το workspace κρυφό μέχρι να αποδεχτεί την πρόσκληση ο προτεινόμενος Owner.
