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
......@@ -59,6 +59,46 @@ public class FaceRecognitionDao {
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) {
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," +
......
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
......@@ -25,5 +25,6 @@ public class Person {
private Integer age;
private Integer gender;
private Integer trackTime;
private Long channelId;
}
\ No newline at end of file
......@@ -15,4 +15,12 @@ import java.util.List;
public interface PersonRecordService {
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 {
@Resource
private BGateDao bGateDao;
@Resource
private BMallDao bMallDao;
@Resource
private ConfigParamDao configParamDao;
......@@ -81,16 +83,42 @@ public class PersonRecordServiceImpl implements PersonRecordService {
@Autowired
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
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)) {
return;
}
//有抓拍记录再删除数据
removeData(mallId, countDate);
removeData(storeId, countDate);
// 是否是自定义的汽车严格模式
boolean strictMode = strictModeMallIds != null && strictModeMallIds.contains(mallId);
......@@ -106,18 +134,18 @@ public class PersonRecordServiceImpl implements PersonRecordService {
effectVisitorsConfig.setUseAge(false);
}
log.info("门店:{} 批次统计,各参数,excludePersonTime: {}, filterAttention: {}, effectVisitorsConfig: {}, personGroupMaxNum: {}, batchStatisticsModel: {}",
mallId, excludePersonTime, filterAttention, effectVisitorsConfig, personGroupMaxNum, batchStatisticsModel);
storeId, excludePersonTime, filterAttention, effectVisitorsConfig, personGroupMaxNum, batchStatisticsModel);
boolean needFilter = filterAttention == 1;
//出入口gateId
List<Long> gateIds = bGateDao.getMallInOutGateIds(mallId);
//出入口channelIds
List<Long> channelIds = bMallDao.getStoreInOutChannelIds(storeId);
//按personUnid分组
Map<String, List<Person>> personMap = personList.stream().collect(Collectors.groupingBy(Person::getPersonUnid));
List<PersonInOutDetail> personInOutDetailList = new ArrayList<>();
//进店离店匹配
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++) {
List<Person> persons;
if (i == indexes.length - 1) {
......@@ -129,15 +157,15 @@ public class PersonRecordServiceImpl implements PersonRecordService {
Person inPerson = null;
Person outPerson = null;
for (Person person : persons) {
if (person.getDirection() == 1 && gateIds.contains(person.getGateId())) {
if (person.getDirection() == 1 && channelIds.contains(person.getChannelId())) {
//进店
inPerson = person;
} else if (!gateIds.contains(person.getGateId())) {
} else if (!channelIds.contains(person.getChannelId())) {
//店内
inSidePersonList.add(person);
} else if (person.getDirection() == -1 && gateIds.contains(person.getGateId())) {
} else if (person.getDirection() == -1 && channelIds.contains(person.getChannelId())) {
//离店
outPerson = person;
}
......@@ -145,7 +173,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
if (inPerson != null) {
PersonInOutDetail personInOutDetail = new PersonInOutDetail();
personInOutDetail.setAccountId(inPerson.getAccountId());
personInOutDetail.setMallId(inPerson.getMallId());
personInOutDetail.setMallId(storeId);
personInOutDetail.setPersonUnid(key);
personInOutDetail.setAge(inPerson.getAge());
personInOutDetail.setGender(inPerson.getGender());
......@@ -182,7 +210,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
//List<PersonInOutDetail> allList = new ArrayList<>();
//allList.addAll(customerList);
//allList.addAll(staffList);
List<DPersonRecord> dPersonRecordList = handlePersonRecordData(inOutDetailList);
List<DPersonRecord> dPersonRecordList = handlePersonRecordData(inOutDetailList, storeId);
//同一批次,只要有一个人被接待,则这个批次所有人都被接待
List<DPersonRecord> recordList = new ArrayList<>();
//List<DPersonRecord> staffRecordList = dPersonRecordList.stream().filter(dPersonRecord -> dPersonRecord.getPersonType() != 0).collect(Collectors.toList());
......@@ -215,7 +243,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
//按personUnid分组
//Map<String, List<DPersonRecord>> personRecordMap = recordList.stream().collect(Collectors.groupingBy(DPersonRecord::getPersonUnid));
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) {
// 根据统计模式,确定是否需要过滤掉人
if (batchStatisticsModel == 3) {
......@@ -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) {
//修改停留时长
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 {
* 处理顾客区域数据,接待,看车,试乘
*
* @param personInOutDetailList
* @param storeId 门店id
* @return
*/
private List<DPersonRecord> handlePersonRecordData(List<PersonInOutDetail> personInOutDetailList) {
private List<DPersonRecord> handlePersonRecordData(List<PersonInOutDetail> personInOutDetailList, Long storeId) {
List<DPersonRecord> dPersonRecordList = new ArrayList<>();
for (PersonInOutDetail personInOutDetail : personInOutDetailList) {
DPersonRecord dPersonRecord = new DPersonRecord();
dPersonRecord.setAccountId(personInOutDetail.getAccountId());
dPersonRecord.setMallId(personInOutDetail.getMallId());
dPersonRecord.setMallId(storeId);
dPersonRecord.setPersonUnid(personInOutDetail.getPersonUnid());
dPersonRecord.setGroupUnid(personInOutDetail.getGroupUnid());
dPersonRecord.setAge(personInOutDetail.getAge());
......@@ -416,7 +445,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
//区域数据详情
List<DPersonTrackDetail> personTrackDetailList = new ArrayList<>();
gatePersonMap.forEach((key, value) -> {
List<DPersonTrackDetail> personTrackDetails = getPersonTrackDetail(personInOutDetail.getGroupUnid(), value);
List<DPersonTrackDetail> personTrackDetails = getPersonTrackDetail(storeId, personInOutDetail.getGroupUnid(), value);
if (!CollectionUtils.isEmpty(personTrackDetails)) {
personTrackDetailList.addAll(personTrackDetails);
}
......@@ -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) {
return null;
}
......@@ -483,7 +512,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
if (inTrackTime != null && inTrackTime > 0) {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId());
personTrackDetail.setMallId(storeId);
personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid);
......@@ -499,7 +528,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
if (outTrackTime != null && outTrackTime > 0) {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId());
personTrackDetail.setMallId(storeId);
personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid);
......@@ -514,7 +543,7 @@ public class PersonRecordServiceImpl implements PersonRecordService {
} else {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId());
personTrackDetail.setMallId(storeId);
personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid);
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!