Last active
January 13, 2016 20:34
-
-
Save kevin-brown/c30104ad18a6949dd684 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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