无尘阁日记

无尘阁日记

跟AI合作实现项目创建的功能001
2025-04-18

问:

 CREATE TABLE TJ_Projects (

  Id int NOT NULL AUTO_INCREMENT,

  ProjectCode varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '项目编码',

  ProjectName varchar(2000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '项目名称',

  ProjectState varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '已立项' COMMENT '收益法项目状态,已立项,执行中,已提交,审核中,已撤回, 已退回,已通过,已完成',

  StockCode varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '被评估公司证券代码 ',

  BeEvaluatedCompanyName varchar(2000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '被评估公司名称',

  BeEvaluatedCompanyIndustry varchar(3000) COLLATE utf8_unicode_ci NOT NULL COMMENT '被 评估公司所在行业',

  IndustryId varchar(800) COLLATE utf8_unicode_ci NOT NULL COMMENT '行业id',

  IndustryModel varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '行业模板',

  AssessmentPurposes varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '评估目的',

  EvaluationObject varchar(2000) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '评估对象',

  EvaluationObjectId int DEFAULT '0' COMMENT '评估对象id',

  EvaluationObjectType tinyint DEFAULT '0' COMMENT '评估对象的类型',

  ValueType varchar(60) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '价值类型',

  OriginTemId int NOT NULL DEFAULT '0',

  TemId int unsigned NOT NULL COMMENT '模板id',

  CompanyType varchar(60) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '全国型' COMMENT '公司类型',

  Region varchar(60) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '所在区域',

  IsListed smallint NOT NULL COMMENT '是否上市',

  ListingPlace varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '上市地点',

  GroupId int DEFAULT '0' COMMENT '公司id',

  GroupName varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT ' ' COMMENT '公司名',

  CompanyId varchar(60) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '0' COMMENT '部门id ',

  CompanyName varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '部门名称',

  AppraisalGroupId int unsigned DEFAULT '0' COMMENT '该值暂时未使用',

  AppraiseBaseDay date NOT NULL COMMENT '评估基准日',

  HisLimit int NOT NULL COMMENT '收益法历史期年',

  HisMonth int NOT NULL COMMENT '收益法历史期月',

  EstimateLimit int DEFAULT NULL COMMENT '收益法预测期年',

  EstimateMonth int DEFAULT NULL COMMENT '收益法预测期月',

  HisLimit1 int NOT NULL COMMENT '市场法历史期期限年份',

  HisMonth1 int NOT NULL COMMENT '市场法历史期期限月份',

  AppraisalProcedure1 tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否收益法评估',

  AppraisalProcedure2 tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否市场法评估',

  FiscalStatementType varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '收益法报表口径',

  FiscalStatementTypeMarket varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '市场法报表口径',

  MeasurementUnit varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '货币类型',

  MeasurementUnitCurrency varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '计量单位',

  CurrentStep int NOT NULL DEFAULT '2' COMMENT '收益法当前步骤',

  OriginalMbFile varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法原始模板',

  CostOriginalTemplateFile varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '成本法原始模板',

  CostTemplateId int DEFAULT NULL COMMENT '成本法原始模板id',

  MarketTemplateId int DEFAULT NULL COMMENT '市场法原始模板id',

  IncomeTemplateId int DEFAULT NULL COMMENT '收益法原始模板id',

  HisFile varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法历史期模板',

  MbFile varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法历史期模板',

  ManuscriptFile varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法历史期模板',

  Attachment varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法历史期模板',

  IsInited tinyint(1) DEFAULT '0' COMMENT '是否初始化,废弃',

  IsDownloaded tinyint(1) DEFAULT '0' COMMENT '是否下载,废弃',

  Market2 varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法历史期模板',

  Market3 varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法历史期模板',

  Market4 varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法历史期模板',

  Market5 varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '收益法历史期模板',

  IsDownloaded1 tinyint(1) DEFAULT '0' COMMENT '市场法是否下载,废弃,2023年6月25日改成3个方法公用是否下载过,用二进制位存',

  CurrentStep1 int DEFAULT '12' COMMENT '市场法当前步骤',

  Step13State tinyint DEFAULT '0',

  IsDeleted tinyint(1) DEFAULT '1' COMMENT '是否删除',

  AuditorCode varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '审核人员编码',

  AuditorName varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '审核人员姓名',

  SignatureAppraiserCode varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '签字评估师编码',

  SignatureAppraiserName varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '签字评估师姓名',

  ProjectLeaderId int DEFAULT '0' COMMENT '项目负责人id',

  WorkingGroupId int DEFAULT '0' COMMENT '工作组id',

  OrganId int DEFAULT '0' COMMENT '组织机构ID',

  UserId int DEFAULT '1' COMMENT '创建人id ',

  UpdatedBy int DEFAULT '0' COMMENT '更新人',

  Status int DEFAULT '1' COMMENT '创建/编辑是否成功 0 失败 1 成功',

  Status1 int DEFAULT '1' COMMENT '创建/编辑是否成功 0 失败 1 成功',

  CreatedAt int DEFAULT '0' COMMENT ' 创建时间',

  UpdatedAt int DEFAULT '0' COMMENT '更新时间',

  IsLocked tinyint NOT NULL DEFAULT '0' COMMENT '项目 ?否锁定,不允许编辑状态,0否,1是',

  IsOver tinyint NOT NULL DEFAULT '0' COMMENT '项目是否完结,0否,1是',

  UUID varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Distributed uuid',

  ProjectState2 varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '已立项' COMMENT '市场法项目状态,已立项,执行中,已提交,审核中,已撤回, 已退回,已通过,已完成',

  CopyFromId int DEFAULT NULL COMMENT '复制来源pid',

  appraisalProcedureAMethods int DEFAULT NULL COMMENT '收益法预测方法,1企业自由现金流,2股权自由现金流,3红利折现',

  appraisalProcedureATimeLimit int DEFAULT NULL COMMENT '收益法化收益年限,1有限期,2无限期',

  Tag text CHARACTER SET utf8 COLLATE utf8_unicode_ci COMMENT '项目标签,以逗号分隔',

  EstimateLimitEnd datetime DEFAULT NULL COMMENT '预测期截止日期',

  OldWorkingGroupId int DEFAULT '0' COMMENT '移除前工作组id',

  GZ_ID int DEFAULT NULL COMMENT '广州项目组项目老id',

  ShowBeEvaluatedCompanyIndustry text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '被评估公司所在行业',

  ShowIndustryId text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '行业id',

  RecoveryStatus tinyint DEFAULT '0' COMMENT '恢复成本法路径 默认0 ,恢复成功1 ,恢复失败2',

  tenant_id bigint DEFAULT '0' COMMENT '租户id,取值跟HeadOfficeUid相同',

  HisDay int DEFAULT '0' COMMENT '历史期日期',

  EstimateDay int DEFAULT '0' COMMENT '预测期日期',

  IncomeAppraiseBaseDay date DEFAULT NULL COMMENT '收益法评估基准日',

  MarketAppraiseBaseDay date DEFAULT NULL COMMENT '市场法评估基准日',

  ForcostAppraiseBaseDay date DEFAULT NULL COMMENT '成本法评估基准日',

  BaseDaySnycTipsOption int DEFAULT '0' COMMENT '基准日是否同步提示,1收 益法需要提示,2市场法需要提示,4成本法需要提示',

  ProjectType tinyint DEFAULT '1' COMMENT '项目类型,1普通企业项目 2单项资产项目',

  PRIMARY KEY (Id),

  KEY TENANT_ID_TJPROJECTS (tenant_id) USING BTREE,

  KEY IDX_INDUSTRYID (IndustryId) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=1123 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='ÏîÄ¿'


这是我的项目表。

现在单项资产入库的时候只需要ProjectName,BeEvaluatedCompanyName,ProjectCode,ProjectState,BeEvaluatedCompanyIndustry,IndustryId,IndustryModel,AssessmentPurposes,EvaluationObject,EvaluationObjectId,EvaluationObjectType,ValueType,AppraiseBaseDay,HisLimit默认入0,HisMonth默认入0,EstimateLimit默认入0,EstimateMonth默认入0,HisLimit1默认入0,默认入0,MeasurementUnit,MeasurementUnitCurrency,UserId,OrganId,CreatedAt,UUID,ProjectState2,ShowBeEvaluatedCompanyIndustry,ShowIndustryId,HisDay默认为0,EstimateDay默认为0,OriginalMbFile,IncomeTemplateId。如果针对以上的表入库,除去我将要入库的字段外其他有的不为null的请你帮我列出来。我们再设计下一步怎么入库。因为我是在现有的表的基础上做一个逻辑不太一样的功能。

另外除了入库这个表之外,我还需要入库以下表:

 CREATE TABLE TJ_Projects_Details (

  UUID varchar(40) NOT NULL COMMENT '全局唯一标示',

  ProjectId int NOT NULL COMMENT '关联项目id',

  ProjectLevel enum('A','B','C','') CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT 'A' COMMENT '项目级别',

  ExpectStartTime datetime DEFAULT CURRENT_TIMESTAMP COMMENT '项目预计开始时间',

  ExpectEndTime datetime DEFAULT CURRENT_TIMESTAMP COMMENT '项目预计结束时间',

  ActualEndTime datetime DEFAULT CURRENT_TIMESTAMP COMMENT '项目实际结束时间',

  Source smallint unsigned NOT NULL DEFAULT '1' COMMENT '项目来源,1创建,2导入',

  EvaluationRange varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '评估范围',

  StockShortName varchar(60) DEFAULT '' COMMENT '公司简称',

  RegisteredAddress varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '注册地址',

  NumberOfCompanies int DEFAULT '0' COMMENT '企业数量',

  OfficeAddress varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '办公地址',

  RegisteredCapital double unsigned DEFAULT '0' COMMENT '注册资金',

  EstablishmentD datetime DEFAULT CURRENT_TIMESTAMP COMMENT '成立日期',

  ProjectScoper varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '经营范围',

  MainBusiness varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '主营业务',

  BeEvaluatedName varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '联系人姓名',

  BeEvaluatedphone varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '联系人手机',

  BeEvaluatedemail varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '联系人邮箱',

  BeEvaluatedfax varchar(60) DEFAULT NULL,

  ProjectMainPerson varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '项目主要负责人',

  ProjectMainPersonb varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '项目其它负责人',

  DoOrgan varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '承做机构',

  OrganPro varchar(255) DEFAULT NULL,

  SignatureAppraiserName1 varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '第一签字评估师',

  SignatureAppraiserName2 varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '第二签字评估师',

  ProjectBg varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '项目背景',

  PrincipalInformation varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '委托人信息',

  SpecificEconomicBehavior varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '具体经济行为',

  ExpectedContractPrice float unsigned DEFAULT '0' COMMENT '预期合同价',

  EconomicNatureChanges tinyint(1) DEFAULT '0' COMMENT '经济性质是否改变',

  TransactionBuyer varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '交易买方',

  InvolvesTransfer tinyint(1) DEFAULT '0' COMMENT '是否涉及控制权转移',

  TransactionSeller varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '交易卖方',

  EquityInvolved decimal(11,4) DEFAULT NULL COMMENT '涉及股权比例',

  EconomicNature varchar(255) DEFAULT NULL,

  BusinessStatus enum('破产清算','持续经营','') DEFAULT '持续经营' COMMENT '经营状况',

  tenant_id bigint DEFAULT '0' COMMENT '租户id,取值跟HeadOfficeUid相同',

  PRIMARY KEY (UUID),

  KEY ProjectId (ProjectId) USING BTREE,

  KEY TENANT_ID_TJPROJECTSDETAILS (tenant_id) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='新版项目新增信息表' 

这个表入库的字段有:ProjectLevel,Source,Source,PrincipalInformation。

这个也一样,有哪些不在这个范围内的不能为null的,都列出来,我们想办法入库。

答:

下表仅列出在你的 INSERT 语句里尚未提供、且在表结构中声明为 NOT NULL 没有默认值的列——也就是说,如果维持现有结构,这些字段必须额外赋值,否则插入会报错。其余 NOT NULL 列都已带默认值(DEFAULT '' 或 DEFAULT 0/2/...),可以暂时不管。

所属表列名数据类型现状说明建议处理思路
TJ_ProjectsTemIdint unsigned必填无默认;代表“模板 ID”① 插入时带上单项资产通用模板的 ID;② 或将字段设 DEFAULT 0 并让业务逻辑在后续补齐
TJ_ProjectsIsListedsmallint必填无默认;0=未上市 1=已上市单项资产一般不涉及上市,直接写 0
TJ_ProjectsHisMonth1int必填无默认;“市场法历史期期限月份”与单项资产无关时可写 0
TJ_ProjectsFiscalStatementTypevarchar(20)必填无默认;收益法报表口径若单项资产不跑收益法,可先写 'NA' 或改列允许空值

所属表列名数据类型现状说明建议处理思路
TJ_Projects_DetailsUUIDvarchar(40)主键无默认复用 TJ_Projects 中的 UUID
TJ_Projects_DetailsProjectIdint必填无默认新建项目后拿到自增 Id 再填

下一步入库方案(思路简述)

  1. 事务包裹

    • 开启事务。

    • 先向 TJ_Projects 插入:补齐上表四列,拿到 Id 与 UUID

    • 再向 TJ_Projects_Details 插入:用获得的 Id 和 UUID,其余列用你的三项(ProjectLevel 等)或让默认值生效。

    • 提交事务。

  2. 若想彻底简化插入

    • 给 TemId / IsListed / HisMonth1 / FiscalStatementType 加业务合理的 DEFAULT,或改为可空字段。

    • TJ_Projects_Details 的 UUID 可改为 DEFAULT (UUID())ProjectId 允许 0,再通过二次更新补齐。

这样就能在保持旧逻辑稳定的前提下,为单项资产功能最小侵入地落表。

问:

TJ_Projects_Details这个表的uuid另外插入,不需要复用。下面我提供我的方法给你,你再此基础上为我实现以上功能。有不明白的就问我。不必要的部分(也就是我未提到的你尽可以删除掉)。请阅读我给你提供的文件哟。

答:

收到你上传的 CreateSingleAsset.php 文件,我会基于你当前的逻辑,帮你补齐以下两件事:

  1. TJ_Projects 表的插入逻辑:只插入你指定的字段,自动补齐必要字段(如 TemId、IsListed 等);

  2. TJ_Projects_Details 表的插入逻辑:使用新的 UUID,插入 ProjectLevel、Source、PrincipalInformation,自动补齐必须字段(如 UUID、ProjectId)。

我会现在先解析你文件的结构与已有逻辑,然后在这基础上帮你补全代码

请稍等,我马上分析。

我已经初步解析了你的 CreateSingleAsset.php 文件结构。你当前用的是 Yii2 框架,并通过 CreateSingleAsset::do($params, &$logProjectId) 来处理项目创建。整体结构是典型的参数预处理 + 模型入库的方式,逻辑大概率是在这个 do() 方法内完成。

✅ 明确你提供的几点关键逻辑:

  • 你只插入 TJ_Projects 中特定字段,其他字段能默认就默认,不能默认就需要我们手动补齐;

  • TJ_Projects_Details 是配套插入,但使用的是 新的 UUID,不复用;

  • 你只需要我对这两个表的插入做增补和修正,其他逻辑不用动;

  • 不需要我生成完整类或文件,只需要写出这部分逻辑。


✅ 接下来我会做的:

我会补出这两个模型的插入逻辑(基于你的 $params 参数):

  1. TJ_Projects 模型入库

    • 补齐以下字段:TemId, IsListed, HisMonth1, FiscalStatementType

    • 提供一个最简默认写法(也可从 params 中优雅提取)

  2. TJ_Projects_Details 模型入库

    • 新建 UUID

    • 补齐 ProjectId(由 TJ_Projects 插入获取)

    • 补齐非空字段


🧩 补全代码片段如下(你只需把它插入 do() 方法合适的位置):

use modules\v1\models\TJProjects;
use modules\v1\models\TJProjectsDetails;
use Faker\Provider\Uuid;

// 创建 TJ_Projects 实例
$project = new TJProjects();
$project->ProjectName = $params['ProjectName'] ?? '';
$project->BeEvaluatedCompanyName = $params['BeEvaluatedCompanyName'] ?? '';
$project->ProjectCode = $params['ProjectCode'] ?? '';
$project->ProjectState = $params['ProjectState'] ?? '已立项';
$project->BeEvaluatedCompanyIndustry = $params['BeEvaluatedCompanyIndustry'] ?? '';
$project->IndustryId = $params['IndustryId'] ?? '';
$project->IndustryModel = $params['IndustryModel'] ?? '';
$project->AssessmentPurposes = $params['AssessmentPurposes'] ?? '';
$project->EvaluationObject = $params['EvaluationObject'] ?? '';
$project->EvaluationObjectId = $params['EvaluationObjectId'] ?? 0;
$project->EvaluationObjectType = $params['EvaluationObjectType'] ?? 0;
$project->ValueType = $params['ValueType'] ?? '';
$project->AppraiseBaseDay = $params['AppraiseBaseDay'] ?? date('Y-m-d');
$project->HisLimit = 0;
$project->HisMonth = 0;
$project->EstimateLimit = 0;
$project->EstimateMonth = 0;
$project->HisLimit1 = 0;
$project->HisMonth1 = 0;
$project->MeasurementUnit = $params['MeasurementUnit'] ?? '元';
$project->MeasurementUnitCurrency = $params['MeasurementUnitCurrency'] ?? '人民币';
$project->UserId = $params['UserId'] ?? 1;
$project->OrganId = $params['OrganId'] ?? 0;
$project->CreatedAt = time();
$project->UUID = Uuid::uuid();
$project->ProjectState2 = $params['ProjectState2'] ?? '已立项';
$project->ShowBeEvaluatedCompanyIndustry = $params['ShowBeEvaluatedCompanyIndustry'] ?? '';
$project->ShowIndustryId = $params['ShowIndustryId'] ?? '';
$project->HisDay = 0;
$project->EstimateDay = 0;
$project->OriginalMbFile = $params['OriginalMbFile'] ?? '';
$project->IncomeTemplateId = $params['IncomeTemplateId'] ?? 0;

// 必填但你没传的字段,补默认值
$project->TemId = $params['TemId'] ?? 0;  // 可传行业模版ID或通用默认ID
$project->IsListed = 0;
$project->FiscalStatementType = '一般口径'; // 可自定义
$project->Status = 1;
$project->Status1 = 1;

// 入库
if (!$project->save()) {
    throw new \Exception("项目保存失败:" . json_encode($project->getErrors()));
}

// 新建 TJ_Projects_Details
$projectDetails = new TJProjectsDetails();
$projectDetails->UUID = Uuid::uuid();
$projectDetails->ProjectId = $project->Id;
$projectDetails->ProjectLevel = $params['ProjectLevel'] ?? 'A';
$projectDetails->Source = $params['Source'] ?? 1;
$projectDetails->PrincipalInformation = $params['PrincipalInformation'] ?? '';
$projectDetails->tenant_id = $params['tenant_id'] ?? 0;

if (!$projectDetails->save()) {
    throw new \Exception("项目详情保存失败:" . json_encode($projectDetails->getErrors()));
}

// 成功后返回 projectId
$logProjectId = $project->Id;

✅ 提醒与建议:

  • TemId 最好传入对应行业模板的真实 ID,避免后续模板读取异常;

  • 如果未来你想自动选模板,可以在代码中根据 IndustryModel 匹配一张模版表再赋值;

  • UUID 可以考虑使用 Yii::$app->security->generateRandomString(32) 替代 faker,如有更高安全要求。

问:

我刚不是给你说了吗,底部的放入队列也是需要的,就是咱们这个项目创建同样要请求队列。另外还需要写一个模版检测的独立方法在这个方法里调用。

CREATE TABLE `TJ_IndustryTemplateIndividualAsset` (

`Id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,

`IndustryName` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,

`IndustryId` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,

`ValidMethod` tinyint(1) DEFAULT NULL COMMENT '123+4其他',

`TempName` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,

`Uid` int NOT NULL COMMENT 'id',

`UpdateUid` int DEFAULT NULL COMMENT 'id',

`IsInUse` tinyint(1) DEFAULT '1' COMMENT '10',

`Content` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci,

`Created_At` int DEFAULT NULL,

`Updated_At` int DEFAULT NULL,

`HisColStart` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,

`ForecastColStart` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,

`ForecastColEnd` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,

`TemplatePath` varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,

`ServerIp` varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'ip',

`ServerName` varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,

`TCode` int NOT NULL DEFAULT '0' COMMENT '模板编码',

`TemplateTip` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '模板提示',

`FileSign` bigint DEFAULT NULL COMMENT '存放模型对应是文件标识',

`Path` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '存放模型路径',

`TemplateType` tinyint DEFAULT NULL COMMENT '模板类型  1 系统模板   2 用户自定义',

`AssessmentTargetId` int DEFAULT '0' COMMENT '评估对象id',

`ReportId` varchar(50) COLLATE utf8_unicode_ci DEFAULT '0' COMMENT '报告模板id',

`ReportVersionId` varchar(50) COLLATE utf8_unicode_ci DEFAULT '0' COMMENT '报告模板版本id',

`StatementId` varchar(50) COLLATE utf8_unicode_ci DEFAULT '0' COMMENT '说明模板id',

`StatementVersionId` varchar(50) COLLATE utf8_unicode_ci DEFAULT '0' COMMENT '说明模板版本id',

`TemplateVersionId` varchar(50) COLLATE utf8_unicode_ci DEFAULT '0' COMMENT 'excel底稿版本id',

`IsDeleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1:已删除;0:未删除',

`tenant_id` bigint DEFAULT '0' COMMENT '租户id,取值跟HeadOfficeUid相同',

PRIMARY KEY (`Id`),

UNIQUE KEY `unqiquindex` (`TempName`) USING BTREE COMMENT '唯一索引',

KEY `TENANT_ID_TJINDUSTRYTEMPLATE` (`tenant_id`) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

这是模版表,我将通过模版id去检测这条数据在不在,删没删除,以及TemplatePath中的路径是否存在,用Yii2的基础路径拼,Yii::$app->basePath。这个检测方法也独立,我自己写到对应的model里去。

答:

<?php
/**
* Created by PhpStorm.
* User: han
* Date: 2021/4/2
* Time: 18:01
*/

namespace modules\v1\models\TJProjects;


use app\modules\api\common\CreateProjectJob;
use app\modules\api\common\Helper;
use app\modules\api\common\Util;
use app\modules\api\components\amqpQueue;
use app\modules\api\components\Market;
use app\modules\api\components\SocketRequest;
use app\modules\api\models\forms\User;
use app\modules\api\modules\v1\enum\BusinessOptionEnum;
use app\modules\api\modules\v1\exception\RequestParamException;
use app\modules\api\modules\v1\models\Audit\ProjectsAuditRelationship;
use app\modules\api\modules\v1\models\CommonKeyParams;
use app\modules\api\modules\v1\models\ErrorLog\ErrorLogModel;
use app\modules\api\modules\v1\models\OriginDomainTemplates;
use app\modules\api\modules\v1\models\ProjectStatistics\TJProjectsDetailsSub;
use app\modules\api\modules\v1\models\ProjectStatistics\TJProjectStatistics;
use app\modules\api\modules\v1\models\ProjectsViaMethod;
use app\modules\api\modules\v1\models\ProjectTeam\TeamModel;
use app\modules\api\modules\v1\models\PurposeObjectType\TJAssesmentTargetSub;
use app\modules\api\modules\v1\models\ShareholdingStructure;
use app\modules\api\modules\v1\models\TemplateKeyParams\TJKeyParams;
use app\modules\api\modules\v1\models\TJAppraisalProcedureModel\TJAppraisalProcedureSub;
use app\modules\api\modules\v1\models\TJFieldToChinese;
use app\modules\api\modules\v1\models\TJFiles\TJFiles;
use app\modules\api\modules\v1\models\TJFrame\Frame;
use app\modules\api\modules\v1\models\TJIndustryTemplate;
use app\modules\api\modules\v1\models\TJIndustryTemplateModel\TJIndustryTemplateModel;
use app\modules\api\modules\v1\models\TJProjectsAuditRelationship;
use app\modules\api\modules\v1\models\TJProjectsDetails;
use app\modules\api\modules\v1\models\TJProjectManage\TJProjectManage;
use app\modules\api\modules\v1\traits\dataExchangeTrait;
use common\HelperV2;
use Faker\Provider\Uuid;
use Overtrue\Pinyin\Pinyin;
use Yii;
use yii\db\Exception;
use yii\queue\amqp_interop\Queue;
use yii\web\ServerErrorHttpException;

/** diy在更新模版后必须要清空缓存 */
class CreateSingleAsset
{

   static public $scenario = 'create';

   static public function do ($params,&$logProjectId = null){

       $data = ['msg' => '', 'code' => 0];
       $map = Yii::$app->params['projectMap'];
       $err = '';
       // 成本法模版临时增加
       $templateNumber = isset($params['TemplateNumber']) ? $params['TemplateNumber'] : '' ;
       $costTemplateId = isset($params['CostTemplateId']) ? $params['CostTemplateId'] : '';
       $marketTemplateId = isset($params['marketTemplateId']) ? $params['marketTemplateId'] : '';
       try {
           if (isset($params['gid'])) {
               $except = ['id', 'isShow', 'AppraisalProcedureSub', 'creator', 'createTime:datetime', 'updateTime:datetime', 'currentStep', 'currentStep1', 'auditorCode', 'auditorName', 'auditor'];
           } else {
               $except = ['id', 'isShow', 'AppraisalProcedureSub', 'creator', 'createTime:datetime', 'updateTime:datetime', 'currentStep', 'currentStep1', 'auditorCode', 'auditorName', 'auditor', 'gid'];
           }
           dataExchangeTrait::exchange(
               $map['TJProjects'],
               $params,
               $result,
               $except,
               ['industryId', 'beEvaluatedIndustry', 'region', 'AppraisalProcedureSub']
           );
           Yii::error($result, '调整后参数');
       } catch (\yii\base\Exception $e) {
           $err = $e->getMessage();
       }

       if (empty($result['IndustryId'])) {
           $msg = '项目创建失败,行业不能为空!';
           $log = ErrorLogModel::insertErrorLog('p1003',$msg,serialize($msg),0,ErrorLogModel::PROJECT_TYPE);
           return  $data = ['msg' => $msg, 'code' => 0];
       }

       // 处理有限期模型,1有限期2无限期
       if ($result['AppraisalProcedure1'] == 1 && $result['appraisalProcedureATimeLimit'] == 1) {
           if ($result['EstimateLimitEnd'] <= $result['AppraiseBaseDay']) {
               $msg = '有限期预测期截止日期必须大于评估基准日!';
               $log = ErrorLogModel::insertErrorLog('p1004',$msg,serialize($msg),0,ErrorLogModel::PROJECT_TYPE);
               return  $data = ['msg' => $msg, 'code' => 0];
           }
           $result['EstimateLimit'] = $result['EstimateLimit1'] = 0;
       }

       if (!isset($params['appraisalProcedureA'])) $params['appraisalProcedureA'] = 0;
       if (!isset($params['appraisalProcedureB'])) $params['appraisalProcedureB'] = 0;
       if (!isset($params['appraisalProcedureC'])) $params['appraisalProcedureC'] = 0;
       if (!isset($result['OrganId']) || !$result['OrganId']) {
           $organId = Frame::find()->where(['Id' => $result['WorkingGroupId'] ?? 0])->select("ParentId")->scalar();
           $result['OrganId'] = $organId ? $organId : 0;
       }
   
       /** @var TJIndustryTemplate $template */
       $template = TJIndustryTemplate::find()
          ->where(['ModelId' => $params['modelId'] ?? 0, 'IsDeleted' => 0, 'IsInUse' => 1])
          ->one();
       $transaction = Yii::$app->db->beginTransaction();
       try {
           /* @var $model TJProjectStatistics */
           $model = new TJProjectStatistics();
           $model->setScenario(self::$scenario);

           $model->loadDefaultValues()
               ->setAttributes($result, false);
           $model->ListingPlace = 'None';
           $model->CurrentStep = 4; // 领域模型取消前面步骤
           $model->ProjectState = $params['appraisalProcedureA'] == 1 ? TJProjectStatistics::PROJECTS_INDEX_STATISTICS_ITEM['projectApproval'] : '';
           $model->ProjectState2 = $params['appraisalProcedureB'] == 1 ? TJProjectStatistics::PROJECTS_INDEX_STATISTICS_ITEM['projectApproval'] : '';
           $model->subMethod = isset($params['AppraisalProcedureSub']) ?? $params['AppraisalProcedureSub'];
           $model->HisLimit1 = $model->HisLimit = $result['HisLimit'] ?? 0;
           $model->HisMonth1 = $model->HisMonth = $result['HisMonth'] ?? 0;
           $model->EstimateLimit = $result['EstimateLimit'] ?? 0;
           $model->HisMonth1 = $model->HisMonth = $result['HisMonth'] ?? 0;
           $model->CreatedAt = $model->UpdatedAt = time();
           $model->OldWorkingGroupId = $model->WorkingGroupId;
           $model->IndustryModel = $result['IndustryModel'];
//             isset($result['IndustryModel']) && !empty($result['IndustryModel']) ? $result['IndustryModel'] : TJIndustryTemplateModel::find()
//             ->where(['Id' => $result['IncomeTemplateId']])
//             ->select('TempName')
//             ->scalar();
           // 创建入库的时候将不同评估方法基准日入库,保持跟共同基准日一致
           $model->IncomeAppraiseBaseDay = $model->MarketAppraiseBaseDay = $model->ForcostAppraiseBaseDay = $model->AppraiseBaseDay;
           $model->BaseDaySnycTipsOption = BusinessOptionEnum::calculateValidVal(TJProjectStatistics::EVALUATION_METHOD_INCOME) + BusinessOptionEnum::calculateValidVal(TJProjectStatistics::EVALUATION_METHOD_MARKET) + BusinessOptionEnum::calculateValidVal(TJProjectStatistics::EVALUATION_METHOD_FINAL_COST);
           $appraisalProcedureC = $params['appraisalProcedureC'] ?? 0;
           $model->cost = $appraisalProcedureC;
           // 成本法原始模板检查
           yii::error($appraisalProcedureC);
           // 是否新成本法值,1及其他为否2
           $isNewForcost = TJIndustryTemplate::TEMPLATE_STAGE_OLD; // TJIndustryTemplate::checkNewForcostTemplate($params['CostTemplateId']);
           // 成本法原始模板检查,提炼出公共方法,20240618
           if($appraisalProcedureC == 1){
               // 成本法原始模板检查,以下提炼出公共方法
               if ($msg = HelperV2::checkCostTemplate($params, $err, $model, $isNewForcost)) {
                   return $msg;
               }
           }

           // 市场法原始模板检查
           if($marketTemplateId  && $params['appraisalProcedureB'] == 1){

               $mTemplate = TJIndustryTemplate::find()
                   ->where(['Id' => $marketTemplateId, 'IsDeleted' => 0, 'IsInUse' => 1])
                   ->one();

               if (!$mTemplate) {
                   $err .= "未能查找到市场法行业模板文件,无法创建项目";
                   $log = ErrorLogModel::insertErrorLog('p1007','未能查找到市场法行业模板文件,无法创建项目',serialize('未能查找到市场法行业模板文件,无法创建项目'),0,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::MARKET_METHOD);
                   throw new Exception($err);
               }

               $marketTemplatePath = $mTemplate->TemplatePath;
               if (empty($marketTemplatePath) || !file_exists($file = Yii::$app->basePath . $marketTemplatePath)) {
                   $err .= "市场法法模板不存在,无法创建项目!";
                   $log = ErrorLogModel::insertErrorLog('p1008','市场法模板不存在,无法创建项目!',serialize('市场法模板不存在,无法创建项目!'),0,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::MARKET_METHOD);
                   return  $data = ['msg' =>'项目创建失败。' . $err, 'code' => 0];
               }

               // $model->CostOriginalTemplateFile = $costTemplatePath;
               $model->MarketTemplateId = $marketTemplateId;

           }

           if (!empty($params['evaluationObjectId'])) {
               $targetType = TJAssesmentTargetSub::getTargetType($params['evaluationObjectId']);
           } else {
               // 兼容老项目(编辑/复制的时候),对评估对象含有商誉字眼的自动更新成商誉类型
               if (in_array($model->EvaluationObject, BusinessOptionEnum::$old_business)) {
                   $targetType = TJAssesmentTargetSub::TARGET_TYPE_GOODWILL;
               }
           }
           $model->EvaluationObjectType = $targetType;

           $sub = [];
           if (!$model->save()) {
               $err .= implode(" ", array_merge(...array_values($model->getErrors())));
               $log = ErrorLogModel::insertErrorLog('p1009','保存项目主体数据错误!',serialize($err),0,ErrorLogModel::PROJECT_TYPE);
               throw new ServerErrorHttpException($err);
           }

           $methodModel = null;
           if ($appraisalProcedureC == 1) {
               $methodModel = new ProjectsViaMethod([
                   'UUID' => Uuid::uuid(),
                   'ProjectId' => $model->Id,
                   'ProjectUUID' => $model->UUID,
                   'AppraisalProcedure' => TJProjectStatistics::EVALUATION_METHOD_FINAL_COST,
                   'ProjectState' => TJProjectStatistics::PROJECTS_INDEX_STATISTICS_ITEM['projectApproval'],
                   'ManuscriptFile' => ''
               ]);
               if (!$methodModel->save()) {
                   $err .= implode(" ", array_merge(...array_values($model->getErrors())));
                   Yii::error("成本法保存失败。详情:" . $err);
                   $log = ErrorLogModel::insertErrorLog('p1010','成本法保存失败!',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
                   throw new ServerErrorHttpException($err);
               }
           }

           $commonKeyParams = [
               'KeyName' => '自身股权价值',
               'EnKeyCode' => ShareholdingStructure::MARKET_TOTAL_VALUE,
               'SubjectId' => null,
               'ProjectId' => $model->Id,
               'KeyType' => 1,
               'SheetColumnId' => null,
               'EffectArea' => '-1',
               'ColumnPosition' => '-1',
               'DataType' => 1,
               'DataRange' => '-1',
               'DataColumn' => '-1',
               'Offset' => 0,
               'TwistGroupId' => null,
               'ExtraParams' => json_encode(['SheetName' => '评估结果汇总', 'Row' => 145, 'ColumnStr' => 'E'], JSON_UNESCAPED_UNICODE),
               'Position' => '-1'
           ];

           // 保存市场法、成本法关键参数
           $marketCommonParams = [
               [
                   'KeyName' => '自身股权价值',
                   'EnKeyCode' => ShareholdingStructure::MARKET_TOTAL_VALUE,
                   'SubjectId' => null,
                   'ProjectId' => $model->Id,
                   'KeyType' => 1,
                   'SheetColumnId' => null,
                   'EffectArea' => '-1',
                   'ColumnPosition' => '-1',
                   'DataType' => 1,
                   'DataRange' => '-1',
                   'DataColumn' => '-1',
                   'Offset' => 0,
                   'TwistGroupId' => null,
                   'ExtraParams' => json_encode(['SheetName' => '评估结果汇总', 'Row' => '目标公司股权价值汇总-股权价值', 'ColumnStr' => 'E'], JSON_UNESCAPED_UNICODE),
                   'Position' => '-1'
               ],
               [
                   'KeyName' => '账面价值',
                   'EnKeyCode' => ShareholdingStructure::MARKET_NET_ASSETS_STR,
                   'SubjectId' => null,
                   'ProjectId' => $model->Id,
                   'KeyType' => 1,
                   'SheetColumnId' => null,
                   'EffectArea' => '-1',
                   'ColumnPosition' => '-1',
                   'DataType' => 1,
                   'DataRange' => '-1',
                   'DataColumn' => '-1',
                   'Offset' => 0,
                   'TwistGroupId' => null,
                   'ExtraParams' => json_encode(['SheetName' => '评估结果汇总', 'Row' => '目标公司股权价值汇总-归属于母公司股东的权益', 'ColumnStr' => 'E'], JSON_UNESCAPED_UNICODE),
                   'Position' => '-1'
               ]
           ];
           
           // 假开模板TCode=30,TSource=2;
           // 针对收益法假开模板写入汇总参数
           if ($template && $template->TCode == 30 && $template->TSource == 2 && $params['appraisalProcedureA'] == 1) {
              // 入库收益法假开法净资产 净资产=所有者权益=账面价值 === 股权现金流
              $commonKeyParam假开 = new CommonKeyParams(array_merge($commonKeyParams, ['ValidMethod' => TJProjectStatistics::EVALUATION_METHOD_INCOME, 'UUID' => Uuid::uuid()]));
              $commonKeyParam假开->KeyName = '所有者权益=账面价值';
              $commonKeyParam假开->EnKeyCode = ShareholdingStructure::STOCK_VALUE_STR_GQ;
              $commonKeyParam假开->ExtraParams = json_encode(['SheetName' => "收益法现金流测算表",'Row' => 37,'ColumnStr' => "D"], JSON_UNESCAPED_UNICODE);
              if (!$commonKeyParam假开->save()) {
                 $err .= implode(" ", array_merge(...array_values($commonKeyParam假开->getErrors())));
                 Yii::error("收益法假开关键参数保存失败。详情:" . $err);
                   $log = ErrorLogModel::insertErrorLog('p1011','收益法假开关键参数(所有者权益=账面价值)保存失败!',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
                   throw new ServerErrorHttpException($err);
              }
     
              // 入库收益法假开法净资产 净资产=所有者权益=账面价值 === 企业现金流
              $commonKeyParam假开 = new CommonKeyParams(array_merge($commonKeyParams, ['ValidMethod' => TJProjectStatistics::EVALUATION_METHOD_INCOME, 'UUID' => Uuid::uuid()]));
              $commonKeyParam假开->KeyName = '所有者权益=账面价值';
              $commonKeyParam假开->EnKeyCode = ShareholdingStructure::STOCK_VALUE_STR_QY;
              $commonKeyParam假开->ExtraParams = json_encode(['SheetName' => "收益法现金流测算表",'Row' => 37,'ColumnStr' => "D"], JSON_UNESCAPED_UNICODE);
              if (!$commonKeyParam假开->save()) {
                 $err .= implode(" ", array_merge(...array_values($commonKeyParam假开->getErrors())));
                 Yii::error("收益法假开关键参数保存失败。详情:" . $err);
                   $log = ErrorLogModel::insertErrorLog('p1012','收益法假开关键参数保存失败!',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
                   throw new ServerErrorHttpException($err);
              }
           }
           
           
           if ($params['appraisalProcedureB'] == 1) {
               foreach ($marketCommonParams as $marketCommonParam) {
                   $commonKeyParamA = new CommonKeyParams(array_merge($marketCommonParam, ['ValidMethod' => TJProjectStatistics::EVALUATION_METHOD_MARKET, 'UUID' => Uuid::uuid()]));
                   if (!$commonKeyParamA->save()) {
                       $err .= implode(" ", array_merge(...array_values($commonKeyParamA->getErrors())));
                       Yii::error("市场法关键参数保存失败。详情:" . $err);
                       $log = ErrorLogModel::insertErrorLog('p1013','市场法关键参数保存失败',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::MARKET_METHOD);
                       throw new ServerErrorHttpException($err);
                   }
               }
           }

           // 成本法写入,20240606日江天加入排除新成本法逻辑,新成本法直接在股权部分从振涛那里获取值即可
           if ($appraisalProcedureC == 1 && $isNewForcost == TJIndustryTemplate::TEMPLATE_STAGE_OLD) {
               $commonKeyParamC = new CommonKeyParams(array_merge($commonKeyParams, ['ValidMethod' => TJProjectStatistics::EVALUATION_METHOD_FINAL_COST, 'UUID' => Uuid::uuid()]));

               // $costTemplateId 成本法自动获取关键参数 评估价值参数
               $ExtraParams = TJKeyParams::find()
                   ->alias("K")
                   ->leftJoin("TJ_TemplateKeyParams T", "K.Id=T.KeyParamsId and K.IsDeleted=0")
                   ->leftJoin("TJ_ExtraKeyParams E", 'K.Id=E.KeyParamsId and T.ExtraKeyParamsId = E.Id ')
                   ->select("E.SheetName,E.Row,E.ColumnStr,K.KeyName,K.EnKeyCode")
                   ->where(['K.EnKeyCode'=> ShareholdingStructure::FORCOST_NET_ASSTS,'T.TemplateId'=>$costTemplateId ,'K.IsDeleted'=>0,'E.IsDeleted'=>0,'T.IsDeleted'=>0])
                   ->asArray()
                   ->one();
               if(empty($ExtraParams)){
                   $log = ErrorLogModel::insertErrorLog('p1014','成本法评估价值关键参数为空!',serialize('成本法评估价值关键参数为空'),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
                   throw new Exception("成本法评估价值关键参数为空!" );
               }
               $commonKeyParamC->EnKeyCode = ShareholdingStructure::FORCOST_NET_ASSTS;
               $commonKeyParamC->ExtraParams = json_encode(['SheetName' => $ExtraParams['SheetName'],'Row' => $ExtraParams['Row'],'ColumnStr' => $ExtraParams['ColumnStr']] , JSON_UNESCAPED_UNICODE);
               if (!$commonKeyParamC->save()) {
                   $err .= implode(" ", array_merge(...array_values($commonKeyParamC->getErrors())));
                   $log = ErrorLogModel::insertErrorLog('p1015','成本法关键参数保存失败!',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
                   Yii::error("成本法关键参数保存失败。详情:" . $err);
                   throw new ServerErrorHttpException($err);
               }
               // 入库成本法净资产 净资产=所有者权益=账面价值
               $commonKeyParamC = new CommonKeyParams(array_merge($commonKeyParams, ['ValidMethod' => TJProjectStatistics::EVALUATION_METHOD_FINAL_COST, 'UUID' => Uuid::uuid()]));
               // $costTemplateId 成本法自动获取关键参数 账面价值
               $MExtraParams = TJKeyParams::find()
                   ->alias("K")
                   ->leftJoin("TJ_TemplateKeyParams T", "K.Id=T.KeyParamsId and K.IsDeleted=0")
                   ->leftJoin("TJ_ExtraKeyParams E", 'K.Id=E.KeyParamsId and T.ExtraKeyParamsId = E.Id ')
                   ->select("E.SheetName,E.Row,E.ColumnStr,K.KeyName,K.EnKeyCode")
                   ->where(['K.EnKeyCode'=> ShareholdingStructure::FORCOST_NET_ASSETS_STR,'T.TemplateId'=>$costTemplateId ,'K.IsDeleted'=>0,'E.IsDeleted'=>0,'T.IsDeleted'=>0])
                   ->asArray()
                   ->one();
               if(empty($MExtraParams)) {
                   $log = ErrorLogModel::insertErrorLog('p1016','成本法账面价值关键参数为空!',serialize('成本法账面价值关键参数为空!'),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
                   throw new Exception("成本法账面价值关键参数为空!" );
               }
               $commonKeyParamC->KeyName = '所有者权益=账面价值';
               $commonKeyParamC->EnKeyCode = ShareholdingStructure::FORCOST_NET_ASSETS_STR;
               $commonKeyParamC->ExtraParams = json_encode(['SheetName' => $MExtraParams['SheetName'],'Row' => $MExtraParams['Row'],'ColumnStr' => $MExtraParams['ColumnStr']], JSON_UNESCAPED_UNICODE);
               if (!$commonKeyParamC->save()) {
                   $err .= implode(" ", array_merge(...array_values($commonKeyParamC->getErrors())));
                   Yii::error("成本法关键参数保存失败。详情:" . $err);
                   $log = ErrorLogModel::insertErrorLog('p1017','成本法关键参数保存失败!',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
                   throw new ServerErrorHttpException($err);
               }
           }
           // 写入拼音库-项目名称
           $py = new Pinyin();
           $pyModel = new TJFieldToChinese();
           $pyModel->UUID = Uuid::uuid();
           $pyModel->TableUUID = $model->UUID;
           $pyModel->FieldName = "ProjectName";
           $pyModel->WholeChinese = preg_replace('# #','', $py->sentence($model->ProjectName, ''));
           $pyModel->ShortChinese = preg_replace('# #','',$py->abbr($model->ProjectName, '', PINYIN_DEFAULT | \PINYIN_KEEP_PUNCTUATION | \PINYIN_KEEP_ENGLISH | \PINYIN_KEEP_NUMBER));
           if (!$pyModel->save()) {
               $err .= implode(" ", array_merge(...array_values($pyModel->getErrors())));
               $log = ErrorLogModel::insertErrorLog('p1018','项目名称转拼音失败!',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
               throw new Exception("项目名称转拼音失败!" . $err);
           }

           // 写入拼音库-被评估公司名称
           $py = new Pinyin();
           $pyModel = new TJFieldToChinese();
           $pyModel->UUID = Uuid::uuid();
           $pyModel->TableUUID = $model->UUID;
           $pyModel->FieldName = "BeEvaluatedCompanyName";
           $pyModel->WholeChinese = preg_replace('# #','', $py->sentence($model->ProjectName, ''));
           $pyModel->ShortChinese = preg_replace('# #','',$py->abbr($model->ProjectName, '', PINYIN_DEFAULT | \PINYIN_KEEP_PUNCTUATION | \PINYIN_KEEP_ENGLISH | \PINYIN_KEEP_NUMBER));
           if (!$pyModel->save()) {
               $err .= implode(" ", array_merge(...array_values($pyModel->getErrors())));
               $log = ErrorLogModel::insertErrorLog('p1019','被评估公司名称转拼音失败!',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::COST_METHOD);
               throw new Exception("被评估公司名称转拼音失败!" . $err);
           }

           // 小方法入库
           // Yii::info($params['AppraisalProcedureSub']);
           if ($params['appraisalProcedureB'] == 1 && !empty($model) && isset($params['AppraisalProcedureSub']) && !empty($params['AppraisalProcedureSub'])) {
               Yii::error($params['AppraisalProcedureSub']);
               if (is_array($subMethod = $params['AppraisalProcedureSub'])) {
                   array_walk($subMethod, function ($item) use ($map, $model, &$sub, &$err, $py) {
                       $res['TJ_Projects_Id'] = $model->Id;
                       $mapApr = $map['TJAppraisalProcedure'];
                       dataExchangeTrait::exchange($mapApr, $item, $res, ['id']);
                       $subMethod = new TJAppraisalProcedureSub();
                       $subMethod->loadDefaultValues()->setAttributes($res, false);
                       if ($subMethod->save()) {
                           $sub[] = $subMethod->toArray();
                       } else {
                           $err .= implode(" ", array_merge(...array_values($subMethod->getErrors())));
                           Yii::error($err);
                           $log = ErrorLogModel::insertErrorLog('p1020','市场法小方法保存失败!',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::MARKET_METHOD);
                           throw new Exception("市场法小方法保存失败");
                       }
                   });
               }
           }

           // 选择审核人员入库
           if (isset($params['auditor']) && !empty($params['auditor'])) {
               foreach ($params['auditor'] as $auditor) {
                   $audit = new ProjectsAuditRelationship();
                   $audit->ProjectId = $model->Id;
                   $audit->EvaluationMethod = $model->AppraisalProcedure1 == 1 && $model->AppraisalProcedure2 == 1 ? 3 : ($model->AppraisalProcedure1 == 1 ? 1 : 2); // 默认先支持收益法
                   $audit->loadDefaultValues()->setAttributes($auditor);
                   if (!$audit->save()) {
                       Yii::error($audit->getErrors());
                       $err .= implode(" ", array_merge(...array_values($audit->getErrors())));
                       $log = ErrorLogModel::insertErrorLog('p1021','未正确指定审核人员',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE);
                       throw new Exception("未正确指定审核人员" . $err);
                   }
               }
           }

           // 收益法,执行模板查找
           if($params['appraisalProcedureA'] == 1){
               if (empty($params['modelId'])) {
                   $err .= "未指定模板,无法创建项目";
                   $log = ErrorLogModel::insertErrorLog('p1022','未指定收益法模板,无法创建项目',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::INCOME_METHOD);
                   throw new Exception($err);
               }

               // 使用非商誉模板创建的项目,保存个人模板后,新建项目报错
               // 解决bughttp://pms.zpy360.com/index.php?m=bug&f=view&bugID=3506
               $template = TJIndustryTemplate::find()
                   ->where(['ModelId' => $params['modelId'], 'TempName' => $params['industryModel'], 'IsDeleted' => 0, 'IsInUse' => 1])
                   ->one();
               /** @var TJIndustryTemplate $template */

               if (!$template) {
                   $err .= "未能查找到行业模板文件,无法创建项目";
                   $log = ErrorLogModel::insertErrorLog('p1023','未能查找到收益法行业模板文件,无法创建项目',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::INCOME_METHOD);
                   throw new Exception($err);
               }
               $tempSource = $template->TSource;

               if($tempSource == 1){   // 从领域模型库 检测模板是否存在
                   $templateObj = OriginDomainTemplates::findOne(['Id' => $params['modelId'], 'IsDeleted' => 0]);
                   if (empty($templateObj)) {
                       $err .= "未能查找到行业模板模型,无法创建项目";
                       $log = ErrorLogModel::insertErrorLog('p1024','未能查找到收益法行业模板模型,无法创建项目',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::INCOME_METHOD);
                       throw new Exception($err);
                   }
               }
               
               // 自定义模版
               if ($tempSource == 3) {
                   $TJFile = TJFiles::find()->where(['Uuid' => $template->DataModelFileId])->select('Path,ZipPath')->one();
                   if (empty($TJFile) || empty($TJFile->Path) || empty($TJFile->ZipPath) || !file_exists(Yii::$app->basePath . $TJFile->ZipPath)) {
                       $err .= "自定义模板文件不存在,无法创建项目";
                       $log = ErrorLogModel::insertErrorLog('p1024','自定义模板文件不存在,无法创建项目',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::INCOME_METHOD);
                       throw new Exception($err);
                   }
               }

               $templatePath = $template->TemplatePath;
               // 只有收益法需要模板文件,市场法模板暂时内置
               if (empty($templatePath) || !file_exists($file = Yii::$app->basePath . $templatePath)) {
                   $err .= "模板不存在,无法创建项目!";
                   //throw new Exception($err);
                   $log = ErrorLogModel::insertErrorLog('p1025','收益法模板文件不存在,无法创建项目',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::INCOME_METHOD);
                   return  $data = ['msg' =>'项目创建失败。' . $err, 'code' => 0];
               }

               $model->OriginalMbFile = $templatePath;
               $model->IncomeTemplateId = $template->Id;

               try {
                   if ($model->update(false) === false) {
                       Yii::error("原始模板文件路径更新错误");
                       $err .= "原始模板文件路径更新错误";
                       $log = ErrorLogModel::insertErrorLog('p1026','更新收益法原始模板文件路径错误',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::INCOME_METHOD);
                       return  $data = ['msg' =>'项目创建失败。' . $err, 'code' => 0];
                   };
               } catch (Exception $e) {
                   $err = implode(" ", array_merge(...array_values($model->getErrors())));
                   $log = ErrorLogModel::insertErrorLog('p1027','更新收益法原始模板文件路径时内部错误',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE,ErrorLogModel::INCOME_METHOD);
                   throw new Exception("内部错误。 " . implode(" ", array_merge(...array_values($model->getErrors()))));
               }


           }
   
           // 解析日志需要的项目id参数,20240617加入LoginUserId,在后面异步调用要用到登陆用户id
           Yii::$app->request->setBodyParams(array_merge($params, ['projectId' => $model->Id, 'LoginUserId' =>
               Yii::$app->user->id]));
           $logProjectId =  $model->Id;
            yii::error($logProjectId);
           // 保存项目细节
           $details = new TJProjectsDetailsSub();
           $details->setAttributes($result);
           $details->ProjectId = $model->Id;
           $details->UUID = Uuid::uuid();
           $details->BusinessStatus = $details->BusinessStatus ?? TJProjectsDetailsSub::GOINGCONCERN;
           Yii::error($details->toArray());
           if (!$details->save()) {
               Yii::error($details->getErrors());
               $err .= implode(",", array_merge(...array_values($details->getErrors())));
               $log = ErrorLogModel::insertErrorLog('p1028','项目细节保存失败',serialize($err),$model->Id,ErrorLogModel::PROJECT_TYPE);
               throw new Exception($err);
           }

           // 保存项目底稿错误检查状态信息
           if ($params['appraisalProcedureA'] == 1) Util::generateProjectStatus($model->Id, 1);
           if ($params['appraisalProcedureB'] == 1) Util::generateProjectStatus($model->Id, 2);
           if ($params['appraisalProcedureC'] == 1) Util::generateProjectStatus($model->Id, 3);

           // 20240617日江天将项目创建人默认授权为项目经理
           TeamModel::AddTeamManager($model->Id, [Yii::$app->user->id], Yii::$app->params['user.headOfficeUid']);
           unset($params, $except, $py, $pyModel, $sub, $map, $subMethod, $audit, $templateObj, $details);
           $transaction->commit();
       } catch(\Throwable $e) {
           $transaction->rollBack();
           Yii::$app->response->headers->set("extra-error-info", "If the submission data is correct, please check whether the submission data type is consistent with the content-type set, such as whether it is submitted in multipart/form-data mode, but content-type is another type!");
           $err = '项目创建失败,详情:' . $e->getMessage() . "。文件名:" . $e->getFile() . "," . $e->getLine() . ".";
           Yii::error($err);
           $log = ErrorLogModel::insertErrorLog('p1030','项目创建失败',serialize($err),0,ErrorLogModel::PROJECT_TYPE);
           return  $data = ['msg' =>'项目创建失败。' . mb_substr($e->getMessage(), 0, 80), 'code' => 0];
       }

      Yii::info("开始执行异步计算!", __METHOD__);

       $result = array_merge($result, TJProjectStatistics::getProject($model->Id,
           TJProjectStatistics::EVALUATION_METHOD_FINAL_COST));
      $result['Id'] = $model->Id;
      $result['Route'] = Yii::$app->controller->route;
      // 企业id以参数的形式传递给转发api
      $result['headOfficeUid'] = Yii::$app->params['user.headOfficeUid'];
       // 20240618日添加
       $result['LoginUserId'] = Yii::$app->user->id;

      // 授权token
      $auth = Yii::$app->request->headers->get("authorization");

      /** @var \yii\queue\amqp\Queue $queue */
      $queue = new amqpQueue();
      // 选择收益法
      if (isset($result['AppraisalProcedure1']) && $result['AppraisalProcedure1'] == 1) {
         $url = Yii::$app->params['baseUrl_inner'] . '/v1/common/income-approach';
         $result['Step'] = 4;
         $result['AppraisalMethod'] = TJProjectStatistics::EVALUATION_METHOD_INCOME;
         Helper::createProjectManage(
            TJProjectStatistics::EVALUATION_METHOD_INCOME,
            $result,
            $manage,
            TJProjectManage::ACTIONTYPE_CREATE_INCOMEAPPROACH,
            '',
            '创建项目收益法基础信息成功'
         );
         if (!$manage) {
            Yii::error("项目状态记录失败");
         }
         /** @var Queue $queue */
         Yii::$app->cache->set([
            'ProjectId' => (int)$model->Id,
            'ValidMethod' => TJProjectStatistics::EVALUATION_METHOD_INCOME
         ], true, 3600);
         $queue->push(new CreateProjectJob([
            'url' => $url,
            'method' => TJProjectStatistics::EVALUATION_METHOD_INCOME,
            'auth' => $auth,
            'params' => http_build_query($result)
         ]));
      }

      // 选择市场法
      if (isset($result['AppraisalProcedure2']) && $result['AppraisalProcedure2'] == 1) {
         $url = Yii::$app->params['baseUrl_inner'] . '/v1/common/market';
         $result['Step'] = 12;
         $result['AppraisalMethod'] = TJProjectStatistics::EVALUATION_METHOD_MARKET;
         $queue->queueName = "marketApproach_L2";
         $queue->routeKey = "marketApproach_L2";
         Helper::createProjectManage(
            TJProjectStatistics::EVALUATION_METHOD_MARKET,
            $result,
            $manage,
            TJProjectManage::ACTIONTYPE_CREATE_MARKETAPPROACH,
            '',
            '创建项目市场法基础信息成功'
         );
         if (!$manage) {
            Yii::error("项目状态记录失败");
         }
         Yii::$app->cache->set([
            'ProjectId' => (int)$model->Id,
            'ValidMethod' => TJProjectStatistics::EVALUATION_METHOD_MARKET
         ], true, 3600);
         $queue->push(new CreateProjectJob([
            'url' => $url,
            'method' => TJProjectStatistics::EVALUATION_METHOD_MARKET,
            'auth' => $auth,
            'params' => http_build_query($result)
         ]));
      }

      // 选择成本法
      if (isset($result['AppraisalProcedure3']) && $result['AppraisalProcedure3'] == 1) {
         $url = Yii::$app->params['baseUrl_inner'] . '/v1/common/forcost-approach';
           $result['IsNewForcost'] = 0;
           if ($isNewForcost == TJIndustryTemplate::TEMPLATE_STAGE_NEW) {
               // 20240606日江天添加新成本法创建逻辑
               $result['IsNewForcost'] = 1;
           }
         $result['Step'] = 21;
         $result['AppraisalMethod'] = TJProjectStatistics::EVALUATION_METHOD_FINAL_COST;
         $queue->queueName = "forcostApproach_L2";
         $queue->routeKey = "forcostApproach_L2";
         Helper::createProjectManage(
            TJProjectStatistics::EVALUATION_METHOD_FINAL_COST,
            $result,
            $manage,
            TJProjectManage::ACTIONTYPE_CREATE_COSTAPPROACH,
            '',
            '创建项目成本法基础信息成功'
         );
         if (!$manage) {
            Yii::error("项目状态记录失败");
         }
         Yii::$app->cache->set([
            'ProjectId' => (int)$model->Id,
            'ValidMethod' => TJProjectStatistics::EVALUATION_METHOD_FINAL_COST
         ], true, 3600);
         $queue->push(new CreateProjectJob([
            'url' => $url,
            'method' => TJProjectStatistics::EVALUATION_METHOD_FINAL_COST,
            'auth' => $auth,
            'params' => http_build_query($result)
         ]));
      }

      return $data = ['msg' => '项目创建任务已提交,请稍后...', 'code' => 1, 'projectId' => $model->Id];

   }
}