1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
package com.ruoyi.device.service.impl;
 
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.ruoyi.common.core.domain.entity.User;
import com.ruoyi.common.utils.QueryWrappers;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.device.dto.DeviceMaintenanceDto;
import com.ruoyi.device.mapper.DeviceMaintenanceMapper;
import com.ruoyi.device.pojo.Device;
import com.ruoyi.device.pojo.DeviceMaintenance;
import com.ruoyi.device.pojo.DeviceMaintenancePlanDetails;
import com.ruoyi.device.service.DeviceMaintenancePlanService;
import com.ruoyi.device.service.DeviceMaintenanceService;
import com.ruoyi.device.service.DeviceService;
import com.ruoyi.framework.exception.ErrorException;
import com.ruoyi.inspect.util.HackLoopTableRenderPolicy;
import com.ruoyi.inspect.util.UserUtils;
import com.ruoyi.system.mapper.UserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
/**
 * 设备维护保养
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DeviceMaintenanceImpl extends ServiceImpl<DeviceMaintenanceMapper, DeviceMaintenance> implements DeviceMaintenanceService {
    @Resource
    private DeviceService deviceService;
    @Resource
    private DeviceMaintenancePlanService deviceMaintenancePlanService;
    @Resource
    private UserMapper userMapper;
 
    /**
     * 设备维护分页查询
     * @return
     */
    @Override
    public IPage<DeviceMaintenanceDto> selectDeviceMaintenancePage(Page page, DeviceMaintenanceDto deviceMaintenance) {
        if (deviceMaintenance.getDeviceId() == null) {
            return new Page();
        }
        return baseMapper.selectDeviceMaintenancePage(page, QueryWrappers.queryWrappers(deviceMaintenance));
    }
 
    /**
     * 保存保养记录(关联保养计划明细,保存后进入待审核,不滚动设备档案日期)
     */
    @Override
    public boolean saveDeviceMaintenance(DeviceMaintenance deviceMaintenance) {
        if (deviceMaintenance == null) {
            throw new ErrorException("缺少保养记录");
        }
        if (deviceMaintenance.getDeviceId() == null) {
            throw new ErrorException("缺少设备id");
        }
        if (deviceMaintenance.getMaintenanceDate() == null) {
            throw new ErrorException("请选择保养日期");
        }
        if (deviceMaintenance.getMaintenanceUserId() == null) {
            throw new ErrorException("请选择维护人");
        }
        DeviceMaintenance exist = deviceMaintenance.getId() == null ? null : baseMapper.selectById(deviceMaintenance.getId());
        if (exist != null) {
            if (exist.getMaintenancePlanDetailId() == null) {
                throw new ErrorException("历史保养记录不允许修改");
            }
            if (exist.getReviewStatus() != null) {
                throw new ErrorException("已审核的保养记录不允许修改");
            }
            // 记录归属由库里的关联决定,避免改到别的设备或计划
            deviceMaintenance.setDeviceId(exist.getDeviceId());
            deviceMaintenance.setMaintenancePlanDetailId(exist.getMaintenancePlanDetailId());
            deviceMaintenance.setReviewStatus(null);
        } else {
            DeviceMaintenancePlanDetails detail = deviceMaintenancePlanService.resolveMaintenancePlanDetail(
                    deviceMaintenance.getDeviceId(), deviceMaintenance.getMaintenancePlanDetailId(), deviceMaintenance.getMaintenanceDate());
            if (!deviceMaintenance.getDeviceId().equals(detail.getDeviceId())) {
                throw new ErrorException("保养计划明细与设备不匹配");
            }
            DeviceMaintenance other = baseMapper.selectOne(Wrappers.<DeviceMaintenance>lambdaQuery()
                    .eq(DeviceMaintenance::getMaintenancePlanDetailId, detail.getMaintenancePlanDetailId())
                    .last("limit 1"));
            if (other != null) {
                throw new ErrorException("该计划已存在保养记录");
            }
            deviceMaintenance.setMaintenancePlanDetailId(detail.getMaintenancePlanDetailId());
            deviceMaintenance.setReviewStatus(null);
            deviceMaintenance.setReviewUserId(null);
            deviceMaintenance.setReviewUserName(null);
            deviceMaintenance.setReviewRemark(null);
            deviceMaintenance.setReviewTime(null);
        }
        User user = userMapper.selectById(deviceMaintenance.getMaintenanceUserId());
        deviceMaintenance.setMaintenanceUserName(user == null ? null : user.getName());
        return saveOrUpdate(deviceMaintenance);
    }
 
    /**
     * 审核保养记录;审核通过后按审核通过当天滚动设备档案的最近/下次保养日期(与核查计划一致)
     */
    @Override
    public boolean reviewDeviceMaintenance(DeviceMaintenanceDto deviceMaintenanceDto) {
        DeviceMaintenance record = findMaintenanceRecord(deviceMaintenanceDto);
        if (record == null) {
            throw new ErrorException("该计划暂无保养记录,请先填写保养记录");
        }
        if (record.getMaintenancePlanDetailId() == null) {
            throw new ErrorException("历史保养记录无需审核");
        }
        if (deviceMaintenanceDto.getReviewStatus() == null) {
            throw new ErrorException("请选择审核结果");
        }
        if (record.getReviewStatus() != null && record.getReviewStatus() == 1) {
            throw new ErrorException("该保养记录已审核通过");
        }
        if (record.getMaintenanceUserId() == null && StringUtils.isBlank(record.getMaintenanceUserName())) {
            throw new ErrorException("请先在编辑中填写维护人");
        }
        Integer reviewerId = SecurityUtils.getUserId().intValue();
        User reviewer = userMapper.selectById(reviewerId);
        boolean updated = this.update(Wrappers.<DeviceMaintenance>lambdaUpdate()
                .eq(DeviceMaintenance::getId, record.getId())
                .set(DeviceMaintenance::getReviewStatus, deviceMaintenanceDto.getReviewStatus())
                .set(DeviceMaintenance::getReviewUserId, reviewerId)
                .set(DeviceMaintenance::getReviewUserName, reviewer == null ? null : reviewer.getName())
                .set(DeviceMaintenance::getReviewRemark, deviceMaintenanceDto.getReviewRemark())
                .set(DeviceMaintenance::getReviewTime, LocalDateTime.now()));
        // 审核通过后,按审核通过当天回写档案的最近保养日期并推算下一轮(与核查计划一致)
        if (updated && deviceMaintenanceDto.getReviewStatus() == 1) {
            LocalDate reviewDate = LocalDate.now();
            // 审核完成年份即归类年份:提前完成的明细从原计划年份挪到审核年份
            deviceMaintenancePlanService.reclassifyMaintenanceDetailByReviewDate(record.getMaintenancePlanDetailId(), reviewDate);
            deviceMaintenancePlanService.updateDeviceMaintenanceDate(record.getDeviceId(), reviewDate);
        }
        return updated;
    }
 
    /**
     * 删除保养记录;审核通过和历史记录不允许删除
     */
    @Override
    public boolean deleteDeviceMaintenance(Integer id) {
        DeviceMaintenance record = id == null ? null : baseMapper.selectById(id);
        if (record == null) {
            return false;
        }
        if (record.getMaintenancePlanDetailId() == null) {
            throw new ErrorException("历史保养记录为留档内容,不允许删除");
        }
        if (record.getReviewStatus() != null && record.getReviewStatus() == 1) {
            throw new ErrorException("审核通过的保养记录为历史记录,不允许删除");
        }
        return removeById(id);
    }
 
    /**
     * 按记录id或计划明细id定位保养记录
     */
    private DeviceMaintenance findMaintenanceRecord(DeviceMaintenanceDto dto) {
        if (dto == null) {
            return null;
        }
        if (dto.getId() != null) {
            return baseMapper.selectById(dto.getId());
        }
        if (dto.getMaintenancePlanDetailId() != null) {
            return baseMapper.selectOne(Wrappers.<DeviceMaintenance>lambdaQuery()
                    .eq(DeviceMaintenance::getMaintenancePlanDetailId, dto.getMaintenancePlanDetailId())
                    .last("limit 1"));
        }
        return null;
    }
 
    /**
     * 导出仪器设备维护保养记录(只读台账,数据来自保养计划生成的保养记录)
     * @param deviceId
     * @param response
     */
    @Override
    public void exportDeviceMaintenance(Integer deviceId, HttpServletResponse response) {
        Device device = deviceId == null ? null : deviceService.getById(deviceId);
        if (device == null) {
            throw new ErrorException("设备不存在");
        }
        // 台账按维护日期正序排列
        List<DeviceMaintenance> records = baseMapper.selectList(Wrappers.<DeviceMaintenance>lambdaQuery()
                .eq(DeviceMaintenance::getDeviceId, deviceId)
                .orderByAsc(DeviceMaintenance::getMaintenanceDate)
                .orderByAsc(DeviceMaintenance::getId));
        List<DeviceMaintenanceDto> deviceMaintenances = new ArrayList<>();
        int index = 1;
        for (DeviceMaintenance record : records) {
            DeviceMaintenanceDto dto = new DeviceMaintenanceDto();
            BeanUtils.copyProperties(record, dto);
            dto.setIndex(index++);
            // 维护人列展示签名图片,未配置签名时用透明图片兜底
            dto.setMaintenanceUserUrlRender(UserUtils.getFinalUserSignatureOrTransparent(record.getMaintenanceUserId()));
            deviceMaintenances.add(dto);
        }
 
        // 获取路径
        InputStream inputStream = this.getClass().getResourceAsStream("/static/word/device-maintenance.docx");
        Configure configure = Configure.builder()
                .bind("deviceMaintenances", new HackLoopTableRenderPolicy())
                .build();
        XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render(
                new HashMap<String, Object>() {{
                    put("deviceName", device.getDeviceName());
                    put("specificationModel", device.getSpecificationModel());
                    put("managementNumber", device.getManagementNumber());
                    put("cycleNote", buildCycleNote(device.getMaintenanceCycle()));
                    put("deviceMaintenances", deviceMaintenances);
                }});
 
        try {
            response.setContentType("application/msword");
            String fileName = URLEncoder.encode(
                    "仪器设备维护保养记录", "UTF-8");
            response.setHeader("Content-disposition",
                    "attachment;filename=" + fileName + ".docx");
            OutputStream os = response.getOutputStream();
            template.write(os);
            os.flush();
            os.close();
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("导出失败");
        }
 
    }
 
    /**
     * 表格底部的维护保养频率说明,按档案里的保养周期(月)生成
     */
    private String buildCycleNote(String maintenanceCycle) {
        if (StringUtils.isBlank(maintenanceCycle)) {
            return "";
        }
        int months;
        try {
            months = Integer.parseInt(maintenanceCycle.trim());
        } catch (NumberFormatException e) {
            return "";
        }
        if (months <= 0) {
            return "";
        }
        if (months == 1) {
            return "维护保养每月 1 次";
        }
        if (months == 3) {
            return "维护保养每季度 1 次";
        }
        if (months == 6) {
            return "维护保养每半年 1 次";
        }
        if (months == 12) {
            return "维护保养每年 1 次";
        }
        if (months % 12 == 0) {
            return "维护保养每 " + months / 12 + " 年 1 次";
        }
        return "维护保养每 " + months + " 个月 1 次";
    }
}