在我们很多应用系统中,往往都需要根据实际情况生成一些编码规则,如订单号、入库单号、出库单号、退货单号等等,我们有时候根据规则自行增加一个函数来生成处理,不过我们仔细观察后,发现它们的编码规则有很大的共通性,因此可以考虑使用一些通用的业务编码规则生成,从而在系统中统一维护即可,本篇随笔介绍如何在WInform界面中实现通用的业务编码规则生成。

1、常见单号的业务编码规则

刚才我们提到一些编码规则,如订单号、入库单号、出库单号、退货单号等等,它们都是有大同小异的规则,有前缀、有日期的编码、有一些流水号,还有一些特殊的规则处理,往往就是这些,需要协调好流水号的增加处理即可。

例如,原来在我的CRM业务模块中,增加了一个函数,用来生成订单号的,如下所示。

        /// <summary>
/// 生成单据号码,编码为XS-{userId}-{yyyyMMdd}-流水号
/// </summary>
/// <returns></returns>
public async Task<string> GetOrderNo()
{
string prefix = string.Format("XS-{0}-{1}", CurrentApiUser.Id, DateTime.Now.ToString("yyyyMMdd")); //获取当天的记录数量+1
DateTime currentDate = DateTime.Now.ToString("yyyy-MM-dd").ToDateTime(); //当前日期
//计算条件数量+1
int count = this.EntityDb.Count(s => s.OrderDate >= currentDate && s.OrderDate <= currentDate.AddDays(1)) + 1; //循环检索,直到不重复的编号
string number = string.Format("{0}-{1}", prefix, count);
while (true)
{
var result = await CheckNumberExist(number);
if (result)
{
//存在增加1再判断
number = string.Format("{0}-{1}", prefix, count++);
}
else
{
break;
}
} return number;
}

这里为了增加对流水号的循环判断,直到没有重复的即可输出来作为订单号。

大多数的编码规则大同小异,因此我们可以考虑使用共同的规则进行处理,类似我们通用字典的模块处理。订单编码,可以在新建订单的时候生成,也可以提供用户手动生成【生成编号】的操作,如下界面所示。

2、设计通用的业务编码规则

我们归纳了一些编码规则,基本上也就是前缀,日期分隔,分隔符,后缀,流水号这些元素的组合,如果需要更加复杂的也可以自行调整接口,我们这里设计一个通用的编码规则,对这些元素进行组合配置,数据库设计如下所示。

根据这些内容,我们使用手工编码或者代码生成工具生成相关的基础代码 (可以基于EnterpriseLibrary的框架代码或者基于SqlSugar开发框架的代码),最终我们都用于WInform的界面调用。

这里以我们基于SqlSugar开发框架的代码生成为例。

生成后,会生成一个相关的业务类,实现相关的CRUD接口,如下代码定义所示,如果你有自己的基础框架实现,那么也可以忽略具体的代码生成,关注业务编码的生成的的规则即可。

   /// <summary>
/// 业务表编码规则 应用层服务接口实现
/// </summary>
public class TableNumberService : MyCrudService<TableNumberInfo, string, TableNumberPagedDto>, ITableNumberService

为了控制编码的规则生成,我们增加一个同步锁来实现冲突处理。

        /// <summary>
/// 同步锁
/// </summary>
private static SemaphoreSlim syncRoot = new SemaphoreSlim(1);

最终我们的实现代码如下所示。

        /// <summary>
/// 根据定义表名、单据头、分割符1、分割符2,生成业务编码。如果生成错误,返回空字符串
/// </summary>
/// <param name="tableNameOrCode">表名或代码</param>
/// <returns></returns>
public async Task<string> GenerateNumber(string tableNameOrCode)
{
string businessNumber = "";
await syncRoot.WaitAsync(); //等待锁
try
{
var info = await base.GetFirstAsync(s => s.TableName == tableNameOrCode || s.Code == tableNameOrCode);
if (info != null)
{
string currentDate = "";
string lastDate = "";
int currentNumber = 1; //流水号起始值
int serialLength = 3; //流水号长度 if(!info.LastGenerateTime.HasValue)
{
info.LastGenerateTime = DateTime.Now;
} if (info.RuleFormat == "年月日")
{
currentDate = DateTime.Now.ToString("yyyyMMdd");
lastDate = info.LastGenerateTime.Value.ToString("yyyyMMdd");
}
else if (info.RuleFormat == "年月")
{
currentDate = DateTime.Now.ToString("yyyyMM");
lastDate = info.LastGenerateTime.Value.ToString("yyyyMM");
} //如果当前日期和最后日期不一致,流水号重置为0
if(!currentDate.Equals(lastDate))
{
info.CurrentValue = 0;
} //如果流水号非起始值,那么累计计算
if(info.CurrentValue.HasValue && info.CurrentValue >= 0)
{
currentNumber = (int)info.CurrentValue + 1;//流水号当前值
} //流水号长度
if(info.ValueLength.HasValue && info.ValueLength > 3)
{
serialLength = (int)info.ValueLength;//流水号长度
}
var SplitString1 = string.IsNullOrEmpty(info.SplitString1) ? "-" : info.SplitString1;
var SplitString2 = string.IsNullOrEmpty(info.SplitString2) ? "-" : info.SplitString2; //生成业务编码
businessNumber = $"{info.Prex}{SplitString1}{currentDate}{SplitString2}{currentNumber.ToString().PadLeft(serialLength, '0')}{info.Suffix}"; //更新记录
info.CurrentValue = currentNumber;
info.SplitString1 = SplitString1;
info.SplitString2 = SplitString2;
info.CurrentNumberString = businessNumber;
info.LastGenerateTime = DateTime.Now;//更新最后生成编码日期 await base.UpdateAsync(info);
}
}
catch (Exception ex)
{
var errorText = $"生成单号时出现错误:{ex.Message}";
LogTextHelper.Error(errorText, ex);
}
finally
{
syncRoot.Release();//释放锁
} return businessNumber;
}

上面主要注意的就是流水号的生成,这个稍微特殊处理一下,如果定义的规则是年月日,那么和最后的生成日期和当前日期不一致的话(转换为年月日对比),就认为流水号重新重置为1,否则是同一天的,流水号递增即可。如果是年月的,也是判断最后日期和当前日期的年月是否一致,不一致则重置为1,否则递增。注意流水号的编码长度,一般为4位,如果不满足的可以增加到6位等。

最终我们实际的业务编码的管理界面和查看的对应编码的界面如下所示,供参考设计界面处理。

编辑单个业务编码规则的界面如下所示。

为了方便,我们这里提供一个【测试生成】的按钮,用于测试具体的编码生成,我们具体的业务调用,就是类似这个调用即可。

var handNo = await BLLFactory<ITableNumberService>.Instance.GenerateNumber(tableNameOrCode);

同样,我们也可以把这个界面搬到WPF框架界面上去,可以重用具体的业务编码规则处理,如上类似的界面处理。

单个通用的业务编码规则的编辑界面如下所示。

因此,不管对于Winform还是WPF的界面,他们的展示方式都是类似的,我们可以重用业务层对通用编码规则的定义。

在Winform应用中增加通用的业务编码规则生成的更多相关文章

  1. 通用的业务编码规则设计实现[转:http://www.cnblogs.com/xqin/p/3708367.html]

    一.背景 每一个企业应用中不可避免的都会涉及到业务编码规则的问题,比如订单管理系统中的订单编号,比如商品管理系统中的商品编码,比如项目管理系统中的项目编码等等,这一系列的编码都需要管理起来,那么它们的 ...

  2. Winform开发框架中工作流模块的业务表单开发

    在我们开发工作流的时候,往往需要设计到具体业务表单信息的编辑,有些是采用动态编辑的,有些则是在开发过程中处理的,各有各的优点,动态编辑的则方便维护各种各样的表单,但是数据的绑定及处理则比较麻烦,而自定 ...

  3. Winform界面中实现通用工具栏按钮的事件处理

    在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和我标准的界面处理方式有所不同,标准的列 ...

  4. 参照企业微信审批业务,在Winform开发框架中工作流模块的实现业务审批

    目前微信的企业号已经切换到企业微信里面,这个是一个APP程序,提供了很丰富的企业应用,其中包括了业务审批处理,审批业务包括请假.报销.费用.出差等很多个审批场景,在Winform开发框架中工作流模块这 ...

  5. Winform开发框架中工作流模块之申请单草稿处理

    在我们开发工作流模块的时候,有时候填写申请单过程中,暂时不想提交审批,那么可以暂存为草稿,以供下次继续填写或者提交处理,那么这个草稿的功能是比较实用的,否则对于一些填写内容比较多的申请单,每次要重填写 ...

  6. Winform开发框架中工作流模块之审批会签操作(2)

    前面随笔介绍了请假申请单和报销申请单两个不同的业务表单的流程处理,一个是单表信息,一个包含明细的主从表信息,后者包含了条件流程的处理,在流程审批中,一般还有一种流程处理就是会签的操作,会签处理是几个审 ...

  7. Winform开发框架中工作流模块之审批会签操作

    在前面介绍了框架中工作流的几个开发过程,本篇随笔重点介绍一下日常审批环节中的具体处理过程,从开始创建表单,以及各个审批.会签过程的流转过程,希望大家对其中流程的处理有一个大概的印象. 1.请假申请表单 ...

  8. Winform开发框架中工作流模块的表设计分析

    在较早博客随笔里面写过文章<Winform开发框架之简易工作流设计>之后,很久没有对工作流部分进行详细的介绍了,本篇继续这个主题,详细介绍其中的设计.实现及效果给大家,这个工作流在好几年前 ...

  9. RDIFramework.NET开发框架编码管理助力业务编码的自动处理

    1.概述 几乎每一个企业应用中不可避免的都会涉及到业务编码规则的问题,比如订单管理中的订单编号,商品管理中的商品编码,项目管理中的项目编码等等,针对这一系列的编码如果直接写在程序中,不仅复杂,代码重复 ...

  10. WinForm开发中通用附件管理控件设计开发参考

    1.引言 在WinForm开发中,文件附件的管理几乎在任何一个应用上都会存在,是一个非常通用集中的公共模块.我们日常记录会伴随着有图片.文档等附件形式来展现,如果为每个业务对象都做一个附件管理,或者每 ...

随机推荐

  1. 耗时6个月,我做了一款干净、免费、开源的AI数据库

    一.Chat2DB简介 在消失的这段时间,我和小伙伴们做了一款集成了AI的数据库管理工具Chat2DB. 他是数据库也集成了AIGC的能力,能够将自然语言转换为SQL,也可以将SQL转换为自然语言,还 ...

  2. ignite

    目录 简介 运行 制作vm文件系统 制作vm基础文件系统文件 创建contianerdClient 创建cniInstance 拉取基础镜像 创建基础文件系统文件 制作vm内核文件 Create vm ...

  3. 使用MD5算法和sha512sum校验和检验文件完整性

    目录 一.前言 二.MD5算法简介 三.什么是校验和 四.使用MD5算法和sha512sum校验和检验文件完整性 五.总结 一.前言 在我们日常生活中,无论是下载文件.传输数据还是备份重要信息,如何确 ...

  4. AI绘画:StableDiffusion炼丹Lora攻略-实战萌宠图片生成

    写在前面的话 近期在小红书发现了许多极其可爱.美观的萌宠图片,对这些美妙的图像深深着迷 于是想着看看利用AI绘画StableDiffusion以下简称(SD)做出来. 以下是详细实操的全过程,包括所有 ...

  5. AI绘画Stable Diffusion实战操作: 62个咒语调教-时尚杂志封面

    今天来给大家分享,如何用sd简单的咒语输出好看的图片的教程,今天做的是时尚杂志专题,话不多说直入主题. 还不会StableDiffusion的基本操作,推荐看看这篇保姆级教程: AI绘画:Stable ...

  6. 虾皮shopee根据ID取商品详情 API 返回值说明

    ​ item_get-根据ID取商品详情  注册开通 shopee.item_get 公共参数 名称 类型 必须 描述 key String 是 调用key(必须以GET方式拼接在URL中) secr ...

  7. excel的烦恼

    Smiling & Weeping ---- 他未对我好半分,偏巧这感情疯长似野草 题目链接:https://www.matiji.net 思路:与新三进制2思路相似,转化为纯26进制,然后往 ...

  8. C++的动态分派在HotSpot VM中的重要应用

    众所周知,多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定.C++ 和 Java 作为当前最为流行的两种面向对象编程语言,其内部对于多态的支持 ...

  9. 使用CEF(六)— 解读CEF的cmake工程配置

    距离笔者的<使用CEF>系列的第一篇文章居然已经过去两年了,在这么长一段时间里,笔者也写了很多其它的文章,再回看<使用CEF(一)- 起步>编写的内容,文笔稚嫩,内容单薄是显而 ...

  10. 轻巧的批量图片压缩工具imgfast

    现在的手机拍照动辄2M3M,还有7M8m的,如果要把这些文件上传到网上应用,浪费网络,占用资源 所以2022年中秋写了这个小工具,可以批量进行图片文件压缩,支持jpg和png. 文件下载链接https ...