feat: 新增宠物管理模块及相关服务更新
This commit is contained in:
parent
b4cbbb6939
commit
5b19922fd3
@ -67,6 +67,9 @@ public class AppointmentController {
|
|||||||
if (params.containsKey("remark") && params.get("remark") != null) {
|
if (params.containsKey("remark") && params.get("remark") != null) {
|
||||||
appointment.setRemark(params.get("remark").toString());
|
appointment.setRemark(params.get("remark").toString());
|
||||||
}
|
}
|
||||||
|
if (params.containsKey("petId") && params.get("petId") != null && !params.get("petId").toString().isBlank()) {
|
||||||
|
appointment.setPetId(Long.valueOf(params.get("petId").toString()));
|
||||||
|
}
|
||||||
|
|
||||||
Appointment created = appointmentService.create(appointment);
|
Appointment created = appointmentService.create(appointment);
|
||||||
return Map.of("code", 200, "message", "创建成功", "data", created);
|
return Map.of("code", 200, "message", "创建成功", "data", created);
|
||||||
|
|||||||
58
src/main/java/com/petstore/controller/PetController.java
Normal file
58
src/main/java/com/petstore/controller/PetController.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package com.petstore.controller;
|
||||||
|
|
||||||
|
import com.petstore.entity.Pet;
|
||||||
|
import com.petstore.service.PetService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/pet")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@CrossOrigin
|
||||||
|
public class PetController {
|
||||||
|
private final PetService petService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表:传 ownerUserId= 查该客户全部宠物;传 storeId= 查本店预约关联出现过的宠物(商家/员工)
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public Map<String, Object> list(@RequestParam(required = false) Long ownerUserId,
|
||||||
|
@RequestParam(required = false) Long storeId) {
|
||||||
|
if (ownerUserId != null) {
|
||||||
|
return Map.of("code", 200, "data", petService.listByOwner(ownerUserId));
|
||||||
|
}
|
||||||
|
if (storeId != null) {
|
||||||
|
return Map.of("code", 200, "data", petService.listByStoreServed(storeId));
|
||||||
|
}
|
||||||
|
return Map.of("code", 400, "message", "请传 ownerUserId 或 storeId");
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
public Map<String, Object> create(@RequestBody Pet pet) {
|
||||||
|
return petService.create(pet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
public Map<String, Object> update(@RequestBody Map<String, Object> body) {
|
||||||
|
Long operatorUserId = Long.valueOf(body.get("operatorUserId").toString());
|
||||||
|
String role = body.get("role").toString();
|
||||||
|
Pet input = new Pet();
|
||||||
|
input.setId(Long.valueOf(body.get("id").toString()));
|
||||||
|
if (body.containsKey("name")) input.setName(body.get("name").toString());
|
||||||
|
if (body.containsKey("petType")) input.setPetType(body.get("petType").toString());
|
||||||
|
if (body.containsKey("breed")) input.setBreed(body.get("breed") != null ? body.get("breed").toString() : null);
|
||||||
|
if (body.containsKey("avatar")) input.setAvatar(body.get("avatar") != null ? body.get("avatar").toString() : null);
|
||||||
|
if (body.containsKey("remark")) input.setRemark(body.get("remark") != null ? body.get("remark").toString() : null);
|
||||||
|
return petService.update(operatorUserId, role, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
public Map<String, Object> delete(@RequestParam Long id,
|
||||||
|
@RequestParam Long operatorUserId,
|
||||||
|
@RequestParam String role) {
|
||||||
|
return petService.delete(id, operatorUserId, role);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,8 +17,9 @@ public class ServiceTypeController {
|
|||||||
private final ServiceTypeService serviceTypeService;
|
private final ServiceTypeService serviceTypeService;
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public Map<String, Object> list(@RequestParam Long storeId) {
|
public Map<String, Object> list(@RequestParam(required = false) Long storeId) {
|
||||||
List<ServiceType> list = serviceTypeService.getByStoreId(storeId);
|
List<ServiceType> list =
|
||||||
|
storeId == null ? serviceTypeService.listSystemDefaultsOnly() : serviceTypeService.getByStoreId(storeId);
|
||||||
return Map.of("code", 200, "data", list);
|
return Map.of("code", 200, "data", list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,9 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/store")
|
@RequestMapping("/api/store")
|
||||||
@ -25,6 +27,26 @@ public class StoreController {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户预约:门店列表(不含邀请码等敏感字段)
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public Map<String, Object> list() {
|
||||||
|
List<Store> all = storeService.listAll();
|
||||||
|
List<Map<String, Object>> rows = all.stream().map(s -> {
|
||||||
|
Map<String, Object> m = new HashMap<>();
|
||||||
|
m.put("id", s.getId());
|
||||||
|
m.put("name", s.getName());
|
||||||
|
m.put("address", s.getAddress());
|
||||||
|
m.put("latitude", s.getLatitude());
|
||||||
|
m.put("longitude", s.getLongitude());
|
||||||
|
m.put("phone", s.getPhone());
|
||||||
|
m.put("logo", s.getLogo());
|
||||||
|
return m;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
return Map.of("code", 200, "data", rows);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/get")
|
@GetMapping("/get")
|
||||||
public Map<String, Object> get(@RequestParam Long id) {
|
public Map<String, Object> get(@RequestParam Long id) {
|
||||||
Store store = storeService.findById(id);
|
Store store = storeService.findById(id);
|
||||||
|
|||||||
@ -26,6 +26,10 @@ public class Appointment {
|
|||||||
@Column(name = "user_id")
|
@Column(name = "user_id")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
|
/** 关联宠物档案(可选,用于本店「服务过的宠物」统计) */
|
||||||
|
@Column(name = "pet_id")
|
||||||
|
private Long petId;
|
||||||
|
|
||||||
/** 技师ID,开始服务时赋值 */
|
/** 技师ID,开始服务时赋值 */
|
||||||
@Column(name = "assigned_user_id")
|
@Column(name = "assigned_user_id")
|
||||||
private Long assignedUserId;
|
private Long assignedUserId;
|
||||||
|
|||||||
43
src/main/java/com/petstore/entity/Pet.java
Normal file
43
src/main/java/com/petstore/entity/Pet.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package com.petstore.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 宠物档案(归属某客户;商家/员工通过预约关联查看本店服务过的宠物)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Entity
|
||||||
|
@Table(name = "t_pet")
|
||||||
|
public class Pet {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 昵称 */
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/** 类型:猫/狗/其他 */
|
||||||
|
@Column(name = "pet_type")
|
||||||
|
private String petType;
|
||||||
|
|
||||||
|
/** 品种(可选) */
|
||||||
|
private String breed;
|
||||||
|
|
||||||
|
/** 头像相对路径 */
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
/** 所属用户(客户) */
|
||||||
|
@Column(name = "owner_user_id")
|
||||||
|
private Long ownerUserId;
|
||||||
|
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Column(name = "create_time")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Column(name = "update_time")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
17
src/main/java/com/petstore/mapper/PetMapper.java
Normal file
17
src/main/java/com/petstore/mapper/PetMapper.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package com.petstore.mapper;
|
||||||
|
|
||||||
|
import com.petstore.entity.Pet;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface PetMapper extends JpaRepository<Pet, Long> {
|
||||||
|
|
||||||
|
List<Pet> findByOwnerUserIdOrderByUpdateTimeDesc(Long ownerUserId);
|
||||||
|
|
||||||
|
/** 本店预约中关联过的宠物(预约.pet_id 指向该宠物) */
|
||||||
|
@Query("SELECT DISTINCT p FROM Pet p, Appointment a WHERE a.petId = p.id AND a.storeId = :storeId ORDER BY p.updateTime DESC")
|
||||||
|
List<Pet> findDistinctPetsServedAtStore(@Param("storeId") Long storeId);
|
||||||
|
}
|
||||||
@ -8,4 +8,7 @@ import java.util.List;
|
|||||||
public interface ServiceTypeMapper extends JpaRepository<ServiceType, Long> {
|
public interface ServiceTypeMapper extends JpaRepository<ServiceType, Long> {
|
||||||
List<ServiceType> findByStoreIdOrStoreIdIsNull(Long storeId);
|
List<ServiceType> findByStoreIdOrStoreIdIsNull(Long storeId);
|
||||||
List<ServiceType> findByStoreId(Long storeId);
|
List<ServiceType> findByStoreId(Long storeId);
|
||||||
|
|
||||||
|
/** 系统内置(store_id 为空) */
|
||||||
|
List<ServiceType> findByStoreIdIsNull();
|
||||||
}
|
}
|
||||||
|
|||||||
98
src/main/java/com/petstore/service/PetService.java
Normal file
98
src/main/java/com/petstore/service/PetService.java
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package com.petstore.service;
|
||||||
|
|
||||||
|
import com.petstore.entity.Pet;
|
||||||
|
import com.petstore.mapper.PetMapper;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PetService {
|
||||||
|
private final PetMapper petMapper;
|
||||||
|
|
||||||
|
/** 客户:仅自己的宠物 */
|
||||||
|
public List<Pet> listByOwner(Long ownerUserId) {
|
||||||
|
if (ownerUserId == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return petMapper.findByOwnerUserIdOrderByUpdateTimeDesc(ownerUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 商家/员工:本店预约中关联过的宠物(预约带 pet_id) */
|
||||||
|
public List<Pet> listByStoreServed(Long storeId) {
|
||||||
|
if (storeId == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return petMapper.findDistinctPetsServedAtStore(storeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> create(Pet pet) {
|
||||||
|
if (pet.getName() == null || pet.getName().isBlank()) {
|
||||||
|
return Map.of("code", 400, "message", "请填写宠物名字");
|
||||||
|
}
|
||||||
|
if (pet.getPetType() == null || pet.getPetType().isBlank()) {
|
||||||
|
return Map.of("code", 400, "message", "请选择宠物类型");
|
||||||
|
}
|
||||||
|
if (pet.getOwnerUserId() == null) {
|
||||||
|
return Map.of("code", 400, "message", "缺少所属用户");
|
||||||
|
}
|
||||||
|
pet.setCreateTime(LocalDateTime.now());
|
||||||
|
pet.setUpdateTime(LocalDateTime.now());
|
||||||
|
Pet saved = petMapper.save(pet);
|
||||||
|
return Map.of("code", 200, "message", "保存成功", "data", saved);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> update(Long operatorUserId, String role, Pet input) {
|
||||||
|
if (input.getId() == null) {
|
||||||
|
return Map.of("code", 400, "message", "缺少宠物ID");
|
||||||
|
}
|
||||||
|
Optional<Pet> opt = petMapper.findById(input.getId());
|
||||||
|
if (opt.isEmpty()) {
|
||||||
|
return Map.of("code", 404, "message", "宠物不存在");
|
||||||
|
}
|
||||||
|
Pet pet = opt.get();
|
||||||
|
if ("customer".equals(role)) {
|
||||||
|
if (!pet.getOwnerUserId().equals(operatorUserId)) {
|
||||||
|
return Map.of("code", 403, "message", "无权修改该宠物");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Map.of("code", 403, "message", "仅客户可编辑自己的宠物档案");
|
||||||
|
}
|
||||||
|
if (input.getName() != null && !input.getName().isBlank()) {
|
||||||
|
pet.setName(input.getName());
|
||||||
|
}
|
||||||
|
if (input.getPetType() != null && !input.getPetType().isBlank()) {
|
||||||
|
pet.setPetType(input.getPetType());
|
||||||
|
}
|
||||||
|
if (input.getBreed() != null) {
|
||||||
|
pet.setBreed(input.getBreed());
|
||||||
|
}
|
||||||
|
if (input.getAvatar() != null) {
|
||||||
|
pet.setAvatar(input.getAvatar());
|
||||||
|
}
|
||||||
|
if (input.getRemark() != null) {
|
||||||
|
pet.setRemark(input.getRemark());
|
||||||
|
}
|
||||||
|
pet.setUpdateTime(LocalDateTime.now());
|
||||||
|
petMapper.save(pet);
|
||||||
|
return Map.of("code", 200, "message", "更新成功", "data", pet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> delete(Long petId, Long operatorUserId, String role) {
|
||||||
|
Optional<Pet> opt = petMapper.findById(petId);
|
||||||
|
if (opt.isEmpty()) {
|
||||||
|
return Map.of("code", 404, "message", "宠物不存在");
|
||||||
|
}
|
||||||
|
Pet pet = opt.get();
|
||||||
|
if (!"customer".equals(role) || !pet.getOwnerUserId().equals(operatorUserId)) {
|
||||||
|
return Map.of("code", 403, "message", "无权删除");
|
||||||
|
}
|
||||||
|
petMapper.deleteById(petId);
|
||||||
|
return Map.of("code", 200, "message", "已删除");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,6 +18,11 @@ public class ServiceTypeService {
|
|||||||
return serviceTypeMapper.findByStoreIdOrStoreIdIsNull(storeId);
|
return serviceTypeMapper.findByStoreIdOrStoreIdIsNull(storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 仅系统默认(未传门店或 C 端尚未绑定门店时用于展示可选名称) */
|
||||||
|
public List<ServiceType> listSystemDefaultsOnly() {
|
||||||
|
return serviceTypeMapper.findByStoreIdIsNull();
|
||||||
|
}
|
||||||
|
|
||||||
/** 老板新增服务类型 */
|
/** 老板新增服务类型 */
|
||||||
public ServiceType create(Long storeId, String name) {
|
public ServiceType create(Long storeId, String name) {
|
||||||
ServiceType st = new ServiceType();
|
ServiceType st = new ServiceType();
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -28,6 +29,11 @@ public class StoreService {
|
|||||||
return storeMapper.findByInviteCode(code);
|
return storeMapper.findByInviteCode(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** C 端预约:列出全部门店供选择 */
|
||||||
|
public List<Store> listAll() {
|
||||||
|
return storeMapper.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
public Store update(Store store) {
|
public Store update(Store store) {
|
||||||
store.setUpdateTime(LocalDateTime.now());
|
store.setUpdateTime(LocalDateTime.now());
|
||||||
return storeMapper.save(store);
|
return storeMapper.save(store);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user