diff --git a/assets/js/build/user_profile_edit.js b/assets/js/build/user_profile_edit.js
index 1b5b545..556e37c 100644
--- a/assets/js/build/user_profile_edit.js
+++ b/assets/js/build/user_profile_edit.js
@@ -49,9 +49,51 @@
var _avatar_upload = __webpack_require__(29);
+ var _bootstrap_tabs = __webpack_require__(16);
+
+ var _user_check_statuses = __webpack_require__(30);
+
$(function () {
(0, _avatar_upload.avatarUploadInit)();
+ (0, _bootstrap_tabs.tabsHashInit)();
+ (0, _user_check_statuses.checkBoxBindingInit)();
+ });
+
+/***/ },
+
+/***/ 16:
+/***/ function(module, exports) {
+
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
});
+ function tabsHashInit() {
+ // store the currently selected tab in the hash value
+ $("a[data-toggle=tab]").on("shown.bs.tab", function (e) {
+ var target = $(e.target);
+ if (target.hasClass("tab-inserted")) {
+ target.siblings(".active").removeClass("active");
+ target.addClass("active");
+ return;
+ }
+ var id = target.attr("href").substr(1);
+ var scrollmem = $('body').scrollTop() || $('html').scrollTop();
+ window.location.hash = id;
+ $('html,body').scrollTop(scrollmem);
+ });
+ }
+
+ function restoreTab() {
+ // on load of the page: switch to the currently selected tab
+ var hash = window.location.hash;
+ var a = $("a[data-toggle=\"tab\"][href=\"" + hash + "\"]");
+ hash && a.tab('show');
+ }
+
+ exports.tabsHashInit = tabsHashInit;
+ exports.restoreTab = restoreTab;
/***/ },
@@ -106,6 +148,104 @@
exports.avatarUploadInit = avatarUploadInit;
+/***/ },
+
+/***/ 30:
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ function checkBoxBindingInit() {
+ /*
+ Скрываем/Показываем формы/части форм, взависимости от выбранных checkBox'ов
+ */
+ var $residency_checkBoxes = $('input[name=fin_info-residency]');
+ var $legal_status_checkBoxes = $('input[name=fin_info-legal_status]');
+ var $legal_status_boxes = $legal_status_checkBoxes.closest('div');
+ var $fin_infos = $('.js-fin-info');
+ var shows = {
+ 'russian_resident': ['individual', 'entity', 'employed'],
+ 'non_russian_resident': ['individual', 'entity'],
+ 'russian_stay_permit': ['individual']
+ };
+ $fin_infos.hide();
+ $('.-russian_stay_permit-individual').hide();
+
+ $residency_checkBoxes.on("click", function (e) {
+ $legal_status_checkBoxes.first().trigger("click");
+ });
+ $residency_checkBoxes.on("change", function (e) {
+ $legal_status_boxes.hide();
+ var value = $(e.target).val();
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = shows[value][Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var legal_status = _step.value;
+
+ $('input[value=' + legal_status + ']').closest('div').show();
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ var fin_info_id = '';
+ fin_info_id += '-' + $residency_checkBoxes.filter(':checked').val();
+ fin_info_id += '-' + $legal_status_checkBoxes.filter(':checked').val();
+ if (fin_info_id == '-non_russian_resident-individual') {
+ $('.-non_russian_resident-individual').hide();
+ $('.-non_russian_resident-individual').children('input').val('');
+ } else {
+ $('.-non_russian_resident-individual').show();
+ }
+ if (fin_info_id == '-russian_stay_permit-individual') {
+ $('.-russian_stay_permit-individual').show();
+ } else {
+ $('.-russian_stay_permit-individual').hide();
+ $('.-russian_stay_permit-individual').children('input').val('');
+ }
+ });
+
+ $legal_status_checkBoxes.on("click", function (e) {
+ $fin_infos.each(function (ind, el) {
+ $(el).find('input').val('');
+ });
+ });
+ $legal_status_checkBoxes.on("change", function (e) {
+ $fin_infos.hide();
+
+ var fin_info_id = '';
+ fin_info_id += '-' + $residency_checkBoxes.filter(':checked').val();
+ fin_info_id += '-' + $legal_status_checkBoxes.filter(':checked').val();
+
+ if (fin_info_id != '-non_russian_resident-entity') {
+ fin_info_id = '-russian_resident';
+ fin_info_id += '-' + $legal_status_checkBoxes.filter(':checked').val();
+ }
+ $('#' + fin_info_id).show();
+ });
+ $residency_checkBoxes.first().trigger("change");
+ $legal_status_checkBoxes.first().trigger("change");
+ }
+
+ exports.checkBoxBindingInit = checkBoxBindingInit;
+
/***/ }
/******/ });
\ No newline at end of file
diff --git a/assets/js/src/seeds/user_check_statuses.js b/assets/js/src/seeds/user_check_statuses.js
new file mode 100644
index 0000000..f748f82
--- /dev/null
+++ b/assets/js/src/seeds/user_check_statuses.js
@@ -0,0 +1,66 @@
+function checkBoxBindingInit() {
+ /*
+ Скрываем/Показываем формы/части форм, взависимости от выбранных checkBox'ов
+ */
+ let $residency_checkBoxes = $('input[name=fin_info-residency]');
+ let $legal_status_checkBoxes = $('input[name=fin_info-legal_status]');
+ let $legal_status_boxes = $legal_status_checkBoxes.closest('div');
+ const $fin_infos = $('.js-fin-info');
+ let shows = {
+ 'russian_resident': ['individual', 'entity', 'employed'],
+ 'non_russian_resident': ['individual', 'entity'],
+ 'russian_stay_permit': ['individual'],
+ };
+ $fin_infos.hide();
+ $('.-russian_stay_permit-individual').hide();
+
+ $residency_checkBoxes.on("click", function (e) {
+ $legal_status_checkBoxes.first().trigger("click");
+ });
+ $residency_checkBoxes.on("change", function (e) {
+ $legal_status_boxes.hide();
+ let value = $(e.target).val();
+ for (let legal_status of shows[value]) {
+ $(`input[value=${legal_status}]`).closest('div').show();
+ }
+
+ let fin_info_id = '';
+ fin_info_id += '-' + $residency_checkBoxes.filter(':checked').val();
+ fin_info_id += '-' + $legal_status_checkBoxes.filter(':checked').val();
+ if (fin_info_id == '-non_russian_resident-individual') {
+ $('.-non_russian_resident-individual').hide();
+ $('.-non_russian_resident-individual').children('input').val('');
+ } else {
+ $('.-non_russian_resident-individual').show()
+ }
+ if (fin_info_id == '-russian_stay_permit-individual') {
+ $('.-russian_stay_permit-individual').show();
+ } else {
+ $('.-russian_stay_permit-individual').hide();
+ $('.-russian_stay_permit-individual').children('input').val('');
+ }
+ });
+
+ $legal_status_checkBoxes.on("click", function (e) {
+ $fin_infos.each(function (ind, el) {
+ $(el).find('input').val('');
+ });
+ });
+ $legal_status_checkBoxes.on("change", function (e) {
+ $fin_infos.hide();
+
+ let fin_info_id = '';
+ fin_info_id += '-' + $residency_checkBoxes.filter(':checked').val();
+ fin_info_id += '-' + $legal_status_checkBoxes.filter(':checked').val();
+
+ if (fin_info_id != '-non_russian_resident-entity') {
+ fin_info_id = '-russian_resident';
+ fin_info_id += '-' + $legal_status_checkBoxes.filter(':checked').val();
+ }
+ $(`#${fin_info_id}`).show();
+ });
+ $residency_checkBoxes.first().trigger("change");
+ $legal_status_checkBoxes.first().trigger("change");
+}
+
+export {checkBoxBindingInit}
\ No newline at end of file
diff --git a/assets/js/src/user_profile_edit.js b/assets/js/src/user_profile_edit.js
index f4653b2..4332002 100644
--- a/assets/js/src/user_profile_edit.js
+++ b/assets/js/src/user_profile_edit.js
@@ -1,5 +1,9 @@
import {avatarUploadInit} from './seeds/avatar_upload'
+import {tabsHashInit, restoreTab} from './seeds/bootstrap_tabs'
+import {checkBoxBindingInit} from './seeds/user_check_statuses'
$(function () {
avatarUploadInit();
+ tabsHashInit();
+ checkBoxBindingInit();
});
\ No newline at end of file
diff --git a/assets/sass/components/custom-components.sass b/assets/sass/components/custom-components.sass
index 5387f4a..1a83782 100644
--- a/assets/sass/components/custom-components.sass
+++ b/assets/sass/components/custom-components.sass
@@ -234,6 +234,10 @@ textarea.description
width: 20px
height: 20px
+label.fin_statuses
+ font-style: italic
+ color: #6b6868
+
.custom-check
cursor: pointer
display: inline-block
@@ -498,4 +502,43 @@ textarea.description
&:last-child a:hover, &:first-child a:hover
background: none !important
color: #2c2c2c
- opacity: 0.8
\ No newline at end of file
+ opacity: 0.8
+
+.rad
+ cursor: pointer
+ user-select: none
+ -webkit-user-select: none
+ -webkit-touch-callout: none
+ >
+ input
+ /* HIDE ORG RADIO & CHECKBOX
+ visibility: hidden
+ position: absolute
+ i
+ /* DEFAULT STYLE
+ display: inline-block
+ vertical-align: middle
+ width: 24px
+ height: 24px
+ border-radius: 50%
+ transition: 0.2s
+ box-shadow: inset 0 0 0 16px #fff
+ border: 1px solid #cccccc
+ background: #cccccc
+ margin-right: 5px
+ &:hover > i
+ /* HOVER STYLE
+ box-shadow: inset 0 0 0 3px #fff
+ background: #cccccc
+ > input:checked + i
+ /* (RADIO CHECKED) STYLE
+ box-shadow: inset 0 0 0 3px #fff
+ background: #cccccc
+
+/* RADIO & CHECKBOX STYLES
+
+/* CHECKBOX OVERWRITE STYLES
+
+label.rad
+ font-style: italic
+ color: #606060
\ No newline at end of file
diff --git a/users/forms.py b/users/forms.py
index 399e851..0e4e564 100644
--- a/users/forms.py
+++ b/users/forms.py
@@ -202,36 +202,56 @@ class UserFinancialInfoEditForm(forms.ModelForm):
model = UserFinancialInfo
fields = (
- 'address',
- 'credit_card_number',
- 'date_of_birth',
+ 'residency',
+ 'legal_status',
+
'fio',
+ 'date_of_birth',
+ 'phone',
+
+ 'postal_address',
+ 'registration_address',
+
+ 'credit_card_number',
'inn',
- 'legal_status',
+
'passport_issue_date',
'passport_issued_by',
'passport_number',
- 'passport_scan',
'passport_series',
- 'phone',
- 'residency',
'subdivision_code',
+
'yandex_money',
+ 'web_money',
+
+ # Юридические данные
+ 'correspondent_account',
+ 'bank_bic',
+ 'bank_inn',
+ 'checking_account',
+ 'bank_name',
+ 'authorized_bank_name',
+ 'ppc',
+ 'psrn',
+
+ 'organization_name',
+ 'organization_registered_address',
+ 'organization_postal_address',
+ 'organization_reg_number'
+
)
widgets = {
- # 'date_of_birth': forms.TextInput(attrs={'class': 'datepicker'}),
- # 'passport_issue_date': forms.TextInput(attrs={'class': 'datepicker'}),
- 'legal_status': forms.RadioSelect(),
- 'residency': forms.RadioSelect(),
+ 'date_of_birth': forms.DateInput(attrs={'class': 'datepicker box-sizing simple-input'}),
+ 'passport_issue_date': forms.DateInput(attrs={'class': 'datepicker box-sizing simple-input'}),
}
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
super().__init__(*args, **kwargs)
- self.fields['residency'].choices = self.fields['residency'].choices[1:]
- self.fields['legal_status'].choices = self.fields['legal_status'].choices[1:]
+ # self.fields['residency'].choices = self.fields['residency'].choices[1:]
+ # self.fields['legal_status'].choices = self.fields['legal_status'].choices[1:]
# self.fields['residency'].empty_label = None
# self.fields['residency'].widget.choices = self.fields['residency'].choices
diff --git a/users/migrations/0023_auto_20170105_1706.py b/users/migrations/0023_auto_20170105_1706.py
new file mode 100644
index 0000000..4309919
--- /dev/null
+++ b/users/migrations/0023_auto_20170105_1706.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2017-01-05 14:06
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0022_user_organization_name'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='postal_address',
+ field=models.CharField(blank=True, max_length=255, verbose_name='Почтовый адрес'),
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='registration_address',
+ field=models.CharField(blank=True, max_length=255, verbose_name='Адрес регистрации'),
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='web_money',
+ field=models.CharField(blank=True, max_length=50),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='credit_card_number',
+ field=models.CharField(blank=True, max_length=50),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='fio',
+ field=models.CharField(blank=True, max_length=255),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='inn',
+ field=models.CharField(blank=True, max_length=100),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='legal_status',
+ field=models.CharField(choices=[('individual', 'Физическое лицо'), ('entity', 'Юридическое лицо'), ('employed', 'Частный предприниматель')], max_length=30),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='passport_issued_by',
+ field=models.CharField(max_length=255, verbose_name='Кем выдан'),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='phone',
+ field=models.CharField(blank=True, max_length=30),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='residency',
+ field=models.CharField(choices=[('russian_resident', 'Резидент РФ'), ('non_russian_resident', 'Нерезидент РФ'), ('russian_stay_permit', 'Вид на жительство')], max_length=50),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='subdivision_code',
+ field=models.CharField(max_length=10, verbose_name='Код подразделения'),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='yandex_money',
+ field=models.CharField(blank=True, max_length=50),
+ ),
+ ]
diff --git a/users/migrations/0024_auto_20170105_1808.py b/users/migrations/0024_auto_20170105_1808.py
new file mode 100644
index 0000000..b6c2030
--- /dev/null
+++ b/users/migrations/0024_auto_20170105_1808.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2017-01-05 15:08
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0023_auto_20170105_1706'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='bank_bic',
+ field=models.CharField(default='', max_length=32, verbose_name='БИК банка'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='bank_inn',
+ field=models.CharField(default='', max_length=32, verbose_name='ИНН банка'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='bank_name',
+ field=models.CharField(default='', max_length=32, verbose_name='Название банка'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='checking_account',
+ field=models.CharField(default='', max_length=64, verbose_name='Расчетный счет'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='correspondent_account',
+ field=models.CharField(default='', max_length=32, verbose_name='Корреспондентский счет'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='organization_name',
+ field=models.CharField(default='', max_length=32, verbose_name='Название организации'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='organization_postal_address',
+ field=models.CharField(default='', max_length=255, verbose_name='Почтовый адрес'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='organization_registered_address',
+ field=models.CharField(default='', max_length=255, verbose_name='Юридический адрес'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='ppc',
+ field=models.CharField(default='', max_length=32, verbose_name='КПП'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='psrn',
+ field=models.CharField(default='', max_length=32, verbose_name='ОГРН'),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='date_of_birth',
+ field=models.DateField(blank=True, null=True),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='passport_issue_date',
+ field=models.DateField(blank=True, null=True),
+ ),
+ ]
diff --git a/users/migrations/0025_auto_20170109_1202.py b/users/migrations/0025_auto_20170109_1202.py
new file mode 100644
index 0000000..d40dcfb
--- /dev/null
+++ b/users/migrations/0025_auto_20170109_1202.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2017-01-09 09:02
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0024_auto_20170105_1808'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='authorized_bank_name',
+ field=models.CharField(default='', max_length=32, verbose_name='Название уполномоченного банка в РФ'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='userfinancialinfo',
+ name='organization_reg_number',
+ field=models.CharField(default='', max_length=64, verbose_name='Регистрационный номер в налоговом органе'),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='inn',
+ field=models.CharField(blank=True, max_length=100, verbose_name='ИНН'),
+ ),
+ migrations.AlterField(
+ model_name='userfinancialinfo',
+ name='legal_status',
+ field=models.CharField(choices=[('individual', 'Физическое лицо'), ('entity', 'Юридическое лицо'), ('employed', 'Индивидуальный предприниматель')], max_length=30),
+ ),
+ ]
diff --git a/users/models.py b/users/models.py
index d0d1123..19f71b8 100644
--- a/users/models.py
+++ b/users/models.py
@@ -56,30 +56,54 @@ class UserFinancialInfo(models.Model):
RESIDENCIES = (
('russian_resident', 'Резидент РФ'),
('non_russian_resident', 'Нерезидент РФ'),
- ('refugee', 'Беженец'),
('russian_stay_permit', 'Вид на жительство'),
)
LEGAL_STATUSES = (
('individual', 'Физическое лицо'),
- ('legal_entity', 'ИП и юридическое лицо'),
+ ('entity', 'Юридическое лицо'),
+ ('employed', 'Индивидуальный предприниматель'),
)
- address = models.CharField(max_length=1000)
- credit_card_number = models.CharField(max_length=50)
- date_of_birth = models.DateField()
- fio = models.CharField(max_length=255)
- inn = models.CharField(max_length=100)
+ residency = models.CharField(max_length=50, choices=RESIDENCIES)
legal_status = models.CharField(max_length=30, choices=LEGAL_STATUSES)
- passport_issue_date = models.DateField()
- passport_issued_by = models.CharField(max_length=255)
- passport_number = models.CharField(max_length=10)
+
+ fio = models.CharField(max_length=255, blank=True)
+ date_of_birth = models.DateField(null=True, blank=True)
+ phone = models.CharField(max_length=30, blank=True)
+
+ # @deprecated
+ address = models.CharField(max_length=1000, blank=True)
+ postal_address = models.CharField(max_length=255, verbose_name='Почтовый адрес', blank=True)
+ registration_address = models.CharField(max_length=255, verbose_name='Адрес регистрации', blank=True)
+
+ credit_card_number = models.CharField(max_length=50, blank=True)
+ inn = models.CharField(max_length=100, blank=True, verbose_name='ИНН')
+
+ passport_issue_date = models.DateField(null=True, blank=True)
+ passport_issued_by = models.CharField(max_length=255, verbose_name="Кем выдан", blank=True)
+ passport_number = models.CharField(max_length=10, blank=True)
passport_scan = models.ImageField(upload_to='users/contractors/')
- passport_series = models.CharField(max_length=6)
- phone = models.CharField(max_length=30)
- residency = models.CharField(max_length=50, choices=RESIDENCIES)
- subdivision_code = models.CharField(max_length=10)
- yandex_money = models.CharField(max_length=50)
+ passport_series = models.CharField(max_length=6, blank=True)
+ subdivision_code = models.CharField(max_length=10, verbose_name='Код подразделения', blank=True)
+
+ yandex_money = models.CharField(max_length=50, blank=True)
+ web_money = models.CharField(max_length=50, blank=True)
+
+ # Юридические данные
+ correspondent_account = models.CharField(max_length=32, verbose_name='Корреспондентский счет', blank=True)
+ bank_bic = models.CharField(max_length=32, verbose_name='БИК банка', blank=True)
+ bank_inn = models.CharField(max_length=32, verbose_name='ИНН банка', blank=True)
+ checking_account = models.CharField(max_length=64, verbose_name='Расчетный счет', blank=True)
+ bank_name = models.CharField(max_length=32, verbose_name='Название банка', blank=True)
+ authorized_bank_name = models.CharField(max_length=32, verbose_name='Название уполномоченного банка в РФ', blank=True)
+ ppc = models.CharField(max_length=32, verbose_name='КПП', blank=True)
+ psrn = models.CharField(max_length=32, verbose_name='ОГРН', blank=True)
+
+ organization_name = models.CharField(max_length=32, verbose_name="Название организации", blank=True)
+ organization_registered_address = models.CharField(max_length=255, verbose_name="Юридический адрес", blank=True)
+ organization_postal_address = models.CharField(max_length=255, verbose_name="Почтовый адрес", blank=True)
+ organization_reg_number = models.CharField(max_length=64, verbose_name="Регистрационный номер в налоговом органе", blank=True)
def __str__(self):
return self.fio
diff --git a/users/static/css/user_profile_edit.css b/users/static/css/user_profile_edit.css
deleted file mode 100644
index 76008f0..0000000
--- a/users/static/css/user_profile_edit.css
+++ /dev/null
@@ -1,146 +0,0 @@
-.mainContent {
- padding: 43px 25px 40px 25px;
-}
-
-/*TODO: Привязать к ширине блока справа*/
-.avatarInset {
- width: 210px;
- height: 210px;
-}
-
-.avatar {
- background-color: #F1F1F1;
- width: 228px;
- height: 228px;
- padding: 10px;
-
-}
-
-.simple-input, .simple-select {
- height: 51px;
- width: 100%;
- border: 1px solid #cccccc;
- outline: none;
- padding: 5px 40px 5px 20px;
- background-color: white;
- margin-bottom: -1px;
-}
-
-.simple-input:-webkit-autofill, .simple-select:-webkit-autofill{
- transition: background-color 5000s ease-in-out 0s
-}
-
-.simple-select select {
- background-color: darkgray;
-}
-
-.simple-select {
- display: flex;
- align-items: center;
- text-align: center;
-}
-
-.simple-select.fill{
- background-color: #F2F2F2;
-}
-
-.simple-select .text{
- color: #a3a3a3;
-}
-
-.toggle .btn {
- padding: 14px 20px;
- border-radius: 40px;
-}
-
-.bottom-line {
- padding-bottom: 10px;
- border-bottom: 1px solid #cccccc;
-}
-
-.top-line {
- /*padding-bottom: 10px;*/
- border-top: 1px solid #cccccc;
-}
-
-/* СУПЕР-костыльная кнопка. Не прикасаться!*/
-.upload-new {
- width: 50%;
- height: 30px;
- overflow: hidden;
- cursor: pointer;
- border-radius: 40px;
- border: 1px solid #FF0029;
-}
-
-.upload-new:hover, .btn-simple:hover {
- box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
- -webkit-transform: scale(1.04);
- -moz-transform: scale(1.04);
- transform: scale(1.04);
-}
-
-.upload-new, .btn-simple {
- transition: all 0.3s;
- cursor: pointer;
-}
-
-.upload-new input {
- display: block !important;
- width: 100% !important;
- height: 30px !important;
- opacity: 0 !important;
- cursor: pointer;
-}
-
-.upload-new p {
- line-height: 30px;
- text-transform: uppercase;
- margin: -30px 0 0 0;
- /*padding: 0 5px 0 5px;*/
- font-size: 12px;
- text-align: center;
- font-family: Myriad;
-}
-
-/** Конец супер-костыля**/
-
-.row-eq-height {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
-}
-
-.info {
- background-color: #F2F2F2;
- padding: 50px 40px;
- margin-top: 20px;
-}
-
-.btn-simple {
- border-radius: 40px;
- padding: 10px 15px;
- border: 1px solid #FF0029;
- /*color: black;*/
- background: none;
- font-family: Myriad;
- font-weight: normal;
- font-style: normal;
- font-size: 14pt;
-}
-
-.no-margin .selected-element {
- margin: 0;
-}
-
-.-live-image-avatar-upload-container .-position-relative-parent {
- position: relative
-}
-
-.-live-image-avatar-upload-container .-live-image-delete {
- position: absolute;
- top: 0;
- right: 0;
- background-color: white;
-}
\ No newline at end of file
diff --git a/users/static/sass/user-profile-edit.sass b/users/static/sass/user-profile-edit.sass
new file mode 100644
index 0000000..24d4827
--- /dev/null
+++ b/users/static/sass/user-profile-edit.sass
@@ -0,0 +1,130 @@
+.mainContent
+ padding: 43px 25px 40px 25px
+
+/*TODO: Привязать к ширине блока справа
+
+.avatarInset
+ width: 210px
+ height: 210px
+
+.avatar
+ background-color: #F1F1F1
+ width: 228px
+ height: 228px
+ padding: 10px
+
+.simple-input, .simple-select
+ height: 51px
+ width: 100%
+ border: 1px solid #cccccc
+ outline: none
+ padding: 5px 40px 5px 20px
+ background-color: white
+ margin-bottom: -1px
+
+.simple-input:-webkit-autofill
+ transition: background-color 5000s ease-in-out 0s
+
+.simple-select
+ &:-webkit-autofill
+ transition: background-color 5000s ease-in-out 0s
+ select
+ background-color: darkgray
+ display: flex
+ align-items: center
+ text-align: center
+ &.fill
+ background-color: #F2F2F2
+ .text
+ color: #a3a3a3
+
+.toggle .btn
+ padding: 14px 20px
+ border-radius: 40px
+
+.bottom-line
+ padding-bottom: 10px
+ border-bottom: 1px solid #cccccc
+
+.top-line
+ /*padding-bottom: 10px;
+ border-top: 1px solid #cccccc
+
+/* СУПЕР-костыльная кнопка. Не прикасаться -)
+
+.upload-new
+ width: 50%
+ height: 30px
+ overflow: hidden
+ cursor: pointer
+ border-radius: 40px
+ border: 1px solid #FF0029
+ &:hover
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.2)
+ -webkit-transform: scale(1.04)
+ -moz-transform: scale(1.04)
+ transform: scale(1.04)
+
+.btn-simple:hover
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.2)
+ -webkit-transform: scale(1.04)
+ -moz-transform: scale(1.04)
+ transform: scale(1.04)
+
+.upload-new, .btn-simple
+ transition: all 0.3s
+ cursor: pointer
+
+.upload-new
+ input
+ display: block !important
+ width: 100% !important
+ height: 30px !important
+ opacity: 0 !important
+ cursor: pointer
+ p
+ line-height: 30px
+ text-transform: uppercase
+ margin: -30px 0 0 0
+ /*padding: 0 5px 0 5px;
+ font-size: 12px
+ text-align: center
+ font-family: Myriad
+
+/** Конец супер-костыля*
+
+.row-eq-height
+ display: -webkit-box
+ display: -webkit-flex
+ display: -ms-flexbox
+ display: flex
+
+.info, .financial_info
+ background-color: #F2F2F2
+ padding: 30px 40px 50px
+ margin-top: 20px
+ .header
+ margin-top: 30px
+
+.btn-simple
+ border-radius: 40px
+ padding: 10px 15px
+ border: 1px solid #FF0029
+ /*color: black;
+ background: none
+ font-family: Myriad
+ font-weight: normal
+ font-style: normal
+ font-size: 14pt
+
+.no-margin .selected-element
+ margin: 0
+
+.-live-image-avatar-upload-container
+ .-position-relative-parent
+ position: relative
+ .-live-image-delete
+ position: absolute
+ top: 0
+ right: 0
+ background-color: white
\ No newline at end of file
diff --git a/users/templates/partials/tabs/tab-user-financial_info.html b/users/templates/partials/tabs/tab-user-financial_info.html
new file mode 100644
index 0000000..0699ba6
--- /dev/null
+++ b/users/templates/partials/tabs/tab-user-financial_info.html
@@ -0,0 +1,418 @@
+
Произошла ошибка (form)
' - '{form}'
- ).format(form=pformat(form.errors)))
-
- context.update({'form': form})
- return render(request, self.template_name, context)
+# class UserProfileEditView(BaseMixin, View):
+# form_class = UserProfileEditForm
+# template_name = 'user_profile_edit.html'
+#
+# def dispatch(self, request, *args, **kwargs):
+# if request.resolver_match.url_name == 'user-experience-edit':
+# if not request.user.is_contractor():
+# raise PermissionDenied
+# self.form_class = UserProfileExperienceEditForm
+# request.experience_edit = True
+# if request.user.is_authenticated() and request.user.pk == int(kwargs.get('pk')):
+# return super().dispatch(request, *args, **kwargs)
+# else:
+# raise PermissionDenied
+#
+# def get(self, request, *args, **kwargs):
+# context = self.get_context_data(**_.merge({}, request.GET, kwargs))
+#
+# form = self.form_class(request=request, instance=request.user)
+# context.update({'form': form})
+#
+# return render(request, self.template_name, context)
+#
+# def post(self, request, *args, **kwargs):
+# context = self.get_context_data(**kwargs)
+#
+# specs = request.POST.getlist('contractor_specializations')
+# request.POST.setlist('contractor_specializations', _.compact(specs)) # Ignore empty input values
+#
+# form = self.form_class(request.POST, request=request, instance=request.user)
+#
+# if form.is_valid():
+# user = form.save()
+#
+# live_image = form.cleaned_data.get('live_image')
+#
+# if live_image:
+# new_image = ContentFile(live_image.file.read())
+# new_image.name = live_image.file.name
+#
+# user.avatar = new_image
+# user.save()
+#
+# live_image.file.delete()
+# live_image.delete()
+#
+# messages.info(request, 'Пользователь успешно отредактирован')
+# redirect_to = request.POST.get('next')
+# return redirect(redirect_to)
+# else:
+# if form.errors:
+# messages.info(request, (
+# 'Произошла ошибка (form)
' +# '{form}'
+# ).format(form=pformat(form.errors)))
+#
+# context.update({'form': form})
+# return render(request, self.template_name, context)
class UserProfileEditViewFull(BaseMixin, View):
form_class = UserProfileEditFullForm
+ fin_info_form_class = UserFinancialInfoEditForm
template_name = 'user_profile_edit.html'
def dispatch(self, request, *args, **kwargs):
@@ -125,15 +126,25 @@ class UserProfileEditViewFull(BaseMixin, View):
context = self.get_context_data(**_.merge({}, request.GET, kwargs))
form = self.form_class(instance=request.user)
+ fin_info_form = self.fin_info_form_class(request=request, instance=request.user.financial_info,
+ prefix='fin_info')
# import code
# code.interact(local=dict(globals(), **locals()))
- context.update({'form': form})
+ context.update({
+ 'form': form,
+ 'fin_info_form': fin_info_form
+ })
+ context.update({
+ 'RESIDENCIES': UserFinancialInfo.RESIDENCIES,
+ 'LEGAL_STATUSES': UserFinancialInfo.LEGAL_STATUSES,
+ })
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
+ # '1,3,4' --> ['1', '3', '4']
specs = tuple(filter(None, re.split(r'\s|,|;', request.POST.get('contractor_specializations', ''))))
request.POST.setlist('contractor_specializations', specs)
@@ -143,10 +154,20 @@ class UserProfileEditViewFull(BaseMixin, View):
constructs = tuple(filter(None, re.split(r'\s|,|;', request.POST.get('contractor_construction_types', ''))))
request.POST.setlist('contractor_construction_types', constructs)
+ print("!)request.POST = ", request.POST)
+
+ # Отфильтровываем пустые значения
+ for key in request.POST.keys():
+ request.POST.setlist(key, list(filter(lambda el: el, request.POST.getlist(key, ''))))
+
form = self.form_class(request.POST, request=request, instance=request.user)
+ print("2)request.POST = ", request.POST)
+ fin_info_form = self.fin_info_form_class(request.POST, request=request,
+ instance=request.user.financial_info, prefix='fin_info')
- if form.is_valid():
+ if form.is_valid() and fin_info_form.is_valid():
user = form.save()
+ fin_info = fin_info_form.save()
live_image = form.cleaned_data.get('live_image')
@@ -160,17 +181,22 @@ class UserProfileEditViewFull(BaseMixin, View):
live_image.file.delete()
live_image.delete()
+ user.financial_info = fin_info
+ user.save()
+
messages.info(request, 'Пользователь успешно отредактирован')
redirect_to = request.POST.get('next')
return redirect(redirect_to)
else:
- if form.errors:
+ if form.errors or fin_info_form.errors:
messages.info(request, (
'Произошла ошибка (form)
' '{form}'
- ).format(form=pformat(form.errors)))
+ 'Произошла ошибка (fin_info_form)
' + '{fin_info_form}'
+ ).format(form=pformat(form.errors), fin_info_form=pformat(fin_info_form.errors)))
- context.update({'form': form})
+ context.update({'form': form, 'fin_info_form': fin_info_form})
return render(request, self.template_name, context)
@@ -252,188 +278,6 @@ class UserFinancialInfoEditView(BaseMixin, View):
return render(request, self.template_name, context)
-# class ContractorFilterViewOld(BaseMixin, View):
-# template_name = 'contractor_filter.html'
-# form_class = ContractorFilterForm
-#
-# def get(self, request, *args, **kwargs):
-# form = self.form_class(request.GET, request=request)
-# context = self.get_context_data(**_.merge({}, request.GET, kwargs))
-# coll = []
-#
-# if form.is_valid():
-# contractors = teams = None
-# contr_count = team_count = None
-# get_contractors = get_teams = None
-# ord = None
-#
-# cro = form.cleaned_data.get('cro')
-# specialization = form.cleaned_data.get('specialization')
-# location = form.cleaned_data.get('location')
-# work_type = form.cleaned_data.get('work_type')
-# build_classif = form.cleaned_data.get('building_classification')
-# constr_type = form.cleaned_data.get('construction_type')
-#
-# party_types = form.cleaned_data.get('party_types')
-# last_party_types = form.cleaned_data.get('last_party_types')
-#
-# if party_types == 'all':
-# get_contractors = get_teams = True
-# elif party_types == 'contractors':
-# get_contractors = True
-# elif party_types == 'teams':
-# get_teams = True
-# elif not party_types:
-# if last_party_types == 'contractors':
-# get_contractors = True
-# elif last_party_types == 'teams':
-# get_teams = True
-# else:
-# get_contractors = get_teams = True
-#
-# if party_types:
-# last_party_types = party_types
-#
-# context.update({'last_party_types': last_party_types})
-#
-# if get_contractors:
-# contractors = User.contractor_objects.all()
-#
-# if cro:
-# contractors = contractors.filter(cro=cro)
-#
-# if specialization:
-# contractors = contractors.filter(
-# contractor_specializations__lft__gte=specialization.lft,
-# contractor_specializations__rght__lte=specialization.rght,
-# )
-#
-# if location:
-# contractors = contractors.filter(
-# location__lft__gte=location.lft,
-# location__rght__lte=location.rght,
-# )
-#
-# if work_type:
-# contractors = contractors.filter(orders__project__work_type=work_type)
-#
-# if build_classif:
-# contractors = contractors.filter(Q(orders__project__realty__building_classification=build_classif) |
-# Q(contractor_building_classifications=build_classif))
-#
-# if constr_type:
-# contractors = contractors.filter(Q(orders__project__realty__construction_type=constr_type) |
-# Q(contractor_construction_types=constr_type))
-#
-# if get_teams:
-# teams = Team.objects.all()
-#
-# if cro:
-# teams = teams.filter(Q(contractors__cro=cro) | Q(owner__cro=cro))
-#
-# if specialization:
-# teams = teams.filter(
-# (
-# Q(contractors__contractor_specializations__lft__gte=specialization.lft)
-# & Q(contractors__contractor_specializations__rght__lte=specialization.rght)
-# ) | (
-# Q(owner__contractor_specializations__lft__gte=specialization.lft)
-# & Q(owner__contractor_specializations__rght__lte=specialization.rght)
-# ),
-# )
-#
-# if location:
-# teams = teams.filter(
-# (
-# Q(contractors__location__lft__gte=location.lft)
-# & Q(contractors__location__rght__lte=location.rght)
-# ) | (
-# Q(owner__location__lft__gte=location.lft)
-# & Q(owner__location__rght__lte=location.rght)
-# ),
-# )
-#
-# if work_type:
-# teams = teams.filter(
-# Q(contractors__orders__project__work_type=work_type)
-# | Q(owner__orders__project__work_type=work_type),
-# )
-#
-# if build_classif:
-# teams = teams.filter(
-# Q(contractors__orders__project__realty__building_classification=build_classif)
-# | Q(owner__orders__project__realty__building_classification=build_classif),
-# )
-#
-# if constr_type:
-# teams = teams.filter(
-# Q(contractors__orders__project__realty__construction_type=constr_type)
-# | Q(owner__orders__project__realty__construction_type=constr_type),
-# )
-#
-# if get_contractors and get_teams:
-# coll = tuple(itertools.chain(contractors.distinct(), teams.distinct()))
-# count = len(coll)
-# display_msg = 'Найдено %s элементов' % count if count > 0 else 'Ничего не найдено'
-# elif get_contractors:
-# coll = contractors.distinct()
-# count = coll.count()
-# display_msg = 'Найдено %s исполнителей' % count if count > 0 else 'Ничего не найдено'
-# elif get_teams:
-# coll = teams.distinct()
-# count = coll.count()
-# display_msg = 'Найдено %s групп' % count if count > 0 else 'Ничего не найдено'
-#
-# order_by = form.cleaned_data.get('order_by')
-# last_order_by = form.cleaned_data.get('last_order_by')
-# reverse_order = form.cleaned_data.get('reverse_order')
-#
-# if order_by:
-# reverse_order = not reverse_order if order_by == last_order_by else False
-# ord = order_by
-# last_order_by = ord
-# elif last_order_by:
-# ord = last_order_by
-#
-# if ord:
-# if ord == 'name':
-# coll = natsort.natsorted(coll, key=lambda obj: getattr(obj, 'username', None) or obj.name,
-# reverse=reverse_order)
-# elif ord == 'created':
-# coll = natsort.natsorted(coll, key=lambda obj: obj.created, reverse=reverse_order)
-#
-# context.update({
-# 'last_order_by': last_order_by,
-# 'reverse_order': reverse_order,
-# })
-# else:
-# display_msg = 'Пожалуйста, введите корректные данные'
-#
-# if form.errors:
-# messages.info(request, (
-# 'Произошла ошибка (form)
' -# '{form}'
-# ).format(form=pformat(form.errors)))
-#
-# paginator = Paginator(coll, settings.PAGE_SIZE)
-# page = request.GET.get('page')
-#
-# try:
-# coll = paginator.page(page)
-# except PageNotAnInteger:
-# coll = paginator.page(1)
-# except EmptyPage:
-# coll = paginator.page(paginator.num_pages)
-#
-# context.update({
-# 'form': form,
-# 'coll': coll,
-# 'is_paginated': True,
-# 'page_obj': coll,
-# 'display_msg': display_msg,
-# })
-#
-# return render(request, self.template_name, context)
# TODO: не работает сортировка по reviews(не получилось создать отзывы) и views(не нашел счетчик просмотров)
class ContractorFilterView(BaseMixin, View):