massive update

This commit is contained in:
2019-01-08 16:09:15 +05:00
parent ad71e72294
commit 39916fa5fb
22 changed files with 1260 additions and 70 deletions

View File

@ -21,8 +21,12 @@
5. Накатите миграции
```
В процессе
python3 dodo.py migrate
```
или
```
python3 dodo.py force_migrate
```
5. Запустите прожект

183
app.py
View File

@ -1,7 +1,10 @@
import datetime
from flask import Flask, render_template, request, redirect, url_for
from data.data_provider import DataProvider
from data.models import Activity
from data.models import Activity, Enterprise, ContactInfo, Division, Head, \
PhoneNumber, Location
app = Flask(__name__)
@ -9,6 +12,7 @@ data_provider = DataProvider(
"postgresql://yaric359:yaric359@localhost:5432/yaric359"
)
@app.route('/')
def hello_world():
return render_template('pages/index.html')
@ -33,5 +37,182 @@ def list_activities():
data=data_provider.get_activities())
@app.route('/enterprises/add/', methods=['GET'])
def add_enterprise():
return render_template('pages/enterprises/add_enterprise.html',
activities=data_provider.get_activities())
@app.route('/enterprises/add/', methods=['POST'])
def add_enterprise_post():
name = request.form['name']
short_name = request.form['short_name']
code = request.form['code']
email = request.form['email']
activities = request.form['activities']
cont_info = ContactInfo(None, email, [], [], [], name, short_name, code)
ent = Enterprise(None, [Activity(act, '') for act in activities], [],
cont_info)
data_provider.create_enterprise(ent)
return redirect(url_for('add_enterprise'))
@app.route('/enterprises/')
def enterprise_list():
return render_template('pages/enterprises/index.html',
data=data_provider.get_enterprises())
@app.route('/enterprises/<int:ent_id>/', methods=["GET"])
def enterprise_details(ent_id):
return render_template('pages/enterprises/details.html',
ent=data_provider.get_enterprise_by_id(ent_id))
@app.route('/divisions/add/', methods=['GET'])
def add_division():
return render_template('pages/division/add_division.html',
activities=data_provider.get_activities(),
enterpises=data_provider.get_enterprises())
@app.route('/divisions/add/', methods=['POST'])
def add_division_post():
name = request.form['name']
short_name = request.form['short_name']
code = request.form['code']
email = request.form['email']
activities = request.form['activities']
ent_id = request.form['ent_id']
cont_info = ContactInfo(None, email, [], [], [], name, short_name, code)
div = Division(None, cont_info, [Activity(act, '') for act in activities])
data_provider.create_division(div, ent_id)
return redirect(url_for('add_division'))
@app.route('/heads/add/', methods=['GET'])
def add_head():
enterprises = data_provider.get_enterprises()
divs = []
for ent in enterprises:
divs.extend(data_provider.get_divisions_by_enterprise(ent.id))
return render_template(
'pages/add_head.html',
enterprises=enterprises,
divisions=divs)
@app.route('/heads/add/', methods=['POST'])
def add_head_post():
first_name = request.form['first_name']
second_name = request.form['second_name']
last_name = request.form['last_name']
con_id = request.form['con_id']
date_start = datetime.datetime.strptime(request.form['date_start'], '%Y-%m-%d').date()
date_end = datetime.datetime.strptime(request.form['date_end'], '%Y-%m-%d').date() if request.form['date_end'] else None
data_provider.create_head(Head(None, date_start, date_end, first_name, second_name, last_name), con_id)
return redirect(url_for('add_head'))
@app.route('/queries/emails/')
def no_email_query():
return render_template(
'pages/queries/count_no_emails.html',
email_count=data_provider.division_count_with_no_email()
)
@app.route('/phones/add/', methods=['GET'])
def add_phone():
enterprises = data_provider.get_enterprises()
divs = []
for ent in enterprises:
divs.extend(data_provider.get_divisions_by_enterprise(ent.id))
return render_template(
'pages/add_phone.html',
enterprises=enterprises,
divisions=divs)
@app.route('/phones/add/', methods=['POST'])
def add_phone_post():
phone = request.form['phone']
con_id = request.form['con_id']
date_start = datetime.datetime.strptime(request.form['date_start'], '%Y-%m-%d').date()
date_end = datetime.datetime.strptime(request.form['date_end'], '%Y-%m-%d').date() if request.form['date_end'] else None
data_provider.create_phone_number(PhoneNumber(None, date_start, date_end, phone), con_id)
return redirect(url_for('add_phone'))
@app.route('/queries/phones/')
def phones_on_date_of_ent():
date = request.args.get('date')
ent_id = request.args.get('ent_id')
enterprises = data_provider.get_enterprises()
if date and ent_id:
res = data_provider.division_phones_of_enterprise(
ent_id,
datetime.datetime.strptime(date, '%Y-%m-%d').date()
)
return render_template(
'pages/queries/phones.html',
enterprises=enterprises,
res=res
)
return render_template(
'pages/queries/phones.html',
enterprises=enterprises
)
@app.route('/locations/add/', methods=['GET'])
def add_location():
enterprises = data_provider.get_enterprises()
divs = []
for ent in enterprises:
divs.extend(data_provider.get_divisions_by_enterprise(ent.id))
return render_template(
'pages/add_location.html',
enterprises=enterprises,
divisions=divs)
@app.route('/locations/add/', methods=['POST'])
def add_location_post():
city = request.form['city']
street = request.form['street']
house = request.form['house']
country = request.form['country']
room = request.form['room']
con_id = request.form['con_id']
date_start = datetime.datetime.strptime(request.form['date_start'], '%Y-%m-%d').date()
date_end = datetime.datetime.strptime(request.form['date_end'], '%Y-%m-%d').date() if request.form['date_end'] else None
data_provider.create_location(Location(None,country, city, street, house, room, date_start, date_end), con_id)
return redirect(url_for('add_location'))
@app.route('/divisions/<int:div_id>/')
def division_details(div_id):
return render_template(
'pages/division/details.html',
div=data_provider.get_division_by_id(div_id)
)
@app.route('/queries/heads/')
def max_heads_change():
date_start = request.args.get('date_start')
date_end = request.args.get('date_end')
if date_end and date_start:
res = data_provider.max_heads_change(datetime.datetime.strptime(date_start, '%Y-%m-%d').date(), datetime.datetime.strptime(date_end, '%Y-%m-%d').date())
return render_template(
'pages/queries/max_heads.html',
res=res
)
return render_template(
'pages/queries/max_heads.html'
)
if __name__ == '__main__':
app.run()

View File

@ -1,5 +1,6 @@
import os
from typing import List
from datetime import date
import psycopg2
@ -12,6 +13,17 @@ class DataProvider:
self._connection: psycopg2 = psycopg2.connect(params)
self.params = params
def delete_tables(self):
cur = self._connection.cursor()
cur.execute(
"SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_schema,table_name")
rows = cur.fetchall()
for row in rows:
print
"dropping table: ", row[1]
cur.execute("drop table " + row[1] + " cascade")
cur.close()
def migrate(self):
with self._connection.cursor() as cur:
f = open(os.path.join("migrations", "201831231.2049_initial.sql"),
@ -22,31 +34,27 @@ class DataProvider:
def get_enterprises(self) -> List[Enterprise]:
with self._connection.cursor() as cursor:
cursor.execute("SELECT id, name, short_name FROM enterprise;")
cursor.execute("SELECT id FROM enterprise;")
res = [Enterprise(
ent_id,
ent_id[0],
self.get_activities_by_enterprpise(ent_id),
self.get_divisions_by_enterprise(ent_id),
self.get_contact_info_by_enterprise(ent_id),
name,
short_name
) for ent_id, name, short_name in cursor.fetchall()]
self.get_contact_info_by_enterprise(ent_id)
) for ent_id in cursor.fetchall()]
self._connection.commit()
return res
def get_enterprise_by_id(self, ent_id: int):
with self._connection.cursor() as cursor:
cursor.execute("SELECT id, name, short_name "
cursor.execute("SELECT id "
"FROM enterprise where id=%s;", (ent_id,))
ent_id, name, short_name = cursor.fetchone()
ent_id = cursor.fetchone()[0]
self._connection.commit()
return Enterprise(
ent_id,
self.get_activities_by_enterprpise(ent_id),
self.get_divisions_by_enterprise(ent_id),
self.get_contact_info_by_enterprise(ent_id),
name,
short_name
self.get_contact_info_by_enterprise(ent_id)
)
def get_activities_by_enterprpise(self, ent_id: int) -> List[Activity]:
@ -66,7 +74,7 @@ class DataProvider:
"SELECT id from division where enterprise = %s", (ent_id,)
)
self._connection.commit()
return [Division(div_id,
return [Division(div_id[0],
self.get_contact_info_by_division(div_id),
self.get_activities_by_division(div_id)
) for div_id in cur.fetchall()]
@ -74,58 +82,68 @@ class DataProvider:
def get_contact_info_by_enterprise(self,
ent_id: int) -> ContactInfo:
with self._connection.cursor() as cur:
cur.execute("SELECT id, email from contact_info "
"where id = (SELECT contact_info "
"FROM enterprise WHERE enterprise.id = %s)",
(ent_id,))
con_id, email = cur.fetchone()
cur.execute(
"SELECT id, email, name, short_name, code from contact_info "
"where id = (SELECT contact_info "
"FROM enterprise WHERE enterprise.id = %s)",
(ent_id,))
con_id, email, name, short_name, code = cur.fetchone()
self._connection.commit()
return ContactInfo(
con_id,
email,
self.get_phone_numbers_by_contact(con_id),
self.get_head_by_contact(con_id),
self.get_locations_by_contact(con_id)
self.get_locations_by_contact(con_id),
name,
short_name,
code
)
def get_contact_info_by_division(self,
div_id: int) -> ContactInfo:
with self._connection.cursor() as cur:
cur.execute("SELECT id, email "
cur.execute("SELECT id, email, name, short_name, code "
"from contact_info where id = (SELECT contact_info "
"FROM division WHERE division.id = %s)",
(div_id,))
con_id, email = cur.fetchone()
con_id, email, name, short_name, code = cur.fetchone()
self._connection.commit()
return ContactInfo(
con_id,
email,
self.get_phone_numbers_by_contact(con_id),
self.get_head_by_contact(con_id),
self.get_locations_by_contact(con_id)
self.get_locations_by_contact(con_id),
name,
short_name,
code
)
def get_phone_numbers_by_contact(self, con_id: int) -> List[PhoneNumber]:
with self._connection.cursor() as cur:
cur.execute("SELECT id, date_of_start, date_of_end "
cur.execute("SELECT id, date_of_start, date_of_end, number "
"FROM phone_number where contact_info = %s",
(con_id,))
self._connection.commit()
return [PhoneNumber(
ph_id,
date_start,
date_end
) for ph_id, date_start, date_end in cur.fetchall()]
date_end,
number
) for ph_id, date_start, date_end, number in cur.fetchall()]
def get_head_by_contact(self, con_id: int) -> List[Head]:
with self._connection.cursor() as cur:
cur.execute("SELECT id, date_of_start, date_of_end "
"FROM head WHERE contact_info = %s",
(con_id,))
cur.fetchall()
cur.execute(
"SELECT id, date_of_start, date_of_end, first_name, second_name, lst_name "
"FROM head WHERE contact_info = %s",
(con_id,))
self._connection.commit()
return [Head(id, date_start, date_end) for id, date_start, date_end
in cur]
return [Head(id, date_start, date_end, first_name, second_name,
last_name) for
id, date_start, date_end, first_name, second_name, last_name
in cur.fetchall()]
def get_locations_by_contact(self, con_id: int) -> List[Location]:
with self._connection.cursor() as cur:
@ -155,8 +173,10 @@ class DataProvider:
def create_contact_info(self, info: ContactInfo):
with self._connection.cursor() as cur:
cur.execute("INSERT INTO contact_info (email) VALUES (%s) "
"RETURNING id", (info.email, ))
cur.execute(
"INSERT INTO contact_info (email, name, short_name, code) VALUES (%s, %s, %s, %s) "
"RETURNING id",
(info.email, info.name, info.short_name, info.code))
info.id = cur.fetchone()[0]
self._connection.commit()
for head in info.head:
@ -169,9 +189,10 @@ class DataProvider:
def create_head(self, head: Head, con_id: int):
with self._connection.cursor() as cur:
cur.execute("INSERT INTO head "
"(date_of_start, date_of_end, contact_info) "
"VALUES (%s, %s, %s) RETURNING id",
(head.date_of_start, head.date_of_end, con_id))
"(date_of_start, date_of_end, contact_info, first_name, second_name, lst_name) "
"VALUES (%s, %s, %s, %s, %s, %s) RETURNING id",
(head.date_of_start, head.date_of_end, con_id,
head.first_name, head.second_name, head.last_name))
head.id = cur.fetchone()[0]
self._connection.commit()
@ -188,9 +209,10 @@ class DataProvider:
def create_phone_number(self, phone: PhoneNumber, con_id: int):
with self._connection.cursor() as cur:
cur.execute("INSERT INTO phone_number "
"(contact_info, date_of_start, date_of_end) VALUES "
"(%s, %s, %s) RETURNING id",
(con_id, phone.date_of_start, phone.date_of_end))
"(contact_info, date_of_start, date_of_end, number) VALUES "
"(%s, %s, %s, %s) RETURNING id",
(con_id, phone.date_of_start, phone.date_of_end,
phone.number))
phone.id = cur.fetchone()[0]
self._connection.commit()
@ -209,11 +231,9 @@ class DataProvider:
with self._connection.cursor() as cur:
self.create_contact_info(enterprise.contact_info)
cur.execute("INSERT INTO enterprise "
"(name, short_name, contact_info) "
"VALUES (%s, %s, %s) RETURNING id",
(enterprise.name,
enterprise.short_name,
enterprise.contact_info.id))
"(contact_info) "
"VALUES (%s) RETURNING id",
(enterprise.contact_info.id,))
enterprise.id = cur.fetchone()[0]
for act in enterprise.activities:
self.add_activity_to_enterprise(enterprise, act)
@ -224,7 +244,7 @@ class DataProvider:
def create_activity(self, activity: Activity):
with self._connection.cursor() as cur:
cur.execute("INSERT INTO activity (name) VALUES (%s) RETURNING id",
(activity.name, ))
(activity.name,))
activity.id = cur.fetchone()[0]
self._connection.commit()
@ -241,11 +261,62 @@ class DataProvider:
"VALUES (%s, %s)", (activity.id, enterprise.id))
self._connection.commit()
def get_activities(self):
def get_activities(self) -> List[Activity]:
with self._connection.cursor() as cur:
cur.execute("SELECT id, name FROM activity")
res = [Activity(id, name) for id, name in cur.fetchall()]
self._connection.commit()
return res
def get_activitiy_by_id(self, act_id: int) -> Activity:
with self._connection.cursor() as cur:
cur.execute("SELECT id, name FROM activity where id = %s",
(act_id,))
id, name = cur.fetchone()
res = Activity(id, name)
self._connection.commit()
return res
def division_count_with_no_email(self) -> int:
with self._connection.cursor() as cur:
cur.execute("SELECT COUNT(*) FROM division "
"INNER JOIN contact_info ci on "
"division.contact_info = ci.id WHERE email = ''")
res = cur.fetchone()[0]
self._connection.commit()
return res
def division_phones_of_enterprise(self, ent_id: int, date_need: date):
with self._connection.cursor() as cur:
cur.execute(
"SELECT name, number FROM phone_number inner join "
"contact_info ci on phone_number.contact_info = ci.id "
"INNER JOIN division d on ci.id = d.contact_info WHERE "
"(date_of_end >= %s or date_of_end is null) and"
" date_of_start <= %s and enterprise = %s",
(date_need, date_need, ent_id))
res = cur.fetchall()
self._connection.commit()
return res
def get_division_by_id(self, div_id: int):
return Division(
div_id,
self.get_contact_info_by_division(div_id),
self.get_activities_by_division(div_id)
)
def max_heads_change(self, date_start: date, date_end: date):
with self._connection.cursor() as cur:
cur.execute(
"SELECT name, COUNT(*) as heads_count FROM head INNER JOIN "
"contact_info ci on head.contact_info = ci.id INNER JOIN "
"division d on ci.id = d.contact_info WHERE (date_of_end <= %s"
" or date_of_end is null) and date_of_start >= %s "
"GROUP BY d.id, name ORDER BY heads_count DESC LIMIT 1",
(date_end, date_start))
res = cur.fetchone()
if res is not None:
res = res[0]
self._connection.commit()
return res

28
data/migrate.py Normal file
View File

@ -0,0 +1,28 @@
from argparse import ArgumentParser
from data.data_provider import DataProvider
from settings import DB_CONN
if __name__ == '__main__':
parser = ArgumentParser(description='Migrate data for database')
parser.add_argument('--force', '-f',
help='Force migrating. Deletes all tables!',
action='store_true')
args = parser.parse_args()
if args.force:
print('forcing migrate')
try:
dp = DataProvider(DB_CONN)
except:
print('problems with connection')
exit(1)
if args.force:
print('erasing tables')
dp.delete_tables()
try:
print('migrating data')
dp.migrate()
print('migrated successfully')
except:
print('migration failed')
exit(1)

View File

@ -9,17 +9,13 @@ class Enterprise:
_id: Optional[int],
activities: List['Activity'],
divisions: List['Division'],
contact_info: 'ContactInfo',
name: str,
short_name: str
contact_info: 'ContactInfo'
):
self.id = _id
self.activities = activities
self.divisions = divisions
self.contact_info = contact_info
self.name = name
self.short_name = short_name
@dataclass
@ -27,6 +23,7 @@ class PhoneNumber:
id: Optional[int]
date_of_start: date
date_of_end: Optional[date]
number: str
class ContactInfo:
@ -34,13 +31,19 @@ class ContactInfo:
email: str,
phone_numbers: List[PhoneNumber],
head: List['Head'],
locations: List['Location']
locations: List['Location'],
name: str,
short_name: str,
code: str
):
self.id = _id
self.phone_numbers = phone_numbers
self.head = head
self.email = email
self.locations = locations
self.name = name
self.short_name = short_name
self.code = code
@dataclass
@ -61,6 +64,9 @@ class Head:
id: Optional[int]
date_of_start: date
date_of_end: Optional[date]
first_name: str
second_name: Optional[str]
last_name: str
@dataclass

View File

@ -20,7 +20,8 @@ class TestDataProvider(TestCase):
loc = Location(None, "Russia", "Orenburg", "Elovaya", "16", "259A",
date(2010, 11, 28), None)
num = PhoneNumber(None, date(2018, 10, 10), None)
cont = ContactInfo(None, "hello@gmail.com", [num], [head], [loc])
cont = ContactInfo(None, "hello@gmail.com", [num], [head], [loc],
'name', 'short_name', 'code')
self.dp.create_contact_info(cont)
print(f"ContactInfo id is {cont.id}")
self.assertIsNotNone(cont.id)
@ -36,15 +37,17 @@ class TestDataProvider(TestCase):
loc = Location(None, "Russia", "Orenburg", "Elovaya", "16", "259A",
date(2010, 11, 28), None)
num = PhoneNumber(None, date(2018, 10, 10), None)
cont = ContactInfo(None, "hello@gmail.com", [num], [head], [loc])
cont = ContactInfo(None, "hello@gmail.com", [num], [head], [loc],
'name', 'short_name', 'code')
head_div = Head(None, date(1998, 10, 11), None)
loc_div = Location(None, "Russia", "Orenburg", "Elovaya", "16", "259A",
date(2010, 11, 28), None)
date(2010, 11, 28), None)
num_div = PhoneNumber(None, date(2018, 10, 10), None)
cont_div = ContactInfo(None, "eeeeee", [num_div],
[head_div], [loc_div])
[head_div], [loc_div], 'name', 'short_name',
'code')
div = Division(None, cont_div, [])
enterprise = Enterprise(None, [], [div], cont, "hello", "world")
enterprise = Enterprise(None, [], [div], cont)
self.dp.create_enterprise(enterprise)
self.assertIsNotNone(div.id)
self.assertIsNotNone(enterprise.id)
@ -62,15 +65,17 @@ class TestDataProvider(TestCase):
loc = Location(None, "Russia", "Orenburg", "Elovaya", "16", "259A",
date(2010, 11, 28), None)
num = PhoneNumber(None, date(2018, 10, 10), None)
cont = ContactInfo(None, "hello@gmail.com", [num], [head], [loc])
cont = ContactInfo(None, "hello@gmail.com", [num], [head], [loc],
'name', 'short_name', 'code')
head_div = Head(None, date(1998, 10, 11), None)
loc_div = Location(None, "Russia", "Orenburg", "Elovaya", "16", "259A",
date(2010, 11, 28), None)
date(2010, 11, 28), None)
num_div = PhoneNumber(None, date(2018, 10, 10), None)
cont_div = ContactInfo(None, "eeeeee", [num_div],
[head_div], [loc_div])
[head_div], [loc_div], 'name', 'short_name',
'code')
div = Division(None, cont_div, [act])
enterprise = Enterprise(None, [act], [div], cont, "hello", "world")
enterprise = Enterprise(None, [act], [div], cont)
self.dp.create_enterprise(enterprise)
test_enterprise = self.dp.get_enterprise_by_id(enterprise.id)
self.assertGreater(len(test_enterprise.activities), 0)

14
dodo.py
View File

@ -1,5 +1,5 @@
#! /usr/bin/env python3
import sys
def task_test():
return {
@ -8,6 +8,18 @@ def task_test():
}
def task_migrate():
return {
'actions': [f'{sys.executable} -m data.migrate']
}
def task_force_migrate():
return {
'actions': [f'{sys.executable} -m data.migrate --f']
}
if __name__ == '__main__':
import doit

View File

@ -5,13 +5,14 @@ CREATE TABLE "activity" (
CREATE TABLE "contact_info" (
"id" SERIAL CONSTRAINT "pk_contact_info" PRIMARY KEY,
"email" TEXT NOT NULL
"email" TEXT NOT NULL,
"name" TEXT NOT NULL,
"short_name" TEXT NOT NULL,
"code" TEXT NOT NULL
);
CREATE TABLE "enterprise" (
"id" SERIAL CONSTRAINT "pk_enterprise" PRIMARY KEY,
"name" TEXT NOT NULL,
"short_name" TEXT NOT NULL,
"contact_info" INTEGER NOT NULL
);
@ -56,7 +57,10 @@ CREATE TABLE "head" (
"id" SERIAL CONSTRAINT "pk_head" PRIMARY KEY,
"date_of_start" DATE NOT NULL,
"date_of_end" DATE,
"contact_info" INTEGER NOT NULL
"contact_info" INTEGER NOT NULL,
"first_name" TEXT NOT NULL,
"second_name" TEXT NOT NULL,
"lst_name" TEXT NOT NULL
);
CREATE INDEX "idx_head__contact_info" ON "head" ("contact_info");
@ -83,7 +87,8 @@ CREATE TABLE "phone_number" (
"id" SERIAL CONSTRAINT "pk_phone_number" PRIMARY KEY,
"contact_info" INTEGER NOT NULL,
"date_of_start" DATE NOT NULL,
"date_of_end" DATE
"date_of_end" DATE,
"number" TEXT NOT NULL
);
CREATE INDEX "idx_phone_number__contact_info" ON "phone_number" ("contact_info");

1
settings.py Normal file
View File

@ -0,0 +1 @@
DB_CONN = "postgresql://yaric359:yaric359@localhost:5432/yaric359"

View File

@ -29,15 +29,48 @@
<a class="nav-link" href="{{ url_for('hello_world') }}">Главная</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="{{ url_for('list_activities') }}" id="navbarDropdown" role="button" data-toggle="dropdown"
<a class="nav-link dropdown-toggle" href="{{ url_for('list_activities') }}" id="navbarDropdownAct" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
Виды деятельности
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-menu" aria-labelledby="navbarDropdownAct">
<a class="dropdown-item" href="{{ url_for('list_activities') }}">Список</a>
<a class="dropdown-item" href="{{ url_for('add_activity') }}">Добавить</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="{{ url_for('list_activities') }}" id="navbarDropdownEnt" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
Предприятия
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownEnt">
<a class="dropdown-item" href="{{ url_for('enterprise_list') }}">Список</a>
<a class="dropdown-item" href="{{ url_for('add_enterprise') }}">Добавить</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('add_division') }}">Добавить отдел</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('add_head') }}">Добавить руководителя</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('add_phone') }}">Добавить телефон</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('add_location') }}">Добавить местоположение</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="{{ url_for('list_activities') }}" id="navbarDropdownEnt" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
Запросы
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownEnt">
<a class="dropdown-item" href="{{ url_for('no_email_query') }}">Список без email</a>
<a class="dropdown-item" href="{{ url_for('phones_on_date_of_ent') }}">Телефоны на заданную даты</a>
<a class="dropdown-item" href="{{ url_for('max_heads_change') }}">Максимальная смена руководителей</a>
</div>
</li>
</ul>
</div>
</nav>

View File

@ -0,0 +1,40 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>Добавить главу</h3>
<form method="post">
<div class="form-group">
<label for="con_id">Руководит</label>
<select class="form-control" id="con_id" name="con_id" required>
{% for item in enterprises %}
<option value="{{ item.contact_info.id }}">Предприятие "{{ item.contact_info.name }}"</option>
{% endfor %}
{% for item in divisions %}
<option value="{{ item.contact_info.id }}">Подразделение "{{ item.contact_info.name }}"</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="last_name">Фамилия</label>
<input class="form-control" id="last_name" name="last_name" required type="text">
</div>
<div class="form-group">
<label for="first_name">Имя</label>
<input class="form-control" id="first_name" name="first_name" required type="text">
</div>
<div class="form-group">
<label for="second_name">Отчество</label>
<input class="form-control" id="second_name" name="second_name" type="text">
</div>
<div class="form-group">
<label for="date_start">Дата вступления</label>
<input class="form-control" id="date_start" name="date_start" required type="date">
</div>
<div class="form-group">
<label for="date_end">Дата снятия</label>
<input class="form-control" id="date_end" name="date_end" type="date">
</div>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>Добавить главу</h3>
<form method="post">
<div class="form-group">
<label for="con_id">Руководит</label>
<select class="form-control" id="con_id" name="con_id" required>
{% for item in enterprises %}
<option value="{{ item.contact_info.id }}">Предприятие "{{ item.contact_info.name }}"</option>
{% endfor %}
{% for item in divisions %}
<option value="{{ item.contact_info.id }}">Подразделение "{{ item.contact_info.name }}"</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="country">Страна</label>
<input class="form-control" id="country" name="country" required type="text">
</div>
<div class="form-group">
<label for="city">Город</label>
<input class="form-control" id="city" name="city" required type="text">
</div>
<div class="form-group">
<label for="street">Улица</label>
<input class="form-control" id="street" name="street" required type="text">
</div>
<div class="form-group">
<label for="house">Здание</label>
<input class="form-control" id="house" name="house" required type="text">
</div>
<div class="form-group">
<label for="room">Комната</label>
<input class="form-control" id="room" name="room" required type="text">
</div>
<div class="form-group">
<label for="date_start">Дата начала</label>
<input class="form-control" id="date_start" name="date_start" required type="date">
</div>
<div class="form-group">
<label for="date_end">Дата конца</label>
<input class="form-control" id="date_end" name="date_end" type="date">
</div>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,32 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>Добавить телефон</h3>
<form method="post">
<div class="form-group">
<label for="con_id">Телефон для</label>
<select class="form-control" id="con_id" name="con_id" required>
{% for item in enterprises %}
<option value="{{ item.contact_info.id }}">Предприятие "{{ item.contact_info.name }}"</option>
{% endfor %}
{% for item in divisions %}
<option value="{{ item.contact_info.id }}">Подразделение "{{ item.contact_info.name }}"</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="phone">Телефон</label>
<input class="form-control" id="phone" name="phone" required type="text">
</div>
<div class="form-group">
<label for="date_start">Дата назначения</label>
<input class="form-control" id="date_start" name="date_start" required type="date">
</div>
<div class="form-group">
<label for="date_end">Дата снятия</label>
<input class="form-control" id="date_end" name="date_end" type="date">
</div>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,41 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>Добавить подразделение</h3>
<form method="post">
<div class="form-group">
<label for="code">Код</label>
<input class="form-control" id="code" name="code" required type="text">
</div>
<div class="form-group">
<label for="ent_id">Предприятие</label>
<select class="form-control" id="ent_id" name="ent_id" required>
{% for item in enterpises %}
<option value="{{ item.id }}">{{ item.contact_info.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="name">Название подразделения</label>
<input class="form-control" id="name" name="name" required type="text">
</div>
<div class="form-group">
<label for="short_name">Краткое название</label>
<input class="form-control" id="short_name" name="short_name" required type="text">
</div>
<div class="form-group">
<label for="email">Email</label>
<input class="form-control" id="email" name="email" type="email">
</div>
<div class="form-group">
<label for="activities">Виды деятельности</label>
<select class="form-control" id="activities" name="activities" required multiple>
{% for activity in activities %}
<option value="{{ activity.id }}">{{ activity.name }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,213 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-4">Код</div>
<div class="col-8">{{ div.contact_info.code }}</div>
</div>
<div class="row">
<div class="col-4">Имя</div>
<div class="col-8">{{ div.contact_info.code }}</div>
</div>
<div class="row">
<div class="col-4">Краткое имя</div>
<div class="col-8">{{ div.contact_info.short_name }}</div>
</div>
<div class="row">
<div class="col-4">Email</div>
<div class="col-8">{{ div.contact_info.email }}</div>
</div>
<div class="row">
<h6>Руководители</h6>
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Фамилия
</th>
<th scope="col">
Имя
</th>
<th scope="col">
Отчество
</th>
<th scope="col">
Дата заступления
</th>
<th scope="col">
Дата снятия
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in div.contact_info.head %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.last_name }}
</td>
<td>
{{ item.first_name }}
</td>
<td>
{{ item.second_name }}
</td>
<td>
{{ item.date_of_start }}
</td>
<td>
{% if not item.date_of_end %}
---
{% else %}
{{ item.date_of_end }}
{% endif %}
</td>
<td>
{% if not item.date_of_end %}
<b>Активен</b>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row">
<h6>Телефоны</h6>
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Номер
</th>
<th scope="col">
Дата заступления
</th>
<th scope="col">
Дата снятия
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in div.contact_info.phone_numbers %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.number }}
</td>
<td>
{{ item.date_of_start }}
</td>
<td>
{% if not item.date_of_end %}
---
{% else %}
{{ item.date_of_end }}
{% endif %}
</td>
<td>
{% if not item.date_of_end %}
<b>Активен</b>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row">
<h6>Местоположения</h6>
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Страна
</th>
<th scope="col">
Город
</th>
<th scope="col">
Улица
</th>
<th scope="col">
Здание
</th>
<th scope="col">
Комната
</th>
<th scope="col">
Дата заступления
</th>
<th scope="col">
Дата снятия
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in div.contact_info.locations %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.country }}
</td>
<td>
{{ item.city }}
</td>
<td>
{{ item.street }}
</td>
<td>
{{ item.house }}
</td>
<td>
{{ item.room }}
</td>
<td>
{{ item.date_of_start }}
</td>
<td>
{% if not item.date_of_end %}
---
{% else %}
{{ item.date_of_end }}
{% endif %}
</td>
<td>
{% if not item.date_of_end %}
<b>Активен</b>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,46 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Имя
</th>
<th scope="col">
Краткое имя
</th>
<th scope="col">
Email
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in data %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.name }}
</td>
<td>
{{ item.short_name }}
</td>
<td>
{{ item.contact_info.email }}
</td>
<td>
<a href="{{ url_for('enterprise_details', ent_id=item.id) }}">Детали</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>Добавить предприятие</h3>
<form method="post" action="{{ url_for('add_enterprise_post') }}">
<div class="form-group">
<label for="code">Код</label>
<input class="form-control" id="code" name="code" required type="text">
</div>
<div class="form-group">
<label for="name">Название предприятия</label>
<input class="form-control" id="name" name="name" required type="text">
</div>
<div class="form-group">
<label for="short_name">Краткое название</label>
<input class="form-control" id="short_name" name="short_name" required type="text">
</div>
<div class="form-group">
<label for="email">Email</label>
<input class="form-control" id="email" name="email" type="email">
</div>
<div class="form-group">
<label for="activities">Виды деятельности</label>
<select class="form-control" id="activities" name="activities" required multiple>
{% for activity in activities %}
<option value="{{ activity.id }}">{{ activity.name }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,266 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-4">Код</div>
<div class="col-8">{{ ent.contact_info.code }}</div>
</div>
<div class="row">
<div class="col-4">Имя</div>
<div class="col-8">{{ ent.contact_info.code }}</div>
</div>
<div class="row">
<div class="col-4">Краткое имя</div>
<div class="col-8">{{ ent.contact_info.short_name }}</div>
</div>
<div class="row">
<div class="col-4">Email</div>
<div class="col-8">{{ ent.contact_info.email }}</div>
</div>
<div class="row">
<h6>Отделы</h6>
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Код
</th>
<th scope="col">
Имя
</th>
<th scope="col">
Краткое имя
</th>
<th scope="col">
Email
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in ent.divisions %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.contact_info.code }}
</td>
<td>
{{ item.contact_info.name }}
</td>
<td>
{{ item.contact_info.short_name }}
</td>
<td>
{{ item.contact_info.email }}
</td>
<td>
<a href="{{ url_for('division_details', div_id=item.id) }}">Детали</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row">
<h6>Руководители</h6>
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Фамилия
</th>
<th scope="col">
Имя
</th>
<th scope="col">
Отчество
</th>
<th scope="col">
Дата заступления
</th>
<th scope="col">
Дата снятия
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in ent.contact_info.head %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.last_name }}
</td>
<td>
{{ item.first_name }}
</td>
<td>
{{ item.second_name }}
</td>
<td>
{{ item.date_of_start }}
</td>
<td>
{% if not item.date_of_end %}
---
{% else %}
{{ item.date_of_end }}
{% endif %}
</td>
<td>
{% if not item.date_of_end %}
<b>Активен</b>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row">
<h6>Телефоны</h6>
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Номер
</th>
<th scope="col">
Дата заступления
</th>
<th scope="col">
Дата снятия
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in ent.contact_info.phone_numbers %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.number }}
</td>
<td>
{{ item.date_of_start }}
</td>
<td>
{% if not item.date_of_end %}
---
{% else %}
{{ item.date_of_end }}
{% endif %}
</td>
<td>
{% if not item.date_of_end %}
<b>Активен</b>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row">
<h6>Местоположения</h6>
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Страна
</th>
<th scope="col">
Город
</th>
<th scope="col">
Улица
</th>
<th scope="col">
Здание
</th>
<th scope="col">
Комната
</th>
<th scope="col">
Дата заступления
</th>
<th scope="col">
Дата снятия
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in ent.contact_info.locations %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.country }}
</td>
<td>
{{ item.city }}
</td>
<td>
{{ item.street }}
</td>
<td>
{{ item.house }}
</td>
<td>
{{ item.room }}
</td>
<td>
{{ item.date_of_start }}
</td>
<td>
{% if not item.date_of_end %}
---
{% else %}
{{ item.date_of_end }}
{% endif %}
</td>
<td>
{% if not item.date_of_end %}
<b>Активен</b>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,52 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<table class="table">
<thead>
<tr>
<th scope="col">
Id
</th>
<th scope="col">
Код
</th>
<th scope="col">
Имя
</th>
<th scope="col">
Краткое имя
</th>
<th scope="col">
Email
</th>
<th scope="col">
</th>
</tr>
</thead>
<tbody>
{% for item in data %}
<tr>
<th scope="row">
{{ item.id }}
</th>
<td>
{{ item.contact_info.code }}
</td>
<td>
{{ item.contact_info.name }}
</td>
<td>
{{ item.contact_info.short_name }}
</td>
<td>
{{ item.contact_info.email }}
</td>
<td>
<a href="{{ url_for('enterprise_details', ent_id=item.id) }}">Детали</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@ -0,0 +1,6 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div>Количество подразделений без электронной почты: {{ email_count }}</div>
</div>
{% endblock %}

View File

@ -0,0 +1,20 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>Добавить телефон</h3>
<form method="get">
<div class="form-group">
<label for="date_start">Начало</label>
<input class="form-control" id="date_start" name="date_start" required type="date">
</div>
<div class="form-group">
<label for="date_end">Конец</label>
<input class="form-control" id="date_end" name="date_end" required type="date">
</div>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
{% if res %}
<div>Подразделение {{ res }}</div>
{% endif %}
</div>
{% endblock %}

View File

@ -0,0 +1,47 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>Добавить телефон</h3>
<form method="get">
<div class="form-group">
<label for="ent_id">Телефон для</label>
<select class="form-control" id="ent_id" name="ent_id" required>
{% for item in enterprises %}
<option value="{{ item.id }}">Предприятие "{{ item.contact_info.name }}"</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="date">На дату</label>
<input class="form-control" id="date" name="date" required type="date">
</div>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
{% if res %}
<table class="table">
<thead>
<tr>
<th scope="col">
Имя
</th>
<th scope="col">
Телефон
</th>
</tr>
</thead>
<tbody>
{% for item in res %}
<tr>
<th scope="row">
{{ item[0] }}
</th>
<td>
{{ item[1] }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
{% endblock %}