diff --git a/README.md b/README.md index 3eb2627..b3d004a 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,22 @@ python manage.py runserver ``` python manage.py shell_plus --use-pythonrc ``` + +---------------------------------------- + +Data generation order: + +1. Superuser +2. Specializations +3. Locations +4. Perm. groups +5. Build. classif-s +6. Constr. types +7. Users +8. Teams +9. Realties +10. Projects +11. Portfolios +12. Reviews + +---------------------------------------- diff --git a/api/views.py b/api/views.py index 408a7ed..8aaeff2 100755 --- a/api/views.py +++ b/api/views.py @@ -55,7 +55,8 @@ class RealtyViewSet(ModelViewSet): class SpecializationViewSet(ModelViewSet): - queryset = Specialization.objects.root_nodes()[0].get_descendants() + # queryset = Specialization.objects.root_nodes()[0].get_descendants() + queryset = Specialization.objects # TODO: Tmp serializer_class = SpecializationSerializer filter_class = SpecializationFilterSet @@ -67,6 +68,7 @@ class UserViewSet(ModelViewSet): class LocationViewSet(ModelViewSet): - queryset = Location.objects.root_nodes()[0].get_descendants() + # queryset = Location.objects.root_nodes()[0].get_descendants() + queryset = Location.objects # TODO: Tmp serializer_class = LocationSerializer filter_class = LocationFilterSet diff --git a/archilance/management/commands/_template.py b/archilance/management/commands/_template.py new file mode 100644 index 0000000..96632b5 --- /dev/null +++ b/archilance/management/commands/_template.py @@ -0,0 +1,20 @@ +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core.management import BaseCommand +from django.utils import timezone +import pydash as _; _.map = _.map_; _.filter = _.filter_ +import random + +from archilance import util +from common.models import Location +from specializations.models import Specialization +from users.models import User, GENDERS, Team + + +class Command(BaseCommand): + def handle(self, *args, **options): + print('---------------------------------------') + print('Generating something...') + print('---------------------------------------') + + pass diff --git a/archilance/management/commands/generate_build_classifs.py b/archilance/management/commands/generate_build_classifs.py new file mode 100644 index 0000000..8a90d35 --- /dev/null +++ b/archilance/management/commands/generate_build_classifs.py @@ -0,0 +1,18 @@ +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core.management import BaseCommand +from django.utils import timezone +import pydash as _; _.map = _.map_; _.filter = _.filter_ +import random + +from archilance import util +from projects.models import BuildingClassfication + + +class Command(BaseCommand): + def handle(self, *args, **options): + print('---------------------------------------') + print('Generating building classifications...') + print('---------------------------------------') + + _.times(lambda i: BuildingClassfication.objects.create(name='Build. classif. %s' % i), 100) diff --git a/archilance/management/commands/generate_constr_types.py b/archilance/management/commands/generate_constr_types.py new file mode 100644 index 0000000..f08b229 --- /dev/null +++ b/archilance/management/commands/generate_constr_types.py @@ -0,0 +1,18 @@ +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core.management import BaseCommand +from django.utils import timezone +import pydash as _; _.map = _.map_; _.filter = _.filter_ +import random + +from archilance import util +from projects.models import ConstructionType + + +class Command(BaseCommand): + def handle(self, *args, **options): + print('---------------------------------------') + print('Generating construction types...') + print('---------------------------------------') + + _.times(lambda i: ConstructionType.objects.create(name='Constr. type %s' % i), 100) diff --git a/archilance/management/commands/generate_portfolios.py b/archilance/management/commands/generate_portfolios.py new file mode 100644 index 0000000..c50b957 --- /dev/null +++ b/archilance/management/commands/generate_portfolios.py @@ -0,0 +1,71 @@ +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core.management import BaseCommand +from django.utils import timezone +import pydash as _; _.map = _.map_; _.filter = _.filter_ +import random + +from archilance import util +from common.models import Location +from projects.models import Portfolio, PortfolioPhoto, CURRENCIES, TERMS, BuildingClassfication , ConstructionType +from specializations.models import Specialization +from users.models import User, Team, GENDERS + + +class Command(BaseCommand): + def handle(self, *args, **options): + print('---------------------------------------') + print('Generating portfolios...') + print('---------------------------------------') + + + # ('photos', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('budget', 'Relation? False', 'Null? True', 'Blank? True', 'Hidden? False'), + # ('building_classification', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('construction_type', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('currency', 'Relation? False', 'Null? True', 'Blank? True', 'Hidden? False'), + # ('description', 'Relation? False', 'Null? False', 'Blank? False', 'Hidden? False'), + # ('location', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('name', 'Relation? False', 'Null? False', 'Blank? False', 'Hidden? False'), + # ('specialization', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('team', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('term', 'Relation? False', 'Null? True', 'Blank? True', 'Hidden? False'), + # ('term_type', 'Relation? False', 'Null? True', 'Blank? True', 'Hidden? False'), + # ('user', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('worksell', 'Relation? False', 'Null? False', 'Blank? True', 'Hidden? False'), + + + def create_portfolio(i): + portf = Portfolio( + name='Portforlio %s' % i, + description="Portforlio %s's description" % i, + budget=util.random_amount(), + currency=_.sample(CURRENCIES)[0], + term=_.random(0, 20), + term_type=_.sample(TERMS)[0], + worksell=_.sample((True, False)), + ) + + portf.save() + + if _.sample((True, False)): + portf.user = User.contractor_objects.order_by('?').first() + else: + portf.team = Team.objects.order_by('?').first() + + portf.building_classification = BuildingClassfication.objects.order_by('?').first() + portf.construction_type = ConstructionType.objects.order_by('?').first() + portf.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first() + portf.specialization = Specialization.objects.root_nodes()[0].get_descendants().order_by('?').first() + + pic_names = _.split('a.png b.png c.jpg d.png e.jpg f.png g.png h.jpg i.png j.png k.jpg l.png m.png n.png o.png p.png q.jpg', ' ') + + _.times( + lambda i_: portf.photos.create(img='_sample_files/%s' % util.take_one_random(pic_names)), + _.random(1, 15), + ) + + portf.save() + return portf + + _.times(create_portfolio, 1000) diff --git a/archilance/management/commands/generate_projects.py b/archilance/management/commands/generate_projects.py index 66f6846..7ff5779 100644 --- a/archilance/management/commands/generate_projects.py +++ b/archilance/management/commands/generate_projects.py @@ -74,7 +74,12 @@ class Command(BaseCommand): project.save() - Order.objects.create(project=project) + Order.objects.create( + project=project, + contractor=_.sample((None, User.contractor_objects.order_by('?').first())), + secure=_.sample((True, False)), + status=_.sample((True, False)), + ) return project diff --git a/archilance/management/commands/generate_realties.py b/archilance/management/commands/generate_realties.py index 9e5c988..fdbc345 100644 --- a/archilance/management/commands/generate_realties.py +++ b/archilance/management/commands/generate_realties.py @@ -33,11 +33,6 @@ class Command(BaseCommand): # ('name', 'Relation? False', 'Null? False', 'Blank? False', 'Hidden? False'), - - _.times(lambda i: BuildingClassfication.objects.create(name='Build. classif. %s' % i), 50) - _.times(lambda i: ConstructionType.objects.create(name='Constr. type %s' % i), 50) - - def create_realty(i): realty = Realty(name='Realty %s' % i) diff --git a/archilance/management/commands/generate_reviews.py b/archilance/management/commands/generate_reviews.py new file mode 100644 index 0000000..649a162 --- /dev/null +++ b/archilance/management/commands/generate_reviews.py @@ -0,0 +1,41 @@ +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core.management import BaseCommand +from django.utils import timezone +import pydash as _; _.map = _.map_; _.filter = _.filter_ +import random + +from archilance import util +from projects.models import Project, Portfolio +from specializations.models import Specialization +from users.models import User, GENDERS, Team +from reviews.models import Review + + +class Command(BaseCommand): + def handle(self, *args, **options): + print('---------------------------------------') + print('Generating reviews...') + print('---------------------------------------') + + def create_review(i): + review = Review() + + review.project = Project.objects.order_by('?').first() + review.stars = _.random(1, 5) + review.text = 'This is a review %s text' % i + review.is_secured = _.sample((True, False)) + + review.save() + + if _.sample((True, False)): + review.from_contractor = User.contractor_objects.order_by('?').first() + review.target_customer = User.customer_objects.order_by('?').first() + else: + review.from_customer = User.customer_objects.order_by('?').first() + review.target_contractor = User.contractor_objects.order_by('?').first() + + review.save() + return review + + _.times(create_review, 300) diff --git a/archilance/management/commands/generate_specializations.py b/archilance/management/commands/generate_specializations.py index cb39472..a288abe 100644 --- a/archilance/management/commands/generate_specializations.py +++ b/archilance/management/commands/generate_specializations.py @@ -18,10 +18,10 @@ class Command(BaseCommand): stages = ('A','B','C','D') for s1 in stages: - x = Specialization.objects.create(name='Стадия %s' % s1, parent=_root) + x = Specialization.objects.create(name='Специализация %s' % s1, parent=_root) for s2 in stages: - y = Specialization.objects.create(name='Стадия %s-%s' % (s1,s2), parent=x) + y = Specialization.objects.create(name='Специализация %s-%s' % (s1,s2), parent=x) for s3 in stages: - z = Specialization.objects.create(name='Стадия %s-%s-%s' % (s1,s2,s3), parent=y) + z = Specialization.objects.create(name='Специализация %s-%s-%s' % (s1,s2,s3), parent=y) for s4 in stages: - Specialization.objects.create(name='Стадия %s-%s-%s-%s' % (s1,s2,s3,s4), parent=z) + Specialization.objects.create(name='Специализация %s-%s-%s-%s' % (s1,s2,s3,s4), parent=z) diff --git a/archilance/management/commands/generate_teams.py b/archilance/management/commands/generate_teams.py new file mode 100644 index 0000000..f5d0317 --- /dev/null +++ b/archilance/management/commands/generate_teams.py @@ -0,0 +1,46 @@ +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core.management import BaseCommand +from django.utils import timezone +import pydash as _; _.map = _.map_; _.filter = _.filter_ +import random + +from archilance import util +from projects.models import Portfolio +from specializations.models import Specialization +from users.models import User, GENDERS, Team + + +class Command(BaseCommand): + def handle(self, *args, **options): + print('---------------------------------------') + print('Generating teams...') + print('---------------------------------------') + + + # ('name', 'Relation? False', 'Null? False', 'Blank? False', 'Hidden? False'), + + # ('portfolios', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('owner', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), + # ('users', 'Relation? True', 'Null? False', '(relation)', 'Hidden? False'), + # ('specializations', 'Relation? True', 'Null? False', '(relation)', 'Hidden? False'), + + + contractors = list(User.contractor_objects.order_by('?')) + + owners = util.take(contractors, len(contractors) // 2) + members = contractors + i = 0 + + for owner in owners: + team = Team(name='Team %s' % i) + team.save() + + team.owner = owner + team.users = _.sample(members, _.random(1, 5)) + + team.specializations = Specialization.objects.root_nodes()[0].get_descendants().order_by('?')[:_.random(1, 5)] + team.portfolios = Portfolio.objects.order_by('?')[:_.random(1, 10)] + + team.save() + i += 1 diff --git a/archilance/management/commands/generate_users.py b/archilance/management/commands/generate_users.py index 17b5c19..e46aac1 100644 --- a/archilance/management/commands/generate_users.py +++ b/archilance/management/commands/generate_users.py @@ -6,6 +6,7 @@ import pydash as _; _.map = _.map_; _.filter = _.filter_ import random from archilance import util +from common.models import Location from specializations.models import Specialization from users.models import User, GENDERS @@ -85,7 +86,7 @@ class Command(BaseCommand): contractor_status=_.sample(User.STATUSES)[0], ) - users = _.times(create_user, 50) + users = _.times(create_user, 500) contractor_group = Group.objects.get(name='Исполнители') @@ -94,6 +95,7 @@ class Command(BaseCommand): for user in users: user.set_password('123') user.groups.add(customer_group if user.pk % 2 == 0 else contractor_group) - user.contractor_specializations = Specialization.objects.order_by('?')[:_.random(1, 5)] + user.contractor_specializations = Specialization.objects.root_nodes()[0].get_descendants().order_by('?')[:_.random(1, 5)] + user.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first() user.save() diff --git a/archilance/management/commands/tmp.py b/archilance/management/commands/tmp.py new file mode 100644 index 0000000..751c975 --- /dev/null +++ b/archilance/management/commands/tmp.py @@ -0,0 +1,28 @@ +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core.management import BaseCommand +from django.utils import timezone +import pydash as _; _.map = _.map_; _.filter = _.filter_ +import random + +from archilance import util +from common.models import Location +from projects.models import Project, Order, CURRENCIES, TERMS, Specialization, Realty +from users.models import User, Team + + +class Command(BaseCommand): + def handle(self, *args, **options): + # for user in User.objects.all(): + # user.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first() + # user.cro = _.sample((True, False)) + # + # user.save() + + #------------------------------------------ + + for team in Team.objects.all(): + # team.specializations = Specialization.objects.root_nodes()[0].get_descendants().order_by('?')[:_.random(1, 5)] + team.created = util.random_date() + + team.save() diff --git a/archilance/settings/base.py b/archilance/settings/base.py index 572c777..9cb8382 100644 --- a/archilance/settings/base.py +++ b/archilance/settings/base.py @@ -248,6 +248,7 @@ EMAIL_DEFAULT = 'noreply@archilance.ru' SHELL_PLUS_POST_IMPORTS = ( # Extra auto imports + 'natsort', ('archilance', 'util'), ('pprint', ('pprint', 'pformat')), ) diff --git a/assets/index.js b/assets/index.js index f86cfa0..380e595 100644 --- a/assets/index.js +++ b/assets/index.js @@ -242,6 +242,7 @@ function getSpecializationTree(specId) { var specs = { specLevel1: null, specLevel2: null, specLevel3: null, specLevel4: null, } + if (specId === null) { return $.when(specs) } else { diff --git a/chat/migrations_/0001_initial.py b/chat/migrations_/0001_initial.py new file mode 100644 index 0000000..7936fa5 --- /dev/null +++ b/chat/migrations_/0001_initial.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-21 15:08 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Message', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('private_type', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'Сообщение', + 'verbose_name_plural': 'Сообщения', + }, + ), + migrations.CreateModel( + name='Notes', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ], + options={ + 'verbose_name': 'Заметка', + 'verbose_name_plural': 'Заметки', + }, + ), + ] diff --git a/chat/migrations_/0002_notes_order.py b/chat/migrations_/0002_notes_order.py new file mode 100644 index 0000000..8062e52 --- /dev/null +++ b/chat/migrations_/0002_notes_order.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-21 15:08 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('chat', '0001_initial'), + ('projects', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='notes', + name='order', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='order_notes', to='projects.Order'), + ), + ] diff --git a/chat/migrations_/0003_auto_20160721_1808.py b/chat/migrations_/0003_auto_20160721_1808.py new file mode 100644 index 0000000..c8cb4f8 --- /dev/null +++ b/chat/migrations_/0003_auto_20160721_1808.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-21 15:08 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('projects', '0001_initial'), + ('chat', '0002_notes_order'), + ] + + operations = [ + migrations.AddField( + model_name='notes', + name='recipent', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recipent_notes', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='notes', + name='sender', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sender_notes', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='message', + name='order', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='order_messages', to='projects.Order'), + ), + migrations.AddField( + model_name='message', + name='recipent', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recipent_messages', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='message', + name='sender', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sender_messages', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/chat/migrations_/__init__.py b/chat/migrations_/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/common/migrations_/0001_initial.py b/common/migrations_/0001_initial.py new file mode 100644 index 0000000..38ffe2f --- /dev/null +++ b/common/migrations_/0001_initial.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-21 15:08 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.db.models.manager +import mptt.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Location', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('type', models.CharField(choices=[('_root', 'Корень'), ('country', 'Страна'), ('region', 'Регион'), ('town', 'Город')], max_length=20)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(db_index=True, editable=False)), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='common.Location')), + ], + options={ + 'verbose_name': 'Местоположение', + 'verbose_name_plural': 'Местоположения', + }, + managers=[ + ('_default_manager', django.db.models.manager.Manager()), + ], + ), + migrations.CreateModel( + name='MainPage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('contractor_text', models.TextField()), + ('customer_text', models.TextField()), + ('video_code', models.TextField()), + ], + options={ + 'verbose_name': 'Главная страница', + }, + ), + migrations.CreateModel( + name='Settings', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('time_notification', models.IntegerField(default=180)), + ], + options={ + 'verbose_name': 'Настройки сайта', + 'verbose_name_plural': 'Настройки сайта', + }, + ), + ] diff --git a/common/migrations_/__init__.py b/common/migrations_/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/common/migrations_mukhtar/0001_initial.py b/common/migrations_mukhtar/0001_initial.py index 7149f56..38ffe2f 100644 --- a/common/migrations_mukhtar/0001_initial.py +++ b/common/migrations_mukhtar/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.6 on 2016-06-15 12:56 +# Generated by Django 1.9.7 on 2016-07-21 15:08 from __future__ import unicode_literals from django.db import migrations, models @@ -17,50 +17,46 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='City', + name='Location', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), + ('name', models.CharField(max_length=50)), + ('type', models.CharField(choices=[('_root', 'Корень'), ('country', 'Страна'), ('region', 'Регион'), ('town', 'Город')], max_length=20)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(db_index=True, editable=False)), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='common.Location')), ], options={ - 'verbose_name_plural': 'Города', - 'verbose_name': 'Город', + 'verbose_name': 'Местоположение', + 'verbose_name_plural': 'Местоположения', }, + managers=[ + ('_default_manager', django.db.models.manager.Manager()), + ], ), migrations.CreateModel( - name='Country', + name='MainPage', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), + ('contractor_text', models.TextField()), + ('customer_text', models.TextField()), + ('video_code', models.TextField()), ], options={ - 'verbose_name_plural': 'Страны', - 'verbose_name': 'Страна', + 'verbose_name': 'Главная страница', }, ), migrations.CreateModel( - name='Location', + name='Settings', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=50)), - ('type', models.CharField(blank=True, choices=[('country', 'Страна'), ('region', 'Регион'), ('town', 'Город')], max_length=20, null=True)), - ('lft', models.PositiveIntegerField(db_index=True, editable=False)), - ('rght', models.PositiveIntegerField(db_index=True, editable=False)), - ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), - ('level', models.PositiveIntegerField(db_index=True, editable=False)), - ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='common.Location')), + ('time_notification', models.IntegerField(default=180)), ], options={ - 'verbose_name_plural': 'Местоположения', - 'verbose_name': 'Местоположение', + 'verbose_name': 'Настройки сайта', + 'verbose_name_plural': 'Настройки сайта', }, - managers=[ - ('_default_manager', django.db.models.manager.Manager()), - ], - ), - migrations.AddField( - model_name='city', - name='country', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cities', to='common.Country'), ), ] diff --git a/common/templatetags/common_tags.py b/common/templatetags/common_tags.py index 502febf..f73a9a0 100644 --- a/common/templatetags/common_tags.py +++ b/common/templatetags/common_tags.py @@ -30,6 +30,11 @@ def to_str(val): return str(val) +@register.filter('class_name') +def class_name(val): + return type(val).__name__ + + @register.filter def multiply(string, times): return string * times diff --git a/projects/forms.py b/projects/forms.py index a7580c3..c5cb322 100644 --- a/projects/forms.py +++ b/projects/forms.py @@ -10,11 +10,6 @@ from common.models import Location from users.models import User -# RealtyFormSet = inlineformset_factory(Project, Realty) - - - - class ProjectFilterForm(forms.ModelForm): PROJECT_ORDER_CHOICES = ( # "Упорядочить по"... ('name', 'названию'), @@ -51,7 +46,8 @@ class ProjectFilterForm(forms.ModelForm): self.fields['specialization'].required = False - self.fields['specialization'].queryset = Specialization.objects.root_nodes()[0].get_descendants() + # self.fields['specialization'].queryset = Specialization.objects.root_nodes()[0].get_descendants() + self.fields['specialization'].queryset = Specialization.objects # TODO: Tmp class ProjectFilterRealtyForm(forms.ModelForm): @@ -79,7 +75,8 @@ class ProjectFilterRealtyForm(forms.ModelForm): self.fields['construction_type'].empty_label = '' self.fields['construction_type'].required = False - self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() + # self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() + self.fields['location'].queryset = Location.objects # TODO: Tmp class CustomerProjectEditForm(forms.ModelForm): @@ -119,7 +116,9 @@ class CustomerProjectEditForm(forms.ModelForm): super().__init__(*args, **kwargs) self.fields['realty'].empty_label = 'Создать новый' - self.fields['specialization'].queryset = Specialization.objects.root_nodes()[0].get_descendants() + + # self.fields['specialization'].queryset = Specialization.objects.root_nodes()[0].get_descendants() + self.fields['specialization'].queryset = Specialization.objects # TODO: Tmp if self.instance.pk: self.fields['files'].queryset = self.instance.files @@ -145,7 +144,8 @@ class RealtyForm(forms.ModelForm): self.request = kwargs.pop('request') super().__init__(*args, **kwargs) - self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() + # self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() + self.fields['location'].queryset = Location.objects # TODO: Tmp class Realty1Form(forms.Form): diff --git a/projects/migrations/0002_auto_20160721_1808.py b/projects/migrations/0002_auto_20160721_1808.py new file mode 100644 index 0000000..ee62ee3 --- /dev/null +++ b/projects/migrations/0002_auto_20160721_1808.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-21 15:08 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import mptt.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('users', '0001_initial'), + ('common', '0001_initial'), + ('projects', '0001_initial'), + ('specializations', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='realty', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='realties', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='projectfile', + name='project', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='files', to='projects.Project'), + ), + migrations.AddField( + model_name='project', + name='customer', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='projects', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='project', + name='realty', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='projects', to='projects.Realty'), + ), + migrations.AddField( + model_name='project', + name='specialization', + field=mptt.fields.TreeForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='projects', to='specializations.Specialization'), + ), + migrations.AddField( + model_name='portfoliophoto', + name='portfolio', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='photos', to='projects.Portfolio'), + ), + migrations.AddField( + model_name='portfolio', + name='building_classification', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='projects.BuildingClassfication'), + ), + migrations.AddField( + model_name='portfolio', + name='construction_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='projects.ConstructionType'), + ), + migrations.AddField( + model_name='portfolio', + name='location', + field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='common.Location'), + ), + migrations.AddField( + model_name='portfolio', + name='specialization', + field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='specializations.Specialization'), + ), + migrations.AddField( + model_name='portfolio', + name='team', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='users.Team'), + ), + migrations.AddField( + model_name='portfolio', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='order', + name='contractor', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='order', + name='project', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='order', to='projects.Project'), + ), + migrations.AddField( + model_name='candidate', + name='answer', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='candidates', to='projects.Answer'), + ), + migrations.AddField( + model_name='candidate', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='candidates', to='projects.Project'), + ), + migrations.AddField( + model_name='answer', + name='contractor', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='answer', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='projects.Project'), + ), + ] diff --git a/projects/migrations_/0001_initial.py b/projects/migrations_/0001_initial.py new file mode 100644 index 0000000..6eb2ceb --- /dev/null +++ b/projects/migrations_/0001_initial.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-21 15:08 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import mptt.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('common', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Answer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('budget', models.DecimalField(decimal_places=0, max_digits=10)), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('currency', models.CharField(choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=5)), + ('term', models.IntegerField(default=0)), + ('term_type', models.CharField(choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=10)), + ('text', models.TextField()), + ], + options={ + 'verbose_name': 'Ответ к проекту', + 'ordering': ('-created',), + 'verbose_name_plural': 'Ответы к проектам', + }, + ), + migrations.CreateModel( + name='BuildingClassfication', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ], + options={ + 'verbose_name': 'Тип здания', + 'verbose_name_plural': 'Типы зданий', + }, + ), + migrations.CreateModel( + name='Candidate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('status', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'Кандидат', + 'verbose_name_plural': 'Кандидаты', + }, + ), + migrations.CreateModel( + name='ConstructionType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ], + options={ + 'verbose_name': 'Вид строительства', + 'verbose_name_plural': 'Виды строительства', + }, + ), + migrations.CreateModel( + name='Order', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('secure', models.BooleanField(default=False)), + ('status', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'Заказ', + 'verbose_name_plural': 'Заказы', + }, + ), + migrations.CreateModel( + name='Portfolio', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('budget', models.DecimalField(blank=True, decimal_places=0, default=0, max_digits=10, null=True)), + ('currency', models.CharField(blank=True, choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=20, null=True)), + ('description', models.TextField()), + ('name', models.CharField(max_length=255)), + ('term', models.IntegerField(blank=True, default=0, null=True)), + ('term_type', models.CharField(blank=True, choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=20, null=True)), + ('worksell', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'Портфолио', + 'verbose_name_plural': 'Портфолио', + }, + ), + migrations.CreateModel( + name='PortfolioPhoto', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('img', models.ImageField(upload_to='projects/portfolio')), + ], + options={ + 'verbose_name': 'Фото портфолио', + 'verbose_name_plural': 'Фото портфолио', + }, + ), + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('budget', models.DecimalField(decimal_places=0, max_digits=10)), + ('budget_by_agreement', models.BooleanField(default=False)), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('cro', models.BooleanField(default=False)), + ('currency', models.CharField(choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=20)), + ('deal_type', models.CharField(choices=[('secure_deal', 'Безопасная сделка (с резервированием бюджета) '), ('direct_payment', 'Прямая оплата Исполнителю на его кошелек/счет')], default='secure_deal', max_length=20)), + ('name', models.CharField(max_length=255)), + ('price_and_term_required', models.BooleanField(default=False)), + ('state', models.CharField(choices=[('active', 'Активный'), ('trashed', 'В корзине'), ('deleted', 'Удален')], default='active', max_length=20)), + ('term', models.IntegerField(default=0)), + ('term_type', models.CharField(choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=20)), + ('text', models.TextField(blank=True)), + ('work_type', models.IntegerField(choices=[(1, 'Проектирование'), (2, 'Техническое сопровождение')], default=1)), + ], + options={ + 'verbose_name': 'Проект', + 'verbose_name_plural': 'Проекты', + }, + ), + migrations.CreateModel( + name='ProjectFile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file', models.FileField(upload_to='projects/project_files')), + ], + options={ + 'verbose_name': 'Файл проекта', + 'verbose_name_plural': 'Файлы проектов', + }, + ), + migrations.CreateModel( + name='Realty', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('building_classification', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='realties', to='projects.BuildingClassfication')), + ('construction_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='realties', to='projects.ConstructionType')), + ('location', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='realties', to='common.Location')), + ], + options={ + 'verbose_name': 'Объект', + 'verbose_name_plural': 'Объекты', + }, + ), + migrations.CreateModel( + name='Stage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cost', models.DecimalField(decimal_places=0, max_digits=10)), + ('cost_type', models.CharField(choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=5)), + ('name', models.CharField(max_length=255)), + ('result', models.CharField(max_length=255)), + ('term', models.IntegerField(default=0)), + ('term_type', models.CharField(choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=10)), + ('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stages', to='projects.Order')), + ], + options={ + 'verbose_name': 'Этап', + 'verbose_name_plural': 'Этапы', + }, + ), + ] diff --git a/projects/migrations_/0002_auto_20160721_1808.py b/projects/migrations_/0002_auto_20160721_1808.py new file mode 100644 index 0000000..ee62ee3 --- /dev/null +++ b/projects/migrations_/0002_auto_20160721_1808.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-21 15:08 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import mptt.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('users', '0001_initial'), + ('common', '0001_initial'), + ('projects', '0001_initial'), + ('specializations', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='realty', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='realties', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='projectfile', + name='project', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='files', to='projects.Project'), + ), + migrations.AddField( + model_name='project', + name='customer', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='projects', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='project', + name='realty', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='projects', to='projects.Realty'), + ), + migrations.AddField( + model_name='project', + name='specialization', + field=mptt.fields.TreeForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='projects', to='specializations.Specialization'), + ), + migrations.AddField( + model_name='portfoliophoto', + name='portfolio', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='photos', to='projects.Portfolio'), + ), + migrations.AddField( + model_name='portfolio', + name='building_classification', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='projects.BuildingClassfication'), + ), + migrations.AddField( + model_name='portfolio', + name='construction_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='projects.ConstructionType'), + ), + migrations.AddField( + model_name='portfolio', + name='location', + field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='common.Location'), + ), + migrations.AddField( + model_name='portfolio', + name='specialization', + field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='specializations.Specialization'), + ), + migrations.AddField( + model_name='portfolio', + name='team', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='users.Team'), + ), + migrations.AddField( + model_name='portfolio', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='order', + name='contractor', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='order', + name='project', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='order', to='projects.Project'), + ), + migrations.AddField( + model_name='candidate', + name='answer', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='candidates', to='projects.Answer'), + ), + migrations.AddField( + model_name='candidate', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='candidates', to='projects.Project'), + ), + migrations.AddField( + model_name='answer', + name='contractor', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='answer', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='projects.Project'), + ), + ] diff --git a/projects/migrations_/__init__.py b/projects/migrations_/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/projects/migrations_mukhtar/0001_initial.py b/projects/migrations_mukhtar/0001_initial.py index 3e88e10..6eb2ceb 100644 --- a/projects/migrations_mukhtar/0001_initial.py +++ b/projects/migrations_mukhtar/0001_initial.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.6 on 2016-05-19 10:22 +# Generated by Django 1.9.7 on 2016-07-21 15:08 from __future__ import unicode_literals from django.db import migrations, models import django.db.models.deletion +import django.utils.timezone +import mptt.fields class Migration(migrations.Migration): @@ -11,6 +13,7 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('common', '0001_initial'), ] operations = [ @@ -18,44 +21,156 @@ class Migration(migrations.Migration): name='Answer', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('cost', models.DecimalField(decimal_places=2, max_digits=10)), - ('cost_type', models.CharField(choices=[('RUR', 'rur'), ('USD', 'usd'), ('EUR', 'eur')], default='RUR', max_length=5)), + ('budget', models.DecimalField(decimal_places=0, max_digits=10)), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('currency', models.CharField(choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=5)), + ('term', models.IntegerField(default=0)), + ('term_type', models.CharField(choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=10)), ('text', models.TextField()), - ('term', models.DecimalField(decimal_places=2, max_digits=10)), - ('term_type', models.CharField(choices=[('HOUR', 'hour'), ('DAY', 'day'), ('MONTH', 'month')], default='hour', max_length=10)), ], options={ 'verbose_name': 'Ответ к проекту', + 'ordering': ('-created',), 'verbose_name_plural': 'Ответы к проектам', }, ), migrations.CreateModel( - name='Portfolio', + name='BuildingClassfication', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ], + options={ + 'verbose_name': 'Тип здания', + 'verbose_name_plural': 'Типы зданий', + }, + ), + migrations.CreateModel( + name='Candidate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('status', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'Кандидат', + 'verbose_name_plural': 'Кандидаты', + }, + ), + migrations.CreateModel( + name='ConstructionType', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255)), + ], + options={ + 'verbose_name': 'Вид строительства', + 'verbose_name_plural': 'Виды строительства', + }, + ), + migrations.CreateModel( + name='Order', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('secure', models.BooleanField(default=False)), + ('status', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'Заказ', + 'verbose_name_plural': 'Заказы', + }, + ), + migrations.CreateModel( + name='Portfolio', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('budget', models.DecimalField(blank=True, decimal_places=0, default=0, max_digits=10, null=True)), + ('currency', models.CharField(blank=True, choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=20, null=True)), ('description', models.TextField()), + ('name', models.CharField(max_length=255)), + ('term', models.IntegerField(blank=True, default=0, null=True)), + ('term_type', models.CharField(blank=True, choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=20, null=True)), + ('worksell', models.BooleanField(default=False)), ], + options={ + 'verbose_name': 'Портфолио', + 'verbose_name_plural': 'Портфолио', + }, ), migrations.CreateModel( name='PortfolioPhoto', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('img', models.ImageField(upload_to='projects/portfolio')), - ('portfolio', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='projects.Portfolio')), ], + options={ + 'verbose_name': 'Фото портфолио', + 'verbose_name_plural': 'Фото портфолио', + }, ), migrations.CreateModel( name='Project', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('budget', models.DecimalField(decimal_places=0, max_digits=10)), + ('budget_by_agreement', models.BooleanField(default=False)), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('cro', models.BooleanField(default=False)), + ('currency', models.CharField(choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=20)), + ('deal_type', models.CharField(choices=[('secure_deal', 'Безопасная сделка (с резервированием бюджета) '), ('direct_payment', 'Прямая оплата Исполнителю на его кошелек/счет')], default='secure_deal', max_length=20)), ('name', models.CharField(max_length=255)), - ('price', models.DecimalField(decimal_places=2, max_digits=10)), + ('price_and_term_required', models.BooleanField(default=False)), + ('state', models.CharField(choices=[('active', 'Активный'), ('trashed', 'В корзине'), ('deleted', 'Удален')], default='active', max_length=20)), + ('term', models.IntegerField(default=0)), + ('term_type', models.CharField(choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=20)), ('text', models.TextField(blank=True)), + ('work_type', models.IntegerField(choices=[(1, 'Проектирование'), (2, 'Техническое сопровождение')], default=1)), ], options={ 'verbose_name': 'Проект', 'verbose_name_plural': 'Проекты', }, ), + migrations.CreateModel( + name='ProjectFile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file', models.FileField(upload_to='projects/project_files')), + ], + options={ + 'verbose_name': 'Файл проекта', + 'verbose_name_plural': 'Файлы проектов', + }, + ), + migrations.CreateModel( + name='Realty', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('building_classification', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='realties', to='projects.BuildingClassfication')), + ('construction_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='realties', to='projects.ConstructionType')), + ('location', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='realties', to='common.Location')), + ], + options={ + 'verbose_name': 'Объект', + 'verbose_name_plural': 'Объекты', + }, + ), + migrations.CreateModel( + name='Stage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cost', models.DecimalField(decimal_places=0, max_digits=10)), + ('cost_type', models.CharField(choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=5)), + ('name', models.CharField(max_length=255)), + ('result', models.CharField(max_length=255)), + ('term', models.IntegerField(default=0)), + ('term_type', models.CharField(choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=10)), + ('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stages', to='projects.Order')), + ], + options={ + 'verbose_name': 'Этап', + 'verbose_name_plural': 'Этапы', + }, + ), ] diff --git a/projects/models.py b/projects/models.py index f166d57..df4edcd 100644 --- a/projects/models.py +++ b/projects/models.py @@ -3,9 +3,10 @@ from datetime import datetime from django.db import models from django.utils import timezone -from users.models import User +from users.models import User, Team from specializations.models import Specialization + CURRENCIES = ( ('rur', 'RUR'), ('usd', 'USD'), @@ -19,6 +20,7 @@ TERMS = ( ('month', 'За месяц'), ) + class BuildingClassfication(models.Model): name = models.CharField(max_length=255) @@ -79,16 +81,16 @@ class Project(models.Model): cro = models.BooleanField(default=False) currency = models.CharField(max_length=20, default='rur', choices=CURRENCIES) customer = models.ForeignKey(User, related_name='projects') + deal_type = models.CharField(max_length=20, default='secure_deal', choices=DEAL_TYPES) name = models.CharField(max_length=255) price_and_term_required = models.BooleanField(default=False) realty = models.ForeignKey(Realty, blank=True, null=True, related_name='projects') - deal_type = models.CharField(max_length=20, default='secure_deal', choices=DEAL_TYPES) specialization = TreeForeignKey(Specialization, related_name='projects') + state = models.CharField(default='active', max_length=20, choices=STATES) term = models.IntegerField(default=0) term_type = models.CharField(max_length=20, choices=TERMS, default='hour') text = models.TextField(blank=True) work_type = models.IntegerField(default=1, choices=WORK_TYPES) - state = models.CharField(default='active', max_length=20, choices=STATES) def __str__(self): return self.name @@ -115,13 +117,13 @@ class ProjectFile(models.Model): class Answer(models.Model): budget = models.DecimalField(max_digits=10, decimal_places=0) - currency = models.CharField(max_length=5, choices=CURRENCIES, default='rur') + contractor = models.ForeignKey(User, related_name='answers') created = models.DateTimeField(default=timezone.now) + currency = models.CharField(max_length=5, choices=CURRENCIES, default='rur') project = models.ForeignKey(Project, related_name='answers') term = models.IntegerField(default=0) term_type = models.CharField(max_length=10, choices=TERMS, default='hour') text = models.TextField() - contractor = models.ForeignKey(User, related_name='answers') def __str__(self): return self.text @@ -178,18 +180,19 @@ class Candidate(models.Model): class Portfolio(models.Model): - description = models.TextField() - name = models.CharField(max_length=255) budget = models.DecimalField(max_digits=10, decimal_places=0, default=0, null=True, blank=True) + building_classification = models.ForeignKey(BuildingClassfication, related_name='portfolios', null=True, blank=True) + construction_type = models.ForeignKey(ConstructionType, related_name='portfolios', null=True, blank=True) currency = models.CharField(max_length=20, default='rur', choices=CURRENCIES, null=True, blank=True) - specialization = TreeForeignKey(Specialization, related_name='portfolios',null=True, blank=True) - term = models.IntegerField(default=0,null=True, blank=True) - term_type = models.CharField(max_length=20, choices=TERMS, default='hour',null=True, blank=True) - building_classification = models.ForeignKey(BuildingClassfication, related_name='portfolios',null=True, blank=True) - construction_type = models.ForeignKey(ConstructionType, related_name='portfolios',null=True, blank=True) + description = models.TextField() location = TreeForeignKey('common.Location', related_name='portfolios', null=True, blank=True) + name = models.CharField(max_length=255) + specialization = TreeForeignKey(Specialization, related_name='portfolios', null=True, blank=True) + team = models.ForeignKey(Team, related_name='portfolios', null=True, blank=True) + term = models.IntegerField(default=0, null=True, blank=True) + term_type = models.CharField(max_length=20, choices=TERMS, default='hour', null=True, blank=True) + user = models.ForeignKey(User, related_name='portfolios', null=True, blank=True) worksell = models.BooleanField(default=False) - user = models.ForeignKey(User, related_name='portfolios') def __str__(self): return self.name @@ -199,20 +202,17 @@ class Portfolio(models.Model): verbose_name_plural = 'Портфолио' def get_cover(self): - cover = None - all_photos = self.portfoliophoto_set.all() - if all_photos: - cover = all_photos[0].img - return cover + photo = self.photos.first() + return photo and photo.img.url class PortfolioPhoto(models.Model): img = models.ImageField(upload_to='projects/portfolio') - portfolio = models.ForeignKey(Portfolio) - + portfolio = models.ForeignKey(Portfolio, related_name='photos') + class Meta: verbose_name = 'Фото портфолио' verbose_name_plural = 'Фото портфолио' - - # def __str__(self): - # return self.img + + def __str__(self): + return self.img and self.img.url or str(self.img) diff --git a/projects/templates/project_filter.html b/projects/templates/project_filter.html index e921393..f8231f2 100644 --- a/projects/templates/project_filter.html +++ b/projects/templates/project_filter.html @@ -13,7 +13,7 @@