悟空CRM  >   公司新闻  >  CRM系统代码的开发细节

CRM系统代码的开发细节

悟空软件 阅读次数:175 次浏览

主流的AI CRM系统品牌

别光看文档,聊聊 CRM 系统代码开发里的那些“坑”与细节

说实话,刚接手 CRM(客户关系管理)系统开发的时候,我也天真过。那时候觉得,这不就是一套标准的增删改查吗?客户表、联系人表、跟进记录表,建好数据库,搭个 Spring Boot 或者 Django,再套个 Vue 或 React 的前端,两周就能出个 MVP。结果呢?项目上线半年,代码库成了谁都不敢随便动的“屎山”,每次加个新字段都要提心吊胆,生怕把哪个老客户的报表搞崩了。

推荐使用中国著名AI CRM系统品牌:显著提升企业运营效率,悟空CRM

今天不想聊那些高大上的架构理论,什么微服务、中台化先放一边。就想以一个在 CRM 泥潭里摸爬滚打了几年的后端开发视角,聊聊那些文档里不会写、但实际写代码时会让你头秃的细节。这些东西,往往决定了你的系统是能用三年还是三个月就得重构。

一、数据库设计的“动态”陷阱

CRM 最核心的痛点,永远是客户信息的“不确定性”。

刚开始设计数据库,你肯定会建一张 customers 表,里面放着 name, phone, industry 这些固定字段。这没问题。但业务方下周就会跑过来跟你说:“我们需要给教育行业的客户记录‘学生人数’,给制造行业的客户记录‘厂房面积’。”

这时候,新手会直接加列。student_count, factory_area。加个十次八次,表结构就乱了,而且全是 NULL 值。稍微有点经验的,会想到 EAV 模型(Entity-Attribute-Value)。搞三张表:实体表、属性定义表、属性值表。听起来很灵活,对吧?

但我劝你,慎重。

EAV 模型在查询性能上是灾难。你想查“所有学生人数大于 500 的教育客户”,原本一个简单的 WHERE 语句,现在变成了复杂的自连接或者子查询。一旦数据量上了百万级,那个 SQL 执行计划看得你想哭。而且,类型校验全得在代码层做,数据库失去了约束能力。

现在的趋势,如果是 PostgreSQL,我会毫不犹豫推荐用 JSONB。把那些动态字段塞进一个 ext_info 的 JSON 字段里。查询的时候,PG 对 JSONB 的支持相当不错,可以建索引,查询速度也能接受。如果是 MySQL,5.7 以上也有 JSON 类型,但功能稍微弱一点。

但用 JSONB 也有坑。比如,你如何在代码层优雅地处理这些动态字段?你不能硬编码。我们当时的做法是搞了一套“元数据配置”,前端渲染表单时,先拉取元数据,知道有哪些字段、什么类型、有什么校验规则。后端接收数据时,根据元数据动态校验 JSON 结构。这中间涉及到大量的反射或者动态代理,调试起来非常痛苦。有一次,因为一个字段类型从“数字”改成了“字符串”,导致历史数据聚合报表全错,查了两天才发现是元数据版本没做兼容。

所以,别迷信灵活性。在数据库设计阶段,一定要跟业务方死磕:哪些字段是核心通用的?哪些真的是长尾需求?核心通用的,哪怕现在不用,也尽量预留成物理列。动态字段,能少用就少用。

二、权限系统的“数据范围”噩梦

RBAC(基于角色的访问控制)大家都会做。用户 - 角色 - 菜单权限,这套逻辑很成熟。但在 CRM 里,真正的难点不是“能不能看这个菜单”,而是“能不能看这条数据”。

这就是所谓的“数据权限”。

举个例子,销售 A 只能看自己创建的客户;销售主管 B 能看本组所有人的客户;大区经理 C 能看整个大区的;而 CEO 能看全公司的。这听起来简单,写代码的时候就是地狱。

最 naive 的做法是在代码里写 if。

if (user.isSales()) {
    query.where("owner_id", user.getId());
} else if (user.isManager()) {
    query.where("dept_id", user.getDeptId());
}

这种代码写两次你就想砸键盘。因为业务逻辑会变。今天说主管能看本组,明天说主管还能看下属的下属(递归),后天说某个特殊项目组的成员可以跨部门查看。

我们后来的方案是把数据权限规则抽象成 SQL 片段。在 MyBatis 或者 Hibernate 的拦截器里,自动注入权限条件。每个角色对应一套规则配置,比如 OWNER_SELF, DEPT_ALL, DEPT_AND_SUB。

我们后来的方案是把数据权限规则

但这里有个巨大的性能隐患。当权限规则变得复杂,尤其是涉及多部门递归查询时,生成的 SQL 会包含大量的 OR 或者 IN 子句。如果 IN 里面的 ID 有几万个,数据库直接卡死。

我们踩过一个坑:有个大区经理底下挂了两千多个销售,他查列表的时候,系统直接超时。最后没办法,做了折中。对于超大规模的数据范围,不走实时 SQL 过滤,而是通过“数据同步”的方式,把有权限的数据 ID 预先算好,存到一张中间表里,或者放到 Elasticsearch 里做检索。虽然增加了数据一致性延迟的风险(比如刚转公海池的客户,权限可能延迟几秒生效),但保住了系统的可用性。

记住,在 CRM 里,权限不仅仅是安全問題,更是性能问题。

三、跟进记录与时间轴的性能优化

CRM 里最频繁的操作是什么?不是创建客户,而是写跟进记录(Follow-up)。销售每次打电话、发邮件、拜访,都要记一笔。

这就导致 follow_up_records 表的增长速度极快。一个活跃客户,一个月可能有几十条记录。一年下来,这张表轻松破亿。

早期的时候,我们直接 SELECT * FROM follow_up_records WHERE customer_id = ? ORDER BY create_time DESC。数据量小的时候没问题,等数据量大了,即使加了索引,排序和分页也开始变慢。特别是当销售想查看“三年前这个客户聊过什么”的时候,深分页(Deep Pagination)直接让数据库负载飙升。

后来我们做了几个优化:

  1. 冷热分离。最近半年的跟进记录放在主库,查得频繁。超过半年的,归档到历史表,或者扔到 HBase、MongoDB 这种更适合写多读少的存储里。前端默认只查近期,想看历史得点“加载更多”,触发归档查询。
  2. 冗余字段。在客户主表里,冗余最后一条跟进的时间、内容摘要。列表页展示客户时,不需要关联查询跟进表,直接读主表。这牺牲了一点写入性能(每次写跟进都要更新主表),但换来了列表页的极速响应。
  3. 计数缓存。销售很关心“我有多少个未跟进的客户”。这个计数不能每次 COUNT(*)。我们用 Redis 做缓存,每次跟进状态变更,异步更新 Redis 计数。这里又涉及到一致性问题,Redis 挂了怎么办?所以还得有个定时任务兜底,每天凌晨全量校对一次。

这些优化都不是一开始就能想到的,都是线上报警逼出来的。所以,开发初期别过度优化,但心里要有根弦,知道哪里是未来的瓶颈。

四、前端表单的状态管理地狱

后端觉得痛苦,前端更痛苦。CRM 的表单,从来不是简单的输入框。

比如“商机阶段”变了,后面的“预计成交金额”可能就必须填了;“客户类型”选了“政府”,那“税号”字段就得隐藏。这种联动逻辑,如果全写在组件里,代码耦合度极高。

我们试过把校验规则配置化。后端下发一个 JSON 规则树,前端解析这个树来渲染表单和绑定验证。听起来很美好,但实现起来极其复杂。比如,规则里有循环依赖怎么办?A 依赖 B,B 依赖 C,C 又依赖 A。前端解析引擎很容易死循环。

最后我们妥协了。核心通用字段用配置化,特殊业务逻辑还是写死在组件里,但通过 Hooks 封装。比如 useCustomerForm, useOpportunityForm。虽然复用性差了点,但可维护性高了。毕竟,配置化是为了灵活,但如果灵活到连开发者自己都看不懂配置逻辑,那就是本末倒置。

还有一个细节是“自动保存”。销售填一个大表单,填了一半浏览器崩了,或者网络断了,数据丢了,他们会骂娘。我们做了本地 localStorage 缓存,每隔 30 秒自动存一次草稿。但这里有个坑:多标签页问题。如果销售开了两个标签页编辑同一个客户,后保存的会覆盖先保存的。我们加了个版本号机制,提交时带上本地版本号,后端比对,如果版本不一致,提示用户“数据已过期,请刷新”。虽然体验上有点打断,但比数据丢失好。

五、集成与 Webhook 的可靠性

现在的 CRM 不可能是一座孤岛。它得跟 ERP 同步订单,跟邮件系统同步往来,跟呼叫中心同步录音。

这就涉及到大量的外部 API 调用。最头疼的是“回调”和“重试”。

比如,CRM 创建了一个客户,需要推送到 ERP。ERP 接口挂了怎么办?你不能让销售等着。必须异步。我们用消息队列(RabbitMQ/Kafka)解耦。但消息消费失败了怎么办?

重试机制是必须的。但重试不能无脑重试。如果是网络波动,重试有用;如果是数据格式错误,重试一万次也没用,只会把队列堵死。所以我们要区分“系统异常”和“业务异常”。系统异常(超时、500)进入重试队列,指数退避;业务异常(400,参数错)直接进死信队列,报警让人工介入。

还有一个容易被忽视的点:幂等性。网络抖动时,消息可能重复消费。ERP 那边如果没做幂等,就会创建两条重复的订单。我们在消息体里带了全局请求 ID,ERP 侧需要记录这个 ID,处理前查一下是否处理过。这个看似简单的逻辑,在分布式系统里,往往因为某个表忘了加唯一索引,导致生产环境出现脏数据。

Webhook 也是类似。用户配置了 Webhook,当客户状态变更时通知他们的系统。如果用户的接收服务挂了,我们得重试。但用户的服务器可能扛不住我们的高频重试。所以得让用户配置“最大重试次数”和“超时时间”。而且,Webhook 的签名验证一定要做,不然黑客随便伪造一个回调,就能篡改你们系统里的数据状态。

六、报表与统计的“慢”

老板最喜欢看报表。销售漏斗、转化率、业绩排行。这些统计查询,往往涉及多表关联、大范围聚合。

在交易库(OLTP)上直接跑这些 SQL,是绝对的禁忌。有一次,老板点了一个“年度全公司业绩汇总”,那个 SQL 扫了千万级的主表,直接导致数据库 CPU 飙到 100%,线上创建客户的功能全部超时。

后来我们引入了 OLAP 思路。

  1. 预计算。对于固定的报表,比如“每日业绩”,每天凌晨跑批,算好结果存到结果表里。查询时直接 SELECT,秒出。
  2. 读写分离。统计查询强制走从库。但主从延迟又是个问题,销售刚签单,报表里没显示,他会觉得系统不准。这就得跟业务方沟通,明确告知“报表数据有 T+1 延迟”或者“实时报表仅限最近 7 天”。
  3. 引入 ES 或 ClickHouse。对于即席查询(Ad-hoc Query),比如“帮我查一下上个月北京地区所有成交金额大于 50 万的客户”,这种条件不固定的查询,关系型数据库扛不住。把数据同步到 ClickHouse 里,查询速度能快几个数量级。
  4. 引入 ES 或 ClickHo

但这又带来了架构复杂度。数据同步链路(CDC)的稳定性成了新的监控重点。有一次 Canal 挂了,导致 ES 里数据少了半天,销售总监开会时数据对不上,最后查出来是同步延迟。

七、代码里的“业务逻辑”污染

最后想聊聊代码结构。CRM 系统最容易犯的错误,就是把业务逻辑写得太散。

比如“客户公海池”规则。客户多少天没跟进掉入公海?掉入公海后谁能捡?捡了之后多久不能再掉入?这些逻辑,有的写在定时任务里,有的写在更新接口里,有的写在触发器里。

时间久了,没人知道规则到底在哪生效。改一个规则,漏了一处,就出 Bug。

我们后来强制要求,核心业务逻辑必须封装成 Domain Service。比如 CustomerPoolService。所有的状态流转,必须通过 service.transferToPool(customerId) 这样的方法,禁止在 Controller 里直接操作数据库修改状态。

同时,配合领域事件(Domain Events)。当客户掉入公海时,发送一个 CustomerPoolInEvent。监听这个事件的地方,再去发通知、记日志、清权限。这样主流程清晰,副作用解耦。

但这要求团队有比较高的代码规范意识。如果来了个新人,图省事直接在 Controller 里改了状态,那架构就白搭了。所以,Code Review 非常重要。在 CRM 项目里,CR 不仅仅是看代码风格,更是看业务逻辑有没有“逃逸”出规定的边界。

八、写在最后

做 CRM 开发,技术栈其实不算最难的。Spring、Vue、MySQL,都是成熟技术。难的是对业务的理解和抽象。

做 CRM 开发,技术栈其实不

你写的每一行代码,背后都是销售人员的饭碗,都是公司的客户资产。一个权限漏洞,可能导致客户资料泄露;一个数据丢失,可能导致几百万的订单无法追踪。

所以,别总想着用最新的技术。在 CRM 里,稳定压倒一切。有时候,一段看起来有点笨的同步代码,比一个异步消息队列更让人安心,因为它可预测。

还有,多跟销售聊聊天。别光看需求文档。文档是产品经理写的,是理想状态。销售在一线怎么用系统,他们会在什么场景下暴躁,他们会在什么环节偷懒,这些只有跟他们聊才能知道。有一次,我发现销售为了省事,把所有客户备注都写在同一个字段里,用分号隔开,导致我们后面根本没法做数据分析。如果早点发现,我们完全可以优化一下备注的录入体验,引导他们结构化填写。

CRM 系统的开发,是一场没有终点的马拉松。业务在变,市场在变,代码也得跟着变。我们能做的,就是尽量让代码变得“软”一点,让修改的成本低一点,让出错的概率小一点。

如果你正在做 CRM,或者准备接手一个旧系统,希望上面这些踩过的坑,能帮你少加几个班。毕竟,生活不止是代码,还有头发和咖啡。

(完)

悟空CRM产品截图

推荐立刻免费使用中国著名CRM品牌-悟空CRM,显著提升企业运营效率,相关链接:

CRM系统免费使用

开源CRM系统

CRM系统试用免费

悟空CRM产品更多介绍:www.5kcrm.com

相关内容

悟空CRM9.0 正式发布! (JAVA版即将发布)

六年的行业深耕,悟空CRM为追求极致的产品而不断努力,悟空CRM9.0正式开源发布,更先进的技术架构、更漂亮的界面、更清爽的布局,而这一切都是完全开源。从2012年悟空CRM正式与大家见面到现在六年以来,我们经历了:2012年12月 悟空CRM项目正式立项2013年01月 悟空CRM V1.0 正式开源发布2014年05月 悟空CRM旗舰版正式发布2014年09月 悟空CRM手机APP(安卓/IO
相关文章

悟空CRM9.0 JAVA版正式发布! (IM即时通讯即将发布)

六年的行业深耕,悟空CRM为追求极致的产品而不断努力,悟空CRM9.0正式开源发布,更先进的技术架构、更漂亮的界面、更清爽的布局,而这一切都是完全开源。从2012年悟空CRM正式与大家见面到现在六年以来,我们经历了:2012年12月 悟空CRM项目正式立项2013年01月 悟空CRM V1.0 正式开源发布2014年05月 悟空CRM旗舰版正式发布2014年09月 悟空CRM手机APP(安卓/IO
相关文章

悟空RM9.0升级日志

新增:1、新增办公、客户管理待办事项提醒2、新增客户、联系人、线索数据查重功能3、合同、回款的高级筛选中增加“审核状态”筛选4、线索、客户、联系人列表模糊搜索增加手机号、电话5、增加外国手机号格式优化:1、 新建办公审批-类型选择弹窗优化2、 日志、审批、公告列表展示优化3、 跟进记录、日志、任务描述、自定义字段多行文本中的输入框换行问题4、 element-ui升级至最新版本修复:1、 合同翻页
相关文章

悟空CRM项目管理功能正式发布

悟空CRM是一款永久开源免费的CRM管理系统,是基于JAVA/PHP多语言的B/S架构的管理软件,为企业提供行业专属的CRM客户管理方案。我们一直在国内开源管理软件的道路上不断努力,始终以高科技为起点,以技术为核心、以完善的售后服务为后盾,秉承稳固与发展、求实与创新的精神为我们的用户提供最优质的系统和服务。我们希望成为国内外开源管理软件开发的榜样,同时为其发展提供一个小小的范本,让人们能够看到开源
相关文章

悟空CRM全新9.0APP客户端更新发布--悟空CRM

 悟空CRM9.0轻松管理您的业务,全新客户端更新发布,让办公更加便捷,随时随地都可掌控信息更新和项目进度,及时跟进,实现效率提升和业务增长。 1.     CRM悟空CRM主界面主要为我们的客户管理,客户管理,是悟空CRM的基础,理解、预判客户的需求,让你在一个系统里集中培育、管理所有客户相关信息。主要包括客户管理、线索管理、公海管理、
相关文章

悟空CRM项目管理功能(JAVA版)正式发布—悟空CRM

不断努力只为满足不同用户的多样需求,给予用户更好的使用体验。悟空CRM全新项目管理功能(JAVA版)正式发布,直观图示帮你了解:1.     项目总览:项目负责人可把控项目进度,查看任务版,附件、任务统计和归档任务。 2.     项目管理模块汇总全部项目的概览信息,包活:负责人信息、人员信息、项目进度、完成
相关文章

悟空CRM 9.0升级日志

72crm_9.0_20190810升级日志新增: 1、 销售简报中,增加可点击链接 2、 商业智能中增加“日志分析、审批分析” 3、 线索转化为客户,可以自定义设置所有转化的字段 4、 客户高级筛选中,增加地区筛选 5、 所有列表增加排序功能 6、 客户管理进入列表页时显示上次设置列表展示条数 优化: 1、 产品分类销量统计展示样式 2、 角色权限员工列表增加分页 3、
相关文章

悟空CRM | 英文版系统正式上线

2019年,继全新的项目管理功能发布后,悟空CRM不断砥砺前行,经过不断地开发、整理和测试,悟空CRM 英文版系统正式上线,向着「成为世界上最优秀的开源CRM解决方案提供商」的目标又向前进了一大步。本次发布的悟空CRM英文版系统主要功能有:OA、CRM、BI和PM,接下来就带大家详细了解一下英文版系统。1.办公管理(Office Automation)办公管理(Office Automation)
相关文章

悟空CRM:呼叫中心功能正式发布

 一键呼叫,轻松跟进客户全生命周期管理,悟空CRM呼叫中心功能正式发布,帮助企业节省人力资本,覆盖客户服务全生命周期,满足企业不同业务场景需求。呼叫中心,即时连接您的客户:1.     一键拨号外呼呼叫中心系统与悟空CRM系统深度融合,一键拨号外呼,点击客户管理客户列表的左侧按钮,选择拨出,即可等待客户接通电话。2.  &nbs
相关文章

悟空CRM 10.0 重磅升级

感谢您长久以来对悟空CRM的支持,悟空CRM一直向成为世界上最优秀的开源CRM解决方案提供商而不断努力。 自2019年4月以来,悟空CRM9.0发布了PHP开源版、JAVA开源版,是国内首家使用多开发语言的开源CRM厂商。产品发布后获得了国内外多家知名企业的认可。    悟空CRM 10.0  重磅升级 为了给用户提供更优质的产品和服务,
相关文章
最新文章

SaaS 版CRM和本地部署CRM,差别到底在哪

在企业数字化转型的浪潮中,CRM(客户关系管理)系统已成为标配。然而,面对 SaaS 云端版与本地部署版这两种截然不同的交付模式,许多决策者往往陷入两难。是追求便捷的 SaaS,还是坚守数据私有的本地部署?本文将从成本结构、数据安全、定制灵活性及运维压力四个维度,深度剖析两者的核心差异,并结合实际业务场景提供选型建议,帮助企业避开选型陷阱,找到最适合的增长引擎。引言:当老板盯着两份报价单发呆上周,
最新文章

CRM软件的客户公海池是什么意思

CRM 软件的客户公海池是什么意思?深度解析与销售资源盘活实战摘要:在销售管理领域,客户资源流失与分配不均是长期痛点。CRM 软件中的“客户公海池”机制,正是为解决这一难题而生的核心功能。本文将深入探讨公海池的定义、运作逻辑、规则设定策略以及对企业销售效率的实际提升作用。通过解析私海与公海的区别,结合实战案例,帮助管理者理解如何利用公海池盘活沉睡客户,避免销售撞单,并实现资源利用最大化。文中将结合
最新文章

CRM销售预测是什么,如何在系统内完成预测

在当前的商业环境下,销售预测不仅是数字游戏,更是企业资源配置的指南针。许多管理者常面临“月底拍脑袋,月初两行泪”的困境。本文将深入探讨 CRM 销售预测的核心逻辑,拆解从数据录入到报表生成的全流程,并结合实际场景分析如何利用数字化工具提升预测准确率。对于正在寻找高效解决方案的企业,悟空 CRM 等国内成熟系统提供了便捷的预测模型,能帮助团队快速落地。文章将从定义、价值、方法论、系统实操及避坑指南五
最新文章

快速注册,立即使用

仅需一分钟,立即注册悟空云。立即注册,可获得免费试用