Shangyitong (II)
1. Data dictionary system
What is a data dictionary? The data dictionary is the commonly used classification data or some fixed data in the management system, such as: provincial, municipal and district three-level linkage data, ethnic data, industry data, academic data, etc. Since the system uses a lot of this data, we need to make a data management and facilitate the management of system data. Generally, the system will basically do data management.
Create service_cmn module under service, reverse engineering the dict table, configure pagination and swagger
Database dictionary analysis
parent_id:
The superior id is used to build a superior and subordinate relationship through id and parent_id. For example: if we want to obtain all industry data, we only need to query the data of parent_id=20000.
name: name, for example: fill in user information, we want to select the tag to select ethnicity, "Han" is the name of the data dictionary
value: value, for example: fill in user information, we need to select the tag to select ethnicity, "1" (the Han nationality's logo) is the value of the data dictionary
dict_code: encoding, encoding is customized by us and is globally unique. For example: if we want to obtain industry data, we can obtain it through parent_id, but parent_id is uncertain, so we can obtain industry data based on encoding
If you want to obtain national data, dict_code = "national"
element ui tree table data
2. Data Dictionary
Only the service implementation class is written here
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
@Autowired
private DictMapper dictMapper;
//Query the sub-data list based on the data id
@Override
@Cacheable(value = "dict",keyGenerator = "keyGenerator") //Add cache
public List<Dict> findChildData(Long id) {
QueryWrapper<Dict> wrapper = new QueryWrapper<>();
wrapper.eq("parent_id", id);
List<Dict> dictList = baseMapper.selectList(wrapper);
//Set hasChildren value in each dict object of list
for (Dict dict : dictList) {
Long dictId = dict.getId();
boolean ischild = this.ischildren(dictId);
dict.setHasChildren(ischild);
}
return dictList;
}
//Judge whether there are children under id
private boolean ischildren(Long id) {
QueryWrapper<Dict> wrapper = new QueryWrapper<>();
wrapper.eq("parent_id", id);
Integer count = baseMapper.selectCount(wrapper);
return count > 0;
}
//Export data dictionary interface
@Override
public void exportDictData(HttpServletResponse response) {
//Set download information
response.setContentType("application/-excel");
response.setCharacterEncoding("utf-8");
String fileName = "dict";
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//Query the database
List<Dict> dictList = baseMapper.selectList(null);
//Convert Dict object to DictEeVo object
List<DictEeVo> dictVoList = new ArrayList<>(dictList.size());
for(Dict dict :dictList){
DictEeVo dictEeVo = new DictEeVo();
BeanUtils.copyProperties(dict,dictEeVo);
dictVoList.add(dictEeVo);
}
//Calling the method for writing
try {
EasyExcel.write(response.getOutputStream(), DictEeVo.class)
.sheet("dict")
.doWrite(dictVoList);
} catch (IOException e) {
e.printStackTrace();
}
}
//Import data dictionary
@Override
@CacheEvict(value = "dict", allEntries=true) // means clear all content in the cache
public void importDictData(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(dictMapper))
.sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
//Query name
@Override
public String getDictName(String dictCode, String value) {
//If dictCode is empty, query directly based on the value
if(StringUtils.isEmpty(dictCode)){
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("value",value);
Dict dict = dictMapper.selectOne(queryWrapper);
return dict.getName();
}else{//If dictCode is not empty, query according to dictCode and value
//Query the dict object according to dictcode, the purpose is to obtain the dict's id value, and query the child id under this id value according to this id value
QueryWrapper<Dict> queryWrapper1 = new QueryWrapper();
queryWrapper1.eq("dict_code",dictCode);
Dict codeDict = dictMapper.selectOne(queryWrapper1);
Long parent_id = codeDict.getId();
//Query based on parentId and value values
QueryWrapper<Dict> queryWrapper2 = new QueryWrapper();
queryWrapper2.eq("parent_id",parent_id).eq("value",value);
Dict finalDict = baseMapper.selectOne(queryWrapper2);
return finalDict.getName();
}
}
//Query child nodes according to dictcode query
@Override
public List<Dict> findByDictCode(String dictCode) {
//Get the corresponding id according to dictcode
QueryWrapper<Dict> queryWrapper1 = new QueryWrapper();
queryWrapper1.eq("dict_code",dictCode);
Dict codeDict = dictMapper.selectOne(queryWrapper1);
//Get child nodes based on id
List<Dict> childData = this.findChildData(codeDict.getId());
return childData;
}
2. Spring Cache Redis
Spring Cache is a very excellent caching component. Since Spring 3.1, it provides annotation cache support similar to @Transactional annotation transactions, and provides Cache abstraction to facilitate switching of various underlying caches (such as redis)
Benefits of using Spring Cache:
1. Provide basic cache abstraction to facilitate switching of various underlying caches;
2. By annotating Cache, we can implement the cache logic transparently applied to our business code like a transaction, and only less code can be completed;
3. Provide transaction rollback cache automatically when rolling back;
4. Supports relatively complex cache logic;
service_util configuration redis
package com.atguigu.yygh.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
import java.time.Duration;
/**
* @author wangyihui
* @create 2021-04-25 15:40
*/
@Configuration
@EnableCaching // Turn on cache processing
public class RedisConfig {
private RedisCacheManager build;
/**
* Custom key rules
*
* @return
*/
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* Set RedisTemplate rules
*
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//Solve the problem of query cache conversion exception
ObjectMapper om = new ObjectMapper();
// Specify the fields to be serialized, field, get and set, and modifier ranges. ANY includes private and public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// Specify the type of serialized input. The class must be non-final modified. Final modified classes, such as String, Integer, etc., will have an exception.
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//Serial number key value
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* Set CacheManager cache rules
*
* @param factory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//Solve the problem of query cache conversion exception
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// Configure serialization (solve the problem of garbled code), expiration time 600 seconds
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
Spring Cache is equivalent to automatic cache, and you need to use RedisTemplate for redis without manual set, get
Common annotations
@Cacheable
The returned results are cached according to the method. The next time you request, if the cache exists, the cache data will be read directly and the cached data will be returned; if the cache does not exist, the method will be executed and the returned results will be stored in the cache. Generally used in query methods.
@CachePut
The method using this annotation flag is executed each time and the result is saved in the specified cache. Other methods can directly read cached data from the response cache without querying the database. Generally used in new methods.
@CacheEvict
The method using this annotation flag will clear the specified cache.
The difference between spring cache and redis
1. For redis cache, springcache only supports String, and other Hash, List, Set, and Zset are not supported. Therefore, for Hash, List, Set, and Zset, RedisTemplate can only be used.
2. Spring cache only supports single table data cache, Redis supports multi-table data cache
3. Integrate MongoDB database
Docker install mongodb here. Don't configure using mongo with user password.
Direct native startup container
docker run -d --restart=always -p 27017:27017 --name mymongo -v /data/db:/data/db -d mongo
Configure mongodb connections. Your mongodb database can also configure connections without yygh_hosp
#mongodb
=mongodb://47.108.170.87:27017/yygh_hosp
**Note: **Try not to use the mongoDb database here to require password verification, otherwise your remote configuration connection will be annoying
Mongodb is used to store hospital-related data information
Here we need to customize the three MongoDb layers, corresponding to hospitals, departments, and typesettings.
@Repository
public interface HospitalRepository extends MongoRepository<Hospital,String> {
//Judge whether there is any data
Hospital getHospitalByHoscode(String hoscode); //MongoRepository has a set of specifications, which are directly named according to the specifications, and will directly call the written method
//Inquiry based on the hospital name
List<Hospital> findHospitalByHosnameLike(String hosname);
}
import com.wang.yygh.model.hosp.Department;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
/**
* @author wangyihui
* @create 2021-11-11 10:03
*/
@Repository
public interface DepartmentRepository extends MongoRepository<Department,String> {
Department getDepartmentByHoscodeAndDepcode(String hoscode, String depcode);
}
import com.wang.yygh.model.hosp.Schedule;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
/**
* @author wangyihui
* @create 2021-11-11 15:51
*/
@Repository
public interface ScheduleRepository extends MongoRepository<Schedule,String> {
//Check according to the hospital number and scheduling number
Schedule getScheduleByHoscodeAndHosScheduleId(String hoscode, String hosScheduleId);
//Check the schedule details based on the hospital number, department number and working date
List<Schedule> findScheduleByHoscodeAndDepcodeAndWorkDate(String hoscode, String depcode, Date toDate);
}
service impl
@Service
public class HospitalSevriceImpl implements HospitalService {
@Autowired
private HospitalRepository hospitalRepository;
@Autowired
private DictFeignClient dictFeignClient;
@Override
public void save(Map<String, Object> parapMap) {
//Convert the map collection of parameters into object Hospital for easy operation
String mapString = JSONObject.toJSONString(parapMap); //Convert map to string first
Hospital hospital = JSONObject.parseObject(mapString, Hospital.class); // Convert strings to Hospital objects
//Judge whether the same data exists
String hoscode = hospital.getHoscode();
Hospital hospitalExist = hospitalRepository.getHospitalByHoscode(hoscode);
//If it exists, make changes
if(hospitalExist != null){
hospital.setStatus(hospitalExist.getStatus());
hospital.setCreateTime(hospitalExist.getCreateTime());
hospital.setUpdateTime(new Date());
hospital.setIsDeleted(0);
hospitalRepository.save(hospital);
}else{
//If it does not exist, add
hospital.setStatus(0);
hospital.setCreateTime(new Date());
hospital.setUpdateTime(new Date());
hospital.setIsDeleted(0);
hospitalRepository.save(hospital);
}
}
//Realize query based on hospital number
@Override
public Hospital getByHoscode(String hoscode) {
Hospital hospital = hospitalRepository.getHospitalByHoscode(hoscode);
return hospital;
}
//Hospital list (condition query pagination)
@Override
public Page<Hospital> selectHospPage(Integer page, Integer limit, HospitalQueryVo hospitalQueryVo) {
//Create a pageable object
Pageable pageable = PageRequest.of(page - 1,limit);
//Create a condition matcher
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
.withIgnoreCase(true);
//Convert hospitalSetQueryVo to hospital object
Hospital hospital = new Hospital();
BeanUtils.copyProperties(hospitalQueryVo,hospital);
//Create an Example object
Example<Hospital> example = Example.of(hospital,matcher);
//Calling method to implement query
Page<Hospital> pages = hospitalRepository.findAll(example, pageable);
//Query all hospital collections and traverse them, and then obtain hospital level information
//Use streaming method
pages.getContent().stream().forEach(item -> {
this.setHospitalHosType(item);
});
return pages;
}
//Update the hospital's online status
@Override
public void updateStatus(String id, Integer status) {
//Check hospital information based on id
Hospital hospital = hospitalRepository.findById(id).get();
hospital.setStatus(status);
hospital.setUpdateTime(new Date());
hospitalRepository.save(hospital);
}
//Inquiry on the hospital details
@Override
public Map<String, Object> getHospById(String id) {
Map<String, Object> result = new HashMap<>();
//Check hospital information based on id and encapsulate the level information into it.
Hospital hospital = this.setHospitalHosType(hospitalRepository.findById(id).get());
result.put("hospital",hospital);
//More intuitive to handle separately
result.put("bookingRule", hospital.getBookingRule());
//No need to return repeatedly
hospital.setBookingRule(null);
return result;
}
//Get the hospital name
@Override
public String getHospName(String hoscode) {
Hospital hospital = hospitalRepository.getHospitalByHoscode(hoscode);
if(hospital != null){
return hospital.getHosname();
}
return null;
}
//Inquiry based on the hospital name
@Override
public List<Hospital> findByHosname(String hosname) {
List<Hospital> list = hospitalRepository.findHospitalByHosnameLike(hosname);
return list;
}
//Get reservation registration details based on the hospital number
@Override
public Map<String, Object> item(String hoscode) {
Map<String, Object> result = new HashMap<>();
//Hospital details
Hospital hospital = this.setHospitalHosType(this.getByHoscode(hoscode));
result.put("hospital", hospital);
//Appointment Rules
result.put("bookingRule", hospital.getBookingRule());
//No need to return repeatedly
hospital.setBookingRule(null);
return result;
}
//Get the query collection of hospitals and traverse the hospital level encapsulation
private Hospital setHospitalHosType(Hospital hospital) {
//Get hospital level name based on dictCode and value
String hostypeString = dictFeignClient.getName("Hostype", hospital.getHostype());
//Inquiry of provinces, cities, regions
String provinceString = dictFeignClient.getName(hospital.getProvinceCode());
String cityString = dictFeignClient.getName(hospital.getCityCode());
String districtString = dictFeignClient.getName(hospital.getDistrictCode());
hospital.getParam().put("hostypeString",hostypeString);
hospital.getParam().put("fullAddress",provinceString + cityString + districtString);
return hospital;
}
}
@Service
public class DepartmentServiceImpl implements DepartmentService {
@Autowired
private DepartmentRepository departmentRepository;
//Upload the department interface
@Override
public void save(Map<String, Object> parampMap) {
//Convert parampMap into Department object
String parampMapString = JSONObject.toJSONString(parampMap);
Department department = JSONObject.parseObject(parampMapString, Department.class);
//Inquiry based on the hospital number and department information
Department departmentExist = departmentRepository
.getDepartmentByHoscodeAndDepcode(department.getHoscode(),department.getDepcode()); //Name adopts spring DATA specification
//Judge whether the department exists
if(departmentExist != null){
//If it exists, make changes
departmentExist.setUpdateTime(new Date());
departmentExist.setIsDeleted(0);
departmentRepository.save(departmentExist);
}else{
department.setCreateTime(new Date());
department.setUpdateTime(new Date());
department.setIsDeleted(0);
departmentRepository.save(department);
}
}
//Inquiry department
@Override
public Page<Department> finPageDepartment(int page, int limit, DepartmentQueryVo departmentQueryVo) {
//MongoRepository develops CRUD
//Create a Pageble object, set the current page and the number of records per page.
Pageable pageable = PageRequest.of(page - 1,limit); // The current page starts at 0, but we start to pass it at 1
//Convert departmentQueryVo object to department object
Department department = new Department();
BeanUtils.copyProperties(departmentQueryVo,department);
department.setIsDeleted(0);
//Create an Example object
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
.withIgnoreCase(true);
Example<Department> example = Example.of(department,matcher);
Page<Department> all = departmentRepository.findAll(example,pageable);
return all;
}
//Delete the department
@Override
public void remove(String hoscode, String depcode) {
//Check department information based on the hospital number and department number
Department department = departmentRepository.getDepartmentByHoscodeAndDepcode(hoscode, depcode);
if(depcode != null){
//delete
departmentRepository.deleteById(department.getId());
}
}
//Check the list of all departments according to the hospital number
@Override
public List<DepartmentVo> findDepTree(String hoscode) {
//Create List collection for final data encapsulation
List<DepartmentVo> result = new ArrayList<>();
//Check information of all departments according to the hospital number
Department departmentQuery = new Department();
departmentQuery.setHoscode(hoscode);
Example<Department> example = Example.of(departmentQuery);
//All department list information
List<Department> departmentList = departmentRepository.findAll(example);
//Group according to the number of the big code to obtain the lower sub-departments in each large department
Map<String, List<Department>> departmentMap =
departmentList.stream().collect(Collectors.groupingBy(Department::getBigcode));
//Transfer the map collection
for(Map.Entry<String,List<Department>> entry : departmentMap.entrySet()){
//Digital department number
String bigcode = entry.getKey();
//All data corresponding to the number of large departments
List<Department> department1List = entry.getValue();
//Encapsulation department
DepartmentVo departmentVo1 = new DepartmentVo();
departmentVo1.setDepcode(bigcode);
departmentVo1.setDepname(department1List.get(0).getBigname());
//Packaging small department
List<DepartmentVo> children = new ArrayList<>();
for(Department department : department1List){
DepartmentVo departmentVo2 = new DepartmentVo();
departmentVo2.setDepcode(department.getDepcode());
departmentVo2.setDepname(department.getDepname());
//Encapsulate to List collection
children.add(departmentVo2);
}
//Place the list of small departments into children in large departments
departmentVo1.setChildren(children);
//Put it into the final result
result.add(departmentVo1);
}
return result;
}
//Check the department name based on the hospital number and department number
@Override
public String getDepName(String hoscode, String depcode) {
Department department = departmentRepository.getDepartmentByHoscodeAndDepcode(hoscode, depcode);
if(department != null){
return department.getDepname();
}
return null;
}
//Check the department according to the hospital number and department number
@Override
public Department getDepartment(String hoscode, String depcode) {
return departmentRepository.getDepartmentByHoscodeAndDepcode(hoscode, depcode);
}
}
@Service
public class ScheduleServiceImpl extends ServiceImpl<ScheduleMapper,Schedule> implements ScheduleService {
@Autowired
private ScheduleRepository scheduleRepository;
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private HospitalService hospitalService;
@Autowired
private DepartmentService departmentService;
//Upload the shift
@Override
public void save(Map<String, Object> parampMap) {
//Convert parampMap into Department object
String parampMapString = JSONObject.toJSONString(parampMap);
Schedule schedule = JSONObject.parseObject(parampMapString, Schedule.class);
//Check according to the hospital number and scheduling number
Schedule scheduleExist = scheduleRepository
.getScheduleByHoscodeAndHosScheduleId(schedule.getHoscode(),schedule.getHosScheduleId()); //Name adopts spring DATA specification
//Judge whether the scheduling exists
if(scheduleExist != null){
//If it exists, make changes
scheduleExist.setUpdateTime(new Date());
scheduleExist.setIsDeleted(0);
scheduleExist.setStatus(1);
scheduleRepository.save(scheduleExist);
}else{
schedule.setCreateTime(new Date());
schedule.setUpdateTime(new Date());
schedule.setIsDeleted(0);
schedule.setStatus(1);
scheduleRepository.save(schedule);
}
}
//Inquiry department
@Override
public Page<Schedule> finPageSchedule(int page, int limit, ScheduleQueryVo scheduleQueryVo) {
//MongoRepository develops CRUD
//Create a Pageble object, set the current page and the number of records per page.
Pageable pageable = PageRequest.of(page - 1,limit); // The current page starts at 0, but we start to pass it at 1
//Convert departmentQueryVo object to department object
Schedule schedule = new Schedule();
BeanUtils.copyProperties(scheduleQueryVo,schedule);
schedule.setIsDeleted(0);
schedule.setStatus(1);
//Create an Example object
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
.withIgnoreCase(true);
Example<Schedule> example = Example.of(schedule,matcher);
Page<Schedule> all = scheduleRepository.findAll(example,pageable);
return all;
}
//Delete the shift schedule
@Override
public void remove(String hoscode, String hosScheduleId) {
//Check relevant information based on the hospital number and scheduling number
Schedule schedule = scheduleRepository.getScheduleByHoscodeAndHosScheduleId(hoscode, hosScheduleId);
if(schedule != null){
scheduleRepository.deleteById(schedule.getId());
}
}
//Check the schedule rules data based on the hospital number and department number
@Override
public Map<String, Object> getReleSchedule(Long page, Long limit, String hoscode, String depcode) {
//Inquiry based on hospital number and department number
Criteria criteria = Criteria.where("hoscode").is(hoscode).and("depcode").is(depcode);
//Group based on workdate date, using MongoTemplate method
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(criteria), //Match the criteria
Aggregation.group("workDate") //Group fields
.first("workDate").as("workDate")
//Statistic number source number
.count().as("docCount")
.sum("reservedNumber").as("reservedNumber") //The number of appointments available in the department
.sum("availableNumber").as("availableNumber"), //The remaining number of appointments in the department
Aggregation.sort(Sort.Direction.DESC,"workDate"),
//Implement paging
Aggregation.skip((page - 1) * limit),
Aggregation.limit(limit)
);
//Calling the method, final execution
//BookingScheduleRuleVo encapsulation returns data
AggregationResults<BookingScheduleRuleVo> aggResults = mongoTemplate.aggregate(agg, Schedule.class, BookingScheduleRuleVo.class);
List<BookingScheduleRuleVo> bookingScheduleRuleVoList = aggResults.getMappedResults();
//Total number of records in group query
Aggregation totalAgg = Aggregation.newAggregation(
Aggregation.match(criteria),
Aggregation.group("workDate")
);
AggregationResults<BookingScheduleRuleVo> totalAggResultS = mongoTemplate.aggregate(totalAgg, Schedule.class, BookingScheduleRuleVo.class);
int total = totalAggResultS.getMappedResults().size();
//Get the corresponding week of workDate date
for(BookingScheduleRuleVo bookingScheduleRuleVo : bookingScheduleRuleVoList){
Date workDate = bookingScheduleRuleVo.getWorkDate();
String dayOfWeek = this.getDayOfWeek(new DateTime(workDate));
bookingScheduleRuleVo.setDayOfWeek(dayOfWeek);
}
//Set the final data to return
Map<String,Object> result = new HashMap<>();
result.put("bookingScheduleRuleList",bookingScheduleRuleVoList);
result.put("total",total);
//Get the hospital name
String hosName = hospitalService.getHospName(hoscode);
//Other basic data (hospital name)
Map<String, String> baseMap = new HashMap<>();
baseMap.put("hosname",hosName);
result.put("baseMap",baseMap);
return result;
}
//Check the schedule details based on the hospital number, department number and working date
@Override
public List<Schedule> getDetailSchedule(String hoscode, String depcode, String workDate) {
//Query mongodb according to the parameters and obtain data
List<Schedule> scheduleList =
scheduleRepository.findScheduleByHoscodeAndDepcodeAndWorkDate(hoscode,depcode,new DateTime(workDate).toDate());
//Travel the obtained list and add the week corresponding to the hospital name, department name, and date to it.
scheduleList.stream().forEach(item -> {
this.packageSchedule(item);
});
return scheduleList;
}
//Get schedule data
@Override
public Map<String,Object> getBookingScheduleRule(Integer page, Integer limit, String hoscode, String depcode) {
Map<String,Object> result = new HashMap<>();
//Get appointment rules based on hospital number
Hospital hospital = hospitalService.getByHoscode(hoscode);
if(hospital == null){
throw new YyghException(ResultCodeEnum.DATA_ERROR);
}
BookingRule bookingRule = hospital.getBookingRule();
// Obtain reservation data according to the reservation rules (pagination)
IPage iPage = this.getListData(page,limit,bookingRule);
//Get the current reservation date
List<Date> dateList = iPage.getRecords();
//Get the remaining data of the department in the date of reservation
Criteria criteria = Criteria.where("hoscode").is(hoscode).and("depcode").is(depcode).and("workDate").in(dateList);
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(criteria),
Aggregation.group("workDate").first("workDate").as("workDate")
.count().as("docCount")
.sum("availableNumber").as("availableNumber")
.sum("reservedNumber").as("reservedNumber")
);
AggregationResults<BookingScheduleRuleVo> aggregateResult = mongoTemplate.aggregate(agg, Schedule.class, BookingScheduleRuleVo.class);
List<BookingScheduleRuleVo> scheduleVoList = aggregateResult.getMappedResults();
//Merge data map collection key: date value: reservation rules and remaining quantity, etc.
Map<Date, BookingScheduleRuleVo> scheduleVoMap = new HashMap<>();
if(!CollectionUtils.isEmpty(scheduleVoList)) {
scheduleVoMap = scheduleVoList.stream().collect(Collectors.toMap(BookingScheduleRuleVo::getWorkDate, BookingScheduleRuleVo -> BookingScheduleRuleVo));
}
//Get reservation-ready typography rules
List<BookingScheduleRuleVo> bookingScheduleRuleVoList = new ArrayList<>();
for(int i=0, len=dateList.size(); i<len; i++) {
Date date = dateList.get(i);
//Get value from map collection based on key date
BookingScheduleRuleVo bookingScheduleRuleVo = scheduleVoMap.get(date);
if(bookingScheduleRuleVo == null){
bookingScheduleRuleVo = new BookingScheduleRuleVo();
//Number of doctors to visit
bookingScheduleRuleVo.setDocCount(0);
//The remaining number of appointments in the department -1 means no number
bookingScheduleRuleVo.setAvailableNumber(-1);
}
bookingScheduleRuleVo.setWorkDate(date);
bookingScheduleRuleVo.setWorkDateMd(date);
//Calculate the week corresponding to the current appointment date
String dayOfWeek = this.getDayOfWeek(new DateTime(date));
bookingScheduleRuleVo.setDayOfWeek(dayOfWeek);
//The last page of the last page is about to make an appointment Status 0: Normal 1: The number will be released soon -1: The registration has been stopped on the same day
if(i == len-1 && page == iPage.getPages()) {
bookingScheduleRuleVo.setStatus(1);
} else {
bookingScheduleRuleVo.setStatus(0);
}
//If the suspension time has passed, you cannot make an appointment
if(i == 0 && page == 1) {
DateTime stopTime = this.getDateTime(new Date(), bookingRule.getStopTime());
if(stopTime.isBeforeNow()) {
//Stop making an appointment
bookingScheduleRuleVo.setStatus(-1);
}
}
bookingScheduleRuleVoList.add(bookingScheduleRuleVo);
}
//Appointment date rule data
result.put("bookingScheduleList", bookingScheduleRuleVoList);
result.put("total", iPage.getTotal());
//Other basic data
Map<String, String> baseMap = new HashMap<>();
//Hospital name
baseMap.put("hosname", hospitalService.getHospName(hoscode));
//Department
Department department =departmentService.getDepartment(hoscode, depcode);
//The name of the department
baseMap.put("bigname", department.getBigname());
//Department name
baseMap.put("depname", department.getDepname());
//moon
baseMap.put("workDateString", new DateTime().toString("yyyyy year MM month"));
//Discharge time
baseMap.put("releaseTime", bookingRule.getReleaseTime());
//Stop time
baseMap.put("stopTime", bookingRule.getStopTime());
result.put("baseMap", baseMap);
return result;
}
// Obtain scheduling data based on scheduling id
@Override
public Schedule getScheduleId(String scheduleId) {
Optional<Schedule> optional = scheduleRepository.findById(scheduleId);
Schedule schedule = optional.get();
return this.packageSchedule(schedule);
}
//Get reservation order data based on schedule id
@Override
public ScheduleOrderVo getScheduleOrderVo(String scheduleId) {
ScheduleOrderVo scheduleOrderVo = new ScheduleOrderVo();
Schedule schedule = this.getScheduleId(scheduleId);
// Schedule schedule = (scheduleId);
if(schedule == null){
throw new YyghException(ResultCodeEnum.PARAM_ERROR);
}
//Get reservation rules information, get from hospital
Hospital hospital = hospitalService.getByHoscode(schedule.getHoscode());
if(hospital == null){
throw new YyghException(ResultCodeEnum.PARAM_ERROR);
}
BookingRule bookingRule = hospital.getBookingRule();
if(bookingRule == null){
throw new YyghException(ResultCodeEnum.PARAM_ERROR);
}
//Set the retrieved data into scheduleOrderVo
scheduleOrderVo.setHoscode(schedule.getHoscode());
scheduleOrderVo.setHosname(hospitalService.getHospName(schedule.getHoscode()));
scheduleOrderVo.setDepcode(schedule.getDepcode());
scheduleOrderVo.setDepname(departmentService.getDepName(schedule.getHoscode(), schedule.getDepcode()));
scheduleOrderVo.setHosScheduleId(schedule.getHosScheduleId());
scheduleOrderVo.setAvailableNumber(schedule.getAvailableNumber());
scheduleOrderVo.setTitle(schedule.getTitle());
scheduleOrderVo.setReserveDate(schedule.getWorkDate());
scheduleOrderVo.setReserveTime(schedule.getWorkTime());
scheduleOrderVo.setAmount(schedule.getAmount());
//The number of days to withdraw (such as -1 the day before the medical treatment, and 0 the day)
int quitDay = bookingRule.getQuitDay();
DateTime quitTime = this.getDateTime(new DateTime(schedule.getWorkDate()).plusDays(quitDay).toDate(), bookingRule.getQuitTime());
scheduleOrderVo.setQuitTime(quitTime.toDate());
//Appointment start time
DateTime startTime = this.getDateTime(new Date(), bookingRule.getReleaseTime());
scheduleOrderVo.setStartTime(startTime.toDate());
//Appointment deadline
DateTime endTime = this.getDateTime(new DateTime().plusDays(bookingRule.getCycle()).toDate(), bookingRule.getStopTime());
scheduleOrderVo.setEndTime(endTime.toDate());
//Registering time that day
DateTime stopTime = this.getDateTime(new Date(), bookingRule.getStopTime());
scheduleOrderVo.setStartTime(stopTime.toDate());
return scheduleOrderVo;
}
//Update scheduling, used for mq
@Override
public void update(Schedule schedule) {
schedule.setUpdateTime(new Date());
scheduleRepository.save(schedule);
}
// Obtain reservation data according to the reservation rules (pagination)
private IPage getListData(Integer page, Integer limit, BookingRule bookingRule) {
//Get the release time of the day yyyy-MM-dd HH:mm
DateTime releaseTime = this.getDateTime(new Date(), bookingRule.getReleaseTime());
//Get reservation period
Integer cycle = bookingRule.getCycle();
//If the time for the number release on that day has passed, the reservation period will be calculated from the next day, and the period will be +1
if(releaseTime.isBeforeNow()){
cycle += 1;
}
//Get all dates that can be booked, and the last day shows the upcoming number.
List<Date> dateList = new ArrayList<>();
for(int i = 0;i < cycle;i++){
DateTime curDateTime = new DateTime().plusDays(i);
String dateString = curDateTime.toString("yyyy-MM-dd");
dateList.add(new DateTime(dateString).toDate());
}
//Because the reservation period is different, each page displays up to 7 days. If the reservation period is greater than 7 days, paging must be performed if the reservation period is greater than 7 days.
List<Date> pageDateList = new ArrayList<>();
int start = (page-1) * limit;
int end = (page -1) * limit + limit;
//If the reservation period is <=7, it will be displayed directly
if(dateList.size() < end){
end = dateList.size();
}
for(int i = start;i < end;i++){
pageDateList.add(dateList.get(i));
}
//If >7, then paginate
IPage<Date> iPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(page,7,dateList.size());
iPage.setRecords(pageDateList);
return iPage;
}
/**
* Convert Date date (yyyy-MM-dd HH:mm) to DateTime
*/
private DateTime getDateTime(Date date, String timeString) {
String dateTimeString = new DateTime(date).toString("yyyy-MM-dd") + " "+ timeString;
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").parseDateTime(dateTimeString);
return dateTime;
}
//Package the week corresponding to the hospital name, department name, and date into schedule details
private Schedule packageSchedule(Schedule schedule) {
//Set the hospital name
schedule.getParam().put("hosname",hospitalService.getHospName(schedule.getHoscode()));
//Set the department name
schedule.getParam().put("depname",departmentService.getDepName(schedule.getHoscode(),schedule.getDepcode()));
//Set the date corresponding to the week
schedule.getParam().put("dayOfWeek",this.getDayOfWeek(new DateTime(schedule.getWorkDate())));
return schedule;
}
/**
* Get the week data based on date
* @param dateTime
* @return
*/
private String getDayOfWeek(DateTime dateTime) {
String dayOfWeek = "";
switch (dateTime.getDayOfWeek()) {
case DateTimeConstants.SUNDAY:
dayOfWeek = "Sunday";
break;
case DateTimeConstants.MONDAY:
dayOfWeek = "on Monday";
break;
case DateTimeConstants.TUESDAY:
dayOfWeek = "Tuesday";
break;
case DateTimeConstants.WEDNESDAY:
dayOfWeek = "Wednesday";
break;
case DateTimeConstants.THURSDAY:
dayOfWeek = "Thursday";
break;
case DateTimeConstants.FRIDAY:
dayOfWeek = "Friday";
break;
case DateTimeConstants.SATURDAY:
dayOfWeek = "Saturday";
default:
break;
}
return dayOfWeek;
}
}
controller: Since the unified reservation platform needs to provide an interface to upload images for external data, we have an API for external use here.
@RestController
@RequestMapping("/api/hosp")
public class ApiController {
@Autowired
private HospitalService hospitalService;
@Autowired
private HospitalSetService hospitalSetService;
@Autowired
private DepartmentService departmentService;
@Autowired
private ScheduleService scheduleService;
//Upload the hospital interface
@PostMapping("saveHospital")
public Result saveHosp(HttpServletRequest request){
//Get the information conveyed by the hospital
Map<String, String[]> parameterMap = request.getParameterMap();
//To avoid subsequent traversal, convert String[] in map to Object
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
// Verify that the signature is consistent
//1. Obtain the signature passed by the hospital system
String hospSign = (String) parampMap.get("sign");
//2. Query the database and query the signature based on the passed hospital code.
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
//3. Encrypt the query signature with MD5
String signKeyMD5 = MD5.encrypt(signKey);
//4. Determine whether the signature is consistent
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//The image data is transmitted by base64 tool class, and during the transmission process, "+" is converted to " ", so we need to convert it back
String logoData = (String) parampMap.get("logoData");
logoData = logoData.replace(" ","+");
parampMap.put("logoData",logoData);
//Calling service method
hospitalService.save(parampMap);
return Result.ok();
}
//Inquiry of the hospital interface
@PostMapping("hospital/show")
public Result getHospital(HttpServletRequest request){
//Get the information conveyed by the hospital
Map<String, String[]> parameterMap = request.getParameterMap();
//To avoid subsequent traversal, convert String[] in map to Object
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Get the passed hospital number
String hoscode = (String) parampMap.get("hoscode");
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Calling the service method
Hospital hospital = hospitalService.getByHoscode(hoscode);
return Result.ok(hospital);
}
//Upload the department interface
@PostMapping("saveDepartment")
public Result saveDepartment(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
// Verify that the signature is consistent
String hospSign = (String) parampMap.get("sign");
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Calling the service method
departmentService.save(parampMap);
return Result.ok();
}
//Department query interface
@PostMapping("department/list")
public Result findDepartment(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Hospital number
String hoscode = (String) parampMap.get("hoscode");
//Current page
int page = Integer.parseInt((String) parampMap.get("page"));
if(StringUtils.isEmpty(page)){
page = 1;
}
//The number of records displayed per page
int limit = Integer.parseInt((String) parampMap.get("limit"));
if(StringUtils.isEmpty(limit)){
limit = 1;
}
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Call service query
//The value of the query condition is encapsulated into departmentQueryVo
DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
departmentQueryVo.setHoscode(hoscode);
Page<Department> pageModel = departmentService.finPageDepartment(page,limit,departmentQueryVo);
return Result.ok(pageModel);
}
//Delete the department interface
@PostMapping("department/remove")
public Result removeDepartment(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Get hospital number and department number
String hoscode = (String) parampMap.get("hoscode");
String depcode = (String) parampMap.get("depcode");
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
departmentService.remove(hoscode,depcode);
return Result.ok();
}
//Upload the shift
@PostMapping("saveSchedule")
public Result saveSchedule(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Signature verification
String hospSign = (String) parampMap.get("sign");
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Calling the service method
scheduleService.save(parampMap);
return Result.ok();
}
//Inquiry scheduling
@PostMapping("schedule/list")
public Result findSchedule(HttpServletRequest request) {
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Hospital number
String hoscode = (String) parampMap.get("hoscode");
//Department number
String depcode = (String) parampMap.get("depcode");
//Current page
int page = Integer.parseInt((String) parampMap.get("page"));
if (StringUtils.isEmpty(page)) {
page = 1;
}
//The number of records displayed per page
int limit = Integer.parseInt((String) parampMap.get("limit"));
if (StringUtils.isEmpty(limit)) {
limit = 1;
}
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if (!hospSign.equals(signKeyMD5)) {
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Call service query
//The value of the query condition is encapsulated into departmentQueryVo
ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
scheduleQueryVo.setHoscode(hoscode);
scheduleQueryVo.setDepcode(depcode);
Page<Schedule> pageModel = scheduleService.finPageSchedule(page, limit, scheduleQueryVo);
return Result.ok(pageModel);
}
//Delete the shift schedule
@PostMapping("schedule/remove")
public Result remove(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Get the hospital number and scheduling number
String hoscode = (String) parampMap.get("hoscode");
String hosScheduleId = (String) parampMap.get("hosScheduleId");
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
scheduleService.remove(hoscode,hosScheduleId);
return Result.ok();
}
}
@Api("Hospital Management Interface")
@RestController
@RequestMapping("/api/hosp/hospital")
public class HospitalApiController {
@Autowired
private HospitalService hospitalService;
@Autowired
private DepartmentService departmentService;
@Autowired
private ScheduleService scheduleService;
@Autowired
private HospitalSetService hospitalSetService;
//Inquiry of the hospital list
@ApiOperation("Query Hospital List")
@GetMapping("findHospList/{page}/{limit}")
public Result findHospList(@PathVariable("page") Integer page,
@PathVariable("limit") Integer limit,
HospitalQueryVo hospitalQueryVo){
Page<Hospital> hospitals = hospitalService.selectHospPage(page, limit, hospitalQueryVo);
List<Hospital> content = hospitals.getContent(); //For front-end calls
int totalPages = hospitals.getTotalPages(); //For front-end calls
return Result.ok(hospitals);
}
//Inquiry based on the hospital name
@ApiOperation("Query by hospital name")
@GetMapping("findByHosname/{hosname}")
public Result findHospList(@PathVariable("hosname") String hosname){
List<Hospital> list = hospitalService.findByHosname(hosname); //Fuzzy query may return multiple, receive with list
return Result.ok(list);
}
//Get the department list based on the hospital number
@ApiOperation("Get the department list based on the hospital number")
@GetMapping("department/{hoscode}")
public Result index(@PathVariable("hoscode") String hoscode){
List<DepartmentVo> list = departmentService.findDepTree(hoscode);
return Result.ok(list);
}
//Get reservation registration details based on the hospital number
@ApiOperation(value = "Get appointment registration details based on hospital number")
@GetMapping("findHospDetail/{hoscode}")
public Result item(@PathVariable("hoscode") String hoscode){
Map<String,Object> map = hospitalService.item(hoscode);
return Result.ok(map);
}
//Get schedule data
@ApiOperation(value = "Get reservation-based schedule data")
@GetMapping("auth/getBookingScheduleRule/{page}/{limit}/{hoscode}/{depcode}")
public Result getBookingSchedule(
@ApiParam(name = "page", value = "Current page number", required = true)
@PathVariable Integer page,
@ApiParam(name = "limit", value = "Number of records per page", required = true)
@PathVariable Integer limit,
@ApiParam(name = "hoscode", value = "Hospital code", required = true)
@PathVariable String hoscode,
@ApiParam(name = "depcode", value = "Department code", required = true)
@PathVariable String depcode) {
return Result.ok(scheduleService.getBookingScheduleRule(page, limit, hoscode, depcode));
}
//Get specific scheduling data
@ApiOperation(value = "Get specific scheduling data")
@GetMapping("auth/findScheduleList/{hoscode}/{depcode}/{workDate}")
public Result findScheduleList(
@ApiParam(name = "hoscode", value = "Hospital code", required = true)
@PathVariable String hoscode,
@ApiParam(name = "depcode", value = "Department code", required = true)
@PathVariable String depcode,
@ApiParam(name = "workDate", value = "Scheduling Date", required = true)
@PathVariable String workDate) {
return Result.ok(scheduleService.getDetailSchedule(hoscode, depcode, workDate));
}
// Obtain scheduling data based on scheduling id
@ApiOperation(value = "Get scheduling data based on scheduling id")
@GetMapping("getSchedule/{scheduleId}")
public Result getSchedule(@PathVariable("scheduleId") String scheduleId){
Schedule schedule = scheduleService.getScheduleId(scheduleId);
return Result.ok(schedule);
}
//Get reservation order data based on schedule id
@ApiOperation(value = "Get reservation order data based on schedule id")
@GetMapping("inner/getScheduleOrderVo/{scheduleId}")
public ScheduleOrderVo getScheduleOrderVo(@PathVariable("scheduleId") String scheduleId) {
return scheduleService.getScheduleOrderVo(scheduleId);
}
//Get hospital signature information
@ApiOperation(value = "Get hospital signature information")
@GetMapping("inner/getSignInfoVo/{hoscode}")
public SignInfoVo getSignInfoVo(@PathVariable("hoscode") String hoscode) {
return hospitalSetService.getSignInfoVo(hoscode);
}
}
4. Upload the hospital
Upload the hospital and the department. Upload the scheduling information is the interface implemented on the unified appointment platform. Then each hospital calls the interface of the unified appointment platform to go to bed with your own hospital.
Here we use hosp_manager to simulate the hospital uploading hospital information
There is a bug here. Your hospital_set table must have a data with id 1.
Upload hospital information, right? The hospital's json string is parsed into a map object and then saved in the mongodb database through the address.
JSONObject respone = HttpRequestHelper.sendRequest(paramMap,this.getApiUrl()+"/api/hosp/saveHospital")
Note that the api address here is the port in service_hosp and then the service_hosp implements /api/hosp/saveHospital of the controller here
service
import ;
import ;
import ;
import ;
import ;
/**
* @author wangyihui
* @create 2021-11-11 18:16
*/
public interface HospitalService {
//Upload the hospital interface
void save(Map<String, Object> parapMap);
//Realize query based on hospital number
Hospital getByHoscode(String hoscode);
//Hospital list (condition query pagination)
Page<Hospital> selectHospPage(Integer page, Integer limit, HospitalQueryVo hospitalQueryVo);
//Update the hospital's upper limit status
void updateStatus(String id, Integer status);
//Inquiry on the hospital details
Map<String, Object> getHospById(String id);
//Get the hospital name
String getHospName(String hoscode);
//Inquiry based on the hospital name
List<Hospital> findByHosname(String hosname);
//Get reservation registration details based on the hospital number
Map<String, Object> item(String hoscode);
}
service impl
@Service
public class HospitalSevriceImpl implements HospitalService {
@Autowired
private HospitalRepository hospitalRepository;
@Autowired
private DictFeignClient dictFeignClient;
@Override
public void save(Map<String, Object> parapMap) {
//Convert the map collection of parameters into object Hospital for easy operation
String mapString = JSONObject.toJSONString(parapMap); //Convert map to string first
Hospital hospital = JSONObject.parseObject(mapString, Hospital.class); // Convert strings to Hospital objects
//Judge whether the same data exists
String hoscode = hospital.getHoscode();
Hospital hospitalExist = hospitalRepository.getHospitalByHoscode(hoscode);
//If it exists, make changes
if(hospitalExist != null){
hospital.setStatus(hospitalExist.getStatus());
hospital.setCreateTime(hospitalExist.getCreateTime());
hospital.setUpdateTime(new Date());
hospital.setIsDeleted(0);
hospitalRepository.save(hospital);
}else{
//If it does not exist, add
hospital.setStatus(0);
hospital.setCreateTime(new Date());
hospital.setUpdateTime(new Date());
hospital.setIsDeleted(0);
hospitalRepository.save(hospital);
}
}
//Realize query based on hospital number
@Override
public Hospital getByHoscode(String hoscode) {
Hospital hospital = hospitalRepository.getHospitalByHoscode(hoscode);
return hospital;
}
//Hospital list (condition query pagination)
@Override
public Page<Hospital> selectHospPage(Integer page, Integer limit, HospitalQueryVo hospitalQueryVo) {
//Create a pageable object
Pageable pageable = PageRequest.of(page - 1,limit);
//Create a condition matcher
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
.withIgnoreCase(true);
//Convert hospitalSetQueryVo to hospital object
Hospital hospital = new Hospital();
BeanUtils.copyProperties(hospitalQueryVo,hospital);
//Create an Example object
Example<Hospital> example = Example.of(hospital,matcher);
//Calling method to implement query
Page<Hospital> pages = hospitalRepository.findAll(example, pageable);
//Query all hospital collections and traverse them, and then obtain hospital level information
//Use streaming method
pages.getContent().stream().forEach(item -> {
this.setHospitalHosType(item);
});
return pages;
}
//Update the hospital's online status
@Override
public void updateStatus(String id, Integer status) {
//Check hospital information based on id
Hospital hospital = hospitalRepository.findById(id).get();
hospital.setStatus(status);
hospital.setUpdateTime(new Date());
hospitalRepository.save(hospital);
}
//Inquiry on the hospital details
@Override
public Map<String, Object> getHospById(String id) {
Map<String, Object> result = new HashMap<>();
//Check hospital information based on id and encapsulate the level information into it.
Hospital hospital = this.setHospitalHosType(hospitalRepository.findById(id).get());
result.put("hospital",hospital);
//More intuitive to handle separately
result.put("bookingRule", hospital.getBookingRule());
//No need to return repeatedly
hospital.setBookingRule(null);
return result;
}
//Get the hospital name
@Override
public String getHospName(String hoscode) {
Hospital hospital = hospitalRepository.getHospitalByHoscode(hoscode);
if(hospital != null){
return hospital.getHosname();
}
return null;
}
//Inquiry based on the hospital name
@Override
public List<Hospital> findByHosname(String hosname) {
List<Hospital> list = hospitalRepository.findHospitalByHosnameLike(hosname);
return list;
}
//Get reservation registration details based on the hospital number
@Override
public Map<String, Object> item(String hoscode) {
Map<String, Object> result = new HashMap<>();
//Hospital details
Hospital hospital = this.setHospitalHosType(this.getByHoscode(hoscode));
result.put("hospital", hospital);
//Appointment Rules
result.put("bookingRule", hospital.getBookingRule());
//No need to return repeatedly
hospital.setBookingRule(null);
return result;
}
//Get the query collection of hospitals and traverse the hospital level encapsulation
private Hospital setHospitalHosType(Hospital hospital) {
//Get hospital level name based on dictCode and value
String hostypeString = dictFeignClient.getName("Hostype", hospital.getHostype());
//Inquiry of provinces, cities, regions
String provinceString = dictFeignClient.getName(hospital.getProvinceCode());
String cityString = dictFeignClient.getName(hospital.getCityCode());
String districtString = dictFeignClient.getName(hospital.getDistrictCode());
hospital.getParam().put("hostypeString",hostypeString);
hospital.getParam().put("fullAddress",provinceString + cityString + districtString);
return hospital;
}
}
controller
@RestController
@RequestMapping("/api/hosp")
public class ApiController {
@Autowired
private HospitalService hospitalService;
@Autowired
private HospitalSetService hospitalSetService;
@Autowired
private DepartmentService departmentService;
@Autowired
private ScheduleService scheduleService;
//Upload the hospital interface
@PostMapping("saveHospital")
public Result saveHosp(HttpServletRequest request){
//Get the information conveyed by the hospital
Map<String, String[]> parameterMap = request.getParameterMap();
//To avoid subsequent traversal, convert String[] in map to Object
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
// Verify that the signature is consistent
//1. Obtain the signature passed by the hospital system
String hospSign = (String) parampMap.get("sign");
//2. Query the database and query the signature based on the passed hospital code.
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
//3. Encrypt the query signature with MD5
String signKeyMD5 = MD5.encrypt(signKey);
//4. Determine whether the signature is consistent
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//The image data is transmitted by base64 tool class, and during the transmission process, "+" is converted to " ", so we need to convert it back
String logoData = (String) parampMap.get("logoData");
logoData = logoData.replace(" ","+");
parampMap.put("logoData",logoData);
//Calling service method
hospitalService.save(parampMap);
return Result.ok();
}
//Inquiry of the hospital interface
@PostMapping("hospital/show")
public Result getHospital(HttpServletRequest request){
//Get the information conveyed by the hospital
Map<String, String[]> parameterMap = request.getParameterMap();
//To avoid subsequent traversal, convert String[] in map to Object
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Get the passed hospital number
String hoscode = (String) parampMap.get("hoscode");
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Calling the service method
Hospital hospital = hospitalService.getByHoscode(hoscode);
return Result.ok(hospital);
}
//Upload the department interface
@PostMapping("saveDepartment")
public Result saveDepartment(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
// Verify that the signature is consistent
String hospSign = (String) parampMap.get("sign");
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Calling the service method
departmentService.save(parampMap);
return Result.ok();
}
//Department query interface
@PostMapping("department/list")
public Result findDepartment(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Hospital number
String hoscode = (String) parampMap.get("hoscode");
//Current page
int page = Integer.parseInt((String) parampMap.get("page"));
if(StringUtils.isEmpty(page)){
page = 1;
}
//The number of records displayed per page
int limit = Integer.parseInt((String) parampMap.get("limit"));
if(StringUtils.isEmpty(limit)){
limit = 1;
}
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Call service query
//The value of the query condition is encapsulated into departmentQueryVo
DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
departmentQueryVo.setHoscode(hoscode);
Page<Department> pageModel = departmentService.finPageDepartment(page,limit,departmentQueryVo);
return Result.ok(pageModel);
}
//Delete the department interface
@PostMapping("department/remove")
public Result removeDepartment(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Get hospital number and department number
String hoscode = (String) parampMap.get("hoscode");
String depcode = (String) parampMap.get("depcode");
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
departmentService.remove(hoscode,depcode);
return Result.ok();
}
//Upload the shift
@PostMapping("saveSchedule")
public Result saveSchedule(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Signature verification
String hospSign = (String) parampMap.get("sign");
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Calling the service method
scheduleService.save(parampMap);
return Result.ok();
}
//Inquiry scheduling
@PostMapping("schedule/list")
public Result findSchedule(HttpServletRequest request) {
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Hospital number
String hoscode = (String) parampMap.get("hoscode");
//Department number
String depcode = (String) parampMap.get("depcode");
//Current page
int page = Integer.parseInt((String) parampMap.get("page"));
if (StringUtils.isEmpty(page)) {
page = 1;
}
//The number of records displayed per page
int limit = Integer.parseInt((String) parampMap.get("limit"));
if (StringUtils.isEmpty(limit)) {
limit = 1;
}
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if (!hospSign.equals(signKeyMD5)) {
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//Call service query
//The value of the query condition is encapsulated into departmentQueryVo
ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
scheduleQueryVo.setHoscode(hoscode);
scheduleQueryVo.setDepcode(depcode);
Page<Schedule> pageModel = scheduleService.finPageSchedule(page, limit, scheduleQueryVo);
return Result.ok(pageModel);
}
//Delete the shift schedule
@PostMapping("schedule/remove")
public Result remove(HttpServletRequest request){
//Get the passed department information
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//Get the hospital number and scheduling number
String hoscode = (String) parampMap.get("hoscode");
String hosScheduleId = (String) parampMap.get("hosScheduleId");
//Signature verification
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
scheduleService.remove(hoscode,hosScheduleId);
return Result.ok();
}
}
Hospital interface simulation system test data
{
"hoscode": "1000_0",
"hosname": "Peking Union Hospital",
"hostype": "1",
"provinceCode": "110000",
"cityCode": "110100",
"districtCode": "110102",
"address": "Looking Road",
"intro": "Peking Union Hospital is a large-scale tertiary-class comprehensive hospital integrating medical care, teaching, and scientific research. It is the national guidance center for diagnosis and treatment of difficult and critical care designated by the National Health and Family Planning Commission. It is also one of the first hospitals to undertake the health care and foreign guests' medical tasks. It is well-known at home and abroad for its complete disciplines, strong technical strength, outstanding specialties, and strong multidisciplinary comprehensive advantages. It ranked first in the "China's Best Hospital Ranking" announced by the Fudan University Hospital Management Institute in 2010, 2011, 2012, 2013 and 2014.\n\nThe hospital was built in 1921 and was founded by the Rockefeller Foundation. At the beginning of its establishment, it was aimed at "building" Become the best medical center in Asia. Over the past 90 years, the hospital has formed the Union spirit of "rigorous, sophisticated, diligent and dedicated" and the inclusive cultural style, and established the modern medical education concept of "three basics" and "three stricts", and formed the Union "three treasures" known for "professors, medical records, and libraries". It has cultivated and created a generation of medical masters such as Zhang Xiaoqian and Lin Qiaozhi and many leaders in modern Chinese medicine. It has also sent a large number of medical management talents to the whole country, and created more than 10 large-scale comprehensive and specialized hospitals that are well-known today. In 2011, based on the summary of 90 years of development experience, it innovatively proposed "treat patients like relatives and improve diseases People's satisfaction; treat colleagues like family and improve employees' sense of happiness" new hospital philosophy.\n\nAt present, the hospital has 2 campuses, a total construction area of 530,000 square meters, more than 4,000 employees, 5 academicians of the two academies, 53 clinical and medical and technical departments, 20 national key disciplines, 29 national key clinical specialties, 16 doctoral programs, 29 master's programs, 6 national continuing medical education bases, 18 secondary resident training bases, and 15 third-level specialist training bases. There are more than 2,000 open hospital beds, with the highest daily outpatient number of about 15,000 people and about 80,000 discharged patients. It was rated as "full" National Civilized Unit", "National Creation and Striving for Advanced Grassroots Party Organization", "National Advanced Collective for Health System", "Capital Health System Civilized Unit", and "Most Popular Grade A Hospital" won the National May 1st Labor Medal. At the same time, the hospital also undertakes the important task of supporting the elderly, young, border and poor areas, important national activities and emergencies, and won the "Special Contribution Award" in the 2008 Beijing Olympics.\n\nFor more than 90 years, Union People have written a brilliant history with their persistent medical aspirations, noble medical ethics, superb medical skills and rigorous academic style. Today, Union People are continuing to work hard to build an "internationally renowned and first-class" hospital.",
"route": "The routes for the East Campus: 106, 108, 110, 111, 116, 684, 685 to the north of Dongdan intersection; 41, 104 Express, 814 to the south of Dongdan intersection; 1, 52, 802 to the west of Dongdan intersection; 20, 25, 37, 39 to the east of Dongdan intersection; 103, 104, 420, 803 to Xindong'an Market; Metro Lines 1 and 5 to Dongdan.\nThe routes for the West Campus: 68 to the east exit of Picai Hutong; see the instructions for more details on the routes.",
"logoData": "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",
"bookingRule": {
"cycle": "10",
"releaseTime": "08:30",
"stopTime": "11:30",
"quitDay": "-1",
"quitTime": "15:30",
"rule": [
"The location of the reservation number in the West Campus District: the registration window for the registration window of the first floor of the outpatient building in West Campus District",
"The location of the appointment number picking of the East Campus District: the registration window for the first floor of the old clinic building in the East Campus District or the registration/payment window for each floor of the new clinic building"
]
}
}
NoticeThe hospital information uploaded here, as well as the simulation system and the unified registered hospital information are consistent.
Uploading departments is the same as uploading hospital information. First, process locally and then deliver the unified appointment platform for saving.
@Override
public boolean saveDepartment(String data) {
JSONArray jsonArray = new JSONArray();
if(!data.startsWith("[")) {
JSONObject jsonObject = JSONObject.parseObject(data);
jsonArray.add(jsonObject);
} else {
jsonArray = JSONArray.parseArray(data);
}
for(int i=0, len=jsonArray.size(); i<len; i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("hoscode",this.getHoscode());
paramMap.put("depcode",jsonObject.getString("depcode"));
paramMap.put("depname",jsonObject.getString("depname"));
paramMap.put("intro",jsonObject.getString("intro"));
paramMap.put("bigcode", jsonObject.getString("bigcode"));
paramMap.put("bigname",jsonObject.getString("bigname"));
paramMap.put("timestamp", HttpRequestHelper.getTimestamp());
paramMap.put("sign",MD5.encrypt(this.getSignKey()));
JSONObject respone = HttpRequestHelper.sendRequest(paramMap,this.getApiUrl()+"/api/hosp/saveDepartment");
System.out.println(respone.toJSONString());
if(null == respone || 200 != respone.getIntValue("code")) {
throw new YyghException(respone.getString("message"), 201);
}
}
return true;
}
Before sending, custom MD5 encryption is performed, and after making an appointment, accepting the unified registration platform, then taking out the signature to decrypt it, and then comparing it from the database. If there is, the department will be saved in the mongodb database.
Convert map to department object. Before adding, query based on the hospital number and department number. If there is one, update it. If there is one, add it.
The hospital's schedule information is that there are many doctors in a department, and each doctor's visit time is different.