Issues (1656)

myems-api/excelexporters/tenantbill.py (3 issues)

1
import base64
2
import datetime
3
from core.utilities import get_translation
4
import os
5
import uuid
6
from decimal import Decimal
7
from openpyxl import Workbook
8
from openpyxl.drawing.image import Image
9
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
10
from core.utilities import round2
11
12
########################################################################################################################
13
# PROCEDURES
14
# Step 1: Validate the report data
15
# Step 2: Generate excel file
16
# Step 3: Encode the excel file to Base64
17
########################################################################################################################
18
19
20 View Code Duplication
def export(report,
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
21
           name,
22
           reporting_start_datetime_local,
23
           reporting_end_datetime_local,
24
           period_type,
25
           language):
26
    ####################################################################################################################
27
    # Step 1: Validate the report data
28
    ####################################################################################################################
29
    if report is None:
30
        return None
31
32
    ####################################################################################################################
33
    # Step 2: Generate excel file from the report data
34
    ####################################################################################################################
35
    filename = generate_excel(report,
36
                              name,
37
                              reporting_start_datetime_local,
38
                              reporting_end_datetime_local,
39
                              period_type,
40
                              language)
41
    ####################################################################################################################
42
    # Step 3: Encode the excel file to Base64
43
    ####################################################################################################################
44
    binary_file_data = b''
45
    try:
46
        with open(filename, 'rb') as binary_file:
47
            binary_file_data = binary_file.read()
48
    except IOError as ex:
49
        print(str(ex))
50
51
    # Base64 encode the bytes
52
    base64_encoded_data = base64.b64encode(binary_file_data)
53
    # get the Base64 encoded data using human-readable characters.
54
    base64_message = base64_encoded_data.decode('utf-8')
55
    # delete the file from server
56
    try:
57
        os.remove(filename)
58
    except NotImplementedError as ex:
59
        print(str(ex))
60
    return base64_message
61
62
63
def generate_excel(report,
64
                   name,
65
                   reporting_start_datetime_local,
66
                   reporting_end_datetime_local,
67
                   period_type,
68
                   language):
69
70
    trans = get_translation(language)
71
    trans.install()
72
    _ = trans.gettext
73
74
    wb = Workbook()
75
    ws = wb.active
76
    ws.title = "TenantBill"
77
78
    # Row height
79
    for i in range(1, 11 + 1):
80
        ws.row_dimensions[i].height = 0.1
81
    ws.row_dimensions[12].height = 30.0
82
    ws.row_dimensions[13].height = 10.0
83
    ws.merge_cells('B13:I13')
84
    for i in range(14, 23 + 1):
85
        ws.row_dimensions[i].height = 0.1
86
    ws.row_dimensions[24].height = 20.0
87
    ws.row_dimensions[25].height = 10.0
88
    ws.merge_cells('B25:I25')
89
    for i in range(26, 35 + 1):
90
        ws.row_dimensions[i].height = 0.1
91
    for i in range(36, 41 + 1):
92
        ws.row_dimensions[i].height = 20.0
93
    ws.row_dimensions[42].height = 10.0
94
    ws.merge_cells('B42:I42')
95
    for i in range(43, 52 + 1):
96
        ws.row_dimensions[i].height = 0.1
97
98
    # Col width
99
    ws.column_dimensions['A'].width = 1.5
100
    for i in range(ord('B'), ord('J')):
101
        ws.column_dimensions[chr(i)].width = 16
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable chr does not seem to be defined.
Loading history...
102
    ws.column_dimensions['J'].width = 1.5
103
104
    # merge cell
105
    ws.merge_cells('C12:H12')
106
107
    ws.merge_cells('C24:I24')
108
109
    # Font
110
    notice_font = Font(name='Arial', size=20, bold=True)
111
    name_font = Font(name='Arial', size=12, bold=True)
112
    title_font = Font(name='Arial', size=11, bold=True)
113
114
    table_fill = PatternFill(fill_type='solid', fgColor='90ee90')
115
    f_border = Border(left=Side(border_style='medium'),
116
                      right=Side(border_style='medium'),
117
                      bottom=Side(border_style='medium'),
118
                      top=Side(border_style='medium')
119
                      )
120
121
    c_c_alignment = Alignment(vertical='center',
122
                              horizontal='center',
123
                              text_rotation=0,
124
                              wrap_text=True,
125
                              shrink_to_fit=False,
126
                              indent=0)
127
    b_r_alignment = Alignment(vertical='bottom',
128
                              horizontal='right',
129
                              text_rotation=0,
130
                              wrap_text=True,
131
                              shrink_to_fit=False,
132
                              indent=0)
133
    b_l_alignment = Alignment(vertical='bottom',
134
                              horizontal='left',
135
                              text_rotation=0,
136
                              wrap_text=True,
137
                              shrink_to_fit=False,
138
                              indent=0)
139
140
    ws['C12'].font = notice_font
141
    ws['C12'].alignment = c_c_alignment
142
    ws['C12'] = _('Payment Notice')
143
144
    # img
145
    img = Image("excelexporters/myemslogo.png")
146
    img.width = 117
147
    img.height = 117
148
    ws.add_image(img, 'I12')
149
150
    if "tenant" not in report.keys() or \
151
            report['tenant'] is None or \
152
            'lease_number' not in report['tenant'].keys() or \
153
            report['tenant']['lease_number'] is None:
154
        ws.row_dimensions[24].height = 0.1
155
    else:
156
        ws['B24'].font = name_font
157
        ws['B24'].alignment = b_r_alignment
158
        ws['B24'] = _('Lease Number') + ':'
159
        ws['C24'].alignment = b_l_alignment
160
        ws['C24'].font = name_font
161
        ws['C24'] = report['tenant']['lease_number']
162
163
    if "tenant" not in report.keys() or \
164
            report['tenant'] is None:
165
        for i in range(36, 41 + 1):
166
            ws.row_dimensions[i].height = 0.1
167
    else:
168
        report_tenant_data = report['tenant']
169
        for i in range(36, 41 + 1):
170
            ws.merge_cells('C{}:D{}'.format(i, i))
171
            ws['C' + str(i)].alignment = b_l_alignment
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable str does not seem to be defined.
Loading history...
172
            ws['C' + str(i)].font = name_font
173
174
        ws['C36'] = report_tenant_data['name']
175
        ws.merge_cells('E36:I36')
176
177
        ws['C37'] = report_tenant_data['rooms']
178
179
        ws['C38'] = report_tenant_data['floors']
180
181
        ws['C39'] = report_tenant_data['buildings']
182
183
        ws['C40'] = report_tenant_data['email']
184
185
        ws['C41'] = report_tenant_data['phone']
186
187
        for i in range(37, 41 + 1):
188
            ws.merge_cells('E{}:G{}'.format(i, i))
189
            ws.merge_cells('H{}:I{}'.format(i, i))
190
            ws['E' + str(i)].alignment = b_r_alignment
191
            ws['E' + str(i)].font = name_font
192
            ws['H' + str(i)].alignment = b_l_alignment
193
            ws['H' + str(i)].font = name_font
194
195
        ws['E37'] = _('Bill Number') + ':'
196
        ws['E38'] = _('Lease Contract Number') + ':'
197
        ws['E39'] = _('Bill Date') + ':'
198
        ws['E40'] = _('Payment Due Date') + ':'
199
        ws['E41'] = _('Amount Payable') + ':'
200
201
        # Simulated data
202
        ws['H37'] = ''
203
        ws['H38'] = report_tenant_data['lease_number']
204
        ws['H39'] = datetime.datetime.strptime(reporting_start_datetime_local, '%Y-%m-%dT%H:%M:%S').isoformat()[0:10]
205
        ws['H40'] = datetime.datetime.strptime(reporting_end_datetime_local, '%Y-%m-%dT%H:%M:%S').isoformat()[0:10]
206
        ws['H41'] = report['reporting_period']['currency_unit'] + \
207
            str(round2(report['reporting_period']['total_cost']
208
                       if 'reporting_period' in report.keys()
209
                          and 'total_cost' in report['reporting_period'].keys()
210
                          and report['reporting_period']['total_cost'] is not None
211
                       else 0, 2))
212
213
    if 'reporting_period' not in report.keys() \
214
            or report['reporting_period'] is None:
215
        pass
216
    else:
217
        ws.row_dimensions[53].height = 25.0
218
        for i in range(ord('B'), ord('J')):
219
            ws[chr(i) + '53'].fill = table_fill
220
            ws[chr(i) + '53'].font = title_font
221
            ws[chr(i) + '53'].alignment = c_c_alignment
222
            ws[chr(i) + '53'].border = f_border
223
224
        ws['B53'] = _('Energy Category')
225
        ws['C53'] = _('Billing Period Start')
226
        ws['D53'] = _('Billing Period End')
227
        ws['E53'] = _('Quantity')
228
        ws['F53'] = _('Unit')
229
        ws['G53'] = _('Amount')
230
        ws['H53'] = _('Tax Rate')
231
        ws['I53'] = _('VAT Output Tax')
232
233
        reporting_period_data = report['reporting_period']
234
        names = reporting_period_data['names']
235
        ca_len = len(names) if names is not None else 0
236
237
        for i in range(54, 54 + ca_len):
238
            ws.row_dimensions[i].height = 20.0
239
            for j in range(ord('B'), ord('J')):
240
                ws[chr(j) + str(i)].font = title_font
241
                ws[chr(j) + str(i)].alignment = c_c_alignment
242
                ws[chr(j) + str(i)].border = f_border
243
244
                if chr(j) == 'B':
245
                    ws[chr(j) + str(i)] = reporting_period_data['names'][i - 54]
246
                elif chr(j) == 'C':
247
                    ws[chr(j) + str(i)] = datetime.datetime.strptime(reporting_start_datetime_local,
248
                                                                     '%Y-%m-%dT%H:%M:%S').isoformat()[0:10]
249
                elif chr(j) == 'D':
250
                    ws[chr(j) + str(i)] = datetime.datetime.strptime(reporting_end_datetime_local,
251
                                                                     '%Y-%m-%dT%H:%M:%S').isoformat()[0:10]
252
                elif chr(j) == 'E':
253
                    ws[chr(j) + str(i)] = round2(reporting_period_data['subtotals_input'][i - 54], 3)
254
                elif chr(j) == 'F':
255
                    ws[chr(j) + str(i)] = reporting_period_data['units'][i - 54]
256
                elif chr(j) == 'G':
257
                    ws[chr(j) + str(i)] = round2(reporting_period_data['subtotals_cost'][i - 54], 2)
258
                elif chr(j) == 'H':
259
                    # Simulated data
260
                    ws[chr(j) + str(i)] = 0
261
                elif chr(j) == 'I':
262
                    # Simulated data
263
                    ws[chr(j) + str(i)] = 0
264
265
        ws.row_dimensions[54 + ca_len].height = 10.0
266
        ws.merge_cells('B{}:H{}'.format((54 + ca_len), (54 + ca_len)))
267
268
        current_row_number = 54 + ca_len + 1
269
        for i in range(current_row_number, current_row_number + 3):
270
            ws.row_dimensions[i].height = 20.0
271
            ws['B' + str(i)].alignment = b_r_alignment
272
            ws['B' + str(i)].font = name_font
273
            ws['H' + str(i)].alignment = b_l_alignment
274
            ws['H' + str(i)].font = name_font
275
            ws.merge_cells('B{}:G{}'.format(i, i))
276
            ws.merge_cells('H{}:I{}'.format(i, i))
277
278
        ws['B' + str(current_row_number)] = _('Subtotal') + ':'
279
        ws['H' + str(current_row_number)] = report['reporting_period']['currency_unit'] + str(
280
            round2(report['reporting_period']['total_cost']
281
                   if 'reporting_period' in report.keys()
282
                      and 'total_cost' in report['reporting_period'].keys()
283
                      and report['reporting_period']['total_cost'] is not None
284
                   else 0, 2))
285
286
        current_row_number += 1
287
288
        # Simulated data
289
        taxes = Decimal(0.00)
290
291
        ws['B' + str(current_row_number)] = _('VAT Output Tax') + ':'
292
        ws['H' + str(current_row_number)] = report['reporting_period']['currency_unit'] + str(round2(taxes, 2))
293
294
        current_row_number += 1
295
296
        ws['B' + str(current_row_number)] = _('Total Amount Payable') + ':'
297
        ws['H' + str(current_row_number)] = report['reporting_period']['currency_unit'] + str(
298
            round2(report['reporting_period']['total_cost'] + taxes
299
                   if 'reporting_period' in report.keys()
300
                      and 'total_cost' in report['reporting_period'].keys()
301
                      and report['reporting_period']['total_cost'] is not None
302
                   else 0 + taxes, 2))
303
304
    filename = str(uuid.uuid4()) + '.xlsx'
305
    wb.save(filename)
306
307
    return filename
308