实际修改: - 店铺维度报表新增真实数据库条件查询:店铺字段走共享镜像 SQL WHERE,主体/能否变更/生效/失效走生命周期行级过滤(左闭右开) - 店铺负责人/部门负责人/利润中心改为店铺账号 PostgreSQL 镜像值, 按店铺名称关联,未匹配时回退经营分析副本库原值 - 能否变更按主表 platform 判定(唯品会MP/淘工厂=否,其余=是), 筛选改为 是/否 下拉;默认生效时间 2026-07-01,失效未记录显示存续中 - 主体维度经营报表接入生命周期收入窗口与注册地址解析市字段 - 同步更新视图测试并重写 StoreReportRepositoryTest 匹配 SQLite 实现 验证:容器内 tests/Feature/Business + tests/Unit/EcommerceFinance + tests/Unit/Business 共 324 passed / 4 skipped;真实数据端到端验证 (无筛选 1935 行、负责人/利润中心/失效区间筛选抽样全对)。 无新增数据库迁移,不涉及生产数据写入。
68 lines
2.6 KiB
PHP
68 lines
2.6 KiB
PHP
<?php
|
||
|
||
namespace App\Business;
|
||
|
||
/**
|
||
* 从工商注册地址(rpt.fys_companyInfo.registeredAddress)解析地级市。
|
||
*
|
||
* 地址标准格式为「省/自治区/直辖市 + 地级行政区 + 区县 + 街道」,按顺序匹配:
|
||
* 1. 直辖市(北京/上海/天津/重庆)本身就是市级,直接返回「XX市」;
|
||
* 2. 剥掉省/自治区前缀后取第一个地级行政区(市/自治州/地区/盟),无省级前缀时直接匹配;
|
||
* 3. 本地地址常省略省/市前缀(如「常州经济开发区…」「武进区…」),
|
||
* 按本地区划前缀映射兜底;
|
||
* 4. 地址缺行政区划或写法不规则时返回 null,由页面按统一缺失值展示。
|
||
*/
|
||
final class RegisteredAddressCity
|
||
{
|
||
private const MUNICIPALITIES = ['北京', '上海', '天津', '重庆'];
|
||
|
||
/** 地级行政区名最长 8 字(克孜勒苏柯尔克孜自治州),过长的匹配多为「自贸试验区」类园区名,宁缺勿错。 */
|
||
private const PREFECTURE_PATTERN = '/^(.{2,8}?(?:市|自治州|地区|盟))/u';
|
||
|
||
private const PROVINCE_PATTERN = '/^(.{2,12}?(?:省|自治区))/u';
|
||
|
||
/** 公司库本地(常州)地址省略省市前缀时的区划前缀映射;按需扩展。 */
|
||
private const DISTRICT_PREFIX_CITY_MAP = [
|
||
'常州' => '常州市',
|
||
'天宁' => '常州市',
|
||
'钟楼' => '常州市',
|
||
'新北' => '常州市',
|
||
'武进' => '常州市',
|
||
'金坛' => '常州市',
|
||
'戚墅堰' => '常州市',
|
||
'溧阳' => '常州市',
|
||
];
|
||
|
||
public static function parse(mixed $address): ?string
|
||
{
|
||
$address = trim((string) ($address ?? ''));
|
||
if ($address === '') {
|
||
return null;
|
||
}
|
||
|
||
// 部分地址带「中国」前缀,剥掉后再匹配行政区划。
|
||
$address = (string) preg_replace('/^(?:中国|中华人民共和国)/u', '', $address);
|
||
|
||
foreach (self::MUNICIPALITIES as $municipality) {
|
||
if (mb_strpos($address, $municipality) === 0) {
|
||
return $municipality . '市';
|
||
}
|
||
}
|
||
|
||
// 剥掉省/自治区前缀后取第一个地级行政区;地址无省级前缀时直接匹配。
|
||
$rest = (string) preg_replace(self::PROVINCE_PATTERN, '', $address);
|
||
if (preg_match(self::PREFECTURE_PATTERN, $rest, $matches) === 1) {
|
||
return $matches[1];
|
||
}
|
||
|
||
// 本地地址省略省/市前缀时按区划前缀识别。
|
||
foreach (self::DISTRICT_PREFIX_CITY_MAP as $prefix => $city) {
|
||
if (mb_strpos($rest, $prefix) === 0) {
|
||
return $city;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|