Passed
Push — master ( 107ae9...7e7300 )
by Guangyu
12:14 queued 12s
created

is_base_period_timestamp_exists()   A

Complexity

Conditions 4

Size

Total Lines 11
Code Lines 8

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 8
dl 11
loc 11
rs 10
c 0
b 0
f 0
cc 4
nop 1
1
import base64
2
import gettext
3
import os
4
import re
5
import uuid
6
from decimal import Decimal
7
8
import openpyxl.utils.cell as format_cell
9
from openpyxl import Workbook
10
from openpyxl.chart import PieChart, Reference, LineChart
11
from openpyxl.chart.label import DataLabelList
12
from openpyxl.drawing.image import Image
13
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
14
15
16
########################################################################################################################
17
# PROCEDURES
18
# Step 1: Validate the report data
19
# Step 2: Generate excel file
20
# Step 3: Encode the excel file bytes to Base64
21
########################################################################################################################
22
23
24 View Code Duplication
def export(report,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
25
           name,
26
           base_period_start_datetime_local,
27
           base_period_end_datetime_local,
28
           reporting_start_datetime_local,
29
           reporting_end_datetime_local,
30
           period_type,
31
           language):
32
    ####################################################################################################################
33
    # Step 1: Validate the report data
34
    ####################################################################################################################
35
    if report is None:
36
        return None
37
38
    ####################################################################################################################
39
    # Step 2: Generate excel file from the report data
40
    ####################################################################################################################
41
    filename = generate_excel(report,
42
                              name,
43
                              base_period_start_datetime_local,
44
                              base_period_end_datetime_local,
45
                              reporting_start_datetime_local,
46
                              reporting_end_datetime_local,
47
                              period_type,
48
                              language)
49
    ####################################################################################################################
50
    # Step 3: Encode the excel file to Base64
51
    ####################################################################################################################
52
    binary_file_data = b''
53
    try:
54
        with open(filename, 'rb') as binary_file:
55
            binary_file_data = binary_file.read()
56
    except IOError as ex:
57
        print(str(ex))
58
59
    # Base64 encode the bytes
60
    base64_encoded_data = base64.b64encode(binary_file_data)
61
    # get the Base64 encoded data using human-readable characters.
62
    base64_message = base64_encoded_data.decode('utf-8')
63
    # delete the file from server
64
    try:
65
        os.remove(filename)
66
    except NotImplementedError as ex:
67
        print(str(ex))
68
    return base64_message
69
70
71 View Code Duplication
def generate_excel(report,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
72
                   name,
73
                   base_period_start_datetime_local,
74
                   base_period_end_datetime_local,
75
                   reporting_start_datetime_local,
76
                   reporting_end_datetime_local,
77
                   period_type,
78
                   language):
79
80
    locale_path = './i18n/'
81
    if language == 'zh_CN':
82
        trans = gettext.translation('myems', locale_path, languages=['zh_CN'])
83
    elif language == 'de':
84
        trans = gettext.translation('myems', locale_path, languages=['de'])
85
    elif language == 'en':
86
        trans = gettext.translation('myems', locale_path, languages=['en'])
87
    else:
88
        trans = gettext.translation('myems', locale_path, languages=['en'])
89
    trans.install()
90
    _ = trans.gettext
91
92
    wb = Workbook()
93
    ws = wb.active
94
    ws.title = "StoreCost"
95
96
    # Row height
97
    ws.row_dimensions[1].height = 118
98
    for i in range(2, 2000 + 1):
99
        ws.row_dimensions[i].height = 42
100
101
    # Col width
102
    ws.column_dimensions['A'].width = 1.5
103
    ws.column_dimensions['B'].width = 20.0
104
    ws.column_dimensions['C'].width = 20.0
105
106
    for i in range(ord('D'), ord('Z')):
107
        ws.column_dimensions[chr(i)].width = 15.0
108
109
    # Font
110
    name_font = Font(name='Arial', size=15, bold=True)
111
    title_font = Font(name='Arial', size=15, bold=True)
112
113
    table_fill = PatternFill(fill_type='solid', fgColor='90ee90')
114
    f_border = Border(left=Side(border_style='medium'),
115
                      right=Side(border_style='medium'),
116
                      bottom=Side(border_style='medium'),
117
                      top=Side(border_style='medium')
118
                      )
119
    b_border = Border(
120
        bottom=Side(border_style='medium'),
121
    )
122
123
    b_c_alignment = Alignment(vertical='bottom',
124
                              horizontal='center',
125
                              text_rotation=0,
126
                              wrap_text=True,
127
                              shrink_to_fit=False,
128
                              indent=0)
129
    c_c_alignment = Alignment(vertical='center',
130
                              horizontal='center',
131
                              text_rotation=0,
132
                              wrap_text=True,
133
                              shrink_to_fit=False,
134
                              indent=0)
135
    b_r_alignment = Alignment(vertical='bottom',
136
                              horizontal='right',
137
                              text_rotation=0,
138
                              wrap_text=True,
139
                              shrink_to_fit=False,
140
                              indent=0)
141
    # Img
142
    img = Image("excelexporters/myems.png")
143
    ws.add_image(img, 'A1')
144
145
    # Title
146
    ws['B3'].alignment = b_r_alignment
147
    ws['B3'] = _('Name') + ':'
148
    ws['C3'].border = b_border
149
    ws['C3'].alignment = b_c_alignment
150
    ws['C3'] = name
151
152
    ws['D3'].alignment = b_r_alignment
153
    ws['D3'] = _('Period Type') + ':'
154
    ws['E3'].border = b_border
155
    ws['E3'].alignment = b_c_alignment
156
    ws['E3'] = period_type
157
158
    ws['B4'].alignment = b_r_alignment
159
    ws['B4'] = _('Reporting Start Datetime') + ':'
160
    ws['C4'].border = b_border
161
    ws['C4'].alignment = b_c_alignment
162
    ws['C4'] = reporting_start_datetime_local
163
164
    ws['D4'].alignment = b_r_alignment
165
    ws['D4'] = _('Reporting End Datetime') + ':'
166
    ws['E4'].border = b_border
167
    ws['E4'].alignment = b_c_alignment
168
    ws['E4'] = reporting_end_datetime_local
169
170
    is_base_period_timestamp_exists_flag = is_base_period_timestamp_exists(report['base_period'])
171
172
    if is_base_period_timestamp_exists_flag:
173
        ws['B5'].alignment = b_r_alignment
174
        ws['B5'] = _('Base Period Start Datetime') + ':'
175
        ws['C5'].border = b_border
176
        ws['C5'].alignment = b_c_alignment
177
        ws['C5'] = base_period_start_datetime_local
178
179
        ws['D5'].alignment = b_r_alignment
180
        ws['D5'] = _('Base Period End Datetime') + ':'
181
        ws['E5'].border = b_border
182
        ws['E5'].alignment = b_c_alignment
183
        ws['E5'] = base_period_end_datetime_local
184
185
    if "reporting_period" not in report.keys() or \
186
            "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0:
187
        filename = str(uuid.uuid4()) + '.xlsx'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable str does not seem to be defined.
Loading history...
188
        wb.save(filename)
189
        return filename
190
191
    ####################################################################################################################
192
    reporting_period_data = report['reporting_period']
193
    if "names" not in reporting_period_data.keys() or \
194
            reporting_period_data['names'] is None or \
195
            len(reporting_period_data['names']) == 0:
196
        for i in range(7, 11 + 1):
197
            ws.row_dimensions[i].height = 0.1
198
    else:
199
        ws['B7'].font = title_font
200
        ws['B7'] = name + ' ' + _('Reporting Period Costs')
201
202
        category = reporting_period_data['names']
203
        ca_len = len(category)
204
205
        ws['B8'].fill = table_fill
206
        ws['B8'].border = f_border
207
208
        ws['B9'].font = title_font
209
        ws['B9'].alignment = c_c_alignment
210
        ws['B9'] = _('Cost')
211
        ws['B9'].border = f_border
212
213
        ws['B10'].font = title_font
214
        ws['B10'].alignment = c_c_alignment
215
        ws['B10'] = _('Per Unit Area')
216
        ws['B10'].border = f_border
217
218
        ws['B11'].font = title_font
219
        ws['B11'].alignment = c_c_alignment
220
        ws['B11'] = _('Increment Rate')
221
        ws['B11'].border = f_border
222
223
        col = 'B'
224
225
        for i in range(0, ca_len):
226
            col = chr(ord('C') + i)
227
            ws[col + '8'].fill = table_fill
228
            ws[col + '8'].font = name_font
229
            ws[col + '8'].alignment = c_c_alignment
230
            ws[col + '8'] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
231
            ws[col + '8'].border = f_border
232
233
            ws[col + '9'].font = name_font
234
            ws[col + '9'].alignment = c_c_alignment
235
            ws[col + '9'] = round(reporting_period_data['subtotals'][i], 2)
236
            ws[col + '9'].border = f_border
237
238
            ws[col + '10'].font = name_font
239
            ws[col + '10'].alignment = c_c_alignment
240
            ws[col + '10'] = round(reporting_period_data['subtotals_per_unit_area'][i], 2)
241
            ws[col + '10'].border = f_border
242
243
            ws[col + '11'].font = name_font
244
            ws[col + '11'].alignment = c_c_alignment
245
            ws[col + '11'] = str(round(reporting_period_data['increment_rates'][i] * 100, 2)) + "%" \
246
                if reporting_period_data['increment_rates'][i] is not None else "-"
247
            ws[col + '11'].border = f_border
248
249
        end_col = chr(ord(col)+1)
250
        ws[end_col + '8'].fill = table_fill
251
        ws[end_col + '8'].font = name_font
252
        ws[end_col + '8'].alignment = c_c_alignment
253
        ws[end_col + '8'] = _("Total") + " (" + reporting_period_data['total_unit'] + ")"
254
        ws[end_col + '8'].border = f_border
255
256
        ws[end_col + '9'].font = name_font
257
        ws[end_col + '9'].alignment = c_c_alignment
258
        ws[end_col + '9'] = round(reporting_period_data['total'], 2)
259
        ws[end_col + '9'].border = f_border
260
261
        ws[end_col + '10'].font = name_font
262
        ws[end_col + '10'].alignment = c_c_alignment
263
        ws[end_col + '10'] = round(reporting_period_data['total_per_unit_area'], 2)
264
        ws[end_col + '10'].border = f_border
265
266
        ws[end_col + '11'].font = name_font
267
        ws[end_col + '11'].alignment = c_c_alignment
268
        ws[end_col + '11'] = str(round(reporting_period_data['total_increment_rate'] * 100, 2)) + "%" \
269
            if reporting_period_data['total_increment_rate'] is not None else "-"
270
        ws[end_col + '11'].border = f_border
271
272
    ####################################################################################################################
273
    if "toppeaks" not in reporting_period_data.keys() or \
274
            reporting_period_data['toppeaks'] is None or \
275
            len(reporting_period_data['toppeaks']) == 0:
276
        for i in range(13, 19 + 1):
277
            ws.row_dimensions[i].height = 0.1
278
    else:
279
        electricity_index = -1
280
        for i in range(len(reporting_period_data['energy_category_ids'])):
281
            if reporting_period_data['energy_category_ids'][i] == 1:
282
                electricity_index = i
283
                break
284
285
        ws['B13'].font = title_font
286
        ws['B13'] = name + ' ' + _('Electricity Costs by Time-Of-Use')
287
288
        ws['B14'].fill = table_fill
289
        ws['B14'].font = name_font
290
        ws['B14'].alignment = c_c_alignment
291
        ws['B14'].border = f_border
292
293
        ws['C14'].fill = table_fill
294
        ws['C14'].font = name_font
295
        ws['C14'].alignment = c_c_alignment
296
        ws['C14'].border = f_border
297
        ws['C14'] = _('Electricity Costs by Time-Of-Use')
298
299
        ws['B15'].font = title_font
300
        ws['B15'].alignment = c_c_alignment
301
        ws['B15'] = _('TopPeak')
302
        ws['B15'].border = f_border
303
304
        ws['C15'].font = title_font
305
        ws['C15'].alignment = c_c_alignment
306
        ws['C15'].border = f_border
307
        ws['C15'] = round(reporting_period_data['toppeaks'][electricity_index], 2) if electricity_index >= 0 else "-"
308
309
        ws['B16'].font = title_font
310
        ws['B16'].alignment = c_c_alignment
311
        ws['B16'] = _('OnPeak')
312
        ws['B16'].border = f_border
313
314
        ws['C16'].font = title_font
315
        ws['C16'].alignment = c_c_alignment
316
        ws['C16'].border = f_border
317
        ws['C16'] = round(reporting_period_data['onpeaks'][electricity_index], 2) if electricity_index >= 0 else "-"
318
319
        ws['B17'].font = title_font
320
        ws['B17'].alignment = c_c_alignment
321
        ws['B17'] = _('MidPeak')
322
        ws['B17'].border = f_border
323
324
        ws['C17'].font = title_font
325
        ws['C17'].alignment = c_c_alignment
326
        ws['C17'].border = f_border
327
        ws['C17'] = round(reporting_period_data['midpeaks'][electricity_index], 2) if electricity_index >= 0 else "-"
328
329
        ws['B18'].font = title_font
330
        ws['B18'].alignment = c_c_alignment
331
        ws['B18'] = _('OffPeak')
332
        ws['B18'].border = f_border
333
334
        ws['C18'].font = title_font
335
        ws['C18'].alignment = c_c_alignment
336
        ws['C18'].border = f_border
337
        ws['C18'] = round(reporting_period_data['offpeaks'][electricity_index], 2) if electricity_index >= 0 else "-"
338
339
        pie = PieChart()
340
        labels = Reference(ws, min_col=2, min_row=15, max_row=18)
341
        pie_data = Reference(ws, min_col=3, min_row=14, max_row=18)
342
        pie.add_data(pie_data, titles_from_data=True)
343
        pie.set_categories(labels)
344
        pie.height = 5.25
345
        pie.width = 8
346
        s1 = pie.series[0]
347
        s1.dLbls = DataLabelList()
348
        s1.dLbls.showCatName = False
349
        s1.dLbls.showVal = True
350
        s1.dLbls.showPercent = True
351
        ws.add_chart(pie, "D14")
352
353
    ####################################################################################################################
354
    current_row_number = 20
355
    if "subtotals" not in reporting_period_data.keys() or \
356
            reporting_period_data['subtotals'] is None or \
357
            len(reporting_period_data['subtotals']) == 0:
358
        for i in range(21, 29 + 1):
359
            current_row_number = 30
360
            ws.row_dimensions[i].height = 0.1
361
    else:
362
        ws['B' + str(current_row_number)].font = title_font
363
        ws['B' + str(current_row_number)] = name + ' ' + _('Costs Proportion')
364
365
        current_row_number += 1
366
367
        table_start_row_number = current_row_number
368
369
        ws['B' + str(current_row_number)].fill = table_fill
370
        ws['B' + str(current_row_number)].font = name_font
371
        ws['B' + str(current_row_number)].alignment = c_c_alignment
372
        ws['B' + str(current_row_number)].border = f_border
373
374
        ws['C' + str(current_row_number)].fill = table_fill
375
        ws['C' + str(current_row_number)].font = name_font
376
        ws['C' + str(current_row_number)].alignment = c_c_alignment
377
        ws['C' + str(current_row_number)].border = f_border
378
        ws['C' + str(current_row_number)] = _('Costs Proportion')
379
380
        current_row_number += 1
381
382
        ca_len = len(reporting_period_data['names'])
383
384
        for i in range(0, ca_len):
385
            ws['B' + str(current_row_number)].font = title_font
386
            ws['B' + str(current_row_number)].alignment = c_c_alignment
387
            ws['B' + str(current_row_number)] = reporting_period_data['names'][i]
388
            ws['B' + str(current_row_number)].border = f_border
389
390
            ws['C' + str(current_row_number)].font = title_font
391
            ws['C' + str(current_row_number)].alignment = c_c_alignment
392
            ws['C' + str(current_row_number)].border = f_border
393
            ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
394
395
            current_row_number += 1
396
397
        table_end_row_number = current_row_number - 1
398
399
        pie = PieChart()
400
        labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
401
        pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number)
402
        pie.add_data(pie_data, titles_from_data=True)
403
        pie.set_categories(labels)
404
        pie.height = 5.25
405
        pie.width = 8
406
        s1 = pie.series[0]
407
        s1.dLbls = DataLabelList()
408
        s1.dLbls.showCatName = False
409
        s1.dLbls.showVal = True
410
        s1.dLbls.showPercent = True
411
        table_cell = 'D' + str(table_start_row_number)
412
        ws.add_chart(pie, table_cell)
413
414
        if ca_len < 4:
415
            current_row_number = current_row_number - ca_len + 4
416
417
    ####################################################################################################################
418
    table_start_draw_flag = current_row_number + 1
419
420
    if "timestamps" not in reporting_period_data.keys() or \
421
            reporting_period_data['timestamps'] is None or \
422
            len(reporting_period_data['timestamps']) == 0:
423
        pass
424
    else:
425
        if not is_base_period_timestamp_exists_flag:
426
            reporting_period_data = report['reporting_period']
427
            times = reporting_period_data['timestamps']
428
            ca_len = len(report['reporting_period']['names'])
429
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
430
            ws['B' + str(current_row_number)].font = title_font
431
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
432
433
            current_row_number += 1
434
            # 1: Stand for blank line  2: Stand for title
435
            current_row_number += ca_len * 6 + real_timestamps_len * 6 + 1 + 2
436
            table_start_row_number = current_row_number
437
438
            time = times[0]
439
            has_data = False
440
441
            if len(time) > 0:
442
                has_data = True
443
444
            if has_data:
445
446
                ws.row_dimensions[current_row_number].height = 60
447
                current_col_number = 2
448
                col = format_cell.get_column_letter(current_col_number)
449
                ws[col + str(current_row_number)].fill = table_fill
450
                ws[col + str(current_row_number)].font = title_font
451
                ws[col + str(current_row_number)].border = f_border
452
                ws[col + str(current_row_number)].alignment = c_c_alignment
453
                ws[col + str(current_row_number)] = _('Datetime')
454
455
                for i in range(0, ca_len):
456
                    current_col_number += 1
457
                    col = format_cell.get_column_letter(current_col_number)
458
459
                    ws[col + str(current_row_number)].fill = table_fill
460
                    ws[col + str(current_row_number)].font = title_font
461
                    ws[col + str(current_row_number)].alignment = c_c_alignment
462
                    ws[col + str(current_row_number)] = reporting_period_data['names'][i] + \
463
                        " (" + reporting_period_data['units'][i] + ")"
464
                    ws[col + str(current_row_number)].border = f_border
465
466
                current_col_number += 1
467
                col = format_cell.get_column_letter(current_col_number)
468
                ws[col + str(current_row_number)].fill = table_fill
469
                ws[col + str(current_row_number)].font = title_font
470
                ws[col + str(current_row_number)].alignment = c_c_alignment
471
                ws[col + str(current_row_number)] = _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
472
                ws[col + str(current_row_number)].border = f_border
473
474
                current_row_number += 1
475
476
                for i in range(0, len(time)):
477
                    current_col_number = 2
478
                    col = format_cell.get_column_letter(current_col_number)
479
480
                    ws[col + str(current_row_number)].font = title_font
481
                    ws[col + str(current_row_number)].alignment = c_c_alignment
482
                    ws[col + str(current_row_number)] = time[i]
483
                    ws[col + str(current_row_number)].border = f_border
484
485
                    total = Decimal(0.0)
486
487
                    for j in range(0, ca_len):
488
                        current_col_number += 1
489
                        col = format_cell.get_column_letter(current_col_number)
490
491
                        ws[col + str(current_row_number)].font = title_font
492
                        ws[col + str(current_row_number)].alignment = c_c_alignment
493
                        ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2)
494
                        total += reporting_period_data['values'][j][i]
495
                        ws[col + str(current_row_number)].border = f_border
496
497
                    current_col_number += 1
498
                    col = format_cell.get_column_letter(current_col_number)
499
                    ws[col + str(current_row_number)].font = title_font
500
                    ws[col + str(current_row_number)].alignment = c_c_alignment
501
                    ws[col + str(current_row_number)] = round(total, 2)
502
                    ws[col + str(current_row_number)].border = f_border
503
504
                    current_row_number += 1
505
506
                table_end_row_number = current_row_number - 1
507
508
                current_col_number = 2
509
                col = format_cell.get_column_letter(current_col_number)
510
511
                ws[col + str(current_row_number)].font = title_font
512
                ws[col + str(current_row_number)].alignment = c_c_alignment
513
                ws[col + str(current_row_number)] = _('Subtotal')
514
                ws[col + str(current_row_number)].border = f_border
515
516
                subtotals = Decimal(0.0)
517
518
                for i in range(0, ca_len):
519
                    current_col_number += 1
520
                    col = format_cell.get_column_letter(current_col_number)
521
                    ws[col + str(current_row_number)].font = title_font
522
                    ws[col + str(current_row_number)].alignment = c_c_alignment
523
                    ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
524
                    subtotals += reporting_period_data['subtotals'][i]
525
                    ws[col + str(current_row_number)].border = f_border
526
527
                    # line
528
                    line = LineChart()
529
                    line.title = _('Reporting Period Costs') + ' - ' \
530
                        + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
531
                    labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
532
                    line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
533
                                          max_row=table_end_row_number)
534
                    line.add_data(line_data, titles_from_data=True)
535
                    line.set_categories(labels)
536
                    line_data = line.series[0]
537
                    line_data.marker.symbol = "circle"
538
                    line_data.smooth = True
539
                    line.x_axis.crosses = 'min'
540
                    line.height = 8.25
541
                    line.width = 24
542
                    line.dLbls = DataLabelList()
543
                    line.dLbls.dLblPos = 't'
544
                    line.dLbls.showVal = True
545
                    line.dLbls.showPercent = False
546
                    chart_col = 'B'
547
                    chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
548
                    ws.add_chart(line, chart_cell)
549
550
                current_col_number += 1
551
                col = format_cell.get_column_letter(current_col_number)
552
                ws[col + str(current_row_number)].font = title_font
553
                ws[col + str(current_row_number)].alignment = c_c_alignment
554
                ws[col + str(current_row_number)] = round(subtotals, 2)
555
                ws[col + str(current_row_number)].border = f_border
556
557
                current_row_number += 2
558
        else:
559
            base_period_data = report['base_period']
560
            reporting_period_data = report['reporting_period']
561
            base_period_timestamps = base_period_data['timestamps']
562
            reporting_period_timestamps = reporting_period_data['timestamps']
563
            # Tip:
564
            #     base_period_data['names'] == reporting_period_data['names']
565
            #     base_period_data['units'] == reporting_period_data['units']
566
            base_period_data_ca_len = len(base_period_data['names'])
567
            reporting_period_data_ca_len = len(reporting_period_data['names'])
568
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
569
            ws['B' + str(current_row_number)].font = title_font
570
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
571
572
            current_row_number += 1
573
            # 1: Stand for blank line  2: Stand for title
574
            current_row_number += reporting_period_data_ca_len * 6 + real_timestamps_len * 6 + 1 + 2
575
            table_start_row_number = current_row_number
576
577
            has_data = False
578
579
            if len(base_period_timestamps[0]) or len(reporting_period_timestamps[0]) > 0:
580
                has_data = True
581
582
            if has_data:
583
                ws.row_dimensions[current_row_number].height = 60
584
                current_col_number = 2
585
                col = format_cell.get_column_letter(current_col_number)
586
                ws[col + str(current_row_number)].fill = table_fill
587
                ws[col + str(current_row_number)].font = title_font
588
                ws[col + str(current_row_number)].border = f_border
589
                ws[col + str(current_row_number)].alignment = c_c_alignment
590
                ws[col + str(current_row_number)] = _('Base Period') + " - " + _('Datetime')
591
592
                for i in range(0, base_period_data_ca_len):
593
                    current_col_number += 1
594
                    col = format_cell.get_column_letter(current_col_number)
595
596
                    ws[col + str(current_row_number)].fill = table_fill
597
                    ws[col + str(current_row_number)].font = title_font
598
                    ws[col + str(current_row_number)].alignment = c_c_alignment
599
                    ws[col + str(current_row_number)] = _('Base Period') + " - " + base_period_data['names'][i] + \
600
                        " (" + base_period_data['units'][i] + ")"
601
                    ws[col + str(current_row_number)].border = f_border
602
603
                current_col_number += 1
604
                col = format_cell.get_column_letter(current_col_number)
605
                ws[col + str(current_row_number)].fill = table_fill
606
                ws[col + str(current_row_number)].font = title_font
607
                ws[col + str(current_row_number)].alignment = c_c_alignment
608
                ws[col + str(current_row_number)] = _('Base Period') + " - " \
609
                    + _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
610
                ws[col + str(current_row_number)].border = f_border
611
612
                current_col_number += 1
613
                col = format_cell.get_column_letter(current_col_number)
614
615
                ws[col + str(current_row_number)].fill = table_fill
616
                ws[col + str(current_row_number)].font = title_font
617
                ws[col + str(current_row_number)].border = f_border
618
                ws[col + str(current_row_number)].alignment = c_c_alignment
619
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " + _('Datetime')
620
621
                for i in range(0, reporting_period_data_ca_len):
622
                    current_col_number += 1
623
                    col = format_cell.get_column_letter(current_col_number)
624
                    ws[col + str(current_row_number)].fill = table_fill
625
                    ws[col + str(current_row_number)].font = title_font
626
                    ws[col + str(current_row_number)].alignment = c_c_alignment
627
                    ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
628
                        + reporting_period_data['names'][i] + " (" + \
629
                        reporting_period_data['units'][i] + ")"
630
                    ws[col + str(current_row_number)].border = f_border
631
632
                current_col_number += 1
633
                col = format_cell.get_column_letter(current_col_number)
634
                ws[col + str(current_row_number)].fill = table_fill
635
                ws[col + str(current_row_number)].font = title_font
636
                ws[col + str(current_row_number)].alignment = c_c_alignment
637
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
638
                    + _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
639
                ws[col + str(current_row_number)].border = f_border
640
641
                current_row_number += 1
642
643
                max_timestamps_len = len(base_period_timestamps[0]) \
644
                    if len(base_period_timestamps[0]) >= len(reporting_period_timestamps[0]) \
645
                    else len(reporting_period_timestamps[0])
646
647
                for i in range(0, max_timestamps_len):
648
                    current_col_number = 2
649
                    col = format_cell.get_column_letter(current_col_number)
650
                    ws[col + str(current_row_number)].font = title_font
651
                    ws[col + str(current_row_number)].alignment = c_c_alignment
652
                    ws[col + str(current_row_number)] = base_period_timestamps[0][i] \
653
                        if i < len(base_period_timestamps[0]) else None
654
                    ws[col + str(current_row_number)].border = f_border
655
656
                    base_period_total = Decimal(0.0)
657
658
                    for j in range(0, base_period_data_ca_len):
659
                        current_col_number += 1
660
                        col = format_cell.get_column_letter(current_col_number)
661
662
                        ws[col + str(current_row_number)].font = title_font
663
                        ws[col + str(current_row_number)].alignment = c_c_alignment
664
                        ws[col + str(current_row_number)] = round(base_period_data['values'][j][i], 2) \
665
                            if i < len(base_period_data['values'][j]) else None
666
                        if i < len(base_period_timestamps[0]):
667
                            base_period_total += base_period_data['values'][j][i]
668
                        ws[col + str(current_row_number)].border = f_border
669
670
                    current_col_number += 1
671
                    col = format_cell.get_column_letter(current_col_number)
672
                    ws[col + str(current_row_number)].font = title_font
673
                    ws[col + str(current_row_number)].alignment = c_c_alignment
674
                    ws[col + str(current_row_number)] = round(base_period_total, 2) \
675
                        if i < len(base_period_timestamps[0]) else None
676
                    ws[col + str(current_row_number)].border = f_border
677
678
                    current_col_number += 1
679
                    col = format_cell.get_column_letter(current_col_number)
680
681
                    ws[col + str(current_row_number)].font = title_font
682
                    ws[col + str(current_row_number)].alignment = c_c_alignment
683
                    ws[col + str(current_row_number)] = reporting_period_timestamps[0][i] \
684
                        if i < len(reporting_period_timestamps[0]) else None
685
                    ws[col + str(current_row_number)].border = f_border
686
687
                    reporting_period_total = Decimal(0.0)
688
689
                    for j in range(0, reporting_period_data_ca_len):
690
                        current_col_number += 1
691
                        col = format_cell.get_column_letter(current_col_number)
692
693
                        ws[col + str(current_row_number)].font = title_font
694
                        ws[col + str(current_row_number)].alignment = c_c_alignment
695
                        ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \
696
                            if i < len(reporting_period_data['values'][j]) else None
697
                        if i < len(reporting_period_timestamps[0]):
698
                            reporting_period_total += reporting_period_data['values'][j][i]
699
                        ws[col + str(current_row_number)].border = f_border
700
701
                    current_col_number += 1
702
                    col = format_cell.get_column_letter(current_col_number)
703
                    ws[col + str(current_row_number)].font = title_font
704
                    ws[col + str(current_row_number)].alignment = c_c_alignment
705
                    ws[col + str(current_row_number)] = round(reporting_period_total, 2) \
706
                        if i < len(reporting_period_timestamps[0]) else None
707
                    ws[col + str(current_row_number)].border = f_border
708
709
                    current_row_number += 1
710
711
                current_col_number = 2
712
                col = format_cell.get_column_letter(current_col_number)
713
                ws[col + str(current_row_number)].font = title_font
714
                ws[col + str(current_row_number)].alignment = c_c_alignment
715
                ws[col + str(current_row_number)] = _('Subtotal')
716
                ws[col + str(current_row_number)].border = f_border
717
718
                base_period_subtotals = Decimal(0.0)
719
720
                for i in range(0, base_period_data_ca_len):
721
                    current_col_number += 1
722
                    col = format_cell.get_column_letter(current_col_number)
723
                    ws[col + str(current_row_number)].font = title_font
724
                    ws[col + str(current_row_number)].alignment = c_c_alignment
725
                    ws[col + str(current_row_number)] = round(base_period_data['subtotals'][i], 2)
726
                    base_period_subtotals += base_period_data['subtotals'][i]
727
                    ws[col + str(current_row_number)].border = f_border
728
729
                current_col_number += 1
730
                col = format_cell.get_column_letter(current_col_number)
731
                ws[col + str(current_row_number)].font = title_font
732
                ws[col + str(current_row_number)].alignment = c_c_alignment
733
                ws[col + str(current_row_number)] = round(base_period_subtotals, 2)
734
                ws[col + str(current_row_number)].border = f_border
735
736
                current_col_number += 1
737
                col = format_cell.get_column_letter(current_col_number)
738
739
                ws[col + str(current_row_number)].font = title_font
740
                ws[col + str(current_row_number)].alignment = c_c_alignment
741
                ws[col + str(current_row_number)] = _('Subtotal')
742
                ws[col + str(current_row_number)].border = f_border
743
744
                reporting_period_subtotals = Decimal(0.0)
745
746
                for i in range(0, reporting_period_data_ca_len):
747
                    current_col_number += 1
748
                    col = format_cell.get_column_letter(current_col_number)
749
                    ws[col + str(current_row_number)].font = title_font
750
                    ws[col + str(current_row_number)].alignment = c_c_alignment
751
                    ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
752
                    reporting_period_subtotals += reporting_period_data['subtotals'][i]
753
                    ws[col + str(current_row_number)].border = f_border
754
755
                current_col_number += 1
756
                col = format_cell.get_column_letter(current_col_number)
757
                ws[col + str(current_row_number)].font = title_font
758
                ws[col + str(current_row_number)].alignment = c_c_alignment
759
                ws[col + str(current_row_number)] = round(reporting_period_subtotals, 2)
760
                ws[col + str(current_row_number)].border = f_border
761
762
                for i in range(0, reporting_period_data_ca_len):
763
                    # line
764
                    line = LineChart()
765
                    line.title = _('Base Period Costs') + " / " \
766
                        + _('Reporting Period Costs') + ' - ' \
767
                        + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
768
                    labels = Reference(ws, min_col=2 + base_period_data_ca_len + 1 + 1,
769
                                       min_row=table_start_row_number + 1,
770
                                       max_row=table_start_row_number + len(reporting_period_timestamps[0]))
771
                    base_line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
772
                                               max_row=table_start_row_number + len(reporting_period_timestamps[0]))
773
                    reporting_line_data = Reference(ws, min_col=3 + base_period_data_ca_len + 1 + 1 + i,
774
                                                    min_row=table_start_row_number,
775
                                                    max_row=table_start_row_number
776
                                                    + len(reporting_period_timestamps[0]))
777
                    line.add_data(base_line_data, titles_from_data=True)
778
                    line.add_data(reporting_line_data, titles_from_data=True)
779
                    line.set_categories(labels)
780
                    for j in range(len(line.series)):
781
                        line.series[j].marker.symbol = "circle"
782
                        line.series[j].smooth = True
783
                    line.x_axis.crosses = 'min'
784
                    line.height = 8.25
785
                    line.width = 24
786
                    line.dLbls = DataLabelList()
787
                    line.dLbls.dLblPos = 't'
788
                    line.dLbls.showVal = True
789
                    line.dLbls.showPercent = False
790
                    chart_col = 'B'
791
                    chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
792
                    ws.add_chart(line, chart_cell)
793
794
                current_row_number += 2
795
796
    ####################################################################################################################
797
    current_sheet_parameters_row_number = table_start_draw_flag + len(reporting_period_data['names']) * 6 + 1
798
    if 'parameters' not in report.keys() or \
799
            report['parameters'] is None or \
800
            'names' not in report['parameters'].keys() or \
801
            report['parameters']['names'] is None or \
802
            len(report['parameters']['names']) == 0 or \
803
            'timestamps' not in report['parameters'].keys() or \
804
            report['parameters']['timestamps'] is None or \
805
            len(report['parameters']['timestamps']) == 0 or \
806
            'values' not in report['parameters'].keys() or \
807
            report['parameters']['values'] is None or \
808
            len(report['parameters']['values']) == 0 or \
809
            timestamps_data_all_equal_0(report['parameters']['timestamps']):
810
        pass
811
    else:
812
813
        ################################################################################################################
814
        # new worksheet
815
        ################################################################################################################
816
817
        parameters_data = report['parameters']
818
819
        parameters_names_len = len(parameters_data['names'])
820
821
        file_name = "Store" + re.sub(r'[^A-Z]', '', ws.title.strip('S')) + "_"
822
        parameters_ws = wb.create_sheet(file_name + _('Parameters'))
823
824
        parameters_timestamps_data_max_len = \
825
            get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
826
827
        # Row height
828
        parameters_ws.row_dimensions[1].height = 102
829
        for i in range(2, 7 + 1):
830
            parameters_ws.row_dimensions[i].height = 42
831
832
        for i in range(8, parameters_timestamps_data_max_len + 10):
833
            parameters_ws.row_dimensions[i].height = 60
834
835
        # Col width
836
        parameters_ws.column_dimensions['A'].width = 1.5
837
838
        parameters_ws.column_dimensions['B'].width = 25.0
839
840
        for i in range(3, 12 + parameters_names_len * 3):
841
            parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
842
843
        # Img
844
        img = Image("excelexporters/myems.png")
845
        parameters_ws.add_image(img, 'A1')
846
847
        # Title
848
        parameters_ws['B3'].alignment = b_r_alignment
849
        parameters_ws['B3'] = _('Name') + ':'
850
        parameters_ws['C3'].border = b_border
851
        parameters_ws['C3'].alignment = b_c_alignment
852
        parameters_ws['C3'] = name
853
854
        parameters_ws['D3'].alignment = b_r_alignment
855
        parameters_ws['D3'] = _('Period Type') + ':'
856
        parameters_ws['E3'].border = b_border
857
        parameters_ws['E3'].alignment = b_c_alignment
858
        parameters_ws['E3'] = period_type
859
860
        parameters_ws['B4'].alignment = b_r_alignment
861
        parameters_ws['B4'] = _('Reporting Start Datetime') + ':'
862
        parameters_ws['C4'].border = b_border
863
        parameters_ws['C4'].alignment = b_c_alignment
864
        parameters_ws['C4'] = reporting_start_datetime_local
865
866
        parameters_ws['D4'].alignment = b_r_alignment
867
        parameters_ws['D4'] = _('Reporting End Datetime') + ':'
868
        parameters_ws['E4'].border = b_border
869
        parameters_ws['E4'].alignment = b_c_alignment
870
        parameters_ws['E4'] = reporting_end_datetime_local
871
872
        parameters_ws_current_row_number = 6
873
874
        parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
875
        parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' ' + _('Parameters')
876
877
        parameters_ws_current_row_number += 1
878
879
        parameters_table_start_row_number = parameters_ws_current_row_number
880
881
        parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
882
883
        parameters_ws_current_row_number += 1
884
885
        table_current_col_number = 2
886
887
        for i in range(0, parameters_names_len):
888
889
            if len(parameters_data['timestamps'][i]) == 0:
890
                continue
891
892
            col = format_cell.get_column_letter(table_current_col_number)
893
894
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
895
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
896
897
            col = format_cell.get_column_letter(table_current_col_number + 1)
898
899
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
900
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
901
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
902
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
903
            parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
904
905
            table_current_row_number = parameters_ws_current_row_number
906
907
            for j, value in enumerate(list(parameters_data['timestamps'][i])):
908
                col = format_cell.get_column_letter(table_current_col_number)
909
910
                parameters_ws[col + str(table_current_row_number)].border = f_border
911
                parameters_ws[col + str(table_current_row_number)].font = title_font
912
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
913
                parameters_ws[col + str(table_current_row_number)] = value
914
915
                col = format_cell.get_column_letter(table_current_col_number + 1)
916
917
                parameters_ws[col + str(table_current_row_number)].border = f_border
918
                parameters_ws[col + str(table_current_row_number)].font = title_font
919
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
920
                parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2)
921
922
                table_current_row_number += 1
923
924
            table_current_col_number = table_current_col_number + 3
925
926
        ################################################################################################################
927
        # parameters chart and parameters table
928
        ################################################################################################################
929
930
        ws['B' + str(current_sheet_parameters_row_number)].font = title_font
931
        ws['B' + str(current_sheet_parameters_row_number)] = name + ' ' + _('Parameters')
932
933
        current_sheet_parameters_row_number += 1
934
935
        chart_start_row_number = current_sheet_parameters_row_number
936
937
        col_index = 0
938
939
        for i in range(0, parameters_names_len):
940
941
            if len(parameters_data['timestamps'][i]) == 0:
942
                continue
943
944
            line = LineChart()
945
            data_col = 3 + col_index * 3
946
            labels_col = 2 + col_index * 3
947
            col_index += 1
948
            line.title = _('Parameters') + ' - ' + \
949
                parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
950
            labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
951
                               max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
952
            line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
953
                                  max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
954
            line.add_data(line_data, titles_from_data=True)
955
            line.set_categories(labels)
956
            line_data = line.series[0]
957
            line_data.marker.symbol = "circle"
958
            line_data.smooth = True
959
            line.x_axis.crosses = 'min'
960
            line.height = 8.25
961
            line.width = 24
962
            line.dLbls = DataLabelList()
963
            line.dLbls.dLblPos = 't'
964
            line.dLbls.showVal = False
965
            line.dLbls.showPercent = False
966
            chart_col = 'B'
967
            chart_cell = chart_col + str(chart_start_row_number)
968
            chart_start_row_number += 6
969
            ws.add_chart(line, chart_cell)
970
971
        current_sheet_parameters_row_number = chart_start_row_number
972
973
        current_sheet_parameters_row_number += 1
974
975
    filename = str(uuid.uuid4()) + '.xlsx'
976
    wb.save(filename)
977
978
    return filename
979
980
981
def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists):
982
    max_len = 0
983
    for i, value in enumerate(list(parameters_timestamps_lists)):
984
        if len(value) > max_len:
985
            max_len = len(value)
986
987
    return max_len
988
989
990
def timestamps_data_all_equal_0(lists):
991
    for i, value in enumerate(list(lists)):
992
        if len(value) > 0:
993
            return False
994
995
    return True
996
997
998
def timestamps_data_not_equal_0(lists):
999
    number = 0
1000
    for i, value in enumerate(list(lists)):
1001
        if len(value) > 0:
1002
            number += 1
1003
    return number
1004
1005
1006 View Code Duplication
def is_base_period_timestamp_exists(base_period_data):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1007
    timestamps = base_period_data['timestamps']
1008
1009
    if len(timestamps) == 0:
1010
        return False
1011
1012
    for timestamp in timestamps:
1013
        if len(timestamp) > 0:
1014
            return True
1015
1016
    return False
1017