站长信息
jeffery.xu
jeffery.xu

软件工程师

欢迎访问我的个人笔记网站!我是一名热爱技术的开发者,专注于Web开发和技术分享。

811495111@qq.com
18521510875
筛选

个人笔记

Linux发布java web
工作笔记

代码 1 更新系统

sudo apt update && sudo apt upgrade -y

2.1 安装 JDK 8

Ubuntu 26.04 官方软件源已不提供 OpenJDK 8 软件包,需要改用 Eclipse Temurin 发行版安装,以下两种方式任选其一:方式一通过 Adoptium 官方 apt 源安装,便于后续随 apt 升级;方式二直接解压压缩包,不依赖第三方源,任何情况下都可用。

2.1.1 方式一:Adoptium apt 源安装

代码 2 添加 Adoptium 源并安装 temurin-8-jdk

sudo apt install -y wget apt-transport-https gpg

sudo mkdir -p /etc/apt/keyrings

wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | sudo gpg --dearmor -o /etc/apt/keyrings/adoptium.gpg

echo "deb [signed-by=/etc/apt/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | sudo tee /etc/apt/sources.list.d/adoptium.list

sudo apt update

sudo apt install -y temurin-8-jdk

apt update adoptium 源报 404,说明当前 Ubuntu 版本的代号尚未被 Adoptium 收录,请改用方式二。

2.1.2 方式二:压缩包安装

代码 3 下载并解压 Temurin 8 /opt/jdk8

cd /tmp

wget https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u422-b05/OpenJDK8U-jdk_x64_linux_hotspot_8u422b05.tar.gz

sudo mkdir -p /opt/jdk8

sudo tar -xzf OpenJDK8U-jdk_x64_linux_hotspot_8u422b05.tar.gz -C /opt/jdk8 --strip-components=1

printf 'export JAVA_HOME=/opt/jdk8\nexport PATH=$JAVA_HOME/bin:$PATH\n' | sudo tee /etc/profile.d/jdk8.sh

source /etc/profile.d/jdk8.sh

压缩包的具体版本号以 adoptium.net 网站最新的 8u 版本为准,替换下载地址中对应文件名即可。

2.1.3 验证安装

代码 4 验证 Java 版本与实际路径

java -version

readlink -f $(which java)

输出应包含 openjdk version "1.8.0_xxx"readlink 的结果即 Java 可执行文件的实际路径(方式二为 /opt/jdk8/bin/java,方式一通常为 /usr/lib/jvm/temurin-8-jdk-amd64/bin/java),第 6 章编写 systemd 服务时需要使用该路径。

2.2 安装并配置 Redis

代码 5 安装 Redis 并验证

sudo apt install -y redis-server

sudo systemctl enable --now redis-server

redis-cli ping

redis-cli ping 返回 PONG 即正常。Ubuntu 默认配置仅监听 127.0.0.1,只有本机可以访问,与本部署形态一致,请勿改为对外监听。如需设置访问密码(生产环境建议设置),编辑 /etc/redis/redis.conf,找到 requirepass 配置行,取消注释并填入密码:

代码 6 Redis 密码配置片段(/etc/redis/redis.conf

requirepass <Redis密码>

代码 7 重启 Redis 并带密码验证

sudo systemctl restart redis-server

redis-cli -a <Redis密码> ping

设置密码后,需要按第 4 章在 application.yml spring.redis.password 中填入同一密码,否则后端启动后会报 Redis 连接认证失败。

2.3 安装 Nginx

代码 8 安装 Nginx 并设为开机自启

sudo apt install -y nginx

sudo systemctl enable --now nginx

systemctl status nginx

状态显示 active (running) 即安装成功,站点配置在第 7 章编写。

2.4 安装 MySQL 客户端(可选)

安装客户端仅用于第 3 章的数据库连通性验证,不安装也可改用端口探测方式:

sudo apt install -y mysql-client

2.5 防火墙配置

Ubuntu 默认防火墙为 ufw。本部署只需对外开放 SSH 80 端口;8080 6379 仅本机使用,不要对外开放。

代码 9 配置 ufw 防火墙

sudo ufw allow OpenSSH

sudo ufw allow 80/tcp

sudo ufw enable

sudo ufw status

特别注意:执行 ufw enable 之前必须先放行 SSH,否则远程连接会被防火墙断开。若 SSH 使用非默认端口,请先将实际端口加入放行规则。

3 数据库准备与连通性验证

3.1 连通性验证

部署服务器必须能访问远程 MySQL 3306 端口。已安装客户端的,直接尝试登录目标库:

代码 10 测试数据库连接

mysql -h <数据库IP> -P 3306 -u <数据库用户名> -p

输入密码后能进入 mysql 提示符即连通正常,输入 exit 退出。未安装客户端时,可用 shell 临时探测端口连通性:

代码 11 探测 3306 端口连通性

timeout 3 bash -c '</dev/tcp/<数据库IP>/3306' && echo OK

若连接超时或被拒绝,依次检查:数据库侧安全组或白名单是否放行了本服务器的出口 IP;数据库账号是否限制了登录主机来源;账号是否对目标库有权限。

3.2 全新空库初始化(可选)

如果目标数据库已经初始化并承载过本系统,跳过本节。全新空库请按表 5 顺序执行仓库 db/ 目录下的脚本。

5 数据库初始化脚本执行顺序

顺序

脚本

内容说明

1

DDLL.sql

建库与系统表结构。注意脚本内含 create database dms,若目标库名不同,需先修改该语句与 use 语句

2

原始数据表结构设计.sql

业务原始数据表结构(dms_raw_sale 等)

3

dms_province_data.sqldms_city_data.sqldms_county_data.sql

省、市、县区基础数据

4

dealer_data.sql

经销商基础数据

5

初始数据.sql

系统账号、部门、菜单、参数等初始数据

6

升级脚本.sql

增量结构升级(历史版本库补齐字段)

7

20260914_disable_login_captcha.sql

关闭登录页验证码的系统参数

 

关于第 7 项:该参数同时存在 Redis 缓存,执行 SQL 后需重启后端服务,或在系统管理的参数设置中点击「刷新缓存」才会生效。

另外注意脚本编码:仓库内各脚本编码不完全一致,部分为 UTF-8,部分为 GBK。导入前建议先统一转换为 UTF-8,或在导入命令中显式指定与文件编码一致的字符集,避免中文数据乱码:

代码 12 按指定字符集导入脚本

mysql -h <数据库IP> -u <数据库用户名> -p --default-character-set=utf8 < <脚本.sql>

4 应用配置修改(打包前)

以下修改均在源码中进行,修改完成后在开发机执行第 5 章的打包命令。涉及的两个配置文件与一个日志文件均位于 dms-master/admin/src/main/resources/ 目录。

4.1 数据源配置(application-druid.yml

系统当前激活的 profile druid(由 application.yml spring.profiles.active: druid 指定),因此数据源在 application-druid.yml 中修改。将 master 数据源替换为远程库连接信息:

代码 13 master 数据源配置片段(application-druid.yml

spring:

    datasource:

        druid:

            master:

                url: jdbc:mysql://<数据库IP>:3306/<库名>?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true

                username: <数据库用户名>

                password: <数据库密码>

连接串中的 serverTimezone=GMT%2B8 allowMultiQueries=true 是业务 SQL 依赖的参数,替换地址与库名时请原样保留。从库 slave 默认关闭,无需修改;文件中可能存在历史注释掉的旧连接信息,保持不动即可,注意不要误启用。

4.2 上传目录与 Redis 配置(application.yml

上传目录 newbit.profile 默认是 Windows 路径,部署到 Linux 必须修改;Redis 安装在本机时,连接配置保持默认即可:

代码 14 上传目录与 Redis 配置片段(application.yml

newbit:

    profile: /home/dms/uploadPath

 

spring:

    redis:

        host: localhost

        port: 6379

        database: 0

        password: <Redis密码,未设置则留空>

4.3 日志目录(logback.xml

日志路径由 logback.xml log.path 属性指定,默认为 /home/newbit/logs,可保持默认(第 6 章会创建该目录),也可改为其他绝对路径:

代码 15 日志路径配置(logback.xml

<property name="log.path" value="/home/newbit/logs" />

4.4 生产环境建议(可选)

以下调整不是部署的必要条件,但对外或生产环境建议执行:

1.      日志级别:application.yml com.newbit 的日志级别默认为 debug,生产环境建议改为 info,减少日志量。

2.      Swaggerswagger.enabled 默认为 true,对外环境建议改为 false

3.      Druid 控制台:application-druid.yml statViewServlet 默认开启且密码较弱,建议修改控制台账号密码,或通过 Nginx 限制 /prod-api/druid 路径的访问来源。

4.      令牌密钥:token.secret 建议更换为足够长的随机字符串;更换后已发放的登录令牌全部失效,用户需重新登录。

5 构建与上传

5.1 后端打包

在源码根目录执行以下命令(构建机需 JDK 8 Maven):

代码 16 后端 Maven 打包

cd dms-master

mvn -pl admin -am clean package -DskipTests

构建产物为 Spring Boot 可执行 jar,位于 dms-master/admin/target/admin.jar

5.2 前端打包

代码 17 前端构建

cd front

npm install

npm run build:prod

构建产物为 front/dist 目录。前端基于 Vue CLI 4 dart-sassNode.js 建议 14 16 版本。推荐直接在日常开发机完成前后端构建,服务器上无需安装 Node Maven

5.3 上传到服务器

Windows 开发机上使用 scp 上传(也可使用 WinSCP 等图形化工具):

代码 18 上传构建产物到服务器(开发机执行)

scp dms-master\admin\target\admin.jar <用户名>@<服务器IP>:/tmp/

scp -r front\dist <用户名>@<服务器IP>:/tmp/dms-dist

上传后文件暂存于服务器 /tmp 目录,后续章节会移动到正式位置。

6 后端部署

6.1 创建目录并就位应用包

代码 19 创建目录并移动 jar

sudo mkdir -p /opt/dms /home/dms/uploadPath /home/newbit/logs

sudo mv /tmp/admin.jar /opt/dms/admin.jar

6.2 创建 systemd 服务

新建服务单元文件 /etc/systemd/system/dms.service(可用 sudo nano 写入,或用 tee 命令写入)。ExecStart Java 路径按 2.1 节的实际安装方式调整:

代码 20 后端服务单元(/etc/systemd/system/dms.service

[Unit]

Description=FRISO DMS Backend Service

After=network.target redis-server.service

 

[Service]

Type=simple

WorkingDirectory=/opt/dms

ExecStart=/opt/jdk8/bin/java -Dfile.encoding=UTF-8 -jar /opt/dms/admin.jar

Restart=on-failure

RestartSec=10

 

[Install]

WantedBy=multi-user.target

说明:-Dfile.encoding=UTF-8 用于规避日志与部分文本处理中的中文乱码;Restart=on-failure 使进程异常退出后 10 秒自动拉起;WorkingDirectory 设为 jar 所在目录,便于相对路径资源访问。

6.3 启动与验证

代码 21 加载并启动后端服务

sudo systemctl daemon-reload

sudo systemctl enable --now dms

systemctl status dms

状态显示 active (running) 即启动成功。继续验证接口与查看日志:

代码 22 验证后端接口与日志

curl http://127.0.0.1:8080/

journalctl -u dms -n 100 --no-pager

tail -f /home/newbit/logs/sys-error.log

curl 返回 JSON 内容(如验证码、错误提示等)说明 8080 已正常监听。若启动失败,sys-error.log journalctl 输出中会包含具体异常,常见原因是数据库连不通或 Redis 认证失败,处理后执行 sudo systemctl restart dms 重启。

7 前端部署与 Nginx 配置

7.1 就位前端文件

代码 23 部署前端静态文件

sudo mkdir -p /var/www

sudo rm -rf /var/www/dms

sudo cp -r /tmp/dms-dist /var/www/dms

7.2 编写站点配置

新建 /etc/nginx/conf.d/dms.conf,内容如下:

代码 24 Nginx 站点配置(/etc/nginx/conf.d/dms.conf

server {

    listen 80;

    server_name _;

 

    client_max_body_size 20m;

 

    location / {

        root  /var/www/dms;

        index index.html;

        try_files $uri $uri/ /index.html;

    }

 

    location /prod-api/ {

        proxy_pass http://127.0.0.1:8080/;

        proxy_set_header Host $host;

        proxy_set_header X-Real-IP $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header X-Forwarded-Proto $scheme;

    }

}

配置要点有三处。其一,try_files:前端路由使用 history 模式,刷新页面或直接访问子路径时需要回退到 index.html,缺少该配置会出现刷新后 404。其二,proxy_pass 末尾的斜杠:Nginx 会把 /prod-api 前缀去除后转发给后端,与前端的 VUE_APP_BASE_API 配置对应,漏写斜杠会导致后端收到带前缀的路径而返回 404。其三,client_max_body_size:后端上传限制为单文件 10MB、单次请求合计 20MBNginx 该值不小于后端限制即可,否则文件上传会被 Nginx 413 状态码拦截。

7.3 启用配置

代码 25 启用站点并重载 Nginx

sudo rm -f /etc/nginx/sites-enabled/default

sudo nginx -t

sudo systemctl reload nginx

Ubuntu 默认站点同样监听 80 端口,需要先删除其软链接避免冲突。nginx -t 校验通过后重载生效;若校验失败,请根据提示检查配置文件的语法。

医院补偿类型功能开发说明
工作笔记


一、需求背景
为支持补偿类型在医院维度上的精细化控制,本次在原有“经销商 / 产品 / 省市补偿类型”基础上,新增“医院补偿类型”能力,并同步打通总部维护侧与 DMS/SOI 应用侧逻辑。
本次改造目标为:
•    总部可维护医院补偿类型关系
•    支持医院补偿类型导入、导出
•    补偿申请选择补偿类型时,按医院规则进行过滤
•    补偿申请新增列表与补偿类型选择逻辑保持一致
---
二、提测范围
1. 总部侧-补偿类型维护
新增“医院”维度的补偿类型维护能力,支持:
•    新增
•    修改
•    查看
•    删除
•    导入
•    导出
2. DMS / SOI 应用侧
在补偿申请相关场景中增加医院维度筛选逻辑,涉及:
•    补偿类型选择弹窗
•    补偿申请新增可选数据列表
•    DMS 端
•    SOI 端
---
三、本次开发内容
1. 总部侧开发内容
1.1 医院补偿类型 CRUD
在补偿类型主档下新增“医院”页签,支持维护医院明细关系。
功能点
•    可选择医院
•    可维护“是否纳入补偿”
•    可查看医院补偿类型明细
•    同一补偿类型下支持多医院维护
•    增加重复校验
业务规则
是否纳入补偿 分两种模式:
•    是:表示当前补偿类型仅对配置的医院生效
•    否:表示当前补偿类型对配置的医院不生效
---
1.2 医院补偿类型一致性控制
同一个补偿类型下,所有医院记录的 是否纳入补偿 必须保持一致,不允许同一补偿类型同时出现“是”和“否”。
已实现
•    前端联动同步
•    后端保存前统一规范化处理
•    导入时一致性校验
---
1.3 医院补偿类型导入
新增医院补偿类型导入能力。
导入规则
•    医院代码必填,且必须存在
•    补偿类型代码必填,且必须存在
•    是否纳入补偿 必填,仅允许填写“是/否”
•    标识必填,仅允许填写“新增/覆盖”
•    同一补偿类型下,是否纳入补偿 必须一致
•    任意一条校验失败,则整批导入失败
标识说明
•    新增:保留原有医院关系,新增本次导入数据
•    覆盖:先清除该补偿类型历史医院数据,再导入本次数据
---
1.4 医院补偿类型导出
新增医院补偿类型导出能力,支持导出以下字段:
•    补偿名称
•    补偿代码
•    医院代码
•    医院名称
•    是否纳入补偿
•    创建时间/创建人
•    修改时间/修改人
---
2. DMS / SOI 应用侧开发内容
2.1 补偿类型选择增加医院筛选逻辑
在补偿申请中选择“补偿类型”时,除原有经销商、产品、省市规则外,新增医院规则过滤。
规则说明
医院条件与原有规则关系为 AND。
即在满足经销商 / 产品 / 省市逻辑的基础上,还需满足医院逻辑。
医院筛选规则
•    若补偿类型未配置医院关系:不限制医院
•    若补偿类型配置为 IsInclude = 1
•    当前医院必须存在于医院补偿配置中
•    若补偿类型配置为 IsInclude = 0
•    当前医院必须不存在于医院补偿配置中
---
2.2 补偿申请新增列表增加同样医院逻辑
为保证补偿申请入口行为一致,补偿申请新增列表同步增加同样的医院筛选逻辑。
已同步场景
•    DMS:CompensateApplicationADD
•    SOI:CompensateApplicationADD_SOI
目标
避免出现以下不一致问题:
•    列表中数据可选,但补偿类型不可选
•    补偿类型可选,但实际列表不应出现
---
四、影响模块
总部维护侧
•    补偿类型主档
•    医院补偿类型子表
•    医院补偿类型导入
•    医院补偿类型导出
应用侧
•    DMS 补偿申请
•    SOI 补偿申请
•    补偿类型选择弹窗
•    补偿申请新增列表
---
五、重点测试场景
1. 总部侧 CRUD 测试
场景 1:新增医院补偿类型
•    新增一个补偿类型
•    关联多个医院
•    是否纳入补偿 = 是
•    保存成功
场景 2:修改医院补偿类型
•    修改已有补偿类型的医院列表
•    修改后保存成功
•    查看明细正常
场景 3:一致性校验
•    同一补偿类型下尝试同时保存“是”和“否”
•    预期:不允许保存 / 系统统一规范化
场景 4:重复医院校验
•    同一补偿类型下重复选择同一家医院
•    预期:不允许重复
---
2. 导入测试
场景 5:正常导入-纳入补偿
•    同一补偿类型导入多个医院
•    是否纳入补偿 均为“是”
•    预期:导入成功
场景 6:正常导入-不纳入补偿
•    同一补偿类型导入多个医院
•    是否纳入补偿 均为“否”
•    预期:导入成功
场景 7:混合导入
•    同一补偿类型下同时导入“是”和“否”
•    预期:导入失败
场景 8:医院代码不存在
•    预期:导入失败
场景 9:补偿类型代码不存在
•    预期:导入失败
场景 10:覆盖导入
•    原有医院关系存在
•    使用“覆盖”重新导入
•    预期:旧数据被替换
---
3. 导出测试
场景 11:医院补偿类型导出
•    从补偿类型列表点击“医院导出”
•    预期:
•    成功下载
•    数据字段完整
•    内容与维护数据一致
---
4. DMS / SOI 应用侧测试
场景 12:未配置医院关系
•    某补偿类型只配置经销商/产品/省市,未配置医院
•    预期:该补偿类型不受医院限制
场景 13:医院纳入补偿
•    配置 IsInclude = 1
•    当前医院在配置内
•    预期:补偿类型可见 / 列表可查
场景 14:医院纳入补偿但不匹配
•    配置 IsInclude = 1
•    当前医院不在配置内
•    预期:补偿类型不可见 / 列表不可查
场景 15:医院不纳入补偿
•    配置 IsInclude = 0
•    当前医院在配置内
•    预期:补偿类型不可见 / 列表不可查
场景 16:医院不纳入补偿且不匹配
•    配置 IsInclude = 0
•    当前医院不在配置内
•    预期:补偿类型可见 / 列表可查
---
5. 联合规则测试
场景 17:省市通过,医院通过
•    预期:可选
场景 18:省市通过,医院不通过
•    预期:不可选
场景 19:省市不通过,医院通过
•    预期:不可选
场景 20:省市与医院都通过
•    预期:最终可用
说明:省市与医院关系为 AND
---
六、注意事项
1.    同一补偿类型下医院关系采用统一模式,不支持部分医院纳入、部分医院排除混用
2.    本次改造不影响现有补偿金额计算公式
3.    本次改造主要影响“补偿类型是否可选”和“申请数据是否可见”
4.    DMS 与 SOI 两侧已同步处理,需分别验证

BusinessView的修改
工作笔记

1) 在模型层新增属性(ViewItem)
在 ..\Wicresoft\BusinessObject\ObjectView\BusinessObjectView.cs 的 ViewItem 中新增了 EndTimeInclude(并提供了对应构造函数),用于标记某个日期查询项是否要“按日期(yyyy-MM-dd)比较”。
---
2) 在查询控件生成阶段把属性下发到 UI 节点
在 ..\SOI\CustomControls\QueryProvider.ascx.cs 的 GenerateQueryItem(ViewItem vi, int rowIndex) 里,增加了:
•    queryItem.Attributes["EndTimeInclude"] = vi.EndTimeInclude.ToString().ToLower();
这样每一行查询项(__queryitem_x)都带上了这个标记。
GridView 的作用是通过 ucQueryProvider.InitQueryProvider(this.BusinessObjectView) 把 BusinessObjectView 传给 QueryProvider,因此 vi.EndTimeInclude 能被拿到并写入 queryItem.Attributes。
---
3) 在过滤拼接阶段按该属性走不同 SQL 逻辑
在 QueryProvider.GetBusinessFilter(...) 的 DateTime 分支中,读取:
•    queryItem.Attributes["EndTimeInclude"]
并做条件拼接分支:
•    非 true:沿用原逻辑(field <= endTime)。
•    true:对字段加 CONVERT(varchar(10), field, 23),确保按 yyyy-MM-dd 比较后再和结束日期拼接。

上线前调整
工作笔记


ADD DMS  经销商基准价功能:

1.列表及查询及导出去掉有效日期、失效日期、修改创建时间为创建日期、新增修改日期。

2.当前年份字段改成使用年份,列表、查询、导出都改掉。

3.价格字段放到产品编码后面。

4.查询条件增加经销商名称查询

5.导出都按照最新列表内容进行导出。

6.货号升级功能看下代码逻辑,做修改的时候,需要更新modifytime字段

弹框查询慢优化
工作笔记

一、当前已改的代码
1. 去掉了 Page_Load 的重复绑定
文件:DMS\OrderInfoMnangerment\OrderInfo\UT_ProductListSelect.aspx.cs
你现在的 InitializeComponent() 里已经把这句注释掉了:
•    this.Load += new System.EventHandler(this.Page_Load);
作用:
•    避免首次打开弹窗时 Page_Load 被重复触发
•    避免 !IsPostBack 里的 ucCustomPaging.LoadData(...) 被多执行一次
---
2. 去掉了 btnQuery 的重复绑定
文件:DMS\OrderInfoMnangerment\OrderInfo\UT_ProductListSelect.aspx.cs
AppendServerEvents() 里原来有两次:
•    this.btnQuery.ButtonClick += ...
现在保留了一次,另一处已注释。
作用:
•    点击“查询”按钮时,避免 btnQuery_ButtonClick() 触发两次
•    避免 GetMyProductInfoList() 被重复调用
---
3. 优化了 GetFilter() 的 SQL 条件拼接
文件:DMS\OrderInfoMnangerment\OrderInfo\UT_ProductListSelect.aspx.cs
这部分是本次真正落地的主要 SQL 优化。
3.1 SSO_SameLotInfo
从:
•    FK_SSO_ProductCategoryID in (...)
改成:
•    exists(select 1 ...)
作用:
•    减少大表 in 子查询带来的额外代价
3.2 UT_OrderDetailInfo
从:
•    ut_product.pkid not in (...)
改成:
•    not exists(select 1 ...)
作用:
•    避免 not in 的执行问题和 NULL 风险
•    更利于索引使用
3.3 SOI_ProductStockAdjust
从:
•    对 StartTime / EndTime 做 CONVERT(...)
改成:
•    StartTime < tomorrowStart
•    EndTime >= todayStart
并且整体改成:
•    not exists(...)
作用:
•    去掉对列的函数转换
•    提升日期范围条件走索引的概率
3.4 FCN_Product
从:
•    CONVERT(nvarchar(10), BuyStartTime, 120) > ...
改成:
•    BuyStartTime >= tomorrowStart
作用:
•    日期字段可走索引
3.5 OPF_ProductSettingRecord + AllowOrderChoose
从:
•    月份比较 CONVERT(nvarchar(7), ...)
•    日期比较 CONVERT(varchar(100), ...)
改成:
•    BeginDate < nextMonthStart
•    EndDate >= monthStart
•    AllowOrderChoose 也改成日期范围比较
作用:
•    去掉月份/日期字符串转换
•    更适合索引
3.6 SOI_ShipToProductPurchase
从:
•    先调用 getShiptoIDCount() 额外查一次
•    再决定是否拼 in (...)
改成:
•    直接一条相关条件:
•    not exists(...) or exists(...)
作用:
•    少一次额外预查询
•    逻辑合并到主 SQL 中
---
二、你当前代码里“虽然没改,但已确认的问题”
1. 弹窗初次打开时多次查询的原因
已确认来源有两个:
•    Page_Load 重复绑定
•    btnQuery 重复绑定
你现在这两个点都已经处理掉了。
2. ucCustomPaging.LoadData(this.GetLastPageNumber(...))
这个仍然保留。
它可能导致:
•    首次打开恢复到旧页码
•    如果旧页码大于总页数,分页控件内部可能再补查一次
这个点还没改。
---
三、已给出但还没正式落地到代码的改动
1. BusinessRule.UT_OrderInfo.GetMyProductInfoList()
文件:..\BusinessRule\OrderInfo\UT_OrderInfo.cs
建议方案已给出,但你还没正式应用到代码里。
核心思路是:
•    删除 subfilter 里重复加的 UT_DealerNetPrice 相关条件
•    把 UT_DealerNetPrice 从“where 过滤”改成“带条件的 inner join”
•    删掉无用的 DOH_ProductLimit join
目的:
•    避免价格表重复过滤
•    尽早缩小结果集
•    让执行计划更清晰
---
四、数据库侧已给出的优化建议
1. 已给出索引创建 SQL
已给出这些表的索引脚本:
•    UT_DealerNetPrice
•    SOI_SDDealerDetails
•    SSO_SameLotInfo
•    UT_OrderDetailInfo
•    SOI_ProductStockAdjust
•    SOI_ProductStockAdjustDetail
•    FCN_Product
•    OPF_ProductSettingRecord
•    AllowOrderChoose
•    SOI_ShipToProductPurchase
•    UT_Product
2. 已给出索引删除 SQL
用于回滚测试。
---
五、目前结论
这次优化的结果可以概括成:
已落地
•    去掉重复事件绑定
•    优化 GetFilter() 里的 in/not in
•    去掉日期字段上的 CONVERT
•    减少一次额外 ShipTo 预查询
未落地但已准备好
•    GetMyProductInfoList() 的 join 改造
•    数据库索引落库执行

VPN
人工智能学习

https://conyss.uk

Order form 在系统中的情况
工作笔记

1) CC4 修改 order form 的核心逻辑
入口在 ServicesBll.cs 的 case "DMS_RProductFamily":
•    SpecialParameter == "CC4IsInApproval":先校验该 CC4 是否在审批流中(CT_CC4IsInApproval)。
•    SpecialParameter == "UpdateProductSalesteam" 且 EDITE:进入
ServicesBll.DMS_Product.cs -> UpdateProductSalesteam(...)。
UpdateProductSalesteam(...) 会把前端传入的 a_OrderFormName_id 写入参数 OrderFormName_Id,然后执行两段 SQL:
1.    CT_UpdateProductSalesteamEdite
批量更新该 CC4 下所有产品:
•    DMS_Product.FK_EDMS_OrderForm_ID = @OrderFormName_Id
2.    CT_UpdateDMS_RProductFamily(编辑)或 CT_ADDDMS_RProductFamily(新增)
更新/新增 CC4 主档:
•    DMS_RProductFamily.FK_EDMS_OrderForm_ID = @OrderFormName_Id
---
2) CC4 改 order form 后会更新哪些表
直接更新:
•    DMS_Product(批量更新该 CC4 下产品的 FK_EDMS_OrderForm_ID)
•    DMS_RProductFamily(更新该 CC4 自身的 FK_EDMS_OrderForm_ID)
同一次逻辑里还会维护(但非 orderform 字段):
•    DMS_RProductFamilyPMUserRelation(培训人员关系增删)
结论:CC4 改 order form 时,不会改 EDMS_OrderForm 主数据本身,而是改“引用关系”。
---
3) 全量排查:哪些功能使用了 orderform 相关表
A. order form 主数据维护
•    功能:DMS_ProductCategroy(名称虽叫 ProductCategroy,实际映射 EDMS_OrderForm)
•    证据:
•    FC_DMS_ProductCategroy.xml -> TableMapping tableName="EDMS_OrderForm"
•    VC_DMS_ProductCategroy.xml -> TableMapping tableName="EDMS_OrderForm"
•    明细配置使用 EDMS_OrderFormDetail(FC/VC_DMS_ProductCategroyDetail.xml)
B. CC4 维护时选择并同步 order form
•    功能:DMS_RProductFamily 编辑(UpdateProductSalesteam)
•    涉及表:
•    DMS_RProductFamily.FK_EDMS_OrderForm_ID
•    DMS_Product.FK_EDMS_OrderForm_ID
C. 经销商“最小采购金额”配置(按经销商 + order form)
•    功能:
•    DMS_DistributorPurchaseOrderSum
•    DMS_DistributorPurchaseOrderSumTimeCtrl
•    对应放大镜:VC_DMS_DistributorPurchaseOrderSum_EDMS_OrderForm、VC_OrderSumTimeCtrl_EDMS_OrderForm
•    涉及表:
•    DMS_DistributorPurchaseOrderSum(FK_EDMS_OrderForm_ID, FK_DMS_DistributorInfo_ID, PurchaseOrderSum)
•    DMS_DistributorPurchaseOrderSumTimeCtrl(FK_EDMS_OrderForm_ID, FK_DMS_DistributorInfo_ID, StartTime, EndTime)
D. 下单金额校验/补偿计算对 order form 的使用
•    功能:
•    EDMS_OrderInfo.queryOrderSum(...)
•    DMSEDMS_OrderInfo.queryDMSOrderSum(...)
•    逻辑:
•    使用订单里的 a_FK_OrderForm_ID 去查 DMS_DistributorPurchaseOrderSum / ...TimeCtrl
•    用于最小采购金额门槛判断
E. 订单与 order form 关系
•    表字段:
•    EDMS_OrderInfo.FK_OrderForm_ID
•    代码:
•    CT_EDMS_OrderInfoUp 更新该字段
•    CT_getOrderFormIDByID / QueryOrderFormID(...) 按订单取 OrderForm
---

Gore修改内容
工作笔记
1 植入报告导出
Implant Report Export
上次CR的一个需求变更:病历号导出的excel表格里面显示完整还是显示****1234按照当前用户系统界面上展示的结果来
A requirement change from last CR: The excel table for exporting the medical record number shows complete or ****1234 according to the results displayed on the current user system interface
2 GSP报表
GSP Reports
QA提出把所有GSP报表字段描述里的“有效期”改成“失效日期”。GSP报表包括:验收管理、入库记录、贮存管理、检查管理、销售管理、出库管理、复核管理、售后退回管理、报损管理。同时E-Order下的经销商发货报表的有效期也同步改成失效日期
QA proposed to change "expiry date" to "expiration date" in all GSP report field descriptions. GSP reports include: Acceptance management, inbound records, storage management, inspection management, sales management, outbound management, review management, post-sale return management, and loss reporting management. At the same time, the validity period of the dealer shipping report under E-Order is also changed to expiration date
3 供货企业资质预警功能
Supplier qualification warning function
1.增加供货企业资质预警:当供货企业资质证书的自然有效期至跟当前时间比分别是30天和1天的时候,会发送邮件提醒RA和 QA;
2. 生产企业资质预警暂不关闭
1 Add supply enterprise qualification warning: When the natural validity period of the supply enterprise qualification certificate is 30 days and 1 day respectively from the current time, an email will be sent to alert RA and QA;
2 The production enterprise qualification warning will not be turned off for the time being
4 暂存订单折扣金额锁定
The discount amount of the temporarily stored orders is locked
1.新增暂存订单折扣金额锁定表,暂存采购单时记录有补偿金额抵扣的订单信息。删除暂存订单时,解锁之前锁定的补偿金额。
2.已有锁定补偿金额的暂存订单,不允许新增、修改、删除订购的产品信息。只能整单做删除。
3.在新增订单或编辑无锁定补偿金额的暂存订单时,系统在计算当前订单的补偿金额需要先去除
1中其它订单锁定的补偿金额
4.包括总部采购订单录入和经销商采购订单录入功能同步修改
1. Add a table for locking discount amounts for temporary orders, which records the information of orders with compensation amount deductions when temporarily storing purchase orders. When deleting a temporary order, unlock the previously locked compensation amount.
2 For a temporary order with a locked compensation amount, it is not allowed to add, modify, or delete the ordered product information. Only the entire order can be deleted.
3. When adding a new order or editing a temporary order without a locked compensation amount, the system needs to remove the compensation amount locked in other orders in 1 before calculating the compensation amount for the current order
4. Including the simultaneous modification of headquarters purchase order entry and dealer purchase order entry functions
5 总部用户邮件提醒的链接调整
Link adjustment for email alerts from headquarters users
因戈尔内部员工登录方式从pingone换成了Entra,登录方式有所不一样,所以需要把总部用户系统接受到的通知所有邮件里面的链接换成https://myapplications.microsoft.com
For gore staff login mode changed from pingone Entra, login way is different, so need to accept headquarters user system to inform all the inside of the email link for https://myapplications.microsoft.com
6 发送订单给仓库
Send the order to the warehouse
1. 创建一个邮件组:HTDK Order,用于发送订单信息给仓库(维护方式与现在一样,该功能不需要开发,只需要在现在的【邮件组管理】菜单去维护即可)
2. 我们在订单审批界面增加一个勾选框,勾选框的内容是【发邮件给仓库】,默认是不勾选的。Melody在审批订单的时候根据实际情况勾选该勾选框   
3. 基于第2点增加判断,如该笔订单的【发邮件给仓库】勾选了且CS点击了审批通过,在审批通过完成后同步推送邮件给HTDK。如【发邮件给仓库】勾选了但是操作的是审批拒绝或者返回,则不发送邮件。
4. 订单审批界面增加【CS填写给仓库的备注】字段,
不管是否勾选了【发邮件给仓库】均为非必填,Melody在审批订单时根据实际情况填写该内容
5.考虑到以上功能是三个业务线共用且目前只for B277的订单,所以【发邮件给仓库】的勾选框和【CS填写给仓库的备注】均为非必填项,CS审批的时候根据实际情况操作
1 Create a mail group: HTDK Order for sending order information to the warehouse (the maintenance method is the same as it is now. This feature does not need to be developed and can be maintained in the current [Mail Group Management] menu)
2. We add a checkbox to the order approval interface, with the content of the checkbox being [Email to the Warehouse], which is unchecked by default. Melody will check the box when approving orders based on the actual situation
3 Add a judgment based on point 2, such as the [Email to Warehouse] option for this order is checked and CS clicks approval, then send an email to HTDK simultaneously after approval is completed. If [Email to Warehouse] is checked but the operation is a rejection or return of approval, no email will be sent.
4 Add a [CS Note to warehouse] field to the order approval interface, which is not required regardless of whether [Email to Warehouse] is checked or not, Melody fills in this content based on the actual situation when approving the order
5. Considering that the above functions are shared by the three business lines and currently only for B277 orders, the checkbox for "Email to Warehouse" and the "CS Notes to Warehouse" are both non-required fields, and CS will operate according to the actual situation during the approval process
7 人工返利附件下载
Download of the manual rebate attachment
经销商下载人工返利附件报错
Dealers have reported an error when downloading the manual rebate attachment
8 补偿类型选项框查询功能
Compensation type option box query function
完善一下补偿申请录入界面(总部+经销商)和人工返利的补偿类型选项框的查询功能(即在选项界面的上方增加补偿代码、补偿名称的查询条件)
Refine the query functionality of the compensation type option box for compensation claims (headquarters + dealer) and manual rebates (i.e. add a query area above the option interface)
9 经销商系统 经销商系统所有查询功能如有可以用【经销商名称】查询的,把【经销商名称】查询提交去掉
10 退货报表打印功能 退货报表打印功能把打印报表的仓库地址和联系人删掉,包括B185跟B277的

 

医院销售代表更新
工作笔记

今天更新医院销售代表

经销商授权申请审批流程优化需求
工作笔记

经销商授权申请审批流程优化需求,见如下详细说明。

2.1 经销商申请授权单时,下拉框选择的客户区域由现在的东南西北四项,在增加一个CL区域选项。

2.2 CE审批时,客户区域下拉框选择项也增加一个CL区域。允许CE做客户区域的内容修改。默认根据经销商提交订单的区域进行内容显示。审批条件修改,单据中的经销商所属类型+客户区域与CE审批人员负责的经销商类型+授权区域相同,才展示带CE审批的数据允许CE审批。

2.3 CMD审批调整,客户区域下拉框选择项也增加一个CL区域,默认根据经销商提交订单的区域进行内容显示。不允许修改。审批条件修改,单据中的经销商所属类型+客户区域与CMD审批人员负责的经销商类型+授权区域相同,才展示对应待审批数据允许CMD人员审批。

2.4 RMD审批调整,客户区域下拉框选择项也增加一个CL区域,默认根据经销商提交订单的区域进行内容显示。不允许修改。审批条件修改,单据中的经销商所属类型+客户区域与RMD审批人员负责的经销商类型+授权区域相同,才展示对应待审批数据允许RMD人员审批。

2.5 总裁办审批调整,客户区域下拉框选择项也增加一个CL区域,默认根据经销商提交订单的区域进行内容显示。不允许修改。审批条件修改,单据中的经销商所属类型+客户区域与总裁办审批人员负责的经销商类型+授权区域相同,才展示对应待审批数据允许总裁办人员审批。

PS

审批流的那个审批状态  CE待审批、CERutrn 等把CXE换成ComEx

把总裁办审批更改成全国渠道审批