diff --git a/api/admin.py b/api/admin.py index aab8598..0caf3fc 100644 --- a/api/admin.py +++ b/api/admin.py @@ -68,6 +68,8 @@ class PrefillAdmin(admin.ModelAdmin): def description(self, obj): return obj.name +class PaystubAdmin(admin.ModelAdmin): + list_display = ('title', 'journal_entry') # Register your models here admin.site.register(Prefill, PrefillAdmin) @@ -84,5 +86,5 @@ def description(self, obj): admin.site.register(PrefillItem) admin.site.register(S3File) admin.site.register(DocSearch) -admin.site.register(Paystub) +admin.site.register(Paystub, PaystubAdmin) admin.site.register(PaystubValue) diff --git a/api/forms.py b/api/forms.py index 80c1077..23c8f71 100644 --- a/api/forms.py +++ b/api/forms.py @@ -287,6 +287,10 @@ def save(self): hero_transaction.create_link(linked_transaction) return hero_transaction +class JournalEntryMetadataForm(forms.Form): + index = forms.IntegerField(min_value=0, widget=forms.HiddenInput()) + paystub_id = forms.CharField(widget=forms.HiddenInput(), required=False) + class BaseJournalEntryItemFormset(BaseModelFormSet): @@ -299,7 +303,10 @@ def __init__(self, *args, **kwargs): def get_entry_total(self): total = 0 for form in self.forms: - amount = form.cleaned_data.get('amount') + try: + amount = form.cleaned_data.get('amount') + except AttributeError: + amount = form.initial.get('amount', None) total += (amount if amount is not None else 0) return total @@ -331,7 +338,6 @@ def save(self, transaction, type, commit=True): return instances - class JournalEntryItemForm(forms.ModelForm): amount = CommaDecimalField( initial=0.00, diff --git a/api/models.py b/api/models.py index d7ca942..42582ce 100644 --- a/api/models.py +++ b/api/models.py @@ -647,6 +647,9 @@ class JournalEntry(models.Model): on_delete=models.CASCADE ) + class Meta: + verbose_name_plural = 'journal entries' + def __str__(self): return str(self.pk) + ': ' + str(self.date) + ' ' + self.description @@ -769,6 +772,9 @@ class DocSearch(models.Model): ] selection = models.CharField(max_length=20, choices=STRING_CHOICES, null=True, blank=True) + class Meta: + verbose_name_plural = 'doc searches' + def __str__(self): account_name = self.account.name if self.account is not None else None selection_value = self.selection if self.selection is not None else '' diff --git a/api/views/journal_entry_views.py b/api/views/journal_entry_views.py new file mode 100644 index 0000000..34a57bc --- /dev/null +++ b/api/views/journal_entry_views.py @@ -0,0 +1,388 @@ +from django.http import HttpResponse +from django.template.loader import render_to_string +from django.views import View +from django.shortcuts import get_object_or_404 +from django.contrib.auth.mixins import LoginRequiredMixin +from django.forms import modelformset_factory +from django.urls import reverse +from api.views.transaction_views import TransactionsViewMixin +from api.models import Transaction, JournalEntryItem, Paystub, PaystubValue, JournalEntry, S3File +from api.forms import ( + TransactionFilterForm, JournalEntryItemForm, + BaseJournalEntryItemFormset, JournalEntryMetadataForm +) + +class JournalEntryViewMixin: + entry_form_template = 'api/entry_forms/journal-entry-item-form.html' + + def get_paystubs_table_html(self): + oustanding_textract_job_files = S3File.objects.filter(documents__isnull=True) + for outstanding_textract_job_file in oustanding_textract_job_files: + outstanding_textract_job_file.create_paystubs_from_textract_data() + + paystubs = Paystub.objects.filter(journal_entry__isnull=True).prefetch_related('paystub_values').select_related('document') + paystubs_template = 'api/tables/paystubs-table.html' + return render_to_string(paystubs_template, {'paystubs': paystubs}) + + def get_combined_formset_errors( + self, debit_formset, credit_formset + ): + form_errors = [] + debit_total = debit_formset.get_entry_total() + credit_total = credit_formset.get_entry_total() + if debit_total != credit_total: + form_errors.append('Debits ($' + str(debit_total) + ') and Credits ($' + str(credit_total) + ') must balance.') + + print(form_errors) + return form_errors + + def check_for_errors(self, request, debit_formset, credit_formset, metadata_form, transaction): + has_errors = False + form_errors = [] + # Check if formsets have errors on their own, then check if they have errors + # in the aggregate (e.g., don't have balanced credits/debits) + if debit_formset.is_valid() and credit_formset.is_valid() and metadata_form.is_valid(): + form_errors = self.get_combined_formset_errors( + debit_formset=debit_formset, + credit_formset=credit_formset + ) + has_errors = bool(form_errors) + else: + print(debit_formset.errors) + print(credit_formset.errors) + print(metadata_form.errors) + has_errors = True + + if not has_errors: + return False, None + + context = { + 'debit_formset': debit_formset, + 'credit_formset': credit_formset, + 'transaction_id': transaction.id, + 'autofocus_debit': True, + 'form_errors': form_errors, + 'prefilled_total': debit_formset.get_entry_total(), + 'debit_prefilled_total': debit_formset.get_entry_total(), + 'credit_prefilled_total': credit_formset.get_entry_total(), + 'metadata_form': metadata_form + } + + html = render_to_string(self.entry_form_template, context) + response = HttpResponse(html) + response.headers['HX-Retarget'] = '#form-div' + return True, response + + def get_journal_entry_form_html( + self, transaction, index=0, debit_formset=None, + credit_formset=None, is_debit=True, form_errors=None, + paystub_id=None): + + if not transaction: + return '' + + context = {} + + if not (debit_formset and credit_formset): + try: + journal_entry = transaction.journal_entry + journal_entry_items = JournalEntryItem.objects.filter( + journal_entry=journal_entry + ) + journal_entry_debits = journal_entry_items.filter( + type=JournalEntryItem.JournalEntryType.DEBIT + ) + journal_entry_credits = journal_entry_items.filter( + type=JournalEntryItem.JournalEntryType.CREDIT + ) + bound_debits_count = journal_entry_debits.count() + bound_credits_count = journal_entry_credits.count() + except JournalEntry.DoesNotExist: + bound_debits_count = 0 + bound_credits_count = 0 + journal_entry_debits = JournalEntryItem.objects.none() + journal_entry_credits = JournalEntryItem.objects.none() + + debits_initial_data = [] + credits_initial_data = [] + + if transaction.amount >= 0: + is_debit = True + else: + is_debit = False + + prefill_debits_count = 0 + prefill_credits_count = 0 + if bound_debits_count + bound_credits_count == 0: + # TODO: Here's where I would insert the paystub prefills + primary_account, secondary_account = (transaction.account, transaction.suggested_account) \ + if is_debit else (transaction.suggested_account, transaction.account) + + debits_initial_data.append({ + 'account': getattr(primary_account, 'name', None), + 'amount': abs(transaction.amount) + }) + + credits_initial_data.append({ + 'account': getattr(secondary_account, 'name', None), + 'amount': abs(transaction.amount) + }) + + if transaction.prefill: + prefill_items = transaction.prefill.prefillitem_set.all().order_by('order') + for item in prefill_items: + if item.journal_entry_item_type == JournalEntryItem.JournalEntryType.DEBIT: + debits_initial_data.append( + {'account': item.account.name, 'amount': 0} + ) + prefill_debits_count += 1 + else: + credits_initial_data.append({'account': item.account.name, 'amount': 0}) + prefill_credits_count += 1 + + if paystub_id: + paystub_values = PaystubValue.objects.filter(paystub__pk=paystub_id).select_related('account') + debits_initial_data = [] + credits_initial_data = [] + prefill_debits_count = 0 + prefill_credits_count = 0 + for paystub_value in paystub_values: + if paystub_value.journal_entry_item_type == JournalEntryItem.JournalEntryType.DEBIT: + debits_initial_data.append( + {'account': paystub_value.account.name, 'amount': paystub_value.amount} + ) + prefill_debits_count += 1 + else: + credits_initial_data.append( + {'account': paystub_value.account.name, 'amount': paystub_value.amount} + ) + prefill_credits_count += 1 + + + debit_formset = modelformset_factory(JournalEntryItem, form=JournalEntryItemForm, formset=BaseJournalEntryItemFormset, extra=max((10-bound_debits_count), prefill_debits_count)) + credit_formset = modelformset_factory(JournalEntryItem, form=JournalEntryItemForm, formset=BaseJournalEntryItemFormset, extra=max((10-bound_credits_count), prefill_credits_count)) + + debit_formset = debit_formset(queryset=journal_entry_debits, initial=debits_initial_data, prefix='debits') + credit_formset = credit_formset(queryset=journal_entry_credits, initial=credits_initial_data, prefix='credits') + + metadata = { + 'index': index, + 'paystub_id': paystub_id + } + metadata_form = JournalEntryMetadataForm(initial=metadata) + # Set the total amounts for the debit and credits + debit_prefilled_total = debit_formset.get_entry_total() + credit_prefilled_total = credit_formset.get_entry_total() + context = { + 'debit_formset': debit_formset, + 'credit_formset': credit_formset, + 'transaction_id': transaction.id, + 'autofocus_debit': is_debit, + 'form_errors': form_errors, + 'debit_prefilled_total': debit_prefilled_total, + 'credit_prefilled_total': credit_prefilled_total, + 'metadata_form': metadata_form + } + + return render_to_string(self.entry_form_template, context) + + +# Called every time the page is filtered +class JournalEntryTableView(TransactionsViewMixin, JournalEntryViewMixin, LoginRequiredMixin, View): + login_url = '/login/' + redirect_field_name = 'next' + + def get(self, request, *args, **kwargs): + form = TransactionFilterForm(request.GET, prefix='filter') + if form.is_valid(): + transactions = form.get_transactions() + table_html = self.get_table_html( + transactions=transactions, + row_url=reverse('journal-entries') + ) + try: + transaction = transactions[0] + except IndexError: + transaction = None + entry_form_html = self.get_journal_entry_form_html( + transaction=transaction + ) + paystubs_table_html = self.get_paystubs_table_html() + view_template = 'api/views/journal-entry-view.html' + context = { + 'entry_form': entry_form_html, + 'table': table_html, + 'paystubs_table': paystubs_table_html, + 'transaction_id': transaction.id, + 'index': 0 + } + + html = render_to_string(view_template, context) + return HttpResponse(html) + + +# Called every time a table row is clicked +# TODO: WTF shoudl I do here +class JournalEntryFormView(TransactionsViewMixin, JournalEntryViewMixin, LoginRequiredMixin, View): + login_url = '/login/' + redirect_field_name = 'next' + item_form_template = 'api/entry_forms/journal-entry-item-form.html' + + def get(self, request, transaction_id): + transaction = Transaction.objects.get(pk=transaction_id) + paystub_id = request.GET.get('paystub_id') + entry_form_html = self.get_journal_entry_form_html( + transaction=transaction, + index=request.GET.get('row_index'), + paystub_id=paystub_id + ) + + return HttpResponse(entry_form_html) + +class PaystubDetailView(TransactionsViewMixin, LoginRequiredMixin, View): + + def get(self, request, paystub_id): + paystub_values = PaystubValue.objects.filter(paystub__pk=paystub_id).select_related('account') + template = 'api/tables/paystubs-table.html' + html = render_to_string( + template, + { + 'paystub_values': paystub_values, + 'paystub_id': paystub_id + } + ) + return HttpResponse(html) + +# Called as the main page +class JournalEntryView(TransactionsViewMixin, JournalEntryViewMixin, LoginRequiredMixin, View): + login_url = '/login/' + redirect_field_name = 'next' + view_template = 'api/views/journal-entry-view.html' + + def get(self, request): + # Collect HTML for all components in view + filter_form_html, transactions = self.get_filter_form_html_and_objects( + is_closed=False, + transaction_type=[ + Transaction.TransactionType.INCOME, + Transaction.TransactionType.PURCHASE + ], + get_url=reverse('journal-entries-table') + ) + table_html = self.get_table_html( + transactions=transactions, + row_url=reverse('journal-entries') + ) + try: + transaction = transactions[0] + except IndexError: + transaction = None + entry_form_html = self.get_journal_entry_form_html( + transaction=transaction + ) + paystubs_table_html = self.get_paystubs_table_html() + context = { + 'filter_form': filter_form_html, + 'table': table_html, + 'entry_form': entry_form_html, + 'paystubs_table': paystubs_table_html, + 'index': 0, + 'transaction_id': transactions[0].pk, + 'is_initial_load': True + } + + html = render_to_string(self.view_template, context) + return HttpResponse(html) + + def post(self, request, transaction_id): + # Build formsets for the credit and debit side of the JE and get transaction + # and metadata form + JournalEntryItemFormset = modelformset_factory( + JournalEntryItem, + formset=BaseJournalEntryItemFormset, + form=JournalEntryItemForm + ) + debit_formset = JournalEntryItemFormset(request.POST, prefix='debits') + credit_formset = JournalEntryItemFormset( + request.POST, + prefix='credits' + ) + metadata_form = JournalEntryMetadataForm(request.POST) + transaction = get_object_or_404(Transaction, pk=transaction_id) + + # First check if the forms are valid and return errors if not + has_errors, response = self.check_for_errors( + debit_formset=debit_formset, + credit_formset=credit_formset, + request=request, + transaction=transaction, + metadata_form=metadata_form + ) + if has_errors: + return response + + debit_formset.save( + transaction, + JournalEntryItem.JournalEntryType.DEBIT + ) + credit_formset.save( + transaction, + JournalEntryItem.JournalEntryType.CREDIT + ) + transaction.close() + + # If there's an attached paystub in the GET request, close it out + paystub_id = metadata_form.cleaned_data.get('paystub_id') + try: + paystub = Paystub.objects.get(pk=paystub_id) + paystub.journal_entry = transaction.journal_entry + paystub.save() + except ValueError: + pass + + # Build the transactions table — use the existing filter settings if valid, + # else return all transactions + filter_form = TransactionFilterForm(request.POST, prefix='filter') + if filter_form.is_valid(): + transactions = filter_form.get_transactions() + index = metadata_form.cleaned_data['index'] + else: + _, transactions = self.get_filter_form_html_and_objects( + is_closed=False, + transaction_type=[ + Transaction.TransactionType.INCOME, + Transaction.TransactionType.PURCHASE + ] + ) + index = 0 + + if len(transactions) == 0: + entry_form_html = '' + else: + # Need to check an index error in case + # user chose the last entry + try: + highlighted_transaction = transactions[index] + except IndexError: + index = 0 + highlighted_transaction = transactions[index] + entry_form_html = self.get_journal_entry_form_html( + transaction=highlighted_transaction, + index=index + ) + + table_html = self.get_table_html( + transactions=transactions, + index=index, + row_url=reverse('journal-entries') + ) + paystubs_table_html = self.get_paystubs_table_html() + context = { + 'table': table_html, + 'entry_form': entry_form_html, + 'index': index, + 'transaction_id': transactions[index].pk, + 'paystubs_table': paystubs_table_html + } + html = render_to_string(self.view_template, context) + return HttpResponse(html) \ No newline at end of file diff --git a/api/views/transaction_views.py b/api/views/transaction_views.py index 8c14661..2ce2c27 100644 --- a/api/views/transaction_views.py +++ b/api/views/transaction_views.py @@ -4,28 +4,16 @@ from django.views import View from django.shortcuts import get_object_or_404 from django.contrib.auth.mixins import LoginRequiredMixin -from django.forms import modelformset_factory from django.urls import reverse -from api.models import Transaction, JournalEntry, JournalEntryItem, Paystub, PaystubValue, S3File +from api.models import Transaction from api.forms import ( - TransactionLinkForm, TransactionFilterForm, JournalEntryItemForm, - BaseJournalEntryItemFormset, TransactionForm + TransactionLinkForm, TransactionFilterForm, TransactionForm ) from api import utils class TransactionsViewMixin: filter_form_template = 'api/filter_forms/transactions-filter-form.html' - entry_form_template = 'api/entry_forms/journal-entry-item-form.html' - - def get_paystubs_table_html(self): - oustanding_textract_job_files = S3File.objects.filter(documents__isnull=True) - for outstanding_textract_job_file in oustanding_textract_job_files: - outstanding_textract_job_file.create_paystubs_from_textract_data() - - paystubs = Paystub.objects.filter(journal_entry__isnull=True).prefetch_related('paystub_values') - paystubs_template = 'api/tables/paystubs-table.html' - return render_to_string(paystubs_template, {'paystubs': paystubs}) def get_filter_form_html_and_objects( self, @@ -94,115 +82,6 @@ def get_transaction_form_html( ) return form_html - def get_journal_entry_form_html( - self, transaction, index=0, debit_formset=None, - credit_formset=None, is_debit=True, form_errors=None, - paystub_id=None): - if not transaction: - return '' - - context = {} - - if not (debit_formset and credit_formset): - try: - journal_entry = transaction.journal_entry - journal_entry_items = JournalEntryItem.objects.filter( - journal_entry=journal_entry - ) - journal_entry_debits = journal_entry_items.filter( - type=JournalEntryItem.JournalEntryType.DEBIT - ) - journal_entry_credits = journal_entry_items.filter( - type=JournalEntryItem.JournalEntryType.CREDIT - ) - bound_debits_count = journal_entry_debits.count() - bound_credits_count = journal_entry_credits.count() - except JournalEntry.DoesNotExist: - bound_debits_count = 0 - bound_credits_count = 0 - journal_entry_debits = JournalEntryItem.objects.none() - journal_entry_credits = JournalEntryItem.objects.none() - - debits_initial_data = [] - credits_initial_data = [] - - if transaction.amount >= 0: - is_debit = True - else: - is_debit = False - - prefill_debits_count = 0 - prefill_credits_count = 0 - if bound_debits_count + bound_credits_count == 0: - # TODO: Here's where I would insert the paystub prefills - primary_account, secondary_account = (transaction.account, transaction.suggested_account) \ - if is_debit else (transaction.suggested_account, transaction.account) - - debits_initial_data.append({ - 'account': getattr(primary_account, 'name', None), - 'amount': abs(transaction.amount) - }) - - credits_initial_data.append({ - 'account': getattr(secondary_account, 'name', None), - 'amount': abs(transaction.amount) - }) - - if transaction.prefill: - prefill_items = transaction.prefill.prefillitem_set.all().order_by('order') - for item in prefill_items: - if item.journal_entry_item_type == JournalEntryItem.JournalEntryType.DEBIT: - debits_initial_data.append( - {'account': item.account.name, 'amount': 0} - ) - prefill_debits_count += 1 - else: - credits_initial_data.append({'account': item.account.name, 'amount': 0}) - prefill_credits_count += 1 - - if paystub_id: - paystub_values = PaystubValue.objects.filter(paystub__pk=paystub_id).select_related('account') - debits_initial_data = [] - credits_initial_data = [] - prefill_debits_count = 0 - prefill_credits_count = 0 - for paystub_value in paystub_values: - if paystub_value.journal_entry_item_type == JournalEntryItem.JournalEntryType.DEBIT: - debits_initial_data.append( - {'account': paystub_value.account.name, 'amount': paystub_value.amount} - ) - prefill_debits_count += 1 - else: - credits_initial_data.append({'account': item.account.name, 'amount': 0}) - prefill_credits_count += 1 - - - debit_formset = modelformset_factory(JournalEntryItem, form=JournalEntryItemForm, formset=BaseJournalEntryItemFormset, extra=max((10-bound_debits_count), prefill_debits_count)) - credit_formset = modelformset_factory(JournalEntryItem, form=JournalEntryItemForm, formset=BaseJournalEntryItemFormset, extra=max((10-bound_credits_count), prefill_credits_count)) - - debit_formset = debit_formset(queryset=journal_entry_debits, initial=debits_initial_data, prefix='debits') - credit_formset = credit_formset(queryset=journal_entry_credits, initial=credits_initial_data, prefix='credits') - - # Set the total amounts for the debit and credits - prefilled_total = 0 - for form in debit_formset: - try: - prefilled_total += form.initial['amount'] - except KeyError: - pass - context = { - 'debit_formset': debit_formset, - 'credit_formset': credit_formset, - 'transaction_id': transaction.id, - 'index': index, - 'autofocus_debit': is_debit, - 'form_errors': form_errors, - 'prefilled_total': prefilled_total, - 'paystub_id': paystub_id - } - - return render_to_string(self.entry_form_template, context) - def get_link_form_html(self): entry_form_template = 'api/entry_forms/transaction-link-form.html' html = render_to_string( @@ -417,223 +296,4 @@ def post(self, request): return HttpResponse(html) print(form.errors) - print(form.non_field_errors()) - -# ------------------Journal Entries View----------------------- - - -# Called every time the page is filtered -class JournalEntryTableView(TransactionsViewMixin, LoginRequiredMixin, View): - login_url = '/login/' - redirect_field_name = 'next' - - def get(self, request, *args, **kwargs): - form = TransactionFilterForm(request.GET, prefix='filter') - if form.is_valid(): - transactions = form.get_transactions() - table_html = self.get_table_html( - transactions=transactions, - row_url=reverse('journal-entries') - ) - try: - transaction = transactions[0] - except IndexError: - transaction = None - entry_form_html = self.get_journal_entry_form_html( - transaction=transaction - ) - content_template = 'api/content/journal-entry-content.html' - context = { - 'entry_form': entry_form_html, - 'table': table_html - } - - html = render_to_string(content_template, context) - return HttpResponse(html) - - -# Called every time a table row is clicked -class JournalEntryFormView(TransactionsViewMixin, LoginRequiredMixin, View): - login_url = '/login/' - redirect_field_name = 'next' - item_form_template = 'api/entry_forms/journal-entry-item-form.html' - - def get(self, request, transaction_id): - transaction = Transaction.objects.get(pk=transaction_id) - paystub_id = None if 'paystub_id' not in request.GET else request.GET.get('paystub_id') - entry_form_html = self.get_journal_entry_form_html( - transaction=transaction, - index=request.GET.get('row_index'), - paystub_id=paystub_id - ) - - return HttpResponse(entry_form_html) - -class PaystubDetailView(TransactionsViewMixin, LoginRequiredMixin, View): - - def get(self, request, paystub_id): - paystub_values = PaystubValue.objects.filter(paystub__pk=paystub_id) - template = 'api/tables/paystubs-table.html' - html = render_to_string( - template, - { - 'paystub_values': paystub_values, - 'paystub_id': paystub_id - } - ) - return HttpResponse(html) - -# Called as the main page -class JournalEntryView(TransactionsViewMixin, LoginRequiredMixin, View): - login_url = '/login/' - redirect_field_name = 'next' - view_template = 'api/views/journal-entry-view.html' - content_template = 'api/content/journal-entry-content.html' - - def get(self, request): - filter_form_html, transactions = self.get_filter_form_html_and_objects( - is_closed=False, - transaction_type=[ - Transaction.TransactionType.INCOME, - Transaction.TransactionType.PURCHASE - ], - get_url=reverse('journal-entries-table') - ) - table_html = self.get_table_html( - transactions=transactions, - row_url=reverse('journal-entries') - ) - try: - transaction = transactions[0] - except IndexError: - transaction = None - entry_form_html = self.get_journal_entry_form_html( - transaction=transaction - ) - paystubs_table_html = self.get_paystubs_table_html() - context = { - 'filter_form': filter_form_html, - 'table': table_html, - 'entry_form': entry_form_html, - 'paystubs_table': paystubs_table_html, - 'index': 0, - 'transaction_id': transactions[0].pk, - 'is_initial_load': True - } - - html = render_to_string(self.view_template, context) - return HttpResponse(html) - - def _get_combined_formset_errors( - self, debit_formset, credit_formset, transaction - ): - form_errors = [] - debit_total = debit_formset.get_entry_total() - credit_total = credit_formset.get_entry_total() - if debit_total != credit_total: - form_errors.append('Debits ($' + str(debit_total) + ') and Credits ($' + str(credit_total) + ') must balance.') - - print(form_errors) - return form_errors - - def post(self, request, transaction_id): - JournalEntryItemFormset = modelformset_factory( - JournalEntryItem, - formset=BaseJournalEntryItemFormset, - form=JournalEntryItemForm - ) - debit_formset = JournalEntryItemFormset(request.POST, prefix='debits') - credit_formset = JournalEntryItemFormset( - request.POST, - prefix='credits' - ) - transaction = get_object_or_404(Transaction, pk=transaction_id) - - # First check if the forms are valid and create JEIs if so - has_errors = False - form_errors = [] - if debit_formset.is_valid() and credit_formset.is_valid(): - form_errors = self._get_combined_formset_errors( - debit_formset=debit_formset, - credit_formset=credit_formset, - transaction=transaction - ) - has_errors = bool(form_errors) - else: - print(debit_formset.errors) - has_errors = True - - if not has_errors: - debit_formset.save( - transaction, - JournalEntryItem.JournalEntryType.DEBIT - ) - credit_formset.save( - transaction, - JournalEntryItem.JournalEntryType.CREDIT - ) - transaction.close() - paystub_id = request.POST.get('paystub_id') - try: - paystub = Paystub.objects.get(pk=paystub_id) - paystub.journal_entry = transaction.journal_entry - paystub.save() - except ValueError: - pass - - # Build the transactions table — use the filter settings if valid, - # else return all transactions - filter_form = TransactionFilterForm(request.POST, prefix='filter') - if filter_form.is_valid(): - transactions = filter_form.get_transactions() - # Default to 0 if 'index' is not provided - index = int(request.POST.get('index', 0)) - else: - _, transactions = self.get_filter_form_html_and_objects( - is_closed=False, - transaction_type=[ - Transaction.TransactionType.INCOME, - Transaction.TransactionType.PURCHASE - ] - ) - index = 0 - - # If either form has errors, return the forms to render the errors, - # else build it - if has_errors: - entry_form_html = self.get_journal_entry_form_html( - transaction=transaction, - index=index, - debit_formset=debit_formset, - credit_formset=credit_formset, - form_errors=form_errors - ) - else: - if len(transactions) == 0: - entry_form_html = None - else: - # Need to check an index error in case - # user chose the last entry - try: - highlighted_transaction = transactions[index] - except IndexError: - index = 0 - highlighted_transaction = transactions[index] - entry_form_html = self.get_journal_entry_form_html( - transaction=highlighted_transaction, - index=index - ) - - table_html = self.get_table_html( - transactions=transactions, - index=index, - row_url=reverse('journal-entries') - ) - context = { - 'table': table_html, - 'entry_form': entry_form_html, - 'index': index, - 'transaction_id': transactions[index].pk - } - html = render_to_string(self.view_template, context) - return HttpResponse(html) + print(form.non_field_errors()) \ No newline at end of file diff --git a/ledger/templates/api/content/journal-entry-content-depr.html b/ledger/templates/api/content/journal-entry-content-depr.html deleted file mode 100644 index 1c35623..0000000 --- a/ledger/templates/api/content/journal-entry-content-depr.html +++ /dev/null @@ -1,6 +0,0 @@ -{{ table }} -{% include "api/components/clickable-row-script.html" %} -{% include "api/components/transactions-scroll.html" %} -
- {{ entry_form }} -
\ No newline at end of file diff --git a/ledger/templates/api/content/transactions-content.html b/ledger/templates/api/content/transactions-content.html index afd4542..747eb3a 100644 --- a/ledger/templates/api/content/transactions-content.html +++ b/ledger/templates/api/content/transactions-content.html @@ -1,5 +1,7 @@ -{{ table }} -
-
-{{ transactions_form }} +
+ {{ table }} +
+
+ {{ transactions_form }} +
\ No newline at end of file diff --git a/ledger/templates/api/content/transactions-link-content.html b/ledger/templates/api/content/transactions-link-content.html index 20fd9ed..d374fab 100644 --- a/ledger/templates/api/content/transactions-link-content.html +++ b/ledger/templates/api/content/transactions-link-content.html @@ -1,5 +1,7 @@ -{{ table }} -{% include "api/components/two-row-select-script.html" %} -