django-ledger 0.7.4.1__py3-none-any.whl → 0.7.5__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/contrib/django_ledger_graphene/bank_account/schema.py +1 -1
- django_ledger/forms/bank_account.py +16 -12
- django_ledger/forms/data_import.py +70 -33
- django_ledger/io/io_core.py +945 -127
- django_ledger/io/io_generator.py +7 -3
- django_ledger/io/ofx.py +37 -16
- django_ledger/migrations/0020_remove_bankaccountmodel_django_ledg_cash_ac_59a8af_idx_and_more.py +44 -0
- django_ledger/migrations/0021_alter_bankaccountmodel_account_model_and_more.py +33 -0
- django_ledger/models/bank_account.py +14 -11
- django_ledger/models/customer.py +3 -13
- django_ledger/models/data_import.py +690 -35
- django_ledger/models/entity.py +39 -24
- django_ledger/models/journal_entry.py +18 -8
- django_ledger/models/mixins.py +17 -3
- django_ledger/models/vendor.py +2 -2
- django_ledger/settings.py +18 -22
- django_ledger/templates/django_ledger/bank_account/tags/bank_accounts_table.html +2 -2
- django_ledger/templates/django_ledger/data_import/data_import_job_txs.html +1 -1
- django_ledger/templates/django_ledger/data_import/import_job_create.html +11 -2
- django_ledger/templates/django_ledger/data_import/tags/data_import_job_txs_imported.html +1 -1
- django_ledger/templates/django_ledger/data_import/tags/data_import_job_txs_table.html +5 -2
- django_ledger/templatetags/django_ledger.py +6 -7
- django_ledger/views/bank_account.py +1 -1
- django_ledger/views/data_import.py +60 -134
- {django_ledger-0.7.4.1.dist-info → django_ledger-0.7.5.dist-info}/METADATA +17 -17
- {django_ledger-0.7.4.1.dist-info → django_ledger-0.7.5.dist-info}/RECORD +31 -29
- {django_ledger-0.7.4.1.dist-info → django_ledger-0.7.5.dist-info}/WHEEL +1 -1
- {django_ledger-0.7.4.1.dist-info → django_ledger-0.7.5.dist-info}/top_level.txt +1 -0
- {django_ledger-0.7.4.1.dist-info → django_ledger-0.7.5.dist-info}/AUTHORS.md +0 -0
- {django_ledger-0.7.4.1.dist-info → django_ledger-0.7.5.dist-info}/LICENSE +0 -0
django_ledger/__init__.py
CHANGED
|
@@ -6,7 +6,7 @@ Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
|
|
|
6
6
|
default_app_config = 'django_ledger.apps.DjangoLedgerConfig'
|
|
7
7
|
|
|
8
8
|
"""Django Ledger"""
|
|
9
|
-
__version__ = '0.7.
|
|
9
|
+
__version__ = '0.7.5'
|
|
10
10
|
__license__ = 'GPLv3 License'
|
|
11
11
|
|
|
12
12
|
__author__ = 'Miguel Sanda'
|
|
@@ -28,7 +28,7 @@ class Bank_account_Query(graphene.ObjectType):
|
|
|
28
28
|
return BankAccountModel.objects.for_entity(
|
|
29
29
|
entity_slug=slug_name,
|
|
30
30
|
user_model=info.context.user
|
|
31
|
-
).select_related('
|
|
31
|
+
).select_related('account_model')
|
|
32
32
|
else:
|
|
33
33
|
return BankAccountModel.objects.none()
|
|
34
34
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from django.forms import ModelForm, TextInput, Select, ValidationError
|
|
2
2
|
from django.utils.translation import gettext_lazy as _
|
|
3
3
|
|
|
4
|
-
from django_ledger.io.roles import ASSET_CA_CASH
|
|
4
|
+
from django_ledger.io.roles import ASSET_CA_CASH, LIABILITY_CL_ACC_PAYABLE, LIABILITY_LTL_MORTGAGE_PAYABLE
|
|
5
5
|
from django_ledger.models import BankAccountModel
|
|
6
6
|
from django_ledger.models.accounts import AccountModel
|
|
7
7
|
from django_ledger.settings import DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
@@ -19,20 +19,24 @@ class BankAccountCreateForm(ModelForm):
|
|
|
19
19
|
user_model=self.USER_MODEL,
|
|
20
20
|
entity_model=self.ENTITY_SLUG
|
|
21
21
|
).available().filter(
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
role__in=[
|
|
23
|
+
ASSET_CA_CASH,
|
|
24
|
+
LIABILITY_CL_ACC_PAYABLE,
|
|
25
|
+
LIABILITY_LTL_MORTGAGE_PAYABLE
|
|
26
|
+
])
|
|
27
|
+
self.fields['account_model'].queryset = account_qs
|
|
24
28
|
|
|
25
29
|
def clean(self):
|
|
26
|
-
|
|
30
|
+
account_model = self.cleaned_data['account_model']
|
|
27
31
|
routing_number = self.cleaned_data['routing_number']
|
|
28
32
|
account_number = self.cleaned_data['account_number']
|
|
29
33
|
|
|
30
|
-
if not
|
|
34
|
+
if not account_model:
|
|
31
35
|
raise ValidationError('Must select a bank account.')
|
|
32
36
|
|
|
33
37
|
# catching unique database constraint...
|
|
34
38
|
if BankAccountModel.objects.filter(
|
|
35
|
-
|
|
39
|
+
account_model=account_model,
|
|
36
40
|
routing_number__exact=routing_number,
|
|
37
41
|
account_number__exact=account_number
|
|
38
42
|
).exists():
|
|
@@ -47,7 +51,7 @@ class BankAccountCreateForm(ModelForm):
|
|
|
47
51
|
'routing_number',
|
|
48
52
|
'aba_number',
|
|
49
53
|
'swift_number',
|
|
50
|
-
'
|
|
54
|
+
'account_model',
|
|
51
55
|
'active'
|
|
52
56
|
]
|
|
53
57
|
widgets = {
|
|
@@ -74,7 +78,7 @@ class BankAccountCreateForm(ModelForm):
|
|
|
74
78
|
'account_type': Select(attrs={
|
|
75
79
|
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
76
80
|
}),
|
|
77
|
-
'
|
|
81
|
+
'account_model': Select(attrs={
|
|
78
82
|
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
79
83
|
})
|
|
80
84
|
}
|
|
@@ -82,7 +86,7 @@ class BankAccountCreateForm(ModelForm):
|
|
|
82
86
|
'name': _('Account Name'),
|
|
83
87
|
'account_number': _('Account Number'),
|
|
84
88
|
'account_type': _('Account Type'),
|
|
85
|
-
'
|
|
89
|
+
'account_model': _('CoA Account'),
|
|
86
90
|
'aba_number': _('ABA Number'),
|
|
87
91
|
'routing_number': _('Routing Number'),
|
|
88
92
|
'active': _('Make Active'),
|
|
@@ -95,7 +99,7 @@ class BankAccountUpdateForm(BankAccountCreateForm):
|
|
|
95
99
|
fields = [
|
|
96
100
|
'name',
|
|
97
101
|
'account_type',
|
|
98
|
-
'
|
|
102
|
+
'account_model',
|
|
99
103
|
'active'
|
|
100
104
|
]
|
|
101
105
|
widgets = {
|
|
@@ -106,13 +110,13 @@ class BankAccountUpdateForm(BankAccountCreateForm):
|
|
|
106
110
|
'account_type': Select(attrs={
|
|
107
111
|
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
108
112
|
}),
|
|
109
|
-
'
|
|
113
|
+
'account_model': Select(attrs={
|
|
110
114
|
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
111
115
|
})
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
def clean(self):
|
|
115
|
-
cash_account = self.cleaned_data['
|
|
119
|
+
cash_account = self.cleaned_data['account_model']
|
|
116
120
|
|
|
117
121
|
if not cash_account:
|
|
118
122
|
raise ValidationError('Must select a bank account.')
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
from django import forms
|
|
2
|
-
from django.forms import (
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
from django.forms import (
|
|
3
|
+
ModelForm, BaseModelFormSet, modelformset_factory,
|
|
4
|
+
Select, NumberInput, HiddenInput,
|
|
5
|
+
TextInput, ValidationError
|
|
6
|
+
)
|
|
5
7
|
from django.utils.translation import gettext_lazy as _
|
|
6
8
|
|
|
7
|
-
from django_ledger.models import
|
|
9
|
+
from django_ledger.models import (
|
|
10
|
+
StagedTransactionModel,
|
|
11
|
+
ImportJobModel,
|
|
12
|
+
EntityModel
|
|
13
|
+
)
|
|
8
14
|
from django_ledger.settings import DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
9
15
|
|
|
10
16
|
|
|
11
17
|
class ImportJobModelCreateForm(ModelForm):
|
|
18
|
+
|
|
19
|
+
def __init__(self, entity_model: EntityModel, *args, **kwargs):
|
|
20
|
+
super().__init__(*args, **kwargs)
|
|
21
|
+
self.ENTITY_MODEL: EntityModel = entity_model
|
|
22
|
+
self.fields['bank_account_model'].queryset = self.ENTITY_MODEL.bankaccountmodel_set.all().active()
|
|
23
|
+
|
|
12
24
|
ofx_file = forms.FileField(
|
|
13
25
|
label='Select File...',
|
|
26
|
+
required=True,
|
|
14
27
|
widget=forms.FileInput(
|
|
15
28
|
attrs={
|
|
16
29
|
'class': 'file-input',
|
|
@@ -21,13 +34,21 @@ class ImportJobModelCreateForm(ModelForm):
|
|
|
21
34
|
class Meta:
|
|
22
35
|
model = ImportJobModel
|
|
23
36
|
fields = [
|
|
24
|
-
'
|
|
37
|
+
'bank_account_model',
|
|
38
|
+
'description',
|
|
25
39
|
]
|
|
26
40
|
widgets = {
|
|
27
41
|
'description': TextInput(attrs={
|
|
28
42
|
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-large',
|
|
29
43
|
'placeholder': _('What\'s this import about?...')
|
|
30
|
-
})
|
|
44
|
+
}),
|
|
45
|
+
'bank_account_model': Select(
|
|
46
|
+
attrs={
|
|
47
|
+
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES,
|
|
48
|
+
}),
|
|
49
|
+
}
|
|
50
|
+
help_texts = {
|
|
51
|
+
'bank_account_model': _('Select the bank account to import transactions from.'),
|
|
31
52
|
}
|
|
32
53
|
|
|
33
54
|
|
|
@@ -48,11 +69,20 @@ class StagedTransactionModelForm(ModelForm):
|
|
|
48
69
|
tx_import = forms.BooleanField(initial=False, required=False)
|
|
49
70
|
tx_split = forms.BooleanField(initial=False, required=False)
|
|
50
71
|
|
|
51
|
-
def __init__(self, *args, **kwargs):
|
|
72
|
+
def __init__(self, base_formset_instance, *args, **kwargs):
|
|
52
73
|
super().__init__(*args, **kwargs)
|
|
74
|
+
self.BASE_FORMSET_INSTANCE = base_formset_instance
|
|
75
|
+
|
|
76
|
+
# for IDE typing hints...
|
|
53
77
|
instance: StagedTransactionModel = getattr(self, 'instance', None)
|
|
54
|
-
if instance:
|
|
55
78
|
|
|
79
|
+
# avoids multiple DB queries rendering the formset...
|
|
80
|
+
self.fields['unit_model'].choices = self.BASE_FORMSET_INSTANCE.UNIT_MODEL_CHOICES
|
|
81
|
+
|
|
82
|
+
# avoids multiple DB queries rendering the formset...
|
|
83
|
+
self.fields['account_model'].choices = self.BASE_FORMSET_INSTANCE.ACCOUNT_MODEL_CHOICES
|
|
84
|
+
|
|
85
|
+
if instance:
|
|
56
86
|
if not instance.is_children():
|
|
57
87
|
self.fields['amount_split'].widget = HiddenInput()
|
|
58
88
|
self.fields['amount_split'].disabled = True
|
|
@@ -100,7 +130,7 @@ class StagedTransactionModelForm(ModelForm):
|
|
|
100
130
|
raise ValidationError(message=_('Cannot import and split at the same time'))
|
|
101
131
|
|
|
102
132
|
class Meta:
|
|
103
|
-
model = StagedTransactionModel
|
|
133
|
+
model = StagedTransactionModel
|
|
104
134
|
fields = [
|
|
105
135
|
'tx_import',
|
|
106
136
|
'bundle_split',
|
|
@@ -123,32 +153,39 @@ class StagedTransactionModelForm(ModelForm):
|
|
|
123
153
|
|
|
124
154
|
class BaseStagedTransactionModelFormSet(BaseModelFormSet):
|
|
125
155
|
|
|
126
|
-
def __init__(self, *args,
|
|
156
|
+
def __init__(self, *args,
|
|
157
|
+
entity_model: EntityModel,
|
|
158
|
+
import_job_model: ImportJobModel,
|
|
159
|
+
**kwargs):
|
|
127
160
|
super().__init__(*args, **kwargs)
|
|
128
|
-
self.ENTITY_SLUG = entity_slug
|
|
129
|
-
self.USER_MODEL = user_model
|
|
130
|
-
self.IMPORT_DISABLED = not exclude_account
|
|
131
|
-
self.CASH_ACCOUNT = exclude_account
|
|
132
|
-
|
|
133
|
-
account_model_qs = AccountModel.objects.for_entity(
|
|
134
|
-
user_model=self.USER_MODEL,
|
|
135
|
-
entity_model=self.ENTITY_SLUG
|
|
136
|
-
).available().order_by('role', 'name')
|
|
137
|
-
|
|
138
|
-
unit_model_qs = EntityUnitModel.objects.for_entity(
|
|
139
|
-
user_model=self.USER_MODEL,
|
|
140
|
-
entity_slug=self.ENTITY_SLUG
|
|
141
|
-
)
|
|
142
161
|
|
|
143
|
-
|
|
144
|
-
|
|
162
|
+
# validates that the job import model belongs to the entity model...
|
|
163
|
+
if import_job_model.entity_uuid != entity_model.uuid:
|
|
164
|
+
raise ValidationError(message=_('Import job does not belong to this entity'))
|
|
145
165
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
form.fields['unit_model'].queryset = unit_model_qs
|
|
166
|
+
self.ENTITY_MODEL = entity_model
|
|
167
|
+
self.IMPORT_JOB_MODEL: ImportJobModel = import_job_model
|
|
168
|
+
self.MAPPED_ACCOUNT_MODEL = self.IMPORT_JOB_MODEL.bank_account_model.account_model
|
|
150
169
|
|
|
151
|
-
|
|
170
|
+
self.account_model_qs = entity_model.get_coa_accounts().available().exclude(
|
|
171
|
+
uuid__exact=self.MAPPED_ACCOUNT_MODEL.uuid
|
|
172
|
+
)
|
|
173
|
+
self.ACCOUNT_MODEL_CHOICES = [
|
|
174
|
+
(a.uuid, a) if i > 0 else (None, '----') for i, a in
|
|
175
|
+
enumerate(self.account_model_qs)
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
self.unit_model_qs = entity_model.entityunitmodel_set.all()
|
|
179
|
+
self.UNIT_MODEL_CHOICES = [
|
|
180
|
+
(u.uuid, u) if i > 0 else (None, '----') for i, u in
|
|
181
|
+
enumerate(self.unit_model_qs)
|
|
182
|
+
]
|
|
183
|
+
self.queryset = self.IMPORT_JOB_MODEL.stagedtransactionmodel_set.all().is_pending()
|
|
184
|
+
|
|
185
|
+
def get_form_kwargs(self, index):
|
|
186
|
+
return {
|
|
187
|
+
'base_formset_instance': self,
|
|
188
|
+
}
|
|
152
189
|
|
|
153
190
|
|
|
154
191
|
StagedTransactionModelFormSet = modelformset_factory(
|
|
@@ -156,6 +193,6 @@ StagedTransactionModelFormSet = modelformset_factory(
|
|
|
156
193
|
form=StagedTransactionModelForm,
|
|
157
194
|
formset=BaseStagedTransactionModelFormSet,
|
|
158
195
|
can_delete=True,
|
|
159
|
-
can_delete_extra=0,
|
|
160
196
|
can_order=False,
|
|
161
|
-
extra=0
|
|
197
|
+
extra=0
|
|
198
|
+
)
|