245 lines
9.7 KiB
Python
245 lines
9.7 KiB
Python
from datetime import datetime, timedelta
|
||
import os
|
||
import shutil
|
||
|
||
from docx import Document
|
||
from docx.text.paragraph import Paragraph
|
||
from docx.shared import Inches, Pt, RGBColor
|
||
from docx.enum.style import WD_STYLE_TYPE
|
||
|
||
import sys
|
||
import subprocess
|
||
import re
|
||
|
||
from random import randint
|
||
import random
|
||
|
||
from pathlib import Path
|
||
|
||
|
||
from pdf2image import convert_from_path
|
||
|
||
from PIL import Image, ImageFilter, ImageDraw
|
||
|
||
from PIL.ImageFilter import (
|
||
BLUR, CONTOUR, DETAIL, EDGE_ENHANCE, EDGE_ENHANCE_MORE,
|
||
EMBOSS, FIND_EDGES, SMOOTH, SMOOTH_MORE, SHARPEN
|
||
)
|
||
|
||
|
||
def convert_to(folder, source, timeout=None):
|
||
args = [libreoffice_exec(), '--headless', '--convert-to', 'pdf', '--outdir', folder, source]
|
||
process = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout)
|
||
filename = re.search('-> (.*?) using filter', process.stdout.decode())
|
||
return filename.group(1)
|
||
|
||
|
||
def libreoffice_exec():
|
||
# TODO: Provide support for more platforms
|
||
if sys.platform == 'darwin':
|
||
return '/Applications/LibreOffice.app/Contents/MacOS/soffice'
|
||
elif sys.platform == 'win32':
|
||
# you need to add libreoffice to path
|
||
return 'soffice.exe'
|
||
return 'libreoffice'
|
||
|
||
|
||
def create_photo(address, user):
|
||
month = datetime.now().month
|
||
info = get_info(user)
|
||
path_to_template = os.path.join(os.path.abspath('.'), 'data', user)
|
||
template_docx = os.path.join(path_to_template, 'new_template.docx')
|
||
if len(info) > 0:
|
||
if not os.path.exists(template_docx):
|
||
# print(f"Копируем шаблоны графиков в {user}")
|
||
template_in_user = shutil.copyfile('new_template.docx', template_docx)
|
||
path_for_photo = os.path.join(path_to_template, str(month), address)
|
||
photos = get_photo(address, user)
|
||
if len(photos) > 0:
|
||
# print(len(photos))
|
||
if len(photos) > 7:
|
||
open_document(template_docx, True, info, address, path_for_photo, user)
|
||
else:
|
||
open_document(template_docx, False, info, address, path_for_photo, user)
|
||
return path_for_photo
|
||
else:
|
||
print(f"Нет фотографий по адресу {address}")
|
||
|
||
|
||
def get_info(user):
|
||
path = os.path.join(os.path.abspath('.'), 'data', user, 'img_5.txt')
|
||
if not os.path.exists(path):
|
||
print(f"Нет файла с информацией у пользователя {user}")
|
||
return []
|
||
with open(path, 'r') as f:
|
||
fd = f.readlines()
|
||
return fd
|
||
|
||
|
||
def get_photo(address, email):
|
||
photos = []
|
||
month = datetime.now().month
|
||
main_path = os.path.join(os.path.abspath('.'), 'data', email, str(month), address)
|
||
if not os.path.exists(main_path):
|
||
print(f"Нет фотографий по адресу: {address}")
|
||
return photos
|
||
else:
|
||
for images in os.listdir(main_path):
|
||
if images.endswith(".jpg") or images.endswith(".jpeg") or images.endswith(".JPG"):
|
||
photos.append(main_path + '/' + images)
|
||
return photos
|
||
|
||
|
||
def open_document(filename, lift, info, address, path_for_photo, user):
|
||
# print(f"Наличие лифта по адресу: {address} - {lift}")
|
||
# print(f"Начинаем подготавливать график для {address}, шаблон {filename}")
|
||
row_for_sign = 0
|
||
document = Document(filename)
|
||
styles = document.styles
|
||
tables = document.tables
|
||
date_now = datetime.today()
|
||
first_date = tables[0].rows[1].cells[0].text
|
||
first_date = datetime.strptime(first_date, '%d.%m.%y')
|
||
if datetime.now().date()-timedelta(12) > first_date.date():
|
||
clear_table(tables, lift, styles, info)
|
||
row_for_sign = fill_table(tables)
|
||
document.save(filename)
|
||
else:
|
||
row_for_sign = fill_table(tables)
|
||
document.save(filename)
|
||
paragraphs = document.paragraphs
|
||
fill_info(paragraphs, styles, info, address, lift)
|
||
document.save(filename)
|
||
make_png_with_sign(filename, row_for_sign, lift, path_for_photo, user)
|
||
|
||
|
||
def make_png_with_sign(filename, row_for_sign, lift, path_for_photo, user):
|
||
# print(f"Создаем картинку из графика {filename}")
|
||
horizontal = 0
|
||
if lift:
|
||
start_vertical = 780
|
||
else:
|
||
start_vertical = 680
|
||
result = convert_to('.', filename, timeout=15)
|
||
pages = convert_from_path(result, 200)
|
||
pages[0].save('template.png', 'PNG')
|
||
img2 = Image.open('template.png')
|
||
img2 = img2.convert("RGBA")
|
||
datas = img2.getdata()
|
||
newData = []
|
||
for item in datas:
|
||
if item[0] == 255 and item[1] == 255 and item[2] == 255:
|
||
newData.append((255, 255, 255, 0))
|
||
else:
|
||
# if item[0] > 120:
|
||
# newData.append((105, 105, 105, 255))
|
||
# else:
|
||
newData.append(item)
|
||
img2.putdata(newData)
|
||
while (row_for_sign+1) > 0:
|
||
# if lift:
|
||
# horizontal = randint(1320, 1450)
|
||
# else:
|
||
horizontal = randint(1320, 1450)
|
||
vertical = start_vertical + ((row_for_sign) * 100)
|
||
# clear_background('my_sign.png')
|
||
sign = Image.open(os.path.join(os.path.abspath('.'), 'data', user, 'sign.png'))
|
||
width, height = sign.size
|
||
sign = sign.resize((int(width*1.5), int(height*1.5)))
|
||
# print(horizontal)
|
||
img2.paste(sign, (horizontal, vertical), sign) # vertical step = 150
|
||
row_for_sign -= 1
|
||
img2.save('template.png', "PNG")
|
||
add_image_to_image('template.png', 'fon2.png', path_for_photo)
|
||
|
||
|
||
def add_image_to_image(filename, filename_fon, dst_folder):
|
||
# print(f"Накладываем график {filename} на фон")
|
||
left = randint(0, 140)
|
||
upper = randint(0, 85)
|
||
w_rand = random.uniform(0.8, 1)
|
||
b_rand = random.uniform(0.5, 0.8)
|
||
try:
|
||
angle = 0
|
||
# img = img.filter(ImageFilter.GaussianBlur(radius=1))
|
||
background = Image.open(filename_fon)
|
||
foreground = Image.open(filename)
|
||
width, height = foreground.size
|
||
size = int(width*0.25), int(height*0.25)
|
||
width_b, height_b = background.size
|
||
foreground = foreground.resize(size).rotate(angle)
|
||
background.paste(foreground, (195, 290), foreground)
|
||
background = background.crop((left, upper, width_b*w_rand, height_b*w_rand))
|
||
background = background.filter(ImageFilter.GaussianBlur(radius=b_rand))
|
||
background.save(os.path.join(dst_folder, 'graph.jpg'))
|
||
# print(os.path.join(dst_folder, 'graph.jpg'))
|
||
# print(os.path.dirname(dst_folder))
|
||
except IOError:
|
||
print(sys.exc_info()[0])
|
||
pass
|
||
|
||
|
||
def delete_paragraph(paragraph):
|
||
p = paragraph._element
|
||
p.getparent().remove(p)
|
||
p._p = p._element = None
|
||
|
||
|
||
def clear_table(tables, lift, styles, info):
|
||
# print(f"Очищаем таблицу в графике")
|
||
fio = info[0].split('\n')[0]
|
||
count = 0
|
||
while count < len(tables[0].rows)-1:
|
||
date_to_add = datetime.now().date()+timedelta(count)
|
||
delete_paragraph(tables[0].rows[count+1].cells[0].paragraphs[0])
|
||
delete_paragraph(tables[0].rows[count+1].cells[2].paragraphs[0])
|
||
par = tables[0].rows[count+1].cells[0].add_paragraph()
|
||
par_fio = tables[0].rows[count+1].cells[2].add_paragraph()
|
||
p = par.add_run(datetime.strftime(date_to_add, '%d.%m.%y'))
|
||
p_fio = par_fio.add_run(fio)
|
||
par_fio.alignment = 1
|
||
p_fio.bold = True
|
||
p.bold = True
|
||
font = p.font
|
||
count += 1
|
||
|
||
|
||
def fill_table(tables):
|
||
# print("Заполняем таблицу в графике")
|
||
r_count = 0
|
||
count = 0
|
||
while count < len(tables[0].rows)-1:
|
||
date_in_cell = tables[0].rows[count+1].cells[0].text
|
||
date_in_cell = datetime.strptime(date_in_cell, '%d.%m.%y')
|
||
if date_in_cell.date() == datetime.now().date():
|
||
r_count = count
|
||
count += 1
|
||
return r_count
|
||
|
||
|
||
def fill_info(paragraphs, styles, info, address, lift):
|
||
# print(f"Заполняем шапку графика в {address}")
|
||
fio = info[0].split('\n')[0]
|
||
dol = info[1].split('\n')[0]
|
||
phone_number = info[2].split('\n')[0]
|
||
for paragraph in paragraphs:
|
||
name_style = paragraph.style.name
|
||
if 'по адресу:' in paragraph.text:
|
||
# p = paragraph.insert_paragraph_before()
|
||
style = styles[name_style]
|
||
style.font.size = Pt(14)
|
||
paragraph.text = ''
|
||
p = paragraph.add_run('по адресу: '+address[:-4]+' Подъезд № ' + address[-2])
|
||
p.bold = True
|
||
font = p.font
|
||
font.color.rgb = RGBColor(128, 128, 128)
|
||
paragraph.style = styles[name_style]
|
||
elif 'Должность:' in paragraph.text:
|
||
paragraph.text = ''
|
||
if lift:
|
||
text_for_perechen = 'Перечень обрабатываемых объектов:\n - Первые этажи подъездов: полы, дверные и оконные ручки, почтовые ящики, панели домофонов и кодовых замков, перила лестничных маршей\n - Лифтовые кабины: напольные покрытия, панели управления лифтами, лифтовые вентиляционные решетки'
|
||
else:
|
||
text_for_perechen = 'Перечень обрабатываемых объектов:\n - Первые этажи подъездов: полы, дверные и оконные ручки, почтовые ящики, панели домофонов и кодовых замков, перила лестничных маршей'
|
||
run = paragraph.add_run(' Должность: ' + dol +' Ф.И.О.: ' + fio + '\n тел: ' + phone_number + '\n' + text_for_perechen)
|
||
font = run.font
|