Repository URL to install this package:
|
Version:
0.1.4 ▾
|
import logging
import sys
from enum import Enum
from django.contrib.postgres.fields import ArrayField, JSONField
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models import Q
from django.db.models.signals import (m2m_changed, post_delete, post_save,
pre_save)
from django.dispatch import receiver
from django_fsm import FSMField, transition
from django_fsm_log.decorators import fsm_log_by, fsm_log_description
from dynamic_preferences.registries import global_preferences_registry
from slugify import slugify
import crm
class Linkage(Enum):
PERSON = 'PERSON'
COMPANY = 'COMPANY'
BOTH = 'BOTH'
class DynamicField(models.Model):
linkage_choices = (
(Linkage.PERSON.value, 'Person'),
(Linkage.COMPANY.value, 'Company'),
(Linkage.BOTH.value, 'Both'),
)
linkage = models.CharField(max_length=10, choices=linkage_choices, default=Linkage.BOTH.value)
title = models.CharField(max_length=64)
key = models.CharField(max_length=64, null=True, blank=True, unique=True)
class Meta:
abstract = True
def get_key(self):
return self.key
def get_empty_dict(self):
return {
'title': self.title,
'field_type': self.get_field_type(),
'content': '',
'class_name': self.__class__.__name__,
}
def save(self, *args, **kwargs):
self.key = slugify(self.title)
old_self = None
if self.id:
old_self = self.__class__.objects.get(id=self.id)
super().save(*args, **kwargs)
for entry in crm.models.entries.Entry.objects.all():
entry.update_or_create_additional_fields(self, old_self)
entry.save()
def delete(self, *args, **kwargs):
key = self.get_key()
super().delete(*args, **kwargs)
for entry in crm.models.entries.Entry.objects.all():
entry.delete_additional_fields(additional_field_key=key)
entry.save()
def __str__(self):
return '%s' % (self.key)
@classmethod
def get_field_for_key(cls, key):
try:
return DynamicCharField.objects.get(key=key)
except DynamicCharField.DoesNotExist:
pass
try:
return DynamicRangeField.objects.get(key=key)
except DynamicRangeField.DoesNotExist:
pass
try:
return DynamicChoiceField.objects.get(key=key)
except DynamicChoiceField.DoesNotExist:
pass
return None
@classmethod
def validate_field_for_key(cls, key, value):
instance = cls.get_field_for_key(key=key)
return instance.validate_field(value)
@classmethod
def get_field_count_for_entry(cls, entry):
count = 0
count += DynamicCharField.objects.filter(Q(linkage=Linkage.BOTH.value) | Q(linkage=entry.get_linkage_value())).count()
count += DynamicRangeField.objects.filter(Q(linkage=Linkage.BOTH.value) | Q(linkage=entry.get_linkage_value())).count()
count += DynamicChoiceField.objects.filter(Q(linkage=Linkage.BOTH.value) | Q(linkage=entry.get_linkage_value())).count()
return count
class DynamicCharField(DynamicField):
def get_field_type(self):
return 'CharField'
def validate_field(self, value):
return (True, '', value)
class DynamicRangeField(DynamicField):
range_min = models.FloatField()
range_max = models.FloatField()
def get_empty_dict(self):
empty_dict = super().get_empty_dict()
empty_dict['range_min'] = self.range_min
empty_dict['range_max'] = self.range_max
return empty_dict
def get_field_type(self):
return 'RangeField'
def validate_field(self, value):
try:
value = float(value)
except ValueError:
return (False, 'Not a number.', None)
if value > self.range_max or value < self.range_min:
return (False, 'Out of range.', None)
return (True, '', value)
class DynamicChoiceField(DynamicField):
choices = ArrayField(models.CharField(max_length=32))
def get_empty_dict(self):
empty_dict = super().get_empty_dict()
empty_dict['choices'] = self.choices
return empty_dict
def get_field_type(self):
return 'ChoiceField'
def validate_field(self, value):
if str(value) in self.choices:
return (True, '', str(value))
else:
return (False, 'Not a valid choice.', None)