From b650277dbcf262857a37c77e7deaf9a196aa898f Mon Sep 17 00:00:00 2001 From: leeroymk Date: Mon, 22 Apr 2024 14:59:28 +0300 Subject: [PATCH 01/11] prepop db add to readme --- README.md | 43 +++++++++++++++++++++++++++++++---------- makedoc/services.py | 6 +++--- scripts/faker_script.py | 6 ++++-- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 0553094..d861347 100644 --- a/README.md +++ b/README.md @@ -12,23 +12,23 @@ ## How to run the project -1. Install Docker and Docker Compose +1. Install `Docker` and `Docker Compose` To get started with Melnichanka, you will need to have Docker and Docker Compose installed on your system. You can follow the instructions for your operating system here and here. Once you have Docker and Docker Compose installed, follow these steps to start the project: - - Clone the repository: +- Clone the repository: ``` git clone https://github.com/KroshkaByte/Melnichanka.git ``` - - Start the project from root directory: +- Start the project from root directory: ``` docker-compose up -d --build ``` - - Open your web browser and navigate to http://localhost:80 to access the application. +- Open your web browser and navigate to http://localhost:80 to access the application. ## Project Description @@ -38,7 +38,7 @@ The application is intended to be used by companies that need to submit shipment The application includes a user-friendly interface that allows users to easily enter data and generate documents. The interface is designed to be intuitive and easy to use, even for users with little or no technical experience. -Melnichanka is built using modern web technologies, including Django, a popular web framework for Python. The application is containerized using Docker and Docker Compose, making it easy to deploy and scale. +Melnichanka is built using modern web technologies, including `Django`, a popular web framework for Python. The application is containerized using Docker and Docker Compose, making it easy to deploy and scale. Overall, Melnichanka is a powerful and flexible tool that can help companies save time and resources when submitting shipment applications. By automating the process of generating documents, Melnichanka can help companies reduce errors, improve efficiency, and focus on their core business. @@ -47,11 +47,34 @@ Overall, Melnichanka is a powerful and flexible tool that can help companies sav To use Melnichanka, follow these steps: - - Enter the required information about the goods, brands, factories, and packages. - - Click the "Generate Documents" button to generate the package of documents required for shipment. - - Review the generated documents and make any necessary edits. - - Download the documents in the desired format (e.g., PDF, Word, Excel). - - Submit the documents to the consignee as required. +- Enter the required information about the goods, brands, factories, and packages. +- Click the `Generate Documents` button to generate the package of documents required for shipment. +- Review the generated documents and make any necessary edits. +- Download the documents in the desired format (e.g., PDF, Word, Excel). +- Submit the documents to the consignee as required. + +## Database Pre-population + +To pre-populate the database with some initial data, you can use the provided script. This script utilizes the `Faker` library to generate fake data. + +Please follow the steps below to run the script: + +- Navigate to the root directory of the project in your terminal. + +- Run the following command: + +``` +python3 manage.py runscript faker_script +``` + +This command will execute the `faker_script` script, which will then populate the database with the generated data. + +Please note that the data generated by the Faker library is random and does not represent any real information. + +## Additional Information + +- Ensure that your `virtual environment` is activated before running the commands, if you're using one. +- The `runscript` command is a part of `django-extensions`. If it's not working, make sure you have `django-extensions` installed and added to your `INSTALLED_APPS` in your Django settings. ## Documentation diff --git a/makedoc/services.py b/makedoc/services.py index f6d0a13..b52f547 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -1,10 +1,10 @@ +import os +from datetime import date, timedelta + import babel.dates import openpyxl -import os import pymorphy3 - -from datetime import date, timedelta from clients.models import Client from logistics.models import RailwayStation from users.models import CustomUser diff --git a/scripts/faker_script.py b/scripts/faker_script.py index 428a46b..3cf85f1 100644 --- a/scripts/faker_script.py +++ b/scripts/faker_script.py @@ -1,9 +1,11 @@ +from random import choice + from faker import Faker + from clients.models import Client, DirectorPosition +from goods.models import Brand, Factory, Flour, Package, Product from logistics.models import City, RailwayStation, TripAuto, TripRailway from users.models import CustomUser, Department, Position -from goods.models import Product, Factory, Flour, Package, Brand -from random import choice fake = Faker("ru_RU") From 32a7b0a34f853d192e5d4d65146ae95d016567f6 Mon Sep 17 00:00:00 2001 From: leeroymk Date: Mon, 22 Apr 2024 22:20:56 +0300 Subject: [PATCH 02/11] added ru locale to dockerfile --- Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Dockerfile b/Dockerfile index 71c8975..595d984 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,3 +12,6 @@ RUN pip install --upgrade pip \ && pip install -r requirements.txt COPY . . + +RUN apt-get update && apt-get install -y locales +RUN localedef -i ru_RU -f UTF-8 ru_RU From 6f0f11462fb120a99bcc0356c87a51aef3084372 Mon Sep 17 00:00:00 2001 From: leeroymk Date: Wed, 24 Apr 2024 17:05:24 +0300 Subject: [PATCH 03/11] refactor makedoc --- makedoc/services.py | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/makedoc/services.py b/makedoc/services.py index b52f547..b74bbb8 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -1,7 +1,7 @@ import os from datetime import date, timedelta -import babel.dates +import babel.dates as bd import openpyxl import pymorphy3 @@ -34,36 +34,35 @@ def get_logistics(request): def get_current_date(): # Сегодняшняя дата - current_date = date.today() - return current_date + return date.today() + + +def format_date_nomn_case(date_object): + # Приводим дату к именительному падежу + return morph.parse(date_object)[0].inflect({"nomn"}).word + + +def format_month_ru_locale(date_object): + # Форматируем месяц согласно русской локали + return bd.format_date(date_object, "MMMM", locale="ru_RU") def get_formatted_date_agreement(): - # Форматируем дату согласно русской локали - formatted_date_agreement = babel.dates.format_date( - get_current_date(), "«d» MMMM y г.", locale="ru_RU" - ) - return formatted_date_agreement + # Форматируем текущую дату согласно русской локали + return bd.format_date(get_current_date(), "«d» MMMM y г.", locale="ru_RU") def get_formatted_date_shipment(): current_date = get_current_date() - next_month_date = current_date + timedelta(days=30) - if next_month_date.month == current_date.month: - month_name = babel.dates.format_date(current_date, "MMMM", locale="ru_RU") - # Склоняем имя месяца - month_name = morph.parse(month_name)[0].inflect({"nomn"}).word - formatted_date_shipment = f"{month_name} {current_date.year} г." + next_month_date = current_date.replace(day=1) + timedelta(days=31) + raw_current_month = format_month_ru_locale(current_date) + raw_next_month = format_month_ru_locale(next_month_date) + current_month = format_date_nomn_case(raw_current_month) + next_month = format_date_nomn_case(raw_next_month) + if current_date.year == next_month_date.year: + return f"{current_month}-{next_month} {current_date.year} г." else: - current_month_name = babel.dates.format_date(current_date, "MMMM", locale="ru_RU") - next_month_name = babel.dates.format_date(next_month_date, "MMMM", locale="ru_RU") - # Склоняем имена месяцев - current_month_name = morph.parse(current_month_name)[0].inflect({"nomn"}).word - next_month_name = morph.parse(next_month_name)[0].inflect({"nomn"}).word - formatted_date_shipment = ( - f"{current_month_name}-" f"{next_month_name} " f"{current_date.year} г." - ) - return formatted_date_shipment + return f"{current_month} {current_date.year} г.-{next_month} {next_month_date.year} г." def write_to_excel_auto(request): From 279de717b500da04c33ce39724d9090a9dca18e9 Mon Sep 17 00:00:00 2001 From: leeroymk Date: Thu, 25 Apr 2024 12:15:56 +0300 Subject: [PATCH 04/11] refactor makedoc with floating variable --- Dockerfile | 3 - makedoc/services.py | 158 +++++++++++++++++++++++++++++++------------- 2 files changed, 113 insertions(+), 48 deletions(-) diff --git a/Dockerfile b/Dockerfile index 595d984..71c8975 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,3 @@ RUN pip install --upgrade pip \ && pip install -r requirements.txt COPY . . - -RUN apt-get update && apt-get install -y locales -RUN localedef -i ru_RU -f UTF-8 ru_RU diff --git a/makedoc/services.py b/makedoc/services.py index b74bbb8..21ec561 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -6,30 +6,31 @@ import pymorphy3 from clients.models import Client +from goods.models import Factory, Product from logistics.models import RailwayStation from users.models import CustomUser +morph = pymorphy3.MorphAnalyzer() + def get_rw(request): - rw = RailwayStation.objects.get(id=1) - return rw + return RailwayStation.objects.first() def get_client(request): - client = Client.objects.all().first() - return client + return Client.objects.all().first() def get_user(request): - user = CustomUser.objects.get(id=1) - return user + return CustomUser.objects.first() def get_logistics(request): pass -morph = pymorphy3.MorphAnalyzer() +def get_product(request): + return Product.objects.first() def get_current_date(): @@ -68,51 +69,118 @@ def get_formatted_date_shipment(): def write_to_excel_auto(request): user = get_user(request) client = get_client(request) + product = get_product(request) # Открытие файла шаблона - template_path = "exel-templates/auto.xlsx" - workbook = openpyxl.load_workbook(template_path) - worksheet = workbook.active + template_path = "makedoc/excel-templates/auto.xlsx" + wb = openpyxl.load_workbook(template_path) + ws = wb.active # Форматирование даты договора formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") - # Разьеденить ячейки - worksheet.unmerge_cells("A1:F1") - worksheet.unmerge_cells("A2:F2") - worksheet.unmerge_cells("A4:F4") - worksheet.unmerge_cells("A17:F17") - worksheet.unmerge_cells("A49:F49") - worksheet.unmerge_cells("A50:F50") + # Номер приложения + ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") - # Записать значений в ячейки - worksheet["A1"] = f"Приложение № {client.last_application_number}" - worksheet["A2"] = ( - f"к договору поставки № {client.contract_number} от {formatted_contract_date}г." + # Номер договора + ws.cell( + row=2, + column=1, + value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", ) - worksheet["A4"] = f"ООО (ИП, АО) «{client.client_name}»" - worksheet["F6"] = get_formatted_date_agreement() - worksheet["A17"] = ( - f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих одинаковую " - f"юридическую силу, по одному для каждой из сторон, вступает в силу с момента " - f"подписания и является неотъемлемой частью договора № {client.contract_number} " - f"от {formatted_contract_date}г." + ws.cell(row=4, column=1, value=client.client_name) + ws.cell(row=6, column=6, value=get_formatted_date_agreement()) + + # Значение строки для стартовой подвижной ячейки + caret = 10 + + # Берем количество товаров из реквеста + goods_quantity = 3 + + # Наполняем таблицу товарами + for _ in range(goods_quantity): + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) + ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") + ws.cell(row=caret, column=4, value=product.package.package) + # Берем из реквеста (рефакторинг) + ws.cell(row=caret, column=5, value=20) + # Возможно применить скидку тут + ws.cell(row=caret, column=6, value=str(product.price)) + caret += 1 + + caret += 1 + + # Комбинат-грузоотправитель + # Берем из реквеста (рефакторинг) + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Грузоотправитель:") + ws.cell(row=caret, column=3, value=str(Factory.objects.first())) + caret += 1 + + # Автоуслуги + # Проверка стоимости доставки в реквесте (рефакторинг) + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Автотранспортные услуги:") + ws.cell( + row=caret, + column=3, + value="не входят в стоимость товара" if 0 else "входят в стоимость товара", + ) + caret += 1 + + # Срок отгрузки + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Срок отгрузки:") + + ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) + caret += 2 + + # Право по дебиторской задолженности + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + + pdz = "▪Продавец имеет право не осуществлять отгрузку товара до полного погашения Покупателем \ +просроченной дебиторской задолженности." + ws.cell(row=caret, column=1, value=pdz) + caret += 1 + + # Юридическая информация + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + + contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих \ +одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ +подписания и является неотъемлемой частью договора № \ +{client.contract_number} от {formatted_contract_date}г." + ws.cell(row=caret, column=1, value=contract_option) + caret += 4 + + # Подписант продавца + ws.cell(row=caret, column=1, value="Генеральный директор") + caret += 1 + ws.cell(row=caret, column=1, value="ООО «Торговый дом «Оскольская мука»") + ws.cell(row=caret, column=6, value="С.А. Годизов") + caret += 8 + + # Подписант покупателя + ws.cell(row=caret, column=1, value=str(client.director_position)) + caret += 1 + ws.cell(row=caret, column=1, value=client.client_name) + # Нужно спарсить имя директора и вывести в сокращенном виде + ws.cell(row=caret, column=6, value=client.director_name) + + caret = 49 + # Контакты менеджера + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + ws.cell(row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}") + caret += 1 + + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + ws.cell( + row=caret, + column=1, + value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", ) - worksheet["C14"] = get_formatted_date_shipment() - worksheet["A35"] = f"{client.director_position}" - worksheet["A36"] = client.client_name - worksheet["F36"] = client.director_name - worksheet["A49"] = f"Ваш персональный менеджер: {user.full_name}" - worksheet["A50"] = f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}" - - # Объединить ячейки - worksheet.merge_cells("A1:F1") - worksheet.merge_cells("A2:F2") - worksheet.merge_cells("A4:F4") - worksheet.merge_cells("A17:F17") - worksheet.merge_cells("A49:F49") - worksheet.merge_cells("A50:F50") + # Тут предлагаю тоже отрефакторить, сделать отдельную функцию для сохранения объекта # Создать структуру каталогов directory = os.path.join( "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] @@ -124,7 +192,7 @@ def write_to_excel_auto(request): directory, f"auto_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx", ) - workbook.save(new_file_path) + wb.save(new_file_path) def write_to_excel_rw(request): @@ -133,7 +201,7 @@ def write_to_excel_rw(request): rw = get_rw(request) # Открытие файла шаблона - template_path = "exel-templates/rw.xlsx" + template_path = "makedoc/excel-templates/rw.xlsx" workbook = openpyxl.load_workbook(template_path) worksheet = workbook.active @@ -199,7 +267,7 @@ def write_to_excel_sluzebnyi(request): user = get_user(request) # Открытие файла шаблона - template_path = "exel-templates/sluz.xlsx" + template_path = "makedoc/excel-templates/sluz.xlsx" workbook = openpyxl.load_workbook(template_path) worksheet = workbook.active From 92c458e55fbb43ae92fdbfbe38bcdb095d5cc245 Mon Sep 17 00:00:00 2001 From: leeroymk Date: Sat, 18 May 2024 14:17:13 +0300 Subject: [PATCH 05/11] remake exidting functions --- makedoc/services.py | 228 ++++++++++++++++++------- makedoc/tests/conftest.py | 0 makedoc/tests/test_services_makedoc.py | 108 ++++++++++++ makedoc/views.py | 3 +- melnichanka/settings.py | 2 +- pytest.ini | 3 +- 6 files changed, 282 insertions(+), 62 deletions(-) create mode 100644 makedoc/tests/conftest.py create mode 100644 makedoc/tests/test_services_makedoc.py diff --git a/makedoc/services.py b/makedoc/services.py index 21ec561..d8e0593 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -7,12 +7,20 @@ from clients.models import Client from goods.models import Factory, Product -from logistics.models import RailwayStation +from logistics.models import City, RailwayStation from users.models import CustomUser morph = pymorphy3.MorphAnalyzer() +def get_region(request): + return City.objects.first() + + +def get_factory(request): + return Factory.objects.first() + + def get_rw(request): return RailwayStation.objects.first() @@ -70,9 +78,10 @@ def write_to_excel_auto(request): user = get_user(request) client = get_client(request) product = get_product(request) + factory = get_factory(request) # Открытие файла шаблона - template_path = "makedoc/excel-templates/auto.xlsx" + template_path = "makedoc/excel-templates/spec.xlsx" wb = openpyxl.load_workbook(template_path) ws = wb.active @@ -114,7 +123,7 @@ def write_to_excel_auto(request): # Берем из реквеста (рефакторинг) ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) ws.cell(row=caret, column=1, value="Грузоотправитель:") - ws.cell(row=caret, column=3, value=str(Factory.objects.first())) + ws.cell(row=caret, column=3, value=factory.full_name) caret += 1 # Автоуслуги @@ -198,57 +207,158 @@ def write_to_excel_auto(request): def write_to_excel_rw(request): user = get_user(request) client = get_client(request) + product = get_product(request) rw = get_rw(request) + factory = get_factory(request) # Открытие файла шаблона - template_path = "makedoc/excel-templates/rw.xlsx" - workbook = openpyxl.load_workbook(template_path) - worksheet = workbook.active + template_path = "makedoc/excel-templates/spec.xlsx" + wb = openpyxl.load_workbook(template_path) + ws = wb.active # Форматирование даты договора formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") - # Разьеденить ячейки - worksheet.unmerge_cells("A1:F1") - worksheet.unmerge_cells("A2:F2") - worksheet.unmerge_cells("A4:F4") - worksheet.unmerge_cells("A26:F26") - worksheet.unmerge_cells("A49:F49") - worksheet.unmerge_cells("A50:F50") - - # Записать значений в ячейки - worksheet["A1"] = f"Приложение № {client.last_application_number}" - worksheet["A2"] = ( - f"к договору поставки № {client.contract_number} от {formatted_contract_date}г." + # Номер приложения + ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") + + # Номер договора + ws.cell( + row=2, + column=1, + value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", + ) + ws.cell(row=4, column=1, value=client.client_name) + ws.cell(row=6, column=6, value=get_formatted_date_agreement()) + + # Значение строки для стартовой подвижной ячейки + caret = 10 + + # Берем количество товаров из реквеста + goods_quantity = 3 + + ws.cell(row=4, column=1, value=client.client_name) + ws.cell(row=6, column=6, value=get_formatted_date_agreement()) + + # Наполняем таблицу товарами + for _ in range(goods_quantity): + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) + ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") + ws.cell(row=caret, column=4, value=product.package.package) + # Берем из реквеста (рефакторинг) + ws.cell(row=caret, column=5, value=20) + # Возможно применить скидку тут + ws.cell(row=caret, column=6, value=str(product.price)) + caret += 1 + + caret += 1 + + ws.cell(row=caret, column=1, value="Поставка осуществляется:") + ws.cell(row=caret, column=3, value="ж/д транспортом") + + caret += 1 + + # Станция назначения + ws.cell(row=caret, column=1, value="Станция отправления:") + ws.cell(row=caret, column=3, value=rw.station_name) + + caret += 1 + + # Грузоотправитель + ws.cell(row=caret, column=1, value="Грузоотправитель:") + ws.cell(row=caret, column=3, value=factory.full_name) + + caret += 1 + + # Условия поставки + ws.cell(row=caret, column=1, value="Условия поставки") + ws.cell( + row=caret, + column=3, + value="франко-вагон станция отправления" if 0 else "франко-вагон станция назначения", + ) + + caret += 1 + + # Срок отгрузки + ws.cell(row=caret, column=1, value="Срок отгрузки:") + ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) + + caret += 2 + + # Отгрузочные реквизиты + ws.cell(row=caret, column=1, value="Отгрузочные реквизиты:") + + caret += 1 + + ws.cell(row=caret, column=1, value="Станция назначения:") + ws.cell(row=caret, column=3, value=client.railway_station.station_name) + + caret += 1 + + # Код станции + ws.cell(row=caret, column=1, value="Код станции:") + ws.cell(row=caret, column=3, value=client.railway_station.station_id) + + caret += 1 + + # Получатель + ws.cell(row=caret, column=1, value="Получатель:") + ws.cell(row=caret, column=3, value=client.receiver_name) + + caret += 1 + + # Код получателя + ws.cell(row=caret, column=1, value="Код получателя:") + ws.cell(row=caret, column=3, value=client.receiver_id) + + caret += 1 + + # ОКПО + ws.cell(row=caret, column=1, value="ОКПО:") + ws.cell(row=caret, column=3, value=client.receiver_okpo) + + caret += 1 + + # Адрес + ws.cell(row=caret, column=1, value="Адрес:") + ws.cell(row=caret, column=3, value=client.receiver_adress) + + caret += 2 + + contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих \ +одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ +подписания и является неотъемлемой частью договора № \ +{client.contract_number} от {formatted_contract_date}г." + ws.cell(row=caret, column=1, value=contract_option) + caret += 4 + + # Подписант продавца + ws.cell(row=caret, column=1, value="Генеральный директор") + caret += 1 + ws.cell(row=caret, column=1, value="ООО «Торговый дом «Оскольская мука»") + ws.cell(row=caret, column=6, value="С.А. Годизов") + caret += 8 + + # Подписант покупателя + ws.cell(row=caret, column=1, value=str(client.director_position)) + caret += 1 + ws.cell(row=caret, column=1, value=client.client_name) + # Нужно спарсить имя директора и вывести в сокращенном виде + ws.cell(row=caret, column=6, value=client.director_name) + + caret = 49 + # Контакты менеджера + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + ws.cell(row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}") + caret += 1 + + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + ws.cell( + row=caret, + column=1, + value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", ) - worksheet["A4"] = f"ООО (ИП, АО) «{client.client_name}»" - worksheet["F6"] = get_formatted_date_agreement() - worksheet[ - "A26" - ] = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих одинаковую \ - юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ - подписания и является неотъемлемой частью договора № {client.contract_number} \ - от {formatted_contract_date}г." - worksheet["C16"] = get_formatted_date_shipment() - worksheet["C19"] = rw.station_name - worksheet["C20"] = rw.station_id - worksheet["C21"] = f"ООО (ИП, АО) {client.receiver_name}" - worksheet["C22"] = client.receiver_id - worksheet["C23"] = client.receiver_okpo - worksheet["C24"] = client.receiver_adress - worksheet["A42"] = f"{client.director_position}" - worksheet["A43"] = client.client_name - worksheet["F43"] = client.director_name - worksheet["A49"] = f"Ваш персональный менеджер: {user.full_name}" - worksheet["A50"] = f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}" - - # Объединить ячейки - worksheet.merge_cells("A1:F1") - worksheet.merge_cells("A2:F2") - worksheet.merge_cells("A4:F4") - worksheet.merge_cells("A26:F26") - worksheet.merge_cells("A49:F49") - worksheet.merge_cells("A50:F50") # Создать структуру каталогов directory = os.path.join( @@ -260,26 +370,28 @@ def write_to_excel_rw(request): new_file_path = os.path.join( directory, f"rw_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx" ) - workbook.save(new_file_path) + wb.save(new_file_path) def write_to_excel_sluzebnyi(request): user = get_user(request) + city = get_region(request) + client = get_client(request) + + # Принимаем с фронта макс размер скидки (пока хардкод) + discount = 15 # Открытие файла шаблона template_path = "makedoc/excel-templates/sluz.xlsx" - workbook = openpyxl.load_workbook(template_path) - worksheet = workbook.active - - # Разьеденить ячейки - worksheet.unmerge_cells("A19:H19") + wb = openpyxl.load_workbook(template_path) + ws = wb.active # Записка - worksheet["A15"] = f"{get_formatted_date_agreement()} № 12/2.2/23/3-" - worksheet["A19"] = "" - - # Объединить ячейки - worksheet.merge_cells("A19:H19") + ws.cell(row=15, column=1, value=f"{get_formatted_date_agreement()} № 12/2.2/23/3-") + text = f"В целях увеличения объема продаж на территории {city.region} прошу Вашего \ +согласования применить скидку для контрагента {client.client_name} (г. {city.city}) до {discount}%\ +в {get_formatted_date_shipment} на продукцию следующего ассортимента: " + ws.cell(row=19, column=1, value=text) # Создать структуру каталогов directory = os.path.join( @@ -292,4 +404,4 @@ def write_to_excel_sluzebnyi(request): directory, f"sluz_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx", ) - workbook.save(new_file_path) + wb.save(new_file_path) diff --git a/makedoc/tests/conftest.py b/makedoc/tests/conftest.py new file mode 100644 index 0000000..e69de29 diff --git a/makedoc/tests/test_services_makedoc.py b/makedoc/tests/test_services_makedoc.py new file mode 100644 index 0000000..b9a716d --- /dev/null +++ b/makedoc/tests/test_services_makedoc.py @@ -0,0 +1,108 @@ +import os +import sys + +import pytest + +from makedoc.services import get_client, get_product, get_user, write_to_excel_auto + +sys.path.append("path/to/your/module/directory") # Добавьте путь к вашему модулю +from unittest.mock import MagicMock + +import openpyxl + + +@pytest.fixture +def mock_request(): + request = MagicMock() + request.user = MagicMock() + request.client = MagicMock() + request.product = MagicMock() + return request + + +@pytest.fixture +def mock_user(): + return MagicMock( + full_name="Test User", phone_number_personal="1234567890", phone_number_work="0987654321" + ) + + +@pytest.fixture +def mock_client(): + client = MagicMock() + client.contract_number = "1234567890" + client.contract_date = "2022-01-01" + client.client_name = "Test Client" + client.director_name = "John Doe" + client.director_position = "CEO" + client.last_application_number = 123 + return client + + +@pytest.fixture +def mock_product(): + product = MagicMock() + product.flour_name = "Test Flour" + product.brand = "Test Brand" + product.package = MagicMock(package="Test Package") + product.price = 10.0 + return product + + +def test_write_to_excel_auto_creates_file( + mock_request, mock_user, mock_client, mock_product, tmp_path +): + get_user.return_value = mock_user + get_client.return_value = mock_client + get_product.return_value = mock_product + + write_to_excel_auto(mock_request) + + assert os.path.exists( + os.path.join(tmp_path, "makedoc", "01.01.2022", "Test", "auto_Test_01.01.2022.xlsx") + ) + + +def test_write_to_excel_auto_fills_data( + mock_request, mock_user, mock_client, mock_product, tmp_path +): + get_user.return_value = mock_user + get_client.return_value = mock_client + get_product.return_value = mock_product + + write_to_excel_auto(mock_request) + + wb = openpyxl.load_workbook( + os.path.join(tmp_path, "makedoc", "01.01.2022", "Test", "auto_Test_01.01.2022.xlsx") + ) + ws = wb.active + + assert ws.cell(row=1, column=1).value == f"Приложение № {mock_client.last_application_number}" + assert ( + ws.cell(row=2, column=1).value + == f"к договору поставки № {mock_client.contract_number} от 01.01.2022г." + ) + assert ws.cell(row=4, column=1).value == mock_client.client_name + assert ws.cell(row=6, column=6).value == "01.01.2022" + assert ws.cell(row=10, column=1).value == f"{mock_product.flour_name} {mock_product.brand}" + assert ws.cell(row=10, column=4).value == mock_product.package.package + assert ws.cell(row=10, column=5).value == 20 + assert ws.cell(row=10, column=6).value == "10.0" + + +# Добавьте дополнительные тесты для проверки других частей файла Excel + + +@pytest.fixture(autouse=True) +def mock_get_formatted_date_agreement(mocker): + mocker.patch("your_module.get_formatted_date_agreement", return_value="01.01.2022") + + +@pytest.fixture(autouse=True) +def mock_get_formatted_date_shipment(mocker): + mocker.patch("your_module.get_formatted_date_shipment", return_value="01.01.2022") + + +@pytest.fixture(autouse=True) +def mock_factory(mocker): + mocker.patch("your_module.Factory.objects.first", return_value="Test Factory") diff --git a/makedoc/views.py b/makedoc/views.py index bd9d7de..5c416ff 100644 --- a/makedoc/views.py +++ b/makedoc/views.py @@ -9,7 +9,8 @@ def create_docs(request): write_to_excel_auto(request) write_to_excel_rw(request) - write_to_excel_sluzebnyi(request) + # Если применяется скидка, пишем служебную записку + write_to_excel_sluzebnyi(request) if 0 else None return HttpResponse("Документы сохранены") diff --git a/melnichanka/settings.py b/melnichanka/settings.py index d66e80a..ff612dd 100644 --- a/melnichanka/settings.py +++ b/melnichanka/settings.py @@ -27,7 +27,7 @@ SECRET_KEY = str(os.getenv("SECRET_KEY")) # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = False +DEBUG = True load_dotenv() CORS_ORIGIN_ALLOW_ALL = False diff --git a/pytest.ini b/pytest.ini index 668edc0..a2a9979 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,5 +1,4 @@ [pytest] DJANGO_SETTINGS_MODULE = melnichanka.settings python_files = tests.py test_*.py *_tests.py -; addopts = --cov=. --cov-branch --cov-fail-under=60 --testdox -vv -addopts = --testdox -vv +addopts = --cov=. --cov-branch --cov-fail-under=60 --testdox -vv From 5db8eb0b406c81a61b2c358a4a13a5f3cbebb20e Mon Sep 17 00:00:00 2001 From: leeroymk Date: Sun, 2 Jun 2024 23:08:40 +0300 Subject: [PATCH 06/11] deleted print --- docker-compose.yml | 1 - makedoc/services.py | 572 ++++++++++++++-------------------------- makedoc/services_old.py | 415 +++++++++++++++++++++++++++++ makedoc/views.py | 12 +- 4 files changed, 620 insertions(+), 380 deletions(-) create mode 100644 makedoc/services_old.py diff --git a/docker-compose.yml b/docker-compose.yml index 825362b..6248bff 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3.8' services: db: image: postgres:16.3-alpine diff --git a/makedoc/services.py b/makedoc/services.py index d62b6e7..0ab8d72 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -4,73 +4,34 @@ import babel.dates as bd import openpyxl import pymorphy3 +from openpyxl.styles import Alignment, Border, Font, Side from clients.models import Client from goods.models import Factory, Product -from logistics.models import City, RailwayStation from users.models import CustomUser morph = pymorphy3.MorphAnalyzer() -def get_region(request): - return City.objects.first() - - -def get_factory(request): - return Factory.objects.first() - - -def get_rw(request): - return RailwayStation.objects.first() - - -def get_client(request): - return Client.objects.all().first() - - -def get_user(request): - return CustomUser.objects.first() - - -def get_logistics(request): - pass - - -def get_product(request): - return Product.objects.first() - - def get_current_date(): - # Сегодняшняя дата return date.today() def format_date_nomn_case(date_object): - # Приводим дату к именительному падежу - return morph.parse(date_object)[0].inflect({"nomn"}).word + return morph.parse(str(date_object))[0].inflect({"nomn"}).word def format_month_ru_locale(date_object): - # Форматируем месяц согласно русской локали return bd.format_date(date_object, "MMMM", locale="ru_RU") def get_formatted_date_agreement(): - # Форматируем текущую дату согласно русской локали return bd.format_date(get_current_date(), "«d» MMMM y г.", locale="ru_RU") def get_formatted_date_shipment(): current_date = get_current_date() - next_month_date = current_date.replace(day=1) + timedelta(days=31) - raw_current_month = format_month_ru_locale(current_date) - raw_next_month = format_month_ru_locale(next_month_date) - current_month = format_date_nomn_case(raw_current_month) - next_month = format_date_nomn_case(raw_next_month) - if current_date.year == next_month_date.year: - return f"{current_month}-{next_month} {current_date.year} г." - next_month_date = current_date.replace(day=1) + timedelta(days=31) + next_month_date = (current_date.replace(day=1) + timedelta(days=31)).replace(day=1) raw_current_month = format_month_ru_locale(current_date) raw_next_month = format_month_ru_locale(next_month_date) current_month = format_date_nomn_case(raw_current_month) @@ -81,335 +42,198 @@ def get_formatted_date_shipment(): return f"{current_month} {current_date.year} г.-{next_month} {next_month_date.year} г." -def write_to_excel_auto(request): - user = get_user(request) - client = get_client(request) - product = get_product(request) - factory = get_factory(request) - - # Открытие файла шаблона - template_path = "makedoc/excel-templates/spec.xlsx" - wb = openpyxl.load_workbook(template_path) - ws = wb.active - - # Форматирование даты договора - formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") - - # Номер приложения - ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") - - # Номер договора - ws.cell( - row=2, - column=1, - value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", - ) - ws.cell(row=4, column=1, value=client.client_name) - ws.cell(row=6, column=6, value=get_formatted_date_agreement()) - - # Значение строки для стартовой подвижной ячейки - caret = 10 - - # Берем количество товаров из реквеста - goods_quantity = 3 - - # Наполняем таблицу товарами - for _ in range(goods_quantity): - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) - ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") - ws.cell(row=caret, column=4, value=product.package.package) - # Берем из реквеста (рефакторинг) - ws.cell(row=caret, column=5, value=20) - # Возможно применить скидку тут - ws.cell(row=caret, column=6, value=str(product.price)) - caret += 1 - - caret += 1 - - # Комбинат-грузоотправитель - # Берем из реквеста (рефакторинг) - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) - ws.cell(row=caret, column=1, value="Грузоотправитель:") - ws.cell(row=caret, column=3, value=factory.full_name) - caret += 1 - - # Автоуслуги - # Проверка стоимости доставки в реквесте (рефакторинг) - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) - ws.cell(row=caret, column=1, value="Автотранспортные услуги:") - ws.cell( - row=caret, - column=3, - value="не входят в стоимость товара" if 0 else "входят в стоимость товара", - ) - caret += 1 - - # Срок отгрузки - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) - ws.cell(row=caret, column=1, value="Срок отгрузки:") - - ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) - caret += 2 - - # Право по дебиторской задолженности - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - - pdz = "▪Продавец имеет право не осуществлять отгрузку товара до полного погашения Покупателем \ -просроченной дебиторской задолженности." - ws.cell(row=caret, column=1, value=pdz) - caret += 1 - - # Юридическая информация - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - - contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих \ -одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ -подписания и является неотъемлемой частью договора № \ -{client.contract_number} от {formatted_contract_date}г." - ws.cell(row=caret, column=1, value=contract_option) - caret += 4 - - # Подписант продавца - ws.cell(row=caret, column=1, value="Генеральный директор") - caret += 1 - ws.cell(row=caret, column=1, value="ООО «Торговый дом «Оскольская мука»") - ws.cell(row=caret, column=6, value="С.А. Годизов") - caret += 8 - - # Подписант покупателя - ws.cell(row=caret, column=1, value=str(client.director_position)) - caret += 1 - ws.cell(row=caret, column=1, value=client.client_name) - # Нужно спарсить имя директора и вывести в сокращенном виде - ws.cell(row=caret, column=6, value=client.director_name) - - caret = 49 - # Контакты менеджера - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - ws.cell(row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}") - caret += 1 - - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - ws.cell( - row=caret, - column=1, - value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", - ) - - # Тут предлагаю тоже отрефакторить, сделать отдельную функцию для сохранения объекта - # Создать структуру каталогов - directory = os.path.join( - "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] - ) - os.makedirs(directory, exist_ok=True) - - # Сохранить файл - new_file_path = os.path.join( - directory, - f"auto_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx", - ) - wb.save(new_file_path) - wb.save(new_file_path) - - -def write_to_excel_rw(request): - user = get_user(request) - client = get_client(request) - product = get_product(request) - rw = get_rw(request) - factory = get_factory(request) - - # Открытие файла шаблона - template_path = "makedoc/excel-templates/spec.xlsx" - wb = openpyxl.load_workbook(template_path) - ws = wb.active - - # Форматирование даты договора - formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") - - # Номер приложения - ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") - - # Номер договора - ws.cell( - row=2, - column=1, - value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", - ) - ws.cell(row=4, column=1, value=client.client_name) - ws.cell(row=6, column=6, value=get_formatted_date_agreement()) - - # Значение строки для стартовой подвижной ячейки - caret = 10 - - # Берем количество товаров из реквеста - goods_quantity = 3 - - ws.cell(row=4, column=1, value=client.client_name) - ws.cell(row=6, column=6, value=get_formatted_date_agreement()) - - # Наполняем таблицу товарами - for _ in range(goods_quantity): - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) - ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") - ws.cell(row=caret, column=4, value=product.package.package) - # Берем из реквеста (рефакторинг) - ws.cell(row=caret, column=5, value=20) - # Возможно применить скидку тут - ws.cell(row=caret, column=6, value=str(product.price)) - caret += 1 - - caret += 1 - - ws.cell(row=caret, column=1, value="Поставка осуществляется:") - ws.cell(row=caret, column=3, value="ж/д транспортом") - - caret += 1 - - # Станция назначения - ws.cell(row=caret, column=1, value="Станция отправления:") - ws.cell(row=caret, column=3, value=rw.station_name) - - caret += 1 - - # Грузоотправитель - ws.cell(row=caret, column=1, value="Грузоотправитель:") - ws.cell(row=caret, column=3, value=factory.full_name) - - caret += 1 - - # Условия поставки - ws.cell(row=caret, column=1, value="Условия поставки") - ws.cell( - row=caret, - column=3, - value="франко-вагон станция отправления" if 0 else "франко-вагон станция назначения", - ) - - caret += 1 - - # Срок отгрузки - ws.cell(row=caret, column=1, value="Срок отгрузки:") - ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) - - caret += 2 - - # Отгрузочные реквизиты - ws.cell(row=caret, column=1, value="Отгрузочные реквизиты:") - - caret += 1 - - ws.cell(row=caret, column=1, value="Станция назначения:") - ws.cell(row=caret, column=3, value=client.railway_station.station_name) - - caret += 1 - - # Код станции - ws.cell(row=caret, column=1, value="Код станции:") - ws.cell(row=caret, column=3, value=client.railway_station.station_id) - - caret += 1 - - # Получатель - ws.cell(row=caret, column=1, value="Получатель:") - ws.cell(row=caret, column=3, value=client.receiver_name) - - caret += 1 - - # Код получателя - ws.cell(row=caret, column=1, value="Код получателя:") - ws.cell(row=caret, column=3, value=client.receiver_id) - - caret += 1 - - # ОКПО - ws.cell(row=caret, column=1, value="ОКПО:") - ws.cell(row=caret, column=3, value=client.receiver_okpo) - - caret += 1 - - # Адрес - ws.cell(row=caret, column=1, value="Адрес:") - ws.cell(row=caret, column=3, value=client.receiver_adress) - - caret += 2 - - contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих \ -одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ -подписания и является неотъемлемой частью договора № \ -{client.contract_number} от {formatted_contract_date}г." - ws.cell(row=caret, column=1, value=contract_option) - caret += 4 - - # Подписант продавца - ws.cell(row=caret, column=1, value="Генеральный директор") - caret += 1 - ws.cell(row=caret, column=1, value="ООО «Торговый дом «Оскольская мука»") - ws.cell(row=caret, column=6, value="С.А. Годизов") - caret += 8 - - # Подписант покупателя - ws.cell(row=caret, column=1, value=str(client.director_position)) - caret += 1 - ws.cell(row=caret, column=1, value=client.client_name) - # Нужно спарсить имя директора и вывести в сокращенном виде - ws.cell(row=caret, column=6, value=client.director_name) - - caret = 49 - # Контакты менеджера - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - ws.cell(row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}") - caret += 1 - - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - ws.cell( - row=caret, - column=1, - value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", - ) - - # Создать структуру каталогов - directory = os.path.join( - "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] - ) - os.makedirs(directory, exist_ok=True) - - # Сохранить файл - new_file_path = os.path.join( - directory, f"rw_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx" - ) - wb.save(new_file_path) - - -def write_to_excel_sluzebnyi(request): - user = get_user(request) - city = get_region(request) - client = get_client(request) - - # Принимаем с фронта макс размер скидки (пока хардкод) - discount = 15 - - # Открытие файла шаблона - template_path = "makedoc/excel-templates/sluz.xlsx" - wb = openpyxl.load_workbook(template_path) - ws = wb.active - - # Записка - ws.cell(row=15, column=1, value=f"{get_formatted_date_agreement()} № 12/2.2/23/3-") - text = f"В целях увеличения объема продаж на территории {city.region} прошу Вашего \ -согласования применить скидку для контрагента {client.client_name} (г. {city.city}) до {discount}%\ -в {get_formatted_date_shipment} на продукцию следующего ассортимента: " - ws.cell(row=19, column=1, value=text) - - # Создать структуру каталогов - directory = os.path.join( - "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] - ) - os.makedirs(directory, exist_ok=True) - - # Сохранить файл - new_file_path = os.path.join( - directory, - f"sluz_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx", - ) - wb.save(new_file_path) +class Documents: + def __init__(self): + self.auto = 0 + self.rw = 0 + self.sluz = 0 + self.sopr_list = 0 + + def update_documents(self, documents_list): + if "auto" in documents_list: + self.auto = 1 + if "rw" in documents_list: + self.rw = 1 + if "sluz" in documents_list: + self.sluz = 1 + if "sopr_list" in documents_list: + self.sopr_list = 1 + + def form_auto_document(self, request): + try: + user = self.get_user(request) + client = self.get_client(request) + product = self.get_product(request) + factory = self.get_factory(request) + except Exception as e: + return f"Error fetching data: {e}" + + template_path = "makedoc/excel-templates/spec.xlsx" + wb = openpyxl.load_workbook(template_path) + ws = wb.active + + self.fill_contract_info(ws, client) + self.fill_product_info(ws, product) + self.fill_factory_info(ws, factory) + self.fill_auto_services(ws) + self.fill_debt_info(ws) + self.fill_legal_info(ws, client) + self.fill_signatures(ws, client) + self.fill_manager_contact(ws, user) + + self.apply_styles(ws) + + self.save_workbook(wb, user) + + def fill_contract_info(self, ws, client): + formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") + title = ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") + title.font = Font(bold=True) + ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") + ws.cell( + row=2, + column=1, + value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", + ) + ws.cell(row=4, column=1, value=client.client_name) + ws.cell(row=6, column=6, value=get_formatted_date_agreement()) + + def fill_product_info(self, ws, product): + caret = 10 + goods_quantity = 7 + thin_border = Border( + left=Side(style="thin"), + right=Side(style="thin"), + top=Side(style="thin"), + bottom=Side(style="thin"), + ) + + for _ in range(goods_quantity): + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) + ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") + ws.cell(row=caret, column=4, value=product.package.package) + ws.cell(row=caret, column=5, value=20) + ws.cell(row=caret, column=6, value=str(product.price)) + + for col_num in range(1, 7): + cell = ws.cell(row=caret, column=col_num) + cell.border = thin_border + if cell.column > 2: + cell.alignment = Alignment(horizontal="center", vertical="center") + caret += 1 + self.caret_product = caret + 1 + + def fill_factory_info(self, ws, factory): + caret = self.caret_product + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Грузоотправитель:") + ws.cell(row=caret, column=3, value=factory.full_name) + self.caret_factory = caret + 1 + + def fill_auto_services(self, ws): + caret = self.caret_factory + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Автотранспортные услуги:") + ws.cell( + row=caret, + column=3, + value="не входят в стоимость товара" if 0 else "входят в стоимость товара", + ) + self.caret_services = caret + 1 + + def fill_debt_info(self, ws): + caret = self.caret_services + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Срок отгрузки:") + ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) + ws.merge_cells(start_row=caret + 1, start_column=1, end_row=caret + 1, end_column=6) + pdz = "▪Продавец имеет право не осуществлять отгрузку товара до полного погашения \ +Покупателем просроченной дебиторской задолженности." + debt = ws.cell(row=caret + 1, column=1, value=pdz) + debt.alignment = Alignment(wrap_text=True, horizontal="justify", vertical="center") + ws.row_dimensions[caret + 1].height = 30 + self.caret_debt = caret + 2 + + def fill_legal_info(self, ws, client): + caret = self.caret_debt + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") + contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, \ +имеющих одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ +подписания и является неотъемлемой частью договора № {client.contract_number} от \ +{formatted_contract_date}г." + legal = ws.cell(row=caret, column=1, value=contract_option) + legal.alignment = Alignment(wrap_text=True, horizontal="justify", vertical="center") + ws.row_dimensions[caret].height = 40 + self.caret_legal = caret + 4 + + def fill_signatures(self, ws, client): + caret = self.caret_legal + ws.cell(row=caret, column=1, value="Генеральный директор") + ws.cell(row=caret + 1, column=1, value="ООО «Торговый дом «Оскольская мука»") + ws.cell(row=caret + 1, column=6, value="С.А. Годизов") + ws.cell(row=caret + 9, column=1, value=str(client.director_position)) + ws.cell(row=caret + 10, column=1, value=client.client_name) + ws.cell(row=caret + 10, column=6, value=client.director_name) + self.caret_signatures = caret + 11 + + def fill_manager_contact(self, ws, user): + caret = 49 + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + manager = ws.cell( + row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}" + ) + manager.alignment = Alignment(horizontal="center", vertical="center") + ws.merge_cells(start_row=caret + 1, start_column=1, end_row=caret + 1, end_column=6) + phone = ws.cell( + row=caret + 1, + column=1, + value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", + ) + phone.alignment = Alignment(horizontal="center", vertical="center") + + def save_workbook(self, wb, user): + directory = os.path.join( + "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] + ) + os.makedirs(directory, exist_ok=True) + new_file_path = os.path.join( + directory, + f"auto_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%м.%Y')}.xlsx", + ) + wb.save(new_file_path) + + def apply_styles(self, ws): + for row in ws.iter_rows(): + for cell in row: + if cell.value is not None: + cell.font = Font(name="Times New Roman", size=12) + + for row_num in [1, 9]: + for cell in ws[row_num]: + if cell.value is not None: + cell.font = Font(bold=True, size=12) + + def get_user(self, request): + try: + return CustomUser.objects.first() + except CustomUser.DoesNotExist: + raise Exception("User not found") + + def get_client(self, request): + try: + return Client.objects.all().first() + except Client.DoesNotExist: + raise Exception("Client not found") + + def get_product(self, request): + try: + return Product.objects.first() + except Product.DoesNotExist: + raise Exception("Product not found") + + def get_factory(self, request): + try: + return Factory.objects.first() + except Factory.DoesNotExist: + raise Exception("Factory not found") diff --git a/makedoc/services_old.py b/makedoc/services_old.py new file mode 100644 index 0000000..d62b6e7 --- /dev/null +++ b/makedoc/services_old.py @@ -0,0 +1,415 @@ +import os +from datetime import date, timedelta + +import babel.dates as bd +import openpyxl +import pymorphy3 + +from clients.models import Client +from goods.models import Factory, Product +from logistics.models import City, RailwayStation +from users.models import CustomUser + +morph = pymorphy3.MorphAnalyzer() + + +def get_region(request): + return City.objects.first() + + +def get_factory(request): + return Factory.objects.first() + + +def get_rw(request): + return RailwayStation.objects.first() + + +def get_client(request): + return Client.objects.all().first() + + +def get_user(request): + return CustomUser.objects.first() + + +def get_logistics(request): + pass + + +def get_product(request): + return Product.objects.first() + + +def get_current_date(): + # Сегодняшняя дата + return date.today() + + +def format_date_nomn_case(date_object): + # Приводим дату к именительному падежу + return morph.parse(date_object)[0].inflect({"nomn"}).word + + +def format_month_ru_locale(date_object): + # Форматируем месяц согласно русской локали + return bd.format_date(date_object, "MMMM", locale="ru_RU") + + +def get_formatted_date_agreement(): + # Форматируем текущую дату согласно русской локали + return bd.format_date(get_current_date(), "«d» MMMM y г.", locale="ru_RU") + + +def get_formatted_date_shipment(): + current_date = get_current_date() + next_month_date = current_date.replace(day=1) + timedelta(days=31) + raw_current_month = format_month_ru_locale(current_date) + raw_next_month = format_month_ru_locale(next_month_date) + current_month = format_date_nomn_case(raw_current_month) + next_month = format_date_nomn_case(raw_next_month) + if current_date.year == next_month_date.year: + return f"{current_month}-{next_month} {current_date.year} г." + next_month_date = current_date.replace(day=1) + timedelta(days=31) + raw_current_month = format_month_ru_locale(current_date) + raw_next_month = format_month_ru_locale(next_month_date) + current_month = format_date_nomn_case(raw_current_month) + next_month = format_date_nomn_case(raw_next_month) + if current_date.year == next_month_date.year: + return f"{current_month}-{next_month} {current_date.year} г." + else: + return f"{current_month} {current_date.year} г.-{next_month} {next_month_date.year} г." + + +def write_to_excel_auto(request): + user = get_user(request) + client = get_client(request) + product = get_product(request) + factory = get_factory(request) + + # Открытие файла шаблона + template_path = "makedoc/excel-templates/spec.xlsx" + wb = openpyxl.load_workbook(template_path) + ws = wb.active + + # Форматирование даты договора + formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") + + # Номер приложения + ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") + + # Номер договора + ws.cell( + row=2, + column=1, + value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", + ) + ws.cell(row=4, column=1, value=client.client_name) + ws.cell(row=6, column=6, value=get_formatted_date_agreement()) + + # Значение строки для стартовой подвижной ячейки + caret = 10 + + # Берем количество товаров из реквеста + goods_quantity = 3 + + # Наполняем таблицу товарами + for _ in range(goods_quantity): + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) + ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") + ws.cell(row=caret, column=4, value=product.package.package) + # Берем из реквеста (рефакторинг) + ws.cell(row=caret, column=5, value=20) + # Возможно применить скидку тут + ws.cell(row=caret, column=6, value=str(product.price)) + caret += 1 + + caret += 1 + + # Комбинат-грузоотправитель + # Берем из реквеста (рефакторинг) + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Грузоотправитель:") + ws.cell(row=caret, column=3, value=factory.full_name) + caret += 1 + + # Автоуслуги + # Проверка стоимости доставки в реквесте (рефакторинг) + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Автотранспортные услуги:") + ws.cell( + row=caret, + column=3, + value="не входят в стоимость товара" if 0 else "входят в стоимость товара", + ) + caret += 1 + + # Срок отгрузки + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Срок отгрузки:") + + ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) + caret += 2 + + # Право по дебиторской задолженности + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + + pdz = "▪Продавец имеет право не осуществлять отгрузку товара до полного погашения Покупателем \ +просроченной дебиторской задолженности." + ws.cell(row=caret, column=1, value=pdz) + caret += 1 + + # Юридическая информация + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + + contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих \ +одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ +подписания и является неотъемлемой частью договора № \ +{client.contract_number} от {formatted_contract_date}г." + ws.cell(row=caret, column=1, value=contract_option) + caret += 4 + + # Подписант продавца + ws.cell(row=caret, column=1, value="Генеральный директор") + caret += 1 + ws.cell(row=caret, column=1, value="ООО «Торговый дом «Оскольская мука»") + ws.cell(row=caret, column=6, value="С.А. Годизов") + caret += 8 + + # Подписант покупателя + ws.cell(row=caret, column=1, value=str(client.director_position)) + caret += 1 + ws.cell(row=caret, column=1, value=client.client_name) + # Нужно спарсить имя директора и вывести в сокращенном виде + ws.cell(row=caret, column=6, value=client.director_name) + + caret = 49 + # Контакты менеджера + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + ws.cell(row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}") + caret += 1 + + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + ws.cell( + row=caret, + column=1, + value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", + ) + + # Тут предлагаю тоже отрефакторить, сделать отдельную функцию для сохранения объекта + # Создать структуру каталогов + directory = os.path.join( + "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] + ) + os.makedirs(directory, exist_ok=True) + + # Сохранить файл + new_file_path = os.path.join( + directory, + f"auto_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx", + ) + wb.save(new_file_path) + wb.save(new_file_path) + + +def write_to_excel_rw(request): + user = get_user(request) + client = get_client(request) + product = get_product(request) + rw = get_rw(request) + factory = get_factory(request) + + # Открытие файла шаблона + template_path = "makedoc/excel-templates/spec.xlsx" + wb = openpyxl.load_workbook(template_path) + ws = wb.active + + # Форматирование даты договора + formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") + + # Номер приложения + ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") + + # Номер договора + ws.cell( + row=2, + column=1, + value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", + ) + ws.cell(row=4, column=1, value=client.client_name) + ws.cell(row=6, column=6, value=get_formatted_date_agreement()) + + # Значение строки для стартовой подвижной ячейки + caret = 10 + + # Берем количество товаров из реквеста + goods_quantity = 3 + + ws.cell(row=4, column=1, value=client.client_name) + ws.cell(row=6, column=6, value=get_formatted_date_agreement()) + + # Наполняем таблицу товарами + for _ in range(goods_quantity): + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) + ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") + ws.cell(row=caret, column=4, value=product.package.package) + # Берем из реквеста (рефакторинг) + ws.cell(row=caret, column=5, value=20) + # Возможно применить скидку тут + ws.cell(row=caret, column=6, value=str(product.price)) + caret += 1 + + caret += 1 + + ws.cell(row=caret, column=1, value="Поставка осуществляется:") + ws.cell(row=caret, column=3, value="ж/д транспортом") + + caret += 1 + + # Станция назначения + ws.cell(row=caret, column=1, value="Станция отправления:") + ws.cell(row=caret, column=3, value=rw.station_name) + + caret += 1 + + # Грузоотправитель + ws.cell(row=caret, column=1, value="Грузоотправитель:") + ws.cell(row=caret, column=3, value=factory.full_name) + + caret += 1 + + # Условия поставки + ws.cell(row=caret, column=1, value="Условия поставки") + ws.cell( + row=caret, + column=3, + value="франко-вагон станция отправления" if 0 else "франко-вагон станция назначения", + ) + + caret += 1 + + # Срок отгрузки + ws.cell(row=caret, column=1, value="Срок отгрузки:") + ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) + + caret += 2 + + # Отгрузочные реквизиты + ws.cell(row=caret, column=1, value="Отгрузочные реквизиты:") + + caret += 1 + + ws.cell(row=caret, column=1, value="Станция назначения:") + ws.cell(row=caret, column=3, value=client.railway_station.station_name) + + caret += 1 + + # Код станции + ws.cell(row=caret, column=1, value="Код станции:") + ws.cell(row=caret, column=3, value=client.railway_station.station_id) + + caret += 1 + + # Получатель + ws.cell(row=caret, column=1, value="Получатель:") + ws.cell(row=caret, column=3, value=client.receiver_name) + + caret += 1 + + # Код получателя + ws.cell(row=caret, column=1, value="Код получателя:") + ws.cell(row=caret, column=3, value=client.receiver_id) + + caret += 1 + + # ОКПО + ws.cell(row=caret, column=1, value="ОКПО:") + ws.cell(row=caret, column=3, value=client.receiver_okpo) + + caret += 1 + + # Адрес + ws.cell(row=caret, column=1, value="Адрес:") + ws.cell(row=caret, column=3, value=client.receiver_adress) + + caret += 2 + + contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих \ +одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ +подписания и является неотъемлемой частью договора № \ +{client.contract_number} от {formatted_contract_date}г." + ws.cell(row=caret, column=1, value=contract_option) + caret += 4 + + # Подписант продавца + ws.cell(row=caret, column=1, value="Генеральный директор") + caret += 1 + ws.cell(row=caret, column=1, value="ООО «Торговый дом «Оскольская мука»") + ws.cell(row=caret, column=6, value="С.А. Годизов") + caret += 8 + + # Подписант покупателя + ws.cell(row=caret, column=1, value=str(client.director_position)) + caret += 1 + ws.cell(row=caret, column=1, value=client.client_name) + # Нужно спарсить имя директора и вывести в сокращенном виде + ws.cell(row=caret, column=6, value=client.director_name) + + caret = 49 + # Контакты менеджера + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + ws.cell(row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}") + caret += 1 + + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) + ws.cell( + row=caret, + column=1, + value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", + ) + + # Создать структуру каталогов + directory = os.path.join( + "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] + ) + os.makedirs(directory, exist_ok=True) + + # Сохранить файл + new_file_path = os.path.join( + directory, f"rw_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx" + ) + wb.save(new_file_path) + + +def write_to_excel_sluzebnyi(request): + user = get_user(request) + city = get_region(request) + client = get_client(request) + + # Принимаем с фронта макс размер скидки (пока хардкод) + discount = 15 + + # Открытие файла шаблона + template_path = "makedoc/excel-templates/sluz.xlsx" + wb = openpyxl.load_workbook(template_path) + ws = wb.active + + # Записка + ws.cell(row=15, column=1, value=f"{get_formatted_date_agreement()} № 12/2.2/23/3-") + text = f"В целях увеличения объема продаж на территории {city.region} прошу Вашего \ +согласования применить скидку для контрагента {client.client_name} (г. {city.city}) до {discount}%\ +в {get_formatted_date_shipment} на продукцию следующего ассортимента: " + ws.cell(row=19, column=1, value=text) + + # Создать структуру каталогов + directory = os.path.join( + "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] + ) + os.makedirs(directory, exist_ok=True) + + # Сохранить файл + new_file_path = os.path.join( + directory, + f"sluz_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx", + ) + wb.save(new_file_path) diff --git a/makedoc/views.py b/makedoc/views.py index 6e43a99..bc9e96f 100644 --- a/makedoc/views.py +++ b/makedoc/views.py @@ -1,11 +1,13 @@ from django.http import HttpResponse -from .services import write_to_excel_auto, write_to_excel_rw, write_to_excel_sluzebnyi +from makedoc.services import Documents def create_docs(request): - write_to_excel_auto(request) - write_to_excel_rw(request) - # Если применяется скидка, пишем служебную записку - write_to_excel_sluzebnyi(request) if 0 else None + docs = Documents() + docs.update_documents(["auto", "rw", "sluz", "sopr_list"]) + + if docs.auto: + docs.form_auto_document(request) + return HttpResponse("Документы сохранены") From a8da9045fefd386ffd93041b6e1cea388be74d0e Mon Sep 17 00:00:00 2001 From: leeroymk Date: Mon, 3 Jun 2024 10:06:25 +0300 Subject: [PATCH 07/11] rw makedoc --- .gitignore | 3 ++ makedoc/services.py | 110 ++++++++++++++++++++++++++++++++++++++++++-- makedoc/views.py | 2 + 3 files changed, 112 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 317aed7..67e7e3a 100644 --- a/.gitignore +++ b/.gitignore @@ -167,3 +167,6 @@ cython_debug/ .vscode/ *.xlsx + +# Temporary documents +makedoc/tempdoc/ diff --git a/makedoc/services.py b/makedoc/services.py index 0ab8d72..1fcdbff 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -8,6 +8,7 @@ from clients.models import Client from goods.models import Factory, Product +from logistics.models import RailwayStation from users.models import CustomUser morph = pymorphy3.MorphAnalyzer() @@ -60,6 +61,7 @@ def update_documents(self, documents_list): self.sopr_list = 1 def form_auto_document(self, request): + self.docname = "auto" try: user = self.get_user(request) client = self.get_client(request) @@ -178,7 +180,7 @@ def fill_signatures(self, ws, client): self.caret_signatures = caret + 11 def fill_manager_contact(self, ws, user): - caret = 49 + caret = 59 ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) manager = ws.cell( row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}" @@ -194,12 +196,16 @@ def fill_manager_contact(self, ws, user): def save_workbook(self, wb, user): directory = os.path.join( - "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] + "makedoc", + "tempdoc", + get_current_date().strftime("%d.%m.%Y"), + user.full_name.split()[0], ) os.makedirs(directory, exist_ok=True) new_file_path = os.path.join( directory, - f"auto_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%м.%Y')}.xlsx", + f"{self.docname}_{user.full_name.split()[0]}_{get_current_date(). + strftime('%d.%m.%Y')}.xlsx", ) wb.save(new_file_path) @@ -237,3 +243,101 @@ def get_factory(self, request): return Factory.objects.first() except Factory.DoesNotExist: raise Exception("Factory not found") + + def get_rw(self, request): + try: + return RailwayStation.objects.all().first() + except RailwayStation.DoesNotExist: + raise Exception("Railway station not found") + + def form_rw_document(self, request): + self.docname = "rw" + try: + user = self.get_user(request) + client = self.get_client(request) + product = self.get_product(request) + rw = self.get_rw(request) + factory = self.get_factory(request) + except Exception as e: + return f"Error fetching data: {e}" + + template_path = "makedoc/excel-templates/spec.xlsx" + wb = openpyxl.load_workbook(template_path) + ws = wb.active + + self.fill_contract_info(ws, client) + self.fill_product_info(ws, product) + self.fill_factory_info(ws, factory) + self.fill_rw_services(ws, rw, factory, client) + self.fill_debt_info(ws) + self.fill_legal_info(ws, client) + self.fill_signatures(ws, client) + self.fill_manager_contact(ws, user) + + self.apply_styles(ws) + + self.save_workbook(wb, user) + + def fill_rw_services(self, ws, rw, factory, client): + caret = self.caret_factory + ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) + ws.cell(row=caret, column=1, value="Поставка осуществляется:") + ws.cell(row=caret, column=3, value="ж/д транспортом") + caret += 1 + + # Станция назначения + ws.cell(row=caret, column=1, value="Станция отправления:") + ws.cell(row=caret, column=3, value=rw.station_name) + caret += 1 + + # Грузоотправитель + ws.cell(row=caret, column=1, value="Грузоотправитель:") + ws.cell(row=caret, column=3, value=factory.full_name) + caret += 1 + + # Условия поставки + ws.cell(row=caret, column=1, value="Условия поставки") + ws.cell( + row=caret, + column=3, + value="франко-вагон станция отправления" if 0 else "франко-вагон станция назначения", + ) + caret += 2 + + # Отгрузочные реквизиты + ws.cell(row=caret, column=1, value="Отгрузочные реквизиты:") + caret += 1 + + ws.cell(row=caret, column=1, value="Станция назначения:") + ws.cell(row=caret, column=3, value=client.railway_station.station_name) + caret += 1 + + # Код станции + ws.cell(row=caret, column=1, value="Код станции:") + station_code_value = ws.cell(row=caret, column=3, value=client.railway_station.station_id) + station_code_value.alignment = Alignment(horizontal="left") + caret += 1 + + # Получатель + ws.cell(row=caret, column=1, value="Получатель:") + ws.cell(row=caret, column=3, value=client.receiver_name) + caret += 1 + + # Код получателя + ws.cell(row=caret, column=1, value="Код получателя:") + receiver_code_value = ws.cell(row=caret, column=3, value=client.receiver_id) + receiver_code_value.alignment = Alignment(horizontal="left") + caret += 1 + + # ОКПО + ws.cell(row=caret, column=1, value="ОКПО:") + okpo_value = ws.cell(row=caret, column=3, value=client.receiver_okpo) + okpo_value.alignment = Alignment(horizontal="left") + caret += 1 + + # Адрес + ws.cell(row=caret, column=1, value="Адрес:") + ws.cell(row=caret, column=3, value=client.receiver_adress) + caret += 1 + + self.caret_services = caret + 1 diff --git a/makedoc/views.py b/makedoc/views.py index bc9e96f..9fc0058 100644 --- a/makedoc/views.py +++ b/makedoc/views.py @@ -9,5 +9,7 @@ def create_docs(request): if docs.auto: docs.form_auto_document(request) + if docs.rw: + docs.form_rw_document(request) return HttpResponse("Документы сохранены") From ce99367f890e0a48c81b7afc3248ccf574cd03bf Mon Sep 17 00:00:00 2001 From: leeroymk Date: Tue, 4 Jun 2024 17:00:05 +0300 Subject: [PATCH 08/11] make service note added --- makedoc/services.py | 63 ++++++++++++++++++++++++++++++++++++--------- makedoc/views.py | 5 ++-- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/makedoc/services.py b/makedoc/services.py index 1fcdbff..aa63fb7 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -8,7 +8,7 @@ from clients.models import Client from goods.models import Factory, Product -from logistics.models import RailwayStation +from logistics.models import City, RailwayStation from users.models import CustomUser morph = pymorphy3.MorphAnalyzer() @@ -18,8 +18,9 @@ def get_current_date(): return date.today() -def format_date_nomn_case(date_object): - return morph.parse(str(date_object))[0].inflect({"nomn"}).word +def format_date_case(date_object, case): + # case - падеж + return morph.parse(str(date_object))[0].inflect({case}).word def format_month_ru_locale(date_object): @@ -30,13 +31,13 @@ def get_formatted_date_agreement(): return bd.format_date(get_current_date(), "«d» MMMM y г.", locale="ru_RU") -def get_formatted_date_shipment(): +def get_formatted_date_shipment(case): current_date = get_current_date() next_month_date = (current_date.replace(day=1) + timedelta(days=31)).replace(day=1) raw_current_month = format_month_ru_locale(current_date) raw_next_month = format_month_ru_locale(next_month_date) - current_month = format_date_nomn_case(raw_current_month) - next_month = format_date_nomn_case(raw_next_month) + current_month = format_date_case(raw_current_month, case) + next_month = format_date_case(raw_next_month, case) if current_date.year == next_month_date.year: return f"{current_month}-{next_month} {current_date.year} г." else: @@ -47,7 +48,7 @@ class Documents: def __init__(self): self.auto = 0 self.rw = 0 - self.sluz = 0 + self.service_note = 0 self.sopr_list = 0 def update_documents(self, documents_list): @@ -55,8 +56,8 @@ def update_documents(self, documents_list): self.auto = 1 if "rw" in documents_list: self.rw = 1 - if "sluz" in documents_list: - self.sluz = 1 + if "service_note" in documents_list: + self.service_note = 1 if "sopr_list" in documents_list: self.sopr_list = 1 @@ -147,7 +148,7 @@ def fill_debt_info(self, ws): caret = self.caret_services ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) ws.cell(row=caret, column=1, value="Срок отгрузки:") - ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) + ws.cell(row=caret, column=3, value=get_formatted_date_shipment("nomn")) ws.merge_cells(start_row=caret + 1, start_column=1, end_row=caret + 1, end_column=6) pdz = "▪Продавец имеет право не осуществлять отгрузку товара до полного погашения \ Покупателем просроченной дебиторской задолженности." @@ -204,8 +205,8 @@ def save_workbook(self, wb, user): os.makedirs(directory, exist_ok=True) new_file_path = os.path.join( directory, - f"{self.docname}_{user.full_name.split()[0]}_{get_current_date(). - strftime('%d.%m.%Y')}.xlsx", + f"{self.docname}_{user.full_name.split()[0]}_\ +{get_current_date().strftime('%d.%m.%Y')}.xlsx", ) wb.save(new_file_path) @@ -250,6 +251,16 @@ def get_rw(self, request): except RailwayStation.DoesNotExist: raise Exception("Railway station not found") + def get_discount(self, request): + # Принимаем с фронта макс размер скидки (пока хардкод) + return 15 + + def get_city(self, request): + try: + return City.objects.all().first() + except City.DoesNotExist: + raise Exception("City not found") + def form_rw_document(self, request): self.docname = "rw" try: @@ -341,3 +352,31 @@ def fill_rw_services(self, ws, rw, factory, client): caret += 1 self.caret_services = caret + 1 + + def form_service_note(self, request): + self.docname = "service_note" + try: + client = self.get_client(request) + discount = self.get_discount(request) + city = self.get_city(request) + user = self.get_user(request) + except Exception as e: + return f"Error fetching data: {e}" + + # Открытие файла шаблона + template_path = "makedoc/excel-templates/service_note.xlsx" + wb = openpyxl.load_workbook(template_path, keep_vba=True) + ws = wb.active + + self.fill_service_note(ws, client, discount, city) + + self.apply_styles(ws) + + self.save_workbook(wb, user) + + def fill_service_note(self, ws, client, discount, city): + ws.cell(row=15, column=1, value=f"{get_formatted_date_agreement()} № 12/2.2/23/3-") + text = f" В целях увеличения объема продаж на территории {city.region} прошу Вашего \ +согласования применить скидку для контрагента {client.client_name} (г. {city.city}) до {discount}%\ + в {get_formatted_date_shipment("loct")} на продукцию следующего ассортимента: " + ws.cell(row=19, column=1, value=text) diff --git a/makedoc/views.py b/makedoc/views.py index 9fc0058..cebf0c6 100644 --- a/makedoc/views.py +++ b/makedoc/views.py @@ -5,11 +5,12 @@ def create_docs(request): docs = Documents() - docs.update_documents(["auto", "rw", "sluz", "sopr_list"]) - + docs.update_documents(["auto", "rw", "service_note", "sopr_list"]) if docs.auto: docs.form_auto_document(request) if docs.rw: docs.form_rw_document(request) + if docs.service_note: + docs.form_service_note(request) return HttpResponse("Документы сохранены") From f6ff7a63311f0ff2d4ff7a878759292b5087ed76 Mon Sep 17 00:00:00 2001 From: leeroymk Date: Tue, 4 Jun 2024 23:16:16 +0300 Subject: [PATCH 09/11] service note done --- makedoc/services.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/makedoc/services.py b/makedoc/services.py index aa63fb7..0f90f79 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -76,7 +76,7 @@ def form_auto_document(self, request): ws = wb.active self.fill_contract_info(ws, client) - self.fill_product_info(ws, product) + self.fill_product_info(ws, product, 10) self.fill_factory_info(ws, factory) self.fill_auto_services(ws) self.fill_debt_info(ws) @@ -101,8 +101,7 @@ def fill_contract_info(self, ws, client): ws.cell(row=4, column=1, value=client.client_name) ws.cell(row=6, column=6, value=get_formatted_date_agreement()) - def fill_product_info(self, ws, product): - caret = 10 + def fill_product_info(self, ws, product, caret): goods_quantity = 7 thin_border = Border( left=Side(style="thin"), @@ -277,7 +276,7 @@ def form_rw_document(self, request): ws = wb.active self.fill_contract_info(ws, client) - self.fill_product_info(ws, product) + self.fill_product_info(ws, product, 10) self.fill_factory_info(ws, factory) self.fill_rw_services(ws, rw, factory, client) self.fill_debt_info(ws) @@ -360,6 +359,7 @@ def form_service_note(self, request): discount = self.get_discount(request) city = self.get_city(request) user = self.get_user(request) + product = self.get_product(request) except Exception as e: return f"Error fetching data: {e}" @@ -368,13 +368,13 @@ def form_service_note(self, request): wb = openpyxl.load_workbook(template_path, keep_vba=True) ws = wb.active - self.fill_service_note(ws, client, discount, city) - + self.fill_text_note(ws, client, discount, city) + self.fill_product_info(ws, product, 22) self.apply_styles(ws) self.save_workbook(wb, user) - def fill_service_note(self, ws, client, discount, city): + def fill_text_note(self, ws, client, discount, city): ws.cell(row=15, column=1, value=f"{get_formatted_date_agreement()} № 12/2.2/23/3-") text = f" В целях увеличения объема продаж на территории {city.region} прошу Вашего \ согласования применить скидку для контрагента {client.client_name} (г. {city.city}) до {discount}%\ From b5e1a226161a7ca75bd500c7f7862673844b3df9 Mon Sep 17 00:00:00 2001 From: leeroymk Date: Wed, 5 Jun 2024 20:09:35 +0300 Subject: [PATCH 10/11] transport sheet done --- makedoc/services.py | 85 +++++--- makedoc/services_old.py | 415 ---------------------------------------- makedoc/views.py | 4 +- 3 files changed, 66 insertions(+), 438 deletions(-) delete mode 100644 makedoc/services_old.py diff --git a/makedoc/services.py b/makedoc/services.py index 0f90f79..c40214e 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -49,7 +49,7 @@ def __init__(self): self.auto = 0 self.rw = 0 self.service_note = 0 - self.sopr_list = 0 + self.transport_sheet = 0 def update_documents(self, documents_list): if "auto" in documents_list: @@ -58,8 +58,8 @@ def update_documents(self, documents_list): self.rw = 1 if "service_note" in documents_list: self.service_note = 1 - if "sopr_list" in documents_list: - self.sopr_list = 1 + if "transport_sheet" in documents_list: + self.transport_sheet = 1 def form_auto_document(self, request): self.docname = "auto" @@ -68,6 +68,7 @@ def form_auto_document(self, request): client = self.get_client(request) product = self.get_product(request) factory = self.get_factory(request) + logistics = self.get_logistics(request) except Exception as e: return f"Error fetching data: {e}" @@ -76,9 +77,9 @@ def form_auto_document(self, request): ws = wb.active self.fill_contract_info(ws, client) - self.fill_product_info(ws, product, 10) + self.fill_product_info(ws, product, logistics, 10) self.fill_factory_info(ws, factory) - self.fill_auto_services(ws) + self.fill_auto_services(ws, logistics) self.fill_debt_info(ws) self.fill_legal_info(ws, client) self.fill_signatures(ws, client) @@ -92,7 +93,6 @@ def fill_contract_info(self, ws, client): formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") title = ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") title.font = Font(bold=True) - ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") ws.cell( row=2, column=1, @@ -101,7 +101,7 @@ def fill_contract_info(self, ws, client): ws.cell(row=4, column=1, value=client.client_name) ws.cell(row=6, column=6, value=get_formatted_date_agreement()) - def fill_product_info(self, ws, product, caret): + def fill_product_info(self, ws, product, logistics, caret): goods_quantity = 7 thin_border = Border( left=Side(style="thin"), @@ -116,8 +116,10 @@ def fill_product_info(self, ws, product, caret): ws.cell(row=caret, column=4, value=product.package.package) ws.cell(row=caret, column=5, value=20) ws.cell(row=caret, column=6, value=str(product.price)) + ws.cell(row=caret, column=7, value=logistics) + ws.cell(row=caret, column=8, value=product.price - logistics) - for col_num in range(1, 7): + for col_num in range(1, 9): cell = ws.cell(row=caret, column=col_num) cell.border = thin_border if cell.column > 2: @@ -132,14 +134,16 @@ def fill_factory_info(self, ws, factory): ws.cell(row=caret, column=3, value=factory.full_name) self.caret_factory = caret + 1 - def fill_auto_services(self, ws): + def fill_auto_services(self, ws, logistics): caret = self.caret_factory ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) ws.cell(row=caret, column=1, value="Автотранспортные услуги:") ws.cell( row=caret, column=3, - value="не входят в стоимость товара" if 0 else "входят в стоимость товара", + value="не входят в стоимость товара" + if logistics != 0 + else "входят в стоимость товара", ) self.caret_services = caret + 1 @@ -251,7 +255,6 @@ def get_rw(self, request): raise Exception("Railway station not found") def get_discount(self, request): - # Принимаем с фронта макс размер скидки (пока хардкод) return 15 def get_city(self, request): @@ -260,6 +263,9 @@ def get_city(self, request): except City.DoesNotExist: raise Exception("City not found") + def get_logistics(self, request): + return 2500 + def form_rw_document(self, request): self.docname = "rw" try: @@ -268,6 +274,7 @@ def form_rw_document(self, request): product = self.get_product(request) rw = self.get_rw(request) factory = self.get_factory(request) + logistics = self.get_logistics(request) except Exception as e: return f"Error fetching data: {e}" @@ -276,7 +283,7 @@ def form_rw_document(self, request): ws = wb.active self.fill_contract_info(ws, client) - self.fill_product_info(ws, product, 10) + self.fill_product_info(ws, product, logistics, 10) self.fill_factory_info(ws, factory) self.fill_rw_services(ws, rw, factory, client) self.fill_debt_info(ws) @@ -295,17 +302,14 @@ def fill_rw_services(self, ws, rw, factory, client): ws.cell(row=caret, column=3, value="ж/д транспортом") caret += 1 - # Станция назначения ws.cell(row=caret, column=1, value="Станция отправления:") ws.cell(row=caret, column=3, value=rw.station_name) caret += 1 - # Грузоотправитель ws.cell(row=caret, column=1, value="Грузоотправитель:") ws.cell(row=caret, column=3, value=factory.full_name) caret += 1 - # Условия поставки ws.cell(row=caret, column=1, value="Условия поставки") ws.cell( row=caret, @@ -314,7 +318,6 @@ def fill_rw_services(self, ws, rw, factory, client): ) caret += 2 - # Отгрузочные реквизиты ws.cell(row=caret, column=1, value="Отгрузочные реквизиты:") caret += 1 @@ -322,30 +325,25 @@ def fill_rw_services(self, ws, rw, factory, client): ws.cell(row=caret, column=3, value=client.railway_station.station_name) caret += 1 - # Код станции ws.cell(row=caret, column=1, value="Код станции:") station_code_value = ws.cell(row=caret, column=3, value=client.railway_station.station_id) station_code_value.alignment = Alignment(horizontal="left") caret += 1 - # Получатель ws.cell(row=caret, column=1, value="Получатель:") ws.cell(row=caret, column=3, value=client.receiver_name) caret += 1 - # Код получателя ws.cell(row=caret, column=1, value="Код получателя:") receiver_code_value = ws.cell(row=caret, column=3, value=client.receiver_id) receiver_code_value.alignment = Alignment(horizontal="left") caret += 1 - # ОКПО ws.cell(row=caret, column=1, value="ОКПО:") okpo_value = ws.cell(row=caret, column=3, value=client.receiver_okpo) okpo_value.alignment = Alignment(horizontal="left") caret += 1 - # Адрес ws.cell(row=caret, column=1, value="Адрес:") ws.cell(row=caret, column=3, value=client.receiver_adress) caret += 1 @@ -360,6 +358,7 @@ def form_service_note(self, request): city = self.get_city(request) user = self.get_user(request) product = self.get_product(request) + logistics = self.get_logistics(request) except Exception as e: return f"Error fetching data: {e}" @@ -369,7 +368,7 @@ def form_service_note(self, request): ws = wb.active self.fill_text_note(ws, client, discount, city) - self.fill_product_info(ws, product, 22) + self.fill_product_info(ws, product, logistics, 22) self.apply_styles(ws) self.save_workbook(wb, user) @@ -380,3 +379,45 @@ def fill_text_note(self, ws, client, discount, city): согласования применить скидку для контрагента {client.client_name} (г. {city.city}) до {discount}%\ в {get_formatted_date_shipment("loct")} на продукцию следующего ассортимента: " ws.cell(row=19, column=1, value=text) + + def form_transport_sheet(self, request): + self.docname = "transport_sheet" + try: + user = self.get_user(request) + product = self.get_product(request) + client = self.get_client(request) + logistics = self.get_logistics(request) + factory = self.get_factory(request) + except Exception as e: + return f"Error fetching data: {e}" + + template_path = "makedoc/excel-templates/transport_sheet.xlsx" + wb = openpyxl.load_workbook(template_path, keep_vba=True) + ws = wb.active + + self.fill_contract_info_transport_sheet(ws, client) + self.fill_product_info(ws, product, logistics, 11) + + self.fill_factory_info(ws, factory) + self.fill_auto_services(ws, logistics) + self.fill_debt_info(ws) + self.fill_legal_info(ws, client) + self.fill_signatures(ws, client) + self.fill_manager_contact(ws, user) + + self.apply_styles(ws) + + self.save_workbook(wb, user) + + def fill_contract_info_transport_sheet(self, ws, client): + formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") + ws.cell(row=1, column=1, value="СОПРОВОДИТЕЛЬНЫЙ ЛИСТ к") + title = ws.cell(row=2, column=1, value=f"Приложению № {client.last_application_number}") + title.font = Font(bold=True) + ws.cell( + row=3, + column=1, + value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", + ) + ws.cell(row=5, column=1, value=client.client_name) + ws.cell(row=7, column=8, value=get_formatted_date_agreement()) diff --git a/makedoc/services_old.py b/makedoc/services_old.py deleted file mode 100644 index d62b6e7..0000000 --- a/makedoc/services_old.py +++ /dev/null @@ -1,415 +0,0 @@ -import os -from datetime import date, timedelta - -import babel.dates as bd -import openpyxl -import pymorphy3 - -from clients.models import Client -from goods.models import Factory, Product -from logistics.models import City, RailwayStation -from users.models import CustomUser - -morph = pymorphy3.MorphAnalyzer() - - -def get_region(request): - return City.objects.first() - - -def get_factory(request): - return Factory.objects.first() - - -def get_rw(request): - return RailwayStation.objects.first() - - -def get_client(request): - return Client.objects.all().first() - - -def get_user(request): - return CustomUser.objects.first() - - -def get_logistics(request): - pass - - -def get_product(request): - return Product.objects.first() - - -def get_current_date(): - # Сегодняшняя дата - return date.today() - - -def format_date_nomn_case(date_object): - # Приводим дату к именительному падежу - return morph.parse(date_object)[0].inflect({"nomn"}).word - - -def format_month_ru_locale(date_object): - # Форматируем месяц согласно русской локали - return bd.format_date(date_object, "MMMM", locale="ru_RU") - - -def get_formatted_date_agreement(): - # Форматируем текущую дату согласно русской локали - return bd.format_date(get_current_date(), "«d» MMMM y г.", locale="ru_RU") - - -def get_formatted_date_shipment(): - current_date = get_current_date() - next_month_date = current_date.replace(day=1) + timedelta(days=31) - raw_current_month = format_month_ru_locale(current_date) - raw_next_month = format_month_ru_locale(next_month_date) - current_month = format_date_nomn_case(raw_current_month) - next_month = format_date_nomn_case(raw_next_month) - if current_date.year == next_month_date.year: - return f"{current_month}-{next_month} {current_date.year} г." - next_month_date = current_date.replace(day=1) + timedelta(days=31) - raw_current_month = format_month_ru_locale(current_date) - raw_next_month = format_month_ru_locale(next_month_date) - current_month = format_date_nomn_case(raw_current_month) - next_month = format_date_nomn_case(raw_next_month) - if current_date.year == next_month_date.year: - return f"{current_month}-{next_month} {current_date.year} г." - else: - return f"{current_month} {current_date.year} г.-{next_month} {next_month_date.year} г." - - -def write_to_excel_auto(request): - user = get_user(request) - client = get_client(request) - product = get_product(request) - factory = get_factory(request) - - # Открытие файла шаблона - template_path = "makedoc/excel-templates/spec.xlsx" - wb = openpyxl.load_workbook(template_path) - ws = wb.active - - # Форматирование даты договора - formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") - - # Номер приложения - ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") - - # Номер договора - ws.cell( - row=2, - column=1, - value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", - ) - ws.cell(row=4, column=1, value=client.client_name) - ws.cell(row=6, column=6, value=get_formatted_date_agreement()) - - # Значение строки для стартовой подвижной ячейки - caret = 10 - - # Берем количество товаров из реквеста - goods_quantity = 3 - - # Наполняем таблицу товарами - for _ in range(goods_quantity): - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) - ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") - ws.cell(row=caret, column=4, value=product.package.package) - # Берем из реквеста (рефакторинг) - ws.cell(row=caret, column=5, value=20) - # Возможно применить скидку тут - ws.cell(row=caret, column=6, value=str(product.price)) - caret += 1 - - caret += 1 - - # Комбинат-грузоотправитель - # Берем из реквеста (рефакторинг) - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) - ws.cell(row=caret, column=1, value="Грузоотправитель:") - ws.cell(row=caret, column=3, value=factory.full_name) - caret += 1 - - # Автоуслуги - # Проверка стоимости доставки в реквесте (рефакторинг) - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) - ws.cell(row=caret, column=1, value="Автотранспортные услуги:") - ws.cell( - row=caret, - column=3, - value="не входят в стоимость товара" if 0 else "входят в стоимость товара", - ) - caret += 1 - - # Срок отгрузки - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) - ws.cell(row=caret, column=1, value="Срок отгрузки:") - - ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) - caret += 2 - - # Право по дебиторской задолженности - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - - pdz = "▪Продавец имеет право не осуществлять отгрузку товара до полного погашения Покупателем \ -просроченной дебиторской задолженности." - ws.cell(row=caret, column=1, value=pdz) - caret += 1 - - # Юридическая информация - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - - contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих \ -одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ -подписания и является неотъемлемой частью договора № \ -{client.contract_number} от {formatted_contract_date}г." - ws.cell(row=caret, column=1, value=contract_option) - caret += 4 - - # Подписант продавца - ws.cell(row=caret, column=1, value="Генеральный директор") - caret += 1 - ws.cell(row=caret, column=1, value="ООО «Торговый дом «Оскольская мука»") - ws.cell(row=caret, column=6, value="С.А. Годизов") - caret += 8 - - # Подписант покупателя - ws.cell(row=caret, column=1, value=str(client.director_position)) - caret += 1 - ws.cell(row=caret, column=1, value=client.client_name) - # Нужно спарсить имя директора и вывести в сокращенном виде - ws.cell(row=caret, column=6, value=client.director_name) - - caret = 49 - # Контакты менеджера - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - ws.cell(row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}") - caret += 1 - - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - ws.cell( - row=caret, - column=1, - value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", - ) - - # Тут предлагаю тоже отрефакторить, сделать отдельную функцию для сохранения объекта - # Создать структуру каталогов - directory = os.path.join( - "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] - ) - os.makedirs(directory, exist_ok=True) - - # Сохранить файл - new_file_path = os.path.join( - directory, - f"auto_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx", - ) - wb.save(new_file_path) - wb.save(new_file_path) - - -def write_to_excel_rw(request): - user = get_user(request) - client = get_client(request) - product = get_product(request) - rw = get_rw(request) - factory = get_factory(request) - - # Открытие файла шаблона - template_path = "makedoc/excel-templates/spec.xlsx" - wb = openpyxl.load_workbook(template_path) - ws = wb.active - - # Форматирование даты договора - formatted_contract_date = client.contract_date.strftime("%d.%m.%Y") - - # Номер приложения - ws.cell(row=1, column=1, value=f"Приложение № {client.last_application_number}") - - # Номер договора - ws.cell( - row=2, - column=1, - value=f"к договору поставки № {client.contract_number} от {formatted_contract_date}г.", - ) - ws.cell(row=4, column=1, value=client.client_name) - ws.cell(row=6, column=6, value=get_formatted_date_agreement()) - - # Значение строки для стартовой подвижной ячейки - caret = 10 - - # Берем количество товаров из реквеста - goods_quantity = 3 - - ws.cell(row=4, column=1, value=client.client_name) - ws.cell(row=6, column=6, value=get_formatted_date_agreement()) - - # Наполняем таблицу товарами - for _ in range(goods_quantity): - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=3) - ws.cell(row=caret, column=1, value=f"{str(product.flour_name)} {product.brand}") - ws.cell(row=caret, column=4, value=product.package.package) - # Берем из реквеста (рефакторинг) - ws.cell(row=caret, column=5, value=20) - # Возможно применить скидку тут - ws.cell(row=caret, column=6, value=str(product.price)) - caret += 1 - - caret += 1 - - ws.cell(row=caret, column=1, value="Поставка осуществляется:") - ws.cell(row=caret, column=3, value="ж/д транспортом") - - caret += 1 - - # Станция назначения - ws.cell(row=caret, column=1, value="Станция отправления:") - ws.cell(row=caret, column=3, value=rw.station_name) - - caret += 1 - - # Грузоотправитель - ws.cell(row=caret, column=1, value="Грузоотправитель:") - ws.cell(row=caret, column=3, value=factory.full_name) - - caret += 1 - - # Условия поставки - ws.cell(row=caret, column=1, value="Условия поставки") - ws.cell( - row=caret, - column=3, - value="франко-вагон станция отправления" if 0 else "франко-вагон станция назначения", - ) - - caret += 1 - - # Срок отгрузки - ws.cell(row=caret, column=1, value="Срок отгрузки:") - ws.cell(row=caret, column=3, value=get_formatted_date_shipment()) - - caret += 2 - - # Отгрузочные реквизиты - ws.cell(row=caret, column=1, value="Отгрузочные реквизиты:") - - caret += 1 - - ws.cell(row=caret, column=1, value="Станция назначения:") - ws.cell(row=caret, column=3, value=client.railway_station.station_name) - - caret += 1 - - # Код станции - ws.cell(row=caret, column=1, value="Код станции:") - ws.cell(row=caret, column=3, value=client.railway_station.station_id) - - caret += 1 - - # Получатель - ws.cell(row=caret, column=1, value="Получатель:") - ws.cell(row=caret, column=3, value=client.receiver_name) - - caret += 1 - - # Код получателя - ws.cell(row=caret, column=1, value="Код получателя:") - ws.cell(row=caret, column=3, value=client.receiver_id) - - caret += 1 - - # ОКПО - ws.cell(row=caret, column=1, value="ОКПО:") - ws.cell(row=caret, column=3, value=client.receiver_okpo) - - caret += 1 - - # Адрес - ws.cell(row=caret, column=1, value="Адрес:") - ws.cell(row=caret, column=3, value=client.receiver_adress) - - caret += 2 - - contract_option = f"▪Настоящее приложение составлено и подписано в двух экземплярах, имеющих \ -одинаковую юридическую силу, по одному для каждой из сторон, вступает в силу с момента \ -подписания и является неотъемлемой частью договора № \ -{client.contract_number} от {formatted_contract_date}г." - ws.cell(row=caret, column=1, value=contract_option) - caret += 4 - - # Подписант продавца - ws.cell(row=caret, column=1, value="Генеральный директор") - caret += 1 - ws.cell(row=caret, column=1, value="ООО «Торговый дом «Оскольская мука»") - ws.cell(row=caret, column=6, value="С.А. Годизов") - caret += 8 - - # Подписант покупателя - ws.cell(row=caret, column=1, value=str(client.director_position)) - caret += 1 - ws.cell(row=caret, column=1, value=client.client_name) - # Нужно спарсить имя директора и вывести в сокращенном виде - ws.cell(row=caret, column=6, value=client.director_name) - - caret = 49 - # Контакты менеджера - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - ws.cell(row=caret, column=1, value=f"Ваш персональный менеджер: {user.full_name}") - caret += 1 - - ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=6) - ws.cell( - row=caret, - column=1, - value=f"Тел. {user.phone_number_personal}, моб. {user.phone_number_work}", - ) - - # Создать структуру каталогов - directory = os.path.join( - "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] - ) - os.makedirs(directory, exist_ok=True) - - # Сохранить файл - new_file_path = os.path.join( - directory, f"rw_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx" - ) - wb.save(new_file_path) - - -def write_to_excel_sluzebnyi(request): - user = get_user(request) - city = get_region(request) - client = get_client(request) - - # Принимаем с фронта макс размер скидки (пока хардкод) - discount = 15 - - # Открытие файла шаблона - template_path = "makedoc/excel-templates/sluz.xlsx" - wb = openpyxl.load_workbook(template_path) - ws = wb.active - - # Записка - ws.cell(row=15, column=1, value=f"{get_formatted_date_agreement()} № 12/2.2/23/3-") - text = f"В целях увеличения объема продаж на территории {city.region} прошу Вашего \ -согласования применить скидку для контрагента {client.client_name} (г. {city.city}) до {discount}%\ -в {get_formatted_date_shipment} на продукцию следующего ассортимента: " - ws.cell(row=19, column=1, value=text) - - # Создать структуру каталогов - directory = os.path.join( - "makedoc", get_current_date().strftime("%d.%m.%Y"), user.full_name.split()[0] - ) - os.makedirs(directory, exist_ok=True) - - # Сохранить файл - new_file_path = os.path.join( - directory, - f"sluz_{user.full_name.split()[0]}_{get_current_date().strftime('%d.%m.%Y')}.xlsx", - ) - wb.save(new_file_path) diff --git a/makedoc/views.py b/makedoc/views.py index cebf0c6..8c0e19f 100644 --- a/makedoc/views.py +++ b/makedoc/views.py @@ -5,12 +5,14 @@ def create_docs(request): docs = Documents() - docs.update_documents(["auto", "rw", "service_note", "sopr_list"]) + docs.update_documents(["auto", "rw", "service_note", "transport_sheet"]) if docs.auto: docs.form_auto_document(request) if docs.rw: docs.form_rw_document(request) if docs.service_note: docs.form_service_note(request) + if docs.transport_sheet: + docs.form_transport_sheet(request) return HttpResponse("Документы сохранены") From ba9373c109151d99f8e810d366933c1d74774304 Mon Sep 17 00:00:00 2001 From: leeroymk Date: Wed, 5 Jun 2024 20:34:33 +0300 Subject: [PATCH 11/11] styling commas --- makedoc/services.py | 10 ++++++---- makedoc/tests/conftest.py | 5 +++-- makedoc/tests/test_views_makedoc.py | 24 ++++++++++++------------ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/makedoc/services.py b/makedoc/services.py index c40214e..4d79f3a 100644 --- a/makedoc/services.py +++ b/makedoc/services.py @@ -285,7 +285,7 @@ def form_rw_document(self, request): self.fill_contract_info(ws, client) self.fill_product_info(ws, product, logistics, 10) self.fill_factory_info(ws, factory) - self.fill_rw_services(ws, rw, factory, client) + self.fill_rw_services(ws, rw, factory, client, logistics) self.fill_debt_info(ws) self.fill_legal_info(ws, client) self.fill_signatures(ws, client) @@ -295,7 +295,7 @@ def form_rw_document(self, request): self.save_workbook(wb, user) - def fill_rw_services(self, ws, rw, factory, client): + def fill_rw_services(self, ws, rw, factory, client, logistics): caret = self.caret_factory ws.merge_cells(start_row=caret, start_column=1, end_row=caret, end_column=2) ws.cell(row=caret, column=1, value="Поставка осуществляется:") @@ -314,7 +314,9 @@ def fill_rw_services(self, ws, rw, factory, client): ws.cell( row=caret, column=3, - value="франко-вагон станция отправления" if 0 else "франко-вагон станция назначения", + value="не входят в стоимость товара" + if logistics != 0 + else "входят в стоимость товара", ) caret += 2 @@ -377,7 +379,7 @@ def fill_text_note(self, ws, client, discount, city): ws.cell(row=15, column=1, value=f"{get_formatted_date_agreement()} № 12/2.2/23/3-") text = f" В целях увеличения объема продаж на территории {city.region} прошу Вашего \ согласования применить скидку для контрагента {client.client_name} (г. {city.city}) до {discount}%\ - в {get_formatted_date_shipment("loct")} на продукцию следующего ассортимента: " + в {get_formatted_date_shipment('loct')} на продукцию следующего ассортимента: " ws.cell(row=19, column=1, value=text) def form_transport_sheet(self, request): diff --git a/makedoc/tests/conftest.py b/makedoc/tests/conftest.py index 89c72bc..0debfc0 100644 --- a/makedoc/tests/conftest.py +++ b/makedoc/tests/conftest.py @@ -7,8 +7,9 @@ @pytest.fixture def user(django_user_model): - return CustomUser.objects.create_user(email='test@example.com', full_name='Test User', - password='testpassword') + return CustomUser.objects.create_user( + email="test@example.com", full_name="Test User", password="testpassword" + ) @pytest.fixture diff --git a/makedoc/tests/test_views_makedoc.py b/makedoc/tests/test_views_makedoc.py index 9c126e3..1ae2c8f 100644 --- a/makedoc/tests/test_views_makedoc.py +++ b/makedoc/tests/test_views_makedoc.py @@ -6,47 +6,47 @@ @pytest.mark.django_db def test__data_view__unauthorized_user_cannot_post_data() -> None: client = APIClient() - url = reverse('data') + url = reverse("data") data = { "client_id": 123, "items": [ {"product_id": 1, "quantity": 2, "discount": 10}, - {"product_id": 2, "quantity": 5, "discount": 4} + {"product_id": 2, "quantity": 5, "discount": 4}, ], "factory_id": 1, - "destination": "New York" + "destination": "New York", } - response = client.post(url, data, format='json') + response = client.post(url, data, format="json") assert response.status_code == 401 # Unauthorized @pytest.mark.django_db def test__goods__authorized_user_can_post_data(authorized_client) -> None: - url = reverse('data') + url = reverse("data") data = { "client_id": 123, "items": [ {"product_id": 1, "quantity": 2, "discount": 10}, - {"product_id": 2, "quantity": 5, "discount": 4} + {"product_id": 2, "quantity": 5, "discount": 4}, ], "factory_id": 1, - "destination": "New York" + "destination": "New York", } - response = authorized_client.post(url, data, format='json') + response = authorized_client.post(url, data, format="json") assert response.status_code == 200 @pytest.mark.django_db def test__goods__authorized_user_post_data_response_is_correct(authorized_client) -> None: - url = reverse('data') + url = reverse("data") data = { "client_id": 123, "items": [ {"product_id": 1, "quantity": 2, "discount": 10}, - {"product_id": 2, "quantity": 5, "discount": 4} + {"product_id": 2, "quantity": 5, "discount": 4}, ], "factory_id": 1, - "destination": "New York" + "destination": "New York", } - response = authorized_client.post(url, data, format='json') + response = authorized_client.post(url, data, format="json") assert response.json() == data