@Entity
@JsonIgnoreProperties({ "handler", "hibernateLazyInitializer" })
public class MeetingRoom implements Serializable {

	private static final long serialVersionUID = -1701470269000866582L;

	@Id
	@GeneratedValue
	private Long id;

	@Column(nullable = false)
	private Long teamId;

	/** 会议室房间编号,唯一. */
	@Column(nullable = false, unique = true)
	private String roomNo;

	/** 会议室大小: 大/中/小. */
	@Column(nullable = false)
	private String size;

	/** 会议室类型: 视频/其他. */
	@Column(nullable = false)
	private String type;

	/** 会议室视频设备的厂商,可选:华为/思科. */
	private String vnedor;

	/** 会议室视频设备的ip,可选. */
	private String ip;

	/** 会议室视频设备终端 id,可选. */
	private String terminalId;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getRoomNo() {
		return roomNo;
	}

	public void setRoomNo(String roomNo) {
		this.roomNo = roomNo;
	}

	public String getSize() {
		return size;
	}

	public void setSize(String size) {
		this.size = size;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getVnedor() {
		return vnedor;
	}

	public void setVnedor(String vnedor) {
		this.vnedor = vnedor;
	}

	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

	public String getTerminalId() {
		return terminalId;
	}

	public void setTerminalId(String terminalId) {
		this.terminalId = terminalId;
	}

	public Long getTeamId() {
		return teamId;
	}

	public void setTeamId(Long teamId) {
		this.teamId = teamId;
	}
} public interface MeetingRoomRepository extends JpaRepository<MeetingRoom, Long> {

	List<MeetingRoom> findByTeamId(Long id);
} @Entity
public class Participant implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private Long id;

	/** 排期 id. */
	@JsonIgnore
	@ManyToOne
	@JoinColumn(name = "schedule_id")
	private Schedule schedule;

	/** 参会人微信 openId. */
	private String openId;

	/** 参会人微信昵名. */
	private String nickName;

	/** 参会人微信头像的链接. */
	private String avatarUrl;

	/** 参会日期. */
	private Date date;

	/** 参加会议表格提交的 formId 用于模板消息通知. */
	private String formId;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Schedule getSchedule() {
		return schedule;
	}

	public void setSchedule(Schedule schedule) {
		this.schedule = schedule;
	}

	public String getNickName() {
		return nickName;
	}

	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	public String getAvatarUrl() {
		return avatarUrl;
	}

	public void setAvatarUrl(String avatarUrl) {
		this.avatarUrl = avatarUrl;
	}

	public String getOpenId() {
		return openId;
	}

	public void setOpenId(String openId) {
		this.openId = openId;
	}

	@JsonFormat(pattern = "yyyy-MM-dd")
	public Date getDate() {
		return date;
	}

	@JsonFormat(pattern = "yyyy-MM-dd")
	public void setDate(Date date) {
		this.date = date;
	}

	public String getFormId() {
		return formId;
	}

	public void setFormId(String formId) {
		this.formId = formId;
	}
}
 @Entity
public class Schedule implements Serializable, Comparable<Schedule> {

	private static final long serialVersionUID = 1L;

	private static final Logger logger = LoggerFactory.getLogger(Schedule.class);

	/** 排期的重复模式：不重复. */
	public static final String REPEAT_MODE_NO = "N";

	/** 排期的重复模式：按周. */
	public static final String REPEAT_MODE_WEEKLY = "W";

	@Id
	@GeneratedValue
	private Long id;

	/** 会议的标题. */
	@Column(nullable = false, length = 1024)
	private String title;

	/** 会议室房间编号. */
	@ManyToOne(fetch = FetchType.EAGER, optional = false)
	private MeetingRoom meetingRoom;

	/** 预订日期. */
	@Column(nullable = false)
	private Date date;

	/** 开始时间,格式为 'HH:mm:ss'. */
	@Column(nullable = false)
	private String startTime;

	/** 结束时间.格式为 'HH:mm:ss'. */
	@Column(nullable = false)
	private String endTime;

	/** 创建者的微信 openId */
	@Column(nullable = false)
	private String creatorOpenId;

	/** 创建者的微信昵称. */
	@Column(nullable = false)
	private String creatorNickName;

	/** 创建者的微信头像的链接. */
	@Column(nullable = false, length = 1024)
	private String creatorAvatarUrl;

	@Column(nullable = false)
	/** 会议重复的模式: N-不重复/W-每周. */
	private String repeatMode;

	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, mappedBy = "schedule")
	private List<Participant> participants = new ArrayList<>();

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public MeetingRoom getMeetingRoom() {
		return meetingRoom;
	}

	@JsonFormat(pattern = "yyyy-MM-dd")
	public Date getDate() {
		return date;
	}

	@JsonFormat(pattern = "yyyy-MM-dd")
	public void setDate(Date date) {
		this.date = date;
	}

	public String getStartTime() {
		return startTime;
	}

	public void setStartTime(String startTime) {
		this.startTime = startTime;
	}

	public String getEndTime() {
		return endTime;
	}

	public void setEndTime(String endTime) {
		this.endTime = endTime;
	}

	public String getCreatorNickName() {
		try {
			return null == creatorNickName ? null : URLDecoder.decode(this.creatorNickName, "utf-8");
		} catch (UnsupportedEncodingException e) {
			logger.warn("decode creatorNickName fail:", e);
			return this.creatorNickName;
		}
	}

	public void setCreatorNickName(String creatorNickName) {
		try {
			this.creatorNickName = URLEncoder.encode(creatorNickName, "utf-8");
		} catch (UnsupportedEncodingException e) {
			logger.warn("encode creatorNickName fail:", e);
			this.creatorNickName = creatorNickName;
		}
	}

	public String getCreatorAvatarUrl() {
		return creatorAvatarUrl;
	}

	public void setCreatorAvatarUrl(String creatorAvatarUrl) {
		this.creatorAvatarUrl = creatorAvatarUrl;
	}

	public String getRepeatMode() {
		return repeatMode;
	}

	public void setRepeatMode(String repeatMode) {
		this.repeatMode = repeatMode;
	}

	public List<Participant> getParticipants() {
		return participants;
	}

	public void setParticipants(List<Participant> participants) {
		this.participants = participants;
	}

	public void setMeetingRoom(MeetingRoom meetingRoom) {
		this.meetingRoom = meetingRoom;
	}

	public String getCreatorOpenId() {
		return creatorOpenId;
	}

	public void setCreatorOpenId(String creatorOpenId) {
		this.creatorOpenId = creatorOpenId;
	}

	public void addParticipant(Participant participant) {
		participant.setSchedule(this);
		this.getParticipants().add(participant);
	}

	/**
	 * @return 当排期的重复模式为按周重复返回 <code>true</code>
	 */
	public boolean isRepeatModeWeekly() {
		return Schedule.REPEAT_MODE_WEEKLY.equals(getRepeatMode());
	}

	/**
	 * 判断当前排期和指定的排期是否有冲突.
	 * 
	 * @param schedule
	 *            指定用来判断是否冲突的排期
	 * @return 有冲突返回 <code>true</code>
	 */
	public boolean isConflict(Schedule schedule) {

		// 同一个排期肯定不算冲突
		if (getId().equals(schedule.getId())) {
			return false;
		}

		if (date.compareTo(schedule.getDate()) != 0) {
			return false;
		}
		if (startTime.compareTo(schedule.getStartTime()) >= 0 && startTime.compareTo(schedule.getEndTime()) < 0) {
			return true;
		}
		if (endTime.compareTo(schedule.getStartTime()) > 0 && endTime.compareTo(schedule.getEndTime()) <= 0) {
			return true;
		}
		if (startTime.compareTo(schedule.getStartTime()) < 0 && endTime.compareTo(schedule.getEndTime()) > 0) {
			return true;
		}
		return false;
	}

	@Override
	public int compareTo(Schedule o) {
		if (this.date.compareTo(o.getDate()) == 0) {
			return this.startTime.compareTo(o.getStartTime());
		} else {
			return this.date.compareTo(o.getDate());
		}
	}
}
 public interface ScheduleRepository extends JpaRepository<Schedule, Long>, ScheduleRepositoryCustom {

	List<Schedule> findByMeetingRoomAndDate(MeetingRoom meetingRoom, Date date);

	List<Schedule> findByMeetingRoomAndRepeatMode(MeetingRoom meetingRoom, String repeatMode);
} @Entity
public class User implements Serializable {

	private static final long serialVersionUID = -726326819568372268L;

	@Id
	@GeneratedValue
	private Long id;

	@Column(nullable = false, length = 200)
	private String name;

	@Column(nullable = false)
	private String mobileNo;

	@Column(nullable = false, unique = true)
	private String openId;

	@Column(nullable = false)
	private String nickName;

	@Column(nullable = false)
	private String avatarUrl;

	@ManyToMany(mappedBy="users")
	@JsonIgnore
	private List<Team> teams;
	
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getMobileNo() {
		return mobileNo;
	}

	public void setMobileNo(String mobileNo) {
		this.mobileNo = mobileNo;
	}

	public String getOpenId() {
		return openId;
	}

	public void setOpenId(String openId) {
		this.openId = openId;
	}

	public String getNickName() {
		return nickName;
	}

	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	public String getAvatarUrl() {
		return avatarUrl;
	}

	public void setAvatarUrl(String avatarUrl) {
		this.avatarUrl = avatarUrl;
	}

	public List<Team> getTeams() {
		return teams;
	}

	public void setTeams(List<Team> teams) {
		this.teams = teams;
	}
	
	
} public interface UserRepository extends JpaRepository<User , Long> {

	User findOneByOpenId(String openId);
} public interface ScheduleService {

	/**
	 * 查找指定会议室指定日期区间的排期，会自动对按周重复的排期进行计算.
	 * 
	 * @param meetingRoomId 会议室 id
	 * @param date 指定日期
	 * @return 符合条件的排期列表
	 */
	List<Schedule> find(Long meetingRoomId, Date date);
} public final class DateUtils {

	/** 简单的日期格式： yyyy-MM-dd */
	public static final String PATTERN_SIMPLE_DATE = "yyyy-MM-dd";

	public static final Date parse(String source, String pattern) {
		try {
			return new SimpleDateFormat(pattern).parse(source);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}

	public static final String format(Date date, String pattern) {
		return new SimpleDateFormat(pattern).format(date);
	}
	
	/**
	 * 判断指定的两个日期的所属的星期是否相同.
	 * 
	 * @return 当两个日期相同时返回 <code>true</code>
	 */
	public static boolean isSameWeekOfday(Date d1, Date d2) {
		Calendar d1Cal = Calendar.getInstance();
		d1Cal.setTime(d1);
		Calendar d2Cal = Calendar.getInstance();
		d2Cal.setTime(d2);
		return d1Cal.get(Calendar.DAY_OF_WEEK) == d2Cal.get(Calendar.DAY_OF_WEEK);
	}

}
 public class DefaultResult<T> implements Result<T> {

	/**
	 * 创建一个成功的结果，不含 payload
	 */
	public static Result<?> newResult() {
		DefaultResult<?> result = new DefaultResult<>();
		result.status = Result.STATUS_SUCCESS;
		result.responseCode = ResponseCodes.RESPONSE_CODE_SUCCESS;
		return result;
	}

	/**
	 * 创建一个成功的结果
	 * 
	 * @param payload 结果中的数据
	 * @return 新创建的交易结果
	 */
	public static <T> Result<T> newResult(T payload) {
		DefaultResult<T> result = new DefaultResult<>();
		result.status = Result.STATUS_SUCCESS;
		result.responseCode = ResponseCodes.RESPONSE_CODE_SUCCESS;
		result.payload = payload;
		return result;
	}

	/**
	 * 创建一个失败的结果
	 * 
	 * @param ex 导致交易失败的具体异常
	 * @return 新创建的交易结果
	 */
	public static <T> Result<T> newFailResult(Throwable ex) {
		DefaultResult<T> result = new DefaultResult<>();
		result.status = Result.STATUS_FAIL;
		result.responseMessage = ex.getMessage();
		result.responseCode = (ex instanceof BusinessException) ? ((BusinessException) ex).getCode()
				: ResponseCodes.RESPONSE_CODE_SYSTEM_ERROR;
		return result;
	}

	/**
	 * 创建一个具有指定错误消息的失败结果
	 * 
	 * @param message 错误消息
	 * @return 新创建的交易结果
	 */
	public static <T> Result<T> newFailResult(String message) {
		DefaultResult<T> result = new DefaultResult<>();
		result.status = Result.STATUS_FAIL;
		result.responseMessage = message;
		result.responseCode = ResponseCodes.RESPONSE_CODE_SYSTEM_ERROR;
		return result;
	}

	private DefaultResult() {
	}

	private Map<String, Object> headers = new HashMap<>();

	private int status;

	private T payload;

	private String responseCode;

	private String responseMessage;

	@Override
	public int getStatus() {
		return status;
	}

	@Override
	public boolean isSuccess() {
		return Result.STATUS_SUCCESS == status;
	}

	@Override
	public String getResponseCode() {
		return responseCode;
	}

	@Override
	public String getResponseMessage() {
		return responseMessage;
	}

	@Override
	public T getPayload() {
		return payload;
	}

	@Override
	public Map<String, Object> getHeaders() {
		return headers;
	}

	@Override
	public Result<T> setHeader(String key, Object value) {
		headers.put(key, value);
		return this;
	}

	@Override
	public Object getHeader(String key) {
		return headers.get(key);
	}
} public interface Result<T> {

	/** 交易结果状态：成功. */
	public static final int STATUS_SUCCESS = 0;

	/** 交易结果状态：失败. */
	public static final int STATUS_FAIL = 1;

	/**
	 * @return 此结果的状态
	 * @see Result#STATUS_FAIL
	 * @see Result#STATUS_SUCCESS
	 */
	int getStatus();

	/**
	 * @return 结果状态为 {@link Result#STATUS_SUCCESS} 返回 <code>true</code>
	 */
	boolean isSuccess();

	/**
	 * @return 响应码
	 */
	String getResponseCode();

	/**
	 * @return 响应消息
	 */
	String getResponseMessage();

	/**
	 * @return 消息所承载的数据
	 */
	T getPayload();

	/**
	 * @return 消息头承载的数据
	 */
	Map<String, Object> getHeaders();

	/**
	 * 向结果中添加 header
	 * 
	 * @param key 添加 header 的 key
	 * @param value 添加 header 的值
	 * @return 当前结果对象
	 */
	Result<T> setHeader(String key, Object value);

	/**
	 * 取指定 key 的头的值
	 * 
	 * @param key 取值的 key
	 * @return header 的值
	 */
	Object getHeader(String key);
}
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import org.catframework.agileworking.domain.MeetingRoom;
import org.catframework.agileworking.domain.MeetingRoomRepository;
import org.catframework.agileworking.domain.Participant;
import org.catframework.agileworking.domain.Schedule;
import org.catframework.agileworking.domain.ScheduleRepository;
import org.catframework.agileworking.domain.User;
import org.catframework.agileworking.domain.UserRepository;
import org.catframework.agileworking.service.ScheduleService;
import org.catframework.agileworking.utils.DateUtils;
import org.catframework.agileworking.web.support.DefaultResult;
import org.catframework.agileworking.web.support.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

package org.catframework.agileworking.web;



@RestController
public class MeetingRoomController {

	@Autowired

	private MeetingRoomRepository meetingRoomRepository;
