feat: 优化预约时段支持及门店配置
This commit is contained in:
parent
870190c709
commit
e4410f5794
@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -16,6 +17,21 @@ import java.util.Map;
|
|||||||
public class AppointmentController {
|
public class AppointmentController {
|
||||||
private final AppointmentService appointmentService;
|
private final AppointmentService appointmentService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 门店某日可预约时段(半小时一档,医院挂号式占号)。
|
||||||
|
* date 格式:yyyy-MM-dd
|
||||||
|
*/
|
||||||
|
@GetMapping("/available-slots")
|
||||||
|
public Map<String, Object> availableSlots(@RequestParam Long storeId, @RequestParam String date) {
|
||||||
|
LocalDate d;
|
||||||
|
try {
|
||||||
|
d = LocalDate.parse(date);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Map.of("code", 400, "message", "日期格式应为 yyyy-MM-dd");
|
||||||
|
}
|
||||||
|
return appointmentService.availableSlots(storeId, d);
|
||||||
|
}
|
||||||
|
|
||||||
/** 获取预约列表(员工查自己/老板查全店) */
|
/** 获取预约列表(员工查自己/老板查全店) */
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public Map<String, Object> list(
|
public Map<String, Object> list(
|
||||||
@ -93,8 +109,7 @@ public class AppointmentController {
|
|||||||
appointment.setPetId(Long.valueOf(params.get("petId").toString()));
|
appointment.setPetId(Long.valueOf(params.get("petId").toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Appointment created = appointmentService.create(appointment);
|
return appointmentService.createBooking(appointment);
|
||||||
return Map.of("code", 200, "message", "创建成功", "data", created);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 开始服务:状态变进行中 + 指定技师 */
|
/** 开始服务:状态变进行中 + 指定技师 */
|
||||||
|
|||||||
@ -42,6 +42,12 @@ public class StoreController {
|
|||||||
m.put("longitude", s.getLongitude());
|
m.put("longitude", s.getLongitude());
|
||||||
m.put("phone", s.getPhone());
|
m.put("phone", s.getPhone());
|
||||||
m.put("logo", s.getLogo());
|
m.put("logo", s.getLogo());
|
||||||
|
if (s.getBookingDayStart() != null) {
|
||||||
|
m.put("bookingDayStart", s.getBookingDayStart().toString());
|
||||||
|
}
|
||||||
|
if (s.getBookingLastSlotStart() != null) {
|
||||||
|
m.put("bookingLastSlotStart", s.getBookingLastSlotStart().toString());
|
||||||
|
}
|
||||||
return m;
|
return m;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
return Map.of("code", 200, "data", rows);
|
return Map.of("code", 200, "data", rows);
|
||||||
@ -63,15 +69,19 @@ public class StoreController {
|
|||||||
|
|
||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
public Map<String, Object> update(@RequestBody Store store) {
|
public Map<String, Object> update(@RequestBody Store store) {
|
||||||
Store updated = storeService.update(store);
|
try {
|
||||||
if (updated == null) {
|
Store updated = storeService.update(store);
|
||||||
return Map.of("code", 404, "message", "店铺不存在");
|
if (updated == null) {
|
||||||
|
return Map.of("code", 404, "message", "店铺不存在");
|
||||||
|
}
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("code", 200);
|
||||||
|
result.put("message", "更新成功");
|
||||||
|
result.put("data", updated);
|
||||||
|
return result;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return Map.of("code", 400, "message", e.getMessage() != null ? e.getMessage() : "参数错误");
|
||||||
}
|
}
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
result.put("code", 200);
|
|
||||||
result.put("message", "更新成功");
|
|
||||||
result.put("data", updated);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
|
|||||||
@ -2,7 +2,9 @@ package com.petstore.entity;
|
|||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Entity
|
@Entity
|
||||||
@ -33,6 +35,20 @@ public class Store {
|
|||||||
|
|
||||||
@Column(name = "invite_code")
|
@Column(name = "invite_code")
|
||||||
private String inviteCode;
|
private String inviteCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可预约:每日首个半点号源起始时刻(须为整点或半点)。
|
||||||
|
* 为 null 时后端按默认 09:00 处理。
|
||||||
|
*/
|
||||||
|
@Column(name = "booking_day_start")
|
||||||
|
private LocalTime bookingDayStart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可预约:每日最后一个可约时段的起始时刻(含),须为整点或半点,且不早于 {@link #bookingDayStart}。
|
||||||
|
* 为 null 时后端按默认 21:30 处理。
|
||||||
|
*/
|
||||||
|
@Column(name = "booking_last_slot_start")
|
||||||
|
private LocalTime bookingLastSlotStart;
|
||||||
|
|
||||||
@Column(name = "create_time")
|
@Column(name = "create_time")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|||||||
@ -4,7 +4,10 @@ import com.petstore.entity.Appointment;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -19,4 +22,14 @@ public interface AppointmentMapper extends JpaRepository<Appointment, Long> {
|
|||||||
Page<Appointment> findByStoreIdAndDeletedFalse(Long storeId, Pageable pageable);
|
Page<Appointment> findByStoreIdAndDeletedFalse(Long storeId, Pageable pageable);
|
||||||
Page<Appointment> findByStoreIdAndStatusAndDeletedFalse(Long storeId, String status, Pageable pageable);
|
Page<Appointment> findByStoreIdAndStatusAndDeletedFalse(Long storeId, String status, Pageable pageable);
|
||||||
Optional<Appointment> findByIdAndDeletedFalse(Long id);
|
Optional<Appointment> findByIdAndDeletedFalse(Long id);
|
||||||
|
|
||||||
|
@Query("SELECT a.appointmentTime FROM Appointment a WHERE a.storeId = :storeId AND a.deleted = false AND (a.status IS NULL OR a.status <> 'cancel') AND a.appointmentTime >= :start AND a.appointmentTime < :end")
|
||||||
|
List<LocalDateTime> findOccupiedAppointmentTimes(
|
||||||
|
@Param("storeId") Long storeId,
|
||||||
|
@Param("start") LocalDateTime start,
|
||||||
|
@Param("end") LocalDateTime end
|
||||||
|
);
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(a) > 0 FROM Appointment a WHERE a.storeId = :storeId AND a.appointmentTime = :t AND a.deleted = false AND (a.status IS NULL OR a.status <> 'cancel')")
|
||||||
|
boolean existsActiveBookingAt(@Param("storeId") Long storeId, @Param("t") LocalDateTime t);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,14 +8,23 @@ import org.springframework.data.domain.PageRequest;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AppointmentService {
|
public class AppointmentService {
|
||||||
private final AppointmentMapper appointmentMapper;
|
private final AppointmentMapper appointmentMapper;
|
||||||
|
private final StoreService storeService;
|
||||||
|
|
||||||
// 员工查看自己的预约
|
// 员工查看自己的预约
|
||||||
public List<Appointment> getByUserId(Long userId) {
|
public List<Appointment> getByUserId(Long userId) {
|
||||||
@ -61,11 +70,102 @@ public class AppointmentService {
|
|||||||
return appointmentMapper.findByIdAndDeletedFalse(id).orElse(null);
|
return appointmentMapper.findByIdAndDeletedFalse(id).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Appointment create(Appointment appointment) {
|
/**
|
||||||
|
* 某门店某日:半小时挂号时段列表(已占用 / 已过 / 可约)。
|
||||||
|
*/
|
||||||
|
public Map<String, Object> availableSlots(Long storeId, LocalDate date) {
|
||||||
|
if (storeId == null || date == null) {
|
||||||
|
return Map.of("code", 400, "message", "缺少门店或日期");
|
||||||
|
}
|
||||||
|
com.petstore.entity.Store store = storeService.findById(storeId);
|
||||||
|
if (store == null) {
|
||||||
|
return Map.of("code", 404, "message", "门店不存在");
|
||||||
|
}
|
||||||
|
StoreBookingWindow window = StoreBookingWindow.fromStore(store);
|
||||||
|
LocalDateTime dayStart = date.atStartOfDay();
|
||||||
|
LocalDateTime dayEnd = date.plusDays(1).atStartOfDay();
|
||||||
|
List<LocalDateTime> occupiedRaw = appointmentMapper.findOccupiedAppointmentTimes(storeId, dayStart, dayEnd);
|
||||||
|
Set<LocalDateTime> occupied = new HashSet<>();
|
||||||
|
for (LocalDateTime t : occupiedRaw) {
|
||||||
|
occupied.add(AppointmentSlotSupport.alignToHalfHour(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
List<Map<String, Object>> rows = new ArrayList<>();
|
||||||
|
for (LocalDateTime slotStart : AppointmentSlotSupport.allSlotStartsOnDay(date, window)) {
|
||||||
|
String hhmm = formatHhMm(slotStart);
|
||||||
|
boolean past = slotStart.isBefore(now);
|
||||||
|
boolean taken = occupied.contains(slotStart);
|
||||||
|
boolean available = !past && !taken;
|
||||||
|
String reason = null;
|
||||||
|
if (past) {
|
||||||
|
reason = "已过时段";
|
||||||
|
} else if (taken) {
|
||||||
|
reason = "已约满";
|
||||||
|
}
|
||||||
|
Map<String, Object> one = new LinkedHashMap<>();
|
||||||
|
one.put("time", hhmm);
|
||||||
|
one.put("available", available);
|
||||||
|
if (reason != null) {
|
||||||
|
one.put("reason", reason);
|
||||||
|
}
|
||||||
|
rows.add(one);
|
||||||
|
}
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
data.put("slots", rows);
|
||||||
|
data.put("dayStart", window.dayStart().toString());
|
||||||
|
data.put("lastSlotStart", window.lastSlotStart().toString());
|
||||||
|
return Map.of("code", 200, "data", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatHhMm(LocalDateTime dt) {
|
||||||
|
return String.format("%02d:%02d", dt.getHour(), dt.getMinute());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建预约:半小时占号,取消({@code cancel})不占号。
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Map<String, Object> createBooking(Appointment appointment) {
|
||||||
|
if (appointment.getAppointmentTime() == null) {
|
||||||
|
return Map.of("code", 400, "message", "请填写预约时间");
|
||||||
|
}
|
||||||
|
LocalDateTime t = AppointmentSlotSupport.alignToHalfHour(appointment.getAppointmentTime());
|
||||||
|
appointment.setAppointmentTime(t);
|
||||||
|
if (appointment.getStoreId() == null) {
|
||||||
|
return Map.of("code", 400, "message", "缺少门店");
|
||||||
|
}
|
||||||
|
com.petstore.entity.Store store = storeService.findById(appointment.getStoreId());
|
||||||
|
if (store == null) {
|
||||||
|
return Map.of("code", 404, "message", "门店不存在");
|
||||||
|
}
|
||||||
|
StoreBookingWindow window = StoreBookingWindow.fromStore(store);
|
||||||
|
if (!AppointmentSlotSupport.isWithinBookableWindow(t, window)) {
|
||||||
|
return Map.of(
|
||||||
|
"code", 400,
|
||||||
|
"message",
|
||||||
|
String.format(
|
||||||
|
"仅可预约 %s~%s 的半点档",
|
||||||
|
window.dayStart(),
|
||||||
|
window.lastSlotStart()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!t.isAfter(LocalDateTime.now())) {
|
||||||
|
return Map.of("code", 400, "message", "不能预约当前及已过去的时段");
|
||||||
|
}
|
||||||
|
if (appointmentMapper.existsActiveBookingAt(appointment.getStoreId(), t)) {
|
||||||
|
return Map.of("code", 409, "message", "该时段已被占用,请更换其它时段");
|
||||||
|
}
|
||||||
appointment.setCreateTime(LocalDateTime.now());
|
appointment.setCreateTime(LocalDateTime.now());
|
||||||
appointment.setUpdateTime(LocalDateTime.now());
|
appointment.setUpdateTime(LocalDateTime.now());
|
||||||
appointment.setDeleted(false);
|
appointment.setDeleted(false);
|
||||||
return appointmentMapper.save(appointment);
|
Appointment saved = appointmentMapper.save(appointment);
|
||||||
|
Map<String, Object> ok = new HashMap<>();
|
||||||
|
ok.put("code", 200);
|
||||||
|
ok.put("message", "创建成功");
|
||||||
|
ok.put("data", saved);
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Appointment updateStatus(Long id, String status) {
|
public Appointment updateStatus(Long id, String status) {
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
package com.petstore.service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预约时段:半小时一档(与前端 halfHourTime 对齐)。
|
||||||
|
*/
|
||||||
|
public final class AppointmentSlotSupport {
|
||||||
|
|
||||||
|
private AppointmentSlotSupport() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将时间对齐到半点档(00 或 30 分,秒纳秒归零)。
|
||||||
|
*/
|
||||||
|
public static LocalDateTime alignToHalfHour(LocalDateTime dt) {
|
||||||
|
if (dt == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int m = dt.getMinute();
|
||||||
|
int nm = m < 30 ? 0 : 30;
|
||||||
|
return dt.withMinute(nm).withSecond(0).withNano(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWithinBookableWindow(LocalDateTime slotStart, StoreBookingWindow window) {
|
||||||
|
if (slotStart == null || window == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LocalTime t = slotStart.toLocalTime();
|
||||||
|
return !t.isBefore(window.dayStart()) && !t.isAfter(window.lastSlotStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在给定放号窗口内,生成某日所有半点起始时刻(含首尾)。
|
||||||
|
*/
|
||||||
|
public static List<LocalDateTime> allSlotStartsOnDay(LocalDate date, StoreBookingWindow window) {
|
||||||
|
List<LocalDateTime> list = new ArrayList<>();
|
||||||
|
LocalDateTime cur = LocalDateTime.of(date, window.dayStart());
|
||||||
|
LocalDateTime end = LocalDateTime.of(date, window.lastSlotStart());
|
||||||
|
while (!cur.isAfter(end)) {
|
||||||
|
list.add(cur);
|
||||||
|
cur = cur.plusMinutes(30);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/main/java/com/petstore/service/StoreBookingWindow.java
Normal file
36
src/main/java/com/petstore/service/StoreBookingWindow.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package com.petstore.service;
|
||||||
|
|
||||||
|
import com.petstore.entity.Store;
|
||||||
|
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 门店可预约放号窗口(半小时一档的首末时刻)。
|
||||||
|
*/
|
||||||
|
public record StoreBookingWindow(LocalTime dayStart, LocalTime lastSlotStart) {
|
||||||
|
|
||||||
|
public static final LocalTime DEFAULT_DAY_START = LocalTime.of(9, 0);
|
||||||
|
public static final LocalTime DEFAULT_LAST_SLOT_START = LocalTime.of(21, 30);
|
||||||
|
|
||||||
|
public static StoreBookingWindow fromStore(Store store) {
|
||||||
|
LocalTime a = (store != null && store.getBookingDayStart() != null)
|
||||||
|
? snapHalfHour(store.getBookingDayStart())
|
||||||
|
: DEFAULT_DAY_START;
|
||||||
|
LocalTime b = (store != null && store.getBookingLastSlotStart() != null)
|
||||||
|
? snapHalfHour(store.getBookingLastSlotStart())
|
||||||
|
: DEFAULT_LAST_SLOT_START;
|
||||||
|
if (b.isBefore(a)) {
|
||||||
|
b = a;
|
||||||
|
}
|
||||||
|
return new StoreBookingWindow(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalTime snapHalfHour(LocalTime t) {
|
||||||
|
if (t == null) {
|
||||||
|
return DEFAULT_DAY_START;
|
||||||
|
}
|
||||||
|
int m = t.getMinute();
|
||||||
|
int nm = m < 30 ? 0 : 30;
|
||||||
|
return LocalTime.of(t.getHour(), nm);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.time.LocalTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -35,12 +36,59 @@ public class StoreService {
|
|||||||
return storeMapper.findAllByDeletedFalse();
|
return storeMapper.findAllByDeletedFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Store update(Store store) {
|
public Store update(Store incoming) {
|
||||||
store.setUpdateTime(LocalDateTime.now());
|
if (incoming == null || incoming.getId() == null) {
|
||||||
if (store.getDeleted() == null) {
|
return null;
|
||||||
store.setDeleted(false);
|
|
||||||
}
|
}
|
||||||
return storeMapper.save(store);
|
Store existing = storeMapper.findByIdAndDeletedFalse(incoming.getId()).orElse(null);
|
||||||
|
if (existing == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (incoming.getName() != null) {
|
||||||
|
existing.setName(incoming.getName());
|
||||||
|
}
|
||||||
|
if (incoming.getPhone() != null) {
|
||||||
|
existing.setPhone(incoming.getPhone());
|
||||||
|
}
|
||||||
|
if (incoming.getAddress() != null) {
|
||||||
|
existing.setAddress(incoming.getAddress());
|
||||||
|
}
|
||||||
|
if (incoming.getIntro() != null) {
|
||||||
|
existing.setIntro(incoming.getIntro());
|
||||||
|
}
|
||||||
|
if (incoming.getLatitude() != null) {
|
||||||
|
existing.setLatitude(incoming.getLatitude());
|
||||||
|
}
|
||||||
|
if (incoming.getLongitude() != null) {
|
||||||
|
existing.setLongitude(incoming.getLongitude());
|
||||||
|
}
|
||||||
|
if (incoming.getLogo() != null) {
|
||||||
|
existing.setLogo(incoming.getLogo());
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalTime start = existing.getBookingDayStart() != null
|
||||||
|
? StoreBookingWindow.snapHalfHour(existing.getBookingDayStart())
|
||||||
|
: StoreBookingWindow.DEFAULT_DAY_START;
|
||||||
|
LocalTime last = existing.getBookingLastSlotStart() != null
|
||||||
|
? StoreBookingWindow.snapHalfHour(existing.getBookingLastSlotStart())
|
||||||
|
: StoreBookingWindow.DEFAULT_LAST_SLOT_START;
|
||||||
|
if (incoming.getBookingDayStart() != null) {
|
||||||
|
start = StoreBookingWindow.snapHalfHour(incoming.getBookingDayStart());
|
||||||
|
}
|
||||||
|
if (incoming.getBookingLastSlotStart() != null) {
|
||||||
|
last = StoreBookingWindow.snapHalfHour(incoming.getBookingLastSlotStart());
|
||||||
|
}
|
||||||
|
if (last.isBefore(start)) {
|
||||||
|
throw new IllegalArgumentException("预约「末号」必须不早于「首号」");
|
||||||
|
}
|
||||||
|
existing.setBookingDayStart(start);
|
||||||
|
existing.setBookingLastSlotStart(last);
|
||||||
|
|
||||||
|
existing.setUpdateTime(LocalDateTime.now());
|
||||||
|
if (existing.getDeleted() == null) {
|
||||||
|
existing.setDeleted(false);
|
||||||
|
}
|
||||||
|
return storeMapper.save(existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean softDelete(Long id) {
|
public boolean softDelete(Long id) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user