root 1 год назад
Сommit
dd58f55aaf
6 измененных файлов с 364 добавлено и 0 удалено
  1. 10 0
      Dockerfile
  2. 139 0
      data_employee.py
  3. 8 0
      docker-compose.yml
  4. 36 0
      employee_attendance.py
  5. 15 0
      requirements.txt
  6. 156 0
      xlsx_creator.py

+ 10 - 0
Dockerfile

@@ -0,0 +1,10 @@
+FROM python:3
+
+WORKDIR /usr/src/app
+
+COPY requirements.txt ./
+RUN pip --proxy http://proxy00.kbsu:3128 install --no-cache-dir -r requirements.txt
+
+COPY . .
+
+CMD [ "python", "./employee_attendance.py" ]

+ 139 - 0
data_employee.py

@@ -0,0 +1,139 @@
+import requests
+import json
+from datetime import datetime, timedelta
+
+
+class DataEmployee:
+    
+    
+    DATA = []
+    API = "http://http-service:http-service@172.16.10.231/acms/hs/api/getbyfio/"
+    
+    def __init__(self, fios, startDate, endDate):
+        self.fios = fios
+        self.startDate = startDate
+        self.endDate = endDate
+        self.get_correct_data_to_table()
+
+    class EmployeesTable():
+        Headers = [
+            {
+                'text': 'День недели',
+                'value': 'wd'
+            },{
+                'text': 'Дата',
+                'value': 'date'
+            },{
+                'text': 'Вход',
+                'value': 'entrance'
+            },{
+                'text': 'Выход',
+                'value': 'exit'
+            },{
+                'text': 'Время пребывания',
+                'value': 'diffTime'
+            }
+        ]
+
+    class DateAttendance:
+        WEEKDAYS = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']
+
+        def __init__(self, date, startDate = None, endDate = None):
+            dateD = datetime.fromisoformat(date)
+            self.wd = self.WEEKDAYS[dateD.weekday()],
+            self.date = dateD.strftime('%d.%m.%Y'),
+
+            if startDate is None and endDate is None:
+                self.entrance = None,
+                self.exit = None
+                self.diffTime = None
+            else:
+                self.entrance = startDate.split('T')[1],
+                self.exit = endDate.split('T')[1]
+                self.diffTime = str(self.get_diff_time(startDate, endDate))
+            
+
+        def get_diff_time(self, startDate, endDate):
+            start = datetime.fromisoformat(startDate)
+            end = datetime.fromisoformat(endDate)
+            return abs(end-start)
+
+    def get_range_date(self):
+        start = datetime.fromisoformat(self.startDate)
+        end = datetime.fromisoformat(self.endDate)
+        range_date = []
+        while start <= end:
+            range_date.append(start)
+            start += timedelta(days=1)
+        
+        return range_date
+
+    def get_correct_data_to_table(self):
+        self.DATA = []
+        date_range = self.get_range_date()
+
+        for data in self.get_data_from_api():
+            
+            employee = self.EmployeesTable()
+            employee.FIO = data['fio']
+            employee.DatesAttendance = []
+            employee.EmptyDatesAttendance = []
+            
+            dates = [x['d'] for x in data['data']]
+            print(dates)
+            for date in self.get_range_date():
+                if date.strftime('%Y-%m-%d') not in dates:
+                    employee.EmptyDatesAttendance.append(self.DateAttendance(str(date)))
+            
+            for d_attandence in data['data']:
+                employee.DatesAttendance.append(self.DateAttendance(d_attandence['d'],
+                    d_attandence['d_first'],
+                    d_attandence['d_last']))
+
+            self.DATA.append(employee)
+
+
+    def get_data_from_api(self):
+        data = []
+        for link_api in self.create_links_api():
+	    response = requests.get(link_api)
+	    try:
+		data.append(json.loads(response.text))
+	    except json.decoder.JSONDecodeError:
+		response.encoding = 'utf-8-sig'
+		data.append(json.loads(response.text))
+
+        return data
+
+    def get_json(self):
+        obj_json = []
+        for data in self.DATA:
+            obj_json.append({
+                'FIO': data.FIO,
+                'STARTDATE': self.startDate,
+                'ENDDATE': self.endDate,
+                'HEADERS': data.Headers,
+                'EmptyDatesAttendance': [{
+                    'wd': x.wd,
+                    'date': x.date,
+                    'entrance': '',
+                    'exit': '',
+                    'diffTime': ''
+                    } for x in data.EmptyDatesAttendance ],
+                'DateAttendance': [{
+                    'wd': x.wd,
+                    'date': x.date,
+                    'entrance': x.entrance,
+                    'exit': x.exit,
+                    'diffTime': str(x.diffTime)
+                } for x in data.DatesAttendance]
+            })
+
+        return obj_json
+
+    def create_links_api(self):
+        list_api = []
+        for fio in self.fios:
+            list_api.append(self.API+fio+'/'+self.startDate.replace('-', '')+'/'+self.endDate.replace('-', ''))
+        
+        return list_api

+ 8 - 0
docker-compose.yml

@@ -0,0 +1,8 @@
+version: '3'
+
+services:
+  my_python: 
+    build: .
+    restart: always
+    ports:
+      - '2029:5000'

+ 36 - 0
employee_attendance.py

@@ -0,0 +1,36 @@
+from flask import Flask, request, Response, jsonify, send_file
+from data_employee import DataEmployee
+from xlsx_creator import xlsx_creator
+import json
+
+app = Flask(__name__)
+
+
+@app.after_request
+def after_request(response):
+    response.headers.add('Access-Control-Allow-Origin', '*')
+    response.headers.add('Access-Control-Allow-Headers',
+                         'Content-Type,Authorization')
+    response.headers.add('Access-Control-Allow-Methods',
+                         'GET,PUT,POST,DELETE,OPTIONS')
+    return response
+
+
+@app.route('/get_data', methods=['POST'])
+def get_data():
+    FIOS = request.values['fios'].split(',')
+    STARTDATE = request.values['startDate']
+    ENDDATE = request.values['endDate']
+    DATA = DataEmployee(FIOS, STARTDATE, ENDDATE)
+
+    return jsonify(DATA.get_json())
+
+
+@app.route('/get_xlsx_file', methods=['POST'])
+def get_xlsx_file():
+    xlsx = xlsx_creator(json.loads(request.data))
+    return send_file(xlsx.cook_xlsx(), as_attachment=xlsx.FileName)
+
+
+if __name__ == "__main__":
+    app.run(host='0.0.0.0')

+ 15 - 0
requirements.txt

@@ -0,0 +1,15 @@
+autopep8==1.6.0
+certifi==2021.10.8
+charset-normalizer==2.0.12
+click==8.1.3
+Flask==2.1.2
+idna==3.3
+itsdangerous==2.1.2
+Jinja2==3.1.2
+MarkupSafe==2.1.1
+pycodestyle==2.8.0
+requests==2.27.1
+toml==0.10.2
+urllib3==1.26.9
+Werkzeug==2.1.2
+XlsxWriter==3.0.3

+ 156 - 0
xlsx_creator.py

@@ -0,0 +1,156 @@
+import xlsxwriter
+from xlsxwriter.utility import xl_range
+from datetime import datetime, timedelta
+
+class xlsx_creator():
+    style_header = {
+        'bold': True,
+        'border': 1,
+        'align': 'center',
+        'valign': 'vcenter'    
+    }
+
+    def __init__(self, DATA, path='/tmp/'):
+        self.FileName= F"employee-attendance-{str(datetime.now())}.xlsx"
+        self.path = path+self.FileName
+        self.DATA = DATA
+        self.workbook = xlsxwriter.Workbook(self.path)
+        self.worksheet = self.workbook.add_worksheet()
+
+    def cook_xlsx(self):
+        self.create_header()
+        self.create_diff_date_and_hours()
+        self.create_sub_head()
+        self.create_body_data()
+        self.workbook.close()
+        return self.path
+
+    def create_header(self):
+        self.worksheet.set_row(0, 70)
+        style_header = self.workbook.add_format(self.style_header)
+        style_header.set_text_wrap() 
+
+        colum = 0     
+        
+        for data in self.DATA:
+            text_header = F"{data['FIO']} \n посещаемость с {data['STARTDATE']}г. по {data['ENDDATE']}г."
+            self.worksheet.merge_range(self.get_column_range(0, colum, 0, colum+4), text_header, style_header)
+            colum += 6
+
+    def convert_str_to_datetime(self, date_string):
+        (h,m,s) = date_string.split(':')
+        return timedelta(hours=int(h), minutes=int(m), seconds=int(s))
+
+    def get_count_work_hours(self, DateAttendance):
+        count_work_hours = timedelta()
+        for x in DateAttendance:
+            count_work_hours += self.convert_str_to_datetime(self.return_correct_value(x["diffTime"]))
+
+        hours, remainder = divmod(count_work_hours.total_seconds(), 3600)
+        minutes, seconds = divmod(remainder, 60)
+        print(count_work_hours)
+        return F"{int(hours)}:{int(minutes)}:{int(seconds)}"
+
+
+    def create_diff_date_and_hours(self):
+        style_body = self.workbook.add_format({
+            'border': 1,
+            'align': 'center',  
+        })
+        style_header = self.workbook.add_format(self.style_header)
+        col_work_day_text = "Количество рабочих дней"
+        col_calendar_day = "Количество календарных дней"
+        col_work_hours = "Количество рабочих часов"
+        column = 0
+
+        for data in self.DATA:
+            self.worksheet.merge_range(self.get_column_range(1, column, 1, column+3),
+                                        col_work_day_text, style_header)
+            self.worksheet.write(1, column+4, len(data['DateAttendance']), style_body)    
+
+            self.worksheet.merge_range(self.get_column_range(2, column, 2, column+3),
+                                       col_calendar_day, style_header)
+            self.worksheet.write(2, column+4, len(data['EmptyDatesAttendance']+data['DateAttendance']), style_body)    
+
+            self.worksheet.merge_range(self.get_column_range(3, column, 3, column+3),
+                                       col_work_hours, style_header)
+            self.worksheet.write(3, column+4, self.get_count_work_hours(data['DateAttendance']), style_body)
+            column += 6
+
+
+    def create_sub_head(self):
+        colum = 0
+        style_header = self.workbook.add_format(self.style_header)
+        style_header.set_text_wrap() 
+        self.worksheet.set_row(4, 30)
+
+
+        for data in self.DATA:
+            self.worksheet.write(4, colum, 'Д/н', style_header)
+            self.worksheet.write(4, colum+1, 'Дата', style_header)
+            self.worksheet.write(4, colum+2, 'Вход',  style_header)
+            self.worksheet.write(4, colum+3, 'Выход',  style_header)
+
+            self.worksheet.set_column(4, colum+4, 15)
+            self.worksheet.write(4, colum+4, 'Время пребывания', style_header)
+            colum += 6
+
+
+    def get_column_range(self, srow, scolumn, erow, ecolumn):
+        return xl_range(srow, scolumn, erow, ecolumn)
+
+    def sort_attendance(self, arr):
+        return sorted(arr, key=lambda x : datetime.strptime(self.return_correct_value(x['date']), '%d.%m.%Y'))
+
+    def is_bold_diff_time(self, val, s, b):
+        val = self.return_correct_value(val)
+        
+        if len(val) > 0:
+            if int(val.split(':')[0]) > 7:
+                return b
+        return s
+        
+    def is_bold_entrance(self, val, s, b):
+        val = self.return_correct_value(val)
+        
+        if len(val) > 0:
+            hours = val.split(':')[0]
+            if int(hours) >= 9 and int(hours) <= 18:
+                return b
+        return s
+
+    def create_body_data(self):
+        colum = 0
+        style_body = self.workbook.add_format({
+            'border': 1,
+            'align': 'center',  
+        })
+
+        style_body_with_bold =  self.workbook.add_format({
+            'border': 1,
+            'align': 'center',  
+            'bold': True
+        })
+
+        for data in self.DATA:
+            body_data = (data['EmptyDatesAttendance']+data['DateAttendance'])
+            row = 5
+            for attendance in self.sort_attendance(body_data):
+                self.worksheet.write(row, colum, self.return_correct_value(attendance['wd']), style_body_with_bold)
+                self.worksheet.write(row, colum+1, self.return_correct_value(attendance['date']), style_body)
+
+                body_entrance_style = self.is_bold_entrance(attendance['entrance'], style_body, style_body_with_bold)
+                self.worksheet.write(row, colum+2, self.return_correct_value(attendance['entrance']),  body_entrance_style)
+                
+                self.worksheet.write(row, colum+3, self.return_correct_value(attendance['exit']),  style_body)
+
+                body_diff_time = self.is_bold_diff_time(attendance['diffTime'], style_body, style_body_with_bold)
+                self.worksheet.write(row, colum+4, self.return_correct_value(attendance['diffTime']), body_diff_time)
+                row += 1
+            colum += 6
+
+    def return_correct_value(self, val):
+        if type(val).__name__ == 'list':
+            return val[0]
+        else:
+            return val