| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- from pathlib import Path
- from docx import Document
- from docx.enum.section import WD_SECTION
- from docx.enum.text import WD_ALIGN_PARAGRAPH
- from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT
- from docx.oxml import OxmlElement
- from docx.oxml.ns import qn
- from docx.shared import Cm, Pt, RGBColor
- OUT = Path(r"C:\Users\sdfgjnfjhkgbjkhdfg\Documents\autoprokat\Отчет_ПМ11_Автопрокат.docx")
- def set_cell_shading(cell, fill):
- tc_pr = cell._tc.get_or_add_tcPr()
- shd = OxmlElement("w:shd")
- shd.set(qn("w:fill"), fill)
- tc_pr.append(shd)
- def set_cell_text(cell, text, bold=False):
- cell.text = ""
- p = cell.paragraphs[0]
- run = p.add_run(str(text))
- run.bold = bold
- run.font.name = "Times New Roman"
- run.font.size = Pt(12)
- cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
- def add_table(doc, title, headers, rows):
- p = doc.add_paragraph(title)
- p.alignment = WD_ALIGN_PARAGRAPH.CENTER
- p.runs[0].font.name = "Times New Roman"
- p.runs[0].font.size = Pt(12)
- table = doc.add_table(rows=1, cols=len(headers))
- table.alignment = WD_TABLE_ALIGNMENT.CENTER
- table.style = "Table Grid"
- for i, h in enumerate(headers):
- set_cell_text(table.rows[0].cells[i], h, True)
- set_cell_shading(table.rows[0].cells[i], "D9EAF7")
- for row in rows:
- cells = table.add_row().cells
- for i, value in enumerate(row):
- set_cell_text(cells[i], value)
- doc.add_paragraph()
- return table
- def add_heading(doc, text, level=1):
- p = doc.add_heading(text, level=level)
- for run in p.runs:
- run.font.name = "Times New Roman"
- run.font.color.rgb = RGBColor(0, 0, 0)
- return p
- def add_paragraph(doc, text="", first_line=True):
- p = doc.add_paragraph()
- p.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
- p.paragraph_format.line_spacing = 1.5
- if first_line:
- p.paragraph_format.first_line_indent = Cm(1.25)
- run = p.add_run(text)
- run.font.name = "Times New Roman"
- run.font.size = Pt(14)
- return p
- def add_bullets(doc, items):
- for item in items:
- p = doc.add_paragraph(style=None)
- p.paragraph_format.left_indent = Cm(1.25)
- p.paragraph_format.line_spacing = 1.5
- run = p.add_run(item)
- run.font.name = "Times New Roman"
- run.font.size = Pt(14)
- def add_code(doc, text):
- p = doc.add_paragraph()
- p.paragraph_format.line_spacing = 1.0
- run = p.add_run(text)
- run.font.name = "Courier New"
- run.font.size = Pt(9)
- def set_document_style(doc):
- section = doc.sections[0]
- section.top_margin = Cm(2)
- section.bottom_margin = Cm(2)
- section.left_margin = Cm(3)
- section.right_margin = Cm(1.5)
- styles = doc.styles
- styles["Normal"].font.name = "Times New Roman"
- styles["Normal"].font.size = Pt(14)
- for style_name in ["Heading 1", "Heading 2", "Heading 3"]:
- style = styles[style_name]
- style.font.name = "Times New Roman"
- style.font.color.rgb = RGBColor(0, 0, 0)
- def title_page(doc):
- lines = [
- "Министерство науки и высшего образования Российской Федерации",
- "Федеральное государственное бюджетное образовательное учреждение высшего образования",
- "«Новгородский государственный университет имени Ярослава Мудрого»",
- "ИНСТИТУТ ЭЛЕКТРОННЫХ И ИНФОРМАЦИОННЫХ СИСТЕМ",
- "ПОЛИТЕХНИЧЕСКИЙ КОЛЛЕДЖ",
- ]
- for line in lines:
- p = doc.add_paragraph()
- p.alignment = WD_ALIGN_PARAGRAPH.CENTER
- r = p.add_run(line)
- r.font.name = "Times New Roman"
- r.font.size = Pt(12)
- if line.isupper():
- r.bold = True
- doc.add_paragraph("\n\n")
- p = doc.add_paragraph("Утверждаю:\n\nЗам. директора по УМ и ВР\n\n____________________\n\n«___» __________ 202_ г.")
- p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
- doc.add_paragraph("\n\n")
- for line, size, bold in [
- ("ПРОИЗВОДСТВЕННАЯ ПРАКТИКА", 16, True),
- ("ПМ.11 РАЗРАБОТКА И АДМИНИСТРИРОВАНИЕ БАЗ ДАННЫХ", 14, True),
- ("09.02.07 Информационные системы и программирование", 12, False),
- ("код и наименование специальности", 10, False),
- ("ОТЧЁТ", 18, True),
- ("по теме: разработка базы данных и приложения «Автопрокат»", 14, True),
- ]:
- p = doc.add_paragraph()
- p.alignment = WD_ALIGN_PARAGRAPH.CENTER
- r = p.add_run(line)
- r.font.name = "Times New Roman"
- r.font.size = Pt(size)
- r.bold = bold
- doc.add_paragraph("\n\n")
- p = doc.add_paragraph("Руководитель от организации:\n____________________\n«___» __________ 202_ г.\n")
- p.alignment = WD_ALIGN_PARAGRAPH.LEFT
- p = doc.add_paragraph("Руководитель от колледжа:\n____________________\n«___» __________ 202_ г.\n")
- p.alignment = WD_ALIGN_PARAGRAPH.LEFT
- p = doc.add_paragraph("Выполнил:\nСтудент гр. ________\n____________________\n«___» __________ 202_ г.")
- p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
- doc.add_page_break()
- def add_contents(doc):
- add_heading(doc, "Содержание", 1)
- items = [
- "Постановка задачи на практику",
- "1 Инструкция по технике безопасности на рабочем месте",
- "2 Должностные обязанности специалиста",
- "3 Выполнение индивидуального задания",
- "3.1 Проектирование модели базы данных",
- "3.2 Словарь данных базы данных",
- "3.3 Создание объектов базы данных",
- "3.4 Руководство пользователя/администратора",
- "3.5 Методы защиты данных в базе данных",
- "4 Задание от предприятия",
- "Заключение",
- "Приложение А",
- "Приложение Б",
- ]
- for item in items:
- p = doc.add_paragraph()
- r = p.add_run(item)
- r.font.name = "Times New Roman"
- r.font.size = Pt(14)
- doc.add_page_break()
- def main():
- doc = Document()
- set_document_style(doc)
- title_page(doc)
- add_contents(doc)
- add_heading(doc, "Постановка задачи на практику", 1)
- add_paragraph(doc, "Задачей данного задания по модулю является проектирование и разработка базы данных, а также графического приложения для работы с ней. В качестве предметной области выбрана система автопроката, предназначенная для учета марок автомобилей, автомобилей, клиентов и договоров аренды.")
- add_paragraph(doc, "Графическое приложение должно обеспечивать вход пользователя в систему, просмотр данных из базы данных, ввод новых записей, поиск, редактирование, удаление, а также формирование отчетных документов. Для разработки приложения выбрана технология Windows Forms на языке C#, а в качестве СУБД используется PostgreSQL.")
- add_paragraph(doc, "Так как проектируемая система является многопользовательской, были спроектированы роли пользователей: администратор, менеджер и пользователь просмотра. Для защиты данных реализованы ограничения целостности на уровне базы данных, параметризованные запросы в приложении, разграничение прав и журналирование операций.")
- add_paragraph(doc, "Задание по модулю ПМ.11 считается завершенным при выполнении следующих этапов работ:")
- add_bullets(doc, [
- "проектирование модели базы данных;",
- "разработка базы данных в СУБД PostgreSQL;",
- "разработка приложения для работы с базой данных;",
- "реализация методов защиты на уровне БД и приложения;",
- "оформление отчета о выполнении индивидуального задания.",
- ])
- add_heading(doc, "1 Инструкция по технике безопасности на рабочем месте", 1)
- add_paragraph(doc, "При работе за компьютером необходимо соблюдать требования техники безопасности, правила эксплуатации оборудования и меры защиты информации. Рабочее место должно быть организовано так, чтобы исключить повышенную нагрузку на зрение, опорно-двигательный аппарат и нервную систему.")
- add_bullets(doc, [
- "перед началом работы проверить исправность компьютера, монитора, клавиатуры и мыши;",
- "не работать с оборудованием при поврежденных кабелях и разъемах;",
- "соблюдать расстояние от глаз до монитора не менее 50-70 см;",
- "делать перерывы при длительной работе за компьютером;",
- "использовать сложные пароли и не передавать учетные данные другим лицам;",
- "не открывать подозрительные файлы и ссылки;",
- "регулярно сохранять результаты работы и создавать резервные копии;",
- "по окончании работы корректно завершать работу программ и выходить из учетной записи.",
- ])
- add_heading(doc, "2 Должностные обязанности специалиста", 1)
- add_paragraph(doc, "В рамках выполнения задания специалист осуществляет анализ предметной области, проектирование структуры базы данных, создание таблиц и связей, разработку пользовательского приложения, настройку доступа и документирование результата.")
- add_paragraph(doc, "К основным обязанностям специалиста при выполнении работы относятся: проектирование ER-модели, создание нормализованной реляционной схемы, разработка SQL-скриптов, заполнение базы тестовыми данными, создание приложения для ввода и обработки данных, реализация защиты информации и подготовка отчета.")
- add_heading(doc, "3 Выполнение индивидуального задания", 1)
- add_heading(doc, "3.1 Проектирование модели базы данных", 2)
- add_paragraph(doc, "В ходе выполнения индивидуального задания была спроектирована база данных «Автопрокат». База данных приведена к третьей нормальной форме. Основными сущностями являются: марка автомобиля, автомобиль, клиент и договор аренды.")
- add_paragraph(doc, "Связи между таблицами имеют следующий вид: одна марка может иметь несколько автомобилей; один автомобиль может участвовать в нескольких договорах аренды; один клиент может оформить несколько договоров аренды. Центральной таблицей предметной области является rental, связывающая клиента и автомобиль.")
- add_heading(doc, "3.2 Словарь данных базы данных", 2)
- add_paragraph(doc, "База данных состоит из следующих основных таблиц:")
- add_bullets(doc, [
- "brand - справочник марок автомобилей;",
- "car - автомобили автопарка;",
- "client - клиенты автопроката;",
- "rental - договоры аренды;",
- "app_user - учетные записи приложения;",
- "audit_log - журнал операций;",
- "app_context - служебный контекст текущего пользователя приложения.",
- ])
- add_table(doc, "Таблица 1 - Таблица brand", ["Название атрибута", "Тип данных", "Назначение", "Ключевое поле"], [
- ["brand_id", "SERIAL", "Уникальный идентификатор марки", "Primary key"],
- ["name", "VARCHAR(50)", "Название марки автомобиля", "UNIQUE"],
- ["country", "VARCHAR(50)", "Страна-производитель", "Нет"],
- ])
- add_table(doc, "Таблица 2 - Таблица car", ["Название атрибута", "Тип данных", "Назначение", "Ключевое поле"], [
- ["car_id", "SERIAL", "Уникальный идентификатор автомобиля", "Primary key"],
- ["license_plate", "VARCHAR(15)", "Государственный номер", "UNIQUE"],
- ["brand_id", "INT", "Ссылка на марку автомобиля", "Foreign key"],
- ["year", "SMALLINT", "Год выпуска автомобиля", "CHECK"],
- ["daily_rate", "NUMERIC(10,2)", "Стоимость аренды за день", "CHECK"],
- ["status", "VARCHAR(20)", "Статус автомобиля", "CHECK"],
- ])
- add_table(doc, "Таблица 3 - Таблица client", ["Название атрибута", "Тип данных", "Назначение", "Ключевое поле"], [
- ["client_id", "SERIAL", "Уникальный идентификатор клиента", "Primary key"],
- ["full_name", "VARCHAR(100)", "ФИО клиента", "Нет"],
- ["phone", "VARCHAR(20)", "Контактный телефон", "UNIQUE"],
- ["address", "TEXT", "Адрес проживания", "Нет"],
- ["license_no", "VARCHAR(20)", "Номер водительского удостоверения", "UNIQUE"],
- ["created_at", "TIMESTAMPTZ", "Дата регистрации", "Нет"],
- ])
- add_table(doc, "Таблица 4 - Таблица rental", ["Название атрибута", "Тип данных", "Назначение", "Ключевое поле"], [
- ["rental_id", "SERIAL", "Уникальный идентификатор договора", "Primary key"],
- ["car_id", "INT", "Ссылка на автомобиль", "Foreign key"],
- ["client_id", "INT", "Ссылка на клиента", "Foreign key"],
- ["start_date", "DATE", "Дата начала аренды", "Нет"],
- ["end_date", "DATE", "Плановая дата возврата", "CHECK"],
- ["actual_return", "DATE", "Фактическая дата возврата", "Нет"],
- ["total_cost", "NUMERIC(10,2)", "Итоговая стоимость", "CHECK"],
- ["status", "VARCHAR(20)", "Статус договора", "CHECK"],
- ])
- add_table(doc, "Таблица 5 - Таблица app_user", ["Название атрибута", "Тип данных", "Назначение", "Ключевое поле"], [
- ["user_id", "SERIAL", "Уникальный идентификатор пользователя", "Primary key"],
- ["login", "VARCHAR(50)", "Логин пользователя", "UNIQUE"],
- ["full_name", "VARCHAR(100)", "ФИО или наименование пользователя", "Нет"],
- ["role", "VARCHAR(20)", "Роль пользователя", "CHECK"],
- ["password_hash", "TEXT", "Хеш пароля", "Нет"],
- ["password_salt", "TEXT", "Соль пароля", "Нет"],
- ["is_active", "BOOLEAN", "Признак активности учетной записи", "Нет"],
- ])
- add_table(doc, "Таблица 6 - Таблица audit_log", ["Название атрибута", "Тип данных", "Назначение", "Ключевое поле"], [
- ["audit_id", "BIGSERIAL", "Уникальный номер события", "Primary key"],
- ["changed_at", "TIMESTAMPTZ", "Дата и время операции", "Нет"],
- ["user_login", "TEXT", "Пользователь, выполнивший операцию", "Нет"],
- ["action", "TEXT", "Тип операции", "Нет"],
- ["entity", "TEXT", "Таблица", "Нет"],
- ["entity_id", "INT", "Идентификатор измененной записи", "Нет"],
- ["details", "TEXT", "Подробности изменения", "Нет"],
- ])
- add_heading(doc, "3.3 Создание объектов базы данных", 2)
- add_paragraph(doc, "В ходе выполнения индивидуального задания были созданы таблицы, индексы, представления, роли, политики безопасности и триггеры аудита. Основная схема расположена в PostgreSQL в схеме garanin_gi базы dbwork.")
- add_paragraph(doc, "Для ускорения выборок созданы индексы по внешним ключам, статусам и датам аренды. Для отчетности созданы представления v_rentals_full, v_available_cars и v_client_stats.")
- add_code(doc, """CREATE VIEW v_rentals_full AS
- SELECT r.rental_id, c.full_name AS client_name, c.phone AS client_phone,
- ca.license_plate, b.name AS brand_name, r.start_date, r.end_date,
- r.actual_return, r.total_cost, r.status
- FROM rental r
- JOIN client c ON c.client_id = r.client_id
- JOIN car ca ON ca.car_id = r.car_id
- JOIN brand b ON b.brand_id = ca.brand_id;""")
- add_heading(doc, "3.4 Руководство пользователя/администратора", 2)
- add_paragraph(doc, "Для запуска приложения необходимо открыть проект Windows Forms и выполнить команду dotnet run либо запустить собранный файл AutorentWinForms.exe. При запуске приложение подключается к серверу PostgreSQL edu-pg.itiscaf.ru, базе dbwork, схеме garanin_gi.")
- add_paragraph(doc, "После запуска отображается форма авторизации. В системе предусмотрены три типа пользователей:")
- add_table(doc, "Таблица 7 - Пользователи приложения", ["Логин", "Роль", "Доступ"], [
- ["garanin_gi", "admin", "Полный доступ ко всем функциям"],
- ["manager", "manager", "Работа с данными и отчетами"],
- ["shagavaliev_iv", "viewer", "Просмотр основных таблиц без отчетов, защиты и аудита"],
- ])
- add_paragraph(doc, "Администратор имеет полный доступ к данным, отчетам, журналу операций и разделу защиты. Менеджер может добавлять, редактировать и удалять рабочие записи, формировать отчеты и просматривать журнал. Пользователь viewer может только просматривать основные таблицы: клиенты, автомобили, марки и аренда.")
- add_paragraph(doc, "В основных вкладках приложения доступны функции поиска, просмотра, добавления, редактирования и удаления записей. Для формирования отчетов предусмотрен экспорт в HTML, TXT и CSV.")
- add_heading(doc, "3.5 Методы защиты данных в базе данных", 2)
- add_paragraph(doc, "В разработанной системе реализована комплексная защита информации на уровне базы данных и на уровне приложения. На уровне PostgreSQL используются ограничения целостности, роли, политики доступа, представления и триггеры журналирования.")
- add_bullets(doc, [
- "PRIMARY KEY исключает повторение идентификаторов записей;",
- "FOREIGN KEY обеспечивает ссылочную целостность между таблицами;",
- "UNIQUE запрещает повторение госномеров, телефонов, водительских удостоверений и названий марок;",
- "CHECK ограничивает диапазоны значений и допустимые статусы;",
- "ON DELETE RESTRICT запрещает удалять записи, используемые в связанных договорах;",
- "Row Level Security применяется для таблицы rental;",
- "audit_log фиксирует операции INSERT, UPDATE и DELETE.",
- ])
- add_paragraph(doc, "На уровне приложения реализованы вход по логину и паролю, разграничение интерфейса по ролям, параметризованные SQL-запросы через Npgsql и защита строки подключения через вынесение параметров в конфигурационный файл.")
- add_code(doc, """CREATE ROLE rent_admin NOLOGIN;
- CREATE ROLE rent_manager NOLOGIN;
- CREATE ROLE rent_viewer NOLOGIN;
- GRANT SELECT, INSERT, UPDATE ON client, car, rental TO rent_manager;
- GRANT SELECT ON ALL TABLES IN SCHEMA public TO rent_viewer;
- ALTER TABLE rental ENABLE ROW LEVEL SECURITY;
- CREATE POLICY manager_access ON rental
- FOR ALL TO rent_manager USING (true) WITH CHECK (true);""")
- add_paragraph(doc, "Дополнительным методом защиты является журналирование операций. В базе данных создана таблица audit_log и триггеры, которые автоматически записывают сведения о действиях пользователя.")
- add_code(doc, """CREATE TRIGGER trg_audit_client
- AFTER INSERT OR UPDATE OR DELETE ON client
- FOR EACH ROW EXECUTE FUNCTION fn_autorent_audit('client_id');""")
- add_heading(doc, "4 Задание от предприятия", 1)
- add_paragraph(doc, "В рамках выполнения задания была разработана информационная система для автоматизации учета автопроката. Работа включала проектирование базы данных, создание таблиц и связей, разработку приложения для пользователей, настройку доступа к удаленному серверу PostgreSQL и оформление отчетной документации.")
- add_paragraph(doc, "Полученный программный продукт может использоваться менеджером автопроката для ведения клиентов, автомобилей, марок и договоров аренды. Администратор получает возможность контролировать журнал операций и параметры защиты, а пользователь просмотра может анализировать данные без риска их изменения.")
- add_heading(doc, "Заключение", 1)
- add_paragraph(doc, "В результате выполнения задания по модулю ПМ.11 были выполнены все основные этапы проектирования и разработки базы данных и приложения для предметной области «Автопрокат». Была разработана нормализованная структура базы данных PostgreSQL, включающая таблицы, связи, ограничения, индексы, представления и триггеры.")
- add_paragraph(doc, "На этапе реализации было создано Windows Forms приложение на языке C#, обеспечивающее авторизацию пользователей, просмотр, поиск, ввод, редактирование и удаление данных, а также формирование отчетных документов. Приложение подключается к удаленной базе данных PostgreSQL и использует параметризованные запросы.")
- add_paragraph(doc, "В системе реализованы методы защиты данных: разграничение ролей, ограничения целостности, проверка прав на уровне интерфейса, журналирование операций и использование защищенной конфигурации подключения. Таким образом, задание по модулю ПМ.11 выполнено в полном объеме.")
- add_heading(doc, "Приложение А", 1)
- p = doc.add_paragraph("(обязательное)")
- p.alignment = WD_ALIGN_PARAGRAPH.CENTER
- add_paragraph(doc, "Рисунок 1 - ER модель базы данных «Автопрокат»")
- add_paragraph(doc, "Рисунок 2 - Реляционная модель базы данных «Автопрокат»")
- add_heading(doc, "Приложение Б", 1)
- p = doc.add_paragraph("(обязательное)")
- p.alignment = WD_ALIGN_PARAGRAPH.CENTER
- add_paragraph(doc, "Рисунок 3 - Создание таблиц brand, car, client, rental")
- add_paragraph(doc, "Рисунок 4 - Создание представлений v_rentals_full, v_available_cars, v_client_stats")
- add_paragraph(doc, "Рисунок 5 - Создание ролей и прав доступа")
- add_paragraph(doc, "Рисунок 6 - Создание триггеров аудита")
- add_code(doc, Path("database_security_postgresql.sql").read_text(encoding="utf-8")[:12000])
- doc.save(OUT)
- print(OUT)
- if __name__ == "__main__":
- main()
|