Showing
20 changed files
with
447 additions
and
16 deletions
xingyun-sc/src/main/java/com/lframework/xingyun/sc/events/quotation/CommonChangedEvent.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/events/quotation/SalesmanQuotationPeerChangedEvent.java
| @@ -4,15 +4,15 @@ import lombok.Getter; | @@ -4,15 +4,15 @@ import lombok.Getter; | ||
| 4 | import org.springframework.context.ApplicationEvent; | 4 | import org.springframework.context.ApplicationEvent; |
| 5 | 5 | ||
| 6 | /** | 6 | /** |
| 7 | - * 同行报价信息变更事件 | 7 | + * 变更事件 |
| 8 | */ | 8 | */ |
| 9 | @Getter | 9 | @Getter |
| 10 | -public class SalesmanQuotationPeerChangedEvent extends ApplicationEvent { | 10 | +public class CommonChangedEvent extends ApplicationEvent { |
| 11 | 11 | ||
| 12 | private static final long serialVersionUID = 1L; | 12 | private static final long serialVersionUID = 1L; |
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | - * 同行报价信息ID | 15 | + * 业务主键ID |
| 16 | */ | 16 | */ |
| 17 | private final String id; | 17 | private final String id; |
| 18 | 18 | ||
| @@ -21,7 +21,7 @@ public class SalesmanQuotationPeerChangedEvent extends ApplicationEvent { | @@ -21,7 +21,7 @@ public class SalesmanQuotationPeerChangedEvent extends ApplicationEvent { | ||
| 21 | */ | 21 | */ |
| 22 | private final String eventType; | 22 | private final String eventType; |
| 23 | 23 | ||
| 24 | - public SalesmanQuotationPeerChangedEvent(Object source, String id, String eventType) { | 24 | + public CommonChangedEvent(Object source, String id, String eventType) { |
| 25 | super(source); | 25 | super(source); |
| 26 | this.id = id; | 26 | this.id = id; |
| 27 | this.eventType = eventType; | 27 | this.eventType = eventType; |
| 1 | +package com.lframework.xingyun.sc.listeners.app; | ||
| 2 | + | ||
| 3 | +import com.lframework.xingyun.sc.events.quotation.CommonChangedEvent; | ||
| 4 | +import com.lframework.xingyun.sc.procurement.websocket.quotation.line.SalesmanQuotationLineRealtimePushService; | ||
| 5 | +import org.springframework.stereotype.Component; | ||
| 6 | +import org.springframework.transaction.event.TransactionPhase; | ||
| 7 | +import org.springframework.transaction.event.TransactionalEventListener; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 业务员报价实时推送监听器 | ||
| 13 | + */ | ||
| 14 | +@Component | ||
| 15 | +public class SalesmanQuotationLineRealtimeListener { | ||
| 16 | + | ||
| 17 | + @Resource | ||
| 18 | + private SalesmanQuotationLineRealtimePushService realtimePushService; | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 业务员报价信息变更后广播当日完整数据 | ||
| 22 | + * | ||
| 23 | + * @param event 变更事件 | ||
| 24 | + */ | ||
| 25 | + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) | ||
| 26 | + public void handleChanged(CommonChangedEvent event) { | ||
| 27 | + realtimePushService.broadcastCurrentDayFullData(event.getEventType()); | ||
| 28 | + } | ||
| 29 | +} |
| 1 | package com.lframework.xingyun.sc.listeners.app; | 1 | package com.lframework.xingyun.sc.listeners.app; |
| 2 | 2 | ||
| 3 | -import com.lframework.xingyun.sc.events.quotation.SalesmanQuotationPeerChangedEvent; | ||
| 4 | -import com.lframework.xingyun.sc.procurement.websocket.quotation.SalesmanQuotationPeerRealtimePushService; | 3 | +import com.lframework.xingyun.sc.events.quotation.CommonChangedEvent; |
| 4 | +import com.lframework.xingyun.sc.procurement.websocket.quotation.peer.SalesmanQuotationPeerRealtimePushService; | ||
| 5 | import javax.annotation.Resource; | 5 | import javax.annotation.Resource; |
| 6 | import org.springframework.stereotype.Component; | 6 | import org.springframework.stereotype.Component; |
| 7 | import org.springframework.transaction.event.TransactionPhase; | 7 | import org.springframework.transaction.event.TransactionPhase; |
| @@ -22,7 +22,7 @@ public class SalesmanQuotationPeerRealtimeListener { | @@ -22,7 +22,7 @@ public class SalesmanQuotationPeerRealtimeListener { | ||
| 22 | * @param event 变更事件 | 22 | * @param event 变更事件 |
| 23 | */ | 23 | */ |
| 24 | @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) | 24 | @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) |
| 25 | - public void handleChanged(SalesmanQuotationPeerChangedEvent event) { | 25 | + public void handleChanged(CommonChangedEvent event) { |
| 26 | realtimePushService.broadcastCurrentDayFullData(event.getEventType()); | 26 | realtimePushService.broadcastCurrentDayFullData(event.getEventType()); |
| 27 | } | 27 | } |
| 28 | } | 28 | } |
| 1 | +package com.lframework.xingyun.sc.procurement.dto.quotation; | ||
| 2 | + | ||
| 3 | +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.io.Serializable; | ||
| 7 | +import java.time.LocalDate; | ||
| 8 | +import java.time.LocalDateTime; | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 业务员报价实时推送消息 | ||
| 13 | + */ | ||
| 14 | +@Data | ||
| 15 | +public class QuotationLineRealtimeMessage implements Serializable { | ||
| 16 | + | ||
| 17 | + private static final long serialVersionUID = 1L; | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 消息类型 | ||
| 21 | + */ | ||
| 22 | + private String messageType; | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 事件类型 | ||
| 26 | + */ | ||
| 27 | + private String eventType; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 业务日期 | ||
| 31 | + */ | ||
| 32 | + private LocalDate businessDate; | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 推送时间 | ||
| 36 | + */ | ||
| 37 | + private LocalDateTime pushTime; | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 数据列表 | ||
| 41 | + */ | ||
| 42 | + private List<SalesmanQuotationLine> records; | ||
| 43 | +} |
| @@ -90,6 +90,24 @@ public class SalesmanQuotationLine extends BaseEntity implements BaseDto { | @@ -90,6 +90,24 @@ public class SalesmanQuotationLine extends BaseEntity implements BaseDto { | ||
| 90 | private String itemId; | 90 | private String itemId; |
| 91 | 91 | ||
| 92 | /** | 92 | /** |
| 93 | + * 报价时间 | ||
| 94 | + */ | ||
| 95 | + @TableField(exist = false) | ||
| 96 | + private String quoteTime; | ||
| 97 | + | ||
| 98 | + /** | ||
| 99 | + * 业务员 | ||
| 100 | + */ | ||
| 101 | + @TableField(exist = false) | ||
| 102 | + private String quoterName; | ||
| 103 | + | ||
| 104 | + /** | ||
| 105 | + * 供应商名称 | ||
| 106 | + */ | ||
| 107 | + @TableField(exist = false) | ||
| 108 | + private String supplierName; | ||
| 109 | + | ||
| 110 | + /** | ||
| 93 | * 创建人ID | 111 | * 创建人ID |
| 94 | */ | 112 | */ |
| 95 | @TableField(fill = FieldFill.INSERT) | 113 | @TableField(fill = FieldFill.INSERT) |
| @@ -16,6 +16,7 @@ import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotatio | @@ -16,6 +16,7 @@ import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotatio | ||
| 16 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; | 16 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; |
| 17 | import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo; | 17 | import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo; |
| 18 | import java.io.Serializable; | 18 | import java.io.Serializable; |
| 19 | +import java.time.LocalDate; | ||
| 19 | import java.util.List; | 20 | import java.util.List; |
| 20 | import org.apache.commons.lang3.StringUtils; | 21 | import org.apache.commons.lang3.StringUtils; |
| 21 | import org.springframework.stereotype.Service; | 22 | import org.springframework.stereotype.Service; |
| @@ -41,6 +42,17 @@ public class SalesmanQuotationLineServiceImpl | @@ -41,6 +42,17 @@ public class SalesmanQuotationLineServiceImpl | ||
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | /** | 44 | /** |
| 45 | + * 查询指定日期创建的业务员报价明细 | ||
| 46 | + * | ||
| 47 | + * @param day 日期 | ||
| 48 | + * @return 业务员报价明细列表 | ||
| 49 | + */ | ||
| 50 | + @Override | ||
| 51 | + public List<SalesmanQuotationLine> queryCurrentDayList(LocalDate day) { | ||
| 52 | + return getBaseMapper().queryCurrentDayList(day); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + /** | ||
| 44 | * 根据ID查询 | 56 | * 根据ID查询 |
| 45 | * | 57 | * |
| 46 | * @param id 主键ID | 58 | * @param id 主键ID |
| @@ -16,7 +16,7 @@ import com.lframework.starter.web.core.utils.PageResultUtil; | @@ -16,7 +16,7 @@ import com.lframework.starter.web.core.utils.PageResultUtil; | ||
| 16 | import com.lframework.starter.web.inner.components.oplog.OtherOpLogType; | 16 | import com.lframework.starter.web.inner.components.oplog.OtherOpLogType; |
| 17 | import com.lframework.xingyun.basedata.entity.BreedRelationship; | 17 | import com.lframework.xingyun.basedata.entity.BreedRelationship; |
| 18 | import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; | 18 | import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; |
| 19 | -import com.lframework.xingyun.sc.events.quotation.SalesmanQuotationPeerChangedEvent; | 19 | +import com.lframework.xingyun.sc.events.quotation.CommonChangedEvent; |
| 20 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationPeer; | 20 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationPeer; |
| 21 | import com.lframework.xingyun.sc.procurement.mappers.quotation.SalesmanQuotationPeerMapper; | 21 | import com.lframework.xingyun.sc.procurement.mappers.quotation.SalesmanQuotationPeerMapper; |
| 22 | import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationPeerService; | 22 | import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationPeerService; |
| @@ -183,6 +183,6 @@ public class SalesmanQuotationPeerServiceImpl | @@ -183,6 +183,6 @@ public class SalesmanQuotationPeerServiceImpl | ||
| 183 | * @param eventType 事件类型 | 183 | * @param eventType 事件类型 |
| 184 | */ | 184 | */ |
| 185 | private void publishChangedEvent(String id, String eventType) { | 185 | private void publishChangedEvent(String id, String eventType) { |
| 186 | - applicationEventPublisher.publishEvent(new SalesmanQuotationPeerChangedEvent(this, id, eventType)); | 186 | + applicationEventPublisher.publishEvent(new CommonChangedEvent(this, id, eventType)); |
| 187 | } | 187 | } |
| 188 | } | 188 | } |
| @@ -29,6 +29,7 @@ import com.lframework.starter.web.inner.service.system.SysUserService; | @@ -29,6 +29,7 @@ import com.lframework.starter.web.inner.service.system.SysUserService; | ||
| 29 | import com.lframework.xingyun.basedata.entity.BreedRelationship; | 29 | import com.lframework.xingyun.basedata.entity.BreedRelationship; |
| 30 | import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; | 30 | import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; |
| 31 | import com.lframework.xingyun.sc.enums.CustomerDevelopStatus; | 31 | import com.lframework.xingyun.sc.enums.CustomerDevelopStatus; |
| 32 | +import com.lframework.xingyun.sc.events.quotation.CommonChangedEvent; | ||
| 32 | import com.lframework.xingyun.sc.procurement.entity.ProcurementDomesticCustomerCredit; | 33 | import com.lframework.xingyun.sc.procurement.entity.ProcurementDomesticCustomerCredit; |
| 33 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotation; | 34 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotation; |
| 34 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; | 35 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; |
| @@ -57,6 +58,7 @@ import java.util.Objects; | @@ -57,6 +58,7 @@ import java.util.Objects; | ||
| 57 | import java.util.Set; | 58 | import java.util.Set; |
| 58 | import java.util.stream.Collectors; | 59 | import java.util.stream.Collectors; |
| 59 | import org.apache.commons.lang3.StringUtils; | 60 | import org.apache.commons.lang3.StringUtils; |
| 61 | +import org.springframework.context.ApplicationEventPublisher; | ||
| 60 | import org.springframework.stereotype.Service; | 62 | import org.springframework.stereotype.Service; |
| 61 | import org.springframework.transaction.annotation.Transactional; | 63 | import org.springframework.transaction.annotation.Transactional; |
| 62 | import javax.annotation.Resource; | 64 | import javax.annotation.Resource; |
| @@ -88,6 +90,8 @@ public class SalesmanQuotationServiceImpl | @@ -88,6 +90,8 @@ public class SalesmanQuotationServiceImpl | ||
| 88 | private SalesmanQuotationLineService salesmanQuotationLineService; | 90 | private SalesmanQuotationLineService salesmanQuotationLineService; |
| 89 | @Resource | 91 | @Resource |
| 90 | private SysRoleService sysRoleService; | 92 | private SysRoleService sysRoleService; |
| 93 | + @Resource | ||
| 94 | + private ApplicationEventPublisher applicationEventPublisher; | ||
| 91 | 95 | ||
| 92 | /** | 96 | /** |
| 93 | * 编号前缀 | 97 | * 编号前缀 |
| @@ -304,6 +308,7 @@ public class SalesmanQuotationServiceImpl | @@ -304,6 +308,7 @@ public class SalesmanQuotationServiceImpl | ||
| 304 | .set(SalesmanQuotation::getStatus, "QUOTED") | 308 | .set(SalesmanQuotation::getStatus, "QUOTED") |
| 305 | .eq(SalesmanQuotation::getId, id); | 309 | .eq(SalesmanQuotation::getId, id); |
| 306 | getBaseMapper().update(wrapper); | 310 | getBaseMapper().update(wrapper); |
| 311 | + publishChangedEvent(id, "CREATE"); | ||
| 307 | } else { | 312 | } else { |
| 308 | Wrapper<SalesmanQuotation> wrapper = Wrappers.lambdaUpdate(SalesmanQuotation.class) | 313 | Wrapper<SalesmanQuotation> wrapper = Wrappers.lambdaUpdate(SalesmanQuotation.class) |
| 309 | .set(SalesmanQuotation::getApprovalStatus, approvalStatus) | 314 | .set(SalesmanQuotation::getApprovalStatus, approvalStatus) |
| @@ -730,6 +735,17 @@ public class SalesmanQuotationServiceImpl | @@ -730,6 +735,17 @@ public class SalesmanQuotationServiceImpl | ||
| 730 | } | 735 | } |
| 731 | } | 736 | } |
| 732 | 737 | ||
| 738 | + | ||
| 739 | + /** | ||
| 740 | + * 发布业务员报价信息变更事件 | ||
| 741 | + * | ||
| 742 | + * @param id 主键ID | ||
| 743 | + * @param eventType 事件类型 | ||
| 744 | + */ | ||
| 745 | + private void publishChangedEvent(String id, String eventType) { | ||
| 746 | + applicationEventPublisher.publishEvent(new CommonChangedEvent(this, id, eventType)); | ||
| 747 | + } | ||
| 748 | + | ||
| 733 | /** | 749 | /** |
| 734 | * 清理缓存 | 750 | * 清理缓存 |
| 735 | * | 751 | * |
| @@ -3,6 +3,7 @@ package com.lframework.xingyun.sc.procurement.mappers.quotation; | @@ -3,6 +3,7 @@ package com.lframework.xingyun.sc.procurement.mappers.quotation; | ||
| 3 | import com.lframework.starter.web.core.mapper.BaseMapper; | 3 | import com.lframework.starter.web.core.mapper.BaseMapper; |
| 4 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; | 4 | import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; |
| 5 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; | 5 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; |
| 6 | +import java.time.LocalDate; | ||
| 6 | import java.util.List; | 7 | import java.util.List; |
| 7 | import org.apache.ibatis.annotations.Param; | 8 | import org.apache.ibatis.annotations.Param; |
| 8 | 9 | ||
| @@ -18,4 +19,12 @@ public interface SalesmanQuotationLineMapper extends BaseMapper<SalesmanQuotatio | @@ -18,4 +19,12 @@ public interface SalesmanQuotationLineMapper extends BaseMapper<SalesmanQuotatio | ||
| 18 | * @return 明细列表 | 19 | * @return 明细列表 |
| 19 | */ | 20 | */ |
| 20 | List<SalesmanQuotationLine> query(@Param("vo") QuerySalesmanQuotationLineVo vo); | 21 | List<SalesmanQuotationLine> query(@Param("vo") QuerySalesmanQuotationLineVo vo); |
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 查询指定日期创建的业务员报价明细 | ||
| 25 | + * | ||
| 26 | + * @param day 日期 | ||
| 27 | + * @return 业务员报价明细表列表 | ||
| 28 | + */ | ||
| 29 | + List<SalesmanQuotationLine> queryCurrentDayList(@Param("day") LocalDate day); | ||
| 21 | } | 30 | } |
| @@ -5,6 +5,7 @@ import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; | @@ -5,6 +5,7 @@ import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; | ||
| 5 | import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationLineVo; | 5 | import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationLineVo; |
| 6 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; | 6 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo; |
| 7 | import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo; | 7 | import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo; |
| 8 | +import java.time.LocalDate; | ||
| 8 | import java.util.List; | 9 | import java.util.List; |
| 9 | 10 | ||
| 10 | /** | 11 | /** |
| @@ -21,6 +22,14 @@ public interface SalesmanQuotationLineService extends BaseMpService<SalesmanQuot | @@ -21,6 +22,14 @@ public interface SalesmanQuotationLineService extends BaseMpService<SalesmanQuot | ||
| 21 | List<SalesmanQuotationLine> query(QuerySalesmanQuotationLineVo vo); | 22 | List<SalesmanQuotationLine> query(QuerySalesmanQuotationLineVo vo); |
| 22 | 23 | ||
| 23 | /** | 24 | /** |
| 25 | + * 查询指定日期创建的业务员报价明细 | ||
| 26 | + * | ||
| 27 | + * @param day 日期 | ||
| 28 | + * @return 业务员报价明细列表 | ||
| 29 | + */ | ||
| 30 | + List<SalesmanQuotationLine> queryCurrentDayList(LocalDate day); | ||
| 31 | + | ||
| 32 | + /** | ||
| 24 | * 根据ID查询 | 33 | * 根据ID查询 |
| 25 | * | 34 | * |
| 26 | * @param id 主键ID | 35 | * @param id 主键ID |
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/CommonWebSocketAuthService.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerWebSocketAuthService.java
| @@ -8,10 +8,10 @@ import javax.annotation.Resource; | @@ -8,10 +8,10 @@ import javax.annotation.Resource; | ||
| 8 | import org.springframework.stereotype.Service; | 8 | import org.springframework.stereotype.Service; |
| 9 | 9 | ||
| 10 | /** | 10 | /** |
| 11 | - * 同行报价信息 WebSocket 鉴权服务 | 11 | + * WebSocket 鉴权服务 |
| 12 | */ | 12 | */ |
| 13 | @Service | 13 | @Service |
| 14 | -public class SalesmanQuotationPeerWebSocketAuthService { | 14 | +public class CommonWebSocketAuthService { |
| 15 | 15 | ||
| 16 | @Resource | 16 | @Resource |
| 17 | private SysUserService sysUserService; | 17 | private SysUserService sysUserService; |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.line; | ||
| 2 | + | ||
| 3 | +import com.lframework.starter.web.core.utils.JsonUtil; | ||
| 4 | +import com.lframework.xingyun.sc.procurement.dto.quotation.QuotationLineRealtimeMessage; | ||
| 5 | +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine; | ||
| 6 | +import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationLineService; | ||
| 7 | +import lombok.extern.slf4j.Slf4j; | ||
| 8 | +import org.springframework.stereotype.Service; | ||
| 9 | +import org.springframework.web.socket.TextMessage; | ||
| 10 | +import org.springframework.web.socket.WebSocketSession; | ||
| 11 | +import javax.annotation.Resource; | ||
| 12 | +import java.io.IOException; | ||
| 13 | +import java.time.LocalDate; | ||
| 14 | +import java.time.LocalDateTime; | ||
| 15 | +import java.util.List; | ||
| 16 | +import java.util.Map; | ||
| 17 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 业务员报价信息实时推送服务 | ||
| 21 | + */ | ||
| 22 | +@Slf4j | ||
| 23 | +@Service | ||
| 24 | +public class SalesmanQuotationLineRealtimePushService { | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 当前在线连接 | ||
| 28 | + */ | ||
| 29 | + private final Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>(); | ||
| 30 | + | ||
| 31 | + @Resource | ||
| 32 | + private SalesmanQuotationLineService salesmanQuotationLineService; | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 注册连接 | ||
| 36 | + * | ||
| 37 | + * @param session WebSocket 会话 | ||
| 38 | + */ | ||
| 39 | + public void register(WebSocketSession session) { | ||
| 40 | + sessionMap.put(session.getId(), session); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 注销连接 | ||
| 45 | + * | ||
| 46 | + * @param session WebSocket 会话 | ||
| 47 | + */ | ||
| 48 | + public void unregister(WebSocketSession session) { | ||
| 49 | + if (session != null) { | ||
| 50 | + sessionMap.remove(session.getId()); | ||
| 51 | + } | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 广播当日完整业务员报价数据 | ||
| 56 | + * | ||
| 57 | + * @param eventType 事件类型 | ||
| 58 | + */ | ||
| 59 | + public void broadcastCurrentDayFullData(String eventType) { | ||
| 60 | + if (sessionMap.isEmpty()) { | ||
| 61 | + return; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + QuotationLineRealtimeMessage message = buildCurrentDayMessage(eventType); | ||
| 65 | + String payload = JsonUtil.toJsonString(message); | ||
| 66 | + for (WebSocketSession session : sessionMap.values()) { | ||
| 67 | + sendMessage(session, payload); | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 向单个连接补推当日完整数据 | ||
| 73 | + * | ||
| 74 | + * @param session WebSocket 会话 | ||
| 75 | + * @param eventType 事件类型 | ||
| 76 | + */ | ||
| 77 | + public void replayCurrentDayFullData(WebSocketSession session, String eventType) { | ||
| 78 | + if (session == null) { | ||
| 79 | + return; | ||
| 80 | + } | ||
| 81 | + sendMessage(session, JsonUtil.toJsonString(buildCurrentDayMessage(eventType))); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + /** | ||
| 85 | + * 构建当日完整数据消息 | ||
| 86 | + * | ||
| 87 | + * @param eventType 事件类型 | ||
| 88 | + * @return 推送消息 | ||
| 89 | + */ | ||
| 90 | + private QuotationLineRealtimeMessage buildCurrentDayMessage(String eventType) { | ||
| 91 | + LocalDate today = LocalDate.now(); | ||
| 92 | + List<SalesmanQuotationLine> records = salesmanQuotationLineService.queryCurrentDayList(today); | ||
| 93 | + | ||
| 94 | + QuotationLineRealtimeMessage message = new QuotationLineRealtimeMessage(); | ||
| 95 | + message.setMessageType("FULL_SYNC"); | ||
| 96 | + message.setEventType(eventType); | ||
| 97 | + message.setBusinessDate(today); | ||
| 98 | + message.setPushTime(LocalDateTime.now()); | ||
| 99 | + message.setRecords(records); | ||
| 100 | + return message; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + /** | ||
| 104 | + * 发送消息 | ||
| 105 | + * | ||
| 106 | + * @param session WebSocket 会话 | ||
| 107 | + * @param payload 消息体 | ||
| 108 | + */ | ||
| 109 | + private void sendMessage(WebSocketSession session, String payload) { | ||
| 110 | + if (session == null || !session.isOpen()) { | ||
| 111 | + unregister(session); | ||
| 112 | + return; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + try { | ||
| 116 | + synchronized (session) { | ||
| 117 | + session.sendMessage(new TextMessage(payload)); | ||
| 118 | + } | ||
| 119 | + } catch (IOException e) { | ||
| 120 | + log.warn("业务员报价信息实时推送失败,sessionId={}", session.getId(), e); | ||
| 121 | + unregister(session); | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | +} |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.line; | ||
| 2 | + | ||
| 3 | +import org.springframework.context.annotation.Configuration; | ||
| 4 | +import org.springframework.web.socket.config.annotation.EnableWebSocket; | ||
| 5 | +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; | ||
| 6 | +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; | ||
| 7 | + | ||
| 8 | +import javax.annotation.Resource; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 业务员报价 WebSocket 配置 | ||
| 12 | + */ | ||
| 13 | +@Configuration | ||
| 14 | +@EnableWebSocket | ||
| 15 | +public class SalesmanQuotationLineWebSocketConfig implements WebSocketConfigurer { | ||
| 16 | + | ||
| 17 | + // 添加这段代码 | ||
| 18 | + static { | ||
| 19 | + System.out.println("========== WebSocket配置类正在加载 =========="); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * WebSocket 路径 | ||
| 24 | + */ | ||
| 25 | + public static final String ENDPOINT = "/ws/procurement/salesmanQuotationLine/realtime"; | ||
| 26 | + | ||
| 27 | + @Resource | ||
| 28 | + private SalesmanQuotationLineWebSocketHandler webSocketHandler; | ||
| 29 | + @Resource | ||
| 30 | + private SalesmanQuotationLineWebSocketHandshakeInterceptor handshakeInterceptor; | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { | ||
| 34 | + System.out.println("========== 正在注册 WebSocket 路径 =========="); | ||
| 35 | + registry.addHandler(webSocketHandler, ENDPOINT) | ||
| 36 | + .addInterceptors(handshakeInterceptor) | ||
| 37 | + .setAllowedOrigins("*"); | ||
| 38 | + } | ||
| 39 | +} |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.line; | ||
| 2 | + | ||
| 3 | +import lombok.extern.slf4j.Slf4j; | ||
| 4 | +import org.apache.commons.lang3.StringUtils; | ||
| 5 | +import org.springframework.stereotype.Component; | ||
| 6 | +import org.springframework.web.socket.CloseStatus; | ||
| 7 | +import org.springframework.web.socket.TextMessage; | ||
| 8 | +import org.springframework.web.socket.WebSocketSession; | ||
| 9 | +import org.springframework.web.socket.handler.TextWebSocketHandler; | ||
| 10 | + | ||
| 11 | +import javax.annotation.Resource; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 业务员报价 WebSocket 处理器 | ||
| 15 | + */ | ||
| 16 | +@Slf4j | ||
| 17 | +@Component | ||
| 18 | +public class SalesmanQuotationLineWebSocketHandler extends TextWebSocketHandler { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private SalesmanQuotationLineRealtimePushService realtimePushService; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void afterConnectionEstablished(WebSocketSession session) { | ||
| 25 | + realtimePushService.register(session); | ||
| 26 | + realtimePushService.replayCurrentDayFullData(session, "INIT"); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + @Override | ||
| 30 | + protected void handleTextMessage(WebSocketSession session, TextMessage message) { | ||
| 31 | + String payload = StringUtils.trimToEmpty(message.getPayload()); | ||
| 32 | + if ("SYNC_TODAY".equalsIgnoreCase(payload) || "RESYNC".equalsIgnoreCase(payload)) { | ||
| 33 | + realtimePushService.replayCurrentDayFullData(session, "RESYNC"); | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @Override | ||
| 38 | + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { | ||
| 39 | + realtimePushService.unregister(session); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public void handleTransportError(WebSocketSession session, Throwable exception) { | ||
| 44 | + log.warn("业务员报价 WebSocket 连接异常,sessionId={}", session.getId(), exception); | ||
| 45 | + realtimePushService.unregister(session); | ||
| 46 | + } | ||
| 47 | +} |
| 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.line; | ||
| 2 | + | ||
| 3 | +import com.lframework.starter.web.inner.entity.SysUser; | ||
| 4 | +import com.lframework.xingyun.sc.procurement.websocket.quotation.CommonWebSocketAuthService; | ||
| 5 | +import org.springframework.http.HttpStatus; | ||
| 6 | +import org.springframework.http.server.ServerHttpRequest; | ||
| 7 | +import org.springframework.http.server.ServerHttpResponse; | ||
| 8 | +import org.springframework.stereotype.Component; | ||
| 9 | +import org.springframework.web.socket.WebSocketHandler; | ||
| 10 | +import org.springframework.web.socket.server.HandshakeInterceptor; | ||
| 11 | + | ||
| 12 | +import javax.annotation.Resource; | ||
| 13 | +import java.util.Map; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 业务员报价 WebSocket 握手鉴权拦截器 | ||
| 17 | + */ | ||
| 18 | +@Component | ||
| 19 | +public class SalesmanQuotationLineWebSocketHandshakeInterceptor implements HandshakeInterceptor { | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 用户ID属性名 | ||
| 23 | + */ | ||
| 24 | + public static final String ATTR_USER_ID = "userId"; | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 用户名称属性名 | ||
| 28 | + */ | ||
| 29 | + public static final String ATTR_USER_NAME = "userName"; | ||
| 30 | + | ||
| 31 | + @Resource | ||
| 32 | + private CommonWebSocketAuthService authService; | ||
| 33 | + | ||
| 34 | + @Override | ||
| 35 | + public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, | ||
| 36 | + WebSocketHandler wsHandler, Map<String, Object> attributes) { | ||
| 37 | + try { | ||
| 38 | + SysUser user = authService.authenticateCurrentUser(); | ||
| 39 | + attributes.put(ATTR_USER_ID, user.getId()); | ||
| 40 | + attributes.put(ATTR_USER_NAME, user.getName()); | ||
| 41 | + return true; | ||
| 42 | + } catch (Exception e) { | ||
| 43 | + response.setStatusCode(HttpStatus.FORBIDDEN); | ||
| 44 | + return false; | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @Override | ||
| 49 | + public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, | ||
| 50 | + WebSocketHandler wsHandler, Exception exception) { | ||
| 51 | + } | ||
| 52 | +} |
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/peer/SalesmanQuotationPeerRealtimePushService.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerRealtimePushService.java
| 1 | -package com.lframework.xingyun.sc.procurement.websocket.quotation; | 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.peer; |
| 2 | 2 | ||
| 3 | import com.lframework.starter.web.core.utils.JsonUtil; | 3 | import com.lframework.starter.web.core.utils.JsonUtil; |
| 4 | import com.lframework.xingyun.sc.procurement.dto.quotation.PeerQuotationRealtimeMessage; | 4 | import com.lframework.xingyun.sc.procurement.dto.quotation.PeerQuotationRealtimeMessage; |
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/peer/SalesmanQuotationPeerWebSocketConfig.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerWebSocketConfig.java
| 1 | -package com.lframework.xingyun.sc.procurement.websocket.quotation; | 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.peer; |
| 2 | 2 | ||
| 3 | import javax.annotation.Resource; | 3 | import javax.annotation.Resource; |
| 4 | import org.springframework.context.annotation.Configuration; | 4 | import org.springframework.context.annotation.Configuration; |
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/peer/SalesmanQuotationPeerWebSocketHandler.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerWebSocketHandler.java
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/peer/SalesmanQuotationPeerWebSocketHandshakeInterceptor.java
renamed from
xingyun-sc/src/main/java/com/lframework/xingyun/sc/procurement/websocket/quotation/SalesmanQuotationPeerWebSocketHandshakeInterceptor.java
| 1 | -package com.lframework.xingyun.sc.procurement.websocket.quotation; | 1 | +package com.lframework.xingyun.sc.procurement.websocket.quotation.peer; |
| 2 | 2 | ||
| 3 | import com.lframework.starter.web.inner.entity.SysUser; | 3 | import com.lframework.starter.web.inner.entity.SysUser; |
| 4 | import java.util.Map; | 4 | import java.util.Map; |
| 5 | import javax.annotation.Resource; | 5 | import javax.annotation.Resource; |
| 6 | + | ||
| 7 | +import com.lframework.xingyun.sc.procurement.websocket.quotation.CommonWebSocketAuthService; | ||
| 6 | import org.springframework.http.HttpStatus; | 8 | import org.springframework.http.HttpStatus; |
| 7 | import org.springframework.http.server.ServerHttpRequest; | 9 | import org.springframework.http.server.ServerHttpRequest; |
| 8 | import org.springframework.http.server.ServerHttpResponse; | 10 | import org.springframework.http.server.ServerHttpResponse; |
| @@ -27,7 +29,7 @@ public class SalesmanQuotationPeerWebSocketHandshakeInterceptor implements Hands | @@ -27,7 +29,7 @@ public class SalesmanQuotationPeerWebSocketHandshakeInterceptor implements Hands | ||
| 27 | public static final String ATTR_USER_NAME = "userName"; | 29 | public static final String ATTR_USER_NAME = "userName"; |
| 28 | 30 | ||
| 29 | @Resource | 31 | @Resource |
| 30 | - private SalesmanQuotationPeerWebSocketAuthService authService; | 32 | + private CommonWebSocketAuthService authService; |
| 31 | 33 | ||
| 32 | @Override | 34 | @Override |
| 33 | public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, | 35 | public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, |
| @@ -16,6 +16,9 @@ | @@ -16,6 +16,9 @@ | ||
| 16 | <result column="estimated_loss" property="estimatedLoss"/> | 16 | <result column="estimated_loss" property="estimatedLoss"/> |
| 17 | <result column="application_attrition" property="applicationAttrition"/> | 17 | <result column="application_attrition" property="applicationAttrition"/> |
| 18 | <result column="item_id" property="itemId"/> | 18 | <result column="item_id" property="itemId"/> |
| 19 | + <result column="quote_time" property="quoteTime"/> | ||
| 20 | + <result column="quoter_name" property="quoterName"/> | ||
| 21 | + <result column="supplier_name" property="supplierName"/> | ||
| 19 | <result column="create_by_id" property="createById"/> | 22 | <result column="create_by_id" property="createById"/> |
| 20 | <result column="create_by" property="createBy"/> | 23 | <result column="create_by" property="createBy"/> |
| 21 | <result column="update_by_id" property="updateById"/> | 24 | <result column="update_by_id" property="updateById"/> |
| @@ -58,4 +61,32 @@ | @@ -58,4 +61,32 @@ | ||
| 58 | </where> | 61 | </where> |
| 59 | ORDER BY tb.create_time ASC | 62 | ORDER BY tb.create_time ASC |
| 60 | </select> | 63 | </select> |
| 64 | + | ||
| 65 | + <sql id="SalesmanQuotationLineSql1"> | ||
| 66 | + SELECT | ||
| 67 | + tb.id, | ||
| 68 | + tb.quotation_id, | ||
| 69 | + sq.quote_time, | ||
| 70 | + sq.quoter_name, | ||
| 71 | + pdc.unit_name AS supplier_name, | ||
| 72 | + br.product_name, | ||
| 73 | + tb.quantity, | ||
| 74 | + tb.purchase_price, | ||
| 75 | + tb.create_by_id, | ||
| 76 | + tb.create_by, | ||
| 77 | + tb.update_by_id, | ||
| 78 | + tb.update_by, | ||
| 79 | + tb.create_time, | ||
| 80 | + tb.update_time | ||
| 81 | + FROM procurement_salesman_quotation_line tb | ||
| 82 | + LEFT JOIN base_data_breed_relationship br ON br.id = tb.product_id | ||
| 83 | + LEFT JOIN procurement_salesman_quotation sq on sq.id=tb.quotation_id | ||
| 84 | + LEFT JOIN procurement_domestic_customer_credit pdc ON pdc.id = sq.supplier_id | ||
| 85 | + </sql> | ||
| 86 | + | ||
| 87 | + <select id="queryCurrentDayList" resultMap="SalesmanQuotationLine"> | ||
| 88 | + <include refid="SalesmanQuotationLineSql1"/> | ||
| 89 | + WHERE DATE(sq.create_time) = #{day} and sq.status='QUOTED' | ||
| 90 | + ORDER BY tb.create_time DESC, tb.quotation_id DESC | ||
| 91 | + </select> | ||
| 61 | </mapper> | 92 | </mapper> |