86ec2b5f807af65f190923883db8002390efc7f4..0146a1483a3368f75daa6eb03aa42c714943e6b2
2025-09-17 mitao
Merge branch 'feature_asset'
0146a1 对比 | 目录
2025-09-17 mitao
资产管理-资产入库
f36922 对比 | 目录
1 文件已重命名
11个文件已修改
6个文件已添加
1313 ■■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationPurchaseController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationStorageController.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationPurchaseDTO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageDTO.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageGeneralDTO.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStoragePropertyDTO.java 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageVehicleDTO.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/emums/ApprovalTypeEnum.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/emums/AssetTypeEnum.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/AssetMain.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/OaApprovalApplications.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/OaApprovalTodo.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/AssetTypeService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationPurchaseService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationStorageService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationPurchaseServiceImpl.java 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationStorageServiceImpl.java 619 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationPurchaseController.java
@@ -3,7 +3,7 @@
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.dto.OaApprovalApplicationPurchaseDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationPurchaseDTO;
import com.ruoyi.system.service.OaApprovalApplicationPurchaseService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationStorageController.java
@@ -1,20 +1,61 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStorageGeneralDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStoragePropertyDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStorageVehicleDTO;
import com.ruoyi.system.service.OaApprovalApplicationStorageService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
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 javax.validation.Valid;
/**
 * <p>
 * 资产入库申请明细表 前端控制器
 * 资产入库申请 前端控制器
 * </p>
 *
 * @author WuGuanFengYue
 * @since 2025-09-15
 * @author CodeBuddy
 * @since 2025-09-17
 */
@Api(tags = {"OA审批-资产入库申请相关接口"})
@Validated
@RestController
@RequestMapping("/oa-approval-application-storage")
@RequiredArgsConstructor
public class OaApprovalApplicationStorageController {
}
    private final OaApprovalApplicationStorageService oaApprovalApplicationStorageService;
    @ApiOperation("提交通用资产入库申请")
    @PostMapping("/submit-general")
    @Log(title = "通用资产入库申请-提交", businessType = BusinessType.INSERT)
    public R<Void> submitGeneralAssetStorage(@Valid @RequestBody OaApprovalApplicationStorageGeneralDTO dto) {
        oaApprovalApplicationStorageService.submitGeneralAssetStorage(dto);
        return R.ok();
    }
    @ApiOperation("提交房产资产入库申请")
    @PostMapping("/submit-property")
    @Log(title = "房产资产入库申请-提交", businessType = BusinessType.INSERT)
    public R<Void> submitPropertyAssetStorage(@Valid @RequestBody OaApprovalApplicationStoragePropertyDTO dto) {
        oaApprovalApplicationStorageService.submitPropertyAssetStorage(dto);
        return R.ok();
    }
    @ApiOperation("提交车辆资产入库申请")
    @PostMapping("/submit-vehicle")
    @Log(title = "车辆资产入库申请-提交", businessType = BusinessType.INSERT)
    public R<Void> submitVehicleAssetStorage(@Valid @RequestBody OaApprovalApplicationStorageVehicleDTO dto) {
        oaApprovalApplicationStorageService.submitVehicleAssetStorage(dto);
        return R.ok();
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationPurchaseDTO.java
File was renamed from ruoyi-system/src/main/java/com/ruoyi/system/dto/OaApprovalApplicationPurchaseDTO.java
@@ -1,4 +1,4 @@
package com.ruoyi.system.dto;
package com.ruoyi.system.dto.asset;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageDTO.java
New file
@@ -0,0 +1,67 @@
package com.ruoyi.system.dto.asset;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDate;
/**
 * 资产入库申请基础DTO
 *
 * @author CodeBuddy
 * @since 2025-09-17
 */
@Data
@ApiModel(value = "OaApprovalApplicationStorageDTO", description = "资产入库申请基础DTO")
public class OaApprovalApplicationStorageDTO {
    @ApiModelProperty(value = "申请部门ID")
    @NotNull(message = "申请部门不能为空")
    private Integer deptId;
    @ApiModelProperty(value = "申请部门名称")
    @NotBlank(message = "申请部门名称不能为空")
    private String deptName;
    @ApiModelProperty(value = "申请人ID")
    @NotNull(message = "申请人不能为空")
    private Integer applicantUserId;
    @ApiModelProperty(value = "申请人姓名")
    @NotBlank(message = "申请人姓名不能为空")
    private String applicantName;
    @ApiModelProperty(value = "申请日期")
    @NotNull(message = "申请日期不能为空")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate applicationDate;
    @ApiModelProperty(value = "入库备注")
    @Size(max = 500, message = "入库备注不能超过500字符")
    private String applicationReason;
    @ApiModelProperty(value = "附件地址,多个使用英文逗号拼接")
    private String attachmentUrl;
    @ApiModelProperty(value = "事项标题")
    @NotBlank(message = "事项标题不能为空")
    private String title;
    @ApiModelProperty(value = "资产类型ID")
    @NotNull(message = "资产类型不能为空")
    private Integer assetTypeId;
    @ApiModelProperty(value = "入库类型 0-正常入库")
    @NotNull(message = "入库类型不能为空")
    private Boolean storageType;
    @ApiModelProperty(value = "入库日期")
    @NotNull(message = "入库日期不能为空")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate storageTime;
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageGeneralDTO.java
New file
@@ -0,0 +1,138 @@
package com.ruoyi.system.dto.asset;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
 * 通用资产入库申请DTO
 *
 * @author CodeBuddy
 * @since 2025-09-17
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "OaApprovalApplicationStorageGeneralDTO", description = "通用资产入库申请DTO")
public class OaApprovalApplicationStorageGeneralDTO extends OaApprovalApplicationStorageDTO {
    @ApiModelProperty(value = "通用资产明细列表")
    @Valid
    @Size(min = 1, message = "资产明细不能为空")
    private List<GeneralAssetItemDTO> assetItems;
    @Data
    @ApiModel(value = "GeneralAssetItemDTO", description = "通用资产明细DTO")
    public static class GeneralAssetItemDTO {
        // 资产主表字段
        @ApiModelProperty(value = "资产原编码")
        private String assetOriginalCode;
        @ApiModelProperty(value = "资产名称")
        @NotBlank(message = "资产名称不能为空")
        private String assetName;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
        @ApiModelProperty(value = "计量单位")
        @NotBlank(message = "计量单位不能为空")
        private String measurementUnit;
        @ApiModelProperty(value = "数量")
        @NotNull(message = "数量不能为空")
        private BigDecimal quantity;
        @ApiModelProperty(value = "单价")
        @NotNull(message = "单价不能为空")
        private BigDecimal unitPrice;
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门ID")
        private Integer ownershipDeptId;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "使用部门/位置ID")
        private Integer useDeptId;
        @ApiModelProperty(value = "仓库ID")
        private Integer warehouseId;
        @ApiModelProperty(value = "仓库名称")
        private String warehouseName;
        @ApiModelProperty(value = "所在位置")
        private String address;
        @ApiModelProperty(value = "资产状态")
        private String assetStatus;
        @ApiModelProperty(value = "备注")
        private String remarks;
        @ApiModelProperty(value = "入账状态")
        private String accountingStatus;
        @ApiModelProperty(value = "入账时间")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate accountingDate;
        @ApiModelProperty(value = "会计凭证号")
        private String accountingVoucherNo;
        @ApiModelProperty(value = "会计科目")
        private String accountingSubject;
        @ApiModelProperty(value = "入账金额")
        private BigDecimal accountingAmount;
        // 通用资产扩展表字段
        @ApiModelProperty(value = "供应商名称")
        private String supplierName;
        @ApiModelProperty(value = "采购日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate purchaseDate;
        @ApiModelProperty(value = "保修期(月)")
        private Integer warrantyPeriod;
        @ApiModelProperty(value = "保修到期日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate warrantyExpireDate;
        @ApiModelProperty(value = "折旧方法")
        private String depreciationMethod;
        @ApiModelProperty(value = "折旧率")
        private BigDecimal depreciationRate;
        @ApiModelProperty(value = "净值")
        private BigDecimal netValue;
        @ApiModelProperty(value = "维护周期(月)")
        private Integer maintenanceCycle;
        @ApiModelProperty(value = "上次维护日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate lastMaintenanceDate;
        @ApiModelProperty(value = "下次维护日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate nextMaintenanceDate;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStoragePropertyDTO.java
New file
@@ -0,0 +1,155 @@
package com.ruoyi.system.dto.asset;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
 * 房产资产入库申请DTO
 *
 * @author CodeBuddy
 * @since 2025-09-17
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "OaApprovalApplicationStoragePropertyDTO", description = "房产资产入库申请DTO")
public class OaApprovalApplicationStoragePropertyDTO extends OaApprovalApplicationStorageDTO {
    @ApiModelProperty(value = "房产资产明细列表")
    @Valid
    @Size(min = 1, message = "资产明细不能为空")
    private List<PropertyAssetItemDTO> assetItems;
    @Data
    @ApiModel(value = "PropertyAssetItemDTO", description = "房产资产明细DTO")
    public static class PropertyAssetItemDTO {
        // 资产主表字段
        @ApiModelProperty(value = "资产原编码")
        private String assetOriginalCode;
        @ApiModelProperty(value = "资产名称")
        @NotBlank(message = "资产名称不能为空")
        private String assetName;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
        @ApiModelProperty(value = "计量单位")
        @NotBlank(message = "计量单位不能为空")
        private String measurementUnit;
        @ApiModelProperty(value = "数量")
        @NotNull(message = "数量不能为空")
        private BigDecimal quantity;
        @ApiModelProperty(value = "单价")
        @NotNull(message = "单价不能为空")
        private BigDecimal unitPrice;
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门ID")
        private Integer ownershipDeptId;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "使用部门/位置ID")
        private Integer useDeptId;
        @ApiModelProperty(value = "仓库ID")
        private Integer warehouseId;
        @ApiModelProperty(value = "仓库名称")
        private String warehouseName;
        @ApiModelProperty(value = "所在位置")
        private String address;
        @ApiModelProperty(value = "资产状态")
        private String assetStatus;
        @ApiModelProperty(value = "备注")
        private String remarks;
        @ApiModelProperty(value = "入账状态")
        private String accountingStatus;
        @ApiModelProperty(value = "入账时间")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate accountingDate;
        @ApiModelProperty(value = "会计凭证号")
        private String accountingVoucherNo;
        @ApiModelProperty(value = "会计科目")
        private String accountingSubject;
        @ApiModelProperty(value = "入账金额")
        private BigDecimal accountingAmount;
        // 房产资产扩展表字段
        @ApiModelProperty(value = "所在区域")
        private String region;
        @ApiModelProperty(value = "设计用途")
        private String designPurpose;
        @ApiModelProperty(value = "楼栋")
        private String building;
        @ApiModelProperty(value = "房间号")
        private String roomNumber;
        @ApiModelProperty(value = "建筑面积(平方米)")
        private BigDecimal constructionArea;
        @ApiModelProperty(value = "结构")
        private String structureType;
        @ApiModelProperty(value = "权证编号")
        private String certificateNumber;
        @ApiModelProperty(value = "建成年月")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate completionDate;
        @ApiModelProperty(value = "详细位置")
        private String detailedLocation;
        @ApiModelProperty(value = "省资产平台填报价值")
        private BigDecimal provincialPlatformValue;
        @ApiModelProperty(value = "安置情况")
        private String resettlementSituation;
        @ApiModelProperty(value = "是否抵押:0-否,1-是")
        private Boolean isMortgaged;
        @ApiModelProperty(value = "承租方")
        private String tenantName;
        @ApiModelProperty(value = "租金")
        private BigDecimal rentalAmount;
        @ApiModelProperty(value = "租赁期限起")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate leaseStartDate;
        @ApiModelProperty(value = "租赁期限止")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate leaseEndDate;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageVehicleDTO.java
New file
@@ -0,0 +1,129 @@
package com.ruoyi.system.dto.asset;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
 * 车辆资产入库申请DTO
 *
 * @author CodeBuddy
 * @since 2025-09-17
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "OaApprovalApplicationStorageVehicleDTO", description = "车辆资产入库申请DTO")
public class OaApprovalApplicationStorageVehicleDTO extends OaApprovalApplicationStorageDTO {
    @ApiModelProperty(value = "车辆资产明细列表")
    @Valid
    @Size(min = 1, message = "资产明细不能为空")
    private List<VehicleAssetItemDTO> assetItems;
    @Data
    @ApiModel(value = "VehicleAssetItemDTO", description = "车辆资产明细DTO")
    public static class VehicleAssetItemDTO {
        // 资产主表字段
        @ApiModelProperty(value = "资产原编码")
        private String assetOriginalCode;
        @ApiModelProperty(value = "资产名称")
        @NotBlank(message = "资产名称不能为空")
        private String assetName;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
        @ApiModelProperty(value = "计量单位")
        @NotBlank(message = "计量单位不能为空")
        private String measurementUnit;
        @ApiModelProperty(value = "数量")
        @NotNull(message = "数量不能为空")
        private BigDecimal quantity;
        @ApiModelProperty(value = "单价")
        @NotNull(message = "单价不能为空")
        private BigDecimal unitPrice;
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门ID")
        private Integer ownershipDeptId;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "使用部门/位置ID")
        private Integer useDeptId;
        @ApiModelProperty(value = "仓库ID")
        private Integer warehouseId;
        @ApiModelProperty(value = "仓库名称")
        private String warehouseName;
        @ApiModelProperty(value = "所在位置")
        private String address;
        @ApiModelProperty(value = "资产状态")
        private String assetStatus;
        @ApiModelProperty(value = "备注")
        private String remarks;
        @ApiModelProperty(value = "入账状态")
        private String accountingStatus;
        @ApiModelProperty(value = "入账时间")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate accountingDate;
        @ApiModelProperty(value = "会计凭证号")
        private String accountingVoucherNo;
        @ApiModelProperty(value = "会计科目")
        private String accountingSubject;
        @ApiModelProperty(value = "入账金额")
        private BigDecimal accountingAmount;
        // 车辆资产扩展表字段
        @ApiModelProperty(value = "车牌号")
        private String licensePlate;
        @ApiModelProperty(value = "车辆识别代码")
        private String vinCode;
        @ApiModelProperty(value = "发动机号")
        private String engineNumber;
        @ApiModelProperty(value = "排量")
        private String displacement;
        @ApiModelProperty(value = "编制情况")
        private String staffingSituation;
        @ApiModelProperty(value = "产地")
        private String origin;
        @ApiModelProperty(value = "取得日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate acquisitionDate;
        @ApiModelProperty(value = "产权形式")
        private String propertyRightForm;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/emums/ApprovalTypeEnum.java
New file
@@ -0,0 +1,37 @@
package com.ruoyi.system.emums;
import lombok.Getter;
import lombok.AllArgsConstructor;
@Getter
@AllArgsConstructor
public enum ApprovalTypeEnum {
    LEAVE(1, "请假申请"),
    OUT(2, "外出申请"),
    BUSINESS_TRIP(3, "出差申请"),
    LEAVE_DESTROY(4, "销假申请"),
    PURCHASE(5, "采购申请"),
    IN_STOCK(6, "资产入库"),
    GRAB(7, "物品领用"),
    BURROW(8, "物品借用"),
    RETURN(9, "借用归还"),
    ASSET_DISPOSE(10, "资产处置"),
    ASSET_CHANGE(11, "资产表更"),
    REIMBURSEMENT(12, "报销申请"),
    MONEY(13, "款项申请"),
    CONTRACT(14, "合同文件"),
    PAYMENT(15, "进度款支付"),
    CONTACT(16, "内部联系单"),
    ADVERTISEMENT(17, "广告制作申请");
    private final Integer code;
    private final String desc;
    public static ApprovalTypeEnum getEnumByCode(Integer code) {
        for (ApprovalTypeEnum e : ApprovalTypeEnum.values()) {
            if (e.code.equals(code)) {
                return e;
            }
        }
        return null;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/emums/AssetTypeEnum.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.system.emums;
import lombok.Getter;
import lombok.AllArgsConstructor;
@Getter
@AllArgsConstructor
public enum AssetTypeEnum {
    GENERAL(0, "通用资产"),
    HOUSE(1, "房产资产"),
    VEHICLE(2, "车辆资产");
    private final Integer code;
    private final String desc;
    public static AssetTypeEnum getEnumByCode(Integer code) {
        for (AssetTypeEnum e : AssetTypeEnum.values()) {
            if (e.code.equals(code)) {
                return e;
            }
        }
        return null;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/model/AssetMain.java
@@ -64,7 +64,7 @@
    @ApiModelProperty(value = "资产主类型:0-通用资产,1-房产资产,2-车辆资产")
    @TableField("asset_main_type")
    private Boolean assetMainType;
    private Integer assetMainType;
    @ApiModelProperty(value = "计量单位")
    @TableField("measurement_unit")
ruoyi-system/src/main/java/com/ruoyi/system/model/OaApprovalApplications.java
@@ -31,7 +31,7 @@
    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    private Integer id;
    @ApiModelProperty(value = "申请单号")
    @TableField("application_code")
ruoyi-system/src/main/java/com/ruoyi/system/model/OaApprovalTodo.java
@@ -30,11 +30,11 @@
    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    private Integer id;
    @ApiModelProperty(value = "申请ID")
    @TableField("application_id")
    private Long applicationId;
    private Integer applicationId;
    @ApiModelProperty(value = "申请单号")
    @TableField("application_code")
ruoyi-system/src/main/java/com/ruoyi/system/service/AssetTypeService.java
@@ -47,4 +47,11 @@
     */
    void batchDeleteAssetType(List<Integer> ids);
    /**
     * 根据资产类型ID获取资产编码前缀
     * @param assetTypeId 资产类型ID
     * @return 资产编码前缀(一级分类简写+二级分类简写)
     */
    String getAssetCodePrefix(Integer assetTypeId);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationPurchaseService.java
@@ -1,7 +1,7 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.dto.OaApprovalApplicationPurchaseDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationPurchaseDTO;
import com.ruoyi.system.model.OaApprovalApplicationPurchase;
/**
ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationStorageService.java
@@ -1,6 +1,9 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStorageGeneralDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStoragePropertyDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStorageVehicleDTO;
import com.ruoyi.system.model.OaApprovalApplicationStorage;
/**
@@ -13,4 +16,24 @@
 */
public interface OaApprovalApplicationStorageService extends IService<OaApprovalApplicationStorage> {
    /**
     * 提交通用资产入库申请
     *
     * @param dto 通用资产入库申请DTO
     */
    void submitGeneralAssetStorage(OaApprovalApplicationStorageGeneralDTO dto);
    /**
     * 提交房产资产入库申请
     *
     * @param dto 房产资产入库申请DTO
     */
    void submitPropertyAssetStorage(OaApprovalApplicationStoragePropertyDTO dto);
    /**
     * 提交车辆资产入库申请
     *
     * @param dto 车辆资产入库申请DTO
     */
    void submitVehicleAssetStorage(OaApprovalApplicationStorageVehicleDTO dto);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java
@@ -233,4 +233,34 @@
        }
    }
    @Override
    public String getAssetCodePrefix(Integer assetTypeId) {
        if (assetTypeId == null) {
            throw new ServiceException("资产类型ID不能为空");
        }
        // 查询当前资产类型
        AssetType currentAssetType = this.getById(assetTypeId);
        if (currentAssetType == null) {
            throw new ServiceException("资产类型不存在");
        }
        String parentTypeCode = "";
        String subTypeCode = currentAssetType.getTypeCode();
        // 如果是二级分类,需要获取父级分类的简写
        if (currentAssetType.getLevel() == 2 && currentAssetType.getParentId() != null && currentAssetType.getParentId() != 0) {
            AssetType parentAssetType = this.getById(currentAssetType.getParentId());
            if (parentAssetType != null) {
                parentTypeCode = parentAssetType.getTypeCode();
            }
        } else if (currentAssetType.getLevel() == 1) {
            // 如果是一级分类,父级简写为空,子类简写就是当前类型简写
            parentTypeCode = currentAssetType.getTypeCode();
            subTypeCode = "";
        }
        return parentTypeCode + subTypeCode;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationPurchaseServiceImpl.java
@@ -5,7 +5,7 @@
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.dto.OaApprovalApplicationPurchaseDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationPurchaseDTO;
import com.ruoyi.system.emums.ApprovalStatusEnum;
import com.ruoyi.system.mapper.OaApprovalApplicationPurchaseMapper;
import com.ruoyi.system.model.OaApprovalApplicationPurchase;
@@ -96,7 +96,7 @@
    /**
     * 创建待办数据
     */
    private void createApprovalTodo(Long applicationId, String applicationCode, OaApprovalFlowNode flowNode, Integer deptId) {
    private void createApprovalTodo(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode, Integer deptId) {
        // 根据审批类型创建待办数据
        Integer approvalType = flowNode.getApprovalType();
        if (approvalType == null) {
@@ -120,7 +120,7 @@
    /**
     * 创建上级部门审批待办
     */
    private void createUpperDeptTodo(Long applicationId, String applicationCode, OaApprovalFlowNode flowNode, Integer deptId) {
    private void createUpperDeptTodo(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode, Integer deptId) {
        // 1. 获取申请部门信息
        if (deptId == null) {
            throw new ServiceException("未填写申请部门信息");
@@ -154,7 +154,7 @@
    /**
     * 创建指定部门审批待办
     */
    private void createSpecifiedDeptTodo(Long applicationId, String applicationCode, OaApprovalFlowNode flowNode) {
    private void createSpecifiedDeptTodo(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode) {
        if (StringUtils.isBlank(flowNode.getApprovalIds())) {
            throw new ServiceException("操作失败,审批流程配置异常");
        }
@@ -174,7 +174,7 @@
    /**
     * 创建指定人员审批待办
     */
    private void createSpecifiedUserTodo(Long applicationId, String applicationCode, OaApprovalFlowNode flowNode) {
    private void createSpecifiedUserTodo(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode) {
        if (StringUtils.isBlank(flowNode.getApprovalIds())) {
            throw new ServiceException("操作失败,审批流程配置异常");
        }
@@ -192,7 +192,7 @@
    /**
     * 创建待办数据项
     */
    private void createTodoItem(Long applicationId, String applicationCode, OaApprovalFlowNode flowNode, List<SysUser> userList) {
    private void createTodoItem(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode, List<SysUser> userList) {
        List<OaApprovalTodo> approvalTodoList = userList.stream().map(item -> {
            OaApprovalTodo todo = new OaApprovalTodo();
            todo.setApplicationId(applicationId);
@@ -236,9 +236,9 @@
    /**
     * 构建采购申请详情数据
     */
    private OaApprovalApplicationPurchase buildOaApprovalApplicationPurchase(OaApprovalApplicationPurchaseDTO dto, Long applicationId) {
    private OaApprovalApplicationPurchase buildOaApprovalApplicationPurchase(OaApprovalApplicationPurchaseDTO dto, Integer applicationId) {
        OaApprovalApplicationPurchase purchase = new OaApprovalApplicationPurchase();
        purchase.setApprovalApplicationId(applicationId.intValue());
        purchase.setApprovalApplicationId(applicationId);
        // 使用事项标题,而非采购说明
        purchase.setTitle(dto.getTitle());
        // 表结构中无 application_date 字段,此处不再设置
@@ -251,11 +251,11 @@
    /**
     * 构建采购资产明细数据
     */
    private List<OaApprovalApplicationPurchaseItem> buildOaApprovalApplicationPurchaseItems(OaApprovalApplicationPurchaseDTO dto, Long applicationId) {
    private List<OaApprovalApplicationPurchaseItem> buildOaApprovalApplicationPurchaseItems(OaApprovalApplicationPurchaseDTO dto, Integer applicationId) {
        return dto.getPurchaseItems().stream()
                .map(item -> {
                    OaApprovalApplicationPurchaseItem purchaseItem = new OaApprovalApplicationPurchaseItem();
                    purchaseItem.setApprovalApplicationId(applicationId.intValue());
                    purchaseItem.setApprovalApplicationId(applicationId);
                    purchaseItem.setAssetName(item.getAssetName());
                    purchaseItem.setAssetTypeId(item.getAssetTypeId());
                    purchaseItem.setSpec(item.getSpec());
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationStorageServiceImpl.java
@@ -1,10 +1,33 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStorageGeneralDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStoragePropertyDTO;
import com.ruoyi.system.dto.asset.OaApprovalApplicationStorageVehicleDTO;
import com.ruoyi.system.emums.ApprovalStatusEnum;
import com.ruoyi.system.emums.ApprovalTypeEnum;
import com.ruoyi.system.emums.AssetTypeEnum;
import com.ruoyi.system.mapper.OaApprovalApplicationStorageMapper;
import com.ruoyi.system.model.OaApprovalApplicationStorage;
import com.ruoyi.system.service.OaApprovalApplicationStorageService;
import com.ruoyi.system.model.*;
import com.ruoyi.system.service.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
@@ -15,6 +38,596 @@
 * @since 2025-09-15
 */
@Service
@RequiredArgsConstructor
public class OaApprovalApplicationStorageServiceImpl extends ServiceImpl<OaApprovalApplicationStorageMapper, OaApprovalApplicationStorage> implements OaApprovalApplicationStorageService {
}
    private final OaApprovalApplicationsService oaApprovalApplicationsService;
    private final AssetMainService assetMainService;
    private final AssetGeneralExtService assetGeneralExtService;
    private final AssetPropertyExtService assetPropertyExtService;
    private final AssetVehicleExtService assetVehicleExtService;
    private final AssetTypeService assetTypeService;
    private final OaApprovalFlowNodeService oaApprovalFlowNodeService;
    private final OaApprovalTodoService oaApprovalTodoService;
    private final ISysUserService sysUserService;
    private final ISysDeptService sysDeptService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitGeneralAssetStorage(OaApprovalApplicationStorageGeneralDTO dto) {
        // 1. 保存审批申请主表数据
        OaApprovalApplications applications = buildOaApprovalApplications(dto);
        // 2. 获取流程节点并创建待办
        OaApprovalFlowNode firstFlowNode = getFirstFlowNode(ApprovalTypeEnum.IN_STOCK.getCode());
        applications.setCurrentFlowNodeId(firstFlowNode.getId());
        oaApprovalApplicationsService.save(applications);
        // 3. 创建待办事项记录
        createApprovalTodo(applications.getId(), applications.getApplicationCode(), firstFlowNode, dto.getDeptId());
        // 4. 保存资产入库申请明细数据
        OaApprovalApplicationStorage storage = buildOaApprovalApplicationStorage(dto, applications.getId());
        save(storage);
        // 5. 保存通用资产数据
        saveGeneralAssets(dto.getAssetItems(), applications.getId(), dto.getAssetTypeId(), dto.getStorageTime());
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitPropertyAssetStorage(OaApprovalApplicationStoragePropertyDTO dto) {
        // 1. 保存审批申请主表数据
        OaApprovalApplications applications = buildOaApprovalApplications(dto);
        // 2. 获取流程节点并创建待办
        OaApprovalFlowNode firstFlowNode = getFirstFlowNode(ApprovalTypeEnum.IN_STOCK.getCode());
        applications.setCurrentFlowNodeId(firstFlowNode.getId());
        oaApprovalApplicationsService.save(applications);
        // 3. 创建待办事项记录
        createApprovalTodo(applications.getId(), applications.getApplicationCode(), firstFlowNode, dto.getDeptId());
        // 4. 保存资产入库申请明细数据
        OaApprovalApplicationStorage storage = buildOaApprovalApplicationStorage(dto, applications.getId());
        save(storage);
        // 5. 保存房产资产数据
        savePropertyAssets(dto.getAssetItems(), applications.getId(), dto.getAssetTypeId(), dto.getStorageTime());
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitVehicleAssetStorage(OaApprovalApplicationStorageVehicleDTO dto) {
        // 1. 保存审批申请主表数据
        OaApprovalApplications applications = buildOaApprovalApplications(dto);
        // 2. 获取流程节点并创建待办
        OaApprovalFlowNode firstFlowNode = getFirstFlowNode(ApprovalTypeEnum.IN_STOCK.getCode());
        applications.setCurrentFlowNodeId(firstFlowNode.getId());
        oaApprovalApplicationsService.save(applications);
        // 3. 创建待办事项记录
        createApprovalTodo(applications.getId(), applications.getApplicationCode(), firstFlowNode, dto.getDeptId());
        // 4. 保存资产入库申请明细数据
        OaApprovalApplicationStorage storage = buildOaApprovalApplicationStorage(dto, applications.getId());
        save(storage);
        // 5. 保存车辆资产数据
        saveVehicleAssets(dto.getAssetItems(), applications.getId(), dto.getAssetTypeId(), dto.getStorageTime());
    }
    /**
     * 保存通用资产数据
     */
    private void saveGeneralAssets(List<OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO> assetItems, Integer applicationId, Integer assetTypeId, LocalDate storageDate) {
        List<AssetMain> allAssetMains = new ArrayList<>();
        List<AssetGeneralExt> allGeneralExts = new ArrayList<>();
        for (OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO item : assetItems) {
            // 根据数量创建对应数量的资产记录
            int quantity = item.getQuantity().intValue();
            for (int i = 0; i < quantity; i++) {
                AssetMain assetMain = buildAssetMain(item, applicationId, assetTypeId, storageDate);
                assetMain.setAssetMainType(AssetTypeEnum.GENERAL.getCode());
                assetMain.setQuantity(BigDecimal.ONE); // 每个资产记录数量为1
                assetMain.setTotalValue(item.getUnitPrice()); // 总价值等于单价
                allAssetMains.add(assetMain);
            }
        }
        // 批量保存资产主表数据
        assetMainService.saveBatch(allAssetMains);
        // 为每个资产主表记录创建对应的扩展信息
        int assetMainIndex = 0;
        for (OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO item : assetItems) {
            int quantity = item.getQuantity().intValue();
            for (int i = 0; i < quantity; i++) {
                AssetGeneralExt generalExt = buildAssetGeneralExt(item, allAssetMains.get(assetMainIndex).getId());
                allGeneralExts.add(generalExt);
                assetMainIndex++;
            }
        }
        assetGeneralExtService.saveBatch(allGeneralExts);
    }
    /**
     * 保存房产资产数据
     */
    private void savePropertyAssets(List<OaApprovalApplicationStoragePropertyDTO.PropertyAssetItemDTO> assetItems, Integer applicationId, Integer assetTypeId, LocalDate storageDate) {
        List<AssetMain> allAssetMains = new ArrayList<>();
        List<AssetPropertyExt> allPropertyExts = new ArrayList<>();
        for (OaApprovalApplicationStoragePropertyDTO.PropertyAssetItemDTO item : assetItems) {
            // 根据数量创建对应数量的资产记录
            int quantity = item.getQuantity().intValue();
            for (int i = 0; i < quantity; i++) {
                AssetMain assetMain = buildAssetMainFromProperty(item, applicationId, assetTypeId, storageDate);
                assetMain.setAssetMainType(AssetTypeEnum.HOUSE.getCode());
                assetMain.setQuantity(BigDecimal.ONE); // 每个资产记录数量为1
                assetMain.setTotalValue(item.getUnitPrice()); // 总价值等于单价
                allAssetMains.add(assetMain);
            }
        }
        // 批量保存资产主表数据
        assetMainService.saveBatch(allAssetMains);
        // 为每个资产主表记录创建对应的扩展信息
        int assetMainIndex = 0;
        for (OaApprovalApplicationStoragePropertyDTO.PropertyAssetItemDTO item : assetItems) {
            int quantity = item.getQuantity().intValue();
            for (int i = 0; i < quantity; i++) {
                AssetPropertyExt propertyExt = buildAssetPropertyExt(item, allAssetMains.get(assetMainIndex).getId());
                allPropertyExts.add(propertyExt);
                assetMainIndex++;
            }
        }
        assetPropertyExtService.saveBatch(allPropertyExts);
    }
    /**
     * 保存车辆资产数据
     */
    private void saveVehicleAssets(List<OaApprovalApplicationStorageVehicleDTO.VehicleAssetItemDTO> assetItems, Integer applicationId, Integer assetTypeId, LocalDate storageDate) {
        List<AssetMain> allAssetMains = new ArrayList<>();
        List<AssetVehicleExt> allVehicleExts = new ArrayList<>();
        for (OaApprovalApplicationStorageVehicleDTO.VehicleAssetItemDTO item : assetItems) {
            // 根据数量创建对应数量的资产记录
            int quantity = item.getQuantity().intValue();
            for (int i = 0; i < quantity; i++) {
                AssetMain assetMain = buildAssetMainFromVehicle(item, applicationId, assetTypeId, storageDate);
                assetMain.setAssetMainType(AssetTypeEnum.VEHICLE.getCode());
                assetMain.setQuantity(BigDecimal.ONE); // 每个资产记录数量为1
                assetMain.setTotalValue(item.getUnitPrice()); // 总价值等于单价
                allAssetMains.add(assetMain);
            }
        }
        // 批量保存资产主表数据
        assetMainService.saveBatch(allAssetMains);
        // 为每个资产主表记录创建对应的扩展信息
        int assetMainIndex = 0;
        for (OaApprovalApplicationStorageVehicleDTO.VehicleAssetItemDTO item : assetItems) {
            int quantity = item.getQuantity().intValue();
            for (int i = 0; i < quantity; i++) {
                AssetVehicleExt vehicleExt = buildAssetVehicleExt(item, allAssetMains.get(assetMainIndex).getId());
                allVehicleExts.add(vehicleExt);
                assetMainIndex++;
            }
        }
        assetVehicleExtService.saveBatch(allVehicleExts);
    }
    /**
     * 构建通用资产主表数据
     */
    private AssetMain buildAssetMain(OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO item, Integer applicationId, Integer assetTypeId, LocalDate storageDate) {
        AssetMain assetMain = new AssetMain();
        assetMain.setApprovalApplicationId(applicationId.intValue());
        assetMain.setAssetOriginalCode(item.getAssetOriginalCode());
        assetMain.setAssetCode(generateAssetCode(assetTypeId, storageDate)); // 系统生成资产编码
        assetMain.setAssetName(item.getAssetName());
        assetMain.setSpecificationModel(item.getSpecificationModel());
        assetMain.setAssetTypeId(assetTypeId);
        assetMain.setMeasurementUnit(item.getMeasurementUnit());
        assetMain.setUnitPrice(item.getUnitPrice());
        assetMain.setUsefulLife(item.getUsefulLife());
        assetMain.setOwnershipDeptId(item.getOwnershipDeptId());
        assetMain.setUserName(item.getUserName());
        assetMain.setUseDeptId(item.getUseDeptId());
        assetMain.setWarehouseId(item.getWarehouseId());
        assetMain.setWarehouseName(item.getWarehouseName());
        assetMain.setAddress(item.getAddress());
        assetMain.setAssetStatus(item.getAssetStatus());
        assetMain.setRemarks(item.getRemarks());
        assetMain.setAccountingStatus(item.getAccountingStatus());
        assetMain.setAccountingDate(item.getAccountingDate());
        assetMain.setAccountingVoucherNo(item.getAccountingVoucherNo());
        assetMain.setAccountingSubject(item.getAccountingSubject());
        assetMain.setAccountingAmount(item.getAccountingAmount());
        assetMain.setDisabled(false);
        return assetMain;
    }
    /**
     * 构建房产资产主表数据
     */
    private AssetMain buildAssetMainFromProperty(OaApprovalApplicationStoragePropertyDTO.PropertyAssetItemDTO item, Integer applicationId, Integer assetTypeId, LocalDate storageDate) {
        AssetMain assetMain = new AssetMain();
        assetMain.setApprovalApplicationId(applicationId.intValue());
        assetMain.setAssetOriginalCode(item.getAssetOriginalCode());
        assetMain.setAssetCode(generateAssetCode(assetTypeId, storageDate));
        assetMain.setAssetName(item.getAssetName());
        assetMain.setSpecificationModel(item.getSpecificationModel());
        assetMain.setAssetTypeId(assetTypeId);
        assetMain.setMeasurementUnit(item.getMeasurementUnit());
        assetMain.setUnitPrice(item.getUnitPrice());
        assetMain.setUsefulLife(item.getUsefulLife());
        assetMain.setOwnershipDeptId(item.getOwnershipDeptId());
        assetMain.setUserName(item.getUserName());
        assetMain.setUseDeptId(item.getUseDeptId());
        assetMain.setWarehouseId(item.getWarehouseId());
        assetMain.setWarehouseName(item.getWarehouseName());
        assetMain.setAddress(item.getAddress());
        assetMain.setAssetStatus(item.getAssetStatus());
        assetMain.setRemarks(item.getRemarks());
        assetMain.setAccountingStatus(item.getAccountingStatus());
        assetMain.setAccountingDate(item.getAccountingDate());
        assetMain.setAccountingVoucherNo(item.getAccountingVoucherNo());
        assetMain.setAccountingSubject(item.getAccountingSubject());
        assetMain.setAccountingAmount(item.getAccountingAmount());
        assetMain.setDisabled(false);
        return assetMain;
    }
    /**
     * 构建车辆资产主表数据
     */
    private AssetMain buildAssetMainFromVehicle(OaApprovalApplicationStorageVehicleDTO.VehicleAssetItemDTO item, Integer applicationId, Integer assetTypeId, LocalDate storageDate) {
        AssetMain assetMain = new AssetMain();
        assetMain.setApprovalApplicationId(applicationId.intValue());
        assetMain.setAssetOriginalCode(item.getAssetOriginalCode());
        assetMain.setAssetCode(generateAssetCode(assetTypeId, storageDate));
        assetMain.setAssetName(item.getAssetName());
        assetMain.setSpecificationModel(item.getSpecificationModel());
        assetMain.setAssetTypeId(assetTypeId);
        assetMain.setMeasurementUnit(item.getMeasurementUnit());
        assetMain.setUnitPrice(item.getUnitPrice());
        assetMain.setUsefulLife(item.getUsefulLife());
        assetMain.setOwnershipDeptId(item.getOwnershipDeptId());
        assetMain.setUserName(item.getUserName());
        assetMain.setUseDeptId(item.getUseDeptId());
        assetMain.setWarehouseId(item.getWarehouseId());
        assetMain.setWarehouseName(item.getWarehouseName());
        assetMain.setAddress(item.getAddress());
        assetMain.setAssetStatus(item.getAssetStatus());
        assetMain.setRemarks(item.getRemarks());
        assetMain.setAccountingStatus(item.getAccountingStatus());
        assetMain.setAccountingDate(item.getAccountingDate());
        assetMain.setAccountingVoucherNo(item.getAccountingVoucherNo());
        assetMain.setAccountingSubject(item.getAccountingSubject());
        assetMain.setAccountingAmount(item.getAccountingAmount());
        assetMain.setDisabled(false);
        return assetMain;
    }
    /**
     * 构建通用资产扩展数据
     */
    private AssetGeneralExt buildAssetGeneralExt(OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO item, Integer assetMainId) {
        AssetGeneralExt generalExt = new AssetGeneralExt();
        generalExt.setAssetMainId(assetMainId);
        generalExt.setSupplierName(item.getSupplierName());
        generalExt.setPurchaseDate(item.getPurchaseDate());
        generalExt.setWarrantyPeriod(item.getWarrantyPeriod());
        generalExt.setWarrantyExpireDate(item.getWarrantyExpireDate());
        generalExt.setDepreciationMethod(item.getDepreciationMethod());
        generalExt.setDepreciationRate(item.getDepreciationRate());
        generalExt.setNetValue(item.getNetValue());
        generalExt.setMaintenanceCycle(item.getMaintenanceCycle());
        generalExt.setLastMaintenanceDate(item.getLastMaintenanceDate());
        generalExt.setNextMaintenanceDate(item.getNextMaintenanceDate());
        generalExt.setDisabled(false);
        return generalExt;
    }
    /**
     * 构建房产资产扩展数据
     */
    private AssetPropertyExt buildAssetPropertyExt(OaApprovalApplicationStoragePropertyDTO.PropertyAssetItemDTO item, Integer assetMainId) {
        AssetPropertyExt propertyExt = new AssetPropertyExt();
        propertyExt.setAssetMainId(assetMainId);
        propertyExt.setRegion(item.getRegion());
        propertyExt.setDesignPurpose(item.getDesignPurpose());
        propertyExt.setBuilding(item.getBuilding());
        propertyExt.setRoomNumber(item.getRoomNumber());
        propertyExt.setConstructionArea(item.getConstructionArea());
        propertyExt.setStructureType(item.getStructureType());
        propertyExt.setCertificateNumber(item.getCertificateNumber());
        propertyExt.setCompletionDate(item.getCompletionDate());
        propertyExt.setDetailedLocation(item.getDetailedLocation());
        propertyExt.setProvincialPlatformValue(item.getProvincialPlatformValue());
        propertyExt.setResettlementSituation(item.getResettlementSituation());
        propertyExt.setIsMortgaged(item.getIsMortgaged());
        propertyExt.setTenantName(item.getTenantName());
        propertyExt.setRentalAmount(item.getRentalAmount());
        propertyExt.setLeaseStartDate(item.getLeaseStartDate());
        propertyExt.setLeaseEndDate(item.getLeaseEndDate());
        propertyExt.setDisabled(false);
        return propertyExt;
    }
    /**
     * 构建车辆资产扩展数据
     */
    private AssetVehicleExt buildAssetVehicleExt(OaApprovalApplicationStorageVehicleDTO.VehicleAssetItemDTO item, Integer assetMainId) {
        AssetVehicleExt vehicleExt = new AssetVehicleExt();
        vehicleExt.setAssetMainId(assetMainId);
        vehicleExt.setLicensePlate(item.getLicensePlate());
        vehicleExt.setVinCode(item.getVinCode());
        vehicleExt.setEngineNumber(item.getEngineNumber());
        vehicleExt.setDisplacement(item.getDisplacement());
        vehicleExt.setStaffingSituation(item.getStaffingSituation());
        vehicleExt.setOrigin(item.getOrigin());
        vehicleExt.setAcquisitionDate(item.getAcquisitionDate());
        vehicleExt.setPropertyRightForm(item.getPropertyRightForm());
        vehicleExt.setDisabled(false);
        return vehicleExt;
    }
    /**
     * 获取第一个流程节点
     */
    private OaApprovalFlowNode getFirstFlowNode(Integer approvalId) {
        List<OaApprovalFlowNode> flowNodes = oaApprovalFlowNodeService.lambdaQuery()
                .eq(OaApprovalFlowNode::getApprovalId, approvalId)
                .eq(OaApprovalFlowNode::getStatus, 1)
                .orderByAsc(OaApprovalFlowNode::getSortOrder)
                .list();
        if (CollectionUtils.isEmpty(flowNodes)) {
            throw new ServiceException("未找到有效的审批流程配置");
        }
        return flowNodes.get(0);
    }
    /**
     * 创建待办数据
     */
    private void createApprovalTodo(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode, Integer deptId) {
        Integer approvalType = flowNode.getApprovalType();
        if (approvalType == null) {
            throw new ServiceException("审批类型不能为空");
        }
        switch (approvalType) {
            case 0:
                createUpperDeptTodo(applicationId, applicationCode, flowNode, deptId);
                break;
            case 1:
                createSpecifiedDeptTodo(applicationId, applicationCode, flowNode);
                break;
            case 2:
                createSpecifiedUserTodo(applicationId, applicationCode, flowNode);
                break;
            default:
                throw new ServiceException("不支持的审批类型: " + approvalType);
        }
    }
    /**
     * 创建上级部门审批待办
     */
    private void createUpperDeptTodo(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode, Integer deptId) {
        if (deptId == null) {
            throw new ServiceException("未填写申请部门信息");
        }
        SysDept currentDept = sysDeptService.selectDeptById(Long.valueOf(deptId));
        if (currentDept == null) {
            throw new ServiceException("申请部门信息不存在");
        }
        if (currentDept.getParentId() == null || currentDept.getParentId() == 0) {
            throw new ServiceException("当前部门没有上级部门");
        }
        SysDept parentDept = sysDeptService.selectDeptById(currentDept.getParentId());
        if (parentDept == null) {
            throw new ServiceException("上级部门信息不存在");
        }
        List<SysUser> users = sysUserService.selectListByDeptId(parentDept.getDeptId().toString());
        if (CollUtil.isEmpty(users)) {
            throw new ServiceException("上级部门下没有找到用户");
        }
        createTodoItem(applicationId, applicationCode, flowNode, users);
    }
    /**
     * 创建指定部门审批待办
     */
    private void createSpecifiedDeptTodo(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode) {
        if (StringUtils.isBlank(flowNode.getApprovalIds())) {
            throw new ServiceException("操作失败,审批流程配置异常");
        }
        List<String> deptIdList = Arrays.stream(flowNode.getApprovalIds().split(",")).collect(Collectors.toList());
        List<SysUser> users = sysUserService.selectListByDeptIds(deptIdList);
        if (CollUtil.isEmpty(users)) {
            throw new ServiceException("指定部门下没有找到用户");
        }
        createTodoItem(applicationId, applicationCode, flowNode, users);
    }
    /**
     * 创建指定人员审批待办
     */
    private void createSpecifiedUserTodo(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode) {
        if (StringUtils.isBlank(flowNode.getApprovalIds())) {
            throw new ServiceException("操作失败,审批流程配置异常");
        }
        List<Integer> userIds = Arrays.stream(flowNode.getApprovalIds().split(","))
                .map(Integer::valueOf).collect(Collectors.toList());
        List<SysUser> users = sysUserService.selectListByUserIds(userIds);
        if (CollUtil.isEmpty(users)) {
            throw new ServiceException("没有找到指定审批用户");
        }
        createTodoItem(applicationId, applicationCode, flowNode, users);
    }
    /**
     * 创建待办数据项
     */
    private void createTodoItem(Integer applicationId, String applicationCode, OaApprovalFlowNode flowNode, List<SysUser> userList) {
        List<OaApprovalTodo> approvalTodoList = userList.stream().map(item -> {
            OaApprovalTodo todo = new OaApprovalTodo();
            todo.setApplicationId(applicationId);
            todo.setApplicationCode(applicationCode);
            todo.setFlowNodeId(flowNode.getId());
            todo.setUserId(item.getUserId().intValue());
            todo.setUserName(item.getNickName());
            if (item.getDeptId() != null) {
                todo.setDeptId(Integer.valueOf(item.getDeptId()));
            }
            todo.setSortOrder(flowNode.getSortOrder());
            todo.setStatus(0);
            todo.setCreateTime(LocalDateTime.now());
            return todo;
        }).collect(Collectors.toList());
        oaApprovalTodoService.saveBatch(approvalTodoList);
    }
    /**
     * 构建审批申请主表数据
     */
    private OaApprovalApplications buildOaApprovalApplications(Object dto) {
        OaApprovalApplications applications = new OaApprovalApplications();
        applications.setApprovalId(ApprovalTypeEnum.IN_STOCK.getCode());
        if (dto instanceof OaApprovalApplicationStorageGeneralDTO) {
            OaApprovalApplicationStorageGeneralDTO generalDTO = (OaApprovalApplicationStorageGeneralDTO) dto;
            applications.setApplicantUserId(generalDTO.getApplicantUserId());
            applications.setApplicantName(generalDTO.getApplicantName());
            applications.setDeptId(generalDTO.getDeptId());
            applications.setDeptName(generalDTO.getDeptName());
            applications.setApplicationDate(generalDTO.getApplicationDate());
            applications.setApplicationReason(generalDTO.getApplicationReason());
            applications.setAttachmentUrl(generalDTO.getAttachmentUrl());
        } else if (dto instanceof OaApprovalApplicationStoragePropertyDTO) {
            OaApprovalApplicationStoragePropertyDTO propertyDTO = (OaApprovalApplicationStoragePropertyDTO) dto;
            applications.setApplicantUserId(propertyDTO.getApplicantUserId());
            applications.setApplicantName(propertyDTO.getApplicantName());
            applications.setDeptId(propertyDTO.getDeptId());
            applications.setDeptName(propertyDTO.getDeptName());
            applications.setApplicationDate(propertyDTO.getApplicationDate());
            applications.setApplicationReason(propertyDTO.getApplicationReason());
            applications.setAttachmentUrl(propertyDTO.getAttachmentUrl());
        } else if (dto instanceof OaApprovalApplicationStorageVehicleDTO) {
            OaApprovalApplicationStorageVehicleDTO vehicleDTO = (OaApprovalApplicationStorageVehicleDTO) dto;
            applications.setApplicantUserId(vehicleDTO.getApplicantUserId());
            applications.setApplicantName(vehicleDTO.getApplicantName());
            applications.setDeptId(vehicleDTO.getDeptId());
            applications.setDeptName(vehicleDTO.getDeptName());
            applications.setApplicationDate(vehicleDTO.getApplicationDate());
            applications.setApplicationReason(vehicleDTO.getApplicationReason());
            applications.setAttachmentUrl(vehicleDTO.getAttachmentUrl());
        }
        applications.setApplicationCode(generateApplicationCode());
        applications.setDisabled(0);
        applications.setApprovalStatus(ApprovalStatusEnum.PENDING.getCode());
        return applications;
    }
    /**
     * 构建资产入库申请明细数据
     */
    private OaApprovalApplicationStorage buildOaApprovalApplicationStorage(Object dto, Integer applicationId) {
        OaApprovalApplicationStorage storage = new OaApprovalApplicationStorage();
        storage.setApprovalApplicationId(applicationId.intValue());
        if (dto instanceof OaApprovalApplicationStorageGeneralDTO) {
            OaApprovalApplicationStorageGeneralDTO generalDTO = (OaApprovalApplicationStorageGeneralDTO) dto;
            storage.setTitle(generalDTO.getTitle());
            storage.setAssetTypeId(generalDTO.getAssetTypeId());
            storage.setStorageType(generalDTO.getStorageType());
            storage.setStorageTime(generalDTO.getStorageTime());
        } else if (dto instanceof OaApprovalApplicationStoragePropertyDTO) {
            OaApprovalApplicationStoragePropertyDTO propertyDTO = (OaApprovalApplicationStoragePropertyDTO) dto;
            storage.setTitle(propertyDTO.getTitle());
            storage.setAssetTypeId(propertyDTO.getAssetTypeId());
            storage.setStorageType(propertyDTO.getStorageType());
            storage.setStorageTime(propertyDTO.getStorageTime());
        } else if (dto instanceof OaApprovalApplicationStorageVehicleDTO) {
            OaApprovalApplicationStorageVehicleDTO vehicleDTO = (OaApprovalApplicationStorageVehicleDTO) dto;
            storage.setTitle(vehicleDTO.getTitle());
            storage.setAssetTypeId(vehicleDTO.getAssetTypeId());
            storage.setStorageType(vehicleDTO.getStorageType());
            storage.setStorageTime(vehicleDTO.getStorageTime());
        }
        return storage;
    }
    /**
     * 生成申请单号
     * 格式:RK + 年月日 + 3位序号
     */
    private String generateApplicationCode() {
        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String prefix = "RK" + dateStr;
        Long count = oaApprovalApplicationsService.lambdaQuery()
                .like(OaApprovalApplications::getApplicationCode, prefix)
                .ge(OaApprovalApplications::getCreateTime, LocalDate.now().atStartOfDay())
                .lt(OaApprovalApplications::getCreateTime, LocalDate.now().plusDays(1).atStartOfDay())
                .count();
        int sequence = (count != null ? count.intValue() : 0) + 1;
        String sequenceStr = String.format("%03d", sequence);
        return prefix + sequenceStr;
    }
    /**
     * 生成资产编码
     * 格式:资产类型一级分类简写+资产类型子类简写+入库日期+【-】+数量顺序编号(4位)
     * 例如:GDFC20250917-0001
     */
    private String generateAssetCode(Integer assetTypeId, LocalDate storageDate) {
        // 根据资产类型ID获取资产编码前缀
        String typeCodePrefix = assetTypeService.getAssetCodePrefix(assetTypeId);
        String dateStr = storageDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String prefix = typeCodePrefix + dateStr + "-";
        // 查询当天该类型资产的数量
        Long count = assetMainService.lambdaQuery()
                .like(AssetMain::getAssetCode, prefix)
                .ge(AssetMain::getCreateTime, storageDate.atStartOfDay())
                .lt(AssetMain::getCreateTime, storageDate.plusDays(1).atStartOfDay())
                .count();
        int sequence = (count != null ? count.intValue() : 0) + 1;
        String sequenceStr = String.format("%04d", sequence);
        return prefix + sequenceStr;
    }
}