global class MergeAgencyActivityBatch implements Database.Batchable<sObject>, Database.Stateful {
|
global Map<Id, Contact> oldIdNewContactMap = new Map<Id, Contact>(); // 7. Agency_Report_Header 和 8. Agency_Report 里用到
|
global Map<Id, Id> oldIdNewUserIdMap = new Map<Id, Id>(); // Agency_XXX table Owner 設定用
|
global Map<Id, Id> newIdOldUserIdMap = new Map<Id, Id>(); // Agency_XXX table Owner 設定用
|
global Map<Id, Agency_Hospital_Link__c> newAgencyHospitalMap = new Map<Id, Agency_Hospital_Link__c>(); // .客户人员(new, key is Hospital__c)
|
|
public String oldAgencyCode;
|
public String newAgencyCode;
|
public Boolean forceFlg;
|
public List<String> emailMessages;
|
public String oldAgencyId;
|
public String newAgencyId;
|
|
global Integer totalCount = 0; // 总件数
|
global Integer failedCount = 0;
|
|
@TestVisible
|
private static List<String> messagesForTest;
|
|
/**
|
* @param forceFlg true:不对有没有New Agency的数据进行check
|
*/
|
global MergeAgencyActivityBatch(String oldAgencyCode, String newAgencyCode, Boolean forceFlg) {
|
this.oldAgencyCode = oldAgencyCode;
|
this.newAgencyCode = newAgencyCode;
|
this.forceFlg = forceFlg;
|
this.emailMessages = new List<String>();
|
}
|
|
// TODO katsu 暫定 1万 超えない前提
|
global Database.QueryLocator start(Database.BatchableContext bc) {
|
Account[] accList;
|
accList = [SELECT Id
|
FROM Account
|
WHERE Management_Code__c = :this.oldAgencyCode];
|
if (accList.size() != 1) {
|
this.emailMessages.add('没有找到 或 有多条 旧经销商 [' + this.oldAgencyCode + '] 的数据, size=' + accList.size());
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
} else {
|
this.oldAgencyId = accList[0].Id;
|
}
|
accList = [SELECT Id
|
FROM Account
|
WHERE Management_Code__c = :this.newAgencyCode];
|
if (accList.size() != 1) {
|
this.emailMessages.add('没有找到 或 有多条 新经销商 [' + this.newAgencyCode + '] 的数据, size=' + accList.size());
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
} else {
|
this.newAgencyId = accList[0].Id;
|
}
|
if (forceFlg == false && [SELECT Id
|
FROM Agency_Contact__c
|
WHERE Agency_Hospital__r.Agency__r.Management_Code__c = :this.newAgencyCode].size() > 0) {
|
|
this.emailMessages.add('.客户人员 里不可以有 New Agency [' + this.newAgencyCode + '] 的数据');
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
if (forceFlg == false && [SELECT Id
|
FROM Agency_Opportunity__c
|
WHERE Agency_Hospital_All__r.Agency__r.Management_Code__c = :this.newAgencyCode].size() > 0) {
|
|
this.emailMessages.add('经销商询价 里不可以有 New Agency [' + this.newAgencyCode + '] 的数据');
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
if (forceFlg == false && [SELECT Id
|
FROM Agency_Report_Header__c
|
WHERE Agency__r.Management_Code__c = :this.newAgencyCode].size() > 0) {
|
|
this.emailMessages.add('.周报一览 里不可以有 New Agency [' + this.newAgencyCode + '] 的数据');
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
if (forceFlg == false && [SELECT Id
|
FROM Agency_Report__c
|
WHERE Agency__r.Management_Code__c = :this.newAgencyCode].size() > 0) {
|
|
this.emailMessages.add('.周报明细 里不可以有 New Agency [' + this.newAgencyCode + '] 的数据');
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
|
// 事前のデータを取得
|
// 1. New Agency_Hospital 新的营销关系
|
for (Agency_Hospital_Link__c nObj : [SELECT Id
|
, Agency__c, Agency__r.Management_Code__c, Hospital__c
|
FROM Agency_Hospital_Link__c
|
WHERE Agency__r.Management_Code__c = :this.newAgencyCode
|
ORDER BY CreatedDate]) {
|
// map的重复不用考虑
|
newAgencyHospitalMap.put(nObj.Hospital__c, nObj);
|
}
|
|
// 5. New Contact
|
String Contact_Agency_RT = Schema.SObjectType.Contact.getRecordTypeInfosByDeveloperName().get('Agency').getRecordTypeId();
|
Map<Id, Contact> newContactMap = new Map<Id, Contact>(); // 取引先責任者(new)
|
Map<String, Contact> newContactNameMap = new Map<String, Contact>(); // 取引先責任者(new, key is Name)
|
for (Contact nObj : [SELECT Id
|
, AccountId, Name, Agency_User__c
|
FROM Contact
|
WHERE RecordTypeId = :Contact_Agency_RT
|
AND Account.Management_Code__c = :this.newAgencyCode]) {
|
|
// Contact.Name重复 check
|
Contact oObj = newContactNameMap.get(nObj.Name);
|
if (oObj != null) {
|
this.emailMessages.add('客户人员 ' + oObj.Name + ' 重复, 请确认 ' + oObj.Id + ' , ' + nObj.Id + ' 的数据');
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
newContactMap.put(nObj.Id, nObj);
|
newContactNameMap.put(nObj.Name, nObj);
|
}
|
|
// 6. Old Contact
|
Map<Id, Contact> oldContactMap = new Map<Id, Contact>();
|
Map<String, Contact> oldContactNameMap = new Map<String, Contact>(); // 取引先責任者(new, key is Name)
|
for (Contact nObj : [SELECT Id, Name
|
, Account.Management_Code__c, Agency_User__c, FirstName, LastName
|
FROM Contact
|
WHERE RecordTypeId = :Contact_Agency_RT
|
AND Agency_User__c = true
|
AND Account.Management_Code__c = :this.oldAgencyCode]) {
|
|
// Contact.Name重复 check
|
Contact oObj = oldContactNameMap.get(nObj.Name);
|
if (oObj != null) {
|
this.emailMessages.add('客户人员 ' + oObj.Name + ' 重复, 请确认 ' + oObj.Id + ' , ' + nObj.Id + ' 的数据');
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
oldContactMap.put(nObj.Id, nObj);
|
oldContactNameMap.put(nObj.Name, nObj);
|
}
|
|
// 新旧UserのMapping
|
Map<String, User> newUserNameMap = new Map<String, User>();
|
for (User nObj : [SELECT Id, Name
|
, ContactId
|
FROM User
|
WHERE IsPortalEnabled = true
|
AND IsActive = true
|
AND Contact.AccountId = :this.newAgencyId
|
AND ContactId IN :newContactMap.keySet()]) {
|
newUserNameMap.put(nObj.Name, nObj);
|
}
|
Map<String, User> oldUserNameMap = new Map<String, User>();
|
for (User nObj : [SELECT Id, Name
|
, ContactId
|
FROM User
|
WHERE IsPortalEnabled = true
|
AND IsActive = true
|
AND Contact.AccountId = :this.oldAgencyId
|
AND ContactId IN :oldContactMap.keySet()]) {
|
oldUserNameMap.put(nObj.Name, nObj);
|
}
|
|
// 5. New User 件数必须和 6 一样(force y也不让过)
|
for (User oObj : oldUserNameMap.values()) {
|
User nObj = newUserNameMap.get(oObj.Name);
|
if (nObj == null) {
|
this.emailMessages.add('User:' + oObj.Name + ' 在 ' + newAgencyCode + ' 里不存在, 请确认有没有造新的用户');
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
this.oldIdNewUserIdMap.put(oObj.Id, nObj.Id);
|
this.newIdOldUserIdMap.put(nObj.Id, oObj.Id);
|
}
|
if (this.oldIdNewUserIdMap.size() == 0) {
|
this.emailMessages.add('没有找到 新经销商的用户数据');
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
|
// 5. New Contact 件数必须和 6 一样(补到 一样 or 超过)
|
List<Contact> upsList = new List<Contact>();
|
for (Contact oObj : oldContactMap.values()) {
|
Contact nObj = newContactNameMap.get(oObj.Name);
|
Boolean isTarget = false;
|
if (nObj == null) {
|
nObj = new Contact(Agency_User__c = true
|
, RecordTypeId = Contact_Agency_RT
|
, FirstName = oObj.FirstName
|
, LastName = oObj.LastName
|
);
|
isTarget = true;
|
}
|
if (nObj.Agency_User__c != true) {
|
isTarget = true;
|
}
|
nObj.AccountId = this.newAgencyId;
|
nObj.Agency_User__c = true;
|
this.oldIdNewContactMap.put(oObj.Id, nObj);
|
if (isTarget) {
|
upsList.add(nObj);
|
}
|
}
|
List<Database.UpsertResult> urList = Database.upsert(upsList, Contact.Fields.Id, false);
|
Integer errorCnt = setUpstError(urList, Contact.getSObjectType(), upsList);
|
totalCount += upsList.size();
|
if (errorCnt > 0) {
|
failedCount += errorCnt;
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
|
// 7. Agency_Report_Header
|
List<Agency_Report_Header__c> oldArhList = [SELECT Id, Name
|
, Old_OwnerId__c, Old_Agency__c, Old_Agency_Person2__c
|
, OwnerId, Agency__c, Agency_Person2__c
|
FROM Agency_Report_Header__c
|
WHERE Agency__r.Management_Code__c = :this.oldAgencyCode];
|
for (Agency_Report_Header__c ups : oldArhList) {
|
if (false == newIdOldUserIdMap.containsKey(ups.OwnerId)) {
|
ups.Old_OwnerId__c = ups.OwnerId;
|
ups.OwnerId = oldIdNewUserIdMap.get(ups.OwnerId);
|
}
|
if (ups.Agency__c != this.newAgencyId) {
|
ups.Old_Agency__c = ups.Agency__c;
|
ups.Agency__c = this.newAgencyId;
|
ups.Agency_ID__c = this.newAgencyId.mid(0, 15);
|
}
|
if (ups.Agency_Person2__c != this.oldIdNewContactMap.get(ups.Agency_Person2__c).Id) {
|
ups.Old_Agency_Person2__c = ups.Agency_Person2__c;
|
ups.Agency_Person2__c = this.oldIdNewContactMap.get(ups.Agency_Person2__c).Id;
|
}
|
}
|
List<Database.SaveResult> srList = Database.update(oldArhList, false);
|
AgencyReportHeaderHandler.shareAgency_Report_Header_ToRole(oldArhList);
|
errorCnt = setSaveError(srList, Agency_Report_Header__c.getSObjectType(), oldArhList);
|
totalCount += oldArhList.size();
|
if (errorCnt > 0) {
|
failedCount += errorCnt;
|
return Database.getQueryLocator([SELECT Id FROM Agency_Hospital_Link__c LIMIT 0]);
|
}
|
|
// Batch実行
|
// 2. Old Agency_Hospital 为基础
|
return Database.getQueryLocator([SELECT Id
|
, Agency__c, Agency__r.Management_Code__c, Hospital__c, Hospital__r.Management_Code__c
|
FROM Agency_Hospital_Link__c
|
WHERE Agency__r.Management_Code__c = :this.oldAgencyCode
|
]
|
);
|
}
|
|
global void execute(Database.BatchableContext BC, List<Agency_Hospital_Link__c> oldAgencyHospitalList) {
|
Map<Id, Agency_Opportunity__c> oldAgencyOpportunityMap = new Map<Id, Agency_Opportunity__c>(); // 经销商询价(old)
|
Map<Id, User> ocsmUserMap = new Map<Id, User>(); //ocsm内部ユーザー
|
|
// 事前のデータを取得
|
// 1. ocsm内部ユーザー
|
ocsmUserMap = new Map<Id, User>([SELECT Id FROM User WHERE IsPortalEnabled = false]);
|
// 2. Old Agency_Hospital 旧的营销关系 -> 新的营销关系
|
Map<Id, Agency_Hospital_Link__c> oldIdNewAgencyHospitalMap = new Map<Id, Agency_Hospital_Link__c>(); // 3. Agency_Contact, 4. Agency_Opportunity, 8. Agency_Report 里用到
|
for (Agency_Hospital_Link__c oObj : oldAgencyHospitalList) {
|
Agency_Hospital_Link__c nObj = this.newAgencyHospitalMap.get(oObj.Hospital__c);
|
if (nObj == null) {
|
this.emailMessages.add('没有找到新的营销关系 请确认是否存在 ' + oObj.Hospital__r.Management_Code__c + ' 的数据');
|
} else {
|
oldIdNewAgencyHospitalMap.put(oObj.Id, nObj);
|
}
|
}
|
|
// 3. Agency_Contact
|
List<Agency_Contact__c> oldAgencyContactList = [SELECT Id, Name
|
, Old_OwnerId__c, Old_Agency_Hospital__c, Old_Agency_ID__c
|
, OwnerId, Agency_Hospital__c, Agency_ID__c
|
FROM Agency_Contact__c
|
WHERE Agency_Hospital__c IN :oldAgencyHospitalList];
|
for (Agency_Contact__c ups : oldAgencyContactList) {
|
if (false == newIdOldUserIdMap.containsKey(ups.OwnerId)) {
|
ups.Old_OwnerId__c = ups.OwnerId;
|
ups.OwnerId = oldIdNewUserIdMap.get(ups.OwnerId);
|
}
|
if (ups.Agency_Hospital__c != oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital__c).Id) {
|
ups.Old_Agency_Hospital__c = ups.Agency_Hospital__c;
|
ups.Agency_Hospital__c = oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital__c).Id;
|
}
|
if (ups.Agency_ID__c != this.newAgencyId.mid(0, 15)) {
|
ups.Old_Agency_ID__c = ups.Agency_ID__c;
|
ups.Agency_ID__c = this.newAgencyId.mid(0, 15);
|
}
|
}
|
List<Database.SaveResult> srList = Database.update(oldAgencyContactList, false);
|
AgencyContactHandler.shareAgency_Contact_ToRole(oldAgencyContactList);
|
failedCount += setSaveError(srList, Agency_Contact__c.getSObjectType(), oldAgencyContactList);
|
totalCount += oldAgencyContactList.size();
|
|
// 4. Agency_Opportunity
|
List<Agency_Opportunity__c> oldAgencyOpportunityList = [SELECT Id, Name
|
, Old_OwnerId__c, Old_Agency__c, Old_Agency_Hospital__c, Old_Agency_Hospital_All__c, Old_Agency_Hospital_Target__c, Old_TargetInputKey__c
|
, OwnerId, Agency__c, Agency_ID__c, Agency_Hospital__c, Agency_Hospital_All__c, Agency_Hospital_Target__c, TargetInputKey__c
|
FROM Agency_Opportunity__c
|
WHERE Agency_Hospital_All__c IN :oldAgencyHospitalList];
|
for (Agency_Opportunity__c ups : oldAgencyOpportunityList) {
|
if (false == newIdOldUserIdMap.containsKey(ups.OwnerId)) {
|
if (true == ocsmUserMap.containsKey(ups.OwnerId)) {
|
//ocsm内部ユーザー:更新しない
|
} else {
|
ups.Old_OwnerId__c = ups.OwnerId;
|
ups.OwnerId = oldIdNewUserIdMap.get(ups.OwnerId);
|
}
|
}
|
if (ups.Agency__c != this.newAgencyId) {
|
ups.Old_Agency__c = ups.Agency__c;
|
ups.Agency__c = this.newAgencyId;
|
ups.Agency_ID__c = this.newAgencyId.mid(0, 15);
|
}
|
if (String.isNotBlank(ups.Agency_Hospital__c)
|
&& ups.Agency_Hospital__c != oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital__c).Id) {
|
ups.Old_Agency_Hospital__c = ups.Agency_Hospital__c;
|
ups.Agency_Hospital__c = oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital__c).Id;
|
}
|
if (String.isNotBlank(ups.Agency_Hospital_All__c)
|
&& ups.Agency_Hospital_All__c != oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital_All__c).Id) {
|
ups.Old_Agency_Hospital_All__c = ups.Agency_Hospital_All__c;
|
ups.Agency_Hospital_All__c = oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital_All__c).Id;
|
}
|
if (String.isNotBlank(ups.Agency_Hospital_Target__c)
|
&& ups.Agency_Hospital_Target__c != oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital_Target__c).Id) {
|
ups.Old_Agency_Hospital_Target__c = ups.Agency_Hospital_Target__c;
|
ups.Agency_Hospital_Target__c = oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital_Target__c).Id;
|
ups.Old_TargetInputKey__c = ups.TargetInputKey__c;
|
ups.TargetInputKey__c = ups.Agency_Hospital_Target__c + ups.TargetInputKey__c.mid(18, 1300);
|
}
|
}
|
srList = Database.update(oldAgencyOpportunityList, false);
|
AgencyOpportunityHandler.shareAgency_Opportunity_ToRole(oldAgencyOpportunityList);
|
failedCount += setSaveError(srList, Agency_Opportunity__c.getSObjectType(), oldAgencyOpportunityList);
|
totalCount += oldAgencyOpportunityList.size();
|
|
// 8. Agency_Report
|
List<Agency_Report__c> oldAgencyReportList = [SELECT Id, Name
|
, Old_Agency__c, Old_Agency_Hospital__c, Old_Person_In_Charge2__c
|
, Agency__c, Agency_ID__c, Agency_Hospital__c, Person_In_Charge2__c
|
FROM Agency_Report__c
|
WHERE Agency__r.Management_Code__c = :this.oldAgencyCode
|
AND Agency_Hospital__c IN :oldAgencyHospitalList];
|
for (Agency_Report__c ups : oldAgencyReportList) {
|
if (ups.Agency__c != this.newAgencyId) {
|
ups.Old_Agency__c = ups.Agency__c;
|
ups.Agency__c = this.newAgencyId;
|
ups.Agency_ID__c = this.newAgencyId.mid(0, 15);
|
}
|
if (String.isNotBlank(ups.Agency_Hospital__c)
|
&& ups.Agency_Hospital__c != oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital__c).Id) {
|
ups.Old_Agency_Hospital__c = ups.Agency_Hospital__c;
|
ups.Agency_Hospital__c = oldIdNewAgencyHospitalMap.get(ups.Agency_Hospital__c).Id;
|
}
|
if (ups.Person_In_Charge2__c != this.oldIdNewContactMap.get(ups.Person_In_Charge2__c).Id) {
|
ups.Old_Person_In_Charge2__c = ups.Person_In_Charge2__c;
|
ups.Person_In_Charge2__c = this.oldIdNewContactMap.get(ups.Person_In_Charge2__c).Id;
|
}
|
}
|
srList = Database.update(oldAgencyReportList, false);
|
failedCount += setSaveError(srList, Agency_Report__c.getSObjectType(), oldAgencyReportList);
|
totalCount += oldAgencyReportList.size();
|
}
|
|
global void finish(Database.BatchableContext BC) {
|
MergeAgencyActivityBatch.messagesForTest = this.emailMessages;
|
// 发 mail
|
BatchEmailUtil eb = new BatchEmailUtil();
|
String title = '经销商用户更名 ' + this.oldAgencyCode + ' -> ' + this.newAgencyCode;
|
String ccStr = null;
|
if(this.emailMessages.size() == 0){
|
eb.successMail(title, totalCount);
|
}else{
|
eb.failedMail(title, String.join(this.emailMessages, '\n'),
|
totalCount, totalCount - failedCount, failedCount);
|
}
|
eb.send();
|
}
|
|
@TestVisible
|
private Integer setUpstError(List<Database.UpsertResult> srList, Schema.sObjectType obj
|
, List<SObject> upsList) {
|
Integer errorCnt = 0;
|
List<String> errMsgList = new List<String>();
|
String objectName = obj.getDescribe().getName();
|
String objectLabel = obj.getDescribe().getLabel();
|
for (Integer i = 0; i < srList.size(); i++) {
|
SObject eObj = upsList[i];
|
Database.UpsertResult sr = srList[i];
|
if (!sr.isSuccess()) {
|
errorCnt++;
|
for (Database.Error err : sr.getErrors()) {
|
String message = objectLabel + ':'
|
+ objectName + '=' + eObj.get('Name')
|
+ ', ' + err.getStatusCode() + ':' + err.getMessage()
|
+ ((err.getFields() != null && err.getFields().size() > 0) ? ', Field:' + String.valueOf(err.getFields()) : '');
|
this.emailMessages.add(message);
|
}
|
}
|
}
|
return errorCnt;
|
}
|
|
@TestVisible
|
private Integer setSaveError(List<Database.SaveResult> srList, Schema.sObjectType obj
|
, List<SObject> upsList) {
|
Integer errorCnt = 0;
|
String objectName = obj.getDescribe().getName();
|
String objectLabel = obj.getDescribe().getLabel();
|
for (Integer i = 0; i < srList.size(); i++) {
|
SObject eObj = upsList[i];
|
Database.SaveResult sr = srList[i];
|
if (!sr.isSuccess()) {
|
errorCnt++;
|
for (Database.Error err : sr.getErrors()) {
|
String message = objectLabel + ':'
|
+ objectName + '=' + eObj.get('Name')
|
+ ', ' + err.getStatusCode() + ':' + err.getMessage()
|
+ ((err.getFields() != null && err.getFields().size() > 0) ? ', Field:' + String.valueOf(err.getFields()) : '');
|
this.emailMessages.add(message);
|
}
|
}
|
}
|
return errorCnt;
|
}
|
|
private static Map<Id, Id> accIdGrpIdMap;
|
public static Id accIdGrpIdMap(Id accId) {
|
if (MergeAgencyActivityBatch.accIdGrpIdMap == null) { MergeAgencyActivityBatch.accIdGrpIdMap = new Map<Id, Id>(); }
|
if (MergeAgencyActivityBatch.accIdGrpIdMap.get(accId) == null) {
|
List<UserRole> roles = [SELECT Id, PortalAccountId
|
FROM UserRole
|
WHERE PortalAccountId = :accId
|
AND PortalRole = 'Worker'];
|
Map<Id, Id> roleIdAccId = new Map<Id, Id>();
|
for (UserRole ur : roles) {
|
roleIdAccId.put(ur.Id, ur.PortalAccountId);
|
}
|
List<Group> groups = [SELECT Id, RelatedId
|
FROM Group
|
WHERE RelatedId = :roleIdAccId.keySet()
|
AND Type = 'RoleAndSubordinates'];
|
for (Group grp : groups) {
|
MergeAgencyActivityBatch.accIdGrpIdMap.put(roleIdAccId.get(grp.RelatedId), grp.Id);
|
}
|
}
|
return MergeAgencyActivityBatch.accIdGrpIdMap.get(accId);
|
}
|
}
|