diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/PdfBoxQrCodeGenerator.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/PdfBoxQrCodeGenerator.java index 30394376..c62a81e1 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/PdfBoxQrCodeGenerator.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/PdfBoxQrCodeGenerator.java @@ -11,12 +11,13 @@ import com.itextpdf.text.Image; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; +import org.dromara.system.domain.vo.SysOssVo; import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.*; +import java.net.FileNameMap; +import java.net.URLConnection; +import java.util.concurrent.CompletableFuture; /** * @author lilemy @@ -121,22 +122,145 @@ public class PdfBoxQrCodeGenerator { * @param y 坐标 * @return 插入二维码后的PDF文件流 */ - public static ByteArrayOutputStream addQRCodeToPDF(String srcPdf, byte[] qrCodeBytes, int pageNum, float x, float y) throws IOException, DocumentException { +// public static ByteArrayOutputStream addQRCodeToPDF(String srcPdf, byte[] qrCodeBytes, int pageNum, float x, float y) throws IOException, DocumentException { +// +// PdfReader reader = new PdfReader(srcPdf); +// ByteArrayOutputStream pdfOut = new ByteArrayOutputStream(); +// PdfStamper stamper = new PdfStamper(reader, pdfOut); +// +// PdfContentByte content = stamper.getOverContent(pageNum); +// Image image = Image.getInstance(qrCodeBytes); +// image.setAbsolutePosition(x, y); // 坐标:左下角为原点 +// image.scaleAbsolute(100, 100); // 设置二维码大小 +// +// content.addImage(image); +// stamper.close(); +// reader.close(); +// +// return pdfOut; +// } + /** + * 在PDF每一页的指定位置添加二维码并返回数据流(根据页面方向自动调整位置) + * + * @param srcPdf 原PDF文件路径(可以是本地路径或网络地址) + * @param qrCodeBytes 二维码图片字节数组 + * @param x X坐标(默认位置) + * @param y Y坐标(默认位置) + * @return 插入二维码后的PDF文件流 + */ + public static ByteArrayOutputStream addQRCodeToPDFOnAllPages(String srcPdf, byte[] qrCodeBytes, float x, float y) + throws IOException, DocumentException { - PdfReader reader = new PdfReader(srcPdf); + PdfReader reader = null; + PdfStamper stamper = null; ByteArrayOutputStream pdfOut = new ByteArrayOutputStream(); - PdfStamper stamper = new PdfStamper(reader, pdfOut); - PdfContentByte content = stamper.getOverContent(pageNum); - Image image = Image.getInstance(qrCodeBytes); - image.setAbsolutePosition(x, y); // 坐标:左下角为原点 - image.scaleAbsolute(100, 100); // 设置二维码大小 + try { + // 判断是网络地址还是本地文件路径 + if (srcPdf.startsWith("http://") || srcPdf.startsWith("https://")) { + // 网络地址:从URL读取PDF + java.net.URL url = new java.net.URL(srcPdf); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + connection.setConnectTimeout(10000); // 连接超时10秒 + connection.setReadTimeout(30000); // 读取超时30秒 + connection.setRequestMethod("GET"); - content.addImage(image); - stamper.close(); - reader.close(); + int responseCode = connection.getResponseCode(); + if (responseCode != java.net.HttpURLConnection.HTTP_OK) { + throw new IOException("无法从URL获取PDF文件,HTTP响应码: " + responseCode + ", URL: " + srcPdf); + } + + java.io.InputStream inputStream = connection.getInputStream(); + reader = new PdfReader(inputStream); + } else { + // 本地文件路径:检查文件是否存在 + File srcFile = new File(srcPdf); + if (!srcFile.exists()) { + throw new IOException("源PDF文件不存在: " + srcPdf); + } + reader = new PdfReader(srcPdf); + } + + stamper = new PdfStamper(reader, pdfOut); + + int numberOfPages = reader.getNumberOfPages(); + + // 遍历每一页并添加二维码 + for (int pageNum = 1; pageNum <= numberOfPages; pageNum++) { + // 获取页面尺寸 + com.itextpdf.text.Rectangle pageSize = reader.getPageSize(pageNum); + float pageWidth = pageSize.getWidth(); + float pageHeight = pageSize.getHeight(); + + // 根据页面方向确定二维码位置 + float qrX, qrY; + + float newWidth, newHeight; + + // 判断页面方向:宽度大于高度为横版,否则为竖版 + if (pageWidth > pageHeight) { + // 横版页面:二维码放在右下角 + qrX = (pageWidth - 90); // 距离右边90点 + qrY = 24; // 距离底部24点 + newWidth = 67; + newHeight = 79; + } else { + // 竖版页面:二维码放在左上角 + qrX = 226; // 距离左边226点 + qrY = pageHeight - 185; // 距离顶部185点 + newWidth = 69; + newHeight = 80; + } + + PdfContentByte content = stamper.getOverContent(pageNum); + Image image = Image.getInstance(qrCodeBytes); + image.setAbsolutePosition(qrX, qrY); // 坐标:左下角为原点 + image.scaleAbsolute(newWidth, newHeight); // 设置二维码大小 + content.addImage(image); + } + + } finally { + if (stamper != null) { + try { + stamper.close(); + } catch (Exception e) { + // 忽略关闭异常 + } + } + if (reader != null) { + try { + reader.close(); + } catch (Exception e) { + // 忽略关闭异常 + } + } + } return pdfOut; } + + + +// public static void main(String[] args) { +// String path = "C:\\Users\\YuanJie\\Desktop\\test.pdf"; +// String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf"; +// +// String params = "ID:[" + 11111 + "] finish"; +// byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(params); +// +// try { +// System.out.println("二维码字节大小: " + bytes.length + " 字节"); +// +// // 在每一页添加二维码 +// PdfBoxQrCodeGenerator.addQRCodeToPDFOnAllPages(path, outputPath, bytes, 450, 700); +// +// System.out.println("PDF文件已成功生成到: " + outputPath); +// System.out.println("生成的PDF大小: " + new File(outputPath).length() + " 字节"); +// +// } catch (Exception e) { +// e.printStackTrace(); +// System.out.println("图纸管理 => 审核结束,向文件添加二维码失败, 错误"); +// } +// } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/impl/DesDrawingServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/impl/DesDrawingServiceImpl.java index cbae353d..427a9e62 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/impl/DesDrawingServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/impl/DesDrawingServiceImpl.java @@ -384,7 +384,7 @@ public class DesDrawingServiceImpl extends ServiceImpl outMonthlyConstructionVos = new ArrayList<>(); @@ -117,12 +120,12 @@ public class OutTableController extends BaseController { vo.setProjectName(busProjectVo.getProjectName()); //1.总产值的计算 2.预计累计产值(截止当前月) 3.月预计产值 - List subProjects = projectService.lambdaQuery().eq(BusProject::getPId, busProjectVo.getId()).list(); - List subProjectIds = subProjects.stream().map(BusProject::getId).toList(); +// List subProjects = projectService.lambdaQuery().eq(BusProject::getPId, busProjectVo.getId()).list(); +// List subProjectIds = subProjects.stream().map(BusProject::getId).toList(); //所有分项工程 - List collect = pgsProgressCategories.stream() - .filter(category -> subProjectIds.contains(category.getProjectId())).toList(); +// List collect = pgsProgressCategories.stream() +// .filter(category -> subProjectIds.contains(category.getProjectId())).toList(); BigDecimal totalValue = BigDecimal.ZERO; BigDecimal estimatedTotalValue = BigDecimal.ZERO; @@ -132,13 +135,10 @@ public class OutTableController extends BaseController { for (OutMonthPlanAudit planAudit : planAudits) { totalValue = totalValue.add(planAudit.getConstructionValue()); YearMonth planMonth = YearMonth.parse(planAudit.getPlanMonth(), formatter); - // 比较大小 - if (planMonth.isBefore(yearMonth)) { + if(!planMonth.isAfter(yearMonth)){ estimatedTotalValue=estimatedTotalValue.add(planAudit.getConstructionValue()); - } else if (planMonth.isAfter(yearMonth)) { - - } else { - estimatedTotalValue = estimatedTotalValue.add(planAudit.getConstructionValue()); + } + if(planMonth.equals(paramMonth)){ monthlyEstimatedValue = planAudit.getConstructionValue(); } } @@ -388,28 +388,28 @@ public class OutTableController extends BaseController { vo.setProjectId(projectVo.getId()); - List list = monthPlanService.lambdaQuery().eq(OutMonthPlan::getProjectId, projectVo.getId()) + List list = monthPlanService.lambdaQuery() + .eq(OutMonthPlan::getProjectId, projectVo.getId()) + .eq(OutMonthPlan::getValueType, bo.getValueType()) .list(); // 计算累计完成值 - BigDecimal totalValue = list.stream() - .map(OutMonthPlan::getCompleteValue) + BigDecimal totalValue = list.stream() + .map(OutMonthPlan::getPlanValue) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); vo.setTotalValue(totalValue); OutMonthPlan matchedPlan = list.stream() - .filter(plan -> Objects.equals(plan.getValueType(), bo.getValueType()) - && Objects.equals(plan.getPlanMonth(), bo.getMonth())) + .filter(plan -> Objects.equals(plan.getPlanMonth(), bo.getMonth())) .findFirst() .orElse(null); - List matchedPlans = list.stream() - .filter(plan -> Objects.equals(plan.getValueType(), bo.getValueType()) - && plan.getPlanMonth() != null - && bo.getMonth() != null - && plan.getPlanMonth().compareTo(bo.getMonth()) <= 0) - .toList(); +// List matchedPlans = list.stream() +// .filter(plan -> plan.getPlanMonth() != null +// && bo.getMonth() != null +// && plan.getPlanMonth().compareTo(bo.getMonth()) <= 0) +// .toList(); vo.setMonthEstimatedValue(matchedPlan == null? BigDecimal.ZERO :matchedPlan.getPlanValue()); @@ -417,7 +417,7 @@ public class OutTableController extends BaseController { vo.setMonthCompletionValue(matchedPlan == null? BigDecimal.ZERO :matchedPlan.getCompleteValue()); // 计算累计完成值 - BigDecimal accumulatedCompleteValue = matchedPlans.stream() + BigDecimal accumulatedCompleteValue = list.stream() .map(OutMonthPlan::getCompleteValue) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/out/domain/bo/OutMonthPlanBo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/out/domain/bo/OutMonthPlanBo.java index c37c744a..d53443dc 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/out/domain/bo/OutMonthPlanBo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/out/domain/bo/OutMonthPlanBo.java @@ -71,5 +71,10 @@ public class OutMonthPlanBo extends BaseEntity { */ private String completeAuditStatus; + /** + * 是否设计 + */ + private Boolean isDesign; + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/out/service/impl/OutMonthPlanServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/out/service/impl/OutMonthPlanServiceImpl.java index 65aa454b..32a456b1 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/out/service/impl/OutMonthPlanServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/out/service/impl/OutMonthPlanServiceImpl.java @@ -35,10 +35,7 @@ import org.dromara.out.service.IOutMonthPlanService; import java.math.BigDecimal; import java.time.LocalDate; import java.time.temporal.TemporalAdjusters; -import java.util.List; -import java.util.Map; -import java.util.Collection; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; /** @@ -142,6 +139,17 @@ public class OutMonthPlanServiceImpl extends ServiceImpl 0; } @@ -173,6 +181,17 @@ public class OutMonthPlanServiceImpl extends ServiceImpl outMonthPlans = baseMapper.selectList(Wrappers.lambdaQuery().in(OutMonthPlan::getId, ids)); + if (!outMonthPlans.isEmpty()) { + List statusList = outMonthPlans.stream().map(OutMonthPlan::getValueType).collect(Collectors.toList()); + if (statusList.contains(BusinessStatusEnum.WAITING.getStatus())) { + throw new ServiceException("计划正在审核中,请勿删除"); + } + if (statusList.contains(BusinessStatusEnum.FINISH.getStatus())) { + throw new ServiceException("计划已审核完成,请勿删除"); + } + } + return baseMapper.deleteByIds(ids) > 0; } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusAttendanceAppController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusAttendanceAppController.java index 538e9ad1..e518fd6e 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusAttendanceAppController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusAttendanceAppController.java @@ -9,6 +9,7 @@ import org.dromara.contractor.service.ISubConstructionUserService; import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq; import org.dromara.project.domain.vo.BusAttendanceRuleVo; import org.dromara.project.domain.vo.BusAttendanceVo; +import org.dromara.project.domain.vo.BusMonthAttendanceVo; import org.dromara.project.service.IBusAttendanceRuleService; import org.dromara.project.service.IBusAttendanceService; import org.springframework.validation.annotation.Validated; @@ -72,12 +73,28 @@ public class BusAttendanceAppController extends BaseController { /** * 获取用户当天打卡记录 */ - @PostMapping("/getTodayAttendance/{projectId}") + @GetMapping("/getTodayAttendance/{projectId}") public R> getTodayAttendance(@NotNull @PathVariable("projectId") Long projectId){ return R.ok(attendanceService.getTodayAttendance(projectId)); } + /** + * 获取用户指定月份打卡记录 + */ + @GetMapping("/getMonthAttendance/{projectId}") + public R> getMonthAttendance(@NotNull @PathVariable("projectId") Long projectId, + @NotNull String month){ + return R.ok(attendanceService.getMonthAttendance(projectId,month)); + } + + /** + * 获取用户打卡异常记录 + */ + @GetMapping("/getAbnormalAttendance/{projectId}") + public R> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId){ + return R.ok(attendanceService.getAbnormalAttendance(projectId)); + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusMonthAttendanceVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusMonthAttendanceVo.java new file mode 100644 index 00000000..adf9b1e8 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusMonthAttendanceVo.java @@ -0,0 +1,42 @@ +package org.dromara.project.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import org.dromara.project.domain.BusAttendance; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + + +/** + * 考勤视图对象 bus_attendance + * + * @author Lion Li + * @date 2025-08-05 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = BusAttendance.class) +public class BusMonthAttendanceVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 打卡日期 + */ + private LocalDate clockDate; + + /** + * 考勤记录 + */ + private List list; + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java index 295e8683..9358408c 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusAttendanceService.java @@ -1,5 +1,6 @@ package org.dromara.project.service; +import jakarta.validation.constraints.NotNull; import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq; import org.dromara.project.domain.vo.BusAttendanceVo; import org.dromara.project.domain.bo.BusAttendanceBo; @@ -8,6 +9,8 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.service.IService; +import org.dromara.project.domain.vo.BusMonthAttendanceVo; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.multipart.MultipartFile; import java.util.Collection; @@ -108,4 +111,14 @@ public interface IBusAttendanceService extends IService{ * 获取用户当天打卡记录 */ List getTodayAttendance(Long projectId); + + /** + * 获取用户指定月份的打卡记录 + */ + List getMonthAttendance(Long projectId, String month); + + /** + * 获取用户指定月份的打卡记录 + */ + List getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java index 2ae95832..83ac5234 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusAttendanceServiceImpl.java @@ -30,6 +30,7 @@ import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum; import org.dromara.project.domain.enums.BusAttendanceCommuterEnum; import org.dromara.project.domain.vo.BusAttendanceRuleVo; +import org.dromara.project.domain.vo.BusMonthAttendanceVo; import org.dromara.project.domain.vo.BusProjectPunchrangeVo; import org.dromara.project.service.*; import org.dromara.system.domain.vo.SysOssVo; @@ -401,6 +402,73 @@ public class BusAttendanceServiceImpl extends ServiceImpl getMonthAttendance(Long projectId, String month) { + // 解析月份字符串获取开始和结束日期 + LocalDate startDate = LocalDate.parse(month + "-01"); + LocalDate endDate = startDate.withDayOfMonth(startDate.lengthOfMonth()); + // 获取当前用户ID + Long userId = LoginHelper.getUserId(); + + List relevancyList = userProjectRelevancyService.list( + Wrappers.lambdaQuery(BusUserProjectRelevancy.class) + .eq(BusUserProjectRelevancy::getProjectId, projectId) + .eq(BusUserProjectRelevancy::getUserId, userId)); + + boolean b = relevancyList.stream().allMatch(relevancy -> "1".equals(relevancy.getUserType())); + + // 查询该月的所有考勤记录 + List attendanceList = baseMapper.selectVoList(Wrappers.lambdaQuery(BusAttendance.class) + .eq(BusAttendance::getUserId, userId) + .eq(b, BusAttendance::getProjectId, projectId) + .ge(BusAttendance::getClockDate, startDate) + .le(BusAttendance::getClockDate, endDate) + .orderByAsc(BusAttendance::getClockDate)); + + + // 按日期分组考勤记录 + Map> attendanceMap = attendanceList.stream() + .collect(Collectors.groupingBy(BusAttendanceVo::getClockDate)); + + // 生成每日考勤记录 + List result = new ArrayList<>(); + LocalDate currentDate = startDate; + + while (!currentDate.isAfter(endDate)) { + BusMonthAttendanceVo busMonthAttendanceVo = new BusMonthAttendanceVo(); + busMonthAttendanceVo.setClockDate(currentDate); + busMonthAttendanceVo.setList(attendanceMap.getOrDefault(currentDate, Collections.emptyList())); + result.add(busMonthAttendanceVo); + currentDate = currentDate.plusDays(1); + } + return result; + } + + + @Override + public List getAbnormalAttendance(Long projectId) { + + List abnormalList = Arrays.asList(BusAttendanceClockStatusEnum.LATE.getValue(), + BusAttendanceClockStatusEnum.LEAVEEARLY.getValue(), + BusAttendanceClockStatusEnum.UNCLOCK.getValue()); + + // 获取当前用户ID + Long userId = LoginHelper.getUserId(); + List relevancyList = userProjectRelevancyService.list( + Wrappers.lambdaQuery(BusUserProjectRelevancy.class) + .eq(BusUserProjectRelevancy::getProjectId, projectId) + .eq(BusUserProjectRelevancy::getUserId, userId)); + + boolean b = relevancyList.stream().allMatch(relevancy -> "1".equals(relevancy.getUserType())); + + + return baseMapper.selectVoList(Wrappers.lambdaQuery(BusAttendance.class) + .eq(BusAttendance::getUserId, userId) + .eq(b, BusAttendance::getProjectId, projectId) + .in(BusAttendance::getClockStatus, abnormalList) + ); + } + /** * 计算打卡时间归属的考勤日(关键:解决跨天场景的日期映射) */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusReissueCardServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusReissueCardServiceImpl.java index 9bda9135..64f6e0df 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusReissueCardServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusReissueCardServiceImpl.java @@ -326,8 +326,6 @@ public class BusReissueCardServiceImpl extends ServiceImpl