Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ public class PermissionConstants {
public static final String OPPORTUNITY_QUOTATION_UPDATE = "OPPORTUNITY_QUOTATION:UPDATE";
public static final String OPPORTUNITY_QUOTATION_DELETE = "OPPORTUNITY_QUOTATION:DELETE";
public static final String OPPORTUNITY_QUOTATION_EXPORT = "OPPORTUNITY_QUOTATION:EXPORT";
public static final String OPPORTUNITY_QUOTATION_VOIDED = "OPPORTUNITY_QUOTATION:VOIDED";
public static final String OPPORTUNITY_QUOTATION_APPROVAL = "OPPORTUNITY_QUOTATION:APPROVAL";

/*------ end: OPPORTUNITY_QUOTATION ------*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,52 @@
package cn.cordys.crm.opportunity.constants;

import cn.cordys.common.util.Translator;
import lombok.Getter;

import static cn.cordys.crm.opportunity.constants.OpportunityStageType.AFOOT;
import static cn.cordys.crm.opportunity.constants.OpportunityStageType.END;

@Getter
public enum ApprovalState {

/**
* 通过
*/
APPROVED,
APPROVED("APPROVED", Translator.get("log.approvalStatus.VOIDED"), END.toString()),

/**
* 不通过
*/
UNAPPROVED,
UNAPPROVED("UNAPPROVED", Translator.get("log.approvalStatus.UNAPPROVED"), END.toString()),

/**
* 提审
*/
APPROVING,
APPROVING("APPROVING", Translator.get("log.approvalStatus.APPROVING"), AFOOT.toString()),

/**
* 作废
* 撤销
*/
VOIDED,
REVOKED("REVOKED", Translator.get("log.approvalStatus.REVOKED"), AFOOT.toString());

/**
* 撤销
* 固定审批节点 ID
*/
private final String id;
/**
* 审批节点名称
*/
REVOKED
private final String name;

/**
* 审批节点类型
*/
private final String type;

ApprovalState(String id, String name, String type) {
this.id = id;
this.name = name;
this.type = type;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public String revoke(@PathVariable("id") String id) {

//作废
@GetMapping("/voided/{id}")
@RequiresPermissions(PermissionConstants.OPPORTUNITY_QUOTATION_UPDATE)
@RequiresPermissions(PermissionConstants.OPPORTUNITY_QUOTATION_VOIDED)
@Operation(summary = "作废报价单")
public String voidQuotation(@PathVariable("id") String id) {
return opportunityQuotationService.voidQuotation(id, SessionUtils.getUserId(), OrganizationContext.getOrganizationId());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package cn.cordys.crm.opportunity.domain;

import cn.cordys.common.domain.BaseModel;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Table;
import lombok.Data;
Expand All @@ -25,4 +24,16 @@ public class OpportunityQuotationApproval implements Serializable {

@Schema(description = "审核状态")
private String approvalStatus;

@Schema(description = "创建人")
private String createUser;

@Schema(description = "修改人")
private String updateUser;

@Schema(description = "创建时间")
private Long createTime;

@Schema(description = "更新时间")
private Long updateTime;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import cn.cordys.crm.contract.domain.ContractField;
import cn.cordys.crm.opportunity.constants.ApprovalState;
import cn.cordys.crm.opportunity.domain.OpportunityQuotation;
import cn.cordys.crm.opportunity.domain.OpportunityQuotationApproval;
import cn.cordys.crm.opportunity.domain.OpportunityQuotationSnapshot;
import cn.cordys.crm.opportunity.dto.request.OpportunityQuotationAddRequest;
import cn.cordys.crm.opportunity.dto.request.OpportunityQuotationBatchRequest;
Expand Down Expand Up @@ -87,6 +88,8 @@ public class OpportunityQuotationService {
private BaseMapper<OpportunityQuotationSnapshot> snapshotBaseMapper;
@Resource
private BaseMapper<ContractField> contractFieldMapper;
@Resource
private BaseMapper<OpportunityQuotationApproval> approvalBaseMapper;


/**
Expand Down Expand Up @@ -119,10 +122,31 @@ public OpportunityQuotation add(OpportunityQuotationAddRequest request, String o
OpportunityQuotationGetResponse response = getOpportunityQuotationGetResponse(opportunityQuotation, moduleFields, moduleFormConfigDTO);
saveSnapshot(opportunityQuotation, moduleFormConfigDTO, response);

//保存报价单审批表
addQuotationApproval(userId, opportunityQuotation.getId());

return opportunityQuotation;

}

/**
* 新增报价单审批表
*
* @param userId 用户ID
* @param quotationId 报价单ID
*/
private void addQuotationApproval(String userId, String quotationId) {
OpportunityQuotationApproval opportunityQuotationApproval = new OpportunityQuotationApproval();
opportunityQuotationApproval.setId(IDGenerator.nextStr());
opportunityQuotationApproval.setQuotationId(quotationId);
opportunityQuotationApproval.setApprovalStatus(ApprovalState.APPROVING.toString());
opportunityQuotationApproval.setCreateUser(userId);
opportunityQuotationApproval.setUpdateUser(userId);
opportunityQuotationApproval.setCreateTime(System.currentTimeMillis());
opportunityQuotationApproval.setUpdateTime(System.currentTimeMillis());
approvalBaseMapper.insert(opportunityQuotationApproval);
}

/**
* 保存商机报价单快照
*
Expand Down Expand Up @@ -169,7 +193,9 @@ public OpportunityQuotationGetResponse get(String id) {
if (opportunityQuotation == null) {
throw new GenericException(Translator.get("opportunity.quotation.not.exist"));
}
if (Strings.CI.equals(opportunityQuotation.getApprovalStatus(), ApprovalState.APPROVED.toString()) || Strings.CI.equals(opportunityQuotation.getApprovalStatus(), ApprovalState.APPROVING.toString())) {
//获取ApprovalState中所有状态的id属性(以后改成获取自定义的审批状态)
List<String> approvalStatusList = Arrays.stream(ApprovalState.values()).map(ApprovalState::getId).toList();
if (approvalStatusList.contains(opportunityQuotation.getApprovalStatus()) && (Strings.CI.equals(opportunityQuotation.getApprovalStatus(), ApprovalState.APPROVED.toString()) || Strings.CI.equals(opportunityQuotation.getApprovalStatus(), ApprovalState.APPROVING.toString()))) {
// 已审核,查询最新快照
LambdaQueryWrapper<OpportunityQuotationSnapshot> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(OpportunityQuotationSnapshot::getQuotationId, id);
Expand Down Expand Up @@ -205,6 +231,11 @@ public String revoke(String id, String userId) {
opportunityQuotation.setUpdateUser(userId);
opportunityQuotation.setUpdateTime(System.currentTimeMillis());
opportunityQuotationMapper.updateById(opportunityQuotation);

//更新报价单审批表
updateQuotationApproval(userId, id, ApprovalState.REVOKED.toString());


return opportunityQuotation.getApprovalStatus();
}

Expand All @@ -220,7 +251,7 @@ public String voidQuotation(String id, String userId, String orgId) {
throw new GenericException(Translator.get("opportunity.quotation.not.exist"));
}
String oldApprovalStatus = oldOpportunityQuotation.getApprovalStatus();
OpportunityQuotation opportunityQuotation = updateApprovalState(oldOpportunityQuotation, ApprovalState.VOIDED.toString(), userId);
OpportunityQuotation opportunityQuotation = updateApprovalState(oldOpportunityQuotation, LogType.VOIDED, userId);
if (opportunityQuotation == null) {
throw new GenericException(Translator.get("opportunity.quotation.not.exist"));
}
Expand Down Expand Up @@ -253,7 +284,9 @@ private void checkQuotationLinked(String id, String key) {
* @param userId 用户ID
*/
public String approve(OpportunityQuotationEditRequest request, String userId, String orgId) {
String noticeKey = Strings.CI.equals(request.getApprovalStatus(), ApprovalState.APPROVED.toString()) ?
//获取ApprovalState中APPROVED状态的id属性(以后改成获取自定义的审批状态)
List<String> approvalStatusList = Arrays.stream(ApprovalState.values()).map(ApprovalState::getId).filter(status -> ApprovalState.APPROVED.toString().equals(status)).toList();
String noticeKey = approvalStatusList.contains(request.getApprovalStatus()) ?
"opportunity.quotation.status.approved" : "opportunity.quotation.status.unapproved";
OpportunityQuotation oldOpportunityQuotation = opportunityQuotationMapper.selectByPrimaryKey(request.getId());
if (oldOpportunityQuotation == null) {
Expand Down Expand Up @@ -358,6 +391,11 @@ public void delete(String id, String userId, String organizationId) {
wrapper.eq(OpportunityQuotationSnapshot::getQuotationId, id);
snapshotBaseMapper.deleteByLambda(wrapper);

//删除审批记录
LambdaQueryWrapper<OpportunityQuotationApproval> approvalWrapper = new LambdaQueryWrapper<>();
approvalWrapper.eq(OpportunityQuotationApproval::getQuotationId, id);
approvalBaseMapper.deleteByLambda(approvalWrapper);

//记录日志
saveSateChangeLog(organizationId, null, userId, LogType.DELETE, opportunityQuotation);

Expand Down Expand Up @@ -421,6 +459,10 @@ public OpportunityQuotation update(OpportunityQuotationEditRequest request, Stri
opportunityQuotation.setApprovalStatus(ApprovalState.APPROVING.toString());
updateFields(moduleFields, opportunityQuotation, orgId, userId);
opportunityQuotationMapper.update(opportunityQuotation);

//更新报价单审批表
updateQuotationApproval(userId, id, ApprovalState.APPROVING.toString());

// 处理日志上下文
baseService.handleUpdateLog(oldOpportunityQuotation, opportunityQuotation, originFields, moduleFields, id, opportunityQuotation.getName());

Expand All @@ -435,6 +477,37 @@ public OpportunityQuotation update(OpportunityQuotationEditRequest request, Stri
return opportunityQuotationMapper.selectByPrimaryKey(id);
}

/**
* 更新报价单审批状态
*
* @param userId 更新用户ID
* @param quotationId 报价单ID
*/
private void updateQuotationApproval(String userId, String quotationId, String approvalStatus) {
LambdaQueryWrapper<OpportunityQuotationApproval> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(OpportunityQuotationApproval::getQuotationId, quotationId);
List<OpportunityQuotationApproval> approvalList = approvalBaseMapper.selectListByLambda(wrapper);
if (CollectionUtils.isEmpty(approvalList)) {
addQuotationApproval(userId, quotationId);
} else {
updateQuotationApprovalState(userId, approvalList.getFirst(), approvalStatus);
}
}

/**
* 更新报价单审批状态
*
* @param userId 更新用户ID
* @param quotationApproval 报价单审批实体
* @param approvalStatus 审批状态
*/
private void updateQuotationApprovalState(String userId, OpportunityQuotationApproval quotationApproval, String approvalStatus) {
quotationApproval.setApprovalStatus(approvalStatus);
quotationApproval.setUpdateTime(System.currentTimeMillis());
quotationApproval.setUpdateUser(userId);
approvalBaseMapper.update(quotationApproval);
}

/**
* 更新自定义字段
*
Expand Down Expand Up @@ -539,11 +612,11 @@ public BatchAffectReasonResponse batchVoidQuotation(OpportunityQuotationBatchReq
successIds.add(item.getId());
LogDTO logDTO = new LogDTO(organizationId, item.getId(), userId, LogType.VOIDED, LogModule.OPPORTUNITY_QUOTATION, item.getName());
logDTO.setOriginalValue(item.getApprovalStatus());
logDTO.setModifiedValue(ApprovalState.VOIDED.toString());
logDTO.setModifiedValue(LogType.VOIDED);
logs.add(logDTO);

});
batchUpdateMapper.batchUpdateApprovalStatus(successIds, ApprovalState.VOIDED.toString(), userId, System.currentTimeMillis());
batchUpdateMapper.batchUpdateApprovalStatus(successIds, LogType.VOIDED, userId, System.currentTimeMillis());
logService.batchAdd(logs);
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
Expand Down Expand Up @@ -630,7 +703,9 @@ public ModuleFormConfigDTO getFormSnapshot(String id, String orgId) {
if (opportunityQuotation == null) {
throw new GenericException(Translator.get("opportunity.quotation.not.exist"));
}
if (Strings.CI.equals(opportunityQuotation.getApprovalStatus(), ApprovalState.APPROVED.toString()) || Strings.CI.equals(opportunityQuotation.getApprovalStatus(), ApprovalState.APPROVING.toString())) {
//获取ApprovalState中所有状态的id属性(以后改成获取自定义的审批状态)
List<String> approvalStatusList = Arrays.stream(ApprovalState.values()).map(ApprovalState::getId).toList();
if (approvalStatusList.contains(opportunityQuotation.getApprovalStatus()) && (Strings.CI.equals(opportunityQuotation.getApprovalStatus(), ApprovalState.APPROVED.toString()) || Strings.CI.equals(opportunityQuotation.getApprovalStatus(), ApprovalState.APPROVING.toString()))) {
LambdaQueryWrapper<OpportunityQuotationSnapshot> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(OpportunityQuotationSnapshot::getQuotationId, id);
OpportunityQuotationSnapshot snapshot = snapshotBaseMapper.selectListByLambda(wrapper).stream().findFirst().orElse(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ log.approvalStatus.VOIDED=Voided
log.approvalStatus.APPROVED=Approved
log.approvalStatus.UNAPPROVED=Unapproved
log.approvalStatus.APPROVING=Approving
log.approvalStatus.REVOKED=Revoked
log.customerId=Account name
log.collectionTime=Pick time
log.expectedEndTime=End time
Expand Down Expand Up @@ -638,7 +639,6 @@ dashboard_url_not_allowed=Dashboard address denied access
log.mkAddress=MaxKB Address
log.apikey=API Key
log.mkEnable=Status

#contract
contract.not.exist=Contract does not exist
contract.archived.cannot.edit=Archived contracts cannot be edited!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ log.approvalStatus.VOIDED=作废
log.approvalStatus.APPROVED=通过
log.approvalStatus.UNAPPROVED=不通过
log.approvalStatus.APPROVING=审批中
log.approvalStatus.REVOKED=撤销
log.customerId=客户名称
log.collectionTime=领取时间
log.expectedEndTime=结束时间
Expand Down Expand Up @@ -638,7 +639,6 @@ dashboard_url_not_allowed=仪表板地址拒绝访问
log.mkAddress=MaxKB 地址
log.apiKey=API Key
log.mkEnable=状态

#contract
contract.not.exist=合同不存在
contract.archived.cannot.edit=合同已归档,无法编辑!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ INSERT INTO sys_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(
INSERT INTO sys_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'org_admin', 'OPPORTUNITY_QUOTATION:DELETE');
INSERT INTO sys_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'org_admin', 'OPPORTUNITY_QUOTATION:EXPORT');
INSERT INTO sys_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'org_admin', 'OPPORTUNITY_QUOTATION:APPROVAL');
INSERT INTO sys_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'org_admin', 'OPPORTUNITY_QUOTATION:VOIDED');

-- init price permissions
INSERT INTO sys_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'org_admin', 'PRICE:READ');
Expand Down
3 changes: 3 additions & 0 deletions backend/crm/src/main/resources/permission.json
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@
},
{
"id": "OPPORTUNITY_QUOTATION:APPROVAL"
},
{
"id": "OPPORTUNITY_QUOTATION:VOIDED"
}
]
}
Expand Down
Loading