feat(sync): 新增 buildings 流输出楼座坐标

This commit is contained in:
xiaoqu
2026-10-26 17:56:54 +08:00
parent 6acb6f7dff
commit 8c5e139bfd
5 changed files with 150 additions and 0 deletions
@@ -0,0 +1,57 @@
package me.iiv.agent.entity.m0;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
/** 楼座(b0.building):设备安装的物理位置,含经纬度。 */
@TableName("building")
public class Building implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Long propertyId;
private String address;
private String province;
private String city;
private String countyseat;
private Double longitude;
private Double latitude;
@TableField("soft_delete")
private Integer softDelete;
@TableField("create_time")
private Date createTime;
@TableField("modify_time")
private Date modifyTime;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Long getPropertyId() { return propertyId; }
public void setPropertyId(Long propertyId) { this.propertyId = propertyId; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String getProvince() { return province; }
public void setProvince(String province) { this.province = province; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getCountyseat() { return countyseat; }
public void setCountyseat(String countyseat) { this.countyseat = countyseat; }
public Double getLongitude() { return longitude; }
public void setLongitude(Double longitude) { this.longitude = longitude; }
public Double getLatitude() { return latitude; }
public void setLatitude(Double latitude) { this.latitude = latitude; }
public Integer getSoftDelete() { return softDelete; }
public void setSoftDelete(Integer softDelete) { this.softDelete = softDelete; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public Date getModifyTime() { return modifyTime; }
public void setModifyTime(Date modifyTime) { this.modifyTime = modifyTime; }
}
@@ -0,0 +1,7 @@
package me.iiv.agent.mapper.m0;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import me.iiv.agent.entity.m0.Building;
public interface BuildingMapper extends BaseMapper<Building> {
}
@@ -0,0 +1,60 @@
package me.iiv.agent.mcp.sync;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import me.iiv.agent.entity.m0.Building;
import me.iiv.agent.entity.m0.User;
import me.iiv.agent.mapper.m0.BuildingMapper;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/** buildings 同步实体(b0.building 楼座,含经纬度)。 */
@Component
public class BuildingsSyncEntity extends AbstractSyncEntity implements SyncEntity {
public static final String NAME = "buildings";
final BuildingMapper buildingMapper;
public BuildingsSyncEntity(BuildingMapper buildingMapper) {
this.buildingMapper = buildingMapper;
}
@Override
public String name() {
return NAME;
}
@Override
public List<SyncRow> fetchPage(Long fromTs, long cutoffTs, Long cursorMt, Long cursorId,
int limit, User user) {
LambdaQueryWrapper<Building> wrapper = new LambdaQueryWrapper<>();
applyWindow(wrapper, fromTs, cutoffTs, cursorMt, cursorId);
applyOrderAndLimit(wrapper, limit);
List<Building> rows = buildingMapper.selectList(wrapper);
List<SyncRow> out = new ArrayList<>(rows.size());
for (Building row : rows) {
long mt = ChangesEngine.effectiveTs(row.getModifyTime(), row.getCreateTime());
out.add(new SyncRow(toItem(row, mt), mt, row.getId()));
}
return out;
}
private Map<String, Object> toItem(Building row, long mt) {
boolean deleted = row.getSoftDelete() != null && row.getSoftDelete() == 1;
Date effective = row.getModifyTime() != null ? row.getModifyTime() : row.getCreateTime();
return SyncChangeSchemas.toMap(new SyncChangeSchemas.BuildingChange(
stableId(row.getId()), stableId(row.getPropertyId()),
row.getName(), row.getAddress(),
row.getProvince(), row.getCity(), row.getCountyseat(),
row.getLongitude(), row.getLatitude(),
ChangesEngine.iso(effective), mt, deleted ? ChangesEngine.iso(effective) : null));
}
private static String stableId(Long id) {
return id == null ? null : String.valueOf(id);
}
}
@@ -85,6 +85,21 @@ final class SyncChangeSchemas {
@JsonProperty("deleted_at") String deletedAt) {
}
record BuildingChange(
@JsonProperty("building_id") String buildingId,
@JsonProperty("property_id") String propertyId,
String name,
String address,
String province,
String city,
String countyseat,
Double longitude,
Double latitude,
@JsonProperty("updated_at") String updatedAt,
long version,
@JsonProperty("deleted_at") String deletedAt) {
}
record ContractChange(
@JsonProperty("contract_id") String contractId,
@JsonProperty("contract_no") String contractNo,
@@ -88,6 +88,17 @@ public class ChangesTools implements ToolObject {
return changesEngine.execute(PropertiesSyncEntity.NAME, syncToken, cursor, limit);
}
@XqTool(category = "sync", kind = "read")
@Tool(name = "buildings.changes.list", description = "增量同步楼座主数据(b0.building,含经纬度)。" + PROTOCOL_DESC
+ "items 字段:building_id/property_id/name/address/province/city/countyseat/"
+ "longitude/latitude/updated_at/version/deleted_at。")
public Map<String, Object> buildingsChangesList(
@ToolParam(required = false, description = SYNC_TOKEN_DESC) String syncToken,
@ToolParam(required = false, description = CURSOR_DESC) String cursor,
@ToolParam(required = false, description = LIMIT_DESC) Integer limit) {
return changesEngine.execute(BuildingsSyncEntity.NAME, syncToken, cursor, limit);
}
@XqTool(category = "sync", kind = "read")
@Tool(name = "contracts.changes.list", description = "增量同步合同主数据(m2.contract_new)。" + PROTOCOL_DESC
+ "items 字段:contract_id/contract_no/contract_name/status(PENDING/REJECTED/ACTIVE/EXPIRED/TERMINATED)/"