From 7c5bbe4aaaad4b47b6576789ee6d4409988b0c94 Mon Sep 17 00:00:00 2001 From: vlnko Date: Wed, 3 Dec 2025 11:16:47 +0300 Subject: [PATCH] first commit --- .DS_Store | Bin 0 -> 8196 bytes .gitignore | 129 + .idea/.gitignore | 8 + .idea/dataSources.xml | 12 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/oasupportapp.iml | 30 + clientapp/.DS_Store | Bin 0 -> 6148 bytes clientapp/__init__.py | 0 clientapp/admin.py | 50 + clientapp/apps.py | 5 + clientapp/forms.py | 42 + clientapp/migrations/0001_initial.py | 101 + .../migrations/0002_auto_20210411_1042.py | 23 + .../0003_remove_customuser_company.py | 17 + .../migrations/0004_customuser_company.py | 19 + .../migrations/0005_customuser_something.py | 18 + .../0006_remove_customuser_something.py | 17 + .../migrations/0007_auto_20210411_1428.py | 20 + .../migrations/0008_status_css_styles.py | 18 + .../migrations/0009_alter_call_author.py | 20 + .../0010_alter_status_css_styles.py | 18 + ...0011_alter_status_css_styles_addmessage.py | 35 + .../0012_alter_addmessage_created.py | 18 + clientapp/migrations/__init__.py | 0 clientapp/models.py | 79 + clientapp/templates/.DS_Store | Bin 0 -> 6148 bytes clientapp/templates/clientapp/.DS_Store | Bin 0 -> 6148 bytes clientapp/templates/clientapp/addnewcall.html | 30 + clientapp/templates/clientapp/archive.html | 35 + clientapp/templates/clientapp/base.html | 30 + clientapp/templates/clientapp/call.html | 101 + clientapp/templates/clientapp/index.html | 47 + clientapp/templates/clientapp/login.html | 36 + clientapp/templates/clientapp/staffhome.html | 45 + clientapp/tests.py | 3 + clientapp/urls.py | 13 + clientapp/views.py | 120 + db.sqlite3 | Bin 0 -> 233472 bytes env/bin/Activate.ps1 | 247 + env/bin/activate | 70 + env/bin/activate.csh | 27 + env/bin/activate.fish | 69 + env/bin/django-admin | 8 + env/bin/pip | 8 + env/bin/pip3 | 8 + env/bin/pip3.12 | 8 + env/bin/python | 1 + env/bin/python3 | 1 + env/bin/python3.12 | 1 + env/bin/sqlformat | 8 + env/pyvenv.cfg | 5 + manage.py | 22 + media/.DS_Store | Bin 0 -> 6148 bytes ...6ea2523ee_Авибус_Мобильная_автостанция.pdf | Bin 0 -> 43961 bytes media/media/wu-yi-lBeqbh6QTpI-unsplash.jpeg | Bin 0 -> 77745 bytes .../wu-yi-lBeqbh6QTpI-unsplash_GNZ8dq7.jpeg | Bin 0 -> 77745 bytes media/media/рязань_по_поводу_18-07-24.txt | 13 + oasupportapp/__init__.py | 0 oasupportapp/asgi.py | 16 + oasupportapp/settings.py | 124 + oasupportapp/urls.py | 13 + oasupportapp/wsgi.py | 16 + readme.md | 3 + requirements.txt | Bin 0 -> 170 bytes static/css/main.css | 398 + static/img/logo.png | Bin 0 -> 7347 bytes staticfiles/admin/css/autocomplete.css | 260 + staticfiles/admin/css/base.css | 966 ++ staticfiles/admin/css/changelists.css | 355 + staticfiles/admin/css/dashboard.css | 26 + staticfiles/admin/css/fonts.css | 20 + staticfiles/admin/css/forms.css | 527 + staticfiles/admin/css/login.css | 79 + staticfiles/admin/css/nav_sidebar.css | 119 + staticfiles/admin/css/responsive.css | 1004 ++ staticfiles/admin/css/responsive_rtl.css | 80 + staticfiles/admin/css/rtl.css | 249 + .../css/vendor/select2/LICENSE-SELECT2.md | 21 + .../admin/css/vendor/select2/select2.css | 481 + .../admin/css/vendor/select2/select2.min.css | 1 + staticfiles/admin/css/widgets.css | 574 + staticfiles/admin/fonts/LICENSE.txt | 202 + staticfiles/admin/fonts/README.txt | 3 + .../admin/fonts/Roboto-Bold-webfont.woff | Bin 0 -> 86184 bytes .../admin/fonts/Roboto-Light-webfont.woff | Bin 0 -> 85692 bytes .../admin/fonts/Roboto-Regular-webfont.woff | Bin 0 -> 85876 bytes staticfiles/admin/img/LICENSE | 20 + staticfiles/admin/img/README.txt | 7 + staticfiles/admin/img/calendar-icons.svg | 14 + staticfiles/admin/img/gis/move_vertex_off.svg | 1 + staticfiles/admin/img/gis/move_vertex_on.svg | 1 + staticfiles/admin/img/icon-addlink.svg | 3 + staticfiles/admin/img/icon-alert.svg | 3 + staticfiles/admin/img/icon-calendar.svg | 9 + staticfiles/admin/img/icon-changelink.svg | 3 + staticfiles/admin/img/icon-clock.svg | 9 + staticfiles/admin/img/icon-deletelink.svg | 3 + staticfiles/admin/img/icon-no.svg | 3 + staticfiles/admin/img/icon-unknown-alt.svg | 3 + staticfiles/admin/img/icon-unknown.svg | 3 + staticfiles/admin/img/icon-viewlink.svg | 3 + staticfiles/admin/img/icon-yes.svg | 3 + staticfiles/admin/img/inline-delete.svg | 3 + staticfiles/admin/img/search.svg | 3 + staticfiles/admin/img/selector-icons.svg | 34 + staticfiles/admin/img/sorting-icons.svg | 19 + staticfiles/admin/img/tooltag-add.svg | 3 + staticfiles/admin/img/tooltag-arrowright.svg | 3 + staticfiles/admin/js/SelectBox.js | 110 + staticfiles/admin/js/SelectFilter2.js | 236 + staticfiles/admin/js/actions.js | 154 + staticfiles/admin/js/actions.min.js | 7 + .../admin/js/admin/DateTimeShortcuts.js | 417 + .../admin/js/admin/RelatedObjectLookups.js | 159 + staticfiles/admin/js/autocomplete.js | 38 + staticfiles/admin/js/calendar.js | 207 + staticfiles/admin/js/cancel.js | 28 + staticfiles/admin/js/change_form.js | 16 + staticfiles/admin/js/collapse.js | 43 + staticfiles/admin/js/collapse.min.js | 2 + staticfiles/admin/js/core.js | 163 + staticfiles/admin/js/inlines.js | 348 + staticfiles/admin/js/inlines.min.js | 11 + staticfiles/admin/js/jquery.init.js | 8 + staticfiles/admin/js/nav_sidebar.js | 39 + staticfiles/admin/js/popup_response.js | 16 + staticfiles/admin/js/prepopulate.js | 43 + staticfiles/admin/js/prepopulate.min.js | 1 + staticfiles/admin/js/prepopulate_init.js | 11 + staticfiles/admin/js/urlify.js | 185 + .../admin/js/vendor/jquery/LICENSE.txt | 20 + staticfiles/admin/js/vendor/jquery/jquery.js | 10872 ++++++++++++++++ .../admin/js/vendor/jquery/jquery.min.js | 2 + .../admin/js/vendor/select2/LICENSE.md | 21 + .../admin/js/vendor/select2/i18n/af.js | 3 + .../admin/js/vendor/select2/i18n/ar.js | 3 + .../admin/js/vendor/select2/i18n/az.js | 3 + .../admin/js/vendor/select2/i18n/bg.js | 3 + .../admin/js/vendor/select2/i18n/bn.js | 3 + .../admin/js/vendor/select2/i18n/bs.js | 3 + .../admin/js/vendor/select2/i18n/ca.js | 3 + .../admin/js/vendor/select2/i18n/cs.js | 3 + .../admin/js/vendor/select2/i18n/da.js | 3 + .../admin/js/vendor/select2/i18n/de.js | 3 + .../admin/js/vendor/select2/i18n/dsb.js | 3 + .../admin/js/vendor/select2/i18n/el.js | 3 + .../admin/js/vendor/select2/i18n/en.js | 3 + .../admin/js/vendor/select2/i18n/es.js | 3 + .../admin/js/vendor/select2/i18n/et.js | 3 + .../admin/js/vendor/select2/i18n/eu.js | 3 + .../admin/js/vendor/select2/i18n/fa.js | 3 + .../admin/js/vendor/select2/i18n/fi.js | 3 + .../admin/js/vendor/select2/i18n/fr.js | 3 + .../admin/js/vendor/select2/i18n/gl.js | 3 + .../admin/js/vendor/select2/i18n/he.js | 3 + .../admin/js/vendor/select2/i18n/hi.js | 3 + .../admin/js/vendor/select2/i18n/hr.js | 3 + .../admin/js/vendor/select2/i18n/hsb.js | 3 + .../admin/js/vendor/select2/i18n/hu.js | 3 + .../admin/js/vendor/select2/i18n/hy.js | 3 + .../admin/js/vendor/select2/i18n/id.js | 3 + .../admin/js/vendor/select2/i18n/is.js | 3 + .../admin/js/vendor/select2/i18n/it.js | 3 + .../admin/js/vendor/select2/i18n/ja.js | 3 + .../admin/js/vendor/select2/i18n/ka.js | 3 + .../admin/js/vendor/select2/i18n/km.js | 3 + .../admin/js/vendor/select2/i18n/ko.js | 3 + .../admin/js/vendor/select2/i18n/lt.js | 3 + .../admin/js/vendor/select2/i18n/lv.js | 3 + .../admin/js/vendor/select2/i18n/mk.js | 3 + .../admin/js/vendor/select2/i18n/ms.js | 3 + .../admin/js/vendor/select2/i18n/nb.js | 3 + .../admin/js/vendor/select2/i18n/ne.js | 3 + .../admin/js/vendor/select2/i18n/nl.js | 3 + .../admin/js/vendor/select2/i18n/pl.js | 3 + .../admin/js/vendor/select2/i18n/ps.js | 3 + .../admin/js/vendor/select2/i18n/pt-BR.js | 3 + .../admin/js/vendor/select2/i18n/pt.js | 3 + .../admin/js/vendor/select2/i18n/ro.js | 3 + .../admin/js/vendor/select2/i18n/ru.js | 3 + .../admin/js/vendor/select2/i18n/sk.js | 3 + .../admin/js/vendor/select2/i18n/sl.js | 3 + .../admin/js/vendor/select2/i18n/sq.js | 3 + .../admin/js/vendor/select2/i18n/sr-Cyrl.js | 3 + .../admin/js/vendor/select2/i18n/sr.js | 3 + .../admin/js/vendor/select2/i18n/sv.js | 3 + .../admin/js/vendor/select2/i18n/th.js | 3 + .../admin/js/vendor/select2/i18n/tk.js | 3 + .../admin/js/vendor/select2/i18n/tr.js | 3 + .../admin/js/vendor/select2/i18n/uk.js | 3 + .../admin/js/vendor/select2/i18n/vi.js | 3 + .../admin/js/vendor/select2/i18n/zh-CN.js | 3 + .../admin/js/vendor/select2/i18n/zh-TW.js | 3 + .../admin/js/vendor/select2/select2.full.js | 6820 ++++++++++ .../js/vendor/select2/select2.full.min.js | 2 + .../admin/js/vendor/xregexp/LICENSE.txt | 21 + .../admin/js/vendor/xregexp/xregexp.js | 4652 +++++++ .../admin/js/vendor/xregexp/xregexp.min.js | 160 + staticfiles/css/main.css | 299 + staticfiles/img/logo.png | Bin 0 -> 7347 bytes 202 files changed, 32631 insertions(+) create mode 100644 .DS_Store create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/dataSources.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/oasupportapp.iml create mode 100644 clientapp/.DS_Store create mode 100644 clientapp/__init__.py create mode 100644 clientapp/admin.py create mode 100644 clientapp/apps.py create mode 100644 clientapp/forms.py create mode 100644 clientapp/migrations/0001_initial.py create mode 100644 clientapp/migrations/0002_auto_20210411_1042.py create mode 100644 clientapp/migrations/0003_remove_customuser_company.py create mode 100644 clientapp/migrations/0004_customuser_company.py create mode 100644 clientapp/migrations/0005_customuser_something.py create mode 100644 clientapp/migrations/0006_remove_customuser_something.py create mode 100644 clientapp/migrations/0007_auto_20210411_1428.py create mode 100644 clientapp/migrations/0008_status_css_styles.py create mode 100644 clientapp/migrations/0009_alter_call_author.py create mode 100644 clientapp/migrations/0010_alter_status_css_styles.py create mode 100644 clientapp/migrations/0011_alter_status_css_styles_addmessage.py create mode 100644 clientapp/migrations/0012_alter_addmessage_created.py create mode 100644 clientapp/migrations/__init__.py create mode 100644 clientapp/models.py create mode 100644 clientapp/templates/.DS_Store create mode 100644 clientapp/templates/clientapp/.DS_Store create mode 100644 clientapp/templates/clientapp/addnewcall.html create mode 100644 clientapp/templates/clientapp/archive.html create mode 100644 clientapp/templates/clientapp/base.html create mode 100644 clientapp/templates/clientapp/call.html create mode 100644 clientapp/templates/clientapp/index.html create mode 100644 clientapp/templates/clientapp/login.html create mode 100644 clientapp/templates/clientapp/staffhome.html create mode 100644 clientapp/tests.py create mode 100644 clientapp/urls.py create mode 100644 clientapp/views.py create mode 100644 db.sqlite3 create mode 100644 env/bin/Activate.ps1 create mode 100644 env/bin/activate create mode 100644 env/bin/activate.csh create mode 100644 env/bin/activate.fish create mode 100755 env/bin/django-admin create mode 100755 env/bin/pip create mode 100755 env/bin/pip3 create mode 100755 env/bin/pip3.12 create mode 120000 env/bin/python create mode 120000 env/bin/python3 create mode 120000 env/bin/python3.12 create mode 100755 env/bin/sqlformat create mode 100644 env/pyvenv.cfg create mode 100755 manage.py create mode 100644 media/.DS_Store create mode 100644 media/media/ee565277-6d18-466b-9cf7-61b6ea2523ee_Авибус_Мобильная_автостанция.pdf create mode 100644 media/media/wu-yi-lBeqbh6QTpI-unsplash.jpeg create mode 100644 media/media/wu-yi-lBeqbh6QTpI-unsplash_GNZ8dq7.jpeg create mode 100644 media/media/рязань_по_поводу_18-07-24.txt create mode 100644 oasupportapp/__init__.py create mode 100644 oasupportapp/asgi.py create mode 100644 oasupportapp/settings.py create mode 100644 oasupportapp/urls.py create mode 100644 oasupportapp/wsgi.py create mode 100644 readme.md create mode 100644 requirements.txt create mode 100644 static/css/main.css create mode 100644 static/img/logo.png create mode 100644 staticfiles/admin/css/autocomplete.css create mode 100644 staticfiles/admin/css/base.css create mode 100644 staticfiles/admin/css/changelists.css create mode 100644 staticfiles/admin/css/dashboard.css create mode 100644 staticfiles/admin/css/fonts.css create mode 100644 staticfiles/admin/css/forms.css create mode 100644 staticfiles/admin/css/login.css create mode 100644 staticfiles/admin/css/nav_sidebar.css create mode 100644 staticfiles/admin/css/responsive.css create mode 100644 staticfiles/admin/css/responsive_rtl.css create mode 100644 staticfiles/admin/css/rtl.css create mode 100644 staticfiles/admin/css/vendor/select2/LICENSE-SELECT2.md create mode 100644 staticfiles/admin/css/vendor/select2/select2.css create mode 100644 staticfiles/admin/css/vendor/select2/select2.min.css create mode 100644 staticfiles/admin/css/widgets.css create mode 100644 staticfiles/admin/fonts/LICENSE.txt create mode 100644 staticfiles/admin/fonts/README.txt create mode 100644 staticfiles/admin/fonts/Roboto-Bold-webfont.woff create mode 100644 staticfiles/admin/fonts/Roboto-Light-webfont.woff create mode 100644 staticfiles/admin/fonts/Roboto-Regular-webfont.woff create mode 100644 staticfiles/admin/img/LICENSE create mode 100644 staticfiles/admin/img/README.txt create mode 100644 staticfiles/admin/img/calendar-icons.svg create mode 100644 staticfiles/admin/img/gis/move_vertex_off.svg create mode 100644 staticfiles/admin/img/gis/move_vertex_on.svg create mode 100644 staticfiles/admin/img/icon-addlink.svg create mode 100644 staticfiles/admin/img/icon-alert.svg create mode 100644 staticfiles/admin/img/icon-calendar.svg create mode 100644 staticfiles/admin/img/icon-changelink.svg create mode 100644 staticfiles/admin/img/icon-clock.svg create mode 100644 staticfiles/admin/img/icon-deletelink.svg create mode 100644 staticfiles/admin/img/icon-no.svg create mode 100644 staticfiles/admin/img/icon-unknown-alt.svg create mode 100644 staticfiles/admin/img/icon-unknown.svg create mode 100644 staticfiles/admin/img/icon-viewlink.svg create mode 100644 staticfiles/admin/img/icon-yes.svg create mode 100644 staticfiles/admin/img/inline-delete.svg create mode 100644 staticfiles/admin/img/search.svg create mode 100644 staticfiles/admin/img/selector-icons.svg create mode 100644 staticfiles/admin/img/sorting-icons.svg create mode 100644 staticfiles/admin/img/tooltag-add.svg create mode 100644 staticfiles/admin/img/tooltag-arrowright.svg create mode 100644 staticfiles/admin/js/SelectBox.js create mode 100644 staticfiles/admin/js/SelectFilter2.js create mode 100644 staticfiles/admin/js/actions.js create mode 100644 staticfiles/admin/js/actions.min.js create mode 100644 staticfiles/admin/js/admin/DateTimeShortcuts.js create mode 100644 staticfiles/admin/js/admin/RelatedObjectLookups.js create mode 100644 staticfiles/admin/js/autocomplete.js create mode 100644 staticfiles/admin/js/calendar.js create mode 100644 staticfiles/admin/js/cancel.js create mode 100644 staticfiles/admin/js/change_form.js create mode 100644 staticfiles/admin/js/collapse.js create mode 100644 staticfiles/admin/js/collapse.min.js create mode 100644 staticfiles/admin/js/core.js create mode 100644 staticfiles/admin/js/inlines.js create mode 100644 staticfiles/admin/js/inlines.min.js create mode 100644 staticfiles/admin/js/jquery.init.js create mode 100644 staticfiles/admin/js/nav_sidebar.js create mode 100644 staticfiles/admin/js/popup_response.js create mode 100644 staticfiles/admin/js/prepopulate.js create mode 100644 staticfiles/admin/js/prepopulate.min.js create mode 100644 staticfiles/admin/js/prepopulate_init.js create mode 100644 staticfiles/admin/js/urlify.js create mode 100644 staticfiles/admin/js/vendor/jquery/LICENSE.txt create mode 100644 staticfiles/admin/js/vendor/jquery/jquery.js create mode 100644 staticfiles/admin/js/vendor/jquery/jquery.min.js create mode 100644 staticfiles/admin/js/vendor/select2/LICENSE.md create mode 100644 staticfiles/admin/js/vendor/select2/i18n/af.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ar.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/az.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/bg.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/bn.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/bs.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ca.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/cs.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/da.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/de.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/dsb.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/el.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/en.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/es.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/et.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/eu.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/fa.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/fi.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/fr.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/gl.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/he.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/hi.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/hr.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/hsb.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/hu.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/hy.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/id.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/is.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/it.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ja.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ka.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/km.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ko.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/lt.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/lv.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/mk.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ms.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/nb.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ne.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/nl.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/pl.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ps.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/pt-BR.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/pt.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ro.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/ru.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/sk.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/sl.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/sq.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/sr-Cyrl.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/sr.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/sv.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/th.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/tk.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/tr.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/uk.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/vi.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/zh-CN.js create mode 100644 staticfiles/admin/js/vendor/select2/i18n/zh-TW.js create mode 100644 staticfiles/admin/js/vendor/select2/select2.full.js create mode 100644 staticfiles/admin/js/vendor/select2/select2.full.min.js create mode 100644 staticfiles/admin/js/vendor/xregexp/LICENSE.txt create mode 100644 staticfiles/admin/js/vendor/xregexp/xregexp.js create mode 100644 staticfiles/admin/js/vendor/xregexp/xregexp.min.js create mode 100644 staticfiles/css/main.css create mode 100644 staticfiles/img/logo.png diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..38192b1659aaf9fe95a8c34c8c35aa86b7ed0e52 GIT binary patch literal 8196 zcmeHMJ&zMH5FIBuln{_kG#tf=P=Z9bQ~to-DM(P?42HtTHX+m+CA)S6KxPt5tZ$F z8BIoEKi7qlvpv^f72+xGZSS>{!EgZ?I)Va0fuKN8ASe(N_*WFbna!o>Iroh>v_XNO zz<;R#zaJ{7Y$Iz^WA&>8jlKfF7SOE=ey{Tn*ow80wW+c2pePdxYeJR1Vki@i{))v# z)~3dqa8ma2p=@SlZzxJ<$M_WuClwhR+MqyCU{L|SyBDZRJ?higxxbf>@O@zB8zl95 zD^6PIE7rdJcy{^G+a1^6S?V9&7T*TWZXuM`khf1A>Qd9mOr;O5SLRN?eV^nO@q=WR zJsaWVrv~RQQJZ4Spi2idrX~$(cr#AgmLJp_J!Rf(&@0;JLE6RkR)V z>FQnmRP5?gkdXKP7%QPYhvn_y#ZKhnw9X)|L|fHRBdd7>mi55%E*{?i5j6eQ`|$LR^;8CTL@jdq0Ce9c0HvPyxx0c`O7 z|GNMC|EghvKPV6sIKc|2LVd5k3j%!XXBEC{S5O literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f2c2717 --- /dev/null +++ b/.gitignore @@ -0,0 +1,129 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +# db.sqlite3 +# db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +# .env +# .venv +# env/ +# venv/ +# ENV/ +# env.bak/ +# venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..bde08ef --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:$PROJECT_DIR$/db.sqlite3 + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..036b26e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e78b641 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/oasupportapp.iml b/.idea/oasupportapp.iml new file mode 100644 index 0000000..5f0441d --- /dev/null +++ b/.idea/oasupportapp.iml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/clientapp/.DS_Store b/clientapp/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..df37fdf29e1194a17157ec8470d0982650e3ca28 GIT binary patch literal 6148 zcmeHKIc~#13?v;DHr%*$xnIZ+7J~8ue;|qFPJseA=~ek%ep-eHf(UY&0B(XIK+Z13 z(PF0%MG?{VvwsxXiO3pmC>IM$v*+duTV+OpaJ*xX7x|Erocr^l`gX#&8|S>q`%nIH zcpb;#Hi=m(Kn17(6`%rC;Li$J?}e?mfs9mu3Q&P>1?>A!;D$AE3iMA0f{y^e25C2} zeU<nqNaSC)g@=gcxXTWr!QGt6a@C6Jc6{r9J literal 0 HcmV?d00001 diff --git a/clientapp/__init__.py b/clientapp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/clientapp/admin.py b/clientapp/admin.py new file mode 100644 index 0000000..22fce4f --- /dev/null +++ b/clientapp/admin.py @@ -0,0 +1,50 @@ +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from .models import * + + +def make_archived(modeladmin, request, queryset): + queryset.update(is_archived=True) +make_archived.short_description = "Отправить в архив" + + +def make_not_archived(modeladmin, request, queryset): + queryset.update(is_archived=False) +make_not_archived.short_description = "Убрать из архива" + + +class AddMessageInline(admin.TabularInline): + model = AddMessage + extra = 0 + + +class Calladmin(admin.ModelAdmin): + list_display = ('title', 'category', 'status', 'created', 'author') + list_editable = ('status',) + list_filter = ('created','status', 'is_archived', 'category') + search_fields = ['title', 'message'] + autocomplete_fields = ('author',) + inlines = [AddMessageInline] + actions = [make_archived, make_not_archived] + + +class CustomUserAdmin(UserAdmin): + model = CustomUser + fieldsets = list(UserAdmin.fieldsets) + [('Дополнительные поля', {'fields': ('company',)})] + list_filter = ('company', 'is_staff', 'is_active') + +class AddMessageAdmin(admin.ModelAdmin): + list_display = ('created', 'id', 'author', 'message', 'file') + list_display_links = ('created', 'id') + raw_id_fields = ('call', 'author') + autocomplete_fields = ('author',) + search_fields = ['message', 'author'] + list_filter = ('created', 'author') + + +admin.site.register(Call, Calladmin) +admin.site.register(Category) +admin.site.register(Status) +admin.site.register(Company) +admin.site.register(CustomUser, CustomUserAdmin) +admin.site.register(AddMessage, AddMessageAdmin) diff --git a/clientapp/apps.py b/clientapp/apps.py new file mode 100644 index 0000000..fda1a09 --- /dev/null +++ b/clientapp/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ClientappConfig(AppConfig): + name = 'clientapp' diff --git a/clientapp/forms.py b/clientapp/forms.py new file mode 100644 index 0000000..5542e2a --- /dev/null +++ b/clientapp/forms.py @@ -0,0 +1,42 @@ +from .models import Call, CustomUser, AddMessage +from django.forms import ModelForm, forms +from django import forms + + +class CallForm(ModelForm): + class Meta: + model = Call + fields = ['title', 'category', 'message', 'file'] + + +class AddMessageForm(ModelForm): + class Meta: + model = AddMessage + fields = ['message', 'file'] + + +class LoginForm(ModelForm): + username = forms.CharField(max_length=40) + password = forms.CharField(max_length=40, widget=forms.PasswordInput) + + def __init__(self, *args, **kwagrs): + super().__init__(*args, **kwagrs) + self.fields['username'].label = 'Логин' + self.fields['password'].label = 'Пароль' + + def clean(self, *args, **kwagrs): + username = self.cleaned_data['username'] + password = self.cleaned_data['password'] + if not CustomUser.objects.filter(username=username).exists(): + raise forms.ValidationError(f'Пользователь с логином {username} не найден в системе.') + user = CustomUser.objects.filter(username=username).first() + if user: + if not user.check_password(password): + raise forms.ValidationError('Неверный пароль') + + class Meta: + model = CustomUser + fields = ['username', 'password'] + widgets = { + 'password': forms.PasswordInput() + } diff --git a/clientapp/migrations/0001_initial.py b/clientapp/migrations/0001_initial.py new file mode 100644 index 0000000..2956c17 --- /dev/null +++ b/clientapp/migrations/0001_initial.py @@ -0,0 +1,101 @@ +# Generated by Django 3.1.7 on 2021-04-10 10:43 + +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=50, verbose_name='Название категории')), + ], + options={ + 'verbose_name': 'Категория обращения', + 'verbose_name_plural': 'Категории обращений', + }, + ), + migrations.CreateModel( + name='Company', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=40, verbose_name='Название компании')), + ('inn', models.CharField(blank=True, max_length=12, null=True, verbose_name='ИНН')), + ('ogrn', models.CharField(blank=True, max_length=13, null=True, verbose_name='ОГРН')), + ], + options={ + 'verbose_name': 'Компания', + 'verbose_name_plural': 'Компании', + }, + ), + migrations.CreateModel( + name='Status', + fields=[ + ('title', models.CharField(max_length=32, verbose_name='Название')), + ('id', models.IntegerField(primary_key=True, serialize=False, verbose_name='Id')), + ], + options={ + 'verbose_name': 'Статус обращения', + 'verbose_name_plural': 'Статусы обращений', + }, + ), + migrations.CreateModel( + name='Call', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('author', models.CharField(default='', max_length=120, verbose_name='Тема')), + ('title', models.CharField(max_length=50, verbose_name='Тема')), + ('message', models.TextField(verbose_name='Описание проблемы')), + ('file', models.FileField(blank=True, null=True, upload_to='media', verbose_name='Файл')), + ('created', models.DateField(auto_now_add=True, verbose_name='Дата создания')), + ('deadline', models.DateField(blank=True, null=True, verbose_name='Дата предполагаемого решения')), + ('verdict', models.TextField(blank=True, default='', null=True, verbose_name='Вердикт')), + ('is_archived', models.BooleanField(default=False, verbose_name='Отправлен в архив')), + ('category', models.ForeignKey(blank=True, default='', null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='clientapp.category', verbose_name='Категория')), + ('status', models.ForeignKey(blank=True, default='', null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='clientapp.status', verbose_name='Статус')), + ], + options={ + 'verbose_name': 'Обращение', + 'verbose_name_plural': 'Обращения', + }, + ), + migrations.CreateModel( + name='CustomUser', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('company', models.ForeignKey(blank=True, default='', null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='clientapp.company')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + ] diff --git a/clientapp/migrations/0002_auto_20210411_1042.py b/clientapp/migrations/0002_auto_20210411_1042.py new file mode 100644 index 0000000..42bb14c --- /dev/null +++ b/clientapp/migrations/0002_auto_20210411_1042.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.7 on 2021-04-11 07:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='call', + name='author', + field=models.CharField(blank=True, default='', max_length=120, verbose_name='Автор'), + ), + migrations.AlterField( + model_name='call', + name='verdict', + field=models.TextField(blank=True, default='', verbose_name='Вердикт'), + ), + ] diff --git a/clientapp/migrations/0003_remove_customuser_company.py b/clientapp/migrations/0003_remove_customuser_company.py new file mode 100644 index 0000000..71d135b --- /dev/null +++ b/clientapp/migrations/0003_remove_customuser_company.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-04-11 08:23 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0002_auto_20210411_1042'), + ] + + operations = [ + migrations.RemoveField( + model_name='customuser', + name='company', + ), + ] diff --git a/clientapp/migrations/0004_customuser_company.py b/clientapp/migrations/0004_customuser_company.py new file mode 100644 index 0000000..e9df533 --- /dev/null +++ b/clientapp/migrations/0004_customuser_company.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.7 on 2021-04-11 08:24 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0003_remove_customuser_company'), + ] + + operations = [ + migrations.AddField( + model_name='customuser', + name='company', + field=models.ForeignKey(blank=True, default='', null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='clientapp.company'), + ), + ] diff --git a/clientapp/migrations/0005_customuser_something.py b/clientapp/migrations/0005_customuser_something.py new file mode 100644 index 0000000..66dfea6 --- /dev/null +++ b/clientapp/migrations/0005_customuser_something.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.7 on 2021-04-11 08:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0004_customuser_company'), + ] + + operations = [ + migrations.AddField( + model_name='customuser', + name='something', + field=models.CharField(default='', max_length=16, verbose_name='Something'), + ), + ] diff --git a/clientapp/migrations/0006_remove_customuser_something.py b/clientapp/migrations/0006_remove_customuser_something.py new file mode 100644 index 0000000..dfa765a --- /dev/null +++ b/clientapp/migrations/0006_remove_customuser_something.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-04-11 09:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0005_customuser_something'), + ] + + operations = [ + migrations.RemoveField( + model_name='customuser', + name='something', + ), + ] diff --git a/clientapp/migrations/0007_auto_20210411_1428.py b/clientapp/migrations/0007_auto_20210411_1428.py new file mode 100644 index 0000000..7d12645 --- /dev/null +++ b/clientapp/migrations/0007_auto_20210411_1428.py @@ -0,0 +1,20 @@ +# Generated by Django 3.1.7 on 2021-04-11 11:28 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0006_remove_customuser_something'), + ] + + operations = [ + migrations.AlterField( + model_name='call', + name='author', + field=models.ForeignKey(blank=True, default='', max_length=120, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/clientapp/migrations/0008_status_css_styles.py b/clientapp/migrations/0008_status_css_styles.py new file mode 100644 index 0000000..aeec6e2 --- /dev/null +++ b/clientapp/migrations/0008_status_css_styles.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.5 on 2021-07-03 11:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0007_auto_20210411_1428'), + ] + + operations = [ + migrations.AddField( + model_name='status', + name='css_styles', + field=models.CharField(blank=True, default='', max_length=512, null=True, verbose_name='Стили CSS'), + ), + ] diff --git a/clientapp/migrations/0009_alter_call_author.py b/clientapp/migrations/0009_alter_call_author.py new file mode 100644 index 0000000..4b7df16 --- /dev/null +++ b/clientapp/migrations/0009_alter_call_author.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.5 on 2021-07-03 14:09 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0008_status_css_styles'), + ] + + operations = [ + migrations.AlterField( + model_name='call', + name='author', + field=models.ForeignKey(blank=True, default='', max_length=120, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Автор обращения'), + ), + ] diff --git a/clientapp/migrations/0010_alter_status_css_styles.py b/clientapp/migrations/0010_alter_status_css_styles.py new file mode 100644 index 0000000..dd1b26b --- /dev/null +++ b/clientapp/migrations/0010_alter_status_css_styles.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.7 on 2024-07-17 13:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0009_alter_call_author'), + ] + + operations = [ + migrations.AlterField( + model_name='status', + name='css_styles', + field=models.CharField(blank=True, default='', max_length=512, null=True, verbose_name='Цвет и CSS'), + ), + ] diff --git a/clientapp/migrations/0011_alter_status_css_styles_addmessage.py b/clientapp/migrations/0011_alter_status_css_styles_addmessage.py new file mode 100644 index 0000000..683bece --- /dev/null +++ b/clientapp/migrations/0011_alter_status_css_styles_addmessage.py @@ -0,0 +1,35 @@ +# Generated by Django 5.0.7 on 2024-07-17 14:50 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0010_alter_status_css_styles'), + ] + + operations = [ + migrations.AlterField( + model_name='status', + name='css_styles', + field=models.CharField(blank=True, default='', max_length=512, null=True, verbose_name='CSS'), + ), + migrations.CreateModel( + name='AddMessage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('message', models.TextField(verbose_name='Текст сообщения')), + ('file', models.FileField(blank=True, null=True, upload_to='media', verbose_name='Файл')), + ('created', models.DateField(auto_now_add=True, verbose_name='Дата создания')), + ('author', models.ForeignKey(blank=True, default='', max_length=120, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Автор сообщения')), + ('call', models.ForeignKey(blank=True, default='', max_length=120, null=True, on_delete=django.db.models.deletion.SET_NULL, to='clientapp.call', verbose_name='Обращение (тикет)')), + ], + options={ + 'verbose_name': 'Доп. сообщение', + 'verbose_name_plural': 'Доп. сообщения', + }, + ), + ] diff --git a/clientapp/migrations/0012_alter_addmessage_created.py b/clientapp/migrations/0012_alter_addmessage_created.py new file mode 100644 index 0000000..0630612 --- /dev/null +++ b/clientapp/migrations/0012_alter_addmessage_created.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.7 on 2024-07-17 15:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('clientapp', '0011_alter_status_css_styles_addmessage'), + ] + + operations = [ + migrations.AlterField( + model_name='addmessage', + name='created', + field=models.DateTimeField(auto_now_add=True, verbose_name='Дата создания'), + ), + ] diff --git a/clientapp/migrations/__init__.py b/clientapp/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/clientapp/models.py b/clientapp/models.py new file mode 100644 index 0000000..2410244 --- /dev/null +++ b/clientapp/models.py @@ -0,0 +1,79 @@ +from django.db import models +from django.contrib.auth.models import AbstractUser + + +class Company(models.Model): + title = models.CharField('Название компании', max_length=40) + inn = models.CharField('ИНН', max_length=12, blank=True, null=True) + ogrn = models.CharField('ОГРН', max_length=13, blank=True, null=True) + + def __str__(self): + return self.title + + class Meta: + verbose_name = 'Компания' + verbose_name_plural = 'Компании' + + +class CustomUser(AbstractUser): + pass + company = models.ForeignKey('Company', default='', on_delete=models.SET_DEFAULT, blank=True, null=True) + + +class Call(models.Model): + author = models.ForeignKey('CustomUser', on_delete=models.SET_NULL, verbose_name='Автор обращения', max_length=120, default='', blank=True, null=True) + category = models.ForeignKey('Category', on_delete=models.SET_DEFAULT, verbose_name='Категория', blank=True, null=True, default='') + title = models.CharField('Тема', max_length=50) + message = models.TextField('Описание проблемы') + file = models.FileField(upload_to='media', verbose_name='Файл', blank=True, null=True) + created = models.DateField('Дата создания', auto_now_add=True) + status = models.ForeignKey('Status', on_delete=models.SET_DEFAULT, verbose_name='Статус', blank=True, null=True, default='') + deadline = models.DateField('Дата предполагаемого решения', blank=True, null=True) + verdict = models.TextField('Вердикт', default='', blank=True) + is_archived = models.BooleanField('Отправлен в архив', default=False) + + def __str__(self): + return self.title + + class Meta: + verbose_name = 'Обращение' + verbose_name_plural = 'Обращения' + + +class Category(models.Model): + title = models.CharField('Название категории', max_length=50) + + def __str__(self): + return self.title + + class Meta: + verbose_name = 'Категория обращения' + verbose_name_plural = 'Категории обращений' + + +class Status(models.Model): + title = models.CharField('Название', max_length=32) + id = models.IntegerField('Id', primary_key=True) + css_styles = models.CharField('CSS', max_length=512, blank=True, null=True, default='') + + def __str__(self): + return self.title + + class Meta: + verbose_name = 'Статус обращения' + verbose_name_plural = 'Статусы обращений' + + +class AddMessage(models.Model): + call = models.ForeignKey('Call', on_delete=models.SET_NULL, verbose_name='Обращение (тикет)', max_length=120, default='', blank=True, null=True) + author = models.ForeignKey('CustomUser', on_delete=models.SET_NULL, verbose_name='Автор сообщения', max_length=120, default='', blank=True, null=True) + message = models.TextField('Текст сообщения') + file = models.FileField(upload_to='media', verbose_name='Файл', blank=True, null=True) + created = models.DateTimeField('Дата создания', auto_now_add=True) + + def __str__(self): + return f'#{self.id} {self.author.username} {self.created}' + + class Meta: + verbose_name = 'Доп. сообщение' + verbose_name_plural = 'Доп. сообщения' \ No newline at end of file diff --git a/clientapp/templates/.DS_Store b/clientapp/templates/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8416e5d0fabf52c26a1179df55d51dc8eda97cee GIT binary patch literal 6148 zcmeHKyG{c^3>-s>Aexkv`wRTRDhgk~4**FDq!Wn*^jGm+`Lv85LPQsuNHl0H*|Y2O z+-j#dp8?qNb8`cjpHDdV25Ss>#r7wE zJ-qC8!+DajQa}nw0VyB_q`<`rc<-gnZxa=zfE17d-wOEmq0t?C;g}eo4u%*3h%=_c zxQjN(|1$rdlC+ZoQs7@HV6)ZZYRM~AZ=GDudu^jX(Y@wCcjG!J4AG8>(T=(C fc6=8_S=W5c=e=-D3_9~cC+cUwb&*MdzgFM~nDP~) literal 0 HcmV?d00001 diff --git a/clientapp/templates/clientapp/.DS_Store b/clientapp/templates/clientapp/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..421ea0401ee7cf6e72112137f49f8134cb63c53a GIT binary patch literal 6148 zcmeHKJ5Iwu5S<|@BBhC_C@A&{xq*qy3334xB85n?oF@HtIS@yn;aI%+0FEqDQotK& z=6UC{YrkU0BObo5t%^^+fH`BVFINn?t{W2QO0JZ|83h!|3)(^!PH|wV;eb2FL&zAOmFJUo(K7Z8Dn&(vkr( zKnA`Tu=}Av4V%Oo=vN1fj{rdXjd#Jb&l1354q%g51L1*almeqvbHvanhreWAlUM_z zT+~m-K6$d{gra^r{KeBnn?PDJKn5-un8b2n{r?gA!~B0)#1$DJ1AmGEown +

Создание обращения

+
+ {% csrf_token %} +

+ + {{ form.title }} +

+

+ + {{ form.category }} +

+

+ + {{ form.message }} +

+

+ + {{ form.file }} +

+
+

{{ error }}

+
+ +{% endblock %} \ No newline at end of file diff --git a/clientapp/templates/clientapp/archive.html b/clientapp/templates/clientapp/archive.html new file mode 100644 index 0000000..8fd0b15 --- /dev/null +++ b/clientapp/templates/clientapp/archive.html @@ -0,0 +1,35 @@ +{% extends 'clientapp/base.html' %} + + +{% block title%} {{ title }} {% endblock %} + +{% block content %} +

Здесь собраны все ваши прошлые обращения, помеченные, как "архивные".

+ +
+

Архивные обращения

+
    + {% if calls %} + {% for el in calls %} +
  • +

    {{ el.title }}

    +
    + {{ el.created }} + {% if el.status %} + {{ el.status }} + {% else %} + Обращение принято, статус пока не установлен. + {% endif %} +
    +
  • + {% endfor %} + {% else %} +

    У вас нет архивных обращений

    + {% endif %} +
+
+{% endblock %} + + diff --git a/clientapp/templates/clientapp/base.html b/clientapp/templates/clientapp/base.html new file mode 100644 index 0000000..b59f25c --- /dev/null +++ b/clientapp/templates/clientapp/base.html @@ -0,0 +1,30 @@ +{% load static %} + + + + + + {% block title %}{% endblock %} + + + + + + +
+ {% block content %}{% endblock %} +
+ + + \ No newline at end of file diff --git a/clientapp/templates/clientapp/call.html b/clientapp/templates/clientapp/call.html new file mode 100644 index 0000000..6207c1c --- /dev/null +++ b/clientapp/templates/clientapp/call.html @@ -0,0 +1,101 @@ +{% extends 'clientapp/base.html' %} + + +{% block title %} Обращение {{ call.id }}: {{ call.title }} {% endblock %} + +{% block content %} + +
+ Вернуться на главную + {% if user.is_staff %} + Открыть в админке + {% endif %} +
+ + + +
+ +
+ {% if call.status %} +

{{ call.status }}

+ {% else %} +

Обращение принято. Статус пока не установлен.

+ {% endif %} + +

{{ call.created }}

+
+ +

Обращение #{{ call.id }}: {{ call.title }}

+ +

{{ call.message }}

+ + {% if call.file %} + + Прикрепленный файл + + {% endif %} + + {% if call.deadline %} +

Дата решения: {{ call.deadline }}

+ {% else %} +

Дата решения: не установлена

+ {% endif %} + + {% if add_messages %} +

Чат по обращению

+ + {% for m in add_messages %} +
+ +

+ {% if not m.author.is_staff %} + {{ m.author.username }} + {% else %} + staff + {% endif %} + {{ m.created|date:'d.m.Y' }} в {{ m.created|date:'H:i' }} + {{ m.message }} +

+ + {% if m.file %} + + Файл + + {% endif %} + +
+ {% endfor %} + + {% endif %} + +

Вердикт по обращению

+ + {% if call.verdict %} +

{{ call.verdict }}

+ {% else %} +

Вердикт пока не установлен.

+ {% endif %} + +
+ + + +
+

Дополнить обращение

+
+ {% csrf_token %} +

+ + {{ form.message }} +

+

+ + {{ form.file }} +

+
+

{{ error }}

+
+
+ +{% endblock %} diff --git a/clientapp/templates/clientapp/index.html b/clientapp/templates/clientapp/index.html new file mode 100644 index 0000000..c57accf --- /dev/null +++ b/clientapp/templates/clientapp/index.html @@ -0,0 +1,47 @@ +{% extends 'clientapp/base.html' %} +{% load static %} + + +{% block title %} {{ title }} {% endblock %} + + +{% block content %} + +

+ Рады вас видеть в службе технической поддержки, + {% if user.first_name %}{{ user.first_name }}{% else %}пользователь {{ user.username }} без имени{% endif %}. + Чем можем помочь? +

+ + + +
+

Открытые обращения

+
    + {% if calls %} + {% for call in calls %} +
  • +

    #{{ call.id }}: {{ call.title }}

    +
    + + {% if call.status %} + {{ call.status }} + {% else %} + Обращение принято, статус пока не установлен. + {% endif %} + {{ call.created }} +
    +
  • + {% endfor %} + {% else %} +

    У вас нет открытых обращений

    + {% endif %} +
+
+ +{% endblock %} + + diff --git a/clientapp/templates/clientapp/login.html b/clientapp/templates/clientapp/login.html new file mode 100644 index 0000000..69338c3 --- /dev/null +++ b/clientapp/templates/clientapp/login.html @@ -0,0 +1,36 @@ + + + + + Логин + + + + + + +
+

Здравствуйте!

+

Это техподдержка ООО "ИЗИ ВЕЙ". Войдите + в систему, чтобы получить помощь.

+
+
+ {% csrf_token %} +

+ + {{ form.username }} +

+

+ + {{ form.password }} +

+ + {{ error }} +
+
+
+ + + \ No newline at end of file diff --git a/clientapp/templates/clientapp/staffhome.html b/clientapp/templates/clientapp/staffhome.html new file mode 100644 index 0000000..c9110db --- /dev/null +++ b/clientapp/templates/clientapp/staffhome.html @@ -0,0 +1,45 @@ +{% extends 'clientapp/base.html' %} +{} + + +{% block title %} {{ title }} {% endblock %} + + +{% block content %} + + +
+

Открытые обращения

+
    + {% if calls %} +
    +
    ID
    +
    Компания
    +
    Автор
    +
    Заголовок
    +
    Статус
    +
    Дата создания
    + {% for call in calls %} +
    #{{ call.id }}
    +
    {{ call.author.company.title }}
    + + +
    + {% if call.status %} + {{ call.status }} + {% else %} + без статуса + {% endif %} +
    +
    {{ call.created|date:'d.m.Y' }}
    + {% endfor %} +
    + {% else %} +

    Обращений пока нет.

    + {% endif %} +
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/clientapp/tests.py b/clientapp/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/clientapp/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/clientapp/urls.py b/clientapp/urls.py new file mode 100644 index 0000000..ff8107d --- /dev/null +++ b/clientapp/urls.py @@ -0,0 +1,13 @@ +from django.urls import path +from . import views + + +urlpatterns = [ + path('', views.homeView, name='home'), + path('calls/create', views.callCreateView, name='new-call'), + path('calls/', views.callDetailView, name='call-detail'), + path('calls/archive', views.callsArchiveView, name='calls-archive'), + path('login', views.loginView, name='login'), + path('logout', views.logoutView, name='logout'), + path('staff', views.staffHomeView, name='staffhome'), +] diff --git a/clientapp/views.py b/clientapp/views.py new file mode 100644 index 0000000..47aa85c --- /dev/null +++ b/clientapp/views.py @@ -0,0 +1,120 @@ +from django.shortcuts import render, redirect +from .models import Call, AddMessage +from .forms import CallForm, LoginForm, AddMessageForm +from django.views.generic import DetailView +from django.contrib.auth import authenticate, login, logout +from django.contrib.auth.decorators import login_required +from django.contrib.auth.mixins import LoginRequiredMixin + + +# LOGIN / LOGOUT + +def loginView(request): + form = LoginForm(request.POST or None) + context = { + 'form': form, + } + + if form.is_valid(): + username = request.POST['username'] + password = request.POST['password'] + user = authenticate(request, username=username, password=password) + if user: + login(request, user) + if user.is_staff == False: + return redirect('home') + else: + return redirect('staffhome') + else: + return render(request, 'clientapp/login.html', context) + + +def logoutView(request): + logout(request) + return redirect('login') + + +# CALLS / ARCHIVE + +@login_required(login_url='login') +def homeView(request): + calls = Call.objects.filter(author__company=request.user.company).filter(is_archived=False) + context = { + 'title': 'Главная страница', + 'calls': calls + } + if request.user.is_staff == False: + return render(request, 'clientapp/index.html', context) + else: + return redirect('staffhome') + + +@login_required(login_url='login') +def callsArchiveView(request): + calls = Call.objects.order_by('-id').filter(author__company=request.user.company).filter(is_archived=True) + context = { + 'title': 'Архив обращений', + 'calls': calls + } + + return render(request, 'clientapp/archive.html', context) + + +@login_required(login_url='login') +def callCreateView(request): + error = '' + if request.method == 'POST': + form = CallForm(request.POST) + if form.is_valid(): + form = form.save(commit=False) + form.author = request.user + form.save() + return redirect('home') + else: + error = 'Форма была неверной. Попробуйте еще раз.' + + form = CallForm() + context = { + 'form': form, + 'error': error, + 'title': 'Создание нового обращения' + } + + return render(request, 'clientapp/addnewcall.html', context) + + +@login_required(login_url='login') +def callDetailView(request, call_id): + call = Call.objects.get(id=call_id) + add_messages = AddMessage.objects.filter(call=call_id).order_by('created') + form = AddMessageForm(request.POST) + + if request.method == 'POST': + if form.is_valid(): + form = form.save(commit=False) + form.author = request.user + form.call = call + form.save() + return redirect('call-detail', call_id) + + context = { + 'call': call, + 'add_messages': add_messages, + 'form': form + } + + return render(request, 'clientapp/call.html', context) + + +@login_required(login_url='login') +def staffHomeView(request): + calls = Call.objects.filter(is_archived=False) + context = { + 'title': 'STAFF: Главная страница', + 'calls': calls + } + + if request.user.is_staff == True: + return render(request, 'clientapp/staffhome.html', context) + else: + return redirect('home') diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..7b13e4012977649bca9a79f7a5a95c432b69554b GIT binary patch literal 233472 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 literal 0 HcmV?d00001 diff --git a/env/bin/Activate.ps1 b/env/bin/Activate.ps1 new file mode 100644 index 0000000..b49d77b --- /dev/null +++ b/env/bin/Activate.ps1 @@ -0,0 +1,247 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/env/bin/activate b/env/bin/activate new file mode 100644 index 0000000..4ef7898 --- /dev/null +++ b/env/bin/activate @@ -0,0 +1,70 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then + # transform D:\path\to\venv to /d/path/to/venv on MSYS + # and to /cygdrive/d/path/to/venv on Cygwin + export VIRTUAL_ENV=$(cygpath "/Users/vlnko/dev/oasupport/env") +else + # use the path as-is + export VIRTUAL_ENV="/Users/vlnko/dev/oasupport/env" +fi + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(env) ${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT="(env) " + export VIRTUAL_ENV_PROMPT +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/env/bin/activate.csh b/env/bin/activate.csh new file mode 100644 index 0000000..61dfdfc --- /dev/null +++ b/env/bin/activate.csh @@ -0,0 +1,27 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. + +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/Users/vlnko/dev/oasupport/env" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = "(env) $prompt" + setenv VIRTUAL_ENV_PROMPT "(env) " +endif + +alias pydoc python -m pydoc + +rehash diff --git a/env/bin/activate.fish b/env/bin/activate.fish new file mode 100644 index 0000000..08bf3fc --- /dev/null +++ b/env/bin/activate.fish @@ -0,0 +1,69 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/). You cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + set -e _OLD_FISH_PROMPT_OVERRIDE + # prevents error when using nested fish instances (Issue #93858) + if functions -q _old_fish_prompt + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + end + + set -e VIRTUAL_ENV + set -e VIRTUAL_ENV_PROMPT + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/Users/vlnko/dev/oasupport/env" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "(env) " (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" + set -gx VIRTUAL_ENV_PROMPT "(env) " +end diff --git a/env/bin/django-admin b/env/bin/django-admin new file mode 100755 index 0000000..be5e697 --- /dev/null +++ b/env/bin/django-admin @@ -0,0 +1,8 @@ +#!/Users/vlnko/dev/oasupport/env/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from django.core.management import execute_from_command_line +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(execute_from_command_line()) diff --git a/env/bin/pip b/env/bin/pip new file mode 100755 index 0000000..b5a02e0 --- /dev/null +++ b/env/bin/pip @@ -0,0 +1,8 @@ +#!/Users/vlnko/dev/oasupport/env/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/pip3 b/env/bin/pip3 new file mode 100755 index 0000000..b5a02e0 --- /dev/null +++ b/env/bin/pip3 @@ -0,0 +1,8 @@ +#!/Users/vlnko/dev/oasupport/env/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/pip3.12 b/env/bin/pip3.12 new file mode 100755 index 0000000..b5a02e0 --- /dev/null +++ b/env/bin/pip3.12 @@ -0,0 +1,8 @@ +#!/Users/vlnko/dev/oasupport/env/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/python b/env/bin/python new file mode 120000 index 0000000..11b9d88 --- /dev/null +++ b/env/bin/python @@ -0,0 +1 @@ +python3.12 \ No newline at end of file diff --git a/env/bin/python3 b/env/bin/python3 new file mode 120000 index 0000000..11b9d88 --- /dev/null +++ b/env/bin/python3 @@ -0,0 +1 @@ +python3.12 \ No newline at end of file diff --git a/env/bin/python3.12 b/env/bin/python3.12 new file mode 120000 index 0000000..a3f0508 --- /dev/null +++ b/env/bin/python3.12 @@ -0,0 +1 @@ +/opt/homebrew/opt/python@3.12/bin/python3.12 \ No newline at end of file diff --git a/env/bin/sqlformat b/env/bin/sqlformat new file mode 100755 index 0000000..b704a96 --- /dev/null +++ b/env/bin/sqlformat @@ -0,0 +1,8 @@ +#!/Users/vlnko/dev/oasupport/env/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from sqlparse.__main__ import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/pyvenv.cfg b/env/pyvenv.cfg new file mode 100644 index 0000000..f62293c --- /dev/null +++ b/env/pyvenv.cfg @@ -0,0 +1,5 @@ +home = /opt/homebrew/opt/python@3.12/bin +include-system-site-packages = false +version = 3.12.4 +executable = /opt/homebrew/Cellar/python@3.12/3.12.4/Frameworks/Python.framework/Versions/3.12/bin/python3.12 +command = /opt/homebrew/opt/python@3.12/bin/python3.12 -m venv /Users/vlnko/dev/oasupport/env diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..7d1a605 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'oasupportapp.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/media/.DS_Store b/media/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6c203b944a5fd638cff3cee28506e97c3efefae2 GIT binary patch literal 6148 zcmeH~O=`nH427lCg+Ml5b~&3Ipf?yya)Ml-ZQMn{#fy^t96e7z1nhPlN_Yb4&1j?q ze+!Q#B05~gSCL*sws2F~TUeQ5|196~DWiPJ`}lL7KIVDys!i5f4IIC*JkMha36KB@ zkN^pgz&|2j_cm<13uPn$5+H#a0ee3bxM@voq5kSX@DTvoA?=2>&l1pL3204ip~%2A zTA|UZK89G{+o2`vYHACOcF`O@H2+y`ih*ggixzBPT3r}OfCN?qo?_qI{eOi2HUF<# zxFrD+crXIm9ZrV<50!W8ugA0eTV`$D;7~6|SbPLvV^{GD+zsc&7SNj7LXm;-L%=aG JkicCDTmg(c6J-DZ literal 0 HcmV?d00001 diff --git a/media/media/ee565277-6d18-466b-9cf7-61b6ea2523ee_Авибус_Мобильная_автостанция.pdf b/media/media/ee565277-6d18-466b-9cf7-61b6ea2523ee_Авибус_Мобильная_автостанция.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8590a03d1ffb564e7eab1ae34652e297f8eabed0 GIT binary patch literal 43961 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 literal 0 HcmV?d00001 diff --git a/media/media/wu-yi-lBeqbh6QTpI-unsplash.jpeg b/media/media/wu-yi-lBeqbh6QTpI-unsplash.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..47d1f541ae05e3522600ca0602fd27de17f3ddce GIT binary patch literal 77745 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