src/main/java/com/ruoyi/basic/controller/CustomerController.java
@@ -13,6 +13,7 @@ import com.ruoyi.framework.web.domain.R; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -43,6 +44,7 @@ * 导åºå®¢æ·æ¡£æ¡å表 */ @Log(title = "å®¢æ·æ¡£æ¡", businessType = BusinessType.EXPORT) @PreAuthorize("@ss.hasPermi('basic:customer:export')") @PostMapping("/export") public void export(HttpServletResponse response, CustomerDto customer) { ExcelUtil<CustomerVo> util = new ExcelUtil<CustomerVo>(CustomerVo.class); @@ -50,6 +52,7 @@ } @PostMapping("/downloadTemplate") @PreAuthorize("@ss.hasPermi('basic:customer:import')") @Log(title = "å®¢æ·æ¡£æ¡-ä¸è½½æ¨¡æ¿", businessType = BusinessType.EXPORT) public void downloadTemplate(HttpServletResponse response) { ExcelUtil<Customer> util = new ExcelUtil<Customer>(Customer.class); @@ -61,6 +64,7 @@ * å¯¼å ¥å®¢æ·æ¡£æ¡ */ @Log(title = "å®¢æ·æ¡£æ¡", businessType = BusinessType.IMPORT) @PreAuthorize("@ss.hasPermi('basic:customer:import')") @PostMapping("/importData") public R importData(MultipartFile file, Integer type) throws Exception { @@ -71,6 +75,7 @@ * è·åå®¢æ·æ¡£æ¡è¯¦ç»ä¿¡æ¯ */ @GetMapping(value = "/{id}") @PreAuthorize("@ss.hasPermi('basic:customer:query')") public R getInfo(@PathVariable("id") Long id) { return R.ok(customerService.selectCustomerDetailById(id)); } @@ -79,6 +84,7 @@ * æ°å¢å®¢æ·æ¡£æ¡ */ @Log(title = "å®¢æ·æ¡£æ¡", businessType = BusinessType.INSERT) @PreAuthorize("@ss.hasPermi('basic:customer:add')") @PostMapping("/addCustomer") public R add(@RequestBody Customer customer) { return R.ok(customerService.insertCustomer(customer)); @@ -88,6 +94,7 @@ * ä¿®æ¹å®¢æ·æ¡£æ¡ */ @Log(title = "å®¢æ·æ¡£æ¡", businessType = BusinessType.UPDATE) @PreAuthorize("@ss.hasPermi('basic:customer:edit')") @PostMapping("/updateCustomer") public R edit(@RequestBody Customer customer) { return R.ok(customerService.updateCustomer(customer)); @@ -97,6 +104,7 @@ * å é¤å®¢æ·æ¡£æ¡ */ @Log(title = "å®¢æ·æ¡£æ¡", businessType = BusinessType.DELETE) @PreAuthorize("@ss.hasPermi('basic:customer:remove')") @DeleteMapping("/delCustomer") public R remove(@RequestBody Long[] ids) { if (ids == null || ids.length == 0) { src/main/java/com/ruoyi/basic/controller/CustomerFinancialReportController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,86 @@ package com.ruoyi.basic.controller; import com.ruoyi.basic.pojo.CustomerFinancialReport; import com.ruoyi.basic.service.CustomerFinancialReportService; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; import io.swagger.v3.oas.annotations.Operation; import lombok.AllArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; /** * 客æ·è¿3å¹´è´¢å¡æ¥è¡¨ */ @RestController @RequestMapping("/basic/customerFinancialReport") @AllArgsConstructor public class CustomerFinancialReportController { private final CustomerFinancialReportService customerFinancialReportService; /** * åå°æå®¢æ·æ¥è¯¢è¿3å¹´è´¢å¡æ¥è¡¨ */ @Operation(summary = "æ¥è¯¢å®¢æ·è¿3å¹´è´¢å¡æ¥è¡¨") @PreAuthorize("@ss.hasPermi('basic:customer:report')") @GetMapping("/list") public AjaxResult list(Long customerId) { return AjaxResult.success(customerFinancialReportService.listByCustomer(customerId)); } /** * 客æ·è´¦å·æ¥è¯¢èªå·±çè¿3å¹´è´¢å¡æ¥è¡¨ */ @Operation(summary = "æ¥è¯¢æçè´¢å¡æ¥è¡¨") @PreAuthorize("@ss.hasPermi('customer:report:mine')") @GetMapping("/mine") public AjaxResult mine() { return AjaxResult.success(customerFinancialReportService.listMine()); } /** * ä¸ä¼ /ä¿®æ¹è´¢å¡æ¥è¡¨ */ @Operation(summary = "ä¸ä¼ è´¢å¡æ¥è¡¨") @Log(title = "客æ·è´¢å¡æ¥è¡¨", businessType = BusinessType.UPDATE) @PreAuthorize("@ss.hasPermi('basic:customer:report') or @ss.hasPermi('customer:report:mine')") @PostMapping("/save") public AjaxResult save(@RequestBody CustomerFinancialReport report) { return AjaxResult.success(customerFinancialReportService.saveReport(report)); } /** * ç³æ¥å®¡æ¹å表ï¼å é¨äººåæ¥çææå®¢æ·çæäº¤æ åµï¼ */ @Operation(summary = "ç³æ¥å®¡æ¹å表") @PreAuthorize("@ss.hasPermi('sales:report:audit')") @GetMapping("/auditList") public AjaxResult auditList(String customerName, Integer reportYear, Integer auditStatus) { return AjaxResult.success(customerFinancialReportService.auditList(customerName, reportYear, auditStatus)); } /** * 审æ¹è´¢å¡æ¥è¡¨ï¼1éè¿ 2éåï¼ */ @Operation(summary = "审æ¹è´¢å¡æ¥è¡¨") @Log(title = "客æ·è´¢å¡æ¥è¡¨", businessType = BusinessType.UPDATE) @PreAuthorize("@ss.hasPermi('sales:report:audit')") @PostMapping("/audit") public AjaxResult audit(@RequestBody CustomerFinancialReport report) { return AjaxResult.success(customerFinancialReportService.auditReport( report.getId(), report.getAuditStatus(), report.getAuditRemark())); } /** * å é¤è´¢å¡æ¥è¡¨ï¼å®¢æ·è´¦å·ä¸å¯å é¤ï¼ */ @Operation(summary = "å é¤è´¢å¡æ¥è¡¨") @Log(title = "客æ·è´¢å¡æ¥è¡¨", businessType = BusinessType.DELETE) @PreAuthorize("@ss.hasPermi('basic:customer:report')") @DeleteMapping("/{id}") public AjaxResult remove(@PathVariable Long id) { customerFinancialReportService.deleteReport(id); return AjaxResult.success(); } } src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
@@ -87,6 +87,7 @@ PURCHASE_RETURN_ORDERS("purchase_return_orders"), SALES_LEDGER_PRODUCT_TEMPLATE("sales_ledger_product_template"), PURCHASE_LEDGER("purchase_ledger"), PURCHASE_LEDGER_SIMPLE("purchase_ledger_simple"), PURCHASE_LEDGER_TEMPLATE("purchase_ledger_template"), // Project Management SHIPPING_ADDRESS("shipping_address"), src/main/java/com/ruoyi/basic/mapper/CustomerFinancialReportMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,7 @@ package com.ruoyi.basic.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.basic.pojo.CustomerFinancialReport; public interface CustomerFinancialReportMapper extends BaseMapper<CustomerFinancialReport> { } src/main/java/com/ruoyi/basic/pojo/Customer.java
@@ -134,4 +134,10 @@ @Schema(description = "æ¯å¦è¢«åé ï¼0-æªåé ï¼1-å·²åé ") private Integer isAssigned; /** * ç»å®çç»å½è´¦å·idï¼customer_user ä¸å¯¹ä¸ç»å®ï¼é客æ·è¡¨åæ®µï¼ */ @TableField(exist = false) private Long bindUserId; } src/main/java/com/ruoyi/basic/pojo/CustomerFinancialReport.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,98 @@ package com.ruoyi.basic.pojo; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; /** * 客æ·è¿3å¹´è´¢å¡æ¥è¡¨ * * @author ruoyi * @date 2026-10-29 */ @TableName("customer_financial_report") @Data public class CustomerFinancialReport implements Serializable { private static final long serialVersionUID = 1L; @TableId(type = IdType.AUTO) private Long id; /** * 客æ·id */ private Long customerId; /** * æ¥è¡¨å¹´åº¦ */ private Integer reportYear; /** * æ¥è¡¨åç§° */ private String reportName; /** * æ¥è¡¨éä»¶ï¼JSONæ°ç»åç¬¦ä¸²ï¼ */ private String reportFiles; /** * 审æ¹ç¶æï¼0å¾ å®¡æ¹ 1å·²éè¿ 2å·²éå */ private Integer auditStatus; /** * 审æ¹äººid */ private Long auditUserId; /** * 审æ¹äºº */ private String auditUserName; /** * å®¡æ¹æ¶é´ */ private LocalDateTime auditTime; /** * å®¡æ¹æè§/éååå */ private String auditRemark; /** * ä¸ä¼ 人id */ private Long uploadUserId; /** * ä¸ä¼ 人 */ private String uploadUserName; @TableField(fill = FieldFill.INSERT) private Long tenantId; @TableField(fill = FieldFill.INSERT) private Long deptId; @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @Schema(description = "客æ·åç§°") @TableField(exist = false) private String customerName; } src/main/java/com/ruoyi/basic/service/CustomerFinancialReportService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,264 @@ package com.ruoyi.basic.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.ruoyi.basic.dto.StorageBlobVO; import com.ruoyi.basic.mapper.CustomerFinancialReportMapper; import com.ruoyi.basic.mapper.CustomerMapper; import com.ruoyi.basic.mapper.CustomerUserMapper; import com.ruoyi.basic.mapper.StorageBlobMapper; import com.ruoyi.basic.pojo.Customer; import com.ruoyi.basic.pojo.CustomerFinancialReport; import com.ruoyi.basic.pojo.CustomerUser; import com.ruoyi.basic.pojo.StorageBlob; import com.ruoyi.basic.utils.FileUtil; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.framework.security.LoginUser; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.time.Year; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; /** * 客æ·è¿3å¹´è´¢å¡æ¥è¡¨Service */ @Service @RequiredArgsConstructor public class CustomerFinancialReportService extends ServiceImpl<CustomerFinancialReportMapper, CustomerFinancialReport> { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private final CustomerMapper customerMapper; private final CustomerUserMapper customerUserMapper; private final StorageBlobMapper storageBlobMapper; private final FileUtil fileUtil; /** * åå°æå®¢æ·æ¥è¯¢è¿3å¹´è´¢å¡æ¥è¡¨ */ public List<CustomerFinancialReport> listByCustomer(Long customerId) { if (customerId == null) { throw new ServiceException("è¯·éæ©å®¢æ·"); } List<CustomerFinancialReport> reports = list(new LambdaQueryWrapper<CustomerFinancialReport>() .eq(CustomerFinancialReport::getCustomerId, customerId) .orderByDesc(CustomerFinancialReport::getReportYear)); refreshFileUrls(reports); fillCustomerName(reports); return reports; } /** * 客æ·è´¦å·æ¥è¯¢èªå·±çè¿3å¹´è´¢å¡æ¥è¡¨ */ public List<CustomerFinancialReport> listMine() { Long customerId = currentCustomerId(); List<CustomerFinancialReport> reports = list(new LambdaQueryWrapper<CustomerFinancialReport>() .eq(CustomerFinancialReport::getCustomerId, customerId) .orderByDesc(CustomerFinancialReport::getReportYear)); refreshFileUrls(reports); fillCustomerName(reports); return reports; } /** * ä¿åè´¢å¡æ¥è¡¨ï¼åä¸å®¢æ·åä¸å¹´åº¦ä» ä¿ç䏿¡ï¼å¯åå¤è¦çä¿®æ¹ */ @Transactional(rollbackFor = Exception.class) public CustomerFinancialReport saveReport(CustomerFinancialReport input) { if (input.getReportYear() == null) { throw new ServiceException("è¯·éæ©æ¥è¡¨å¹´åº¦"); } int currentYear = Year.now().getValue(); if (input.getReportYear() < currentYear - 2 || input.getReportYear() > currentYear) { throw new ServiceException("åªè½ä¸ä¼ æè¿ä¸ä¸ªå¹´åº¦çè´¢å¡æ¥è¡¨"); } if (StringUtils.isBlank(input.getReportFiles())) { throw new ServiceException("请ä¸ä¼ è´¢å¡æ¥è¡¨éä»¶"); } Long customerId; if (isCustomerAccount()) { customerId = currentCustomerId(); } else { customerId = input.getCustomerId(); if (customerId == null || customerMapper.selectById(customerId) == null) { throw new ServiceException("客æ·ä¸åå¨"); } } CustomerFinancialReport entity = getOne(new LambdaQueryWrapper<CustomerFinancialReport>() .eq(CustomerFinancialReport::getCustomerId, customerId) .eq(CustomerFinancialReport::getReportYear, input.getReportYear()), false); LoginUser loginUser = SecurityUtils.getLoginUser(); if (entity == null) { entity = new CustomerFinancialReport(); entity.setCustomerId(customerId); entity.setReportYear(input.getReportYear()); } entity.setReportName(input.getReportName()); entity.setReportFiles(input.getReportFiles()); // éæ°æäº¤ååå°å¾ 审æ¹ç¶æï¼çå¾ å é¨äººåéæ°å®¡æ¹ entity.setAuditStatus(0); entity.setAuditUserId(null); entity.setAuditUserName(null); entity.setAuditTime(null); entity.setAuditRemark(null); entity.setUploadUserId(loginUser.getUserId()); entity.setUploadUserName(loginUser.getNickName()); saveOrUpdate(entity); return entity; } /** * ç³æ¥å®¡æ¹å表ï¼å é¨äººåæ¥çææå®¢æ·çæäº¤æ åµ */ public List<CustomerFinancialReport> auditList(String customerName, Integer reportYear, Integer auditStatus) { LambdaQueryWrapper<CustomerFinancialReport> wrapper = new LambdaQueryWrapper<CustomerFinancialReport>() .eq(reportYear != null, CustomerFinancialReport::getReportYear, reportYear) .eq(auditStatus != null, CustomerFinancialReport::getAuditStatus, auditStatus) .orderByDesc(CustomerFinancialReport::getUpdateTime); if (StringUtils.isNotBlank(customerName)) { List<Long> customerIds = customerMapper.selectList(new LambdaQueryWrapper<Customer>() .like(Customer::getCustomerName, customerName)) .stream().map(Customer::getId).filter(Objects::nonNull).collect(Collectors.toList()); if (customerIds.isEmpty()) { return new java.util.ArrayList<>(); } wrapper.in(CustomerFinancialReport::getCustomerId, customerIds); } List<CustomerFinancialReport> reports = list(wrapper); refreshFileUrls(reports); fillCustomerName(reports); return reports; } /** * 审æ¹è´¢å¡æ¥è¡¨ï¼1éè¿ 2éå */ @Transactional(rollbackFor = Exception.class) public CustomerFinancialReport auditReport(Long id, Integer auditStatus, String auditRemark) { if (isCustomerAccount()) { throw new ServiceException("客æ·è´¦å·æ æå®¡æ¹è´¢å¡æ¥è¡¨"); } if (id == null) { throw new ServiceException("è¯·éæ©ç³æ¥è®°å½"); } if (auditStatus == null || auditStatus != 1 && auditStatus != 2) { throw new ServiceException("审æ¹ç»æä¸æ£ç¡®"); } CustomerFinancialReport entity = getById(id); if (entity == null) { throw new ServiceException("ç³æ¥è®°å½ä¸åå¨"); } LoginUser loginUser = SecurityUtils.getLoginUser(); entity.setAuditStatus(auditStatus); entity.setAuditUserId(loginUser.getUserId()); entity.setAuditUserName(loginUser.getNickName()); entity.setAuditTime(LocalDateTime.now()); entity.setAuditRemark(auditRemark); updateById(entity); return entity; } /** * å é¤è´¢å¡æ¥è¡¨ï¼ä» åå°äººåå¯å é¤ï¼å®¢æ·è´¦å·ä¸å 许å é¤ */ @Transactional(rollbackFor = Exception.class) public void deleteReport(Long id) { if (isCustomerAccount()) { throw new ServiceException("客æ·è´¦å·æ æå é¤è´¢å¡æ¥è¡¨"); } CustomerFinancialReport entity = getById(id); if (entity == null) { throw new ServiceException("è´¢å¡æ¥è¡¨ä¸åå¨"); } removeById(id); } /** * éæ°çæéä»¶é¢è§/ä¸è½½å°åï¼æ°æ®åºä¸ä¿åçæ¯ä¸ä¼ æ¶ç带ç¾åå°åï¼ä¼è¿æï¼è¯»åæ¶ææä»¶idå·æ° */ private void refreshFileUrls(List<CustomerFinancialReport> reports) { if (reports == null || reports.isEmpty()) { return; } for (CustomerFinancialReport report : reports) { String files = report.getReportFiles(); if (StringUtils.isBlank(files)) { continue; } try { JsonNode root = OBJECT_MAPPER.readTree(files); if (root == null || !root.isArray()) { continue; } for (JsonNode node : root) { Long blobId = node.hasNonNull("id") ? node.get("id").asLong() : null; if (blobId == null) { continue; } StorageBlob blob = storageBlobMapper.selectById(blobId); if (blob == null) { continue; } StorageBlobVO vo = new StorageBlobVO(); vo.setUidFilename(blob.getUidFilename()); vo.setPath(blob.getPath()); vo.setResourceKey(blob.getResourceKey()); ObjectNode objectNode = (ObjectNode) node; objectNode.put("url", fileUtil.buildSignedPreviewUrl(vo)); objectNode.put("downloadURL", fileUtil.buildSignedDownloadUrl(vo)); if (!node.hasNonNull("name")) { objectNode.put("name", blob.getOriginalFilename()); } } report.setReportFiles(OBJECT_MAPPER.writeValueAsString(root)); } catch (Exception e) { // æ§æ°æ®æé JSON æ ¼å¼ï¼ä¿æåå¼ } } } private boolean isCustomerAccount() { Long userId = SecurityUtils.getUserId(); return !SecurityUtils.isAdmin(userId) && SecurityUtils.hasRole("customer"); } /** * è·åå½åç»å½è´¦å·ç»å®ç客æ·id */ private Long currentCustomerId() { CustomerUser binding = customerUserMapper.selectOne(new LambdaQueryWrapper<CustomerUser>() .eq(CustomerUser::getUserId, SecurityUtils.getUserId()).last("limit 1")); if (binding == null || binding.getCustomerId() == null) { throw new ServiceException("å½åè´¦å·å°æªç»å®å®¢æ·ï¼è¯·è系管çå"); } return binding.getCustomerId(); } private void fillCustomerName(List<CustomerFinancialReport> reports) { if (reports == null || reports.isEmpty()) { return; } Set<Long> ids = reports.stream().map(CustomerFinancialReport::getCustomerId) .filter(Objects::nonNull).collect(Collectors.toSet()); if (ids.isEmpty()) { return; } List<Customer> customers = customerMapper.selectBatchIds(ids); java.util.Map<Long, String> nameMap = customers.stream() .collect(Collectors.toMap(Customer::getId, Customer::getCustomerName, (a, b) -> a)); reports.forEach(item -> item.setCustomerName(nameMap.getOrDefault(item.getCustomerId(), ""))); } } src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -33,6 +33,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -70,6 +71,8 @@ private CustomerReturnVisitService customerReturnVisitService; @Autowired private CustomerUserService customerUserService; @Autowired private JdbcTemplate jdbcTemplate; /** * æ¥è¯¢å®¢æ·æ¡£æ¡ @@ -92,6 +95,13 @@ public CustomerVo selectCustomerDetailById(Long id) { CustomerVo customerVo = new CustomerVo(); BeanUtils.copyProperties(this.getById(id), customerVo); // åæ¾ç»å®çç»å½è´¦å· CustomerUser binding = customerUserService.getOne(new LambdaQueryWrapper<CustomerUser>() .eq(CustomerUser::getCustomerId, id).last("limit 1"), false); if (binding != null) { customerVo.setBindUserId(binding.getUserId()); } // æ¥è¯¢è·è¿è®°å½ List<CustomerFollowUp> followUpList = customerFollowUpService.list( @@ -196,11 +206,14 @@ * @return ç»æ */ @Override @Transactional(rollbackFor = Exception.class) public int insertCustomer(Customer customer) { LoginUser loginUser = SecurityUtils.getLoginUser(); Long tenantId = loginUser.getTenantId(); customer.setTenantId(tenantId); return customerMapper.insert(customer); int rows = customerMapper.insert(customer); saveCustomerBinding(customer.getId(), customer.getBindUserId()); return rows; } /** @@ -210,12 +223,38 @@ * @return ç»æ */ @Override @Transactional(rollbackFor = Exception.class) public int updateCustomer(Customer customer) { LoginUser loginUser = SecurityUtils.getLoginUser(); Long tenantId = loginUser.getTenantId(); validateCustomerEditPermission(customer.getId()); customer.setTenantId(tenantId); return customerMapper.updateById(customer); int rows = customerMapper.updateById(customer); saveCustomerBinding(customer.getId(), customer.getBindUserId()); return rows; } /** * ä¿å客æ·ä¸ç»å½è´¦å·çä¸å¯¹ä¸ç»å®å ³ç³» */ private void saveCustomerBinding(Long customerId, Long bindUserId) { if (customerId == null) { return; } customerUserService.remove(new LambdaQueryWrapper<CustomerUser>() .eq(CustomerUser::getCustomerId, customerId)); if (bindUserId == null) { return; } // ä¸ä¸ªç»å½è´¦å·åªè½ç»å®ä¸ä¸ªå®¢æ· customerUserService.remove(new LambdaQueryWrapper<CustomerUser>() .eq(CustomerUser::getUserId, bindUserId)); CustomerUser binding = new CustomerUser(); binding.setCustomerId(customerId); binding.setUserId(bindUserId); customerUserService.save(binding); // ç»å®è´¦å·èªå¨æäºâ客æ·âè§è²ï¼ä½¿å ¶ç»å½ååªè½è®¿é®å®¢æ·é¨æ· jdbcTemplate.update("INSERT IGNORE INTO sys_user_role (user_id, role_id) " + "SELECT ?, role_id FROM sys_role WHERE role_key = 'customer' AND del_flag = '0'", bindUserId); } /** @@ -418,22 +457,6 @@ customer.setType(1); customer.setIsAssigned(0); return this.updateById(customer); } private void validateCustomerEditPermission(Long customerId) { Customer customer = customerMapper.selectById(customerId); if (customer == null) { throw new RuntimeException("å®¢æ·æ¡£æ¡ä¸åå¨"); } if (!hasSalesModuleReference(customerId)) { return; } if (Objects.equals(customer.getType(), 0)) { throw new RuntimeException("已被é宿¨¡åå¼ç¨çç§æµ·å®¢æ·ä¸è½ç¼è¾"); } if (Objects.equals(customer.getType(), 1) && Objects.equals(customer.getIsAssigned(), 1)) { throw new RuntimeException("å·²é¢ç¨å¹¶ä¸è¢«é宿¨¡åå¼ç¨çå ¬æµ·å®¢æ·ä¸è½ç¼è¾"); } } private void validatePublicSeaRecyclePermission(Long customerId) { src/main/java/com/ruoyi/customerPortal/controller/CustomerSubmissionController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,49 @@ package com.ruoyi.customerPortal.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.customerPortal.dto.ReviewSubmissionDto; import com.ruoyi.customerPortal.pojo.CustomerSubmission; import com.ruoyi.customerPortal.service.CustomerSubmissionService; import com.ruoyi.framework.web.domain.AjaxResult; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/customer/submission") @RequiredArgsConstructor public class CustomerSubmissionController { private final CustomerSubmissionService customerSubmissionService; @GetMapping("/mine") @PreAuthorize("@ss.hasPermi('customer:submission:mine')") public AjaxResult mine(Page<CustomerSubmission> page, Integer reportYear, Integer status) { return AjaxResult.success(customerSubmissionService.listMine(page, reportYear, status)); } @PostMapping @PreAuthorize("@ss.hasPermi('customer:submission:mine')") public AjaxResult submit(@RequestBody CustomerSubmission submission) { return AjaxResult.success(customerSubmissionService.submit(submission)); } @GetMapping("/manage/list") @PreAuthorize("@ss.hasPermi('customer:submission:manage')") public AjaxResult manageList(Page<CustomerSubmission> page, Long customerId, Integer reportYear, Integer status) { return AjaxResult.success(customerSubmissionService.listManage(page, customerId, reportYear, status)); } @PutMapping("/review") @PreAuthorize("@ss.hasPermi('customer:submission:manage')") public AjaxResult review(@RequestBody ReviewSubmissionDto dto) { customerSubmissionService.review(dto); return AjaxResult.success(); } } src/main/java/com/ruoyi/customerPortal/dto/ReviewSubmissionDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,13 @@ package com.ruoyi.customerPortal.dto; import lombok.Data; @Data public class ReviewSubmissionDto { private Long id; /** 1å¤çä¸ 2å·²åå¸ 3å·²éå */ private Integer status; private String resultText; private String resultFiles; private String reviewRemark; } src/main/java/com/ruoyi/customerPortal/mapper/CustomerSubmissionMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,7 @@ package com.ruoyi.customerPortal.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.customerPortal.pojo.CustomerSubmission; public interface CustomerSubmissionMapper extends BaseMapper<CustomerSubmission> { } src/main/java/com/ruoyi/customerPortal/pojo/CustomerSubmission.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,45 @@ package com.ruoyi.customerPortal.pojo; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.time.LocalDateTime; /** 客æ·å¹´åº¦ç³æ¥ææååå¸ç»æã */ @Data @TableName("customer_submission") public class CustomerSubmission { @TableId(type = IdType.AUTO) private Long id; private Long customerId; private Integer reportYear; private String reportName; private String materialFiles; /** 0å¾ å®¡æ ¸ 1å¤çä¸ 2å·²åå¸ 3å·²éå */ private Integer status; private String resultText; private String resultFiles; private String reviewRemark; private Long submitUserId; private String submitUserName; private Long publishUserId; private String publishUserName; private LocalDateTime publishTime; private Integer isDeleted; @TableField(fill = FieldFill.INSERT) private Long tenantId; @TableField(fill = FieldFill.INSERT) private Long deptId; @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @TableField(exist = false) private String customerName; } src/main/java/com/ruoyi/customerPortal/service/CustomerSubmissionService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,165 @@ package com.ruoyi.customerPortal.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.mapper.CustomerMapper; import com.ruoyi.basic.mapper.CustomerUserMapper; import com.ruoyi.basic.pojo.Customer; import com.ruoyi.basic.pojo.CustomerUser; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.customerPortal.dto.ReviewSubmissionDto; import com.ruoyi.customerPortal.mapper.CustomerSubmissionMapper; import com.ruoyi.customerPortal.pojo.CustomerSubmission; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.time.Year; import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class CustomerSubmissionService extends ServiceImpl<CustomerSubmissionMapper, CustomerSubmission> { private final CustomerUserMapper customerUserMapper; private final CustomerMapper customerMapper; public Page<CustomerSubmission> listMine(Page<CustomerSubmission> page, Integer reportYear, Integer status) { CustomerUser binding = currentBinding(); LambdaQueryWrapper<CustomerSubmission> query = new LambdaQueryWrapper<CustomerSubmission>() .eq(CustomerSubmission::getCustomerId, binding.getCustomerId()) .eq(CustomerSubmission::getIsDeleted, 0) .eq(reportYear != null, CustomerSubmission::getReportYear, reportYear) .eq(status != null, CustomerSubmission::getStatus, status) .orderByDesc(CustomerSubmission::getReportYear) .orderByDesc(CustomerSubmission::getCreateTime); return fillCustomerName(page(page, query)); } public Page<CustomerSubmission> listManage(Page<CustomerSubmission> page, Long customerId, Integer reportYear, Integer status) { ensureStaff(); LambdaQueryWrapper<CustomerSubmission> query = new LambdaQueryWrapper<CustomerSubmission>() .eq(CustomerSubmission::getIsDeleted, 0) .eq(customerId != null, CustomerSubmission::getCustomerId, customerId) .eq(reportYear != null, CustomerSubmission::getReportYear, reportYear) .eq(status != null, CustomerSubmission::getStatus, status) .orderByAsc(CustomerSubmission::getStatus) .orderByDesc(CustomerSubmission::getUpdateTime); return fillCustomerName(page(page, query)); } @Transactional(rollbackFor = Exception.class) public CustomerSubmission submit(CustomerSubmission input) { CustomerUser binding = currentBinding(); int currentYear = Year.now().getValue(); if (input.getReportYear() == null || input.getReportYear() < currentYear - 2 || input.getReportYear() > currentYear) { throw new ServiceException("åªè½æäº¤æè¿ä¸ä¸ªå¹´åº¦çè´¢å¡ææ"); } if (input.getMaterialFiles() == null || input.getMaterialFiles().isBlank()) { throw new ServiceException("请è³å°ä¸ä¼ ä¸ä»½ææ"); } CustomerSubmission entity = getOne(new LambdaQueryWrapper<CustomerSubmission>() .eq(CustomerSubmission::getCustomerId, binding.getCustomerId()) .eq(CustomerSubmission::getReportYear, input.getReportYear()) .eq(CustomerSubmission::getIsDeleted, 0), false); if (entity != null && entity.getStatus() != null && entity.getStatus() != 0 && entity.getStatus() != 3) { throw new ServiceException("ææå·²åçæç»æå·²åå¸ï¼ä¸è½å次修æ¹"); } if (entity == null) { entity = new CustomerSubmission(); entity.setCustomerId(binding.getCustomerId()); entity.setReportYear(input.getReportYear()); entity.setSubmitUserId(SecurityUtils.getUserId()); entity.setSubmitUserName(SecurityUtils.getLoginUser().getNickName()); entity.setIsDeleted(0); } entity.setReportName(input.getReportName()); entity.setMaterialFiles(input.getMaterialFiles()); entity.setStatus(0); entity.setReviewRemark(null); entity.setResultText(null); entity.setResultFiles(null); entity.setPublishUserId(null); entity.setPublishUserName(null); entity.setPublishTime(null); saveOrUpdate(entity); return entity; } @Transactional(rollbackFor = Exception.class) public void review(ReviewSubmissionDto dto) { ensureStaff(); if (dto.getId() == null || dto.getStatus() == null || (dto.getStatus() != 1 && dto.getStatus() != 2 && dto.getStatus() != 3)) { throw new ServiceException("å®¡æ ¸åæ°ä¸æ£ç¡®"); } CustomerSubmission entity = getById(dto.getId()); if (entity == null || Objects.equals(entity.getIsDeleted(), 1)) { throw new ServiceException("ç³æ¥è®°å½ä¸åå¨"); } Integer oldStatus = entity.getStatus(); if (dto.getStatus() == 1 && !Objects.equals(oldStatus, 0)) { throw new ServiceException("åªæå¾ å®¡æ ¸ææå¯ä»¥åç"); } if (dto.getStatus() == 2 && !Objects.equals(oldStatus, 1)) { throw new ServiceException("åªæå¤ç䏿æå¯ä»¥åå¸ç»æ"); } if (dto.getStatus() == 3 && !Objects.equals(oldStatus, 0) && !Objects.equals(oldStatus, 1)) { throw new ServiceException("å½åç¶æä¸è½éå"); } if (dto.getStatus() == 3 && (dto.getReviewRemark() == null || dto.getReviewRemark().isBlank())) { throw new ServiceException("éåæ¶å¿ é¡»å¡«ååå "); } if (dto.getStatus() == 2 && (dto.getResultText() == null || dto.getResultText().isBlank()) && (dto.getResultFiles() == null || dto.getResultFiles().isBlank())) { throw new ServiceException("å叿¶è¯·å¡«åç»æè¯´ææä¸ä¼ ç»ææä»¶"); } entity.setStatus(dto.getStatus()); entity.setResultText(dto.getResultText()); entity.setResultFiles(dto.getResultFiles()); entity.setReviewRemark(dto.getReviewRemark()); if (dto.getStatus() == 2) { entity.setPublishUserId(SecurityUtils.getUserId()); entity.setPublishUserName(SecurityUtils.getLoginUser().getNickName()); entity.setPublishTime(LocalDateTime.now()); } updateById(entity); } private CustomerUser currentBinding() { CustomerUser binding = customerUserMapper.selectOne(new LambdaQueryWrapper<CustomerUser>() .eq(CustomerUser::getUserId, SecurityUtils.getUserId()).last("limit 1")); if (binding == null) { throw new ServiceException("å½åè´¦å·å°æªç»å®å®¢æ·ï¼è¯·è系管çå"); } return binding; } private void ensureStaff() { if (!SecurityUtils.isAdmin(SecurityUtils.getUserId()) && SecurityUtils.hasRole("customer")) { throw new ServiceException("客æ·è´¦å·æ ææ§è¡æ¤æä½"); } } private Page<CustomerSubmission> fillCustomerName(Page<CustomerSubmission> result) { Set<Long> ids = result.getRecords().stream().map(CustomerSubmission::getCustomerId) .filter(Objects::nonNull).collect(Collectors.toSet()); Map<Long, Customer> customerMap = ids.isEmpty() ? Collections.emptyMap() : customerMapper.selectBatchIds(ids) .stream().collect(Collectors.toMap(Customer::getId, Function.identity(), (a, b) -> a)); result.getRecords().forEach(item -> { Customer customer = customerMap.get(item.getCustomerId()); item.setCustomerName(customer == null ? "" : customer.getCustomerName()); }); return result; } } src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java
@@ -42,6 +42,9 @@ private String source; // 项ç®åç±» private String projectClassification; private Long managerId; private String managerName; private Long salesmanId; src/main/java/com/ruoyi/projectManagement/pojo/Info.java
@@ -74,6 +74,12 @@ private String source; /** * 项ç®åç±» */ @TableField(value = "project_classification") private String projectClassification; /** * 项ç®ç»çid */ @TableField(value = "manager_id") src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerSimpleController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,134 @@ package com.ruoyi.purchase.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.domain.R; import com.ruoyi.purchase.mapper.PurchaseLedgerSimpleMapper; import com.ruoyi.purchase.pojo.PurchaseLedgerSimple; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.*; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Date; import java.util.List; /** * éè´å°è´¦ï¼ç®ï¼Controller * åªååºç¡å°è´¦çå¢å æ¹æ¥ä¸å¯¼åºï¼ä¸ä¸ååãä¾åºåã产åãå ¥åºç模åå ³èã */ @RestController @RequestMapping("/purchase/simpleLedger") @Tag(name = "éè´å°è´¦ï¼ç®ï¼") @AllArgsConstructor public class PurchaseLedgerSimpleController { private final PurchaseLedgerSimpleMapper purchaseLedgerSimpleMapper; /** * å页å表 */ @GetMapping("/list") @Operation(summary = "éè´å°è´¦ï¼ç®ï¼å页å表") public R list(@RequestParam(defaultValue = "1") long current, @RequestParam(defaultValue = "10") long size, @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate paymentDateStart, @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate paymentDateEnd, @RequestParam(required = false) String paymentMethod) { LambdaQueryWrapper<PurchaseLedgerSimple> wrapper = new LambdaQueryWrapper<>(); if (paymentDateStart != null) { wrapper.ge(PurchaseLedgerSimple::getPaymentDate, toDate(paymentDateStart)); } if (paymentDateEnd != null) { wrapper.le(PurchaseLedgerSimple::getPaymentDate, toDate(paymentDateEnd)); } if (paymentMethod != null && !paymentMethod.isBlank()) { wrapper.eq(PurchaseLedgerSimple::getPaymentMethod, paymentMethod); } wrapper.orderByDesc(PurchaseLedgerSimple::getPurchaseDate) .orderByDesc(PurchaseLedgerSimple::getId); return R.ok(purchaseLedgerSimpleMapper.selectPage(new Page<>(current, size), wrapper)); } /** * 详æ */ @GetMapping("/{id}") @Operation(summary = "éè´å°è´¦ï¼ç®ï¼è¯¦æ ") public R getById(@PathVariable Long id) { return R.ok(purchaseLedgerSimpleMapper.selectById(id)); } /** * æ°å¢ãç¼è¾ */ @PostMapping("/save") @Log(title = "éè´å°è´¦ï¼ç®ï¼", businessType = BusinessType.INSERT) @Operation(summary = "éè´å°è´¦ï¼ç®ï¼æ°å¢ãç¼è¾") public AjaxResult save(@RequestBody PurchaseLedgerSimple entity) { Date now = new Date(); if (entity.getId() == null) { entity.setCreateTime(now); entity.setUpdateTime(now); purchaseLedgerSimpleMapper.insert(entity); } else { entity.setUpdateTime(now); purchaseLedgerSimpleMapper.updateById(entity); } return AjaxResult.success(entity.getId()); } /** * å é¤ */ @DeleteMapping("/delete") @Log(title = "éè´å°è´¦ï¼ç®ï¼", businessType = BusinessType.DELETE) @Operation(summary = "éè´å°è´¦ï¼ç®ï¼å é¤") public AjaxResult delete(@RequestBody List<Long> ids) { if (ids == null || ids.isEmpty()) { return AjaxResult.error("è¯·éæ©è¦å é¤çæ°æ®"); } purchaseLedgerSimpleMapper.deleteBatchIds(ids); return AjaxResult.success(); } /** * å¯¼åº */ @PostMapping("/export") @Log(title = "éè´å°è´¦ï¼ç®ï¼", businessType = BusinessType.EXPORT) @Operation(summary = "éè´å°è´¦ï¼ç®ï¼å¯¼åº") public void export(HttpServletResponse response, @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate paymentDateStart, @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate paymentDateEnd, @RequestParam(required = false) String paymentMethod) { LambdaQueryWrapper<PurchaseLedgerSimple> wrapper = new LambdaQueryWrapper<>(); if (paymentDateStart != null) { wrapper.ge(PurchaseLedgerSimple::getPaymentDate, toDate(paymentDateStart)); } if (paymentDateEnd != null) { wrapper.le(PurchaseLedgerSimple::getPaymentDate, toDate(paymentDateEnd)); } if (paymentMethod != null && !paymentMethod.isBlank()) { wrapper.eq(PurchaseLedgerSimple::getPaymentMethod, paymentMethod); } wrapper.orderByDesc(PurchaseLedgerSimple::getPurchaseDate) .orderByDesc(PurchaseLedgerSimple::getId); List<PurchaseLedgerSimple> list = purchaseLedgerSimpleMapper.selectList(wrapper); ExcelUtil<PurchaseLedgerSimple> util = new ExcelUtil<>(PurchaseLedgerSimple.class); util.exportExcel(response, list, "éè´å°è´¦"); } private Date toDate(LocalDate date) { return Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()); } } src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerSimpleMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,12 @@ package com.ruoyi.purchase.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.purchase.pojo.PurchaseLedgerSimple; import org.apache.ibatis.annotations.Mapper; /** * éè´å°è´¦ï¼ç®ï¼Mapper */ @Mapper public interface PurchaseLedgerSimpleMapper extends BaseMapper<PurchaseLedgerSimple> { } src/main/java/com/ruoyi/purchase/pojo/PurchaseLedgerSimple.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,122 @@ package com.ruoyi.purchase.pojo; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; /** * éè´å°è´¦ï¼ç®ï¼å¯¹è±¡ purchase_ledger_simple * * ä» ä¿çéè´æ¥æãæ¯åºæ¥æãéé¢ãéè´ç©åãå票å·ç ã仿¬¾æ¹å¼ã夿³¨çåºç¡ä¿¡æ¯ï¼ * ä¸ä¸ååãä¾åºåã产åãå ¥åºç模åå ³èã */ @Getter @Setter @TableName("purchase_ledger_simple") @Schema(name = "PurchaseLedgerSimple对象", description = "éè´å°è´¦ï¼ç®ï¼") public class PurchaseLedgerSimple implements Serializable { private static final long serialVersionUID = 1L; @Schema(description = "主é®ID") @TableId(value = "id", type = IdType.AUTO) private Long id; /** * æ¯åºæ¥æ */ @Schema(description = "æ¯åºæ¥æ") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @Excel(name = "æ¯åºæ¥æ", width = 20, dateFormat = "yyyy-MM-dd") private Date paymentDate; /** * éè´æ¥æ */ @Schema(description = "éè´æ¥æ") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @Excel(name = "éè´æ¥æ", width = 20, dateFormat = "yyyy-MM-dd") private Date purchaseDate; /** * éé¢ */ @Schema(description = "éé¢") @Excel(name = "éé¢") private BigDecimal amount; /** * éè´ç©å */ @Schema(description = "éè´ç©å") @Excel(name = "éè´ç©å") private String purchaseGoods; /** * å票å·ç */ @Schema(description = "å票å·ç ") @Excel(name = "å票å·ç ") private String invoiceNumber; /** * 仿¬¾æ¹å¼ */ @Schema(description = "仿¬¾æ¹å¼") @Excel(name = "仿¬¾æ¹å¼") private String paymentMethod; /** * 夿³¨ */ @Schema(description = "夿³¨") @Excel(name = "夿³¨") private String remark; /** * å½å ¥äººid */ @Schema(description = "å½å ¥äººid") private Long recorderId; /** * å½å ¥äºº */ @Schema(description = "å½å ¥äºº") @Excel(name = "å½å ¥äºº") private String recorderName; /** * å½å ¥æ¥æ */ @Schema(description = "å½å ¥æ¥æ") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @Excel(name = "å½å ¥æ¥æ", width = 20, dateFormat = "yyyy-MM-dd") private Date entryDate; @Schema(description = "åå»ºç¨æ·") @TableField(fill = FieldFill.INSERT) private Long createUser; @TableField(fill = FieldFill.INSERT) private Long deptId; @Schema(description = "å建æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; @Schema(description = "æ´æ°æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; } src/main/java/com/ruoyi/sales/controller/BusinessApprovalController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,33 @@ package com.ruoyi.sales.controller; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.sales.dto.BusinessReviewDto; import com.ruoyi.sales.service.BusinessApprovalService; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/business/approval") @RequiredArgsConstructor public class BusinessApprovalController { private final BusinessApprovalService businessApprovalService; @PostMapping("/submit/{id}") @PreAuthorize("@ss.hasPermi('business:approval:submit')") public AjaxResult submit(@PathVariable Long id) { businessApprovalService.submit(id); return AjaxResult.success(); } @PutMapping("/review") @PreAuthorize("@ss.hasPermi('business:approval:review')") public AjaxResult review(@RequestBody BusinessReviewDto dto) { return AjaxResult.success(businessApprovalService.review(dto)); } } src/main/java/com/ruoyi/sales/dto/BusinessReviewDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,11 @@ package com.ruoyi.sales.dto; import lombok.Data; @Data public class BusinessReviewDto { private Long salesLedgerId; private Boolean approved; private String remark; private Long planId; } src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -9,6 +9,7 @@ import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Date; /** @@ -139,6 +140,15 @@ @TableField(fill = FieldFill.INSERT) private Long deptId; /** ä¸å¡å®¡æ¹ï¼0è稿 1å¾ å®¡æ¹ 2å·²éè¿ 3å·²éå */ private Integer businessApprovalStatus; private String businessApprovalRemark; private Long businessApprovedBy; private String businessApprovedName; private LocalDateTime businessApprovedTime; private LocalDateTime businessSubmittedTime; private Long projectManagementInfoId; @Schema(description = "æ¯å¦æç产记å½") @TableField(exist = false) private Boolean hasProductionRecord; src/main/java/com/ruoyi/sales/service/BusinessApprovalService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,124 @@ package com.ruoyi.sales.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.enums.PlanStageEnum; import com.ruoyi.common.enums.ReviewStatusEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.projectManagement.dto.PlanStageDto; import com.ruoyi.projectManagement.mapper.InfoMapper; import com.ruoyi.projectManagement.mapper.PlanMapper; import com.ruoyi.projectManagement.mapper.PlanNodeMapper; import com.ruoyi.projectManagement.pojo.Info; import com.ruoyi.projectManagement.pojo.Plan; import com.ruoyi.projectManagement.pojo.PlanNode; import com.ruoyi.sales.dto.BusinessReviewDto; import com.ruoyi.sales.mapper.SalesLedgerMapper; import com.ruoyi.sales.pojo.SalesLedger; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; @Service @RequiredArgsConstructor public class BusinessApprovalService { private final SalesLedgerMapper salesLedgerMapper; private final InfoMapper infoMapper; private final PlanMapper planMapper; private final PlanNodeMapper planNodeMapper; @Transactional(rollbackFor = Exception.class) public void submit(Long id) { SalesLedger ledger = requireLedger(id); Integer status = ledger.getBusinessApprovalStatus(); if (status != null && status == 2) { throw new ServiceException("该ä¸å¡å·²ç»å®¡æ¹éè¿"); } ledger.setBusinessApprovalStatus(1); ledger.setBusinessApprovalRemark(null); ledger.setBusinessSubmittedTime(LocalDateTime.now()); salesLedgerMapper.updateById(ledger); } @Transactional(rollbackFor = Exception.class) public Long review(BusinessReviewDto dto) { if (dto.getSalesLedgerId() == null || dto.getApproved() == null) { throw new ServiceException("审æ¹åæ°ä¸å®æ´"); } SalesLedger ledger = requireLedger(dto.getSalesLedgerId()); if (ledger.getBusinessApprovalStatus() == null || ledger.getBusinessApprovalStatus() != 1) { throw new ServiceException("åªæå¾ å®¡æ¹ä¸å¡å¯ä»¥å®¡æ ¸"); } ledger.setBusinessApprovedBy(SecurityUtils.getUserId()); ledger.setBusinessApprovedName(SecurityUtils.getLoginUser().getNickName()); ledger.setBusinessApprovedTime(LocalDateTime.now()); ledger.setBusinessApprovalRemark(dto.getRemark()); if (!dto.getApproved()) { ledger.setBusinessApprovalStatus(3); salesLedgerMapper.updateById(ledger); return null; } Long projectId = ledger.getProjectManagementInfoId(); if (projectId == null) { projectId = createProject(ledger, dto.getPlanId()); ledger.setProjectManagementInfoId(projectId); } ledger.setBusinessApprovalStatus(2); salesLedgerMapper.updateById(ledger); return projectId; } private Long createProject(SalesLedger ledger, Long selectedPlanId) { Plan plan = selectedPlanId == null ? planMapper.selectOne(new LambdaQueryWrapper<Plan>() .eq(Plan::getName, "项ç®ç³æ¥å é¶æ®µ") .eq(Plan::getIsDelete, 0).last("limit 1")) : planMapper.selectById(selectedPlanId); if (plan == null) { throw new ServiceException("æªæ¾å°â项ç®ç³æ¥å é¶æ®µâ计åï¼è¯·å æ§è¡å级SQL"); } List<PlanNode> nodes = planNodeMapper.selectList(new LambdaQueryWrapper<PlanNode>() .eq(PlanNode::getProjectManagementPlanId, plan.getId()) .eq(PlanNode::getIsDelete, 0).orderByAsc(PlanNode::getSort)); if (nodes.isEmpty()) { throw new ServiceException("项ç®å é¶æ®µå°æªé ç½®"); } Info info = new Info(); info.setNo("XM" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE) + String.format("%06d", ledger.getId())); info.setTitle(ledger.getProjectName() == null || ledger.getProjectName().isBlank() ? ledger.getCustomerName() + "ç³æ¥é¡¹ç®" : ledger.getProjectName()); info.setClientId(ledger.getCustomerId()); info.setClientName(ledger.getCustomerName()); info.setEstablishTime(LocalDate.now()); info.setProjectManagementPlanId(plan.getId()); info.setSource("ä¸å¡å®¡æ¹"); info.setManagerId(SecurityUtils.getUserId()); info.setManagerName(SecurityUtils.getLoginUser().getNickName()); info.setSalesmanName(ledger.getSalesman()); info.setIsDelete(0); info.setPlanStartTime(LocalDate.now()); info.setReviewStatus(ReviewStatusEnum.APPROVED.getCode()); info.setStatus(PlanStageEnum.TO_BEGIN.getCode()); info.setOrderDate(ledger.getExecutionDate()); info.setOrderAmount(ledger.getContractAmount() == null ? null : ledger.getContractAmount().toPlainString()); info.setRemark(ledger.getRemarks()); info.setAttachment(ledger.getAttachmentMaterials()); info.setDeptId(ledger.getDeptId()); info.setPlanStage(nodes.stream().map(node -> new PlanStageDto(node.getId(), node.getName(), PlanStageEnum.TO_BEGIN, node.getSort(), node.getEstimatedDuration())).toList()); infoMapper.insert(info); return info.getId(); } private SalesLedger requireLedger(Long id) { SalesLedger ledger = salesLedgerMapper.selectById(id); if (ledger == null) { throw new ServiceException("ä¸å¡è®°å½ä¸åå¨"); } return ledger; } } src/main/resources/application-dev.yml
@@ -74,7 +74,7 @@ druid: # ä¸»åºæ°æ®æº master: url: jdbc:mysql://36.213.90.123:11101/product-inventory-management-thzs?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 url: jdbc:mysql://36.213.150.237:10000/product-inventory-management-xmgl?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8 username: root password: xd@123456.. # ä»åºæ°æ®æº @@ -260,7 +260,7 @@ upload-dir: D:/ruoyi/prod/uploads # æ£å¼ç®å½ åæå é¤ path: D:/ruoyi/prod/uploads # ä¸ä¼ ç®å½ urlPrefix: /common # 龿¥åç¼ domain: http://127.0.0.1:7006 # åååç¼ domain: http://127.0.0.1:7005 # åååç¼ expired: 120 # è¿ææ¶é´(åä½:åé) useLimit: 10 # ä½¿ç¨æ¬¡æ° compress: true # æ¯å¦å缩 src/main/resources/mapper/projectManagement/InfoMapper.xml
@@ -14,6 +14,7 @@ <result property="establishTime" column="establish_time" jdbcType="TIMESTAMP"/> <result property="projectManagementPlanId" column="project_management_plan_id" jdbcType="BIGINT"/> <result property="source" column="source" jdbcType="VARCHAR"/> <result property="projectClassification" column="project_classification" jdbcType="VARCHAR"/> <result property="managerId" column="manager_id" jdbcType="BIGINT"/> <result property="managerName" column="manager_name" jdbcType="VARCHAR"/> <result property="salesmanId" column="salesman_id" jdbcType="BIGINT"/> src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -26,6 +26,13 @@ T1.entry_person, T1.remarks, T1.attachment_materials, T1.business_approval_status, T1.business_approval_remark, T1.business_approved_by, T1.business_approved_name, T1.business_approved_time, T1.business_submitted_time, T1.project_management_info_id, T1.tenant_id, T1.contract_amount, T1.execution_date, @@ -54,6 +61,13 @@ T1.entry_person, T1.remarks, T1.attachment_materials, T1.business_approval_status, T1.business_approval_remark, T1.business_approved_by, T1.business_approved_name, T1.business_approved_time, T1.business_submitted_time, T1.project_management_info_id, T1.tenant_id, T1.contract_amount, T1.net_contract_amount,