本文已参与「新人创作礼」活动,一起开启掘金创作之路。
【前言】:我们知道做集成时,由于不能预知什么时候会出现意料之外的异常,在异常出现时如果没有对用户或者某个类设置Debug Log,很难重现问题并排错。因为不能永久性的检测同步时系统debug的数据。所以,新建一个集成日志对象来管理集成信息就显得尤为重要。
在介绍自定义集成日志前,不妨先看下sf处理Test Class异常的日志页面:
【搭建步骤】:
-
创建Integration Log数据模型:
-
调整相关布局:
-
360view 3.1 主记录视图
3.2 最近查看视图
3.3 列表视图 - 根据apex class做filter
【集成Sample】: 实例1:ACC_QuoteSyncApprovalResult
/**
* @author SetsuNa.Wang
*/
@RestResource(urlMapping = '/ACC_QuoteSyncApprovalResult/*')
global class ACC_QuoteSyncApprovalResult {
// request parameters
global class ParameterData {
public String QuoteNumber;
public String RISQuoteApproveNumber;
public String ApproveResult;
public String ApproveRemarks;
}
global class ParameterDataList {
public List<ParameterData> paraList;
}
// response result
global class SyncReturnResult {
public String QUOTENUMBER;
public String FAILREASON;
public String ISSUCCESS;// String True/False
}
@HttpPost
global static List<SyncReturnResult> doPost() {
List<SyncReturnResult> rt = new List<SyncReturnResult>();
Integration_Log__c log = new Integration_Log__c();
log.Integration_Log__c = '';
log.Integration_Apex__c = 'ACC_QuoteSyncApprovalResult';
log.Start_Time__c = datetime.now().format('yyyy-MM-dd HH:mm:ss');
try{
RestRequest req = RestContext.request;
//Convert the requestBody into a string
String bodyStr = req.requestBody.toString();
System.debug('bodyStr: ' + bodyStr);
log.Integration_Log__c = 'Request Body: ' + bodyStr;
ParameterDataList parameter = new ParameterDataList();
//Deserialize the received Json data to the Apex object
parameter = (ParameterDataList)JSON.deserialize(bodyStr, ParameterDataList.class);
System.debug('parameter: ' + parameter + ' - parameter.paraList: ' + parameter.paraList);
if(!parameter.paraList.isEmpty()) {
List<String> quoteIdList = new List<String>();
// Get quote id's list from params.
for(ParameterData para : parameter.paraList) {
System.debug('start loop...');
quoteIdList.add(para.QuoteNumber);
}
// Query the quote list by id list from params.
List<Quote> queryList = new List<Quote>();
Map<String, Quote> updateMap = new Map<String, Quote>();
List<String> invalidData = new List<String>();
queryList = [SELECT Id, ACC_Judgement_ID__c, ACC_Quote_Number_Ext__c, Status FROM Quote WHERE ACC_Quote_Number_Ext__c IN: quoteIdList];
//queryList = [SELECT Id, ACC_Judgement_ID__c, Status FROM Quote];
system.debug('queryList:' + queryList);
// Create map of update quote
if (queryList.size() > 0) {
for (Quote quote : queryList) {
updateMap.put(quote.ACC_Quote_Number_Ext__c, quote);
}
// If query result is empty, return fail reason and insert log.
} else {
SyncReturnResult syncResult = new SyncReturnResult();
syncResult.IsSuccess = 'False';
syncResult.FailReason = Label.ACC_Interface_No_Valid_Data_Error_Msg;
rt.add(syncResult);
log.IsSuccess__c = false;
log.Excepition__c = Label.ACC_Interface_No_Valid_Data_Error_Msg;
log.End_Time__c = datetime.now().format('yyyy-MM-dd HH:mm:ss');
system.debug('log:' + log);
insert log;
RestResponse resp = RestContext.response;
String respJson = json.serialize(rt);
system.debug('json string ------------>' + respJson);
String respBody = EncodingUtil.urlDecode(respJson, 'utf-8');
resp.responseBody = Blob.valueof(respBody);
return rt;
}
Map<String, Quote> updateQuoteMap = new Map<String, Quote>();
// Loop the parameters, divide update quote and invalid quote.
for(ParameterData para : parameter.paraList) {
SyncReturnResult syncResult = new SyncReturnResult();
// Add exist quote into update list.
if (updateMap.get(para.QuoteNumber) != null) {
Quote quote = updateMap.get(para.QuoteNumber);
if (String.isBlank(para.ApproveRemarks) && !'Approved'.equals(para.ApproveResult)) {
syncResult.IsSuccess = 'false';
syncResult.FailReason = 'Approval remarks cannot be empty.';
} else {
quote.ACC_Judgement_ID__c = para.RISQuoteApproveNumber;
quote.Status = 'Approved'.equals(para.ApproveResult) ? Label.ACC_Quote_Status_Approved_In_OA : 'Rejected';
quote.ACC_Approval_Remarks__c = para.ApproveRemarks; // TODO waiting for BA confirm.OA
quote.ACC_Need_Send_Rejection_Email__c = true; //trigger workflow to send email notification
updateQuoteMap.put(quote.Id, quote);
syncResult.IsSuccess = 'True';
}
// add invalid quote into invalidData list.
} else {
invalidData.add(para.QuoteNumber);
syncResult.IsSuccess = 'False';
syncResult.FailReason = 'QuoteNumber is not exist.';
}
syncResult.QuoteNumber = para.QuoteNumber;
// response body.
rt.add(syncResult);
}
List<Quote> updateList = updateQuoteMap.values();
if (updateList.size() > 0) {
update updateList;
log.Integration_Log__c += 'Successed:' + updateList;
}
log.Integration_Log__c += 'Failed:' + invalidData;
log.IsSuccess__c = true;
}else {
log.IsSuccess__c = false;
log.Integration_Log__c += 'The parameter cannot be null.';
}
}catch(Exception e) {
system.debug(e.getMessage());
log.IsSuccess__c = false;
log.Excepition__c = e.getMessage();
}
log.End_Time__c = datetime.now().format('yyyy-MM-dd HH:mm:ss');
system.debug('log:' + log);
insert log;
RestResponse resp = RestContext.response;
String respJson = json.serialize(rt);
system.debug('json string ------------>' + respJson);
String respBody = EncodingUtil.urlDecode(respJson, 'utf-8');
resp.responseBody = Blob.valueof(respBody);
return rt;
}
}
Test Class:
@isTest
private class ACC_QuoteSyncApprovalResultTest {
@testSetUp static void setup() {
//insert custom setting
Running_number__c objseq = new Running_number__c(name = 'number chk', seq__c = 1);
insert objseq;
Account a = new Account();
a.Name = 'testAccount';
insert a;
Opportunity opp = new Opportunity();
opp.Name = 'opp1';
opp.StageName = 'Design';
opp.CloseDate = System.Today();
insert opp;
Quote q = new Quote();
q.Name = 'syncQuoteResult';
q.RecordTypeId = ACC_Utility.getRecordTypeMapBySobj('Quote').get('ACC_PAPAGZ');
q.Quote_To_Account__c = a.Id;
q.OpportunityId = opp.Id;
insert q;
Quote quote = new Quote(
Name = 'TestQuote-Click01',
RecordTypeId = ACC_Utility.getRecordTypeMapBySobj('Quote').get('ACC_PAPAGZ'),
OpportunityId = opp.Id,
Status = 'Approved in OA'
//IsSyncing = false
);
// insert quote;
}
static testMethod void testParameterNull() {
ACC_QuoteSyncApprovalResult.ParameterDataList jsonData = new ACC_QuoteSyncApprovalResult.ParameterDataList();
jsonData.paraList = new List<ACC_QuoteSyncApprovalResult.ParameterData>();
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
String reqJson = json.serialize(jsonData);
System.debug('reqJson = ' + reqJson);
req.requestBody = Blob.valueof(reqJson);
req.requestURI = 'https://cac-pa--partial.cs97.my.salesforce.com/services/apexrest/ACC_QuoteSyncApprovalResult/';
req.httpMethod = 'POST';
RestContext.request = req;
RestContext.response = res;
ACC_QuoteSyncApprovalResult.doPost();
}
static testMethod void testQueryResultEmpty() {
ACC_QuoteSyncApprovalResult.ParameterDataList jsonData = new ACC_QuoteSyncApprovalResult.ParameterDataList();
jsonData.paraList = new List<ACC_QuoteSyncApprovalResult.ParameterData>();
Test.startTest();
ACC_QuoteSyncApprovalResult.ParameterData item = new ACC_QuoteSyncApprovalResult.ParameterData();
jsonData.paraList.add(item);
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
String reqJson = json.serialize(jsonData);
System.debug('reqJson = ' + reqJson);
req.requestBody = Blob.valueof(reqJson);
req.requestURI = 'https://cac-pa--partial.cs97.my.salesforce.com/services/apexrest/ACC_QuoteSyncApprovalResult/';
req.httpMethod = 'POST';
RestContext.request = req;
RestContext.response = res;
ACC_QuoteSyncApprovalResult.doPost();
Test.stopTest();
}
static testMethod void testRejectedRemarksEmpty() {
ACC_QuoteSyncApprovalResult.ParameterDataList jsonData = new ACC_QuoteSyncApprovalResult.ParameterDataList();
jsonData.paraList = new List<ACC_QuoteSyncApprovalResult.ParameterData>();
Quote q = [select Id, ACC_Quote_Number_Ext__c from Quote where Name = 'syncQuoteResult' limit 1];
Test.startTest();
ACC_QuoteSyncApprovalResult.ParameterData item = new ACC_QuoteSyncApprovalResult.ParameterData();
item.QuoteNumber = q.ACC_Quote_Number_Ext__c;
item.RISQuoteApproveNumber = '123456';
item.ApproveResult = 'Rejected';
jsonData.paraList.add(item);
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
String reqJson = json.serialize(jsonData);
System.debug('reqJson = ' + reqJson);
req.requestBody = Blob.valueof(reqJson);
req.requestURI = 'https://cac-pa--partial.cs97.my.salesforce.com/services/apexrest/ACC_QuoteSyncApprovalResult/';
req.httpMethod = 'POST';
RestContext.request = req;
RestContext.response = res;
ACC_QuoteSyncApprovalResult.doPost();
Test.stopTest();
}
static testMethod void testQuoteSuccess() {
ACC_QuoteSyncApprovalResult.ParameterDataList jsonData = new ACC_QuoteSyncApprovalResult.ParameterDataList();
jsonData.paraList = new List<ACC_QuoteSyncApprovalResult.ParameterData>();
Quote q = [select Id, ACC_Quote_Number_Ext__c from Quote where Name = 'syncQuoteResult' limit 1];
Test.startTest();
ACC_QuoteSyncApprovalResult.ParameterData item = new ACC_QuoteSyncApprovalResult.ParameterData();
item.QuoteNumber = q.ACC_Quote_Number_Ext__c;
item.RISQuoteApproveNumber = '123456';
item.ApproveResult = 'Approved';
item.ApproveRemarks = 'ok';
jsonData.paraList.add(item);
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
String reqJson = json.serialize(jsonData);
System.debug('reqJson = ' + reqJson);
req.requestBody = Blob.valueof(reqJson);
req.requestURI = 'https://cac-pa--partial.cs97.my.salesforce.com/services/apexrest/ACC_QuoteSyncApprovalResult/';
req.httpMethod = 'POST';
RestContext.request = req;
RestContext.response = res;
ACC_QuoteSyncApprovalResult.doPost();
Test.stopTest();
}
}
实例2:ACC_QuoteSyncToRIS
@RestResource(urlMapping = '/ACC_QuoteSyncToRIS/*')
global class ACC_QuoteSyncToRIS{
/* Input Quote Information */
public class QuoteInfo {
public String OPPORTUNITYNUMBER;
public String OPPORTUNITYNAME;
public String OPPORTUNITYSTAGE;
public String QUOTENUMBER;
public String DEALERCODE;
public String DEALERNAME;
public String OWNERNAME;
public String ESTIMATEDDELIVERYDATE;
public String SALESREPRESENTATIVE;
public String SALESREPRESENTATIVENO;
// ----- Add by SIT R2 2018.01.25 Start -----
public String SALESORG;
public String SALESCHANNEL;
// ----- Add by SIT R2 2018.01.25 End -------
public String COSTCENTERCODE;
public String QUOTEABOUT;
public String ATTCHMENTURL;
public String REBATE;
public String TOTALLISTPRICE;
public String TOTALSALESPRICE;
public String TOTALLISTPRICEDISCOUNTRATE;
public String TOTALINDICATIVEPRICEDISCOUNTRATE;
public String TOTALBPPRICEPROFIT;
public String TOTALCOSTPRICEPROFIT;
public String TOTALBPPRICEPROFITABILITY;
public String TOTALCOSTPRICEPROFITABILITY;
public List<ProductItem> PRODUCTITEMS;
}
/* QuoteLineItem Information */
public class ProductItem {
public String ITEMNUMBER;
public String PRODUCT;
public String PRODUCTGROUP;
public String PRODUCTSUBGROUP1;
public String PRODUCTSUBGROUP2;
public String QUANTITY;
public String LISTPRICE;
public String INDICATIVEPRICE;
public String SALESPRICE;
public String LISTPRICEDISCOUNTRATE;
public String INDICATIVEPRICEDISCOUNTRATE;
public String INDICATIVEPRICEDISCOUNTAMOUNT;
public String TOTALINDICATIVEPRICEDISCOUNTAMOUNT;
public String BPPRICEPROFIT;
public String COSTPRICEPROFIT;
public String BPPRICEPROFITABILITY;
public String COSTPRICEPROFITABILITY;
}
public class ResponseData {
public String RS;
public String ERRMSG;
public ResDetail DATA;
public String errorCode;
public String msg;
public String result;
public String success;
}
public class ResDetail {
public String FailReason;
public String IsSuccess;
public String RISQuoteApproveID;
}
@HttpPost
Webservice static String doPost(String quoteId, String description){
// new Integration Log
Integration_Log__c integrationLog = new Integration_Log__c();
integrationLog.Integration_Apex__c = 'ACC_QuoteSyncToRIS';
integrationLog.Start_Time__c = DateTime.now().format('yyyy-MM-dd HH:mm:ss');
integrationLog.Integration_Log__c = '';
integrationLog.Excepition__c = '';
system.debug('Sync start...time: ' + integrationLog.Start_Time__c);
QuoteInfo quoteInfo = new QuoteInfo();
try {
// Query quote data from salesforce.
Quote quote = [SELECT Id,
Opportunity.Id,
Opportunity.Name,
Opportunity.ACC_Opportunity_Number_Ext__c,
ACC_Opportunity_Stage__c,
QuoteNumber,
ACC_Quote_Number_Ext__c,
Opportunity.ACC_Partner_Id__c,
Opportunity.ACC_Partner__r.SAP_ID__c,
Opportunity.ACC_Partner__r.Name,
Opportunity.ACC_Partner__r.ACC_Sales_Org__r.ACC_Org_Number__c,
Opportunity.ACC_Partner__r.ACC_Sales_Channel__r.ACC_Channel_Number__c,
Opportunity.ACC_Building_Owner_Name__c,
Opportunity.Estimated_Delivery_Date__c,
Opportunity.ACC_Sales_Representative__c,
Opportunity.ACC_Sales_Representative__r.UserNo__c,
Opportunity.ACC_Sales_Representative_ID__c,
ACC_Cost_Center__c,
ACC_Judgement_Description__c,
(SELECT Id FROM Attachments LIMIT 1),
ACC_Rebate_1000__c,
ACC_Total_List_Price__c,
ACC_Total_Sales_Price__c,
ACC_Total_Discount_Rate_List_Price__c,
ACC_Total_Discount_Rate_Indicative_Price__c,
ACC_Total_BP_Price_Profit_1000__c,
ACC_Total_Cost_Price_Profit_1000__c,
ACC_Profitability_Compared_To_BP_Price__c,
ACC_Profitability_Compared_To_Cost_Price__c,
ACC_Judgement_ID__c,
(SELECT Id,
QuoteId,
LineNumber,
Product2.Name,
Product2.Product_Group__c,
Product2.Product_Subgroup1__c,
Product2.Product_Subgroup2__c,
Quantity,
ListPrice,
ACC_Indicative_Price__c,
UnitPrice,
ACC_Unit_Discount_Rate__c,
ACC_Indicative_Discount_Rate__c,
ACC_Differences_in_Indicative_Price__c,
ACC_Total_Difference_Price__c,
ACC_Profit_CT_BP_Price__c,
ACC_Profit_CT_Cost_Price__c,
ACC_Unit_Profitability_CT_BP_Price__c,
ACC_Unit_Profitability_CT_Cost_Price__c
FROM QuoteLineItems)
FROM Quote
WHERE Status =: Label.ACC_Quote_Status_Approved_In_Salesforce
AND Id =: quoteId];
// Quote and QuoteLineItem is not null.
// Push data into request body objects.
if (quote != null) {
quoteInfo.OPPORTUNITYNUMBER = quote.Opportunity.ACC_Opportunity_Number_Ext__c;
quoteInfo.OPPORTUNITYNAME = quote.Opportunity.Name;
quoteInfo.OPPORTUNITYSTAGE = quote.ACC_Opportunity_Stage__c;
quoteInfo.QUOTENUMBER = quote.ACC_Quote_Number_Ext__c;
quoteInfo.DEALERCODE = quote.Opportunity.ACC_Partner__r.SAP_ID__c;
quoteInfo.DEALERNAME = quote.Opportunity.ACC_Partner__r.Name;
if (String.isNotBlank(quote.Opportunity.ACC_Building_Owner_Name__c)) {
quoteInfo.OWNERNAME = quote.Opportunity.ACC_Building_Owner_Name__c;
} else {
quoteInfo.OWNERNAME = '';
}
quoteInfo.ESTIMATEDDELIVERYDATE = quote.Opportunity.Estimated_Delivery_Date__c == null ? '' : String.valueOf(quote.Opportunity.Estimated_Delivery_Date__c);
quoteInfo.SALESREPRESENTATIVE = quote.Opportunity.ACC_Sales_Representative__c;
quoteInfo.SALESREPRESENTATIVENO = quote.Opportunity.ACC_Sales_Representative__r.UserNo__c;
quoteInfo.SALESORG = quote.Opportunity.ACC_Partner__r.ACC_Sales_Org__r.ACC_Org_Number__c == null ? '':quote.Opportunity.ACC_Partner__r.ACC_Sales_Org__r.ACC_Org_Number__c;
quoteInfo.SALESCHANNEL = quote.Opportunity.ACC_Partner__r.ACC_Sales_Channel__r.ACC_Channel_Number__c == null ? '':quote.Opportunity.ACC_Partner__r.ACC_Sales_Channel__r.ACC_Channel_Number__c;
quoteInfo.COSTCENTERCODE = quote.ACC_Cost_Center__c;
quoteInfo.QUOTEABOUT = description;
if (!quote.Attachments.isEmpty()) {
for (Attachment att : quote.Attachments) {
quoteInfo.ATTCHMENTURL = '&startURL=/content/session?url=' + Label.ACC_Common_File_Domain + att.Id;
}
} else {
quoteInfo.ATTCHMENTURL = '';
}
quoteInfo.REBATE = quote.ACC_Rebate_1000__c == null ? '' : String.valueOf(quote.ACC_Rebate_1000__c);
quoteInfo.TOTALLISTPRICE = quote.ACC_Total_List_Price__c == null ? '' : String.valueOf(quote.ACC_Total_List_Price__c);
quoteInfo.TOTALSALESPRICE = quote.ACC_Total_Sales_Price__c == null ? '' : String.valueOf(quote.ACC_Total_Sales_Price__c);
quoteInfo.TOTALLISTPRICEDISCOUNTRATE = quote.ACC_Total_Discount_Rate_List_Price__c == null ? '' : String.valueOf(quote.ACC_Total_Discount_Rate_List_Price__c.setscale(4));
quoteInfo.TOTALINDICATIVEPRICEDISCOUNTRATE = quote.ACC_Total_Discount_Rate_Indicative_Price__c == null ? '' : String.valueOf(quote.ACC_Total_Discount_Rate_Indicative_Price__c.setscale(4));
quoteInfo.TOTALBPPRICEPROFIT = quote.ACC_Total_BP_Price_Profit_1000__c == null ? '' : String.valueOf(quote.ACC_Total_BP_Price_Profit_1000__c);
quoteInfo.TOTALCOSTPRICEPROFIT = quote.ACC_Total_Cost_Price_Profit_1000__c == null ? '' : String.valueOf(quote.ACC_Total_Cost_Price_Profit_1000__c);
quoteInfo.TOTALBPPRICEPROFITABILITY = quote.ACC_Profitability_Compared_To_BP_Price__c == null ? '' : String.valueOf(quote.ACC_Profitability_Compared_To_BP_Price__c.setscale(4));
quoteInfo.TOTALCOSTPRICEPROFITABILITY = quote.ACC_Profitability_Compared_To_Cost_Price__c == null ? '' : String.valueOf(quote.ACC_Profitability_Compared_To_Cost_Price__c.setscale(4));
quoteInfo.PRODUCTITEMS = new List<ProductItem>();
if (!quote.QuoteLineItems.isEmpty()) {
for (QuoteLineItem item : quote.QuoteLineItems) {
ProductItem productItem = new ProductItem();
productItem.ITEMNUMBER = item.LineNumber;
productItem.PRODUCT = item.Product2.Name;
productItem.PRODUCTGROUP = item.Product2.Product_Group__c;
productItem.PRODUCTSUBGROUP1 = item.Product2.Product_Subgroup1__c;
productItem.PRODUCTSUBGROUP2 = item.Product2.Product_Subgroup2__c;
productItem.QUANTITY = item.Quantity == null ? '' : String.valueOf(item.Quantity);
productItem.LISTPRICE = item.ListPrice == null ? '' : String.valueOf(item.ListPrice);
productItem.INDICATIVEPRICE = item.ACC_Indicative_Price__c == null ? '' : String.valueOf(item.ACC_Indicative_Price__c);
productItem.SALESPRICE = item.UnitPrice == null ? '' : String.valueOf(item.UnitPrice);
productItem.LISTPRICEDISCOUNTRATE = item.ACC_Unit_Discount_Rate__c == null ? '' : String.valueOf(item.ACC_Unit_Discount_Rate__c);
productItem.INDICATIVEPRICEDISCOUNTRATE = item.ACC_Indicative_Discount_Rate__c == null ? '' : String.valueOf(item.ACC_Indicative_Discount_Rate__c);
productItem.INDICATIVEPRICEDISCOUNTAMOUNT = item.ACC_Differences_in_Indicative_Price__c == null ? '' : String.valueOf(item.ACC_Differences_in_Indicative_Price__c);
productItem.TOTALINDICATIVEPRICEDISCOUNTAMOUNT = item.ACC_Total_Difference_Price__c == null ? '' : String.valueOf(item.ACC_Total_Difference_Price__c);
productItem.BPPRICEPROFIT = item.ACC_Profit_CT_BP_Price__c == null ? '' : String.valueOf(item.ACC_Profit_CT_BP_Price__c);
productItem.COSTPRICEPROFIT = item.ACC_Profit_CT_Cost_Price__c == null ? '' : String.valueOf(item.ACC_Profit_CT_Cost_Price__c);
productItem.BPPRICEPROFITABILITY = item.ACC_Unit_Profitability_CT_BP_Price__c == null ? '' : String.valueOf(item.ACC_Unit_Profitability_CT_BP_Price__c);
productItem.COSTPRICEPROFITABILITY = item.ACC_Unit_Profitability_CT_Cost_Price__c == null ? '' : String.valueOf(item.ACC_Unit_Profitability_CT_Cost_Price__c);
quoteInfo.PRODUCTITEMS.add(productItem);
}
}
}
} catch (Exception ex) {
integrationLog.Integration_Log__c += ex.getMessage();
}
HttpRequest req = new HttpRequest();
// API server url.
String apiServer = Label.ACC_Interface_ApiServer;
// API method name.
String cmd = Label.ACC_Interface_CMD;
String access_key = Label.ACC_Interface_Access_Key;
String secret = Label.ACC_Interface_Secret;
String timestamp = String.valueOf(DateTime.now().getTime());
//String REQ_ID = ACC_Utility.generateRandomString(36) + '_SF_' + DateTime.now().format('yyyyMMdd');
//中间件log ID 这个参数的是否有必要,去现场提问
String REQ_ID = 'b77c4886-851a-4ff0-b160-4c9e4494e51b' + '_SF_' + DateTime.now().format('yyyyMMdd');
String REQ_TIME_beforeEncode = DateTime.now().format('yyyy-MM-dd HH:mm:ss');
String REQ_TIME = EncodingUtil.urlEncode(String.valueOf(DateTime.now()), 'UTF-8');
//String sig = 'DDDA902E8A35F3CA7C86FE121ECCF54B';
String SRCSYSTEM = Label.ACC_Interface_SRCSYSTEM;
String DESSYSTEM = Label.ACC_Interface_DESSYSTEM;
String APINAME = Label.ACC_Interface_APINAME;
String APICODE = Label.ACC_Interface_APICODE;
String INJSONSTR_beforeEncode = JSON.serialize(quoteInfo);
String INJSONSTR = ACC_Utility.UrlEncodeObject(quoteInfo);
system.debug(timestamp);
String sig_method = 'HmacMD5';
// Create signature string
String secretString = secret + 'APICODE' + APICODE + 'APINAME' + APINAME + 'DESSYSTEM' + DESSYSTEM +
'INJSONSTR' + INJSONSTR_beforeEncode + 'REQ_ID' + REQ_ID + 'REQ_TIME' + REQ_TIME_beforeEncode + 'SRCSYSTEM' + SRCSYSTEM +
'access_key' + access_key +
'cmd' + cmd + 'formatjson' + 'sig_method' + sig_method + 'timestamp' + timestamp;
system.debug('secretString:' + secretString);
// get signature
Blob sigBlob = crypto.generateMac('hmacMD5', Blob.valueOf(secretString), Blob.valueOf(secret));
system.debug('sign size:' + sigBlob.size());
system.debug('sign common:' + EncodingUtil.convertToHex(sigBlob));
String sig = EncodingUtil.convertToHex(sigBlob).toUpperCase();
system.debug(sig);
system.debug('quoteInfo:' + quoteInfo);
system.debug('INJSONSTR:' + INJSONSTR);
/*
String endpoint = apiServer +
'?REQ_ID=' + REQ_ID +
'&APINAME=' + EncodingUtil.urlEncode(APINAME, 'UTF-8') +
'&REQ_TIME=' + REQ_TIME +
'&INJSONSTR=' + INJSONSTR +
'&format=json' +
'&sig=' + sig +
'&sig_method=' + sig_method +
'&SRCSYSTEM=' + SRCSYSTEM +
'&DESSYSTEM=' + DESSYSTEM +
'&access_key=' + access_key +
'&APICODE=' + APICODE +
'&cmd=' + cmd +
//'&secret=' + secret +
'×tamp=' + timestamp;
req.setEndpoint(endpoint);
*/
String reqBody = 'REQ_ID=' + REQ_ID +
'&APINAME=' + EncodingUtil.urlEncode(APINAME, 'UTF-8') +
'&REQ_TIME=' + REQ_TIME +
'&INJSONSTR=' + INJSONSTR +
'&format=json' +
'&sig=' + sig +
'&sig_method=' + sig_method +
'&SRCSYSTEM=' + SRCSYSTEM +
'&DESSYSTEM=' + DESSYSTEM +
'&access_key=' + access_key +
'&APICODE=' + APICODE +
'&cmd=' + cmd +
//'&secret=' + secret +
'×tamp=' + timestamp;
req.setBody(reqBody);
system.debug('req body: ' + reqBody);
req.setEndpoint(apiServer);
system.debug('endpoint:' + req.getEndpoint());
req.setMethod('POST');
system.debug('request:' + req);
Http http = new Http();
try {
// send request and get response data.
HttpResponse res = http.send(req);
system.debug('STATUS:'+res.getStatus());
system.debug('STATUS_CODE:'+res.getStatusCode());
system.debug('BODY: '+res.getBody());
integrationLog.Integration_Log__c += 'Response:' + res.getBody();
ResponseData resData = (ResponseData)JSON.deserialize(res.getBody(), ACC_QuoteSyncToRIS.ResponseData.class);
if (String.isNotBlank(resData.errorCode)) {
integrationLog.IsSuccess__c = false;
integrationLog.Integration_Log__c += 'ResponseError:' + resData.msg;
integrationLog.Excepition__c += 'Failed';
} else if ('N'.equals(resData.RS)) {
integrationLog.IsSuccess__c = false;
integrationLog.Integration_Log__c += 'ResponseError:' + resData.ERRMSG;
integrationLog.Excepition__c += resData.ERRMSG;
// RS:"Y", Data.IsSuccess:"True", update quote Judgement id with RISQuoteApproveID.
} else if ('Y'.equals(resData.RS)) {
if ('True'.equals(resData.DATA.IsSuccess)) {
Quote updateQuote = new Quote();
updateQuote.Id = quoteId;
updateQuote.ACC_Judgement_ID__c = resData.DATA.RISQuoteApproveID;
update updateQuote;
integrationLog.IsSuccess__c = true;
integrationLog.Integration_Log__c += 'updateQuote:' + updateQuote.Id + ';' + 'JudgementId:' + updateQuote.ACC_Judgement_ID__c;
} else {
integrationLog.IsSuccess__c = false;
integrationLog.Integration_Log__c += 'ResponseError:' + resData.DATA.FailReason;
integrationLog.Excepition__c += resData.DATA.FailReason;
}
}
integrationLog.End_Time__c = DateTime.now().format('yyyy-MM-dd HH:mm:ss');
system.debug('Sync end...time: ' + integrationLog.End_Time__c);
upsert(integrationLog);
if (String.isBlank(integrationLog.Excepition__c)) {
return 'success';
} else {
return 'failed';
}
} catch (Exception ex) {
system.debug('ERROR: '+ ex.getMessage());
integrationLog.Excepition__c += ex.getMessage();
}
integrationLog.End_Time__c = DateTime.now().format('yyyy-MM-dd HH:mm:ss');
system.debug('Sync end...time: ' + integrationLog.End_Time__c);
upsert(integrationLog);
return '';
}
}
Test Class:
@isTest
public class ACC_QuoteSyncToRISTest {
@isTest static void myUnitTest(){
//insert custom setting
Running_number__c objseq = new Running_number__c(name = 'number chk', seq__c = 1);
insert objseq;
Id pricebookId = Test.getStandardPricebookId();
// Pricebook2 - custom
Pricebook2 pb = new Pricebook2(
Name = 'PAPAGZ',
IsActive = true
);
insert pb;
// Product2 - product1
Product2 product1 = new Product2(
IsActive = true,
Name = 'Test_product1',
Product_Group__c = 'PAC'
);
insert product1;
// Product2 - product2
Product2 product2 = new Product2(
IsActive = true,
Name = 'Test_product2',
Product_Group__c = 'PAC'
);
insert product2;
// PricebookEntry standardprice1
PricebookEntry standardprice1 = new PricebookEntry(
Pricebook2Id = pricebookId,
Product2Id = product1.Id,
UnitPrice = 1000,
IsActive = true
);
insert standardprice1;
// PricebookEntry standardprice2
PricebookEntry standardprice2 = new PricebookEntry(
Pricebook2Id = pricebookId,
Product2Id = product2.Id,
UnitPrice = 1000,
IsActive = true
);
insert standardprice2;
// PricebookEntry pbe1
PricebookEntry pbe1 = new PricebookEntry(
Pricebook2Id = pb.Id,
Product2Id = product1.Id,
UnitPrice = 1000,
Cost_Price__c = 900,
ACC_Cost_Price_A__c = 950,
ACC_Cost_Price_B__c = 940,
ACC_Indicative_Price_1__c = 880,
ACC_Indicative_Price_2__c = 870,
ACC_Indicative_Price_3__c = 860,
ACC_Indicative_Price_4__c = 850,
IsActive = true,
UseStandardPrice = false
);
insert pbe1;
// PricebookEntry pbe2
PricebookEntry pbe2 = new PricebookEntry(
Pricebook2Id = pb.Id,
Product2Id = product2.Id,
UnitPrice = 1000,
Cost_Price__c = 900,
ACC_Cost_Price_A__c = 950,
ACC_Cost_Price_B__c = 940,
ACC_Indicative_Price_1__c = 880,
ACC_Indicative_Price_2__c = 870,
ACC_Indicative_Price_3__c = 860,
ACC_Indicative_Price_4__c = 850,
IsActive = true,
UseStandardPrice = false
);
insert pbe2;
Account acc=new Account(
name='acc1',
SAP_ID__c = 'test'
);
insert acc;
List<User> userList = ACC_TestDataUtility.getUserList();
userList[0].UserNo__c = 'test';
update userList[0];
Opportunity opp = new Opportunity(
Name = 'TestOppOnClick-Opportunity01',
RecordTypeId = ACC_Utility.getRecordTypeMapBySobj('Opportunity').get('ACC_PAPAGZ'),
Pricebook2Id = pb.Id,
StageName = 'Identification',
ACC_Partner__C = acc.Id,
ACC_Sales_Representative__c = userList[0].id,
ACC_Planning_Purposes__c = 'Public Building',
// ACC_Rank__c = 'A',
CloseDate = System.Today().addDays(10),
Corporate_Discount__c = 0.15
// LastModifiedDate = ''
);
insert opp;
Opportunity opp1 = new Opportunity(
Name = 'TestOppOnClick-Opportunity01',
RecordTypeId = ACC_Utility.getRecordTypeMapBySobj('Opportunity').get('ACC_PAPAGZ'),
Pricebook2Id = pb.Id,
StageName = 'Identification',
ACC_Partner__C = acc.Id,
ACC_Sales_Representative__c = userList[0].id,
ACC_Planning_Purposes__c = 'Public Building',
ACC_Estimated_Delivery_Start_Month__c = System.Today(),
ACC_Estimated_Delivery_End_Month__c = System.Today(),
ACC_Estimated_Tender_Date__c = System.Today(),
ACC_Authorization_Date__c = System.Today(),
// ACC_Rank__c = 'S',
CloseDate = System.Today().addDays(10)
// LastModifiedDate = ''
);
insert opp1;
OpportunityLineItem opp2LineItem = new OpportunityLineItem(
OpportunityId = opp.Id,
Product2Id = product1.Id,
PricebookEntryId = pbe1.Id,
Quantity = 10,
TotalPrice = 10000,
Category__c = 'Others',
Category_if_others__c = 'Others',
Discount = 60
);
insert opp2LineItem;
Quote quote = new Quote(
Name = 'TestQuote99',
RecordTypeId = ACC_Utility.getRecordTypeMapBySobj('Quote').get('ACC_PAPAGZ'),
Pricebook2Id = pb.Id,
OpportunityId = opp.Id,
Status = 'Approved in Salesforce',
Approver__c = 'Sarwanto Dedi',
Progress_Payment__c = 'pay1\npay2',
Note__c = 'note1_note2',
IsPPNDisplayed__c = true,
seq__c = 7632
);
insert quote;
QuoteLineItem qlt1 = new QuoteLineItem(
QuoteId = quote.Id,
Product2Id = product1.Id,
PricebookEntryId = pbe1.Id,
Quantity = 100,
UnitPrice = 8000,
System_CategoryPGI__c = 'test Category',
FloorPGI__c = 'All'
);
insert qlt1;
/* ACC_QuoteSyncToRIS.ResponseData jsonData = new ACC_QuoteSyncToRIS.ResponseData();
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
String reqJson = json.serialize(jsonData);
req.requestBody = Blob.valueof(reqJson);
req.requestURI = 'https://cac-pa--partial.cs97.my.salesforce.com/services/apexrest/ACC_QuoteSyncToRIS/';
req.httpMethod = 'POST';
RestContext.request = req;
RestContext.response = res;*/
ACC_QuoteSyncToRIS.doPost(quote.id,'test');
}
}