简介:一款面向小型企业和个体经营者的免费进销存管理软件,基于窗体程序开发,提供进货、销售、库存、财务等核心管理功能,并附带OA源码,支持二次开发定制,适用于日常商业运营中的进销存流程优化。资源包共161个文件,约10.99MB,涵盖程序运行所需的dll、bpl动态库与exe可执行文件,同时包含html帮助文档、gif操作示意、xls表格模板、mdb数据库、css/js样式脚本以及reg注册表配置等,便于部署参考与功能扩展。目前已有355人学习下载。软件代码结构完整,从内容预览可见包含多个动态库文件、启动脚本与数据库备份,使用者可借助源码研究进销存业务逻辑,结合窗体界面理解商品台账、库存预警和报表生成机制,也可直接部署试用,降低企业信息化门槛。
1. 一套能改源码的免费进销存:onlyit 窗体程序能帮你做到什么程度
第一次把 onlyit 这套免费进销存装进库房那台旧电脑,是在帮本地一个做五金批发的经销商梳理库存。几百个 SKU 的账已经在 Excel 里彻底炸了,进出库记录全靠一人一张表,月底对账对到半夜还是差两万块。换到 onlyit 之后,首先意识到它和你平时用的 SaaS 进销存不是一回事:这是典型的 C/S 架构窗体程序,点开即用、响应快,数据落在本地数据库里,不依赖浏览器,也不存在按年续费这回事。更意外的是,这套免费版连 OA 审批和角色权限都一并打包了,采购单、销售单的审核可以直接挂到审批流上。对小微企业来说是低成本摆脱 Excel 乱账的方案;对想学真实业务系统的开发者来说,这是一套能直接编译、调试、改功能的完整源码包。
2. 部署前必修课:窗体程序的运行环境、数据库初始化与期初数据迁移
2.1 技术栈判断:为什么窗体程序在小型企业里依然比 Web 版顺手
onlyit121020 版属于典型的 Windows 窗体程序,底层是 .NET Framework。这类软件在企业内网里运行,客户端直连数据库,不经过 Web 中间层。很多做库房管理的人第一次接触这种架构会不适应,觉得它不像现在的网页系统那样打开浏览器就能用。但实际部署过之后会发现,窗体程序在局域网里的体验有很多 Web 版给不了的优势。
| 对比项 | 窗体程序(本资源) | 常见 Web 进销存 |
|---|---|---|
| 部署位置 | 每台客户端安装,服务器装数据库 | 服务器部署应用,客户端浏览器访问 |
| 网络依赖 | 局域网直连数据库,无外网也能用 | 依赖内网或公网服务可用性 |
| 操作响应 | 原生控件渲染,点按无延迟 | 受浏览器和网络延迟影响 |
| 数据访问 | 客户端直接读写数据库 | 通过 API 间接访问 |
| 离线能力 | 断网不影响已连内网的桌面端 | 服务不可用则整体停摆 |
| 源码修改 | 直接打开项目改窗体、编译 | 需要改前端和后台接口 |
如果你服务的是一家仓库和办公室在同一栋楼、员工十人上下的商贸公司,这种 C/S 架构反而比 Web 版省心:不需要养一个运维去维护 IIS 或 Nginx,也不牵涉域名和 HTTPS 证书。客户端装上就能跑,数据库备份好就万事大吉。
选择这套软件的一个重要理由是“源码完整”。窗体程序的事件、按钮、数据访问层都是可见的,遇到业务上需要调整的逻辑,比如审核后能否反审核、销售单是否允许改价,直接在源码里定位对应事件改掉即可。对比黑匣子一样的商业闭源软件,这种透明度对二开来说非常友好。
2.2 数据库初始化:连接字符串、服务账号与首次登录配置
onlyit 这类窗体进销存通常使用 SQL Server 存放业务数据。拿到安装包之后,先别急着双击主程序,不然八成会因为连不上数据库而白屏。正常的初始化顺序是先把数据库服务准备好,再让程序去连接它。
整个初始化过程分四步:
- 安装 SQL Server,Express 版也可以,最低建议 2008 R2 及以上。
- 开启 SQL Server 的 TCP/IP 协议,并把服务登录模式改为“混合验证模式”。
- 新建数据库实例,创建一个独立的登录账号并赋予 db_owner 权限。
- 修改程序目录下的连接字符串配置文件,然后启动主程序。
连接字符串通常存放在 exe 同目录的 app.config 或 exename.exe.config 里。这里给出一个常见的配置写法:
<configuration> <connectionStrings> <add name="MainDb" connectionString="Server=192.168.1.21;Database=OnlyIt_Data;User Id=onlyit_user;Password=YourPass123!;MultipleActiveResultSets=True;TrustServerCertificate=True" providerName="System.Data.SqlClient" /> </connectionStrings> </configuration>逻辑说明:这段 XML 是给程序找数据库用的寻址信息。“Server”指向数据库所在机器的内网 IP,不要写成 localhost,除非程序和数据库在同一台机器;“Database”指定账套库名;“User Id”和“Password”是之前建好的独立登录账号;“MultipleActiveResultSets=True”让同一个连接可以同时跑多个查询,避免快速点按钮时出现“连接忙”报错;“TrustServerCertificate=True”在局域网内不配置证书时使用。
注意一个细节:不要图省事直接在连接串里用 sa 账号。我给一家小店做初始化时图方便用的 sa,后来离职员工拿着管理端密码进了数据库后台。从那以后我始终坚持给账套单独建账号,权限只给这一个库,避免整个实例裸奔。这个习惯也建议你保留。
2.3 期初数据导入:从 Excel 到账套的一次性迁移
程序能正常登录后,下一步就是搬数据。大部分使用场景是从别的软件或纸质账本切换到 onlyit,期初库存、未结采购单、应收应付、供应商和客户档案全部要搬进新账套。
我一般建议分为两个批次导入:先导供应商、客户、商品基础档案,再期初库存。原因很简单:库存明细要关联商品档案,如果商品还没建档,库存导进去也是无主数据,后面盘点会一直对不上。导入模板在安装包的“导入模板”目录里,Excel 列的顺序和表头不能随意改动,常见的列是:仓库编码、商品编码、商品名称、规格型号、单位、期初数量、期初成本。
拿到模板之后,在真正导入之前,先对整理好的 Excel 做一遍数据体检,避免导入中途报错。用 SQL 的方式来看就是重复编码检查:
-- 导入前检测商品档案里是否有重复编码 SELECT 商品编码, COUNT(*) AS cnt FROM 商品档案导入表 GROUP BY 商品编码 HAVING COUNT(*) > 1; -- 导入后核对库存总额,确保期初金额不为负数 SELECT SUM(期初数量 * 期初成本) AS 期初总金额 FROM 期初库存导入表;逻辑说明:第一段 SQL 统计每个商品编码出现的次数,一旦出现重复值,导入时主键约束会直接把整批数据打回,提示“违反主键约束”。第二段 SQL 用来在导入完成后核对总金额,确保没有负数成本或空单价混进去。参数上要注意,“期初成本”字段在绝大多数情况下应该是含税成本价,不要填销售价,否则后续毛利统计会全线失真。
3. 单据流转与库存联动:采购、销售、调拨的审核状态与处理逻辑
3.1 单据状态机:草稿、审核、过账对库存产生什么影响
进销存系统中最核心的不是界面好不好看,而是单据状态和库存之间的联动关系。onlyit 的采购入库单、销售出库单、库存调拨单基本都遵循一条状态流转线:草稿 -> 审核 -> 过账,少数场景还支持冲销。
| 状态 | 触发操作 | 库存影响 | 说明 |
|---|---|---|---|
| 草稿 | 保存 | 无 | 尚未生效,可任意修改 |
| 已审核 | 审核按钮 | 按单据方向增减 | 库存锁定,普通操作员不可改 |
| 已过账 | 记账按钮 | 已计入成本/应收应付 | 生成对应的财务记录 |
| 已冲销 | 冲销按钮 | 反向增减 | 用于单据做错后的更正 |
这里最容易理解错的地方是“审核”和“过账”的关系。在多数免费版里,审核和过账可能合成一个按钮,点一下就同时完成。但不管是合成还是分开,核心规则不变:库存只在审核那一刻变更。草稿状态下的单据无论怎么改,都不会动库存数量。
实际业务中,我给一家做管材批发的客户部署时遇到一个场景:销售先开了单,但仓库没货,采购还没到。如果开单时直接锁库存,后面发现库存不足就要删单重做。这个系统的处理方式是允许先开草稿单,等采购入库审核后再回来审核销售单。这里提醒一句:只在审核时变更库存,就要求开单员必须养成分两次操作的习惯——先录单,确认库存足够再审核。如果养成了“录完就审核”的肌肉记忆,负库存基本躲不掉。
3.2 组装单与拆装单:按箱进、按个出的多规格商品处理
五金、日化、食品批发行业普遍存在一个现象:进货整箱,出货按个。一箱螺丝 50 盒,每盒 100 个,如果商品档案里只建一个“螺丝”的档案,库存单位到底是箱还是个,永远说不清。onlyit 专门用组装单和拆装单来解决这类问题,这也是它与普通记账软件最大的区别之一。
组装单的逻辑是把多个子件商品合成一个父件商品。例如父件是“螺丝套箱”,子件是 50 盒螺丝和一个外包装箱。审核组装单时,系统自动减少子件库存,增加父件库存。拆装单一反操作,审核后把父件拆回子件。
组装成本的计算有一个关键参数,叫“损耗率”。实际生产中没有哪个组装过程能做到 100% 不浪费,损耗率就是用来摊成本的。成本计算关系:
decimal childTotalCost = 子件成本合计; decimal lossRate = 2; // 百分比,例如 2 表示 2% decimal parentCost = childTotalCost / (1 - lossRate / 100m);逻辑说明:这段代码计算组装后父件的入库成本。分母中的“1 - lossRate/100”是把损耗摊进成品成本。比如子件总成本是 98 元,损耗率 2%,父件成本就是 98 / 0.98 = 100 元。参数调整上,损耗率对成本的影响很直接:损耗率设高了会虚增库存成本,毛利被压低;设低了成本失真,毛利虚高。我建议实际取数时参考三个月的组装作废记录,别拍脑袋填 5%。系统里这个参数通常在组装单据的工具上设置,不同版本字段名可能叫“损耗率”或“材料损耗百分比”。
3.3 库存预警与积压分析:直接写 SQL 盯数据
窗体进销存普遍自带库存预警界面,但如果数据量大了,或者老板要的是“低于安全库存的 SKU 清单”,直接写 SQL 连数据库查比在界面上翻页快得多。下面是一条典型的库存预警查询:
SELECT p.商品名称, p.规格型号, SUM(s.库存数量) AS 当前库存, p.最低库存, p.最高库存 FROM 库存表 s JOIN 商品档案表 p ON s.商品编码 = p.商品编码 GROUP BY p.商品名称, p.规格型号, p.最低库存, p.最高库存 HAVING SUM(s.库存数量) <= p.最低库存 ORDER BY SUM(s.库存数量) - p.最低库存 ASC;逻辑说明:先用库存表和商品档案表做关联,按商品维度汇总总库存,再用 HAVING 过滤出低于或等于安全库存的商品。注意这里不能用 WHERE,因为“当前库存”是聚合函数 SUM 的结果,条件只能写在 HAVING 里。参数上,“最低库存”和“最高库存”在商品档案里先维护好,阈值大小直接影响这条查询是否有效。
4. 带 OA 的进销存:审批流、角色权限与源码扩展点
4.1 审核按钮背后的事件驱动逻辑:OA 模块挂在哪个钩子上
onlyit 不止是进销存,搜索关键词里还带了 OA 源码。很多用户只盯着库存功能,把 OA 当摆设。实际拆过源码之后会发现,它的审批中心是独立设计的,并且跟业务单据打通了。
审批流在窗体程序里的实现方式通常是事件驱动:用户在界面上点“审核”按钮,程序先判断这张单据类型是否需要在审批中心走流程,如果需要,就生成一条待办任务,把单据状态置为“审批中”,等审批人处理后,再回调单据审核接口。下面这个 C# 片段是我在二次开发时常用的判断逻辑:
// 单据审核前检查是否需要走审批流 if (order.RequireApproval && approvalService.GetApprovalStatus(order.Id) != ApprovalStatus.Approved) { MessageBox.Show("单据未完成审批,无法过账", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } approvalService.Submit(order.Id, currentUser.Id, "提交采购审批");逻辑说明:代码先检查订单对象上的“RequireApproval”布尔字段,这个字段在单据类型表里配置,哪些单据需要审批由管理员在界面上勾选。“GetApprovalStatus”是审批服务提供的方法,返回当前单据在审批流中的状态。只有已经 Approved 的单据才允许继续过账。“Submit”方法提交待办任务,参数是单据号、当前操作人 ID 和审批说明。如果把“RequireApproval”改成永远为 true,整条业务单据链路就会卡在审批环节,所以这个字段的默认值在初始化时要根据业务确认清楚。
4.2 角色权限配置:菜单、按钮和数据可见范围怎么控制
权限系统对于一个带 OA 的进销存来说,实际作用比表面上看到的更重要。仓库管库存、财务管成本、业务管客户,如果所有操作员都能审核销售单,内控等于零。onlyit 的权限模型是典型的“操作员 -> 角色 -> 权限点”三层结构,权限点精确到窗体和按钮。
SELECT r.角色名称, p.权限标识 FROM 角色表 r JOIN 角色权限表 p ON r.角色ID = p.角色ID WHERE p.权限标识 LIKE '单据.销售%' ORDER BY r.角色名称;逻辑说明:通过角色权限关联表查出每个角色在“销售单据”这个模块下拥有的权限点。权限标识的命名规则一般是“模块.功能点”,比如“单据.销售审核”“库存.盘点执行”。二次开发新增一个按钮时,记得在权限表里插入对应的权限记录,否则窗体上按钮会正常显示,但点击时提示“当前用户无权执行”。
这里有一个实际踩过的坑:给 A 角色分配了“销售单审核”权限,但操作员登录后审核按钮是灰色的。后来排查发现,角色确实有权限,但操作员的账号没有被挂到这个角色上,系统里新增操作员时“绑定角色”和“录入密码”是两个独立步骤,漏掉绑定角色,账号就属于无角色状态,按钮权限全部缺失。
4.3 把 OA 模块真正用起来:请假、报销和采购申请共用一条审批链
很多小微企业引入进销存只是要一本库存账,OA 模块往往被冷落。但实际用起来之后会发现,只把业务单据放进 OA 是浪费。onlyit 自带的 OA 功能至少包含三类常用审批:请假申请、费用报销、采购申请。
这三类申请走的是同一条审批链路:申请人填写单子 -> 提交 -> 部门负责人审批 -> 财务/老板终审 -> 归档。相比微信里发条消息等回复的方式,它的价值在于每一笔审批都有单据号、时间戳和最终意见,月底想复盘“这个月采购申请到底批了多少”的时候,直接查审批中心就能拉出明细。采购申请审批通过后,还能一键关联生成采购订单,这在源码层面是通过“源单”字段实现的。
从部署角度说,OA 模块的初始化比进销存简单得多:关键是先把组织架构维护好。组织架构表里要体现上下级关系,审批流才能按“上级审批”规则自动路由。如果导入员工时没有维护汇报关系,审批单到了待办列表里就只能手动指定审批人。
5. 避坑指南:窗体程序实战中的五个典型翻车现场
5.1 数据库连不上,程序启动直接白屏
现象:双击主程序后没有弹出登录窗,直接抛“在与 SQL Server 建立连接时发生与网络相关或特定实例的错误”,或者干脆停留在灰色空白窗体。
原因:最常见的是 SQL Server 服务没启动,其次是 TCP/IP 协议被禁用,再就是连接字符串里 Server 字段写成了“localhost”而数据库在另一台机器。这套软件使用的是数据库直连模式,任何一环不通都会导致程序启动异常。
解决:先确认服务器上 SQL Server 服务已启动,客户端和服务端能互相 ping 通。然后在服务器上打开“SQL Server 配置管理器”,把“SQL Server 网络配置 -> 协议 -> TCP/IP”改为“已启用”,并重启 SQL Server 服务。最后检查 app.config 里的连接字符串,Server 字段必须是数据库服务器的实际 IP,而不是 localhost。
5.2 库存变负数,月底盘点账实不符
现象:商品档案里没做过出库单,库存表里却出现了负数;或者盘点时发现实物还有 20 件,系统账面却是 -5 件。
原因:多数是单据审核顺序倒置——先审核了销售出库单,之后才补做采购入库单,并且系统参数允许负库存出库。这在“先出货后补单”的小公司里太常见了,业务着急,系统又没拦住,最后账目只能靠盘点调整找平。
解决:优先检查系统参数里的“允许负库存”开关,不要为了图方便留在开启状态。已经出现的负库存,正确做法不是直接改库存表,而是找到那张问题出库单反审核,把审核顺序理顺之后再重新审核。如果单据数量已经积压到月底,最快的止损方案是做一张盘点单,把账面调整为实物数量。
5.3 审核按钮没反应,审批流不触发
现象:操作员有审核权,点了“审核”按钮,窗体没提示、单据没变化,像什么都没发生过。
原因:多半是审批流配置和角色权限两处中的一处出了问题。要么这张单据类型被勾选了“需要审批”,但审批流程定义里没有配置任何审批节点,导致提交后无人处理;要么操作员账号没挂角色,按钮事件里做了权限判断后直接 return。
解决:先去单据类型设置里确认“需要审批”的勾选状态,再去审批流定义确认该单据类型至少有一个审批节点。同时用上面第 4.2 节的那条 SQL 查询,确认操作员对应的角色确实拥有该按钮的权限点。按钮事件的源码如果加了日志,打开日志文件能看到具体阻断位置,按日志提示逐层排除。
5.4 多人同时开单,保存时程序卡死或报“该死锁”
现象:月底集中开票时,两个以上操作员同时保存单据,其中一个界面弹“事务死锁”,单据保存失败。
原因:窗体程序客户端直连数据库,默认事务隔离级别下,两个事务同时更新同一张单据主表时会发生锁竞争。尤其是销售开单时同时写入单据头、单据明细、库存流水和多张关联表,锁升级和死锁的概率会明显提升。
解决:常规做法是把事务隔离级别调整为“读已提交”,并让业务逻辑里先更新主表再更新明细表,所有操作保持一致的加锁顺序。此外在连接字符串里启用 MARS(MultipleActiveResultSets=True)能缓解同一连接上多个查询相互阻塞的问题。还要叮嘱操作员,同一份单据不要开两个窗口重复编辑。
5.5 升级新版本后旧账套打不开
现象:从旧版本覆盖安装到 121020 版,启动后提示“数据库版本过低”或“无法附加账套”,旧数据好像凭空消失了。
原因:新版程序的数据结构可能加了字段、改了表结构,旧账套没有随程序同步升级。很多 Windows 窗体程序做升级时,程序文件更新了,但数据库升级脚本没有自动执行。
解决:在覆盖安装前,先通过数据库管理工具把账套库做一次完整备份。升级后如果提示版本不匹配,在安装包目录里找到“数据库升级脚本”目录,按版本号从低到高逐级执行 SQL 脚本。切记不要直接用新程序去附加旧数据文件,先执行升级脚本再启动程序。这套流程我也翻车过一次,后来凡是涉及版本升级,备份账套成为我的固定动作。
6. 备份、防呆与二次开发的三个落地习惯
6.1 用 SQL 命令做定时备份,不依赖人工点按钮
窗体进销存的数据全在数据库里,数据库挂了,一切归零。这套软件自带备份功能,但它的备份逻辑依赖主程序界面操作,如果服务器上的程序一直没打开,备份也就停了。我更习惯直接在数据库服务器上加一个 SQL 作业,每天凌晨自动备份。用一条简单的 sqlcmd 命令就可以验证备份可用:
sqlcmd -S 192.168.1.21 -U onlyit_user -P YourPass123! -Q "BACKUP DATABASE OnlyIt_Data TO DISK='D:\backup\onlyit_$(date +%Y%m%d).bak' WITH FORMAT, INIT"逻辑说明:这条命令通过 sqlcmd 工具连接 SQL Server,执行 BACKUP DATABASE 语句生成备份文件。$(date +%Y%m%d) 是脚本层面的日期拼接,让备份文件名按天变化。加 WITH FORMAT 和 INIT 表示覆盖同名文件并重建备份媒体集。参数配置上,注意把备份路径 D:\backup 先建好,SQL Server 服务账号对该目录要有写入权限,否则作业会一直报错但备份文件始终不出现。
6.2 改源码前先做三件事:备份、记录原逻辑、小步编译
二次开发时最容易翻车的不是写不出代码,而是改完编译通过后,连锁影响了好几处原有功能。我的习惯是:任何改动之前先备份财务相关模块的源码目录,然后在代码里用注释记录原始逻辑,最后每次只改一个功能点就编译一次测试。不要一次性改十个地方再统一编译,窗体程序如果报错,定位问题的成本会成倍增加。
像给销售单加一个“客户备注”字段这种需求,完整路径是:数据库里给销售单明细表扩展字段 -> 在窗体设计器里拖一个文本框 -> 绑定数据源字段 -> 修改保存逻辑补齐字段写入。每一步都很直接,但每一步都可能在编译时报“找不到字段”的错误——因为数据访问层的实体类没有同步更新。记住:加数据库字段,同步改实体类、数据访问接口、窗体绑定这四层,少改一层编译就过不去。
从那次数据库升级翻车之后,我每次给客户交付这套系统,强制自己走一遍从备份数据库到新建账套、导入少量测试数据、开单审核出库的完整流程,哪怕客户催得再急也不能省。这套系统虽然免费,但一旦用起来就是公司的业务命脉,小心一点总归没错。希望这份拆解能帮你在部署和二次开发时少走几段弯路。
本文还有配套的精品资源,点击获取