Compare commits
16 Commits
d897e12335
...
master-yly
| Author | SHA1 | Date | |
|---|---|---|---|
| dd4c2fc1df | |||
| 803dbf2aa5 | |||
| 3938004783 | |||
| a9ac968749 | |||
| a7a7f40a35 | |||
| 7bbe527477 | |||
| 15891708de | |||
| 59e05e85b1 | |||
| 7f5a045cab | |||
| 4345c2193f | |||
| 23ff1b0b1d | |||
| 44fd20316d | |||
| e3e26574c6 | |||
| 5996173abd | |||
| 76c68cd544 | |||
| fedf789511 |
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"kiroAgent.configureMCP": "Disabled"
|
||||
}
|
||||
313
CLAUDE.md
313
CLAUDE.md
@@ -2,215 +2,186 @@
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## 项目概述
|
||||
## Project Overview
|
||||
|
||||
**数字支行辅助管理系统(IBS)** - 基于 若依框架 v3.8.8 的前后端分离全栈项目,专注于银行支行的网格化营销、客户管理和走访业务。
|
||||
This is a full-stack banking management system (数字支行辅助管理系统) built on the RuoYi framework v3.8.8. It provides grid-based customer relationship management, customer grouping, visit tracking, and performance statistics for banking institutions.
|
||||
|
||||
## 常用命令
|
||||
- **Backend**: Spring Boot 2.5.14 + MyBatis + MySQL + Redis + JWT
|
||||
- **Frontend**: Vue 2.6.12 + Element UI 2.15.14
|
||||
- **Java Version**: 1.8
|
||||
|
||||
### 后端开发
|
||||
## Architecture
|
||||
|
||||
```bash
|
||||
# Maven 打包(跳过测试)
|
||||
mvn clean package -Dmaven.test.skip=true
|
||||
### Backend Module Structure
|
||||
|
||||
# 运行已打包的 JAR
|
||||
cd ruoyi-admin/target
|
||||
java -jar -Xms256m -Xmx1024m ruoyi-admin.jar
|
||||
The backend is a multi-module Maven project with the following modules:
|
||||
|
||||
# 后端服务地址
|
||||
http://localhost:8080
|
||||
|
||||
# Swagger API 文档
|
||||
http://localhost:8080/swagger-ui/index.html
|
||||
|
||||
# 测试登录接口获取 token
|
||||
POST /login/test?username=admin&password=admin123
|
||||
```
|
||||
ruoyi/
|
||||
├── ruoyi-admin/ # Web entry point, main application (RuoYiApplication)
|
||||
├── ruoyi-framework/ # Core framework (security, config, interceptors)
|
||||
├── ruoyi-system/ # System management (users, roles, menus, depts)
|
||||
├── ruoyi-common/ # Common utilities, annotations, domain classes
|
||||
├── ruoyi-quartz/ # Scheduled task management
|
||||
├── ruoyi-generator/ # Code generation tools
|
||||
├── ibs/ # Main business module: grid customer management (网格营销)
|
||||
└── ibs-group/ # Customer group management module (客户分组)
|
||||
```
|
||||
|
||||
### 前端开发
|
||||
### Business Domain Structure
|
||||
|
||||
Each business module (e.g., `ibs`, `ibs-group`) follows this package structure:
|
||||
|
||||
```
|
||||
com.ruoyi.<module>/
|
||||
├── controller/ # REST controllers (handle HTTP requests)
|
||||
├── service/ # Business logic layer
|
||||
├── mapper/ # MyBatis mappers (database access)
|
||||
├── domain/
|
||||
│ ├── entity/ # Database entities
|
||||
│ ├── dto/ # Data Transfer Objects (request)
|
||||
│ └── vo/ # View Objects (response)
|
||||
└── handler/ # Custom MyBatis type handlers
|
||||
```
|
||||
|
||||
### Frontend Structure
|
||||
|
||||
```
|
||||
ruoyi-ui/
|
||||
├── src/
|
||||
│ ├── api/ # API request modules (organized by feature)
|
||||
│ ├── views/ # Page components
|
||||
│ ├── components/ # Reusable components
|
||||
│ ├── store/ # Vuex state management
|
||||
│ ├── router/ # Vue Router configuration
|
||||
│ ├── utils/ # Utility functions
|
||||
│ └── directive/ # Custom Vue directives
|
||||
```
|
||||
|
||||
## Build and Run Commands
|
||||
|
||||
### Backend (Maven)
|
||||
|
||||
```bash
|
||||
# Clean build artifacts
|
||||
cd bin && clean.bat
|
||||
|
||||
# Package the project (creates JAR in ruoyi-admin/target/)
|
||||
cd bin && package.bat
|
||||
|
||||
# Run the backend server (requires packaged JAR)
|
||||
cd bin && run.bat
|
||||
|
||||
# Or run directly with Maven from ruoyi-admin/
|
||||
mvn spring-boot:run
|
||||
|
||||
# The main class is: com.ruoyi.RuoYiApplication
|
||||
# Default port: 8080
|
||||
```
|
||||
|
||||
### Frontend (npm/Vue CLI)
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 开发环境运行(端口 80,代理到 localhost:8080)
|
||||
# Development server (runs on port 80)
|
||||
npm run dev
|
||||
|
||||
# 生产环境构建
|
||||
# For older Node.js versions with OpenSSL issues
|
||||
npm run dev_t
|
||||
|
||||
# Build for production
|
||||
npm run build:prod
|
||||
|
||||
# 代码检查
|
||||
# Build for staging
|
||||
npm run build:stage
|
||||
|
||||
# Build for pre-production
|
||||
npm run build:pre
|
||||
|
||||
# Lint code
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### 数据库连接
|
||||
## Development Configuration
|
||||
|
||||
```bash
|
||||
# 通过 MCP MySQL 工具连接
|
||||
# 地址: 116.62.17.81:3306
|
||||
# 数据库: ibs
|
||||
# 用户名: root
|
||||
```
|
||||
### Application Profiles
|
||||
|
||||
## 核心架构
|
||||
Backend uses Spring profiles located in `ruoyi-admin/src/main/resources/`:
|
||||
- `application.yml` - Base configuration
|
||||
- `application-dev.yml` - Development environment
|
||||
- `application-uat.yml` - UAT environment
|
||||
- `application-pre.yml` - Pre-production
|
||||
- `application-pro.yml` - Production
|
||||
|
||||
### 后端模块结构
|
||||
Active profile is set in `application.yml` (default: `dev`).
|
||||
|
||||
```
|
||||
ruoyi-admin/ # 主入口模块,包含启动类和配置文件
|
||||
ruoyi-framework/ # 框架核心:安全配置、缓存、数据源等
|
||||
ruoyi-system/ # 系统管理:用户、角色、菜单、字典等
|
||||
ruoyi-common/ # 通用工具:工具类、注解、常量等
|
||||
ruoyi-quartz/ # 定时任务模块
|
||||
ruoyi-generator/ # 代码生成器
|
||||
ibs/ # ★ 业务模块:数字支行核心业务 ★
|
||||
```
|
||||
### Frontend API Proxy
|
||||
|
||||
### IBS 业务模块 (核心业务)
|
||||
The Vue dev server proxies API requests to `http://localhost:8080`:
|
||||
- Frontend dev server: `http://localhost:80`
|
||||
- API requests: `/dev-api/*` → `http://localhost:8080/*`
|
||||
|
||||
位置: `ibs/src/main/java/com/ruoyi/ibs/`
|
||||
## Key Patterns and Conventions
|
||||
|
||||
**主要业务包:**
|
||||
### Backend Code Patterns
|
||||
|
||||
| 包名 | 功能 | 说明 |
|
||||
|------|------|------|
|
||||
| `grid` | 网格管理 | 支行网格划分、分配、统计 |
|
||||
| `cmpm` | 客户经理管理 | 客户经理信息维护 |
|
||||
| `list` | 客户列表管理 | 零售/商户/企业客户管理 |
|
||||
| `visit` | 走访管理 | 走访任务、记录、轨迹 |
|
||||
| `task` | 任务管理 | 营销任务分配和跟踪 |
|
||||
| `draw` | 绘图/网格绘制 | 基于百度地图的网格绘制 |
|
||||
| `custmap` | 客户地图 | 客户地理分布可视化 |
|
||||
| `dashboard` | 仪表盘 | 数据统计和展示 |
|
||||
| `datavisual` | 数据可视化 | 报表和图表 |
|
||||
| `rules` | 规则配置 | 业务规则配置 |
|
||||
| `qxhy` | 青县惠银接口 | 外部系统对接 |
|
||||
| `websocket` | WebSocket通信 | 实时通信支持 |
|
||||
1. **Controller-Service-Mapper Layering**
|
||||
- Controllers handle HTTP requests/responses, use `@RestController`
|
||||
- Services contain business logic, use `@Service`
|
||||
- Mappers use MyBatis annotations or XML files in `resources/mapper/`
|
||||
|
||||
**业务模块命名规范:**
|
||||
- 新建模块命名: `ibs` + 主要功能(如 `ibs-grid`, `ibs-customer`)
|
||||
- Controller 放在新建模块中,不与若依框架混合
|
||||
- Entity 使用 `@Data` 注解
|
||||
- Service 使用 `@Resource` 注解,不继承 `ServiceImpl`
|
||||
- DAO 使用 MyBatis Plus,复杂操作在 XML 中编写 SQL
|
||||
2. **DTO/VO Pattern**
|
||||
- DTOs (Data Transfer Objects) for incoming requests
|
||||
- VOs (View Objects) for outgoing responses
|
||||
- Entities map directly to database tables
|
||||
|
||||
### 前端结构
|
||||
3. **Security & Authentication**
|
||||
- JWT-based authentication via `TokenService`
|
||||
- Role-based access: `head`, `branch`, `outlet`, `manager`
|
||||
- Use `SecurityUtils` for current user context: `SecurityUtils.getUsername()`, `SecurityUtils.getDeptId()`, `SecurityUtils.userRole()`
|
||||
|
||||
```
|
||||
ruoyi-ui/src/
|
||||
├── api/ # API 接口定义
|
||||
├── views/ # 页面视图
|
||||
│ ├── grid/ # 网格管理相关页面
|
||||
│ ├── customer/ # 客户管理
|
||||
│ ├── taskManage/ # 任务管理
|
||||
│ ├── dashboard/ # 仪表盘
|
||||
│ └── ...
|
||||
├── components/ # 公共组件
|
||||
├── map/ # 地图相关(百度地图集成)
|
||||
├── store/ # Vuex 状态管理
|
||||
└── router/ # 路由配置
|
||||
```
|
||||
4. **Pagination**
|
||||
- Uses `PageHelper` for database pagination
|
||||
- Controllers return `TableDataInfo` with `total` and `rows`
|
||||
|
||||
### 数据库表命名规范
|
||||
5. **Caching**
|
||||
- Uses `RedisCache` for Redis operations
|
||||
- Cache keys often follow pattern: `{module}:{feature}:{key}`
|
||||
|
||||
- 新建表需加项目前缀: `ibs_` + 表名
|
||||
- 示例: `ibs_grid`, `ibs_customer`, `ibs_visit_record`
|
||||
### Frontend Code Patterns
|
||||
|
||||
## 关键技术点
|
||||
1. **API Modules**
|
||||
- Each feature has a dedicated API file in `src/api/`
|
||||
- Uses `request()` wrapper around axios
|
||||
- API base URL is configured in `src/utils/request.js`
|
||||
|
||||
### 1. 地图集成
|
||||
2. **Vuex Store**
|
||||
- Modules in `src/store/modules/`: user, app, permission, settings, tagsView
|
||||
- State persists via `vuex-persistedstate`
|
||||
|
||||
项目深度集成百度地图 API,用于:
|
||||
- 网格绘制和编辑
|
||||
- 客户地理位置标注
|
||||
- 走访轨迹记录
|
||||
- 客户分布热力图
|
||||
3. **Permission Directives**
|
||||
- `v-hasPermi` for button-level permissions
|
||||
- `v-hasRole` for role-based display
|
||||
|
||||
**相关配置:**
|
||||
- 百度地图 AK 在前端配置
|
||||
- 使用 JTS 库进行地理空间计算
|
||||
## Common Business Concepts
|
||||
|
||||
### 2. 批量导入优化
|
||||
- **网格**: Grid-based territory management for customer assignment
|
||||
- **客户经理**: Relationship managers assigned to customers
|
||||
- **客户星级**: Customer rating levels (5星, 4星, 3星, 2星, 1星, 基础, 长尾)
|
||||
- **AUM (Asset Under Management)**: Customer assets, tracked with monthly averages
|
||||
- **PAD走访**: Mobile visit records for customer interactions
|
||||
|
||||
设计批量导入功能时:
|
||||
- 使用批量操作提高响应速度
|
||||
- 导入结果只展示失败数据,不展示成功数据
|
||||
- 使用 EasyExcel 处理 Excel
|
||||
## MyBatis Configuration
|
||||
|
||||
### 3. 多端支持
|
||||
- Mapper XML files: `classpath*:mapper/**/*Mapper.xml`
|
||||
- Type aliases: `com.ruoyi.**.domain`
|
||||
- Custom type handlers: `com.ruoyi.ibs.handler`
|
||||
- Pagination: `pagehelper` with MySQL dialect
|
||||
|
||||
- PC 端: 主要管理和配置功能
|
||||
- PAD 端: 走访记录功能(移动端)
|
||||
## Notes
|
||||
|
||||
### 4. 外部系统对接
|
||||
|
||||
| 系统 | 地址 | 用途 |
|
||||
|------|------|------|
|
||||
| 青县惠银 | http://158.234.96.76:5002 | 业务数据对接 |
|
||||
| BI 系统 | http://158.220.52.42:9388/bi | 数据分析和报表 |
|
||||
| 阿里云 OSS | - | 文件存储 |
|
||||
|
||||
## 开发规范
|
||||
|
||||
### 代码分层
|
||||
|
||||
- **Entity**: 实体类,不继承 BaseEntity,单独添加审计字段
|
||||
- **DTO**: 接口传参专用类
|
||||
- **VO**: 返回数据专用类
|
||||
- **Service**: 业务逻辑,使用 `@Resource` 注入
|
||||
- **Mapper**: MyBatis Plus + XML 混合使用
|
||||
|
||||
### 审计字段
|
||||
|
||||
通过注解实现自动填充:
|
||||
```java
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
```
|
||||
|
||||
### 分页
|
||||
|
||||
使用 MyBatis Plus 分页插件自动处理,传入 `Page` 对象即可。
|
||||
|
||||
### 前端菜单配置
|
||||
|
||||
添加新页面后,需要在数据库 `sys_menu` 表中配置菜单权限。
|
||||
|
||||
## 重要配置文件
|
||||
|
||||
| 文件 | 位置 | 说明 |
|
||||
|------|------|------|
|
||||
| 后端配置 | `ruoyi-admin/src/main/resources/application-dev.yml` | 数据库、Redis、第三方服务配置 |
|
||||
| 前端配置 | `ruoyi-ui/vue.config.js` | 开发服务器、代理配置 |
|
||||
| 菜单数据 | 数据库 `sys_menu` 表 | 菜单权限配置 |
|
||||
|
||||
## 测试账号
|
||||
|
||||
- 用户名: `admin`
|
||||
- 密码: `admin123`
|
||||
|
||||
## Swagger 接口文档
|
||||
|
||||
启动后端后访问: `http://localhost:8080/swagger-ui/index.html`
|
||||
|
||||
## 开发流程建议
|
||||
|
||||
1. **数据库设计**: 新建表需加 `ibs_` 前缀
|
||||
2. **后端实体类**: 使用 `@Data` 注解,添加审计字段注解
|
||||
3. **后端业务层**: 在 `ibs` 模块下开发,简单 CRUD 用 MyBatis Plus,复杂操作用 XML
|
||||
4. **后端测试**: 使用 `/login/test` 获取 token 后测试接口
|
||||
5. **前端开发**: 在 `ruoyi-ui/views/` 下对应业务模块开发
|
||||
6. **菜单配置**: 在 `sys_menu` 表添加菜单项
|
||||
7. **API 文档**: 生成后保存在 `doc/api/` 目录
|
||||
- The project uses Chinese comments and variable names in many places
|
||||
- Scheduled tasks use Quartz via `ruoyi-quartz` module
|
||||
- File upload path configured in `application.yml`: `ruoyi.profile`
|
||||
- Swagger/Knife4j API docs available when running
|
||||
|
||||
88
ibs-group/pom.xml
Normal file
88
ibs-group/pom.xml
Normal file
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>3.8.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ibs-group</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Mockito依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.3.3</version> <!-- 请根据需要选择合适的版本 -->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- JUnit依赖 -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version> <!-- 请根据需要选择合适的版本 -->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.locationtech.jts</groupId>
|
||||
<artifactId>jts-core</artifactId>
|
||||
<version>1.18.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>5.3.31</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.postgresql</groupId>-->
|
||||
<!-- <artifactId>postgresql</artifactId>-->
|
||||
<!-- <version>42.3.3</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel-core</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.opencsv</groupId>
|
||||
<artifactId>opencsv</artifactId>
|
||||
<version>5.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ibs</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.ruoyi.group.controller;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.group.domain.dto.CustGroupMemberTemplate;
|
||||
import com.ruoyi.group.domain.dto.CustGroupQueryDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.vo.CustGroupVO;
|
||||
import com.ruoyi.group.service.ICustGroupService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "客群管理接口")
|
||||
@RestController
|
||||
@RequestMapping("/group/cust")
|
||||
public class CustGroupController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private ICustGroupService custGroupService;
|
||||
|
||||
/**
|
||||
* 查询客群列表
|
||||
*/
|
||||
@ApiOperation("查询客群列表")
|
||||
@Log(title = "客群管理-查询客群列表")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo listCustGroup(CustGroupQueryDTO dto) {
|
||||
startPage();
|
||||
List<CustGroupVO> list = custGroupService.listCustGroup(dto);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询客群详情
|
||||
*/
|
||||
@ApiOperation("根据ID查询客群详情")
|
||||
@Log(title = "客群管理-查询客群详情")
|
||||
@GetMapping("/{id}")
|
||||
public AjaxResult getCustGroup(@PathVariable Long id) {
|
||||
CustGroupVO custGroup = custGroupService.getCustGroup(id);
|
||||
return AjaxResult.success(custGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步创建客群(模板导入)
|
||||
* gridType、regionGridIds、drawGridIds 包含在 dto 中
|
||||
*/
|
||||
@ApiOperation("异步创建客群(模板导入)")
|
||||
@Log(title = "客群管理-异步创建客群", businessType = BusinessType.INSERT)
|
||||
@PostMapping(value = "/createByTemplate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public AjaxResult createCustGroupByTemplate(
|
||||
@RequestPart("dto") @Valid String dtoJson,
|
||||
@RequestPart("file") MultipartFile file) {
|
||||
CustGroup custGroup = JSON.parseObject(dtoJson, CustGroup.class);
|
||||
return AjaxResult.success("操作成功", custGroupService.createCustGroupByTemplate(custGroup, file));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新客群(模板导入)
|
||||
* gridType、regionGridIds、drawGridIds 包含在 dto 中
|
||||
* file 参数可选:不传文件则只更新客群信息,传文件则追加客户
|
||||
*/
|
||||
@ApiOperation("更新客群(模板导入)")
|
||||
@Log(title = "客群管理-更新客群(模板导入)", businessType = BusinessType.UPDATE)
|
||||
@PostMapping(value = "/updateByTemplate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public AjaxResult updateCustGroupByTemplate(
|
||||
@RequestPart("dto") @Valid String dtoJson,
|
||||
@RequestPart(value = "file", required = false) MultipartFile file) {
|
||||
CustGroup custGroup = JSON.parseObject(dtoJson, CustGroup.class);
|
||||
return AjaxResult.success(custGroupService.updateCustGroupByTemplate(custGroup, file));
|
||||
}
|
||||
|
||||
/**
|
||||
* 轮询客群创建状态
|
||||
*/
|
||||
@ApiOperation("轮询客群创建状态")
|
||||
@Log(title = "客群管理-轮询客群创建状态")
|
||||
@GetMapping("/createStatus/{id}")
|
||||
public AjaxResult getCreateStatus(@PathVariable Long id) {
|
||||
String status = custGroupService.getCreateStatus(id);
|
||||
return AjaxResult.success("操作成功", status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户信息模板下载
|
||||
*/
|
||||
@ApiOperation("客户信息模板")
|
||||
@Log(title = "客群管理-客户信息模板", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/download")
|
||||
public void download(HttpServletResponse response) {
|
||||
ExcelUtil<CustGroupMemberTemplate> util = new ExcelUtil<>(CustGroupMemberTemplate.class);
|
||||
util.exportExcel(response, null, "客户信息模板");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除客群
|
||||
*/
|
||||
@ApiOperation("删除客群")
|
||||
@Log(title = "客群管理-删除客群", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/delete")
|
||||
public AjaxResult deleteCustGroup(@RequestBody List<Long> idList) {
|
||||
String result = custGroupService.deleteCustGroup(idList);
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已有的客群标签列表
|
||||
*/
|
||||
@ApiOperation("获取所有客群标签")
|
||||
@Log(title = "客群管理-获取客群标签")
|
||||
@GetMapping("/tags")
|
||||
public AjaxResult getAllGroupTags() {
|
||||
List<String> tags = custGroupService.getAllGroupTags();
|
||||
return AjaxResult.success(tags);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.ruoyi.group.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.group.domain.dto.CustGroupMemberQueryDTO;
|
||||
import com.ruoyi.group.domain.vo.CustGroupMemberVO;
|
||||
import com.ruoyi.group.service.ICustGroupMemberService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群客户Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "客群客户接口")
|
||||
@RestController
|
||||
@RequestMapping("/group/member")
|
||||
public class CustGroupMemberController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private ICustGroupMemberService custGroupMemberService;
|
||||
|
||||
/**
|
||||
* 分页查询客群客户列表
|
||||
*/
|
||||
@ApiOperation("分页查询客群客户列表")
|
||||
@Log(title = "客群客户-查询客户列表")
|
||||
@GetMapping("/list/{groupId}")
|
||||
public TableDataInfo listCustGroupMembers(@PathVariable Long groupId,
|
||||
CustGroupMemberQueryDTO dto) {
|
||||
// 注意:startPage()在Service内部调用,因为权限检查会先执行SQL导致分页失效
|
||||
List<CustGroupMemberVO> list = custGroupMemberService.listCustGroupMembers(groupId, dto);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动移除客群客户
|
||||
*/
|
||||
@ApiOperation("手动移除客群客户")
|
||||
@Log(title = "客群客户-手动移除客户", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/remove")
|
||||
public AjaxResult removeMembers(@RequestParam Long groupId, @RequestBody List<Long> memberIds) {
|
||||
String result = custGroupMemberService.removeMembers(groupId, memberIds);
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package com.ruoyi.group.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.group.domain.entity.GroupCmpmCountGongsi825;
|
||||
import com.ruoyi.group.domain.entity.GroupCmpmCountLingshou825;
|
||||
import com.ruoyi.group.domain.entity.GroupCustCountGongsi825;
|
||||
import com.ruoyi.group.domain.entity.GroupCustCountLingshou825;
|
||||
import com.ruoyi.group.service.IGroupPerformanceService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "客群业绩统计")
|
||||
@RestController
|
||||
@RequestMapping("/group/performance")
|
||||
public class GroupPerformanceController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private IGroupPerformanceService groupPerformanceService;
|
||||
|
||||
@ApiOperation("查询零售客群业绩汇总列表")
|
||||
@GetMapping("/ls/list")
|
||||
public TableDataPageInfo<GroupCmpmCountLingshou825> selectLsCountList(String dt, String groupName) {
|
||||
Page<Object> page = startPage();
|
||||
List<GroupCmpmCountLingshou825> list = groupPerformanceService.selectLsCountList(dt, groupName);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
@ApiOperation("查询公司客群业绩汇总列表")
|
||||
@GetMapping("/gs/list")
|
||||
public TableDataPageInfo<GroupCmpmCountGongsi825> selectGsCountList(String dt, String groupName) {
|
||||
Page<Object> page = startPage();
|
||||
List<GroupCmpmCountGongsi825> list = groupPerformanceService.selectGsCountList(dt, groupName);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
@ApiOperation("查询零售客群客户明细")
|
||||
@GetMapping("/ls/custList")
|
||||
public TableDataPageInfo<GroupCustCountLingshou825> selectLsCustList(@RequestParam String groupId,
|
||||
String custName,
|
||||
String custIdc,
|
||||
String dt) {
|
||||
Page<Object> page = startPage();
|
||||
List<GroupCustCountLingshou825> list = groupPerformanceService.selectLsCustList(groupId, custName, custIdc, dt);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
@ApiOperation("查询公司客群客户明细")
|
||||
@GetMapping("/gs/custList")
|
||||
public TableDataPageInfo<GroupCustCountGongsi825> selectGsCustList(@RequestParam String groupId,
|
||||
String custName,
|
||||
String socialCreditCode,
|
||||
String dt) {
|
||||
Page<Object> page = startPage();
|
||||
List<GroupCustCountGongsi825> list = groupPerformanceService.selectGsCustList(groupId, custName, socialCreditCode, dt);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
@Log(title = "导出零售客群业绩汇总")
|
||||
@ApiOperation(value = "导出零售客群业绩汇总", produces = "application/octet-stream")
|
||||
@GetMapping("/exportLs")
|
||||
public void exportLs(HttpServletResponse response, String dt, String groupName) {
|
||||
try {
|
||||
ExcelUtil<GroupCmpmCountLingshou825> util = new ExcelUtil<>(GroupCmpmCountLingshou825.class);
|
||||
util.exportExcel(response, groupPerformanceService.selectLsCountList(dt, groupName), "零售客群业绩汇总");
|
||||
} catch (Exception e) {
|
||||
logger.error("导出零售客群业绩汇总失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Log(title = "导出公司客群业绩汇总")
|
||||
@ApiOperation(value = "导出公司客群业绩汇总", produces = "application/octet-stream")
|
||||
@GetMapping("/exportGs")
|
||||
public void exportGs(HttpServletResponse response, String dt, String groupName) {
|
||||
try {
|
||||
ExcelUtil<GroupCmpmCountGongsi825> util = new ExcelUtil<>(GroupCmpmCountGongsi825.class);
|
||||
util.exportExcel(response, groupPerformanceService.selectGsCountList(dt, groupName), "公司客群业绩汇总");
|
||||
} catch (Exception e) {
|
||||
logger.error("导出公司客群业绩汇总失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Log(title = "导出零售客群客户明细")
|
||||
@ApiOperation(value = "导出零售客群客户明细", produces = "application/octet-stream")
|
||||
@GetMapping("/exportLsCust")
|
||||
public void exportLsCust(HttpServletResponse response,
|
||||
@RequestParam String groupId,
|
||||
String custName,
|
||||
String custIdc,
|
||||
String dt) {
|
||||
try {
|
||||
ExcelUtil<GroupCustCountLingshou825> util = new ExcelUtil<>(GroupCustCountLingshou825.class);
|
||||
util.exportExcel(response, groupPerformanceService.selectLsCustList(groupId, custName, custIdc, dt), "零售客群客户明细");
|
||||
} catch (Exception e) {
|
||||
logger.error("导出零售客群客户明细失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Log(title = "导出公司客群客户明细")
|
||||
@ApiOperation(value = "导出公司客群客户明细", produces = "application/octet-stream")
|
||||
@GetMapping("/exportGsCust")
|
||||
public void exportGsCust(HttpServletResponse response,
|
||||
@RequestParam String groupId,
|
||||
String custName,
|
||||
String socialCreditCode,
|
||||
String dt) {
|
||||
try {
|
||||
ExcelUtil<GroupCustCountGongsi825> util = new ExcelUtil<>(GroupCustCountGongsi825.class);
|
||||
util.exportExcel(response, groupPerformanceService.selectGsCustList(groupId, custName, socialCreditCode, dt), "公司客群客户明细");
|
||||
} catch (Exception e) {
|
||||
logger.error("导出公司客群客户明细失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.ruoyi.group.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 客群客户查询DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "客群客户查询条件")
|
||||
public class CustGroupMemberQueryDTO {
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
@ApiModelProperty(value = "页码", hidden = true)
|
||||
private Integer pageNum;
|
||||
|
||||
/**
|
||||
* 每页数量
|
||||
*/
|
||||
@ApiModelProperty(value = "每页数量", hidden = true)
|
||||
private Integer pageSize;
|
||||
|
||||
/**
|
||||
* 客户类型:0=个人, 1=商户, 2=企业
|
||||
*/
|
||||
@ApiModelProperty(value = "客户类型")
|
||||
private String custType;
|
||||
|
||||
/**
|
||||
* 客户姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "客户姓名")
|
||||
private String custName;
|
||||
|
||||
/**
|
||||
* 客户经理柜员号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理柜员号")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 客户经理姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理姓名")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 当前用户角色
|
||||
*/
|
||||
@ApiModelProperty(value = "当前用户角色", hidden = true)
|
||||
private String userRole;
|
||||
|
||||
/**
|
||||
* 当前用户名
|
||||
*/
|
||||
@ApiModelProperty(value = "当前用户名", hidden = true)
|
||||
private String currentUserName;
|
||||
|
||||
/**
|
||||
* 当前机构ID
|
||||
*/
|
||||
@ApiModelProperty(value = "当前机构ID", hidden = true)
|
||||
private Long currentDeptId;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.ruoyi.group.domain.dto;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 客群客户Excel模板
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CustGroupMemberTemplate {
|
||||
|
||||
/**
|
||||
* 客户类型
|
||||
*/
|
||||
@ApiModelProperty(value = "客户类型:个人/企业/商户", name = "custType")
|
||||
@Excel(name = "客户类型(个人/企业/商户)", prompt = "必填", combo = "个人,企业,商户")
|
||||
private String custType;
|
||||
|
||||
/**
|
||||
* 客户号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户号", name = "custId")
|
||||
@Excel(name = "客户号", prompt = "必填")
|
||||
private String custId;
|
||||
|
||||
/**
|
||||
* 客户姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "客户姓名", name = "custName")
|
||||
@Excel(name = "客户姓名")
|
||||
private String custName;
|
||||
|
||||
/**
|
||||
* 客户身份证号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户身份证号(个人客户必填)", name = "custIdc")
|
||||
@Excel(name = "客户身份证号(个人客户必填)")
|
||||
private String custIdc;
|
||||
|
||||
/**
|
||||
* 统信码
|
||||
*/
|
||||
@ApiModelProperty(value = "统信码(企业/商户客户必填)", name = "socialCreditCode")
|
||||
@Excel(name = "统信码(企业/商户客户必填)")
|
||||
private String socialCreditCode;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.ruoyi.group.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客群查询DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CustGroupQueryDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 客群名称(模糊查询)
|
||||
*/
|
||||
@ApiModelProperty(value = "客群名称", name = "groupName")
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 客群模式:0=静态, 1=动态
|
||||
*/
|
||||
@ApiModelProperty(value = "客群模式", name = "groupMode")
|
||||
private String groupMode;
|
||||
|
||||
/**
|
||||
* 创建方式:1=模板导入, 2=绩效网格, 3=地理网格, 4=自定义网格
|
||||
*/
|
||||
@ApiModelProperty(value = "创建方式", name = "createMode")
|
||||
private String createMode;
|
||||
|
||||
/**
|
||||
* 客群状态:0=正常, 1=已禁用
|
||||
*/
|
||||
@ApiModelProperty(value = "客群状态", name = "groupStatus")
|
||||
private String groupStatus;
|
||||
|
||||
/**
|
||||
* 客群标签(模糊匹配)
|
||||
*/
|
||||
@ApiModelProperty(value = "客群标签", name = "groupTags")
|
||||
private String groupTags;
|
||||
|
||||
/**
|
||||
* 视图类型:mine=我创建的,sharedToMe=下发给我的
|
||||
*/
|
||||
@ApiModelProperty(value = "视图类型", name = "viewType")
|
||||
private String viewType;
|
||||
|
||||
/**
|
||||
* 当前用户是否属于总行管理员口径
|
||||
*/
|
||||
@ApiModelProperty(value = "当前用户是否总行管理员", hidden = true)
|
||||
private Boolean headRole;
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
@ApiModelProperty(value = "页码", name = "pageNum")
|
||||
private Integer pageNum = 1;
|
||||
|
||||
/**
|
||||
* 每页大小
|
||||
*/
|
||||
@ApiModelProperty(value = "每页大小", name = "pageSize")
|
||||
private Integer pageSize = 10;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.ruoyi.group.domain.dto;
|
||||
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 网格导入客群DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class GridImportDTO {
|
||||
|
||||
/**
|
||||
* 客群信息
|
||||
*/
|
||||
@ApiModelProperty(value = "客群信息", name = "custGroup")
|
||||
@Valid
|
||||
@NotNull(message = "客群信息不能为空")
|
||||
private CustGroup custGroup;
|
||||
|
||||
/**
|
||||
* 网格类型:0=绩效网格, 1=地理网格, 2=绘制网格
|
||||
*/
|
||||
@ApiModelProperty(value = "网格类型:0=绩效网格, 1=地理网格, 2=绘制网格", name = "gridType")
|
||||
@NotBlank(message = "网格类型不能为空")
|
||||
private String gridType;
|
||||
|
||||
/**
|
||||
* 绩效网格业务类型:retail=零售, corporate=公司(gridType=0时必填)
|
||||
*/
|
||||
@ApiModelProperty(value = "绩效网格业务类型:retail=零售, corporate=公司", name = "cmpmBizType")
|
||||
private String cmpmBizType;
|
||||
|
||||
/**
|
||||
* 绩效网格客户经理柜员号列表(gridType=0时必填)
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理柜员号列表", name = "userNames")
|
||||
private List<String> userNames;
|
||||
|
||||
/**
|
||||
* 地理网格ID列表(gridType=1时必填)
|
||||
*/
|
||||
@ApiModelProperty(value = "地理网格ID列表", name = "regionGridIds")
|
||||
private List<Long> regionGridIds;
|
||||
|
||||
/**
|
||||
* 绘制网格ID列表(gridType=2时必填)
|
||||
*/
|
||||
@ApiModelProperty(value = "绘制网格ID列表", name = "drawGridIds")
|
||||
private List<Long> drawGridIds;
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.ruoyi.group.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群实体
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@TableName("ibs_cust_group")
|
||||
public class CustGroup {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID", name = "id")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客群名称
|
||||
*/
|
||||
@ApiModelProperty(value = "客群名称", name = "groupName")
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 客群模式:0=静态, 1=动态
|
||||
*/
|
||||
@ApiModelProperty(value = "客群模式:0=静态, 1=动态", name = "groupMode")
|
||||
private String groupMode;
|
||||
|
||||
/**
|
||||
* 客群类型:0=零售类(个人+商户), 1=公司类(企业)
|
||||
*/
|
||||
@ApiModelProperty(value = "客群类型:0=零售类(个人+商户), 1=公司类(企业)", name = "groupType")
|
||||
private String groupType;
|
||||
|
||||
/**
|
||||
* 柜员号
|
||||
*/
|
||||
@ApiModelProperty(value = "柜员号", name = "userName")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 柜员名称
|
||||
*/
|
||||
@ApiModelProperty(value = "柜员名称", name = "nickName")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 所属机构ID
|
||||
*/
|
||||
@ApiModelProperty(value = "所属机构ID", name = "deptId")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 是否开启共享:0=否, 1=是
|
||||
*/
|
||||
@ApiModelProperty(value = "是否开启共享:0=否, 1=是", name = "shareEnabled")
|
||||
private Integer shareEnabled;
|
||||
|
||||
/**
|
||||
* 可见部门ID列表(逗号分隔)
|
||||
*/
|
||||
@ApiModelProperty(value = "可见部门ID列表(逗号分隔)", name = "shareDeptIds")
|
||||
private String shareDeptIds;
|
||||
|
||||
/**
|
||||
* 客群状态:0=正常, 1=已禁用
|
||||
*/
|
||||
@ApiModelProperty(value = "客群状态:0=正常, 1=已禁用", name = "groupStatus")
|
||||
private String groupStatus;
|
||||
|
||||
/**
|
||||
* 创建状态:0=创建中, 1=创建成功, 2=创建失败
|
||||
*/
|
||||
@ApiModelProperty(value = "创建状态:0=创建中, 1=创建成功, 2=创建失败", name = "createStatus")
|
||||
private String createStatus;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 删除标识:0=正常, 1=删除
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
@TableField("del_flag")
|
||||
private Integer delFlag;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ApiModelProperty(value = "备注", name = "remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 客群标签(多个标签用逗号分隔)
|
||||
*/
|
||||
@ApiModelProperty(value = "客群标签(多个标签用逗号分隔)", name = "groupTags")
|
||||
@TableField("group_tags")
|
||||
private String groupTags;
|
||||
|
||||
/**
|
||||
* 网格类型:0=绩效网格, 1=地理网格, 2=绘制网格(管户关系来源)
|
||||
*/
|
||||
@ApiModelProperty(value = "网格类型(管户关系来源):0=绩效网格, 1=地理网格, 2=绘制网格", name = "gridType")
|
||||
private String gridType;
|
||||
|
||||
/**
|
||||
* 地理网格ID列表(逗号分隔,动态客群使用)
|
||||
*/
|
||||
@ApiModelProperty(value = "地理网格ID列表", name = "regionGridIds")
|
||||
private String regionGridIds;
|
||||
|
||||
/**
|
||||
* 绘制网格ID列表(逗号分隔,动态客群使用)
|
||||
*/
|
||||
@ApiModelProperty(value = "绘制网格ID列表", name = "drawGridIds")
|
||||
private String drawGridIds;
|
||||
|
||||
/**
|
||||
* 有效期截止时间
|
||||
*/
|
||||
@ApiModelProperty(value = "有效期截止时间", name = "validTime")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date validTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.ruoyi.group.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 客群客户关联实体
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@TableName("ibs_cust_group_member")
|
||||
public class CustGroupMember {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID", name = "id")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客群ID
|
||||
*/
|
||||
@ApiModelProperty(value = "客群ID", name = "groupId")
|
||||
private Long groupId;
|
||||
|
||||
/**
|
||||
* 客户类型:0=个人, 1=商户, 2=企业
|
||||
*/
|
||||
@ApiModelProperty(value = "客户类型:0=个人, 1=商户, 2=企业", name = "custType")
|
||||
private String custType;
|
||||
|
||||
/**
|
||||
* 客户号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户号", name = "custId")
|
||||
private String custId;
|
||||
|
||||
/**
|
||||
* 客户姓名(冗余)
|
||||
*/
|
||||
@ApiModelProperty(value = "客户姓名(冗余)", name = "custName")
|
||||
private String custName;
|
||||
|
||||
/**
|
||||
* 客户身份证号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户身份证号", name = "custIdc")
|
||||
private String custIdc;
|
||||
|
||||
/**
|
||||
* 统信码(商户/企业有)
|
||||
*/
|
||||
@ApiModelProperty(value = "统信码(商户/企业有)", name = "socialCreditCode")
|
||||
private String socialCreditCode;
|
||||
|
||||
/**
|
||||
* 客户经理柜员号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理柜员号", name = "userName")
|
||||
@TableField("user_name")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 客户经理姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理姓名", name = "nickName")
|
||||
@TableField("nick_name")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 网点ID
|
||||
*/
|
||||
@ApiModelProperty(value = "网点ID", name = "outletId")
|
||||
@TableField("outlet_id")
|
||||
private Long outletId;
|
||||
|
||||
/**
|
||||
* 网点名称
|
||||
*/
|
||||
@ApiModelProperty(value = "网点名称", name = "outletName")
|
||||
@TableField("outlet_name")
|
||||
private String outletName;
|
||||
|
||||
/**
|
||||
* 支行ID
|
||||
*/
|
||||
@ApiModelProperty(value = "支行ID", name = "branchId")
|
||||
@TableField("branch_id")
|
||||
private Long branchId;
|
||||
|
||||
/**
|
||||
* 支行名称
|
||||
*/
|
||||
@ApiModelProperty(value = "支行名称", name = "branchName")
|
||||
@TableField("branch_name")
|
||||
private String branchName;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 删除标识:0=正常, 1=删除
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
@TableField("del_flag")
|
||||
private Integer delFlag;
|
||||
|
||||
/**
|
||||
* 手动移除标识:0=否, 1=是(被手动移除的客户不会被定时任务重新导入)
|
||||
*/
|
||||
@ApiModelProperty(value = "手动移除标识:0=否, 1=是", name = "manualRemove")
|
||||
@TableField("manual_remove")
|
||||
private Integer manualRemove;
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package com.ruoyi.group.domain.entity;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客群业绩汇总统计_公司825
|
||||
*/
|
||||
@Data
|
||||
public class GroupCmpmCountGongsi825 implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Excel(name = "统计日期")
|
||||
private String dt;
|
||||
|
||||
private String groupId;
|
||||
|
||||
@Excel(name = "客群名称")
|
||||
private String groupName;
|
||||
|
||||
@Excel(name = "客群模式")
|
||||
private String groupMode;
|
||||
|
||||
@Excel(name = "归属支行")
|
||||
private String deptId;
|
||||
|
||||
@Excel(name = "归属支行名称")
|
||||
private String deptName;
|
||||
|
||||
@Excel(name = "归属网点")
|
||||
private String outletsId;
|
||||
|
||||
@Excel(name = "归属网点名称")
|
||||
private String outletsName;
|
||||
|
||||
@Excel(name = "归属客户经理")
|
||||
private String userName;
|
||||
|
||||
@Excel(name = "入格客户数")
|
||||
private Integer custNum;
|
||||
|
||||
@Excel(name = "活期存款余额")
|
||||
private String hqCurBalance;
|
||||
|
||||
@Excel(name = "保证金存款余额")
|
||||
private String bzCurBalance;
|
||||
|
||||
@Excel(name = "贷款余额")
|
||||
private String loanBalanceCny;
|
||||
|
||||
@Excel(name = "贴现余额")
|
||||
private String financeProd711Balance;
|
||||
|
||||
@Excel(name = "承兑汇票余额")
|
||||
private String financeProd716Balance;
|
||||
|
||||
@Excel(name = "贷款年日均")
|
||||
private String loanYearDailyaverage;
|
||||
|
||||
@Excel(name = "签发承兑汇票率")
|
||||
private String qfcdRat;
|
||||
|
||||
@Excel(name = "贴现业务率")
|
||||
private String txRat;
|
||||
|
||||
@Excel(name = "保函业务率")
|
||||
private String bhRat;
|
||||
|
||||
@Excel(name = "有效代发工资率")
|
||||
private String yxdfgzRat;
|
||||
|
||||
@Excel(name = "代扣电费率")
|
||||
private String dkdfRat;
|
||||
|
||||
@Excel(name = "代扣水费率")
|
||||
private String dksfRat;
|
||||
|
||||
@Excel(name = "代扣税费率")
|
||||
private String dkshfRat;
|
||||
|
||||
@Excel(name = "票据宝签约率")
|
||||
private String pjbRat;
|
||||
|
||||
@Excel(name = "财资宝签约率")
|
||||
private String czbRat;
|
||||
|
||||
@Excel(name = "收付宝签约率")
|
||||
private String sfbRat;
|
||||
|
||||
@Excel(name = "贸融宝签约率")
|
||||
private String mrbRat;
|
||||
|
||||
@Excel(name = "数字生态产品签约率")
|
||||
private String szstRat;
|
||||
|
||||
@Excel(name = "开户率")
|
||||
private String khRat;
|
||||
|
||||
@Excel(name = "国际结算业务率")
|
||||
private String gjjsywRat;
|
||||
|
||||
@Excel(name = "远期结算汇业务率")
|
||||
private String yqjshRat;
|
||||
|
||||
@Excel(name = "签发承兑汇票数")
|
||||
private Integer qfcdNum;
|
||||
|
||||
@Excel(name = "贴现业务数")
|
||||
private Integer txNum;
|
||||
|
||||
@Excel(name = "保函业务数")
|
||||
private Integer bhNum;
|
||||
|
||||
@Excel(name = "有效代发工资数")
|
||||
private Integer yxdfgzNum;
|
||||
|
||||
@Excel(name = "月均代发工资笔数")
|
||||
private String ustrCountPerM;
|
||||
|
||||
@Excel(name = "月均代发工资金额(元)")
|
||||
private String ustrBalM;
|
||||
|
||||
@Excel(name = "代扣电费数")
|
||||
private Integer dkdfNum;
|
||||
|
||||
@Excel(name = "代扣水费数")
|
||||
private Integer dksfNum;
|
||||
|
||||
@Excel(name = "代扣税费数")
|
||||
private Integer dkshfNum;
|
||||
|
||||
@Excel(name = "票据宝签约数")
|
||||
private Integer pjbNum;
|
||||
|
||||
@Excel(name = "财资宝签约数")
|
||||
private Integer czbNum;
|
||||
|
||||
@Excel(name = "收付宝签约数")
|
||||
private Integer sfbNum;
|
||||
|
||||
@Excel(name = "贸融宝签约数")
|
||||
private Integer mrbNum;
|
||||
|
||||
@Excel(name = "数字生态产品签约数")
|
||||
private Integer szstNum;
|
||||
|
||||
@Excel(name = "开户数")
|
||||
private Integer khNum;
|
||||
|
||||
@Excel(name = "国际结算业务数")
|
||||
private Integer gjjsywNum;
|
||||
|
||||
@Excel(name = "远期结算汇业务数")
|
||||
private Integer yqjshNum;
|
||||
|
||||
private String regionCode;
|
||||
|
||||
private String opsDept;
|
||||
|
||||
@Excel(name = "合同签约率")
|
||||
private String htqyRat;
|
||||
|
||||
@Excel(name = "合同签约数")
|
||||
private Integer htqyNum;
|
||||
|
||||
private String deptType;
|
||||
|
||||
@Excel(name = "近365天已走访人数")
|
||||
private String zf365cnt;
|
||||
|
||||
@Excel(name = "近180天已走访人数")
|
||||
private String zf180cnt;
|
||||
|
||||
@Excel(name = "近90天已走访人数")
|
||||
private String zf90cnt;
|
||||
|
||||
@Excel(name = "近30天已走访人数")
|
||||
private String zf30cnt;
|
||||
|
||||
@Excel(name = "近365天走访率")
|
||||
private String zf365rt;
|
||||
|
||||
@Excel(name = "近180天走访率")
|
||||
private String zf180rt;
|
||||
|
||||
@Excel(name = "近90天走访率")
|
||||
private String zf90rt;
|
||||
|
||||
@Excel(name = "近30天走访率")
|
||||
private String zf30rt;
|
||||
|
||||
@Excel(name = "建档率")
|
||||
private String phRat;
|
||||
|
||||
@Excel(name = "建档数")
|
||||
private String phNum;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.ruoyi.group.domain.entity;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客群业绩汇总统计_零售825
|
||||
*/
|
||||
@Data
|
||||
public class GroupCmpmCountLingshou825 implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Excel(name = "统计日期")
|
||||
private String dt;
|
||||
|
||||
private String groupId;
|
||||
|
||||
@Excel(name = "客群名称")
|
||||
private String groupName;
|
||||
|
||||
@Excel(name = "客群模式")
|
||||
private String groupMode;
|
||||
|
||||
@Excel(name = "归属支行机构号")
|
||||
private String deptId;
|
||||
|
||||
@Excel(name = "归属支行名称")
|
||||
private String deptName;
|
||||
|
||||
@Excel(name = "归属网点机构号")
|
||||
private String outletsId;
|
||||
|
||||
@Excel(name = "归属网点名称")
|
||||
private String outletsName;
|
||||
|
||||
@Excel(name = "归属客户经理")
|
||||
private String userName;
|
||||
|
||||
@Excel(name = "入格客户数")
|
||||
private Integer custNum;
|
||||
|
||||
@Excel(name = "近365天已走访人数")
|
||||
private String zf365cnt;
|
||||
|
||||
@Excel(name = "近180天已走访人数")
|
||||
private String zf180cnt;
|
||||
|
||||
@Excel(name = "近90天已走访人数")
|
||||
private String zf90cnt;
|
||||
|
||||
@Excel(name = "近30天已走访人数")
|
||||
private String zf30cnt;
|
||||
|
||||
@Excel(name = "近365天走访率")
|
||||
private String zf365rt;
|
||||
|
||||
@Excel(name = "近180天走访率")
|
||||
private String zf180rt;
|
||||
|
||||
@Excel(name = "近90天走访率")
|
||||
private String zf90rt;
|
||||
|
||||
@Excel(name = "近30天走访率")
|
||||
private String zf30rt;
|
||||
|
||||
@Excel(name = "活期存款余额(元)")
|
||||
private String curBalD;
|
||||
|
||||
@Excel(name = "授信率(%)")
|
||||
private String sxRat;
|
||||
|
||||
@Excel(name = "用信覆盖率")
|
||||
private String yxRat;
|
||||
|
||||
@Excel(name = "授信户数")
|
||||
private Integer sxNum;
|
||||
|
||||
@Excel(name = "用信户数")
|
||||
private Integer yxNum;
|
||||
|
||||
@Excel(name = "授信金额(合同)")
|
||||
private String sxBal;
|
||||
|
||||
@Excel(name = "贷款余额(元)")
|
||||
private String balLoan;
|
||||
|
||||
@Excel(name = "贷款年日均(元)")
|
||||
private String loanAve;
|
||||
|
||||
@Excel(name = "合同签约率(%)")
|
||||
private String yxhtRat;
|
||||
|
||||
@Excel(name = "代扣电费覆盖率(%)")
|
||||
private String dianRat;
|
||||
|
||||
@Excel(name = "代扣水费率(%)")
|
||||
private String shuiRat;
|
||||
|
||||
@Excel(name = "代扣税费率(%)")
|
||||
private String taxRat;
|
||||
|
||||
@Excel(name = "开户率(%)")
|
||||
private String openRat;
|
||||
|
||||
@Excel(name = "合同签约客户数")
|
||||
private Integer yxhtNum;
|
||||
|
||||
@Excel(name = "代扣电费客户数")
|
||||
private Integer dianNum;
|
||||
|
||||
@Excel(name = "代扣水费客户数")
|
||||
private Integer shuiNum;
|
||||
|
||||
@Excel(name = "代扣税费数")
|
||||
private Integer taxNum;
|
||||
|
||||
@Excel(name = "开户数")
|
||||
private Integer openNum;
|
||||
|
||||
@Excel(name = "存款余额(元)")
|
||||
private String depBal;
|
||||
|
||||
@Excel(name = "财富余额(元)")
|
||||
private String finBal;
|
||||
|
||||
@Excel(name = "个人核心客户数")
|
||||
private Integer grhxNum;
|
||||
|
||||
@Excel(name = "财富有效客户数")
|
||||
private Integer cfyxNum;
|
||||
|
||||
@Excel(name = "有效信用卡数")
|
||||
private Integer yxxykNum;
|
||||
|
||||
@Excel(name = "有效社保卡户数")
|
||||
private Integer yxsbkNum;
|
||||
|
||||
@Excel(name = "二换三社保卡户数")
|
||||
private Integer twoTo3SbkNum;
|
||||
|
||||
@Excel(name = "养老金迁移至社保卡户数")
|
||||
private Integer yljToSbkNum;
|
||||
|
||||
@Excel(name = "丰收互联客户数")
|
||||
private Integer fshlNum;
|
||||
|
||||
@Excel(name = "有效收单商户")
|
||||
private Integer yxsdNum;
|
||||
|
||||
@Excel(name = "核心收单户数")
|
||||
private String hxsdNum;
|
||||
|
||||
private String regionCode;
|
||||
|
||||
private String opsDept;
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.ruoyi.group.domain.entity;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客群客户明细统计_公司825
|
||||
*/
|
||||
@Data
|
||||
public class GroupCustCountGongsi825 implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String groupId;
|
||||
|
||||
@Excel(name = "客户名称")
|
||||
private String custName;
|
||||
|
||||
@Excel(name = "客户证件号")
|
||||
private String socialCreditCode;
|
||||
|
||||
@Excel(name = "客户内码")
|
||||
private String custIsn;
|
||||
|
||||
@Excel(name = "活期存款余额")
|
||||
private String hqCurBalance;
|
||||
|
||||
@Excel(name = "保证金存款余额")
|
||||
private String bzCurBalance;
|
||||
|
||||
@Excel(name = "是否授信")
|
||||
private String isCredit;
|
||||
|
||||
@Excel(name = "贷款余额")
|
||||
private String loanBalanceCny;
|
||||
|
||||
@Excel(name = "贷款年日均")
|
||||
private String loanYearDailyaverage;
|
||||
|
||||
@Excel(name = "是否有签发承兑汇票")
|
||||
private String financeProd716OpenFlag;
|
||||
|
||||
@Excel(name = "承兑汇票余额")
|
||||
private String financeProd716Balance;
|
||||
|
||||
@Excel(name = "是否有贴现业务")
|
||||
private String financeProd711OpenFlag;
|
||||
|
||||
@Excel(name = "贴现金额")
|
||||
private String financeProd711Balance;
|
||||
|
||||
@Excel(name = "是否有保函业务")
|
||||
private String intlBussinessJcbhOpenFlag;
|
||||
|
||||
@Excel(name = "是否为有效代发工资客户")
|
||||
private String isUstr;
|
||||
|
||||
@Excel(name = "月均代发工资笔数")
|
||||
private String ustrCountPerM;
|
||||
|
||||
@Excel(name = "月均代发工资金额(元)")
|
||||
private String ustrBalM;
|
||||
|
||||
@Excel(name = "是否代扣电费")
|
||||
private String elecchargeSignFlag;
|
||||
|
||||
@Excel(name = "是否代扣水费")
|
||||
private String waterchargeSignFlag;
|
||||
|
||||
@Excel(name = "是否代扣税费")
|
||||
private String taxdeductionSignFlag;
|
||||
|
||||
@Excel(name = "是否票据宝签约")
|
||||
private String pjb;
|
||||
|
||||
@Excel(name = "是否财资宝签约")
|
||||
private String czb;
|
||||
|
||||
@Excel(name = "是否收付宝签约")
|
||||
private String sfb;
|
||||
|
||||
@Excel(name = "是否贸融宝签约")
|
||||
private String mrb;
|
||||
|
||||
@Excel(name = "是否数字生态产品签约")
|
||||
private String szst;
|
||||
|
||||
@Excel(name = "是否开户")
|
||||
private String isOpenSts;
|
||||
|
||||
@Excel(name = "是否国际结算业务")
|
||||
private String intlBussinessOpenFlag;
|
||||
|
||||
@Excel(name = "是否有远期结算汇业务")
|
||||
private String intlBussiness325OpenFlag;
|
||||
|
||||
private String regionCode;
|
||||
|
||||
private String opsDept;
|
||||
|
||||
private String custType;
|
||||
|
||||
@Excel(name = "是否合同签约")
|
||||
private String isHtqy;
|
||||
|
||||
@Excel(name = "归属支行名称")
|
||||
private String deptName;
|
||||
|
||||
@Excel(name = "归属网点id")
|
||||
private String outletsId;
|
||||
|
||||
@Excel(name = "归属网点名称")
|
||||
private String outletsName;
|
||||
|
||||
@Excel(name = "归属客户经理")
|
||||
private String userName;
|
||||
|
||||
@Excel(name = "归属支行id")
|
||||
private String deptId;
|
||||
|
||||
@Excel(name = "近365天有无走访")
|
||||
private String is365zf;
|
||||
|
||||
@Excel(name = "近180天有无走访")
|
||||
private String is180zf;
|
||||
|
||||
@Excel(name = "近90天有无走访")
|
||||
private String is90zf;
|
||||
|
||||
@Excel(name = "近30天有无走访")
|
||||
private String is30zf;
|
||||
|
||||
private String dt;
|
||||
|
||||
@Excel(name = "是否建档")
|
||||
private String isPh;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.ruoyi.group.domain.entity;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客群客户明细统计_零售825
|
||||
*/
|
||||
@Data
|
||||
public class GroupCustCountLingshou825 implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String groupId;
|
||||
|
||||
@Excel(name = "客户名称")
|
||||
private String custName;
|
||||
|
||||
@Excel(name = "客户证件号")
|
||||
private String custIdc;
|
||||
|
||||
@Excel(name = "客户内码")
|
||||
private String custIsn;
|
||||
|
||||
@Excel(name = "活期存款余额")
|
||||
private String curBalD;
|
||||
|
||||
@Excel(name = "贷款余额")
|
||||
private String balLoan;
|
||||
|
||||
@Excel(name = "贷款年日均")
|
||||
private String loanAve;
|
||||
|
||||
@Excel(name = "是否授信")
|
||||
private String isSx;
|
||||
|
||||
@Excel(name = "是否用信")
|
||||
private String isYx;
|
||||
|
||||
@Excel(name = "授信金额")
|
||||
private String sxBal;
|
||||
|
||||
@Excel(name = "是否合同签约")
|
||||
private String isYxht;
|
||||
|
||||
@Excel(name = "是否持有信用卡")
|
||||
private String isXyk;
|
||||
|
||||
@Excel(name = "是否开通丰收互联")
|
||||
private String fshl;
|
||||
|
||||
@Excel(name = "是否办理收单")
|
||||
private String isSd;
|
||||
|
||||
@Excel(name = "是否代扣电费")
|
||||
private String dian;
|
||||
|
||||
@Excel(name = "是否代扣水费")
|
||||
private String shui;
|
||||
|
||||
@Excel(name = "是否代扣税费")
|
||||
private String tax;
|
||||
|
||||
@Excel(name = "开户数")
|
||||
private String openNum;
|
||||
|
||||
@Excel(name = "存款余额")
|
||||
private String depBal;
|
||||
|
||||
@Excel(name = "财富余额")
|
||||
private String finBal;
|
||||
|
||||
@Excel(name = "是否个人核心客户")
|
||||
private String isGrhx;
|
||||
|
||||
@Excel(name = "是否财富有效客户")
|
||||
private String isCfyx;
|
||||
|
||||
@Excel(name = "是否有效社保卡客户")
|
||||
private String isYxsbk;
|
||||
|
||||
@Excel(name = "是否二换三社保卡")
|
||||
private String is2to3Sbk;
|
||||
|
||||
@Excel(name = "是否养老金迁移至社保卡")
|
||||
private String isYljToSbk;
|
||||
|
||||
private String regionCode;
|
||||
|
||||
private String opsDept;
|
||||
|
||||
private String custType;
|
||||
|
||||
@Excel(name = "近365天有无走访")
|
||||
private String is365zf;
|
||||
|
||||
@Excel(name = "近180天有无走访")
|
||||
private String is180zf;
|
||||
|
||||
@Excel(name = "近90天有无走访")
|
||||
private String is90zf;
|
||||
|
||||
@Excel(name = "近30天有无走访")
|
||||
private String is30zf;
|
||||
|
||||
private String dt;
|
||||
|
||||
@Excel(name = "是否核心收单")
|
||||
private String isHxsd;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.ruoyi.group.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 客群客户VO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CustGroupMemberVO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID", name = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客群ID
|
||||
*/
|
||||
@ApiModelProperty(value = "客群ID", name = "groupId")
|
||||
private Long groupId;
|
||||
|
||||
/**
|
||||
* 客户类型:0=个人, 1=商户, 2=企业
|
||||
*/
|
||||
@ApiModelProperty(value = "客户类型:0=个人, 1=商户, 2=企业", name = "custType")
|
||||
private String custType;
|
||||
|
||||
/**
|
||||
* 客户号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户号", name = "custId")
|
||||
private String custId;
|
||||
|
||||
/**
|
||||
* 客户姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "客户姓名", name = "custName")
|
||||
private String custName;
|
||||
|
||||
/**
|
||||
* 客户身份证号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户身份证号", name = "custIdc")
|
||||
private String custIdc;
|
||||
|
||||
/**
|
||||
* 统信码(商户/企业有)
|
||||
*/
|
||||
@ApiModelProperty(value = "统信码(商户/企业有)", name = "socialCreditCode")
|
||||
private String socialCreditCode;
|
||||
|
||||
/**
|
||||
* 客户经理柜员号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理柜员号", name = "userName")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 客户经理姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理姓名", name = "nickName")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 网点ID
|
||||
*/
|
||||
@ApiModelProperty(value = "网点ID", name = "outletId")
|
||||
private Long outletId;
|
||||
|
||||
/**
|
||||
* 网点名称
|
||||
*/
|
||||
@ApiModelProperty(value = "网点名称", name = "outletName")
|
||||
private String outletName;
|
||||
|
||||
/**
|
||||
* 支行ID
|
||||
*/
|
||||
@ApiModelProperty(value = "支行ID", name = "branchId")
|
||||
private Long branchId;
|
||||
|
||||
/**
|
||||
* 支行名称
|
||||
*/
|
||||
@ApiModelProperty(value = "支行名称", name = "branchName")
|
||||
private String branchName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "创建时间", name = "createTime")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 存量状态:true=存量客户(系统存在),false=非存量客户(系统不存在)
|
||||
*/
|
||||
@ApiModelProperty(value = "存量状态:true=存量客户,false=非存量客户", name = "isExisting")
|
||||
private Boolean isExisting;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.ruoyi.group.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群VO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CustGroupVO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID", name = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客群名称
|
||||
*/
|
||||
@ApiModelProperty(value = "客群名称", name = "groupName")
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 客群模式:0=静态, 1=动态
|
||||
*/
|
||||
@ApiModelProperty(value = "客群模式:0=静态, 1=动态", name = "groupMode")
|
||||
private String groupMode;
|
||||
|
||||
/**
|
||||
* 客群类型:0=零售类(个人+商户), 1=公司类(企业)
|
||||
*/
|
||||
@ApiModelProperty(value = "客群类型:0=零售类(个人+商户), 1=公司类(企业)", name = "groupType")
|
||||
private String groupType;
|
||||
|
||||
/**
|
||||
* 柜员号
|
||||
*/
|
||||
@ApiModelProperty(value = "柜员号", name = "userName")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 柜员名称
|
||||
*/
|
||||
@ApiModelProperty(value = "柜员名称", name = "nickName")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 所属机构ID
|
||||
*/
|
||||
@ApiModelProperty(value = "所属机构ID", name = "deptId")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 是否开启共享:0=否, 1=是
|
||||
*/
|
||||
@ApiModelProperty(value = "是否开启共享:0=否, 1=是", name = "shareEnabled")
|
||||
private Integer shareEnabled;
|
||||
|
||||
/**
|
||||
* 可见部门ID列表(逗号分隔)
|
||||
*/
|
||||
@ApiModelProperty(value = "可见部门ID列表(逗号分隔)", name = "shareDeptIds")
|
||||
private String shareDeptIds;
|
||||
|
||||
/**
|
||||
* 客群状态:0=正常, 1=已禁用
|
||||
*/
|
||||
@ApiModelProperty(value = "客群状态:0=正常, 1=已禁用", name = "groupStatus")
|
||||
private String groupStatus;
|
||||
|
||||
/**
|
||||
* 客户数量
|
||||
*/
|
||||
@ApiModelProperty(value = "客户数量", name = "custCount")
|
||||
private Integer custCount;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@ApiModelProperty(value = "创建者", name = "createBy")
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "创建时间", name = "createTime")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@ApiModelProperty(value = "更新者", name = "updateBy")
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "更新时间", name = "updateTime")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ApiModelProperty(value = "备注", name = "remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 客群标签(多个标签用逗号分隔)
|
||||
*/
|
||||
@ApiModelProperty(value = "客群标签(多个标签用逗号分隔)", name = "groupTags")
|
||||
private String groupTags;
|
||||
|
||||
/**
|
||||
* 有效期截止时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "有效期截止时间", name = "validTime")
|
||||
private Date validTime;
|
||||
|
||||
/**
|
||||
* 创建状态:0=创建中, 1=创建成功, 2=创建失败
|
||||
*/
|
||||
@ApiModelProperty(value = "创建状态:0=创建中, 1=创建成功, 2=创建失败", name = "createStatus")
|
||||
private String createStatus;
|
||||
|
||||
/**
|
||||
* 网格类型(管户关系来源):0=绩效网格, 1=地理网格, 2=绘制网格
|
||||
*/
|
||||
@ApiModelProperty(value = "网格类型(管户关系来源):0=绩效网格, 1=地理网格, 2=绘制网格", name = "gridType")
|
||||
private String gridType;
|
||||
|
||||
/**
|
||||
* 地理网格ID列表(逗号分隔)
|
||||
*/
|
||||
@ApiModelProperty(value = "地理网格ID列表", name = "regionGridIds")
|
||||
private String regionGridIds;
|
||||
|
||||
/**
|
||||
* 绘制网格ID列表(逗号分隔)
|
||||
*/
|
||||
@ApiModelProperty(value = "绘制网格ID列表", name = "drawGridIds")
|
||||
private String drawGridIds;
|
||||
|
||||
/**
|
||||
* 客户列表
|
||||
*/
|
||||
@ApiModelProperty(value = "客户列表", name = "custList")
|
||||
private List<CustGroupMemberVO> custList;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.ruoyi.group.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.group.domain.dto.CustGroupQueryDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.vo.CustGroupVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Mapper
|
||||
public interface CustGroupMapper extends BaseMapper<CustGroup> {
|
||||
|
||||
/**
|
||||
* 查询客群数量(根据部门ID和共享设置)
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @param userName 用户名
|
||||
* @return 数量
|
||||
*/
|
||||
// Long countByDeptOrUser(@Param("deptId") Long deptId, @Param("userName") Long userName);
|
||||
|
||||
/**
|
||||
* 查询客群列表
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 客群VO列表
|
||||
*/
|
||||
List<CustGroupVO> selectCustGroupList(@Param("dto") CustGroupQueryDTO dto,
|
||||
@Param("userName") String userName,
|
||||
@Param("deptId") String deptId,
|
||||
@Param("headId") String headId);
|
||||
|
||||
/**
|
||||
* 根据ID查询客群详情
|
||||
*
|
||||
* @param id 客群ID
|
||||
* @return 客群VO
|
||||
*/
|
||||
CustGroupVO selectCustGroupById(@Param("id") Long id,
|
||||
@Param("userName") String userName,
|
||||
@Param("deptId") String deptId,
|
||||
@Param("headRole") Boolean headRole,
|
||||
@Param("headId") String headId);
|
||||
|
||||
/**
|
||||
* 校验当前用户是否有客群查看权限
|
||||
*
|
||||
* @param id 客群ID
|
||||
* @param userName 当前用户名
|
||||
* @param deptId 当前部门ID
|
||||
* @return 可查看数量
|
||||
*/
|
||||
Long countVisibleCustGroup(@Param("id") Long id,
|
||||
@Param("userName") String userName,
|
||||
@Param("deptId") String deptId,
|
||||
@Param("headRole") Boolean headRole,
|
||||
@Param("headId") String headId);
|
||||
|
||||
/**
|
||||
* 校验客群是否属于总行管理员共享操作范围
|
||||
*
|
||||
* @param id 客群ID
|
||||
* @return 数量
|
||||
*/
|
||||
Long countHeadOperableCustGroup(@Param("id") Long id,
|
||||
@Param("headId") String headId);
|
||||
|
||||
/**
|
||||
* 查询所有已有的客群标签
|
||||
*
|
||||
* @return 标签列表
|
||||
*/
|
||||
List<String> selectAllGroupTags();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.ruoyi.group.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.group.domain.dto.CustGroupMemberQueryDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroupMember;
|
||||
import com.ruoyi.group.domain.vo.CustGroupMemberVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群客户关联Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Mapper
|
||||
public interface CustGroupMemberMapper extends BaseMapper<CustGroupMember> {
|
||||
|
||||
/**
|
||||
* 分页查询客群客户列表
|
||||
*
|
||||
* @param groupId 客群ID
|
||||
* @param dto 查询条件
|
||||
* @return 客户列表
|
||||
*/
|
||||
List<CustGroupMemberVO> selectCustGroupMemberList(@Param("groupId") Long groupId,
|
||||
@Param("dto") CustGroupMemberQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 批量插入客群客户(INSERT IGNORE,遇到重复键自动跳过)
|
||||
*
|
||||
* @param memberList 客户列表
|
||||
*/
|
||||
void batchInsertMembers(@Param("list") List<CustGroupMember> memberList);
|
||||
|
||||
/**
|
||||
* 批量查询个人客户是否存在(根据客户号+身份证号)
|
||||
*
|
||||
* @param custIds 客户号列表
|
||||
* @return 存在的客户号列表
|
||||
*/
|
||||
List<String> selectExistingRetailCustIds(@Param("list") List<String> custIds);
|
||||
|
||||
/**
|
||||
* 批量查询商户客户是否存在(根据客户号+统信码)
|
||||
*
|
||||
* @param custIds 客户号列表
|
||||
* @return 存在的客户号列表
|
||||
*/
|
||||
List<String> selectExistingMerchantCustIds(@Param("list") List<String> custIds);
|
||||
|
||||
/**
|
||||
* 批量查询企业客户是否存在(根据客户号+统信码)
|
||||
*
|
||||
* @param custIds 客户号列表
|
||||
* @return 存在的客户号列表
|
||||
*/
|
||||
List<String> selectExistingBusinessCustIds(@Param("list") List<String> custIds);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.group.mapper;
|
||||
|
||||
import com.ruoyi.group.domain.entity.GroupCmpmCountGongsi825;
|
||||
import com.ruoyi.group.domain.entity.GroupCmpmCountLingshou825;
|
||||
import com.ruoyi.group.domain.entity.GroupCustCountGongsi825;
|
||||
import com.ruoyi.group.domain.entity.GroupCustCountLingshou825;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface GroupPerformanceMapper {
|
||||
|
||||
List<GroupCmpmCountLingshou825> selectLsCountList(HashMap<String, Object> paramMap);
|
||||
|
||||
List<GroupCmpmCountGongsi825> selectGsCountList(HashMap<String, Object> paramMap);
|
||||
|
||||
List<GroupCustCountLingshou825> selectLsCustList(HashMap<String, Object> paramMap);
|
||||
|
||||
List<GroupCustCountGongsi825> selectGsCustList(HashMap<String, Object> paramMap);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.ruoyi.group.service;
|
||||
|
||||
import com.ruoyi.group.domain.dto.CustGroupMemberQueryDTO;
|
||||
import com.ruoyi.group.domain.vo.CustGroupMemberVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群客户服务接口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ICustGroupMemberService {
|
||||
|
||||
/**
|
||||
* 分页查询客群客户列表
|
||||
*
|
||||
* @param groupId 客群ID
|
||||
* @param dto 查询条件
|
||||
* @return 客户列表
|
||||
*/
|
||||
List<CustGroupMemberVO> listCustGroupMembers(Long groupId, CustGroupMemberQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 手动移除客群客户
|
||||
*
|
||||
* @param groupId 客群ID
|
||||
* @param memberIds 客户ID列表
|
||||
* @return 结果
|
||||
*/
|
||||
String removeMembers(Long groupId, List<Long> memberIds);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.ruoyi.group.service;
|
||||
|
||||
import com.ruoyi.group.domain.dto.CustGroupQueryDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.vo.CustGroupVO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ICustGroupService {
|
||||
|
||||
/**
|
||||
* 查询客群列表
|
||||
*/
|
||||
List<CustGroupVO> listCustGroup(CustGroupQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 根据ID查询客群详情
|
||||
*/
|
||||
CustGroupVO getCustGroup(Long id);
|
||||
|
||||
/**
|
||||
* 校验当前用户是否有客群查看权限
|
||||
*/
|
||||
void checkCustGroupViewPermission(Long id);
|
||||
|
||||
/**
|
||||
* 异步创建客群(模板导入)
|
||||
* gridType、regionGridIds、drawGridIds 从 custGroup 中获取
|
||||
*
|
||||
* @param custGroup 客群实体(包含 gridType、regionGridIds、drawGridIds)
|
||||
* @param file Excel文件
|
||||
* @return 客群ID
|
||||
*/
|
||||
String createCustGroupByTemplate(CustGroup custGroup, MultipartFile file);
|
||||
|
||||
/**
|
||||
* 更新客群(模板导入)
|
||||
* gridType、regionGridIds、drawGridIds 从 custGroup 中获取
|
||||
*
|
||||
* @param custGroup 客群实体(包含 gridType、regionGridIds、drawGridIds)
|
||||
* @param file Excel文件
|
||||
* @return 结果消息
|
||||
*/
|
||||
String updateCustGroupByTemplate(CustGroup custGroup, MultipartFile file);
|
||||
|
||||
/**
|
||||
* 删除客群
|
||||
*/
|
||||
String deleteCustGroup(List<Long> idList);
|
||||
|
||||
/**
|
||||
* 检查客群名称是否存在
|
||||
*/
|
||||
boolean checkGroupNameExist(String groupName);
|
||||
|
||||
/**
|
||||
* 查询客群创建状态
|
||||
*/
|
||||
String getCreateStatus(Long id);
|
||||
|
||||
/**
|
||||
* 更新动态客群(定时任务调用)
|
||||
*/
|
||||
void updateDynamicCustGroups();
|
||||
|
||||
/**
|
||||
* 检查并禁用过期客群(定时任务调用)
|
||||
*/
|
||||
void checkAndDisableExpiredGroups();
|
||||
|
||||
/**
|
||||
* 获取所有已有的客群标签列表
|
||||
*
|
||||
* @return 标签列表
|
||||
*/
|
||||
List<String> getAllGroupTags();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ruoyi.group.service;
|
||||
|
||||
import com.ruoyi.group.domain.entity.GroupCmpmCountGongsi825;
|
||||
import com.ruoyi.group.domain.entity.GroupCmpmCountLingshou825;
|
||||
import com.ruoyi.group.domain.entity.GroupCustCountGongsi825;
|
||||
import com.ruoyi.group.domain.entity.GroupCustCountLingshou825;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IGroupPerformanceService {
|
||||
|
||||
List<GroupCmpmCountLingshou825> selectLsCountList(String dt, String groupName);
|
||||
|
||||
List<GroupCmpmCountGongsi825> selectGsCountList(String dt, String groupName);
|
||||
|
||||
List<GroupCustCountLingshou825> selectLsCustList(String groupId, String custName, String custIdc, String dt);
|
||||
|
||||
List<GroupCustCountGongsi825> selectGsCustList(String groupId, String custName, String socialCreditCode, String dt);
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.ruoyi.group.service.impl;
|
||||
|
||||
import com.ruoyi.group.domain.dto.CustGroupMemberQueryDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.entity.CustGroupMember;
|
||||
import com.ruoyi.group.domain.vo.CustGroupMemberVO;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.group.mapper.CustGroupMapper;
|
||||
import com.ruoyi.group.mapper.CustGroupMemberMapper;
|
||||
import com.ruoyi.group.service.ICustGroupService;
|
||||
import com.ruoyi.group.service.ICustGroupMemberService;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 客群客户服务实现类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class CustGroupMemberServiceImpl implements ICustGroupMemberService {
|
||||
|
||||
@Resource
|
||||
private CustGroupMemberMapper custGroupMemberMapper;
|
||||
|
||||
@Resource
|
||||
private CustGroupMapper custGroupMapper;
|
||||
|
||||
@Resource
|
||||
private ICustGroupService custGroupService;
|
||||
|
||||
@Override
|
||||
public List<CustGroupMemberVO> listCustGroupMembers(Long groupId, CustGroupMemberQueryDTO dto) {
|
||||
custGroupService.checkCustGroupViewPermission(groupId);
|
||||
dto.setUserRole(SecurityUtils.userRole());
|
||||
dto.setCurrentUserName(SecurityUtils.getUsername());
|
||||
dto.setCurrentDeptId(SecurityUtils.getDeptId());
|
||||
// 在权限检查之后启动分页,避免权限检查SQL消耗分页设置
|
||||
int pageNum = dto.getPageNum() != null ? dto.getPageNum() : 1;
|
||||
int pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
// 1. 查询客群成员列表(分页)
|
||||
List<CustGroupMemberVO> memberList = custGroupMemberMapper.selectCustGroupMemberList(groupId, dto);
|
||||
if (memberList == null || memberList.isEmpty()) {
|
||||
return memberList;
|
||||
}
|
||||
|
||||
// 2. 按客户类型分组,批量查询存量状态
|
||||
// 个人客户
|
||||
List<String> retailCustIds = memberList.stream()
|
||||
.filter(m -> "0".equals(m.getCustType()))
|
||||
.map(CustGroupMemberVO::getCustId)
|
||||
.collect(Collectors.toList());
|
||||
// 商户客户
|
||||
List<String> merchantCustIds = memberList.stream()
|
||||
.filter(m -> "1".equals(m.getCustType()))
|
||||
.map(CustGroupMemberVO::getCustId)
|
||||
.collect(Collectors.toList());
|
||||
// 企业客户
|
||||
List<String> businessCustIds = memberList.stream()
|
||||
.filter(m -> "2".equals(m.getCustType()))
|
||||
.map(CustGroupMemberVO::getCustId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 3. 批量查询各类型存量客户
|
||||
Set<String> existingRetailCustIds = new HashSet<>();
|
||||
Set<String> existingMerchantCustIds = new HashSet<>();
|
||||
Set<String> existingBusinessCustIds = new HashSet<>();
|
||||
|
||||
if (!retailCustIds.isEmpty()) {
|
||||
existingRetailCustIds.addAll(custGroupMemberMapper.selectExistingRetailCustIds(retailCustIds));
|
||||
}
|
||||
if (!merchantCustIds.isEmpty()) {
|
||||
existingMerchantCustIds.addAll(custGroupMemberMapper.selectExistingMerchantCustIds(merchantCustIds));
|
||||
}
|
||||
if (!businessCustIds.isEmpty()) {
|
||||
existingBusinessCustIds.addAll(custGroupMemberMapper.selectExistingBusinessCustIds(businessCustIds));
|
||||
}
|
||||
|
||||
// 4. 填充存量状态
|
||||
for (CustGroupMemberVO member : memberList) {
|
||||
String custType = member.getCustType();
|
||||
String custId = member.getCustId();
|
||||
if ("0".equals(custType)) {
|
||||
member.setIsExisting(existingRetailCustIds.contains(custId));
|
||||
} else if ("1".equals(custType)) {
|
||||
member.setIsExisting(existingMerchantCustIds.contains(custId));
|
||||
} else if ("2".equals(custType)) {
|
||||
member.setIsExisting(existingBusinessCustIds.contains(custId));
|
||||
} else {
|
||||
member.setIsExisting(false);
|
||||
}
|
||||
}
|
||||
|
||||
return memberList;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String removeMembers(Long groupId, List<Long> memberIds) {
|
||||
// 检查客群是否存在
|
||||
CustGroup custGroup = custGroupMapper.selectById(groupId);
|
||||
if (custGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
if (!SecurityUtils.hasRole("headAdmin")
|
||||
&& !SecurityUtils.hasRole("headPublic")
|
||||
&& !SecurityUtils.hasRole("headPrivate")
|
||||
&& !SecurityUtils.hasRole("headOps")) {
|
||||
throw new ServiceException("无权限操作该客群");
|
||||
}
|
||||
Long count = custGroupMapper.countHeadOperableCustGroup(groupId, SecurityUtils.getHeadId());
|
||||
if (count == null || count <= 0) {
|
||||
throw new ServiceException("无权限操作该客群");
|
||||
}
|
||||
|
||||
// 删除客户关联
|
||||
memberIds.forEach(memberId -> {
|
||||
CustGroupMember member = custGroupMemberMapper.selectById(memberId);
|
||||
if (member != null && member.getGroupId().equals(groupId)) {
|
||||
// 设置手动移除标识
|
||||
member.setManualRemove(1);
|
||||
custGroupMemberMapper.updateById(member);
|
||||
// 逻辑删除
|
||||
custGroupMemberMapper.deleteById(memberId);
|
||||
}
|
||||
});
|
||||
|
||||
return "移除成功";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,952 @@
|
||||
package com.ruoyi.group.service.impl;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.ibs.cmpm.domain.vo.GridCmpmVO;
|
||||
import com.ruoyi.ibs.cmpm.service.GridCmpmService;
|
||||
import com.ruoyi.ibs.dashboard.service.NotificationService;
|
||||
import com.ruoyi.ibs.draw.mapper.DrawGridShapeRelateMapper;
|
||||
import com.ruoyi.ibs.grid.domain.entity.RegionCustUser;
|
||||
import com.ruoyi.ibs.grid.service.RegionGridListService;
|
||||
import com.ruoyi.group.domain.dto.CustGroupMemberTemplate;
|
||||
import com.ruoyi.group.domain.dto.CustGroupQueryDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.entity.CustGroupMember;
|
||||
import com.ruoyi.group.domain.vo.CustGroupVO;
|
||||
import com.ruoyi.group.mapper.CustGroupMapper;
|
||||
import com.ruoyi.group.mapper.CustGroupMemberMapper;
|
||||
import com.ruoyi.group.service.ICustGroupService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 客群Service实现
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CustGroupServiceImpl implements ICustGroupService {
|
||||
|
||||
@Resource
|
||||
private CustGroupMapper custGroupMapper;
|
||||
|
||||
@Resource
|
||||
private CustGroupMemberMapper custGroupMemberMapper;
|
||||
|
||||
@Resource(name = "excelImportExecutor")
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Resource
|
||||
private GridCmpmService gridCmpmService;
|
||||
|
||||
@Resource
|
||||
private RegionGridListService regionGridListService;
|
||||
|
||||
@Resource
|
||||
private DrawGridShapeRelateMapper drawGridShapeRelateMapper;
|
||||
|
||||
@Resource
|
||||
private NotificationService notificationService;
|
||||
|
||||
@Resource
|
||||
private TransactionTemplate transactionTemplate;
|
||||
|
||||
@Override
|
||||
public List<CustGroupVO> listCustGroup(CustGroupQueryDTO dto) {
|
||||
dto.setHeadRole(isHeadCustGroupAdmin());
|
||||
return custGroupMapper.selectCustGroupList(
|
||||
dto,
|
||||
SecurityUtils.getUsername(),
|
||||
String.valueOf(SecurityUtils.getDeptId()),
|
||||
SecurityUtils.getHeadId()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustGroupVO getCustGroup(Long id) {
|
||||
CustGroupVO custGroup = custGroupMapper.selectCustGroupById(
|
||||
id,
|
||||
SecurityUtils.getUsername(),
|
||||
String.valueOf(SecurityUtils.getDeptId()),
|
||||
isHeadCustGroupAdmin(),
|
||||
SecurityUtils.getHeadId()
|
||||
);
|
||||
if (custGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
return custGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String createCustGroupByTemplate(CustGroup custGroup, MultipartFile file) {
|
||||
assertHeadCustGroupAdmin();
|
||||
// 检查客群名称是否存在
|
||||
if (checkGroupNameExist(custGroup.getGroupName())) {
|
||||
throw new ServiceException("客群名称已存在");
|
||||
}
|
||||
// 获取当前用户信息
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
custGroup.setUserName(user.getUserName());
|
||||
custGroup.setNickName(user.getNickName());
|
||||
custGroup.setDeptId(SecurityUtils.getDeptId());
|
||||
// 设置默认值
|
||||
if (StringUtils.isEmpty(custGroup.getGroupMode())) {
|
||||
custGroup.setGroupMode("0"); // 静态
|
||||
}
|
||||
if (StringUtils.isEmpty(custGroup.getGroupStatus())) {
|
||||
custGroup.setGroupStatus("0");
|
||||
}
|
||||
// 设置创建状态为创建中
|
||||
custGroup.setCreateStatus("0");
|
||||
// 插入客群
|
||||
custGroupMapper.insert(custGroup);
|
||||
// 获取当前用户部门编码(异步线程中无法获取)
|
||||
String headId = SecurityUtils.getHeadId();
|
||||
// 异步导入客户
|
||||
executorService.submit(() -> doImportCustGroupByTemplate(custGroup, file, headId));
|
||||
return String.valueOf(custGroup.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String updateCustGroupByTemplate(CustGroup custGroup, MultipartFile file) {
|
||||
// 检查客群是否存在
|
||||
CustGroup existGroup = custGroupMapper.selectById(custGroup.getId());
|
||||
if (existGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
assertOperatePermission(existGroup);
|
||||
// 检查客群是否正在创建或更新
|
||||
if ("0".equals(existGroup.getCreateStatus())) {
|
||||
throw new ServiceException("客群正在处理中,请稍后再试");
|
||||
}
|
||||
// 更新客群基本信息
|
||||
if (!existGroup.getGroupName().equals(custGroup.getGroupName()) && checkGroupNameExist(custGroup.getGroupName())) {
|
||||
throw new ServiceException("客群名称已存在");
|
||||
}
|
||||
// 重新查询数据库,获取最新状态
|
||||
CustGroup latestGroup = custGroupMapper.selectById(custGroup.getId());
|
||||
latestGroup.setGroupName(custGroup.getGroupName());
|
||||
latestGroup.setGroupMode(custGroup.getGroupMode());
|
||||
latestGroup.setRemark(custGroup.getRemark());
|
||||
latestGroup.setValidTime(custGroup.getValidTime());
|
||||
latestGroup.setShareEnabled(custGroup.getShareEnabled());
|
||||
latestGroup.setShareDeptIds(custGroup.getShareDeptIds());
|
||||
latestGroup.setGroupTags(custGroup.getGroupTags());
|
||||
// 保存网格参数(从 custGroup 中获取)
|
||||
latestGroup.setGridType(custGroup.getGridType());
|
||||
latestGroup.setRegionGridIds(custGroup.getRegionGridIds());
|
||||
latestGroup.setDrawGridIds(custGroup.getDrawGridIds());
|
||||
latestGroup.setUpdateBy(SecurityUtils.getUsername());
|
||||
latestGroup.setUpdateTime(new Date());
|
||||
|
||||
// 判断是否需要导入客户文件
|
||||
if (file != null && !file.isEmpty()) {
|
||||
// 有文件:设置状态为"更新中",异步导入客户
|
||||
latestGroup.setCreateStatus("0");
|
||||
custGroupMapper.updateById(latestGroup);
|
||||
// 获取当前用户部门编码(异步线程中无法获取)
|
||||
String headId = SecurityUtils.getHeadId();
|
||||
// 异步导入客户(使用最新状态的对象)
|
||||
final CustGroup finalGroup = latestGroup;
|
||||
executorService.submit(() -> doImportCustGroupByTemplate(finalGroup, file, headId));
|
||||
return "客群更新中";
|
||||
} else {
|
||||
// 无文件:只更新客群信息,直接完成
|
||||
latestGroup.setCreateStatus("1");
|
||||
custGroupMapper.updateById(latestGroup);
|
||||
return "客群更新成功";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String deleteCustGroup(List<Long> idList) {
|
||||
if (idList == null || idList.isEmpty()) {
|
||||
throw new ServiceException("请选择要删除的客群");
|
||||
}
|
||||
for (Long id : idList) {
|
||||
CustGroup custGroup = custGroupMapper.selectById(id);
|
||||
if (custGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
assertOperatePermission(custGroup);
|
||||
// 删除客群客户关联
|
||||
LambdaQueryWrapper<CustGroupMember> memberWrapper = new LambdaQueryWrapper<>();
|
||||
memberWrapper.eq(CustGroupMember::getGroupId, id);
|
||||
custGroupMemberMapper.delete(memberWrapper);
|
||||
// 删除客群
|
||||
custGroupMapper.deleteById(id);
|
||||
}
|
||||
return "客群删除成功";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkGroupNameExist(String groupName) {
|
||||
LambdaQueryWrapper<CustGroup> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustGroup::getGroupName, groupName);
|
||||
wrapper.ne(CustGroup::getCreateStatus, "2");
|
||||
return custGroupMapper.selectCount(wrapper) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateStatus(Long id) {
|
||||
CustGroup custGroup = custGroupMapper.selectById(id);
|
||||
if (custGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
return custGroup.getCreateStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkCustGroupViewPermission(Long id) {
|
||||
Long count = custGroupMapper.countVisibleCustGroup(
|
||||
id,
|
||||
SecurityUtils.getUsername(),
|
||||
String.valueOf(SecurityUtils.getDeptId()),
|
||||
isHeadCustGroupAdmin(),
|
||||
SecurityUtils.getHeadId()
|
||||
);
|
||||
if (count == null || count <= 0) {
|
||||
throw new ServiceException("客群不存在或无查看权限");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHeadCustGroupAdmin() {
|
||||
return SecurityUtils.hasRole("headAdmin")
|
||||
|| SecurityUtils.hasRole("headPublic")
|
||||
|| SecurityUtils.hasRole("headPrivate")
|
||||
|| SecurityUtils.hasRole("headOps");
|
||||
}
|
||||
|
||||
public void assertHeadCustGroupAdmin() {
|
||||
if (!isHeadCustGroupAdmin()) {
|
||||
throw new ServiceException("当前用户无权限操作该功能");
|
||||
}
|
||||
}
|
||||
|
||||
private void assertOperatePermission(CustGroup custGroup) {
|
||||
assertHeadCustGroupAdmin();
|
||||
Long count = custGroupMapper.countHeadOperableCustGroup(custGroup.getId(), SecurityUtils.getHeadId());
|
||||
if (count == null || count <= 0) {
|
||||
throw new ServiceException("无权限操作该客群");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDynamicCustGroups() {
|
||||
log.info("开始更新动态客群...");
|
||||
|
||||
// 查询所有动态客群
|
||||
LambdaQueryWrapper<CustGroup> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustGroup::getGroupMode, "1"); // 1=动态
|
||||
wrapper.eq(CustGroup::getGroupStatus, "0"); // 0=正常
|
||||
wrapper.eq(CustGroup::getCreateStatus, "1"); // 1=创建成功
|
||||
List<CustGroup> dynamicGroups = custGroupMapper.selectList(wrapper);
|
||||
|
||||
if (dynamicGroups.isEmpty()) {
|
||||
log.info("没有需要更新的动态客群");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("找到 {} 个动态客群需要更新", dynamicGroups.size());
|
||||
Date now = new Date();
|
||||
int successCount = 0;
|
||||
int failureCount = 0;
|
||||
|
||||
for (CustGroup custGroup : dynamicGroups) {
|
||||
// 检查有效期,过期的客群跳过更新
|
||||
if (custGroup.getValidTime() != null && custGroup.getValidTime().before(now)) {
|
||||
log.info("动态客群已过期,跳过更新,客群ID:{},客群名称:{},有效期:{}",
|
||||
custGroup.getId(), custGroup.getGroupName(), custGroup.getValidTime());
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
updateDynamicCustGroup(custGroup);
|
||||
successCount++;
|
||||
log.info("动态客群更新成功,客群ID:{},客群名称:{}", custGroup.getId(), custGroup.getGroupName());
|
||||
} catch (Exception e) {
|
||||
failureCount++;
|
||||
log.error("动态客群更新失败,客群ID:{},客群名称:{}", custGroup.getId(), custGroup.getGroupName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("动态客群更新完成,总计:{},成功:{},失败:{}",
|
||||
dynamicGroups.size(),
|
||||
successCount,
|
||||
failureCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAndDisableExpiredGroups() {
|
||||
log.info("开始检查并禁用过期客群...");
|
||||
|
||||
Date now = new Date();
|
||||
|
||||
// 查询所有正常状态且有过期时间的客群
|
||||
LambdaQueryWrapper<CustGroup> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustGroup::getGroupStatus, "0"); // 0=正常
|
||||
wrapper.isNotNull(CustGroup::getValidTime);
|
||||
wrapper.le(CustGroup::getValidTime, now); // validTime <= now
|
||||
List<CustGroup> expiredGroups = custGroupMapper.selectList(wrapper);
|
||||
|
||||
if (expiredGroups.isEmpty()) {
|
||||
log.info("没有需要禁用的过期客群");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("找到 {} 个过期客群需要禁用", expiredGroups.size());
|
||||
|
||||
for (CustGroup custGroup : expiredGroups) {
|
||||
try {
|
||||
custGroup.setGroupStatus("1"); // 1=已禁用
|
||||
custGroupMapper.updateById(custGroup);
|
||||
log.info("客群已禁用,客群ID:{},客群名称:{},有效期:{}",
|
||||
custGroup.getId(), custGroup.getGroupName(), custGroup.getValidTime());
|
||||
} catch (Exception e) {
|
||||
log.error("禁用过期客群失败,客群ID:{},客群名称:{}", custGroup.getId(), custGroup.getGroupName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("过期客群禁用完成,总计:{}", expiredGroups.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新单个动态客群的管户关系,保留客户集合本身不变。
|
||||
*/
|
||||
private void updateDynamicCustGroup(CustGroup custGroup) {
|
||||
transactionTemplate.executeWithoutResult(status -> {
|
||||
try {
|
||||
// 从客群部门获取 headId(定时任务中无登录用户上下文)
|
||||
String headId = "";
|
||||
if (custGroup.getDeptId() != null) {
|
||||
String deptIdStr = String.valueOf(custGroup.getDeptId());
|
||||
headId = deptIdStr.length() >= 3 ? deptIdStr.substring(0, 3) : deptIdStr;
|
||||
}
|
||||
|
||||
// 查询现有客户成员(排除手动移除的客户)
|
||||
LambdaQueryWrapper<CustGroupMember> existWrapper = new LambdaQueryWrapper<>();
|
||||
existWrapper.eq(CustGroupMember::getGroupId, custGroup.getId())
|
||||
.eq(CustGroupMember::getDelFlag, 0)
|
||||
.eq(CustGroupMember::getManualRemove, 0);
|
||||
List<CustGroupMember> existMembers = custGroupMemberMapper.selectList(existWrapper);
|
||||
|
||||
if (existMembers.isEmpty()) {
|
||||
log.info("客群中没有客户,跳过更新,客群ID:{}", custGroup.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, CustGroupMember> baseMemberMap = new LinkedHashMap<>();
|
||||
Map<String, List<CustGroupMember>> existMemberMap = new LinkedHashMap<>();
|
||||
for (CustGroupMember member : existMembers) {
|
||||
String key = buildCustKey(member.getCustId(), member.getCustType());
|
||||
baseMemberMap.putIfAbsent(key, member);
|
||||
existMemberMap.computeIfAbsent(key, k -> new ArrayList<>()).add(member);
|
||||
}
|
||||
|
||||
Map<String, List<CustGroupMember>> gridRelMap = queryGridRelationshipsMap(custGroup, new ArrayList<>(baseMemberMap.values()), headId);
|
||||
|
||||
int updateCount = 0;
|
||||
int insertCount = 0;
|
||||
int deleteCount = 0;
|
||||
|
||||
for (Map.Entry<String, CustGroupMember> entry : baseMemberMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
CustGroupMember baseMember = entry.getValue();
|
||||
List<CustGroupMember> currentList = existMemberMap.getOrDefault(key, Collections.emptyList());
|
||||
List<CustGroupMember> desiredList = buildDesiredMembers(baseMember, gridRelMap.get(key));
|
||||
|
||||
int commonSize = Math.min(currentList.size(), desiredList.size());
|
||||
for (int i = 0; i < commonSize; i++) {
|
||||
CustGroupMember current = currentList.get(i);
|
||||
CustGroupMember desired = desiredList.get(i);
|
||||
current.setUserName(desired.getUserName());
|
||||
current.setNickName(desired.getNickName());
|
||||
current.setOutletId(desired.getOutletId());
|
||||
current.setOutletName(desired.getOutletName());
|
||||
current.setBranchId(desired.getBranchId());
|
||||
current.setBranchName(desired.getBranchName());
|
||||
current.setUpdateTime(new Date());
|
||||
custGroupMemberMapper.updateById(current);
|
||||
updateCount++;
|
||||
}
|
||||
|
||||
for (int i = commonSize; i < currentList.size(); i++) {
|
||||
custGroupMemberMapper.deleteById(currentList.get(i).getId());
|
||||
deleteCount++;
|
||||
}
|
||||
|
||||
for (int i = commonSize; i < desiredList.size(); i++) {
|
||||
CustGroupMember newMember = desiredList.get(i);
|
||||
newMember.setGroupId(custGroup.getId());
|
||||
newMember.setCreateTime(new Date());
|
||||
custGroupMemberMapper.insert(newMember);
|
||||
insertCount++;
|
||||
}
|
||||
}
|
||||
|
||||
log.info("客群管户关系更新完成,客群ID:{},客户数:{},更新:{},新增:{},删除:{}",
|
||||
custGroup.getId(), baseMemberMap.size(), updateCount, insertCount, deleteCount);
|
||||
} catch (Exception e) {
|
||||
status.setRollbackOnly();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 从对应网格查询客户的最新管户关系,返回 Map(key = custId_custType)
|
||||
*/
|
||||
private Map<String, List<CustGroupMember>> queryGridRelationshipsMap(CustGroup custGroup, List<CustGroupMember> members, String headId) {
|
||||
Map<String, List<CustGroupMember>> result = new LinkedHashMap<>();
|
||||
String gridType = custGroup.getGridType();
|
||||
|
||||
if (StringUtils.isEmpty(gridType)) {
|
||||
log.warn("动态客群未配置网格类型,跳过管户关系更新,客群ID:{}", custGroup.getId());
|
||||
return result;
|
||||
}
|
||||
|
||||
if ("0".equals(gridType)) {
|
||||
fillCmpmRelationships(result, members, headId);
|
||||
} else if ("1".equals(gridType)) {
|
||||
fillRegionRelationships(result, parseGridIds(custGroup.getRegionGridIds()), members, headId);
|
||||
} else if ("2".equals(gridType)) {
|
||||
fillDrawRelationships(result, parseGridIds(custGroup.getDrawGridIds()), members, headId);
|
||||
} else {
|
||||
log.warn("动态客群网格类型暂不支持,客群ID:{},gridType:{}", custGroup.getId(), gridType);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void fillCmpmRelationships(Map<String, List<CustGroupMember>> result, List<CustGroupMember> members, String headId) {
|
||||
List<Map<String, String>> retailCustList = new ArrayList<>();
|
||||
List<Map<String, String>> corporateCustList = new ArrayList<>();
|
||||
|
||||
for (CustGroupMember member : members) {
|
||||
Map<String, String> custInfo = new HashMap<>();
|
||||
custInfo.put("custId", member.getCustId());
|
||||
custInfo.put("custType", member.getCustType());
|
||||
if ("0".equals(member.getCustType()) || "1".equals(member.getCustType())) {
|
||||
retailCustList.add(custInfo);
|
||||
} else if ("2".equals(member.getCustType())) {
|
||||
corporateCustList.add(custInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (!retailCustList.isEmpty()) {
|
||||
List<GridCmpmVO> relationships = gridCmpmService.getRelationshipsByCustList("retail", headId, retailCustList);
|
||||
for (GridCmpmVO cmpm : relationships) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setUserName(cmpm.getUserName());
|
||||
member.setNickName(cmpm.getNickName());
|
||||
member.setOutletId(cmpm.getOutletId());
|
||||
member.setOutletName(cmpm.getOutletName());
|
||||
member.setBranchId(cmpm.getBranchId());
|
||||
member.setBranchName(cmpm.getBranchName());
|
||||
addRelationship(result, buildCustKey(cmpm.getCustId(), cmpm.getCustType()), member);
|
||||
}
|
||||
}
|
||||
|
||||
if (!corporateCustList.isEmpty()) {
|
||||
List<GridCmpmVO> relationships = gridCmpmService.getRelationshipsByCustList("corporate", headId, corporateCustList);
|
||||
for (GridCmpmVO cmpm : relationships) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setUserName(cmpm.getUserName());
|
||||
member.setNickName(cmpm.getNickName());
|
||||
member.setOutletId(cmpm.getOutletId());
|
||||
member.setOutletName(cmpm.getOutletName());
|
||||
member.setBranchId(cmpm.getBranchId());
|
||||
member.setBranchName(cmpm.getBranchName());
|
||||
addRelationship(result, buildCustKey(cmpm.getCustId(), cmpm.getCustType()), member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fillRegionRelationships(Map<String, List<CustGroupMember>> result, List<Long> regionGridIds,
|
||||
List<CustGroupMember> members, String headId) {
|
||||
if (regionGridIds == null || regionGridIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> targetCustKeys = members.stream()
|
||||
.map(member -> buildCustKey(member.getCustId(), member.getCustType()))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
List<RegionCustUser> custUsers = regionGridListService.selectAllCustByGridIds(regionGridIds, headId);
|
||||
for (RegionCustUser custUser : custUsers) {
|
||||
String key = buildCustKey(custUser.getCustId(), custUser.getCustType());
|
||||
if (!targetCustKeys.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
addRegionCustUserRelationships(result, key, custUser);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillDrawRelationships(Map<String, List<CustGroupMember>> result, List<Long> drawGridIds,
|
||||
List<CustGroupMember> members, String headId) {
|
||||
if (drawGridIds == null || drawGridIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> targetCustKeys = members.stream()
|
||||
.map(member -> buildCustKey(member.getCustId(), member.getCustType()))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (Long gridId : drawGridIds) {
|
||||
List<RegionCustUser> custUsers = drawGridShapeRelateMapper.selectCustByDrawGridId(gridId, headId);
|
||||
if (custUsers == null || custUsers.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (RegionCustUser custUser : custUsers) {
|
||||
String key = buildCustKey(custUser.getCustId(), custUser.getCustType());
|
||||
if (!targetCustKeys.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
addRegionCustUserRelationships(result, key, custUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addRegionCustUserRelationships(Map<String, List<CustGroupMember>> result, String key, RegionCustUser custUser) {
|
||||
String[] userNames = custUser.getUserNames() != null ? custUser.getUserNames().split(",") : new String[0];
|
||||
String[] nickNames = custUser.getNickNames() != null ? custUser.getNickNames().split(",") : new String[0];
|
||||
String[] outletIds = custUser.getOutletIds() != null ? custUser.getOutletIds().split(",") : new String[0];
|
||||
String[] outletNames = custUser.getOutletNames() != null ? custUser.getOutletNames().split(",") : new String[0];
|
||||
String[] branchIds = custUser.getBranchIds() != null ? custUser.getBranchIds().split(",") : new String[0];
|
||||
String[] branchNames = custUser.getBranchNames() != null ? custUser.getBranchNames().split(",") : new String[0];
|
||||
|
||||
int count = Math.max(userNames.length, 1);
|
||||
for (int i = 0; i < count; i++) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setUserName(i < userNames.length ? userNames[i] : null);
|
||||
member.setNickName(i < nickNames.length ? nickNames[i] : null);
|
||||
member.setOutletId(parseLongValue(i < outletIds.length ? outletIds[i] : null));
|
||||
member.setOutletName(i < outletNames.length ? outletNames[i] : null);
|
||||
member.setBranchId(parseLongValue(i < branchIds.length ? branchIds[i] : null));
|
||||
member.setBranchName(i < branchNames.length ? branchNames[i] : null);
|
||||
addRelationship(result, key, member);
|
||||
}
|
||||
}
|
||||
|
||||
private void addRelationship(Map<String, List<CustGroupMember>> result, String key, CustGroupMember relationship) {
|
||||
List<CustGroupMember> relationshipList = result.computeIfAbsent(key, k -> new ArrayList<>());
|
||||
boolean exists = relationshipList.stream().anyMatch(item ->
|
||||
Objects.equals(StringUtils.trimToNull(item.getUserName()), StringUtils.trimToNull(relationship.getUserName()))
|
||||
&& Objects.equals(StringUtils.trimToNull(item.getNickName()), StringUtils.trimToNull(relationship.getNickName()))
|
||||
&& Objects.equals(item.getOutletId(), relationship.getOutletId())
|
||||
&& Objects.equals(StringUtils.trimToNull(item.getOutletName()), StringUtils.trimToNull(relationship.getOutletName()))
|
||||
&& Objects.equals(item.getBranchId(), relationship.getBranchId())
|
||||
&& Objects.equals(StringUtils.trimToNull(item.getBranchName()), StringUtils.trimToNull(relationship.getBranchName())));
|
||||
if (!exists) {
|
||||
relationshipList.add(relationship);
|
||||
}
|
||||
}
|
||||
|
||||
private List<CustGroupMember> buildDesiredMembers(CustGroupMember baseMember, List<CustGroupMember> relationships) {
|
||||
List<CustGroupMember> result = new ArrayList<>();
|
||||
if (relationships == null || relationships.isEmpty()) {
|
||||
CustGroupMember member = copyBaseMember(baseMember);
|
||||
clearRelationshipFields(member);
|
||||
result.add(member);
|
||||
return result;
|
||||
}
|
||||
|
||||
for (CustGroupMember relationship : relationships) {
|
||||
CustGroupMember member = copyBaseMember(baseMember);
|
||||
member.setUserName(relationship.getUserName());
|
||||
member.setNickName(relationship.getNickName());
|
||||
member.setOutletId(relationship.getOutletId());
|
||||
member.setOutletName(relationship.getOutletName());
|
||||
member.setBranchId(relationship.getBranchId());
|
||||
member.setBranchName(relationship.getBranchName());
|
||||
result.add(member);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private CustGroupMember copyBaseMember(CustGroupMember source) {
|
||||
CustGroupMember target = new CustGroupMember();
|
||||
target.setGroupId(source.getGroupId());
|
||||
target.setCustType(source.getCustType());
|
||||
target.setCustId(source.getCustId());
|
||||
target.setCustName(source.getCustName());
|
||||
target.setCustIdc(source.getCustIdc());
|
||||
target.setSocialCreditCode(source.getSocialCreditCode());
|
||||
target.setCreateBy(source.getCreateBy());
|
||||
return target;
|
||||
}
|
||||
|
||||
private void clearRelationshipFields(CustGroupMember member) {
|
||||
member.setUserName(null);
|
||||
member.setNickName(null);
|
||||
member.setOutletId(null);
|
||||
member.setOutletName(null);
|
||||
member.setBranchId(null);
|
||||
member.setBranchName(null);
|
||||
}
|
||||
|
||||
private String buildCustKey(String custId, String custType) {
|
||||
return custId + "_" + custType;
|
||||
}
|
||||
|
||||
private Long parseLongValue(String value) {
|
||||
if (StringUtils.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
return Long.valueOf(value.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步导入客户(模板导入 + 管户关系匹配)
|
||||
*/
|
||||
private void doImportCustGroupByTemplate(CustGroup custGroup, MultipartFile file, String headId) {
|
||||
try {
|
||||
// 1. 解析Excel获取客户信息
|
||||
List<CustGroupMemberTemplate> templateList = EasyExcel.read(file.getInputStream())
|
||||
.head(CustGroupMemberTemplate.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
if (templateList.isEmpty()) {
|
||||
throw new ServiceException("导入列表为空");
|
||||
}
|
||||
|
||||
// 2. 校验和去重,构建客户信息Map (custId + custType -> CustGroupMember)
|
||||
Map<String, CustGroupMember> custInfoMap = new LinkedHashMap<>();
|
||||
for (CustGroupMemberTemplate template : templateList) {
|
||||
// 校验客户类型
|
||||
String custType = template.getCustType();
|
||||
if (StringUtils.isEmpty(custType)) {
|
||||
throw new ServiceException("客户类型不能为空");
|
||||
}
|
||||
// 转换客户类型值
|
||||
String custTypeValue;
|
||||
switch (custType) {
|
||||
case "个人":
|
||||
custTypeValue = "0";
|
||||
break;
|
||||
case "企业":
|
||||
custTypeValue = "2";
|
||||
break;
|
||||
case "商户":
|
||||
custTypeValue = "1";
|
||||
break;
|
||||
default:
|
||||
throw new ServiceException("客户类型填写错误,只能填写:个人、企业、商户");
|
||||
}
|
||||
// 校验客户类型与客群类型是否匹配
|
||||
String groupType = custGroup.getGroupType();
|
||||
if ("0".equals(groupType)) {
|
||||
// 零售类客群:只允许个人(0)和商户(1)
|
||||
if (!"0".equals(custTypeValue) && !"1".equals(custTypeValue)) {
|
||||
throw new ServiceException("零售类客群只能导入个人和商户客户,客户[" + template.getCustId() + "]类型为" + custType + ",不符合要求");
|
||||
}
|
||||
} else if ("1".equals(groupType)) {
|
||||
// 公司类客群:只允许企业(2)
|
||||
if (!"2".equals(custTypeValue)) {
|
||||
throw new ServiceException("公司类客群只能导入企业客户,客户[" + template.getCustId() + "]类型为" + custType + ",不符合要求");
|
||||
}
|
||||
}
|
||||
// 客户号不能为空
|
||||
if (StringUtils.isEmpty(template.getCustId())) {
|
||||
throw new ServiceException("客户号不能为空");
|
||||
}
|
||||
// 构建唯一键
|
||||
String key = template.getCustId() + "_" + custTypeValue;
|
||||
if (custInfoMap.containsKey(key)) {
|
||||
continue; // 跳过重复客户
|
||||
}
|
||||
// 创建客户成员(仅客户信息)
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustType(custTypeValue);
|
||||
member.setCustId(template.getCustId());
|
||||
member.setCustName(template.getCustName());
|
||||
member.setCustIdc(template.getCustIdc());
|
||||
member.setSocialCreditCode(template.getSocialCreditCode());
|
||||
member.setCreateTime(new Date());
|
||||
// 个人客户必须有身份证号
|
||||
if ("0".equals(custTypeValue) && StringUtils.isEmpty(member.getCustIdc())) {
|
||||
throw new ServiceException("个人客户[" + template.getCustId() + "]身份证号不能为空");
|
||||
}
|
||||
// 企业/商户客户必须有统信码
|
||||
if (("1".equals(custTypeValue) || "2".equals(custTypeValue))
|
||||
&& StringUtils.isEmpty(member.getSocialCreditCode())) {
|
||||
throw new ServiceException("企业/商户客户[" + template.getCustId() + "]统信码不能为空");
|
||||
}
|
||||
custInfoMap.put(key, member);
|
||||
}
|
||||
|
||||
final int[] successCount = {0};
|
||||
final int[] skippedCount = {0};
|
||||
|
||||
transactionTemplate.executeWithoutResult(status -> {
|
||||
try {
|
||||
// 3. 从网格中查询管户关系
|
||||
List<CustGroupMember> relationshipList = queryCustRelationships(custGroup, headId);
|
||||
|
||||
// 4. 构建管户关系Map (custId + custType -> List<CustGroupMember>)
|
||||
Map<String, List<CustGroupMember>> relationshipMap = new HashMap<>();
|
||||
for (CustGroupMember rel : relationshipList) {
|
||||
String key = rel.getCustId() + "_" + rel.getCustType();
|
||||
relationshipMap.computeIfAbsent(key, k -> new ArrayList<>()).add(rel);
|
||||
}
|
||||
|
||||
// 5. 合并客户信息和管户关系,生成最终成员列表
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
for (Map.Entry<String, CustGroupMember> entry : custInfoMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
CustGroupMember custInfo = entry.getValue();
|
||||
List<CustGroupMember> relationships = relationshipMap.get(key);
|
||||
|
||||
if (relationships != null && !relationships.isEmpty()) {
|
||||
for (CustGroupMember rel : relationships) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustType(custInfo.getCustType());
|
||||
member.setCustId(custInfo.getCustId());
|
||||
member.setCustName(custInfo.getCustName());
|
||||
member.setCustIdc(custInfo.getCustIdc());
|
||||
member.setSocialCreditCode(custInfo.getSocialCreditCode());
|
||||
member.setCreateTime(new Date());
|
||||
member.setUserName(rel.getUserName());
|
||||
member.setNickName(rel.getNickName());
|
||||
member.setOutletId(rel.getOutletId());
|
||||
member.setOutletName(rel.getOutletName());
|
||||
member.setBranchId(rel.getBranchId());
|
||||
member.setBranchName(rel.getBranchName());
|
||||
memberList.add(member);
|
||||
}
|
||||
} else {
|
||||
memberList.add(custInfo);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("开始批量插入客户(模板导入),客群ID:{},客户总数:{}", custGroup.getId(), memberList.size());
|
||||
for (CustGroupMember member : memberList) {
|
||||
try {
|
||||
custGroupMemberMapper.insert(member);
|
||||
successCount[0]++;
|
||||
} catch (DuplicateKeyException e) {
|
||||
skippedCount[0]++;
|
||||
log.debug("客户已存在,跳过:groupId={}, custId={}", member.getGroupId(), member.getCustId());
|
||||
}
|
||||
}
|
||||
|
||||
log.info("客群客户导入完成(模板),客群ID:{},成功:{},跳过重复:{}",
|
||||
custGroup.getId(), successCount[0], skippedCount[0]);
|
||||
custGroup.setCreateStatus("1");
|
||||
custGroup.setUpdateBy(custGroup.getCreateBy());
|
||||
custGroup.setUpdateTime(new Date());
|
||||
custGroupMapper.updateById(custGroup);
|
||||
} catch (Exception e) {
|
||||
status.setRollbackOnly();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
// 发送成功通知
|
||||
String successMsg = String.format("客群【%s】导入完成,成功导入 %d 条客户数据", custGroup.getGroupName(), successCount[0]);
|
||||
notificationService.sendNotification(custGroup.getCreateBy(), successMsg);
|
||||
} catch (Exception e) {
|
||||
log.error("客群客户导入失败,客群ID:{},异常:{}", custGroup.getId(), e.getMessage(), e);
|
||||
|
||||
transactionTemplate.executeWithoutResult(status -> {
|
||||
custGroup.setCreateStatus("2");
|
||||
custGroup.setUpdateBy(custGroup.getCreateBy());
|
||||
custGroup.setUpdateTime(new Date());
|
||||
custGroupMapper.updateById(custGroup);
|
||||
});
|
||||
// 发送失败通知
|
||||
String failMsg = String.format("客群【%s】导入失败:%s", custGroup.getGroupName(), e.getMessage());
|
||||
notificationService.sendNotification(custGroup.getCreateBy(), failMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析网格ID字符串为List
|
||||
*/
|
||||
private List<Long> parseGridIds(String gridIdsStr) {
|
||||
if (StringUtils.isEmpty(gridIdsStr)) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.stream(gridIdsStr.split(","))
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.map(Long::valueOf)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 从网格中查询管户关系
|
||||
*/
|
||||
private List<CustGroupMember> queryCustRelationships(CustGroup custGroup, String headId) {
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
String gridType = custGroup.getGridType();
|
||||
List<Long> regionGridIds = parseGridIds(custGroup.getRegionGridIds());
|
||||
List<Long> drawGridIds = parseGridIds(custGroup.getDrawGridIds());
|
||||
|
||||
if (StringUtils.isEmpty(gridType)) {
|
||||
return memberList;
|
||||
}
|
||||
|
||||
if ("0".equals(gridType)) {
|
||||
memberList.addAll(queryRelationshipsFromCmpmGrid(custGroup, headId));
|
||||
} else if ("1".equals(gridType)) {
|
||||
memberList.addAll(queryRelationshipsFromRegionGrid(custGroup, regionGridIds, headId));
|
||||
} else if ("2".equals(gridType)) {
|
||||
memberList.addAll(queryRelationshipsFromDrawGrid(custGroup, drawGridIds, headId));
|
||||
}
|
||||
|
||||
return memberList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从绩效网格查询管户关系(全量匹配)
|
||||
*/
|
||||
private List<CustGroupMember> queryRelationshipsFromCmpmGrid(CustGroup custGroup, String headId) {
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
List<String> gridTypes = new ArrayList<>();
|
||||
String groupType = custGroup.getGroupType();
|
||||
|
||||
if ("0".equals(groupType)) {
|
||||
gridTypes.add("retail");
|
||||
} else if ("1".equals(groupType)) {
|
||||
gridTypes.add("corporate");
|
||||
} else {
|
||||
return memberList;
|
||||
}
|
||||
|
||||
for (String gridType : gridTypes) {
|
||||
List<GridCmpmVO> cmpmList = gridCmpmService.selectAllForImport(gridType, headId);
|
||||
for (GridCmpmVO cmpm : cmpmList) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustId(cmpm.getCustId());
|
||||
member.setCustType(cmpm.getCustType());
|
||||
member.setUserName(cmpm.getUserName());
|
||||
member.setNickName(cmpm.getNickName());
|
||||
member.setOutletId(cmpm.getOutletId());
|
||||
member.setOutletName(cmpm.getOutletName());
|
||||
member.setBranchId(cmpm.getBranchId());
|
||||
member.setBranchName(cmpm.getBranchName());
|
||||
memberList.add(member);
|
||||
}
|
||||
}
|
||||
return memberList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从地理网格查询管户关系
|
||||
*/
|
||||
private List<CustGroupMember> queryRelationshipsFromRegionGrid(CustGroup custGroup, List<Long> regionGridIds, String headId) {
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
if (regionGridIds == null || regionGridIds.isEmpty()) {
|
||||
return memberList;
|
||||
}
|
||||
|
||||
List<RegionCustUser> custUsers = regionGridListService.selectAllCustByGridIds(regionGridIds, headId);
|
||||
for (RegionCustUser custUser : custUsers) {
|
||||
String[] userNames = custUser.getUserNames() != null ? custUser.getUserNames().split(",") : new String[0];
|
||||
String[] nickNames = custUser.getNickNames() != null ? custUser.getNickNames().split(",") : new String[0];
|
||||
String[] outletIds = custUser.getOutletIds() != null ? custUser.getOutletIds().split(",") : new String[0];
|
||||
String[] outletNames = custUser.getOutletNames() != null ? custUser.getOutletNames().split(",") : new String[0];
|
||||
String[] branchIds = custUser.getBranchIds() != null ? custUser.getBranchIds().split(",") : new String[0];
|
||||
String[] branchNames = custUser.getBranchNames() != null ? custUser.getBranchNames().split(",") : new String[0];
|
||||
|
||||
int count = Math.max(userNames.length, 1);
|
||||
for (int i = 0; i < count; i++) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustId(custUser.getCustId());
|
||||
member.setCustType(custUser.getCustType());
|
||||
member.setUserName(i < userNames.length ? userNames[i] : null);
|
||||
member.setNickName(i < nickNames.length ? nickNames[i] : null);
|
||||
member.setOutletId(i < outletIds.length && StringUtils.isNotEmpty(outletIds[i]) ? Long.valueOf(outletIds[i]) : null);
|
||||
member.setOutletName(i < outletNames.length ? outletNames[i] : null);
|
||||
member.setBranchId(i < branchIds.length && StringUtils.isNotEmpty(branchIds[i]) ? Long.valueOf(branchIds[i]) : null);
|
||||
member.setBranchName(i < branchNames.length ? branchNames[i] : null);
|
||||
memberList.add(member);
|
||||
}
|
||||
}
|
||||
return memberList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从绘制网格查询管户关系
|
||||
*/
|
||||
private List<CustGroupMember> queryRelationshipsFromDrawGrid(CustGroup custGroup, List<Long> drawGridIds, String headId) {
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
if (drawGridIds == null || drawGridIds.isEmpty()) {
|
||||
return memberList;
|
||||
}
|
||||
|
||||
for (Long gridId : drawGridIds) {
|
||||
List<RegionCustUser> custUsers = drawGridShapeRelateMapper.selectCustByDrawGridId(gridId, headId);
|
||||
if (custUsers != null && !custUsers.isEmpty()) {
|
||||
for (RegionCustUser custUser : custUsers) {
|
||||
String[] userNames = custUser.getUserNames() != null ? custUser.getUserNames().split(",") : new String[0];
|
||||
String[] nickNames = custUser.getNickNames() != null ? custUser.getNickNames().split(",") : new String[0];
|
||||
String[] outletIds = custUser.getOutletIds() != null ? custUser.getOutletIds().split(",") : new String[0];
|
||||
String[] outletNames = custUser.getOutletNames() != null ? custUser.getOutletNames().split(",") : new String[0];
|
||||
String[] branchIds = custUser.getBranchIds() != null ? custUser.getBranchIds().split(",") : new String[0];
|
||||
String[] branchNames = custUser.getBranchNames() != null ? custUser.getBranchNames().split(",") : new String[0];
|
||||
|
||||
int count = Math.max(userNames.length, 1);
|
||||
for (int i = 0; i < count; i++) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustId(custUser.getCustId());
|
||||
member.setCustType(custUser.getCustType());
|
||||
member.setUserName(i < userNames.length ? userNames[i] : null);
|
||||
member.setNickName(i < nickNames.length ? nickNames[i] : null);
|
||||
member.setOutletId(i < outletIds.length && StringUtils.isNotEmpty(outletIds[i]) ? Long.valueOf(outletIds[i]) : null);
|
||||
member.setOutletName(i < outletNames.length ? outletNames[i] : null);
|
||||
member.setBranchId(i < branchIds.length && StringUtils.isNotEmpty(branchIds[i]) ? Long.valueOf(branchIds[i]) : null);
|
||||
member.setBranchName(i < branchNames.length ? branchNames[i] : null);
|
||||
memberList.add(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return memberList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllGroupTags() {
|
||||
// 查询所有已有标签(逗号分隔的字符串)
|
||||
List<String> tagStrings = custGroupMapper.selectAllGroupTags();
|
||||
if (tagStrings == null || tagStrings.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 将逗号分隔的标签拆分并去重
|
||||
Set<String> tagSet = new LinkedHashSet<>();
|
||||
for (String tagString : tagStrings) {
|
||||
if (StringUtils.isNotEmpty(tagString)) {
|
||||
String[] tags = tagString.split(",");
|
||||
for (String tag : tags) {
|
||||
String trimmedTag = tag.trim();
|
||||
if (StringUtils.isNotEmpty(trimmedTag)) {
|
||||
tagSet.add(trimmedTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(tagSet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.ruoyi.group.service.impl;
|
||||
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.group.domain.entity.GroupCmpmCountGongsi825;
|
||||
import com.ruoyi.group.domain.entity.GroupCmpmCountLingshou825;
|
||||
import com.ruoyi.group.domain.entity.GroupCustCountGongsi825;
|
||||
import com.ruoyi.group.domain.entity.GroupCustCountLingshou825;
|
||||
import com.ruoyi.group.mapper.GroupPerformanceMapper;
|
||||
import com.ruoyi.group.service.IGroupPerformanceService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class GroupPerformanceServiceImpl implements IGroupPerformanceService {
|
||||
|
||||
@Resource
|
||||
private GroupPerformanceMapper groupPerformanceMapper;
|
||||
|
||||
@Override
|
||||
public List<GroupCmpmCountLingshou825> selectLsCountList(String dt, String groupName) {
|
||||
return groupPerformanceMapper.selectLsCountList(buildLsCountParams(dt, groupName));
|
||||
}
|
||||
|
||||
private HashMap<String, Object> buildLsCountParams(String dt, String groupName) {
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
if (SecurityUtils.userRole().equals("branch")) {
|
||||
paramMap.put("isBranch", true);
|
||||
}
|
||||
if (SecurityUtils.userRole().equals("outlet")) {
|
||||
paramMap.put("isOutlet", true);
|
||||
}
|
||||
if (SecurityUtils.userRole().equals("manager")) {
|
||||
paramMap.put("isManager", true);
|
||||
}
|
||||
paramMap.put("deptId", SecurityUtils.getDeptId());
|
||||
paramMap.put("userName", SecurityUtils.getUsername());
|
||||
paramMap.put("dt", dt);
|
||||
paramMap.put("groupName", groupName);
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupCmpmCountGongsi825> selectGsCountList(String dt, String groupName) {
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("userRole", "head");
|
||||
if (SecurityUtils.userRole().equals("branch")) {
|
||||
paramMap.put("userRole", "branch");
|
||||
paramMap.put("isBranch", true);
|
||||
}
|
||||
if (SecurityUtils.userRole().equals("outlet")) {
|
||||
paramMap.put("userRole", "outlet");
|
||||
paramMap.put("isOutlet", true);
|
||||
}
|
||||
if (SecurityUtils.userRole().equals("manager")) {
|
||||
paramMap.put("userRole", "manager");
|
||||
paramMap.put("isManager", true);
|
||||
}
|
||||
paramMap.put("deptId", SecurityUtils.getDeptId());
|
||||
paramMap.put("userName", SecurityUtils.getUsername());
|
||||
paramMap.put("dt", dt);
|
||||
paramMap.put("groupName", groupName);
|
||||
return groupPerformanceMapper.selectGsCountList(paramMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupCustCountLingshou825> selectLsCustList(String groupId, String custName, String custIdc, String dt) {
|
||||
return groupPerformanceMapper.selectLsCustList(buildLsCustParams(groupId, custName, custIdc, dt));
|
||||
}
|
||||
|
||||
private HashMap<String, Object> buildLsCustParams(String groupId, String custName, String custIdc, String dt) {
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("deptId", SecurityUtils.getDeptId());
|
||||
paramMap.put("userName", SecurityUtils.getUsername());
|
||||
paramMap.put("groupId", groupId);
|
||||
paramMap.put("custName", custName);
|
||||
paramMap.put("custIdc", custIdc);
|
||||
paramMap.put("dt", dt);
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupCustCountGongsi825> selectGsCustList(String groupId, String custName, String socialCreditCode, String dt) {
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
if (SecurityUtils.userRole().equals("branch")) {
|
||||
paramMap.put("isBranch", true);
|
||||
}
|
||||
if (SecurityUtils.userRole().equals("outlet")) {
|
||||
paramMap.put("isOutlet", true);
|
||||
}
|
||||
if (SecurityUtils.userRole().equals("manager")) {
|
||||
paramMap.put("isManager", true);
|
||||
}
|
||||
paramMap.put("deptId", SecurityUtils.getDeptId());
|
||||
paramMap.put("userName", SecurityUtils.getUsername());
|
||||
paramMap.put("groupId", groupId);
|
||||
paramMap.put("custName", custName);
|
||||
paramMap.put("socialCreditCode", socialCreditCode);
|
||||
paramMap.put("dt", dt);
|
||||
return groupPerformanceMapper.selectGsCustList(paramMap);
|
||||
}
|
||||
}
|
||||
175
ibs-group/src/main/resources/mapper/group/CustGroupMapper.xml
Normal file
175
ibs-group/src/main/resources/mapper/group/CustGroupMapper.xml
Normal file
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.group.mapper.CustGroupMapper">
|
||||
|
||||
<sql id="custGroupVisibleBaseCondition">
|
||||
AND (
|
||||
<choose>
|
||||
<when test="headRole != null and headRole">
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user su
|
||||
LEFT JOIN sys_user_role sur ON su.user_id = sur.user_id
|
||||
LEFT JOIN sys_role sr ON sur.role_id = sr.role_id
|
||||
WHERE su.user_name = cg.user_name
|
||||
AND LEFT(CAST(cg.dept_id AS CHAR), 3) = #{headId}
|
||||
AND sr.role_key IN ('headAdmin', 'headPublic', 'headPrivate', 'headOps')
|
||||
)
|
||||
</when>
|
||||
<otherwise>
|
||||
1 = 2
|
||||
</otherwise>
|
||||
</choose>
|
||||
OR (
|
||||
cg.share_enabled = 1
|
||||
AND cg.group_status = '0'
|
||||
AND cg.share_dept_ids IS NOT NULL
|
||||
AND cg.share_dept_ids != ''
|
||||
AND find_in_set(#{deptId}, cg.share_dept_ids)
|
||||
)
|
||||
)
|
||||
</sql>
|
||||
|
||||
<sql id="custGroupVisibleCondition">
|
||||
<choose>
|
||||
<when test="dto != null and dto.viewType == 'mine'">
|
||||
<choose>
|
||||
<when test="dto.headRole">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user su
|
||||
LEFT JOIN sys_user_role sur ON su.user_id = sur.user_id
|
||||
LEFT JOIN sys_role sr ON sur.role_id = sr.role_id
|
||||
WHERE su.user_name = cg.user_name
|
||||
AND LEFT(CAST(cg.dept_id AS CHAR), 3) = #{headId}
|
||||
AND sr.role_key IN ('headAdmin', 'headPublic', 'headPrivate', 'headOps')
|
||||
)
|
||||
</when>
|
||||
<otherwise>
|
||||
AND 1 = 2
|
||||
</otherwise>
|
||||
</choose>
|
||||
</when>
|
||||
<when test="dto != null and dto.viewType == 'sharedToMe'">
|
||||
AND cg.share_enabled = 1
|
||||
AND cg.group_status = '0'
|
||||
AND cg.share_dept_ids IS NOT NULL
|
||||
AND cg.share_dept_ids != ''
|
||||
AND find_in_set(#{deptId}, cg.share_dept_ids)
|
||||
</when>
|
||||
<otherwise>
|
||||
<include refid="custGroupVisibleBaseCondition"/>
|
||||
</otherwise>
|
||||
</choose>
|
||||
</sql>
|
||||
|
||||
<select id="selectCustGroupList" resultType="CustGroupVO">
|
||||
SELECT
|
||||
cg.id,
|
||||
cg.group_name,
|
||||
cg.group_mode,
|
||||
cg.group_type,
|
||||
cg.user_name,
|
||||
cg.nick_name,
|
||||
cg.dept_id,
|
||||
cg.share_enabled,
|
||||
cg.share_dept_ids,
|
||||
cg.group_status,
|
||||
cg.group_tags,
|
||||
cg.create_by,
|
||||
cg.create_time,
|
||||
cg.update_by,
|
||||
cg.update_time,
|
||||
cg.remark,
|
||||
cg.del_flag,
|
||||
(SELECT COUNT(*) FROM ibs_cust_group_member cgm WHERE cgm.group_id = cg.id AND cgm.del_flag = '0') AS cust_count
|
||||
FROM ibs_cust_group cg
|
||||
<where>
|
||||
cg.del_flag = '0'
|
||||
AND cg.create_status = '1'
|
||||
<include refid="custGroupVisibleCondition"/>
|
||||
<if test="dto.groupName != null and dto.groupName != ''">
|
||||
AND cg.group_name LIKE CONCAT('%', #{dto.groupName}, '%')
|
||||
</if>
|
||||
<if test="dto.groupMode != null and dto.groupMode != ''">
|
||||
AND cg.group_mode = #{dto.groupMode}
|
||||
</if>
|
||||
<if test="dto.groupStatus != null and dto.groupStatus != ''">
|
||||
AND cg.group_status = #{dto.groupStatus}
|
||||
</if>
|
||||
<if test="dto.groupTags != null and dto.groupTags != ''">
|
||||
AND cg.group_tags LIKE CONCAT('%', #{dto.groupTags}, '%')
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY cg.create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectCustGroupById" resultType="CustGroupVO">
|
||||
SELECT
|
||||
cg.id,
|
||||
cg.group_name,
|
||||
cg.group_mode,
|
||||
cg.group_type,
|
||||
cg.user_name,
|
||||
cg.nick_name,
|
||||
cg.dept_id,
|
||||
cg.share_enabled,
|
||||
cg.share_dept_ids,
|
||||
cg.group_status,
|
||||
cg.group_tags,
|
||||
cg.valid_time,
|
||||
cg.create_by,
|
||||
cg.create_time,
|
||||
cg.update_by,
|
||||
cg.update_time,
|
||||
cg.remark,
|
||||
cg.create_status,
|
||||
cg.grid_type,
|
||||
cg.region_grid_ids,
|
||||
cg.draw_grid_ids,
|
||||
(SELECT COUNT(*) FROM ibs_cust_group_member cgm WHERE cgm.group_id = cg.id AND cgm.del_flag = '0') AS cust_count
|
||||
FROM ibs_cust_group cg
|
||||
WHERE cg.id = #{id}
|
||||
AND cg.del_flag = '0'
|
||||
AND cg.create_status = '1'
|
||||
<include refid="custGroupVisibleBaseCondition"/>
|
||||
</select>
|
||||
|
||||
<select id="countVisibleCustGroup" resultType="java.lang.Long">
|
||||
SELECT COUNT(1)
|
||||
FROM ibs_cust_group cg
|
||||
WHERE cg.id = #{id}
|
||||
AND cg.del_flag = '0'
|
||||
AND cg.create_status = '1'
|
||||
<include refid="custGroupVisibleBaseCondition"/>
|
||||
</select>
|
||||
|
||||
<select id="countHeadOperableCustGroup" resultType="java.lang.Long">
|
||||
SELECT COUNT(1)
|
||||
FROM ibs_cust_group cg
|
||||
WHERE cg.id = #{id}
|
||||
AND cg.del_flag = '0'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user su
|
||||
LEFT JOIN sys_user_role sur ON su.user_id = sur.user_id
|
||||
LEFT JOIN sys_role sr ON sur.role_id = sr.role_id
|
||||
WHERE su.user_name = cg.user_name
|
||||
AND LEFT(CAST(cg.dept_id AS CHAR), 3) = #{headId}
|
||||
AND sr.role_key IN ('headAdmin', 'headPublic', 'headPrivate', 'headOps')
|
||||
)
|
||||
</select>
|
||||
|
||||
<select id="selectAllGroupTags" resultType="java.lang.String">
|
||||
SELECT DISTINCT group_tags
|
||||
FROM ibs_cust_group
|
||||
WHERE del_flag = '0'
|
||||
AND create_status = '1'
|
||||
AND group_tags IS NOT NULL
|
||||
AND group_tags != ''
|
||||
ORDER BY group_tags
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.group.mapper.CustGroupMemberMapper">
|
||||
|
||||
<select id="selectCustGroupMemberList" resultType="CustGroupMemberVO">
|
||||
SELECT
|
||||
cgm.id,
|
||||
cgm.group_id,
|
||||
cgm.cust_type,
|
||||
cgm.cust_id,
|
||||
cgm.cust_name,
|
||||
cgm.cust_idc,
|
||||
cgm.social_credit_code,
|
||||
cgm.user_name,
|
||||
cgm.nick_name,
|
||||
cgm.outlet_id,
|
||||
cgm.outlet_name,
|
||||
cgm.branch_id,
|
||||
cgm.branch_name,
|
||||
cgm.create_time
|
||||
FROM ibs_cust_group_member cgm
|
||||
<where>
|
||||
cgm.group_id = #{groupId}
|
||||
AND cgm.del_flag = '0'
|
||||
<choose>
|
||||
<when test="dto != null and dto.userRole == 'branch'">
|
||||
AND cgm.branch_id = #{dto.currentDeptId}
|
||||
</when>
|
||||
<when test="dto != null and dto.userRole == 'outlet'">
|
||||
AND cgm.outlet_id = #{dto.currentDeptId}
|
||||
</when>
|
||||
<when test="dto != null and dto.userRole == 'manager'">
|
||||
AND cgm.user_name = #{dto.currentUserName}
|
||||
</when>
|
||||
</choose>
|
||||
<if test="dto != null and dto.custType != null and dto.custType != ''">
|
||||
AND cgm.cust_type = #{dto.custType}
|
||||
</if>
|
||||
<if test="dto != null and dto.custName != null and dto.custName != ''">
|
||||
AND cgm.cust_name LIKE CONCAT('%', #{dto.custName}, '%')
|
||||
</if>
|
||||
<if test="dto != null and dto.userName != null and dto.userName != ''">
|
||||
AND cgm.user_name = #{dto.userName}
|
||||
</if>
|
||||
<if test="dto != null and dto.nickName != null and dto.nickName != ''">
|
||||
AND cgm.nick_name LIKE CONCAT('%', #{dto.nickName}, '%')
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY cgm.create_time ASC
|
||||
</select>
|
||||
|
||||
<!-- 批量查询个人客户是否存在 -->
|
||||
<select id="selectExistingRetailCustIds" resultType="String">
|
||||
SELECT DISTINCT t.cust_id
|
||||
FROM ibs_cust_group_member t
|
||||
INNER JOIN cust_info_retail c ON t.cust_id = c.cust_id AND t.cust_idc = c.cust_idc
|
||||
WHERE t.del_flag = '0'
|
||||
AND t.cust_type = '0'
|
||||
AND t.cust_id IN
|
||||
<foreach collection="list" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<!-- 批量查询商户客户是否存在 -->
|
||||
<select id="selectExistingMerchantCustIds" resultType="String">
|
||||
SELECT DISTINCT t.cust_id
|
||||
FROM ibs_cust_group_member t
|
||||
INNER JOIN cust_info_merchant c ON t.cust_id = c.cust_id AND t.social_credit_code = c.social_credit_code
|
||||
WHERE t.del_flag = '0'
|
||||
AND t.cust_type = '1'
|
||||
AND t.cust_id IN
|
||||
<foreach collection="list" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<!-- 批量查询企业客户是否存在 -->
|
||||
<select id="selectExistingBusinessCustIds" resultType="String">
|
||||
SELECT DISTINCT t.cust_id
|
||||
FROM ibs_cust_group_member t
|
||||
INNER JOIN cust_info_business c ON t.cust_id = c.cust_id AND t.social_credit_code = c.social_credit_code
|
||||
WHERE t.del_flag = '0'
|
||||
AND t.cust_type = '2'
|
||||
AND t.cust_id IN
|
||||
<foreach collection="list" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<!-- 批量插入客群客户(INSERT IGNORE,遇到重复键自动跳过) -->
|
||||
<insert id="batchInsertMembers">
|
||||
INSERT IGNORE INTO ibs_cust_group_member
|
||||
(group_id, cust_type, cust_id, cust_name, cust_idc, social_credit_code,
|
||||
user_name, nick_name, outlet_id, outlet_name, branch_id, branch_name,
|
||||
create_by, create_time, del_flag, manual_remove)
|
||||
VALUES
|
||||
<foreach collection="list" item="item" index="index" separator=",">
|
||||
(#{item.groupId}, #{item.custType}, #{item.custId}, #{item.custName}, #{item.custIdc}, #{item.socialCreditCode},
|
||||
#{item.userName}, #{item.nickName}, #{item.outletId}, #{item.outletName}, #{item.branchId}, #{item.branchName},
|
||||
#{item.createBy}, NOW(), '0', '0')
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,245 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.group.mapper.GroupPerformanceMapper">
|
||||
|
||||
<select id="selectLsCountList" resultType="com.ruoyi.group.domain.entity.GroupCmpmCountLingshou825">
|
||||
SELECT
|
||||
dt,
|
||||
group_id,
|
||||
group_name,
|
||||
group_mode,
|
||||
dept_id,
|
||||
dept_name,
|
||||
outlets_id,
|
||||
outlets_name,
|
||||
user_name,
|
||||
cust_num,
|
||||
zf_365cnt,
|
||||
zf_180cnt,
|
||||
zf_90cnt,
|
||||
zf_30cnt,
|
||||
zf_365rt,
|
||||
zf_180rt,
|
||||
zf_90rt,
|
||||
zf_30rt,
|
||||
cur_bal_d,
|
||||
sx_rat,
|
||||
yx_rat,
|
||||
sx_num,
|
||||
yx_num,
|
||||
sx_bal,
|
||||
bal_loan,
|
||||
loan_ave,
|
||||
yxht_rat,
|
||||
dian_rat,
|
||||
shui_rat,
|
||||
tax_rat,
|
||||
open_rat,
|
||||
yxht_num,
|
||||
dian_num,
|
||||
shui_num,
|
||||
tax_num,
|
||||
open_num,
|
||||
dep_bal,
|
||||
fin_bal,
|
||||
grhx_num,
|
||||
cfyx_num,
|
||||
yxxyk_num,
|
||||
yxsbk_num,
|
||||
`2to3_sbk_num` as twoTo3SbkNum,
|
||||
ylj_to_sbk_num,
|
||||
fshl_num,
|
||||
yxsd_num,
|
||||
hxsd_num,
|
||||
region_code,
|
||||
ops_dept
|
||||
FROM group_cmpm_count_lingshou_825
|
||||
<where>
|
||||
<if test="dt != null and dt != ''">and dt = #{dt}</if>
|
||||
<if test="groupName != null and groupName != ''">and group_name like concat('%', #{groupName}, '%')</if>
|
||||
<if test="isBranch == true">and dept_id like concat('%',concat(#{deptId},'%'))</if>
|
||||
<if test="isOutlet == true">and outlets_id like concat('%',concat(#{deptId},'%'))</if>
|
||||
<if test="isManager == true">and user_name like concat('%',concat(#{userName},'%'))</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectGsCountList" resultType="com.ruoyi.group.domain.entity.GroupCmpmCountGongsi825">
|
||||
SELECT
|
||||
dt,
|
||||
group_id,
|
||||
group_name,
|
||||
group_mode,
|
||||
dept_id,
|
||||
dept_name,
|
||||
outlets_id,
|
||||
outlets_name,
|
||||
user_name,
|
||||
cust_num,
|
||||
hq_cur_balance,
|
||||
bz_cur_balance,
|
||||
loan_balance_cny,
|
||||
finance_prod_711_balance,
|
||||
finance_prod_716_balance,
|
||||
loan_year_dailyaverage,
|
||||
qfcd_rat,
|
||||
tx_rat,
|
||||
bh_rat,
|
||||
yxdfgz_rat,
|
||||
dkdf_rat,
|
||||
dksf_rat,
|
||||
dkshf_rat,
|
||||
pjb_rat,
|
||||
czb_rat,
|
||||
sfb_rat,
|
||||
mrb_rat,
|
||||
szst_rat,
|
||||
kh_rat,
|
||||
gjjsyw_rat,
|
||||
yqjsh_rat,
|
||||
qfcd_num,
|
||||
tx_num,
|
||||
bh_num,
|
||||
yxdfgz_num,
|
||||
ustr_count_per_m,
|
||||
ustr_bal_m,
|
||||
dkdf_num,
|
||||
dksf_num,
|
||||
dkshf_num,
|
||||
pjb_num,
|
||||
czb_num,
|
||||
sfb_num,
|
||||
mrb_num,
|
||||
szst_num,
|
||||
kh_num,
|
||||
gjjsyw_num,
|
||||
yqjsh_num,
|
||||
region_code,
|
||||
ops_dept,
|
||||
htqy_rat,
|
||||
htqy_num,
|
||||
dept_type,
|
||||
zf_365cnt,
|
||||
zf_180cnt,
|
||||
zf_90cnt,
|
||||
zf_30cnt,
|
||||
zf_365rt,
|
||||
zf_180rt,
|
||||
zf_90rt,
|
||||
zf_30rt,
|
||||
ph_rat,
|
||||
ph_num
|
||||
FROM group_cmpm_count_gongsi_825
|
||||
<where>
|
||||
<if test="dt != null and dt != ''">and dt = #{dt}</if>
|
||||
<if test="groupName != null and groupName != ''">and group_name like concat('%', #{groupName}, '%')</if>
|
||||
<if test=" isBranch == true">and dept_id like concat('%',concat(#{deptId},'%'))</if>
|
||||
<if test=" isOutlet == true">and outlets_id like concat('%',concat(#{deptId},'%'))</if>
|
||||
<if test=" isManager == true">and user_name like concat('%',concat(#{userName},'%'))</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectLsCustList" resultType="com.ruoyi.group.domain.entity.GroupCustCountLingshou825">
|
||||
SELECT
|
||||
group_id,
|
||||
cust_name,
|
||||
cust_idc,
|
||||
cust_isn,
|
||||
cur_bal_d,
|
||||
bal_loan,
|
||||
loan_ave,
|
||||
is_sx,
|
||||
is_yx,
|
||||
sx_bal,
|
||||
is_yxht,
|
||||
is_xyk,
|
||||
fshl,
|
||||
is_sd,
|
||||
dian,
|
||||
shui,
|
||||
tax,
|
||||
open_num,
|
||||
dep_bal,
|
||||
fin_bal,
|
||||
is_grhx,
|
||||
is_cfyx,
|
||||
is_yxsbk,
|
||||
is_2to3_sbk,
|
||||
is_ylj_to_sbk,
|
||||
region_code,
|
||||
ops_dept,
|
||||
cust_type,
|
||||
is_365zf,
|
||||
is_180zf,
|
||||
is_90zf,
|
||||
is_30zf,
|
||||
dt,
|
||||
is_hxsd
|
||||
FROM group_cust_count_lingshou_825
|
||||
<where>
|
||||
group_id = #{groupId}
|
||||
<if test="dt != null and dt != ''">and dt = #{dt}</if>
|
||||
<if test="custName != null and custName != ''">and cust_name like concat('%', #{custName}, '%')</if>
|
||||
<if test="custIdc != null and custIdc != ''">and cust_idc like concat('%', #{custIdc}, '%')</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectGsCustList" resultType="com.ruoyi.group.domain.entity.GroupCustCountGongsi825">
|
||||
SELECT
|
||||
group_id,
|
||||
cust_name,
|
||||
social_credit_code,
|
||||
cust_isn,
|
||||
hq_cur_balance,
|
||||
bz_cur_balance,
|
||||
is_credit,
|
||||
loan_balance_cny,
|
||||
loan_year_dailyaverage,
|
||||
finance_prod_716_open_flag,
|
||||
finance_prod_716_balance,
|
||||
finance_prod_711_open_flag,
|
||||
finance_prod_711_balance,
|
||||
intl_bussiness_jcbh_open_flag,
|
||||
is_ustr,
|
||||
ustr_count_per_m,
|
||||
ustr_bal_m,
|
||||
eleccharge_sign_flag,
|
||||
watercharge_sign_flag,
|
||||
taxdeduction_sign_flag,
|
||||
pjb,
|
||||
czb,
|
||||
sfb,
|
||||
mrb,
|
||||
szst,
|
||||
is_open_sts,
|
||||
intl_bussiness_open_flag,
|
||||
intl_bussiness_325_open_flag,
|
||||
region_code,
|
||||
ops_dept,
|
||||
cust_type,
|
||||
is_htqy,
|
||||
dept_name,
|
||||
outlets_id,
|
||||
outlets_name,
|
||||
user_name,
|
||||
dept_id,
|
||||
is_365zf,
|
||||
is_180zf,
|
||||
is_90zf,
|
||||
is_30zf,
|
||||
dt,
|
||||
is_ph
|
||||
FROM group_cust_count_gongsi_825
|
||||
<where>
|
||||
group_id = #{groupId}
|
||||
<if test="dt != null and dt != ''">and dt = #{dt}</if>
|
||||
<if test="isBranch == true">and dept_id like concat('%',concat(#{deptId},'%'))</if>
|
||||
<if test="isOutlet == true">and outlets_id like concat('%',concat(#{deptId},'%'))</if>
|
||||
<if test="isManager == true">and user_name like concat('%',concat(#{userName},'%'))</if>
|
||||
<if test="custName != null and custName != ''">and cust_name like concat('%', #{custName}, '%')</if>
|
||||
<if test="socialCreditCode != null and socialCreditCode != ''">and social_credit_code like concat('%', #{socialCreditCode}, '%')</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -5,6 +5,7 @@ import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.ibs.cmpm.domain.dto.CustLevelDTO;
|
||||
import com.ruoyi.ibs.cmpm.domain.dto.CustManagerDTO;
|
||||
@@ -97,6 +98,24 @@ public class GridCmpmController extends BaseController {
|
||||
return gridCmpmService.selectCustManagerResult();
|
||||
}
|
||||
|
||||
@GetMapping("/custManager/custLevel/list")
|
||||
@Log(title = "绩效网格-管户报表星级列表")
|
||||
@ApiOperation("管户报表星级列表")
|
||||
public AjaxResult getCustLevelListForManager() {
|
||||
return success(gridCmpmService.getCustLevelListForManager());
|
||||
}
|
||||
|
||||
@PostMapping("/custManager/export")
|
||||
@Log(title = "绩效网格-管户报表异步导出", businessType = BusinessType.EXPORT)
|
||||
@ApiOperation("管户报表异步导出")
|
||||
public AjaxResult exportCustManager(@RequestBody(required = false) CustManagerDTO custManagerDTO) {
|
||||
if (custManagerDTO == null) {
|
||||
custManagerDTO = new CustManagerDTO();
|
||||
}
|
||||
String taskId = gridCmpmService.exportCustManagerAsync(custManagerDTO);
|
||||
return AjaxResult.success("导出任务创建成功,请稍后前往下载中心下载", taskId);
|
||||
}
|
||||
|
||||
@GetMapping("/custLevel/count")
|
||||
@Log(title = "绩效网格-查询客户分层等级")
|
||||
@ApiOperation("查询客户分层等级")
|
||||
@@ -110,4 +129,5 @@ public class GridCmpmController extends BaseController {
|
||||
public AjaxResult selectCustBaseInfoList(@RequestBody CustBaseInfo custBaseInfo) {
|
||||
return AjaxResult.success( gridCmpmCustService.selectCustInfoList (custBaseInfo)) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,4 +18,8 @@ public class CustManagerDTO {
|
||||
@ApiModelProperty(value = "网点名",notes = "")
|
||||
private String branchId;
|
||||
|
||||
/** 状态类型:current(本月)、last(上月)、rise(上升)、fall(下降) */
|
||||
@ApiModelProperty(value = "状态类型", notes = "current(本月)、last(上月)、rise(上升)、fall(下降)")
|
||||
private String statusType;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.ruoyi.ibs.cmpm.domain.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -24,74 +23,92 @@ public class DwbRetailCustLevelManagerDetailVO {
|
||||
|
||||
/** 网点号 */
|
||||
@ApiModelProperty(value = "网点号")
|
||||
@ExcelProperty("网点号")
|
||||
private String outletId;
|
||||
|
||||
/** 网点名 */
|
||||
@ApiModelProperty(value = "网点名")
|
||||
@ExcelProperty("网点名")
|
||||
private String outletName;
|
||||
|
||||
/** 支行号 */
|
||||
@ApiModelProperty(value = "支行号")
|
||||
@ExcelProperty("支行号")
|
||||
private String branchId;
|
||||
|
||||
/** 支行名 */
|
||||
@ApiModelProperty(value = "支行名")
|
||||
@ExcelProperty("支行名")
|
||||
private String branchName;
|
||||
|
||||
/** 客户名称 */
|
||||
@ApiModelProperty(value = "客户名称")
|
||||
@ExcelProperty("客户名称")
|
||||
private String custName;
|
||||
|
||||
/** 客户证件号 */
|
||||
@ApiModelProperty(value = "客户证件号")
|
||||
@ExcelProperty("客户证件号")
|
||||
private String custIdc;
|
||||
|
||||
/** 客户内码 */
|
||||
@ApiModelProperty(value = "客户内码")
|
||||
@ExcelProperty("客户内码")
|
||||
private String custIsn;
|
||||
|
||||
/** 年龄 */
|
||||
@ApiModelProperty(value = "年龄")
|
||||
@ExcelProperty("年龄")
|
||||
private String custAge;
|
||||
|
||||
/** 性别 */
|
||||
@ApiModelProperty(value = "性别")
|
||||
@ExcelProperty("性别")
|
||||
private String custSex;
|
||||
|
||||
/** 联系电话 */
|
||||
@ApiModelProperty(value = "联系电话")
|
||||
@ExcelProperty("联系电话")
|
||||
private String custPhone;
|
||||
|
||||
/** 联系地址 */
|
||||
@ApiModelProperty(value = "联系地址")
|
||||
@ExcelProperty("联系地址")
|
||||
private String custAddress;
|
||||
|
||||
/** 总资产余额 */
|
||||
@ApiModelProperty(value = "总资产余额")
|
||||
@ExcelProperty("总资产余额")
|
||||
private BigDecimal custAumBal;
|
||||
|
||||
/** 总资产余额较上月变动 */
|
||||
@ApiModelProperty(value = "总资产余额较上月变动")
|
||||
@ExcelProperty("总资产余额较上月变动")
|
||||
private BigDecimal aumBalCompLm;
|
||||
|
||||
/** 总资产月日均 */
|
||||
@ApiModelProperty(value = "总资产月日均")
|
||||
@ExcelProperty("总资产余额月日均")
|
||||
private BigDecimal custAumMonthAvg;
|
||||
|
||||
/** 客户星级 */
|
||||
@ApiModelProperty(value = "客户星级")
|
||||
@ExcelProperty("客户星级")
|
||||
private String custLevel;
|
||||
|
||||
/** 星级较上月变动 */
|
||||
@ApiModelProperty(value = "星级较上月变动")
|
||||
@ExcelProperty("星级较上月变动")
|
||||
private String custLevelCompLm;
|
||||
|
||||
/** 责任人 */
|
||||
@ApiModelProperty(value = "责任人")
|
||||
@ExcelProperty("责任人")
|
||||
private String managerName;
|
||||
|
||||
/** 责任人柜员号 */
|
||||
@ApiModelProperty(value = "责任人柜员号")
|
||||
@ExcelProperty("责任人柜员号")
|
||||
private String managerId;
|
||||
|
||||
}
|
||||
|
||||
@@ -8,11 +8,15 @@ import com.ruoyi.ibs.cmpm.domain.entity.GridCmpm;
|
||||
import com.ruoyi.ibs.cmpm.domain.vo.DwbRetailCustLevelManagerDetailVO;
|
||||
import com.ruoyi.ibs.cmpm.domain.vo.DwbRetailResultVO;
|
||||
import com.ruoyi.ibs.cmpm.domain.vo.GridCmpmClaimVO;
|
||||
import com.ruoyi.ibs.cmpm.domain.vo.GridCmpmVO;
|
||||
import com.ruoyi.ibs.customerselect.domain.CustBaseInfo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.cursor.Cursor;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author 吴凯程
|
||||
@@ -43,6 +47,11 @@ public interface GridCmpmMapper {
|
||||
|
||||
List<DwbRetailCustLevelManagerDetailVO> getCustManagerList(CustManagerDTO custManagerDTO);
|
||||
|
||||
List<DwbRetailCustLevelManagerDetailVO> getCustManagerListByPage(@Param("dto") CustManagerDTO custManagerDTO,
|
||||
@Param("headId") String headId,
|
||||
@Param("offset") Integer offset,
|
||||
@Param("pageSize") Integer pageSize);
|
||||
|
||||
int getCustLevelCount(CustManagerDTO custManagerDTO);
|
||||
|
||||
List<CustBaseInfo> selectCustInfoFromGridCmpm(CustBaseInfo custBaseInfo);
|
||||
@@ -60,6 +69,23 @@ public interface GridCmpmMapper {
|
||||
|
||||
List<String> selectManagerList();
|
||||
|
||||
/**
|
||||
* 全量查询绩效网格客户列表(用于客群管户关系匹配,不按客户经理过滤)
|
||||
* @param gridType 网格类型
|
||||
* @param headId 总行ID
|
||||
* @return 客户列表(包含管户关系信息)
|
||||
*/
|
||||
List<GridCmpmVO> getAllCustomerListForImport(@Param("gridType") String gridType, @Param("headId") String headId);
|
||||
|
||||
/**
|
||||
* 根据客户ID和类型列表查询管户关系(用于动态客群更新管户关系)
|
||||
* @param gridType 网格类型(retail/corporate)
|
||||
* @param headId 总行ID
|
||||
* @param custInfoList 客户信息列表(包含custId和custType)
|
||||
* @return 客户管户关系列表
|
||||
*/
|
||||
List<GridCmpmVO> getRelationshipsByCustList(@Param("gridType") String gridType, @Param("headId") String headId, @Param("custInfoList") List<Map<String, String>> custInfoList);
|
||||
|
||||
|
||||
// List<CustBaseInfo> selectCustInfoRetailFromGridCmpm(CustBaseInfo custBaseInfo);
|
||||
//
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.ruoyi.ibs.cmpm.service;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.alibaba.excel.write.metadata.WriteSheet;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.bean.BeanUtils;
|
||||
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||
import com.ruoyi.ibs.cmpm.domain.dto.CustLevelDTO;
|
||||
import com.ruoyi.ibs.cmpm.domain.dto.CustManagerDTO;
|
||||
import com.ruoyi.ibs.cmpm.domain.dto.GridCmpmListDTO;
|
||||
@@ -14,11 +18,19 @@ import com.ruoyi.ibs.cmpm.domain.vo.DwbRetailCustLevelManagerDetailVO;
|
||||
import com.ruoyi.ibs.cmpm.domain.vo.DwbRetailResultVO;
|
||||
import com.ruoyi.ibs.cmpm.domain.vo.GridCmpmVO;
|
||||
import com.ruoyi.ibs.cmpm.mapper.GridCmpmMapper;
|
||||
import com.ruoyi.ibs.task.domain.entity.ImportExportTask;
|
||||
import com.ruoyi.ibs.task.mapper.ImportExportTaskMapper;
|
||||
import com.ruoyi.system.enums.OssFileEnum;
|
||||
import com.ruoyi.system.service.OssFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -27,6 +39,7 @@ import java.util.stream.Collectors;
|
||||
* @Date 2025/10/15
|
||||
**/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class GridCmpmService {
|
||||
|
||||
|
||||
@@ -39,6 +52,15 @@ public class GridCmpmService {
|
||||
@Resource
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Resource
|
||||
private ImportExportTaskMapper importExportTaskMapper;
|
||||
|
||||
@Resource
|
||||
private OssFileService ossFileService;
|
||||
|
||||
@Resource(name = "excelExportExecutor")
|
||||
private ExecutorService executorService;
|
||||
|
||||
private final String CUST_LEVEL_COUNT_KEY = "GRID_CMPM_CUST_LEVEL_COUNT_";
|
||||
|
||||
public List<GridCmpmVO> selectManageList(GridCmpmListDTO gridCmpmRetailListDTO){
|
||||
@@ -94,33 +116,32 @@ public class GridCmpmService {
|
||||
}
|
||||
|
||||
public List<DwbRetailCustLevelManagerDetailVO> selectCustManagerList(CustManagerDTO custManagerDTO) {
|
||||
String userRole = SecurityUtils.userRole();
|
||||
if (userRole.equals("manager")){
|
||||
//客户经理查自己
|
||||
custManagerDTO.setManagerId(SecurityUtils.getUsername());
|
||||
}else if (userRole.equals("outlet")){
|
||||
//网点管理员查网点
|
||||
custManagerDTO.setOutletId(String.valueOf(SecurityUtils.getDeptId()));
|
||||
}else if (userRole.equals("branch")){
|
||||
//支行管理员查支行
|
||||
custManagerDTO.setBranchId(String.valueOf(SecurityUtils.getDeptId()));
|
||||
}
|
||||
//其他角色查全部
|
||||
applyCustManagerScope(custManagerDTO);
|
||||
return gridCmpmMapper.getCustManagerList(custManagerDTO);
|
||||
}
|
||||
|
||||
public int custLevelCount(CustManagerDTO custManagerDTO) {
|
||||
String userRole = SecurityUtils.userRole();
|
||||
if (userRole.equals("manager")){
|
||||
//客户经理查自己
|
||||
custManagerDTO.setManagerId(SecurityUtils.getUsername());
|
||||
}else if (userRole.equals("outlet")){
|
||||
//网点管理员查网点
|
||||
custManagerDTO.setOutletId(String.valueOf(SecurityUtils.getDeptId()));
|
||||
}else if (userRole.equals("branch")){
|
||||
//支行管理员查支行
|
||||
custManagerDTO.setBranchId(String.valueOf(SecurityUtils.getDeptId()));
|
||||
public String exportCustManagerAsync(CustManagerDTO custManagerDTO) {
|
||||
applyCustManagerScope(custManagerDTO);
|
||||
String headId = SecurityUtils.getHeadId();
|
||||
|
||||
ImportExportTask task = new ImportExportTask();
|
||||
String taskId = IdUtils.randomUUID();
|
||||
task.setId(taskId);
|
||||
task.setStatus("0");
|
||||
Date now = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
task.setFileName(sdf.format(now) + "管户报表导出");
|
||||
task.setUserName(SecurityUtils.getUsername());
|
||||
task.setCreateTime(now);
|
||||
importExportTaskMapper.insert(task);
|
||||
|
||||
String userName = SecurityUtils.getUsername();
|
||||
executorService.submit(() -> doExportCustManager(taskId, custManagerDTO, userName, headId));
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public int custLevelCount(CustManagerDTO custManagerDTO) {
|
||||
applyCustManagerScope(custManagerDTO);
|
||||
return gridCmpmMapper.getCustLevelCount(custManagerDTO);
|
||||
}
|
||||
|
||||
@@ -152,6 +173,13 @@ public class GridCmpmService {
|
||||
return new DwbRetailResultVO();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管户报表星级列表
|
||||
*/
|
||||
public List<String> getCustLevelListForManager() {
|
||||
return gridCmpmMapper.getCustLevelList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 每月定时设置统计数据
|
||||
*/
|
||||
@@ -226,7 +254,6 @@ public class GridCmpmService {
|
||||
// 获取上月各星级客户数
|
||||
Map<String, Integer> historyLevelCountMap = getCustLevelCountMap(custManagerDTO, "last");
|
||||
Map<String, Integer> custLevelCompLm = calculateLevelChanges(historyLevelCountMap, currentLevelCountMap);
|
||||
vo.setCustLevelCompLm(custLevelCompLm);
|
||||
|
||||
// 在 vo.setCustLevelCompLm 之前,按顺序重新组织数据
|
||||
String[] order = {"5星", "4星", "3星", "2星", "1星", "基础", "长尾"};
|
||||
@@ -268,6 +295,64 @@ public class GridCmpmService {
|
||||
return custLevelCountMap;
|
||||
}
|
||||
|
||||
private void applyCustManagerScope(CustManagerDTO custManagerDTO) {
|
||||
String userRole = SecurityUtils.userRole();
|
||||
if (userRole.equals("manager")) {
|
||||
custManagerDTO.setManagerId(SecurityUtils.getUsername());
|
||||
} else if (userRole.equals("outlet")) {
|
||||
custManagerDTO.setOutletId(String.valueOf(SecurityUtils.getDeptId()));
|
||||
} else if (userRole.equals("branch")) {
|
||||
custManagerDTO.setBranchId(String.valueOf(SecurityUtils.getDeptId()));
|
||||
}
|
||||
}
|
||||
|
||||
private void doExportCustManager(String taskId, CustManagerDTO custManagerDTO, String userName, String headId) {
|
||||
ImportExportTask task = importExportTaskMapper.selectById(taskId);
|
||||
File tempFile = null;
|
||||
try {
|
||||
tempFile = File.createTempFile("管户报表导出_" + taskId + "-", ".xlsx");
|
||||
ExcelWriter excelWriter = EasyExcel.write(tempFile, DwbRetailCustLevelManagerDetailVO.class).build();
|
||||
WriteSheet writeSheet = EasyExcel.writerSheet("管户报表").build();
|
||||
int pageSize = 1000;
|
||||
int pageNum = 0;
|
||||
List<DwbRetailCustLevelManagerDetailVO> pageData;
|
||||
|
||||
do {
|
||||
pageData = gridCmpmMapper.getCustManagerListByPage(custManagerDTO, headId, pageNum * pageSize, pageSize);
|
||||
if (!pageData.isEmpty()) {
|
||||
excelWriter.write(pageData, writeSheet);
|
||||
}
|
||||
pageNum++;
|
||||
} while (pageData.size() == pageSize);
|
||||
|
||||
excelWriter.finish();
|
||||
|
||||
String ossUUId = ossFileService.uploadFileToOss(
|
||||
OssFileEnum.CUST_MANAGER_REPORT,
|
||||
tempFile,
|
||||
"管户报表导出_" + taskId + ".xlsx",
|
||||
userName
|
||||
);
|
||||
|
||||
task.setStatus("1");
|
||||
task.setFileUrl(ossUUId);
|
||||
task.setFinishTime(new Date());
|
||||
importExportTaskMapper.updateById(task);
|
||||
} catch (Exception e) {
|
||||
task.setStatus("2");
|
||||
task.setFinishTime(new Date());
|
||||
task.setErrorMsg(e.getMessage());
|
||||
importExportTaskMapper.updateById(task);
|
||||
} finally {
|
||||
if (Objects.nonNull(tempFile)) {
|
||||
boolean deleted = tempFile.delete();
|
||||
if (!deleted) {
|
||||
log.warn("临时文件删除失败: {}", tempFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算客户等级变化情况
|
||||
private Map<String, Integer> calculateLevelChanges(Map<String, Integer> historyMap, Map<String, Integer> currentMap) {
|
||||
Map<String, Integer> changesMap = new HashMap<>();
|
||||
@@ -296,4 +381,28 @@ public class GridCmpmService {
|
||||
return changesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全量查询绩效网格客户列表(用于客群管户关系匹配,不依赖SecurityUtils)
|
||||
* @param gridType 网格类型
|
||||
* @param headId 总行ID
|
||||
* @return 客户列表(包含管户关系信息)
|
||||
*/
|
||||
public List<GridCmpmVO> selectAllForImport(String gridType, String headId) {
|
||||
return gridCmpmMapper.getAllCustomerListForImport(gridType, headId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据客户ID列表查询管户关系(用于动态客群更新管户关系)
|
||||
* @param gridType 网格类型(retail/corporate)
|
||||
* @param headId 总行ID
|
||||
* @param custInfoList 客户信息列表(包含custId和custType)
|
||||
* @return 客户管户关系列表
|
||||
*/
|
||||
public List<GridCmpmVO> getRelationshipsByCustList(String gridType, String headId, List<Map<String, String>> custInfoList) {
|
||||
if (custInfoList == null || custInfoList.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return gridCmpmMapper.getRelationshipsByCustList(gridType, headId, custInfoList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.rmi.ServerException;
|
||||
@@ -220,4 +222,18 @@ public class MyCustomerController extends BaseController {
|
||||
}
|
||||
return AjaxResult.success(iSysCampaignGroupCustomerService.appointCustCamp( custId, custName, custIdc, custPhone, custIsn,socialCreditCode,lpName, campaignId, custType));
|
||||
}
|
||||
|
||||
@Log(title = "我的客户-异步导入企业客户价值分层", businessType = com.ruoyi.common.enums.BusinessType.IMPORT)
|
||||
@PostMapping(value = "/importBusinessCustLevelAsync", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@ApiOperation("异步导入企业客户价值分层")
|
||||
public AjaxResult importBusinessCustLevelAsync(@RequestPart("file") MultipartFile file) {
|
||||
return AjaxResult.success("导入任务已提交,后台正在处理", myCustomerService.importBusinessCustLevelAsync(file));
|
||||
}
|
||||
|
||||
@Log(title = "我的客户-查询企业客户价值分层导入状态")
|
||||
@GetMapping("/importBusinessCustLevelStatus/{taskId}")
|
||||
@ApiOperation("查询企业客户价值分层导入状态")
|
||||
public AjaxResult importBusinessCustLevelStatus(@PathVariable String taskId) {
|
||||
return AjaxResult.success(myCustomerService.getBusinessCustLevelImportStatus(taskId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ruoyi.ibs.customerselect.domain;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BusinessCustLevelImportExcelDTO {
|
||||
|
||||
@ExcelProperty("统信码")
|
||||
private String socialCreditCode;
|
||||
|
||||
@ExcelProperty("价值分层")
|
||||
private String custLevel;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.ibs.customerselect.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class BusinessCustLevelImportTaskVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 0-处理中 1-成功 2-失败
|
||||
*/
|
||||
private String status;
|
||||
|
||||
private String message;
|
||||
|
||||
private Integer totalCount;
|
||||
|
||||
private Integer successCount;
|
||||
|
||||
private Integer ignoredCount;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String createTime;
|
||||
|
||||
private String finishTime;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.ibs.customerselect.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.common.core.domain.entity.CustInfoBusiness;
|
||||
import com.ruoyi.ibs.customerselect.domain.BusinessCustLevelImportExcelDTO;
|
||||
import com.ruoyi.ibs.customerselect.domain.CustBaseInfo;
|
||||
import com.ruoyi.ibs.customerselect.domain.CustInfoDeleteFromAnchor;
|
||||
import com.ruoyi.ibs.customerselect.domain.CustInfoUpdateFromAnchor;
|
||||
@@ -242,4 +243,10 @@ public interface CustInfoBusinessMapper extends BaseMapper<CustInfoBusiness>
|
||||
public int insertCustomersToBusinessByScCode(List<SysGroupCustomer> sysGroupCustomers);
|
||||
|
||||
List<CustInfoBusiness> selectRecord(String socialCreditCode);
|
||||
|
||||
List<String> selectExistingSocialCreditCodes(@Param("socialCreditCodes") List<String> socialCreditCodes,
|
||||
@Param("deptCode") String deptCode);
|
||||
|
||||
int batchUpdateCustLevelBySocialCreditCode(@Param("list") List<BusinessCustLevelImportExcelDTO> list,
|
||||
@Param("deptCode") String deptCode);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.ibs.customerselect.service;
|
||||
|
||||
import com.ruoyi.ibs.customerselect.domain.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -41,4 +42,8 @@ public interface IMyCustomerService {
|
||||
public CustListSearchVo selectCustomListSearchVo(CustBaseInfo sysCustomerBasedata);
|
||||
|
||||
MerchantMcspInfo selectmerchantMessage(String custId);
|
||||
|
||||
String importBusinessCustLevelAsync(MultipartFile file);
|
||||
|
||||
BusinessCustLevelImportTaskVO getBusinessCustLevelImportStatus(String taskId);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
package com.ruoyi.ibs.customerselect.service.Impl;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.annotation.DataScope;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.CustInfoBusiness;
|
||||
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||
import com.ruoyi.ibs.dashboard.service.NotificationService;
|
||||
import com.ruoyi.ibs.customerselect.domain.BusinessCustLevelImportExcelDTO;
|
||||
import com.ruoyi.ibs.customerselect.domain.BusinessCustLevelImportTaskVO;
|
||||
import com.ruoyi.ibs.customerselect.domain.*;
|
||||
import com.ruoyi.ibs.customerselect.domain.vo.GridRelateVO;
|
||||
import com.ruoyi.ibs.customerselect.mapper.CustInfoBusinessMapper;
|
||||
@@ -32,9 +38,16 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -45,6 +58,10 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
public class MyCustomerServiceImpl implements IMyCustomerService {
|
||||
|
||||
private static final String BUSINESS_CUST_LEVEL_IMPORT_TASK_KEY = "BUSINESS_CUST_LEVEL_IMPORT_TASK_";
|
||||
private static final int BUSINESS_CUST_LEVEL_IMPORT_BATCH_SIZE = 1000;
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Autowired
|
||||
private CustInfoBusinessMapper custInfoBusinessMapper;
|
||||
|
||||
@@ -80,6 +97,12 @@ public class MyCustomerServiceImpl implements IMyCustomerService {
|
||||
@Resource
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Resource
|
||||
private NotificationService notificationService;
|
||||
|
||||
@Resource(name = "excelImportExecutor")
|
||||
private ExecutorService excelImportExecutor;
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(MyCustomerServiceImpl.class);
|
||||
|
||||
/**
|
||||
@@ -467,5 +490,154 @@ public class MyCustomerServiceImpl implements IMyCustomerService {
|
||||
return merchantMcspInfoMapper.selectOne(new LambdaQueryWrapper<MerchantMcspInfo>().eq(MerchantMcspInfo::getCustId,custId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String importBusinessCustLevelAsync(MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new ServiceException("导入文件不能为空");
|
||||
}
|
||||
byte[] fileBytes;
|
||||
try {
|
||||
fileBytes = file.getBytes();
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("读取导入文件失败");
|
||||
}
|
||||
String taskId = IdUtils.fastSimpleUUID();
|
||||
String userName = SecurityUtils.getUsername();
|
||||
String deptCode = SecurityUtils.getHeadId();
|
||||
BusinessCustLevelImportTaskVO taskVO = new BusinessCustLevelImportTaskVO();
|
||||
taskVO.setStatus("0");
|
||||
taskVO.setMessage("导入任务已提交,后台正在处理");
|
||||
taskVO.setTotalCount(0);
|
||||
taskVO.setSuccessCount(0);
|
||||
taskVO.setIgnoredCount(0);
|
||||
taskVO.setUserName(userName);
|
||||
taskVO.setCreateTime(formatNow());
|
||||
cacheBusinessCustLevelImportTask(taskId, taskVO);
|
||||
excelImportExecutor.submit(() -> doImportBusinessCustLevel(taskId, userName, deptCode, fileBytes));
|
||||
return taskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusinessCustLevelImportTaskVO getBusinessCustLevelImportStatus(String taskId) {
|
||||
BusinessCustLevelImportTaskVO taskVO = redisCache.getCacheObject(getBusinessCustLevelImportTaskKey(taskId));
|
||||
if (taskVO == null) {
|
||||
throw new ServiceException("导入任务不存在或已过期");
|
||||
}
|
||||
return taskVO;
|
||||
}
|
||||
|
||||
private void doImportBusinessCustLevel(String taskId, String userName, String deptCode, byte[] fileBytes) {
|
||||
BusinessCustLevelImportTaskVO taskVO = redisCache.getCacheObject(getBusinessCustLevelImportTaskKey(taskId));
|
||||
if (taskVO == null) {
|
||||
taskVO = new BusinessCustLevelImportTaskVO();
|
||||
taskVO.setUserName(userName);
|
||||
taskVO.setCreateTime(formatNow());
|
||||
}
|
||||
try {
|
||||
List<BusinessCustLevelImportExcelDTO> importRows = EasyExcel.read(new ByteArrayInputStream(fileBytes))
|
||||
.head(BusinessCustLevelImportExcelDTO.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
|
||||
Map<String, String> levelMap = new LinkedHashMap<>();
|
||||
if (importRows != null) {
|
||||
for (BusinessCustLevelImportExcelDTO row : importRows) {
|
||||
String socialCreditCode = normalizeImportCell(row.getSocialCreditCode());
|
||||
String custLevel = normalizeImportCell(row.getCustLevel());
|
||||
if (StringUtils.isEmpty(socialCreditCode)) {
|
||||
continue;
|
||||
}
|
||||
levelMap.put(socialCreditCode, custLevel);
|
||||
}
|
||||
}
|
||||
|
||||
if (levelMap.isEmpty()) {
|
||||
throw new ServiceException("Excel中未识别到有效的统信码和价值分层数据");
|
||||
}
|
||||
|
||||
List<String> existingSocialCreditCodes = getExistingBusinessSocialCreditCodes(new ArrayList<>(levelMap.keySet()), deptCode);
|
||||
Set<String> existingCodeSet = new HashSet<>(existingSocialCreditCodes);
|
||||
List<BusinessCustLevelImportExcelDTO> updateList = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry : levelMap.entrySet()) {
|
||||
if (!existingCodeSet.contains(entry.getKey())) {
|
||||
continue;
|
||||
}
|
||||
BusinessCustLevelImportExcelDTO dto = new BusinessCustLevelImportExcelDTO();
|
||||
dto.setSocialCreditCode(entry.getKey());
|
||||
dto.setCustLevel(entry.getValue());
|
||||
updateList.add(dto);
|
||||
}
|
||||
|
||||
batchUpdateBusinessCustLevel(updateList, deptCode);
|
||||
|
||||
int totalCount = levelMap.size();
|
||||
int successCount = updateList.size();
|
||||
int ignoredCount = totalCount - successCount;
|
||||
String message = String.format("公司客户视图分层分类数据导入完成,成功更新%d条,忽略%d条", successCount, ignoredCount);
|
||||
|
||||
taskVO.setStatus("1");
|
||||
taskVO.setMessage(message);
|
||||
taskVO.setTotalCount(totalCount);
|
||||
taskVO.setSuccessCount(successCount);
|
||||
taskVO.setIgnoredCount(ignoredCount);
|
||||
taskVO.setFinishTime(formatNow());
|
||||
cacheBusinessCustLevelImportTask(taskId, taskVO);
|
||||
notificationService.sendNotification(userName, message);
|
||||
} catch (Exception e) {
|
||||
String errorMsg = StringUtils.isNotEmpty(e.getMessage()) ? e.getMessage() : "导入失败,请检查文件内容";
|
||||
taskVO.setStatus("2");
|
||||
taskVO.setMessage(errorMsg);
|
||||
taskVO.setFinishTime(formatNow());
|
||||
cacheBusinessCustLevelImportTask(taskId, taskVO);
|
||||
notificationService.sendNotification(userName, "公司客户视图分层分类数据导入失败:" + errorMsg);
|
||||
logger.error("公司客户视图分层分类数据导入失败,taskId={}", taskId, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void batchUpdateBusinessCustLevel(List<BusinessCustLevelImportExcelDTO> updateList, String deptCode) {
|
||||
if (updateList == null || updateList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < updateList.size(); i += BUSINESS_CUST_LEVEL_IMPORT_BATCH_SIZE) {
|
||||
int endIndex = Math.min(i + BUSINESS_CUST_LEVEL_IMPORT_BATCH_SIZE, updateList.size());
|
||||
custInfoBusinessMapper.batchUpdateCustLevelBySocialCreditCode(updateList.subList(i, endIndex), deptCode);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getExistingBusinessSocialCreditCodes(List<String> socialCreditCodes, String deptCode) {
|
||||
if (socialCreditCodes == null || socialCreditCodes.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> existingSocialCreditCodes = new ArrayList<>();
|
||||
for (int i = 0; i < socialCreditCodes.size(); i += BUSINESS_CUST_LEVEL_IMPORT_BATCH_SIZE) {
|
||||
int endIndex = Math.min(i + BUSINESS_CUST_LEVEL_IMPORT_BATCH_SIZE, socialCreditCodes.size());
|
||||
List<String> batchCodes = socialCreditCodes.subList(i, endIndex);
|
||||
List<String> batchResult = custInfoBusinessMapper.selectExistingSocialCreditCodes(batchCodes, deptCode);
|
||||
if (batchResult != null && !batchResult.isEmpty()) {
|
||||
existingSocialCreditCodes.addAll(batchResult);
|
||||
}
|
||||
}
|
||||
return existingSocialCreditCodes;
|
||||
}
|
||||
|
||||
private void cacheBusinessCustLevelImportTask(String taskId, BusinessCustLevelImportTaskVO taskVO) {
|
||||
redisCache.setCacheObject(getBusinessCustLevelImportTaskKey(taskId), taskVO, 24, TimeUnit.HOURS);
|
||||
}
|
||||
|
||||
private String getBusinessCustLevelImportTaskKey(String taskId) {
|
||||
return BUSINESS_CUST_LEVEL_IMPORT_TASK_KEY + taskId;
|
||||
}
|
||||
|
||||
private String normalizeImportCell(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmedValue = value.trim();
|
||||
return trimmedValue.isEmpty() ? null : trimmedValue;
|
||||
}
|
||||
|
||||
private String formatNow() {
|
||||
return LocalDateTime.now().format(DATE_TIME_FORMATTER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ public class DashboardController extends BaseController {
|
||||
public TableDataInfo list(SysNotice notice)
|
||||
{
|
||||
startPage();
|
||||
notice.setCurrentHeadDeptId(SecurityUtils.getHeadId() + "000");
|
||||
List<SysNotice> list = noticeService.selectNoticeList(notice);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,16 @@ public class DrawGridController extends BaseController {
|
||||
return getDataTable(gridList, page);
|
||||
}
|
||||
|
||||
@ApiOperation("获取网格列表(用于客群创建,简化查询)")
|
||||
@Log(title = "自定义绘制网格--获取网格列表(客群创建用)")
|
||||
@GetMapping("/simpleList")
|
||||
public R<List<DrawGridListVO>> getSimpleGridList(DrawGridListDTO drawGridListDTO) {
|
||||
drawGridListDTO.setUserName(SecurityUtils.getUsername());
|
||||
drawGridListDTO.setDeptId(SecurityUtils.getDeptId());
|
||||
List<DrawGridListVO> gridList = drawGridService.getSimpleGridList(drawGridListDTO);
|
||||
return R.ok(gridList);
|
||||
}
|
||||
|
||||
@ApiOperation("分页获取网格内客户列表")
|
||||
@Log(title = "自定义绘制网格--分页获取网格内客户列表")
|
||||
@GetMapping("/cust/list")
|
||||
|
||||
@@ -17,6 +17,4 @@ public interface DrawGridCustUserUnbindMapper extends BaseMapper<DrawGridCustUse
|
||||
List<DrawGridCustVO> getCustList(DrawGridCustListDTO drawGridCustListDTO);
|
||||
|
||||
List<DrawGridCustVO> getCustListByManager(DrawGridCustListDTO drawGridCustListDTO);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ package com.ruoyi.ibs.draw.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.ibs.draw.domain.entity.DrawGridShapeRelate;
|
||||
import com.ruoyi.ibs.grid.domain.entity.RegionCustUser;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author 吴凯程
|
||||
@@ -10,4 +14,16 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
**/
|
||||
@Mapper
|
||||
public interface DrawGridShapeRelateMapper extends BaseMapper<DrawGridShapeRelate> {
|
||||
|
||||
/**
|
||||
* 根据网格ID查询关联的图形(用于异步导入客群,原生SQL绕过拦截器)
|
||||
* @param gridId 网格ID
|
||||
* @return 图形关联列表
|
||||
*/
|
||||
List<DrawGridShapeRelate> selectByGridId(@Param("gridId") Long gridId);
|
||||
|
||||
/**
|
||||
* 根据绘制网格ID查询所有客户(用于客群导入,直接拼接headId绕过拦截器)
|
||||
*/
|
||||
List<RegionCustUser> selectCustByDrawGridId(@Param("gridId") Long gridId, @Param("headId") String headId);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@ public interface DrawGridService {
|
||||
|
||||
List<DrawGridListVO> getGridList(DrawGridListDTO drawGridListDTO);
|
||||
|
||||
/**
|
||||
* 获取网格列表(用于客群创建,简化查询不统计客户数量)
|
||||
* @param drawGridListDTO 查询条件
|
||||
* @return 网格列表(不含客户数量)
|
||||
*/
|
||||
List<DrawGridListVO> getSimpleGridList(DrawGridListDTO drawGridListDTO);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -334,6 +334,15 @@ public class DrawGridServiceImpl implements DrawGridService {
|
||||
return gridList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DrawGridListVO> getSimpleGridList(DrawGridListDTO drawGridListDTO) {
|
||||
if (SecurityUtils.userRole().equals("manager")) {
|
||||
return drawGridMapper.getGridListByManager(drawGridListDTO);
|
||||
} else {
|
||||
return drawGridMapper.getGridList(drawGridListDTO);
|
||||
}
|
||||
}
|
||||
|
||||
private CustCountDTO getCustCountByGrid(Long gridId) {
|
||||
CustCountDTO custCountDTO = new CustCountDTO();
|
||||
LambdaQueryWrapper<DrawGridShapeRelate> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
@@ -1,56 +1,68 @@
|
||||
package com.ruoyi.ibs.grid.controller;
|
||||
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountGongsi;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshouNew825;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountGongsi;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshouNew825;
|
||||
import com.ruoyi.ibs.grid.service.GridCountService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Api(tags = "网格汇总")
|
||||
@RestController
|
||||
@RequestMapping("/ibs/GridCount/")
|
||||
public class GridCountController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
GridCountService service;
|
||||
private GridCountService service;
|
||||
|
||||
@ApiOperation(value = "查询零售汇总网格列表")
|
||||
@GetMapping("LsList")
|
||||
public TableDataPageInfo<GridCmpmCountLingshou> selectLsCountList(String town, String village,String dt) {
|
||||
public TableDataPageInfo<?> selectLsCountList(String town, String village, String dt) {
|
||||
Page<Object> page = startPage();
|
||||
List<GridCmpmCountLingshou> list = service.selectLsCountList(town, village,dt);
|
||||
if (isNewRetailTenant()) {
|
||||
List<GridCmpmCountLingshouNew825> list = service.selectLsCountListNew825(town, village, dt);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
List<GridCmpmCountLingshou> list = service.selectLsCountList(town, village, dt);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "查询公司汇总网格列表")
|
||||
@GetMapping("GsList")
|
||||
public TableDataPageInfo<GridCmpmCountGongsi> selectGsCountList(String town, String village,String dt) {
|
||||
public TableDataPageInfo<GridCmpmCountGongsi> selectGsCountList(String town, String village, String dt) {
|
||||
Page<Object> page = startPage();
|
||||
List<GridCmpmCountGongsi> list = service.selectGsCountList(town, village,dt);
|
||||
List<GridCmpmCountGongsi> list = service.selectGsCountList(town, village, dt);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "导出零售汇总网格", produces = "application/octet-stream")
|
||||
@GetMapping("exportLs")
|
||||
public void exportLs(HttpServletResponse response, String town, String village,String dt) {
|
||||
public void exportLs(HttpServletResponse response, String town, String village, String dt) {
|
||||
try {
|
||||
if (isNewRetailTenant()) {
|
||||
ExcelUtil<GridCmpmCountLingshouNew825> util = new ExcelUtil<>(GridCmpmCountLingshouNew825.class);
|
||||
util.exportExcel(response, service.selectLsCountListNew825(town, village, dt), "零售网格汇总");
|
||||
return;
|
||||
}
|
||||
ExcelUtil<GridCmpmCountLingshou> util = new ExcelUtil<>(GridCmpmCountLingshou.class);
|
||||
util.exportExcel(response, service.selectLsCountList(town, village,dt), "零售网格汇总");
|
||||
util.exportExcel(response, service.selectLsCountList(town, village, dt), "零售网格汇总");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -59,10 +71,10 @@ public class GridCountController extends BaseController {
|
||||
@Log(title = "导出公司汇总网格")
|
||||
@ApiOperation(value = "导出公司汇总网格", produces = "application/octet-stream")
|
||||
@GetMapping("exportGs")
|
||||
public void exportGs(HttpServletResponse response, String town, String village,String dt) {
|
||||
public void exportGs(HttpServletResponse response, String town, String village, String dt) {
|
||||
try {
|
||||
ExcelUtil<GridCmpmCountGongsi> util = new ExcelUtil<>(GridCmpmCountGongsi.class);
|
||||
util.exportExcel(response, service.selectGsCountList(town, village,dt), "公司网格汇总");
|
||||
util.exportExcel(response, service.selectGsCountList(town, village, dt), "公司网格汇总");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -71,45 +83,55 @@ public class GridCountController extends BaseController {
|
||||
@Log(title = "查询零售客户明细")
|
||||
@ApiOperation(value = "查询零售客户明细")
|
||||
@GetMapping("LsCustList")
|
||||
public TableDataPageInfo<GridCustCountLingshou> selectLsCustList(@RequestParam String regionCode, String custName, String custIdc,String dt) {
|
||||
public TableDataPageInfo<?> selectLsCustList(@RequestParam String regionCode, String custName, String custIdc, String dt) {
|
||||
Page<Object> page = startPage();
|
||||
List<GridCustCountLingshou> list = service.selectLsCustList(regionCode, custName, custIdc,dt);
|
||||
if (isNewRetailTenant()) {
|
||||
List<GridCustCountLingshouNew825> list = service.selectLsCustListNew825(regionCode, custName, custIdc, dt);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
List<GridCustCountLingshou> list = service.selectLsCustList(regionCode, custName, custIdc, dt);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
@Log(title = "查询公司客户明细")
|
||||
@ApiOperation(value = "查询公司客户明细")
|
||||
@GetMapping("GsCustList")
|
||||
public TableDataPageInfo<GridCustCountGongsi> selectGsCustList(@RequestParam String regionCode, String custName, String socialCreditCode,String dt) {
|
||||
public TableDataPageInfo<GridCustCountGongsi> selectGsCustList(@RequestParam String regionCode, String custName, String socialCreditCode, String dt) {
|
||||
Page<Object> page = startPage();
|
||||
List<GridCustCountGongsi> list = service.selectGsCustList(regionCode, custName, socialCreditCode,dt);
|
||||
List<GridCustCountGongsi> list = service.selectGsCustList(regionCode, custName, socialCreditCode, dt);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Log(title = "导出零售客户明细")
|
||||
@ApiOperation(value = "导出零售客户明细", produces = "application/octet-stream")
|
||||
@GetMapping("exportLsCust")
|
||||
public void exportLsCust(HttpServletResponse response, @RequestParam String regionCode, String custName, String custIdc,String dt) {
|
||||
public void exportLsCust(HttpServletResponse response, @RequestParam String regionCode, String custName, String custIdc, String dt) {
|
||||
try {
|
||||
if (isNewRetailTenant()) {
|
||||
ExcelUtil<GridCustCountLingshouNew825> util = new ExcelUtil<>(GridCustCountLingshouNew825.class);
|
||||
util.exportExcel(response, service.selectLsCustListNew825(regionCode, custName, custIdc, dt), "网格客户明细");
|
||||
return;
|
||||
}
|
||||
ExcelUtil<GridCustCountLingshou> util = new ExcelUtil<>(GridCustCountLingshou.class);
|
||||
util.exportExcel(response, service.selectLsCustList(regionCode, custName, custIdc,dt), "网格客户明细");
|
||||
util.exportExcel(response, service.selectLsCustList(regionCode, custName, custIdc, dt), "网格客户明细");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Log(title = "导出公司客户明细")
|
||||
@ApiOperation(value = "导出公司客户明细", produces = "application/octet-stream")
|
||||
@GetMapping("exportGsCust")
|
||||
public void exportGsCust(HttpServletResponse response, @RequestParam String regionCode, String custName, String socialCreditCode,String dt) {
|
||||
public void exportGsCust(HttpServletResponse response, @RequestParam String regionCode, String custName, String socialCreditCode, String dt) {
|
||||
try {
|
||||
ExcelUtil<GridCustCountGongsi> util = new ExcelUtil<>(GridCustCountGongsi.class);
|
||||
util.exportExcel(response, service.selectGsCustList(regionCode, custName, socialCreditCode,dt), "网格客户明细");
|
||||
util.exportExcel(response, service.selectGsCustList(regionCode, custName, socialCreditCode, dt), "网格客户明细");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNewRetailTenant() {
|
||||
return SecurityUtils.getDeptId().toString().startsWith("825");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.ruoyi.ibs.grid.domain.dto.GridCustListDTO;
|
||||
import com.ruoyi.ibs.grid.domain.dto.RegionGridListDTO;
|
||||
import com.ruoyi.ibs.grid.domain.entity.RegionGrid;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionCustUserVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridGroupVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridListVO;
|
||||
import com.ruoyi.ibs.grid.mapper.RegionGridMapper;
|
||||
import com.ruoyi.ibs.grid.service.RegionGridListService;
|
||||
@@ -108,6 +109,14 @@ public class RegionGridListController extends BaseController {
|
||||
return AjaxResult.success("开始更新行社所有网格");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询地理网格列表(专用于客群创建)
|
||||
*/
|
||||
@ApiOperation("查询地理网格列表(专用于客群创建)")
|
||||
@Log(title = "地理网格-查询地理网格列表(客群创建用)")
|
||||
@GetMapping("/groupList")
|
||||
public AjaxResult getRegionGridListForGroup(RegionGridListDTO dto) {
|
||||
return AjaxResult.success(regionGridListService.getRegionGridListForGroup(dto));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.ruoyi.ibs.grid.domain.entity;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 网格汇总统计_零售825专用对象 grid_cmpm_count_lingshou_new_825
|
||||
*/
|
||||
@Data
|
||||
public class GridCmpmCountLingshouNew825 implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Excel(name = "统计日期")
|
||||
private String dt;
|
||||
@Excel(name = "一级网格名称")
|
||||
private String gridName;
|
||||
@Excel(name = "二级网格名称")
|
||||
private String gridName2;
|
||||
@Excel(name = "县/区")
|
||||
private String county;
|
||||
@Excel(name = "镇/街道")
|
||||
private String town;
|
||||
@Excel(name = "村/社区")
|
||||
private String village;
|
||||
@Excel(name = "归属支行机构号")
|
||||
private String deptId;
|
||||
@Excel(name = "归属支行名称")
|
||||
private String deptName;
|
||||
@Excel(name = "归属网点机构号")
|
||||
private String outletsId;
|
||||
@Excel(name = "归属网点名称")
|
||||
private String outletsName;
|
||||
@Excel(name = "归属客户经理")
|
||||
private String userName;
|
||||
@Excel(name = "入格客户数")
|
||||
private Integer custNum;
|
||||
@Excel(name = "近365天已走访人数")
|
||||
private String zf365cnt;
|
||||
@Excel(name = "近180天已走访人数")
|
||||
private String zf180cnt;
|
||||
@Excel(name = "近90天已走访人数")
|
||||
private String zf90cnt;
|
||||
@Excel(name = "近30天已走访人数")
|
||||
private String zf30cnt;
|
||||
@Excel(name = "近365天走访率")
|
||||
private String zf365rt;
|
||||
@Excel(name = "近180天走访率")
|
||||
private String zf180rt;
|
||||
@Excel(name = "近90天走访率")
|
||||
private String zf90rt;
|
||||
@Excel(name = "近30天走访率")
|
||||
private String zf30rt;
|
||||
@Excel(name = "活期存款余额(元)")
|
||||
private String curBalD;
|
||||
@Excel(name = "授信率(%)")
|
||||
private String sxRat;
|
||||
@Excel(name = "用信覆盖率")
|
||||
private String yxRat;
|
||||
@Excel(name = "授信户数")
|
||||
private Integer sxNum;
|
||||
@Excel(name = "用信户数")
|
||||
private Integer yxNum;
|
||||
@Excel(name = "授信金额(合同)")
|
||||
private String sxBal;
|
||||
@Excel(name = "贷款余额(元)")
|
||||
private String balLoan;
|
||||
@Excel(name = "贷款年日均(元)")
|
||||
private String loanAve;
|
||||
@Excel(name = "合同签约率(%)")
|
||||
private String yxhtRat;
|
||||
@Excel(name = "代扣电费覆盖率(%)")
|
||||
private String dianRat;
|
||||
@Excel(name = "代扣水费率(%)")
|
||||
private String shuiRat;
|
||||
@Excel(name = "代扣税费率(%)")
|
||||
private String taxRat;
|
||||
@Excel(name = "开户率(%)")
|
||||
private String openRat;
|
||||
@Excel(name = "合同签约客户数")
|
||||
private Integer yxhtNum;
|
||||
@Excel(name = "代扣电费客户数")
|
||||
private Integer dianNum;
|
||||
@Excel(name = "代扣水费客户数")
|
||||
private Integer shuiNum;
|
||||
@Excel(name = "代扣税费数")
|
||||
private Integer taxNum;
|
||||
@Excel(name = "开户数")
|
||||
private Integer openNum;
|
||||
@Excel(name = "存款余额(元)")
|
||||
private String depBal;
|
||||
@Excel(name = "财富余额(元)")
|
||||
private String finBal;
|
||||
@Excel(name = "个人核心客户数")
|
||||
private Integer grhxNum;
|
||||
@Excel(name = "财富有效客户数")
|
||||
private Integer cfyxNum;
|
||||
@Excel(name = "有效信用卡数")
|
||||
private Integer yxxykNum;
|
||||
@Excel(name = "有效社保卡户数")
|
||||
private Integer yxsbkNum;
|
||||
@Excel(name = "有效社保卡新增")
|
||||
private Integer twoTo3SbkNum;
|
||||
@Excel(name = "养老金迁移至社保卡户数")
|
||||
private Integer yljToSbkNum;
|
||||
@Excel(name = "丰收互联客户数")
|
||||
private Integer fshlNum;
|
||||
@Excel(name = "有效收单商户")
|
||||
private Integer yxsdNum;
|
||||
@Excel(name = "核心收单户数")
|
||||
private Integer hxsdNum;
|
||||
private String regionCode;
|
||||
private String opsDept;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.ruoyi.ibs.grid.domain.entity;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客户明细统计_零售825专用对象 grid_cust_count_lingshou_new_825
|
||||
*/
|
||||
@Data
|
||||
public class GridCustCountLingshouNew825 implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Excel(name = "客户名称")
|
||||
private String custName;
|
||||
@Excel(name = "客户证件号")
|
||||
private String custIdc;
|
||||
@Excel(name = "客户内码")
|
||||
private String custIsn;
|
||||
@Excel(name = "活期存款余额")
|
||||
private String curBalD;
|
||||
@Excel(name = "贷款余额")
|
||||
private String balLoan;
|
||||
@Excel(name = "贷款年日均")
|
||||
private String loanAve;
|
||||
@Excel(name = "是否授信")
|
||||
private String isSx;
|
||||
@Excel(name = "是否用信")
|
||||
private String isYx;
|
||||
@Excel(name = "授信金额")
|
||||
private String sxBal;
|
||||
@Excel(name = "是否合同签约")
|
||||
private String isYxht;
|
||||
@Excel(name = "是否持有信用卡")
|
||||
private String isXyk;
|
||||
@Excel(name = "是否开通丰收互联")
|
||||
private String fshl;
|
||||
@Excel(name = "是否办理收单")
|
||||
private String isSd;
|
||||
@Excel(name = "是否代扣电费")
|
||||
private String dian;
|
||||
@Excel(name = "是否代扣水费")
|
||||
private String shui;
|
||||
@Excel(name = "是否代扣税费")
|
||||
private String tax;
|
||||
@Excel(name = "开户数")
|
||||
private String openNum;
|
||||
@Excel(name = "存款余额")
|
||||
private String depBal;
|
||||
@Excel(name = "财富余额")
|
||||
private String finBal;
|
||||
@Excel(name = "是否个人核心客户")
|
||||
private String isGrhx;
|
||||
@Excel(name = "是否财富有效客户")
|
||||
private String isCfyx;
|
||||
@Excel(name = "是否有效社保卡客户")
|
||||
private String isYxsbk;
|
||||
@Excel(name = "是否有效社保卡新增")
|
||||
private String is2to3Sbk;
|
||||
@Excel(name = "是否养老金迁移至社保卡")
|
||||
private String isYljToSbk;
|
||||
@Excel(name = "是否核心收单")
|
||||
private String isHxsd;
|
||||
private String regionCode;
|
||||
private String opsDept;
|
||||
private String custType;
|
||||
@Excel(name = "近365天有无走访")
|
||||
private String is365zf;
|
||||
@Excel(name = "近180天有无走访")
|
||||
private String is180zf;
|
||||
@Excel(name = "近90天有无走访")
|
||||
private String is90zf;
|
||||
@Excel(name = "近30天有无走访")
|
||||
private String is30zf;
|
||||
private String dt;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.ruoyi.ibs.grid.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 地理网格选择VO - 专用于客群创建时的网格选择
|
||||
* 只包含必要字段,提升查询效率
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class RegionGridGroupVO implements Serializable {
|
||||
|
||||
/**
|
||||
* 网格主键
|
||||
*/
|
||||
@ApiModelProperty(value = "网格主键")
|
||||
private Long gridId;
|
||||
|
||||
/**
|
||||
* 网格名称
|
||||
*/
|
||||
@ApiModelProperty(value = "网格名称")
|
||||
private String gridName;
|
||||
}
|
||||
@@ -2,8 +2,10 @@ package com.ruoyi.ibs.grid.mapper;
|
||||
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountGongsi;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshouNew825;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountGongsi;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshouNew825;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -12,10 +14,12 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface GridCountMapper {
|
||||
List<GridCmpmCountLingshou> selectLsCountList(HashMap<String, Object> paramMap);
|
||||
List<GridCmpmCountLingshouNew825> selectLsCountListNew825(HashMap<String, Object> paramMap);
|
||||
|
||||
List<GridCmpmCountGongsi> selectGsCountList(HashMap<String, Object> paramMap);
|
||||
|
||||
List<GridCustCountLingshou> selectLsCustList(HashMap<String, Object> paramMap);
|
||||
List<GridCustCountLingshouNew825> selectLsCustListNew825(HashMap<String, Object> paramMap);
|
||||
|
||||
List<GridCustCountGongsi> selectGsCustList(HashMap<String, Object> paramMap);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,13 @@ public interface RegionCustUserMapper extends BaseMapper<RegionCustUser> {
|
||||
|
||||
Long countCustInSecGrid(@Param("gridId") Long gridId, @Param("custType") String custType);
|
||||
|
||||
/**
|
||||
* 根据网格ID列表查询所有客户(用于异步导入客群,直接根据gridIds查询无需区分等级)
|
||||
* @param gridIds 网格ID列表
|
||||
* @param headId 总行机构号前三位(用于拼接动态表名)
|
||||
*/
|
||||
List<RegionCustUser> selectAllCustByGridIds(@Param("gridIds") List<Long> gridIds, @Param("headId") String headId);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.ruoyi.ibs.grid.domain.dto.GridCustListDTO;
|
||||
import com.ruoyi.ibs.grid.domain.dto.RegionGridListDTO;
|
||||
import com.ruoyi.ibs.grid.domain.entity.RegionGrid;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridCustVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridGroupVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridListVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionUnbindVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
@@ -69,4 +70,10 @@ public interface RegionGridMapper extends BaseMapper<RegionGrid> {
|
||||
|
||||
List<Long> getSecGridIdByTopGridId(@Param("gridId") Long gridId);
|
||||
|
||||
/**
|
||||
* 查询地理网格列表(简化版)- 专用于客群创建
|
||||
* 只返回gridId和gridName,避免N+1查询问题
|
||||
*/
|
||||
List<RegionGridGroupVO> getRegionGridListForGroup(RegionGridListDTO regionGridListDTO);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,18 +2,22 @@ package com.ruoyi.ibs.grid.service;
|
||||
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountGongsi;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshouNew825;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountGongsi;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshouNew825;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public interface GridCountService {
|
||||
List<GridCmpmCountLingshou> selectLsCountList(String town,String village,String dt);
|
||||
List<GridCmpmCountLingshouNew825> selectLsCountListNew825(String town, String village, String dt);
|
||||
|
||||
List<GridCmpmCountGongsi> selectGsCountList(String town, String village,String dt);
|
||||
|
||||
List<GridCustCountLingshou> selectLsCustList(String regionCode, String custName, String custIdc,String dt);
|
||||
List<GridCustCountLingshouNew825> selectLsCustListNew825(String regionCode, String custName, String custIdc, String dt);
|
||||
|
||||
List<GridCustCountGongsi> selectGsCustList(String regionCode, String custName, String socialCreditCode,String dt);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.ruoyi.ibs.grid.domain.entity.RegionCustUser;
|
||||
import com.ruoyi.ibs.grid.domain.entity.RegionGrid;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionCustUserVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridCustVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridGroupVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridListVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionUnbindVo;
|
||||
|
||||
@@ -35,4 +36,21 @@ public interface RegionGridListService {
|
||||
|
||||
List<RegionGridListVO> getSecGridListByManager(RegionGridListDTO regionGridListDTO);
|
||||
|
||||
/**
|
||||
* 根据网格ID列表批量查询所有客户(用于导入客群,优化版)
|
||||
* @param gridIds 网格ID列表
|
||||
* @param headId 总行机构号前三位(用于拼接动态表名)
|
||||
* @return 客户列表(去重)
|
||||
*/
|
||||
List<RegionCustUser> selectAllCustByGridIds(List<Long> gridIds, String headId);
|
||||
|
||||
/**
|
||||
* 查询地理网格列表(简化版)- 专用于客群创建
|
||||
* 只返回gridId和gridName,避免N+1查询问题
|
||||
* @param regionGridListDTO 查询条件
|
||||
* @return 网格列表(仅包含ID和名称)
|
||||
*/
|
||||
List<RegionGridGroupVO> getRegionGridListForGroup(RegionGridListDTO regionGridListDTO);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ package com.ruoyi.ibs.grid.service.impl;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountGongsi;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshouNew825;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountGongsi;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshou;
|
||||
import com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshouNew825;
|
||||
import com.ruoyi.ibs.grid.mapper.GridCountMapper;
|
||||
import com.ruoyi.ibs.grid.service.GridCountService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -21,6 +23,15 @@ public class GridCountServiceimpl implements GridCountService {
|
||||
|
||||
@Override
|
||||
public List<GridCmpmCountLingshou> selectLsCountList(String town,String village,String dt) {
|
||||
return mapper.selectLsCountList(buildLsCountParams(town, village, dt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GridCmpmCountLingshouNew825> selectLsCountListNew825(String town, String village, String dt) {
|
||||
return mapper.selectLsCountListNew825(buildLsCountParams(town, village, dt));
|
||||
}
|
||||
|
||||
private HashMap<String, Object> buildLsCountParams(String town, String village, String dt) {
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
if(SecurityUtils.userRole().equals("branch")){
|
||||
paramMap.put("isBranch",true);
|
||||
@@ -36,7 +47,7 @@ public class GridCountServiceimpl implements GridCountService {
|
||||
paramMap.put("town",town);
|
||||
paramMap.put("village",village);
|
||||
paramMap.put("dt",dt);
|
||||
return mapper.selectLsCountList(paramMap);
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,6 +76,15 @@ public class GridCountServiceimpl implements GridCountService {
|
||||
|
||||
@Override
|
||||
public List<GridCustCountLingshou> selectLsCustList(String regionCode, String custName, String custIdc,String dt) {
|
||||
return mapper.selectLsCustList(buildLsCustParams(regionCode, custName, custIdc, dt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GridCustCountLingshouNew825> selectLsCustListNew825(String regionCode, String custName, String custIdc, String dt) {
|
||||
return mapper.selectLsCustListNew825(buildLsCustParams(regionCode, custName, custIdc, dt));
|
||||
}
|
||||
|
||||
private HashMap<String, Object> buildLsCustParams(String regionCode, String custName, String custIdc, String dt) {
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("deptId",SecurityUtils.getDeptId());
|
||||
paramMap.put("userName",SecurityUtils.getUsername());
|
||||
@@ -72,7 +92,7 @@ public class GridCountServiceimpl implements GridCountService {
|
||||
paramMap.put("custName",custName);
|
||||
paramMap.put("custIdc",custIdc);
|
||||
paramMap.put("dt",dt);
|
||||
return mapper.selectLsCustList(paramMap);
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.ibs.grid.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.bean.BeanUtils;
|
||||
import com.ruoyi.ibs.draw.domain.dto.grid.CustCountDTO;
|
||||
@@ -11,6 +12,7 @@ import com.ruoyi.ibs.grid.domain.dto.UnbindDTO;
|
||||
import com.ruoyi.ibs.grid.domain.entity.*;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionCustUserVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridCustVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridGroupVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionGridListVO;
|
||||
import com.ruoyi.ibs.grid.domain.vo.RegionUnbindVo;
|
||||
import com.ruoyi.ibs.grid.mapper.*;
|
||||
@@ -429,4 +431,35 @@ public class RegionGridListServiceImpl implements RegionGridListService {
|
||||
|
||||
return secGridListByManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据网格ID列表批量查询所有客户(用于导入客群,优化版)
|
||||
* @param gridIds 网格ID列表
|
||||
* @return 客户列表(去重)
|
||||
*/
|
||||
@Override
|
||||
public List<RegionCustUser> selectAllCustByGridIds(List<Long> gridIds, String headId) {
|
||||
return regionCustUserMapper.selectAllCustByGridIds(gridIds, headId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询地理网格列表(简化版)- 专用于客群创建
|
||||
* 只返回gridId和gridName,避免N+1查询问题
|
||||
* @param regionGridListDTO 查询条件
|
||||
* @return 网格列表(仅包含ID和名称)
|
||||
*/
|
||||
@Override
|
||||
public List<RegionGridGroupVO> getRegionGridListForGroup(RegionGridListDTO regionGridListDTO) {
|
||||
// 设置当前用户部门ID用于权限过滤
|
||||
regionGridListDTO.setDeptId(SecurityUtils.getDeptId());
|
||||
|
||||
// 如果是总行用户,设置归属部室
|
||||
if (SecurityUtils.isHead()) {
|
||||
regionGridListDTO.setOpsDept(SecurityUtils.getOpsDept());
|
||||
}
|
||||
|
||||
// 直接查询,一次SQL完成,无N+1问题
|
||||
return regionGridMapper.getRegionGridListForGroup(regionGridListDTO);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -312,6 +312,13 @@ public class SysCampaignController extends BaseController {
|
||||
.stream().collect(HashMap::new, (m, v) -> m.put(v.getUuid(),v.getModelName()), HashMap::putAll)));
|
||||
}
|
||||
|
||||
@PostMapping("/updateVisitInfoFeedback")
|
||||
@ApiOperation("更新PAD走访反馈")
|
||||
@Log(title ="pad走访记录-更新走访反馈", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult updateVisitInfoFeedback(@RequestBody VisitInfoFeedbackUpdateDTO updateDTO) {
|
||||
return toAjax(sysCampaignService.updateVisitInfoFeedback(updateDTO));
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
@ApiOperation("根据campaignId删除任务")
|
||||
@Log(title = "走访-根据campaignId删除任务")
|
||||
|
||||
@@ -41,6 +41,14 @@ public class CustInfoBusinessVo {
|
||||
@ApiModelProperty(value = "手动打标")
|
||||
private List<TreeNode> tagManual;
|
||||
|
||||
/** 九维画像分数 */
|
||||
@ApiModelProperty(value = "九维画像分数")
|
||||
private Ent9vPortraitOrc ent9vPortrait;
|
||||
|
||||
/** 九维画像详细信息 */
|
||||
@ApiModelProperty(value = "九维画像详细信息")
|
||||
private NineVFinalInfoOrc nineVFinalInfo;
|
||||
|
||||
public List<TreeNode> getTagManual() {
|
||||
return tagManual;
|
||||
}
|
||||
@@ -187,4 +195,20 @@ public class CustInfoBusinessVo {
|
||||
public void setTabEnmuVos(List<TreeNode> tabEnmuVos) {
|
||||
this.tabEnmuVos = tabEnmuVos;
|
||||
}
|
||||
|
||||
public Ent9vPortraitOrc getEnt9vPortrait() {
|
||||
return ent9vPortrait;
|
||||
}
|
||||
|
||||
public void setEnt9vPortrait(Ent9vPortraitOrc ent9vPortrait) {
|
||||
this.ent9vPortrait = ent9vPortrait;
|
||||
}
|
||||
|
||||
public NineVFinalInfoOrc getNineVFinalInfo() {
|
||||
return nineVFinalInfo;
|
||||
}
|
||||
|
||||
public void setNineVFinalInfo(NineVFinalInfoOrc nineVFinalInfo) {
|
||||
this.nineVFinalInfo = nineVFinalInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.ruoyi.ibs.list.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 企业九维画像分数对象 ent_9v_portrait_orc_825
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-03-18
|
||||
*/
|
||||
@Data
|
||||
@TableName("ent_9v_portrait_orc_825")
|
||||
public class Ent9vPortraitOrc implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 统一社会信用代码 */
|
||||
private String uniscid;
|
||||
|
||||
/** 客户内码 */
|
||||
@TableField("cst_id")
|
||||
private String cstId;
|
||||
|
||||
/** 机构号 */
|
||||
@TableField("org_no")
|
||||
private String orgNo;
|
||||
|
||||
/** score_1合规经营 */
|
||||
@TableField("score_1")
|
||||
private BigDecimal score1;
|
||||
|
||||
/** score_2风险准入 */
|
||||
@TableField("score_2")
|
||||
private BigDecimal score2;
|
||||
|
||||
/** score_3高管信用评价 */
|
||||
@TableField("score_3")
|
||||
private String score3;
|
||||
|
||||
/** score_4股东信用评价 */
|
||||
@TableField("score_4")
|
||||
private BigDecimal score4;
|
||||
|
||||
/** score_5社会贡献度 */
|
||||
@TableField("score_5")
|
||||
private BigDecimal score5;
|
||||
|
||||
/** score_6稳定经营 */
|
||||
@TableField("score_6")
|
||||
private BigDecimal score6;
|
||||
|
||||
/** score_7经营能力 */
|
||||
@TableField("score_7")
|
||||
private BigDecimal score7;
|
||||
|
||||
/** score_8偿债能力 */
|
||||
@TableField("score_8")
|
||||
private BigDecimal score8;
|
||||
|
||||
/** score_9潜在代偿资源 */
|
||||
@TableField("score_9")
|
||||
private BigDecimal score9;
|
||||
|
||||
/** 九维总分 */
|
||||
@TableField("score_all")
|
||||
private BigDecimal scoreAll;
|
||||
|
||||
/** 九维总分排名 */
|
||||
@TableField("score_all_rank")
|
||||
private BigDecimal scoreAllRank;
|
||||
|
||||
/** 会计日期 */
|
||||
@TableField("dat_dt")
|
||||
private String datDt;
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
package com.ruoyi.ibs.list.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 企业九维画像详细信息对象 9v_final_info_orc_825
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-03-18
|
||||
*/
|
||||
@Data
|
||||
@TableName("9v_final_info_orc_825")
|
||||
public class NineVFinalInfoOrc implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 统一社会信用代码 */
|
||||
private String uniscid;
|
||||
|
||||
/** 机构号 */
|
||||
@TableField("org_no")
|
||||
private String orgNo;
|
||||
|
||||
/** 一、企业合规经营模块 */
|
||||
|
||||
/** 是否存在经营异常名录信息 */
|
||||
@TableField("score_1_1")
|
||||
private String score11;
|
||||
|
||||
/** 是否存在严重违法失信企业名单信息 */
|
||||
@TableField("score_1_2")
|
||||
private String score12;
|
||||
|
||||
/** 企业环境行为信仰登记是否为"E"或D */
|
||||
@TableField("score_1_3")
|
||||
private String score13;
|
||||
|
||||
/** 是否存在税务重大税收违法黑名单信息 */
|
||||
@TableField("score_1_4")
|
||||
private String score14;
|
||||
|
||||
/** 是否存在拖欠工资黑名单 */
|
||||
@TableField("score_1_5")
|
||||
private String score15;
|
||||
|
||||
/** 是否存在工商吊销企业信息 */
|
||||
@TableField("score_1_6")
|
||||
private String score16;
|
||||
|
||||
/** 二、企业风险准入模块 */
|
||||
|
||||
/** 是否存在注销企业信息 */
|
||||
@TableField("score_2_1")
|
||||
private String score21;
|
||||
|
||||
/** 是否存在执行案件信息 */
|
||||
@TableField("score_2_2")
|
||||
private String score22;
|
||||
|
||||
/** 是否存在查封信息 */
|
||||
@TableField("score_2_3")
|
||||
private String score23;
|
||||
|
||||
/** 是否存在单位未履行生效裁判信息 */
|
||||
@TableField("score_2_4")
|
||||
private String score24;
|
||||
|
||||
/** 是否存在企业破产清算信息 */
|
||||
@TableField("score_2_5")
|
||||
private String score25;
|
||||
|
||||
/** 是否失信被执行人 */
|
||||
@TableField("score_2_6")
|
||||
private String score26;
|
||||
|
||||
/** 是否为诉讼案件被告 */
|
||||
@TableField("score_2_7")
|
||||
private String score27;
|
||||
|
||||
/** 三、高管信用评价模块 */
|
||||
|
||||
/** 是否存在查封信息(score_3) */
|
||||
@TableField("score_3_1")
|
||||
private String score31;
|
||||
|
||||
/** 是否存在执行案件信息(score_3) */
|
||||
@TableField("score_3_2")
|
||||
private String score32;
|
||||
|
||||
/** 是否存在个人未履行生效裁判信息 */
|
||||
@TableField("score_3_3")
|
||||
private String score33;
|
||||
|
||||
/** 是否存在拖欠工资黑名单(score_3) */
|
||||
@TableField("score_3_4")
|
||||
private String score34;
|
||||
|
||||
/** 是否失信被执行人(score_3) */
|
||||
@TableField("score_3_5")
|
||||
private String score35;
|
||||
|
||||
/** 是否存在刑事案件被告人生效判决信息 */
|
||||
@TableField("score_3_6")
|
||||
private String score36;
|
||||
|
||||
/** 是否为诉讼案件被告(score_3) */
|
||||
@TableField("score_3_7")
|
||||
private String score37;
|
||||
|
||||
/** 四、股东信用评价模块 */
|
||||
|
||||
/** 是否存在查封信息(score_4) */
|
||||
@TableField("score_4_1")
|
||||
private String score41;
|
||||
|
||||
/** 是否存在执行案件信息(score_4) */
|
||||
@TableField("score_4_2")
|
||||
private String score42;
|
||||
|
||||
/** 是否存在个人未履行生效裁判信息(score_4) */
|
||||
@TableField("score_4_3")
|
||||
private String score43;
|
||||
|
||||
/** 是否存在拖欠工资黑名单(score_4) */
|
||||
@TableField("score_4_4")
|
||||
private String score44;
|
||||
|
||||
/** 是否失信被执行人(score_4) */
|
||||
@TableField("score_4_5")
|
||||
private String score45;
|
||||
|
||||
/** 是否存在刑事案件被告人生效判决信息(score_4) */
|
||||
@TableField("score_4_6")
|
||||
private String score46;
|
||||
|
||||
/** 是否为诉讼案件被告(score_4) */
|
||||
@TableField("score_4_7")
|
||||
private String score47;
|
||||
|
||||
/** 是否存在企业未履行生效裁判信息 */
|
||||
@TableField("score_4_8")
|
||||
private String score48;
|
||||
|
||||
/** 五、企业社会贡献度模块 */
|
||||
|
||||
/** 前12个月纳税金额 */
|
||||
@TableField("score_5_1")
|
||||
private String score51;
|
||||
|
||||
/** 纳税等级 */
|
||||
@TableField("score_5_2")
|
||||
private String score52;
|
||||
|
||||
/** 缴纳社保人数 */
|
||||
@TableField("score_5_3")
|
||||
private String score53;
|
||||
|
||||
/** 公积金缴纳人数 */
|
||||
@TableField("score_5_4")
|
||||
private String score54;
|
||||
|
||||
/** 是否为出口退税生产清单企业 */
|
||||
@TableField("score_5_5")
|
||||
private String score55;
|
||||
|
||||
/** 六、企业稳定经营模块 */
|
||||
|
||||
/** 市场主体经营年限 */
|
||||
@TableField("score_6_1")
|
||||
private String score61;
|
||||
|
||||
/** 股东(或发起人)或投资人信息认缴出资人数 */
|
||||
@TableField("score_6_2")
|
||||
private String score62;
|
||||
|
||||
/** 最大股东持股占比 */
|
||||
@TableField("score_6_3")
|
||||
private String score63;
|
||||
|
||||
/** 近三年法定代表人变更次数 */
|
||||
@TableField("score_6_4")
|
||||
private String score64;
|
||||
|
||||
/** 近三年股东变更次数 */
|
||||
@TableField("score_6_5")
|
||||
private String score65;
|
||||
|
||||
/** 近三年经营范围变更次数 */
|
||||
@TableField("score_6_6")
|
||||
private String score66;
|
||||
|
||||
/** 近三年经营地址变更次数 */
|
||||
@TableField("score_6_7")
|
||||
private String score67;
|
||||
|
||||
/** 近三年缴税年数 */
|
||||
@TableField("score_6_8")
|
||||
private String score68;
|
||||
|
||||
/** 法人户籍 */
|
||||
@TableField("score_6_9")
|
||||
private String score69;
|
||||
|
||||
/** 法人婚姻状况 */
|
||||
@TableField("score_6_10")
|
||||
private String score610;
|
||||
|
||||
/** 七、企业经营能力模块 */
|
||||
|
||||
/** 上年增值税金额 */
|
||||
@TableField("score_7_1")
|
||||
private String score71;
|
||||
|
||||
/** 今年增值税同比变动 */
|
||||
@TableField("score_7_2")
|
||||
private String score72;
|
||||
|
||||
/** 上年企业所得税金额 */
|
||||
@TableField("score_7_3")
|
||||
private String score73;
|
||||
|
||||
/** 今年所得税同比变动 */
|
||||
@TableField("score_7_4")
|
||||
private String score74;
|
||||
|
||||
/** 缴纳社保人数同比变动 */
|
||||
@TableField("score_7_5")
|
||||
private String score75;
|
||||
|
||||
/** 公积金缴纳人数同比变动 */
|
||||
@TableField("score_7_6")
|
||||
private String score76;
|
||||
|
||||
/** 当年纳税金额同比变动 */
|
||||
@TableField("score_7_7")
|
||||
private String score77;
|
||||
|
||||
/** 上年出口退税金额 */
|
||||
@TableField("score_7_8")
|
||||
private String score78;
|
||||
|
||||
/** 八、企业偿债能力模块 */
|
||||
|
||||
/** 房产套数 */
|
||||
@TableField("score_8_1")
|
||||
private String score81;
|
||||
|
||||
/** 房产面积 */
|
||||
@TableField("score_8_2")
|
||||
private String score82;
|
||||
|
||||
/** 未抵押房产套数 */
|
||||
@TableField("score_8_3")
|
||||
private String score83;
|
||||
|
||||
/** 未抵押房产面积 */
|
||||
@TableField("score_8_4")
|
||||
private String score84;
|
||||
|
||||
/** 已抵押房产被担保债权数额 */
|
||||
@TableField("score_8_5")
|
||||
private String score85;
|
||||
|
||||
/** 企业车产金额 */
|
||||
@TableField("score_8_6")
|
||||
private String score86;
|
||||
|
||||
/** 九、潜在代偿资源模块 */
|
||||
|
||||
/** 法人及股东房产面积合计 */
|
||||
@TableField("score_9_1")
|
||||
private String score91;
|
||||
|
||||
/** 法人及股东房产套数合计 */
|
||||
@TableField("score_9_2")
|
||||
private String score92;
|
||||
|
||||
/** 法人及股东未抵押房产套数合计 */
|
||||
@TableField("score_9_3")
|
||||
private String score93;
|
||||
|
||||
/** 法人及股东未抵押房产面积 */
|
||||
@TableField("score_9_4")
|
||||
private String score94;
|
||||
|
||||
/** 法人及股东已抵押房产被担保债权数额合计 */
|
||||
@TableField("score_9_5")
|
||||
private String score95;
|
||||
|
||||
/** 法人代表车产金额 */
|
||||
@TableField("score_9_6")
|
||||
private String score96;
|
||||
|
||||
/** 十、企业环境信用模块 */
|
||||
|
||||
/** 生态信用扣分 */
|
||||
@TableField("score_b015")
|
||||
private String scoreB015;
|
||||
|
||||
/** 列入环境失信黑名单时间 */
|
||||
@TableField("score_b016_time")
|
||||
private String scoreB016Time;
|
||||
|
||||
/** 列入环境失信黑名单原因 */
|
||||
@TableField("score_b016_reason")
|
||||
private String scoreB016Reason;
|
||||
|
||||
/** 环境行为信用评价等级 */
|
||||
@TableField("score_a020")
|
||||
private String scoreA020;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ruoyi.ibs.list.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class VisitFeedbackItemDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(value = "反馈类型")
|
||||
private String feedbackType;
|
||||
|
||||
@ApiModelProperty(value = "反馈产品列表")
|
||||
private List<String> products;
|
||||
}
|
||||
@@ -117,4 +117,40 @@ public class VisitInfo {
|
||||
@ApiModelProperty(value = "走访备注")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "互动地址")
|
||||
private String interAddr;
|
||||
|
||||
@ApiModelProperty(value = "协同员工名称")
|
||||
private String colStafName;
|
||||
|
||||
@ApiModelProperty(value = "后续备注")
|
||||
private String laterNote;
|
||||
|
||||
@ApiModelProperty(value = "意向产品值")
|
||||
private String intentionProductValue;
|
||||
|
||||
@ApiModelProperty(value = "反馈状态")
|
||||
private String feedbackStatus;
|
||||
|
||||
@ApiModelProperty(value = "走访来源")
|
||||
private String sourceOfInterview;
|
||||
|
||||
@ApiModelProperty(value = "文件名")
|
||||
private String filename;
|
||||
|
||||
@ApiModelProperty(value = "外呼状态")
|
||||
private String outCallStatus;
|
||||
|
||||
@ApiModelProperty(value = "外呼意向")
|
||||
private String outCallIntention;
|
||||
|
||||
@ApiModelProperty(value = "来源")
|
||||
private String source;
|
||||
|
||||
@ApiModelProperty(value = "分析值")
|
||||
private String analysisValue;
|
||||
|
||||
@ApiModelProperty(value = "设备")
|
||||
private String facility;
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ public class VisitInfoDTO {
|
||||
@ApiModelProperty(value = "柜员名称")
|
||||
private String visName;
|
||||
|
||||
/** 柜员号 */
|
||||
@ApiModelProperty(value = "柜员号")
|
||||
private String visId;
|
||||
|
||||
/** 走访时间 */
|
||||
@ApiModelProperty(value = "走访时间")
|
||||
private String visTime;
|
||||
@@ -29,6 +33,10 @@ public class VisitInfoDTO {
|
||||
@ApiModelProperty(value = "客户类型 0个人,1商户,2企业")
|
||||
private String custType;
|
||||
|
||||
/** 活动ID */
|
||||
@ApiModelProperty(value = "活动ID")
|
||||
private String campaignId;
|
||||
|
||||
/** 异常走访标签(筛选是否异常) */
|
||||
@ApiModelProperty(value = "异常走访标签 0正常 1走访频率异常 2走访持续时长异常 3签退时间异常")
|
||||
private String abnormalVisitTag;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.ruoyi.ibs.list.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class VisitInfoFeedbackUpdateDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(value = "走访记录ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "走访渠道")
|
||||
private String source;
|
||||
|
||||
@ApiModelProperty(value = "走访备注")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "客户意愿结构化数据")
|
||||
private List<VisitFeedbackItemDTO> feedbackItems;
|
||||
|
||||
@ApiModelProperty(value = "客户意愿拼接值")
|
||||
private String intentionProductValue;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String userRole;
|
||||
|
||||
private String deptId;
|
||||
}
|
||||
@@ -128,4 +128,40 @@ public class VisitInfoVO {
|
||||
@ApiModelProperty(value = "走访结果")
|
||||
private String interRes;
|
||||
|
||||
@ApiModelProperty(value = "实地拜访地址")
|
||||
private String interAddr;
|
||||
|
||||
@ApiModelProperty(value = "协同走访客户经理")
|
||||
private String colStafName;
|
||||
|
||||
@ApiModelProperty(value = "事后备注")
|
||||
private String laterNote;
|
||||
|
||||
@ApiModelProperty(value = "走访反馈")
|
||||
private String intentionProductValue;
|
||||
|
||||
@ApiModelProperty(value = "反馈状态")
|
||||
private String feedbackStatus;
|
||||
|
||||
@ApiModelProperty(value = "走访来源")
|
||||
private String sourceOfInterview;
|
||||
|
||||
@ApiModelProperty(value = "批量导入文件名")
|
||||
private String filename;
|
||||
|
||||
@ApiModelProperty(value = "外呼状态")
|
||||
private String outCallStatus;
|
||||
|
||||
@ApiModelProperty(value = "客户意愿")
|
||||
private String outCallIntention;
|
||||
|
||||
@ApiModelProperty(value = "走访来源:1null:pad 2:企业微信 3:pc")
|
||||
private String source;
|
||||
|
||||
@ApiModelProperty(value = "nlp模型提取")
|
||||
private String analysisValue;
|
||||
|
||||
@ApiModelProperty(value = "预授信额度")
|
||||
private String facility;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.ibs.list.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.ibs.list.domain.Ent9vPortraitOrc;
|
||||
|
||||
/**
|
||||
* 企业九维画像分数Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-03-18
|
||||
*/
|
||||
public interface Ent9vPortraitOrcMapper extends BaseMapper<Ent9vPortraitOrc> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.ibs.list.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.ibs.list.domain.NineVFinalInfoOrc;
|
||||
|
||||
/**
|
||||
* 企业九维画像详细信息Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-03-18
|
||||
*/
|
||||
public interface NineVFinalInfoOrcMapper extends BaseMapper<NineVFinalInfoOrc> {
|
||||
}
|
||||
@@ -156,6 +156,10 @@ public interface SysCampaignMapper extends BaseMapper<SysCampaign> {
|
||||
|
||||
List<VisitInfoVO> selectVisitInfoList(VisitInfoDTO visitInfoDTO);
|
||||
|
||||
List<VisitInfoVO> selectVisitInfoList875(VisitInfoDTO visitInfoDTO);
|
||||
|
||||
int updateVisitInfoFeedback(VisitInfoFeedbackUpdateDTO updateDTO);
|
||||
|
||||
@Update("UPDATE sys_campaign SET del_flag = '2' where campaign_id = #{campaignId}")
|
||||
int deleteSysCampaignByCampaignId(@Param("campaignId") String campaignId);
|
||||
|
||||
|
||||
@@ -115,5 +115,7 @@ public interface ISysCampaignService {
|
||||
|
||||
public List<VisitInfoVO> selectVisitInfoVoList(VisitInfoDTO visitInfoDTO);
|
||||
|
||||
int updateVisitInfoFeedback(VisitInfoFeedbackUpdateDTO updateDTO);
|
||||
|
||||
public int deleteSysCampaign(String campaignId);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ import com.ruoyi.ibs.grid.util.CustExcelUtil;
|
||||
import com.ruoyi.ibs.list.domain.*;
|
||||
import com.ruoyi.ibs.list.mapper.CorporateShareholderMapper;
|
||||
import com.ruoyi.ibs.list.mapper.CustInfoRetailMapper;
|
||||
import com.ruoyi.ibs.list.mapper.Ent9vPortraitOrcMapper;
|
||||
import com.ruoyi.ibs.list.mapper.FamilyMembersMapper;
|
||||
import com.ruoyi.ibs.list.mapper.NineVFinalInfoOrcMapper;
|
||||
import com.ruoyi.ibs.list.mapper.SignedProductsMapper;
|
||||
import com.ruoyi.ibs.list.service.ICustInfoBusinessService;
|
||||
import com.ruoyi.system.mapper.SysIndustryMapper;
|
||||
@@ -75,6 +77,12 @@ public class CustInfoBusinessServiceImpl implements ICustInfoBusinessService
|
||||
@Autowired
|
||||
private FamilyMembersMapper familyMembersMapper;
|
||||
|
||||
@Autowired
|
||||
private Ent9vPortraitOrcMapper ent9vPortraitOrcMapper;
|
||||
|
||||
@Autowired
|
||||
private NineVFinalInfoOrcMapper nineVFinalInfoOrcMapper;
|
||||
|
||||
@Autowired
|
||||
private CustMapMapper custMapMapper;
|
||||
|
||||
@@ -138,6 +146,17 @@ public class CustInfoBusinessServiceImpl implements ICustInfoBusinessService
|
||||
//查询手动标签列表
|
||||
List<CustManualTagVO> tagCreateVos = familyMembersMapper.selectManualTag(params);
|
||||
custInfoBusinessVo.setTagManual(TreeNode.convertToTreeByParentId(tagCreateVos));
|
||||
|
||||
// 仅当登录机构为825时,查询九维画像数据
|
||||
if ("825".equals(getHeadId())) {
|
||||
LambdaQueryWrapper<Ent9vPortraitOrc> portraitWrapper = new LambdaQueryWrapper<>();
|
||||
portraitWrapper.eq(Ent9vPortraitOrc::getUniscid, custInfoBusiness.getSocialCreditCode());
|
||||
custInfoBusinessVo.setEnt9vPortrait(ent9vPortraitOrcMapper.selectOne(portraitWrapper));
|
||||
|
||||
LambdaQueryWrapper<NineVFinalInfoOrc> finalInfoWrapper = new LambdaQueryWrapper<>();
|
||||
finalInfoWrapper.eq(NineVFinalInfoOrc::getUniscid, custInfoBusiness.getSocialCreditCode());
|
||||
custInfoBusinessVo.setNineVFinalInfo(nineVFinalInfoOrcMapper.selectOne(finalInfoWrapper));
|
||||
}
|
||||
}
|
||||
return custInfoBusinessVo;
|
||||
}
|
||||
|
||||
@@ -2175,9 +2175,31 @@ public class SysCampaignServiceImpl implements ISysCampaignService
|
||||
visitInfoDTO.setUserName(SecurityUtils.getUsername());
|
||||
visitInfoDTO.setUserRole(SecurityUtils.userRole());
|
||||
visitInfoDTO.setDeptId(String.valueOf(SecurityUtils.getDeptId()));
|
||||
if ("875".equals(SecurityUtils.getHeadId())) {
|
||||
return sysCampaignMapper.selectVisitInfoList875(visitInfoDTO);
|
||||
}
|
||||
return sysCampaignMapper.selectVisitInfoList(visitInfoDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateVisitInfoFeedback(VisitInfoFeedbackUpdateDTO updateDTO) {
|
||||
if (updateDTO == null || updateDTO.getId() == null) {
|
||||
throw new ServiceException("走访记录ID不能为空");
|
||||
}
|
||||
String deptId = String.valueOf(SecurityUtils.getDeptId());
|
||||
if (!deptId.startsWith("875")) {
|
||||
throw new ServiceException("当前机构无权维护PAD走访反馈");
|
||||
}
|
||||
updateDTO.setUserName(SecurityUtils.getUsername());
|
||||
updateDTO.setUserRole(SecurityUtils.userRole());
|
||||
updateDTO.setDeptId(deptId);
|
||||
updateDTO.setSource(StringUtils.trimToNull(updateDTO.getSource()));
|
||||
updateDTO.setRemark(StringUtils.trimToNull(updateDTO.getRemark()));
|
||||
updateDTO.setIntentionProductValue(buildIntentionProductValue(updateDTO.getFeedbackItems()));
|
||||
int rows = sysCampaignMapper.updateVisitInfoFeedback(updateDTO);
|
||||
return rows;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteSysCampaign(String campaignId) {
|
||||
SysCampaign sysCampaign = sysCampaignMapper.selectSysCampaignByCampaignId(campaignId);
|
||||
@@ -2186,4 +2208,28 @@ public class SysCampaignServiceImpl implements ISysCampaignService
|
||||
}
|
||||
return sysCampaignMapper.deleteSysCampaignByCampaignId(campaignId);
|
||||
}
|
||||
private String buildIntentionProductValue(List<VisitFeedbackItemDTO> feedbackItems) {
|
||||
if (feedbackItems == null || feedbackItems.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String joinedValue = feedbackItems.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(item -> {
|
||||
String feedbackType = StringUtils.trimToNull(item.getFeedbackType());
|
||||
List<String> products = Optional.ofNullable(item.getProducts())
|
||||
.orElse(Collections.emptyList())
|
||||
.stream()
|
||||
.map(StringUtils::trimToNull)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (feedbackType == null || products.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return feedbackType + ":" + String.join(",", products);
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.joining(";"));
|
||||
return StringUtils.trimToNull(joinedValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package com.ruoyi.ibs.task.controller;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||
import com.ruoyi.ibs.task.domain.dto.AlterForwardRequest;
|
||||
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
||||
import com.ruoyi.ibs.task.domain.entity.Alter;
|
||||
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
||||
@@ -95,12 +98,37 @@ public class WorkRecordController extends BaseController {
|
||||
@GetMapping("/alter/allList")
|
||||
@Log(title = "工作台-查询预警信息")
|
||||
@ApiOperation("查询所有预警信息")
|
||||
public TableDataPageInfo<AlterVO> allAlterList(String status, String alterType) {
|
||||
public TableDataPageInfo<AlterVO> allAlterList(String status, String alterType, String forwardFlag) {
|
||||
Page<Object> page = startPage();
|
||||
List<AlterVO> list = workRecordService.getAllAlterList(status, alterType);
|
||||
List<AlterVO> list = workRecordService.getAllAlterList(status, alterType, forwardFlag);
|
||||
return getDataTable(list, page);
|
||||
}
|
||||
|
||||
@GetMapping("/alter/forward/meta")
|
||||
@Log(title = "工作台-查询预警转发元数据")
|
||||
@ApiOperation("查询预警转发元数据")
|
||||
public AjaxResult getAlterForwardMeta(@RequestParam String ids) {
|
||||
List<Long> idList = Arrays.stream(ids.split(","))
|
||||
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
||||
.map(Long::valueOf)
|
||||
.collect(Collectors.toList());
|
||||
return AjaxResult.success(workRecordService.getAlterForwardMeta(idList));
|
||||
}
|
||||
|
||||
@PostMapping("/alter/forward")
|
||||
@Log(title = "工作台-转发预警信息")
|
||||
@ApiOperation("批量转发预警信息")
|
||||
public AjaxResult forwardAlter(@Validated @RequestBody AlterForwardRequest request) {
|
||||
AlterForwardResultVO result = workRecordService.forwardAlter(request);
|
||||
if (result.getSuccessCount() > 0 && result.getFailCount() > 0) {
|
||||
return AjaxResult.success("成功转发" + result.getSuccessCount() + "条,失败" + result.getFailCount() + "条", result);
|
||||
}
|
||||
if (result.getSuccessCount() > 0) {
|
||||
return AjaxResult.success("成功转发" + result.getSuccessCount() + "条", result);
|
||||
}
|
||||
return AjaxResult.error("未能成功转发,失败" + result.getFailCount() + "条");
|
||||
}
|
||||
|
||||
@GetMapping("/alter/count")
|
||||
@Log(title = "工作台-查询预警推送次数")
|
||||
@ApiOperation("查询预警推送次数")
|
||||
@@ -131,4 +159,15 @@ public class WorkRecordController extends BaseController {
|
||||
return toAjax(workRecordService.updateReadTime(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有预警类型
|
||||
*/
|
||||
@GetMapping("/alter/types")
|
||||
@Log(title = "工作台-查询预警类型")
|
||||
@ApiOperation("查询所有预警类型")
|
||||
public AjaxResult getAlterTypes() {
|
||||
List<String> types = workRecordService.getAlterTypes();
|
||||
return AjaxResult.success(types);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.ruoyi.ibs.task.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class AlterForwardRequest {
|
||||
|
||||
@NotEmpty(message = "请选择需要转发的预警")
|
||||
private List<Long> ids;
|
||||
|
||||
@NotBlank(message = "请选择转发目标类型")
|
||||
private String targetType;
|
||||
|
||||
private Long deptId;
|
||||
|
||||
private String userName;
|
||||
|
||||
private Boolean useHistory;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ruoyi.ibs.task.domain.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class ForwardTarget {
|
||||
|
||||
private String targetType;
|
||||
|
||||
private Long deptId;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String targetName;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.ibs.task.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("alter_assign_history")
|
||||
public class AlterAssignHistory implements Serializable {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("预警类型")
|
||||
private String alterType;
|
||||
|
||||
@ApiModelProperty("客户号")
|
||||
private String custId;
|
||||
|
||||
@ApiModelProperty("客户姓名")
|
||||
private String custName;
|
||||
|
||||
@ApiModelProperty("所属支行/当前操作机构ID")
|
||||
private Long deptId;
|
||||
|
||||
@ApiModelProperty("最近一次转发目标类型:dept/user")
|
||||
private String lastAssignTargetType;
|
||||
|
||||
@ApiModelProperty("最近一次转发目标部门ID")
|
||||
private Long lastAssignTargetDeptId;
|
||||
|
||||
@ApiModelProperty("最近一次转发目标用户账号")
|
||||
private String lastAssignTargetUser;
|
||||
|
||||
@ApiModelProperty("最近一次转发目标名称")
|
||||
private String lastAssignTargetName;
|
||||
|
||||
@ApiModelProperty("最近一次转发操作人账号")
|
||||
private String lastAssignByUser;
|
||||
|
||||
@ApiModelProperty("最近一次转发操作人角色")
|
||||
private String lastAssignByRole;
|
||||
|
||||
@ApiModelProperty("更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -94,4 +94,8 @@ public class WorkRecord implements Serializable {
|
||||
@ApiModelProperty(value = "是否逾期", notes = "")
|
||||
private Integer isOverdue;
|
||||
|
||||
/** 当前承接部门ID,仅转发到网点时使用 */
|
||||
@ApiModelProperty(value = "当前承接部门ID", notes = "")
|
||||
private Long deptId;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ruoyi.ibs.task.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AlterAssignTargetVO {
|
||||
|
||||
@ApiModelProperty("目标编码")
|
||||
private String targetCode;
|
||||
|
||||
@ApiModelProperty("目标名称")
|
||||
private String targetName;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.ruoyi.ibs.task.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class AlterForwardMetaVO {
|
||||
|
||||
@ApiModelProperty("可选网点列表")
|
||||
private List<AlterAssignTargetVO> deptOptions = new ArrayList<>();
|
||||
|
||||
@ApiModelProperty("可选客户经理列表")
|
||||
private List<AlterAssignTargetVO> userOptions = new ArrayList<>();
|
||||
|
||||
@ApiModelProperty("历史推荐目标类型:dept/user")
|
||||
private String recommendedTargetType;
|
||||
|
||||
@ApiModelProperty("历史推荐目标编码")
|
||||
private String recommendedTargetCode;
|
||||
|
||||
@ApiModelProperty("历史推荐目标名称")
|
||||
private String recommendedTargetName;
|
||||
|
||||
@ApiModelProperty("是否仅允许按历史推荐转发")
|
||||
private Boolean historyOnly = false;
|
||||
|
||||
@ApiModelProperty("是否存在历史推荐")
|
||||
private Boolean hasHistoryRecommend = false;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ruoyi.ibs.task.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AlterForwardResultVO {
|
||||
|
||||
@ApiModelProperty("成功数量")
|
||||
private int successCount;
|
||||
|
||||
@ApiModelProperty("失败数量")
|
||||
private int failCount;
|
||||
}
|
||||
@@ -47,6 +47,14 @@ public class AlterVO {
|
||||
@ApiModelProperty(value = "客户内码", notes = "")
|
||||
private String custIsn;
|
||||
|
||||
/** 当前承接部门ID */
|
||||
@ApiModelProperty(value = "当前承接部门ID", notes = "")
|
||||
private Long deptId;
|
||||
|
||||
/** 当前承接网点名称 */
|
||||
@ApiModelProperty(value = "当前承接网点名称", notes = "")
|
||||
private String deptName;
|
||||
|
||||
/** 状态 */
|
||||
@ApiModelProperty(value = "状态", notes = "")
|
||||
private String status;
|
||||
@@ -62,4 +70,12 @@ public class AlterVO {
|
||||
/** 是否需要反馈 */
|
||||
@ApiModelProperty(value = "是否需要反馈", notes = "")
|
||||
private String isFeedback;
|
||||
|
||||
/** 转发标识:1需要转发,0无需转发 */
|
||||
@ApiModelProperty(value = "转发标识", notes = "")
|
||||
private String forwardFlag;
|
||||
|
||||
/** 是否可转发 */
|
||||
@ApiModelProperty(value = "是否可转发", notes = "")
|
||||
private Boolean canForward;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.ruoyi.ibs.task.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.ibs.task.domain.entity.AlterAssignHistory;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface AlterAssignHistoryMapper extends BaseMapper<AlterAssignHistory> {
|
||||
}
|
||||
@@ -6,9 +6,9 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
||||
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
||||
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
||||
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
||||
import com.ruoyi.ibs.task.domain.vo.*;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
@@ -86,10 +86,26 @@ public interface WorkRecordMapper extends BaseMapper<WorkRecord> {
|
||||
* @return 预警信息
|
||||
*/
|
||||
List<AlterVO> selectAllAlterList(@Param("deptId") String deptId, @Param("role") String role,
|
||||
@Param("status") String status, @Param("alterType") String alterType, @Param("username") String username);
|
||||
@Param("status") String status, @Param("alterType") String alterType,
|
||||
@Param("username") String username, @Param("forwardFlag") String forwardFlag);
|
||||
|
||||
AlterCountVO selectAlterCount(@Param("reportTime") Date reportTime, @Param("role") String role, @Param("deptId") String deptId);
|
||||
|
||||
List<AlterAssignTargetVO> selectForwardDeptTargets(@Param("branchDeptId") Long branchDeptId);
|
||||
|
||||
List<AlterAssignTargetVO> selectForwardUserTargets(@Param("deptId") Long deptId, @Param("role") String role);
|
||||
|
||||
int updateAlterForwardToDept(@Param("id") Long id, @Param("sourceUserName") String sourceUserName,
|
||||
@Param("targetDeptId") Long targetDeptId, @Param("updateBy") String updateBy);
|
||||
|
||||
int updateAlterForwardToUserByBranch(@Param("id") Long id, @Param("sourceUserName") String sourceUserName,
|
||||
@Param("targetUserName") String targetUserName, @Param("targetNickName") String targetNickName,
|
||||
@Param("updateBy") String updateBy);
|
||||
|
||||
int updateAlterForwardToUserByOutlet(@Param("id") Long id, @Param("sourceDeptId") Long sourceDeptId,
|
||||
@Param("targetUserName") String targetUserName, @Param("targetNickName") String targetNickName,
|
||||
@Param("updateBy") String updateBy);
|
||||
|
||||
/**
|
||||
* 设置工作清单为过期
|
||||
*
|
||||
@@ -112,4 +128,12 @@ public interface WorkRecordMapper extends BaseMapper<WorkRecord> {
|
||||
List<AlterConfigVO> selectAlterConfigList(String alterType);
|
||||
|
||||
int updateAlterConfig(AlterConfig alterConfig);
|
||||
|
||||
/**
|
||||
* 查询所有预警类型
|
||||
*
|
||||
* @param headId 总部ID(部门ID前三位)
|
||||
* @return 预警类型列表
|
||||
*/
|
||||
List<String> selectAlterTypes(@Param("headId") String headId);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
||||
import com.ruoyi.ibs.task.domain.dto.AlterForwardRequest;
|
||||
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
||||
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
||||
import com.ruoyi.ibs.task.domain.vo.*;
|
||||
@@ -61,7 +62,23 @@ public interface WorkRecordService{
|
||||
* @param alterType
|
||||
* @return
|
||||
*/
|
||||
List<AlterVO> getAllAlterList(String status, String alterType);
|
||||
List<AlterVO> getAllAlterList(String status, String alterType, String forwardFlag);
|
||||
|
||||
/**
|
||||
* 获取预警转发元数据
|
||||
*
|
||||
* @param id 预警ID
|
||||
* @return 转发元数据
|
||||
*/
|
||||
AlterForwardMetaVO getAlterForwardMeta(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 批量转发预警
|
||||
*
|
||||
* @param request 转发请求
|
||||
* @return 结果
|
||||
*/
|
||||
AlterForwardResultVO forwardAlter(AlterForwardRequest request);
|
||||
/**
|
||||
* 定时任务生成工作清单
|
||||
*
|
||||
@@ -85,4 +102,11 @@ public interface WorkRecordService{
|
||||
int updateReadTime(Long id);
|
||||
|
||||
AlterCountVO getAlterCount(Date reportTime);
|
||||
|
||||
/**
|
||||
* 查询所有预警类型
|
||||
*
|
||||
* @return 预警类型列表
|
||||
*/
|
||||
List<String> getAlterTypes();
|
||||
}
|
||||
|
||||
@@ -11,19 +11,29 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.ibs.task.domain.dto.AlterForwardRequest;
|
||||
import com.ruoyi.ibs.task.domain.dto.ForwardTarget;
|
||||
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
||||
import com.ruoyi.ibs.task.domain.entity.AlterAssignHistory;
|
||||
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
||||
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
||||
import com.ruoyi.ibs.task.domain.vo.*;
|
||||
import com.ruoyi.ibs.task.mapper.AlterAssignHistoryMapper;
|
||||
import com.ruoyi.ibs.task.mapper.WorkRecordMapper;
|
||||
import com.ruoyi.ibs.task.service.WorkRecordService;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.system.domain.SysPost;
|
||||
import com.ruoyi.system.service.ISysDeptService;
|
||||
import com.ruoyi.system.service.ISysPostService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -39,15 +49,35 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Service
|
||||
public class WorkRecordServiceImpl implements WorkRecordService {
|
||||
|
||||
private final static String alterTypesRedisKey = "work:record:alter:types";
|
||||
private static final String ROLE_MANAGER = "manager";
|
||||
private static final String ROLE_BRANCH = "branch";
|
||||
private static final String ROLE_OUTLET = "outlet";
|
||||
private static final String TARGET_TYPE_DEPT = "dept";
|
||||
private static final String TARGET_TYPE_USER = "user";
|
||||
private static final Set<String> FORWARD_ALTER_TYPES = new HashSet<>(Arrays.asList(
|
||||
"个人资产客户定期存款",
|
||||
"个人资产客户封闭式理财"
|
||||
));
|
||||
|
||||
@Autowired
|
||||
private WorkRecordMapper workRecordMapper;
|
||||
|
||||
@Autowired
|
||||
private AlterAssignHistoryMapper alterAssignHistoryMapper;
|
||||
|
||||
@Autowired
|
||||
private ISysPostService sysPostService;
|
||||
|
||||
@Autowired
|
||||
private ISysDeptService sysDeptService;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService sysUserService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
/**
|
||||
* 查询我的工作清单
|
||||
*
|
||||
@@ -137,7 +167,9 @@ public class WorkRecordServiceImpl implements WorkRecordService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<AlterVO> getAlterList(String status, String alterType) {
|
||||
String username = SecurityUtils.getUsername();
|
||||
return workRecordMapper.selectAlterList(username, status, alterType);
|
||||
List<AlterVO> alterVOS = workRecordMapper.selectAlterList(username, status, alterType);
|
||||
fillAlterExtFields(alterVOS);
|
||||
return alterVOS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,27 +182,98 @@ public class WorkRecordServiceImpl implements WorkRecordService {
|
||||
* @return 预警信息
|
||||
*/
|
||||
@Override
|
||||
public List<AlterVO> getAllAlterList(String status, String alterType) {
|
||||
List<AlterVO> alterVOS = workRecordMapper.selectAllAlterList(String.valueOf(SecurityUtils.getDeptId()), SecurityUtils.userRole(), status, alterType, SecurityUtils.getUsername());
|
||||
// 将 userName 和 nickName 以 "userName-nickName" 的方式拼接后设置到 custInfo 字段
|
||||
if (alterVOS != null && !alterVOS.isEmpty()) {
|
||||
alterVOS.forEach(alterVO -> {
|
||||
String userName = alterVO.getUserName();
|
||||
String nickName = alterVO.getNickName();
|
||||
if (userName != null && nickName != null) {
|
||||
alterVO.setUserInfo(nickName + "-" + userName);
|
||||
} else if (userName != null) {
|
||||
alterVO.setUserInfo(userName);
|
||||
} else if (nickName != null) {
|
||||
alterVO.setUserInfo(nickName);
|
||||
} else {
|
||||
alterVO.setUserInfo("");
|
||||
}
|
||||
});
|
||||
}
|
||||
public List<AlterVO> getAllAlterList(String status, String alterType, String forwardFlag) {
|
||||
List<AlterVO> alterVOS = workRecordMapper.selectAllAlterList(
|
||||
String.valueOf(SecurityUtils.getDeptId()),
|
||||
SecurityUtils.userRole(),
|
||||
status,
|
||||
alterType,
|
||||
SecurityUtils.getUsername(),
|
||||
forwardFlag
|
||||
);
|
||||
fillAlterExtFields(alterVOS);
|
||||
return alterVOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询转发弹窗所需元数据。
|
||||
* 单选时返回手动选项并附带历史推荐;多选时根据是否存在历史记录决定走手动分配还是历史推荐模式。
|
||||
*/
|
||||
@Override
|
||||
public AlterForwardMetaVO getAlterForwardMeta(List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
throw new ServiceException("请选择需要转发的预警");
|
||||
}
|
||||
AlterForwardMetaVO metaVO = new AlterForwardMetaVO();
|
||||
String role = requireForwardRole();
|
||||
Long currentDeptId = SecurityUtils.getDeptId();
|
||||
String currentUser = SecurityUtils.getUsername();
|
||||
List<WorkRecord> workRecords = workRecordMapper.selectBatchIds(ids);
|
||||
if (workRecords == null || workRecords.size() != ids.size()) {
|
||||
throw new ServiceException("存在预警记录已不存在,请刷新后重试");
|
||||
}
|
||||
workRecords.forEach(item -> validateRecordBeforeForward(item, role, currentUser, currentDeptId));
|
||||
if (ids.size() > 1) {
|
||||
boolean hasAnyHistory = workRecords.stream()
|
||||
.map(item -> getHistoryRecommend(item.getCustId(), currentDeptId, role))
|
||||
.anyMatch(Objects::nonNull);
|
||||
metaVO.setHasHistoryRecommend(hasAnyHistory);
|
||||
metaVO.setHistoryOnly(hasAnyHistory);
|
||||
if (!hasAnyHistory) {
|
||||
fillManualOptions(metaVO, role, currentDeptId);
|
||||
}
|
||||
return metaVO;
|
||||
}
|
||||
WorkRecord workRecord = workRecords.get(0);
|
||||
fillManualOptions(metaVO, role, currentDeptId);
|
||||
fillHistoryRecommend(metaVO, workRecord.getCustId(), currentDeptId, role);
|
||||
return metaVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行预警转发。
|
||||
* 支持手动分配和按历史推荐分配两种模式,并分别统计成功和失败数量。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AlterForwardResultVO forwardAlter(AlterForwardRequest request) {
|
||||
String role = requireForwardRole();
|
||||
String currentUser = SecurityUtils.getUsername();
|
||||
Long currentDeptId = SecurityUtils.getDeptId();
|
||||
AlterForwardResultVO result = new AlterForwardResultVO();
|
||||
boolean useHistory = Boolean.TRUE.equals(request.getUseHistory());
|
||||
ForwardTarget manualTarget = useHistory ? null : resolveManualTarget(request, role, currentDeptId);
|
||||
|
||||
List<WorkRecord> workRecords = workRecordMapper.selectBatchIds(request.getIds());
|
||||
if (workRecords == null || workRecords.size() != request.getIds().size()) {
|
||||
throw new ServiceException("存在预警记录已不存在,请刷新后重试");
|
||||
}
|
||||
|
||||
for (WorkRecord workRecord : workRecords) {
|
||||
validateRecordBeforeForward(workRecord, role, currentUser, currentDeptId);
|
||||
AlterAssignHistory history = useHistory ? getHistoryRecommend(workRecord.getCustId(), currentDeptId, role) : null;
|
||||
ForwardTarget target = useHistory ? resolveHistoryTarget(history, role, currentDeptId) : manualTarget;
|
||||
if (target == null) {
|
||||
result.setFailCount(result.getFailCount() + 1);
|
||||
continue;
|
||||
}
|
||||
int row = doForward(workRecord.getId(), currentUser, currentDeptId, role, target);
|
||||
if (row <= 0) {
|
||||
result.setFailCount(result.getFailCount() + 1);
|
||||
continue;
|
||||
}
|
||||
result.setSuccessCount(result.getSuccessCount() + row);
|
||||
if (useHistory) {
|
||||
if (history != null) {
|
||||
saveAssignHistoryByHistory(workRecord, history, role, currentDeptId);
|
||||
}
|
||||
} else {
|
||||
saveAssignHistory(workRecord, manualTarget, role, currentDeptId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时任务生成工作清单
|
||||
*
|
||||
@@ -253,6 +356,19 @@ public class WorkRecordServiceImpl implements WorkRecordService {
|
||||
return alterCountVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAlterTypes() {
|
||||
String headId = SecurityUtils.getHeadId();
|
||||
String cacheKey = alterTypesRedisKey + ":" + headId;
|
||||
List<String> cachedTypes = redisCache.getCacheObject(cacheKey);
|
||||
if (cachedTypes != null) {
|
||||
return cachedTypes;
|
||||
}
|
||||
List<String> types = workRecordMapper.selectAlterTypes(headId);
|
||||
redisCache.setCacheObjectToEndDay(cacheKey, types);
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户权限范围内所有post_ids
|
||||
* @return
|
||||
@@ -332,4 +448,306 @@ public class WorkRecordServiceImpl implements WorkRecordService {
|
||||
return java.sql.Timestamp.valueOf(endTime);
|
||||
}
|
||||
|
||||
private void fillAlterExtFields(List<AlterVO> alterVOS) {
|
||||
if (alterVOS == null || alterVOS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String role = SecurityUtils.userRole();
|
||||
Long currentDeptId = SecurityUtils.getDeptId();
|
||||
String currentUser = SecurityUtils.getUsername();
|
||||
alterVOS.forEach(alterVO -> {
|
||||
alterVO.setForwardFlag(parseForwardFlag(alterVO.getAlterDetail()));
|
||||
alterVO.setAlterDetail(stripForwardPrefix(alterVO.getAlterDetail()));
|
||||
alterVO.setUserInfo(buildUserInfo(alterVO.getUserName(), alterVO.getNickName()));
|
||||
alterVO.setCanForward(canForward(alterVO, role, currentDeptId, currentUser));
|
||||
});
|
||||
}
|
||||
|
||||
private String buildUserInfo(String userName, String nickName) {
|
||||
if (StringUtils.isNotEmpty(userName) && StringUtils.isNotEmpty(nickName)) {
|
||||
return nickName + "-" + userName;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(userName)) {
|
||||
return userName;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(nickName)) {
|
||||
return nickName;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String parseForwardFlag(String alterDetail) {
|
||||
if (StringUtils.isEmpty(alterDetail)) {
|
||||
return "";
|
||||
}
|
||||
if (alterDetail.startsWith("[FORWARD=1]")) {
|
||||
return "1";
|
||||
}
|
||||
if (alterDetail.startsWith("[FORWARD=0]")) {
|
||||
return "0";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String stripForwardPrefix(String alterDetail) {
|
||||
if (StringUtils.isEmpty(alterDetail)) {
|
||||
return alterDetail;
|
||||
}
|
||||
if (alterDetail.startsWith("[FORWARD=1] ")) {
|
||||
return alterDetail.substring(12);
|
||||
}
|
||||
if (alterDetail.startsWith("[FORWARD=0] ")) {
|
||||
return alterDetail.substring(12);
|
||||
}
|
||||
if (alterDetail.startsWith("[FORWARD=1]") || alterDetail.startsWith("[FORWARD=0]")) {
|
||||
return alterDetail.substring(11);
|
||||
}
|
||||
return alterDetail;
|
||||
}
|
||||
|
||||
private Boolean canForward(AlterVO alterVO, String role, Long currentDeptId, String currentUser) {
|
||||
if (!FORWARD_ALTER_TYPES.contains(alterVO.getAlterType())) {
|
||||
return false;
|
||||
}
|
||||
if (!"1".equals(alterVO.getForwardFlag())) {
|
||||
return false;
|
||||
}
|
||||
if ("2".equals(alterVO.getStatus())) {
|
||||
return false;
|
||||
}
|
||||
if (ROLE_BRANCH.equals(role)) {
|
||||
return StringUtils.equals(currentUser, alterVO.getUserName()) && alterVO.getDeptId() == null;
|
||||
}
|
||||
if (ROLE_OUTLET.equals(role)) {
|
||||
return alterVO.getDeptId() != null && alterVO.getDeptId().equals(currentDeptId) && StringUtils.isEmpty(alterVO.getUserName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验当前登录角色是否具备预警转发能力,并返回角色标识。
|
||||
*/
|
||||
private String requireForwardRole() {
|
||||
String role = SecurityUtils.userRole();
|
||||
if (!ROLE_BRANCH.equals(role) && !ROLE_OUTLET.equals(role)) {
|
||||
throw new ServiceException("当前角色不支持转发预警");
|
||||
}
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验预警记录当前是否仍处于登录人可转发范围内,防止页面停留期间数据状态已变化。
|
||||
*/
|
||||
private void validateRecordBeforeForward(WorkRecord workRecord, String role, String currentUser, Long currentDeptId) {
|
||||
if (workRecord == null || workRecord.getId() == null) {
|
||||
throw new ServiceException("预警记录不存在");
|
||||
}
|
||||
if (!Integer.valueOf(1).equals(workRecord.getIsAlter())) {
|
||||
throw new ServiceException("当前记录不是预警信息");
|
||||
}
|
||||
if (!FORWARD_ALTER_TYPES.contains(workRecord.getAlterType())) {
|
||||
throw new ServiceException("当前预警类型不支持转发");
|
||||
}
|
||||
if (!"1".equals(parseForwardFlag(workRecord.getAlterDetail()))) {
|
||||
throw new ServiceException("当前预警已有管户,无需转发");
|
||||
}
|
||||
if ("2".equals(workRecord.getStatus())) {
|
||||
throw new ServiceException("当前预警已完成,不能转发");
|
||||
}
|
||||
if (ROLE_BRANCH.equals(role)) {
|
||||
if (!StringUtils.equals(currentUser, workRecord.getUserName()) || workRecord.getDeptId() != null) {
|
||||
throw new ServiceException("当前预警已不在您的待转发范围内");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ROLE_OUTLET.equals(role)) {
|
||||
if (workRecord.getDeptId() == null || !workRecord.getDeptId().equals(currentDeptId) || StringUtils.isNotEmpty(workRecord.getUserName())) {
|
||||
throw new ServiceException("当前预警已不在本网点待转发范围内");
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new ServiceException("当前角色不支持转发预警");
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析手动转发目标,并顺带完成目标权限范围校验。
|
||||
*/
|
||||
private ForwardTarget resolveManualTarget(AlterForwardRequest request, String role, Long currentDeptId) {
|
||||
if (TARGET_TYPE_DEPT.equals(request.getTargetType())) {
|
||||
if (request.getDeptId() == null) {
|
||||
throw new ServiceException("请选择转发网点");
|
||||
}
|
||||
if (!ROLE_BRANCH.equals(role)) {
|
||||
throw new ServiceException("网点管理员只能转发给客户经理");
|
||||
}
|
||||
String deptName = getAllowedDeptName(request.getDeptId(), currentDeptId);
|
||||
return new ForwardTarget(TARGET_TYPE_DEPT, request.getDeptId(), null, null, deptName);
|
||||
}
|
||||
if (!TARGET_TYPE_USER.equals(request.getTargetType()) || StringUtils.isEmpty(request.getUserName())) {
|
||||
throw new ServiceException("请选择转发客户经理");
|
||||
}
|
||||
SysUser user = getAllowedTargetUser(request.getUserName(), role, currentDeptId);
|
||||
String targetName = StringUtils.isNotEmpty(user.getNickName()) ? user.getNickName() : user.getUserName();
|
||||
return new ForwardTarget(TARGET_TYPE_USER, null, user.getUserName(), user.getNickName(), targetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将历史分配记录转换成可执行的转发目标;若历史目标已失效,则返回空。
|
||||
*/
|
||||
private ForwardTarget resolveHistoryTarget(AlterAssignHistory history, String role, Long currentDeptId) {
|
||||
if (history == null) {
|
||||
return null;
|
||||
}
|
||||
if (TARGET_TYPE_DEPT.equals(history.getLastAssignTargetType())) {
|
||||
if (history.getLastAssignTargetDeptId() == null) {
|
||||
return null;
|
||||
}
|
||||
String deptName = getAllowedDeptName(history.getLastAssignTargetDeptId(), currentDeptId);
|
||||
return new ForwardTarget(TARGET_TYPE_DEPT, history.getLastAssignTargetDeptId(), null, null, deptName);
|
||||
}
|
||||
if (!TARGET_TYPE_USER.equals(history.getLastAssignTargetType()) || StringUtils.isEmpty(history.getLastAssignTargetUser())) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
SysUser user = getAllowedTargetUser(history.getLastAssignTargetUser(), role, currentDeptId);
|
||||
String targetName = StringUtils.isNotEmpty(user.getNickName()) ? user.getNickName() : user.getUserName();
|
||||
return new ForwardTarget(TARGET_TYPE_USER, null, user.getUserName(), user.getNickName(), targetName);
|
||||
} catch (ServiceException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按目标类型执行真正的转发落库更新。
|
||||
*/
|
||||
private int doForward(Long workRecordId, String currentUser, Long currentDeptId, String role, ForwardTarget target) {
|
||||
if (TARGET_TYPE_DEPT.equals(target.getTargetType())) {
|
||||
return workRecordMapper.updateAlterForwardToDept(workRecordId, currentUser, target.getDeptId(), currentUser);
|
||||
}
|
||||
if (ROLE_BRANCH.equals(role)) {
|
||||
return workRecordMapper.updateAlterForwardToUserByBranch(
|
||||
workRecordId, currentUser, target.getUserName(), target.getNickName(), currentUser
|
||||
);
|
||||
}
|
||||
return workRecordMapper.updateAlterForwardToUserByOutlet(
|
||||
workRecordId, currentDeptId, target.getUserName(), target.getNickName(), currentUser
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验目标网点是否在当前支行管理员的可转发范围内,并返回网点名称。
|
||||
*/
|
||||
private String getAllowedDeptName(Long targetDeptId, Long currentDeptId) {
|
||||
List<AlterAssignTargetVO> deptOptions = workRecordMapper.selectForwardDeptTargets(currentDeptId);
|
||||
return deptOptions.stream()
|
||||
.filter(item -> String.valueOf(targetDeptId).equals(item.getTargetCode()))
|
||||
.map(AlterAssignTargetVO::getTargetName)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new ServiceException("所选网点不在当前支行可转发范围内"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验目标客户经理是否在当前管理员可转发范围内,并返回用户信息。
|
||||
*/
|
||||
private SysUser getAllowedTargetUser(String targetUserName, String role, Long currentDeptId) {
|
||||
List<AlterAssignTargetVO> userOptions = workRecordMapper.selectForwardUserTargets(currentDeptId, ROLE_MANAGER);
|
||||
boolean matched = userOptions.stream().anyMatch(item -> StringUtils.equals(targetUserName, item.getTargetCode()));
|
||||
if (!matched) {
|
||||
if (ROLE_BRANCH.equals(role)) {
|
||||
throw new ServiceException("所选客户经理不在当前支行可转发范围内");
|
||||
}
|
||||
throw new ServiceException("所选客户经理不在当前网点可转发范围内");
|
||||
}
|
||||
SysUser user = sysUserService.selectUserByUserName(targetUserName);
|
||||
if (user == null || StringUtils.isEmpty(user.getUserName())) {
|
||||
throw new ServiceException("转发目标客户经理不存在");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充手动分配弹窗可选项;支行管理员可选网点和客户经理,网点管理员仅可选客户经理。
|
||||
*/
|
||||
private void fillManualOptions(AlterForwardMetaVO metaVO, String role, Long currentDeptId) {
|
||||
if (ROLE_BRANCH.equals(role)) {
|
||||
metaVO.setDeptOptions(workRecordMapper.selectForwardDeptTargets(currentDeptId));
|
||||
metaVO.setUserOptions(workRecordMapper.selectForwardUserTargets(currentDeptId, ROLE_MANAGER));
|
||||
return;
|
||||
}
|
||||
if (ROLE_OUTLET.equals(role)) {
|
||||
metaVO.setUserOptions(workRecordMapper.selectForwardUserTargets(currentDeptId, ROLE_MANAGER));
|
||||
return;
|
||||
}
|
||||
throw new ServiceException("当前角色不支持转发预警");
|
||||
}
|
||||
|
||||
/**
|
||||
* 按客户、当前部门和当前角色查询历史推荐,并回填到前端元数据中。
|
||||
*/
|
||||
private void fillHistoryRecommend(AlterForwardMetaVO metaVO, String custId, Long deptId, String role) {
|
||||
AlterAssignHistory history = getHistoryRecommend(custId, deptId, role);
|
||||
if (history == null) {
|
||||
return;
|
||||
}
|
||||
metaVO.setHasHistoryRecommend(true);
|
||||
metaVO.setRecommendedTargetType(history.getLastAssignTargetType());
|
||||
if (TARGET_TYPE_DEPT.equals(history.getLastAssignTargetType())) {
|
||||
metaVO.setRecommendedTargetCode(history.getLastAssignTargetDeptId() == null ? "" : String.valueOf(history.getLastAssignTargetDeptId()));
|
||||
} else {
|
||||
metaVO.setRecommendedTargetCode(history.getLastAssignTargetUser());
|
||||
}
|
||||
metaVO.setRecommendedTargetName(history.getLastAssignTargetName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存本次手动分配结果;同一客户在同部门、同角色下只维护一条最新历史。
|
||||
*/
|
||||
private void saveAssignHistory(WorkRecord workRecord, ForwardTarget target, String role, Long currentDeptId) {
|
||||
AlterAssignHistory history = getHistoryRecommend(workRecord.getCustId(), currentDeptId, role);
|
||||
if (history == null) {
|
||||
history = new AlterAssignHistory();
|
||||
history.setCustId(workRecord.getCustId());
|
||||
}
|
||||
history.setAlterType(workRecord.getAlterType());
|
||||
history.setCustName(workRecord.getCustName());
|
||||
history.setDeptId(currentDeptId);
|
||||
history.setLastAssignTargetType(target.getTargetType());
|
||||
history.setLastAssignTargetDeptId(target.getDeptId());
|
||||
history.setLastAssignTargetUser(target.getUserName());
|
||||
history.setLastAssignTargetName(target.getTargetName());
|
||||
history.setLastAssignByUser(SecurityUtils.getUsername());
|
||||
history.setLastAssignByRole(role);
|
||||
history.setUpdateTime(new Date());
|
||||
if (history.getId() == null) {
|
||||
alterAssignHistoryMapper.insert(history);
|
||||
} else {
|
||||
alterAssignHistoryMapper.updateById(history);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按历史推荐成功转发后,刷新该客户最新一次分配历史的更新时间和目标信息。
|
||||
*/
|
||||
private void saveAssignHistoryByHistory(WorkRecord workRecord, AlterAssignHistory sourceHistory, String role, Long currentDeptId) {
|
||||
ForwardTarget target = new ForwardTarget(
|
||||
sourceHistory.getLastAssignTargetType(),
|
||||
sourceHistory.getLastAssignTargetDeptId(),
|
||||
sourceHistory.getLastAssignTargetUser(),
|
||||
null,
|
||||
sourceHistory.getLastAssignTargetName()
|
||||
);
|
||||
saveAssignHistory(workRecord, target, role, currentDeptId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前角色在当前部门下,对指定客户的最近一次分配历史。
|
||||
*/
|
||||
private AlterAssignHistory getHistoryRecommend(String custId, Long deptId, String role) {
|
||||
return alterAssignHistoryMapper.selectOne(new LambdaQueryWrapper<AlterAssignHistory>()
|
||||
.eq(AlterAssignHistory::getCustId, custId)
|
||||
.eq(AlterAssignHistory::getDeptId, deptId)
|
||||
.eq(AlterAssignHistory::getLastAssignByRole, role)
|
||||
.last("limit 1"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -857,6 +857,28 @@
|
||||
select id,cust_name from cust_info_business where social_credit_code = #{socialCreditCode}
|
||||
</select>
|
||||
|
||||
<select id="selectExistingSocialCreditCodes" resultType="java.lang.String">
|
||||
select social_credit_code
|
||||
from cust_info_business_${deptCode}
|
||||
where social_credit_code in
|
||||
<foreach item="socialCreditCode" collection="socialCreditCodes" open="(" separator="," close=")">
|
||||
#{socialCreditCode}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<update id="batchUpdateCustLevelBySocialCreditCode">
|
||||
update cust_info_business_${deptCode}
|
||||
set cust_level = case social_credit_code
|
||||
<foreach item="item" collection="list">
|
||||
when #{item.socialCreditCode} then #{item.custLevel}
|
||||
</foreach>
|
||||
end
|
||||
where social_credit_code in
|
||||
<foreach item="item" collection="list" open="(" separator="," close=")">
|
||||
#{item.socialCreditCode}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<insert id="insertCustomersToBusinessByScCode" parameterType="java.util.List">
|
||||
INSERT INTO cust_info_business
|
||||
(cust_id,cust_name, social_credit_code, update_by, update_time, cust_phone, industry, asset, credit)
|
||||
|
||||
@@ -184,19 +184,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</insert>
|
||||
|
||||
<select id="selectAlterList" resultType="AlterVO">
|
||||
select id, user_name, nick_name, alter_type, alter_detail, cust_id, cust_name, read_time, status, remark, is_feedback, cust_isn
|
||||
from work_record
|
||||
select wr.id, wr.user_name, wr.nick_name, wr.alter_type, wr.alter_detail, wr.cust_id, wr.cust_name,
|
||||
wr.read_time, wr.status, wr.remark, wr.is_feedback, wr.cust_isn, wr.dept_id, sd.dept_name
|
||||
from work_record wr
|
||||
left join sys_dept sd on wr.dept_id = sd.dept_id
|
||||
<where>
|
||||
is_alter = 1
|
||||
and user_name= #{username}
|
||||
wr.is_alter = 1
|
||||
and wr.user_name= #{username}
|
||||
<if test="status != null and status != ''">
|
||||
and status = #{status}
|
||||
and wr.status = #{status}
|
||||
</if>
|
||||
<if test="alterType != null and alterType != ''">
|
||||
and alter_type LIKE CONCAT('%', #{alterType}, '%')
|
||||
and wr.alter_type = #{alterType}
|
||||
</if>
|
||||
</where>
|
||||
order by create_time desc, status asc
|
||||
order by wr.create_time desc, wr.status asc
|
||||
</select>
|
||||
|
||||
<select id="selectAlterCount" resultType="AlterCountVO">
|
||||
@@ -209,45 +211,148 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
from work_record wr
|
||||
left join sys_user su on su.user_name = wr.user_name
|
||||
left join sys_dept d on su.dept_id = d.dept_id
|
||||
left join sys_dept wd on wr.dept_id = wd.dept_id
|
||||
where wr.is_alter = 1
|
||||
and wr.create_time <= #{reportTime}
|
||||
and (
|
||||
<choose>
|
||||
<when test="role != null and role == 'outlet'"> su.dept_id = #{deptId} </when>
|
||||
<when test="role != null and role == 'branch'"> (su.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) </when>
|
||||
<when test="role != null and role == 'private'"> (left(su.dept_id,3) = left(#{deptId},3) and wr.cust_type in ('0', '1')) </when>
|
||||
<when test="role != null and role == 'public'"> (left(su.dept_id,3) = left(#{deptId},3) and wr.cust_type = '2') </when>
|
||||
<when test="role != null and role == 'ops'"> left(su.dept_id,3) = left(#{deptId},3) </when>
|
||||
<when test="role != null and role == 'head'"> left(su.dept_id,3) = left(#{deptId},3) </when>
|
||||
<when test="role != null and role == 'outlet'"> (su.dept_id = #{deptId} or wr.dept_id = #{deptId}) </when>
|
||||
<when test="role != null and role == 'branch'"> ((su.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) or (wr.dept_id = #{deptId} or find_in_set(#{deptId},wd.ancestors))) </when>
|
||||
<when test="role != null and role == 'private'"> ((left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) and wr.cust_type in ('0', '1')) </when>
|
||||
<when test="role != null and role == 'public'"> ((left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) and wr.cust_type = '2') </when>
|
||||
<when test="role != null and role == 'ops'"> (left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) </when>
|
||||
<when test="role != null and role == 'head'"> (left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) </when>
|
||||
</choose>)
|
||||
</select>
|
||||
|
||||
<select id="selectAllAlterList" resultType="AlterVO">
|
||||
select wr.id, wr.user_name, wr.nick_name, wr.alter_type, wr.alter_detail, wr.cust_id, wr.cust_name, wr.read_time, wr.status, wr.remark, wr.cust_type, wr.is_feedback, wr.cust_isn
|
||||
select wr.id, wr.user_name, wr.nick_name, wr.alter_type, wr.alter_detail, wr.cust_id, wr.cust_name, wr.read_time,
|
||||
wr.status, wr.remark, wr.cust_type, wr.is_feedback, wr.cust_isn, wr.dept_id, wd.dept_name
|
||||
from work_record wr
|
||||
left join sys_user su on su.user_name = wr.user_name
|
||||
left join sys_dept d on su.dept_id = d.dept_id
|
||||
left join sys_dept wd on wr.dept_id = wd.dept_id
|
||||
where wr.is_alter = 1
|
||||
<if test="status != null and status != ''">
|
||||
and wr.status = #{status}
|
||||
</if>
|
||||
<if test="alterType != null and alterType != ''">
|
||||
and wr.alter_type LIKE CONCAT('%', #{alterType}, '%')
|
||||
and wr.alter_type = #{alterType}
|
||||
</if>
|
||||
<if test="forwardFlag != null and forwardFlag != ''">
|
||||
<choose>
|
||||
<when test='forwardFlag == "1"'>
|
||||
and wr.alter_type in ('个人资产客户定期存款', '个人资产客户封闭式理财')
|
||||
and wr.alter_detail like '[FORWARD=1]%'
|
||||
</when>
|
||||
<when test='forwardFlag == "0"'>
|
||||
and (
|
||||
(wr.alter_type in ('个人资产客户定期存款', '个人资产客户封闭式理财')
|
||||
and wr.alter_detail like '[FORWARD=0]%')
|
||||
or wr.alter_type not in ('个人资产客户定期存款', '个人资产客户封闭式理财')
|
||||
)
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
<!-- "走访异常提醒"类型直接通过用户名匹配,其他类型按角色权限处理 -->
|
||||
and ((wr.alter_type = '走访异常提醒' and wr.user_name = #{username}) or
|
||||
(wr.alter_type != '走访异常提醒' and (
|
||||
<choose>
|
||||
<when test="role != null and role == 'outlet'"> su.dept_id = #{deptId} </when>
|
||||
<when test="role != null and role == 'branch'"> (su.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) </when>
|
||||
<when test="role != null and role == 'private'"> (left(su.dept_id,3) = left(#{deptId},3) and wr.cust_type in ('0', '1')) </when>
|
||||
<when test="role != null and role == 'public'"> (left(su.dept_id,3) = left(#{deptId},3) and wr.cust_type = '2') </when>
|
||||
<when test="role != null and role == 'ops'"> left(su.dept_id,3) = left(#{deptId},3) </when>
|
||||
<when test="role != null and role == 'head'"> left(su.dept_id,3) = left(#{deptId},3) </when>
|
||||
<when test="role != null and role == 'outlet'"> (su.dept_id = #{deptId} or wr.dept_id = #{deptId}) </when>
|
||||
<when test="role != null and role == 'branch'"> ((su.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) or (wr.dept_id = #{deptId} or find_in_set(#{deptId},wd.ancestors))) </when>
|
||||
<when test="role != null and role == 'private'"> ((left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) and wr.cust_type in ('0', '1')) </when>
|
||||
<when test="role != null and role == 'public'"> ((left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) and wr.cust_type = '2') </when>
|
||||
<when test="role != null and role == 'ops'"> (left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) </when>
|
||||
<when test="role != null and role == 'head'"> (left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) </when>
|
||||
</choose> )))
|
||||
order by wr.create_time desc, wr.status asc, wr.user_name desc
|
||||
</select>
|
||||
|
||||
<select id="selectForwardDeptTargets" resultType="AlterAssignTargetVO">
|
||||
select cast(sd.dept_id as char) as targetCode, sd.dept_name as targetName
|
||||
from sys_dept sd
|
||||
where sd.del_flag = '0'
|
||||
and sd.status = '0'
|
||||
and sd.dept_type = 'outlet'
|
||||
and sd.parent_id = #{branchDeptId}
|
||||
order by sd.order_num, sd.dept_id
|
||||
</select>
|
||||
|
||||
<select id="selectForwardUserTargets" resultType="AlterAssignTargetVO">
|
||||
select su.user_name as targetCode, concat(su.nick_name, '-', su.user_name) as targetName
|
||||
from sys_user su
|
||||
where su.del_flag = '0'
|
||||
and su.status = '0'
|
||||
and su.dept_id = #{deptId}
|
||||
<choose>
|
||||
<when test="role == 'manager'">
|
||||
and su.role_id = 102
|
||||
</when>
|
||||
<when test="role == 'branch'">
|
||||
and su.role_id = 101
|
||||
</when>
|
||||
<when test="role == 'outlet'">
|
||||
and su.role_id = 116
|
||||
</when>
|
||||
<otherwise>
|
||||
and 1 = 2
|
||||
</otherwise>
|
||||
</choose>
|
||||
order by su.nick_name, su.user_name
|
||||
</select>
|
||||
|
||||
<update id="updateAlterForwardToDept">
|
||||
update work_record
|
||||
set user_name = null,
|
||||
nick_name = null,
|
||||
dept_id = #{targetDeptId},
|
||||
read_time = null,
|
||||
update_time = sysdate(),
|
||||
update_by = #{updateBy}
|
||||
where id = #{id}
|
||||
and user_name = #{sourceUserName}
|
||||
and dept_id is null
|
||||
and is_alter = 1
|
||||
</update>
|
||||
|
||||
<update id="updateAlterForwardToUserByBranch">
|
||||
update work_record
|
||||
set user_name = #{targetUserName},
|
||||
nick_name = #{targetNickName},
|
||||
alter_detail = case
|
||||
when alter_detail like '[FORWARD=1] %' then concat('[FORWARD=0] ', substring(alter_detail, 13))
|
||||
when alter_detail like '[FORWARD=1]%' then concat('[FORWARD=0]', substring(alter_detail, 12))
|
||||
else alter_detail
|
||||
end,
|
||||
dept_id = null,
|
||||
read_time = null,
|
||||
update_time = sysdate(),
|
||||
update_by = #{updateBy}
|
||||
where id = #{id}
|
||||
and user_name = #{sourceUserName}
|
||||
and dept_id is null
|
||||
and is_alter = 1
|
||||
</update>
|
||||
|
||||
<update id="updateAlterForwardToUserByOutlet">
|
||||
update work_record
|
||||
set user_name = #{targetUserName},
|
||||
nick_name = #{targetNickName},
|
||||
alter_detail = case
|
||||
when alter_detail like '[FORWARD=1] %' then concat('[FORWARD=0] ', substring(alter_detail, 13))
|
||||
when alter_detail like '[FORWARD=1]%' then concat('[FORWARD=0]', substring(alter_detail, 12))
|
||||
else alter_detail
|
||||
end,
|
||||
dept_id = null,
|
||||
read_time = null,
|
||||
update_time = sysdate(),
|
||||
update_by = #{updateBy}
|
||||
where id = #{id}
|
||||
and dept_id = #{sourceDeptId}
|
||||
and user_name is null
|
||||
and is_alter = 1
|
||||
</update>
|
||||
|
||||
<select id="selectAlterConfigList" resultType="AlterConfigVO">
|
||||
select id, alter_type, prod_type, warn_role, warn_threshold, update_time, update_by, type
|
||||
from alter_config
|
||||
@@ -268,4 +373,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<select id="selectAlterTypes" resultType="string">
|
||||
select distinct alter_type
|
||||
from work_record
|
||||
where is_alter = 1
|
||||
and alter_type is not null
|
||||
and alter_type != ''
|
||||
and left(user_name, 3) = #{headId}
|
||||
order by alter_type
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -142,9 +142,61 @@
|
||||
<if test="managerId != null and managerId !='' ">and manager_id = #{managerId}</if>
|
||||
<if test="outletId != null and outletId !='' ">and outlet_id = #{outletId}</if>
|
||||
<if test="branchId != null and branchId !='' ">and branch_id = #{branchId}</if>
|
||||
<if test="statusType != null and statusType !=''">
|
||||
<choose>
|
||||
<when test="statusType == 'current'">
|
||||
<!-- 本月:本月是指定星级的客户 -->
|
||||
and cust_level = #{custLevel}
|
||||
</when>
|
||||
<when test="statusType == 'last'">
|
||||
<!-- 上月:上月是指定星级的客户 -->
|
||||
and cust_level_lm = #{custLevel}
|
||||
</when>
|
||||
<when test="statusType == 'rise'">
|
||||
<!-- 上升:上升到指定星级的客户(本月是指定星级,上月星级更低) -->
|
||||
and cust_level = #{custLevel}
|
||||
and cust_level_comp_lm like '上升%'
|
||||
</when>
|
||||
<when test="statusType == 'fall'">
|
||||
<!-- 下降:从指定星级下降的客户(上月是指定星级,本月星级更低) -->
|
||||
and cust_level_lm = #{custLevel}
|
||||
and cust_level_comp_lm like '下降%'
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="getCustManagerListByPage" resultType="DwbRetailCustLevelManagerDetailVO">
|
||||
select id, outlet_id, outlet_name, branch_id, branch_name, cust_name, cust_idc, cust_isn, cust_age, cust_sex, cust_phone, cust_address, cust_aum_bal,
|
||||
aum_bal_comp_lm, cust_aum_month_avg, cust_level, cust_level_comp_lm, manager_name, manager_id
|
||||
from dwb_retail_cust_level_manager_detail_${headId}
|
||||
<where>
|
||||
<if test="dto.managerId != null and dto.managerId !='' ">and manager_id = #{dto.managerId}</if>
|
||||
<if test="dto.outletId != null and dto.outletId !='' ">and outlet_id = #{dto.outletId}</if>
|
||||
<if test="dto.branchId != null and dto.branchId !='' ">and branch_id = #{dto.branchId}</if>
|
||||
<if test="dto.statusType != null and dto.statusType !=''">
|
||||
<choose>
|
||||
<when test="dto.statusType == 'current'">
|
||||
and cust_level = #{dto.custLevel}
|
||||
</when>
|
||||
<when test="dto.statusType == 'last'">
|
||||
and cust_level_lm = #{dto.custLevel}
|
||||
</when>
|
||||
<when test="dto.statusType == 'rise'">
|
||||
and cust_level = #{dto.custLevel}
|
||||
and cust_level_comp_lm like '上升%'
|
||||
</when>
|
||||
<when test="dto.statusType == 'fall'">
|
||||
and cust_level_lm = #{dto.custLevel}
|
||||
and cust_level_comp_lm like '下降%'
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</where>
|
||||
limit #{offset}, #{pageSize}
|
||||
</select>
|
||||
|
||||
<select id="getCustLevelCount" resultType="Integer">
|
||||
select count(1)
|
||||
from dwb_retail_cust_level_manager_detail
|
||||
@@ -438,6 +490,7 @@
|
||||
select distinct
|
||||
cust_level
|
||||
from dwb_retail_cust_level_manager_detail_875
|
||||
order by cust_level
|
||||
</select>
|
||||
|
||||
<select id="getCustCountByLevel" resultType="int">
|
||||
@@ -482,4 +535,20 @@
|
||||
where manager_id is not null
|
||||
</select>
|
||||
|
||||
<!-- 全量查询绩效网格客户列表(用于客群管户关系匹配,不按客户经理过滤)-->
|
||||
<select id="getAllCustomerListForImport" resultType="GridCmpmVO">
|
||||
select cust_id, cust_type, user_name, nick_name, outlet_id, outlet_name, branch_id, branch_name
|
||||
from grid_cmpm_${gridType}_${headId}
|
||||
</select>
|
||||
|
||||
<!-- 根据客户ID列表查询管户关系(用于动态客群更新管户关系)-->
|
||||
<select id="getRelationshipsByCustList" resultType="GridCmpmVO">
|
||||
select cust_id, cust_type, user_name, nick_name, outlet_id, outlet_name, branch_id, branch_name
|
||||
from grid_cmpm_${gridType}_${headId}
|
||||
where
|
||||
<foreach item="custInfo" collection="custInfoList" separator=" or " open="(" close=")">
|
||||
(cust_id = #{custInfo.custId} and cust_type = #{custInfo.custType})
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -55,8 +55,5 @@
|
||||
<if test="custName != null and custName != ''">AND b.cust_name like concat('%', #{custName}, '%')</if>
|
||||
<if test="custType != null and custType != ''">AND b.cust_type = #{custType}</if>
|
||||
</select>
|
||||
<select id="">
|
||||
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.ibs.draw.mapper.DrawGridShapeRelateMapper">
|
||||
|
||||
<select id="selectByGridId" resultType="com.ruoyi.ibs.draw.domain.entity.DrawGridShapeRelate">
|
||||
SELECT *
|
||||
FROM grid_draw_shape_relate
|
||||
WHERE grid_id = #{gridId}
|
||||
AND delete_flag = '0'
|
||||
</select>
|
||||
|
||||
<select id="selectCustByDrawGridId" resultType="com.ruoyi.ibs.grid.domain.entity.RegionCustUser">
|
||||
SELECT DISTINCT
|
||||
sc.cust_id,
|
||||
sc.cust_name,
|
||||
sc.cust_type
|
||||
FROM grid_draw_shape_relate sr
|
||||
INNER JOIN draw_shape_cust_${headId} sc ON sc.shape_id = sr.shape_id
|
||||
WHERE sr.grid_id = #{gridId}
|
||||
AND sr.delete_flag = '0'
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -21,6 +21,24 @@
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectLsCountListNew825" resultType="com.ruoyi.ibs.grid.domain.entity.GridCmpmCountLingshouNew825">
|
||||
SELECT dt, grid_name, grid_name2, county, town, village, dept_id, dept_name, outlets_id, outlets_name,
|
||||
user_name, cust_num, zf_365cnt, zf_180cnt, zf_90cnt, zf_30cnt, zf_365rt, zf_180rt, zf_90rt,
|
||||
zf_30rt, cur_bal_d, sx_rat, yx_rat, sx_num, yx_num, sx_bal, bal_loan, loan_ave, yxht_rat, dian_rat,
|
||||
shui_rat, tax_rat, open_rat, yxht_num, dian_num, shui_num, tax_num, open_num, dep_bal, fin_bal,
|
||||
grhx_num, cfyx_num, yxxyk_num, yxsbk_num, `2to3_sbk_num` as twoTo3SbkNum, ylj_to_sbk_num,
|
||||
fshl_num, yxsd_num, hxsd_num, region_code, ops_dept
|
||||
FROM grid_cmpm_count_lingshou_new_825
|
||||
<where>
|
||||
<if test=" dt != null and dt != ''">and dt = #{dt}</if>
|
||||
<if test=" town != null and town != ''">and town like concat('%',concat(#{town},'%'))</if>
|
||||
<if test=" village != null and village != ''">and village like concat('%',concat(#{village},'%'))</if>
|
||||
<if test=" isBranch == true">and dept_id like concat('%',concat(#{deptId},'%'))</if>
|
||||
<if test=" isOutlet == true">and outlets_id like concat('%',concat(#{deptId},'%'))</if>
|
||||
<if test=" isManager == true">and user_name like concat('%',concat(#{userName},'%'))</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectGsCountList" resultType="com.ruoyi.ibs.grid.domain.entity.GridCmpmCountGongsi">
|
||||
SELECT dt, grid_name, grid_name2, town, dept_id,dept_name, outlets_id,outlets_name, user_name,
|
||||
cust_num, hq_cur_balance, bz_cur_balance, loan_balance_cny, finance_prod_711_balance,ustr_count_per_m,ustr_bal_m,
|
||||
@@ -59,6 +77,47 @@
|
||||
<if test=" custIdc != null and custIdc != ''">and cust_idc like concat('%',concat(#{custIdc},'%'))</if>
|
||||
</select>
|
||||
|
||||
<select id="selectLsCustListNew825" resultType="com.ruoyi.ibs.grid.domain.entity.GridCustCountLingshouNew825">
|
||||
SELECT cust_name,
|
||||
cust_idc,
|
||||
cust_isn,
|
||||
cur_bal_d,
|
||||
bal_loan,
|
||||
loan_ave,
|
||||
is_sx,
|
||||
is_yx,
|
||||
sx_bal,
|
||||
is_yxht,
|
||||
is_xyk,
|
||||
fshl,
|
||||
is_sd,
|
||||
dian,
|
||||
shui,
|
||||
tax,
|
||||
open_num,
|
||||
dep_bal,
|
||||
fin_bal,
|
||||
is_grhx,
|
||||
is_cfyx,
|
||||
is_yxsbk,
|
||||
is_2to3_sbk,
|
||||
is_ylj_to_sbk,
|
||||
is_hxsd,
|
||||
region_code,
|
||||
ops_dept,
|
||||
cust_type,
|
||||
is_365zf,
|
||||
is_180zf,
|
||||
is_90zf,
|
||||
is_30zf,
|
||||
dt
|
||||
FROM grid_cust_count_lingshou_new_825
|
||||
where region_code = #{regionCode}
|
||||
<if test=" dt != null and dt != ''">and dt = #{dt}</if>
|
||||
<if test=" custName != null and custName != ''">and cust_name like concat('%',concat(#{custName},'%'))</if>
|
||||
<if test=" custIdc != null and custIdc != ''">and cust_idc like concat('%',concat(#{custIdc},'%'))</if>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectGsCustList" resultType="com.ruoyi.ibs.grid.domain.entity.GridCustCountGongsi">
|
||||
SELECT cust_name, social_credit_code, cust_isn, hq_cur_balance, bz_cur_balance, is_credit,
|
||||
|
||||
@@ -121,4 +121,30 @@
|
||||
WHERE sec_grid_id = #{gridId}
|
||||
AND cust_type = #{custType}
|
||||
</select>
|
||||
|
||||
<!-- 根据网格ID列表查询所有客户(一级或二级网格) -->
|
||||
<select id="selectAllCustByGridIds" resultType="RegionCustUser">
|
||||
SELECT DISTINCT cust_id, cust_name, cust_type
|
||||
FROM grid_region_cust_user_${headId}
|
||||
WHERE (top_grid_id IN
|
||||
<foreach collection="gridIds" item="gridId" index="index" open="(" separator="," close=")">
|
||||
#{gridId}
|
||||
</foreach>
|
||||
OR sec_grid_id IN
|
||||
<foreach collection="gridIds" item="gridId" index="index" open="(" separator="," close=")">
|
||||
#{gridId}
|
||||
</foreach>)
|
||||
</select>
|
||||
|
||||
<!-- 根据绘制网格ID查询所有客户(用于客群导入,直接拼接headId绕过拦截器) -->
|
||||
<select id="selectCustByDrawGridId" resultType="RegionCustUser">
|
||||
SELECT DISTINCT
|
||||
sc.cust_id,
|
||||
sc.cust_name,
|
||||
sc.cust_type
|
||||
FROM grid_draw_shape_relate sr
|
||||
LEFT JOIN draw_shape_cust_${headId} sc ON sc.shape_id = sr.shape_id
|
||||
WHERE sr.grid_id = #{gridId}
|
||||
AND sr.delete_flag = '0'
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -339,4 +339,26 @@
|
||||
<select id="getSecGridIdByTopGridId" resultType="Long">
|
||||
select grid_id from grid_region_grid where parent_grid_id = #{gridId} and grid_level = '2' and delete_flag = '0'
|
||||
</select>
|
||||
|
||||
<!-- 查询地理网格列表(简化版)- 专用于客群创建 -->
|
||||
<select id="getRegionGridListForGroup" parameterType="RegionGridListDTO" resultType="RegionGridGroupVO">
|
||||
select distinct a.grid_id, a.grid_name
|
||||
from grid_region_grid a
|
||||
left join grid_region_user_relate c on c.grid_id = a.grid_id
|
||||
where a.delete_flag = '0'
|
||||
and c.delete_flag = '0'
|
||||
and a.grid_level = #{gridLevel}
|
||||
and (a.dept_id in (select dept_id from sys_dept where dept_id = #{deptId} or find_in_set(#{deptId}, ancestors))
|
||||
or c.relate_dept_id in (select dept_id from sys_dept where dept_id = #{deptId} or find_in_set(#{deptId}, ancestors)))
|
||||
<if test="opsDept != null and opsDept != ''">
|
||||
and a.ops_dept = #{opsDept}
|
||||
</if>
|
||||
<if test="gridDutyType != null and gridDutyType != ''">
|
||||
and a.grid_duty_type = #{gridDutyType}
|
||||
</if>
|
||||
<if test="gridName != null and gridName != ''">
|
||||
and a.grid_name like concat('%', #{gridName}, '%')
|
||||
</if>
|
||||
ORDER BY a.grid_name
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -239,17 +239,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
case when left(vc.campaign_id,7)='appoint' then '-1' else sc.create_role end as create_role ,
|
||||
|
||||
case
|
||||
when dep2.dept_type = 'head' then dep.dept_id
|
||||
else dep2.dept_id
|
||||
when hist_branch_dep.dept_id is not null then hist_branch_dep.dept_id
|
||||
when current_branch_dep.dept_type = 'head' or current_branch_dep.dept_type is null then current_outlet_dep.dept_id
|
||||
else current_branch_dep.dept_id
|
||||
end as dept_id,
|
||||
case
|
||||
when dep2.dept_type = 'head' then ''
|
||||
else dep.dept_name
|
||||
when hist_branch_dep.dept_id is not null then ifnull(hist_outlet_dep.dept_name, '')
|
||||
when current_branch_dep.dept_type = 'head' or current_branch_dep.dept_type is null then ''
|
||||
else current_outlet_dep.dept_name
|
||||
end as outlets,
|
||||
|
||||
case
|
||||
when dep2.dept_type = 'head' then dep.dept_name
|
||||
else dep2.dept_name
|
||||
when hist_branch_dep.dept_id is not null then hist_branch_dep.dept_name
|
||||
when current_branch_dep.dept_type = 'head' or current_branch_dep.dept_type is null then current_outlet_dep.dept_name
|
||||
else current_branch_dep.dept_name
|
||||
end as dept_name,
|
||||
|
||||
concat( su.nick_name, '-', su.user_name ) as nick_name,
|
||||
@@ -261,25 +264,48 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
visit_campaign_count vc left join sys_campaign sc on
|
||||
vc.campaign_id = sc.campaign_id left join sys_user su on
|
||||
vc.dept_id = su.user_name
|
||||
left join sys_dept dep on su.dept_id = dep.dept_id
|
||||
left join sys_dept dep2 on dep.parent_id = dep2.dept_id
|
||||
left join (
|
||||
select campaign_id, user_id, max(dept_id) as dept_id, max(outlets_id) as outlets_id
|
||||
from sys_campaign_group_customer
|
||||
where user_id is not null
|
||||
group by campaign_id, user_id
|
||||
) scgc_his on scgc_his.campaign_id = vc.campaign_id and scgc_his.user_id = su.user_id
|
||||
left join sys_dept hist_branch_dep on scgc_his.dept_id = hist_branch_dep.dept_id
|
||||
left join sys_dept hist_outlet_dep on scgc_his.outlets_id = hist_outlet_dep.dept_id
|
||||
left join sys_dept current_outlet_dep on su.dept_id = current_outlet_dep.dept_id
|
||||
left join sys_dept current_branch_dep on current_outlet_dep.parent_id = current_branch_dep.dept_id
|
||||
where
|
||||
vc.dept_type = '3'
|
||||
<if test="campaignId != null and campaignId != ''"> and vc.campaign_id = #{campaignId}</if>
|
||||
<if test="campaignName != null and campaignName != ''"> AND sc.campaign_name like concat('%', #{campaignName}, '%')</if>
|
||||
<choose>
|
||||
<when test="outletsId != null">
|
||||
AND (dep.dept_id = #{outletsId} OR dep2.dept_id = #{outletsId})
|
||||
AND ifnull(
|
||||
scgc_his.outlets_id,
|
||||
case
|
||||
when current_branch_dep.dept_type = 'head' or current_branch_dep.dept_type is null then null
|
||||
else current_outlet_dep.dept_id
|
||||
end
|
||||
) = #{outletsId}
|
||||
</when>
|
||||
<otherwise>
|
||||
<if test="deptId != null and personType == 'branch' and deptId.toString().endsWith('000')">
|
||||
AND dep.dept_id = #{deptId}
|
||||
</if>
|
||||
<if test="deptId != null and personType == 'branch'">
|
||||
AND (dep.dept_id = #{deptId} OR dep2.dept_id = #{deptId})
|
||||
AND ifnull(
|
||||
scgc_his.dept_id,
|
||||
case
|
||||
when current_branch_dep.dept_type = 'head' or current_branch_dep.dept_type is null then current_outlet_dep.dept_id
|
||||
else current_branch_dep.dept_id
|
||||
end
|
||||
) = #{deptId}
|
||||
</if>
|
||||
<if test="deptId != null and personType == 'outlet'">
|
||||
AND (dep.dept_id = #{deptId})
|
||||
AND ifnull(
|
||||
scgc_his.outlets_id,
|
||||
case
|
||||
when current_branch_dep.dept_type = 'head' or current_branch_dep.dept_type is null then null
|
||||
else current_outlet_dep.dept_id
|
||||
end
|
||||
) = #{deptId}
|
||||
</if>
|
||||
</otherwise>
|
||||
</choose>
|
||||
|
||||
@@ -127,6 +127,18 @@
|
||||
<result property="remark" column="remark" />
|
||||
<result property="custType" column="cust_type" />
|
||||
<result property="deptName" column="dept_name" />
|
||||
<result property="interAddr" column="inter_addr" />
|
||||
<result property="colStafName" column="col_staf_name" />
|
||||
<result property="laterNote" column="later_note" />
|
||||
<result property="intentionProductValue" column="intention_product_value" />
|
||||
<result property="feedbackStatus" column="feedback_status" />
|
||||
<result property="sourceOfInterview" column="source_of_interview" />
|
||||
<result property="filename" column="filename" />
|
||||
<result property="outCallStatus" column="out_call_status" />
|
||||
<result property="outCallIntention" column="out_call_intention" />
|
||||
<result property="source" column="source" />
|
||||
<result property="analysisValue" column="analysis_value" />
|
||||
<result property="facility" column="facility" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectSysCampaignVo">
|
||||
@@ -1388,8 +1400,10 @@
|
||||
from visit_info vi
|
||||
left join sys_dept d on vi.dept_id = d.dept_id
|
||||
<where>
|
||||
<if test="campaignId != null and campaignId != ''"> and vi.campaign_id = #{campaignId}</if>
|
||||
<if test="custType != null and custType != ''"> and vi.cust_type = #{custType}</if>
|
||||
<if test="visName != null and visName != ''"> and vi.vis_name like concat('%', #{visName}, '%')</if>
|
||||
<if test="visId != null and visId != ''"> and vi.vis_id = #{visId}</if>
|
||||
<if test="custIdc != null and custIdc != ''"> and vi.cust_idc = #{custIdc}</if>
|
||||
<if test="socialCreditCode != null and socialCreditCode != ''"> and vi.social_credit_code = #{socialCreditCode}</if>
|
||||
<if test="abnormalVisitTag != null and abnormalVisitTag != ''"> and vi.abnormal_visit_tag = #{abnormalVisitTag}</if>
|
||||
@@ -1410,4 +1424,57 @@
|
||||
order by vi.sign_in_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectVisitInfoList875" parameterType="VisitInfoDTO" resultType="VisitInfoVO">
|
||||
select vi.id,vi.campaign_id,vi.campaign_name,vi.vis_name,vi.vis_id,vi.dept_id,d.dept_name,vi.vis_time,vi.cust_name,vi.cust_type,vi.cust_idc,
|
||||
vi.social_credit_code,vi.create_by,vi.create_time,vi.update_by,vi.update_time,vi.remark,vi.sign_in_time,vi.sign_out_time,vi.sign_in_address,
|
||||
vi.sign_out_address,vi.abnormal_visit_tag,vi.abnormal_visit_info,vi.sign_in_coordinate,vi.sign_out_coordinate,vi.is_valid_cust,vi.marketing_way,vi.inter_res,
|
||||
vi.inter_addr,vi.col_staf_name,vi.later_note,vi.intention_product_value,vi.feedback_status,vi.source_of_interview,vi.filename,
|
||||
vi.out_call_status,vi.out_call_intention,vi.source,vi.analysis_value,vi.facility
|
||||
from visit_info_875 vi
|
||||
left join sys_dept d on vi.dept_id = d.dept_id
|
||||
<where>
|
||||
<if test="campaignId != null and campaignId != ''"> and vi.campaign_id = #{campaignId}</if>
|
||||
<if test="custType != null and custType != ''"> and vi.cust_type = #{custType}</if>
|
||||
<if test="visName != null and visName != ''"> and vi.vis_name like concat('%', #{visName}, '%')</if>
|
||||
<if test="visId != null and visId != ''"> and vi.vis_id = #{visId}</if>
|
||||
<if test="custIdc != null and custIdc != ''"> and vi.cust_idc = #{custIdc}</if>
|
||||
<if test="socialCreditCode != null and socialCreditCode != ''"> and vi.social_credit_code = #{socialCreditCode}</if>
|
||||
<if test="abnormalVisitTag != null and abnormalVisitTag != ''"> and vi.abnormal_visit_tag = #{abnormalVisitTag}</if>
|
||||
<if test="marketingWay != null and marketingWay != ''"> and vi.marketing_way = #{marketingWay}</if>
|
||||
<if test="interRes != null and interRes != ''"> and vi.inter_res = #{interRes}</if>
|
||||
<if test="visTime != null">
|
||||
and (vi.sign_in_time like concat(#{visTime}, '%') or vi.sign_out_time like concat(#{visTime}, '%'))
|
||||
</if>
|
||||
<if test="userRole != null">
|
||||
<choose>
|
||||
<when test="userRole == 'manager'"> and vi.vis_id = #{userName} </when>
|
||||
<when test="userRole == 'outlet'"> and d.dept_id = #{deptId} </when>
|
||||
<when test="userRole == 'branch'"> and (d.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) </when>
|
||||
<when test="userRole in {'head', 'ops', 'public', 'private'}"> and left(d.dept_id,3) = left(#{deptId},3) </when>
|
||||
</choose>
|
||||
</if>
|
||||
</where>
|
||||
order by vi.sign_in_time desc
|
||||
</select>
|
||||
|
||||
<update id="updateVisitInfoFeedback" parameterType="VisitInfoFeedbackUpdateDTO">
|
||||
update visit_info_875 vi
|
||||
left join sys_dept d on vi.dept_id = d.dept_id
|
||||
set vi.source = #{source},
|
||||
vi.remark = #{remark},
|
||||
vi.intention_product_value = #{intentionProductValue},
|
||||
vi.inter_res = '0',
|
||||
vi.update_by = #{userName},
|
||||
vi.update_time = sysdate()
|
||||
where vi.id = #{id}
|
||||
<if test="userRole != null">
|
||||
<choose>
|
||||
<when test="userRole == 'manager'"> and vi.vis_id = #{userName} </when>
|
||||
<when test="userRole == 'outlet'"> and d.dept_id = #{deptId} </when>
|
||||
<when test="userRole == 'branch'"> and (d.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) </when>
|
||||
<when test="userRole in {'head', 'ops', 'public', 'private'}"> and left(d.dept_id,3) = left(#{deptId},3) </when>
|
||||
</choose>
|
||||
</if>
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
8
pom.xml
8
pom.xml
@@ -215,6 +215,13 @@
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 数字支行-客群模块 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ibs-group</artifactId>
|
||||
<version>3.8.8</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -226,6 +233,7 @@
|
||||
<module>ruoyi-generator</module>
|
||||
<module>ruoyi-common</module>
|
||||
<module>ibs</module>
|
||||
<module>ibs-group</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
||||
@@ -74,6 +74,13 @@
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 客群管理-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ibs-group</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -28,6 +28,10 @@ spring:
|
||||
username: root
|
||||
password: Kfcx@1234
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://rm-bp17634n45cj631s0ao.mysql.rds.aliyuncs.com/ibs?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
|
||||
# username: znsj
|
||||
# password: Znsj@123456
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
@@ -78,12 +82,14 @@ spring:
|
||||
redis:
|
||||
# 地址
|
||||
host: 116.62.17.81
|
||||
# host: r-bp1mmtcknvsscsrjrypd.redis.rds.aliyuncs.com
|
||||
# 端口,默认为6379
|
||||
port: 6380
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
password: Kfcx@1234
|
||||
# password: N0f3d12c4a927eee1+
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
lettuce:
|
||||
@@ -121,5 +127,9 @@ oss:
|
||||
accessKeyId: LTAI5tMsUgorcgnpTxZDV1wS
|
||||
accessKeySecret: c7qIjXIPx8Cz2CriJpYGyCFwFjRxeB
|
||||
bucketName: oss-wkc
|
||||
# endpoint: oss-cn-hangzhou.aliyuncs.comBucket:znjgoss.oss-cn-hangzhou.aliyuncs.com
|
||||
# accessKeyId: LTAI5tCRocKhQaCtFnYKp46w
|
||||
# accessKeySecret: 0ovFbMQWas1wOZTG91mpKbV70JgR32
|
||||
# bucketName: oss-wkc
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user