Skip to content

Instantly share code, notes, and snippets.

@kevin-brown
Last active January 13, 2016 20:34
Show Gist options
  • Save kevin-brown/c30104ad18a6949dd684 to your computer and use it in GitHub Desktop.
Save kevin-brown/c30104ad18a6949dd684 to your computer and use it in GitHub Desktop.
class BankQuerySet(models.QuerySet):
def owned_by(self, citizen):
from django.db.models import Q
organizations_owned_by_citizen = Organization.objects.filter(
owners__in=[citizen]
).distinct()
return self.filter(
(Q(owner_id=citizen.id) & Q(owner_ct=Citizen)) |
(Q(owner_id__in=organizations_owned_by_citizen) & Q(owner_ct=Organization))
)
class RuleQuerySet(models.QuerySet):
def on_date(self, _date):
return self.get(start_date__lte=_date, end_date__gte=_date)
class TransferQuerySet(models.QuerySet):
def on_date(self, _date):
return self.filter(when__lt=_date + timedelta(days=1), when__gte=_date)
class Rule(models.Model):
start_date = models.DateField()
end_date = models.DateField()
deposit_percent = models.DecimalField(max_digits=10, decimal_places=3)
credit_percent = models.DecimalField(max_digits=10, decimal_places=3)
objects = RuleQuerySet.as_manager()
class BankAccount(models.Model):
DEBET = 1
CREDIT = 2
method = models.PositiveSmallIntegerField(choices=(
(DEBET, 'Дебет'),
(CREDIT, 'Кредит'),
))
when_opened = models.DateField()
owner = GenericForeignKey(
'object_id',
'object_ct',
)
owner_id = models.PositiveIntegerField()
owner_ct = models.ForeignKey("contenttypes.ContentType")
def __unicode__(self):
prefix = "L" if self.is_legal() else "N"
prefix += "D" if self.method == self.DEBET else "C"
public_id = str(self.id).zfill(4)
return "%s (#%s)" % (self.owner, prefix + public_id)
def is_legal(self):
return self.owner_ct is Organization
def is_owner(self, citizen):
if self.owner is Citizen:
return self.owner_id == citizen.id
return self.owner.owners.filter(id=citizen.id).exists()
@property
def balance(self):
today = timezone.localtime(timezone.now()).date()
if self.method == self.CREDIT:
percent = Rule.objects.on_date(self.when_opened).credit_percent * decimal.Decimal("0.01")
else:
percent = Rule.objects.on_date(self.when_opened).deposit_percent * decimal.Decimal("0.01")
result = 0
current_date = self.when_opened
while current_date <= today:
dd = self.sum_total_transfers_on_date(current_date)
result += dd
if current_date < today:
result *= 1 + percent
current_date += timedelta(days=1)
return result
def sum_total_transfers_on_date(self, _date):
result = 0
result -= sum(x.total for x in self.cashing_set.on_date(_date))
result -= sum(x.total for x in self.outcome_transfers.on_date(_date))
result += sum(x.total for x in self.deposit_set.all().on_date(_date))
result += sum(x.total for x in self.income_transfers.on_date(_date))
return result
class MoneyTransfer(models.Model):
sender = models.ForeignKey(BankAccount, related_name='outcome_transfers', verbose_name="Отправитель")
receiver = models.ForeignKey(BankAccount, related_name='income_transfers', verbose_name="Получатель")
when = models.DateTimeField(verbose_name="Время")
total = models.DecimalField(max_digits=10, decimal_places=3, verbose_name="Сумма")
comment = models.CharField(max_length=255, verbose_name="Комментарий")
objects = TransferQuerySet.as_manager()
class Deposit(models.Model):
account = models.ForeignKey(BankAccount)
total = models.DecimalField(max_digits=10, decimal_places=3)
banker = models.ForeignKey(Citizen)
when = models.DateTimeField()
objects = TransferQuerySet.as_manager()
class Cashing(models.Model):
account = models.ForeignKey(BankAccount)
total = models.DecimalField(max_digits=10, decimal_places=3)
banker = models.ForeignKey(Citizen)
when = models.DateTimeField()
objects = TransferQuerySet.as_manager()
class BankObjectMixin(object):
def get_queryset(self):
return BankAccount.objects.owned_by(self.request.user.citizen)
class AccountDetail(BankObjectMixin, DetailView):
model = BankAccount
template_name = 'bank/account_detail.html'
class SendTransfer(BankObjectMixin, SingleObjectMixin, FormView):
model = BankAccount
form_class = SendTransferForm
template_name = 'bank/send_transfer.html'
def form_valid(self, form):
data = form.cleaned_data
MoneyTransfer.objects.create(
sender=self.get_object(),
receiver=data['receiver'], # ModelChoiceField in the form
total=data['total'], # FloatField in the form, etc.
when=timezone.localtime(timezone.now()),
comment=data['comment']
)
return redirect('AccountDetail', self.get_object().pk)
def get_form_kwargs(self):
kwargs = super(SendTransfer, self).get_form_kwargs()
kwargs['sender'] = self.get_object()
kwargs['user'] = self.request.user
return kwargs
class OutcomeTransfers(BankObjectMixin, DetailView):
model = BankAccount
template_name = 'bank/report.html'
def _get_queryset(self):
return self.get_object().outcome_transfers.all()
def get_context_data(self, **kwargs):
data = super(OutcomeTransfers, self).get_context_data()
queryset = self._get_queryset()
if 'sort' in self.request.GET:
queryset = queryset.order_by(self.request.GET['sort'])
data['table'] = MoneyTransferTable(queryset)
return data
class IncomeTransfers(BankObjectMixin, DetailView):
model = BankAccount
template_name = 'bank/report.html'
def _get_queryset(self):
return self.get_object().income_transfers.all()
def get_context_data(self, **kwargs):
data = super(IncomeTransfers, self).get_context_data()
queryset = self._get_queryset()
if 'sort' in self.request.GET:
queryset = queryset.order_by(self.request.GET['sort'])
data['table'] = MoneyTransferTable(queryset)
return data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment