【问题标题】:Database Design - Employee Clocking In and Out System [closed]数据库设计 - 员工打卡进出系统[关闭]
【发布时间】:2012-03-06 13:30:52
【问题描述】:

我想开发员工打卡系统(网站)。

我关心两件事:

  • 如果员工从昨天开始忘记“下班”,而他们今天有“下班”,则应向经理举报。

  • 员工可能会加班,例如:周一上午 11:00 至周二上午 1:30(午夜之后)打卡。我不希望系统认为员工忘记打卡了..

    • 员工可以每天打卡和打卡多次。

如何解决这个问题以及在数据库设计方面可以改进哪些方面?

员工表:

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| name        | varchar(50)  | NO   |     | NULL    |                |
| password    | varchar(50)  | NO   |     | NULL    |                |
| hourly_rate | decimal(6,2) | NO   |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

时钟表:

+----------------+----------+------+-----+---------+----------------+
| Field          | Type     | Null | Key | Default | Extra          |
+----------------+----------+------+-----+---------+----------------+
| id             | int(11)  | NO   | PRI | NULL    | auto_increment |
| staff_id       | int(11)  | NO   |     | NULL    |                |
| clock_in_date  | datetime | NO   |     | NULL    |                |
| clock_out_date | datetime | NO   |     | NULL    |                |
+----------------+----------+------+-----+---------+----------------+

【问题讨论】:

    标签: mysql database database-design logic


    【解决方案1】:

    伙计,你在这里打开的虫子是多么巨大啊。在一家只做时钟系统的公司工作后,我再也不想做这件事了!

    我意识到我的回答非常概念化,并解决了问题正常范围之外的一些问题,但这是为了概述此类应用程序中的数据库设计和结构概念。这些信息也来自我最近在该领域所做的专业开发,因此它不仅是假设的,而且在实践中得到了证明。

    当您查看这种类型的系统时,您最好最初使用指标作为标志,这通常是出拳次数与比较每条记录的比较。比较 1,000 名员工的每条记录并不是最好的事情!

    例如,如果用户在 24 小时内进行了 8 次打卡(一天开始、早上休息开始、早上休息结束、午餐开始、午餐结束、下午休息开始、下午休息结束和一天结束),您可以确定在此期间不太可能没有错过打卡并且发生了加班,但是如果在 24 小时内有 7 打卡(一天开始、早上休息开始、早上休息结束、午餐开始、午餐结束、下午休息一天的开始和结束)您知道缺少一拳,并且该人忘记了一天的打卡。请注意下午休息时间不存在。

    但是,这不是完全证明,仅提供指示性参考,您需要将轮班时间表与出拳进行比较,以确保没有任何遗漏。因为有可能午餐结束和下午休息结束都错过了留下 6 次打卡,您可以设置您的代码来标记该员工不是 X 次打卡的任何内容。标记后,您然后对该员工在该期间进行实际比较,以找出实际发生的事情和遗漏的事情。

    这并不意味着您不比较所有记录,但是这取决于员工的数量,这可能会导致对每条记录进行精确比较时出现一些大问题,这通常对于更多的记录更好员工使用 2 台服务器,1 台仅用于数据收集和接口,第二台用于运行比较过程。

    正如我所提到的,对于此类应用程序并使用不同的时间表,您还需要查看轮班时间表以进行比较。您将希望为每个员工保留一个填充记录,该记录将在轮班开始之前和轮班结束之后给予相同的时间。这将意味着加班超过 1 个时间段的可能性很小。基本公式非常简单:轮班小时数 - 24 小时 / 2 = 时间填充

    现在,您可以在该用户的轮班时间表之前和之后放置时间填充。但是您仍然需要处理轮班调换、变更或超过 24 小时的轮班。这是真正变得棘手的地方。您将需要查看一个包含重叠时间(填充、轮班和打孔)的表格,然后可以将其与未来对时间表的任何调整进行核对,因为事实上更改在考勤中并不少见。

    现在您还需要保存一张病假和假期缺勤时间表,然后需要在打卡/打卡表中标记此数据,因为这是您比较的数据。当标记设置一段时间后,可以在比较中跳过记录并在报告中留下注释,而无需运行其他操作来检查它。

    几乎在最后,请注意您需要忘记通常的日期/时间约定来衡量一系列变量吗?更不用说在多个日期有效和高效地工作?因此,您通常最好只使用 dd/mm/YYYY hh:mm:ss 的开始和结束时间,因为测量使用 UNIX 时间来计算已经过去了多少时间。说要能够审计,大多数系统确实需要“日期戳”记录,因此在发布报告时可能需要服务器端对此进行处理。

    最后,我还建议持有一个结果表,这将为每个用户提供报告结果,这样当您想提供历史记录时,您可以动态生成文档,但您不必浪费处理能力进行比较每次请求报告时记录。

    我希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      从领域的角度来看,这并不完全正确。

      出于审计目的或故障排除需要打卡或打卡。 因此,您需要存储所有员工的个人出拳历史记录。

      您的时钟表可能是派生数据。

      时钟表应该是

      +----------------+----------+------+-----+---------+----------------+
      | Field          | Type     | Null | Key | Default | Extra          |
      +----------------+----------+------+-----+---------+----------------+
      | id             | int(11)  | NO   | PRI | NULL    | auto_increment |
      | staff_id       | int(11)  | NO   |     | NULL    |                |
      | clock_type     | int(1)   | NO   |     | 0       | 0-in, 1-out    |
      | clock          | datetime | NO   |     | NULL    |                |
      +----------------+----------+------+-----+---------+----------------+
      

      【讨论】:

      • 这会增加不必要的复杂性,以确定该人是否在再次打卡之前已经打卡。原来的设计更好。应尽可能避免使用 EAV 表。
      • 不,原版变得超级复杂,我从经验中得知。任何新手都会选择原始设计,但没有注意到 db 不应该向您报告您的愿望,而是以最少冗余的形式提供数据。您可以保留一个冗余的合并报告表(进出)以便快速检索。
      • @shikhar 你可能是对的。看看我发布的这个问题。 stackoverflow.com/questions/12632302/…
      【解决方案3】:

      我并没有真正看到您的设计存在问题,而是我看到定义不佳的需求存在问题。您需要更好地定义经理何时更改以考虑多天的轮班。也许最好的规则是,如果有人 24 小时没有打卡,或者如果他们尝试第二次打卡,主管会收到通知。您可能还需要数据库上的触发器,如果​​缺少时钟输出,则不允许时钟输入。或者您可以允许打卡,并将缺少的打卡发送给主管处理。

      您特别需要的一件事是审核(一个单独的表),以便您可以查看谁在何时更改了记录。如果对某人的时间有疑问,您应该能够分辨出谁更改了记录以及旧值是什么。

      打卡(我假设他们会根据打卡时间获得报酬)是一项需要严格内部控制的活动(在数据库级别而不是在应用程序中!如果您试图阻止,内部控制绝不能在应用程序级别进行)欺诈。)任何人都不应直接访问该表。他们应该只能通过一个存储过程来进行更改,该存储过程确切地规定了他们可以做什么。

      您可能希望为主管和非主管制定特定规则。一般来说,任何与时间相关的事情都只能由该人的主管在事后更改。我会有一个强制执行此操作的触发器,应只允许输入时间表的人更改数据中的时钟,并且仅当它为空时才允许。所有其他更改都应来自此人的主管。因此,您可能需要一个表来存储组织结构,或者至少需要一个显示员工主管是谁的字段。

      如果人们要根据打卡时间和输出来支付费用,那么在最终确定业务规则之前,您可能需要与您的会计人员和他们的审计师核实一下。此类事情的内部控制可能非常复杂且难以纠正。

      我看到的一个设计问题是小时费率列,它会随着时间的推移而变化,你会希望能够知道这一点(特别是如果费率在支付期中间由于某种原因发生变化),所以我会打破这个到一个相关的表。同样,需要严格执行此表的权利。除了人力资源人员,任何人都不能在小时费率字段中输入数据。

      【讨论】:

        【解决方案4】:

        您的数据库设计看起来不错。它应该只记录进出时间。您应该在应用程序的其他地方编写业务规则。 You may read this article on wikipedia 关注点分离。

        【讨论】:

          【解决方案5】:

          您需要在clock_out_date 上允许NULL。这样,您可以在签到时记录下签到,只需留下clock_out_date NULL 以表明用户尚未签出。

          如果您计划支持每个事件/天的多次签入/签出,那么您还需要在时钟表中添加一个事件/天 ID 列,以便您可以按事件/天对签入进行分组。正如您所指出的,该日期不能用于对跨越午夜的签入进行分组。我们使用 event_id,但也许您需要 payroll_date。

          我正在为类似的系统使用相同的时钟表结构。它已经生产一年了,我不会改变任何事情。我们以 UTC 格式存储所有时间。

          请注意,我们不会将此系统用于工资核算,并且工资核算系统可能存在重要的审计要求。

          【讨论】:

          • 类似的打卡日期永远不允许为空
          • @HLGEM,感谢您的澄清。
          • 感谢您的建议。有时工作人员可能会每天签入和签出(任何随机原因) - 所以你的意思是我需要添加 week_day 字段?还有工作人员可能会加班怎么办,例如:周一上午 11:00 至周二上午 1:30(午夜之后)打卡。这将如何运作。
          • 您可能有一些算法来计算工资单日期,但对于 24 小时营业的商店,您可能需要将其与个人的日程安排联系起来。
          猜你喜欢
          • 2014-01-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-13
          • 1970-01-01
          • 2012-02-12
          • 1970-01-01
          相关资源
          最近更新 更多