Merge branch 'dev_business' into fix/hsy/20260811
| | |
| | | `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'ç»æåç§°', |
| | | `base_salary` decimal(12, 2) NOT NULL COMMENT 'åºæ¬å·¥èµ', |
| | | `performance_ratio` decimal(4, 2) NULL DEFAULT 0.00 COMMENT '绩æå·¥èµå æ¯ï¼%ï¼', |
| | | `overtime_pay_ratio` decimal(4, 2) NULL DEFAULT 1.50 COMMENT 'å çå·¥èµåç', |
| | | `overtime_pay_ratio` decimal(4, 2) NULL DEFAULT 1.50 COMMENT '工使¥å çå·¥èµåç', |
| | | `rest_day_overtime_pay_ratio` decimal(4, 2) NULL DEFAULT 2.00 COMMENT '伿¯æ¥å çå·¥èµåç', |
| | | `legal_holiday_overtime_pay_ratio` decimal(4, 2) NULL DEFAULT 3.00 COMMENT 'æ³å®è忥å çå·¥èµåç', |
| | | `social_security_base` decimal(12, 2) NULL DEFAULT NULL COMMENT '社ä¿åºæ°', |
| | | `housing_fund_base` decimal(12, 2) NULL DEFAULT NULL COMMENT 'å
¬ç§¯éåºæ°', |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æï¼0-å¯ç¨ï¼1-ç¦ç¨', |
| | |
| | | `name` varchar(100) NOT NULL COMMENT 'ç»æåç§°', |
| | | `base_salary` decimal(12,2) NOT NULL COMMENT 'åºæ¬å·¥èµ', |
| | | `performance_ratio` decimal(4,2) DEFAULT 0 COMMENT '绩æå·¥èµå æ¯ï¼%ï¼', |
| | | `overtime_pay_ratio` decimal(4,2) DEFAULT 1.5 COMMENT 'å çå·¥èµåç', |
| | | `overtime_pay_ratio` decimal(4,2) DEFAULT 1.5 COMMENT '工使¥å çå·¥èµåç', |
| | | `rest_day_overtime_pay_ratio` decimal(4,2) DEFAULT 2.0 COMMENT '伿¯æ¥å çå·¥èµåç', |
| | | `legal_holiday_overtime_pay_ratio` decimal(4,2) DEFAULT 3.0 COMMENT 'æ³å®è忥å çå·¥èµåç', |
| | | `social_security_base` decimal(12,2) DEFAULT NULL COMMENT '社ä¿åºæ°', |
| | | `housing_fund_base` decimal(12,2) DEFAULT NULL COMMENT 'å
¬ç§¯éåºæ°', |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æï¼0-å¯ç¨ï¼1-ç¦ç¨', |
| | |
| | | -- ============================================= |
| | | -- æ§è¡å®ææç¤º |
| | | -- ============================================= |
| | | SELECT 'HRM 人åèµæºæ¨¡å SQL åå§å宿ï¼' AS result; |
| | | SELECT 'HRM 人åèµæºæ¨¡å SQL åå§å宿ï¼' AS result; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- HRM å çç³è¯·ï¼åååå
¬å®¡æ¹ + èªé
¬æ ¸ç®æ°æ®æº |
| | | |
| | | CREATE TABLE IF NOT EXISTS `hrm_overtime_application` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ç³è¯·ID', |
| | | `no` varchar(32) NOT NULL COMMENT 'ç³è¯·åå·', |
| | | `user_id` bigint NOT NULL COMMENT 'ç³»ç»ç¨æ·ID', |
| | | `employee_id` bigint NOT NULL COMMENT 'åå·¥ID', |
| | | `dept_id` bigint NOT NULL COMMENT 'é¨é¨ID', |
| | | `overtime_date` date NOT NULL COMMENT 'å çæ¥æ', |
| | | `start_time` time NOT NULL COMMENT 'å¼å§æ¶é´', |
| | | `end_time` time NOT NULL COMMENT 'ç»ææ¶é´', |
| | | `duration` decimal(6,1) NOT NULL COMMENT 'æ£é¤ç¨é¤åçå çæ¶é¿ï¼0.5å°æ¶åæ´ï¼', |
| | | `overtime_type` tinyint NOT NULL COMMENT '1-工使¥ï¼2-伿¯æ¥ï¼3-æ³å®è忥', |
| | | `cross_day` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦è·¨å¤©', |
| | | `meal_deduction` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦æ£é¤ç¨é¤æ¶é´', |
| | | `meal_deduction_hours` decimal(4,1) NOT NULL DEFAULT 0 COMMENT 'ç¨é¤æ£é¤å°æ¶æ°', |
| | | `reason` varchar(500) NOT NULL COMMENT 'å çåå ', |
| | | `related_type` tinyint DEFAULT NULL COMMENT 'å
³èç±»åï¼1-项ç®ï¼2-å·¥å', |
| | | `related_code` varchar(100) DEFAULT NULL COMMENT '项ç®/å·¥åç¼å·', |
| | | `work_content` varchar(1000) DEFAULT NULL COMMENT 'å·¥ä½å
容ç®è¿°', |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT '0-è稿ï¼10-审æ¹ä¸ï¼20-éè¿ï¼30-驳åï¼40-æ¤é', |
| | | `process_instance_id` varchar(64) DEFAULT NULL COMMENT 'åååå
¬æµç¨å®ä¾ID', |
| | | `approve_time` datetime DEFAULT NULL COMMENT '审æ¹å®ææ¶é´', |
| | | `creator` varchar(64) DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `updater` varchar(64) DEFAULT '' COMMENT 'æ´æ°è
', |
| | | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´', |
| | | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å é¤', |
| | | PRIMARY KEY (`id`), |
| | | UNIQUE KEY `uk_hrm_overtime_no` (`no`), |
| | | KEY `idx_hrm_overtime_user_date_status` (`user_id`, `overtime_date`, `status`), |
| | | KEY `idx_hrm_overtime_process_instance` (`process_instance_id`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HRMå çç³è¯·è¡¨'; |
| | | |
| | | -- åååå
¬æµç¨åç±»å·²å¨ bpm/manager/category ä¸ç»´æ¤ï¼åç±»ç¼ç 为 overtime_approveã |
| | | -- ä»éå¨è¯¥åç±»ä¸å»ºç«å¹¶å叿µç¨å®ä¹ key=hrm_overtimeã |
| | | |
| | | -- 人äºå®¡æ¹èååæé®æé |
| | | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 6007, 'å çç³è¯·', '', 2, 4, 6002, 'overtime', 'ep:timer', 'hrm/overtime/index', 'HrmOvertimeApplication', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 6007); |
| | | |
| | | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 60071, 'å çç³è¯·æ¥è¯¢', 'hrm:overtime:query', 3, 1, 6007, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 60071); |
| | | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 60072, 'å çç³è¯·æ°å¢', 'hrm:overtime:create', 3, 2, 6007, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 60072); |
| | | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 60073, 'å çç³è¯·ä¿®æ¹', 'hrm:overtime:update', 3, 3, 6007, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 60073); |
| | | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 60074, 'å çç³è¯·å é¤', 'hrm:overtime:delete', 3, 4, 6007, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 60074); |
| | | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 60075, 'å çç³è¯·æäº¤', 'hrm:overtime:submit', 3, 5, 6007, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 60075); |
| | | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 60076, 'å çç³è¯·æ¤é', 'hrm:overtime:cancel', 3, 6, 6007, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 60076); |
| | | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 60077, 'å çç³è¯·ç®¡ç', 'hrm:overtime:manage', 3, 7, 6007, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 60077); |
| | | |
| | | INSERT INTO `system_role_menu` (`role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 1, menu_id, '1', NOW(), '1', NOW(), b'0' FROM ( |
| | | SELECT 6007 menu_id UNION ALL SELECT 60071 UNION ALL SELECT 60072 UNION ALL |
| | | SELECT 60073 UNION ALL SELECT 60074 UNION ALL SELECT 60075 UNION ALL SELECT 60076 UNION ALL SELECT 60077 |
| | | ) ids WHERE NOT EXISTS (SELECT 1 FROM `system_role_menu` rm WHERE rm.`role_id` = 1 AND rm.`menu_id` = ids.menu_id); |
| | | |
| | | SELECT 'HRM å çç³è¯·åå§å宿ï¼è¯·å¨åååå
¬åå¸ hrm_overtime æµç¨' AS result; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- HRM èªé
¬ç»æé
ç½®èå䏿éï¼å¯é夿§è¡ï¼ |
| | | |
| | | INSERT INTO `system_menu` |
| | | (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, |
| | | `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | VALUES |
| | | (6025, 'èªé
Ⱦ', '', 2, 3, 6020, 'structure', 'ep:set-up', |
| | | 'hrm/salary/structure/index', 'HrmSalaryStructure', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'), |
| | | (60251, 'èªé
¬ç»ææ¥è¯¢', 'hrm:salary-structure:query', 3, 1, 6025, '', '', '', NULL, |
| | | 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'), |
| | | (60252, 'èªé
¬ç»ææ°å¢', 'hrm:salary-structure:create', 3, 2, 6025, '', '', '', NULL, |
| | | 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'), |
| | | (60253, 'èªé
¬ç»æä¿®æ¹', 'hrm:salary-structure:update', 3, 3, 6025, '', '', '', NULL, |
| | | 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'), |
| | | (60254, 'èªé
¬ç»æå é¤', 'hrm:salary-structure:delete', 3, 4, 6025, '', '', '', NULL, |
| | | 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0') |
| | | ON DUPLICATE KEY UPDATE |
| | | `name` = VALUES(`name`), `permission` = VALUES(`permission`), `parent_id` = VALUES(`parent_id`), |
| | | `path` = VALUES(`path`), `icon` = VALUES(`icon`), `component` = VALUES(`component`), |
| | | `component_name` = VALUES(`component_name`), `status` = VALUES(`status`), `deleted` = b'0'; |
| | | |
| | | INSERT INTO `system_role_menu` |
| | | (`role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) |
| | | SELECT 1, menu_id, '1', NOW(), '1', NOW(), b'0' |
| | | FROM ( |
| | | SELECT 6025 AS menu_id UNION ALL SELECT 60251 UNION ALL SELECT 60252 |
| | | UNION ALL SELECT 60253 UNION ALL SELECT 60254 |
| | | ) menu_ids |
| | | WHERE NOT EXISTS ( |
| | | SELECT 1 FROM `system_role_menu` role_menu |
| | | WHERE role_menu.`role_id` = 1 AND role_menu.`menu_id` = menu_ids.menu_id AND role_menu.`deleted` = b'0' |
| | | ); |
| | | |
| | | SELECT 'HRM èªé
¬ç»æèååå§å宿' AS result; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- èªé
¬ç»æå¢å 伿¯æ¥ãæ³å®è忥å çå·¥èµåç |
| | | -- å·²æç工使¥åçç»§ç»ä½¿ç¨ overtime_pay_ratio åæ®µ |
| | | |
| | | ALTER TABLE `hrm_salary_structure` |
| | | ADD COLUMN `rest_day_overtime_pay_ratio` decimal(4,2) DEFAULT 2.00 |
| | | COMMENT '伿¯æ¥å çå·¥èµåç' AFTER `overtime_pay_ratio`, |
| | | ADD COLUMN `legal_holiday_overtime_pay_ratio` decimal(4,2) DEFAULT 3.00 |
| | | COMMENT 'æ³å®è忥å çå·¥èµåç' AFTER `rest_day_overtime_pay_ratio`; |
| | |
| | | import org.flowable.task.api.TaskInfo; |
| | | import tools.jackson.databind.JsonNode; |
| | | |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | |
| | | || !BpmModelFormTypeEnum.NORMAL.getType().equals(processDefinitionInfo.getFormType())) { |
| | | return null; |
| | | } |
| | | // å岿µç¨å®ä¹ãä¸å¡è¡¨åæµç¨å¯è½æ²¡æåä½ formFieldsãæ¤æ¶æ²¡æå¯å±ç¤ºçæè¦ï¼ |
| | | // ä¸è½å ä¸ºåæ¡æµç¨æ°æ®ç¼ºå°è¡¨ååæ®µé
ç½®å¯¼è´æ´ä¸ªâæçæµç¨/å¾
åâå页æ¥è¯¢å¤±è´¥ã |
| | | if (ObjectUtil.isEmpty(processDefinitionInfo.getFormFields())) { |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | // è§£æè¡¨åé
ç½® |
| | | Map<String, BpmFormFieldVO> formFieldsMap = new LinkedHashMap<>(); |
| | |
| | | package cn.iocoder.yudao.module.bpm.service.message; |
| | | |
| | | import cn.iocoder.yudao.framework.web.config.WebProperties; |
| | | import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert; |
| | | import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum; |
| | | import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; |
| | | import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; |
| | | import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; |
| | | import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskTimeoutReqDTO; |
| | | import cn.iocoder.yudao.module.system.api.sms.SmsSendApi; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * BPM æ¶æ¯ Service å®ç°ç±» |
| | | * |
| | | * 注æï¼å·²å
³éçä¿¡éç¥åè½ï¼ç¸å
³æ¹æ³ä»
è®°å½æ¥å¿ï¼ä¸åè°ç¨çä¿¡å鿥å£ï¼ |
| | | * 以é¿å
âç信模æ¿ä¸åå¨âçé®é¢ã |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | |
| | | @Slf4j |
| | | public class BpmMessageServiceImpl implements BpmMessageService { |
| | | |
| | | @Resource |
| | | private SmsSendApi smsSendApi; |
| | | |
| | | @Resource |
| | | private WebProperties webProperties; |
| | | |
| | | @Override |
| | | public void sendMessageWhenProcessInstanceApprove(BpmMessageSendWhenProcessInstanceApproveReqDTO reqDTO) { |
| | | Map<String, Object> templateParams = new HashMap<>(); |
| | | templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); |
| | | templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); |
| | | smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(), |
| | | BpmMessageEnum.PROCESS_INSTANCE_APPROVE.getSmsTemplateCode(), templateParams)); |
| | | log.info("[sendMessageWhenProcessInstanceApprove][å·²å
³éçä¿¡éç¥ï¼è·³è¿åé][processInstanceId: {}]", reqDTO.getProcessInstanceId()); |
| | | } |
| | | |
| | | @Override |
| | | public void sendMessageWhenProcessInstanceReject(BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO) { |
| | | Map<String, Object> templateParams = new HashMap<>(); |
| | | templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); |
| | | templateParams.put("reason", reqDTO.getReason()); |
| | | templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); |
| | | smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(), |
| | | BpmMessageEnum.PROCESS_INSTANCE_REJECT.getSmsTemplateCode(), templateParams)); |
| | | log.info("[sendMessageWhenProcessInstanceReject][å·²å
³éçä¿¡éç¥ï¼è·³è¿åé][processInstanceId: {}]", reqDTO.getProcessInstanceId()); |
| | | } |
| | | |
| | | @Override |
| | | public void sendMessageWhenTaskAssigned(BpmMessageSendWhenTaskCreatedReqDTO reqDTO) { |
| | | Map<String, Object> templateParams = new HashMap<>(); |
| | | templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); |
| | | templateParams.put("taskName", reqDTO.getTaskName()); |
| | | templateParams.put("startUserNickname", reqDTO.getStartUserNickname()); |
| | | templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); |
| | | smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getAssigneeUserId(), |
| | | BpmMessageEnum.TASK_ASSIGNED.getSmsTemplateCode(), templateParams)); |
| | | log.info("[sendMessageWhenTaskAssigned][å·²å
³éçä¿¡éç¥ï¼è·³è¿åé][processInstanceId: {}]", reqDTO.getProcessInstanceId()); |
| | | } |
| | | |
| | | @Override |
| | | public void sendMessageWhenTaskTimeout(BpmMessageSendWhenTaskTimeoutReqDTO reqDTO) { |
| | | Map<String, Object> templateParams = new HashMap<>(); |
| | | templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); |
| | | templateParams.put("taskName", reqDTO.getTaskName()); |
| | | templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); |
| | | smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getAssigneeUserId(), |
| | | BpmMessageEnum.TASK_TIMEOUT.getSmsTemplateCode(), templateParams)); |
| | | } |
| | | |
| | | private String getProcessInstanceDetailUrl(String taskId) { |
| | | return webProperties.getAdminUi().getUrl() + "/bpm/process-instance/detail?id=" + taskId; |
| | | log.info("[sendMessageWhenTaskTimeout][å·²å
³éçä¿¡éç¥ï¼è·³è¿åé][processInstanceId: {}]", reqDTO.getProcessInstanceId()); |
| | | } |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | @Test |
| | | public void testGetSummary_normalFormWithoutFields_returnEmpty() { |
| | | // åå¤åæ°ï¼ä¸å¡è¡¨åæå岿µç¨å®ä¹å¯è½æ²¡æåä½ formFieldsã |
| | | BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionInfo(null, null); |
| | | |
| | | // è°ç¨ & æè¨ï¼ç¼ºå°æè¦å段æ¶è¿å空æè¦ï¼ä¸è½å½±åæ´ä¸ªå页æ¥å£ã |
| | | assertEquals(Collections.emptyList(), |
| | | FlowableUtils.getSummary(processDefinitionInfo, Collections.emptyMap())); |
| | | } |
| | | |
| | | @Test |
| | | public void testGetSummary_notNormalForm_returnNull() { |
| | | // åå¤åæ° |
| | | BpmProcessDefinitionInfoDO processDefinitionInfo = BpmProcessDefinitionInfoDO.builder() |
| | |
| | | import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; |
| | | import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; |
| | | import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; |
| | | import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; |
| | | import cn.iocoder.yudao.module.erp.enums.ErpPurchaseOrderSourceTypeEnum; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.dto.SrmSupplierRespDTO; |
| | |
| | | import java.util.Map; |
| | | |
| | | import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | |
| | | return success(purchaseOrderService.confirmReceipt(id)); |
| | | } |
| | | |
| | | @PostMapping("/reverse-approve") |
| | | @Operation(summary = "å审æ¹ï¼åååå
¬å·²åä»»å¡ä¸æ¤åå·²å®¡æ ¸è®¢åï¼ç´æ¥éæ°è¿å
¥å¾
å审æ¹ï¼") |
| | | @Parameter(name = "processInstanceId", description = "æµç¨å®ä¾ç¼å·", required = true) |
| | | @PreAuthorize("@ss.hasPermission('erp:purchase-order:update-status')") |
| | | public CommonResult<Boolean> reverseApprove(@RequestParam("processInstanceId") String processInstanceId) { |
| | | // 1. æ ¹æ®æµç¨å®ä¾ç¼å·æ¾å°éè´è®¢å |
| | | ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.getPurchaseOrderByProcessInstanceId(processInstanceId); |
| | | if (purchaseOrder == null) { |
| | | throw exception(PURCHASE_ORDER_NOT_EXISTS); |
| | | } |
| | | // 2. åå®¡æ ¸ï¼å·²å®¡æ ¸ -> æªå®¡æ ¸ï¼å«å
¥åº/éè´§æ ¡éªï¼ |
| | | purchaseOrderService.updatePurchaseOrderStatus(purchaseOrder.getId(), ErpAuditStatus.PROCESS.getStatus()); |
| | | // 3. èªå¨éæ°æäº¤å®¡æ¹ -> 订åç´æ¥åå°åååå
¬å¾
åä»»å¡ |
| | | purchaseOrderService.submitPurchaseOrder(purchaseOrder.getId(), "purchase_order_approve", getLoginUserId()); |
| | | return success(true); |
| | | } |
| | | |
| | | private PageResult<ErpPurchaseOrderRespVO> buildPurchaseOrderVOPageResult(PageResult<ErpPurchaseOrderDO> pageResult) { |
| | | if (CollUtil.isEmpty(pageResult.getList())) { |
| | | return PageResult.empty(pageResult.getTotal()); |
| | |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; |
| | | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| | | |
| | | @Schema(description = "管çåå° - ERP éè´ç³è¯·å页 Request VO") |
| | | @Data |
| | |
| | | private Integer status; |
| | | |
| | | @Schema(description = "ç³è¯·æ¶é´") |
| | | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) |
| | | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| | | private LocalDateTime[] requestTime; |
| | | |
| | | @Schema(description = "产åç¼å·", example = "1") |
| | |
| | | return selectOne(ErpPurchaseOrderDO::getNo, no); |
| | | } |
| | | |
| | | default ErpPurchaseOrderDO selectByProcessInstanceId(String processInstanceId) { |
| | | return selectOne(ErpPurchaseOrderDO::getProcessInstanceId, processInstanceId); |
| | | } |
| | | |
| | | default List<ErpPurchaseOrderDO> selectList(Long supplierId, Integer status) { |
| | | return selectList(new LambdaQueryWrapperX<ErpPurchaseOrderDO>() |
| | | .eqIfPresent(ErpPurchaseOrderDO::getSupplierId, supplierId) |
| | |
| | | PROCESS(10, "æªå®¡æ ¸"), // æªå®¡æ ¸/è稿 |
| | | APPROVING(15, "审æ¹ä¸"), // 审æ¹ä¸ |
| | | APPROVE(20, "å·²å®¡æ ¸"), // å®¡æ ¸éè¿ |
| | | CANCEL(30, "å·²ä½åº"); // å·²ä½åº/å·²æ¤é |
| | | CANCEL(30, "å·²ä½åº"), // å·²ä½åº/å·²æ¤é |
| | | REJECT(35, "已驳å"); // 审æ¹è¢«é©³å |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()).map(ErpAuditStatus::getStatus).toArray(Integer[]::new); |
| | | |
| | |
| | | ErpPurchaseOrderDO getPurchaseOrder(Long id); |
| | | |
| | | /** |
| | | * æ ¹æ® BPM æµç¨å®ä¾ç¼å·æ¥è¯¢éè´è®¢åï¼ç¨äºåååå
¬å审æ¹ï¼ |
| | | * |
| | | * @param processInstanceId æµç¨å®ä¾ç¼å· |
| | | * @return éè´è®¢å |
| | | */ |
| | | ErpPurchaseOrderDO getPurchaseOrderByProcessInstanceId(String processInstanceId); |
| | | |
| | | /** |
| | | * æ ¡éªéè´è®¢åï¼å·²ç»å®¡æ ¸éè¿ |
| | | * |
| | | * @param id ç¼å· |
| | |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| | | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | | import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | |
| | | /** |
| | | * BPM éè´è®¢å审æ¹åç±»ç¼ç |
| | | */ |
| | | private static final String PURCHASE_ORDER_APPROVE_CATEGORY_CODE = "purchase_request_approve"; |
| | | private static final String PURCHASE_ORDER_APPROVE_CATEGORY_CODE = "purchase_order_approve"; |
| | | /** |
| | | * BPM éè´è®¢åå®¡æ¹æµç¨å®ä¹ Keyï¼å建订ååèªå¨æäº¤å°åååå
¬å®¡æ¹ï¼ |
| | | */ |
| | | private static final String PURCHASE_ORDER_APPROVE_PROCESS_DEFINITION_KEY = "purchase_order_approve"; |
| | | |
| | | @Resource |
| | | private ErpPurchaseOrderMapper purchaseOrderMapper; |
| | |
| | | // 2.3 ç»å®éä»¶ |
| | | storageAttachmentApi.bindAttachments("file", "erp_purchase_order", |
| | | purchaseOrder.getId(), createReqVO.getBlobIds()); |
| | | |
| | | // 3. å建åèªå¨æäº¤å®¡æ¹å°åååå
¬ï¼å®¡æ¹å¨åååå
¬å®æï¼ä¸å¨æ¬é¡µé¢å®¡æ¹ï¼ |
| | | submitPurchaseOrder(purchaseOrder.getId(), PURCHASE_ORDER_APPROVE_PROCESS_DEFINITION_KEY, getLoginUserId()); |
| | | |
| | | return purchaseOrder.getId(); |
| | | } |
| | | |
| | |
| | | if (BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult)) { |
| | | return ErpAuditStatus.APPROVE.getStatus(); |
| | | } else if (BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult)) { |
| | | return ErpAuditStatus.PROCESS.getStatus(); |
| | | return ErpAuditStatus.REJECT.getStatus(); |
| | | } else if (BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult)) { |
| | | return ErpAuditStatus.CANCEL.getStatus(); |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public ErpPurchaseOrderDO getPurchaseOrderByProcessInstanceId(String processInstanceId) { |
| | | return purchaseOrderMapper.selectByProcessInstanceId(processInstanceId); |
| | | } |
| | | |
| | | @Override |
| | | public ErpPurchaseOrderDO validatePurchaseOrder(Long id) { |
| | | ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); |
| | | if (ObjectUtil.notEqual(purchaseOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.erp.service.purchase.listener; |
| | | |
| | | import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; |
| | | import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener; |
| | | import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseOrderService; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | /** |
| | | * éè´è®¢å审æ¹ç¶æçå¬å¨ |
| | | * |
| | | * çå¬ BPM æµç¨å®ä¾ç¶æåæ´äºä»¶ï¼æ´æ°éè´è®¢åç审æ¹ç¶æï¼åååå
¬å®¡æ¹åååï¼ |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @Component |
| | | @Slf4j |
| | | public class ErpPurchaseOrderStatusListener extends BpmProcessInstanceStatusEventListener { |
| | | |
| | | /** |
| | | * éè´è®¢åå®¡æ¹æµç¨å®ä¹ Key |
| | | */ |
| | | private static final String PROCESS_DEFINITION_KEY = "purchase_order_approve"; |
| | | |
| | | @Resource |
| | | private ErpPurchaseOrderService purchaseOrderService; |
| | | |
| | | @Override |
| | | protected String getProcessDefinitionKey() { |
| | | return PROCESS_DEFINITION_KEY; |
| | | } |
| | | |
| | | @Override |
| | | protected void onEvent(BpmProcessInstanceStatusEvent event) { |
| | | Long orderId; |
| | | try { |
| | | orderId = Long.parseLong(event.getBusinessKey()); |
| | | } catch (NumberFormatException e) { |
| | | log.warn("[onEvent] businessKey({}) 䏿¯ææçéè´è®¢åç¼å·", event.getBusinessKey()); |
| | | return; |
| | | } |
| | | |
| | | log.info("[onEvent] æ¶å°BPM审æ¹äºä»¶ï¼orderId={}, status={}", orderId, event.getStatus()); |
| | | |
| | | try { |
| | | purchaseOrderService.updatePurchaseOrderAuditStatus(orderId, event.getStatus()); |
| | | log.info("[onEvent] éè´è®¢å({}) 审æ¹ç¶ææ´æ°å®æ", orderId); |
| | | } catch (Exception e) { |
| | | log.error("[onEvent] æ´æ°éè´è®¢å审æ¹ç¶æå¤±è´¥ï¼orderId={}", orderId, e); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi; |
| | | import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsCreateReqDTO; |
| | | import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import jakarta.annotation.Resource; |
| | |
| | | @Validated |
| | | @Slf4j |
| | | public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { |
| | | |
| | | /** |
| | | * MPS ç¶æï¼å·²åæ¶ï¼å¯¹åº MES 模å MesProMpsStatusEnum.CANCELED çå¼ 3ï¼ |
| | | */ |
| | | private static final Integer MPS_STATUS_CANCELED = 3; |
| | | |
| | | @Resource |
| | | private ErpSaleOrderMapper saleOrderMapper; |
| | |
| | | if (item.getNeedProduction() == null || item.getNeedProduction() != 1) { |
| | | continue; |
| | | } |
| | | // é¿å
审æ¹/å审æ¹é夿ä½å¯¼è´åä¸ä¸ªéå®è®¢åå·äº§ç夿¡ MPS |
| | | MesProMpsRespDTO existingMps = mpsApi.getMpsBySaleOrderItemId(item.getId()); |
| | | if (existingMps != null && ObjectUtil.notEqual(existingMps.getStatus(), MPS_STATUS_CANCELED)) { |
| | | log.info("[createMpsForSaleOrder] éå®è®¢åæç»({}) å·²åå¨ MPS({})ï¼ç¶æ={}ï¼è·³è¿å建", |
| | | item.getId(), existingMps.getId(), existingMps.getStatus()); |
| | | continue; |
| | | } |
| | | try { |
| | | Long mpsId = createMpsForSaleOrderItem(saleOrder, item); |
| | | if (mpsId != null) { |
| | |
| | | ErrorCode RESIGNATION_APPLICATION_EXISTS = new ErrorCode(1_030_003_005, "该å工已åå¨ç¦»èç³è¯·ï¼è¯·å¿éå¤æäº¤"); |
| | | ErrorCode RESIGNATION_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_030_003_006, "离èå®¡æ¹æµç¨ä¸åå¨"); |
| | | |
| | | // ========== å çç³è¯· 1-030-008-000 ========== |
| | | ErrorCode OVERTIME_APPLICATION_NOT_EXISTS = new ErrorCode(1_030_008_000, "å çç³è¯·ä¸åå¨"); |
| | | ErrorCode OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT = new ErrorCode(1_030_008_001, "å çç³è¯·æ´æ°å¤±è´¥ï¼åå ï¼ä¸æ¯èç¨¿ç¶æ"); |
| | | ErrorCode OVERTIME_APPLICATION_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_030_008_002, "å çç³è¯·æäº¤å¤±è´¥ï¼åå ï¼ä¸æ¯èç¨¿ç¶æ"); |
| | | ErrorCode OVERTIME_APPLICATION_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_030_008_003, "æ´æ°å çç³è¯·å®¡æ¹ç¶æå¤±è´¥ï¼åå ï¼ä¸æ¯å®¡æ¹ä¸ç¶æ"); |
| | | ErrorCode OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_030_008_004, "å çå®¡æ¹æµç¨ä¸åå¨ï¼è¯·å
å¨åååå
¬ä¸é
置并å叿µç¨"); |
| | | ErrorCode OVERTIME_APPLICATION_EMPLOYEE_NOT_EXISTS = new ErrorCode(1_030_008_005, "å½åè´¦å·æªå
³èå工档æ¡"); |
| | | ErrorCode OVERTIME_APPLICATION_TIME_INVALID = new ErrorCode(1_030_008_006, "å çæ¶æ®µææ£é¤æ¶é¿ä¸åæ³"); |
| | | |
| | | // ========== ç¨æ·æ°æ®äº¤æ¥ 1-030-007-000 ========== |
| | | ErrorCode USER_HANDOVER_NOT_EXISTS = new ErrorCode(1_030_007_000, "ç¨æ·äº¤æ¥è®°å½ä¸åå¨"); |
| | | ErrorCode USER_HANDOVER_ALREADY_EXISTS = new ErrorCode(1_030_007_001, "该离èç³è¯·å·²åå¨äº¤æ¥è®°å½"); |
| | |
| | | ErrorCode EMPLOYEE_SOCIAL_SECURITY_NOT_EXISTS = new ErrorCode(1_030_005_009, "å工社ä¿å
¬ç§¯éæ¡£æ¡ä¸åå¨"); |
| | | ErrorCode SOCIAL_SECURITY_SCHEME_NOT_EXISTS = new ErrorCode(1_030_005_010, "社ä¿å
¬ç§¯éæ¹æ¡ä¸åå¨"); |
| | | ErrorCode LEAVE_TYPE_CONFIG_NOT_EXISTS = new ErrorCode(1_030_005_011, "请åç±»åæ£æ¬¾é
ç½®ä¸åå¨"); |
| | | ErrorCode LEAVE_TYPE_CONFIG_TYPE_EXISTS = new ErrorCode(1_030_005_022, "该请åç±»åæ£æ¬¾é
置已åå¨"); |
| | | ErrorCode SALARY_PAYMENT_EXISTS = new ErrorCode(1_030_005_012, "è¯¥å¨æèªèµåæ¾å°è´¦å·²åå¨"); |
| | | ErrorCode SALARY_CALCULATION_NO_CONFIRMED = new ErrorCode(1_030_005_013, "è¯¥å¨ææ²¡æå·²ç¡®è®¤çèªé
¬æ ¸ç®è®°å½"); |
| | | ErrorCode SALARY_PAYMENT_ALREADY_PAY = new ErrorCode(1_030_005_014, "èªèµåæ¾å°è´¦å·²åæ¾ï¼è¯·å¿é夿ä½"); |
| | |
| | | ErrorCode SALARY_PAYMENT_REVOKE_FAIL = new ErrorCode(1_030_005_022, "æ¤éåæ¾å¤±è´¥ï¼åå ï¼è¯¥æç»æªåæ¾"); |
| | | ErrorCode SALARY_PAYMENT_DELETE_FAIL = new ErrorCode(1_030_005_023, "å é¤å¤±è´¥ï¼åå ï¼ä»
å¾
åæ¾ç¶æå¯å é¤ï¼è¯·å
æ¤é已忾æç»"); |
| | | ErrorCode SALARY_PAYMENT_HAS_PAID_DETAIL = new ErrorCode(1_030_005_024, "å é¤å¤±è´¥ï¼åå ï¼åå¨å·²åæ¾æç»ï¼è¯·å
æ¤é"); |
| | | ErrorCode SALARY_STRUCTURE_NAME_EXISTS = new ErrorCode(1_030_005_025, "èªé
¬ç»æåç§°å·²åå¨"); |
| | | ErrorCode SALARY_STRUCTURE_IN_USE = new ErrorCode(1_030_005_026, "èªé
¬ç»ææ£å¨è¢«å工使ç¨ï¼æ æ³å é¤"); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.enums; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Arrays; |
| | | |
| | | /** å çç±»ååæ³å®å·¥èµåçã */ |
| | | @Getter |
| | | @RequiredArgsConstructor |
| | | public enum HrmOvertimeTypeEnum { |
| | | |
| | | WORKDAY(1, "工使¥å ç", new BigDecimal("1.5")), |
| | | REST_DAY(2, "伿¯æ¥å ç", new BigDecimal("2.0")), |
| | | LEGAL_HOLIDAY(3, "æ³å®è忥å ç", new BigDecimal("3.0")); |
| | | |
| | | private final Integer type; |
| | | private final String name; |
| | | private final BigDecimal salaryMultiplier; |
| | | |
| | | public static HrmOvertimeTypeEnum valueOfType(Integer type) { |
| | | return Arrays.stream(values()).filter(item -> item.type.equals(type)).findFirst().orElse(null); |
| | | } |
| | | |
| | | public static String getName(Integer type) { |
| | | HrmOvertimeTypeEnum value = valueOfType(type); |
| | | return value == null ? "" : value.name; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.approval; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; |
| | | import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.*; |
| | | import cn.iocoder.yudao.module.hrm.service.approval.HrmOvertimeApplicationService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | |
| | | @Tag(name = "管çåå° - HRM å çç³è¯·") |
| | | @RestController |
| | | @RequestMapping("/hrm/overtime") |
| | | @Validated |
| | | public class HrmOvertimeApplicationController { |
| | | @Resource private HrmOvertimeApplicationService service; |
| | | @Resource private SecurityFrameworkService securityFrameworkService; |
| | | |
| | | @PostMapping("/create") @PreAuthorize("@ss.hasPermission('hrm:overtime:create')") |
| | | public CommonResult<Long> create(@Valid @RequestBody HrmOvertimeApplicationSaveReqVO reqVO) { |
| | | return success(service.create(reqVO, SecurityFrameworkUtils.getLoginUserId())); |
| | | } |
| | | @PutMapping("/update") @PreAuthorize("@ss.hasPermission('hrm:overtime:update')") |
| | | public CommonResult<Boolean> update(@Valid @RequestBody HrmOvertimeApplicationSaveReqVO reqVO) { |
| | | service.update(reqVO, SecurityFrameworkUtils.getLoginUserId()); return success(true); |
| | | } |
| | | @DeleteMapping("/delete") @PreAuthorize("@ss.hasPermission('hrm:overtime:delete')") |
| | | public CommonResult<Boolean> delete(@RequestParam Long id) { |
| | | service.delete(id, SecurityFrameworkUtils.getLoginUserId()); return success(true); |
| | | } |
| | | @GetMapping("/get") @PreAuthorize("@ss.hasAnyPermissions('hrm:overtime:query', 'bpm:task:query')") |
| | | public CommonResult<HrmOvertimeApplicationRespVO> get(@RequestParam Long id) { |
| | | return success(service.getDetail(id, SecurityFrameworkUtils.getLoginUserId(), canManage())); |
| | | } |
| | | @GetMapping("/current-applicant") @PreAuthorize("@ss.hasPermission('hrm:overtime:create')") |
| | | public CommonResult<HrmOvertimeApplicationRespVO> currentApplicant() { |
| | | return success(service.getCurrentApplicant(SecurityFrameworkUtils.getLoginUserId())); |
| | | } |
| | | @GetMapping("/page") @PreAuthorize("@ss.hasPermission('hrm:overtime:query')") |
| | | public CommonResult<PageResult<HrmOvertimeApplicationRespVO>> page(@Valid HrmOvertimeApplicationPageReqVO reqVO) { |
| | | if (!canManage()) { |
| | | reqVO.setUserId(SecurityFrameworkUtils.getLoginUserId()); |
| | | } |
| | | return success(service.getPage(reqVO)); |
| | | } |
| | | @PostMapping("/submit") @PreAuthorize("@ss.hasPermission('hrm:overtime:submit')") |
| | | public CommonResult<Boolean> submit(@RequestParam Long id, @RequestParam String processDefinitionKey) { |
| | | service.submit(id, processDefinitionKey, SecurityFrameworkUtils.getLoginUserId()); return success(true); |
| | | } |
| | | @PostMapping("/cancel") @PreAuthorize("@ss.hasPermission('hrm:overtime:cancel')") |
| | | public CommonResult<Boolean> cancel(@RequestParam Long id) { |
| | | service.cancel(id, SecurityFrameworkUtils.getLoginUserId()); return success(true); |
| | | } |
| | | @GetMapping("/approve-process-definition-list") @PreAuthorize("@ss.hasPermission('hrm:overtime:query')") |
| | | public CommonResult<List<Map<String, Object>>> processes() { return success(service.getApproveProcessDefinitionList()); } |
| | | |
| | | private boolean canManage() { |
| | | return securityFrameworkService.hasPermission("hrm:overtime:manage"); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.time.LocalDate; |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class HrmOvertimeApplicationPageReqVO extends PageParam { |
| | | private String no; |
| | | private Long userId; |
| | | private Long deptId; |
| | | private LocalDate overtimeDate; |
| | | private Integer overtimeType; |
| | | private Integer status; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | |
| | | @Schema(description = "管çåå° - å çç³è¯· Response VO") |
| | | @Data |
| | | public class HrmOvertimeApplicationRespVO { |
| | | private Long id; |
| | | private String no; |
| | | private Long userId; |
| | | private Long employeeId; |
| | | private String employeeName; |
| | | private String employeeNo; |
| | | private Long deptId; |
| | | private String deptName; |
| | | private String postName; |
| | | private LocalDate overtimeDate; |
| | | private LocalTime startTime; |
| | | private LocalTime endTime; |
| | | private BigDecimal duration; |
| | | private Integer overtimeType; |
| | | private String overtimeTypeName; |
| | | private Boolean crossDay; |
| | | private Boolean mealDeduction; |
| | | private BigDecimal mealDeductionHours; |
| | | private String reason; |
| | | private Integer relatedType; |
| | | private String relatedCode; |
| | | private String workContent; |
| | | private Integer status; |
| | | private String statusName; |
| | | private String processInstanceId; |
| | | private LocalDateTime approveTime; |
| | | private LocalDateTime createTime; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.DecimalMin; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalTime; |
| | | |
| | | @Schema(description = "管çåå° - å çç³è¯·æ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | | public class HrmOvertimeApplicationSaveReqVO { |
| | | private Long id; |
| | | @NotNull(message = "å çæ¥æä¸è½ä¸ºç©º") |
| | | private LocalDate overtimeDate; |
| | | @NotNull(message = "å¼å§æ¶é´ä¸è½ä¸ºç©º") |
| | | private LocalTime startTime; |
| | | @NotNull(message = "ç»ææ¶é´ä¸è½ä¸ºç©º") |
| | | private LocalTime endTime; |
| | | @NotNull(message = "å çæ¶é¿ä¸è½ä¸ºç©º") |
| | | @DecimalMin(value = "0.5", message = "å çæ¶é¿ä¸è½å°äº 0.5 å°æ¶") |
| | | private BigDecimal duration; |
| | | @NotNull(message = "å çç±»åä¸è½ä¸ºç©º") |
| | | private Integer overtimeType; |
| | | private Boolean crossDay; |
| | | private Boolean mealDeduction; |
| | | private BigDecimal mealDeductionHours; |
| | | @NotBlank(message = "å çåå ä¸è½ä¸ºç©º") |
| | | private String reason; |
| | | private Integer relatedType; |
| | | private String relatedCode; |
| | | private String workContent; |
| | | } |
| | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordImportExcelVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordImportReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordRespVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO; |
| | |
| | | HrmEmployeeDO employee = employeeMap.get(respVO.getUserId()); |
| | | if (employee != null) { |
| | | respVO.setUserName(employee.getName()); |
| | | respVO.setPhone(employee.getPhone()); |
| | | } |
| | | // é¨é¨åç§° |
| | | DeptRespDTO dept = deptMap.get(respVO.getDeptId()); |
| | |
| | | HrmEmployeeDO employee = employeeService.getEmployee(attendanceRecord.getUserId()); |
| | | if (employee != null) { |
| | | respVO.setUserName(employee.getName()); |
| | | respVO.setPhone(employee.getPhone()); |
| | | } |
| | | } |
| | | if (attendanceRecord.getDeptId() != null) { |
| | |
| | | return success(respVO); |
| | | } |
| | | |
| | | @GetMapping("/get-import-template") |
| | | @Operation(summary = "ä¸è½½èå¤è®°å½å¯¼å
¥æ¨¡æ¿") |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance-record:import')") |
| | | public void importTemplate(HttpServletResponse response) throws IOException { |
| | | List<HrmAttendanceRecordImportExcelVO> list = Collections.singletonList( |
| | | HrmAttendanceRecordImportExcelVO.builder() |
| | | .userName("å¼ ä¸") |
| | | .phone("13800138000") |
| | | .date(java.time.LocalDate.of(2026, 1, 15)) |
| | | .clockInTime(java.time.LocalDateTime.of(2026, 1, 15, 8, 30)) |
| | | .clockOutTime(java.time.LocalDateTime.of(2026, 1, 15, 17, 30)) |
| | | .clockInType(1) |
| | | .clockOutType(1) |
| | | .location("åå
¬åº") |
| | | .remark("ç¤ºä¾æ°æ®") |
| | | .build() |
| | | ); |
| | | ExcelUtils.write(response, "èå¤å¯¼å
¥æ¨¡æ¿.xls", "èå¤è®°å½", HrmAttendanceRecordImportExcelVO.class, list); |
| | | } |
| | | |
| | | @PostMapping("/import") |
| | | @Operation(summary = "导å
¥èå¤è®°å½") |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance-record:import')") |
| | | public CommonResult<String> importExcel(@Valid HrmAttendanceRecordImportReqVO importReqVO) throws IOException { |
| | | List<HrmAttendanceRecordImportExcelVO> list = ExcelUtils.read(importReqVO.getFile(), HrmAttendanceRecordImportExcelVO.class); |
| | | if (CollUtil.isEmpty(list)) { |
| | | return success("没æå¯å¯¼å
¥çæ°æ®"); |
| | | } |
| | | int successCount = 0; |
| | | Set<String> missingNames = new LinkedHashSet<>(); |
| | | Set<String> duplicateNames = new LinkedHashSet<>(); |
| | | Set<String> invalidRows = new LinkedHashSet<>(); |
| | | for (HrmAttendanceRecordImportExcelVO item : list) { |
| | | if (item.getDate() == null) { |
| | | invalidRows.add((item.getUserName() == null || item.getUserName().isBlank()) ? "æªå¡«å§åçè¡" : "è夿¥æä¸ºç©º(" + item.getUserName().trim() + ")"); |
| | | continue; |
| | | } |
| | | if (item.getUserName() == null || item.getUserName().isBlank()) { |
| | | invalidRows.add("è夿¥æä¸º " + item.getDate() + " 使ªå¡«åå·¥å§å"); |
| | | continue; |
| | | } |
| | | List<HrmEmployeeDO> employees = employeeService.getEmployeeListByName(item.getUserName().trim()); |
| | | if (employees.isEmpty()) { |
| | | missingNames.add(item.getUserName().trim()); |
| | | continue; |
| | | } |
| | | HrmEmployeeDO employee = employees.get(0); |
| | | // åå¨å¤ä¸ªåååå·¥æ¶ï¼ç¨ææºå·åºå |
| | | if (employees.size() > 1) { |
| | | String phone = item.getPhone() != null ? item.getPhone().trim() : null; |
| | | List<HrmEmployeeDO> matchedByPhone = new ArrayList<>(); |
| | | if (phone != null && !phone.isEmpty()) { |
| | | for (HrmEmployeeDO emp : employees) { |
| | | if (phone.equals(emp.getPhone())) { |
| | | matchedByPhone.add(emp); |
| | | } |
| | | } |
| | | } |
| | | if (matchedByPhone.size() == 1) { |
| | | employee = matchedByPhone.get(0); |
| | | } else { |
| | | duplicateNames.add(item.getUserName().trim()); |
| | | continue; |
| | | } |
| | | } |
| | | HrmAttendanceRecordDO record = attendanceRecordService.getAttendanceRecordByUserIdAndDate(employee.getId(), item.getDate()); |
| | | if (record == null) { |
| | | record = HrmAttendanceRecordDO.builder() |
| | | .userId(employee.getId()).deptId(employee.getDeptId()).date(item.getDate()) |
| | | .clockInTime(item.getClockInTime()).clockOutTime(item.getClockOutTime()) |
| | | .clockInType(item.getClockInType()).clockOutType(item.getClockOutType()) |
| | | .location(item.getLocation()).remark(item.getRemark()) |
| | | .dataSource(2).build(); |
| | | attendanceRecordService.createImportedRecord(record); |
| | | } else if (Boolean.TRUE.equals(importReqVO.getUpdateSupport())) { |
| | | record.setClockInTime(item.getClockInTime()); |
| | | record.setClockOutTime(item.getClockOutTime()); |
| | | record.setClockInType(item.getClockInType()); |
| | | record.setClockOutType(item.getClockOutType()); |
| | | record.setLocation(item.getLocation()); |
| | | record.setRemark(item.getRemark()); |
| | | attendanceRecordService.updateImportedRecord(record); |
| | | } |
| | | successCount++; |
| | | } |
| | | StringBuilder msg = new StringBuilder("æå导å
¥ " + successCount + " æ¡"); |
| | | if (!missingNames.isEmpty()) { |
| | | msg.append("ï¼ä»¥ä¸åå·¥ä¸åå¨ï¼æªè½å¯¼å
¥ï¼").append(String.join("ã", missingNames)); |
| | | } |
| | | if (!duplicateNames.isEmpty()) { |
| | | msg.append("ï¼ä»¥ä¸åå·¥åå¨å¤ååååå·¥ï¼éè¡¥å
ææºå·åºåï¼æªè½å¯¼å
¥ï¼").append(String.join("ã", duplicateNames)); |
| | | } |
| | | if (!invalidRows.isEmpty()) { |
| | | msg.append("ï¼ä»¥ä¸è®°å½æ°æ®ä¸å®æ´ï¼æªè½å¯¼å
¥ï¼").append(String.join("ã", invalidRows)); |
| | | } |
| | | return success(msg.toString()); |
| | | } |
| | | |
| | | @GetMapping("/export-excel") |
| | | @Operation(summary = "导åºèå¤è®°å½ Excel") |
| | | @PreAuthorize("@ss.hasPermission('hrm:attendance:export')") |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; |
| | | |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| | | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * èå¤è®°å½ Excel 导å
¥æ¨¡æ¿ VO |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class HrmAttendanceRecordImportExcelVO { |
| | | |
| | | @ExcelProperty("åå·¥å§å") |
| | | private String userName; |
| | | |
| | | @ExcelProperty("ææºå·") |
| | | private String phone; |
| | | |
| | | @ExcelProperty("è夿¥æ") |
| | | private LocalDate date; |
| | | |
| | | @ExcelProperty("ä¸çæå¡æ¶é´") |
| | | private LocalDateTime clockInTime; |
| | | |
| | | @ExcelProperty("ä¸çæå¡æ¶é´") |
| | | private LocalDateTime clockOutTime; |
| | | |
| | | @ExcelProperty(value = "ä¸çæå¡ç±»å", converter = DictConvert.class) |
| | | @DictFormat("hrm_clock_type") |
| | | private Integer clockInType; |
| | | |
| | | @ExcelProperty(value = "ä¸çæå¡ç±»å", converter = DictConvert.class) |
| | | @DictFormat("hrm_clock_type") |
| | | private Integer clockOutType; |
| | | |
| | | @ExcelProperty("æå¡å°ç¹") |
| | | private String location; |
| | | |
| | | @ExcelProperty("夿³¨") |
| | | private String remark; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | @Schema(description = "管çåå° - èå¤è®°å½å¯¼å
¥ Request VO") |
| | | @Data |
| | | public class HrmAttendanceRecordImportReqVO { |
| | | |
| | | @Schema(description = "Excel æä»¶", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "Excel æä»¶ä¸è½ä¸ºç©º") |
| | | private MultipartFile file; |
| | | |
| | | @Schema(description = "æ¯å¦è¦çå·²åå¨çæ°æ®") |
| | | private Boolean updateSupport = false; |
| | | } |
| | |
| | | @ExcelProperty("é¨é¨åç§°") |
| | | private String deptName; |
| | | |
| | | @Schema(description = "ææºå·") |
| | | @ExcelProperty("ææºå·") |
| | | private String phone; |
| | | |
| | | @Schema(description = "è夿¥æ") |
| | | @ExcelProperty("è夿¥æ") |
| | | private LocalDate date; |
| | |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmLeaveTypeConfigCreateReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmLeaveTypeConfigRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmLeaveTypeConfigSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmLeaveTypeConfigDO; |
| | |
| | | |
| | | @GetMapping("/list") |
| | | @Operation(summary = "è·åææè¯·åç±»åé
ç½®å表") |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary:query')") |
| | | @PreAuthorize("@ss.hasPermission('hrm:leave-type-config:query')") |
| | | public CommonResult<List<HrmLeaveTypeConfigRespVO>> getLeaveTypeConfigList() { |
| | | List<HrmLeaveTypeConfigDO> list = leaveTypeConfigService.getLeaveTypeConfigList(); |
| | | return success(BeanUtils.toBean(list, HrmLeaveTypeConfigRespVO.class)); |
| | |
| | | @GetMapping("/get") |
| | | @Operation(summary = "è·å请åç±»åé
ç½®") |
| | | @Parameter(name = "leaveType", description = "请åç±»å", required = true, example = "1") |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary:query')") |
| | | @PreAuthorize("@ss.hasPermission('hrm:leave-type-config:query')") |
| | | public CommonResult<HrmLeaveTypeConfigRespVO> getLeaveTypeConfig(@RequestParam("leaveType") Integer leaveType) { |
| | | HrmLeaveTypeConfigDO config = leaveTypeConfigService.getLeaveTypeConfig(leaveType); |
| | | return success(BeanUtils.toBean(config, HrmLeaveTypeConfigRespVO.class)); |
| | | } |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "æ°å¢è¯·åç±»åé
ç½®") |
| | | @PreAuthorize("@ss.hasPermission('hrm:leave-type-config:create')") |
| | | public CommonResult<Long> createLeaveTypeConfig(@Valid @RequestBody HrmLeaveTypeConfigCreateReqVO createReqVO) { |
| | | HrmLeaveTypeConfigDO config = BeanUtils.toBean(createReqVO, HrmLeaveTypeConfigDO.class); |
| | | leaveTypeConfigService.createLeaveTypeConfig(config); |
| | | return success(config.getId()); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Operation(summary = "æ´æ°è¯·åç±»åé
ç½®") |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary:update')") |
| | | @PreAuthorize("@ss.hasPermission('hrm:leave-type-config:update')") |
| | | public CommonResult<Boolean> updateLeaveTypeConfig(@Valid @RequestBody HrmLeaveTypeConfigSaveReqVO updateReqVO) { |
| | | HrmLeaveTypeConfigDO config = BeanUtils.toBean(updateReqVO, HrmLeaveTypeConfigDO.class); |
| | | leaveTypeConfigService.updateLeaveTypeConfig(config); |
| | | return success(true); |
| | | } |
| | | |
| | | @DeleteMapping("/delete") |
| | | @Operation(summary = "å é¤è¯·åç±»åé
ç½®") |
| | | @Parameter(name = "id", description = "é
ç½®ID", required = true) |
| | | @PreAuthorize("@ss.hasPermission('hrm:leave-type-config:delete')") |
| | | public CommonResult<Boolean> deleteLeaveTypeConfig(@RequestParam("id") Long id) { |
| | | leaveTypeConfigService.deleteLeaveTypeConfig(id); |
| | | return success(true); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.salary; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmSalaryStructureRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmSalaryStructureSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSalaryStructureDO; |
| | | import cn.iocoder.yudao.module.hrm.service.salary.HrmSalaryStructureService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.DeleteMapping; |
| | | 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; |
| | | |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | |
| | | @Tag(name = "管çåå° - HRM èªé
Ⱦ") |
| | | @RestController |
| | | @RequestMapping("/hrm/salary/structure") |
| | | @Validated |
| | | public class HrmSalaryStructureController { |
| | | |
| | | @Resource |
| | | private HrmSalaryStructureService salaryStructureService; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "å建èªé
Ⱦ") |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary-structure:create')") |
| | | public CommonResult<Long> createSalaryStructure(@Valid @RequestBody HrmSalaryStructureSaveReqVO reqVO) { |
| | | return success(salaryStructureService.createSalaryStructure( |
| | | BeanUtils.toBean(reqVO, HrmSalaryStructureDO.class))); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Operation(summary = "æ´æ°èªé
Ⱦ") |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary-structure:update')") |
| | | public CommonResult<Boolean> updateSalaryStructure(@Valid @RequestBody HrmSalaryStructureSaveReqVO reqVO) { |
| | | salaryStructureService.updateSalaryStructure(BeanUtils.toBean(reqVO, HrmSalaryStructureDO.class)); |
| | | return success(true); |
| | | } |
| | | |
| | | @DeleteMapping("/delete") |
| | | @Operation(summary = "å é¤èªé
Ⱦ") |
| | | @Parameter(name = "id", description = "ç»æç¼å·", required = true) |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary-structure:delete')") |
| | | public CommonResult<Boolean> deleteSalaryStructure(@RequestParam("id") Long id) { |
| | | salaryStructureService.deleteSalaryStructure(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @GetMapping("/get") |
| | | @Operation(summary = "è·å¾èªé
Ⱦ") |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary-structure:query')") |
| | | public CommonResult<HrmSalaryStructureRespVO> getSalaryStructure(@RequestParam("id") Long id) { |
| | | return success(BeanUtils.toBean(salaryStructureService.getSalaryStructure(id), |
| | | HrmSalaryStructureRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/list") |
| | | @Operation(summary = "è·å¾èªé
¬ç»æå表") |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary-structure:query')") |
| | | public CommonResult<List<HrmSalaryStructureRespVO>> getSalaryStructureList( |
| | | @RequestParam(value = "name", required = false) String name, |
| | | @RequestParam(value = "status", required = false) Integer status) { |
| | | return success(BeanUtils.toBean(salaryStructureService.getSalaryStructureList(name, status), |
| | | HrmSalaryStructureRespVO.class)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @Schema(description = "管çåå° - 请åç±»åæ£æ¬¾é
ç½®æ°å¢ Request VO") |
| | | @Data |
| | | public class HrmLeaveTypeConfigCreateReqVO { |
| | | |
| | | @Schema(description = "请åç±»åï¼1-äºå, 2-ç
å, 3-å¹´å, 4-å©å, 5-产å, 6-丧å", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "请åç±»åä¸è½ä¸ºç©º") |
| | | private Integer leaveType; |
| | | |
| | | @Schema(description = "ç±»ååç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "äºå") |
| | | @NotBlank(message = "ç±»ååç§°ä¸è½ä¸ºç©º") |
| | | private String name; |
| | | |
| | | @Schema(description = "æ£æ¬¾æ¯ä¾ï¼0-1ä¹é´ï¼å¦0.5表示æ£50%ï¼", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.5") |
| | | @NotNull(message = "æ£æ¬¾æ¯ä¾ä¸è½ä¸ºç©º") |
| | | private BigDecimal deductionRatio; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | |
| | | @Schema(description = "ç¶æï¼0-å¯ç¨, 1-ç¦ç¨") |
| | | private Integer status; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Schema(description = "管çåå° - èªé
Ⱦ Response VO") |
| | | @Data |
| | | public class HrmSalaryStructureRespVO { |
| | | |
| | | @Schema(description = "ç»æç¼å·") |
| | | private Long id; |
| | | @Schema(description = "ç»æåç§°") |
| | | private String name; |
| | | @Schema(description = "工使¥å çå·¥èµåç") |
| | | private BigDecimal overtimePayRatio; |
| | | @Schema(description = "伿¯æ¥å çå·¥èµåç") |
| | | private BigDecimal restDayOvertimePayRatio; |
| | | @Schema(description = "æ³å®è忥å çå·¥èµåç") |
| | | private BigDecimal legalHolidayOvertimePayRatio; |
| | | @Schema(description = "ç¶æï¼0-å¯ç¨ï¼1-ç¦ç¨") |
| | | private Integer status; |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | @Schema(description = "å建æ¶é´") |
| | | private LocalDateTime createTime; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.DecimalMax; |
| | | import jakarta.validation.constraints.DecimalMin; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import jakarta.validation.constraints.Size; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @Schema(description = "管çåå° - èªé
¬ç»ææ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | | public class HrmSalaryStructureSaveReqVO { |
| | | |
| | | @Schema(description = "ç»æç¼å·", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "ç»æåç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "æ ååå·¥èªé
¬") |
| | | @NotBlank(message = "ç»æåç§°ä¸è½ä¸ºç©º") |
| | | @Size(max = 100, message = "ç»æåç§°ä¸è½è¶
è¿ 100 个å符") |
| | | private String name; |
| | | |
| | | @Schema(description = "工使¥å çå·¥èµåçï¼0 表示ä¸è®¡å çå·¥èµ", example = "1.50") |
| | | @NotNull(message = "工使¥å çåçä¸è½ä¸ºç©º") |
| | | @DecimalMin(value = "0", message = "工使¥å çåçä¸è½å°äº 0") |
| | | @DecimalMax(value = "10", message = "工使¥å çåçä¸è½å¤§äº 10") |
| | | private BigDecimal overtimePayRatio; |
| | | |
| | | @Schema(description = "伿¯æ¥å çå·¥èµåçï¼0 表示ä¸è®¡è¯¥ç±»åå çå·¥èµ", example = "2.00") |
| | | @NotNull(message = "伿¯æ¥å çåçä¸è½ä¸ºç©º") |
| | | @DecimalMin(value = "0", message = "伿¯æ¥å çåçä¸è½å°äº 0") |
| | | @DecimalMax(value = "10", message = "伿¯æ¥å çåçä¸è½å¤§äº 10") |
| | | private BigDecimal restDayOvertimePayRatio; |
| | | |
| | | @Schema(description = "æ³å®è忥å çå·¥èµåçï¼0 表示ä¸è®¡è¯¥ç±»åå çå·¥èµ", example = "3.00") |
| | | @NotNull(message = "æ³å®è忥å çåçä¸è½ä¸ºç©º") |
| | | @DecimalMin(value = "0", message = "æ³å®è忥å çåçä¸è½å°äº 0") |
| | | @DecimalMax(value = "10", message = "æ³å®è忥å çåçä¸è½å¤§äº 10") |
| | | private BigDecimal legalHolidayOvertimePayRatio; |
| | | |
| | | @Schema(description = "ç¶æï¼0-å¯ç¨ï¼1-ç¦ç¨", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") |
| | | @NotNull(message = "ç¶æä¸è½ä¸ºç©º") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | @Size(max = 500, message = "夿³¨ä¸è½è¶
è¿ 500 个å符") |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.dal.dataobject.approval; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | |
| | | @TableName("hrm_overtime_application") |
| | | @KeySequence("hrm_overtime_application_seq") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class HrmOvertimeApplicationDO extends BaseDO { |
| | | @TableId |
| | | private Long id; |
| | | private String no; |
| | | /** ç³»ç»ç¨æ· ID */ |
| | | private Long userId; |
| | | private Long deptId; |
| | | private Long employeeId; |
| | | private LocalDate overtimeDate; |
| | | private LocalTime startTime; |
| | | private LocalTime endTime; |
| | | private BigDecimal duration; |
| | | private Integer overtimeType; |
| | | private Boolean crossDay; |
| | | private Boolean mealDeduction; |
| | | private BigDecimal mealDeductionHours; |
| | | private String reason; |
| | | /** 1-项ç®ï¼2-å·¥å */ |
| | | private Integer relatedType; |
| | | private String relatedCode; |
| | | private String workContent; |
| | | private Integer status; |
| | | private String processInstanceId; |
| | | private LocalDateTime approveTime; |
| | | } |
| | |
| | | private BigDecimal performanceRatio; |
| | | |
| | | /** |
| | | * å çå·¥èµåç |
| | | * 工使¥å çå·¥èµåç |
| | | */ |
| | | private BigDecimal overtimePayRatio; |
| | | |
| | | /** |
| | | * 伿¯æ¥å çå·¥èµåç |
| | | */ |
| | | private BigDecimal restDayOvertimePayRatio; |
| | | |
| | | /** |
| | | * æ³å®è忥å çå·¥èµåç |
| | | */ |
| | | private BigDecimal legalHolidayOvertimePayRatio; |
| | | |
| | | /** |
| | | * 社ä¿åºæ° |
| | |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.dal.mysql.approval; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmOvertimeApplicationPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmOvertimeApplicationDO; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.util.List; |
| | | |
| | | @Mapper |
| | | public interface HrmOvertimeApplicationMapper extends BaseMapperX<HrmOvertimeApplicationDO> { |
| | | |
| | | default PageResult<HrmOvertimeApplicationDO> selectPage(HrmOvertimeApplicationPageReqVO reqVO) { |
| | | return selectPage(reqVO, new LambdaQueryWrapperX<HrmOvertimeApplicationDO>() |
| | | .likeIfPresent(HrmOvertimeApplicationDO::getNo, reqVO.getNo()) |
| | | .eqIfPresent(HrmOvertimeApplicationDO::getUserId, reqVO.getUserId()) |
| | | .eqIfPresent(HrmOvertimeApplicationDO::getDeptId, reqVO.getDeptId()) |
| | | .eqIfPresent(HrmOvertimeApplicationDO::getOvertimeDate, reqVO.getOvertimeDate()) |
| | | .eqIfPresent(HrmOvertimeApplicationDO::getOvertimeType, reqVO.getOvertimeType()) |
| | | .eqIfPresent(HrmOvertimeApplicationDO::getStatus, reqVO.getStatus()) |
| | | .orderByDesc(HrmOvertimeApplicationDO::getId)); |
| | | } |
| | | |
| | | default HrmOvertimeApplicationDO selectByProcessInstanceId(String processInstanceId) { |
| | | return selectOne(HrmOvertimeApplicationDO::getProcessInstanceId, processInstanceId); |
| | | } |
| | | |
| | | default List<HrmOvertimeApplicationDO> selectApprovedByUserAndDateRange(Long userId, LocalDate start, LocalDate end) { |
| | | return selectList(new LambdaQueryWrapperX<HrmOvertimeApplicationDO>() |
| | | .eq(HrmOvertimeApplicationDO::getUserId, userId) |
| | | .eq(HrmOvertimeApplicationDO::getStatus, HrmAuditStatusEnum.APPROVE.getStatus()) |
| | | .between(HrmOvertimeApplicationDO::getOvertimeDate, start, end)); |
| | | } |
| | | } |
| | |
| | | return selectOne(HrmEmployeeDO::getPhone, phone); |
| | | } |
| | | |
| | | default HrmEmployeeDO selectByName(String name) { |
| | | return selectOne(HrmEmployeeDO::getName, name); |
| | | } |
| | | |
| | | default List<HrmEmployeeDO> selectListByName(String name) { |
| | | return selectList(HrmEmployeeDO::getName, name); |
| | | } |
| | | |
| | | default HrmEmployeeDO selectByEmployeeNo(String employeeNo) { |
| | | return selectOne(HrmEmployeeDO::getEmployeeNo, employeeNo); |
| | | } |
| | |
| | | .orderByAsc(HrmEmployeeDO::getName)); |
| | | } |
| | | |
| | | } |
| | | default Long selectCountBySalaryStructureId(Long salaryStructureId) { |
| | | return selectCount(HrmEmployeeDO::getSalaryStructureId, salaryStructureId); |
| | | } |
| | | |
| | | } |
| | |
| | | .orderByDesc(HrmEmployeeSalaryDO::getEffectiveDate)); |
| | | } |
| | | |
| | | } |
| | | default Long selectCountBySalaryStructureId(Long salaryStructureId) { |
| | | return selectCount(HrmEmployeeSalaryDO::getSalaryStructureId, salaryStructureId); |
| | | } |
| | | |
| | | } |
| | |
| | | @Mapper |
| | | public interface HrmSalaryStructureMapper extends BaseMapperX<HrmSalaryStructureDO> { |
| | | |
| | | default List<HrmSalaryStructureDO> selectListByStatus(Integer status) { |
| | | default List<HrmSalaryStructureDO> selectListByCondition(String name, Integer status) { |
| | | return selectList(new LambdaQueryWrapperX<HrmSalaryStructureDO>() |
| | | .likeIfPresent(HrmSalaryStructureDO::getName, name) |
| | | .eqIfPresent(HrmSalaryStructureDO::getStatus, status) |
| | | .orderByAsc(HrmSalaryStructureDO::getName)); |
| | | } |
| | | |
| | | } |
| | | default List<HrmSalaryStructureDO> selectListByStatus(Integer status) { |
| | | return selectListByCondition(null, status); |
| | | } |
| | | |
| | | default HrmSalaryStructureDO selectByName(String name) { |
| | | return selectOne(HrmSalaryStructureDO::getName, name); |
| | | } |
| | | |
| | | } |
| | |
| | | */ |
| | | public static final String RESIGNATION_APPLICATION_NO_PREFIX = "RA"; |
| | | |
| | | /** å çç³è¯·ç¼å·åç¼ */ |
| | | public static final String OVERTIME_APPLICATION_NO_PREFIX = "OT"; |
| | | |
| | | /** |
| | | * åå·¥ååç¼å·åç¼ |
| | | */ |
| | |
| | | return generate(RESIGNATION_APPLICATION_NO_PREFIX, 4); |
| | | } |
| | | |
| | | public String generateOvertimeApplicationNo() { |
| | | return generate(OVERTIME_APPLICATION_NO_PREFIX, 4); |
| | | } |
| | | |
| | | /** |
| | | * çæåå·¥ååç¼å·ï¼æ ¼å¼ï¼HT + yyyyMMdd + 4ä½èªå¢ |
| | | * ä¾å¦ï¼HT202401010001 |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.approval; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmOvertimeApplicationPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmOvertimeApplicationRespVO; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmOvertimeApplicationSaveReqVO; |
| | | import jakarta.validation.Valid; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | public interface HrmOvertimeApplicationService { |
| | | String BPM_PROCESS_DEFINITION_KEY = "hrm_overtime"; |
| | | String APPROVE_CATEGORY_CODE = "overtime_approve"; |
| | | |
| | | Long create(@Valid HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId); |
| | | void update(@Valid HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId); |
| | | void delete(Long id, Long loginUserId); |
| | | HrmOvertimeApplicationRespVO getDetail(Long id, Long loginUserId, boolean canManage); |
| | | HrmOvertimeApplicationRespVO getCurrentApplicant(Long loginUserId); |
| | | PageResult<HrmOvertimeApplicationRespVO> getPage(HrmOvertimeApplicationPageReqVO reqVO); |
| | | void submit(Long id, String processDefinitionKey, Long loginUserId); |
| | | void cancel(Long id, Long loginUserId); |
| | | List<Map<String, Object>> getApproveProcessDefinitionList(); |
| | | void updateAuditStatus(Long id, Integer status); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.approval; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.NumberUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; |
| | | import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; |
| | | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO; |
| | | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; |
| | | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| | | import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.*; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmOvertimeApplicationDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmOvertimeApplicationMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmOvertimeTypeEnum; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.PostApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.Duration; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*; |
| | | |
| | | @Service |
| | | @Slf4j |
| | | public class HrmOvertimeApplicationServiceImpl implements HrmOvertimeApplicationService { |
| | | @Resource private HrmOvertimeApplicationMapper mapper; |
| | | @Resource private HrmEmployeeMapper employeeMapper; |
| | | @Resource private HrmNoRedisDAO noRedisDAO; |
| | | @Resource private DeptApi deptApi; |
| | | @Resource private PostApi postApi; |
| | | @Resource private BpmProcessInstanceApi bpmProcessInstanceApi; |
| | | @Resource private BpmProcessInstanceService bpmProcessInstanceService; |
| | | @Resource private BpmTaskService bpmTaskService; |
| | | @Resource private BpmCategoryService bpmCategoryService; |
| | | @Resource private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long create(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId) { |
| | | HrmEmployeeDO employee = requireEmployee(loginUserId); |
| | | HrmOvertimeApplicationDO application = BeanUtils.toBean(reqVO, HrmOvertimeApplicationDO.class); |
| | | applyApplicantAndCalculatedTime(application, employee); |
| | | application.setNo(noRedisDAO.generateOvertimeApplicationNo()); |
| | | application.setStatus(HrmAuditStatusEnum.DRAFT.getStatus()); |
| | | mapper.insert(application); |
| | | return application.getId(); |
| | | } |
| | | |
| | | @Override |
| | | public void update(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId) { |
| | | HrmOvertimeApplicationDO existing = requireOwnedDraft(reqVO.getId(), loginUserId); |
| | | HrmOvertimeApplicationDO update = BeanUtils.toBean(reqVO, HrmOvertimeApplicationDO.class); |
| | | applyApplicantAndCalculatedTime(update, requireEmployee(loginUserId)); |
| | | update.setId(existing.getId()); |
| | | mapper.updateById(update); |
| | | } |
| | | |
| | | @Override |
| | | public void delete(Long id, Long loginUserId) { |
| | | HrmOvertimeApplicationDO application = require(id); |
| | | boolean deletable = Objects.equals(application.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus()) |
| | | || Objects.equals(application.getStatus(), HrmAuditStatusEnum.CANCEL.getStatus()); |
| | | if (!Objects.equals(application.getUserId(), loginUserId) || !deletable) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | | mapper.deleteById(id); |
| | | } |
| | | |
| | | @Override |
| | | public HrmOvertimeApplicationRespVO getDetail(Long id, Long loginUserId, boolean canManage) { |
| | | HrmOvertimeApplicationDO application = mapper.selectById(id); |
| | | if (application != null && !canManage && !Objects.equals(application.getUserId(), loginUserId) |
| | | && !isProcessParticipant(application.getProcessInstanceId(), loginUserId)) { |
| | | return null; |
| | | } |
| | | return application == null ? null : buildResp(application); |
| | | } |
| | | |
| | | @Override |
| | | public HrmOvertimeApplicationRespVO getCurrentApplicant(Long loginUserId) { |
| | | HrmEmployeeDO employee = requireEmployee(loginUserId); |
| | | HrmOvertimeApplicationRespVO resp = new HrmOvertimeApplicationRespVO(); |
| | | fillEmployee(resp, employee); |
| | | return resp; |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<HrmOvertimeApplicationRespVO> getPage(HrmOvertimeApplicationPageReqVO reqVO) { |
| | | PageResult<HrmOvertimeApplicationDO> page = mapper.selectPage(reqVO); |
| | | return new PageResult<>(page.getList().stream().map(this::buildResp).toList(), page.getTotal()); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void submit(Long id, String processDefinitionKey, Long loginUserId) { |
| | | HrmOvertimeApplicationDO application = requireOwnedDraft(id, loginUserId); |
| | | validateProcessDefinitions(); |
| | | ProcessDefinition definition = bpmProcessDefinitionService.getActiveProcessDefinition(processDefinitionKey); |
| | | if (definition == null || !BPM_PROCESS_DEFINITION_KEY.equals(definition.getKey())) { |
| | | throw exception(OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS); |
| | | } |
| | | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(loginUserId, |
| | | new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(processDefinitionKey) |
| | | .setBusinessKey(String.valueOf(id))); |
| | | mapper.updateById(HrmOvertimeApplicationDO.builder().id(id).processInstanceId(processInstanceId) |
| | | .status(HrmAuditStatusEnum.PROCESS.getStatus()).build()); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void cancel(Long id, Long loginUserId) { |
| | | HrmOvertimeApplicationDO application = require(id); |
| | | if (!Objects.equals(application.getUserId(), loginUserId) |
| | | || !Objects.equals(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS); |
| | | } |
| | | bpmProcessInstanceService.cancelProcessInstanceByStartUser(loginUserId, |
| | | new BpmProcessInstanceCancelReqVO().setId(application.getProcessInstanceId()).setReason("ç³è¯·äººæ¤éå çç³è¯·")); |
| | | } |
| | | |
| | | @Override |
| | | public List<Map<String, Object>> getApproveProcessDefinitionList() { |
| | | validateProcessDefinitions(); |
| | | List<BpmProcessDefinitionInfoDO> infos = bpmProcessDefinitionService |
| | | .getProcessDefinitionInfoListByCategory(APPROVE_CATEGORY_CODE); |
| | | Set<String> ids = convertSet(infos, BpmProcessDefinitionInfoDO::getProcessDefinitionId); |
| | | Map<String, ProcessDefinition> latest = new HashMap<>(); |
| | | for (ProcessDefinition definition : bpmProcessDefinitionService.getProcessDefinitionList(ids)) { |
| | | if (definition.isSuspended()) continue; |
| | | latest.compute(definition.getKey(), (key, old) -> old == null || definition.getVersion() > old.getVersion() ? definition : old); |
| | | } |
| | | return latest.values().stream().map(item -> { |
| | | Map<String, Object> value = new HashMap<>(); |
| | | value.put("id", item.getId()); value.put("key", item.getKey()); value.put("name", item.getName()); |
| | | value.put("version", item.getVersion()); return value; |
| | | }).collect(Collectors.toList()); |
| | | } |
| | | |
| | | @Override |
| | | public void updateAuditStatus(Long id, Integer status) { |
| | | HrmOvertimeApplicationDO application = require(id); |
| | | if (!Objects.equals(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS); |
| | | } |
| | | mapper.updateById(HrmOvertimeApplicationDO.builder().id(id).status(status) |
| | | .approveTime(LocalDateTime.now()).build()); |
| | | } |
| | | |
| | | private void validateProcessDefinitions() { |
| | | if (!bpmCategoryService.getCategoryMap(Collections.singleton(APPROVE_CATEGORY_CODE)).containsKey(APPROVE_CATEGORY_CODE)) { |
| | | throw exception(OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS); |
| | | } |
| | | List<BpmProcessDefinitionInfoDO> infos = bpmProcessDefinitionService.getProcessDefinitionInfoListByCategory(APPROVE_CATEGORY_CODE); |
| | | if (CollUtil.isEmpty(infos)) throw exception(OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS); |
| | | Set<String> ids = convertSet(infos, BpmProcessDefinitionInfoDO::getProcessDefinitionId); |
| | | if (bpmProcessDefinitionService.getProcessDefinitionList(ids).stream().noneMatch(item -> !item.isSuspended())) { |
| | | throw exception(OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS); |
| | | } |
| | | } |
| | | |
| | | private void applyApplicantAndCalculatedTime(HrmOvertimeApplicationDO application, HrmEmployeeDO employee) { |
| | | if (HrmOvertimeTypeEnum.valueOfType(application.getOvertimeType()) == null) { |
| | | throw exception(OVERTIME_APPLICATION_TIME_INVALID); |
| | | } |
| | | application.setUserId(employee.getUserId()); |
| | | application.setEmployeeId(employee.getId()); |
| | | application.setDeptId(employee.getDeptId()); |
| | | long minutes = Duration.between(application.getStartTime(), application.getEndTime()).toMinutes(); |
| | | boolean crossDay = minutes <= 0; |
| | | if (crossDay) minutes += 24 * 60; |
| | | BigDecimal mealHours = Boolean.TRUE.equals(application.getMealDeduction()) |
| | | ? Optional.ofNullable(application.getMealDeductionHours()).orElse(BigDecimal.ONE) : BigDecimal.ZERO; |
| | | BigDecimal rawHours = BigDecimal.valueOf(minutes).divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP); |
| | | if (Boolean.TRUE.equals(application.getMealDeduction()) |
| | | && (mealHours.compareTo(new BigDecimal("0.5")) < 0 |
| | | || mealHours.compareTo(new BigDecimal("4")) > 0 |
| | | || mealHours.compareTo(rawHours) >= 0)) { |
| | | throw exception(OVERTIME_APPLICATION_TIME_INVALID); |
| | | } |
| | | BigDecimal hours = rawHours |
| | | .subtract(mealHours).multiply(BigDecimal.valueOf(2)).setScale(0, RoundingMode.HALF_UP) |
| | | .divide(BigDecimal.valueOf(2), 1, RoundingMode.UNNECESSARY); |
| | | if (hours.compareTo(BigDecimal.ZERO) <= 0) throw exception(OVERTIME_APPLICATION_TIME_INVALID); |
| | | application.setCrossDay(crossDay); |
| | | application.setMealDeductionHours(mealHours); |
| | | application.setDuration(hours); |
| | | } |
| | | |
| | | private HrmOvertimeApplicationDO require(Long id) { |
| | | HrmOvertimeApplicationDO value = mapper.selectById(id); |
| | | if (value == null) throw exception(OVERTIME_APPLICATION_NOT_EXISTS); |
| | | return value; |
| | | } |
| | | |
| | | private HrmOvertimeApplicationDO requireOwnedDraft(Long id, Long userId) { |
| | | HrmOvertimeApplicationDO value = require(id); |
| | | if (!Objects.equals(value.getUserId(), userId) |
| | | || !Objects.equals(value.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | private HrmEmployeeDO requireEmployee(Long userId) { |
| | | HrmEmployeeDO employee = employeeMapper.selectByUserId(userId); |
| | | if (employee == null) throw exception(OVERTIME_APPLICATION_EMPLOYEE_NOT_EXISTS); |
| | | return employee; |
| | | } |
| | | |
| | | /** å½åå¾
å审æ¹äººææ¾å¤çè¿è¯¥æµç¨ç审æ¹äººå¯æ¥çä¸å¡è¯¦æ
ã */ |
| | | private boolean isProcessParticipant(String processInstanceId, Long userId) { |
| | | if (processInstanceId == null || userId == null) { |
| | | return false; |
| | | } |
| | | if (bpmTaskService.getTodoTask(userId, null, processInstanceId) != null) { |
| | | return true; |
| | | } |
| | | return bpmTaskService.getTaskListByProcessInstanceId(processInstanceId, true).stream() |
| | | .anyMatch(task -> Objects.equals(NumberUtil.parseLong(task.getAssignee(), null), userId) |
| | | || Objects.equals(NumberUtil.parseLong(task.getOwner(), null), userId)); |
| | | } |
| | | |
| | | private HrmOvertimeApplicationRespVO buildResp(HrmOvertimeApplicationDO application) { |
| | | HrmOvertimeApplicationRespVO resp = BeanUtils.toBean(application, HrmOvertimeApplicationRespVO.class); |
| | | HrmEmployeeDO employee = employeeMapper.selectById(application.getEmployeeId()); |
| | | if (employee != null) fillEmployee(resp, employee); |
| | | resp.setOvertimeTypeName(HrmOvertimeTypeEnum.getName(application.getOvertimeType())); |
| | | resp.setStatusName(HrmAuditStatusEnum.getNameByStatus(application.getStatus())); |
| | | return resp; |
| | | } |
| | | |
| | | private void fillEmployee(HrmOvertimeApplicationRespVO resp, HrmEmployeeDO employee) { |
| | | resp.setUserId(employee.getUserId()); resp.setEmployeeId(employee.getId()); |
| | | resp.setEmployeeName(employee.getName()); resp.setEmployeeNo(employee.getEmployeeNo()); |
| | | resp.setDeptId(employee.getDeptId()); |
| | | DeptRespDTO dept = employee.getDeptId() == null ? null : deptApi.getDept(employee.getDeptId()); |
| | | PostRespDTO post = employee.getPostId() == null ? null |
| | | : postApi.getPostMap(Collections.singleton(employee.getPostId())).get(employee.getPostId()); |
| | | resp.setDeptName(dept == null ? null : dept.getName()); |
| | | resp.setPostName(post == null ? null : post.getName()); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.approval.listener; |
| | | |
| | | import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; |
| | | import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum; |
| | | import cn.iocoder.yudao.module.hrm.service.approval.HrmOvertimeApplicationService; |
| | | import cn.iocoder.yudao.module.hrm.util.HrmAuditStatusUtils; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | @Component |
| | | public class HrmOvertimeApplicationStatusListener extends BpmProcessInstanceStatusEventListener { |
| | | @Resource private HrmOvertimeApplicationService service; |
| | | @Override protected String getProcessDefinitionKey() { return HrmOvertimeApplicationService.BPM_PROCESS_DEFINITION_KEY; } |
| | | @Override protected void onEvent(BpmProcessInstanceStatusEvent event) { |
| | | Integer status = HrmAuditStatusUtils.convertBpmResultToAuditStatus(event.getStatus()); |
| | | if (status == null) status = HrmAuditStatusEnum.PROCESS.getStatus(); |
| | | service.updateAuditStatus(Long.valueOf(event.getBusinessKey()), status); |
| | | } |
| | | } |
| | |
| | | */ |
| | | HrmAttendanceRecordDO getAttendanceRecordByUserIdAndDate(Long userId, LocalDate date); |
| | | |
| | | /** å建导å
¥çèå¤è®°å½ */ |
| | | void createImportedRecord(HrmAttendanceRecordDO record); |
| | | |
| | | /** æ´æ°å¯¼å
¥çèå¤è®°å½ */ |
| | | void updateImportedRecord(HrmAttendanceRecordDO record); |
| | | |
| | | /** |
| | | * æå¡ï¼ä¸çæå¡ï¼ |
| | | * |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void createImportedRecord(HrmAttendanceRecordDO record) { |
| | | // æèå¤è§åéç®æå¡ç±»å䏿¶é¿ï¼ä¸ä¿¡ä»» Excel å¡«åçå¼ |
| | | fillClockTypes(record); |
| | | fillCalculatedHours(record); |
| | | attendanceRecordMapper.insert(record); |
| | | } |
| | | |
| | | @Override |
| | | public void updateImportedRecord(HrmAttendanceRecordDO record) { |
| | | fillClockTypes(record); |
| | | fillCalculatedHours(record); |
| | | attendanceRecordMapper.updateById(record); |
| | | } |
| | | |
| | | /** |
| | | * æèå¤è§åéç®ä¸ä¸çæå¡ç±»åï¼æ£å¸¸/è¿å°/æ©éï¼ï¼ä¸æå¡é»è¾ä¿æä¸è´ |
| | | */ |
| | | private void fillClockTypes(HrmAttendanceRecordDO record) { |
| | | if (record.getDeptId() == null) { |
| | | return; |
| | | } |
| | | HrmAttendanceRuleDO rule = attendanceRuleService.getAttendanceRuleByDeptId(record.getDeptId()); |
| | | if (rule == null) { |
| | | return; |
| | | } |
| | | // ä¸çæå¡ç±»åï¼æäº ä¸çæ¶é´+è¿å°å
许 记为è¿å° |
| | | if (record.getClockInTime() != null && rule.getWorkStartTime() != null) { |
| | | int lateAllowMinutes = rule.getLateAllowMinutes() != null ? rule.getLateAllowMinutes() : 0; |
| | | LocalTime lateThreshold = rule.getWorkStartTime().plusMinutes(lateAllowMinutes); |
| | | LocalTime clockInOnly = record.getClockInTime().toLocalTime(); |
| | | record.setClockInType(clockInOnly.isAfter(lateThreshold) |
| | | ? HrmAttendanceClockTypeEnum.LATE.getType() |
| | | : HrmAttendanceClockTypeEnum.NORMAL.getType()); |
| | | } |
| | | // ä¸çæå¡ç±»åï¼æ©äº ä¸çæ¶é´-æ©éå
许 记为æ©é |
| | | if (record.getClockOutTime() != null && rule.getWorkEndTime() != null) { |
| | | int earlyAllowMinutes = rule.getEarlyAllowMinutes() != null ? rule.getEarlyAllowMinutes() : 0; |
| | | LocalTime earlyThreshold = rule.getWorkEndTime().minusMinutes(earlyAllowMinutes); |
| | | LocalTime clockOutOnly = record.getClockOutTime().toLocalTime(); |
| | | record.setClockOutType(clockOutOnly.isBefore(earlyThreshold) |
| | | ? HrmAttendanceClockTypeEnum.EARLY.getType() |
| | | : HrmAttendanceClockTypeEnum.NORMAL.getType()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®ä¸ä¸çæå¡æ¶é´åèå¤è§åï¼è®¡ç®å·¥ä½æ¶é¿ä¸å çæ¶é¿ |
| | | */ |
| | | private void fillCalculatedHours(HrmAttendanceRecordDO record) { |
| | | // 工使¶é¿ = ä¸çæå¡æ¶é´ - ä¸çæå¡æ¶é´ï¼ä¸æå¡é»è¾ä¸è´ï¼ |
| | | if (record.getClockInTime() != null && record.getClockOutTime() != null) { |
| | | Duration duration = Duration.between(record.getClockInTime(), record.getClockOutTime()); |
| | | BigDecimal workHours = BigDecimal.valueOf(duration.toMinutes()) |
| | | .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP); |
| | | record.setWorkHours(workHours); |
| | | } |
| | | // å çæ¶é¿ï¼æèå¤è§åçæ åä¸çæ¶é´è®¡ç®è¶
é¢é¨å |
| | | if (record.getClockOutTime() != null && record.getDeptId() != null) { |
| | | HrmAttendanceRuleDO rule = attendanceRuleService.getAttendanceRuleByDeptId(record.getDeptId()); |
| | | if (rule != null && rule.getWorkEndTime() != null) { |
| | | LocalTime workEnd = rule.getWorkEndTime(); |
| | | LocalDate outDate = record.getClockOutTime().toLocalDate(); |
| | | LocalDateTime workEndDateTime = LocalDateTime.of(outDate, workEnd); |
| | | if (record.getClockOutTime().isAfter(workEndDateTime)) { |
| | | Duration overtimeDuration = Duration.between(workEndDateTime, record.getClockOutTime()); |
| | | BigDecimal overtimeThreshold = rule.getOvertimeThreshold() != null |
| | | ? rule.getOvertimeThreshold() : BigDecimal.ZERO; |
| | | BigDecimal overtimeHours = BigDecimal.valueOf(overtimeDuration.toMinutes()) |
| | | .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP); |
| | | record.setOvertimeHours(overtimeHours.compareTo(overtimeThreshold) > 0 ? overtimeHours : BigDecimal.ZERO); |
| | | } else { |
| | | record.setOvertimeHours(BigDecimal.ZERO); |
| | | } |
| | | } else { |
| | | record.setOvertimeHours(BigDecimal.ZERO); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public HrmAttendanceRecordDO clockIn(Long userId, LocalDateTime clockTime, String location) { |
| | | LocalDate clockDate = clockTime.toLocalDate(); |
| | |
| | | */ |
| | | HrmEmployeeDO getEmployeeByUserId(Long userId); |
| | | |
| | | /** æ ¹æ®åå·¥å§åè·ååå·¥ */ |
| | | HrmEmployeeDO getEmployeeByName(String name); |
| | | |
| | | /** æ ¹æ®åå·¥å§åè·åææåååå·¥ */ |
| | | List<HrmEmployeeDO> getEmployeeListByName(String name); |
| | | |
| | | /** |
| | | * 导å
¥åå·¥å表 |
| | | * |
| | |
| | | } |
| | | |
| | | @Override |
| | | public HrmEmployeeDO getEmployeeByName(String name) { |
| | | return employeeMapper.selectByName(name); |
| | | } |
| | | |
| | | @Override |
| | | public List<HrmEmployeeDO> getEmployeeListByName(String name) { |
| | | return employeeMapper.selectListByName(name); |
| | | } |
| | | |
| | | @Override |
| | | public HrmEmployeeImportRespVO importEmployeeList(List<HrmEmployeeImportExcelVO> importEmployees, |
| | | HrmEmployeeImportReqVO importReqVO) { |
| | | // 1. æ ¡éªé空 |
| | |
| | | HrmLeaveTypeConfigDO getLeaveTypeConfig(Integer leaveType); |
| | | |
| | | /** |
| | | * æ°å¢è¯·åç±»åé
ç½® |
| | | */ |
| | | void createLeaveTypeConfig(HrmLeaveTypeConfigDO config); |
| | | |
| | | /** |
| | | * æ´æ°è¯·åç±»åé
ç½® |
| | | */ |
| | | void updateLeaveTypeConfig(HrmLeaveTypeConfigDO config); |
| | | |
| | | /** |
| | | * å é¤è¯·åç±»åé
ç½® |
| | | */ |
| | | void deleteLeaveTypeConfig(Long id); |
| | | |
| | | } |
| | |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.LEAVE_TYPE_CONFIG_NOT_EXISTS; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.LEAVE_TYPE_CONFIG_TYPE_EXISTS; |
| | | |
| | | /** |
| | | * 请åç±»åæ£æ¬¾é
ç½® Service å®ç°ç±» |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void createLeaveTypeConfig(HrmLeaveTypeConfigDO config) { |
| | | // æ ¡éªåä¸è¯·åç±»ååªå
许åå¨ä¸æ¡é
ç½® |
| | | if (leaveTypeConfigMapper.selectCount(HrmLeaveTypeConfigDO::getLeaveType, config.getLeaveType()) > 0) { |
| | | throw exception(LEAVE_TYPE_CONFIG_TYPE_EXISTS); |
| | | } |
| | | leaveTypeConfigMapper.insert(config); |
| | | } |
| | | |
| | | @Override |
| | | public void updateLeaveTypeConfig(HrmLeaveTypeConfigDO config) { |
| | | validateLeaveTypeConfigExists(config.getId()); |
| | | leaveTypeConfigMapper.updateById(config); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteLeaveTypeConfig(Long id) { |
| | | validateLeaveTypeConfigExists(id); |
| | | leaveTypeConfigMapper.deleteById(id); |
| | | } |
| | | |
| | | private void validateLeaveTypeConfigExists(Long id) { |
| | | if (leaveTypeConfigMapper.selectById(id) == null) { |
| | | throw exception(LEAVE_TYPE_CONFIG_NOT_EXISTS); |
| | |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmSalaryCalculationPageReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmLeaveApplicationDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmOvertimeApplicationDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmEmployeeSalaryDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmEmployeeSocialSecurityDO; |
| | |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSalaryPaymentDetailDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSalaryPaymentDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSocialSecuritySchemeDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSalaryStructureDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmLeaveApplicationMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmOvertimeApplicationMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmEmployeeSalaryMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmEmployeeSocialSecurityMapper; |
| | |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSalaryPaymentDetailMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSalaryPaymentMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSocialSecuritySchemeMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSalaryStructureMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmOvertimeTypeEnum; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | @Resource |
| | | private HrmLeaveApplicationMapper leaveApplicationMapper; |
| | | @Resource |
| | | private HrmOvertimeApplicationMapper overtimeApplicationMapper; |
| | | @Resource |
| | | private HrmSalaryStructureMapper salaryStructureMapper; |
| | | @Resource |
| | | private HrmLeaveTypeConfigMapper leaveTypeConfigMapper; |
| | | @Resource |
| | | private HrmSalaryPaymentMapper salaryPaymentMapper; |
| | |
| | | if (existCalculations.size() > 1) { |
| | | throw exception(SALARY_CALCULATION_DUPLICATE, employee.getName(), period); |
| | | } |
| | | continue; // å·²åå¨åè·³è¿ |
| | | // 已确认æå·²åæ¾çè®°å½ä¸å¯èªå¨æ¹åï¼å¾
确认记å½å
许éç®ï¼ä»¥å¸æ¶åæ¥å®¡æ¹éè¿çå çã |
| | | if (existCalculations.get(0).getStatus() != 0) { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | // 2.2 è·ååå·¥èªé
¬æ¡£æ¡ï¼æåå·¥IDæ¥è¯¢ï¼ |
| | |
| | | // 2.5 æå»ºæ ¸ç®è®°å½ï¼å
嫿£é¤è®¡ç®ï¼éè¿æ¹æ¡è·åæ¯ä¾ï¼ |
| | | HrmSalaryCalculationDO calculation = buildSalaryCalculation(period, employeeId, employee, employeeSalary, socialSecurity, scheme, effectiveDate); |
| | | |
| | | // 2.6 çææ ¸ç®åå· |
| | | String no = noRedisDAO.generateSalaryCalculationNo(); |
| | | while (salaryCalculationMapper.selectByNo(no) != null) { |
| | | no = noRedisDAO.generateSalaryCalculationNo(); |
| | | // 2.6 ä¿åï¼é¦æ¬¡çæåå·ï¼å·²æå¾
确认记å½åä¿çåå·å¹¶è¦çéç®ç»æ |
| | | if (CollUtil.isNotEmpty(existCalculations)) { |
| | | HrmSalaryCalculationDO existing = existCalculations.get(0); |
| | | calculation.setId(existing.getId()); |
| | | calculation.setNo(existing.getNo()); |
| | | salaryCalculationMapper.updateById(calculation); |
| | | } else { |
| | | String no = noRedisDAO.generateSalaryCalculationNo(); |
| | | while (salaryCalculationMapper.selectByNo(no) != null) { |
| | | no = noRedisDAO.generateSalaryCalculationNo(); |
| | | } |
| | | calculation.setNo(no); |
| | | salaryCalculationMapper.insert(calculation); |
| | | } |
| | | calculation.setNo(no); |
| | | |
| | | // 2.7 ä¿åæ ¸ç®è®°å½ |
| | | salaryCalculationMapper.insert(calculation); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * æå»ºé»è®¤çåå·¥èªé
¬æ¡£æ¡ï¼åºäºå工表çåºæ¬å·¥èµï¼ |
| | | * æå»ºé»è®¤çåå·¥èªé
¬æ¡£æ¡ãåºæ¬å·¥èµç»ä¸åå工档æ¡ï¼ç»©æå·¥èµé»è®¤ä¸èªå¨çæã |
| | | */ |
| | | private HrmEmployeeSalaryDO buildDefaultEmployeeSalary(Long employeeId, HrmEmployeeDO employee) { |
| | | BigDecimal baseSalary = employee.getBaseSalary() != null ? employee.getBaseSalary() : BigDecimal.ZERO; |
| | | return HrmEmployeeSalaryDO.builder() |
| | | .userId(employeeId) // 使ç¨åå·¥ID |
| | | .salaryStructureId(employee.getSalaryStructureId()) |
| | | .baseSalary(employee.getBaseSalary() != null ? employee.getBaseSalary() : BigDecimal.ZERO) |
| | | .baseSalary(baseSalary) |
| | | .performanceSalary(BigDecimal.ZERO) |
| | | .mealAllowance(BigDecimal.ZERO) |
| | | .transportAllowance(BigDecimal.ZERO) |
| | |
| | | BigDecimal mealAllowance = employeeSalary.getMealAllowance() != null ? employeeSalary.getMealAllowance() : BigDecimal.ZERO; |
| | | BigDecimal transportAllowance = employeeSalary.getTransportAllowance() != null ? employeeSalary.getTransportAllowance() : BigDecimal.ZERO; |
| | | BigDecimal otherAllowance = employeeSalary.getOtherAllowance() != null ? employeeSalary.getOtherAllowance() : BigDecimal.ZERO; |
| | | BigDecimal overtimePay = BigDecimal.ZERO; |
| | | OvertimeSalary overtimeSalary = calculateOvertimeSalary(employee, employeeSalary, period, baseSalary); |
| | | BigDecimal overtimePay = overtimeSalary.pay(); |
| | | |
| | | // åºåå·¥èµæ»é¢ |
| | | BigDecimal totalIncome = baseSalary.add(performanceSalary).add(mealAllowance) |
| | | .add(transportAllowance).add(otherAllowance).add(overtimePay); |
| | | |
| | | // è·å社ä¿åºæ°ï¼å工档æ¡ä¸ç个æ§ååºæ°ï¼ |
| | | // è·å社ä¿åºæ°ï¼åå·¥ç¤¾ä¿æ¡£æ¡ > åå·¥åºæ¬å·¥èµ |
| | | BigDecimal socialSecurityBase = (socialSecurity != null && socialSecurity.getSocialSecurityBase() != null) |
| | | ? socialSecurity.getSocialSecurityBase() : baseSalary; |
| | | |
| | | // è·åå
¬ç§¯éåºæ°ï¼å工档æ¡ä¸ç个æ§ååºæ°ï¼ |
| | | // è·åå
¬ç§¯éåºæ°ï¼åå·¥ç¤¾ä¿æ¡£æ¡ > åå·¥åºæ¬å·¥èµ |
| | | BigDecimal housingFundBase = (socialSecurity != null && socialSecurity.getHousingFundBase() != null) |
| | | ? socialSecurity.getHousingFundBase() : baseSalary; |
| | | |
| | |
| | | .leaveDeduction(leaveDeduction) |
| | | .actualSalary(actualSalary) |
| | | .workDays(22) // é»è®¤å·¥ä½æ¥ |
| | | .overtimeHours(BigDecimal.ZERO) |
| | | .overtimeHours(overtimeSalary.hours()) |
| | | .status(0) // å¾
确认 |
| | | .build(); |
| | | } |
| | |
| | | |
| | | return totalLeaveDeduction; |
| | | } |
| | | |
| | | /** |
| | | * æ±æ»å½æå®¡æ¹éè¿çå çç³è¯·ãå°æ¶å·¥èµæåºæ¬å·¥èµ / 21.75 / 8 计ç®ï¼ |
| | | * 工使¥é»è®¤ 1.5 åã伿¯æ¥é»è®¤ 2 åãæ³å®è忥é»è®¤ 3 åï¼åå¯ç±èªé
¬ç»æè¦çã |
| | | */ |
| | | private OvertimeSalary calculateOvertimeSalary(HrmEmployeeDO employee, HrmEmployeeSalaryDO employeeSalary, |
| | | String period, BigDecimal baseSalary) { |
| | | if (employee.getUserId() == null) { |
| | | return new OvertimeSalary(BigDecimal.ZERO, BigDecimal.ZERO); |
| | | } |
| | | YearMonth month = YearMonth.parse(period); |
| | | List<HrmOvertimeApplicationDO> applications = overtimeApplicationMapper.selectApprovedByUserAndDateRange( |
| | | employee.getUserId(), month.atDay(1), month.atEndOfMonth()); |
| | | if (CollUtil.isEmpty(applications)) { |
| | | return new OvertimeSalary(BigDecimal.ZERO, BigDecimal.ZERO); |
| | | } |
| | | Long structureId = employeeSalary.getSalaryStructureId() != null |
| | | ? employeeSalary.getSalaryStructureId() : employee.getSalaryStructureId(); |
| | | HrmSalaryStructureDO structure = structureId == null ? null : salaryStructureMapper.selectById(structureId); |
| | | BigDecimal workdayMultiplier = structure != null && structure.getOvertimePayRatio() != null |
| | | ? structure.getOvertimePayRatio() : HrmOvertimeTypeEnum.WORKDAY.getSalaryMultiplier(); |
| | | BigDecimal restDayMultiplier = structure != null && structure.getRestDayOvertimePayRatio() != null |
| | | ? structure.getRestDayOvertimePayRatio() : HrmOvertimeTypeEnum.REST_DAY.getSalaryMultiplier(); |
| | | BigDecimal legalHolidayMultiplier = structure != null && structure.getLegalHolidayOvertimePayRatio() != null |
| | | ? structure.getLegalHolidayOvertimePayRatio() : HrmOvertimeTypeEnum.LEGAL_HOLIDAY.getSalaryMultiplier(); |
| | | BigDecimal hourlySalary = baseSalary.divide(new BigDecimal("21.75"), 8, RoundingMode.HALF_UP) |
| | | .divide(new BigDecimal("8"), 8, RoundingMode.HALF_UP); |
| | | BigDecimal totalHours = BigDecimal.ZERO; |
| | | BigDecimal totalPay = BigDecimal.ZERO; |
| | | for (HrmOvertimeApplicationDO application : applications) { |
| | | BigDecimal hours = application.getDuration() == null ? BigDecimal.ZERO : application.getDuration(); |
| | | HrmOvertimeTypeEnum type = HrmOvertimeTypeEnum.valueOfType(application.getOvertimeType()); |
| | | if (type == null || hours.signum() <= 0) { |
| | | continue; |
| | | } |
| | | BigDecimal multiplier = switch (type) { |
| | | case WORKDAY -> workdayMultiplier; |
| | | case REST_DAY -> restDayMultiplier; |
| | | case LEGAL_HOLIDAY -> legalHolidayMultiplier; |
| | | }; |
| | | totalHours = totalHours.add(hours); |
| | | totalPay = totalPay.add(hourlySalary.multiply(hours).multiply(multiplier)); |
| | | } |
| | | return new OvertimeSalary(totalHours.setScale(1, RoundingMode.HALF_UP), |
| | | totalPay.setScale(2, RoundingMode.HALF_UP)); |
| | | } |
| | | |
| | | private record OvertimeSalary(BigDecimal hours, BigDecimal pay) {} |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | salaryCalculationMapper.deleteById(id); |
| | | } |
| | | |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.salary; |
| | | |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSalaryStructureDO; |
| | | |
| | | import java.util.List; |
| | | |
| | | public interface HrmSalaryStructureService { |
| | | |
| | | Long createSalaryStructure(HrmSalaryStructureDO structure); |
| | | |
| | | void updateSalaryStructure(HrmSalaryStructureDO structure); |
| | | |
| | | void deleteSalaryStructure(Long id); |
| | | |
| | | HrmSalaryStructureDO getSalaryStructure(Long id); |
| | | |
| | | List<HrmSalaryStructureDO> getSalaryStructureList(String name, Integer status); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.hrm.service.salary; |
| | | |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSalaryStructureDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmEmployeeSalaryMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSalaryStructureMapper; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SALARY_STRUCTURE_IN_USE; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SALARY_STRUCTURE_NAME_EXISTS; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SALARY_STRUCTURE_NOT_EXISTS; |
| | | |
| | | @Service |
| | | @Validated |
| | | public class HrmSalaryStructureServiceImpl implements HrmSalaryStructureService { |
| | | |
| | | @Resource |
| | | private HrmSalaryStructureMapper salaryStructureMapper; |
| | | @Resource |
| | | private HrmEmployeeMapper employeeMapper; |
| | | @Resource |
| | | private HrmEmployeeSalaryMapper employeeSalaryMapper; |
| | | |
| | | @Override |
| | | public Long createSalaryStructure(HrmSalaryStructureDO structure) { |
| | | validateNameUnique(null, structure.getName()); |
| | | // åºæ¬å·¥èµç±å工档æ¡ç»´æ¤ãæ°æ®åºåå²å段éç©ºï¼æ°å»ºç»æç»ä¸åå
¥å ä½å¼ 0ã |
| | | structure.setBaseSalary(BigDecimal.ZERO); |
| | | salaryStructureMapper.insert(structure); |
| | | return structure.getId(); |
| | | } |
| | | |
| | | @Override |
| | | public void updateSalaryStructure(HrmSalaryStructureDO structure) { |
| | | validateExists(structure.getId()); |
| | | validateNameUnique(structure.getId(), structure.getName()); |
| | | salaryStructureMapper.updateById(structure); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteSalaryStructure(Long id) { |
| | | validateExists(id); |
| | | if (employeeMapper.selectCountBySalaryStructureId(id) > 0 |
| | | || employeeSalaryMapper.selectCountBySalaryStructureId(id) > 0) { |
| | | throw exception(SALARY_STRUCTURE_IN_USE); |
| | | } |
| | | salaryStructureMapper.deleteById(id); |
| | | } |
| | | |
| | | @Override |
| | | public HrmSalaryStructureDO getSalaryStructure(Long id) { |
| | | return salaryStructureMapper.selectById(id); |
| | | } |
| | | |
| | | @Override |
| | | public List<HrmSalaryStructureDO> getSalaryStructureList(String name, Integer status) { |
| | | return salaryStructureMapper.selectListByCondition(name, status); |
| | | } |
| | | |
| | | private void validateExists(Long id) { |
| | | if (id == null || salaryStructureMapper.selectById(id) == null) { |
| | | throw exception(SALARY_STRUCTURE_NOT_EXISTS); |
| | | } |
| | | } |
| | | |
| | | private void validateNameUnique(Long id, String name) { |
| | | HrmSalaryStructureDO structure = salaryStructureMapper.selectByName(name); |
| | | if (structure != null && !structure.getId().equals(id)) { |
| | | throw exception(SALARY_STRUCTURE_NAME_EXISTS); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportExcelVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportRespVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemPageReqVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemRespVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemSaveReqVO; |
| | |
| | | import cn.iocoder.yudao.module.mes.api.wm.warehouse.dto.MesWmWarehouseRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.Parameters; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | @GetMapping("/get-import-template") |
| | | @Operation(summary = "è·å¾å¯¼å
¥ç©ææ¨¡æ¿") |
| | | public void importTemplate(HttpServletResponse response) throws IOException { |
| | | List<MdmItemImportExcelVO> list = Arrays.asList( |
| | | MdmItemImportExcelVO.builder().code("ITEM001").name("示ä¾ç©æ").specification("è§æ ¼").status(0).isBatchManaged(false).build() |
| | | ); |
| | | ExcelUtils.write(response, "ç©æå¯¼å
¥æ¨¡æ¿.xls", "ç©æ", MdmItemImportExcelVO.class, list); |
| | | } |
| | | |
| | | @PostMapping("/import") |
| | | @Operation(summary = "导å
¥ç©æ") |
| | | @Parameters({ |
| | | @Parameter(name = "file", description = "Excel æä»¶", required = true), |
| | | @Parameter(name = "updateSupport", description = "æ¯å¦æ¯ææ´æ°ï¼é»è®¤ä¸º false", example = "true") |
| | | }) |
| | | @PreAuthorize("@ss.hasPermission('mdm:item:import')") |
| | | public CommonResult<MdmItemImportRespVO> importExcel(@RequestParam("file") MultipartFile file, |
| | | @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { |
| | | List<MdmItemImportExcelVO> list = ExcelUtils.read(file, MdmItemImportExcelVO.class); |
| | | return success(itemService.importItemList(list, updateSupport)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mdm.controller.admin.item.vo; |
| | | |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * MDM ç©æå¯¼å
¥ Excel VO |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class MdmItemImportExcelVO { |
| | | |
| | | @ExcelProperty("ç©æç¼ç ") |
| | | private String code; |
| | | |
| | | @ExcelProperty("ç©æåç§°") |
| | | private String name; |
| | | |
| | | @ExcelProperty("æ¡ç ") |
| | | private String barCode; |
| | | |
| | | @ExcelProperty("è§æ ¼åå·") |
| | | private String specification; |
| | | |
| | | @ExcelProperty("ç©æåç±»ç¼ç ") |
| | | private String categoryCode; |
| | | |
| | | @ExcelProperty("计éåä½ç¼ç ") |
| | | private String unitMeasureCode; |
| | | |
| | | @ExcelProperty("è¾
åä½1ç¼ç ") |
| | | private String unitMeasureCode2; |
| | | |
| | | @ExcelProperty("è¾
åä½1æ¢ç®æ¯ç") |
| | | private BigDecimal unitMeasureRate1; |
| | | |
| | | @ExcelProperty("è¾
åä½2ç¼ç ") |
| | | private String unitMeasureCode3; |
| | | |
| | | @ExcelProperty("è¾
åä½2æ¢ç®æ¯ç") |
| | | private BigDecimal unitMeasureRate2; |
| | | |
| | | @ExcelProperty("é»è®¤ä»åºç¼ç ") |
| | | private String warehouseCode; |
| | | |
| | | @ExcelProperty("éè´ä»·") |
| | | private BigDecimal purchasePrice; |
| | | |
| | | @ExcelProperty("éå®ä»·") |
| | | private BigDecimal salesPrice; |
| | | |
| | | @ExcelProperty("ææ¬ä»·") |
| | | private BigDecimal costPrice; |
| | | |
| | | @ExcelProperty("å®å
¨åºå") |
| | | private BigDecimal safetyStock; |
| | | |
| | | @ExcelProperty("æä½åºå") |
| | | private BigDecimal minStock; |
| | | |
| | | @ExcelProperty("æé«åºå") |
| | | private BigDecimal maxStock; |
| | | |
| | | @ExcelProperty("æ¯å¦æ¹æ¬¡ç®¡ç") |
| | | private Boolean isBatchManaged; |
| | | |
| | | @ExcelProperty("ä¿è´¨æ(天)") |
| | | private Integer expiryDay; |
| | | |
| | | @ExcelProperty("ç¶æ") |
| | | private Integer status; |
| | | |
| | | @ExcelProperty("æ¯å¦åæ¥å°MES") |
| | | private Boolean syncMes; |
| | | |
| | | @ExcelProperty("夿³¨") |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mdm.controller.admin.item.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Schema(description = "管çåå° - MDM ç©æå¯¼å
¥ Response VO") |
| | | @Data |
| | | @Builder |
| | | public class MdmItemImportRespVO { |
| | | |
| | | @Schema(description = "å建æåçç©ææ°ç»", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private List<String> createList; |
| | | |
| | | @Schema(description = "æ´æ°æåçç©ææ°ç»", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private List<String> updateList; |
| | | |
| | | @Schema(description = "导å
¥å¤±è´¥çç©æéå key ä¸ºç©æåï¼value 为失败åå ", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private Map<String, String> failureList; |
| | | |
| | | } |
| | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureImportExcelVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureImportRespVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasurePageReqVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureSaveReqVO; |
| | | import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO; |
| | | import cn.iocoder.yudao.module.mdm.service.unit.MdmUnitMeasureService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.Parameters; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | |
| | | return success(unitMeasureService.getUnitMeasureList(ids)); |
| | | } |
| | | |
| | | @GetMapping("/get-import-template") |
| | | @Operation(summary = "è·å¾å¯¼å
¥è®¡éå使¨¡æ¿") |
| | | public void importTemplate(HttpServletResponse response) throws IOException { |
| | | List<MdmUnitMeasureImportExcelVO> list = Arrays.asList( |
| | | MdmUnitMeasureImportExcelVO.builder().code("PC").name("ç").primaryFlag(true).changeRate(new java.math.BigDecimal("1")).status(0).remark("示ä¾ï¼ä¸»åä½").build(), |
| | | MdmUnitMeasureImportExcelVO.builder().code("XIA").name("ç®±").primaryFlag(false).primaryCode("PC").changeRate(new java.math.BigDecimal("100")).status(0).remark("示ä¾ï¼1ç®±=100ç").build() |
| | | ); |
| | | ExcelUtils.write(response, "计éåä½å¯¼å
¥æ¨¡æ¿.xls", "计éåä½", MdmUnitMeasureImportExcelVO.class, list); |
| | | } |
| | | |
| | | @PostMapping("/import") |
| | | @Operation(summary = "导å
¥è®¡éåä½") |
| | | @Parameters({ |
| | | @Parameter(name = "file", description = "Excel æä»¶", required = true), |
| | | @Parameter(name = "updateSupport", description = "æ¯å¦æ¯ææ´æ°ï¼é»è®¤ä¸º false", example = "true") |
| | | }) |
| | | @PreAuthorize("@ss.hasPermission('mdm:unit-measure:import')") |
| | | public CommonResult<MdmUnitMeasureImportRespVO> importExcel(@RequestParam("file") MultipartFile file, |
| | | @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { |
| | | List<MdmUnitMeasureImportExcelVO> list = ExcelUtils.read(file, MdmUnitMeasureImportExcelVO.class); |
| | | return success(unitMeasureService.importUnitMeasureList(list, updateSupport)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mdm.controller.admin.unit.vo; |
| | | |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| | | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; |
| | | import cn.iocoder.yudao.module.system.enums.DictTypeConstants; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * MDM 计éåä½å¯¼å
¥ Excel VO |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class MdmUnitMeasureImportExcelVO { |
| | | |
| | | @ExcelProperty("åä½ç¼ç ") |
| | | private String code; |
| | | |
| | | @ExcelProperty("åä½åç§°") |
| | | private String name; |
| | | |
| | | @ExcelProperty("æ¯å¦ä¸»åä½") |
| | | private Boolean primaryFlag; |
| | | |
| | | @ExcelProperty("主åä½ç¼ç ") |
| | | private String primaryCode; |
| | | |
| | | @ExcelProperty("ä¸ä¸»å使¢ç®æ¯ä¾") |
| | | private BigDecimal changeRate; |
| | | |
| | | @ExcelProperty(value = "ç¶æ", converter = DictConvert.class) |
| | | @DictFormat(DictTypeConstants.COMMON_STATUS) |
| | | private Integer status; |
| | | |
| | | @ExcelProperty("夿³¨") |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mdm.controller.admin.unit.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Schema(description = "管çåå° - MDM 计éåä½å¯¼å
¥ Response VO") |
| | | @Data |
| | | @Builder |
| | | public class MdmUnitMeasureImportRespVO { |
| | | |
| | | @Schema(description = "å建æåçå使°ç»", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private List<String> createList; |
| | | |
| | | @Schema(description = "æ´æ°æåçå使°ç»", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private List<String> updateList; |
| | | |
| | | @Schema(description = "导å
¥å¤±è´¥çåä½éå key 为åä½åï¼value 为失败åå ", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private Map<String, String> failureList; |
| | | |
| | | } |
| | |
| | | ErrorCode MDM_ITEM_SKU_IS_DISABLE = new ErrorCode(1_050_005, "ç©æSKUå·²ç¦ç¨"); |
| | | ErrorCode MDM_ITEM_SKU_CODE_DUPLICATE = new ErrorCode(1_050_006, "SKUç¼ç å·²åå¨"); |
| | | ErrorCode MDM_ITEM_EXISTS_REFERENCE = new ErrorCode(1_050_007, "ç©æå·²è¢«ä¸å¡å¼ç¨ï¼æ æ³å é¤"); |
| | | ErrorCode MDM_ITEM_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_008, "导å
¥çç©ææ°æ®ä¸è½ä¸ºç©º"); |
| | | |
| | | // ========== ç©æåç±»ç¸å
³ 1-050-051 ~ 1-050-100 ========== |
| | | ErrorCode MDM_ITEM_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_051, "ç©æåç±»ä¸åå¨"); |
| | |
| | | ErrorCode MDM_UNIT_MEASURE_CODE_DUPLICATE = new ErrorCode(1_050_102, "计éåä½ç¼ç å·²åå¨"); |
| | | ErrorCode MDM_UNIT_MEASURE_NAME_DUPLICATE = new ErrorCode(1_050_103, "计éåä½åç§°å·²åå¨"); |
| | | ErrorCode MDM_UNIT_MEASURE_EXISTS_ITEM = new ErrorCode(1_050_104, "计éåä½è¢«ç©æä½¿ç¨ï¼æ æ³å é¤"); |
| | | ErrorCode MDM_UNIT_MEASURE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_105, "导å
¥ç计éå使°æ®ä¸è½ä¸ºç©º"); |
| | | |
| | | // ========== åçç¸å
³ 1-050-151 ~ 1-050-200 ========== |
| | | ErrorCode MDM_BRAND_NOT_EXISTS = new ErrorCode(1_050_151, "åçä¸åå¨"); |
| | |
| | | package cn.iocoder.yudao.module.mdm.service.item; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportExcelVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportRespVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemPageReqVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemSaveReqVO; |
| | | import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemDO; |
| | |
| | | */ |
| | | List<MdmItemDO> getItemSimpleList(); |
| | | |
| | | /** |
| | | * 导å
¥ç©æ |
| | | * |
| | | * @param importList 导å
¥å表 |
| | | * @param isUpdateSupport æ¯å¦æ¯ææ´æ° |
| | | * @return 导å
¥ç»æ |
| | | */ |
| | | MdmItemImportRespVO importItemList(List<MdmItemImportExcelVO> importList, Boolean isUpdateSupport); |
| | | |
| | | } |
| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportExcelVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportRespVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemPageReqVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemSaveReqVO; |
| | | import cn.iocoder.yudao.module.mdm.dal.dataobject.category.MdmItemCategoryDO; |
| | | import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemBatchConfigDO; |
| | | import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemDO; |
| | | import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO; |
| | | import cn.iocoder.yudao.module.mdm.dal.mysql.category.MdmItemCategoryMapper; |
| | | import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemBatchConfigMapper; |
| | | import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemMapper; |
| | | import cn.iocoder.yudao.module.mdm.dal.mysql.unit.MdmUnitMeasureMapper; |
| | | import cn.iocoder.yudao.module.mdm.service.brand.MdmBrandService; |
| | | import cn.iocoder.yudao.module.mdm.service.category.MdmItemCategoryService; |
| | | import cn.iocoder.yudao.module.mdm.service.unit.MdmUnitMeasureService; |
| | |
| | | private MesMdItemApi mesMdItemApi; |
| | | @Resource |
| | | private MdmItemBatchConfigMapper itemBatchConfigMapper; |
| | | |
| | | @Resource |
| | | private MdmItemCategoryMapper itemCategoryMapper; |
| | | |
| | | @Resource |
| | | private MdmUnitMeasureMapper unitMeasureMapper; |
| | | |
| | | @Resource |
| | | private MesMdItemTypeApi mesMdItemTypeApi; |
| | |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public MdmItemImportRespVO importItemList(List<MdmItemImportExcelVO> importList, Boolean isUpdateSupport) { |
| | | if (CollUtil.isEmpty(importList)) { |
| | | throw exception(MDM_ITEM_IMPORT_LIST_IS_EMPTY); |
| | | } |
| | | MdmItemImportRespVO respVO = MdmItemImportRespVO.builder() |
| | | .createList(new ArrayList<>()).updateList(new ArrayList<>()) |
| | | .failureList(new LinkedHashMap<>()).build(); |
| | | |
| | | // 1. é¢çï¼åç±»ç¼ç -> IDãåä½ç¼ç -> ID |
| | | Map<String, Long> categoryCodeIdMap = new HashMap<>(); |
| | | for (MdmItemCategoryDO category : itemCategoryMapper.selectList()) { |
| | | if (category.getCode() != null) { |
| | | categoryCodeIdMap.put(category.getCode(), category.getId()); |
| | | } |
| | | } |
| | | Map<String, Long> unitCodeIdMap = new HashMap<>(); |
| | | for (MdmUnitMeasureDO unit : unitMeasureMapper.selectList()) { |
| | | unitCodeIdMap.put(unit.getCode(), unit.getId()); |
| | | } |
| | | |
| | | // 2. éå导å
¥ |
| | | for (MdmItemImportExcelVO importVO : importList) { |
| | | // 2.1 åºç¡æ ¡éª |
| | | if (StrUtil.isBlank(importVO.getCode()) || StrUtil.isBlank(importVO.getName())) { |
| | | respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), "ç©æç¼ç åç©æåç§°ä¸è½ä¸ºç©º"); |
| | | continue; |
| | | } |
| | | // 2.2 è§£æåç±» |
| | | Long categoryId = null; |
| | | if (StrUtil.isNotBlank(importVO.getCategoryCode())) { |
| | | categoryId = categoryCodeIdMap.get(importVO.getCategoryCode()); |
| | | if (categoryId == null) { |
| | | respVO.getFailureList().put(importVO.getName(), "ç©æåç±»ç¼ç ä¸åå¨ï¼" + importVO.getCategoryCode()); |
| | | continue; |
| | | } |
| | | } |
| | | // 2.3 è§£æä¸»åä½ |
| | | Long unitMeasureId = null; |
| | | if (StrUtil.isNotBlank(importVO.getUnitMeasureCode())) { |
| | | unitMeasureId = unitCodeIdMap.get(importVO.getUnitMeasureCode()); |
| | | if (unitMeasureId == null) { |
| | | respVO.getFailureList().put(importVO.getName(), "计éåä½ç¼ç ä¸åå¨ï¼" + importVO.getUnitMeasureCode()); |
| | | continue; |
| | | } |
| | | } |
| | | // 2.4 è§£æè¾
åä½1 |
| | | Long unitMeasureId2 = null; |
| | | if (StrUtil.isNotBlank(importVO.getUnitMeasureCode2())) { |
| | | unitMeasureId2 = unitCodeIdMap.get(importVO.getUnitMeasureCode2()); |
| | | if (unitMeasureId2 == null) { |
| | | respVO.getFailureList().put(importVO.getName(), "è¾
åä½1ç¼ç ä¸åå¨ï¼" + importVO.getUnitMeasureCode2()); |
| | | continue; |
| | | } |
| | | } |
| | | // 2.5 è§£æè¾
åä½2 |
| | | Long unitMeasureId3 = null; |
| | | if (StrUtil.isNotBlank(importVO.getUnitMeasureCode3())) { |
| | | unitMeasureId3 = unitCodeIdMap.get(importVO.getUnitMeasureCode3()); |
| | | if (unitMeasureId3 == null) { |
| | | respVO.getFailureList().put(importVO.getName(), "è¾
åä½2ç¼ç ä¸åå¨ï¼" + importVO.getUnitMeasureCode3()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | // 2.6 ç»è£
SaveReqVOï¼å¤ç¨ create/update é»è¾ï¼ |
| | | MdmItemSaveReqVO saveReqVO = new MdmItemSaveReqVO(); |
| | | saveReqVO.setCode(importVO.getCode()); |
| | | saveReqVO.setName(importVO.getName()); |
| | | saveReqVO.setBarCode(importVO.getBarCode()); |
| | | saveReqVO.setSpecification(importVO.getSpecification()); |
| | | saveReqVO.setCategoryId(categoryId); |
| | | saveReqVO.setUnitMeasureId(unitMeasureId); |
| | | saveReqVO.setUnitMeasureId2(unitMeasureId2); |
| | | saveReqVO.setUnitMeasureRate1(importVO.getUnitMeasureRate1()); |
| | | saveReqVO.setUnitMeasureId3(unitMeasureId3); |
| | | saveReqVO.setUnitMeasureRate2(importVO.getUnitMeasureRate2()); |
| | | saveReqVO.setPurchasePrice(importVO.getPurchasePrice()); |
| | | saveReqVO.setSalesPrice(importVO.getSalesPrice()); |
| | | saveReqVO.setCostPrice(importVO.getCostPrice()); |
| | | saveReqVO.setSafetyStock(importVO.getSafetyStock()); |
| | | saveReqVO.setMinStock(importVO.getMinStock()); |
| | | saveReqVO.setMaxStock(importVO.getMaxStock()); |
| | | saveReqVO.setIsBatchManaged(importVO.getIsBatchManaged()); |
| | | saveReqVO.setExpiryDay(importVO.getExpiryDay()); |
| | | saveReqVO.setStatus(importVO.getStatus() != null ? importVO.getStatus() : cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus()); |
| | | saveReqVO.setSyncMes(importVO.getSyncMes() != null ? importVO.getSyncMes() : false); |
| | | saveReqVO.setRemark(importVO.getRemark()); |
| | | saveReqVO.setItemType(1); // é»è®¤ç©æç±»åï¼ç©æ |
| | | |
| | | // 2.7 å·²åå¨ï¼æç¼ç å¤æï¼ |
| | | MdmItemDO existByCode = itemMapper.selectByCode(importVO.getCode()); |
| | | try { |
| | | if (existByCode != null) { |
| | | if (!Boolean.TRUE.equals(isUpdateSupport)) { |
| | | respVO.getFailureList().put(importVO.getName(), "ç©æç¼ç å·²åå¨"); |
| | | continue; |
| | | } |
| | | saveReqVO.setId(existByCode.getId()); |
| | | updateItem(saveReqVO); |
| | | respVO.getUpdateList().add(importVO.getName()); |
| | | } else { |
| | | createItem(saveReqVO); |
| | | respVO.getCreateList().add(importVO.getName()); |
| | | } |
| | | } catch (Exception ex) { |
| | | // åæ¡å¤±è´¥ï¼è®°å½å¹¶ç»§ç» |
| | | String reason = ex instanceof cn.iocoder.yudao.framework.common.exception.ServiceException |
| | | ? ((cn.iocoder.yudao.framework.common.exception.ServiceException) ex).getMessage() |
| | | : ex.getMessage(); |
| | | respVO.getFailureList().put(importVO.getName(), reason == null ? "导å
¥å¤±è´¥" : reason); |
| | | } |
| | | } |
| | | return respVO; |
| | | } |
| | | |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.mdm.service.unit; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureImportExcelVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureImportRespVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasurePageReqVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureSaveReqVO; |
| | | import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO; |
| | |
| | | */ |
| | | MdmUnitMeasureDO getUnitMeasureByCode(String code); |
| | | |
| | | /** |
| | | * 导å
¥è®¡éåä½ |
| | | * |
| | | * @param importList 导å
¥å表 |
| | | * @param isUpdateSupport æ¯å¦æ¯ææ´æ° |
| | | * @return 导å
¥ç»æ |
| | | */ |
| | | MdmUnitMeasureImportRespVO importUnitMeasureList(List<MdmUnitMeasureImportExcelVO> importList, Boolean isUpdateSupport); |
| | | |
| | | } |
| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureImportExcelVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureImportRespVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasurePageReqVO; |
| | | import cn.iocoder.yudao.module.mdm.controller.admin.unit.vo.MdmUnitMeasureSaveReqVO; |
| | | import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO; |
| | |
| | | return unitMeasureMapper.selectByCode(code); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public MdmUnitMeasureImportRespVO importUnitMeasureList(List<MdmUnitMeasureImportExcelVO> importList, Boolean isUpdateSupport) { |
| | | if (CollUtil.isEmpty(importList)) { |
| | | throw exception(MDM_UNIT_MEASURE_IMPORT_LIST_IS_EMPTY); |
| | | } |
| | | MdmUnitMeasureImportRespVO respVO = MdmUnitMeasureImportRespVO.builder() |
| | | .createList(new ArrayList<>()).updateList(new ArrayList<>()) |
| | | .failureList(new LinkedHashMap<>()).build(); |
| | | |
| | | // 1. 建ç«ç¼ç -> ID æ å°ï¼å
å è½½ç°æåä½ï¼åå å æ¬æ¬¡æ°å»ºçåä½ï¼ï¼ç¨äºè§£æ"主åä½ç¼ç "å |
| | | Map<String, Long> codeIdMap = new HashMap<>(); |
| | | for (MdmUnitMeasureDO unit : unitMeasureMapper.selectList()) { |
| | | codeIdMap.put(unit.getCode(), unit.getId()); |
| | | } |
| | | // è®°å½æ¬æ¬¡å¯¼å
¥å·²å¤çè¿çç¼ç ï¼é¿å
å䏿件å
åç»è¡æ¾ä¸å°å导å
¥ç主åä½ |
| | | Map<String, Long> importedCodeIdMap = new HashMap<>(); |
| | | |
| | | // 2. éå导å
¥ |
| | | for (MdmUnitMeasureImportExcelVO importVO : importList) { |
| | | // 2.1 åºç¡æ ¡éª |
| | | if (StrUtil.isBlank(importVO.getCode()) || StrUtil.isBlank(importVO.getName())) { |
| | | respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), "åä½ç¼ç ååä½åç§°ä¸è½ä¸ºç©º"); |
| | | continue; |
| | | } |
| | | // 2.2 è§£æä¸»åä½ IDï¼é主å使¶å¿
填主åä½ç¼ç ï¼ |
| | | Long primaryId = null; |
| | | if (StrUtil.isNotBlank(importVO.getPrimaryCode())) { |
| | | primaryId = importedCodeIdMap.get(importVO.getPrimaryCode()) != null |
| | | ? importedCodeIdMap.get(importVO.getPrimaryCode()) |
| | | : codeIdMap.get(importVO.getPrimaryCode()); |
| | | if (primaryId == null) { |
| | | respVO.getFailureList().put(importVO.getName(), "主åä½ç¼ç ä¸åå¨ï¼" + importVO.getPrimaryCode()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | // 2.3 å·²åå¨ï¼æç¼ç å¤æï¼ |
| | | MdmUnitMeasureDO existByCode = unitMeasureMapper.selectByCode(importVO.getCode()); |
| | | if (existByCode != null) { |
| | | if (!Boolean.TRUE.equals(isUpdateSupport)) { |
| | | respVO.getFailureList().put(importVO.getName(), "åä½ç¼ç å·²åå¨"); |
| | | continue; |
| | | } |
| | | // æ¯ææ´æ°ï¼ä»¥ç¼ç ä¸ºåæ´æ° |
| | | MdmUnitMeasureDO updateObj = BeanUtils.toBean(importVO, MdmUnitMeasureDO.class); |
| | | updateObj.setId(existByCode.getId()); |
| | | updateObj.setPrimaryId(primaryId); |
| | | unitMeasureMapper.updateById(updateObj); |
| | | respVO.getUpdateList().add(importVO.getName()); |
| | | } else { |
| | | // 2.4 æ ¡éªåç§°å¯ä¸ï¼æ°å¢åºæ¯ï¼ |
| | | MdmUnitMeasureDO existByName = unitMeasureMapper.selectByName(importVO.getName()); |
| | | if (existByName != null) { |
| | | respVO.getFailureList().put(importVO.getName(), "åä½åç§°å·²åå¨"); |
| | | continue; |
| | | } |
| | | // 2.5 æ°å¢ |
| | | MdmUnitMeasureDO newObj = BeanUtils.toBean(importVO, MdmUnitMeasureDO.class); |
| | | newObj.setPrimaryId(primaryId); |
| | | unitMeasureMapper.insert(newObj); |
| | | respVO.getCreateList().add(importVO.getName()); |
| | | // è®°å½æ¬æ¬¡æ°å»ºçç¼ç ï¼ä¾åæä»¶åç»è¡å¼ç¨ |
| | | importedCodeIdMap.put(importVO.getCode(), newObj.getId()); |
| | | } |
| | | } |
| | | return respVO; |
| | | } |
| | | |
| | | } |
| | |
| | | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeImportExcelVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeImportRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; |
| | |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.Parameters; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | |
| | | .setItemOrProduct(itemType.getItemOrProduct()))); |
| | | } |
| | | |
| | | @GetMapping("/get-import-template") |
| | | @Operation(summary = "è·å¾å¯¼å
¥ç©æäº§åå类模æ¿") |
| | | public void importTemplate(HttpServletResponse response) throws IOException { |
| | | List<MesMdItemTypeImportExcelVO> list = Arrays.asList( |
| | | MesMdItemTypeImportExcelVO.builder().code("RAW").name("åææ").itemOrProduct("ITEM").sort(1).status(0).remark("示ä¾ï¼é¡¶çº§åç±»").build(), |
| | | MesMdItemTypeImportExcelVO.builder().code("METAL").name("é屿æ").parentCode("RAW").itemOrProduct("ITEM").sort(1).status(0).remark("示ä¾ï¼ç¶åç±»ç¼ç 为 RAW").build() |
| | | ); |
| | | ExcelUtils.write(response, "ç©æå类导å
¥æ¨¡æ¿.xls", "ç©æåç±»", MesMdItemTypeImportExcelVO.class, list); |
| | | } |
| | | |
| | | @PostMapping("/import") |
| | | @Operation(summary = "导å
¥ç©æäº§ååç±»") |
| | | @Parameters({ |
| | | @Parameter(name = "file", description = "Excel æä»¶", required = true), |
| | | @Parameter(name = "updateSupport", description = "æ¯å¦æ¯ææ´æ°ï¼é»è®¤ä¸º false", example = "true") |
| | | }) |
| | | @PreAuthorize("@ss.hasPermission('mes:md-item-type:import')") |
| | | public CommonResult<MesMdItemTypeImportRespVO> importExcel(@RequestParam("file") MultipartFile file, |
| | | @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { |
| | | List<MesMdItemTypeImportExcelVO> list = ExcelUtils.read(file, MesMdItemTypeImportExcelVO.class); |
| | | return success(itemTypeService.importItemTypeList(list, updateSupport)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; |
| | | |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * MES ç©æäº§åå类导å
¥ Excel VO |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class MesMdItemTypeImportExcelVO { |
| | | |
| | | @ExcelProperty("åç±»ç¼ç ") |
| | | private String code; |
| | | |
| | | @ExcelProperty("åç±»åç§°") |
| | | private String name; |
| | | |
| | | @ExcelProperty("ç¶åç±»ç¼ç ") |
| | | private String parentCode; |
| | | |
| | | @ExcelProperty("ç©æ/äº§åæ è¯") |
| | | private String itemOrProduct; |
| | | |
| | | @ExcelProperty("æ¾ç¤ºæåº") |
| | | private Integer sort; |
| | | |
| | | @ExcelProperty("ç¶æ") |
| | | private Integer status; |
| | | |
| | | @ExcelProperty("夿³¨") |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Schema(description = "管çåå° - MES ç©æäº§åå类导å
¥ Response VO") |
| | | @Data |
| | | @Builder |
| | | public class MesMdItemTypeImportRespVO { |
| | | |
| | | @Schema(description = "å建æåçåç±»æ°ç»", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private List<String> createList; |
| | | |
| | | @Schema(description = "æ´æ°æåçåç±»æ°ç»", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private List<String> updateList; |
| | | |
| | | @Schema(description = "导å
¥å¤±è´¥çåç±»éå key 为åç±»åï¼value 为失败åå ", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private Map<String, String> failureList; |
| | | |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.pd.document; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pd.document.MesPdDocumentDO; |
| | | import cn.iocoder.yudao.module.mes.service.pd.document.MesPdDocumentService; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | // 1.1 æ¹éè·åå
³èæ°æ®ï¼ä¸ä¼ äººï¼ |
| | | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(list, MesPdDocumentDO::getUploadUserId)); |
| | | // 2. æ¼æ¥ VO |
| | | return BeanUtils.toBean(list, MesPdDocumentRespVO.class, vo -> { |
| | | List<MesPdDocumentRespVO> voList = BeanUtils.toBean(list, MesPdDocumentRespVO.class, vo -> { |
| | | MapUtils.findAndThen(userMap, vo.getUploadUserId(), |
| | | user -> vo.setUploadUserNickname(user.getNickname())); |
| | | }); |
| | | // 3. æ¼æ¥æä»¶ä¿¡æ¯ï¼ä¼å
å第ä¸ä¸ªéä»¶çå°åä½ä¸º fileUrlï¼å¹¶å¨æªå¡«æä»¶åæ¶èªå¨è¡¥å
¨ |
| | | for (MesPdDocumentRespVO vo : voList) { |
| | | List<StorageBlobRespDTO> attachments = storageAttachmentApi.listAttachments("mes_pd_document", vo.getId()); |
| | | if (CollUtil.isNotEmpty(attachments)) { |
| | | StorageBlobRespDTO first = attachments.get(0); |
| | | vo.setFileUrl(first.getUrl()); |
| | | if (StrUtil.isEmpty(vo.getFileName())) { |
| | | vo.setFileName(first.getName()); |
| | | } |
| | | } |
| | | } |
| | | return voList; |
| | | } |
| | | |
| | | } |
| | |
| | | @ExcelProperty("æä»¶å") |
| | | private String fileName; |
| | | |
| | | @Schema(description = "æä»¶å°å", example = "https://www.iocoder.cn/design_v1.pdf") |
| | | private String fileUrl; |
| | | |
| | | @Schema(description = "ä¸ä¼ 人", example = "1") |
| | | private Long uploadUserId; |
| | | |
| | |
| | | return success(returnVendorService.checkReturnVendorQuantity(id)); |
| | | } |
| | | |
| | | @PostMapping("/import-purchase-order-items") |
| | | @Operation(summary = "æ ¹æ®å
³èéè´è®¢å带å
¥ç©ææç»") |
| | | @Parameter(name = "id", description = "ç¼å·", required = true) |
| | | @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:update')") |
| | | public CommonResult<Integer> importPurchaseOrderItems(@RequestParam("id") Long id) { |
| | | return success(returnVendorService.importPurchaseOrderItems(id)); |
| | | } |
| | | |
| | | // ==================== æ¼æ¥ VO ==================== |
| | | |
| | | private List<MesWmReturnVendorRespVO> buildRespVOList(List<MesWmReturnVendorDO> list) { |
| | |
| | | .collect(java.util.stream.Collectors.toMap(SrmSupplierRespDTO::getId, s -> s)); |
| | | // 2. æå»ºç»æ |
| | | return BeanUtils.toBean(list, MesWmReturnVendorRespVO.class, vo -> |
| | | MapUtils.findAndThen(vendorMap, vo.getVendorId(), vendor -> |
| | | vo.setVendorName(vendor.getName()))); |
| | | MapUtils.findAndThen(vendorMap, vo.getVendorId(), vendor -> { |
| | | vo.setVendorName(vendor.getName()); |
| | | vo.setVendorCode(vendor.getCode()); |
| | | })); |
| | | } |
| | | |
| | | } |
| | |
| | | @Schema(description = "éè´§ååç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "ä¾åºåéè´§") |
| | | private String name; |
| | | |
| | | @Schema(description = "éè´è®¢åç¼å·", example = "1") |
| | | private Long purchaseOrderId; |
| | | |
| | | @Schema(description = "éè´è®¢åç¼å·", example = "PO20250226001") |
| | | private String purchaseOrderCode; |
| | | |
| | |
| | | @NotBlank(message = "éè´§ååç§°ä¸è½ä¸ºç©º") |
| | | private String name; |
| | | |
| | | @Schema(description = "éè´è®¢åç¼å·", example = "1") |
| | | private Long purchaseOrderId; |
| | | |
| | | @Schema(description = "éè´è®¢åç¼å·", example = "PO20250226001") |
| | | private String purchaseOrderCode; |
| | | |
| | |
| | | private String name; |
| | | /** |
| | | * éè´è®¢åç¼å· |
| | | * |
| | | * å
³è ERP éè´è®¢å {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO#getId()} |
| | | */ |
| | | private Long purchaseOrderId; |
| | | /** |
| | | * éè´è®¢åç¼ç ï¼åä½å段ï¼ç¨äºæ¾ç¤ºï¼ |
| | | */ |
| | | private String purchaseOrderCode; |
| | | /** |
| | |
| | | .le(MesDvMeteringDO::getNextCheckDate, end)); |
| | | } |
| | | |
| | | default List<MesDvMeteringDO> selectListByNextCheckDateBefore(LocalDate date) { |
| | | return selectList(new LambdaQueryWrapperX<MesDvMeteringDO>() |
| | | .isNotNull(MesDvMeteringDO::getNextCheckDate) |
| | | .lt(MesDvMeteringDO::getNextCheckDate, date)); |
| | | } |
| | | |
| | | } |
| | |
| | | */ |
| | | String METERING_EXPIRE_REMIND_SCAN = "mes:dv:metering:remind:scan:"; |
| | | |
| | | /** |
| | | * 计éå¨å
·å·²è¿ææéå»é |
| | | * |
| | | * KEY æ ¼å¼ï¼mes:dv:metering:overdue:remind:{meteringId}:{nextCheckDate} |
| | | * VALUE æ°æ®æ ¼å¼ï¼1 |
| | | * |
| | | * ä¸ {@link #METERING_EXPIRE_REMIND} ç¸äºç¬ç«ï¼ä¿è¯å¨å
·è¿æåä»è½åç¬æé䏿¬¡ |
| | | */ |
| | | String METERING_EXPIRE_REMIND_OVERDUE = "mes:dv:metering:overdue:remind:"; |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * å°è¯æ è®°å·²æéï¼å·²è¿æåºæ¯ï¼60 天å
åªæé䏿¬¡ï¼ |
| | | * |
| | | * 使ç¨ç¬ç«ç KEYï¼ä¸ {@link #tryMarkReminded} ç¸äºé离ï¼ä¿è¯å¨å
·è¿æåä»è½åç¬æé䏿¬¡ |
| | | * |
| | | * @param meteringId 计éå¨å
·ç¼å· |
| | | * @param nextCheckDate å°ææ¥ |
| | | * @return true è¡¨ç¤ºé¦æ¬¡æ è®°æåï¼éè¦åéæé |
| | | */ |
| | | public boolean tryMarkOverdueReminded(Long meteringId, LocalDate nextCheckDate) { |
| | | String key = RedisKeyConstants.METERING_EXPIRE_REMIND_OVERDUE + meteringId + ":" + nextCheckDate; |
| | | return Boolean.TRUE.equals(stringRedisTemplate.opsForValue().setIfAbsent(key, "1", REMIND_TIMEOUT)); |
| | | } |
| | | |
| | | /** |
| | | * å°è¯è·åå½å¤©çæ«æé¨é©ï¼é¿å
å¤å®ä¾å¹¶åé夿«æ |
| | | * |
| | | * @param today å½å¤©æ¥æ |
| | |
| | | ErrorCode MD_ITEM_TYPE_CODE_DUPLICATE = new ErrorCode(1_040_100_005, "åä¸ç¶åç±»ä¸å·²åå¨è¯¥ç¼ç çåç±»"); |
| | | ErrorCode MD_ITEM_TYPE_PARENT_IS_CHILD = new ErrorCode(1_040_100_006, "ä¸è½è®¾ç½®èªå·±çåå类为ç¶åç±»"); |
| | | ErrorCode MD_ITEM_TYPE_EXITS_ITEM = new ErrorCode(1_040_100_007, "该åç±»ä¸åå¨ç©æï¼æ æ³å é¤"); |
| | | ErrorCode MD_ITEM_TYPE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_100_008, "导å
¥çç©æåç±»æ°æ®ä¸è½ä¸ºç©º"); |
| | | |
| | | // ========== MES åºç¡æ°æ®-计éåä½ï¼1-040-101-000ï¼ ========== |
| | | ErrorCode MD_UNIT_MEASURE_NOT_EXISTS = new ErrorCode(1_040_101_000, "计éåä½ä¸åå¨"); |
| | |
| | | ErrorCode WM_RETURN_VENDOR_DETAIL_NOT_EXISTS = new ErrorCode(1_040_711_200, "ä¾åºåéè´§åæç»ä¸åå¨"); |
| | | ErrorCode WM_RETURN_VENDOR_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_711_201, "éè´§æç»æ°éå¿
é¡»å¤§äº 0"); |
| | | ErrorCode WM_RETURN_VENDOR_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_711_202, "æ£è´§æç»ä¸å±äºæå®çä¾åºåéè´§å"); |
| | | ErrorCode WM_RETURN_VENDOR_PURCHASE_ORDER_REQUIRED = new ErrorCode(1_040_711_008, "请å
éæ©éè´è®¢å"); |
| | | ErrorCode WM_RETURN_VENDOR_PURCHASE_ORDER_NO_ITEM = new ErrorCode(1_040_711_009, "éè´è®¢åæ æç»æ°æ®ï¼æ æ³å¸¦å
¥ç©æ"); |
| | | |
| | | // ========== MES ä»åºç®¡ç-äº§åæ¶è´§åï¼1-040-712-000ï¼ ========== |
| | | ErrorCode WM_PRODUCT_RECPT_NOT_EXISTS = new ErrorCode(1_040_712_000, "äº§åæ¶è´§åä¸åå¨"); |
| | |
| | | */ |
| | | private static final int DEFAULT_REMIND_DAYS = 30; |
| | | /** |
| | | * å°ææéç«å
信模æ¿ç¼å· |
| | | * å³å°å°ææéç«å
信模æ¿ç¼å· |
| | | */ |
| | | private static final String REMIND_TEMPLATE_CODE = "mes_metering_expire_remind"; |
| | | /** |
| | | * å·²è¿ææéç«å
信模æ¿ç¼å· |
| | | */ |
| | | private static final String OVERDUE_TEMPLATE_CODE = "mes_metering_expire_overdue"; |
| | | |
| | | @Resource |
| | | private MesDvMeteringMapper meteringMapper; |
| | |
| | | } |
| | | // 2. 读åæé天æ°ï¼é»è®¤ 30ï¼ |
| | | int remindDays = getRemindDays(); |
| | | // 3. æ¥è¯¢ [today, today + remindDays] å°æçå¨å
· |
| | | List<MesDvMeteringDO> list = meteringMapper.selectListByNextCheckDateBetween( |
| | | // 3. æ¥è¯¢å·²è¿æï¼å°ææ¥ < ä»å¤©ï¼ä¸å³å°å°æï¼å°ææ¥å¨ [today, today + remindDays]ï¼çå¨å
· |
| | | List<MesDvMeteringDO> overdueList = meteringMapper.selectListByNextCheckDateBefore(today); |
| | | List<MesDvMeteringDO> dueList = meteringMapper.selectListByNextCheckDateBetween( |
| | | today, today.plusDays(remindDays)); |
| | | // 4. éå°åéç«å
ä¿¡ï¼æå¨å
· + å°ææ¥å»éï¼ |
| | | for (MesDvMeteringDO metering : list) { |
| | | // 4. éå°åéç«å
ä¿¡ï¼æå¨å
· + å°ææ¥å»éï¼ä¸¤ç±»ç¸äºç¬ç«ï¼ |
| | | for (MesDvMeteringDO metering : overdueList) { |
| | | if (metering.getChargeUserId() == null || metering.getNextCheckDate() == null) { |
| | | continue; |
| | | } |
| | | if (!meteringRemindRedisDAO.tryMarkOverdueReminded(metering.getId(), metering.getNextCheckDate())) { |
| | | continue; |
| | | } |
| | | sendRemindMessage(metering, OVERDUE_TEMPLATE_CODE); |
| | | } |
| | | for (MesDvMeteringDO metering : dueList) { |
| | | if (metering.getChargeUserId() == null || metering.getNextCheckDate() == null) { |
| | | continue; |
| | | } |
| | | if (!meteringRemindRedisDAO.tryMarkReminded(metering.getId(), metering.getNextCheckDate())) { |
| | | continue; |
| | | } |
| | | sendRemindMessage(metering); |
| | | sendRemindMessage(metering, REMIND_TEMPLATE_CODE); |
| | | } |
| | | } catch (Exception ex) { |
| | | // best-effortï¼æé失败ä¸å½±åå表æ¥è¯¢ |
| | |
| | | } |
| | | } |
| | | |
| | | private void sendRemindMessage(MesDvMeteringDO metering) { |
| | | private void sendRemindMessage(MesDvMeteringDO metering, String templateCode) { |
| | | Map<String, Object> params = new HashMap<>(); |
| | | params.put("meteringCode", metering.getCode()); |
| | | params.put("meteringName", metering.getName()); |
| | | params.put("nextCheckDate", metering.getNextCheckDate().toString()); |
| | | NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO() |
| | | .setUserId(metering.getChargeUserId()) |
| | | .setTemplateCode(REMIND_TEMPLATE_CODE) |
| | | .setTemplateCode(templateCode) |
| | | .setTemplateParams(params); |
| | | notifyMessageSendApi.sendSingleMessageToAdmin(reqDTO); |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.mes.service.md.item; |
| | | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeImportExcelVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeImportRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; |
| | |
| | | */ |
| | | List<MesMdItemTypeDO> getItemTypeChildrenList(Long parentId); |
| | | |
| | | /** |
| | | * 导å
¥ç©æäº§ååç±» |
| | | * |
| | | * @param importList 导å
¥å表 |
| | | * @param isUpdateSupport æ¯å¦æ¯ææ´æ° |
| | | * @return 导å
¥ç»æ |
| | | */ |
| | | MesMdItemTypeImportRespVO importItemTypeList(List<MesMdItemTypeImportExcelVO> importList, Boolean isUpdateSupport); |
| | | |
| | | } |
| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mdm.api.category.MdmItemCategoryApi; |
| | | import cn.iocoder.yudao.module.mdm.api.category.dto.MdmItemCategoryRespDTO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeImportExcelVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeImportRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; |
| | |
| | | return mesDO; |
| | | } |
| | | |
| | | @Override |
| | | @org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class) |
| | | public MesMdItemTypeImportRespVO importItemTypeList(List<MesMdItemTypeImportExcelVO> importList, Boolean isUpdateSupport) { |
| | | if (CollUtil.isEmpty(importList)) { |
| | | throw exception(MD_ITEM_TYPE_IMPORT_LIST_IS_EMPTY); |
| | | } |
| | | MesMdItemTypeImportRespVO respVO = MesMdItemTypeImportRespVO.builder() |
| | | .createList(new ArrayList<>()).updateList(new ArrayList<>()) |
| | | .failureList(new LinkedHashMap<>()).build(); |
| | | |
| | | // 1. 建ç«ç¼ç -> ID æ å°ï¼ç°æåç±» + æ¬æ¬¡æ°å»ºåç±»ï¼ï¼ç¨äºè§£æ"ç¶åç±»ç¼ç "å |
| | | Map<String, Long> codeIdMap = new HashMap<>(); |
| | | for (MesMdItemTypeDO itemType : itemTypeMapper.selectList()) { |
| | | codeIdMap.put(itemType.getCode(), itemType.getId()); |
| | | } |
| | | Map<String, Long> importedCodeIdMap = new HashMap<>(); |
| | | |
| | | // 2. éå导å
¥ |
| | | for (MesMdItemTypeImportExcelVO importVO : importList) { |
| | | // 2.1 åºç¡æ ¡éª |
| | | if (StrUtil.isBlank(importVO.getCode()) || StrUtil.isBlank(importVO.getName())) { |
| | | respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), "åç±»ç¼ç ååç±»åç§°ä¸è½ä¸ºç©º"); |
| | | continue; |
| | | } |
| | | // 2.2 è§£æç¶åç±» ID |
| | | Long parentId = MesMdItemTypeDO.PARENT_ID_ROOT; |
| | | if (StrUtil.isNotBlank(importVO.getParentCode())) { |
| | | Long pid = importedCodeIdMap.get(importVO.getParentCode()) != null |
| | | ? importedCodeIdMap.get(importVO.getParentCode()) |
| | | : codeIdMap.get(importVO.getParentCode()); |
| | | if (pid == null) { |
| | | respVO.getFailureList().put(importVO.getName(), "ç¶åç±»ç¼ç ä¸åå¨ï¼" + importVO.getParentCode()); |
| | | continue; |
| | | } |
| | | parentId = pid; |
| | | } |
| | | |
| | | // 2.3 å·²åå¨ï¼æç¼ç å¤æï¼ |
| | | MesMdItemTypeDO existByCode = itemTypeMapper.selectByCode(importVO.getCode()); |
| | | if (existByCode != null) { |
| | | if (!Boolean.TRUE.equals(isUpdateSupport)) { |
| | | respVO.getFailureList().put(importVO.getName(), "åç±»ç¼ç å·²åå¨"); |
| | | continue; |
| | | } |
| | | MesMdItemTypeDO updateObj = BeanUtils.toBean(importVO, MesMdItemTypeDO.class); |
| | | updateObj.setId(existByCode.getId()); |
| | | updateObj.setParentId(parentId); |
| | | itemTypeMapper.updateById(updateObj); |
| | | respVO.getUpdateList().add(importVO.getName()); |
| | | } else { |
| | | // 2.4 æ ¡éªåä¸ç¶åç±»ä¸åç§°å¯ä¸ |
| | | MesMdItemTypeDO existByName = itemTypeMapper.selectByParentIdAndName(parentId, importVO.getName()); |
| | | if (existByName != null) { |
| | | respVO.getFailureList().put(importVO.getName(), "åä¸ç¶åç±»ä¸å·²åå¨è¯¥åç§°çåç±»"); |
| | | continue; |
| | | } |
| | | // 2.5 æ ¡éªåä¸ç¶åç±»ä¸ç¼ç å¯ä¸ |
| | | MesMdItemTypeDO existByParentCode = itemTypeMapper.selectByParentIdAndCode(parentId, importVO.getCode()); |
| | | if (existByParentCode != null) { |
| | | respVO.getFailureList().put(importVO.getName(), "åä¸ç¶åç±»ä¸å·²åå¨è¯¥ç¼ç çåç±»"); |
| | | continue; |
| | | } |
| | | // 2.6 æ°å¢ |
| | | MesMdItemTypeDO newObj = BeanUtils.toBean(importVO, MesMdItemTypeDO.class); |
| | | newObj.setParentId(parentId); |
| | | itemTypeMapper.insert(newObj); |
| | | respVO.getCreateList().add(importVO.getName()); |
| | | importedCodeIdMap.put(importVO.getCode(), newObj.getId()); |
| | | } |
| | | } |
| | | return respVO; |
| | | } |
| | | |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.mes.service.pd.document; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pd.document.vo.MesPdDocumentPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pd.document.vo.MesPdDocumentSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pd.document.MesPdDocumentDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pd.document.MesPdDocumentMapper; |
| | | import cn.iocoder.yudao.module.mes.service.pd.project.MesPdProjectService; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | |
| | | projectService.validateProjectExists(createReqVO.getProjectId()); |
| | | // æå
¥ |
| | | MesPdDocumentDO document = BeanUtils.toBean(createReqVO, MesPdDocumentDO.class); |
| | | // è¡¥å
ä¸ä¼ 人ãä¸ä¼ æ¶é´ |
| | | if (document.getUploadUserId() == null) { |
| | | document.setUploadUserId(SecurityFrameworkUtils.getLoginUserId()); |
| | | } |
| | | if (document.getUploadTime() == null) { |
| | | document.setUploadTime(LocalDateTime.now()); |
| | | } |
| | | documentMapper.insert(document); |
| | | storageAttachmentApi.bindAttachments("file", "mes_pd_document", |
| | | document.getId(), createReqVO.getBlobIds()); |
| | | // æªå¡«åæä»¶åæ¶ï¼ä»ä¸ä¼ éä»¶èªå¨è¡¥å
¨ |
| | | fillFileNameIfAbsent(document); |
| | | return document.getId(); |
| | | } |
| | | |
| | | @Override |
| | | public void updateDocument(MesPdDocumentSaveReqVO updateReqVO) { |
| | | // æ ¡éªåå¨ |
| | | validateDocumentExists(updateReqVO.getId()); |
| | | MesPdDocumentDO existing = validateDocumentExists(updateReqVO.getId()); |
| | | // æ´æ° |
| | | MesPdDocumentDO updateObj = BeanUtils.toBean(updateReqVO, MesPdDocumentDO.class); |
| | | // ä¿çåä¸ä¼ 人ãä¸ä¼ æ¶é´ï¼å岿°æ®ä¸ºç©ºæ¶è¡¥é½ |
| | | if (updateObj.getUploadUserId() == null) { |
| | | updateObj.setUploadUserId(existing.getUploadUserId() != null |
| | | ? existing.getUploadUserId() : SecurityFrameworkUtils.getLoginUserId()); |
| | | } |
| | | if (updateObj.getUploadTime() == null) { |
| | | updateObj.setUploadTime(existing.getUploadTime() != null |
| | | ? existing.getUploadTime() : LocalDateTime.now()); |
| | | } |
| | | documentMapper.updateById(updateObj); |
| | | storageAttachmentApi.updateAttachments("file", "mes_pd_document", updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | // æªå¡«åæä»¶åæ¶ï¼ä»ä¸ä¼ éä»¶èªå¨è¡¥å
¨ |
| | | fillFileNameIfAbsent(updateObj); |
| | | } |
| | | |
| | | @Override |
| | |
| | | return document; |
| | | } |
| | | |
| | | /** |
| | | * æªå¡«åæä»¶åæ¶ï¼ä»ä¸ä¼ éä»¶èªå¨è¡¥å
¨æä»¶å |
| | | * |
| | | * @param document è®¾è®¡èµæ |
| | | */ |
| | | private void fillFileNameIfAbsent(MesPdDocumentDO document) { |
| | | if (StrUtil.isNotEmpty(document.getFileName())) { |
| | | return; |
| | | } |
| | | List<StorageBlobRespDTO> attachments = storageAttachmentApi.listAttachments("mes_pd_document", document.getId()); |
| | | if (CollUtil.isNotEmpty(attachments)) { |
| | | document.setFileName(attachments.get(0).getName()); |
| | | documentMapper.updateById(document); |
| | | } |
| | | } |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderSourceTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService; |
| | |
| | | throw exception(PRO_MPS_NOT_ISSUED); |
| | | } |
| | | |
| | | // 级èåæ¶å
³èçç产工å |
| | | // 级èåæ¶å
³èçç产工åï¼è·éå·¥åå½åç¶æï¼ä¸ä¸è¯¯ä¼¤åå¹¶ä¸åçå
±äº«å·¥åï¼ |
| | | if (mps.getWorkOrderId() != null) { |
| | | try { |
| | | workOrderService.cancelWorkOrder(mps.getWorkOrderId()); |
| | | log.info("[cancelMps] 级èåæ¶ç产工åï¼workOrderId={}", mps.getWorkOrderId()); |
| | | } catch (Exception e) { |
| | | // å·¥åå¯è½å·²å®ææå·²åæ¶ï¼è®°å½æ¥å¿ä½ä¸é»æ¢ MPS åæ¶ |
| | | log.warn("[cancelMps] åæ¶ç产工å失败ï¼workOrderId={}ï¼åå ï¼{}", mps.getWorkOrderId(), e.getMessage()); |
| | | // 1. ç»è®¡è¯¥å·¥å被å¤å°æ¡ MPS å¼ç¨ï¼åå¹¶ä¸åç夿¡ MPS å
±äº«åä¸ä¸ªå·¥å |
| | | Long refCount = mpsMapper.selectCount(MesProMpsDO::getWorkOrderId, mps.getWorkOrderId()); |
| | | if (refCount != null && refCount > 1) { |
| | | // å
±äº«å·¥åï¼åªåæ¶å½å MPSï¼ä¸å¨å·¥å |
| | | log.info("[cancelMps] ç产工å({}) 被 {} æ¡ MPS å
±ç¨ï¼è·³è¿çº§èåæ¶å·¥å", |
| | | mps.getWorkOrderId(), refCount); |
| | | } else { |
| | | MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(mps.getWorkOrderId()); |
| | | if (workOrder != null |
| | | && MesProWorkOrderStatusEnum.CONFIRMED.getStatus().equals(workOrder.getStatus())) { |
| | | // åªæ"已确认"ç¶æçå·¥åæéè¦çº§èåæ¶ |
| | | workOrderService.cancelWorkOrder(mps.getWorkOrderId()); |
| | | log.info("[cancelMps] 级èåæ¶ç产工åï¼workOrderId={}", mps.getWorkOrderId()); |
| | | } else { |
| | | // å·¥åå·²æ¯è稿/已宿/å·²åæ¶ï¼æ é级èåæ¶ï¼ç´æ¥åæ¶ MPS |
| | | log.info("[cancelMps] ç产工å({}) ç¶æä¸º {}ï¼æ é级èåæ¶", |
| | | mps.getWorkOrderId(), workOrder != null ? workOrder.getStatus() : "null"); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | * 夿å个 MPS æ¯å¦å®æ |
| | | */ |
| | | private boolean isMpsFinished(MesProMpsDO mps) { |
| | | // 已忶ç MPS è§ä¸ºç»æï¼ä¸åé»å¡çäº§å®æå¤æï¼ä¸ checkCanCreateSalesNotice çå£å¾ä¿æä¸è´ï¼ |
| | | if (MesProMpsStatusEnum.CANCELED.getStatus().equals(mps.getStatus())) { |
| | | return true; |
| | | } |
| | | // 1. å·²ç产æ°é >= è®¡åæ°é |
| | | BigDecimal quantityProduced = ObjUtil.defaultIfNull(mps.getQuantityProduced(), BigDecimal.ZERO); |
| | | if (quantityProduced.compareTo(mps.getQuantity()) < 0) { |
| | |
| | | Long getReturnVendorCountByVendorId(Long vendorId); |
| | | |
| | | /** |
| | | * æ ¹æ®å
³èçéè´è®¢åï¼å¸¦å
¥ç©ææç»å°éè´§åè¡ |
| | | * |
| | | * @param id éè´§åç¼å· |
| | | * @return 带å
¥çç©æè¡æ° |
| | | */ |
| | | int importPurchaseOrderItems(Long id); |
| | | |
| | | /** |
| | | * æ ¡éªä¾åºåéè´§ååå¨ä¸ä¸ºèç¨¿ç¶æ |
| | | * |
| | | * @param id ç¼å· |
| | |
| | | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLineSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDetailDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; |
| | |
| | | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnVendorStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderItemRespDTO; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderRespDTO; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; |
| | |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| | |
| | | private SrmSupplierApi srmSupplierApi; |
| | | @Resource |
| | | private MesWmTransactionService wmTransactionService; |
| | | @Resource |
| | | private ErpPurchaseOrderApi purchaseOrderApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createReturnVendor(MesWmReturnVendorSaveReqVO createReqVO) { |
| | | // 1. æ ¡éªæ°æ® |
| | | validateReturnVendorSaveData(createReqVO); |
| | | // 1.1. è¥éè´è®¢åå·ä¸ºç©ºä½å
³èäºéè´è®¢åï¼åä» ERP éè´è®¢åè¡¥é½è®¢åå· |
| | | fillPurchaseOrderCode(createReqVO); |
| | | |
| | | // 2. æå
¥ä¸»è¡¨ |
| | | MesWmReturnVendorDO returnVendor = BeanUtils.toBean(createReqVO, MesWmReturnVendorDO.class); |
| | |
| | | public void updateReturnVendor(MesWmReturnVendorSaveReqVO updateReqVO) { |
| | | // 1. æ ¡éªæ°æ® |
| | | validateReturnVendorSaveData(updateReqVO); |
| | | // 1.1. è¥éè´è®¢åå·ä¸ºç©ºä½å
³èäºéè´è®¢åï¼åä» ERP éè´è®¢åè¡¥é½è®¢åå· |
| | | fillPurchaseOrderCode(updateReqVO); |
| | | |
| | | // 2. æ´æ°ä¸»è¡¨ |
| | | MesWmReturnVendorDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnVendorDO.class); |
| | | returnVendorMapper.updateById(updateObj); |
| | | } |
| | | |
| | | /** |
| | | * å½éè´è®¢åå·ä¸ºç©ºãä½å
³èäºéè´è®¢åæ¶ï¼ä» ERP éè´è®¢åè¡¥é½éè´è®¢åå· |
| | | */ |
| | | private void fillPurchaseOrderCode(MesWmReturnVendorSaveReqVO reqVO) { |
| | | if (reqVO == null || reqVO.getPurchaseOrderId() == null) { |
| | | return; |
| | | } |
| | | if (cn.hutool.core.util.StrUtil.isNotBlank(reqVO.getPurchaseOrderCode())) { |
| | | return; |
| | | } |
| | | ErpPurchaseOrderRespDTO purchaseOrder = |
| | | purchaseOrderApi.getPurchaseOrder(reqVO.getPurchaseOrderId()).getCheckedData(); |
| | | if (purchaseOrder != null) { |
| | | reqVO.setPurchaseOrderCode(purchaseOrder.getNo()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | return returnVendorMapper.selectCountByVendorId(vendorId); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int importPurchaseOrderItems(Long id) { |
| | | // 1. æ ¡éªéè´§ååå¨ä¸ä¸ºèç¨¿ç¶æ |
| | | MesWmReturnVendorDO returnVendor = validateReturnVendorExistsAndPrepare(id); |
| | | if (returnVendor.getPurchaseOrderId() == null) { |
| | | throw exception(WM_RETURN_VENDOR_PURCHASE_ORDER_REQUIRED); |
| | | } |
| | | |
| | | // 2. è·åéè´è®¢ååæç» |
| | | ErpPurchaseOrderRespDTO purchaseOrder = purchaseOrderApi.getPurchaseOrder(returnVendor.getPurchaseOrderId()).getCheckedData(); |
| | | if (purchaseOrder == null) { |
| | | throw exception(WM_PURCHASE_ORDER_NOT_EXISTS); |
| | | } |
| | | List<ErpPurchaseOrderItemRespDTO> items = purchaseOrderApi.getPurchaseOrderItemList(returnVendor.getPurchaseOrderId()).getCheckedData(); |
| | | if (CollUtil.isEmpty(items)) { |
| | | throw exception(WM_RETURN_VENDOR_PURCHASE_ORDER_NO_ITEM); |
| | | } |
| | | |
| | | // 3. å·²åå¨çè¡ç©æéåï¼æç©æå»éï¼é¿å
éå¤å¸¦å
¥ï¼ |
| | | Set<Long> existsItemIds = new HashSet<>(); |
| | | List<MesWmReturnVendorLineDO> existingLines = returnVendorLineService.getReturnVendorLineListByReturnId(id); |
| | | if (CollUtil.isNotEmpty(existingLines)) { |
| | | existsItemIds.addAll(convertList(existingLines, MesWmReturnVendorLineDO::getItemId)); |
| | | } |
| | | |
| | | // 4. éåéè´è®¢åæç»ï¼çæéè´§è¡ï¼å¯éæ°é = å·²å
¥åº - å·²éè´§ï¼ |
| | | int importedCount = 0; |
| | | for (ErpPurchaseOrderItemRespDTO item : items) { |
| | | if (item.getProductId() == null || existsItemIds.contains(item.getProductId())) { |
| | | continue; |
| | | } |
| | | BigDecimal inCount = item.getInCount() != null ? item.getInCount() : BigDecimal.ZERO; |
| | | BigDecimal returnCount = item.getReturnCount() != null ? item.getReturnCount() : BigDecimal.ZERO; |
| | | BigDecimal quantity = inCount.subtract(returnCount); |
| | | if (quantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | continue; |
| | | } |
| | | MesWmReturnVendorLineSaveReqVO lineReqVO = new MesWmReturnVendorLineSaveReqVO(); |
| | | lineReqVO.setReturnId(id); |
| | | lineReqVO.setItemId(item.getProductId()); |
| | | lineReqVO.setQuantity(quantity); |
| | | lineReqVO.setRemark(item.getRemark()); |
| | | returnVendorLineService.createReturnVendorLine(lineReqVO); |
| | | importedCount++; |
| | | } |
| | | return importedCount; |
| | | } |
| | | |
| | | } |
| | |
| | | @ToString(callSuper = true) |
| | | public class SrmSupplierCertificatePageReqVO extends PageParam { |
| | | |
| | | @Schema(description = "èµè´¨è¯ä¹¦åç§°", example = "è¥ä¸æ§ç
§") |
| | | private String certificateName; |
| | | |
| | | @Schema(description = "ä¾åºåID", example = "1") |
| | | private Long supplierId; |
| | | |
| | |
| | | |
| | | default PageResult<SrmSupplierCertificateDO> selectPage(SrmSupplierCertificatePageReqVO reqVO) { |
| | | return selectPage(reqVO, new LambdaQueryWrapperX<SrmSupplierCertificateDO>() |
| | | .likeIfPresent(SrmSupplierCertificateDO::getCertificateName, reqVO.getCertificateName()) |
| | | .eqIfPresent(SrmSupplierCertificateDO::getSupplierId, reqVO.getSupplierId()) |
| | | .eqIfPresent(SrmSupplierCertificateDO::getCertificateType, reqVO.getCertificateType()) |
| | | .orderByDesc(SrmSupplierCertificateDO::getId)); |
| | |
| | | ErrorCode SUPPLIER_CODE_EXISTS = new ErrorCode(1_040_100_001, "ä¾åºåç¼ç å·²åå¨"); |
| | | ErrorCode SUPPLIER_EXISTS_REFERENCE = new ErrorCode(1_040_100_002, "ä¾åºå被ä¸å¡å¼ç¨ï¼æ æ³å é¤"); |
| | | ErrorCode SUPPLIER_CONTACT_NOT_EXISTS = new ErrorCode(1_040_100_003, "ä¾åºåè系人ä¸åå¨"); |
| | | ErrorCode SUPPLIER_NOT_ENABLE = new ErrorCode(1_040_100_004, "ä¾åºåå·²åç¨ï¼æ æ³å䏿æ "); |
| | | |
| | | // ========== ä¾åºååå
¥ 1_040_200_000 ========== |
| | | ErrorCode APPLY_NOT_EXISTS = new ErrorCode(1_040_200_000, "åå
¥ç³è¯·ä¸åå¨"); |
| | |
| | | package cn.iocoder.yudao.module.srm.service.supplier; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | |
| | | @Override |
| | | public List<SrmSupplierDO> getSupplierAllList() { |
| | | return supplierMapper.selectList(new LambdaQueryWrapperX<SrmSupplierDO>() |
| | | // è¿æ»¤åç¨ä¾åºåï¼ä¿çæªè®¾ç½®ç¶æä¸å¯ç¨ç¶æçæ¡£æ¡ä¾åºåï¼ä»
ç¨äºæææ åºæ¯ï¼ |
| | | .and(w -> w.isNull(SrmSupplierDO::getStatus) |
| | | .or() |
| | | .ne(SrmSupplierDO::getStatus, CommonStatusEnum.DISABLE.getStatus())) |
| | | .orderByAsc(SrmSupplierDO::getId)); |
| | | } |
| | | |
| | |
| | | package cn.iocoder.yudao.module.srm.service.tender; |
| | | |
| | | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmSupplierQuoteSaveReqVO; |
| | | import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmTenderBidSaveReqVO; |
| | | import cn.iocoder.yudao.module.srm.dal.dataobject.SrmSupplierDO; |
| | | import cn.iocoder.yudao.module.srm.dal.dataobject.SrmSupplierQuoteDO; |
| | | import cn.iocoder.yudao.module.srm.dal.dataobject.SrmTenderBidDO; |
| | | import cn.iocoder.yudao.module.srm.dal.dataobject.SrmTenderProjectDO; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmSupplierApplyMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmSupplierMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmSupplierQuoteMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderBidMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderProjectMapper; |
| | |
| | | private SrmTenderProjectMapper tenderProjectMapper; |
| | | |
| | | @Resource |
| | | private SrmSupplierApplyMapper supplierApplyMapper; |
| | | private SrmSupplierMapper supplierMapper; |
| | | |
| | | // ========== ææ ç®¡ç ========== |
| | | |
| | |
| | | if (project.getEndTime() != null && LocalDateTime.now().isAfter(project.getEndTime())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_END_TIME_PASSED); |
| | | } |
| | | // æ ¡éªä¾åºåæ¯å¦å·²éè¿åå
¥å®¡æ¹ |
| | | if (!supplierApplyMapper.existsApprovedBySupplierId(createReqVO.getSupplierId())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_SUPPLIER_NOT_APPROVED); |
| | | // æ ¡éªææ ä¾åºååå¨ä¸æªåç¨ï¼åå
¥ç¶æä¸éå¶ææ ï¼ä¸æ çæéè´è®¢åæ¶èªå¨åå
¥ï¼ |
| | | SrmSupplierDO supplier = supplierMapper.selectById(createReqVO.getSupplierId()); |
| | | if (supplier == null) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.SUPPLIER_NOT_EXISTS); |
| | | } |
| | | if (CommonStatusEnum.isDisable(supplier.getStatus())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.SUPPLIER_NOT_ENABLE, supplier.getName()); |
| | | } |
| | | // æ ¡éªææ ç¼å·æ¯å¦éå¤ |
| | | if (tenderBidMapper.existsByBidNo(createReqVO.getBidNo())) { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.controller.admin.companyconfig; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.system.controller.admin.companyconfig.vo.SystemCompanyConfigRespVO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.companyconfig.vo.SystemCompanyConfigSaveReqVO; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.companyconfig.SystemCompanyConfigDO; |
| | | import cn.iocoder.yudao.module.system.service.companyconfig.SystemCompanyConfigService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.annotation.security.PermitAll; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | |
| | | @Tag(name = "管çåå° - å
¬å¸åçä¿¡æ¯") |
| | | @RestController |
| | | @RequestMapping("/system/company-config") |
| | | @Validated |
| | | public class SystemCompanyConfigController { |
| | | |
| | | @Resource |
| | | private SystemCompanyConfigService companyConfigService; |
| | | |
| | | /** |
| | | * è·å¾å
¬å¸åçä¿¡æ¯ |
| | | * |
| | | * å
ç»å½å
¬å¼æ¥å£ï¼ä¾å端ç»å½é¡µ / åºç¨å¯å¨æ¶è¯»åå
¬å¸åç§°ãlogoãç»å½é¡µæ é¢ã |
| | | */ |
| | | @GetMapping("/get") |
| | | @Operation(summary = "è·å¾å
¬å¸åçä¿¡æ¯ï¼å
ç»å½å
¬å¼ï¼") |
| | | @PermitAll |
| | | public CommonResult<SystemCompanyConfigRespVO> getCompanyConfig() { |
| | | SystemCompanyConfigDO config = companyConfigService.getCompanyConfig(); |
| | | return success(BeanUtils.toBean(config, SystemCompanyConfigRespVO.class)); |
| | | } |
| | | |
| | | /** |
| | | * ä¿åå
¬å¸åçä¿¡æ¯ |
| | | * |
| | | * åè¡ upsertï¼éç»å½ä¸æ¥æ system:company-config:update æéã |
| | | * æééè¿èåãå
¬å¸ä¿¡æ¯é
ç½® - ä¿®æ¹ãææï¼è§ sql/mysql/system_company_config_menu.sqlï¼ã |
| | | */ |
| | | @PostMapping("/save") |
| | | @Operation(summary = "ä¿åå
¬å¸åçä¿¡æ¯") |
| | | @PreAuthorize("@ss.hasPermission('system:company-config:update')") |
| | | public CommonResult<Long> saveCompanyConfig(@Valid @RequestBody SystemCompanyConfigSaveReqVO reqVO) { |
| | | return success(companyConfigService.saveCompanyConfig(reqVO)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.controller.admin.companyconfig.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Schema(description = "管çåå° - å
¬å¸åçä¿¡æ¯ Response VO") |
| | | @Data |
| | | public class SystemCompanyConfigRespVO { |
| | | |
| | | @Schema(description = "主é®", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "å
¬å¸åç§°", example = "å®å¤ä¹æ³åå·¥") |
| | | private String companyName; |
| | | |
| | | @Schema(description = "logo æ°¸ä¹
å
¬å¼é¾æ¥ï¼previewURLï¼", example = "http://domain/admin-api/system/storage-blob/preview/xxx?publicKey=xxx") |
| | | private String logoUrl; |
| | | |
| | | @Schema(description = "logo 对åºç blob è®°å½ ID", example = "86") |
| | | private Long logoBlobId; |
| | | |
| | | @Schema(description = "ç»å½é¡µæ é¢", example = "å¶é è¿è¥ç®¡çå¹³å°") |
| | | private String loginTitle; |
| | | |
| | | @Schema(description = "ç»å½é¡µæè¿°", example = "å·¥ç¨åã髿§è½ãè·¨ç»ä»¶åºçå端模ç") |
| | | private String loginDescription; |
| | | |
| | | @Schema(description = "å建æ¶é´", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private LocalDateTime createTime; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.controller.admin.companyconfig.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.Size; |
| | | import lombok.Data; |
| | | |
| | | @Schema(description = "管çåå° - å
¬å¸åçä¿¡æ¯ä¿å Request VO") |
| | | @Data |
| | | public class SystemCompanyConfigSaveReqVO { |
| | | |
| | | @Schema(description = "主é®ï¼åè¡é
ç½®ï¼å¯ä¸ä¼ ï¼", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "å
¬å¸åç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "å®å¤ä¹æ³åå·¥") |
| | | @NotBlank(message = "å
¬å¸åç§°ä¸è½ä¸ºç©º") |
| | | @Size(max = 128, message = "å
¬å¸åç§°ä¸è½è¶
è¿128个å符") |
| | | private String companyName; |
| | | |
| | | @Schema(description = "logo æ°¸ä¹
å
¬å¼é¾æ¥ï¼previewURLï¼", example = "http://domain/admin-api/system/storage-blob/preview/xxx?publicKey=xxx") |
| | | @Size(max = 512, message = "logo å°åä¸è½è¶
è¿512个å符") |
| | | private String logoUrl; |
| | | |
| | | @Schema(description = "logo 对åºç blob è®°å½ ID", example = "86") |
| | | private Long logoBlobId; |
| | | |
| | | @Schema(description = "ç»å½é¡µæ é¢", example = "å¶é è¿è¥ç®¡çå¹³å°") |
| | | @Size(max = 128, message = "ç»å½é¡µæ é¢ä¸è½è¶
è¿128个å符") |
| | | private String loginTitle; |
| | | |
| | | @Schema(description = "ç»å½é¡µæè¿°", example = "å·¥ç¨åã髿§è½ãè·¨ç»ä»¶åºçå端模ç") |
| | | @Size(max = 128, message = "ç»å½é¡µæè¿°ä¸è½è¶
è¿128个å符") |
| | | private String loginDescription; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.dal.dataobject.companyconfig; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * å
¬å¸åçä¿¡æ¯é
ç½® DO |
| | | * |
| | | * åè¡é
ç½®ï¼ä¿åå
¬å¸åç§°/logo/ç»å½é¡µæ é¢ï¼å端å¯å¨æ¶è¯»åå¹¶èå¨ç»å½é¡µãèåæ ãç½é¡µæ é¢ã |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @TableName("system_company_config") |
| | | @KeySequence("system_company_config_seq") // ç¨äº OracleãPostgreSQLãKingbaseãDB2ãH2 æ°æ®åºç主é®èªå¢ãå¦ææ¯ MySQL çæ°æ®åºï¼å¯ä¸åã |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class SystemCompanyConfigDO extends BaseDO { |
| | | |
| | | /** |
| | | * ä¸»é® |
| | | */ |
| | | private Long id; |
| | | /** |
| | | * å
¬å¸åç§° |
| | | */ |
| | | private String companyName; |
| | | /** |
| | | * logo æ°¸ä¹
å
¬å¼é¾æ¥ï¼public-upload è¿åç previewURLï¼ |
| | | */ |
| | | private String logoUrl; |
| | | /** |
| | | * logo 对åºç blob è®°å½ ID |
| | | */ |
| | | private Long logoBlobId; |
| | | /** |
| | | * ç»å½é¡µæ é¢ |
| | | */ |
| | | private String loginTitle; |
| | | /** |
| | | * ç»å½é¡µæè¿° |
| | | */ |
| | | private String loginDescription; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.dal.mysql.companyconfig; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.companyconfig.SystemCompanyConfigDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * å
¬å¸åçä¿¡æ¯é
ç½® Mapper |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @Mapper |
| | | public interface SystemCompanyConfigMapper extends BaseMapperX<SystemCompanyConfigDO> { |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.service.companyconfig; |
| | | |
| | | import cn.iocoder.yudao.module.system.controller.admin.companyconfig.vo.SystemCompanyConfigSaveReqVO; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.companyconfig.SystemCompanyConfigDO; |
| | | |
| | | /** |
| | | * å
¬å¸åçä¿¡æ¯é
ç½® Service æ¥å£ |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | public interface SystemCompanyConfigService { |
| | | |
| | | /** |
| | | * è·å¾å
¬å¸åçä¿¡æ¯ï¼åè¡é
ç½®ï¼ |
| | | * |
| | | * @return å
¬å¸åçä¿¡æ¯ï¼æªé
ç½®æ¶è¿å null |
| | | */ |
| | | SystemCompanyConfigDO getCompanyConfig(); |
| | | |
| | | /** |
| | | * ä¿åå
¬å¸åçä¿¡æ¯ï¼åè¡ upsertï¼ |
| | | * |
| | | * @param reqVO ä¿åè¯·æ± |
| | | * @return ä¸»é® |
| | | */ |
| | | Long saveCompanyConfig(SystemCompanyConfigSaveReqVO reqVO); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.service.companyconfig; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.system.controller.admin.companyconfig.vo.SystemCompanyConfigSaveReqVO; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.companyconfig.SystemCompanyConfigDO; |
| | | import cn.iocoder.yudao.module.system.dal.mysql.companyconfig.SystemCompanyConfigMapper; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å
¬å¸åçä¿¡æ¯é
ç½® Service å®ç°ç±» |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @Service |
| | | public class SystemCompanyConfigServiceImpl implements SystemCompanyConfigService { |
| | | |
| | | @Resource |
| | | private SystemCompanyConfigMapper companyConfigMapper; |
| | | |
| | | @Override |
| | | public SystemCompanyConfigDO getCompanyConfig() { |
| | | // åè¡é
ç½®ï¼æä¸»é®ååºåç¬¬ä¸æ¡ |
| | | List<SystemCompanyConfigDO> list = companyConfigMapper.selectList(new LambdaQueryWrapperX<SystemCompanyConfigDO>() |
| | | .orderByAsc(SystemCompanyConfigDO::getId) |
| | | .last("LIMIT 1")); |
| | | return CollUtil.getFirst(list); |
| | | } |
| | | |
| | | @Override |
| | | public Long saveCompanyConfig(SystemCompanyConfigSaveReqVO reqVO) { |
| | | SystemCompanyConfigDO config = getCompanyConfig(); |
| | | if (config == null) { |
| | | // 馿¬¡ä¿åï¼æå
¥ |
| | | SystemCompanyConfigDO insertObj = BeanUtils.toBean(reqVO, SystemCompanyConfigDO.class); |
| | | companyConfigMapper.insert(insertObj); |
| | | return insertObj.getId(); |
| | | } |
| | | // å·²åå¨ï¼æ´æ°åè¡ |
| | | SystemCompanyConfigDO updateObj = BeanUtils.toBean(reqVO, SystemCompanyConfigDO.class); |
| | | updateObj.setId(config.getId()); |
| | | companyConfigMapper.updateById(updateObj); |
| | | return config.getId(); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | server: |
| | | port: 48080 |
| | | |
| | | --- #################### æ°æ®åºç¸å
³é
ç½® #################### |
| | | spring: |
| | | autoconfigure: |
| | | # noinspection SpringBootApplicationYaml |
| | | exclude: |
| | | - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # é»è®¤ local ç¯å¢ï¼ä¸å¼å¯ Quartz çèªå¨é
ç½® |
| | | - org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # ç¦ç¨ AI 模åç Qdrantï¼æå¨å建 |
| | | - org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration # ç¦ç¨ AI 模åç Redisï¼æå¨å建 |
| | | - org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # ç¦ç¨ AI 模åç Milvusï¼æå¨å建 |
| | | - org.dromara.trans.config.TransServiceConfig # TODO èè¿ï¼easy-trans å
¼å®¹ Spring Boot 4 åç§»é¤ï¼TransServiceConfig å¼ç¨äºå·²ç§»é¤ç RestTemplateBuilderï¼ |
| | | # ç¦ç¨æªé
ç½® API Key çæ¨¡åèªå¨é
ç½®ï¼åªä¿çéä¹åé® Embedding çæå¨é
ç½®ï¼ |
| | | - org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration |
| | | - org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration |
| | | - org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration |
| | | - org.springframework.ai.model.openai.autoconfigure.OpenAiAudioSpeechAutoConfiguration |
| | | - org.springframework.ai.model.openai.autoconfigure.OpenAiAudioTranscriptionAutoConfiguration |
| | | - org.springframework.ai.model.openai.autoconfigure.OpenAiModerationAutoConfiguration |
| | | - org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration |
| | | - org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration |
| | | - org.springframework.ai.model.google.genai.autoconfigure.chat.GoogleGenAiChatAutoConfiguration |
| | | - org.springframework.ai.model.google.genai.autoconfigure.embedding.GoogleGenAiEmbeddingConnectionAutoConfiguration |
| | | - org.springframework.ai.model.google.genai.autoconfigure.embedding.GoogleGenAiTextEmbeddingAutoConfiguration |
| | | - org.springframework.ai.model.ollama.autoconfigure.OllamaApiAutoConfiguration |
| | | - org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration |
| | | - org.springframework.ai.model.ollama.autoconfigure.OllamaEmbeddingAutoConfiguration |
| | | - org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration |
| | | # æ°æ®æºé
置项 |
| | | datasource: |
| | | druid: # Druid ãçæ§ãç¸å
³çå
¨å±é
ç½® |
| | | web-stat-filter: |
| | | enabled: true |
| | | stat-view-servlet: |
| | | enabled: true |
| | | allow: # 设置ç½ååï¼ä¸å¡«åå
许ææè®¿é® |
| | | url-pattern: /druid/* |
| | | login-username: # æ§å¶å°ç®¡çç¨æ·ååå¯ç |
| | | login-password: |
| | | filter: |
| | | stat: |
| | | enabled: true |
| | | log-slow-sql: true # æ
¢ SQL è®°å½ |
| | | slow-sql-millis: 100 |
| | | merge-sql: true |
| | | wall: |
| | | config: |
| | | multi-statement-allow: true |
| | | dynamic: # 夿°æ®æºé
ç½® |
| | | druid: # Druid ãè¿æ¥æ± ãç¸å
³çå
¨å±é
ç½® |
| | | initial-size: 1 # åå§è¿æ¥æ° |
| | | min-idle: 1 # æå°è¿æ¥æ± æ°é |
| | | max-active: 20 # æå¤§è¿æ¥æ± æ°é |
| | | max-wait: 60000 # é
ç½®è·åè¿æ¥çå¾
è¶
æ¶çæ¶é´ï¼åä½ï¼æ¯«ç§ï¼1 åéï¼ |
| | | time-between-eviction-runs-millis: 60000 # é
ç½®é´éå¤ä¹
æè¿è¡ä¸æ¬¡æ£æµï¼æ£æµéè¦å
³éç空é²è¿æ¥ï¼åä½ï¼æ¯«ç§ï¼1 åéï¼ |
| | | min-evictable-idle-time-millis: 600000 # é
ç½®ä¸ä¸ªè¿æ¥å¨æ± 䏿å°çåçæ¶é´ï¼åä½ï¼æ¯«ç§ï¼10 åéï¼ |
| | | max-evictable-idle-time-millis: 1800000 # é
ç½®ä¸ä¸ªè¿æ¥å¨æ± 䏿大çåçæ¶é´ï¼åä½ï¼æ¯«ç§ï¼30 åéï¼ |
| | | validation-query: SELECT 1 FROM DUAL # é
ç½®æ£æµè¿æ¥æ¯å¦ææ |
| | | test-while-idle: true |
| | | test-on-borrow: false |
| | | test-on-return: false |
| | | pool-prepared-statements: true # æ¯å¦å¼å¯ PreparedStatement ç¼å |
| | | max-pool-prepared-statement-per-connection-size: 20 # æ¯ä¸ªè¿æ¥ç¼åç PreparedStatement æ°é |
| | | primary: master |
| | | datasource: |
| | | master: |
| | | url: jdbc:mysql://172.17.0.1:9002/mom-wtxc?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X è¿æ¥çç¤ºä¾ |
| | | # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X è¿æ¥çç¤ºä¾ |
| | | # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL è¿æ¥çç¤ºä¾ |
| | | # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle è¿æ¥çç¤ºä¾ |
| | | # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer è¿æ¥çç¤ºä¾ |
| | | # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM è¿æ¥çç¤ºä¾ |
| | | # url: jdbc:kingbase8://127.0.0.1:54321/test # 人大éä» KingbaseES è¿æ¥çç¤ºä¾ |
| | | # url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss è¿æ¥çç¤ºä¾ |
| | | # url: jdbc:postgresql://127.0.0.1:5866/ruoyi-vue-pro # çé« HighGo è¿æ¥çç¤ºä¾ |
| | | username: root |
| | | password: wtxc@123456.. |
| | | # username: sa # SQL Server è¿æ¥çç¤ºä¾ |
| | | # password: Yudao@2024 # SQL Server è¿æ¥çç¤ºä¾ |
| | | # username: SYSDBA # DM è¿æ¥çç¤ºä¾ |
| | | # password: SYSDBA001 # DM è¿æ¥çç¤ºä¾ |
| | | # username: root # OpenGauss è¿æ¥çç¤ºä¾ |
| | | # password: Yudao@2024 # OpenGauss è¿æ¥çç¤ºä¾ |
| | | # username: root # çé« HighGo è¿æ¥çç¤ºä¾ |
| | | # password: 123456 # çé« HighGo è¿æ¥çç¤ºä¾ |
| | | # tdengine: # IoT æ°æ®åºï¼éè¦ IoT ç©èç½åå¼å¯å¢ï¼ï¼ |
| | | # lazy: true # å¼å¯æå è½½ï¼ä¿è¯å¯å¨é度 |
| | | # url: jdbc:TAOS-WS://127.0.0.1:6041/ruoyi_vue_pro?varcharAsString=true&enableAutoReconnect=true # åè§ï¼https://t.zsxq.com/qaX9cï¼å¼å¯ TDengine WebSocket èªå¨éè¿ |
| | | # driver-class-name: com.taosdata.jdbc.ws.WebSocketDriver |
| | | # username: root |
| | | # password: taosdata |
| | | # druid: |
| | | # validation-query: SELECT SERVER_STATUS() # TDengine æ°æ®æºçæææ§æ£æ¥ SQL |
| | | |
| | | # Redis é
ç½®ãRedisson é»è®¤çé
置足å¤ä½¿ç¨ï¼ä¸è¬ä¸éè¦è¿è¡è°ä¼ |
| | | data: |
| | | redis: |
| | | host: 172.17.0.1 # å°å |
| | | port: 6379 # ç«¯å£ |
| | | database: 1 # æ°æ®åºç´¢å¼ |
| | | # password: dev # å¯ç ï¼å»ºè®®ç产ç¯å¢å¼å¯ |
| | | |
| | | --- #################### 宿¶ä»»å¡ç¸å
³é
ç½® #################### |
| | | |
| | | # Quartz é
置项ï¼å¯¹åº QuartzProperties é
置类 |
| | | spring: |
| | | quartz: |
| | | auto-startup: true # æ¬å°å¼åç¯å¢ï¼å°½éä¸è¦å¼å¯ Job |
| | | scheduler-name: schedulerName # Scheduler ååãé»è®¤ä¸º schedulerName |
| | | job-store-type: jdbc # Job åå¨å¨ç±»åãé»è®¤ä¸º memory 表示å
åï¼å¯é jdbc ä½¿ç¨æ°æ®åºã |
| | | wait-for-jobs-to-complete-on-shutdown: true # åºç¨å
³éæ¶ï¼æ¯å¦çå¾
宿¶ä»»å¡æ§è¡å®æãé»è®¤ä¸º false ï¼å»ºè®®è®¾ç½®ä¸º true |
| | | properties: # æ·»å Quartz Scheduler éå 屿§ï¼æ´å¤å¯ä»¥ç http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html ææ¡£ |
| | | org: |
| | | quartz: |
| | | # Scheduler ç¸å
³é
ç½® |
| | | scheduler: |
| | | instanceName: schedulerName |
| | | instanceId: AUTO # èªå¨çæ instance ID |
| | | # JobStore ç¸å
³é
ç½® |
| | | jobStore: |
| | | # JobStore å®ç°ç±»ãå¯è§å客ï¼https://blog.csdn.net/weixin_42458219/article/details/122247162 |
| | | class: org.springframework.scheduling.quartz.LocalDataSourceJobStore |
| | | isClustered: true # æ¯éç¾¤æ¨¡å¼ |
| | | clusterCheckinInterval: 15000 # éç¾¤æ£æ¥é¢çï¼åä½ï¼æ¯«ç§ãé»è®¤ä¸º 15000ï¼å³ 15 ç§ |
| | | misfireThreshold: 60000 # misfire éå¼ï¼åä½ï¼æ¯«ç§ã |
| | | # çº¿ç¨æ± ç¸å
³é
ç½® |
| | | threadPool: |
| | | threadCount: 25 # çº¿ç¨æ± 大å°ãé»è®¤ä¸º 10 ã |
| | | threadPriority: 5 # 线ç¨ä¼å
级 |
| | | class: org.quartz.simpl.SimpleThreadPool # çº¿ç¨æ± ç±»å |
| | | jdbc: # ä½¿ç¨ JDBC ç JobStore çæ¶åï¼JDBC çé
ç½® |
| | | initialize-schema: NEVER # æ¯å¦èªå¨ä½¿ç¨ SQL åå§å Quartz è¡¨ç»æãè¿é设置æ never ï¼æä»¬æå¨åå»ºè¡¨ç»æã |
| | | |
| | | --- #################### æå¡ä¿éç¸å
³é
ç½® #################### |
| | | |
| | | # Lock4j é
置项 |
| | | lock4j: |
| | | acquire-timeout: 3000 # è·ååå¸å¼éè¶
æ¶æ¶é´ï¼é»è®¤ä¸º 3000 æ¯«ç§ |
| | | expire: 30000 # åå¸å¼éçè¶
æ¶æ¶é´ï¼é»è®¤ä¸º 30000 æ¯«ç§ |
| | | |
| | | --- #################### çæ§ç¸å
³é
ç½® #################### |
| | | |
| | | # Actuator çæ§ç«¯ç¹çé
置项 |
| | | management: |
| | | endpoints: |
| | | web: |
| | | base-path: /actuator # Actuator æä¾ç API æ¥å£çæ ¹ç®å½ãé»è®¤ä¸º /actuator |
| | | exposure: |
| | | include: '*' # éè¦å¼æ¾ç端ç¹ãé»è®¤å¼åªæå¼ health å info 两个端ç¹ãéè¿è®¾ç½® * ï¼å¯ä»¥å¼æ¾ææç«¯ç¹ã |
| | | |
| | | # Spring Boot Admin é
置项 |
| | | spring: |
| | | boot: |
| | | admin: |
| | | # Spring Boot Admin Client 客æ·ç«¯çç¸å
³é
ç½® |
| | | client: |
| | | url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server å°å |
| | | instance: |
| | | service-host-type: IP # 注åå®ä¾æ¶ï¼ä¼å
ä½¿ç¨ IP [IP, HOST_NAME, CANONICAL_HOST_NAME] |
| | | username: admin |
| | | password: admin |
| | | # Spring Boot Admin Server æå¡ç«¯çç¸å
³é
ç½® |
| | | context-path: /admin # é
ç½® Spring |
| | | # å
许åµå
¥ iframe çååï¼æ¯æéé
符ï¼ï¼å®é
é¨ç½²æ¶ï¼å¯ä»¥æ¹ä¸º "'self' [ä½ çå
¬ç½åå]" |
| | | frame-ancestors: "'self' localhost localhost:48080 127.0.0.1 127.0.0.1:48080" |
| | | |
| | | # æ¥å¿æä»¶é
ç½® |
| | | logging: |
| | | file: |
| | | name: logs/${spring.application.name}.log # æ¥å¿æä»¶åï¼ç¸å¯¹äºé¡¹ç®æ ¹ç®å½ |
| | | level: |
| | | # é
ç½®èªå·±åç MyBatis Mapper æå°æ¥å¿ |
| | | cn.iocoder.yudao.module.bpm.dal.mysql: debug |
| | | cn.iocoder.yudao.module.infra.dal.mysql: debug |
| | | cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # é
ç½® ApiErrorLogMapper çæ¥å¿çº§å«ä¸º infoï¼é¿å
å GlobalExceptionHandler éå¤æå° |
| | | cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # é
ç½® JobLogMapper çæ¥å¿çº§å«ä¸º info |
| | | cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # é
ç½® FileConfigMapper çæ¥å¿çº§å«ä¸º info |
| | | cn.iocoder.yudao.module.system.dal.mysql: debug |
| | | cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # é
ç½® SmsChannelMapper çæ¥å¿çº§å«ä¸º info |
| | | cn.iocoder.yudao.module.member.dal.mysql: debug |
| | | cn.iocoder.yudao.module.crm.dal.mysql: debug |
| | | cn.iocoder.yudao.module.erp.dal.mysql: debug |
| | | cn.iocoder.yudao.module.mes.dal.mysql: debug |
| | | cn.iocoder.yudao.module.ai.dal.mysql: debug |
| | | cn.iocoder.yudao.module.im.dal.mysql: debug |
| | | org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO èè¿ï¼å
ç¦ç¨ï¼Spring Boot 3.X åå¨é¨åé误ç WARN æç¤º |
| | | |
| | | debug: false |
| | | |
| | | yudao: |
| | | ai: |
| | | vector-store: |
| | | type: milvus # åéåºç±»åï¼milvus |
| | | milvus: |
| | | initialize-schema: true |
| | | database-name: test |
| | | collection-name: knowledge_segment_wtxc |
| | | host: 36.213.90.123 |
| | | port: 19530 |
| | | |
| | | --- #################### è¶
级管çåç¸å
³é
ç½® #################### |
| | | |
| | | # è¶
级管çåé
置项ï¼è®¾ç½®å½åé¡¹ç®ææèªå®ä¹çé
ç½® |
| | | yudao: |
| | | captcha: |
| | | enable: false # æ¬å°ç¯å¢ï¼ææ¶å
³éå¾çéªè¯ç ï¼æ¹ä¾¿ç»å½çæ¥å£çæµè¯ï¼ |
| | | security: |
| | | mock-enable: true |
| | | access-log: # è®¿é®æ¥å¿çé
置项 |
| | | enable: false |
| | | demo: false # å
³éæ¼ç¤ºæ¨¡å¼ |
| | | storage: # æä»¶ä¸ä¼ é
ç½® |
| | | path: /data/javaWork/mom/file # æä»¶å卿 ¹ç®å½ |
| | | url-prefix: /admin-api/system/storage-blob # URLè·¯å¾åç¼ |
| | | domain: http://42.63.71.140:9001 # åååç¼ï¼æå®é
ååé
ç½®ï¼ï¼å端é
置好åä¸å¤ªå¯¹ç°å¨æ¯ç´è¿åç«¯ï¼ææè¦åç«¯ç«¯å£ |
| | | expired: 120 # tokenè¿ææ¶é´ï¼åéï¼ |
| | | use-limit: 10 # tokenä½¿ç¨æ¬¡æ°ä¸é |
| | | jwt-secret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG # JWTå¯é¥ |
| | | compress: true # æ¯å¦å缩å¾ç |
| | | need-compress-size: 10MB # 触åå缩çæä»¶å¤§å°éå¼ |
| | | compress-quality: 0.5 # å缩质é(0.0-1.0) |