malixds_

Untitled

Feb 12th, 2024
9
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.87 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="en">
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>PDF</title>
  7. </head>
  8.  
  9. <body>
  10. <div id="convertedPage" class="converted__page">
  11.  
  12. <div class="logo">
  13. <img src="data:image/png;base64,{{img}}">
  14. </div>
  15.  
  16. <div class="info">
  17. <div class="info__items">
  18. <div class="info__item-text">
  19. <p class="info__text">
  20. <p class="text info__date">Дата:{{inpObj["date"]}}</p>
  21. <p class="text info__id">ID:{{inpObj["id"]}}</p>
  22. <p class="text info__customer">Заказчик:{{inpObj["customer"]}}</p>
  23. <p class="text info__partner">Партнёр:{{inpObj["partner"]}}</p>
  24. <p class="text info__distributor">Дистрибьютор:{{inpObj["distributor"]}}</p>
  25. </p>
  26. </div>
  27. <div class="info__item-result">
  28. <p class="text info__date-result" id="date"></p>
  29. <p class="text info__id-result" id="ID"></p>
  30. <p class="text info__customer-result" id="customer"></p>
  31. <p class="text info__partner-result" id="partner"></p>
  32. <p class="text info__distributor-result" id="distributor"></p>
  33. </div>
  34. </div>
  35. </div>
  36.  
  37. <div class="assessment">
  38. <h3 class="assessment_title">Бюджетная оценка</h3>
  39. <div class="assessment__text">
  40. <p class="assessment__text-item" id="action_time">{{inpObj["offer"]}}</p>
  41. <p class="assessment__text-item" id="shipping_time">{{inpObj["delivery"]}}</p>
  42. <p class="assessment__text-item" id="payment_conditions">{{inpObj["payment"]}}</p>
  43. <p class="assessment__text-item" id="warranty_conditions">{{inpObj["warranty"]}}</p>
  44. <p class="assessment__text-item" id="shipping_conditions">{{inpObj["shipping"]}}</p>
  45. <p class="assessment__text-item" id="correct">{{inpObj["correct"]}}</p>
  46. </div>
  47. </div>
  48.  
  49. <div class="resume">
  50. <table class="main__table">
  51. <thead class="main__table-header">
  52. <tr class="main__table-tr">
  53. <th class="main__table-header-text">№</th>
  54. <th class="main__table-header-text">Наименование</th>
  55. <th class="main__table-header-text">Количество</th>
  56. <th class="main__table-header-text">Цена (РРЦ) <br> USD с НДС</th>
  57. <th class="main__table-header-text">Сумма (РРЦ) <br> USD с НДС</th>
  58. </tr>
  59. </thead>
  60. <tbody class="main__table-body">
  61. <tr>
  62. <td id="num">1</td>
  63. <td id="config_name">{{inpObj["server_name"]}}</td>
  64. <td id="config_quantity">1</td>
  65. <td id="price_pdf">{{inpObj["price"]}}</td>
  66. <td id="summ_pdf">{{inpObj["summary"]}}</td>
  67. </tr>
  68. <tr>
  69. <td></td>
  70. <td class="component-cell">
  71. <ul class="component-list">
  72. {% for obj in object %}
  73. {% if obj != None %}
  74. <li class="component-item">{{obj}}</li>
  75. {%endif%}
  76. {%endfor%}
  77. </ul>
  78. </td>
  79. <td class="quantity-cell">
  80. <ul class="quantity-list">
  81. {% for num in number%}
  82. {%if num != 0 %}
  83. <li class="quantity-item">{{num}}</li>
  84. {% endif %}
  85. {%endfor%}
  86.  
  87. </ul>
  88. </td>
  89. <td></td>
  90. <td></td>
  91. </tr>
  92. <tr>
  93. </tbody>
  94. </table>
  95. </div>
  96.  
  97.  
  98. <style>
  99. .component-list {
  100. list-style-type: none;
  101. /* Убираем маркеры списка */
  102. padding: 0;
  103. /* Убираем внешние отступы */
  104. margin: 0;
  105. /* Убираем внутренние отступы */
  106. height: 100%;
  107. display: flex;
  108. flex-direction: column;
  109. justify-content: space-between;
  110. }
  111. .quantity-item, .component-item {
  112. margin: 0;
  113. padding: 0;
  114. }
  115.  
  116. /* Устанавливаем стиль для списка количества */
  117. .quantity-list {
  118. list-style-type: none;
  119. /* Убираем маркеры списка */
  120. padding: 0;
  121. /* Убираем внешние отступы */
  122. margin: 0;
  123. /* Убираем внутренние отступы */
  124. height: 100%;
  125. display: flex;
  126. flex-direction: column;
  127. justify-content: space-between;
  128. }
  129.  
  130. .component-cell,
  131. .quantity-cell {
  132. height: 100%;
  133. /* Занимаем всю доступную высоту ячейки */
  134. padding: 0;
  135. /* Убираем внутренние отступы */
  136. margin: 0;
  137. /* Убираем внешние отступы */
  138. }
  139.  
  140. input:active,
  141. input:hover,
  142. input:focus {
  143. outline: none;
  144. }
  145.  
  146. body {
  147. background-color: #fff;
  148. }
  149.  
  150. .info,
  151. .logo,
  152. .assessment,
  153. .resume {
  154. padding: 0 50px;
  155. }
  156.  
  157. .info__items {
  158. display: flex;
  159. }
  160.  
  161. .info__item-input {}
  162.  
  163. .info__item-text {
  164. margin-right: 3rem;
  165. }
  166.  
  167. .assessment {
  168. text-align: left;
  169. }
  170.  
  171. .table__inside-body-td-name {
  172. text-align: left !important;
  173. }
  174.  
  175. table {
  176. width: 100%;
  177. border-collapse: collapse;
  178. /* border-spacing: 0 10px; Первое значение - горизонтальный отступ, второе - вертикальный */
  179. margin-bottom: 20px;
  180. font-size: 14px;
  181. }
  182.  
  183. th,
  184. td {
  185. border: 2px solid #000;
  186. padding: 8px 2px;
  187.  
  188. }
  189.  
  190. th {
  191. background-color: #fff;
  192. text-align: center !important;
  193. }
  194.  
  195. /* Указываем процентное значение ширины для каждой колонны */
  196. th:nth-child(1),
  197. td:nth-child(1) {
  198. width: 10%;
  199. text-align: center;
  200. /* Центрирование текста в первой колонне */
  201. }
  202.  
  203. th:nth-child(2),
  204. td:nth-child(2) {
  205. width: 50%;
  206. margin-bottom: 10px;
  207. /* Отступ только после ячейки 2-1 */
  208. }
  209.  
  210. th:nth-child(3),
  211. td:nth-child(3) {
  212. width: 10%;
  213. text-align: center;
  214. }
  215.  
  216. th:nth-child(4),
  217. td:nth-child(4) {
  218. width: 15%;
  219. text-align: right;
  220.  
  221. }
  222.  
  223. th:nth-child(5),
  224. td:nth-child(5) {
  225. width: 15%;
  226. text-align: right;
  227. }
  228. </style>
  229. </div>
  230. </body>
  231.  
  232. input:active,
  233. input:hover,
  234. input:focus {
  235. outline: none;
  236. }
  237.  
  238. .info,
  239. .logo,
  240. .assessment,
  241. .resume {
  242. padding: 0 50px;
  243. }
  244.  
  245. .info__items {
  246. display: flex;
  247. }
  248.  
  249. .info__item-input {}
  250.  
  251. .info__item-text {
  252. margin-right: 3rem;
  253. }
  254.  
  255. .assessment {
  256. text-align: center;
  257. }
  258.  
  259. .table__inside-body-td-name {
  260. text-align: left !important;
  261. }
  262.  
  263. table {
  264. width: 100%;
  265. border-collapse: collapse;
  266. /* border-spacing: 0 10px; Первое значение - горизонтальный отступ, второе - вертикальный */
  267. margin-bottom: 20px;
  268. }
  269.  
  270. th,
  271. td {
  272. border: 2px solid #000;
  273. padding: 8px 2px;
  274. }
  275.  
  276. th {
  277. background-color: #fff;
  278. text-align: center !important;
  279. }
  280.  
  281. /* Указываем процентное значение ширины для каждой колонны */
  282. th:nth-child(1),
  283. td:nth-child(1) {
  284. width: 10%;
  285. text-align: center;
  286. /* Центрирование текста в первой колонне */
  287. }
  288.  
  289. th:nth-child(2),
  290. td:nth-child(2) {
  291. width: 50%;
  292. margin-bottom: 10px;
  293. /* Отступ только после ячейки 2-1 */
  294. }
  295.  
  296. th:nth-child(3),
  297. td:nth-child(3) {
  298. width: 10%;
  299. text-align: center;
  300. }
  301.  
  302. th:nth-child(4),
  303. td:nth-child(4) {
  304. width: 15%;
  305. text-align: right;
  306.  
  307. }
  308.  
  309. th:nth-child(5),
  310. td:nth-child(5) {
  311. width: 15%;
  312. text-align: right;
  313. }
  314.  
  315.  
  316. @app.route('/make_pdf', methods = ['POST'])
  317. @login_required
  318. def make_pdf():
  319. data = request.get_json()
  320. object,number = [], []
  321. env = Environment(loader=FileSystemLoader('.'))
  322.  
  323. '''
  324. TODO: Пройти по объекту data и отфильтровать наполнение:
  325. в object пихать название, а в number его количество.
  326.  
  327. (Тебе надо будет установить wkhtmltopdf(в консоли ссылка будет)
  328. и папку расположить на диске D как тут D:\\wkhtmltopdf\\bin\\wkhtmltopdf.exe)
  329. '''
  330. commodity_needed = ['cpu', 'ram', 'drives', 'gpus', 'fc_adapters', 'psu', 'transceiver', 'raid', 'bios',
  331. 'bmc', 'dss_software', 'cipf', 'wifiBluetoothAdapter', 'lte', 'stylus', 'operating_system',
  332. 'mouse', 'keyboard', 'network_ocp_controllers', 'network_adapters', 'cables', 'cabel',
  333. 'mobile_rack', ]
  334. cables = ['hdminisas', 'aoc', 'dac', 'patchcord', 'psu_cable']
  335. drives = ['sata', 'sas', 'm2', 'nvme']
  336.  
  337. for i in data: # Писать тут
  338. if data[i] != None and i in commodity_needed and len(data[i]) > 0:
  339. name, quantity = [], []
  340.  
  341. if i == 'drives':
  342. for j in data[i]:
  343. if j == 'on_backplane' or j == 'on_jbod':
  344. for z in data[i][j]:
  345. for u in z:
  346. if u in drives and len(z[u]) > 0:
  347. for y in z[u]:
  348. name.append(y['name'])
  349. quantity.append(y['quantity'])
  350. else:
  351. for j in data[i]['m2']:
  352. name.append(j['name'])
  353. quantity.append(j['quantity'])
  354. elif i == 'cables':
  355. for j in data[i]:
  356. for z in data[i][j]:
  357. name.append(z['name'])
  358. quantity.append(z['quantity'])
  359. else:
  360. if type(data[i]) is list:
  361. for j in data[i]:
  362. name.append(j['name'])
  363. quantity.append(j['quantity'])
  364. else:
  365. name.append(data[i]['name'])
  366. quantity.append(data[i]['quantity'])
  367.  
  368. if len(name) > 0 and len(quantity) > 0:
  369. object = object + name
  370. number = number + quantity
  371.  
  372.  
  373. template = env.get_template("templates/html_to_pdf.html")
  374. pdf_template = template.render(inpObj=data["inpObj"], number=number, object=object, img=image_file_path_to_base64_string(r"/home/malixds/work/aquarius_flask/static/images/logo.jpg"))
  375. path = "/usr/bin/wkhtmltopdf"
  376. postfix = ''.join(random.choices(string.ascii_letters, k=3))
  377. filename = data["server_name"] + postfix
  378. for w in postfix:
  379. filename += w
  380. config = pdfkit.configuration(wkhtmltopdf=path)
  381. pdfkit.from_string(pdf_template, f"/tmp/{filename}.pdf", configuration=config)
  382. return {
  383. "path": f"/tmp/{filename}.pdf"
  384. }
  385.  
  386.  
Add Comment
Please, Sign In to add comment