django-ledger 0.8.0__py3-none-any.whl → 0.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of django-ledger might be problematic. Click here for more details.
- django_ledger/__init__.py +1 -1
- django_ledger/forms/account.py +45 -46
- django_ledger/forms/data_import.py +182 -64
- django_ledger/io/io_core.py +507 -374
- django_ledger/migrations/0026_stagedtransactionmodel_customer_model_and_more.py +56 -0
- django_ledger/models/__init__.py +2 -1
- django_ledger/models/bill.py +337 -300
- django_ledger/models/customer.py +47 -34
- django_ledger/models/data_import.py +770 -289
- django_ledger/models/entity.py +882 -637
- django_ledger/models/mixins.py +421 -282
- django_ledger/models/receipt.py +1083 -0
- django_ledger/models/transactions.py +105 -41
- django_ledger/models/unit.py +42 -30
- django_ledger/models/utils.py +12 -2
- django_ledger/models/vendor.py +85 -66
- django_ledger/settings.py +1 -0
- django_ledger/static/django_ledger/bundle/djetler.bundle.js +1 -1
- django_ledger/static/django_ledger/bundle/djetler.bundle.js.LICENSE.txt +1 -13
- django_ledger/templates/django_ledger/bills/bill_update.html +1 -1
- django_ledger/templates/django_ledger/components/period_navigator.html +5 -3
- django_ledger/templates/django_ledger/customer/customer_detail.html +87 -0
- django_ledger/templates/django_ledger/customer/customer_list.html +0 -1
- django_ledger/templates/django_ledger/customer/tags/customer_table.html +3 -1
- django_ledger/templates/django_ledger/data_import/tags/data_import_job_txs_imported.html +24 -3
- django_ledger/templates/django_ledger/data_import/tags/data_import_job_txs_table.html +26 -10
- django_ledger/templates/django_ledger/entity/entity_dashboard.html +2 -2
- django_ledger/templates/django_ledger/invoice/invoice_update.html +1 -1
- django_ledger/templates/django_ledger/layouts/base.html +3 -1
- django_ledger/templates/django_ledger/layouts/content_layout_1.html +1 -1
- django_ledger/templates/django_ledger/receipt/customer_receipt_report.html +115 -0
- django_ledger/templates/django_ledger/receipt/receipt_delete.html +30 -0
- django_ledger/templates/django_ledger/receipt/receipt_detail.html +89 -0
- django_ledger/templates/django_ledger/receipt/receipt_list.html +134 -0
- django_ledger/templates/django_ledger/receipt/vendor_receipt_report.html +115 -0
- django_ledger/templates/django_ledger/vendor/tags/vendor_table.html +3 -2
- django_ledger/templates/django_ledger/vendor/vendor_detail.html +86 -0
- django_ledger/templatetags/django_ledger.py +338 -191
- django_ledger/urls/__init__.py +1 -0
- django_ledger/urls/customer.py +3 -0
- django_ledger/urls/data_import.py +3 -0
- django_ledger/urls/receipt.py +102 -0
- django_ledger/urls/vendor.py +1 -0
- django_ledger/views/__init__.py +1 -0
- django_ledger/views/customer.py +56 -14
- django_ledger/views/data_import.py +119 -66
- django_ledger/views/mixins.py +112 -86
- django_ledger/views/receipt.py +294 -0
- django_ledger/views/vendor.py +53 -14
- {django_ledger-0.8.0.dist-info → django_ledger-0.8.2.dist-info}/METADATA +1 -1
- {django_ledger-0.8.0.dist-info → django_ledger-0.8.2.dist-info}/RECORD +55 -45
- django_ledger/static/django_ledger/bundle/styles.bundle.js +0 -1
- {django_ledger-0.8.0.dist-info → django_ledger-0.8.2.dist-info}/WHEEL +0 -0
- {django_ledger-0.8.0.dist-info → django_ledger-0.8.2.dist-info}/licenses/AUTHORS.md +0 -0
- {django_ledger-0.8.0.dist-info → django_ledger-0.8.2.dist-info}/licenses/LICENSE +0 -0
- {django_ledger-0.8.0.dist-info → django_ledger-0.8.2.dist-info}/top_level.txt +0 -0
django_ledger/__init__.py
CHANGED
django_ledger/forms/account.py
CHANGED
|
@@ -5,10 +5,19 @@ Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
|
|
|
5
5
|
Contributions to this module:
|
|
6
6
|
* Miguel Sanda <msanda@arrobalytics.com>
|
|
7
7
|
"""
|
|
8
|
+
|
|
8
9
|
from random import randint
|
|
9
10
|
from typing import Optional
|
|
10
11
|
|
|
11
|
-
from django.forms import
|
|
12
|
+
from django.forms import (
|
|
13
|
+
TextInput,
|
|
14
|
+
Select,
|
|
15
|
+
ModelForm,
|
|
16
|
+
ChoiceField,
|
|
17
|
+
ValidationError,
|
|
18
|
+
CheckboxInput,
|
|
19
|
+
HiddenInput,
|
|
20
|
+
)
|
|
12
21
|
from django.utils.translation import gettext_lazy as _
|
|
13
22
|
from treebeard.forms import MoveNodeForm
|
|
14
23
|
|
|
@@ -62,25 +71,27 @@ class AccountModelCreateForm(ModelForm):
|
|
|
62
71
|
'balance_type',
|
|
63
72
|
'active',
|
|
64
73
|
'active',
|
|
65
|
-
'coa_model'
|
|
74
|
+
'coa_model',
|
|
66
75
|
]
|
|
67
76
|
widgets = {
|
|
68
|
-
'code': TextInput(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
'
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
'code': TextInput(
|
|
78
|
+
attrs={
|
|
79
|
+
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES,
|
|
80
|
+
'placeholder': _(
|
|
81
|
+
'Alpha Numeric (auto generated if not provided)...'
|
|
82
|
+
),
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
'name': TextInput(
|
|
86
|
+
attrs={
|
|
87
|
+
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES,
|
|
88
|
+
'placeholder': _('Account Name...'),
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
'role': Select(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES}),
|
|
79
92
|
'role_default': CheckboxInput(),
|
|
80
|
-
'balance_type': Select(attrs={
|
|
81
|
-
|
|
82
|
-
}),
|
|
83
|
-
'coa_model': HiddenInput()
|
|
93
|
+
'balance_type': Select(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES}),
|
|
94
|
+
'coa_model': HiddenInput(),
|
|
84
95
|
}
|
|
85
96
|
|
|
86
97
|
|
|
@@ -88,7 +99,7 @@ class AccountModelUpdateForm(MoveNodeForm):
|
|
|
88
99
|
"""
|
|
89
100
|
AccountModelUpdateForm
|
|
90
101
|
|
|
91
|
-
A form for updating account model, inheriting from MoveNodeForm.
|
|
102
|
+
A form for updating the account model, inheriting from MoveNodeForm.
|
|
92
103
|
|
|
93
104
|
Attributes
|
|
94
105
|
----------
|
|
@@ -98,36 +109,32 @@ class AccountModelUpdateForm(MoveNodeForm):
|
|
|
98
109
|
An optional choice field for selecting the relative node.
|
|
99
110
|
"""
|
|
100
111
|
|
|
101
|
-
_position = ChoiceField(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
_ref_node_id = ChoiceField(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
_position = ChoiceField(
|
|
113
|
+
required=True,
|
|
114
|
+
label=_('Position'),
|
|
115
|
+
widget=Select(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES}),
|
|
116
|
+
)
|
|
117
|
+
_ref_node_id = ChoiceField(
|
|
118
|
+
required=False,
|
|
119
|
+
label=_('Relative to'),
|
|
120
|
+
widget=Select(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES}),
|
|
121
|
+
)
|
|
112
122
|
|
|
113
123
|
def __init__(self, *args, **kwargs):
|
|
114
124
|
super().__init__(*args, **kwargs)
|
|
115
125
|
self.fields['role'].disabled = True
|
|
116
126
|
self.fields['coa_model'].disabled = True
|
|
117
127
|
|
|
118
|
-
|
|
119
128
|
@classmethod
|
|
120
129
|
def mk_dropdown_tree(cls, model, for_node: Optional[AccountModel] = None):
|
|
121
|
-
"""
|
|
130
|
+
"""Creates a tree-like list of choices"""
|
|
122
131
|
|
|
123
132
|
if not for_node:
|
|
124
133
|
raise ValidationError(message='Must provide for_node argument.')
|
|
125
134
|
|
|
126
135
|
qs = for_node.get_account_move_choice_queryset()
|
|
127
136
|
|
|
128
|
-
return [
|
|
129
|
-
(i.uuid, f'{"-" * (i.depth - 1)} {i}') for i in qs
|
|
130
|
-
]
|
|
137
|
+
return [(i.uuid, f'{"-" * (i.depth - 1)} {i}') for i in qs]
|
|
131
138
|
|
|
132
139
|
def clean_role(self):
|
|
133
140
|
return self.instance.role
|
|
@@ -147,17 +154,9 @@ class AccountModelUpdateForm(MoveNodeForm):
|
|
|
147
154
|
widgets = {
|
|
148
155
|
'role': HiddenInput(),
|
|
149
156
|
'coa_model': HiddenInput(),
|
|
150
|
-
'parent': Select(attrs={
|
|
151
|
-
|
|
152
|
-
}),
|
|
153
|
-
'
|
|
154
|
-
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
155
|
-
}),
|
|
156
|
-
'code': TextInput(attrs={
|
|
157
|
-
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
158
|
-
}),
|
|
159
|
-
'name': TextInput(attrs={
|
|
160
|
-
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
161
|
-
}),
|
|
157
|
+
'parent': Select(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES}),
|
|
158
|
+
'balance_type': Select(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES}),
|
|
159
|
+
'code': TextInput(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES}),
|
|
160
|
+
'name': TextInput(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES}),
|
|
162
161
|
'role_default': CheckboxInput(),
|
|
163
162
|
}
|
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
from django import forms
|
|
2
2
|
from django.forms import (
|
|
3
|
-
ModelForm,
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
ModelForm,
|
|
4
|
+
BaseModelFormSet,
|
|
5
|
+
modelformset_factory,
|
|
6
|
+
Select,
|
|
7
|
+
NumberInput,
|
|
8
|
+
HiddenInput,
|
|
9
|
+
TextInput,
|
|
10
|
+
ValidationError,
|
|
6
11
|
)
|
|
7
12
|
from django.utils.translation import gettext_lazy as _
|
|
8
13
|
|
|
14
|
+
from django_ledger.io import GROUP_EXPENSES, GROUP_INCOME
|
|
9
15
|
from django_ledger.models import (
|
|
10
16
|
StagedTransactionModel,
|
|
11
17
|
ImportJobModel,
|
|
12
|
-
EntityModel
|
|
18
|
+
EntityModel,
|
|
13
19
|
)
|
|
14
20
|
from django_ledger.settings import DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
15
21
|
|
|
16
22
|
|
|
17
23
|
class ImportJobModelCreateForm(ModelForm):
|
|
18
|
-
|
|
19
24
|
def __init__(self, entity_model: EntityModel, *args, **kwargs):
|
|
20
25
|
super().__init__(*args, **kwargs)
|
|
21
26
|
self.ENTITY_MODEL: EntityModel = entity_model
|
|
22
|
-
self.fields[
|
|
27
|
+
self.fields[
|
|
28
|
+
'bank_account_model'
|
|
29
|
+
].queryset = self.ENTITY_MODEL.bankaccountmodel_set.all().active()
|
|
23
30
|
|
|
24
31
|
ofx_file = forms.FileField(
|
|
25
32
|
label='Select File...',
|
|
26
33
|
required=True,
|
|
27
|
-
widget=forms.FileInput(
|
|
28
|
-
attrs={
|
|
29
|
-
'class': 'file-input',
|
|
30
|
-
'accept': '.ofx,.qfx'
|
|
31
|
-
})
|
|
34
|
+
widget=forms.FileInput(attrs={'class': 'file-input', 'accept': '.ofx,.qfx'}),
|
|
32
35
|
)
|
|
33
36
|
|
|
34
37
|
class Meta:
|
|
@@ -38,30 +41,31 @@ class ImportJobModelCreateForm(ModelForm):
|
|
|
38
41
|
'description',
|
|
39
42
|
]
|
|
40
43
|
widgets = {
|
|
41
|
-
'description': TextInput(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
'description': TextInput(
|
|
45
|
+
attrs={
|
|
46
|
+
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-large',
|
|
47
|
+
'placeholder': _('Name this import...'),
|
|
48
|
+
}
|
|
49
|
+
),
|
|
45
50
|
'bank_account_model': Select(
|
|
46
51
|
attrs={
|
|
47
52
|
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES,
|
|
48
|
-
}
|
|
53
|
+
}
|
|
54
|
+
),
|
|
49
55
|
}
|
|
50
56
|
help_texts = {
|
|
51
|
-
'bank_account_model': _(
|
|
57
|
+
'bank_account_model': _(
|
|
58
|
+
'Select the bank account to import transactions from.'
|
|
59
|
+
),
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
|
|
55
63
|
class ImportJobModelUpdateForm(ModelForm):
|
|
56
64
|
class Meta:
|
|
57
65
|
model = ImportJobModel
|
|
58
|
-
fields = [
|
|
59
|
-
'description'
|
|
60
|
-
]
|
|
66
|
+
fields = ['description']
|
|
61
67
|
widgets = {
|
|
62
|
-
'description': TextInput(attrs={
|
|
63
|
-
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
64
|
-
})
|
|
68
|
+
'description': TextInput(attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES})
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
|
|
@@ -71,37 +75,90 @@ class StagedTransactionModelForm(ModelForm):
|
|
|
71
75
|
|
|
72
76
|
def __init__(self, base_formset_instance, *args, **kwargs):
|
|
73
77
|
super().__init__(*args, **kwargs)
|
|
74
|
-
self.BASE_FORMSET_INSTANCE =
|
|
78
|
+
self.BASE_FORMSET_INSTANCE: 'BaseStagedTransactionModelFormSet' = (
|
|
79
|
+
base_formset_instance
|
|
80
|
+
)
|
|
81
|
+
self.VENDOR_CHOICES = self.BASE_FORMSET_INSTANCE.VENDOR_CHOICES
|
|
82
|
+
self.VENDOR_MAP = self.BASE_FORMSET_INSTANCE.VENDOR_MAP
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
self.CUSTOMER_CHOICES = self.BASE_FORMSET_INSTANCE.CUSTOMER_CHOICES
|
|
85
|
+
self.CUSTOMER_MAP = self.BASE_FORMSET_INSTANCE.CUSTOMER_MAP
|
|
78
86
|
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
self.EXPENSE_ACCOUNT_CHOICES = (
|
|
88
|
+
self.BASE_FORMSET_INSTANCE.ACCOUNT_MODEL_EXPENSES_CHOICES
|
|
89
|
+
)
|
|
90
|
+
self.SALES_ACCOUNT_CHOICES = (
|
|
91
|
+
self.BASE_FORMSET_INSTANCE.ACCOUNT_MODEL_SALES_CHOICES
|
|
92
|
+
)
|
|
93
|
+
self.SHOW_VENDOR_FIELD: bool = False
|
|
94
|
+
self.SHOW_CUSTOMER_FIELD: bool = False
|
|
95
|
+
|
|
96
|
+
staged_tx_model: StagedTransactionModel = getattr(self, 'instance', None)
|
|
97
|
+
|
|
98
|
+
if staged_tx_model.can_migrate_receipt():
|
|
99
|
+
if staged_tx_model.is_expense():
|
|
100
|
+
self.fields['customer_model'].widget = forms.HiddenInput()
|
|
101
|
+
self.fields['vendor_model'].choices = self.VENDOR_CHOICES
|
|
102
|
+
self.fields['account_model'].choices = self.EXPENSE_ACCOUNT_CHOICES
|
|
103
|
+
self.SHOW_VENDOR_FIELD = True
|
|
104
|
+
elif staged_tx_model.is_sales():
|
|
105
|
+
self.fields['vendor_model'].widget = forms.HiddenInput()
|
|
106
|
+
self.fields['customer_model'].choices = self.CUSTOMER_CHOICES
|
|
107
|
+
self.fields['account_model'].choices = self.SALES_ACCOUNT_CHOICES
|
|
108
|
+
self.SHOW_CUSTOMER_FIELD = True
|
|
109
|
+
else:
|
|
110
|
+
self.fields['customer_model'].widget = forms.HiddenInput()
|
|
111
|
+
self.fields['vendor_model'].widget = forms.HiddenInput()
|
|
112
|
+
# avoids multiple DB queries rendering the formset...
|
|
113
|
+
self.fields[
|
|
114
|
+
'account_model'
|
|
115
|
+
].choices = self.BASE_FORMSET_INSTANCE.ACCOUNT_MODEL_CHOICES
|
|
81
116
|
|
|
82
117
|
# avoids multiple DB queries rendering the formset...
|
|
83
|
-
self.fields[
|
|
118
|
+
self.fields[
|
|
119
|
+
'unit_model'
|
|
120
|
+
].choices = self.BASE_FORMSET_INSTANCE.UNIT_MODEL_CHOICES
|
|
84
121
|
|
|
85
|
-
if
|
|
86
|
-
if not
|
|
122
|
+
if staged_tx_model:
|
|
123
|
+
if not staged_tx_model.is_children():
|
|
87
124
|
self.fields['amount_split'].widget = HiddenInput()
|
|
88
125
|
self.fields['amount_split'].disabled = True
|
|
89
126
|
else:
|
|
90
127
|
self.fields['bundle_split'].widget = HiddenInput()
|
|
91
128
|
self.fields['bundle_split'].disabled = True
|
|
92
129
|
|
|
93
|
-
if
|
|
130
|
+
if staged_tx_model.has_children():
|
|
131
|
+
self.fields['receipt_type'].widget = HiddenInput()
|
|
132
|
+
self.fields['receipt_type'].disabled = True
|
|
133
|
+
|
|
134
|
+
if not staged_tx_model.can_have_account():
|
|
94
135
|
self.fields['account_model'].widget = HiddenInput()
|
|
95
136
|
self.fields['account_model'].disabled = True
|
|
96
137
|
|
|
97
|
-
if not
|
|
138
|
+
if not staged_tx_model.can_have_unit():
|
|
98
139
|
self.fields['unit_model'].widget = HiddenInput()
|
|
99
140
|
self.fields['unit_model'].disabled = True
|
|
100
141
|
|
|
101
|
-
|
|
142
|
+
# receipt-related field visibility: not allowed for children rows
|
|
143
|
+
if staged_tx_model.is_children():
|
|
144
|
+
for f in [
|
|
145
|
+
'receipt_type',
|
|
146
|
+
'vendor_model',
|
|
147
|
+
'customer_model',
|
|
148
|
+
'bundle_split',
|
|
149
|
+
]:
|
|
150
|
+
self.fields[f].widget = HiddenInput()
|
|
151
|
+
self.fields[f].disabled = True
|
|
152
|
+
|
|
153
|
+
if staged_tx_model.is_single():
|
|
154
|
+
self.fields['bundle_split'].widget = HiddenInput()
|
|
155
|
+
self.fields['bundle_split'].disabled = True
|
|
156
|
+
|
|
157
|
+
if not staged_tx_model.can_migrate():
|
|
102
158
|
self.fields['tx_import'].widget = HiddenInput()
|
|
103
159
|
self.fields['tx_import'].disabled = True
|
|
104
|
-
|
|
160
|
+
|
|
161
|
+
if not staged_tx_model.can_split():
|
|
105
162
|
self.fields['tx_split'].widget = HiddenInput()
|
|
106
163
|
self.fields['tx_split'].disabled = True
|
|
107
164
|
|
|
@@ -114,8 +171,9 @@ class StagedTransactionModelForm(ModelForm):
|
|
|
114
171
|
def clean_unit_model(self):
|
|
115
172
|
staged_txs_model: StagedTransactionModel = self.instance
|
|
116
173
|
if not staged_txs_model.can_have_unit():
|
|
117
|
-
if staged_txs_model.
|
|
174
|
+
if staged_txs_model.is_children():
|
|
118
175
|
return staged_txs_model.parent.unit_model
|
|
176
|
+
return None
|
|
119
177
|
return self.cleaned_data['unit_model']
|
|
120
178
|
|
|
121
179
|
def clean_tx_import(self):
|
|
@@ -125,10 +183,23 @@ class StagedTransactionModelForm(ModelForm):
|
|
|
125
183
|
return self.cleaned_data['tx_import']
|
|
126
184
|
|
|
127
185
|
def clean(self):
|
|
128
|
-
# cannot import and split at the same time
|
|
129
186
|
if self.cleaned_data['tx_import'] and self.cleaned_data['tx_split']:
|
|
130
187
|
raise ValidationError(message=_('Cannot import and split at the same time'))
|
|
131
188
|
|
|
189
|
+
staged_txs_model: StagedTransactionModel = self.instance
|
|
190
|
+
if all(
|
|
191
|
+
[
|
|
192
|
+
staged_txs_model.has_children(),
|
|
193
|
+
staged_txs_model.has_receipt(),
|
|
194
|
+
not staged_txs_model.bundle_split,
|
|
195
|
+
]
|
|
196
|
+
):
|
|
197
|
+
raise ValidationError(
|
|
198
|
+
message=_(
|
|
199
|
+
'Receipt transactions cannot be split into multiple receipts.'
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
|
|
132
203
|
class Meta:
|
|
133
204
|
model = StagedTransactionModel
|
|
134
205
|
fields = [
|
|
@@ -136,51 +207,98 @@ class StagedTransactionModelForm(ModelForm):
|
|
|
136
207
|
'bundle_split',
|
|
137
208
|
'amount_split',
|
|
138
209
|
'account_model',
|
|
139
|
-
'unit_model'
|
|
210
|
+
'unit_model',
|
|
211
|
+
'receipt_type',
|
|
212
|
+
'vendor_model',
|
|
213
|
+
'customer_model',
|
|
140
214
|
]
|
|
141
215
|
widgets = {
|
|
142
|
-
'account_model': Select(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
216
|
+
'account_model': Select(
|
|
217
|
+
attrs={
|
|
218
|
+
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-small',
|
|
219
|
+
}
|
|
220
|
+
),
|
|
221
|
+
'unit_model': Select(
|
|
222
|
+
attrs={
|
|
223
|
+
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-small',
|
|
224
|
+
}
|
|
225
|
+
),
|
|
226
|
+
'amount_split': NumberInput(
|
|
227
|
+
attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-small'}
|
|
228
|
+
),
|
|
229
|
+
'vendor_model': Select(
|
|
230
|
+
attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-small'}
|
|
231
|
+
),
|
|
232
|
+
'customer_model': Select(
|
|
233
|
+
attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-small'}
|
|
234
|
+
),
|
|
235
|
+
'receipt_type': Select(
|
|
236
|
+
attrs={'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-small'}
|
|
237
|
+
),
|
|
151
238
|
}
|
|
152
239
|
|
|
153
240
|
|
|
154
241
|
class BaseStagedTransactionModelFormSet(BaseModelFormSet):
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
242
|
+
def __init__(
|
|
243
|
+
self,
|
|
244
|
+
*args,
|
|
245
|
+
entity_model: EntityModel,
|
|
246
|
+
import_job_model: ImportJobModel,
|
|
247
|
+
**kwargs,
|
|
248
|
+
):
|
|
160
249
|
super().__init__(*args, **kwargs)
|
|
161
250
|
|
|
162
251
|
# validates that the job import model belongs to the entity model...
|
|
163
252
|
if import_job_model.entity_uuid != entity_model.uuid:
|
|
164
|
-
raise ValidationError(
|
|
253
|
+
raise ValidationError(
|
|
254
|
+
message=_('Import job does not belong to this entity')
|
|
255
|
+
)
|
|
165
256
|
|
|
166
257
|
self.ENTITY_MODEL = entity_model
|
|
167
258
|
self.IMPORT_JOB_MODEL: ImportJobModel = import_job_model
|
|
168
|
-
self.MAPPED_ACCOUNT_MODEL = self.IMPORT_JOB_MODEL.bank_account_model.account_model
|
|
169
259
|
|
|
170
|
-
self.
|
|
171
|
-
|
|
260
|
+
self.queryset = (
|
|
261
|
+
self.IMPORT_JOB_MODEL.stagedtransactionmodel_set.all().is_pending()
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
self.MAPPED_ACCOUNT_MODEL = (
|
|
265
|
+
self.IMPORT_JOB_MODEL.bank_account_model.account_model
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
self.account_model_qs = (
|
|
269
|
+
entity_model.get_coa_accounts()
|
|
270
|
+
.available()
|
|
271
|
+
.exclude(uuid__exact=self.MAPPED_ACCOUNT_MODEL.uuid)
|
|
172
272
|
)
|
|
173
|
-
self.ACCOUNT_MODEL_CHOICES = [
|
|
174
|
-
(a.uuid, a)
|
|
175
|
-
|
|
273
|
+
self.ACCOUNT_MODEL_CHOICES = [(None, '----')] + [
|
|
274
|
+
(a.uuid, a) for a in self.account_model_qs
|
|
275
|
+
]
|
|
276
|
+
self.ACCOUNT_MODEL_EXPENSES_CHOICES = [(None, '----')] + [
|
|
277
|
+
(a.uuid, a) for a in self.account_model_qs if a.role in GROUP_EXPENSES
|
|
278
|
+
]
|
|
279
|
+
self.ACCOUNT_MODEL_SALES_CHOICES = [(None, '----')] + [
|
|
280
|
+
(a.uuid, a) for a in self.account_model_qs if a.role in GROUP_INCOME
|
|
176
281
|
]
|
|
177
282
|
|
|
178
283
|
self.unit_model_qs = entity_model.entityunitmodel_set.all()
|
|
179
|
-
self.UNIT_MODEL_CHOICES = [
|
|
180
|
-
(u.uuid, u)
|
|
181
|
-
|
|
284
|
+
self.UNIT_MODEL_CHOICES = [(None, '----')] + [
|
|
285
|
+
(u.uuid, u) for i, u in enumerate(self.unit_model_qs)
|
|
286
|
+
]
|
|
287
|
+
|
|
288
|
+
self.VENDOR_MODEL_QS = entity_model.vendormodel_set.visible()
|
|
289
|
+
len(self.VENDOR_MODEL_QS)
|
|
290
|
+
self.CUSTOMER_MODEL_QS = entity_model.customermodel_set.visible()
|
|
291
|
+
len(self.CUSTOMER_MODEL_QS)
|
|
292
|
+
|
|
293
|
+
self.VENDOR_CHOICES = [(None, '-----')] + [
|
|
294
|
+
(str(v.uuid), v) for v in self.VENDOR_MODEL_QS
|
|
182
295
|
]
|
|
183
|
-
self.
|
|
296
|
+
self.CUSTOMER_CHOICES = [(None, '-----')] + [
|
|
297
|
+
(str(c.uuid), c) for c in self.CUSTOMER_MODEL_QS
|
|
298
|
+
]
|
|
299
|
+
|
|
300
|
+
self.VENDOR_MAP = dict(self.VENDOR_CHOICES)
|
|
301
|
+
self.CUSTOMER_MAP = dict(self.CUSTOMER_CHOICES)
|
|
184
302
|
|
|
185
303
|
def get_form_kwargs(self, index):
|
|
186
304
|
return {
|
|
@@ -194,5 +312,5 @@ StagedTransactionModelFormSet = modelformset_factory(
|
|
|
194
312
|
formset=BaseStagedTransactionModelFormSet,
|
|
195
313
|
can_delete=True,
|
|
196
314
|
can_order=False,
|
|
197
|
-
extra=0
|
|
315
|
+
extra=0,
|
|
198
316
|
)
|