Beispiel #1
0
 def select_table_path(self, table_key):
     default_path = os.path.dirname(self.settings_configs[table_key])
     select_path = self.open_file_dialog( default_path=default_path, extension=["*.xlsx", "*.xls"])
     if select_path is None:
         return
     self.settings_configs[table_key] = select_path
     Configs.get_instance().save_json()
     self.refresh_UI()
Beispiel #2
0
 def select_out_path(self):
     default_path = self.settings_configs["out_path"]
     select_path = self.open_dir_dialog(default_path=default_path)
     if select_path is None:
         return
     self.settings_configs["out_path"] = select_path
     Configs.get_instance().save_json()
     self.refresh_UI()
Beispiel #3
0
 def remove_all_checkins(self, day):
     day_str = str(day)
     added_checkins_config = Configs.get_instance(
     ).get_member_checkin_temp_config(self.name)
     if day_str not in added_checkins_config:
         return
     added_checkins_config.pop(day_str)
     Configs.get_instance().save_temp_json()
     self.load_added_checkins()
Beispiel #4
0
 def add_checkin(self, day, time):
     added_checkins_config = Configs.get_instance(
     ).get_member_checkin_temp_config(self.name)
     day_str = str(day)
     if day_str not in added_checkins_config:
         added_checkins_config[day_str] = []
     day_checkins = added_checkins_config[day_str]
     day_checkins.append(time)
     day_checkins.sort(key=lambda key: (key[0], key[1]))
     Configs.get_instance().save_temp_json()
     self.load_added_checkins()
Beispiel #5
0
 def set_leaves(self, time_text_list, need_save=True):
     if 1 == len(time_text_list) % 2:
         return False
     self.leave_dict = {}
     for idx in range(0, len(time_text_list), 2):
         if not self.add_leave(time_text_list[idx],
                               time_text_list[idx + 1]):
             return False
     if need_save:
         Configs.get_instance().set_member_leave_temp_config(
             self.name, time_text_list)
     return True
Beispiel #6
0
 def calc_all_data(self):
     #缺卡
     self.lack_checkin_count = 0
     #迟到早退
     self.late_or_early_count = 0
     self.late_or_early_duration = 0
     self.late_or_early_fine_number = 0
     self.late_early_time_dict = {}
     #工作天数
     self.work_days = 0
     #放假天数
     self.holidays = 0
     #请假时长
     self.day_leave_durations = []
     self.leave_durations = timedelta()
     #重新加载配置
     self.load_leaves_data()
     self.load_added_checkins()
     self.load_config_data()
     for index in range(1, CommonDatas.get_instance().days_number + 1):
         if not self.in_company(index):
             #没入职
             pass
         elif not Configs.get_instance().get_is_work_time(index):
             #休息日
             self.holidays += 1
         else:
             self.work_days += 1
             duration, late, early = self.calc_late_and_early_time(index)
             self.late_early_time_dict[index] = [duration, late, early]
             if 0 < duration:
                 self.late_or_early_count += 1
                 self.late_or_early_duration += duration
                 self.late_or_early_fine_number += Configs.get_instance(
                 ).get_fine_number(duration)
             if 30 <= duration:
                 self.lack_checkin_count += 1
         #请假时长
         leave_duration_am = timedelta()
         leave_duration_pm = timedelta()
         leave_times = self.get_leave_time_range(index)
         lunch_break_start, lunch_break_end = CommonDatas.get_instance(
         ).create_lunch_break(index)
         for leave_time in leave_times:
             if leave_time[0] < lunch_break_start:
                 leave_duration_am += leave_time[1] - leave_time[0]
             else:
                 leave_duration_pm += leave_time[1] - leave_time[0]
         self.day_leave_durations.append(
             (leave_duration_am, leave_duration_pm))
         self.leave_durations += (leave_duration_am + leave_duration_pm)
     if 5 < self.late_or_early_count:
         self.late_or_early_fine_number *= 2
Beispiel #7
0
 def open(self):
     super().open()
     self.widget.show()
     self.calendar.setMinimumDate(CommonDatas.get_instance().start_date)
     self.calendar.setMaximumDate(CommonDatas.get_instance().end_date)
     work_time = Configs.get_instance().get_config("work_time")
     self.timeEditOut.setTime(QTime(work_time[1][0], work_time[1][1]))
     self.timeEditIn.setTime(QTime(work_time[0][0], work_time[0][1]))
     lunch_break = Configs.get_instance().get_config("lunch_break")
     self.lunchBreakEditOut.setTime(QTime(lunch_break[1][0], lunch_break[1][1]))
     self.lunchBreakEditIn.setTime(QTime(lunch_break[0][0], lunch_break[0][1]))
     self.work_time_table = Configs.get_instance().get_temp_config("work_time_table").copy()
     self.on_time_change()
     self.refresh_UI()
Beispiel #8
0
 def add_leave(self, start, end):
     try:
         work_time = Configs.get_instance().get_config("work_time")
         start_date = Functions.string2datetime(start)
         end_date = Functions.string2datetime(end)
         while start_date < end_date:
             lunch_break_start, lunch_break_end = CommonDatas.get_instance(
             ).create_lunch_break(start_date.day)
             tempend_date = CommonDatas.get_instance().create_work_time(
                 start_date.day)[1]
             if end_date < tempend_date:
                 tempend_date = end_date
             if start_date < lunch_break_start and lunch_break_end < tempend_date:
                 #午休的时间拆开
                 self._add_leave(start_date, lunch_break_start)
                 self._add_leave(lunch_break_end, tempend_date)
             else:
                 self._add_leave(start_date, tempend_date)
             if start_date.day == CommonDatas.get_instance().days_number:
                 break
             else:
                 start_date = CommonDatas.get_instance().create_work_time(
                     start_date.day + 1)[0]
     except Exception as e:
         print(e)
         return False
     return True
Beispiel #9
0
 def create_work_time(self, day):
     from Scripts.Data.Configs import Configs
     work_time = Configs.get_instance().get_config("work_time")
     start_time = self.create_datetime(day=day,
                                       hour=work_time[0][0],
                                       minute=work_time[0][1])
     end_time = self.create_datetime(day=day,
                                     hour=work_time[1][0],
                                     minute=work_time[1][1])
     return start_time, end_time
Beispiel #10
0
 def create_lunch_break(self, day):
     from Scripts.Data.Configs import Configs
     lunch_break = Configs.get_instance().get_config("lunch_break")
     start_time = self.create_datetime(day=day,
                                       hour=lunch_break[0][0],
                                       minute=lunch_break[0][1])
     end_time = self.create_datetime(day=day,
                                     hour=lunch_break[1][0],
                                     minute=lunch_break[1][1])
     return start_time, end_time
Beispiel #11
0
    def save_config(self):
        in_time = self.timeEditIn.time()
        out_time = self.timeEditOut.time()
        work_time = []
        work_time.append([in_time.hour(), in_time.minute()])
        work_time.append([out_time.hour(), out_time.minute()])
        Configs.get_instance().set_config("work_time", work_time)
        lunch_break_in_time = self.lunchBreakEditIn.time()
        lunch_break_out_time = self.lunchBreakEditOut.time()
        lunch_break = []
        lunch_break.append([lunch_break_in_time.hour(), lunch_break_in_time.minute()])
        lunch_break.append([lunch_break_out_time.hour(), lunch_break_out_time.minute()])
        Configs.get_instance().set_config("lunch_break", lunch_break)
        Configs.get_instance().save_json()

        Configs.get_instance().set_temp_config("work_time_table", self.work_time_table)
        Configs.get_instance().save_temp_json()
        from Scripts.UI.UIMain import UIMain
        UIMain.get_instance().refresh_UI()
Beispiel #12
0
 def refresh_UI(self):
     self.settings_configs = Configs.get_instance().get_config("settings")
     detail_table_path = self.settings_configs["detail_table_path"]
     summary_table_path = self.settings_configs["summary_table_path"]
     out_path = self.settings_configs["out_path"]
     if os.path.isfile(detail_table_path):
         self.detailPathEdit.setText(detail_table_path)
     if os.path.isfile(summary_table_path):
         self.summaryPathEdit.setText(summary_table_path)
     if os.path.isdir(out_path):
         self.outPathEdit.setText(out_path)
Beispiel #13
0
 def set_config(self, **kwargs):
     member_config = Configs.get_instance().get_member_config(self.name)
     if "email" in kwargs:
         member_config["email"] = kwargs["email"]
     if "bank_card" in kwargs:
         member_config["bank_card"] = kwargs["bank_card"]
     if "profession" in kwargs:
         member_config["profession"] = kwargs["profession"]
     if "department_1" in kwargs:
         member_config["department_1"] = kwargs["department_1"]
     if "department_2" in kwargs:
         member_config["department_2"] = kwargs["department_2"]
     if "in_date" in kwargs:
         member_config["in_date"] = Functions.QDateTime2string(
             kwargs["in_date"])
     if "out_date" in kwargs:
         member_config["out_date"] = Functions.QDateTime2string(
             kwargs["out_date"])
     Configs.get_instance().save_json()
     self.load_config_data()
Beispiel #14
0
 def load_added_checkins(self):
     start_date = CommonDatas.get_instance().start_date
     self.added_checkin_list = []
     added_checkins_config = Configs.get_instance(
     ).get_member_checkin_temp_config(self.name)
     for day in range(1, CommonDatas.get_instance().days_number + 1):
         checkins = []
         day_checkins = []
         if str(day) in added_checkins_config:
             checkins = added_checkins_config[str(day)]
         for checkin in checkins:
             day_checkins.append(CommonDatas.get_instance().create_datetime(
                 day=day, hour=checkin[0], minute=checkin[1]))
         self.added_checkin_list.append(day_checkins)
Beispiel #15
0
 def export_file(self):
     error_tips = None
     miss_member = False
     settings_configs = Configs.get_instance().get_config("settings")
     if False and not os.path.isfile(settings_configs["detail_table_path"]):
         error_tips = "请选择明细表模板"
     elif False and not os.path.isfile(
             settings_configs["summary_table_path"]):
         error_tips = "请选择汇总表模板"
     elif not os.path.isdir(settings_configs["out_path"]):
         error_tips = "请选择输出文件路径"
     else:
         show_out_member = self.showOutMember.isChecked()
         for name, member in CommonDatas.get_instance().get_all_member_dict(
                 show_out_member).items():
             if len(member.email) <= 0:
                 error_tips = name + "的邮箱没填写"
             elif len(member.bank_card) <= 0:
                 error_tips = name + "的银行卡号没填写"
             if error_tips is not None:
                 miss_member = member
                 break
     if error_tips is not None:
         reply = QMessageBox.warning(self.widget, 'Message', error_tips,
                                     QMessageBox.Yes, QMessageBox.Yes)
         if reply == QMessageBox.Yes:
             if miss_member is not False:
                 self.open_edit_member_data(member=miss_member)
             else:
                 self.open_settings()
         return
     try:
         #导出明细表
         ExportXLSX.export_detail_table(
             settings_configs["detail_table_path"],
             settings_configs["out_path"])
         #导出汇总表
         ExportXLSX.export_summary_table(
             settings_configs["summary_table_path"],
             settings_configs["out_path"])
     except PermissionError as exc:
         QMessageBox.warning(self.widget, "Error", "文件导出错误" + str(exc),
                             QMessageBox.Yes)
     else:
         os.system("start explorer " +
                   settings_configs["out_path"].replace("/", "\\"))
Beispiel #16
0
    def load_config_data(self):
        start_date = CommonDatas.get_instance().start_date
        member_config = Configs.get_instance().get_member_config(self.name)
        self.email = member_config["email"]
        self.bank_card = member_config["bank_card"]
        self.profession = member_config["profession"]
        self.department_1 = member_config["department_1"]
        self.department_2 = member_config["department_2"]
        self.in_date = Functions.string2datetime(member_config["in_date"])
        self.out_date = Functions.string2datetime(member_config["out_date"])

        self.ignore = (self.out_date.year == start_date.year
                       and self.out_date.month < start_date.month)
        if self.in_date.year == start_date.year and start_date.month < self.in_date.month:
            #还没入职
            self.ignore = True
        if self.in_date.year == start_date.year and self.in_date.month == start_date.month and 15 < self.in_date.day:
            #上个月15号以后入职不统计
            self.ignore = True
Beispiel #17
0
 def refresh_select_member(self, new_member=None):
     if new_member is not None:
         self.select_member = new_member
     if self.select_member is None:
         return
     self.select_member.calc_all_data()
     cur_year = CommonDatas.get_instance().start_date.year
     cur_month = CommonDatas.get_instance().start_date.month
     for index in range(1, CommonDatas.get_instance().days_number + 1):
         brush = QtGui.QBrush()
         if not self.select_member.in_company(index):
             #没入职或者离职了
             brush.setColor(QtGui.QColor('Black'))
         elif not Configs.get_instance().get_is_work_time(index):
             #休息日
             brush.setColor(QtGui.QColor('Black'))
         elif 0 < self.select_member.is_late_or_early(index):
             #迟到
             brush.setColor(QtGui.QColor('Red'))
         else:
             brush.setColor(QtGui.QColor('Green'))
         cmd_fmt = QtGui.QTextCharFormat()
         cmd_fmt.setForeground(brush)
         self.calendar.setDateTextFormat(QDate(cur_year, cur_month, index),
                                         cmd_fmt)
     self.leaveMember.setCurrentText(self.select_member.name)
     self.inDateEdit.setDateTime(self.select_member.in_date)
     self.outDateEdit.setDateTime(self.select_member.out_date)
     #显示
     member = self.select_member
     self.detailedInfo.setText(member.name)
     self.detailedInfo.append("缺卡次数:{0}".format(member.lack_checkin_count))
     self.detailedInfo.append("迟到早退天数:{0} 罚款总数:{1}".format(
         member.late_or_early_count, member.late_or_early_fine_number))
     self.detailedInfo.append("工作天数:{0} 休息天数:{1}".format(
         member.work_days, member.holidays))
     self.detailedInfo.append("请假次数:{0} 请假时长:{1}".format(
         member.get_leave_count(),
         Functions.timedelta2string(member.get_leave_duration())))
Beispiel #18
0
def export_detail_table(template_path, out_dir):
    start_date = CommonDatas.get_instance().start_date
    out_path = os.path.join(out_dir,
                            "{0:02d}月考勤明细.xlsx".format(start_date.month))
    #out_path = copy_template(template_path, out_dir, "{0:02d}月考勤明细{1}")
    xlsx_table = openpyxl.Workbook()
    xlsx_sheet = xlsx_table.get_active_sheet()
    #成员信息
    member_dict = CommonDatas.get_instance().get_all_member_dict()
    member_list = list(member_dict.values())
    #初始表格样式
    sheet_row, sheet_column = init_detail_sheet(
        xlsx_sheet, len(member_list),
        CommonDatas.get_instance().days_number)
    #成员数据
    for index, member in enumerate(member_list):
        row = 5 + index
        member.calc_all_data()
        #序号
        xlsx_sheet.cell(row, 1).value = index + 1
        #名字
        xlsx_sheet.cell(row, 2).value = member.name
        #打卡情况
        for day in range(1, CommonDatas.get_instance().days_number + 1):
            colum1 = 2 + 2 * day - 1  #上午
            colum2 = colum1 + 1  #下午
            cur_date = CommonDatas.get_instance().create_datetime(day=day)
            xlsx_cell1 = xlsx_sheet.cell(row, colum1)
            xlsx_cell2 = xlsx_sheet.cell(row, colum2)
            #初始化
            xlsx_cell1.value = "√"
            xlsx_cell2.value = "√"

            if not member.in_company(day):
                #没入职
                xlsx_sheet.merge_cells(None, row, colum1, row, colum2)
                xlsx_cell1.value = "未入职"
            elif not Configs.get_instance().get_is_work_time(day):
                #休息
                xlsx_cell1.value = "休息"
                xlsx_cell2.value = "休息"
            elif 0 < member.is_late_or_early(day):
                #迟到或者早退
                duration, late, early = member.get_late_and_early_time(day)
                if 1440 == duration or 480 == duration:
                    xlsx_sheet.merge_cells(None, row, colum1, row, colum2)
                    xlsx_cell1.fill = const_fill_purple
                    xlsx_cell1.value = "缺卡"
                else:
                    if 0 < late:
                        xlsx_cell1.fill = const_fill_yellow
                        xlsx_cell1.value = "迟到{0}分钟".format(late)
                    if 0 < early:
                        xlsx_cell2.fill = const_fill_yellow
                        xlsx_cell2.value = " 早退{0}分钟".format(early)
            #计算请假
            leave_duration, am_duration, pm_duration = member.get_leave_duration(
                day)
            work_day_duration = CommonDatas.get_instance(
            ).get_work_day_duration()
            if leave_duration == work_day_duration:
                #全天请假
                xlsx_cell1.fill = const_fill_red
                xlsx_cell2.fill = const_fill_red
                xlsx_sheet.merge_cells(None, row, colum1, row, colum2)
                xlsx_cell1.value = "请假" + Functions.timedelta2string(
                    leave_duration)
            else:
                if 0 < am_duration.total_seconds():
                    xlsx_cell1.fill = const_fill_red
                    xlsx_cell1.value = "请假" + Functions.timedelta2string(
                        am_duration)
                if 0 < pm_duration.total_seconds():
                    xlsx_cell2.fill = const_fill_red
                    xlsx_cell2.value = "请假" + Functions.timedelta2string(
                        pm_duration)

        cloum_offset = 2 + 2 * CommonDatas.get_instance().days_number + 1
        #请假次数
        xlsx_sheet.cell(row, cloum_offset).value = member.get_leave_count()
        #请假小时
        xlsx_sheet.cell(row,
                        cloum_offset + 1).value = Functions.timedelta2string(
                            member.get_leave_duration())
        #迟到次数
        xlsx_sheet.cell(row,
                        cloum_offset + 2).value = member.late_or_early_count
        #缺卡次数
        xlsx_sheet.cell(row,
                        cloum_offset + 3).value = member.lack_checkin_count
        #罚款金额
        xlsx_sheet.cell(row, cloum_offset +
                        4).value = member.late_or_early_fine_number
    xlsx_table.save(out_path)
Beispiel #19
0
 def get_leave_text_list(self):
     return Configs.get_instance().get_member_leave_temp_config(self.name)
Beispiel #20
0
 def load_leaves_data(self):
     leave_text_list = Configs.get_instance().get_member_leave_temp_config(
         self.name)
     self.set_leaves(leave_text_list, False)
Beispiel #21
0
 def add_in_checkin(self):
     date = self.calendar.selectedDate()
     work_time = Configs.get_instance().get_config("work_time")
     self.select_member.add_checkin(int(date.day()),
                                    [work_time[0][0], work_time[0][1]])
     self.refresh_select_member()