society-self-service/sstreasury/models.py

147 lines
4.6 KiB
Python

# Society Self-Service
# Copyright © 2018-2019 Yingtong Li (RunasSudo)
#
# 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 <https://www.gnu.org/licenses/>.
from django.contrib.auth.models import User
from django.db import models
from jsonfield import JSONField
from enum import Enum
class DescriptionEnum(Enum):
def __new__(cls, value, description):
obj = object.__new__(cls)
obj._value_ = value
obj.description = description
return obj
class Budget(models.Model):
pass
class BudgetComment(models.Model):
budget = models.ForeignKey(Budget, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name='+')
time = models.DateTimeField()
content = models.TextField()
class Meta:
ordering = ['id']
class BudgetState(DescriptionEnum):
DRAFT = 10, 'Draft'
RESUBMIT = 20, 'Returned for redrafting'
AWAIT_REVIEW = 30, 'Awaiting Treasury review'
ENDORSED = 40, 'Endorsed by Treasury, awaiting committee approval'
APPROVED = 50, 'Approved'
#CANCELLED = 60, 'Cancelled'
class BudgetAction(DescriptionEnum):
CREATE = 5, 'Created'
EDIT = 10, 'Edited'
UPDATE_STATE = 20, 'Updated state'
class BudgetRevision(models.Model):
budget = models.ForeignKey(Budget, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
date = models.DateField()
contributors = models.ManyToManyField(User, related_name='+')
comments = models.TextField()
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name='+')
time = models.DateTimeField()
state = models.IntegerField(choices=[(v.value, v.description) for v in BudgetState])
revenue = JSONField(default=[])
revenue_comments = models.TextField()
expense = JSONField(default=[])
expense_no_emergency_fund = models.BooleanField()
expense_comments = models.TextField()
action = models.IntegerField(choices=[(v.value, v.description) for v in BudgetAction])
def copy(self):
contributors = list(self.contributors.all())
self.pk, self.id = None, None
self.save()
self.contributors.add(*contributors)
def can_view(self, user):
if user == self.author:
return True
if user in self.contributors.all():
return True
if user.groups.filter(name='Treasury').exists():
return True
if (self.state == BudgetState.ENDORSED or self.state == BudgetState.APPROVED) and user.groups.filter(name='Committee').exists():
return True
return False
class Meta:
ordering = ['id']
class ClaimState(DescriptionEnum):
DRAFT = 10, 'Draft'
RESUBMIT = 20, 'Returned for redrafting'
AWAIT_REVIEW = 30, 'Awaiting Treasury approval'
APPROVED = 40, 'Approved by Treasury, awaiting payment'
PAID = 50, 'Paid'
class ClaimAction(DescriptionEnum):
CREATE = 5, 'Created'
EDIT = 10, 'Edited'
UPDATE_STATE = 20, 'Updated state'
class ReimbursementClaim(models.Model):
purpose = models.CharField(max_length=100)
date = models.DateField()
comments = models.TextField()
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name='+')
time = models.DateTimeField()
state = models.IntegerField(choices=[(v.value, v.description) for v in ClaimState])
items = JSONField(default=[])
def can_view(self, user):
if user == self.author:
return True
if user.groups.filter(name='Treasury').exists():
return True
return False
class ClaimReceipt(models.Model):
claim = models.ForeignKey(ReimbursementClaim, on_delete=models.CASCADE)
uploaded_file = models.FileField()
class ClaimComment(models.Model):
claim = models.ForeignKey(ReimbursementClaim, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name='+')
time = models.DateTimeField()
content = models.TextField()
class Meta:
ordering = ['id']
class ClaimHistory(models.Model):
claim = models.ForeignKey(ReimbursementClaim, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name='+')
state = models.IntegerField(choices=[(v.value, v.description) for v in ClaimState])
time = models.DateTimeField()
action = models.IntegerField(choices=[(v.value, v.description) for v in ClaimAction])