Commit 706ef0b7 by 毛树良

[chg]:百货:支持通过场所id统计场所下所有门店的批次/接待数据

1 parent 377cf53b
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.BMall;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import jakarta.annotation.Resource;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*/
@Repository
public class BMallDao {
@Resource
private JdbcTemplate jdbcTemplate;
/**
* 查询门店
* @param mallId
* @return
*/
public BMall getMallById(Long mallId) {
String sql = "select id,name,parent_id,unid,status,external_id,group_id from b_mall where id = ?;";
List<BMall> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(BMall.class), mallId);
if (list == null || list.size() == 0) {
return null;
}
return list.get(0);
}
/**
* 查询场所下的门店
* @param locationMallId
* @return
*/
public List<Long> getMallByLocationMallId(Long locationMallId) {
String sql = "select id from b_mall where parent_id = ?;";
return jdbcTemplate.queryForList(sql, Long.class, locationMallId);
}
/**
* 查询门店的出入口通道id
* @param storeId
* @return
*/
public List<Long> getStoreInOutChannelIds(Long storeId) {
String sql = "SELECT channel_id FROM r_mall_gate WHERE mall_id = ? and is_mall_gate = 1 and in_out = 1;";
return jdbcTemplate.queryForList(sql, Long.class, storeId);
}
}
\ No newline at end of file \ No newline at end of file
...@@ -59,6 +59,46 @@ public class FaceRecognitionDao { ...@@ -59,6 +59,46 @@ public class FaceRecognitionDao {
return namedParameterJdbcTemplate.query(sql, queryMap, new BeanPropertyRowMapper<>(Person.class)); return namedParameterJdbcTemplate.query(sql, queryMap, new BeanPropertyRowMapper<>(Person.class));
} }
/**
* 查询门店数据
* select * from d_face_recognition
* where countdate between :startDate and :endDate and counttime >= :startTime and counttime < :endTime and person_type = 0
*
* and ((mall_id = :mallId and direction in(-1,1) and channel_id IN ( SELECT channel_id FROM r_mall_gate WHERE mall_id = :storeId and is_mall_gate = 1 and in_out = 1))
* or (mall_id = :storeId and direction=6))
*
* order by person_unid asc, counttime asc;
*
* @param mallId
* @param countDate
* @return
*/
public List<Person> queryFaceRecognitionList(Long mallId, Long storeId, Date countDate) {
DateTimeParam dateTimeParam = dateTimeParamService.getDateTimeParam(mallId, countDate);
String sql = "select account_id,mall_id,gate_id,person_unid,direction,track_time,countdate as countDate,person_type,age,gender,channel_id," +
"counttime as countTime from d_face_recognition where mall_id = :mallId and countdate between :startDate and :endDate and counttime >= :startTime and counttime < :endTime and person_type = 0 " +
"and ((mall_id = :mallId and direction in(-1,1) and channel_id IN ( SELECT channel_id FROM r_mall_gate WHERE mall_id = :storeId and is_mall_gate = 1 and in_out = 1)) " +
"or (mall_id = :storeId and direction=6)) " +
"order by person_unid asc, counttime asc;";
String sqlNoMultipleDay = "select account_id,mall_id,gate_id,person_unid,direction,track_time,countdate as countDate,person_type,age,gender,channel_id," +
"counttime as countTime from d_face_recognition where mall_id = :mallId and countdate = :startDate and counttime >= :startTime and counttime < :endTime and person_type = 0 " +
"and ((mall_id = :mallId and direction in(-1,1) and channel_id IN ( SELECT channel_id FROM r_mall_gate WHERE mall_id = :storeId and is_mall_gate = 1 and in_out = 1)) " +
"or (mall_id = :storeId and direction=6)) " +
"order by person_unid asc, counttime asc;";
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("mallId", mallId);
queryMap.put("storeId", storeId);
queryMap.put("startDate", dateTimeParam.getStartDate());
queryMap.put("endDate", dateTimeParam.getEndDate());
queryMap.put("startTime", dateTimeParam.getStartDateTime());
queryMap.put("endTime", dateTimeParam.getEndDateTime());
if (DateUtil.isSameDay(dateTimeParam.getStartDate(), dateTimeParam.getEndDate())) {
return namedParameterJdbcTemplate.query(sqlNoMultipleDay, queryMap, new BeanPropertyRowMapper<>(Person.class));
}
return namedParameterJdbcTemplate.query(sql, queryMap, new BeanPropertyRowMapper<>(Person.class));
}
public List<Person> queryFaceRecognitionList(Long mallId, Date countDate) { public List<Person> queryFaceRecognitionList(Long mallId, Date countDate) {
DateTimeParam dateTimeParam = dateTimeParamService.getDateTimeParam(mallId, countDate); DateTimeParam dateTimeParam = dateTimeParamService.getDateTimeParam(mallId, countDate);
String sql = "select account_id,mall_id,gate_id,person_unid,direction,track_time,countdate as countDate,person_type,age,gender," + String sql = "select account_id,mall_id,gate_id,person_unid,direction,track_time,countdate as countDate,person_type,age,gender," +
......
package com.viontech.keliu.entity;
import lombok.Data;
/**
* @author: msl
* Date: 2025/10/28
*/
@Data
public class BMall {
private Long id;
private String name;
private Integer status;
private Long groupId;
private String externalId;
private String unid;
private Long parentId;
}
\ No newline at end of file \ No newline at end of file
...@@ -25,5 +25,6 @@ public class Person { ...@@ -25,5 +25,6 @@ public class Person {
private Integer age; private Integer age;
private Integer gender; private Integer gender;
private Integer trackTime; private Integer trackTime;
private Long channelId;
} }
\ No newline at end of file \ No newline at end of file
...@@ -15,4 +15,12 @@ import java.util.List; ...@@ -15,4 +15,12 @@ import java.util.List;
public interface PersonRecordService { public interface PersonRecordService {
void handlePersonRecord(Long mallId, Date countDate); void handlePersonRecord(Long mallId, Date countDate);
/**
*
* @param mallId 场所id
* @param storeId 门店id
* @param countDate 统计日期
*/
void handlePersonRecord(Long mallId, Long storeId, Date countDate);
} }
...@@ -43,6 +43,8 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -43,6 +43,8 @@ public class PersonRecordServiceImpl implements PersonRecordService {
@Resource @Resource
private BGateDao bGateDao; private BGateDao bGateDao;
@Resource
private BMallDao bMallDao;
@Resource @Resource
private ConfigParamDao configParamDao; private ConfigParamDao configParamDao;
...@@ -81,16 +83,42 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -81,16 +83,42 @@ public class PersonRecordServiceImpl implements PersonRecordService {
@Autowired @Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate; private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
/**
* 注意:只处理场所下的门店数据,不处理场所本身数据
* @param mallId 场所id
* @param countDate 统计日期
*/
public void handlePersonRecord(Long mallId, Date countDate) {
// 查询场所下所有门店
BMall location = bMallDao.getMallById(mallId);
if (location == null) {
log.info("门店不存在:{}", mallId);
return;
}
Long parentId = location.getParentId();
if (parentId != null) {
log.info("门店:{} 不是场所,不处理", mallId);
} else {// 是场所
List<Long> storeIds = bMallDao.getMallByLocationMallId(mallId);
if (storeIds == null || storeIds.isEmpty()) {
log.info("门店不存在子门店:{}", mallId);
return;
}
for (Long storeId : storeIds) {
handlePersonRecord(mallId, storeId, countDate);
}
}
}
@Override @Override
public void handlePersonRecord(Long mallId, Date countDate) { public void handlePersonRecord(Long mallId, Long storeId, Date countDate) {
List<Person> personList = faceRecognitionDao.queryFaceRecognitionList(mallId, countDate); List<Person> personList = faceRecognitionDao.queryFaceRecognitionList(mallId, storeId, countDate);
if (CollectionUtils.isEmpty(personList)) { if (CollectionUtils.isEmpty(personList)) {
return; return;
} }
//有抓拍记录再删除数据 //有抓拍记录再删除数据
removeData(mallId, countDate); removeData(storeId, countDate);
// 是否是自定义的汽车严格模式 // 是否是自定义的汽车严格模式
boolean strictMode = strictModeMallIds != null && strictModeMallIds.contains(mallId); boolean strictMode = strictModeMallIds != null && strictModeMallIds.contains(mallId);
...@@ -106,18 +134,18 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -106,18 +134,18 @@ public class PersonRecordServiceImpl implements PersonRecordService {
effectVisitorsConfig.setUseAge(false); effectVisitorsConfig.setUseAge(false);
} }
log.info("门店:{} 批次统计,各参数,excludePersonTime: {}, filterAttention: {}, effectVisitorsConfig: {}, personGroupMaxNum: {}, batchStatisticsModel: {}", log.info("门店:{} 批次统计,各参数,excludePersonTime: {}, filterAttention: {}, effectVisitorsConfig: {}, personGroupMaxNum: {}, batchStatisticsModel: {}",
mallId, excludePersonTime, filterAttention, effectVisitorsConfig, personGroupMaxNum, batchStatisticsModel); storeId, excludePersonTime, filterAttention, effectVisitorsConfig, personGroupMaxNum, batchStatisticsModel);
boolean needFilter = filterAttention == 1; boolean needFilter = filterAttention == 1;
//出入口gateId //出入口channelIds
List<Long> gateIds = bGateDao.getMallInOutGateIds(mallId); List<Long> channelIds = bMallDao.getStoreInOutChannelIds(storeId);
//按personUnid分组 //按personUnid分组
Map<String, List<Person>> personMap = personList.stream().collect(Collectors.groupingBy(Person::getPersonUnid)); Map<String, List<Person>> personMap = personList.stream().collect(Collectors.groupingBy(Person::getPersonUnid));
List<PersonInOutDetail> personInOutDetailList = new ArrayList<>(); List<PersonInOutDetail> personInOutDetailList = new ArrayList<>();
//进店离店匹配 //进店离店匹配
personMap.forEach((key, value) -> { personMap.forEach((key, value) -> {
//按出入口的进切割 //按出入口的进切割
int[] indexes = ListUtil.indexOfAll(value, person -> person.getDirection() == 1 && gateIds.contains(person.getGateId())); int[] indexes = ListUtil.indexOfAll(value, person -> person.getDirection() == 1 && channelIds.contains(person.getChannelId()));
for (int i = 0; i < indexes.length; i++) { for (int i = 0; i < indexes.length; i++) {
List<Person> persons; List<Person> persons;
if (i == indexes.length - 1) { if (i == indexes.length - 1) {
...@@ -129,15 +157,15 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -129,15 +157,15 @@ public class PersonRecordServiceImpl implements PersonRecordService {
Person inPerson = null; Person inPerson = null;
Person outPerson = null; Person outPerson = null;
for (Person person : persons) { for (Person person : persons) {
if (person.getDirection() == 1 && gateIds.contains(person.getGateId())) { if (person.getDirection() == 1 && channelIds.contains(person.getChannelId())) {
//进店 //进店
inPerson = person; inPerson = person;
} else if (!gateIds.contains(person.getGateId())) { } else if (!channelIds.contains(person.getChannelId())) {
//店内 //店内
inSidePersonList.add(person); inSidePersonList.add(person);
} else if (person.getDirection() == -1 && gateIds.contains(person.getGateId())) { } else if (person.getDirection() == -1 && channelIds.contains(person.getChannelId())) {
//离店 //离店
outPerson = person; outPerson = person;
} }
...@@ -145,7 +173,7 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -145,7 +173,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
if (inPerson != null) { if (inPerson != null) {
PersonInOutDetail personInOutDetail = new PersonInOutDetail(); PersonInOutDetail personInOutDetail = new PersonInOutDetail();
personInOutDetail.setAccountId(inPerson.getAccountId()); personInOutDetail.setAccountId(inPerson.getAccountId());
personInOutDetail.setMallId(inPerson.getMallId()); personInOutDetail.setMallId(storeId);
personInOutDetail.setPersonUnid(key); personInOutDetail.setPersonUnid(key);
personInOutDetail.setAge(inPerson.getAge()); personInOutDetail.setAge(inPerson.getAge());
personInOutDetail.setGender(inPerson.getGender()); personInOutDetail.setGender(inPerson.getGender());
...@@ -182,7 +210,7 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -182,7 +210,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
//List<PersonInOutDetail> allList = new ArrayList<>(); //List<PersonInOutDetail> allList = new ArrayList<>();
//allList.addAll(customerList); //allList.addAll(customerList);
//allList.addAll(staffList); //allList.addAll(staffList);
List<DPersonRecord> dPersonRecordList = handlePersonRecordData(inOutDetailList); List<DPersonRecord> dPersonRecordList = handlePersonRecordData(inOutDetailList, storeId);
//同一批次,只要有一个人被接待,则这个批次所有人都被接待 //同一批次,只要有一个人被接待,则这个批次所有人都被接待
List<DPersonRecord> recordList = new ArrayList<>(); List<DPersonRecord> recordList = new ArrayList<>();
//List<DPersonRecord> staffRecordList = dPersonRecordList.stream().filter(dPersonRecord -> dPersonRecord.getPersonType() != 0).collect(Collectors.toList()); //List<DPersonRecord> staffRecordList = dPersonRecordList.stream().filter(dPersonRecord -> dPersonRecord.getPersonType() != 0).collect(Collectors.toList());
...@@ -215,7 +243,7 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -215,7 +243,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
//按personUnid分组 //按personUnid分组
//Map<String, List<DPersonRecord>> personRecordMap = recordList.stream().collect(Collectors.groupingBy(DPersonRecord::getPersonUnid)); //Map<String, List<DPersonRecord>> personRecordMap = recordList.stream().collect(Collectors.groupingBy(DPersonRecord::getPersonUnid));
List<DPersonRecord> personRecordList = new ArrayList<>(); List<DPersonRecord> personRecordList = new ArrayList<>();
log.info("开始过滤并保存DPersonRecord. mallId:{}, countDate:{}", mallId, DateUtil.formatDate(countDate)); log.info("开始过滤并保存DPersonRecord. mallId:{}, countDate:{}", storeId, DateUtil.formatDate(countDate));
for (DPersonRecord dPersonRecord : recordList) { for (DPersonRecord dPersonRecord : recordList) {
// 根据统计模式,确定是否需要过滤掉人 // 根据统计模式,确定是否需要过滤掉人
if (batchStatisticsModel == 3) { if (batchStatisticsModel == 3) {
...@@ -234,14 +262,14 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -234,14 +262,14 @@ public class PersonRecordServiceImpl implements PersonRecordService {
} }
//修改统计数据 //修改统计数据
updateFaceRecognitionSta(mallId, countDate, personRecordList, needFilter, effectVisitorsConfig, personGroupMaxNum); updateFaceRecognitionSta(storeId, countDate, personRecordList, needFilter, effectVisitorsConfig, personGroupMaxNum);
//修改统计数据小时 //修改统计数据小时
updateFaceRecognitionStaHour(mallId, countDate, personRecordList, needFilter, effectVisitorsConfig, personGroupMaxNum); updateFaceRecognitionStaHour(storeId, countDate, personRecordList, needFilter, effectVisitorsConfig, personGroupMaxNum);
if (needFilter) { if (needFilter) {
//修改停留时长 //修改停留时长
updateMallDayResidenceCountData(mallId, countDate, personRecordList); updateMallDayResidenceCountData(storeId, countDate, personRecordList);
//修改停留时长分布 //修改停留时长分布
updateFaceResidence(mallId, countDate, personRecordList); updateFaceResidence(storeId, countDate, personRecordList);
} }
} }
...@@ -365,14 +393,15 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -365,14 +393,15 @@ public class PersonRecordServiceImpl implements PersonRecordService {
* 处理顾客区域数据,接待,看车,试乘 * 处理顾客区域数据,接待,看车,试乘
* *
* @param personInOutDetailList * @param personInOutDetailList
* @param storeId 门店id
* @return * @return
*/ */
private List<DPersonRecord> handlePersonRecordData(List<PersonInOutDetail> personInOutDetailList) { private List<DPersonRecord> handlePersonRecordData(List<PersonInOutDetail> personInOutDetailList, Long storeId) {
List<DPersonRecord> dPersonRecordList = new ArrayList<>(); List<DPersonRecord> dPersonRecordList = new ArrayList<>();
for (PersonInOutDetail personInOutDetail : personInOutDetailList) { for (PersonInOutDetail personInOutDetail : personInOutDetailList) {
DPersonRecord dPersonRecord = new DPersonRecord(); DPersonRecord dPersonRecord = new DPersonRecord();
dPersonRecord.setAccountId(personInOutDetail.getAccountId()); dPersonRecord.setAccountId(personInOutDetail.getAccountId());
dPersonRecord.setMallId(personInOutDetail.getMallId()); dPersonRecord.setMallId(storeId);
dPersonRecord.setPersonUnid(personInOutDetail.getPersonUnid()); dPersonRecord.setPersonUnid(personInOutDetail.getPersonUnid());
dPersonRecord.setGroupUnid(personInOutDetail.getGroupUnid()); dPersonRecord.setGroupUnid(personInOutDetail.getGroupUnid());
dPersonRecord.setAge(personInOutDetail.getAge()); dPersonRecord.setAge(personInOutDetail.getAge());
...@@ -416,7 +445,7 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -416,7 +445,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
//区域数据详情 //区域数据详情
List<DPersonTrackDetail> personTrackDetailList = new ArrayList<>(); List<DPersonTrackDetail> personTrackDetailList = new ArrayList<>();
gatePersonMap.forEach((key, value) -> { gatePersonMap.forEach((key, value) -> {
List<DPersonTrackDetail> personTrackDetails = getPersonTrackDetail(personInOutDetail.getGroupUnid(), value); List<DPersonTrackDetail> personTrackDetails = getPersonTrackDetail(storeId, personInOutDetail.getGroupUnid(), value);
if (!CollectionUtils.isEmpty(personTrackDetails)) { if (!CollectionUtils.isEmpty(personTrackDetails)) {
personTrackDetailList.addAll(personTrackDetails); personTrackDetailList.addAll(personTrackDetails);
} }
...@@ -449,7 +478,7 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -449,7 +478,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
} }
private List<DPersonTrackDetail> getPersonTrackDetail(String groupUnid, List<Person> personList) { private List<DPersonTrackDetail> getPersonTrackDetail(Long storeId, String groupUnid, List<Person> personList) {
if (personList.size() < 2) { if (personList.size() < 2) {
return null; return null;
} }
...@@ -483,7 +512,7 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -483,7 +512,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
if (inTrackTime != null && inTrackTime > 0) { if (inTrackTime != null && inTrackTime > 0) {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail(); DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId()); personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId()); personTrackDetail.setMallId(storeId);
personTrackDetail.setGateId(person.getGateId()); personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid()); personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid); personTrackDetail.setGroupUnid(groupUnid);
...@@ -499,7 +528,7 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -499,7 +528,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
if (outTrackTime != null && outTrackTime > 0) { if (outTrackTime != null && outTrackTime > 0) {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail(); DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId()); personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId()); personTrackDetail.setMallId(storeId);
personTrackDetail.setGateId(person.getGateId()); personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid()); personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid); personTrackDetail.setGroupUnid(groupUnid);
...@@ -514,7 +543,7 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -514,7 +543,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
} else { } else {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail(); DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId()); personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId()); personTrackDetail.setMallId(storeId);
personTrackDetail.setGateId(person.getGateId()); personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid()); personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid); personTrackDetail.setGroupUnid(groupUnid);
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!