mirror of
https://github.com/ae-utbm/sith.git
synced 2024-12-25 17:21:15 +00:00
ruff rule DJ
Co-authored-by: Bartuccio Antoine <klmp200@users.noreply.github.com>
This commit is contained in:
parent
f941435232
commit
2ac578c3ad
@ -61,6 +61,15 @@ class Company(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("company")
|
verbose_name = _("company")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:co_edit", kwargs={"co_id": self.id})
|
||||||
|
|
||||||
|
def get_display_name(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -87,15 +96,6 @@ class Company(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:co_edit", kwargs={"co_id": self.id})
|
|
||||||
|
|
||||||
def get_display_name(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
|
|
||||||
class BankAccount(models.Model):
|
class BankAccount(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=30)
|
name = models.CharField(_("name"), max_length=30)
|
||||||
@ -112,6 +112,12 @@ class BankAccount(models.Model):
|
|||||||
verbose_name = _("Bank account")
|
verbose_name = _("Bank account")
|
||||||
ordering = ["club", "name"]
|
ordering = ["club", "name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:bank_details", kwargs={"b_account_id": self.id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -125,12 +131,6 @@ class BankAccount(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:bank_details", kwargs={"b_account_id": self.id})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
|
|
||||||
class ClubAccount(models.Model):
|
class ClubAccount(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=30)
|
name = models.CharField(_("name"), max_length=30)
|
||||||
@ -151,6 +151,12 @@ class ClubAccount(models.Model):
|
|||||||
verbose_name = _("Club account")
|
verbose_name = _("Club account")
|
||||||
ordering = ["bank_account", "name"]
|
ordering = ["bank_account", "name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:club_details", kwargs={"c_account_id": self.id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -188,12 +194,6 @@ class ClubAccount(models.Model):
|
|||||||
def get_open_journal(self):
|
def get_open_journal(self):
|
||||||
return self.journals.filter(closed=False).first()
|
return self.journals.filter(closed=False).first()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:club_details", kwargs={"c_account_id": self.id})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def get_display_name(self):
|
def get_display_name(self):
|
||||||
return _("%(club_account)s on %(bank_account)s") % {
|
return _("%(club_account)s on %(bank_account)s") % {
|
||||||
"club_account": self.name,
|
"club_account": self.name,
|
||||||
@ -224,6 +224,12 @@ class GeneralJournal(models.Model):
|
|||||||
verbose_name = _("General journal")
|
verbose_name = _("General journal")
|
||||||
ordering = ["-start_date"]
|
ordering = ["-start_date"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:journal_details", kwargs={"j_id": self.id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -249,12 +255,6 @@ class GeneralJournal(models.Model):
|
|||||||
def can_be_viewed_by(self, user):
|
def can_be_viewed_by(self, user):
|
||||||
return self.club_account.can_be_viewed_by(user)
|
return self.club_account.can_be_viewed_by(user)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:journal_details", kwargs={"j_id": self.id})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def update_amounts(self):
|
def update_amounts(self):
|
||||||
self.amount = 0
|
self.amount = 0
|
||||||
self.effective_amount = 0
|
self.effective_amount = 0
|
||||||
@ -356,6 +356,18 @@ class Operation(models.Model):
|
|||||||
unique_together = ("number", "journal")
|
unique_together = ("number", "journal")
|
||||||
ordering = ["-number"]
|
ordering = ["-number"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.amount} € | {self.date} | {self.accounting_type} | {self.done}"
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.number is None:
|
||||||
|
self.number = self.journal.operations.count() + 1
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
self.journal.update_amounts()
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:journal_details", kwargs={"j_id": self.journal.id})
|
||||||
|
|
||||||
def __getattribute__(self, attr):
|
def __getattribute__(self, attr):
|
||||||
if attr == "target":
|
if attr == "target":
|
||||||
return self.get_target()
|
return self.get_target()
|
||||||
@ -409,12 +421,6 @@ class Operation(models.Model):
|
|||||||
tar = Company.objects.filter(id=self.target_id).first()
|
tar = Company.objects.filter(id=self.target_id).first()
|
||||||
return tar
|
return tar
|
||||||
|
|
||||||
def save(self):
|
|
||||||
if self.number is None:
|
|
||||||
self.number = self.journal.operations.count() + 1
|
|
||||||
super().save()
|
|
||||||
self.journal.update_amounts()
|
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -443,17 +449,6 @@ class Operation(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:journal_details", kwargs={"j_id": self.journal.id})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%d € | %s | %s | %s" % (
|
|
||||||
self.amount,
|
|
||||||
self.date,
|
|
||||||
self.accounting_type,
|
|
||||||
self.done,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AccountingType(models.Model):
|
class AccountingType(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -486,6 +481,12 @@ class AccountingType(models.Model):
|
|||||||
verbose_name = _("accounting type")
|
verbose_name = _("accounting type")
|
||||||
ordering = ["movement_type", "code"]
|
ordering = ["movement_type", "code"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.code + " - " + self.get_movement_type_display() + " - " + self.label
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:type_list")
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -496,12 +497,6 @@ class AccountingType(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:type_list")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.code + " - " + self.get_movement_type_display() + " - " + self.label
|
|
||||||
|
|
||||||
|
|
||||||
class SimplifiedAccountingType(models.Model):
|
class SimplifiedAccountingType(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -520,6 +515,15 @@ class SimplifiedAccountingType(models.Model):
|
|||||||
verbose_name = _("simplified type")
|
verbose_name = _("simplified type")
|
||||||
ordering = ["accounting_type__movement_type", "accounting_type__code"]
|
ordering = ["accounting_type__movement_type", "accounting_type__code"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
f"{self.get_movement_type_display()} "
|
||||||
|
f"- {self.accounting_type.code} - {self.label}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("accounting:simple_type_list")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def movement_type(self):
|
def movement_type(self):
|
||||||
return self.accounting_type.movement_type
|
return self.accounting_type.movement_type
|
||||||
@ -527,18 +531,6 @@ class SimplifiedAccountingType(models.Model):
|
|||||||
def get_movement_type_display(self):
|
def get_movement_type_display(self):
|
||||||
return self.accounting_type.get_movement_type_display()
|
return self.accounting_type.get_movement_type_display()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("accounting:simple_type_list")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return (
|
|
||||||
self.get_movement_type_display()
|
|
||||||
+ " - "
|
|
||||||
+ self.accounting_type.code
|
|
||||||
+ " - "
|
|
||||||
+ self.label
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Label(models.Model):
|
class Label(models.Model):
|
||||||
"""Label allow a club to sort its operations"""
|
"""Label allow a club to sort its operations"""
|
||||||
|
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
|
|||||||
name="owner_group",
|
name="owner_group",
|
||||||
field=models.ForeignKey(
|
field=models.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
default=club.models.Club.get_default_owner_group,
|
default=club.models.get_default_owner_group,
|
||||||
related_name="owned_club",
|
related_name="owned_club",
|
||||||
to="core.Group",
|
to="core.Group",
|
||||||
),
|
),
|
||||||
|
140
club/models.py
140
club/models.py
@ -40,6 +40,11 @@ from core.models import Group, MetaGroup, Notification, Page, RealGroup, SithFil
|
|||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
|
|
||||||
|
# This function prevents generating migration upon settings change
|
||||||
|
def get_default_owner_group():
|
||||||
|
return settings.SITH_GROUP_ROOT_ID
|
||||||
|
|
||||||
|
|
||||||
class Club(models.Model):
|
class Club(models.Model):
|
||||||
"""
|
"""
|
||||||
The Club class, made as a tree to allow nice tidy organization
|
The Club class, made as a tree to allow nice tidy organization
|
||||||
@ -74,10 +79,6 @@ class Club(models.Model):
|
|||||||
)
|
)
|
||||||
address = models.CharField(_("address"), max_length=254)
|
address = models.CharField(_("address"), max_length=254)
|
||||||
|
|
||||||
# This function prevents generating migration upon settings change
|
|
||||||
def get_default_owner_group():
|
|
||||||
return settings.SITH_GROUP_ROOT_ID
|
|
||||||
|
|
||||||
owner_group = models.ForeignKey(
|
owner_group = models.ForeignKey(
|
||||||
Group,
|
Group,
|
||||||
related_name="owned_club",
|
related_name="owned_club",
|
||||||
@ -105,6 +106,34 @@ class Club(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["name", "unix_name"]
|
ordering = ["name", "unix_name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
old = Club.objects.filter(id=self.id).first()
|
||||||
|
creation = old is None
|
||||||
|
if not creation and old.unix_name != self.unix_name:
|
||||||
|
self._change_unixname(self.unix_name)
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
if creation:
|
||||||
|
board = MetaGroup(name=self.unix_name + settings.SITH_BOARD_SUFFIX)
|
||||||
|
board.save()
|
||||||
|
member = MetaGroup(name=self.unix_name + settings.SITH_MEMBER_SUFFIX)
|
||||||
|
member.save()
|
||||||
|
subscribers = Group.objects.filter(
|
||||||
|
name=settings.SITH_MAIN_MEMBERS_GROUP
|
||||||
|
).first()
|
||||||
|
self.make_home()
|
||||||
|
self.home.edit_groups.set([board])
|
||||||
|
self.home.view_groups.set([member, subscribers])
|
||||||
|
self.home.save()
|
||||||
|
self.make_page()
|
||||||
|
cache.set(f"sith_club_{self.unix_name}", self)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("club:club_view", kwargs={"club_id": self.id})
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def president(self):
|
def president(self):
|
||||||
return self.members.filter(
|
return self.members.filter(
|
||||||
@ -183,28 +212,6 @@ class Club(models.Model):
|
|||||||
self.page.parent = self.parent.page
|
self.page.parent = self.parent.page
|
||||||
self.page.save(force_lock=True)
|
self.page.save(force_lock=True)
|
||||||
|
|
||||||
@transaction.atomic()
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
old = Club.objects.filter(id=self.id).first()
|
|
||||||
creation = old is None
|
|
||||||
if not creation and old.unix_name != self.unix_name:
|
|
||||||
self._change_unixname(self.unix_name)
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
if creation:
|
|
||||||
board = MetaGroup(name=self.unix_name + settings.SITH_BOARD_SUFFIX)
|
|
||||||
board.save()
|
|
||||||
member = MetaGroup(name=self.unix_name + settings.SITH_MEMBER_SUFFIX)
|
|
||||||
member.save()
|
|
||||||
subscribers = Group.objects.filter(
|
|
||||||
name=settings.SITH_MAIN_MEMBERS_GROUP
|
|
||||||
).first()
|
|
||||||
self.make_home()
|
|
||||||
self.home.edit_groups.set([board])
|
|
||||||
self.home.view_groups.set([member, subscribers])
|
|
||||||
self.home.save()
|
|
||||||
self.make_page()
|
|
||||||
cache.set(f"sith_club_{self.unix_name}", self)
|
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
# Invalidate the cache of this club and of its memberships
|
# Invalidate the cache of this club and of its memberships
|
||||||
for membership in self.members.ongoing().select_related("user"):
|
for membership in self.members.ongoing().select_related("user"):
|
||||||
@ -212,12 +219,6 @@ class Club(models.Model):
|
|||||||
cache.delete(f"sith_club_{self.unix_name}")
|
cache.delete(f"sith_club_{self.unix_name}")
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("club:club_view", kwargs={"club_id": self.id})
|
|
||||||
|
|
||||||
def get_display_name(self):
|
def get_display_name(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@ -373,14 +374,21 @@ class Membership(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
self.club.name
|
f"{self.club.name} - {self.user.username} "
|
||||||
+ " - "
|
f"- {settings.SITH_CLUB_ROLES[self.role]} "
|
||||||
+ self.user.username
|
f"- {str(_('past member')) if self.end_date is not None else ''}"
|
||||||
+ " - "
|
|
||||||
+ str(settings.SITH_CLUB_ROLES[self.role])
|
|
||||||
+ str(" - " + str(_("past member")) if self.end_date is not None else "")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
if self.end_date is None:
|
||||||
|
cache.set(f"membership_{self.club_id}_{self.user_id}", self)
|
||||||
|
else:
|
||||||
|
cache.set(f"membership_{self.club_id}_{self.user_id}", "not_member")
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("club:club_members", kwargs={"club_id": self.club_id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be super edited by the given user
|
Method to see if that object can be super edited by the given user
|
||||||
@ -400,16 +408,6 @@ class Membership(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("club:club_members", kwargs={"club_id": self.club_id})
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
if self.end_date is None:
|
|
||||||
cache.set(f"membership_{self.club_id}_{self.user_id}", self)
|
|
||||||
else:
|
|
||||||
cache.set(f"membership_{self.club_id}_{self.user_id}", "not_member")
|
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
cache.delete(f"membership_{self.club_id}_{self.user_id}")
|
cache.delete(f"membership_{self.club_id}_{self.user_id}")
|
||||||
@ -451,6 +449,26 @@ class Mailing(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s - %s" % (self.club, self.email_full)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if not self.is_moderated:
|
||||||
|
for user in (
|
||||||
|
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
|
||||||
|
.first()
|
||||||
|
.users.all()
|
||||||
|
):
|
||||||
|
if not user.notifications.filter(
|
||||||
|
type="MAILING_MODERATION", viewed=False
|
||||||
|
).exists():
|
||||||
|
Notification(
|
||||||
|
user=user,
|
||||||
|
url=reverse("com:mailing_admin"),
|
||||||
|
type="MAILING_MODERATION",
|
||||||
|
).save(*args, **kwargs)
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if Mailing.objects.filter(email=self.email).exists():
|
if Mailing.objects.filter(email=self.email).exists():
|
||||||
raise ValidationError(_("This mailing list already exists."))
|
raise ValidationError(_("This mailing list already exists."))
|
||||||
@ -488,26 +506,6 @@ class Mailing(models.Model):
|
|||||||
resp += sub.fetch_format()
|
resp += sub.fetch_format()
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
def save(self):
|
|
||||||
if not self.is_moderated:
|
|
||||||
for user in (
|
|
||||||
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
|
|
||||||
.first()
|
|
||||||
.users.all()
|
|
||||||
):
|
|
||||||
if not user.notifications.filter(
|
|
||||||
type="MAILING_MODERATION", viewed=False
|
|
||||||
).exists():
|
|
||||||
Notification(
|
|
||||||
user=user,
|
|
||||||
url=reverse("com:mailing_admin"),
|
|
||||||
type="MAILING_MODERATION",
|
|
||||||
).save()
|
|
||||||
super().save()
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s - %s" % (self.club, self.email_full)
|
|
||||||
|
|
||||||
|
|
||||||
class MailingSubscription(models.Model):
|
class MailingSubscription(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -535,6 +533,9 @@ class MailingSubscription(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (("user", "email", "mailing"),)
|
unique_together = (("user", "email", "mailing"),)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if not self.user and not self.email:
|
if not self.user and not self.email:
|
||||||
raise ValidationError(_("At least user or email is required"))
|
raise ValidationError(_("At least user or email is required"))
|
||||||
@ -577,6 +578,3 @@ class MailingSubscription(models.Model):
|
|||||||
|
|
||||||
def fetch_format(self):
|
def fetch_format(self):
|
||||||
return self.get_email + " "
|
return self.get_email + " "
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email)
|
|
||||||
|
@ -46,14 +46,14 @@ class Sith(models.Model):
|
|||||||
weekmail_destinations = models.TextField(_("weekmail destinations"), default="")
|
weekmail_destinations = models.TextField(_("weekmail destinations"), default="")
|
||||||
version = utils.get_git_revision_short_hash()
|
version = utils.get_git_revision_short_hash()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "⛩ Sith ⛩"
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
return False
|
return False
|
||||||
return user.is_com_admin
|
return user.is_com_admin
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "⛩ Sith ⛩"
|
|
||||||
|
|
||||||
|
|
||||||
NEWS_TYPES = [
|
NEWS_TYPES = [
|
||||||
("NOTICE", _("Notice")),
|
("NOTICE", _("Notice")),
|
||||||
@ -90,23 +90,6 @@ class News(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
|
||||||
if user.is_anonymous:
|
|
||||||
return False
|
|
||||||
return user.is_com_admin or user == self.author
|
|
||||||
|
|
||||||
def can_be_edited_by(self, user):
|
|
||||||
return user.is_com_admin
|
|
||||||
|
|
||||||
def can_be_viewed_by(self, user):
|
|
||||||
return self.is_moderated or user.is_com_admin
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("com:news_detail", kwargs={"news_id": self.id})
|
|
||||||
|
|
||||||
def get_full_url(self):
|
|
||||||
return "https://%s%s" % (settings.SITH_URL, self.get_absolute_url())
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s: %s" % (self.type, self.title)
|
return "%s: %s" % (self.type, self.title)
|
||||||
|
|
||||||
@ -124,6 +107,23 @@ class News(models.Model):
|
|||||||
param="1",
|
param="1",
|
||||||
).save()
|
).save()
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("com:news_detail", kwargs={"news_id": self.id})
|
||||||
|
|
||||||
|
def get_full_url(self):
|
||||||
|
return "https://%s%s" % (settings.SITH_URL, self.get_absolute_url())
|
||||||
|
|
||||||
|
def is_owned_by(self, user):
|
||||||
|
if user.is_anonymous:
|
||||||
|
return False
|
||||||
|
return user.is_com_admin or user == self.author
|
||||||
|
|
||||||
|
def can_be_edited_by(self, user):
|
||||||
|
return user.is_com_admin
|
||||||
|
|
||||||
|
def can_be_viewed_by(self, user):
|
||||||
|
return self.is_moderated or user.is_com_admin
|
||||||
|
|
||||||
|
|
||||||
def news_notification_callback(notif):
|
def news_notification_callback(notif):
|
||||||
count = (
|
count = (
|
||||||
@ -185,6 +185,9 @@ class Weekmail(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["-id"]
|
ordering = ["-id"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Weekmail {self.id} (sent: {self.sent}) - {self.title}"
|
||||||
|
|
||||||
def send(self):
|
def send(self):
|
||||||
"""
|
"""
|
||||||
Send the weekmail to all users with the receive weekmail option opt-in.
|
Send the weekmail to all users with the receive weekmail option opt-in.
|
||||||
@ -240,9 +243,6 @@ class Weekmail(models.Model):
|
|||||||
"""
|
"""
|
||||||
return "http://" + settings.SITH_URL + static("com/img/weekmail_footerP22.png")
|
return "http://" + settings.SITH_URL + static("com/img/weekmail_footerP22.png")
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "Weekmail %s (sent: %s) - %s" % (self.id, self.sent, self.title)
|
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
return False
|
return False
|
||||||
@ -273,18 +273,21 @@ class WeekmailArticle(models.Model):
|
|||||||
)
|
)
|
||||||
rank = models.IntegerField(_("rank"), default=-1)
|
rank = models.IntegerField(_("rank"), default=-1)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s - %s (%s)" % (self.title, self.author, self.club)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
return False
|
return False
|
||||||
return user.is_com_admin
|
return user.is_com_admin
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s - %s (%s)" % (self.title, self.author, self.club)
|
|
||||||
|
|
||||||
|
|
||||||
class Screen(models.Model):
|
class Screen(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=128)
|
name = models.CharField(_("name"), max_length=128)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def active_posters(self):
|
def active_posters(self):
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
return self.posters.filter(is_moderated=True, date_begin__lte=now).filter(
|
return self.posters.filter(is_moderated=True, date_begin__lte=now).filter(
|
||||||
@ -296,9 +299,6 @@ class Screen(models.Model):
|
|||||||
return False
|
return False
|
||||||
return user.is_com_admin
|
return user.is_com_admin
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s" % (self.name)
|
|
||||||
|
|
||||||
|
|
||||||
class Poster(models.Model):
|
class Poster(models.Model):
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
@ -328,6 +328,9 @@ class Poster(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.is_moderated:
|
if not self.is_moderated:
|
||||||
for u in (
|
for u in (
|
||||||
@ -360,6 +363,3 @@ class Poster(models.Model):
|
|||||||
@property
|
@property
|
||||||
def page(self):
|
def page(self):
|
||||||
return self.club.page
|
return self.club.page
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
|
|||||||
field=models.ForeignKey(
|
field=models.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
verbose_name="owner group",
|
verbose_name="owner group",
|
||||||
default=core.models.Page.get_default_owner_group,
|
default=core.models.get_default_owner_group,
|
||||||
related_name="owned_page",
|
related_name="owned_page",
|
||||||
to="core.Group",
|
to="core.Group",
|
||||||
),
|
),
|
||||||
|
177
core/models.py
177
core/models.py
@ -845,12 +845,15 @@ class Preferences(models.Model):
|
|||||||
_("get a notification for every refilling"), default=False
|
_("get a notification for every refilling"), default=False
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_display_name(self):
|
def __str__(self):
|
||||||
return self.user.get_display_name()
|
return f"Preferences of {self.user}"
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return self.user.get_absolute_url()
|
return self.user.get_absolute_url()
|
||||||
|
|
||||||
|
def get_display_name(self):
|
||||||
|
return self.user.get_display_name()
|
||||||
|
|
||||||
|
|
||||||
def get_directory(instance, filename):
|
def get_directory(instance, filename):
|
||||||
return ".{0}/{1}".format(instance.get_parent_path(), filename)
|
return ".{0}/{1}".format(instance.get_parent_path(), filename)
|
||||||
@ -928,6 +931,31 @@ class SithFile(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("file")
|
verbose_name = _("file")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.get_parent_path() + "/" + self.name
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
sas = SithFile.objects.filter(id=settings.SITH_SAS_ROOT_DIR_ID).first()
|
||||||
|
self.is_in_sas = sas in self.get_parent_list() or self == sas
|
||||||
|
copy_rights = False
|
||||||
|
if self.id is None:
|
||||||
|
copy_rights = True
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
if copy_rights:
|
||||||
|
self.copy_rights()
|
||||||
|
if self.is_in_sas:
|
||||||
|
for u in (
|
||||||
|
RealGroup.objects.filter(id=settings.SITH_GROUP_SAS_ADMIN_ID)
|
||||||
|
.first()
|
||||||
|
.users.all()
|
||||||
|
):
|
||||||
|
Notification(
|
||||||
|
user=u,
|
||||||
|
url=reverse("sas:moderation"),
|
||||||
|
type="SAS_MODERATION",
|
||||||
|
param="1",
|
||||||
|
).save()
|
||||||
|
|
||||||
def can_be_managed_by(self, user: User) -> bool:
|
def can_be_managed_by(self, user: User) -> bool:
|
||||||
"""
|
"""
|
||||||
Tell if the user can manage the file (edit, delete, etc.) or not.
|
Tell if the user can manage the file (edit, delete, etc.) or not.
|
||||||
@ -1033,28 +1061,6 @@ class SithFile(models.Model):
|
|||||||
if self.is_file and (self.file is None or self.file == ""):
|
if self.is_file and (self.file is None or self.file == ""):
|
||||||
raise ValidationError(_("You must provide a file"))
|
raise ValidationError(_("You must provide a file"))
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
sas = SithFile.objects.filter(id=settings.SITH_SAS_ROOT_DIR_ID).first()
|
|
||||||
self.is_in_sas = sas in self.get_parent_list() or self == sas
|
|
||||||
copy_rights = False
|
|
||||||
if self.id is None:
|
|
||||||
copy_rights = True
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
if copy_rights:
|
|
||||||
self.copy_rights()
|
|
||||||
if self.is_in_sas:
|
|
||||||
for u in (
|
|
||||||
RealGroup.objects.filter(id=settings.SITH_GROUP_SAS_ADMIN_ID)
|
|
||||||
.first()
|
|
||||||
.users.all()
|
|
||||||
):
|
|
||||||
Notification(
|
|
||||||
user=u,
|
|
||||||
url=reverse("sas:moderation"),
|
|
||||||
type="SAS_MODERATION",
|
|
||||||
param="1",
|
|
||||||
).save()
|
|
||||||
|
|
||||||
def apply_rights_recursively(self, *, only_folders=False):
|
def apply_rights_recursively(self, *, only_folders=False):
|
||||||
children = self.children.all()
|
children = self.children.all()
|
||||||
if only_folders:
|
if only_folders:
|
||||||
@ -1189,9 +1195,6 @@ class SithFile(models.Model):
|
|||||||
def get_download_url(self):
|
def get_download_url(self):
|
||||||
return reverse("core:download", kwargs={"file_id": self.id})
|
return reverse("core:download", kwargs={"file_id": self.id})
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.get_parent_path() + "/" + self.name
|
|
||||||
|
|
||||||
|
|
||||||
class LockError(Exception):
|
class LockError(Exception):
|
||||||
"""There was a lock error on the object"""
|
"""There was a lock error on the object"""
|
||||||
@ -1211,6 +1214,11 @@ class NotLocked(LockError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# This function prevents generating migration upon settings change
|
||||||
|
def get_default_owner_group():
|
||||||
|
return settings.SITH_GROUP_ROOT_ID
|
||||||
|
|
||||||
|
|
||||||
class Page(models.Model):
|
class Page(models.Model):
|
||||||
"""
|
"""
|
||||||
The page class to build a Wiki
|
The page class to build a Wiki
|
||||||
@ -1250,10 +1258,6 @@ class Page(models.Model):
|
|||||||
# playing with a Page object, use get_full_name() instead!
|
# playing with a Page object, use get_full_name() instead!
|
||||||
_full_name = models.CharField(_("page name"), max_length=255, blank=True)
|
_full_name = models.CharField(_("page name"), max_length=255, blank=True)
|
||||||
|
|
||||||
# This function prevents generating migration upon settings change
|
|
||||||
def get_default_owner_group():
|
|
||||||
return settings.SITH_GROUP_ROOT_ID
|
|
||||||
|
|
||||||
owner_group = models.ForeignKey(
|
owner_group = models.ForeignKey(
|
||||||
Group,
|
Group,
|
||||||
related_name="owned_page",
|
related_name="owned_page",
|
||||||
@ -1286,6 +1290,38 @@ class Page(models.Model):
|
|||||||
("change_prop_page", "Can change the page's properties (groups, ...)"),
|
("change_prop_page", "Can change the page's properties (groups, ...)"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.get_full_name()
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Performs some needed actions before and after saving a page in database
|
||||||
|
"""
|
||||||
|
locked = kwargs.pop("force_lock", False)
|
||||||
|
if not locked:
|
||||||
|
locked = self.is_locked()
|
||||||
|
if not locked:
|
||||||
|
raise NotLocked("The page is not locked and thus can not be saved")
|
||||||
|
self.full_clean()
|
||||||
|
if not self.id:
|
||||||
|
super().save(
|
||||||
|
*args, **kwargs
|
||||||
|
) # Save a first time to correctly set _full_name
|
||||||
|
# This reset the _full_name just before saving to maintain a coherent field quicker for queries than the
|
||||||
|
# recursive method
|
||||||
|
# It also update all the children to maintain correct names
|
||||||
|
self._full_name = self.get_full_name()
|
||||||
|
for c in self.children.all():
|
||||||
|
c.save()
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
self.unset_lock()
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
"""
|
||||||
|
This is needed for black magic powered UpdateView's children
|
||||||
|
"""
|
||||||
|
return reverse("core:page", kwargs={"page_name": self._full_name})
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_page_by_full_name(name):
|
def get_page_by_full_name(name):
|
||||||
"""
|
"""
|
||||||
@ -1293,9 +1329,6 @@ class Page(models.Model):
|
|||||||
"""
|
"""
|
||||||
return Page.objects.filter(_full_name=name).first()
|
return Page.objects.filter(_full_name=name).first()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
"""
|
"""
|
||||||
Cleans up only the name for the moment, but this can be used to make any treatment before saving the object
|
Cleans up only the name for the moment, but this can be used to make any treatment before saving the object
|
||||||
@ -1333,29 +1366,6 @@ class Page(models.Model):
|
|||||||
p = p.parent
|
p = p.parent
|
||||||
return l
|
return l
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Performs some needed actions before and after saving a page in database
|
|
||||||
"""
|
|
||||||
locked = kwargs.pop("force_lock", False)
|
|
||||||
if not locked:
|
|
||||||
locked = self.is_locked()
|
|
||||||
if not locked:
|
|
||||||
raise NotLocked("The page is not locked and thus can not be saved")
|
|
||||||
self.full_clean()
|
|
||||||
if not self.id:
|
|
||||||
super().save(
|
|
||||||
*args, **kwargs
|
|
||||||
) # Save a first time to correctly set _full_name
|
|
||||||
# This reset the _full_name just before saving to maintain a coherent field quicker for queries than the
|
|
||||||
# recursive method
|
|
||||||
# It also update all the children to maintain correct names
|
|
||||||
self._full_name = self.get_full_name()
|
|
||||||
for c in self.children.all():
|
|
||||||
c.save()
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
self.unset_lock()
|
|
||||||
|
|
||||||
def is_locked(self):
|
def is_locked(self):
|
||||||
"""
|
"""
|
||||||
Is True if the page is locked, False otherwise
|
Is True if the page is locked, False otherwise
|
||||||
@ -1415,15 +1425,6 @@ class Page(models.Model):
|
|||||||
return self.lock_user
|
return self.lock_user
|
||||||
raise NotLocked("The page is not locked and thus can not return its user")
|
raise NotLocked("The page is not locked and thus can not return its user")
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
"""
|
|
||||||
This is needed for black magic powered UpdateView's children
|
|
||||||
"""
|
|
||||||
return reverse("core:page", kwargs={"page_name": self._full_name})
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.get_full_name()
|
|
||||||
|
|
||||||
def get_full_name(self):
|
def get_full_name(self):
|
||||||
"""
|
"""
|
||||||
Computes the real full_name of the page based on its name and its parent's name
|
Computes the real full_name of the page based on its name and its parent's name
|
||||||
@ -1480,15 +1481,22 @@ class PageRev(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["date"]
|
ordering = ["date"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.__dict__)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.revision is None:
|
||||||
|
self.revision = self.page.revisions.all().count() + 1
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
# Don't forget to unlock, otherwise, people will have to wait for the page's timeout
|
||||||
|
self.page.unset_lock()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
"""
|
"""
|
||||||
This is needed for black magic powered UpdateView's children
|
This is needed for black magic powered UpdateView's children
|
||||||
"""
|
"""
|
||||||
return reverse("core:page", kwargs={"page_name": self.page._full_name})
|
return reverse("core:page", kwargs={"page_name": self.page._full_name})
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self.__dict__)
|
|
||||||
|
|
||||||
def __getattribute__(self, attr):
|
def __getattribute__(self, attr):
|
||||||
if attr == "owner_group":
|
if attr == "owner_group":
|
||||||
return self.page.owner_group
|
return self.page.owner_group
|
||||||
@ -1504,13 +1512,6 @@ class PageRev(models.Model):
|
|||||||
def can_be_edited_by(self, user):
|
def can_be_edited_by(self, user):
|
||||||
return self.page.can_be_edited_by(user)
|
return self.page.can_be_edited_by(user)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
if self.revision is None:
|
|
||||||
self.revision = self.page.revisions.all().count() + 1
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
# Don't forget to unlock, otherwise, people will have to wait for the page's timeout
|
|
||||||
self.page.unset_lock()
|
|
||||||
|
|
||||||
|
|
||||||
class Notification(models.Model):
|
class Notification(models.Model):
|
||||||
user = models.ForeignKey(
|
user = models.ForeignKey(
|
||||||
@ -1529,15 +1530,6 @@ class Notification(models.Model):
|
|||||||
return self.get_type_display() % self.param
|
return self.get_type_display() % self.param
|
||||||
return self.get_type_display()
|
return self.get_type_display()
|
||||||
|
|
||||||
def callback(self):
|
|
||||||
# Get the callback defined in settings to update existing
|
|
||||||
# notifications
|
|
||||||
mod_name, func_name = settings.SITH_PERMANENT_NOTIFICATIONS[self.type].rsplit(
|
|
||||||
".", 1
|
|
||||||
)
|
|
||||||
mod = importlib.import_module(mod_name)
|
|
||||||
getattr(mod, func_name)(self)
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.id and self.type in settings.SITH_PERMANENT_NOTIFICATIONS:
|
if not self.id and self.type in settings.SITH_PERMANENT_NOTIFICATIONS:
|
||||||
old_notif = self.user.notifications.filter(type=self.type).last()
|
old_notif = self.user.notifications.filter(type=self.type).last()
|
||||||
@ -1547,6 +1539,15 @@ class Notification(models.Model):
|
|||||||
return
|
return
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
def callback(self):
|
||||||
|
# Get the callback defined in settings to update existing
|
||||||
|
# notifications
|
||||||
|
mod_name, func_name = settings.SITH_PERMANENT_NOTIFICATIONS[self.type].rsplit(
|
||||||
|
".", 1
|
||||||
|
)
|
||||||
|
mod = importlib.import_module(mod_name)
|
||||||
|
getattr(mod, func_name)(self)
|
||||||
|
|
||||||
|
|
||||||
class Gift(models.Model):
|
class Gift(models.Model):
|
||||||
label = models.CharField(_("label"), max_length=255)
|
label = models.CharField(_("label"), max_length=255)
|
||||||
@ -1585,8 +1586,8 @@ class OperationLog(models.Model):
|
|||||||
_("operation type"), max_length=40, choices=settings.SITH_LOG_OPERATION_TYPE
|
_("operation type"), max_length=40, choices=settings.SITH_LOG_OPERATION_TYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
|
||||||
return user.is_root
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s - %s - %s" % (self.operation_type, self.label, self.operator)
|
return "%s - %s - %s" % (self.operation_type, self.label, self.operator)
|
||||||
|
|
||||||
|
def is_owned_by(self, user):
|
||||||
|
return user.is_root
|
||||||
|
@ -93,7 +93,7 @@ def search_user(query):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def search_club(query,* , as_json=False):
|
def search_club(query, *, as_json=False):
|
||||||
clubs = []
|
clubs = []
|
||||||
if query:
|
if query:
|
||||||
clubs = Club.objects.filter(name__icontains=query).all()
|
clubs = Club.objects.filter(name__icontains=query).all()
|
||||||
|
@ -18,7 +18,15 @@ from counter.models import (
|
|||||||
class BillingInfoForm(forms.ModelForm):
|
class BillingInfoForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = BillingInfo
|
model = BillingInfo
|
||||||
exclude = ["customer"]
|
fields = [
|
||||||
|
"first_name",
|
||||||
|
"last_name",
|
||||||
|
"address_1",
|
||||||
|
"address_2",
|
||||||
|
"zip_code",
|
||||||
|
"city",
|
||||||
|
"country",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class StudentCardForm(forms.ModelForm):
|
class StudentCardForm(forms.ModelForm):
|
||||||
|
@ -62,6 +62,19 @@ class Customer(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s - %s" % (self.user.username, self.account_id)
|
return "%s - %s" % (self.user.username, self.account_id)
|
||||||
|
|
||||||
|
def save(self, *args, allow_negative=False, is_selling=False, **kwargs):
|
||||||
|
"""
|
||||||
|
is_selling : tell if the current action is a selling
|
||||||
|
allow_negative : ignored if not a selling. Allow a selling to put the account in negative
|
||||||
|
Those two parameters avoid blocking the save method of a customer if his account is negative
|
||||||
|
"""
|
||||||
|
if self.amount < 0 and (is_selling and not allow_negative):
|
||||||
|
raise ValidationError(_("Not enough money"))
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("core:user_account", kwargs={"user_id": self.user.pk})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def can_record(self):
|
def can_record(self):
|
||||||
return self.recorded_products > -settings.SITH_ECOCUP_LIMIT
|
return self.recorded_products > -settings.SITH_ECOCUP_LIMIT
|
||||||
@ -128,16 +141,6 @@ class Customer(models.Model):
|
|||||||
account = cls.objects.create(user=user, account_id=account_id)
|
account = cls.objects.create(user=user, account_id=account_id)
|
||||||
return account, True
|
return account, True
|
||||||
|
|
||||||
def save(self, *args, allow_negative=False, is_selling=False, **kwargs):
|
|
||||||
"""
|
|
||||||
is_selling : tell if the current action is a selling
|
|
||||||
allow_negative : ignored if not a selling. Allow a selling to put the account in negative
|
|
||||||
Those two parameters avoid blocking the save method of a customer if his account is negative
|
|
||||||
"""
|
|
||||||
if self.amount < 0 and (is_selling and not allow_negative):
|
|
||||||
raise ValidationError(_("Not enough money"))
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
|
|
||||||
def recompute_amount(self):
|
def recompute_amount(self):
|
||||||
refillings = self.refillings.aggregate(sum=Sum(F("amount")))["sum"]
|
refillings = self.refillings.aggregate(sum=Sum(F("amount")))["sum"]
|
||||||
self.amount = refillings if refillings is not None else 0
|
self.amount = refillings if refillings is not None else 0
|
||||||
@ -150,9 +153,6 @@ class Customer(models.Model):
|
|||||||
self.amount -= purchases
|
self.amount -= purchases
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("core:user_account", kwargs={"user_id": self.user.pk})
|
|
||||||
|
|
||||||
def get_full_url(self):
|
def get_full_url(self):
|
||||||
return "".join(["https://", settings.SITH_URL, self.get_absolute_url()])
|
return "".join(["https://", settings.SITH_URL, self.get_absolute_url()])
|
||||||
|
|
||||||
@ -178,6 +178,9 @@ class BillingInfo(models.Model):
|
|||||||
city = models.CharField(_("City"), max_length=50)
|
city = models.CharField(_("City"), max_length=50)
|
||||||
country = CountryField(blank_label=_("Country"))
|
country = CountryField(blank_label=_("Country"))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.first_name} {self.last_name}"
|
||||||
|
|
||||||
def to_3dsv2_xml(self) -> str:
|
def to_3dsv2_xml(self) -> str:
|
||||||
"""
|
"""
|
||||||
Convert the data from this model into a xml usable
|
Convert the data from this model into a xml usable
|
||||||
@ -199,9 +202,6 @@ class BillingInfo(models.Model):
|
|||||||
xml = dict2xml(data, wrap="Billing", newlines=False)
|
xml = dict2xml(data, wrap="Billing", newlines=False)
|
||||||
return '<?xml version="1.0" encoding="UTF-8" ?>' + xml
|
return '<?xml version="1.0" encoding="UTF-8" ?>' + xml
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"{self.first_name} {self.last_name}"
|
|
||||||
|
|
||||||
|
|
||||||
class ProductType(models.Model):
|
class ProductType(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -222,6 +222,12 @@ class ProductType(models.Model):
|
|||||||
verbose_name = _("product type")
|
verbose_name = _("product type")
|
||||||
ordering = ["-priority", "name"]
|
ordering = ["-priority", "name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("counter:producttype_list")
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -232,12 +238,6 @@ class ProductType(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("counter:producttype_list")
|
|
||||||
|
|
||||||
|
|
||||||
class Product(models.Model):
|
class Product(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -282,6 +282,12 @@ class Product(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("product")
|
verbose_name = _("product")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s (%s)" % (self.name, self.code)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("counter:product_list")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_record_product(self):
|
def is_record_product(self):
|
||||||
return settings.SITH_ECOCUP_CONS == self.id
|
return settings.SITH_ECOCUP_CONS == self.id
|
||||||
@ -302,9 +308,6 @@ class Product(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("counter:product_list")
|
|
||||||
|
|
||||||
def can_be_sold_to(self, user: User) -> bool:
|
def can_be_sold_to(self, user: User) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if whether the user given in parameter has the right to buy
|
Check if whether the user given in parameter has the right to buy
|
||||||
@ -329,9 +332,6 @@ class Product(models.Model):
|
|||||||
def profit(self):
|
def profit(self):
|
||||||
return self.selling_price - self.purchase_price
|
return self.selling_price - self.purchase_price
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s (%s)" % (self.name, self.code)
|
|
||||||
|
|
||||||
|
|
||||||
class CounterQuerySet(models.QuerySet):
|
class CounterQuerySet(models.QuerySet):
|
||||||
def annotate_has_barman(self, user: User) -> CounterQuerySet:
|
def annotate_has_barman(self, user: User) -> CounterQuerySet:
|
||||||
@ -388,13 +388,6 @@ class Counter(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("counter")
|
verbose_name = _("counter")
|
||||||
|
|
||||||
def __getattribute__(self, name):
|
|
||||||
if name == "edit_groups":
|
|
||||||
return Group.objects.filter(
|
|
||||||
name=self.club.unix_name + settings.SITH_BOARD_SUFFIX
|
|
||||||
).all()
|
|
||||||
return object.__getattribute__(self, name)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@ -403,6 +396,13 @@ class Counter(models.Model):
|
|||||||
return reverse("eboutic:main")
|
return reverse("eboutic:main")
|
||||||
return reverse("counter:details", kwargs={"counter_id": self.id})
|
return reverse("counter:details", kwargs={"counter_id": self.id})
|
||||||
|
|
||||||
|
def __getattribute__(self, name):
|
||||||
|
if name == "edit_groups":
|
||||||
|
return Group.objects.filter(
|
||||||
|
name=self.club.unix_name + settings.SITH_BOARD_SUFFIX
|
||||||
|
).all()
|
||||||
|
return object.__getattribute__(self, name)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
return False
|
return False
|
||||||
@ -629,16 +629,6 @@ class Refilling(models.Model):
|
|||||||
self.customer.user.get_display_name(),
|
self.customer.user.get_display_name(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
|
||||||
if user.is_anonymous:
|
|
||||||
return False
|
|
||||||
return user.is_owner(self.counter) and self.payment_method != "CARD"
|
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
|
||||||
self.customer.amount -= self.amount
|
|
||||||
self.customer.save()
|
|
||||||
super().delete(*args, **kwargs)
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.date:
|
if not self.date:
|
||||||
self.date = timezone.now()
|
self.date = timezone.now()
|
||||||
@ -663,6 +653,16 @@ class Refilling(models.Model):
|
|||||||
).save()
|
).save()
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
def is_owned_by(self, user):
|
||||||
|
if user.is_anonymous:
|
||||||
|
return False
|
||||||
|
return user.is_owner(self.counter) and self.payment_method != "CARD"
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
self.customer.amount -= self.amount
|
||||||
|
self.customer.save()
|
||||||
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Selling(models.Model):
|
class Selling(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -723,59 +723,6 @@ class Selling(models.Model):
|
|||||||
self.customer.user.get_display_name(),
|
self.customer.user.get_display_name(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
|
||||||
if user.is_anonymous:
|
|
||||||
return False
|
|
||||||
return user.is_owner(self.counter) and self.payment_method != "CARD"
|
|
||||||
|
|
||||||
def can_be_viewed_by(self, user):
|
|
||||||
if (
|
|
||||||
not hasattr(self, "customer") or self.customer is None
|
|
||||||
): # Customer can be set to Null
|
|
||||||
return False
|
|
||||||
return user == self.customer.user
|
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
|
||||||
if self.payment_method == "SITH_ACCOUNT":
|
|
||||||
self.customer.amount += self.quantity * self.unit_price
|
|
||||||
self.customer.save()
|
|
||||||
super().delete(*args, **kwargs)
|
|
||||||
|
|
||||||
def send_mail_customer(self):
|
|
||||||
event = self.product.eticket.event_title or _("Unknown event")
|
|
||||||
subject = _("Eticket bought for the event %(event)s") % {"event": event}
|
|
||||||
message_html = _(
|
|
||||||
"You bought an eticket for the event %(event)s.\nYou can download it directly from this link %(eticket)s.\nYou can also retrieve all your e-tickets on your account page %(url)s."
|
|
||||||
) % {
|
|
||||||
"event": event,
|
|
||||||
"url": "".join(
|
|
||||||
(
|
|
||||||
'<a href="',
|
|
||||||
self.customer.get_full_url(),
|
|
||||||
'">',
|
|
||||||
self.customer.get_full_url(),
|
|
||||||
"</a>",
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"eticket": "".join(
|
|
||||||
(
|
|
||||||
'<a href="',
|
|
||||||
self.get_eticket_full_url(),
|
|
||||||
'">',
|
|
||||||
self.get_eticket_full_url(),
|
|
||||||
"</a>",
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
message_txt = _(
|
|
||||||
"You bought an eticket for the event %(event)s.\nYou can download it directly from this link %(eticket)s.\nYou can also retrieve all your e-tickets on your account page %(url)s."
|
|
||||||
) % {
|
|
||||||
"event": event,
|
|
||||||
"url": self.customer.get_full_url(),
|
|
||||||
"eticket": self.get_eticket_full_url(),
|
|
||||||
}
|
|
||||||
self.customer.user.email_user(subject, message_txt, html_message=message_html)
|
|
||||||
|
|
||||||
def save(self, *args, allow_negative=False, **kwargs):
|
def save(self, *args, allow_negative=False, **kwargs):
|
||||||
"""
|
"""
|
||||||
allow_negative : Allow this selling to use more money than available for this user
|
allow_negative : Allow this selling to use more money than available for this user
|
||||||
@ -858,6 +805,59 @@ class Selling(models.Model):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def is_owned_by(self, user):
|
||||||
|
if user.is_anonymous:
|
||||||
|
return False
|
||||||
|
return user.is_owner(self.counter) and self.payment_method != "CARD"
|
||||||
|
|
||||||
|
def can_be_viewed_by(self, user):
|
||||||
|
if (
|
||||||
|
not hasattr(self, "customer") or self.customer is None
|
||||||
|
): # Customer can be set to Null
|
||||||
|
return False
|
||||||
|
return user == self.customer.user
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
if self.payment_method == "SITH_ACCOUNT":
|
||||||
|
self.customer.amount += self.quantity * self.unit_price
|
||||||
|
self.customer.save()
|
||||||
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
|
def send_mail_customer(self):
|
||||||
|
event = self.product.eticket.event_title or _("Unknown event")
|
||||||
|
subject = _("Eticket bought for the event %(event)s") % {"event": event}
|
||||||
|
message_html = _(
|
||||||
|
"You bought an eticket for the event %(event)s.\nYou can download it directly from this link %(eticket)s.\nYou can also retrieve all your e-tickets on your account page %(url)s."
|
||||||
|
) % {
|
||||||
|
"event": event,
|
||||||
|
"url": "".join(
|
||||||
|
(
|
||||||
|
'<a href="',
|
||||||
|
self.customer.get_full_url(),
|
||||||
|
'">',
|
||||||
|
self.customer.get_full_url(),
|
||||||
|
"</a>",
|
||||||
|
)
|
||||||
|
),
|
||||||
|
"eticket": "".join(
|
||||||
|
(
|
||||||
|
'<a href="',
|
||||||
|
self.get_eticket_full_url(),
|
||||||
|
'">',
|
||||||
|
self.get_eticket_full_url(),
|
||||||
|
"</a>",
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
message_txt = _(
|
||||||
|
"You bought an eticket for the event %(event)s.\nYou can download it directly from this link %(eticket)s.\nYou can also retrieve all your e-tickets on your account page %(url)s."
|
||||||
|
) % {
|
||||||
|
"event": event,
|
||||||
|
"url": self.customer.get_full_url(),
|
||||||
|
"eticket": self.get_eticket_full_url(),
|
||||||
|
}
|
||||||
|
self.customer.user.email_user(subject, message_txt, html_message=message_html)
|
||||||
|
|
||||||
def get_eticket_full_url(self):
|
def get_eticket_full_url(self):
|
||||||
eticket_url = reverse("counter:eticket_pdf", kwargs={"selling_id": self.id})
|
eticket_url = reverse("counter:eticket_pdf", kwargs={"selling_id": self.id})
|
||||||
return "".join(["https://", settings.SITH_URL, eticket_url])
|
return "".join(["https://", settings.SITH_URL, eticket_url])
|
||||||
@ -926,6 +926,14 @@ class CashRegisterSummary(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "At %s by %s - Total: %s €" % (self.counter, self.user, self.get_total())
|
return "At %s by %s - Total: %s €" % (self.counter, self.user, self.get_total())
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if not self.id:
|
||||||
|
self.date = timezone.now()
|
||||||
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("counter:cash_summary_list")
|
||||||
|
|
||||||
def __getattribute__(self, name):
|
def __getattribute__(self, name):
|
||||||
if name[:5] == "check":
|
if name[:5] == "check":
|
||||||
checks = self.items.filter(check=True).order_by("value").all()
|
checks = self.items.filter(check=True).order_by("value").all()
|
||||||
@ -978,14 +986,6 @@ class CashRegisterSummary(models.Model):
|
|||||||
t += it.quantity * it.value
|
t += it.quantity * it.value
|
||||||
return t
|
return t
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
if not self.id:
|
|
||||||
self.date = timezone.now()
|
|
||||||
return super().save(*args, **kwargs)
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("counter:cash_summary_list")
|
|
||||||
|
|
||||||
|
|
||||||
class CashRegisterSummaryItem(models.Model):
|
class CashRegisterSummaryItem(models.Model):
|
||||||
cash_summary = models.ForeignKey(
|
cash_summary = models.ForeignKey(
|
||||||
@ -1005,6 +1005,9 @@ class CashRegisterSummaryItem(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("cash register summary item")
|
verbose_name = _("cash register summary item")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.value)
|
||||||
|
|
||||||
|
|
||||||
class Eticket(models.Model):
|
class Eticket(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -1027,16 +1030,16 @@ class Eticket(models.Model):
|
|||||||
secret = models.CharField(_("secret"), max_length=64, unique=True)
|
secret = models.CharField(_("secret"), max_length=64, unique=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s" % (self.product.name)
|
return self.product.name
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("counter:eticket_list")
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.id:
|
if not self.id:
|
||||||
self.secret = base64.b64encode(os.urandom(32))
|
self.secret = base64.b64encode(os.urandom(32))
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("counter:eticket_list")
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -1064,6 +1067,21 @@ class StudentCard(models.Model):
|
|||||||
|
|
||||||
UID_SIZE = 14
|
UID_SIZE = 14
|
||||||
|
|
||||||
|
uid = models.CharField(
|
||||||
|
_("uid"), max_length=UID_SIZE, unique=True, validators=[MinLengthValidator(4)]
|
||||||
|
)
|
||||||
|
customer = models.ForeignKey(
|
||||||
|
Customer,
|
||||||
|
related_name="student_cards",
|
||||||
|
verbose_name=_("student cards"),
|
||||||
|
null=False,
|
||||||
|
blank=False,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.uid
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_valid(uid):
|
def is_valid(uid):
|
||||||
return (
|
return (
|
||||||
@ -1080,15 +1098,3 @@ class StudentCard(models.Model):
|
|||||||
if isinstance(obj, User):
|
if isinstance(obj, User):
|
||||||
return StudentCard.can_create(self.customer, obj)
|
return StudentCard.can_create(self.customer, obj)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
uid = models.CharField(
|
|
||||||
_("uid"), max_length=14, unique=True, validators=[MinLengthValidator(4)]
|
|
||||||
)
|
|
||||||
customer = models.ForeignKey(
|
|
||||||
Customer,
|
|
||||||
related_name="student_cards",
|
|
||||||
verbose_name=_("student cards"),
|
|
||||||
null=False,
|
|
||||||
blank=False,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
)
|
|
||||||
|
@ -56,6 +56,9 @@ class Basket(models.Model):
|
|||||||
)
|
)
|
||||||
date = models.DateTimeField(_("date"), auto_now=True)
|
date = models.DateTimeField(_("date"), auto_now=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.user}'s basket ({self.items.all().count()} items)"
|
||||||
|
|
||||||
def add_product(self, p: Product, q: int = 1):
|
def add_product(self, p: Product, q: int = 1):
|
||||||
"""
|
"""
|
||||||
Given p an object of the Product model and q an integer,
|
Given p an object of the Product model and q an integer,
|
||||||
@ -207,9 +210,6 @@ class Basket(models.Model):
|
|||||||
data.append(("PBX_HMAC", pbx_hmac.hexdigest().upper()))
|
data.append(("PBX_HMAC", pbx_hmac.hexdigest().upper()))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s's basket (%d items)" % (self.user, self.items.all().count())
|
|
||||||
|
|
||||||
|
|
||||||
class Invoice(models.Model):
|
class Invoice(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -226,6 +226,9 @@ class Invoice(models.Model):
|
|||||||
date = models.DateTimeField(_("date"), auto_now=True)
|
date = models.DateTimeField(_("date"), auto_now=True)
|
||||||
validated = models.BooleanField(_("validated"), default=False)
|
validated = models.BooleanField(_("validated"), default=False)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.user} - {self.get_total()} - {self.date}"
|
||||||
|
|
||||||
def get_total(self) -> float:
|
def get_total(self) -> float:
|
||||||
total = self.items.aggregate(
|
total = self.items.aggregate(
|
||||||
total=Sum(F("quantity") * F("product_unit_price"))
|
total=Sum(F("quantity") * F("product_unit_price"))
|
||||||
@ -268,9 +271,6 @@ class Invoice(models.Model):
|
|||||||
self.validated = True
|
self.validated = True
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s - %s - %s" % (self.user, self.get_total(), self.date)
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractBaseItem(models.Model):
|
class AbstractBaseItem(models.Model):
|
||||||
product_id = models.IntegerField(_("product id"))
|
product_id = models.IntegerField(_("product id"))
|
||||||
|
@ -163,16 +163,16 @@ class ElectionList(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.title
|
||||||
|
|
||||||
def can_be_edited_by(self, user):
|
def can_be_edited_by(self, user):
|
||||||
return user.can_edit(self.election)
|
return user.can_edit(self.election)
|
||||||
|
|
||||||
def delete(self):
|
def delete(self, *args, **kwargs):
|
||||||
for candidature in self.candidatures.all():
|
for candidature in self.candidatures.all():
|
||||||
candidature.delete()
|
candidature.delete()
|
||||||
super().delete()
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.title
|
|
||||||
|
|
||||||
|
|
||||||
class Candidature(models.Model):
|
class Candidature(models.Model):
|
||||||
@ -201,6 +201,9 @@ class Candidature(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.role.title} : {self.user.username}"
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
for vote in self.votes.all():
|
for vote in self.votes.all():
|
||||||
vote.delete()
|
vote.delete()
|
||||||
@ -209,9 +212,6 @@ class Candidature(models.Model):
|
|||||||
def can_be_edited_by(self, user):
|
def can_be_edited_by(self, user):
|
||||||
return (user == self.user) or user.can_edit(self.role.election)
|
return (user == self.user) or user.can_edit(self.role.election)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s : %s" % (self.role.title, self.user.username)
|
|
||||||
|
|
||||||
|
|
||||||
class Vote(models.Model):
|
class Vote(models.Model):
|
||||||
"""
|
"""
|
||||||
|
@ -14,7 +14,7 @@ class Migration(migrations.Migration):
|
|||||||
name="edit_groups",
|
name="edit_groups",
|
||||||
field=models.ManyToManyField(
|
field=models.ManyToManyField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default=forum.models.Forum.get_default_edit_group,
|
default=forum.models.get_default_edit_group,
|
||||||
related_name="editable_forums",
|
related_name="editable_forums",
|
||||||
to="core.Group",
|
to="core.Group",
|
||||||
),
|
),
|
||||||
@ -24,7 +24,7 @@ class Migration(migrations.Migration):
|
|||||||
name="view_groups",
|
name="view_groups",
|
||||||
field=models.ManyToManyField(
|
field=models.ManyToManyField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default=forum.models.Forum.get_default_view_group,
|
default=forum.models.get_default_view_group,
|
||||||
related_name="viewable_forums",
|
related_name="viewable_forums",
|
||||||
to="core.Group",
|
to="core.Group",
|
||||||
),
|
),
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
@ -37,6 +38,15 @@ from club.models import Club
|
|||||||
from core.models import Group, User
|
from core.models import Group, User
|
||||||
|
|
||||||
|
|
||||||
|
# Those functions prevent generating migration upon settings changes
|
||||||
|
def get_default_edit_group():
|
||||||
|
return [settings.SITH_GROUP_OLD_SUBSCRIBERS_ID]
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_view_group():
|
||||||
|
return [settings.SITH_GROUP_PUBLIC_ID]
|
||||||
|
|
||||||
|
|
||||||
class Forum(models.Model):
|
class Forum(models.Model):
|
||||||
"""
|
"""
|
||||||
The Forum class, made as a tree to allow nice tidy organization
|
The Forum class, made as a tree to allow nice tidy organization
|
||||||
@ -46,13 +56,6 @@ class Forum(models.Model):
|
|||||||
view_groups allows some groups to view a forum
|
view_groups allows some groups to view a forum
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Those functions prevent generating migration upon settings changes
|
|
||||||
def get_default_edit_group():
|
|
||||||
return [settings.SITH_GROUP_OLD_SUBSCRIBERS_ID]
|
|
||||||
|
|
||||||
def get_default_view_group():
|
|
||||||
return [settings.SITH_GROUP_PUBLIC_ID]
|
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True, db_index=True)
|
id = models.AutoField(primary_key=True, db_index=True)
|
||||||
name = models.CharField(_("name"), max_length=64)
|
name = models.CharField(_("name"), max_length=64)
|
||||||
description = models.CharField(_("description"), max_length=512, default="")
|
description = models.CharField(_("description"), max_length=512, default="")
|
||||||
@ -98,8 +101,8 @@ class Forum(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["number"]
|
ordering = ["number"]
|
||||||
|
|
||||||
def clean(self):
|
def __str__(self):
|
||||||
self.check_loop()
|
return self.name
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
copy_rights = False
|
copy_rights = False
|
||||||
@ -109,6 +112,12 @@ class Forum(models.Model):
|
|||||||
if copy_rights:
|
if copy_rights:
|
||||||
self.copy_rights()
|
self.copy_rights()
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("forum:view_forum", kwargs={"forum_id": self.id})
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
self.check_loop()
|
||||||
|
|
||||||
def set_topic_number(self):
|
def set_topic_number(self):
|
||||||
self._topic_number = self.get_topic_number()
|
self._topic_number = self.get_topic_number()
|
||||||
self.save()
|
self.save()
|
||||||
@ -166,11 +175,11 @@ class Forum(models.Model):
|
|||||||
return True
|
return True
|
||||||
try:
|
try:
|
||||||
m = Forum._club_memberships[self.id][user.id]
|
m = Forum._club_memberships[self.id][user.id]
|
||||||
except:
|
except KeyError:
|
||||||
m = self.owner_club.get_membership_for(user)
|
m = self.owner_club.get_membership_for(user)
|
||||||
try:
|
try:
|
||||||
Forum._club_memberships[self.id][user.id] = m
|
Forum._club_memberships[self.id][user.id] = m
|
||||||
except:
|
except KeyError:
|
||||||
Forum._club_memberships[self.id] = {}
|
Forum._club_memberships[self.id] = {}
|
||||||
Forum._club_memberships[self.id][user.id] = m
|
Forum._club_memberships[self.id][user.id] = m
|
||||||
if m:
|
if m:
|
||||||
@ -187,9 +196,6 @@ class Forum(models.Model):
|
|||||||
objs.append(cur)
|
objs.append(cur)
|
||||||
cur = cur.parent
|
cur = cur.parent
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s" % (self.name)
|
|
||||||
|
|
||||||
def get_full_name(self):
|
def get_full_name(self):
|
||||||
return "/".join(
|
return "/".join(
|
||||||
chain.from_iterable(
|
chain.from_iterable(
|
||||||
@ -197,9 +203,6 @@ class Forum(models.Model):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("forum:view_forum", kwargs={"forum_id": self.id})
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def parent_list(self):
|
def parent_list(self):
|
||||||
return self.get_parent_list()
|
return self.get_parent_list()
|
||||||
@ -256,11 +259,17 @@ class ForumTopic(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["-_last_message__date"]
|
ordering = ["-_last_message__date"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.title
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
self.forum.set_topic_number() # Recompute the cached value
|
self.forum.set_topic_number() # Recompute the cached value
|
||||||
self.forum.set_last_message()
|
self.forum.set_last_message()
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("forum:view_topic", kwargs={"topic_id": self.id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
return self.forum.is_owned_by(user)
|
return self.forum.is_owned_by(user)
|
||||||
|
|
||||||
@ -270,23 +279,15 @@ class ForumTopic(models.Model):
|
|||||||
def can_be_viewed_by(self, user):
|
def can_be_viewed_by(self, user):
|
||||||
return user.can_view(self.forum)
|
return user.can_view(self.forum)
|
||||||
|
|
||||||
def __str__(self):
|
def get_first_unread_message(self, user: User) -> ForumMessage | None:
|
||||||
return "%s" % (self.title)
|
if not hasattr(user, "forum_infos"):
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("forum:view_topic", kwargs={"topic_id": self.id})
|
|
||||||
|
|
||||||
def get_first_unread_message(self, user):
|
|
||||||
try:
|
|
||||||
msg = (
|
|
||||||
self.messages.exclude(readers=user)
|
|
||||||
.filter(date__gte=user.forum_infos.last_read_date)
|
|
||||||
.order_by("id")
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
return msg
|
|
||||||
except:
|
|
||||||
return None
|
return None
|
||||||
|
return (
|
||||||
|
self.messages.exclude(readers=user)
|
||||||
|
.filter(date__gte=user.forum_infos.last_read_date)
|
||||||
|
.order_by("id")
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def last_message(self):
|
def last_message(self):
|
||||||
@ -332,6 +333,9 @@ class ForumMessage(models.Model):
|
|||||||
self.topic._message_number = self.topic.messages.count()
|
self.topic._message_number = self.topic.messages.count()
|
||||||
self.topic.save()
|
self.topic.save()
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("forum:view_message", kwargs={"message_id": self.id})
|
||||||
|
|
||||||
def is_first_in_topic(self):
|
def is_first_in_topic(self):
|
||||||
return bool(self.id == self.topic.messages.order_by("date").first().id)
|
return bool(self.id == self.topic.messages.order_by("date").first().id)
|
||||||
|
|
||||||
@ -356,9 +360,6 @@ class ForumMessage(models.Model):
|
|||||||
def can_be_moderated_by(self, user):
|
def can_be_moderated_by(self, user):
|
||||||
return self.topic.forum.is_owned_by(user) or user.id == self.author.id
|
return self.topic.forum.is_owned_by(user) or user.id == self.author.id
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("forum:view_message", kwargs={"message_id": self.id})
|
|
||||||
|
|
||||||
def get_url(self):
|
def get_url(self):
|
||||||
return (
|
return (
|
||||||
self.topic.get_absolute_url()
|
self.topic.get_absolute_url()
|
||||||
@ -378,11 +379,10 @@ class ForumMessage(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def mark_as_read(self, user):
|
def mark_as_read(self, user):
|
||||||
try: # Need the try/except because of AnonymousUser
|
if user.is_anonymous:
|
||||||
if not self.is_read(user):
|
return
|
||||||
self.readers.add(user)
|
if not self.is_read(user):
|
||||||
except:
|
self.readers.add(user)
|
||||||
pass
|
|
||||||
|
|
||||||
def is_read(self, user):
|
def is_read(self, user):
|
||||||
return (self.date < user.forum_infos.last_read_date) or (
|
return (self.date < user.forum_infos.last_read_date) or (
|
||||||
@ -413,6 +413,9 @@ class ForumMessageMeta(models.Model):
|
|||||||
date = models.DateTimeField(_("date"), default=timezone.now)
|
date = models.DateTimeField(_("date"), default=timezone.now)
|
||||||
action = models.CharField(_("action"), choices=MESSAGE_META_ACTIONS, max_length=16)
|
action = models.CharField(_("action"), choices=MESSAGE_META_ACTIONS, max_length=16)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.user.nick_name} ({self.date})"
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
self.message._deleted = self.message.is_deleted()
|
self.message._deleted = self.message.is_deleted()
|
||||||
|
@ -127,6 +127,9 @@ class GalaxyLane(models.Model):
|
|||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.star1} -> {self.star2} ({self.distance})"
|
||||||
|
|
||||||
|
|
||||||
class StarDict(TypedDict):
|
class StarDict(TypedDict):
|
||||||
id: int
|
id: int
|
||||||
|
@ -37,6 +37,12 @@ class Launderette(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Launderette")
|
verbose_name = _("Launderette")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("launderette:launderette_list")
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -63,12 +69,6 @@ class Launderette(models.Model):
|
|||||||
def can_be_viewed_by(self, user):
|
def can_be_viewed_by(self, user):
|
||||||
return user.is_subscribed
|
return user.is_subscribed
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("launderette:launderette_list")
|
|
||||||
|
|
||||||
def get_machine_list(self):
|
def get_machine_list(self):
|
||||||
return Machine.objects.filter(launderette_id=self.id)
|
return Machine.objects.filter(launderette_id=self.id)
|
||||||
|
|
||||||
@ -98,6 +98,15 @@ class Machine(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Machine")
|
verbose_name = _("Machine")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s %s" % (self._meta.verbose_name, self.name)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse(
|
||||||
|
"launderette:launderette_admin",
|
||||||
|
kwargs={"launderette_id": self.launderette.id},
|
||||||
|
)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Method to see if that object can be edited by the given user
|
Method to see if that object can be edited by the given user
|
||||||
@ -112,15 +121,6 @@ class Machine(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s %s" % (self._meta.verbose_name, self.name)
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse(
|
|
||||||
"launderette:launderette_admin",
|
|
||||||
kwargs={"launderette_id": self.launderette.id},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Token(models.Model):
|
class Token(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=5)
|
name = models.CharField(_("name"), max_length=5)
|
||||||
@ -148,6 +148,12 @@ class Token(models.Model):
|
|||||||
unique_together = ("name", "launderette", "type")
|
unique_together = ("name", "launderette", "type")
|
||||||
ordering = ["type", "name"]
|
ordering = ["type", "name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
f"{self.__class__._meta.verbose_name} {self.get_type_display()} "
|
||||||
|
f"#{self.name} ({self.launderette.name})"
|
||||||
|
)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if self.name == "":
|
if self.name == "":
|
||||||
raise DataError(_("Token name can not be blank"))
|
raise DataError(_("Token name can not be blank"))
|
||||||
@ -168,18 +174,6 @@ class Token(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return (
|
|
||||||
self.__class__._meta.verbose_name
|
|
||||||
+ " "
|
|
||||||
+ self.get_type_display()
|
|
||||||
+ " #"
|
|
||||||
+ self.name
|
|
||||||
+ " ("
|
|
||||||
+ self.launderette.name
|
|
||||||
+ ")"
|
|
||||||
)
|
|
||||||
|
|
||||||
def is_avaliable(self):
|
def is_avaliable(self):
|
||||||
if not self.borrow_date and not self.user:
|
if not self.borrow_date and not self.user:
|
||||||
return True
|
return True
|
||||||
@ -214,9 +208,6 @@ class Slot(models.Model):
|
|||||||
verbose_name = _("Slot")
|
verbose_name = _("Slot")
|
||||||
ordering = ["start_date"]
|
ordering = ["start_date"]
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
|
||||||
return user == self.user
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "User: %s - Date: %s - Type: %s - Machine: %s - Token: %s" % (
|
return "User: %s - Date: %s - Type: %s - Machine: %s - Token: %s" % (
|
||||||
self.user,
|
self.user,
|
||||||
@ -225,3 +216,6 @@ class Slot(models.Model):
|
|||||||
self.machine.name,
|
self.machine.name,
|
||||||
self.token,
|
self.token,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def is_owned_by(self, user):
|
||||||
|
return user == self.user
|
||||||
|
@ -141,6 +141,12 @@ class UV(models.Model):
|
|||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.code
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("pedagogy:uv_detail", kwargs={"uv_id": self.id})
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Can be created by superuser, root or pedagogy admin user
|
Can be created by superuser, root or pedagogy admin user
|
||||||
@ -160,9 +166,6 @@ class UV(models.Model):
|
|||||||
|
|
||||||
return int(sum(comments.values_list(field, flat=True)) / comments.count())
|
return int(sum(comments.values_list(field, flat=True)) / comments.count())
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("pedagogy:uv_detail", kwargs={"uv_id": self.id})
|
|
||||||
|
|
||||||
def has_user_already_commented(self, user):
|
def has_user_already_commented(self, user):
|
||||||
"""
|
"""
|
||||||
Help prevent multiples comments from the same user
|
Help prevent multiples comments from the same user
|
||||||
@ -194,9 +197,6 @@ class UV(models.Model):
|
|||||||
def grade_work_load_average(self):
|
def grade_work_load_average(self):
|
||||||
return self.__grade_average_generic("grade_work_load")
|
return self.__grade_average_generic("grade_work_load")
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.code
|
|
||||||
|
|
||||||
|
|
||||||
class UVComment(models.Model):
|
class UVComment(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -252,6 +252,14 @@ class UVComment(models.Model):
|
|||||||
)
|
)
|
||||||
publish_date = models.DateTimeField(_("publish date"), blank=True)
|
publish_date = models.DateTimeField(_("publish date"), blank=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.uv} - {self.author}"
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.publish_date is None:
|
||||||
|
self.publish_date = timezone.now()
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
"""
|
"""
|
||||||
Is owned by a pedagogy admin, a superuser or the author himself
|
Is owned by a pedagogy admin, a superuser or the author himself
|
||||||
@ -265,14 +273,6 @@ class UVComment(models.Model):
|
|||||||
"""
|
"""
|
||||||
return self.reports.exists()
|
return self.reports.exists()
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s - %s" % (self.uv, self.author)
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
if self.publish_date is None:
|
|
||||||
self.publish_date = timezone.now()
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class UVResult(models.Model):
|
class UVResult(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -303,6 +303,9 @@ class UVResult(models.Model):
|
|||||||
validators=[validators.RegexValidator("[AP][0-9]{3}")],
|
validators=[validators.RegexValidator("[AP][0-9]{3}")],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.user.username} ; {self.uv.code} ; {self.grade}"
|
||||||
|
|
||||||
|
|
||||||
class UVCommentReport(models.Model):
|
class UVCommentReport(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -323,6 +326,9 @@ class UVCommentReport(models.Model):
|
|||||||
)
|
)
|
||||||
reason = models.TextField(_("reason"))
|
reason = models.TextField(_("reason"))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.reporter.username} : {self.reason}"
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def uv(self):
|
def uv(self):
|
||||||
return self.comment.uv
|
return self.comment.uv
|
||||||
|
@ -70,7 +70,19 @@ optional = true
|
|||||||
version = "1.4.25"
|
version = "1.4.25"
|
||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff.lint]
|
||||||
select = ["I", "A", "F401", "UP008", "UP009"]
|
select = [
|
||||||
|
"I", # isort
|
||||||
|
"B",
|
||||||
|
"A", # shadowing of Python builtins
|
||||||
|
"F401", # unused import
|
||||||
|
"DJ", # django-specific rules,
|
||||||
|
"UP008", # Use super() instead of super(__class__, self)
|
||||||
|
"UP009" # utf-8 encoding declaration is unnecessary
|
||||||
|
]
|
||||||
|
|
||||||
|
ignore = [
|
||||||
|
"DJ001", # null=True in CharField/TextField. this one would require a migration
|
||||||
|
]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
DJANGO_SETTINGS_MODULE = "sith.settings"
|
DJANGO_SETTINGS_MODULE = "sith.settings"
|
||||||
|
@ -149,10 +149,10 @@ class ShoppingListItem(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s - %s" % (self.name, self.shopping_lists.first())
|
return f"{self.name} - {self.shopping_lists.first()}"
|
||||||
|
|
||||||
def can_be_viewed_by(self, user):
|
|
||||||
return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("stock:shoppinglist_list")
|
return reverse("stock:shoppinglist_list")
|
||||||
|
|
||||||
|
def can_be_viewed_by(self, user):
|
||||||
|
return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)
|
||||||
|
@ -22,6 +22,7 @@ from django.contrib.auth.forms import PasswordResetForm
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from core.models import User
|
from core.models import User
|
||||||
@ -65,26 +66,11 @@ class Subscription(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["subscription_start"]
|
ordering = ["subscription_start"]
|
||||||
|
|
||||||
def clean(self):
|
def __str__(self):
|
||||||
try:
|
if hasattr(self, "member") and self.member is not None:
|
||||||
for s in (
|
return f"{self.member.username} - {self.pk}"
|
||||||
Subscription.objects.filter(member=self.member)
|
else:
|
||||||
.exclude(pk=self.pk)
|
return f"No user - {self.pk}"
|
||||||
.all()
|
|
||||||
):
|
|
||||||
if (
|
|
||||||
s.is_valid_now()
|
|
||||||
and s.subscription_end
|
|
||||||
- timedelta(weeks=settings.SITH_SUBSCRIPTION_END)
|
|
||||||
> date.today()
|
|
||||||
):
|
|
||||||
raise ValidationError(
|
|
||||||
_("You can not subscribe many time for the same period")
|
|
||||||
)
|
|
||||||
except: # This should not happen, because the form should have handled the data before, but sadly, it still
|
|
||||||
# calls the model validation :'(
|
|
||||||
# TODO see SubscriptionForm's clean method
|
|
||||||
raise ValidationError(_("Subscription error"))
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
super().save()
|
super().save()
|
||||||
@ -105,11 +91,20 @@ class Subscription(models.Model):
|
|||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("core:user_edit", kwargs={"user_id": self.member.pk})
|
return reverse("core:user_edit", kwargs={"user_id": self.member.pk})
|
||||||
|
|
||||||
def __str__(self):
|
def clean(self):
|
||||||
if hasattr(self, "member") and self.member is not None:
|
today = timezone.now().date()
|
||||||
return self.member.username + " - " + str(self.pk)
|
active_subscriptions = Subscription.objects.exclude(pk=self.pk).filter(
|
||||||
else:
|
subscription_start__gte=today, subscription_end__lte=today
|
||||||
return "No user - " + str(self.pk)
|
)
|
||||||
|
for s in active_subscriptions:
|
||||||
|
if (
|
||||||
|
s.is_valid_now()
|
||||||
|
and s.subscription_end - timedelta(weeks=settings.SITH_SUBSCRIPTION_END)
|
||||||
|
> date.today()
|
||||||
|
):
|
||||||
|
raise ValidationError(
|
||||||
|
_("You can not subscribe many time for the same period")
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def compute_start(d: date = None, duration: int = 1, user: User = None) -> date:
|
def compute_start(d: date = None, duration: int = 1, user: User = None) -> date:
|
||||||
|
@ -83,6 +83,9 @@ class Trombi(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.club.name)
|
return str(self.club.name)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("trombi:detail", kwargs={"trombi_id": self.id})
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.subscription_deadline > self.comments_deadline:
|
if self.subscription_deadline > self.comments_deadline:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
@ -92,9 +95,6 @@ class Trombi(models.Model):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse("trombi:detail", kwargs={"trombi_id": self.id})
|
|
||||||
|
|
||||||
def is_owned_by(self, user):
|
def is_owned_by(self, user):
|
||||||
return user.can_edit(self.club)
|
return user.can_edit(self.club)
|
||||||
|
|
||||||
@ -192,6 +192,9 @@ class TrombiComment(models.Model):
|
|||||||
content = models.TextField(_("content"), default="")
|
content = models.TextField(_("content"), default="")
|
||||||
is_moderated = models.BooleanField(_("is the comment moderated"), default=False)
|
is_moderated = models.BooleanField(_("is the comment moderated"), default=False)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.author} : {self.content}"
|
||||||
|
|
||||||
def can_be_viewed_by(self, user):
|
def can_be_viewed_by(self, user):
|
||||||
if user.id == self.target.user.id:
|
if user.id == self.target.user.id:
|
||||||
return False
|
return False
|
||||||
@ -220,8 +223,8 @@ class TrombiClubMembership(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s - %s - %s (%s)" % (self.user, self.club, self.role, self.start)
|
return "%s - %s - %s (%s)" % (self.user, self.club, self.role, self.start)
|
||||||
|
|
||||||
def can_be_edited_by(self, user):
|
|
||||||
return user.id == self.user.user.id or user.can_edit(self.user.trombi)
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("trombi:profile")
|
return reverse("trombi:profile")
|
||||||
|
|
||||||
|
def can_be_edited_by(self, user):
|
||||||
|
return user.id == self.user.user.id or user.can_edit(self.user.trombi)
|
||||||
|
Loading…
Reference in New Issue
Block a user