Skip to main content

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 model
  • SpVisits - Visit tracking model
  • SpUserVisits - User visit relationships
  • SpActivityLogs - Activity logging model
  • SpUserTracking - Tracking Related model
  • SpBeatPlan - 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

  1. Access the tracking interface: Navigate to /salestrack/ in your application

  2. 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

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. 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)

Source distribution for django-salestrack 1.0.6
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)

Table of built distributions (wheels) for django-salestrack 1.0.6
File Interpreter ABI Platform Actions
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page