Django SalesTrack
A comprehensive Django app for tracking sales personnel, distributors, and retailers with Google Maps integration and advanced filtering capabilities.
Features
- Multi-tier Tracking: Track employees, distributors, and retailers with hierarchical relationships
- Google Maps Integration: Interactive map visualization with custom markers and clustering
- Advanced Filtering: Dynamic filter controls with individual marker counts
- Performance Optimized: Bulk database queries and efficient data loading for large datasets
- Activity Tracking: Log and visualize sales activities and visits
- GeoJSON Support: Export tracking data in GeoJSON format
- Responsive UI: Mobile-friendly interface with dynamic control states
Installation
1. Install the package
Basic installation:
pip install django-salestrack
With MySQL support:
pip install django-salestrack[mysql]
With REST API support:
pip install django-salestrack[api]
Full installation:
pip install django-salestrack[mysql,api]
2. Add to Django settings
Add 'salestrack' to your INSTALLED_APPS in settings.py:
INSTALLED_APPS = [
...
'salestrack',
...
]
3. Configure URLs
Include the salestrack URLs in your main urls.py:
from django.urls import path, include
urlpatterns = [
...
path('salestrack/', include('salestrack.urls')),
...
]
4. Database Setup
This app requires specific database models. Make sure you have models similar to:
SpUsers- User/Employee modelSpVisits- Visit tracking modelSpUserVisits- User visit relationshipsSpActivityLogs- Activity logging modelSpUserTracking- Tracking Related modelSpBeatPlan- Beat Plan Related model
Configuration
Required Settings
Add these settings to your Django settings.py:
# Google Maps API Key (required)
GOOGLE_MAPS_API_KEY = 'your-google-maps-api-key'
# Database configuration (MySQL recommended)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'your_database_name',
'USER': 'your_database_user',
'PASSWORD': 'your_database_password',
'HOST': 'localhost',
'PORT': '3306',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
}
}
}
Optional Settings
# Customize marker clustering (optional)
SALESTRACK_CLUSTER_MARKERS = True
SALESTRACK_MAX_MARKERS_PER_REQUEST = 1000
# Performance settings (optional)
SALESTRACK_BATCH_SIZE = 500
SALESTRACK_CACHE_TIMEOUT = 300 # seconds
Usage
Basic Setup
-
Access the tracking interface: Navigate to
/salestrack/in your application -
API Endpoints:
/salestrack/user-markers/- Get marker data/salestrack/tracks.geo- Get GeoJSON track data
Model Requirements
Your models should follow this structure:
# Example model structure (adapt to your needs)
class SpUsers(AbstractBaseUser):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
emp_sap_id = models.CharField(max_length=50)
store_name = models.CharField(max_length=255, blank=True, null=True)
latitude = models.CharField(max_length=100, blank=True, null=True)
longitude = models.CharField(max_length=100, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
reporting_to_id = models.IntegerField()
class SpVisits(models.Model):
user = models.ForeignKey('SpUsers', on_delete=models.SET_NULL, blank=True, null=True)
outlet_id = models.IntegerField()
beat_id = models.IntegerField()
checkin_datetime = models.DateTimeField()
checkout_datetime = models.DateTimeField(blank=True, null=True)
visit_status = models.IntegerField()
quotation_status = models.IntegerField()
reason_id = models.IntegerField(blank=True, null=True)
reason_remark = models.CharField(max_length=250, blank=True, null=True)
total_retail_time = models.TimeField(blank=True, null=True)
no_order = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class SpUserVisits(models.Model):
user = models.ForeignKey(
SpUsers,
on_delete=models.CASCADE,
related_name="distributor_visits",
null=True,
blank=True
)
employee = models.ForeignKey(
SpUsers,
on_delete=models.CASCADE,
related_name="employee_visits",
null=True,
blank=True
)
checkin_datetime = models.DateTimeField()
checkout_datetime = models.DateTimeField(blank=True, null=True)
visit_status = models.IntegerField()
latitude = models.CharField(max_length=100, blank=True, null=True)
longitude = models.CharField(max_length=100, blank=True, null=True)
reason_remark = models.CharField(max_length=250, blank=True, null=True)
total_retail_time = models.TimeField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class SpActivityLogs(models.Model):
module = models.CharField(max_length=100, blank=True, null=True)
sub_module = models.CharField(max_length=100, blank=True, null=True)
heading = models.TextField()
activity = models.TextField()
user = models.ForeignKey('SpUsers', on_delete=models.CASCADE, related_name='activity_logs')
user_name = models.CharField(max_length=150)
icon = models.CharField(max_length=100, blank=True, null=True)
platform = models.CharField(max_length=50)
status = models.IntegerField(default=1)
platform_icon = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
latitude = models.CharField(max_length=100, blank=True, null=True)
longitude = models.CharField(max_length=100, blank=True, null=True)
class SpUserTracking(models.Model):
user = models.ForeignKey('SpUsers', on_delete=models.CASCADE, related_name="tracks")
latitude = models.CharField(max_length=25, blank=True, null=True)
longitude = models.CharField(max_length=25, blank=True, null=True)
accuracy = models.FloatField(blank=True, null=True)
velocity = models.FloatField(blank=True, null=True)
distance_travelled = models.FloatField(blank=True, null=True)
sync_date_time = models.DateTimeField(blank=True, null=True)
flag = models.IntegerField(default=0, blank=True, null=True)
travel_charges = models.FloatField(blank=True, null=True)
message = models.CharField(max_length=222, blank=True, null=True)
status = models.CharField(max_length=45, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
battery_percentage = models.IntegerField(blank=True, null=True)
class SpBeatPlan(models.Model):
user_id = models.IntegerField()
activity_type_id = models.IntegerField()
activity_type_name = models.CharField(max_length=70)
distributor_id = models.IntegerField()
distributor_name = models.CharField(max_length=60)
store_name = models.CharField(max_length=60,null=True,blank=True)
employee_id = models.IntegerField(default=0)
beat_id = models.IntegerField()
beat_name = models.CharField(max_length=70)
scheduled_beat_date = models.DateTimeField()
remark = models.CharField(max_length=250, blank=True, null=True)
beat_status = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Frontend Integration
The app includes a complete Google Maps interface with:
- Dynamic marker loading and filtering
- Marker type toggles with individual counts
- Performance optimizations for large datasets
- Automatic control state management during API calls
API Reference
GET /user-markers/
Returns marker data for map visualization.
Parameters:
date(optional): Filter by specific date (YYYY-MM-DD format)
Response:
{
"employees": [...],
"distributors": [...],
"retailers": [...],
"activities": [...]
}
GET /tracks.geo
Returns GeoJSON formatted tracking data.
Parameters:
date(optional): Filter by specific date
Response:
{
"type": "FeatureCollection",
"features": [...]
}
Performance Considerations
- The app is optimized for datasets with 7,000+ markers
- Uses bulk database queries to minimize N+1 problems
- Implements client-side batching for large marker sets
- Includes control disable/enable during API calls
Dependencies
Core dependencies:
- Django >= 3.2 (compatible with Django 3.2, 4.x, and 5.x)
- requests >= 2.20.0
- python-dateutil >= 2.7.0
Optional dependencies:
- mysqlclient >= 2.0.0 (install with
[mysql]) - django-mysql >= 4.5.0 (install with
[mysql]) - djangorestframework >= 3.13.0 (install with
[api])
Browser Support
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
License
MIT License
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Support
For support, please open an issue in the GitHub repository or contact the maintainers.
Metadata
Release files for django-salestrack 1.0.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| django_salestrack-1.0.6.tar.gz | 30.9 kB | Without provenance | Details for django_salestrack-1.0.6.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| django_salestrack-1.0.6-py3-none-any.whl | Python 3 | none | any | Details for django_salestrack-1.0.6-py3-none-any.whl |
Total release size: 62.9 kB
Release files / django_salestrack-1.0.6.tar.gz
| Download URL | django_salestrack-1.0.6.tar.gz |
|---|---|
| Size | 30.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6bf8179ac18482eb72a028197833a7f8139c8c776846e5b789e480dae8f9b11c
|
|
BLAKE2b-256 checksum How to use checksums |
357fe8ebbf3de693674e07931d9e15141febb6971c508a8b4dcc228d57dc8243
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.20
|
Release files / django_salestrack-1.0.6-py3-none-any.whl
| Download URL | django_salestrack-1.0.6-py3-none-any.whl |
|---|---|
| Size | 32.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
da0c422a6f43446865034282b2779d844498e6d6fc0ba3d9f57d71251031d524
|
|
BLAKE2b-256 checksum How to use checksums |
a3676bd0b9c6d7debd6820fd5774ebde9a2a4a94a9ddbe608b5ba033eeef5f27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.20
|
Security for django-salestrack 1.0.6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.