| 2026-02-11 | gongchunyi | ![]() |
| 2026-02-11 | zss | ![]() |
| 2026-02-11 | gongchunyi | ![]() |
| 2026-02-11 | liding | ![]() |
| 2026-02-11 | zss | ![]() |
| 2026-02-11 | zss | ![]() |
| 2026-02-11 | gongchunyi | ![]() |
| 2026-02-11 | gongchunyi | ![]() |
| 2026-02-11 | gongchunyi | ![]() |
| 2026-02-11 | zss | ![]() |
src/main/java/com/ruoyi/CodeGenerator.java
@@ -19,11 +19,11 @@ // æ¼ç¤ºä¾åï¼æ§è¡ main æ¹æ³æ§å¶å°è¾å ¥æ¨¡å表åå车èªå¨çæå¯¹åºé¡¹ç®ç®å½ä¸ public class CodeGenerator { public static String database_url = "jdbc:mysql://localhost:3306/product-inventory-management-new"; public static String database_url = "jdbc:mysql://1.15.17.182:9999/product-inventory-management-new"; public static String database_username = "root"; public static String database_password= "123456"; public static String database_password= "xd@123456.."; public static String author = "è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸"; public static String model = "purchase"; // 模å public static String model = "staff"; // 模å public static String setParent = "com.ruoyi."+ model; // å è·¯å¾ public static String tablePrefix = ""; // è®¾ç½®è¿æ»¤è¡¨åç¼ public static void main(String[] args) { src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.dto.ProductDto; @@ -12,6 +13,7 @@ import com.ruoyi.basic.pojo.Product; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.basic.service.IProductModelService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.poi.ExcelUtil; @@ -23,9 +25,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.*; import java.util.stream.Collectors; /** @@ -103,9 +103,16 @@ ExcelUtil<ProductModel> productModelExcelUtil = new ExcelUtil<>(ProductModel.class); List<ProductModel> productModelList = productModelExcelUtil.importExcel(file.getInputStream()); if (productModelList == null || productModelList.isEmpty()) { if (CollectionUtils.isEmpty(productModelList)) { return AjaxResult.error("å¯¼å ¥æ°æ®ä¸è½ä¸ºç©º"); } // è·åå½å产å䏿æçè§æ ¼åå·å List<ProductModel> existingModels = list(new LambdaQueryWrapper<ProductModel>().eq(ProductModel::getProductId, productId)); Set<String> existingModelNames = existingModels.stream().map(ProductModel::getModel).collect(Collectors.toSet()); List<ProductModel> waitToSaveList = new ArrayList<>(); int skipCount = 0; for (int i = 0; i < productModelList.size(); i++) { ProductModel item = productModelList.get(i); @@ -117,14 +124,31 @@ if (StringUtils.isEmpty(item.getUnit())) { return AjaxResult.error("第 " + rowNum + " è¡å¯¼å ¥å¤±è´¥: [åä½] ä¸è½ä¸ºç©º"); } // å»é,妿已å å«è¯¥åå·,åè·³è¿ if (existingModelNames.contains(item.getModel())) { skipCount++; continue; } item.setProductId(product.getId()); waitToSaveList.add(item); existingModelNames.add(item.getModel()); } saveOrUpdateBatch(productModelList); return AjaxResult.success("æåå¯¼å ¥ " + productModelList.size() + " æ¡æ°æ®"); if (!waitToSaveList.isEmpty()) { saveBatch(waitToSaveList); } if (skipCount == 0) { return AjaxResult.success(String.format("æåå¯¼å ¥ %d æ¡æ°æ®", waitToSaveList.size())); } else { return AjaxResult.success(String.format("æåå¯¼å ¥ %d æ¡ï¼è·³è¿å·²å卿°æ® %d æ¡", waitToSaveList.size(), skipCount)); } } catch (Exception e) { log.error("å¯¼å ¥äº§åè§æ ¼å¼å¸¸", e); return AjaxResult.error("å¯¼å ¥å¤±è´¥"); throw new ServiceException("å¯¼å ¥å¤±è´¥"); } } } src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java
@@ -5,17 +5,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.framework.web.domain.R; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; 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.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.*; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.controller.BaseController; @@ -99,4 +93,11 @@ { return toAjax(noticeService.readAll()); } @PostMapping("appReadNotice") @ApiOperation("ç§»å¨ç«¯æ ¹æ®æ¶æ¯IDè¿è¡å·²è¯»") public AjaxResult appReadNotice(@RequestParam("noticeId") Long noticeId) { boolean result = noticeService.appReadNotice(noticeId); return toAjax(result); } } src/main/java/com/ruoyi/project/system/domain/SysNotice.java
@@ -3,8 +3,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import org.apache.commons.lang3.builder.ToStringBuilder; @@ -20,11 +19,13 @@ * @author ruoyi */ @Data @TableName("sys_notice") public class SysNotice { private static final long serialVersionUID = 1L; /** å ¬åID */ @TableId(value = "notice_id", type = IdType.AUTO) private Long noticeId; /** å ¬åæ é¢ */ src/main/java/com/ruoyi/project/system/service/ISysNoticeService.java
@@ -82,4 +82,11 @@ */ void simpleNoticeAll(final String title, final String message,final String jumpPath); /** * APPç¹å»æ¨éæ¶æ¯æ´æ¹ä¸ºå·²è¯»ç¶æ * * @param noticeId æ¶æ¯ID * @return 失败/æå */ boolean appReadNotice(Long noticeId); } src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
@@ -28,6 +28,7 @@ import com.ruoyi.project.system.domain.SysNotice; import com.ruoyi.project.system.mapper.SysNoticeMapper; import com.ruoyi.project.system.service.ISysNoticeService; import org.springframework.transaction.annotation.Transactional; /** * å ¬å æå¡å±å®ç° @@ -230,4 +231,20 @@ return sysNotice; } @Override @Transactional(rollbackFor = Exception.class) public boolean appReadNotice(Long noticeId) { if (noticeId == null) { return false; } SysNotice sysNotice = noticeMapper.selectNoticeById(noticeId); if (sysNotice == null) { return false; } sysNotice.setStatus("1"); return noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate() .eq(SysNotice::getNoticeId, noticeId) .eq(SysNotice::getStatus, "0") .set(SysNotice::getStatus, "1")) > 0; } } src/main/java/com/ruoyi/project/system/service/impl/UnipushService.java
@@ -1,5 +1,6 @@ package com.ruoyi.project.system.service.impl; import com.alibaba.fastjson2.JSON; import com.getui.push.v2.sdk.ApiHelper; import com.getui.push.v2.sdk.GtApiConfiguration; import com.getui.push.v2.sdk.api.PushApi; @@ -25,6 +26,7 @@ import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -84,6 +86,7 @@ // æ¨é sendRoutingPush( sysNotice.getNoticeId(), client.getCid(), sysNotice.getNoticeTitle(), sysNotice.getRemark() != null ? sysNotice.getRemark() : sysNotice.getNoticeContent(), @@ -139,18 +142,23 @@ /** * åéåäººè·¯ç±æ¨é */ private void sendRoutingPush(String cid, String title, String content, String targetPath) { log.info("å夿¨éæ¶æ¯: CID={}, Title={}, TargetPath={}", cid, title, targetPath); private void sendRoutingPush(Long noticeId, String cid, String title, String content, String targetPath) { log.info("å夿¨éæ¶æ¯:NoticeId={}, CID={}, Title={}, TargetPath={}", noticeId, cid, title, targetPath); PushDTO<Audience> pushDTO = new PushDTO<>(); pushDTO.setRequestId("REQ_" + System.currentTimeMillis()); // å¨çº¿éä¼ å 容 PushMessage pushMessage = new PushMessage(); String transmissionContent = String.format( "{\"title\":\"%s\",\"content\":\"%s\",\"payload\":\"%s\"}", title, content, targetPath ); Map<String, Object> pushMessageMap = new HashMap<>(); Map<String, Object> payloadMap = new HashMap<>(); pushMessageMap.put("title", title); pushMessageMap.put("content", content); payloadMap.put("url", targetPath); payloadMap.put("noticeId", noticeId); pushMessageMap.put("payload", JSON.toJSONString(payloadMap)); String transmissionContent = JSON.toJSONString(pushMessageMap); pushMessage.setTransmission(transmissionContent); pushDTO.setPushMessage(pushMessage); @@ -160,7 +168,7 @@ pushDTO.setAudience(audience); // 离线æ¨ééé pushDTO.setPushChannel(getPushChannel(title, content, targetPath)); // pushDTO.setPushChannel(getPushChannel(noticeId, title, content, targetPath)); try { ApiResult<Map<String, Map<String, String>>> result = pushApi.pushToSingleByCid(pushDTO); @@ -175,7 +183,7 @@ } @NotNull private PushChannel getPushChannel(String title, String content, String targetPath) { private PushChannel getPushChannel(Long noticeId, String title, String content, String targetPath) { PushChannel pushChannel = new PushChannel(); AndroidDTO androidDTO = new AndroidDTO(); Ups ups = new Ups(); src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -14,10 +14,7 @@ import com.ruoyi.sales.dto.InvoiceLedgerDto; import com.ruoyi.sales.dto.SalesLedgerDto; import com.ruoyi.sales.mapper.InvoiceLedgerMapper; import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper; import com.ruoyi.sales.mapper.ReceiptPaymentMapper; import com.ruoyi.sales.pojo.InvoiceLedger; import com.ruoyi.sales.pojo.InvoiceRegistrationProduct; import com.ruoyi.sales.pojo.ReceiptPayment; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.service.ICommonFileService; @@ -39,10 +36,7 @@ import java.io.OutputStream; import java.math.BigDecimal; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.*; import java.util.stream.Collectors; /** @@ -64,9 +58,6 @@ @Autowired private InvoiceLedgerMapper invoiceLedgerMapper; @Autowired private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; @Autowired private ReceiptPaymentMapper receiptPaymentMapper; @@ -267,69 +258,85 @@ */ @GetMapping("/listPage") public IPage<SalesLedger> listPage(Page page, SalesLedgerDto salesLedgerDto) { IPage<SalesLedger> iPage = salesLedgerService.selectSalesLedgerListPage(page,salesLedgerDto); // 计ç®å·²å¼ç¥¨éé¢/æªå¼ç¥¨éé¢(已填åå票éé¢ä¸ºå) if(CollectionUtils.isEmpty(iPage.getRecords())){ return iPage; } List<Long> salesLedgerIds = iPage.getRecords().stream().map(SalesLedger::getId).collect(Collectors.toList()); List<InvoiceLedgerDto> invoiceLedgerDtoList = invoiceLedgerMapper.invoicedTotal(salesLedgerIds); if(CollectionUtils.isEmpty(invoiceLedgerDtoList)){ return iPage; } // 计ç®å款éé¢ï¼å¾ 忬¾éé¢ List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(new LambdaQueryWrapper<InvoiceRegistrationProduct>() .in(InvoiceRegistrationProduct::getSalesLedgerId, salesLedgerIds)); IPage<SalesLedger> iPage = salesLedgerService.selectSalesLedgerListPage(page, salesLedgerDto); List<InvoiceLedger> invoiceLedgers = invoiceLedgerMapper.selectList(new LambdaQueryWrapper<InvoiceLedger>() .in(InvoiceLedger::getInvoiceRegistrationProductId, invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getId).collect(Collectors.toList()))); List<ReceiptPayment> receiptPayments = new ArrayList<>(); if(!CollectionUtils.isEmpty(invoiceLedgers)){ receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper<ReceiptPayment>() .in(ReceiptPayment::getInvoiceLedgerId, invoiceLedgers.stream().map(InvoiceLedger::getId).collect(Collectors.toList()))); // æ¥è¯¢ç»æä¸ºç©º,ç´æ¥è¿å if (CollectionUtils.isEmpty(iPage.getRecords())) { return iPage; } for (SalesLedger salesLedger : iPage.getRecords()) { boolean existFlag = false; BigDecimal noInvoiceAmountTotal = BigDecimal.ZERO; BigDecimal invoiceTotal = BigDecimal.ZERO; for (InvoiceLedgerDto invoiceLedgerDto : invoiceLedgerDtoList) { if (salesLedger.getId().intValue() == invoiceLedgerDto.getSalesLedgerId()) { noInvoiceAmountTotal = salesLedger.getContractAmount().subtract(invoiceLedgerDto.getInvoiceTotal()); invoiceTotal = invoiceLedgerDto.getInvoiceTotal(); existFlag = true; if(!CollectionUtils.isEmpty(receiptPayments)){ List<InvoiceRegistrationProduct> collect = invoiceRegistrationProducts.stream() .filter(item -> salesLedger.getId().equals(Long.parseLong(item.getSalesLedgerId().toString()))) .collect(Collectors.toList()); List<Integer> collect1 = collect.stream() .map(InvoiceRegistrationProduct::getId).collect(Collectors.toList()); List<InvoiceLedger> collect2 = invoiceLedgers.stream() .filter(item -> collect1.contains(item.getInvoiceRegistrationProductId())) .collect(Collectors.toList()); // è·å已忬¾éé¢ List<ReceiptPayment> collect3 = receiptPayments.stream() .filter(item -> collect2.stream().anyMatch(item1 -> item1.getId().equals(item.getInvoiceLedgerId()))) .collect(Collectors.toList()); BigDecimal receiptPaymentAmountTotal = collect3.stream().map(ReceiptPayment::getReceiptPaymentAmount) .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); // è·åå¾ åæ¬¾éé¢ BigDecimal noReceiptPaymentAmountTotal = invoiceLedgerDto.getInvoiceTotal().subtract(receiptPaymentAmountTotal); salesLedger.setReceiptPaymentAmountTotal(receiptPaymentAmountTotal); salesLedger.setNoReceiptAmount(noReceiptPaymentAmountTotal); } break; // è·åå½å页ææå°è´¦è®°å½ç ID éå List<Long> salesLedgerIds = iPage.getRecords().stream().map(SalesLedger::getId).collect(Collectors.toList()); // æ¥è¯¢å票信æ¯çå·²å¼ç¥¨éé¢ List<InvoiceLedgerDto> invoiceLedgerDtoList = invoiceLedgerMapper.invoicedTotal(salesLedgerIds); if (CollectionUtils.isEmpty(invoiceLedgerDtoList)) { invoiceLedgerDtoList = Collections.emptyList(); } // 转æ¢åç¥¨æ°æ®, key 为å°è´¦ID, value 为该å°è´¦çæ»å¼ç¥¨éé¢ Map<Long, BigDecimal> invoiceTotals = invoiceLedgerDtoList.stream() .filter(dto -> dto.getSalesLedgerId() != null && dto.getInvoiceTotal() != null) .collect(Collectors.toMap( dto -> dto.getSalesLedgerId().longValue(), InvoiceLedgerDto::getInvoiceTotal, BigDecimal::add // åå¨éå¤IDæ§è¡ç´¯å )); // æ¥è¯¢å款/仿¬¾è®°å½ List<ReceiptPayment> receiptPayments = Collections.emptyList(); if (!CollectionUtils.isEmpty(salesLedgerIds)) { receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper<ReceiptPayment>() .in(ReceiptPayment::getSalesLedgerId, salesLedgerIds)); } // 转æ¢åæ¬¾æ°æ®, key 为å°è´¦ID, value 为该å°è´¦çæ»å款éé¢ Map<Long, BigDecimal> receiptTotals = new HashMap<>(); if (!CollectionUtils.isEmpty(receiptPayments)) { for (ReceiptPayment receiptPayment : receiptPayments) { if (receiptPayment.getSalesLedgerId() != null && receiptPayment.getReceiptPaymentAmount() != null) { // 妿 key åå¨åç¸å ,ä¸åå¨åæ¾å ¥ receiptTotals.merge(receiptPayment.getSalesLedgerId(), receiptPayment.getReceiptPaymentAmount(), BigDecimal::add); } } if(existFlag){ salesLedger.setNoInvoiceAmountTotal(noInvoiceAmountTotal); }else { salesLedger.setNoInvoiceAmountTotal(salesLedger.getContractAmount()); } salesLedger.setInvoiceTotal(invoiceTotal); } for (SalesLedger salesLedger : iPage.getRecords()) { Long ledgerId = salesLedger.getId(); // ååæ»éé¢ BigDecimal contractAmount = salesLedger.getContractAmount() == null ? BigDecimal.ZERO : salesLedger.getContractAmount(); // å¼ç¥¨æ»é¢å忬¾æ»é¢ BigDecimal invoiceTotal = invoiceTotals.getOrDefault(ledgerId, BigDecimal.ZERO); BigDecimal receiptPaymentAmountTotal = receiptTotals.getOrDefault(ledgerId, BigDecimal.ZERO); // æªå¼ç¥¨éé¢ = ååéé¢ - å·²å¼ç¥¨éé¢ BigDecimal noInvoiceAmountTotal = contractAmount.subtract(invoiceTotal); if (noInvoiceAmountTotal.compareTo(BigDecimal.ZERO) < 0) { noInvoiceAmountTotal = BigDecimal.ZERO; } // å¾ åæ¬¾éé¢ = å·²å¼ç¥¨éé¢ - 已忬¾éé¢ BigDecimal noReceiptPaymentAmountTotal = invoiceTotal.subtract(receiptPaymentAmountTotal); if (noReceiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) < 0) { noReceiptPaymentAmountTotal = BigDecimal.ZERO; } salesLedger.setNoInvoiceAmountTotal(noInvoiceAmountTotal); salesLedger.setInvoiceTotal(invoiceTotal); salesLedger.setReceiptPaymentAmountTotal(receiptPaymentAmountTotal); salesLedger.setNoReceiptAmount(noReceiptPaymentAmountTotal); // å¦æå·²ç»æè¿å¼ç¥¨æå款æä½,åä¸å 许ç¼è¾ boolean hasInvoiceOperation = invoiceTotal.compareTo(BigDecimal.ZERO) > 0; boolean hasReceiptOperation = receiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) > 0; salesLedger.setIsEdit(!(hasInvoiceOperation || hasReceiptOperation)); } if (ObjectUtils.isNotEmpty(salesLedgerDto.getStatus())) { if (salesLedgerDto.getStatus()) { iPage.getRecords().removeIf(salesLedger -> Objects.equals(salesLedger.getNoInvoiceAmountTotal(), new BigDecimal("0.00"))); // æ¸ é¤ææâæªå¼ç¥¨éé¢â为 0 çè®°å½ iPage.getRecords().removeIf(salesLedger -> Objects.equals(salesLedger.getNoInvoiceAmountTotal(), new BigDecimal("0.00"))); iPage.setTotal(iPage.getRecords().size()); } } src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
@@ -72,15 +72,14 @@ * æ¥è¯¢äº§åä¿¡æ¯å表 */ @GetMapping("/list") public AjaxResult list(SalesLedgerProduct salesLedgerProduct) { public AjaxResult list(SalesLedgerProduct salesLedgerProduct) { List<SalesLedgerProduct> list = salesLedgerProductService.selectSalesLedgerProductList(salesLedgerProduct); list.forEach(item -> { if (item.getFutureTickets().compareTo(BigDecimal.ZERO) == 0) { item.setFutureTickets(item.getQuantity()); } if (item.getFutureTickets().compareTo(BigDecimal.ZERO) == 0) { item.setFutureTickets(BigDecimal.ZERO); } if (item.getFutureTicketsAmount().compareTo(BigDecimal.ZERO) == 0) { item.setFutureTicketsAmount(item.getTaxInclusiveTotalPrice()); item.setFutureTicketsAmount(BigDecimal.ZERO); } // ProcurementPageDto procurementDto = new ProcurementPageDto(); // procurementDto.setSalesLedgerProductId(item.getId()); @@ -89,13 +88,13 @@ // BigDecimal stockQuantity = stockUtils.getStockQuantity(item.getProductModelId()).get("stockQuantity"); // ProcurementPageDtoCopy procurementDtoCopy = result.getRecords().get(0); if (item.getApproveStatus() != 2) { if (item.getHasSufficientStock() == 0) { item.setApproveStatus(0); }else { item.setApproveStatus(1); } if (item.getApproveStatus() != 2) { if (item.getHasSufficientStock() == 0) { item.setApproveStatus(0); } else { item.setApproveStatus(1); } } }); return AjaxResult.success(list); } src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -143,5 +143,9 @@ @TableField(exist = false) //æ¯å¦åè´§(å°è´¦é¡µé¢é¢è²æ§å¶) private Boolean isFh; @TableField(exist = false) //æ¯å¦å¯ç¼è¾ private Boolean isEdit; } src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java
@@ -3,7 +3,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -13,7 +12,10 @@ import com.ruoyi.sales.dto.InvoiceRegistrationProductDto; import com.ruoyi.sales.dto.SalesLedgerDto; import com.ruoyi.sales.excel.InvoiceRegisAndProductExcelDto; import com.ruoyi.sales.mapper.*; import com.ruoyi.sales.mapper.InvoiceLedgerMapper; import com.ruoyi.sales.mapper.InvoiceRegistrationMapper; import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.pojo.InvoiceLedger; import com.ruoyi.sales.pojo.InvoiceRegistration; import com.ruoyi.sales.pojo.InvoiceRegistrationProduct; @@ -85,18 +87,16 @@ throw new RuntimeException("éå®å°è´¦äº§åä¸åå¨ï¼IDï¼" + productDatum.getId()); } // 计ç®ç´¯è®¡å¼ç¥¨ BigDecimal newInvoiceNum = dbProduct.getInvoiceNum().add(currentInvoiceNum); // æªå¼ç¥¨ BigDecimal noInvoiceAmount = dbProduct.getNoInvoiceAmount(); BigDecimal noInvoiceNum = dbProduct.getNoInvoiceNum(); BigDecimal newInvoiceAmount = dbProduct.getInvoiceAmount().add(currentInvoiceAmount); // å©ä½æªå¼ç¥¨ BigDecimal newNoInvoiceNum = noInvoiceNum.subtract(currentInvoiceNum); BigDecimal newNoInvoiceAmount = noInvoiceAmount.subtract(currentInvoiceAmount); // è®¡ç®æªå¼ç¥¨ BigDecimal newNoInvoiceNum = dbProduct.getQuantity().subtract(newInvoiceNum); BigDecimal newNoInvoiceAmount = dbProduct.getTaxInclusiveTotalPrice().subtract(newInvoiceAmount); if (newNoInvoiceNum.compareTo(BigDecimal.ZERO) < 0 || newNoInvoiceAmount.compareTo(BigDecimal.ZERO) < 0) { if (newNoInvoiceAmount.compareTo(BigDecimal.ZERO) < 0) { throw new RuntimeException("å¼ç¥¨æ°éæéé¢è¶ è¿ååæ»é"); } @@ -105,8 +105,6 @@ null, new LambdaUpdateWrapper<SalesLedgerProduct>() .eq(SalesLedgerProduct::getId, dbProduct.getId()) .set(SalesLedgerProduct::getInvoiceNum, newInvoiceNum) .set(SalesLedgerProduct::getInvoiceAmount, newInvoiceAmount) .set(SalesLedgerProduct::getNoInvoiceNum, newNoInvoiceNum) .set(SalesLedgerProduct::getNoInvoiceAmount, newNoInvoiceAmount) ); src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -72,6 +72,7 @@ byId.setExpressCompany(req.getExpressCompany()); byId.setStatus("å·²åè´§"); byId.setShippingCarNumber(req.getShippingCarNumber()); byId.setShippingDate(req.getShippingDate()); boolean update = this.updateById(byId); // è¿ç§»æä»¶ if(CollectionUtils.isNotEmpty(req.getTempFileIds())){ src/main/java/com/ruoyi/staff/controller/PersonalAttendanceLocationConfigController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,53 @@ package com.ruoyi.staff.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.domain.R; import com.ruoyi.staff.dto.PersonalAttendanceRecordsDto; import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig; import com.ruoyi.staff.pojo.PersonalAttendanceRecords; import com.ruoyi.staff.service.PersonalAttendanceLocationConfigService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import java.util.List; /** * <p> * 人åæå¡è§åé ç½® å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-02-11 09:41:34 */ @RestController @RequestMapping("/personalAttendanceLocationConfig") @Api(tags = "人åæå¡è§åé ç½®") public class PersonalAttendanceLocationConfigController { @Autowired private PersonalAttendanceLocationConfigService personalAttendanceLocationConfigService; @ApiOperation("æ°å¢/ä¿®æ¹äººåæå¡è§åé ç½®") @PostMapping("/add") public R add(@RequestBody PersonalAttendanceLocationConfig personalAttendanceLocationConfig){ return R.ok(personalAttendanceLocationConfigService.saveOrUpdate(personalAttendanceLocationConfig)); } @ApiOperation("å页æ¥è¯¢äººåæå¡è§åé ç½®") @GetMapping("/listPage") public R listPage(Page page){ return R.ok(personalAttendanceLocationConfigService.page(page)); } @ApiOperation("å é¤äººåæå¡è§åé ç½®") @DeleteMapping("/del") public R del(@RequestBody List<Integer> ids) { return R.ok(personalAttendanceLocationConfigService.removeBatchByIds(ids)); } } src/main/java/com/ruoyi/staff/controller/PersonalAttendanceRecordsController.java
@@ -6,6 +6,7 @@ import com.ruoyi.staff.pojo.PersonalAttendanceRecords; import com.ruoyi.staff.service.PersonalAttendanceRecordsService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -21,30 +22,30 @@ */ @RestController @RequestMapping("/personalAttendanceRecords") @Api(tags = "æå¡ç¾å°") @Api(tags = "人åæå¡ç¾å°") public class PersonalAttendanceRecordsController { @Resource private PersonalAttendanceRecordsService personalAttendanceRecordsService; // æ°å¢ @ApiOperation("æ°å¢æå¡ç¾å°") @PostMapping("") public AjaxResult add(@RequestBody PersonalAttendanceRecords personalAttendanceRecord){ return AjaxResult.success(personalAttendanceRecordsService.add(personalAttendanceRecord)); public AjaxResult add(@RequestBody PersonalAttendanceRecordsDto personalAttendanceRecordsDto){ return AjaxResult.success(personalAttendanceRecordsService.add(personalAttendanceRecordsDto)); } // å表æ¥è¯¢ @ApiOperation("å页æ¥è¯¢æå¡ç¾å°") @GetMapping("/listPage") public AjaxResult listPage(Page page, PersonalAttendanceRecordsDto personalAttendanceRecordsDto){ return AjaxResult.success(personalAttendanceRecordsService.listPage(page, personalAttendanceRecordsDto)); } // 仿¥è夿°æ® @ApiOperation("è·åå½å人çèå¤ç¸å ³æ°æ®") @GetMapping("/today") public AjaxResult todayInfo(PersonalAttendanceRecordsDto personalAttendanceRecordsDto){ return AjaxResult.success(personalAttendanceRecordsService.todayInfo(personalAttendanceRecordsDto)); } // å¯¼åº @ApiOperation("å¯¼åºæå¡ç¾å°") @PostMapping("/export") public void export(HttpServletResponse response, PersonalAttendanceRecordsDto personalAttendanceRecordsDto) { personalAttendanceRecordsService.export(response, personalAttendanceRecordsDto); src/main/java/com/ruoyi/staff/dto/PersonalAttendanceRecordsDto.java
@@ -1,10 +1,18 @@ package com.ruoyi.staff.dto; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import com.ruoyi.staff.pojo.PersonalAttendanceRecords; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; import java.time.LocalTime; @Data @ExcelIgnoreUnannotated public class PersonalAttendanceRecordsDto extends PersonalAttendanceRecords { @Excel(name = "å§å", sort = 3) private String staffName; @@ -16,4 +24,20 @@ private String deptName; private Long deptId; //æå¡çç»åº¦ private Double longitude; //æå¡ç纬度 private Double latitude; //æ åä¸çæ¶é´ @JsonFormat(pattern = "HH:mm") @DateTimeFormat(pattern = "HH:mm") private LocalTime startAt; //æ åä¸çæ¶é´ @JsonFormat(pattern = "HH:mm") @DateTimeFormat(pattern = "HH:mm") private LocalTime endAt; } src/main/java/com/ruoyi/staff/mapper/PersonalAttendanceLocationConfigMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.staff.mapper; import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * <p> * 人åæå¡è§åé ç½® Mapper æ¥å£ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-02-11 09:41:34 */ @Mapper public interface PersonalAttendanceLocationConfigMapper extends BaseMapper<PersonalAttendanceLocationConfig> { } src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceLocationConfig.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,60 @@ package com.ruoyi.staff.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import java.time.LocalDateTime; import java.time.LocalTime; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; import org.springframework.format.annotation.DateTimeFormat; /** * <p> * 人åæå¡è§åé ç½® * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-02-11 09:41:34 */ @Getter @Setter @TableName("personal_attendance_location_config") @ApiModel(value = "PersonalAttendanceLocationConfig对象", description = "人åæå¡è§åé ç½®") public class PersonalAttendanceLocationConfig implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty("é¨é¨id") private Integer sysDeptId; @ApiModelProperty("å°ç¹åç§°") private String locationName; @ApiModelProperty("ç»åº¦") private Double longitude; @ApiModelProperty("纬度") private Double latitude; @ApiModelProperty("æå¡èå´") private Double radius; @ApiModelProperty("ä¸çæ¶é´") @JsonFormat(pattern = "HH:mm") @DateTimeFormat(pattern = "HH:mm") private LocalTime startAt; @ApiModelProperty("ä¸çæ¶é´") @JsonFormat(pattern = "HH:mm") @DateTimeFormat(pattern = "HH:mm") private LocalTime endAt; } src/main/java/com/ruoyi/staff/service/PersonalAttendanceLocationConfigService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.staff.service; import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig; import com.baomidou.mybatisplus.extension.service.IService; /** * <p> * 人åæå¡è§åé ç½® æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-02-11 09:41:34 */ public interface PersonalAttendanceLocationConfigService extends IService<PersonalAttendanceLocationConfig> { } src/main/java/com/ruoyi/staff/service/PersonalAttendanceRecordsService.java
@@ -21,7 +21,7 @@ public interface PersonalAttendanceRecordsService extends IService<PersonalAttendanceRecords> { IPage<PersonalAttendanceRecordsDto> listPage(Page page, PersonalAttendanceRecordsDto personalAttendanceRecordsDto); int add(PersonalAttendanceRecords personalAttendanceRecords); int add(PersonalAttendanceRecordsDto personalAttendanceRecordsDto); PersonalAttendanceRecordsDto todayInfo(PersonalAttendanceRecordsDto personalAttendanceRecordsDto); src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceLocationConfigServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,25 @@ package com.ruoyi.staff.service.impl; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig; import com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper; import com.ruoyi.staff.service.PersonalAttendanceLocationConfigService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * <p> * 人åæå¡è§åé ç½® æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-02-11 09:41:34 */ @Service public class PersonalAttendanceLocationConfigServiceImpl extends ServiceImpl<PersonalAttendanceLocationConfigMapper, PersonalAttendanceLocationConfig> implements PersonalAttendanceLocationConfigService { } src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java
@@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.base.BaseException; @@ -12,13 +13,16 @@ import com.ruoyi.project.system.service.ISysDictDataService; import com.ruoyi.staff.dto.PersonalAttendanceRecordsDto; import com.ruoyi.staff.dto.StaffOnJobDto; import com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper; import com.ruoyi.staff.mapper.StaffOnJobMapper; import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig; import com.ruoyi.staff.pojo.PersonalAttendanceRecords; import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper; import com.ruoyi.staff.pojo.StaffOnJob; import com.ruoyi.staff.service.PersonalAttendanceRecordsService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.staff.task.PersonalAttendanceRecordsTask; import com.ruoyi.staff.utils.LocationUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -29,6 +33,7 @@ import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.List; @@ -41,6 +46,7 @@ * @since 2026-02-09 01:20:07 */ @Service @Transactional(rollbackFor = Exception.class) public class PersonalAttendanceRecordsServiceImpl extends ServiceImpl<PersonalAttendanceRecordsMapper, PersonalAttendanceRecords> implements PersonalAttendanceRecordsService { @Autowired private PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper; @@ -49,7 +55,7 @@ private StaffOnJobMapper staffOnJobMapper; @Autowired private PersonalAttendanceRecordsTask personalAttendanceRecordsTask; private PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper; @Autowired private ISysDictDataService dictDataService; @@ -58,37 +64,52 @@ private SysDeptMapper sysDeptMapper; @Override @Transactional(rollbackFor = Exception.class) public int add(PersonalAttendanceRecords personalAttendanceRecords) { public int add(PersonalAttendanceRecordsDto personalAttendanceRecordsDto) { // å½åæ¶é´ LocalDate currentDate = LocalDate.now(); // é¦å æ ¹æ®ç¨æ·IDæ¥è¯¢åå·¥ä¿¡æ¯ LocalDateTime currentDateTime = LocalDateTime.now(); /*æ¥è¯¢å工信æ¯*/ QueryWrapper<StaffOnJob> staffQueryWrapper = new QueryWrapper<>(); staffQueryWrapper.eq("staff_no", SecurityUtils.getUsername()); StaffOnJob staffOnJob = staffOnJobMapper.selectOne(staffQueryWrapper); if (staffOnJob == null) { throw new BaseException("å½åç¨æ·æ²¡æå¯¹åºçå工信æ¯"); } // å½åæ¶é´ LocalDateTime currentDateTime = LocalDateTime.now(); // 妿æå¡æ¶é´è¶ è¿èå¤ä¸çæ¶é´ä¸è½æå¡ /*夿æå¡ä½ç½®æ¯å¦å¨è§åèå´å */ List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(Wrappers.<PersonalAttendanceLocationConfig>lambdaQuery() .eq(PersonalAttendanceLocationConfig::getSysDeptId, staffOnJob.getSysDeptId()) .orderByDesc(PersonalAttendanceLocationConfig::getId)); if (personalAttendanceLocationConfigs == null || personalAttendanceLocationConfigs.isEmpty()) { throw new BaseException("å½åé¨é¨æ²¡æè®¾ç½®æå¡è§å"); } Double punchLongitude = personalAttendanceRecordsDto.getLongitude(); //æå¡çç»åº¦ Double punchLatitude = personalAttendanceRecordsDto.getLatitude(); // æå¡ç纬度 if (punchLongitude == null || punchLatitude == null) { throw new BaseException("æå¡å¤±è´¥ï¼æªè·åå°æ¨çä½ç½®ä¿¡æ¯ï¼è¯·å¼å¯å®ä½æé"); } //è®¡ç®æå¡ä½ç½®ä¸èå¤ç¹çè·ç¦» PersonalAttendanceLocationConfig locationConfig = personalAttendanceLocationConfigs.get(0);//è·åææ°ç䏿¡æ°æ® double allowedRadius = locationConfig.getRadius(); // å 许çèå´ï¼ç±³ï¼ double actualDistance = LocationUtils.calculateDistance( punchLatitude, punchLongitude, // åå·¥æå¡çç»çº¬åº¦ locationConfig.getLatitude(), locationConfig.getLongitude() // èå¤ç¹çç»çº¬åº¦ ); //夿æ¯å¦å¨èå´å if (actualDistance > allowedRadius) { throw new BaseException(String.format("æå¡å¤±è´¥ï¼æ¨å½åä½ç½®è·ç¦»èå¤ç¹%.2fç±³ï¼è¶ åºå 许èå´ï¼%sç±³ï¼", actualDistance, allowedRadius)); } /*夿æå¡æ¶é´*/ LocalTime endAt = locationConfig.getEndAt(); //ä¸çæ¶é´ // è·åèå¤ä¸çæ¶é´ç¹ String[] timeConfigs = getAttendanceTimeConfig(); String timeConfig = timeConfigs[1]; String[] timeParts = timeConfig.split(":"); int standardHour = Integer.parseInt(timeParts[0]); int standardMinute = Integer.parseInt(timeParts[1]); int standardHour = endAt.getHour(); int standardMinute = endAt.getMinute(); // å½åæ¶é´ int actualHour = currentDateTime.getHour(); int actualMinute = currentDateTime.getMinute(); // 夿æå¡æ¶é´æ¯å¦æäºå½åæ¶é´ if (actualHour > standardHour || (actualHour == standardHour && actualMinute > standardMinute)) { throw new BaseException("æå¡æ¶é´ä¸è½æäºä¸çæ¶é´"); throw new BaseException(String.format("æå¡å¤±è´¥ï¼æå¡æ¶é´ä¸è½æäºä¸çæ¶é´ï¼%02d:%02dï¼", standardHour, standardMinute)); } // æ ¹æ®åå·¥IDåå½åæ¥ææ¥è¯¢æå¡è®°å½ QueryWrapper<PersonalAttendanceRecords> attendanceQueryWrapper = new QueryWrapper<>(); attendanceQueryWrapper.eq("staff_on_job_id", staffOnJob.getId()) @@ -97,10 +118,11 @@ // æ ¹æ®åå ¸è®¾ç½®çè夿¶é´å¤æè¿å°æ©é if (attendanceRecord == null) { // ä¸å卿å¡è®°å½ï¼å建æ°è®°å½ PersonalAttendanceRecords personalAttendanceRecords = new PersonalAttendanceRecords(); personalAttendanceRecords.setStaffOnJobId(staffOnJob.getId()); personalAttendanceRecords.setDate(currentDate); personalAttendanceRecords.setWorkStartAt(currentDateTime); personalAttendanceRecords.setStatus(determineAttendanceStatus(personalAttendanceRecords, true)); personalAttendanceRecords.setStatus(determineAttendanceStatus(personalAttendanceRecords, true,locationConfig)); personalAttendanceRecords.setRemark(personalAttendanceRecords.getRemark()); personalAttendanceRecords.setTenantId(staffOnJob.getTenantId()); return personalAttendanceRecordsMapper.insert(personalAttendanceRecords); @@ -117,7 +139,7 @@ .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP); attendanceRecord.setWorkHours(workHours); // æ´æ°èå¤ç¶æ attendanceRecord.setStatus(determineAttendanceStatus(attendanceRecord, false)); attendanceRecord.setStatus(determineAttendanceStatus(attendanceRecord, false,locationConfig)); return personalAttendanceRecordsMapper.updateById(attendanceRecord); } else { throw new BaseException("æ¨å·²ç»æè¿å¡äº,æ éé夿å¡!!!"); @@ -125,46 +147,22 @@ } } // è·åè夿¶é´é ç½® private String[] getAttendanceTimeConfig() { String[] timeConfigs = new String[2]; try { String dictType = "sys_work_time"; // è·åä¸çæ¶é´é ç½®ï¼é»è®¤ä¸º09:00 String startTimeConfig = dictDataService.selectDictLabel(dictType, "start_at"); timeConfigs[0] = (startTimeConfig == null || startTimeConfig.trim().isEmpty()) ? "09:00" : startTimeConfig; // è·åä¸çæ¶é´é ç½®ï¼é»è®¤ä¸º18:00 String endTimeConfig = dictDataService.selectDictLabel(dictType, "end_at"); timeConfigs[1] = (endTimeConfig == null || endTimeConfig.trim().isEmpty()) ? "18:00" : endTimeConfig; return timeConfigs; } catch (Exception e) { timeConfigs[0] = "09:00"; // é»è®¤ä¸çæ¶é´ timeConfigs[1] = "18:00"; // é»è®¤ä¸çæ¶é´ return timeConfigs; } } // æ ¹æ®å®é æ¶é´åæ¯å¦ä¸çæ¶é´å¤æèå¤ç¶æ // 0 æ£å¸¸ 1 è¿å° 2 æ©é 3 è¿å°æ©é 4 ç¼ºå¤ private Integer determineAttendanceStatus(PersonalAttendanceRecords attendanceRecord, boolean isStart) { private Integer determineAttendanceStatus(PersonalAttendanceRecords attendanceRecord, boolean isStart,PersonalAttendanceLocationConfig locationConfig) { //夿æ¯ä¸çæå¡è¿æ¯ä¸çæå¡ LocalDateTime actualTime = isStart ? attendanceRecord.getWorkStartAt() : attendanceRecord.getWorkEndAt(); try { // è·åè夿¶é´é ç½® String[] timeConfigs = getAttendanceTimeConfig(); String timeConfig = isStart ? timeConfigs[0] : timeConfigs[1]; // è§£ææ åæ¶é´ String[] timeParts = timeConfig.split(":"); int standardHour = Integer.parseInt(timeParts[0]); int standardMinute = Integer.parseInt(timeParts[1]); LocalTime startAt = locationConfig.getStartAt();//ä¸çæ¶é´ LocalTime endAt = locationConfig.getEndAt();//ä¸çæ¶é´ LocalTime timeConfig = isStart ? startAt : endAt; // è§£æå°æ¶ååé int standardHour = timeConfig.getHour(); int standardMinute = timeConfig.getMinute(); // è·åå®é æ¶é´çæ¶å int actualHour = actualTime.getHour(); int actualMinute = actualTime.getMinute(); // å¤æç¶æ if (isStart) { // ä¸çæå¡ï¼è¶ è¿æ åæ¶é´ç®è¿å° @@ -180,9 +178,7 @@ return 2; // æ©é } } return 0; // æ£å¸¸ } catch (Exception e) { // 妿è·åé 置失败ï¼é»è®¤è¿åæ£å¸¸ç¶æ log.warn("è·åè夿¶é´é 置失败ï¼ä½¿ç¨é»è®¤ç¶æï¼" + e.getMessage()); @@ -240,7 +236,14 @@ resultDto.setDeptId(staffOnJob.getSysDeptId() != null ? staffOnJob.getSysDeptId() : null); SysDept dept = sysDeptMapper.selectDeptById(staffOnJob.getSysDeptId()); resultDto.setDeptName(dept != null ? dept.getDeptName() : null); //è·å该å工对åºçæå¡è§å List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(Wrappers.<PersonalAttendanceLocationConfig>lambdaQuery() .eq(PersonalAttendanceLocationConfig::getSysDeptId, staffOnJob.getSysDeptId()) .orderByDesc(PersonalAttendanceLocationConfig::getId)); if (personalAttendanceLocationConfigs.size()>0){ resultDto.setStartAt(personalAttendanceLocationConfigs.get(0).getStartAt()); resultDto.setEndAt(personalAttendanceLocationConfigs.get(0).getEndAt()); } return resultDto; } src/main/java/com/ruoyi/staff/utils/LocationUtils.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,37 @@ package com.ruoyi.staff.utils; // å·¥å ·ç±»ï¼è®¡ç®ä¸¤ä¸ªç»çº¬åº¦ä¹é´çè·ç¦»ï¼çé¢è·ç¦»ï¼ public class LocationUtils { private static final double EARTH_RADIUS = 6371000; // å°çåå¾ï¼åä½ç±³ /** * 计ç®ä¸¤ä¸ªç»çº¬åº¦ä¹é´çè·ç¦»ï¼ç±³ï¼ * @param lat1 第ä¸ä¸ªç¹çº¬åº¦ * @param lon1 第ä¸ä¸ªç¹ç»åº¦ * @param lat2 第äºä¸ªç¹çº¬åº¦ * @param lon2 第äºä¸ªç¹ç»åº¦ * @return è·ç¦»ï¼ç±³ï¼ */ public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) { // 转弧度 double radLat1 = Math.toRadians(lat1); double radLon1 = Math.toRadians(lon1); double radLat2 = Math.toRadians(lat2); double radLon2 = Math.toRadians(lon2); // å·®å¼ double deltaLat = radLat1 - radLat2; double deltaLon = radLon1 - radLon2; // çé¢è·ç¦»å ¬å¼ double distance = 2 * Math.asin(Math.sqrt( Math.pow(Math.sin(deltaLat / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(deltaLon / 2), 2) )); distance = distance * EARTH_RADIUS; // ä¿ç两ä½å°æ° distance = Math.round(distance * 100) / 100.0; return distance; } } src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
@@ -9,17 +9,18 @@ SET contract_amount = #{totalTaxInclusiveAmount} WHERE id = #{id} </update> <select id="selectPurchaseLedgerListPage" resultType="com.ruoyi.purchase.dto.PurchaseLedgerDto"> select SELECT pl.id, pl.purchase_contract_number , pl.purchase_contract_number, pl.sales_contract_no, pl.supplier_id, pl.supplier_name, pl.project_name, pl.contract_amount, IFNULL(sum(tr.invoice_amount),0) as receipt_payment_amount, pl.contract_amount-IFNULL(sum(tr.invoice_amount),0) AS unReceipt_payment_amount, IFNULL(tr_sum.total_invoice_amount, 0) AS receipt_payment_amount, pl.contract_amount - IFNULL(tr_sum.total_invoice_amount, 0) AS unReceipt_payment_amount, pl.entry_date, pl.execution_date, pl.recorder_id, @@ -30,42 +31,41 @@ pl.approval_status, pl.payment_method, pl.remarks from purchase_ledger pl left join sales_ledger_product slp on slp.sales_ledger_id = pl.id and slp.type=2 left join product_record pr on pl.id = pr.purchase_ledger_id left join ticket_registration tr on tr.id = pr.ticket_registration_id left join supplier_manage sm on pl.supplier_id = sm.id FROM purchase_ledger pl LEFT JOIN ( SELECT purchase_ledger_id, SUM(invoice_amount) AS total_invoice_amount FROM ticket_registration GROUP BY purchase_ledger_id ) tr_sum ON pl.id = tr_sum.purchase_ledger_id LEFT JOIN supplier_manage sm ON pl.supplier_id = sm.id <where> 1 = 1 <if test="c.purchaseContractNumber != null and c.purchaseContractNumber != ''"> and pl.purchase_contract_number like concat('%',#{c.purchaseContractNumber},'%') AND pl.purchase_contract_number LIKE CONCAT('%', #{c.purchaseContractNumber}, '%') </if> <if test="c.approvalStatus != null and c.approvalStatus != ''"> and pl.approval_status = #{c.approvalStatus} AND pl.approval_status = #{c.approvalStatus} </if> <if test="c.supplierName != null and c.supplierName != ''"> and pl.supplier_name like concat('%',#{c.supplierName},'%') AND pl.supplier_name LIKE CONCAT('%', #{c.supplierName}, '%') </if> <if test="c.salesContractNo != null and c.salesContractNo != ''"> and pl.sales_contract_no like concat('%',#{c.salesContractNo},'%') AND pl.sales_contract_no LIKE CONCAT('%', #{c.salesContractNo}, '%') </if> <if test="c.projectName != null and c.projectName != ''"> and pl.project_name like concat('%',#{c.projectName},'%') AND pl.project_name LIKE CONCAT('%', #{c.projectName}, '%') </if> <if test="c.entryDateStart != null and c.entryDateStart != '' "> AND pl.entry_date >= DATE_FORMAT(#{c.entryDateStart},'%Y-%m-%d') <if test="c.entryDateStart != null and c.entryDateStart != ''"> AND pl.entry_date >= #{c.entryDateStart} </if> <if test="c.entryDateEnd != null and c.entryDateEnd != '' "> AND pl.entry_date <= DATE_FORMAT(#{c.entryDateEnd},'%Y-%m-%d') <if test="c.entryDateEnd != null and c.entryDateEnd != ''"> AND pl.entry_date <= #{c.entryDateEnd} </if> </where> group by pl.id, pl.purchase_contract_number, pl.sales_contract_no, pl.supplier_name, pl.project_name,pl.entry_date, pl.recorder_name, pl.contract_amount order by pl.entry_date desc ORDER BY pl.entry_date DESC </select> <select id="getPaymentRegistrationDtoById" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto"> SELECT T1.id, src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -8,23 +8,23 @@ SELECT T1.*, CASE WHEN t2.qualitity-t2.locked_quantity >= T1.quantity THEN 1 WHEN (IFNULL(t2.qualitity, 0) - IFNULL(t2.locked_quantity, 0)) >= IFNULL(T1.quantity, 0) THEN 1 ELSE 0 END as has_sufficient_stock FROM sales_ledger_product T1 LEFT JOIN stock_inventory t2 ON T1.product_model_id = t2.product_model_id <where> 1=1 <if test="salesLedgerProduct.salesLedgerId != null and salesLedgerProduct.salesLedgerId != '' "> <if test="salesLedgerProduct.salesLedgerId != null"> AND T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId} </if> <if test="salesLedgerProduct.type != null and salesLedgerProduct.type != '' "> <if test="salesLedgerProduct.type != null"> AND T1.type = #{salesLedgerProduct.type} </if> </where> ORDER BY T1.register_date DESC </select> <select id="selectSalesLedgerProductByMainId" resultType="com.ruoyi.sales.pojo.SalesLedgerProduct"> select slp.* from quality_inspect qi src/main/resources/mapper/staff/PersonalAttendanceLocationConfigMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig"> <id column="id" property="id" /> <result column="sys_dept_id" property="sysDeptId" /> <result column="location_name" property="locationName" /> <result column="longitude" property="longitude" /> <result column="latitude" property="latitude" /> <result column="radius" property="radius" /> <result column="start_at" property="startAt" /> <result column="end_at" property="endAt" /> </resultMap> </mapper>