lingo/lingo/agendas/models.py

187 lines
5.8 KiB
Python

# lingo - payment and billing system
# Copyright (C) 2022 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import copy
from django.conf import settings
from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from lingo.utils.misc import LingoImportError, clean_import_data, generate_slug
class Agenda(models.Model):
label = models.CharField(_('Label'), max_length=150)
slug = models.SlugField(_('Identifier'), max_length=160, unique=True)
category_label = models.CharField(_('Category label'), max_length=150, null=True)
category_slug = models.SlugField(_('Category identifier'), max_length=160, null=True)
check_type_group = models.ForeignKey(
'CheckTypeGroup',
verbose_name=_('Check type group'),
blank=True,
null=True,
on_delete=models.SET_NULL,
)
regie = models.ForeignKey(
'invoicing.Regie',
verbose_name=_('Regie'),
blank=True,
null=True,
on_delete=models.SET_NULL,
)
class Meta:
ordering = ['label']
def __str__(self):
return self.label
def save(self, *args, **kwargs):
if not self.slug:
self.slug = generate_slug(self)
super().save(*args, **kwargs)
@property
def base_slug(self):
return slugify(self.label)
def export_json(self):
return {
'slug': self.slug,
'check_type_group': self.check_type_group.slug if self.check_type_group else None,
}
@classmethod
def import_json(cls, data):
data = copy.deepcopy(data)
try:
agenda = Agenda.objects.get(slug=data['slug'])
except Agenda.DoesNotExist:
raise LingoImportError(_('Missing "%s" agenda') % data['slug'])
if data.get('check_type_group'):
try:
data['check_type_group'] = CheckTypeGroup.objects.get(slug=data['check_type_group'])
except CheckTypeGroup.DoesNotExist:
raise LingoImportError(_('Missing "%s" check type group') % data['check_type_group'])
agenda.check_type_group = data.get('check_type_group')
agenda.save()
return False, agenda
def get_chrono_url(self):
if not settings.KNOWN_SERVICES.get('chrono'):
return
chrono = list(settings.KNOWN_SERVICES['chrono'].values())[0]
chrono_url = chrono.get('url') or ''
return '%smanage/agendas/%s/settings/' % (chrono_url, self.slug)
class CheckTypeGroup(models.Model):
slug = models.SlugField(_('Identifier'), max_length=160, unique=True)
label = models.CharField(_('Label'), max_length=150)
class Meta:
ordering = ['label']
def __str__(self):
return self.label
def save(self, *args, **kwargs):
if not self.slug:
self.slug = generate_slug(self)
super().save(*args, **kwargs)
@property
def base_slug(self):
return slugify(self.label)
@classmethod
def import_json(cls, data):
check_types = data.pop('check_types', [])
data = clean_import_data(cls, data)
group, created = cls.objects.update_or_create(slug=data['slug'], defaults=data)
for check_type in check_types:
check_type['group'] = group
CheckType.import_json(check_type)
return created, group
def export_json(self):
return {
'label': self.label,
'slug': self.slug,
'check_types': [a.export_json() for a in self.check_types.all()],
}
class CheckTypeManager(models.Manager):
def absences(self):
return self.filter(kind='absence', disabled=False)
def presences(self):
return self.filter(kind='presence', disabled=False)
class CheckType(models.Model):
group = models.ForeignKey(CheckTypeGroup, on_delete=models.CASCADE, related_name='check_types')
slug = models.SlugField(_('Identifier'), max_length=160)
label = models.CharField(_('Label'), max_length=150)
kind = models.CharField(
_('Kind'),
max_length=8,
choices=[('absence', _('Absence')), ('presence', _('Presence'))],
default='absence',
)
pricing = models.DecimalField(
_('Pricing'), max_digits=5, decimal_places=2, help_text=_('Fixed pricing'), blank=True, null=True
)
pricing_rate = models.PositiveIntegerField(
_('Pricing rate'), help_text=_('Percentage rate'), blank=True, null=True
)
disabled = models.BooleanField(_('Disabled'), default=False)
objects = CheckTypeManager()
class Meta:
ordering = ['label']
unique_together = ['group', 'slug']
def __str__(self):
return self.label
def save(self, *args, **kwargs):
if not self.slug:
self.slug = generate_slug(self, group=self.group)
super().save(*args, **kwargs)
@property
def base_slug(self):
return slugify(self.label)
@classmethod
def import_json(cls, data):
data = clean_import_data(cls, data)
cls.objects.update_or_create(slug=data['slug'], group=data['group'], defaults=data)
def export_json(self):
return {
'label': self.label,
'slug': self.slug,
'kind': self.kind,
}