有关 签到/签退 业务逻辑 的梳理与学习

  导言

     最近搞到了个签到管理,其中的业务逻辑感觉有点复杂(可能是我的方向不对),虽然是实现了,不过代码和逻辑很多,也有些乱,想趁着还记得逻辑来记录梳理一下,看看自己以后有没有更好的思路,或者有大佬有思路也可以在评论指导一下,非常感谢( ̄▽ ̄)!

 业务

    签到可以有时间段限制,一天可以有多段可签到时间(如9:00到12:00,15:00到18:00...),签退不能超过最大签到时间,也不能跨时间段签到)。

 逻辑

  由于可签到时间段我是按一天来想,所以格式是从一天的零点算起到当天的24:结束,所以下面的一些逻辑和实现也参照这个来。

    签到:

    这个比较简单,可以拿个bool变量IsInSignInTime 开始为假,判断当前签到时间是否在签到时间段里,直接拿到存数据库的时间段列表来循环判断就行,如果当前时间既大于可签到时间段开始时间又小于结束时间的话,就说明在可签到时间段里反之直接返回前端错误。

    签退:

    签退除了前端传的数据有误之外不管是 超过最大签到时间 还是 跨时间段 都是可以直接签退成功的,就是有上面两种情况的就要把本次签到的时间记为零

   1.跨时间段 

    由于上面在创建签到时做了限制,如果有可签到时间段,那最大签到时间不能超过24小时(如果超24小时的话肯定会跨时间段的)。所以签退只需考虑签到时间为一天以内的情况,有以下两种状态:

 1)签退跨时间段,但是没跨天

  这样直接和签到的逻辑差不多,拿个bool变量,如果跨了时间段就把其变真,后面做个置零判断。

  2)签退跨天,但是没跨可签到时间段

  如果有签到时间段:

这样还要在1)的循环中作判断,看有没有这样从今天晚上12点之前到明天凌晨0点的时间段,如果有的话就额外判断用户的签到时间段在不在这里面。在的话就不能判为跨时间。

C#代码实现

说明:

签到记录的时间是按分钟来记的,时间段的比较是用了C#的TimeOnly来比。里面有点注释掉的代码,不影响实现。

#region 签到记录接口/// <summary>/// 签到定义/// </summary>/// <returns></returns>[HttpPost][Authorization]public IActionResult Create([FromBody] SignInOrSignOutDto parm){var signIn = _signInService.GetId(parm.SignInID);if (_signInService.Any(m => m.SignInNo == signIn.SignInNo && m.Enable == false)){return toResponse(StatusCodeType.Error, $"该签到未启用,不能签到!");}//签到启用//没有同一条签到记录//在签到时间段//存在同一签到记录且状态为1的签到记录if (_signInRecordService.Any(m => m.SignInID == parm.SignInID && m.UserID == parm.UserID && m.Status == 1)){return toResponse(StatusCodeType.Error, $"不能重复签到!");}//不在签到时间段//从中拿到签到时间段// 将JSON字符串反序列化为List<SignInPeriods>对象列表var signInPeriodsList = JsonConvert.DeserializeObject<List<SignInPeriodsDto>>(signIn.SignInPeriods);TimeOnly currentTime = TimeOnly.FromDateTime(DateTime.Now);//拿个变量在循环里,如果当前时间在签到时间段就为真,反之为假bool IsInSignInTime = false;//循环比较判断foreach(SignInPeriodsDto signInPeriod in signInPeriodsList){if(signInPeriod.StartTime < currentTime&& signInPeriod.EndTime > currentTime){//在里面变真IsInSignInTime = true;}}//为假就是不在签到时间段,返回错误if (!IsInSignInTime){return toResponse(StatusCodeType.Error, $"不在签到时间段!");}try{var signInRecord = parm.Adapt<Base_SignInRecord>().ToCreate(_tokenManager.GetSessionInfo());signInRecord.Status = 1;signInRecord.StartTime = DateTime.Now;_unitOfWork.BeginTran();//新增签到记录表var response = _signInRecordService.Add(signInRecord);//改签到表对应签到的当前签到人数_signInService.Update(m => m.ID == parm.SignInID, m => new Base_SignIn(){CurrentSignInNum = signIn.CurrentSignInNum + 1,});//改用户-签到表对应用户状态为在线/签到_signInUsersService.Update(m => m.SignInNo == signIn.SignInNo && m.UserID == parm.UserID, m => new Base_SignIn_Users(){IsOnline = true});_unitOfWork.CommitTran();return toResponse(response);}catch (Exception){_unitOfWork.RollbackTran();throw;}}/// <summary>/// 签退定义/// </summary>/// <returns></returns>[HttpPost][Authorization]public IActionResult Delete([FromBody] SignInOrSignOutDto parm){//拿到数据var signIn = _signInService.GetId(parm.SignInID);var signInRecord = _signInRecordService.GetFirst(m => m.SignInID == signIn.ID && m.UserID == parm.UserID && m.Status == 1);if (_signInService.Any(m => m.SignInNo == signIn.SignInNo && m.Enable == false)){return toResponse(StatusCodeType.Error, $"该签到未启用,不能签退!");}//不做数的 体现在Time字段上//超出最大签到时间的//横跨签到时间段的//算出签到时间TimeDateTime currentTimeForDateTime = DateTime.Now;var TimePeriod = currentTimeForDateTime - signInRecord.StartTime;var currentTime = TimeOnly.FromDateTime(currentTimeForDateTime);测试 可删算出签到时间Time//DateTime currentTimeForDateTime = new DateTime(2024, 9, 24, 07, 49, 15);//var TimePeriod = currentTimeForDateTime - signInRecord.StartTime;var currentTime = TimeOnly.FromDateTime(currentTimeForDateTime);//TimeOnly currentTime = TimeOnly.Parse("07:49:15");int  Time = (int)TimePeriod.TotalMinutes;//签到提示信息,如果签到没问题就直接输成功var remindMessager = "成功";//从中拿到签到时间段// 将JSON字符串反序列化为List<SignInPeriods>对象列表var signInPeriodsList = JsonConvert.DeserializeObject<List<SignInPeriodsDto>>(signIn.SignInPeriods);//看是否超了最大时间if (Time > signIn.MaxSignInTime && signIn.MaxSignInTime != 0){Time = 0;remindMessager = "签到时间超出最大签到时间,本次签到时间置零!";}//如果是开了可签到时间段if (!string.IsNullOrEmpty(signIn.SignInPeriods)){直接拿开始时间和现在时间做判断,看其是这个时间段是否在某一时间段里面,其他不满足的都是跨时间段的//if (Time < 1440)//没隔天 一天的分钟计数//{//把签到记录表的开始签到时间转成TimeOnlyvar StartTime = TimeOnly.FromDateTime(signInRecord.StartTime);//拿个变量在循环里,如果时间段没跨签到时间段就为真,反之为假bool IsInSignInTime = false;//看有没有开始时间为0:00的时间段和结束时间为24:00的时间段SignInPeriodsDto todayPeriod = null; //结束时间为24:00的时间段SignInPeriodsDto nextDayPeriod = null;//开始时间为0:00的时间段//循环比较判断foreach (SignInPeriodsDto signInPeriod in signInPeriodsList){if (signInPeriod.StartTime < StartTime && signInPeriod.EndTime > currentTime){//在里面变真IsInSignInTime = true;}if (signInPeriod.StartTime == TimeOnly.MinValue) //看其开始时间段是否为为0:00{nextDayPeriod = signInPeriod;}if (signInPeriod.EndTime == new TimeOnly(23, 59, 59)) //看其结束时间段是否为为24:00{todayPeriod = signInPeriod;}}//有的话看开始签到时间是否在大于结束时间为24:00的时间段里   及  签退时间是否在在开始时间为0:00的时间段里//不满足条件的直接判跨时间段if (todayPeriod != null && nextDayPeriod != null){   //可以考虑将跨天取消掉,分别判是否在签到时间段里和单独看是否在跨天时间段里就行//可以在添加签到时加个判断,如过加了时间段,那最大时间就不能出现超过24小时的情况,//可以免除上面签到和签退时间隔天了还在同一签到时间段的情况if(todayPeriod.StartTime< StartTime&& nextDayPeriod.EndTime >currentTime){IsInSignInTime = true;}}//如果没设置最大签到时间但是设置了时间段//只判断其有没有超时间段,在关键判断那看其签到时间是不是超了一天// Time > 1440由于上面已经验证了有没有时间段,所以到这的都是有时间段的,不用额外判断了if (!IsInSignInTime|| Time > 1440)//跨时间段了{Time = 0;remindMessager = "横跨时间段,本次签到时间置零!";}//}}//至此留下了符合条件的try{var userSession = _tokenManager.GetSessionInfo();_unitOfWork.BeginTran();//改签到记录表状态为 签退,补上签到时间Timevar response = _signInRecordService.Update(m => m.SignInID == signIn.ID && m.UserID == parm.UserID && m.Status == 1, m => new Base_SignInRecord(){Status = 0,EndTime = currentTimeForDateTime,Time = Time,});//改签到表在线签到人数-1_signInService.Update(m => m.ID == parm.SignInID, m => new Base_SignIn(){CurrentSignInNum = signIn.CurrentSignInNum - 1,UpdateID = userSession.UserID,UpdateName = userSession.UserName,UpdateTime = DateTime.Now});//改 用户-签到表对应用户状态为离线/签退_signInUsersService.Update(m => m.SignInNo == signIn.SignInNo && m.UserID == parm.UserID,m=> new Base_SignIn_Users(){IsOnline = false});_unitOfWork.CommitTran();return toResponse(StatusCodeType.Success, remindMessager);}catch (Exception){_unitOfWork.RollbackTran();throw;}}#endregion

结语

   这个搞了有些久,还是怕有些情况没考虑,不过接口是考虑到的情况都测试通过了的。想着还有没有更优雅,更便捷的解决方法,不管是从业务开始考虑,还是从我这方法开始优化,那就看以后的我有没有时间看了,或者各位大佬指点一下,我会很开心的!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149863.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Day 43~48 smbms

SMBMS SMBMS是超市订单管理系统的简称 数据库&#xff1a; 项目如何让搭建&#xff1f; 考虑使用不使用Maven&#xff1f; 依赖&#xff0c;jar 项目搭建准备工作 1.搭建一个mavenweb项目 2.配置Tomcat 3.测试项目是否能够跑起来 4.导入项目中会遇到的jar包 jsp,servle…

html TAB切换按钮变色、自动生成table--使用函数优化结构

<!DOCTYPE html> <head> <meta charset"UTF-8"> <title>Dynamic Tabs with Table Data</title> <style> /* 简单的样式 */ .tab-content { display: none; border: 1px solid #ccc; padding: 1px; marg…

基于Springboot社区论坛JAVA|VUE|SSM计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…

2024双11买什么东西比较好?2024双十一好物推荐

双十一各种爆款商品&#xff0c;打折商品非常多&#xff0c;容易让人挑花眼也容易落入消费主义的陷阱&#xff0c;买回家后发现并不实用&#xff0c;甚至可能是自己平常生活中根本用不上的东西&#xff01;即使是打折活动也要在购买前考虑一下自己是否需要&#xff0c;在日常生…

Android (rust) vulkan (JNI) 画一个三角形: VulkanSurfaceView 初始化

上文说到, vulkan 作为一种 GPU 编程接口标准, 具有很好的跨平台能力. 并且在 wayland (GNU/Linux) 成功使用 vulkan 绘制了一个三角形. 今天, 我们同样使用 vulkano (rust), 在 Android (手机) 也画一个三角形吧 ~ 本文的解决方案主要参考了 stackoverflow 的一篇文章 (链接…

ITU标准引领车内通讯新纪元

在现代汽车科技更迭的今天&#xff0c;车内通讯与免提通话系统的性能与稳定性成为了消费者购车时不可忽视的重要因素。随着国际电信联盟&#xff08;ITU&#xff09;一系列标准的推出&#xff0c;车内通讯体验正迈向新的高度。本文将深入探讨ITU-T P.1100、P.1110、P.1120、P.1…

PTA L1-070 吃火锅

L1-070 吃火锅&#xff08;15分&#xff09; 以上图片来自微信朋友圈&#xff1a;这种天气你有什么破事打电话给我基本没用。但是如果你说“吃火锅”&#xff0c;那就厉害了&#xff0c;我们的故事就开始了。 本题要求你实现一个程序&#xff0c;自动检查你朋友给你发来的信息…

Django 对数据库的增删改查

新增 使用方法&#xff1a;类模型.objects.create 类模型 from django.db import models# Create your models here. class Car(models.Model):user models.CharField(max_length200)plate_number models.CharField(max_length20)def __str__(self):return f{self.user} -…

论文 | Reframing Instructional Prompts to GPTk’s Language

作者&#xff1a;Swaroop Mishra, Daniel Khashabi, Chitta Baral, Yejin Choi, Hannaneh Hajishirzi 论文摘要&#xff1a;语言模型 (LM) 更容易遵循哪些类型的指令提示&#xff1f; 我们通过进行广泛的实证分析来研究这个问题&#xff0c;这些分析阐明了成功指令提示的重要特…

vs2019 当前不会命中断点,还没有为该文档加载任何符号

问题&#xff1a; 解决问题&#xff1a; 1.检查C/C中的调试信息格式&#xff1b; 2. 检查连接器中的生成调试信息&#xff1b; 3.我的错误是修改过调试中的 “命令”这项导致的&#xff0c;下图已经改回默认&#xff1b;

责任链模式优化 文章发布的接口(长度验证,敏感词验证,图片验证等环节) 代码,示例

需求&#xff1a;后端需要提供一个文章发布的接口&#xff0c;接口中需要先对文章内容进行如下校验&#xff0c;校验通过后才能发布 1. 文章长度不能超过1万个字符 2. 不能有敏感词 3. 文章中图片需要合规 责任链相当于一个链条一样&#xff0c;链条上有很多节点&#xff0c;节…

基于STM32设计的室内育苗环境管理系统(物联网)

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成 1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发 1.5 模块的技术详情介绍【1】ESP8266-WIFI模块【2】MQ135传感器【4】DHT11传感器【5】B1750传感器 …

1. 值、类型与运算符

在计算机的世界里&#xff0c;只有数据。你可以读取数据、修改数据、创建新数据&#xff0c;但不能提及非数据的内容。所有这些数据都存储为长位序列&#xff0c;因此本质上是相似的。 位&#xff08;比特&#xff09;是任何类型的二值事物&#xff0c;通常被描述为0和1。在计算…

CORE Kestrel Web、InProcess、OutOfProcess、启动配置、读取配置文件

Kestrel 服务 ASP.NET Core是一个跨平台框架。 这意味着它支持在不同类型的操作系统&#xff08;例如Windows&#xff0c;Linux或Mac&#xff09;上开发和运行应用程序。 Kestrel是ASP.NET Core应用程序的跨平台Web服务器。 这意味着该服务器支持ASP.NET Core支持的所有平台和…

VIN码识别:提升汽车行业效率的智能解决方案

随着汽车行业的快速发展&#xff0c;汽车管理与服务的数字化需求日益增加。无论是汽车制造商、经销商、还是售后服务人员&#xff0c;都希望通过更便捷、高效的方式获取汽车的基本信息。在这样的背景下&#xff0c;VIN码识别接口成为了一种有效的智能解决方案。 什么是VIN码&am…

[笔记]某视觉三维定位系统参数表

表中的参数是彼此关联的&#xff0c;其实是就是视频解算的速度。里面的1秒直接对应1FPS300m秒直接对应3FPS0-20m的识别范围&#xff0c;与摄像头分辨率、视在焦距与摄像头基线有明确的对应关系。它的矩阵非正方。怀疑一组用于远距&#xff0c;一组用于近距&#xff0c;属于固定…

Redis系列补充:聊聊布隆过滤器(go语言实践篇)

1 介绍 布隆过滤器&#xff08;Bloom Filter&#xff09;是 Redis 4.0 版本之后提供的新功能&#xff0c;我们一般将它当做插件加载到 Redis Service服务器中&#xff0c;给 Redis 提供强大的滤重功能。 它是一种概率性数据结构&#xff0c;可用于判断一个元素是否存在于一个集…

Register Two Point Sets 注册两个点集

文章目录 Register Two Point Sets 注册两个点集Visualize Gradient Descent 可视化梯度下降Hyperparameter Search 超参数搜索JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4类说明 原文url: https://examples.itk.org/src/registration/metricsv4/registertwopointse…

2024/9/24有关1x1卷积核

深度学习笔记&#xff08;六&#xff09;&#xff1a;1x1卷积核的作用归纳和实例分析_1x1卷积降维-CSDN博客 从这篇文章写的很好&#xff0c;主要讲的就是1x1卷积核有降维作用&#xff0c;还有就是线性映射作用&#xff08;一般步进长度设置为的为1&#xff0c;也相当于是全连…

R包:ggspatial空间画图

ggplot2语法的空间图形画图 Spatial data plus the power of the ggplot2 framework means easier mapping. 加载R包 # install.packages("ggspatial")library(ggplot2) library(ggspatial) load_longlake_data()Using layer_spatial() and annotation_spatial() g…