diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/address/SysDeptBuildingDto.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/address/SysDeptBuildingDto.java new file mode 100644 index 000000000..61a912344 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/address/SysDeptBuildingDto.java @@ -0,0 +1,12 @@ +package com.bsd.pjcloud.admin.api.dto.address; + +import com.bsd.pjcloud.admin.api.entity.address.SysDeptBuildingEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "单位楼栋") +public class SysDeptBuildingDto extends SysDeptBuildingEntity { +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/address/SysUserAddressDto.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/address/SysUserAddressDto.java new file mode 100644 index 000000000..98c733854 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/address/SysUserAddressDto.java @@ -0,0 +1,12 @@ +package com.bsd.pjcloud.admin.api.dto.address; + +import com.bsd.pjcloud.admin.api.entity.address.SysUserAddressEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "用户配送地址") +public class SysUserAddressDto extends SysUserAddressEntity { +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/address/SysDeptBuildingEntity.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/address/SysDeptBuildingEntity.java new file mode 100644 index 000000000..919b2f040 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/address/SysDeptBuildingEntity.java @@ -0,0 +1,63 @@ +package com.bsd.pjcloud.admin.api.entity.address; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.bsd.pjcloud.common.core.util.TenantTable; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 单位(部门)下楼栋,后台维护,前端下拉 + */ +@Data +@TenantTable +@TableName("sys_dept_building") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "单位楼栋") +public class SysDeptBuildingEntity extends Model { + + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "主键") + private Long id; + + @NotNull(message = "单位不能为空") + @Schema(description = "单位/部门ID") + private Long deptId; + + @NotBlank(message = "楼栋名称不能为空") + @Schema(description = "楼栋名称") + private String buildingName; + + @NotNull(message = "排序不能为空") + @Schema(description = "排序") + private Integer sortOrder; + + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建人") + private String createBy; + + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改人") + private String updateBy; + + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改时间") + private LocalDateTime updateTime; + + @TableLogic + @TableField(fill = FieldFill.INSERT) + @Schema(description = "删除标记") + private String delFlag; + + @Schema(description = "租户ID") + private Long tenantId; +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/address/SysUserAddressEntity.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/address/SysUserAddressEntity.java new file mode 100644 index 000000000..59f641c85 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/address/SysUserAddressEntity.java @@ -0,0 +1,72 @@ +package com.bsd.pjcloud.admin.api.entity.address; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.bsd.pjcloud.common.core.util.TenantTable; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 用户配送地址:单位(部门)+楼栋+房间号,可多条、一条默认 + */ +@Data +@TenantTable +@TableName("sys_user_address") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "用户配送地址") +public class SysUserAddressEntity extends Model { + + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "主键") + private Long id; + + @Schema(description = "用户ID(服务端写入,客户端不必传)") + private Long userId; + + @NotNull(message = "单位不能为空") + @Schema(description = "单位/部门ID") + private Long deptId; + + @NotNull(message = "楼栋不能为空") + @Schema(description = "楼栋ID") + private Long buildingId; + + @NotBlank(message = "房间号不能为空") + @Schema(description = "房间号") + private String roomNo; + + @Schema(description = "地址标签") + private String addressLabel; + + @Schema(description = "是否默认 1是 0否") + private String isDefault; + + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建人") + private String createBy; + + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改人") + private String updateBy; + + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改时间") + private LocalDateTime updateTime; + + @TableLogic + @TableField(fill = FieldFill.INSERT) + @Schema(description = "删除标记") + private String delFlag; + + @Schema(description = "租户ID") + private Long tenantId; +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/address/SysUserAddressVo.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/address/SysUserAddressVo.java new file mode 100644 index 000000000..1c3327cff --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/address/SysUserAddressVo.java @@ -0,0 +1,44 @@ +package com.bsd.pjcloud.admin.api.vo.address; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户配送地址(含单位名、楼栋名与拼接展示) + */ +@Data +@Schema(description = "用户配送地址VO") +public class SysUserAddressVo implements Serializable { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "用户ID") + private Long userId; + + @Schema(description = "单位/部门ID") + private Long deptId; + + @Schema(description = "单位名称(部门名称)") + private String deptName; + + @Schema(description = "楼栋ID") + private Long buildingId; + + @Schema(description = "楼栋名称") + private String buildingName; + + @Schema(description = "房间号") + private String roomNo; + + @Schema(description = "地址标签") + private String addressLabel; + + @Schema(description = "是否默认 1是 0否") + private String isDefault; + + @Schema(description = "完整展示:单位+楼栋+房间号") + private String fullAddress; +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/address/SysDeptBuildingController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/address/SysDeptBuildingController.java new file mode 100644 index 000000000..8685411d0 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/address/SysDeptBuildingController.java @@ -0,0 +1,84 @@ +package com.bsd.pjcloud.admin.controller.address; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.admin.api.dto.address.SysDeptBuildingDto; +import com.bsd.pjcloud.admin.api.entity.address.SysDeptBuildingEntity; +import com.bsd.pjcloud.admin.service.SysDeptBuildingService; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.log.annotation.SysLog; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.http.HttpHeaders; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 单位(部门)下楼栋维护,供订餐选址楼栋下拉 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/sysDeptBuilding") +@Tag(name = "单位楼栋管理") +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class SysDeptBuildingController { + + private final SysDeptBuildingService sysDeptBuildingService; + + /** + * 按单位查询楼栋(下单/维护地址时下拉;登录即可) + */ + @GetMapping("/list-by-dept") + @Operation(summary = "按单位ID查询楼栋列表") + public R> listByDept(@RequestParam("deptId") Long deptId) { + return R.ok(sysDeptBuildingService.listByDeptId(deptId)); + } + + @GetMapping("/page") + @Operation(summary = "分页查询单位楼栋(管理端)") + @PreAuthorize("@pms.hasPermission('admin_sysDeptBuilding_view')") + public R> page(@ParameterObject Page page, + @RequestParam(value = "deptId", required = false) Long deptId) { + return R.ok(sysDeptBuildingService.page(page, Wrappers.lambdaQuery() + .eq(deptId != null, SysDeptBuildingEntity::getDeptId, deptId) + .orderByAsc(SysDeptBuildingEntity::getSortOrder) + .orderByAsc(SysDeptBuildingEntity::getId))); + } + + @GetMapping("/{id}") + @Operation(summary = "楼栋详情") + @PreAuthorize("@pms.hasPermission('admin_sysDeptBuilding_view')") + public R getById(@PathVariable Long id) { + return R.ok(sysDeptBuildingService.getById(id)); + } + + @SysLog("新增单位楼栋") + @PostMapping + @PreAuthorize("@pms.hasPermission('admin_sysDeptBuilding_add')") + public R save(@Valid @RequestBody SysDeptBuildingDto dto) { + return R.ok(sysDeptBuildingService.create(dto)); + } + + @SysLog("修改单位楼栋") + @PutMapping + @PreAuthorize("@pms.hasPermission('admin_sysDeptBuilding_edit')") + public R update(@Valid @RequestBody SysDeptBuildingDto dto) { + sysDeptBuildingService.edit(dto); + return R.ok(); + } + + @SysLog("删除单位楼栋") + @DeleteMapping + @PreAuthorize("@pms.hasPermission('admin_sysDeptBuilding_del')") + public R remove(@RequestBody Long[] ids) { + sysDeptBuildingService.removeBuildingsByIds(CollUtil.toList(ids)); + return R.ok(); + } +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/address/SysUserAddressController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/address/SysUserAddressController.java new file mode 100644 index 000000000..055dc8103 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/address/SysUserAddressController.java @@ -0,0 +1,84 @@ +package com.bsd.pjcloud.admin.controller.address; + +import com.bsd.pjcloud.admin.api.dto.address.SysUserAddressDto; +import com.bsd.pjcloud.admin.api.vo.address.SysUserAddressVo; +import com.bsd.pjcloud.admin.service.SysUserAddressService; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.log.annotation.SysLog; +import com.bsd.pjcloud.common.security.annotation.Inner; +import com.bsd.pjcloud.common.security.service.PjcloudUser; +import com.bsd.pjcloud.common.security.util.SecurityUtils; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 用户配送地址:单位(部门)+楼栋+房间号,多地址与默认地址 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/sysUserAddress") +@Tag(name = "用户配送地址") +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class SysUserAddressController { + + private final SysUserAddressService sysUserAddressService; + + /* ---------- App / 当前用户 ---------- */ + + @GetMapping("/app/list") + @Operation(summary = "当前用户配送地址列表") + public R> appList() { + PjcloudUser user = SecurityUtils.getUser(); + return R.ok(sysUserAddressService.listVoByUserId(user.getId())); + } + + @SysLog("新增用户配送地址") + @PostMapping("/app") + @Operation(summary = "新增配送地址") + public R appSave(@Valid @RequestBody SysUserAddressDto dto) { + PjcloudUser user = SecurityUtils.getUser(); + return R.ok(sysUserAddressService.saveForUser(user.getId(), dto)); + } + + @SysLog("修改用户配送地址") + @PutMapping("/app") + @Operation(summary = "修改配送地址") + public R appUpdate(@Valid @RequestBody SysUserAddressDto dto) { + PjcloudUser user = SecurityUtils.getUser(); + sysUserAddressService.updateForUser(user.getId(), dto); + return R.ok(); + } + + @SysLog("删除用户配送地址") + @DeleteMapping("/app/{id}") + @Operation(summary = "删除配送地址") + public R appRemove(@PathVariable Long id) { + PjcloudUser user = SecurityUtils.getUser(); + sysUserAddressService.removeForUser(user.getId(), id); + return R.ok(); + } + + @PutMapping("/app/default/{id}") + @Operation(summary = "设为默认配送地址") + public R appSetDefault(@PathVariable Long id) { + PjcloudUser user = SecurityUtils.getUser(); + sysUserAddressService.setDefault(user.getId(), id); + return R.ok(); + } + + /* ---------- 服务间(订餐等) ---------- */ + + @Inner + @GetMapping("/inner/list-by-user-id") + @Operation(summary = "按用户ID查询配送地址(内部)") + public R> innerListByUserId(@RequestParam Long userId) { + return R.ok(sysUserAddressService.listVoByUserId(userId)); + } +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/address/SysDeptBuildingMapper.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/address/SysDeptBuildingMapper.java new file mode 100644 index 000000000..d5c48f554 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/address/SysDeptBuildingMapper.java @@ -0,0 +1,9 @@ +package com.bsd.pjcloud.admin.mapper.address; + +import com.bsd.pjcloud.admin.api.entity.address.SysDeptBuildingEntity; +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysDeptBuildingMapper extends PjcloudBaseMapper { +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/address/SysUserAddressMapper.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/address/SysUserAddressMapper.java new file mode 100644 index 000000000..caf6aa77d --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/address/SysUserAddressMapper.java @@ -0,0 +1,9 @@ +package com.bsd.pjcloud.admin.mapper.address; + +import com.bsd.pjcloud.admin.api.entity.address.SysUserAddressEntity; +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysUserAddressMapper extends PjcloudBaseMapper { +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysDeptBuildingService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysDeptBuildingService.java new file mode 100644 index 000000000..4392a9310 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysDeptBuildingService.java @@ -0,0 +1,21 @@ +package com.bsd.pjcloud.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.admin.api.dto.address.SysDeptBuildingDto; +import com.bsd.pjcloud.admin.api.entity.address.SysDeptBuildingEntity; + +import java.util.List; + +public interface SysDeptBuildingService extends IService { + + List listByDeptId(Long deptId); + + Long create(SysDeptBuildingDto dto); + + void edit(SysDeptBuildingDto dto); + + /** + * 批量删除;若楼栋仍被用户地址引用则拒绝 + */ + void removeBuildingsByIds(List ids); +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserAddressService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserAddressService.java new file mode 100644 index 000000000..2c4a38ea1 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserAddressService.java @@ -0,0 +1,21 @@ +package com.bsd.pjcloud.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.admin.api.dto.address.SysUserAddressDto; +import com.bsd.pjcloud.admin.api.entity.address.SysUserAddressEntity; +import com.bsd.pjcloud.admin.api.vo.address.SysUserAddressVo; + +import java.util.List; + +public interface SysUserAddressService extends IService { + + List listVoByUserId(Long userId); + + Long saveForUser(Long userId, SysUserAddressDto dto); + + void updateForUser(Long userId, SysUserAddressDto dto); + + void removeForUser(Long userId, Long addressId); + + void setDefault(Long userId, Long addressId); +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/address/SysDeptBuildingServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/address/SysDeptBuildingServiceImpl.java new file mode 100644 index 000000000..e95d6b405 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/address/SysDeptBuildingServiceImpl.java @@ -0,0 +1,91 @@ +package com.bsd.pjcloud.admin.service.impl.address; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.admin.api.dto.address.SysDeptBuildingDto; +import com.bsd.pjcloud.admin.api.entity.address.SysDeptBuildingEntity; +import com.bsd.pjcloud.admin.api.entity.address.SysUserAddressEntity; +import com.bsd.pjcloud.admin.mapper.address.SysDeptBuildingMapper; +import com.bsd.pjcloud.admin.mapper.address.SysUserAddressMapper; +import com.bsd.pjcloud.admin.service.SysDeptBuildingService; +import com.bsd.pjcloud.admin.service.SysDeptService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class SysDeptBuildingServiceImpl extends ServiceImpl + implements SysDeptBuildingService { + + private final SysDeptService sysDeptService; + private final SysUserAddressMapper sysUserAddressMapper; + + @Override + public List listByDeptId(Long deptId) { + return list(Wrappers.lambdaQuery() + .eq(SysDeptBuildingEntity::getDeptId, deptId) + .orderByAsc(SysDeptBuildingEntity::getSortOrder) + .orderByAsc(SysDeptBuildingEntity::getId)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long create(SysDeptBuildingDto dto) { + if (sysDeptService.getById(dto.getDeptId()) == null) { + throw new IllegalArgumentException("单位不存在"); + } + if (ObjectUtil.isEmpty(dto.getSortOrder())) { + dto.setSortOrder(0); + } + assertUniqueName(dto.getDeptId(), dto.getBuildingName(), null); + baseMapper.insert(dto); + return dto.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void edit(SysDeptBuildingDto dto) { + if (dto.getId() == null) { + throw new IllegalArgumentException("楼栋ID不能为空"); + } + SysDeptBuildingEntity old = getById(dto.getId()); + if (old == null) { + throw new IllegalArgumentException("楼栋不存在"); + } + if (sysDeptService.getById(dto.getDeptId()) == null) { + throw new IllegalArgumentException("单位不存在"); + } + assertUniqueName(dto.getDeptId(), dto.getBuildingName(), dto.getId()); + baseMapper.updateById(dto); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void removeBuildingsByIds(List ids) { + if (ids == null || ids.isEmpty()) { + return; + } + for (Long buildingId : ids) { + Long cnt = sysUserAddressMapper.selectCount(Wrappers.lambdaQuery() + .eq(SysUserAddressEntity::getBuildingId, buildingId)); + if (cnt != null && cnt > 0) { + throw new IllegalStateException("该楼栋已被用户配送地址引用,无法删除"); + } + } + removeBatchByIds(ids); + } + + private void assertUniqueName(Long deptId, String buildingName, Long excludeId) { + Long cnt = baseMapper.selectCount(Wrappers.lambdaQuery() + .eq(SysDeptBuildingEntity::getDeptId, deptId) + .eq(SysDeptBuildingEntity::getBuildingName, buildingName) + .ne(excludeId != null, SysDeptBuildingEntity::getId, excludeId)); + if (cnt != null && cnt > 0) { + throw new IllegalArgumentException("同一单位下楼栋名称不能重复"); + } + } +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/address/SysUserAddressServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/address/SysUserAddressServiceImpl.java new file mode 100644 index 000000000..c0ace83cb --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/address/SysUserAddressServiceImpl.java @@ -0,0 +1,168 @@ +package com.bsd.pjcloud.admin.service.impl.address; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.admin.api.dto.address.SysUserAddressDto; +import com.bsd.pjcloud.admin.api.entity.SysDept; +import com.bsd.pjcloud.admin.api.entity.address.SysDeptBuildingEntity; +import com.bsd.pjcloud.admin.api.entity.address.SysUserAddressEntity; +import com.bsd.pjcloud.admin.api.vo.address.SysUserAddressVo; +import com.bsd.pjcloud.admin.mapper.address.SysUserAddressMapper; +import com.bsd.pjcloud.admin.service.SysDeptBuildingService; +import com.bsd.pjcloud.admin.service.SysDeptService; +import com.bsd.pjcloud.admin.service.SysUserAddressService; +import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class SysUserAddressServiceImpl extends ServiceImpl + implements SysUserAddressService { + + private final SysDeptService sysDeptService; + private final SysDeptBuildingService sysDeptBuildingService; + + @Override + public List listVoByUserId(Long userId) { + List list = list(Wrappers.lambdaQuery() + .eq(SysUserAddressEntity::getUserId, userId) + .orderByDesc(SysUserAddressEntity::getIsDefault) + .orderByDesc(SysUserAddressEntity::getUpdateTime)); + if (list.isEmpty()) { + return List.of(); + } + List deptIds = list.stream().map(SysUserAddressEntity::getDeptId).distinct().toList(); + List buildingIds = list.stream().map(SysUserAddressEntity::getBuildingId).distinct().toList(); + Map deptMap = sysDeptService.listByIds(deptIds).stream() + .collect(Collectors.toMap(SysDept::getDeptId, d -> d, (a, b) -> a)); + Map buildingMap = sysDeptBuildingService.listByIds(buildingIds).stream() + .collect(Collectors.toMap(SysDeptBuildingEntity::getId, b -> b, (a, c) -> a)); + + List vos = new ArrayList<>(); + for (SysUserAddressEntity e : list) { + vos.add(toVo(e, deptMap.get(e.getDeptId()), buildingMap.get(e.getBuildingId()))); + } + return vos; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long saveForUser(Long userId, SysUserAddressDto dto) { + validateBinding(dto); + dto.setUserId(userId); + if (StrUtil.isBlank(dto.getIsDefault())) { + dto.setIsDefault(YesNoEnum.NO.getCode()); + } + long existing = count(Wrappers.lambdaQuery().eq(SysUserAddressEntity::getUserId, userId)); + if (existing == 0 || YesNoEnum.YES.getCode().equals(dto.getIsDefault())) { + clearDefault(userId); + dto.setIsDefault(YesNoEnum.YES.getCode()); + } + baseMapper.insert(dto); + return dto.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateForUser(Long userId, SysUserAddressDto dto) { + if (dto.getId() == null) { + throw new IllegalArgumentException("地址ID不能为空"); + } + SysUserAddressEntity old = getById(dto.getId()); + if (old == null || !userId.equals(old.getUserId())) { + throw new IllegalArgumentException("地址不存在"); + } + validateBinding(dto); + dto.setUserId(userId); + if (YesNoEnum.YES.getCode().equals(dto.getIsDefault())) { + clearDefault(userId); + dto.setIsDefault(YesNoEnum.YES.getCode()); + } else if (StrUtil.isBlank(dto.getIsDefault())) { + dto.setIsDefault(old.getIsDefault()); + } + baseMapper.updateById(dto); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void removeForUser(Long userId, Long addressId) { + SysUserAddressEntity old = getById(addressId); + if (old == null || !userId.equals(old.getUserId())) { + throw new IllegalArgumentException("地址不存在"); + } + removeById(addressId); + if (YesNoEnum.YES.getCode().equals(old.getIsDefault())) { + List rest = list(Wrappers.lambdaQuery() + .eq(SysUserAddressEntity::getUserId, userId) + .orderByDesc(SysUserAddressEntity::getUpdateTime)); + if (!rest.isEmpty()) { + SysUserAddressEntity first = rest.get(0); + first.setIsDefault(YesNoEnum.YES.getCode()); + updateById(first); + } + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void setDefault(Long userId, Long addressId) { + SysUserAddressEntity entity = getById(addressId); + if (entity == null || !userId.equals(entity.getUserId())) { + throw new IllegalArgumentException("地址不存在"); + } + clearDefault(userId); + entity.setIsDefault(YesNoEnum.YES.getCode()); + updateById(entity); + } + + private void clearDefault(Long userId) { + List defaults = list(Wrappers.lambdaQuery() + .eq(SysUserAddressEntity::getUserId, userId) + .eq(SysUserAddressEntity::getIsDefault, YesNoEnum.YES.getCode())); + for (SysUserAddressEntity d : defaults) { + d.setIsDefault(YesNoEnum.NO.getCode()); + updateById(d); + } + } + + private void validateBinding(SysUserAddressDto dto) { + if (dto.getDeptId() == null || dto.getBuildingId() == null) { + throw new IllegalArgumentException("单位与楼栋不能为空"); + } + if (sysDeptService.getById(dto.getDeptId()) == null) { + throw new IllegalArgumentException("单位不存在"); + } + SysDeptBuildingEntity building = sysDeptBuildingService.getById(dto.getBuildingId()); + if (building == null) { + throw new IllegalArgumentException("楼栋不存在"); + } + if (!building.getDeptId().equals(dto.getDeptId())) { + throw new IllegalArgumentException("所选楼栋不属于该单位"); + } + } + + private static SysUserAddressVo toVo(SysUserAddressEntity e, SysDept dept, SysDeptBuildingEntity building) { + SysUserAddressVo vo = new SysUserAddressVo(); + vo.setId(e.getId()); + vo.setUserId(e.getUserId()); + vo.setDeptId(e.getDeptId()); + vo.setDeptName(dept != null ? dept.getName() : null); + vo.setBuildingId(e.getBuildingId()); + vo.setBuildingName(building != null ? building.getBuildingName() : null); + vo.setRoomNo(e.getRoomNo()); + vo.setAddressLabel(e.getAddressLabel()); + vo.setIsDefault(e.getIsDefault()); + String unit = dept != null ? StrUtil.nullToEmpty(dept.getName()) : ""; + String bname = building != null ? StrUtil.nullToEmpty(building.getBuildingName()) : ""; + vo.setFullAddress(unit + bname + StrUtil.nullToEmpty(e.getRoomNo())); + return vo; + } +}