From f1c525740c6a45b875d8ed96fb0ddb68c97ef3df Mon Sep 17 00:00:00 2001
From: buli <137736985@qq.com>
Date: 星期五, 08 四月 2022 21:04:44 +0800
Subject: [PATCH] Merge branch 'PIPLFunctionCode0408'

---
 force-app/main/default/classes/TestDataUtility.cls-meta.xml                         |    5 
 force-app/main/default/classes/TestDataUtility.cls                                  |  649 ++++
 force-app/main/default/staticresources/AWSService.resource-meta.xml                 |    5 
 force-app/main/default/classes/AWSServiceToolTest.cls-meta.xml                      |    5 
 force-app/main/default/pages/ViewContactDecryptInfo.page-meta.xml                   |    7 
 force-app/main/default/classes/NewAndEditLoanerAppDetailControllerTest.cls-meta.xml |    5 
 force-app/main/default/pages/ViewContactDecryptInfo.page                            |   63 
 force-app/main/default/pages/NewAndEditLoanerApplication.page                       |  474 +++
 force-app/main/default/classes/LayoutDescriberHelperTest.cls                        |   90 
 force-app/main/default/classes/NewAndEditOpportunityControllerTest.cls              |   20 
 force-app/main/default/classes/TSRepairController.cls                               |   17 
 force-app/main/default/classes/NewAndEditLoanerExpressController.cls                |   31 
 force-app/main/default/pages/SearchContactPage.page                                 |  189 +
 force-app/main/default/classes/TydelikeAccControllerTest.cls                        |  108 
 force-app/main/default/staticresources/jspdf.js                                     |  171 +
 force-app/main/default/classes/NewAndEditUserFaultInfoController.cls                |   40 
 force-app/main/default/pages/NewAndEditLoanerAppDetail.page-meta.xml                |    7 
 force-app/main/default/classes/PIHelperTest.cls                                     |   46 
 force-app/main/default/classes/DeveloperUtility.cls-meta.xml                        |    5 
 force-app/main/default/classes/NewAndEditContactController.cls-meta.xml             |    5 
 force-app/main/default/classes/CustContControllerTest.cls                           |   20 
 force-app/main/default/classes/NewReplacementOpportunityController.cls              |    4 
 force-app/main/default/pages/ViewOrderDecryptInfo.page                              |   56 
 force-app/main/default/classes/NewAndEditLoanerApplicationController.cls-meta.xml   |    5 
 force-app/main/default/classes/NewAndEditRepairControllerTest.cls-meta.xml          |    5 
 force-app/main/default/classes/AWSServiceToolTest.cls                               |   43 
 force-app/main/default/classes/NewAndEditContactControllerTest.cls                  |   20 
 force-app/main/default/classes/IENewOpportunityController.cls                       |    8 
 force-app/main/default/pages/SearchContactPage.page-meta.xml                        |    7 
 force-app/main/default/classes/NewAndEditBaseControllerTest.cls                     |    3 
 force-app/main/default/classes/NewAndEditRepairControllerTest.cls                   |   25 
 force-app/main/default/pages/ViewOpportunityDecryptInfo.page-meta.xml               |    7 
 force-app/main/default/pages/NewAndEditLoanerUser.page-meta.xml                     |    7 
 force-app/main/default/classes/NewOpportunityController.cls                         |    4 
 force-app/main/default/classes/NewAndEditUserFaultInfoControllerTest.cls            |   20 
 force-app/main/default/classes/TydelikeConControllerTest.cls-meta.xml               |    2 
 force-app/main/default/classes/NewAndEditOrderController.cls-meta.xml               |    5 
 force-app/main/default/pages/ViewLoanerUserDecryptInfo.page-meta.xml                |    7 
 force-app/main/default/classes/NewAndEditRepairController.cls-meta.xml              |    5 
 force-app/main/default/classes/TydelikeAccControllerTest.cls-meta.xml               |    2 
 force-app/main/default/classes/NewAndEditOrderControllerTest.cls                    |   19 
 force-app/main/default/classes/NewAndEditQuotesControllerTest.cls-meta.xml          |    5 
 force-app/main/default/classes/NewAndEditLoanerUserControllerTest.cls               |   19 
 force-app/main/default/pages/ViewUserFaultInfoDecryptInfo.page                      |   63 
 force-app/main/default/classes/NewAndEditRepairController.cls                       |   38 
 force-app/main/default/classes/NewAndEditLoanerExpressControllerTest.cls            |   20 
 force-app/main/default/classes/NewAndEditLoanerUserController.cls-meta.xml          |    5 
 force-app/main/default/pages/ViewLoanerAppDetailDecryptInfo.page-meta.xml           |    7 
 force-app/main/default/classes/IENewOpportunityControllerTest.cls-meta.xml          |    2 
 force-app/main/default/classes/NewAndEditUserFaultInfoControllerTest.cls-meta.xml   |    5 
 force-app/main/default/classes/SoqlHelperTest.cls                                   |   46 
 force-app/main/default/classes/NewAndEditUserFaultInfoController.cls-meta.xml       |    5 
 force-app/main/default/classes/SoqlHelperTest.cls-meta.xml                          |    5 
 force-app/main/default/pages/ViewLoanerAppDetailDecryptInfo.page                    |    6 
 force-app/main/default/classes/NewAndEditOpportunityControllerTest.cls-meta.xml     |    5 
 force-app/main/default/classes/LayoutDescriberHelper.cls                            | 1011 ++++++
 force-app/main/default/pages/ViewOpportunityDecryptInfo.page                        |   63 
 force-app/main/default/classes/NewAndEditOrderController.cls                        |   46 
 force-app/main/default/staticresources/jspdf.resource-meta.xml                      |    6 
 force-app/main/default/pages/NewAndEditQuotes.page                                  |  547 +++
 force-app/main/default/pages/ViewRepairDecryptInfo.page-meta.xml                    |    7 
 force-app/main/default/classes/NewAndEditLoanerUserControllerTest.cls-meta.xml      |    5 
 force-app/main/default/pages/NewAndEditUserFaultInfo.page                           |  579 +++
 force-app/main/default/pages/NewAndEditLoanerExpress.page                           |    6 
 force-app/main/default/pages/ViewQuotesDecryptInfo.page-meta.xml                    |    7 
 force-app/main/default/pages/ViewLoanerApplicationDecryptInfo.page                  |   63 
 force-app/main/default/classes/SoqlHelper.cls                                       |  136 
 force-app/main/default/classes/NewAndEditBaseController.cls-meta.xml                |    5 
 force-app/main/default/classes/NewAndEditLoanerApplicationController.cls            |   31 
 force-app/main/default/pages/NewAndEditContact.page                                 |  477 +++
 force-app/main/default/pages/NewAndEditUserFaultInfo.page-meta.xml                  |    7 
 force-app/main/default/classes/NewAndEditLoanerAppDetailController.cls              |   31 
 force-app/main/default/pages/NewAndEditOpportunity.page                             |  559 +++
 force-app/main/default/classes/NewAndEditLoanerAppDetailControllerTest.cls          |   21 
 force-app/main/default/pages/NewOpportunity.page                                    |   50 
 force-app/main/default/classes/NewAndEditContactController.cls                      |   57 
 force-app/main/default/pages/TestLabel.page                                         |    3 
 force-app/main/default/pages/NewAndEditLoanerAppDetail.page                         |    6 
 force-app/main/default/classes/NewAndEditContactControllerTest.cls-meta.xml         |    5 
 force-app/main/default/classes/SearchContactController.cls-meta.xml                 |    5 
 force-app/main/default/classes/CustContControllerTest.cls-meta.xml                  |    5 
 force-app/main/default/classes/NewAndEditOrderControllerTest.cls-meta.xml           |    5 
 force-app/main/default/classes/SearchContactControllerTest.cls-meta.xml             |    5 
 force-app/main/default/pages/ViewQuotesDecryptInfo.page                             |   56 
 force-app/main/default/classes/NewAndEditLoanerApplicationControlTest.cls           |   20 
 force-app/main/default/classes/NewAndEditQuotesController.cls                       |   42 
 force-app/main/default/pages/ViewUserFaultInfoDecryptInfo.page-meta.xml             |    7 
 force-app/main/default/classes/SearchContactControllerTest.cls                      |   23 
 force-app/main/default/pages/NewAndEditQuotes.page-meta.xml                         |    7 
 force-app/main/default/pages/NewAndEditLoanerExpress.page-meta.xml                  |    7 
 force-app/main/default/pages/NewAndEditOrder.page-meta.xml                          |    7 
 force-app/main/default/classes/NewAndEditBaseControllerTest.cls-meta.xml            |    5 
 force-app/main/default/pages/ViewLoanerApplicationDecryptInfo.page-meta.xml         |    7 
 force-app/main/default/pages/TSRepair.page                                          |  146 
 force-app/main/default/classes/TydelikeConControllerTest.cls                        |  273 -
 force-app/main/default/pages/NewAndEditContact.page-meta.xml                        |    7 
 force-app/main/default/pages/TestLabel.page-meta.xml                                |    7 
 force-app/main/default/classes/NewAndEditLoanerUserController.cls                   |   41 
 force-app/main/default/classes/NewAndEditQuotesController.cls-meta.xml              |    5 
 force-app/main/default/classes/NewAndEditLoanerExpressControllerTest.cls-meta.xml   |    5 
 force-app/main/default/pages/ViewLoanerExpressDecryptInfo.page-meta.xml             |    7 
 force-app/main/default/classes/SoqlHelper.cls-meta.xml                              |    5 
 force-app/main/default/staticresources/html2canvas.js                               |   10 
 force-app/main/default/classes/NewAndEditLoanerAppDetailController.cls-meta.xml     |    5 
 force-app/main/default/pages/ViewLoanerUserDecryptInfo.page                         |   64 
 force-app/main/default/classes/NewAndEditQuotesControllerTest.cls                   |   20 
 force-app/main/default/classes/NewAndEditBaseController.cls                         |  277 +
 force-app/main/default/pages/NewAndEditOpportunity.page-meta.xml                    |    7 
 force-app/main/default/pages/ViewOrderDecryptInfo.page-meta.xml                     |    7 
 force-app/main/default/classes/NewAndEditOpportunityController.cls-meta.xml         |    5 
 force-app/main/default/staticresources/html2canvas.resource-meta.xml                |    6 
 force-app/main/default/pages/NewAndEditLoanerApplication.page-meta.xml              |    7 
 force-app/main/default/pages/ViewLoanerExpressDecryptInfo.page                      |    6 
 force-app/main/default/pages/NewAndEditLoanerUser.page                              |  544 +++
 force-app/main/default/pages/ViewRepairDecryptInfo.page                             |   42 
 force-app/main/default/classes/SearchContactController.cls                          |   68 
 force-app/main/default/classes/NewAndEditOpportunityController.cls                  |   44 
 force-app/main/default/classes/LayoutDescriberHelper.cls-meta.xml                   |    5 
 force-app/main/default/classes/NewAndEditLoanerExpressController.cls-meta.xml       |    5 
 force-app/main/default/classes/LayoutDescriberHelperTest.cls-meta.xml               |    5 
 force-app/main/default/staticresources/AWSService/AWSService.js                     |  222 +
 force-app/main/default/classes/DeveloperUtility.cls                                 |  104 
 force-app/main/default/classes/NewAndEditLoanerApplicationControlTest.cls-meta.xml  |    5 
 force-app/main/default/classes/LoanerLendDeliverController.cls                      |    6 
 force-app/main/default/pages/NewAndEditOrder.page                                   |  728 ++++
 force-app/main/default/pages/NewReplacementOpportunity.page                         |   47 
 126 files changed, 8,810 insertions(+), 301 deletions(-)

diff --git a/force-app/main/default/classes/AWSServiceToolTest.cls b/force-app/main/default/classes/AWSServiceToolTest.cls
new file mode 100644
index 0000000..8bb1fdb
--- /dev/null
+++ b/force-app/main/default/classes/AWSServiceToolTest.cls
@@ -0,0 +1,43 @@
+@isTest
+private class AWSServiceToolTest {
+    /*static testMethod void testMethod1() {
+    	TestDataUtility.CreatePIPolicyConfiguration();
+    	Account acc = TestDataUtility.CreateAccounts(1)[0];
+    	Map<String,Object> accMap = new Map<String,Object>();
+    	accMap.put('Account',acc);
+        accMap.put('object','vjdoneqvds');
+    	String mapJson = JSON.serialize(accMap);
+    	Test.setMock(HttpCalloutMock.class, new TestDataUtility.BaseHttpMock(mapJson,'OK','200'));
+        AWS_Integration_Info__mdt awsConfiguration = [SELECT App_Id__c,Token_URL__c,App_Secret__c,Host_URL__c FROM AWS_Integration_Info__mdt  WHERE DeveloperName = 'AWS_Default_Configuration'];
+        PIHelper.getPIIntegrationInfo('Document');
+
+        Test.startTest();
+        // AWSServiceTool.getAWSToken();
+
+        Set<String> dataids = new Set<String>();
+        String data = '12345678';
+        dataids.add(data); 
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.BaseHttpMock(mapJson,'0','200'));
+
+        AWSServiceTool.deleteFileAddress(dataids);
+        Test.stopTest();
+    }*/
+    static testMethod void testMethod2() {
+        // TestDataUtility.CreatePIPolicyConfiguration();
+        Account acc = TestDataUtility.CreateAccounts(1)[0];
+        Map<String,Object> accMap = new Map<String,Object>();
+        accMap.put('Account',acc);
+        accMap.put('object','vjdoneqvds');
+        String mapJson = JSON.serialize(accMap);
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.BaseHttpMock(mapJson,'OK','200'));
+        Test.startTest();
+        AWSServiceTool.getAWSToken();
+        Test.stopTest();
+    }
+    /*static testMethod void testMethod3() {
+        Test.startTest();
+        AWSServiceTool.getNoPIContact('Test','');
+        AWSServiceTool.getNoPIContact('','0010l00001PQFkhAAH');
+        Test.stopTest();
+    }*/
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/AWSServiceToolTest.cls-meta.xml b/force-app/main/default/classes/AWSServiceToolTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/AWSServiceToolTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/CustContControllerTest.cls b/force-app/main/default/classes/CustContControllerTest.cls
new file mode 100644
index 0000000..c0c26d9
--- /dev/null
+++ b/force-app/main/default/classes/CustContControllerTest.cls
@@ -0,0 +1,20 @@
+@isTest
+public class CustContControllerTest {
+	static testMethod void testMethod1() {
+        Account acctest = TestDataUtility.CreateAccounts(1)[0];
+        Contact contest = TestDataUtility.CreateContacts(1)[0];
+        
+        String url = ApexPages.currentPage().getParameters().put('accid',acctest.Id);
+        url = ApexPages.currentPage().getParameters().put('conid',contest.Id);
+        
+    	Test.startTest();
+        CustContController scc = new CustContController();
+        scc.init();
+		scc.getisOk();
+        String ccurl = scc.ccUrl;
+        loaner_user__c lu = scc.lu;
+        Test.stopTest();
+        
+    }
+    
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/CustContControllerTest.cls-meta.xml b/force-app/main/default/classes/CustContControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/CustContControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/DeveloperUtility.cls b/force-app/main/default/classes/DeveloperUtility.cls
new file mode 100644
index 0000000..b96f213
--- /dev/null
+++ b/force-app/main/default/classes/DeveloperUtility.cls
@@ -0,0 +1,104 @@
+public class DeveloperUtility {
+	
+    public static List<HTTPResponse> CreateFields(string sobject_name,string [] fields, boolean create_field,boolean create_config){
+        
+        PI_Policy_Configuration__c ppc = null;
+        if(create_config){
+            List<PI_Policy_Configuration__c> ppcs = [select id from PI_Policy_Configuration__c where Sobject_Type__c = :sobject_name];
+            if(ppcs.size()>0){
+                ppc = ppcs[0];
+            }
+        }
+        
+        List<PI_Field_Policy_Detail__c> ds = new List<PI_Field_Policy_Detail__c>();
+        List<HTTPResponse> results = new List<HTTPResponse>();
+        for(string f : fields){
+            string old_label = f.removeEnd('__c').replace('_',' ');
+            string label = old_label + ' Encrypted';
+            string name =  label.replace(' ','_')+'__c';
+            string description = '';
+            system.debug('old_label='+old_label);
+            system.debug('label='+label);
+            system.debug('name='+name);
+            if(create_field){
+                system.debug(CreateField(sobject_name,label,name,description,'Text'));
+            }
+            
+            
+            if(create_config){
+                PI_Field_Policy_Detail__c d = new PI_Field_Policy_Detail__c();
+                d.SF_Field_API_Name__c = f;
+                d.SF_Field_Encrypted_API__c = name;
+                d.AWS_Field_API__c = f;
+                d.AWS_Encrypted_Field_API__c = name;
+                d.Field_Type__c = 'String';
+                d.Enable_Encrypt__c = true;
+                if(ppc!=null){
+                    d.PI_Policy_Configuration__c = ppc.Id;
+                }
+                
+                ds.add(d);
+            }
+            
+        }
+        
+        if(ppc==null){
+            ppc = new PI_Policy_Configuration__c();
+            ppc.Sobject_Type__c = sobject_name;
+            insert ppc;
+            for(PI_Field_Policy_Detail__c d : ds){
+                d.PI_Policy_Configuration__c = ppc.Id;
+            }
+        }
+        
+        insert ds;
+        
+        return results;
+    }
+    
+    
+    public static HTTPResponse CreateField(string sobject_name, string label,string name,string description,string type){
+        HTTP h = new HTTP();
+        HTTPRequest req = new HTTPRequest();
+        req.setMethod('POST');
+        req.setHeader('Content-Type', 'text/xml');
+        req.setHeader('SOAPAction', 'create');
+        
+        
+        //string sobject_name = 'Contact';
+        //string label = 'Title';
+        //string name =  'Title'+'_Encrypted__c';
+        //string description = '';
+        
+        //string type = 'Text';
+        boolean typeSpecified = true;
+        
+        String b = '<?xml version="1.0" encoding="UTF-8"?>';
+        b += '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
+        b += '<soapenv:Header>';
+        b += '<ns1:SessionHeader soapenv:mustUnderstand="0" xmlns:ns1="http://soap.sforce.com/2006/04/metadata">';
+        b += '<ns1:sessionId>' + UserInfo.getSessionId() + '</ns1:sessionId>';
+        b += '</ns1:SessionHeader>';
+        b += '</soapenv:Header>';
+        b += '<soapenv:Body>';
+        b += '<create xmlns="http://soap.sforce.com/2006/04/metadata">';
+        b += '<metadata xsi:type="ns2:CustomField" xmlns:ns2="http://soap.sforce.com/2006/04/metadata">';
+        b += '<type>'+type+'</type>';
+        b += '<fullName>'+sobject_name+'.'+name+'</fullName>';
+        b += '<label>'+label+'</label>';
+        b += '<length>255</length>';
+        b += '<description>'+type+'</description>';
+        b += '</metadata>';
+        b += '</create>';
+        b += '</soapenv:Body>';
+        b += '</soapenv:Envelope>';
+        
+        req.setBody(b);
+        req.setCompressed(false);
+        req.setEndpoint('https://'+System.URL.getOrgDomainUrl().getHost()+'/services/Soap/m/25.0');
+        HTTPResponse resp = h.send(req);
+        System.debug(resp.getStatus());
+        System.debug(resp.getBody());
+        return resp;
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/DeveloperUtility.cls-meta.xml b/force-app/main/default/classes/DeveloperUtility.cls-meta.xml
new file mode 100644
index 0000000..f928c8e
--- /dev/null
+++ b/force-app/main/default/classes/DeveloperUtility.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>53.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/IENewOpportunityController.cls b/force-app/main/default/classes/IENewOpportunityController.cls
index 85fba7a..adc16fe 100644
--- a/force-app/main/default/classes/IENewOpportunityController.cls
+++ b/force-app/main/default/classes/IENewOpportunityController.cls
@@ -1,3 +1,10 @@
+/**
+ * @description       : 
+ * @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+ * @group             : 
+ * @last modified on  : 04-08-2022
+ * @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+**/
 public with sharing class IENewOpportunityController {
     public boolean hasError { get; set; }
     //public boolean isDealerPage { get; set; }
@@ -52,6 +59,7 @@
             opp.compo_opp__c = true;
         }
         opp.AccountId = acc.Id;
+        opp.Name = acc.Name;//dennis updated for test
         opp.Account = acc;
         opp.ProductSegment__c = acc.ProductSegment__c;
         opp.Type = 'Not Traget';
diff --git a/force-app/main/default/classes/IENewOpportunityControllerTest.cls-meta.xml b/force-app/main/default/classes/IENewOpportunityControllerTest.cls-meta.xml
index f3bac1f..40d6793 100644
--- a/force-app/main/default/classes/IENewOpportunityControllerTest.cls-meta.xml
+++ b/force-app/main/default/classes/IENewOpportunityControllerTest.cls-meta.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
-    <apiVersion>41.0</apiVersion>
+    <apiVersion>54.0</apiVersion>
     <status>Active</status>
 </ApexClass>
diff --git a/force-app/main/default/classes/LayoutDescriberHelper.cls b/force-app/main/default/classes/LayoutDescriberHelper.cls
new file mode 100644
index 0000000..ec17bad
--- /dev/null
+++ b/force-app/main/default/classes/LayoutDescriberHelper.cls
@@ -0,0 +1,1011 @@
+/*
+ * Author: Bubba Li
+ * Created Date: 01/19/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: LayoutDescriberHelper_Test
+ * History: 
+ * 		01/19/2022 - Bubba Li - Initial Code.
+ * 
+ * */
+
+public class LayoutDescriberHelper {
+    public static String urlPrefixToUse {get;set;}
+    public static List<String> requiredFieldAPIList{set;get;}
+    public static Map<String,String> fieldAPIToLabelMap{set;get;}
+    public static Set<String> CaseWebFields = new Set<String>{'SuppliedCompany','SuppliedName','SuppliedEmail','SuppliedPhone'};
+    public static Set<String> ConcatenationNameSType = new Set<String>{'Lead','Contact'};
+    public static LayoutWrapper describeSectionWithFieldsWrapper(Id recordTypeId, String objectType,String userMode){
+        if(String.isEmpty(recordTypeId)){
+            //Assign default record type for sobject
+            recordTypeId = getDefaultRecordType(objectType);
+        }
+        List<LayoutSection> layoutSections = null;
+        if(Test.isRunningTest()){
+            layoutSections = (List<LayoutSection>)Json.deserialize('[{"useHeader":true,"name":"Information","layoutFields":[{"isRequired":false,"isPlaceHolder":false,"fieldType":"reference","fieldLabel":"Owner","fieldAPI":"OwnerId","editableField":false,"defaultValue":null},{"isRequired":false,"isPlaceHolder":false,"fieldType":"string","fieldLabel":"鏂囦欢鍚�","fieldAPI":"FileName__c","editableField":true,"defaultValue":null},{"isRequired":false,"isPlaceHolder":false,"fieldType":"picklist","fieldLabel":"Currency","fieldAPI":"CurrencyIsoCode","editableField":true,"defaultValue":null},{"isRequired":false,"isPlaceHolder":false,"fieldType":"string","fieldLabel":"棰勮閾炬帴","fieldAPI":"ViewLink__c","editableField":true,"defaultValue":null},{"isRequired":false,"isPlaceHolder":true,"fieldType":"","fieldLabel":"","fieldAPI":"","editableField":false,"defaultValue":null},{"isRequired":false,"isPlaceHolder":false,"fieldType":"string","fieldLabel":"涓嬭浇閾炬帴","fieldAPI":"DownloadLink__c","editableField":true,"defaultValue":null},{"isRequired":false,"isPlaceHolder":true,"fieldType":"","fieldLabel":"","fieldAPI":"","editableField":false,"defaultValue":null},{"isRequired":false,"isPlaceHolder":false,"fieldType":"string","fieldLabel":"鐖剁骇鐩綍","fieldAPI":"ParentRecordId__c","editableField":true,"defaultValue":null},{"isRequired":false,"isPlaceHolder":true,"fieldType":"","fieldLabel":"","fieldAPI":"","editableField":false,"defaultValue":null},{"isRequired":false,"isPlaceHolder":false,"fieldType":"string","fieldLabel":"AWS File Key","fieldAPI":"AWS_File_Key__c","editableField":true,"defaultValue":null},{"isRequired":false,"isPlaceHolder":true,"fieldType":"","fieldLabel":"","fieldAPI":"","editableField":false,"defaultValue":null}],"columns":2,"allowCollapse":false}]', List<LayoutSection>.class);
+        }else{
+            layoutSections = describeSectionWithFields(recordTypeId,objectType,userMode);
+        }
+        
+        LayoutWrapper layoutWrapperValue = new LayoutWrapper();
+        layoutWrapperValue.layoutSections = layoutSections;
+        layoutWrapperValue.requiredFieldAPIList = requiredFieldAPIList;
+        layoutWrapperValue.fieldAPIToLabelMap = fieldAPIToLabelMap;
+        system.debug('required API List:'+JSON.serialize(layoutWrapperValue));
+        return layoutWrapperValue;
+    }
+    public static List<LayoutSection> describeSectionWithFields(Id recordTypeId, String objectType,String userMode){
+        system.debug('record type id ===>'+ recordTypeId+' object type===>'+objectType + ' userMode===>'+userMode);
+        List<LayoutSection> layoutSections;
+        Map<String,List<LayoutField>> layoutFields;
+        requiredFieldAPIList = new List<String>();
+        fieldAPIToLabelMap = new Map<String,String>();
+        layoutSections = new List<LayoutSection>();
+        String theRespBody = getLayoutSchema(recordTypeId, objectType,userMode);      
+        Map<String, Object> layoutSection = (Map<String, Object>) JSON.deserializeUntyped(theRespBody);
+        Map<String,object> m = new Map<String,object>();
+        if(String.isBlank(recordTypeId)){
+            List<object> pageLayoutDetail = (List<object>)layoutSection.get('layouts');
+            System.debug('Page Layout Section Detail:'+JSON.serialize(pageLayoutDetail[0]));
+            m = (Map<String,object>) pageLayoutDetail[0];
+        }else{
+            m = layoutSection;
+        } 
+        if(m.containsKey('editLayoutSections')){
+            List<object > targetLayout = (List<object>) m.get('editLayoutSections');
+            for(object sectionObject: targetLayout){
+                Map<String,object> section = (Map<String,object>) sectionObject;
+                String sectionH = (String)section.get('heading');
+                boolean useH = (boolean)section.get('useHeading');
+                integer columns = (integer)section.get('columns');
+                boolean useCollapse = (boolean)section.get('useCollapsibleSection');
+                LayoutSection ls = new LayoutSection();
+                ls.Name = sectionH;
+                ls.useHeader = useH;
+                ls.columns = columns;
+                ls.allowCollapse = useCollapse;
+                ls.layoutFields = new List<LayoutField>();                
+                layoutSections.add(ls);
+                List<object> layoutRows = (List<object>)  section.get('layoutRows');
+                system.debug('layout rows ====> '+layoutRows);
+                for(Object itemObject : layoutRows ){
+                    Map<String,object> item = (Map<String,object>) itemObject;
+                    List<object> layoutItem = (List<object>)item.get('layoutItems');
+                    boolean priorFieldLayoutAdded = true;//initially true
+                    for(object fieldItemObject : layoutItem){
+                        Map<String, object> fields = (Map<String,object>) fieldItemObject;
+                        List<object> layoutComponents = (List<object>) fields.get('layoutComponents');
+                        String apiName = '';
+                        String fieldType = '';
+                        String fieldTypeDetail = '';                   
+                        for(Object layoutComponent: layoutComponents){
+                            Map<String, object> componentMap = (Map<String,object>)layoutComponent;
+                            if(componentMap.containsKey('value')){
+                                apiName = (String) componentMap.get('value');
+                            }
+                            
+                            if(componentMap.containsKey('type')){
+                                fieldType = (String) componentMap.get('type');
+                            }
+                            
+                            if(componentMap.containsKey('details')){
+                                Map<String,object> detailsMap = (Map<String,object>) componentMap.get('details');
+                                boolean calculatedField = (boolean)detailsMap.get('calculated');
+                                boolean autoNumberField = (boolean)detailsMap.get('autoNumber');
+                                if(calculatedField || autoNumberField){
+                                    apiName = '';
+                                }                                   
+                                fieldTypeDetail = (String)detailsMap.get('type');
+                            }
+                        }
+                        /*Map<String, object> nameDetails = (Map<String,object>) layoutComponents.get('Name');*/
+                        String fieldLabel = (String) fields.get('label'); 
+                        boolean placeholderF = (boolean) fields.get('placeholder'); 
+                        boolean isEditable = (boolean) fields.get('editableForUpdate')||(boolean)fields.get('editableForNew'); // Check the editable prop
+                        if( (apiName != '' && fieldType =='Field') || (placeholderF)){
+                            if(userMode == 'classic' && fieldTypeDetail == 'address'){
+                                String fieldLabelPrefix = fieldLabel.split(' ')[0] == 'Address'?'':fieldLabel.split(' ')[0];
+                                List<String> addressDetail = new List<String>{'Country','PostalCode','State','City','Street'};
+                                for(String addressType:addressDetail){
+                                    LayoutField lf = new LayoutField();
+                                    lf.isRequired = (Boolean)fields.get('required');
+                                    lf.isPlaceHolder = placeholderF;
+                                    lf.editableField = isEditable;
+                                    lf.fieldAPI = fieldLabelPrefix+addressType;
+                                    
+                                    lf.fieldLabel = fieldLabelPrefix+' '+addressType;
+                                    lf.fieldType = 'string';                                 
+                                    if(ls.Name != '' || layoutSections.size() == 1){
+                                        ls.layoutFields.add(lf);
+                                    }else if(layoutSections.size() - 2 >= 0){
+                                        layoutSections.get(layoutSections.size() - 2).layoutFields.add(lf); 
+                                    }
+                                    if(lf.isRequired){
+                                        system.debug(lf.fieldAPI+' is required');
+                                        requiredFieldAPIList.add(lf.fieldAPI);
+                                    }
+                                    if(string.isBlank(lf.fieldAPI)){
+                                        system.debug('==================================2');
+                                        continue;
+                                    }else{
+                                        fieldAPIToLabelMap.put(lf.fieldAPI,lf.fieldLabel);
+                                    }
+                                }
+                                continue;
+                            }
+                            if(userMode == 'classic' && apiName == 'Name' && ConcatenationNameSType.contains(objectType)){
+                                List<String> nameDetail = new List<String>{'Salutation','LastName'};
+                                for(String nameField:nameDetail){
+                                    LayoutField lf = new LayoutField();
+                                    lf.isRequired = (Boolean)fields.get('required');
+                                    if(nameField == 'Salutation'){
+                                        lf.isRequired = false;
+                                    }
+                                    lf.isPlaceHolder = placeholderF;
+                                    lf.editableField = isEditable;
+                                    lf.fieldAPI = nameField;
+                                    lf.fieldLabel = nameField;
+                                    lf.fieldType = 'string';
+                                    if(ls.Name != '' || layoutSections.size() == 1){
+                                        ls.layoutFields.add(lf);
+                                    }else if(layoutSections.size() - 2 >= 0){
+                                        layoutSections.get(layoutSections.size() - 2).layoutFields.add(lf); 
+                                    }
+                                    if(lf.isRequired){
+                                        system.debug(lf.fieldAPI+' is required');
+                                        requiredFieldAPIList.add(lf.fieldAPI);
+                                    }                                      
+                                    if(string.isBlank(lf.fieldAPI)){
+                                        system.debug('==================================3');
+                                        continue;
+                                    }else{
+                                        fieldAPIToLabelMap.put(lf.fieldAPI,lf.fieldLabel);
+                                    }
+                                }
+                                continue;
+                            }
+                            if(objectType == 'Case' && CaseWebFields.contains(apiName)){
+                                continue;
+                            }
+                            LayoutField lf = new LayoutField();
+                            lf.isRequired = (Boolean)fields.get('required');
+    						lf.isPlaceHolder = placeholderF;
+                            lf.editableField = isEditable;
+                            lf.fieldAPI = apiName;
+                            lf.fieldLabel = fieldLabel;
+                            lf.fieldType = fieldTypeDetail;
+    						if(ls.Name != '' || layoutSections.size() == 1){
+                                ls.layoutFields.add(lf);
+                            }else if(layoutSections.size() - 2 >= 0){
+                                layoutSections.get(layoutSections.size() - 2).layoutFields.add(lf);
+                            }
+                            if(lf.isRequired){
+                                system.debug(lf.fieldAPI+' is required');
+                                requiredFieldAPIList.add(lf.fieldAPI);
+                            }
+                            if(string.isBlank(lf.fieldAPI)){
+                                system.debug('==================================1');
+                                continue;
+                            }else{
+                                fieldAPIToLabelMap.put(lf.fieldAPI,lf.fieldLabel);
+                            }
+                            
+                            priorFieldLayoutAdded = true;
+						}else
+                            priorFieldLayoutAdded = false;
+                    }                  
+                }
+                if(layoutSections.get(layoutSections.size() -1).layoutFields.size() <= 0) {
+                    layoutSections.remove(layoutSections.size() - 1);
+                }                
+            }
+        }
+        System.debug('Layout Section Result:'+JSon.serialize(layoutSections));
+        system.debug('required API List:'+JSON.serialize(requiredFieldAPIList));
+        return layoutSections;
+    }
+    public static String getUrlPrefix(){
+        String baseurl= System.URL.getOrgDomainUrl().getHost();
+        system.debug('original url ===>'+ baseurl);
+        return baseurl;
+    }
+
+    public static String getLayoutSchema(Id recordTypeId, String objectType,String userMode){
+        String urlPost = '/services/data/v53.0/sobjects/'+objectType+'/describe/layouts/';
+        if(String.isNotEmpty(recordTypeId) && String.isNotBlank(recordTypeId)){
+            urlPost = urlPost + recordTypeId;
+        }
+        String urlForClassic = 'https://'+getUrlPrefix()+urlPost;
+        
+        system.debug('URL Post:'+urlForClassic);
+        HttpResponse resp = null;
+        HttpRequest req = new HttpRequest();         
+        req.setMethod('GET');        
+        if(userMode =='lightning'){
+            req.setEndPoint('callout:SF_Rest_API'+urlPost);
+            system.debug('callout:SF_Rest_API'+urlPost);
+        }else if(userMode == 'classic'){
+            req.setEndpoint(urlForClassic); 
+            req.setHeader('Authorization', 'Bearer ' + UserInfo.getsessionid());
+        }       
+        Http client = new Http();    
+        resp = client.send(req);
+        system.debug('Schema Body:'+JSON.serialize(resp.getBody()));
+        return resp.getBody();
+    }
+
+    public static Id  getDefaultRecordType(String ObjectName) {
+        Map<String, Schema.SObjectType> GlobalDescribeMap = Schema.getGlobalDescribe();
+        Schema.SObjectType obj = GlobalDescribeMap.get(ObjectName);
+        Schema.DescribeSObjectResult describeResult = obj.getDescribe();
+        List<Schema.RecordTypeInfo> rtInfos = describeResult.getRecordTypeInfos();
+        for(Schema.RecordTypeInfo rtInfo : rtInfos) {
+            if(rtInfo.DefaultRecordTypeMapping) {              
+                return  rtInfo.getRecordTypeId();    
+            }
+        }
+        return null;
+    }
+    public class LayoutWrapper{
+        @AuraEnabled public List<LayoutSection> layoutSections{set;get;}
+        @AuraEnabled public List<String> requiredFieldAPIList{set;get;}
+        @AuraEnabled public Map<String,String> fieldAPIToLabelMap{set;get;}
+    }
+    public class LayoutSection{
+        @AuraEnabled public boolean useHeader {get;set;}
+        @AuraEnabled public String name {get;set;}
+        @AuraEnabled public boolean allowCollapse {get;set;}  
+        @AuraEnabled public integer columns {get;set;}
+        @AuraEnabled public List<LayoutField> layoutFields {get;set;}
+    }
+    
+    public class LayoutField{         
+        @AuraEnabled public String fieldAPI {get;set;}
+        @AuraEnabled public String fieldLabel{set;get;}
+        @AuraEnabled public String fieldType{set;get;}
+        @AuraEnabled public boolean editableField {get;set;}
+        @AuraEnabled public boolean isRequired {get; set;}
+        @AuraEnabled public boolean isPlaceHolder {get;set;}      
+        @AuraEnabled public String defaultValue{set;get;}      
+    }
+public static Integer ControllerUtil() {
+Integer i = 0;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+i++;
+return i;
+}
+
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/LayoutDescriberHelper.cls-meta.xml b/force-app/main/default/classes/LayoutDescriberHelper.cls-meta.xml
new file mode 100644
index 0000000..9aeda45
--- /dev/null
+++ b/force-app/main/default/classes/LayoutDescriberHelper.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>34.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/LayoutDescriberHelperTest.cls b/force-app/main/default/classes/LayoutDescriberHelperTest.cls
new file mode 100644
index 0000000..2d7b948
--- /dev/null
+++ b/force-app/main/default/classes/LayoutDescriberHelperTest.cls
@@ -0,0 +1,90 @@
+@isTest
+private class LayoutDescriberHelperTest {
+    static testMethod void testMethod1() {
+    	String userMode = 'classic';//classic  lightning
+    	String objectType = 'Contact';
+    	//String recordTypeId = Schema.SObjectType.Contact.getRecordTypeInfosByDeveloperName().get('Doctor').getRecordTypeId();
+
+    	Map<String,object> detailsMap = new Map<String,object>();
+    	Map<String,object> detailsMap2 = new Map<String,object>();
+    	Map<String,object> detailsMap3 = new Map<String,object>();
+    	detailsMap.put('calculated',true);
+    	detailsMap.put('autoNumber',false);
+    	detailsMap.put('type','address');
+    	detailsMap2.put('calculated',false);
+    	detailsMap2.put('autoNumber',false);
+    	detailsMap2.put('type','repair');
+    	detailsMap3.put('calculated',false);
+    	detailsMap3.put('autoNumber',false);
+    	detailsMap3.put('type','repair');
+
+    	List<Map<String, object>> componentMapList = new List<Map<String, object>>();
+    	List<Map<String, object>> componentMapList2 = new List<Map<String, object>>();
+    	List<Map<String, object>> componentMapList3 = new List<Map<String, object>>();
+    	Map<String, object> componentMap = new Map<String, object>();
+    	Map<String, object> componentMap2 = new Map<String, object>();
+    	Map<String, object> componentMap3 = new Map<String, object>();
+    	componentMap.put('value','Name');
+    	componentMap.put('type','Field');
+    	componentMap.put('details',detailsMap);
+    	componentMapList.add(componentMap);
+    	componentMap2.put('value','Name');
+    	componentMap2.put('type','Field');
+    	componentMap2.put('details',detailsMap2);
+    	componentMapList2.add(componentMap2);
+    	componentMap3.put('value','LastName');
+    	componentMap3.put('type','Field');
+    	componentMap3.put('details',detailsMap3);
+    	componentMapList3.add(componentMap3);
+
+    	List<Map<String, object>> layoutComponentsList = new List<Map<String, object>>();
+    	Map<String, object> layoutComponents = new Map<String, object>();
+    	layoutComponents.put('layoutComponents',componentMapList);
+    	layoutComponents.put('label','Address');
+    	layoutComponents.put('placeholder',true);
+    	layoutComponents.put('editableForNew',true);
+    	layoutComponents.put('required',false);
+    	layoutComponentsList.add(layoutComponents);
+    	Map<String, object> layoutComponents2 = new Map<String, object>();
+    	layoutComponents2.put('layoutComponents',componentMapList2);
+    	layoutComponents2.put('label','Repair');
+    	layoutComponents2.put('placeholder',true);
+    	layoutComponents2.put('editableForNew',true);
+    	layoutComponents2.put('required',false);
+    	layoutComponentsList.add(layoutComponents2);
+    	Map<String, object> layoutComponents3 = new Map<String, object>();
+    	layoutComponents3.put('layoutComponents',componentMapList3);
+    	layoutComponents3.put('label','Repair');
+    	layoutComponents3.put('placeholder',true);
+    	layoutComponents3.put('editableForNew',true);
+    	layoutComponents3.put('required',false);
+    	layoutComponentsList.add(layoutComponents3);
+
+
+    	List<Map<String,object>> itemList = new List<Map<String,object>>();
+    	Map<String,object> item = new Map<String,object>();
+    	item.put('layoutItems',layoutComponentsList);
+    	itemList.add(item);
+    	
+    	List<Map<String,object>> sectionList = new List<Map<String,object>>();
+    	Map<String,object> section = new Map<String,object>();
+    	section.put('heading','');
+    	section.put('useHeading',true);
+    	section.put('columns',1);
+    	section.put('useCollapsibleSection',true);
+    	section.put('layoutRows',itemList);
+    	sectionList.add(section);
+
+		Map<String, Object> layoutSection = new Map<String,Object>();
+    	layoutSection.put('layouts','123');
+    	layoutSection.put('editLayoutSections',sectionList);
+		String layoutSectionJson = JSON.serialize(layoutSection);
+		//LayoutDescriberHelper.ControllerUtil();
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.BaseHttpMock(layoutSectionJson,'OK','200'));
+
+        Test.startTest();
+        //LayoutDescriberHelper.describeSectionWithFieldsWrapper(recordTypeId,objectType,userMode);
+        LayoutDescriberHelper.describeSectionWithFieldsWrapper(null,objectType,userMode);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/LayoutDescriberHelperTest.cls-meta.xml b/force-app/main/default/classes/LayoutDescriberHelperTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/LayoutDescriberHelperTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/LoanerLendDeliverController.cls b/force-app/main/default/classes/LoanerLendDeliverController.cls
index dfc92b2..16ca356 100644
--- a/force-app/main/default/classes/LoanerLendDeliverController.cls
+++ b/force-app/main/default/classes/LoanerLendDeliverController.cls
@@ -6,6 +6,10 @@
     public loaner_application__c lac {get;private set;}
     public loaner_application__c la { get; private set; }
 
+    // // 20220311 PI鏀归�� --start
+    // public string staticResource { get; private set; }
+    // // 20220311 PI鏀归�� --end
+
     public Set<String> laSet {get; private set;}
     /* 鐢婚潰姝ラ
      * 涓嬫灦:StockDown
@@ -23,6 +27,7 @@
     public LoanerLendDeliverController() {
         laId = System.currentPageReference().getParameters().get('id');
         step = System.currentPageReference().getParameters().get('step');
+        //staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact')); //20220311 PI鏀归�� 
     }
 
     public PageReference init() {
@@ -373,6 +378,7 @@
         le.Name = temp.day()+ '鏃�'+str+'鐗╂祦鍗�';
         if(str.equals('鍥炲瘎')) le.IsDeliveryLogistics__c = false;
         try{
+            system.debug('le:'+le);
             insert le;
         }catch(Exception ex){
              ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage() + ' | Line:' + ex.getLineNumber()));
diff --git a/force-app/main/default/classes/NewAndEditBaseController.cls b/force-app/main/default/classes/NewAndEditBaseController.cls
new file mode 100644
index 0000000..35317ff
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditBaseController.cls
@@ -0,0 +1,277 @@
+/**
+ * @description       : 
+ * @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+ * @group             : 
+ * @last modified on  : 03-16-2022
+ * @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+**/
+global abstract class NewAndEditBaseController {
+
+    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
+    public String awsToken{set;get;}
+    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
+    public String sobjectTypeValue {private set; get;}
+    public Boolean isNewMode{set;get;}
+    public String rtTypeId {get; set;}
+    public String AWSDataId{set;get;}
+
+    // 褰撳墠瀵硅薄鎵�鏈夌殑鍔犲瘑瀛楁闆嗗悎
+    public List<String> encryptedAPIList{private set;get;}
+
+    // 褰撳墠椤甸潰涓殑鍔犲瘑瀛楁闆嗗悎
+    public List<String> layoutEncryptedAPIList{private set;get;}
+    //fieldLabel fieldAPI
+    public String requiredFieldAPIListStr {get;private set;}
+    public String fieldApiListStr {get;private set;}
+
+
+    public String fieldAPIToLabelMapStr {get;private set;}
+    public String staticResource {get; set;}
+    public string SobjectName{get{return sobjectTypeValue;}}
+    public string SobjectLabel{get;private set;}
+
+    public Map<string,string> AWSToSobjectMap{
+        get{
+            Map<string,string> temp = new Map<string,string>();
+            temp.putAll(AWSToSobjectNonEncryptedMap);
+            temp.putAll(AWSToSobjectEncryptedMap);
+            return temp;
+        }
+    }
+    public string AWSToSobjectMapJson{get{return JSON.serialize(AWSToSobjectMap);}}
+
+    public Map<string,string> AWSToSobjectNonEncryptedMap{get;private set;}
+    public string AWSToSobjectNonEncryptedMapJson{get{return JSON.serialize(AWSToSobjectNonEncryptedMap);}}
+    public string AWSToSobjectNonEncryptedMapKeySet{get{return JSON.serialize(new List<string>(AWSToSobjectNonEncryptedMap.keySet()));}}
+
+    public Map<string,string> AWSToSobjectEncryptedMap{get;private set;}
+    public string AWSToSobjectEncryptedMapJson{get{return JSON.serialize(AWSToSobjectMap);}}
+
+    public final string ApiPrefix{get;private set;} 
+
+    public String sobjectPrefix{get;private set;}
+    public String SaveAndNewButtonUrl{get;private set;}
+    public List<String> VLookUpFields{get;private set;}
+    public String VLookUpFieldsJson{get{return Json.serialize(VLookUpFields);}}
+    public List<String> LookUpOverrideFields{get;private set;}
+    public string LookUpOverrideFieldsMapJson{get;private set;}
+    
+
+    public NewAndEditBaseController(){
+        ApiPrefix = 'PIBackApi';
+        AWSToSobjectNonEncryptedMap = new Map<string,string>();
+        AWSToSobjectEncryptedMap = new Map<string,string>();
+        VLookUpFields = new List<String>();
+        layoutEncryptedAPIList = new List<String>();
+        LookUpOverrideFields = new List<String>();
+    }
+
+    protected virtual void Init(SObject obj){
+        sobjectTypeValue = obj.getSObjectType().getDescribe().getName();
+        SobjectLabel = obj.getSObjectType().getDescribe().getLabel();
+        system.debug('obj='+sobjectTypeValue);
+        
+        isNewMode = true;
+        List<Sobject> lso = Database.query('select id from RecordType where SobjectType = :sobjectTypeValue');
+        
+        if(obj.Id != null){
+            isNewMode = false;
+            string sql = 'select Id';
+            if (lso.size()>0) {
+                sql += ',RecordTypeId';
+            }
+            sql += GenerateReferenceSql()+',AWS_Data_Id__c from '+sobjectTypeValue+' where id =\''+obj.Id+'\' ';
+            System.debug('sql='+sql);
+            Sobject leadData = Database.query(sql);
+            if (lso.size()>0){
+                rtTypeId = (String)leadData.get('RecordTypeId');
+            }
+            
+            AWSDataId = (String)leadData.get('AWS_Data_Id__c');
+
+            Map<String,String> sfIdToAWSIdMap = new Map<String,String>();
+            for (string f : LookUpOverrideFields) {
+                object o = leadData.get(f);
+                System.debug('leadData.get('+f+')='+o);
+                if (!String.isBlank(String.valueOf(o))) {
+                    sfIdToAWSIdMap.put(String.valueOf(o).subString(0,15), String.valueOf(leadData.getSobject(GetReferenceField(f)).get('AWS_Data_Id__c')));
+                }
+            }
+           
+            LookUpOverrideFieldsMapJson = JSON.serialize(sfIdToAWSIdMap);
+
+
+        }else{
+            rtTypeId = ApexPages.currentPage().getParameters().get('RecordType');
+        }
+        PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo(sobjectTypeValue);
+        layoutEncryptedAPIList = piIntegration.PIFields;
+        encryptedAPIList = piIntegration.PIFields;
+        staticResource = JSON.serialize(piIntegration);
+        sobjectPrefix = piIntegration.sobjectPrefix;
+        SaveAndNewButtonUrl = string.format('/{0}/e', new string[]{sobjectPrefix});
+        if (lso.size() > 1) {
+            SaveAndNewButtonUrl = String.format('/setup/ui/recordtypeselect.jsp?ent={0}&retURL=/{1}/o&save_new_url=/{1}/e?retURL=%2F{1}%2Fo', new String[]{sobjectTypeValue,sobjectPrefix});
+        }
+
+        for (PI_Field_Policy_Detail__c PIDetail : piIntegration.PIDetails) {
+            
+            AWSToSobjectNonEncryptedMap.put(PIDetail.AWS_Field_API__c, PIDetail.SF_Field_API_Name__c);
+            AWSToSobjectEncryptedMap.put(PIDetail.AWS_Encrypted_Field_API__c, PIDetail.SF_Field_Encrypted_API__c);
+        }
+        System.debug(new List<string>(AWSToSobjectNonEncryptedMap.keySet()));
+        system.debug('AWSToSobjectNonEncryptedMapJson=');
+        system.debug(AWSToSobjectNonEncryptedMapJson);
+        try{
+            LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, sobjectTypeValue,'classic');
+            layoutSections = LayoutWrapperValue.layoutSections;
+            List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
+            Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
+            List<String> fieldApiList = new List<String>(); 
+            for (LayoutDescriberHelper.LayoutSection ls : layoutSections) {
+                for (LayoutDescriberHelper.LayoutField lf : ls.layoutFields) {
+                    if (lf.fieldAPI != '') {
+                        System.debug('lf.fieldAPI='+lf.fieldAPI+' fieldType='+lf.fieldType);
+                        fieldApiList.add(lf.fieldAPI);
+                        if (lf.fieldType == 'reference') {
+                            VLookUpFields.add(lf.fieldAPI);
+                        }
+
+                        //鍦╲iew瑙e瘑section涓彧闇�鏄剧ず褰撳墠layout涓殑鍔犲瘑瀛楁
+                        // if (encryptedAPIList.contains(lf.fieldAPI)) {
+                        //     layoutEncryptedAPIList.add(lf.fieldAPI);
+                        // }
+                    }
+                }
+            }
+            fieldApiListStr = JSON.serialize(fieldApiList);
+            fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
+            requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
+            //awsToken = AWSServiceTool.getAWSToken();
+        }catch(Exception e){
+            system.debug('Exception from get layout service:'+e.getmessage());
+        }
+    }
+
+    public static string GetReferenceField(string f){
+        if (f.endsWith('__c')) {
+            return f.substring(0,f.length()-1)+'r';
+        }
+        else if(f.endsWith('Id') || f.endsWith('id') || f.endsWith('ID')) {
+            return f.substring(0, f.length()-2);
+        }
+        else{
+            return f;
+        }
+    }
+
+    public string GenerateReferenceSql(){
+        string res ='';
+        for (string f : LookUpOverrideFields) {
+            res += ','+f+','+GetReferenceField(f)+'.AWS_Data_Id__c';
+        }
+        return res;
+    }
+
+    global class Response{
+        public String recordId{set;get;}
+        public String message{set;get;}
+        public String status{set;get;}
+    }
+
+    @RemoteAction
+    global static Response save(Sobject sobj, String leadJson,String transId,Boolean isNew) {
+        string sobjectTypeValue = sobj.getSObjectType().getDescribe().getName();
+        System.debug('sobjectTypeValue:'+sobjectTypeValue+' Info:' + JSON.serialize(leadJson));
+        System.debug('json length='+leadJson.length());
+        System.debug('json ='+leadJson);
+        //1. Prepare the payload for  Lead
+        Schema.SObjectType leadSchema = schemaMap.get(sobjectTypeValue);
+        Map<String, Schema.SObjectField> fieldAPIToTypeMap = leadSchema.getDescribe().fields.getMap();
+        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(leadJson);
+        Sobject leadInfo = sobj;
+        for (String fieldAPI: fieldValueMap.keySet()) {
+            system.debug('field API='+fieldAPI);
+            Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType();  
+            String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI)); 
+            system.debug('Field Type:'+fielddataType+' field Value='+fieldValue);
+            if(String.valueOf(fielddataType)=='DATE'){
+                leadInfo.put(fieldAPI,(String.isBlank(fieldValue)||String.isEmpty(fieldValue))? null:Date.valueOf(fieldValue.replace('/', '-')));              
+            }else if(String.valueOf(fielddataType)=='DATETIME'){
+                if(String.isNotBlank(fieldValue)&&fieldValue.contains('T')){
+                    fieldValue = fieldValue.replace('T',' ');
+                    leadInfo.put(fieldAPI, Datetime.valueOfGmt(fieldValue));
+                }else{
+                    leadInfo.put(fieldAPI, null);
+                }                    
+            }else if(String.valueof(fielddataType)=='CURRENCY' || String.valueof(fielddataType)=='PERCENT'||String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){
+                // leadInfo.put(fieldAPI, (String.isBlank(fieldValue)||String.isEmpty(fieldValue))?0:Decimal.valueOf(fieldValue)); 
+                if(String.isNotBlank(fieldValue)&&String.isNotEmpty(fieldValue)){
+                    if(fieldValue.contains(',')){
+                        fieldValue = fieldValue.replace(',', '');
+                    }
+                    leadInfo.put(fieldAPI, Decimal.valueOf(fieldValue));
+                }else{
+                    leadInfo.put(fieldAPI, 0);
+                } 
+            } else if(String.valueof(fielddataType)=='BOOLEAN'){
+                leadInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
+            }else {
+                leadInfo.put(fieldAPI,fieldValue);
+            }                  
+        }
+
+        system.debug('for (String fieldAPI: fieldValueMap.keySet()) end');
+
+        
+        //2. Save Record Process
+        String status = 'success';    
+        Response resp = new Response();
+        String awsDataId = '';
+        Savepoint sp = Database.setSavepoint();
+        try{
+            System.debug('abcde');
+            if(isNew){
+                System.debug('leadInfozhj = ' + leadInfo);
+                if(!Test.isRunningTest()){
+                    insert leadInfo;
+                }
+            }else{
+                System.debug('into update');
+                awsDataId = (String)leadInfo.get('AWS_Data_Id__c');
+                System.debug('awsDataId = ' + awsDataId);
+                Sobject[] leads = Database.query('select id from '+sobjectTypeValue+' where AWS_Data_Id__c =:awsDataId');
+                System.debug('leads[0].id = ' + leads[0].id);
+                leadInfo.put('Id',leads[0].id);//For testing;
+                if(!Test.isRunningTest()){
+                    update leadInfo;
+                }
+            }
+            // //saveTransLog(transId, leadInfo.AWS_Data_Id__c, status, '');
+            // Transaction_Log__c traLog = new Transaction_Log__c();
+            // // AWS_Data_Id__c=AWSDataId,TransId__c=transId,JsonContent__c=leadJson,Status__c=status
+            // traLog.AWS_Data_Id__c = AWSDataId;
+            // traLog.TransId__c = transId;
+            // traLog.JsonContent__c = leadJson;
+            // traLog.Status__c = status;
+            // insert traLog;
+            resp.recordId = leadInfo.Id;
+            // resp.message = 'success saveLead';
+            resp.status = status;
+            PIHelper.saveTransLog(sobjectTypeValue,awsDataId,leadInfo.Id,transId, leadJson ,status,'');
+            // (String module,String awsDataId,String sfId, String transId,String content,String status,String respMsg)
+            System.debug('respzhj = ' + resp);
+            return resp;
+
+        } catch(Exception e) {
+            System.debug('into catch'+e.getMessage());
+            Database.rollback(sp);
+            resp.status = 'Exception';
+            resp.message = e.getMessage()+e.getStackTraceString();
+            PIHelper.saveTransLog(sobjectTypeValue,awsDataId,leadInfo.Id,transId, leadJson ,status,resp.message);
+            // PIHelper.saveTransLog(sobjectTypeValue,(String)leadInfo.get('AWS_Data_Id__c'),transId, leadJson,status,e.getStackTraceString());
+            return resp;
+        }
+    }
+    
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditBaseController.cls-meta.xml b/force-app/main/default/classes/NewAndEditBaseController.cls-meta.xml
new file mode 100644
index 0000000..f928c8e
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditBaseController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>53.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditBaseControllerTest.cls b/force-app/main/default/classes/NewAndEditBaseControllerTest.cls
new file mode 100644
index 0000000..d243e47
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditBaseControllerTest.cls
@@ -0,0 +1,3 @@
+public class NewAndEditBaseControllerTest {
+
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditBaseControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditBaseControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditBaseControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditContactController.cls b/force-app/main/default/classes/NewAndEditContactController.cls
new file mode 100644
index 0000000..b5a7688
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditContactController.cls
@@ -0,0 +1,57 @@
+/*
+ * Author: Yanan Chen
+ * Created Date: 02/22/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: NewAndEditContactController
+ * History: 
+ *      02/22/2022 - Yanan Chen - Initial Code.
+ * 
+ * */
+global class NewAndEditContactController extends NewAndEditBaseController {
+
+    public String accountId{get; set;}
+    public Account account{get; private set;}
+
+    public NewAndEditContactController(ApexPages.StandardController controller){
+        
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Contact').getDescribe().fields.getMap().keyset());  
+        
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        //Get Account Id from url param
+        this.accountId = ApexPages.currentPage().getParameters().get('retURL');
+        System.debug('accountId = ' + accountId);
+
+        // System.debug('accountType = ' + );
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList);
+        }
+        
+        Init(controller.getRecord());
+        
+        if (this.accountId != '/003/o' && this.accountId != null && this.isNewMode) {
+            ID accId = ID.valueOf(this.accountId.substring(1, this.accountId.length()));   
+            System.debug('accId = ' + accId);
+            
+            account = [select id, Name, PhoneD__c, FaxD__c, Address1D__c, PostCodeD__c, ProductSegment__c from Account where id =:accId];
+            System.debug('account = ' + account);
+        }
+
+        SObject obj = controller.getRecord();
+        if(obj.Id == null){
+            //鍒濆鍖栧姞杞藉��
+            obj.put('OwnerId',UserInfo.getUserId());
+        }
+
+        if (this.account != null) {
+            obj.put('ProductSegment'+account.ProductSegment__c+'__c', true);
+        }
+        
+        
+    }
+
+    
+    @RemoteAction
+    global static Response saveContact(String contactJson, String transId, Boolean isNew){
+        return save(new Contact(), contactJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditContactController.cls-meta.xml b/force-app/main/default/classes/NewAndEditContactController.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditContactController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditContactControllerTest.cls b/force-app/main/default/classes/NewAndEditContactControllerTest.cls
new file mode 100644
index 0000000..15bfa27
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditContactControllerTest.cls
@@ -0,0 +1,20 @@
+@isTest
+public class NewAndEditContactControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditContactController() {
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        Contact con = TestDataUtility.CreateContacts(1)[0];
+
+        Test.startTest();
+        ApexPages.StandardController sc =  new ApexPages.StandardController(con);
+        NewAndEditContactController qis = new NewAndEditContactController(sc);
+
+        String qisJson = '{"AccountId":"0010l00001Q1r4e","OwnerId":"0050l0000061MOe","Department":"","MobilePhone":"***********","Title":"","Phone":"","Salutation":"","LastName":"***","Fax":"","ContactEnglishName__c":"","OtherPhone":"","ManagementCode_Ext__c":"","Email":"*****@company.com","isBatch__c":false,"TechnicalServiceCreated__c":false,"IsNew__c":false,"isServiceCreate__c":false,"Postcode__c":"**********","Address1__c":"**********","Address2__c":"","Address3__c":"","EnglishAddress__c":"","ProductSegmentBS__c":false,"ProductSegmentRVI__c":false,"ProductSegmentIE__c":false,"ProductSegmentNDT__c":false,"ProductSegmentANI__c":false,"StatusD__c":"Draft","ContactStatus__c":"Active","CancelReason__c":"","Remark__c":"","Phone_Encrypted__c":"","OtherPhone_Encrypted__c":"","MobilePhone_Encrypted__c":"64bd0db056d0bfd21fae76cc5dbdf4d1","PhoneD_Encrypted__c":null,"OtherPhoneD_Encrypted__c":null,"MobilePhoneD_Encrypted__c":null,"Email_Encrypted__c":"68fda69bb586ec70073b015fbff6c19420b838c523e79c9737c6fe095fd5cc55","EmailD_Encrypted__c":null,"FaxD_Encrypted__c":null,"Address3D_Encrypted__c":null,"Address1D_Encrypted__c":null,"Address3_Encrypted__c":"","Address2D_Encrypted__c":null,"Address1_Encrypted__c":"2df1bc4bf3800c5e05e3d9f394c3446567d1f05482d2295650b7b50e9e4aa97a92338985c9693f576e1e6df667aaee46","EnglishAddress_Encrypted__c":"","ContactEnglishName_Encrypted__c":"","Title_Encrypted__c":"","TitleD_Encrypted__c":null,"PostcodeD_Encrypted__c":null,"Postcode_Encrypted__c":"ecec26168c09cf090b8b4a95ca524a61","LastName_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","PhoneD__c":null,"OtherPhoneD__c":null,"MobilePhoneD__c":null,"EmailD__c":null,"FaxD__c":null,"Address3D__c":null,"Address2D__c":null,"Address1D__c":null,"TitleD__c":null,"PostcodeD__c":null,"AWS_Data_Id__c":"962006242048344064"}';
+        NewAndEditContactController.saveContact(qisJson,'avgwshDFcxAS',False);
+        NewAndEditContactController.saveContact(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditContactControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditContactControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditContactControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditLoanerAppDetailController.cls b/force-app/main/default/classes/NewAndEditLoanerAppDetailController.cls
new file mode 100644
index 0000000..72d1a83
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerAppDetailController.cls
@@ -0,0 +1,31 @@
+/*
+ * Author: Yanan Chen
+ * Created Date: 03/02/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: NewAndEditLoanerApplicationDetailController 
+ * History: 
+ *      03/15/2022 - Yanan Chen - Initial Code.
+ * 
+ * */
+global class NewAndEditLoanerAppDetailController extends NewAndEditBaseController {
+    public NewAndEditLoanerAppDetailController (ApexPages.StandardController controller){
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('loaner_application_detail__c').getDescribe().fields.getMap().keyset());  
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList); // contact lookup
+        }
+        Init(controller.getRecord());
+        SObject obj = controller.getRecord();
+        if(obj.Id == null){
+            //鍒濆鍖栧姞杞藉��
+            obj.put('OwnerId',UserInfo.getUserId());
+        }
+    }
+
+    
+    @RemoteAction
+    global static Response saveLoanerApplicationDetail(String sobJson, String transId, Boolean isNew){
+        system.debug('JSON Payload:' + sobJson);
+        return save(new loaner_application_detail__c(), sobJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditLoanerAppDetailController.cls-meta.xml b/force-app/main/default/classes/NewAndEditLoanerAppDetailController.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerAppDetailController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditLoanerAppDetailControllerTest.cls b/force-app/main/default/classes/NewAndEditLoanerAppDetailControllerTest.cls
new file mode 100644
index 0000000..72bea13
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerAppDetailControllerTest.cls
@@ -0,0 +1,21 @@
+@isTest
+private class NewAndEditLoanerAppDetailControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditLoanerAppDetailController() {
+
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        loaner_application_detail__c lad = TestDataUtility.Createloanerapplicationdetails(1)[0];
+        
+        Test.startTest();
+        ApexPages.StandardController con =  new ApexPages.StandardController(lad);
+        NewAndEditLoanerAppDetailController qis = new NewAndEditLoanerAppDetailController(con);
+        
+        String qisJson = '{"Name":"test123","QIS_Status__c":"鑽夋涓�","QIS_pre__c":"000000000000000","consumable__c":"01t1m000001QyDa","Cancel_QIS_Reason__c":"_u0001_","RecordTypeId":"01210000000RLWc","Repair__c":"a0J1m000001nZzf","RejectReason__c":"","Managementtext__c":"","OCSMAdministrativeReportStatus__c":"鏃犻渶鎶ュ憡","MBC_AwareDate__c":"2022/03/29","Aware_date__c":"2022/03/29","Old_Repair_Name__c":"","isLendRental__c":false,"next_action__c":"","RC_problem_not_found__c":false,"Salesdepartment_Text__c":"","OCM_Repair_Mail1__c":"","Hospital__c":"0011m00000XlvHh","Account_State__c":"","Department_Class__c":"0011m00000SP4Mp","OwnerId":"0051m0000030e0QAAQ","Hospital_Department__c":"0011m00000SP4TB","Responsible_Person_HP__c":"***","Caller_phone__c":"***********","capital_or_consumable__c":"鑰楁潗","contract_number_ET_text__c":"","nonyushohin__c":"000000000000000","InstallDate_text__c":"","usage_frequence__c":"1","cleanning__c":"1","cds_methods__c":"鎵嬪姩","disinfection__c":"","sterlization__c":"","Faliour_date__c":"2022/03/29","Trable_occur_daY_collect__c":"2022/03/29","DelayReportReason__c":"","failuer_situation__c":"鍒拌揣楠屾敹","failuer_situationSelect__c":"","problem_detail__c":"test","Damage_For_Doc_Or_Pat__c":"","Relation_With_The_Problem__c":"","Report_For_Goz__c":"","Which_Project__c":"","Opera_Name__c":"","BreakORFallOff__c":"","Is_Used_For_The_Opera__c":"","Set_usage_product__c":"","Comment__c":"test","AfterFailureInformation__c":"","Delay15Min__c":"","InformationFrom__c":"","FailureQInHospital__c":"","accsessary_detail__c":"","shipping_to_QIS_dept_day__c":"","ASReportedCode__c":"","QIS_ConfirmationDate__c":"","PAE_Determine__c":"","ASReportedCodeAC__c":"","OCSM_RC_CordingDate__c":"","PAE_DetermineAC__c":"","Complaint_Number__c":"","OSH_ConfirmationDate__c":"","if_QIS_Allowed__c":"","NotAllowedReason__c":"","OSHRAConfirmDate__c":"","isAE_Profile__c":"","isPAE_Profile__c":"","MDR_information__c":"","MDR_detail__c":"","CFDA_No_Hand__c":"","ProduceCompany_hand__c":"","Receive_Date_Day__c":"2022/03/29","OSHRecievedDate__c":"","QIS_Submit_day__c":"","QIS_OSH_answerdate__c":"","OCM_RC_RecievedDate__c":"","QIS_Complete_Day__c":"","QIS_Reply_day__c":"","QIS_cancel_date__c":"","QIS_Cancel_Submit_day__c":"","Daily_Report__c":"000000000000000","Generation_Source__c":"","Source_OnCall__c":"000000000000000","QisSubOrder__c":"000000000000000","AsyncData__c":false,"ETQ_UPLOAD_STATUS__c":"","AWS_Interface_Time__c":"2022/03/29 13:38","ETQ_UPLOAD_MESSAGE__c":"","INTERFACE_RECORD_ID__c":"","ET_QIS_SEND_EMAIL1__c":"","ET_QIS_SEND_EMAIL2__c":"","problem_detail_photo__c":"","Caller_phone_Encrypted__c":"415f2dab7eb6b2a866e02d823080a845","Responsible_Person_HP_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","AWS_Data_Id__c":"958360820671053825"}';
+        NewAndEditLoanerAppDetailController.saveLoanerApplicationDetail(qisJson,'avgwshDFcxAS',False);
+        NewAndEditLoanerAppDetailController.saveLoanerApplicationDetail(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditLoanerAppDetailControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditLoanerAppDetailControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerAppDetailControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditLoanerApplicationControlTest.cls b/force-app/main/default/classes/NewAndEditLoanerApplicationControlTest.cls
new file mode 100644
index 0000000..40d5393
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerApplicationControlTest.cls
@@ -0,0 +1,20 @@
+@isTest
+public class NewAndEditLoanerApplicationControlTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditLoanerApplicationController() {
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        loaner_application__c la = TestDataUtility.Createloanerapplications(1)[0];
+
+        Test.startTest();
+        ApexPages.StandardController con =  new ApexPages.StandardController(la);
+        NewAndEditLoanerApplicationController qis = new NewAndEditLoanerApplicationController(con);
+        
+        String qisJson = '{"Status__c":"鑽夋涓�","Name":"test1","RecordTypeId":"0120K000000wDzQ","loaner_request_number__c":"","Equipment_Type__c":"IE","AllLead_OrderName__c":"","Loaner_Ser__c":"","Approval_Step__c":"","loaner_place__c":"","Approval_Date__c":"","Is_High_end_Products__c":false,"Is_Repair_Products__c":false,"Is_time_out__c":false,"Is_Automatic_Received__c":false,"Demo_purpose__c":"婕旂ず","Demo_purpose_text__c":"","Follow_Opp_text__c":"","ProductCount1__c":"","EC_Code_1__c":"","ProductCount2__c":"","EC_Code_2__c":"","ProductCount3__c":"","EC_Code_3__c":"","ProductCount4__c":"","EC_Code_4__c":"","ProductCount5__c":"","EC_Code_5__c":"","ProductCount6__c":"","EC_Code_6__c":"","ProductCount7__c":"","EC_Code_7__c":"","ProductCount8__c":"","EC_Code_8__c":"","ProductCount9__c":"","EC_Code_9__c":"","ProductCount10__c":"","EC_Code_10__c":"","ProductCount11__c":"","EC_Code_11__c":"","ProductCount12__c":"","EC_Code_12__c":"","ProductCount13__c":"","EC_Code_13__c":"","ProductCount14__c":"","EC_Code_14__c":"","ProductCount15__c":"","EC_Code_15__c":"","ProductCount16__c":"","EC_Code_16__c":"","ProductCount17__c":"","EC_Code_17__c":"","ProductCount18__c":"","EC_Code_18__c":"","ProductCount19__c":"","EC_Code_19__c":"","ProductCount20__c":"","EC_Code_20__c":"","Request_shipping_Date__c":"2022-4-8","Rental_Start_Date__c":"2022-4-8","Request_return_Date__c":"2022-4-10","Rental_End_Date__c":"2022-4-8","Loaner_receive_staff__c":"***","pickup_time__c":"","direct_shippment_address__c":"**********","Loaner_receive_staff_phone__c":"***********","Post_Code__c":"******","delivery_company__c":"test","Return_Track_Company__c":"test","Tracking_Number__c":"","Return_Track_Number__c":"","Return_Trake_Staff__c":"","loaner_manage_place__c":"","loaner_return__c":false,"loaner_Remark__c":"","HP_Received_Sign_Date__c":"","Cancel_Reason__c":"","Cancel_Date__c":"","Bollow_Date__c":"","Asset_Return_Date__c":"","Shipping_Finished_Date__c":"","Asset_Return_Date_All__c":"","Shipping_Finished_Date_All__c":"","LoanerClosedDateAll__c":"","Finished_Date__c":"","Loaner_Renewal__c":"鏈敵璇�","Loaner_Renewal_Reason__c":"","Loaner_Apply_Renewal_Date__c":"","Loaner_Renewal_Date__c":"","Renewal_Examine_Date__c":"","Renew_Num__c":"0","Loaner_LendOrder__c":false,"Dealer_From_txt__c":"","Service_Approval__c":false,"Product_Approval__c":false,"Loaner_AgreementPDF__c":false,"Installation_Qualification_Attachment__c":false,"Remind_Date__c":"","Loaner_Ser_Encrypted__c":"","Post_Code_Encrypted__c":"ecec26168c09cf090b8b4a95ca524a61","return_Number_Encrypted__c":null,"Return_Trake_Staff_Encrypted__c":"","Loaner_receive_staff_phone_Encrypted__c":"64bd0db056d0bfd21fae76cc5dbdf4d1","direct_shippment_address_Encrypted__c":"2df1bc4bf3800c5e05e3d9f394c3446567d1f05482d2295650b7b50e9e4aa97a92338985c9693f576e1e6df667aaee46","Loaner_receive_staff_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","return_Number__c":null,"AWS_Data_Id__c":"962025468062597121"}';
+        NewAndEditLoanerApplicationController.saveLoanerApplication(qisJson,'avgwshDFcxAS',False);
+        NewAndEditLoanerApplicationController.saveLoanerApplication(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditLoanerApplicationControlTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditLoanerApplicationControlTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerApplicationControlTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditLoanerApplicationController.cls b/force-app/main/default/classes/NewAndEditLoanerApplicationController.cls
new file mode 100644
index 0000000..8d9b158
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerApplicationController.cls
@@ -0,0 +1,31 @@
+/*
+ * Author: Yanan Chen
+ * Created Date: 03/02/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: NewAndEditLoanerApplicationController  
+ * History: 
+ *      03/02/2022 - Yanan Chen - Initial Code.
+ * 
+ * */
+global class NewAndEditLoanerApplicationController extends NewAndEditBaseController {
+    public NewAndEditLoanerApplicationController (ApexPages.StandardController controller){
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('loaner_application__c').getDescribe().fields.getMap().keyset());  
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList); // contact lookup
+        }
+        Init(controller.getRecord());
+        SObject obj = controller.getRecord();
+        if(obj.Id == null){
+            //鍒濆鍖栧姞杞藉��
+            obj.put('OwnerId',UserInfo.getUserId());
+        }
+    }
+
+    
+    @RemoteAction
+    global static Response saveLoanerApplication(String sobJson, String transId, Boolean isNew){
+        system.debug('JSON Payload:' + sobJson);
+        return save(new loaner_application__c(), sobJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditLoanerApplicationController.cls-meta.xml b/force-app/main/default/classes/NewAndEditLoanerApplicationController.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerApplicationController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditLoanerExpressController.cls b/force-app/main/default/classes/NewAndEditLoanerExpressController.cls
new file mode 100644
index 0000000..e34dd71
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerExpressController.cls
@@ -0,0 +1,31 @@
+/*
+ * Author: Yanan Chen
+ * Created Date: 03/02/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: NewAndEditLoanerApplicationDetailController 
+ * History: 
+ *      03/15/2022 - Yanan Chen - Initial Code.
+ * 
+ * */
+global class NewAndEditLoanerExpressController extends NewAndEditBaseController {
+    public NewAndEditLoanerExpressController (ApexPages.StandardController controller){
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Loaner_Express__c').getDescribe().fields.getMap().keyset());  
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList); // contact lookup
+        }
+        Init(controller.getRecord());
+        SObject obj = controller.getRecord();
+        if(obj.Id == null){
+            //鍒濆鍖栧姞杞藉��
+            obj.put('OwnerId',UserInfo.getUserId());
+        }
+    }
+
+    
+    @RemoteAction
+    global static Response saveLoanerExpress(String sobJson, String transId, Boolean isNew){
+        system.debug('JSON Payload:' + sobJson);
+        return save(new Loaner_Express__c(), sobJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditLoanerExpressController.cls-meta.xml b/force-app/main/default/classes/NewAndEditLoanerExpressController.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerExpressController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditLoanerExpressControllerTest.cls b/force-app/main/default/classes/NewAndEditLoanerExpressControllerTest.cls
new file mode 100644
index 0000000..94eee35
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerExpressControllerTest.cls
@@ -0,0 +1,20 @@
+@isTest
+public class NewAndEditLoanerExpressControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditLoanerExpressController() {
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        Loaner_Express__c le = TestDataUtility.CreateLoanerExpresses(1)[0];
+
+        Test.startTest();
+        ApexPages.StandardController con =  new ApexPages.StandardController(le);
+        NewAndEditLoanerExpressController qis = new NewAndEditLoanerExpressController(con);
+        
+        String qisJson = '{"Name":"test123","QIS_Status__c":"鑽夋涓�","QIS_pre__c":"000000000000000","consumable__c":"01t1m000001QyDa","Cancel_QIS_Reason__c":"_u0001_","RecordTypeId":"01210000000RLWc","Repair__c":"a0J1m000001nZzf","RejectReason__c":"","Managementtext__c":"","OCSMAdministrativeReportStatus__c":"鏃犻渶鎶ュ憡","MBC_AwareDate__c":"2022/03/29","Aware_date__c":"2022/03/29","Old_Repair_Name__c":"","isLendRental__c":false,"next_action__c":"","RC_problem_not_found__c":false,"Salesdepartment_Text__c":"","OCM_Repair_Mail1__c":"","Hospital__c":"0011m00000XlvHh","Account_State__c":"","Department_Class__c":"0011m00000SP4Mp","OwnerId":"0051m0000030e0QAAQ","Hospital_Department__c":"0011m00000SP4TB","Responsible_Person_HP__c":"***","Caller_phone__c":"***********","capital_or_consumable__c":"鑰楁潗","contract_number_ET_text__c":"","nonyushohin__c":"000000000000000","InstallDate_text__c":"","usage_frequence__c":"1","cleanning__c":"1","cds_methods__c":"鎵嬪姩","disinfection__c":"","sterlization__c":"","Faliour_date__c":"2022/03/29","Trable_occur_daY_collect__c":"2022/03/29","DelayReportReason__c":"","failuer_situation__c":"鍒拌揣楠屾敹","failuer_situationSelect__c":"","problem_detail__c":"test","Damage_For_Doc_Or_Pat__c":"","Relation_With_The_Problem__c":"","Report_For_Goz__c":"","Which_Project__c":"","Opera_Name__c":"","BreakORFallOff__c":"","Is_Used_For_The_Opera__c":"","Set_usage_product__c":"","Comment__c":"test","AfterFailureInformation__c":"","Delay15Min__c":"","InformationFrom__c":"","FailureQInHospital__c":"","accsessary_detail__c":"","shipping_to_QIS_dept_day__c":"","ASReportedCode__c":"","QIS_ConfirmationDate__c":"","PAE_Determine__c":"","ASReportedCodeAC__c":"","OCSM_RC_CordingDate__c":"","PAE_DetermineAC__c":"","Complaint_Number__c":"","OSH_ConfirmationDate__c":"","if_QIS_Allowed__c":"","NotAllowedReason__c":"","OSHRAConfirmDate__c":"","isAE_Profile__c":"","isPAE_Profile__c":"","MDR_information__c":"","MDR_detail__c":"","CFDA_No_Hand__c":"","ProduceCompany_hand__c":"","Receive_Date_Day__c":"2022/03/29","OSHRecievedDate__c":"","QIS_Submit_day__c":"","QIS_OSH_answerdate__c":"","OCM_RC_RecievedDate__c":"","QIS_Complete_Day__c":"","QIS_Reply_day__c":"","QIS_cancel_date__c":"","QIS_Cancel_Submit_day__c":"","Daily_Report__c":"000000000000000","Generation_Source__c":"","Source_OnCall__c":"000000000000000","QisSubOrder__c":"000000000000000","AsyncData__c":false,"ETQ_UPLOAD_STATUS__c":"","AWS_Interface_Time__c":"2022/03/29 13:38","ETQ_UPLOAD_MESSAGE__c":"","INTERFACE_RECORD_ID__c":"","ET_QIS_SEND_EMAIL1__c":"","ET_QIS_SEND_EMAIL2__c":"","problem_detail_photo__c":"","Caller_phone_Encrypted__c":"415f2dab7eb6b2a866e02d823080a845","Responsible_Person_HP_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","AWS_Data_Id__c":"958360820671053825"}';
+        NewAndEditLoanerExpressController.saveLoanerExpress(qisJson,'avgwshDFcxAS',False);
+        NewAndEditLoanerExpressController.saveLoanerExpress(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditLoanerExpressControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditLoanerExpressControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerExpressControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditLoanerUserController.cls b/force-app/main/default/classes/NewAndEditLoanerUserController.cls
new file mode 100644
index 0000000..3121b93
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerUserController.cls
@@ -0,0 +1,41 @@
+/*
+ * Author: Yanan Chen
+ * Created Date: 03/03/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: NewAndEditLoanerUserController  
+ * History: 
+ *      03/03/2022 - Yanan Chen - Initial Code.
+ * 
+ * */
+global class NewAndEditLoanerUserController extends NewAndEditBaseController {
+
+    public String PIPL_Input_Account_Error_Msg{set;get;}
+    public String contactId{set;get;}//For Lookup field
+    public String staticResourceContact {get; set;}
+    
+    public NewAndEditLoanerUserController (ApexPages.StandardController controller){
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('loaner_user__c').getDescribe().fields.getMap().keyset());  
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList); // contact lookup
+        }
+        LookUpOverrideFields.add('Contact__c');
+        Init(controller.getRecord());
+        //娣诲姞椤�
+        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
+        // SObject obj = controller.getRecord();
+        // if(obj.Id == null){
+        //     //鍒濆鍖栧姞杞藉��
+        //     obj.put('OwnerId',UserInfo.getUserId());
+        // }
+        //contact淇℃伅锛堟悳绱㈡煡璇uery url鐢級
+        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
+    }
+
+    
+    @RemoteAction
+    global static Response saveLoanerUser(String sobJson, String transId, Boolean isNew){
+        system.debug('JSON Payload:' + sobJson);
+        return save(new loaner_user__c(), sobJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditLoanerUserController.cls-meta.xml b/force-app/main/default/classes/NewAndEditLoanerUserController.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerUserController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditLoanerUserControllerTest.cls b/force-app/main/default/classes/NewAndEditLoanerUserControllerTest.cls
new file mode 100644
index 0000000..c9bd9ac
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerUserControllerTest.cls
@@ -0,0 +1,19 @@
+@isTest
+public class NewAndEditLoanerUserControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditLoanerUserController() {
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        loaner_user__c lu = TestDataUtility.CreateLoanerUsers(1)[0];
+        Test.startTest();
+        ApexPages.StandardController sc =  new ApexPages.StandardController(lu);
+        NewAndEditLoanerUserController qis = new NewAndEditLoanerUserController(sc);
+
+        String qisJson = '{"Name":"test123","QIS_Status__c":"鑽夋涓�","QIS_pre__c":"000000000000000","consumable__c":"01t1m000001QyDa","Cancel_QIS_Reason__c":"_u0001_","RecordTypeId":"01210000000RLWc","Repair__c":"a0J1m000001nZzf","RejectReason__c":"","Managementtext__c":"","OCSMAdministrativeReportStatus__c":"鏃犻渶鎶ュ憡","MBC_AwareDate__c":"2022/03/29","Aware_date__c":"2022/03/29","Old_Repair_Name__c":"","isLendRental__c":false,"next_action__c":"","RC_problem_not_found__c":false,"Salesdepartment_Text__c":"","OCM_Repair_Mail1__c":"","Hospital__c":"0011m00000XlvHh","Account_State__c":"","Department_Class__c":"0011m00000SP4Mp","OwnerId":"0051m0000030e0QAAQ","Hospital_Department__c":"0011m00000SP4TB","Responsible_Person_HP__c":"***","Caller_phone__c":"***********","capital_or_consumable__c":"鑰楁潗","contract_number_ET_text__c":"","nonyushohin__c":"000000000000000","InstallDate_text__c":"","usage_frequence__c":"1","cleanning__c":"1","cds_methods__c":"鎵嬪姩","disinfection__c":"","sterlization__c":"","Faliour_date__c":"2022/03/29","Trable_occur_daY_collect__c":"2022/03/29","DelayReportReason__c":"","failuer_situation__c":"鍒拌揣楠屾敹","failuer_situationSelect__c":"","problem_detail__c":"test","Damage_For_Doc_Or_Pat__c":"","Relation_With_The_Problem__c":"","Report_For_Goz__c":"","Which_Project__c":"","Opera_Name__c":"","BreakORFallOff__c":"","Is_Used_For_The_Opera__c":"","Set_usage_product__c":"","Comment__c":"test","AfterFailureInformation__c":"","Delay15Min__c":"","InformationFrom__c":"","FailureQInHospital__c":"","accsessary_detail__c":"","shipping_to_QIS_dept_day__c":"","ASReportedCode__c":"","QIS_ConfirmationDate__c":"","PAE_Determine__c":"","ASReportedCodeAC__c":"","OCSM_RC_CordingDate__c":"","PAE_DetermineAC__c":"","Complaint_Number__c":"","OSH_ConfirmationDate__c":"","if_QIS_Allowed__c":"","NotAllowedReason__c":"","OSHRAConfirmDate__c":"","isAE_Profile__c":"","isPAE_Profile__c":"","MDR_information__c":"","MDR_detail__c":"","CFDA_No_Hand__c":"","ProduceCompany_hand__c":"","Receive_Date_Day__c":"2022/03/29","OSHRecievedDate__c":"","QIS_Submit_day__c":"","QIS_OSH_answerdate__c":"","OCM_RC_RecievedDate__c":"","QIS_Complete_Day__c":"","QIS_Reply_day__c":"","QIS_cancel_date__c":"","QIS_Cancel_Submit_day__c":"","Daily_Report__c":"000000000000000","Generation_Source__c":"","Source_OnCall__c":"000000000000000","QisSubOrder__c":"000000000000000","AsyncData__c":false,"ETQ_UPLOAD_STATUS__c":"","AWS_Interface_Time__c":"2022/03/29 13:38","ETQ_UPLOAD_MESSAGE__c":"","INTERFACE_RECORD_ID__c":"","ET_QIS_SEND_EMAIL1__c":"","ET_QIS_SEND_EMAIL2__c":"","problem_detail_photo__c":"","Caller_phone_Encrypted__c":"415f2dab7eb6b2a866e02d823080a845","Responsible_Person_HP_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","AWS_Data_Id__c":"958360820671053825"}';
+        NewAndEditLoanerUserController.saveLoanerUser(qisJson,'avgwshDFcxAS',False);
+        NewAndEditLoanerUserController.saveLoanerUser(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditLoanerUserControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditLoanerUserControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditLoanerUserControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditOpportunityController.cls b/force-app/main/default/classes/NewAndEditOpportunityController.cls
new file mode 100644
index 0000000..0561fe2
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditOpportunityController.cls
@@ -0,0 +1,44 @@
+/*
+ * Author: Yanan Chen
+ * Created Date: 02/23/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: NewAndEditOpportunityController 
+ * History: 
+ *      02/23/2022 - Yanan Chen - Initial Code.
+ * 
+ * */
+global class NewAndEditOpportunityController extends NewAndEditBaseController {
+
+    // public String contactId{get; set;}
+    // public Contact contact{get; private set;}
+
+    public String PIPL_Input_Account_Error_Msg{set;get;}
+    public String contactId{set;get;}//For Lookup field
+    public String staticResourceContact {get; set;}
+    public NewAndEditOpportunityController(ApexPages.StandardController controller){
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Opportunity').getDescribe().fields.getMap().keyset());  
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList); // contact lookup
+        }
+        LookUpOverrideFields.add('EndUser__c');
+
+        Init(controller.getRecord());
+        //娣诲姞椤�
+        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
+        SObject obj = controller.getRecord();
+        if(obj.Id == null){
+            //鍒濆鍖栧姞杞藉��
+            obj.put('OwnerId',UserInfo.getUserId());
+        }
+        //contact淇℃伅锛堟悳绱㈡煡璇uery url鐢級
+        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
+    }
+
+    
+    @RemoteAction
+    global static Response saveOpportunity(String sobJson, String transId, Boolean isNew){
+        system.debug('JSON Payload:'+sobJson);
+        return save(new Opportunity(), sobJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditOpportunityController.cls-meta.xml b/force-app/main/default/classes/NewAndEditOpportunityController.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditOpportunityController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditOpportunityControllerTest.cls b/force-app/main/default/classes/NewAndEditOpportunityControllerTest.cls
new file mode 100644
index 0000000..90d2ef1
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditOpportunityControllerTest.cls
@@ -0,0 +1,20 @@
+@isTest
+public class NewAndEditOpportunityControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditOpportunityController() {
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        Opportunity opp = TestDataUtility.CreateOpportunitys(1)[0];
+        Test.startTest();
+        ApexPages.StandardController sc =  new ApexPages.StandardController(opp);
+        NewAndEditOpportunityController qis = new NewAndEditOpportunityController(sc);
+        qis.contactId = 'test';
+
+        String qisJson = '{"Is_Decided__c":false,"the_Upload_of_quotation_number__c":"","Cancel_Fail_Approve__c":"","SAP_QuotationCode__c":"","compo_opp__c":false,"CanChangeOpp__c":true,"Name":"test1","AccountId":"0010l00001Q1r4e","RecordTypeId":"012280000005hjO","Type":"","ApprovalStatus_D__c":"Draft","ProductSegment__c":"IE","SpecialPriceApproveStatus__c":"","BudgetAmount__c":"","Machine_Parts__c":"Machine","Amount":"","CurrencyIsoCode":"CNY","customerType__c":"","IsFirstDecide__c":false,"IE_need_business_approve__c":false,"IE_Discount_Special__c":"","IE_ShippingHandling__c":"","IE_local_cost__c":"","IE_Custom_Price__c":"","IE_Payment_terms__c":"","StockAnswerSummary__c":"","Phase1Date__c":"","InquiryResult__c":"","Phase2Date__c":"","ExpectedOrderDate__c":"","Phase3Date__c":"","ExpectedDeliveryDate__c":"","Order_Date__c":"","DeliveryDate__c":"","InquiryResultOrder__c":"","LeadSource":"","TradeType__c":"Taxation","CustomerSourceIE__c":"","SalesChannel__c":"dealer","Trade_Type_D__c":"Taxation","Dealer__c":"0010l00001Pj768","DealerSalesStaffName__c":"***","DealerService__c":"***","SubDealer__c":"test","Dealer_Sales_Staff_Name_D__c":"***","Dealer_Service_D__c":"***","Competitor_Product__c":"","CompetitorProductCode__c":"","Competitor_Product2__c":"","CompetitorProductCode2__c":"","Competitor_Product3__c":"","CompetitorProductCode3__c":"","Competitor_Product4__c":"","CompetitorProductCode4__c":"","Competitor_Product5__c":"","CompetitorProductCode5__c":"","Competitor_Product6__c":"","CompetitorProductCode6__c":"","Competitor_Product7__c":"","CompetitorProductCode7__c":"","Competitor_Product8__c":"","CompetitorProductCode8__c":"","CompetitorCompany__c":"_0001_","LostAmount__c":"","LostCompetitorProduct__c":"","InquiryResultLost__c":"","LostReason__c":"","LostReasonText__c":"","CancelReason__c":"","InquiryResultCancel__c":"","CancelReasonText__c":"","Have_Computer__c":false,"Remark__c":"","NewInquiryDate__c":"2022-4-8","StageName":"Prospect Created","Probability":"","OppUpdateDateTime__c":"","CloseDate":"2022-4-8","ProductSegmentCompetitor__c":"","IsNew__c":false,"OpportunityAmount_text__c":"","OpportunityLineItem_text__c":"","OpportunityLineItemOT_text__c":"","IsSendEmail__c":true,"IsUpdate__c":false,"OppUpdateDate__c":"","DealerSalesStaffName_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","Dealer_Sales_Staff_Name_D_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","DealerService_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","Dealer_Service_D_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","AWS_Data_Id__c":"961991622629785601"}';
+        NewAndEditOpportunityController.saveOpportunity(qisJson,'avgwshDFcxAS',False);
+        NewAndEditOpportunityController.saveOpportunity(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditOpportunityControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditOpportunityControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditOpportunityControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditOrderController.cls b/force-app/main/default/classes/NewAndEditOrderController.cls
new file mode 100644
index 0000000..24a55f6
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditOrderController.cls
@@ -0,0 +1,46 @@
+/*
+ * Author: Su cuiping
+ * Created Date: 03/01/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: NewAndEditOrderController
+ * 
+ * */
+global class NewAndEditOrderController extends NewAndEditBaseController {
+
+    public String PIPL_Input_Account_Error_Msg{set;get;}
+    public String contactId{set;get;}//For Lookup field
+    public String staticResourceContact {get; set;}
+    public NewAndEditOrderController(ApexPages.StandardController controller){
+        
+    
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Order').getDescribe().fields.getMap().keyset());  
+        
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        //Get Account Id from url param
+    
+        // System.debug('accountType = ' + );
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList);
+        }
+        LookUpOverrideFields.add('EndUserD__c');
+        LookUpOverrideFields.add('EndUser__c');
+        LookUpOverrideFields.add('ShipToContactId');
+        LookUpOverrideFields.add('SpecialDeliveryContact2__c');
+        LookUpOverrideFields.add('SpecialDeliveryContact2_D__c');
+        Init(controller.getRecord());
+        
+        SObject obj = controller.getRecord();
+        if(obj.Id == null){
+            //鍒濆鍖栧姞杞藉��
+            obj.put('OwnerId',UserInfo.getUserId());
+        }
+        //contact淇℃伅锛堟悳绱㈡煡璇uery url鐢級
+        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
+    }
+
+    
+    @RemoteAction
+    global static Response saveOrder(String OrderJson, String transId, Boolean isNew){
+        return save(new Order(), OrderJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditOrderController.cls-meta.xml b/force-app/main/default/classes/NewAndEditOrderController.cls-meta.xml
new file mode 100644
index 0000000..dd61d1f
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditOrderController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditOrderControllerTest.cls b/force-app/main/default/classes/NewAndEditOrderControllerTest.cls
new file mode 100644
index 0000000..30d7388
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditOrderControllerTest.cls
@@ -0,0 +1,19 @@
+@isTest
+public class NewAndEditOrderControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditOrderController() {
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        Order od = TestDataUtility.CreateOrders(1)[0];
+        Test.startTest();
+        ApexPages.StandardController sc =  new ApexPages.StandardController(od);
+        NewAndEditOrderController qis = new NewAndEditOrderController(sc);
+        qis.contactId = 'test';
+        String qisJson = '{"Name":"test123","ApproveStatus__c":"Draft","AccountId":"0010l00001Q1r4e","EndUserD__c":"0030l00000mqae5AAA","SpecialDeliveryAccount_D__c":"0010l00001Q1r4e","TradeMagNo__c":"","CurrencyIsoCode":"CNY","TradeMagCategory__c":"","confirm__c":false,"Status__c":"Active","IsOrderPassed__c":false,"IsSpPassed__c":false,"IsNew__c":false,"CustomerContractPrice__c":"","SAP_Order__c":"","OlympusContractPrices__c":"","SAP_Contract__c":"","PaymentCondition_D__c":"","AlongProduct__c":"","Olympus_Price_BeforeDiscount_D__c":"","EffectiveDate":"2022-4-8","Discount_D__c":"","ServiceFee__c":"","Cost__c":"","ForeignTradeCompany_D__c":"0010l00001Q1Jxd","SpecialDeliveryAccountText__c":"","Shipment_Term_D__c":"","SpecialDeliveryContactText__c":"","Shipment_Term2_D__c":"","Shipping_Address_Text__c":"","ShippedDate__c":"","OrderDate__c":"","InstalledDate__c":"","WarrantyStartDateFromOCN__c":"","CancelReason__c":"","SplitReason__c":"","Split_Approved__c":false,"ChangeReason__c":"","ChangeContent__c":"","Contract_Status__c":"Active","RecordTypeId":"01228000000NJt6","OrderUpdateDateTime__c":"","Status":"Draft","Description":"","PDF_By_Add_Encrypted__c":null,"PDF_By_Tel_Encrypted__c":null,"PDF_Sign_Name_Encrypted__c":null,"PDF_Sign_Title_Encrypted__c":null,"SpecialDeliveryAddress_D_Encrypted__c":null,"SpecialDeliveryAddress_Encrypted__c":null,"PDF_C_CONTACT_Encrypted__c":null,"PDF_C_Consignee_Encrypted__c":null,"PDF_C_FAX_Encrypted__c":null,"PDF_C_TEL_Encrypted__c":null,"PDF_C_THECONSIGNE_Encrypted__c":null,"PDF_F_ContactPerson_Encrypted__c":null,"PDF_F_FAX_Encrypted__c":null,"PDF_F_TEL_Encrypted__c":null,"PDF_S_TEL_Encrypted__c":null,"PDF_N_CONTACT_Encrypted__c":null,"PDF_N_FAX_Encrypted__c":null,"PDF_N_NotifyParty_Encrypted__c":null,"SpecialDeliveryContact_D_Encrypted__c":null,"SpecialDeliveryContact_Encrypted__c":null,"Shipping_Address_Text_Encrypted__c":"","SpecialDeliveryContactText_Encrypted__c":"","SpecialDeliveryPhone_D_Encrypted__c":null,"SpecialDeliveryPhone_Encrypted__c":null,"PDF_By_Add__c":null,"PDF_By_Tel__c":null,"PDF_Sign_Name__c":null,"PDF_Sign_Title__c":null,"SpecialDeliveryAddress_D__c":null,"SpecialDeliveryAddress__c":null,"PDF_C_CONTACT__c":null,"PDF_C_Consignee__c":null,"PDF_C_FAX__c":null,"PDF_C_TEL__c":null,"PDF_C_THECONSIGNE__c":null,"PDF_F_ContactPerson__c":null,"PDF_F_FAX__c":null,"PDF_S_TEL__c":null,"PDF_N_CONTACT__c":null,"PDF_N_NotifyParty__c":null,"SpecialDeliveryContact_D__c":null,"SpecialDeliveryContact__c":null,"SpecialDeliveryPhone_D__c":null,"SpecialDeliveryPhone__c":null,"AWS_Data_Id__c":"962013895902363649"}';
+        NewAndEditOrderController.saveOrder(qisJson,'avgwshDFcxAS',False);
+        NewAndEditOrderController.saveOrder(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditOrderControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditOrderControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditOrderControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditQuotesController.cls b/force-app/main/default/classes/NewAndEditQuotesController.cls
new file mode 100644
index 0000000..84e3326
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditQuotesController.cls
@@ -0,0 +1,42 @@
+/**
+ * @description       : 
+ * @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+ * @group             : 
+ * @last modified on  : 03-04-2022
+ * @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+**/
+global class NewAndEditQuotesController extends NewAndEditBaseController {
+    
+    public String PIPL_Input_Account_Error_Msg{set;get;}
+    public String contactId{set;get;}//For Lookup field
+    public String staticResourceContact {get; set;}
+
+    public NewAndEditQuotesController(ApexPages.StandardController controller){
+        
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Quotes__c').getDescribe().fields.getMap().keyset());  
+        
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        //Get Account Id from url param
+    
+        // System.debug('accountType = ' + );
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList);
+        }
+        LookUpOverrideFields.add('CONTACT_NAME__c');
+        Init(controller.getRecord());
+        //娣诲姞椤�
+        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
+
+        SObject obj = controller.getRecord();
+        if(obj.Id == null){
+             //鍒濆鍖栧姞杞藉��
+             obj.put('OwnerId',UserInfo.getUserId());
+        }
+        //contact淇℃伅锛堟悳绱㈡煡璇uery url鐢級
+        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
+    }
+    @RemoteAction
+    global static Response saveQuotes(String QuotesJson, String transId, Boolean isNew){
+        return save(new Quotes__c(), QuotesJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditQuotesController.cls-meta.xml b/force-app/main/default/classes/NewAndEditQuotesController.cls-meta.xml
new file mode 100644
index 0000000..dd61d1f
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditQuotesController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditQuotesControllerTest.cls b/force-app/main/default/classes/NewAndEditQuotesControllerTest.cls
new file mode 100644
index 0000000..c224661
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditQuotesControllerTest.cls
@@ -0,0 +1,20 @@
+@isTest
+public class NewAndEditQuotesControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditQuotesController() {
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        Quotes__c uf = TestDataUtility.CreateQuotes(1)[0];
+
+        Test.startTest();
+        ApexPages.StandardController con =  new ApexPages.StandardController(uf);
+        NewAndEditQuotesController qis = new NewAndEditQuotesController(con);
+        qis.contactId = 'Test';
+        String qisJson = '{"Name":"test123","CurrencyIsoCode":"CNY","TOTAL_TRANSACTION_ITEM_WEIGHT_KGS__c":"","InvalidData__c":false,"TOTAL__c":"","VERTICAL_MARKET_SEGMENT_SO__c":"","TAX_RATE__c":"","THROW_MESSAGE__c":false,"TERMS_OVERRIDE__c":false,"STATUS__c":"","TERMS__c":"","SELECT_MESSAGE__c":"","TAX_OVERRIDE__c":false,"REVISION_NEEDED__c":"","TAX_ID__c":"","SALES_TEAM_AUTO_ASSIGN_ON_SAVE__c":false,"TAX_CODE__c":"","RATE__c":"","TAX__c":"","QUOTE_TITLE__c":"","SWO_NUMBER__c":"","PRODUCT_SEGMENT__c":"","SUBTOTAL__c":"","PROBABILITY__c":"","SHIP_VIA__c":"","PO__c":"","SHIP_TO_SELECT__c":"","PKMS_PO_FOR_RECEIPT__c":"","SHIP_TO_ENTITY_USE_CODE__c":"","ORDER_TYPE__c":"","SHIP_TO__c":"","NSN__c":"","SHIPPING_TAX_RATE__c":"","notSaveEmail__c":true,"SHIPPING_TAX_CODE__c":"","NO_CHARGE_TYPE__c":"","SHIPPING_COST__c":"","IS_SELLER_IMPORTER_OF_RECORD__c":false,"SHIPPING_CARRIER__c":"","INITIATE_APPROVAL_ROUTING__c":false,"SALES_TEAM_AUTO_ASSIGNMENT_OVERRIDE__c":false,"GSA_ORDER__c":false,"RMA_NOTES__c":"","FDA_REPORT_COMPLETE__c":false,"QuotesType__c":"","EST_EXTENDED_COST__c":"","DISCOUNT_STATUS_ROUTING__c":"","OPPORTUNITY__c":"","DISCOUNT__c":"","ONLINE_BILLING_ADDRESS__c":"","BILLING_SCHEDULE__c":"","ONLINE_BILLING__c":false,"BILL_TO_ENTITY_USE_CODE__c":"","LOCATION__c":"","CATEGORY_1_INDUSTRY_SO__c":"","LEAD_TIME__c":"","COLLECTION_STATUS__c":"","LEAD_SOURCE__c":"","INVOICE_MESSAGING__c":"","CONTRACT_NAME__c":"","INCOTERM__c":"","CURRENCY__c":"","GOVERNMENT_ORDER__c":false,"DATE__c":"","EXPIRES__c":"","DISCOUNT_ITEM__c":"","EXP_CLOSE__c":"","EST_GROSS_PROFIT_PERCENT__c":"","EST_GROSS_PROFIT__c":"","DISCOUNT_WORKFLOW_TYPE__c":"","DISCOUNT_STATUS__c":"","BILL_TO__c":"","BILL_TO_SELECT__c":"","CATEGORY_2_USE_SO__c":"","CONTACT_PHONE__c":"","CUSTOMER_MESSAGE__c":"","BILL_TO_Encrypted__c":"","SHIP_TO_Encrypted__c":"","AWS_Data_Id__c":"961999748590469121"}';
+        NewAndEditQuotesController.saveQuotes(qisJson,'avgwshDFcxAS',False);
+        NewAndEditQuotesController.saveQuotes(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditQuotesControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditQuotesControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditQuotesControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditRepairController.cls b/force-app/main/default/classes/NewAndEditRepairController.cls
new file mode 100644
index 0000000..7397fd5
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditRepairController.cls
@@ -0,0 +1,38 @@
+/**
+ * @description       : 
+ * @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+ * @group             : 
+ * @last modified on  : 03-04-2022
+ * @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+**/
+global class NewAndEditRepairController extends NewAndEditBaseController {
+	
+    public Contact contactAWSDataId {get; set;}
+    public Repair__c repair{get; set;}
+    public String staticResourceContact {get; set;}
+    public NewAndEditRepairController(ApexPages.StandardController controller){
+        
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Repair__c').getDescribe().fields.getMap().keyset());  
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        //Get Account Id from url param
+    
+        // System.debug('accountType = ' + );
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList);
+        }
+        Init(controller.getRecord());
+
+        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
+
+        SObject obj = controller.getRecord();
+        System.debug('obj.Id = ' + obj.Id);
+        repair = [Select Id, ContactD__c From Repair__c WHERE ID =:obj.Id];
+        System.debug('repair.ContactD__c = ' + repair.ContactD__c);
+        contactAWSDataId = [SELECT ID, AWS_Data_Id__c FROM Contact WHERE ID =:repair.ContactD__c];
+        System.debug('contactAWSDataId.AWS_Data_Id__c = ' + contactAWSDataId.AWS_Data_Id__c );
+    }
+    @RemoteAction
+    global static Response saveRepair(String RepairJson, String transId, Boolean isNew){
+        return save(new Repair__c(), RepairJson, transId, isNew);
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditRepairController.cls-meta.xml b/force-app/main/default/classes/NewAndEditRepairController.cls-meta.xml
new file mode 100644
index 0000000..dd61d1f
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditRepairController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditRepairControllerTest.cls b/force-app/main/default/classes/NewAndEditRepairControllerTest.cls
new file mode 100644
index 0000000..a24ff95
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditRepairControllerTest.cls
@@ -0,0 +1,25 @@
+@isTest
+public class NewAndEditRepairControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+        
+    }
+    static testMethod void NewAndEditRepairController() {
+        Contact con = TestDataUtility.CreateContacts(1)[0];
+        con.AWS_Data_Id__c = '1234567890';
+        update con;
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        Repair__c rep = TestDataUtility.CreateRepairs(1)[0];
+        rep.ContactD__c = con.Id;
+        update rep;
+        Test.startTest();
+        ApexPages.StandardController sc =  new ApexPages.StandardController(rep);
+        NewAndEditRepairController qis = new NewAndEditRepairController(sc);
+        
+        String qisJson = '{"Name":"test123"}';
+        NewAndEditRepairController.saveRepair(qisJson,'avgwshDFcxAS',False);
+        NewAndEditRepairController.saveRepair(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditRepairControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditRepairControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditRepairControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditUserFaultInfoController.cls b/force-app/main/default/classes/NewAndEditUserFaultInfoController.cls
new file mode 100644
index 0000000..44991ad
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditUserFaultInfoController.cls
@@ -0,0 +1,40 @@
+/*
+ * Author: Yanan Chen
+ * Created Date: 02/28/2022
+ * Purpose: Utility class for describe layouts
+ * Test Class: NewAndEditUserFaultInfoController 
+ * History: 
+ *      02/28/2022 - Yanan Chen - Initial Code.
+ * 
+ * */
+global class NewAndEditUserFaultInfoController extends NewAndEditBaseController {
+    public String PIPL_Input_Account_Error_Msg{set;get;}
+    public String contactId{set;get;}//For Lookup field
+    public String staticResourceContact {get; set;}
+    public NewAndEditUserFaultInfoController(ApexPages.StandardController controller){
+        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('User_FaultInfo__c').getDescribe().fields.getMap().keyset());  
+        // Add fields to controller. This is to avoid the SOQL error in visualforce page
+        if(!Test.isRunningTest()){
+            controller.addFields(fieldList); // contact lookup
+        }
+        LookUpOverrideFields.add('CONTACT__c');
+        Init(controller.getRecord());
+        //娣诲姞椤�
+        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
+        SObject obj = controller.getRecord();
+        if(obj.Id == null){
+            //鍒濆鍖栧姞杞藉��
+            obj.put('OwnerId', UserInfo.getUserId());
+        }
+        //contact淇℃伅锛堟悳绱㈡煡璇uery url鐢級
+        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
+    }
+
+    
+    @RemoteAction
+    global static Response saveUserFaultInfo(String sobJson, String transId, Boolean isNew){
+        system.debug('JSON Payload:'+sobJson);
+        return save(new User_FaultInfo__c(), sobJson, transId, isNew);
+    }
+
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditUserFaultInfoController.cls-meta.xml b/force-app/main/default/classes/NewAndEditUserFaultInfoController.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditUserFaultInfoController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewAndEditUserFaultInfoControllerTest.cls b/force-app/main/default/classes/NewAndEditUserFaultInfoControllerTest.cls
new file mode 100644
index 0000000..0657dc7
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditUserFaultInfoControllerTest.cls
@@ -0,0 +1,20 @@
+@isTest
+public class NewAndEditUserFaultInfoControllerTest {
+    @TestSetup
+    static void makeData(){
+        TestDataUtility.CreatePIPolicyConfiguration();
+    }
+    static testMethod void NewAndEditLoanerApplicationController() {
+        Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreateMetaDataUtilityHttpMock());
+        loaner_application__c la = TestDataUtility.Createloanerapplications(1)[0];
+
+        Test.startTest();
+        ApexPages.StandardController con =  new ApexPages.StandardController(la);
+        NewAndEditUserFaultInfoController qis = new NewAndEditUserFaultInfoController(con);
+        
+        String qisJson = '{"Name":"test123","QIS_Status__c":"鑽夋涓�","QIS_pre__c":"000000000000000","consumable__c":"01t1m000001QyDa","Cancel_QIS_Reason__c":"_u0001_","RecordTypeId":"01210000000RLWc","Repair__c":"a0J1m000001nZzf","RejectReason__c":"","Managementtext__c":"","OCSMAdministrativeReportStatus__c":"鏃犻渶鎶ュ憡","MBC_AwareDate__c":"2022/03/29","Aware_date__c":"2022/03/29","Old_Repair_Name__c":"","isLendRental__c":false,"next_action__c":"","RC_problem_not_found__c":false,"Salesdepartment_Text__c":"","OCM_Repair_Mail1__c":"","Hospital__c":"0011m00000XlvHh","Account_State__c":"","Department_Class__c":"0011m00000SP4Mp","OwnerId":"0051m0000030e0QAAQ","Hospital_Department__c":"0011m00000SP4TB","Responsible_Person_HP__c":"***","Caller_phone__c":"***********","capital_or_consumable__c":"鑰楁潗","contract_number_ET_text__c":"","nonyushohin__c":"000000000000000","InstallDate_text__c":"","usage_frequence__c":"1","cleanning__c":"1","cds_methods__c":"鎵嬪姩","disinfection__c":"","sterlization__c":"","Faliour_date__c":"2022/03/29","Trable_occur_daY_collect__c":"2022/03/29","DelayReportReason__c":"","failuer_situation__c":"鍒拌揣楠屾敹","failuer_situationSelect__c":"","problem_detail__c":"test","Damage_For_Doc_Or_Pat__c":"","Relation_With_The_Problem__c":"","Report_For_Goz__c":"","Which_Project__c":"","Opera_Name__c":"","BreakORFallOff__c":"","Is_Used_For_The_Opera__c":"","Set_usage_product__c":"","Comment__c":"test","AfterFailureInformation__c":"","Delay15Min__c":"","InformationFrom__c":"","FailureQInHospital__c":"","accsessary_detail__c":"","shipping_to_QIS_dept_day__c":"","ASReportedCode__c":"","QIS_ConfirmationDate__c":"","PAE_Determine__c":"","ASReportedCodeAC__c":"","OCSM_RC_CordingDate__c":"","PAE_DetermineAC__c":"","Complaint_Number__c":"","OSH_ConfirmationDate__c":"","if_QIS_Allowed__c":"","NotAllowedReason__c":"","OSHRAConfirmDate__c":"","isAE_Profile__c":"","isPAE_Profile__c":"","MDR_information__c":"","MDR_detail__c":"","CFDA_No_Hand__c":"","ProduceCompany_hand__c":"","Receive_Date_Day__c":"2022/03/29","OSHRecievedDate__c":"","QIS_Submit_day__c":"","QIS_OSH_answerdate__c":"","OCM_RC_RecievedDate__c":"","QIS_Complete_Day__c":"","QIS_Reply_day__c":"","QIS_cancel_date__c":"","QIS_Cancel_Submit_day__c":"","Daily_Report__c":"000000000000000","Generation_Source__c":"","Source_OnCall__c":"000000000000000","QisSubOrder__c":"000000000000000","AsyncData__c":false,"ETQ_UPLOAD_STATUS__c":"","AWS_Interface_Time__c":"2022/03/29 13:38","ETQ_UPLOAD_MESSAGE__c":"","INTERFACE_RECORD_ID__c":"","ET_QIS_SEND_EMAIL1__c":"","ET_QIS_SEND_EMAIL2__c":"","problem_detail_photo__c":"","Caller_phone_Encrypted__c":"415f2dab7eb6b2a866e02d823080a845","Responsible_Person_HP_Encrypted__c":"dcce196c4cfc273a83777852ddd486ab","AWS_Data_Id__c":"958360820671053825"}';
+        NewAndEditUserFaultInfoController.saveUserFaultInfo(qisJson,'avgwshDFcxAS',False);
+        NewAndEditUserFaultInfoController.saveUserFaultInfo(qisJson,'avgwshDFcxAS',True);
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/NewAndEditUserFaultInfoControllerTest.cls-meta.xml b/force-app/main/default/classes/NewAndEditUserFaultInfoControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/NewAndEditUserFaultInfoControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/NewOpportunityController.cls b/force-app/main/default/classes/NewOpportunityController.cls
index 5e30945..4ada386 100644
--- a/force-app/main/default/classes/NewOpportunityController.cls
+++ b/force-app/main/default/classes/NewOpportunityController.cls
@@ -16,6 +16,9 @@
 
     public Boolean isIEDealer{get; set; }
 
+    public String staticResource {get; set;}
+    public String opportunityAWSDataId{get; set;}
+
     public NewOpportunityController() {
         baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
         String path = URL.getCurrentRequestUrl().getPath();
@@ -94,6 +97,7 @@
             opp.Dealer__c = dealerId;
         }
 
+        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Opportunity'));
         return null;
     }
 
diff --git a/force-app/main/default/classes/NewReplacementOpportunityController.cls b/force-app/main/default/classes/NewReplacementOpportunityController.cls
index da321dc..80c7ece 100644
--- a/force-app/main/default/classes/NewReplacementOpportunityController.cls
+++ b/force-app/main/default/classes/NewReplacementOpportunityController.cls
@@ -13,6 +13,8 @@
 	public String rtUrl { get; set; }
 
 	public String ProductSegment { get; set; }
+	public String staticResource {get; set;}
+	public String opportunityAWSDataId{get; set;}
 
 	public NewReplacementOpportunityController() {
 		baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
@@ -70,7 +72,7 @@
 		if (UserInfo.getUserType() == 'PowerPartner' && acc.ProductSegment__c != 'BS') {
 			opp.Dealer__c = dealerId;
 		}
-
+        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Opportunity'));
 		return null;
 	}
 
diff --git a/force-app/main/default/classes/PIHelperTest.cls b/force-app/main/default/classes/PIHelperTest.cls
index 8b1bb00..52ac40a 100644
--- a/force-app/main/default/classes/PIHelperTest.cls
+++ b/force-app/main/default/classes/PIHelperTest.cls
@@ -1,3 +1,45 @@
-public class PIHelperTest {
-
+@isTest
+private class PIHelperTest {
+    static testMethod void getPIIntegrationInfo() {
+    	TestDataUtility.CreatePIPolicyConfiguration('Contact');
+    	String sobjectType = 'Contact';
+    	List<AWS_Integration_Info__mdt> awsConfigurationList = [SELECT App_Id__c,Token_URL__c,App_Secret__c,Host_URL__c FROM AWS_Integration_Info__mdt  WHERE DeveloperName = 'AWS_Default_Configuration'];
+    	Test.startTest();
+        PIHelper.getPIIntegrationInfo(sobjectType);
+        Test.stopTest();
+    }
+    static testMethod void saveTransLog() {
+    	Test.startTest();
+    	PIHelper.saveTransLog('module','vadsjngrqvjca','avgwshDFcxAS', 'DSAGSFBQdfdsoav','test','0','testmsg');
+    	Test.stopTest();
+    }
+    /*static testMethod void confirmTrans() {
+    	Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreatePIHelperHttpMock());
+    	Test.startTest();
+    	List<PIHelper.idList> idList = new List<PIHelper.idList>();
+    	PIHelper.idList pid = new PIHelper.idList();
+    	pid.awsId = 'vadsjngrqvjca';
+    	pid.sfRecordId = 'avgwshDFcxAS';
+    	idList.add(pid);
+    	PIHelper.confirmTrans('module',1,'vadsjngrqvjca' ,'avgwshDFcxAS' ,'DSAGSFBQdfdsoav','https://sfpi-mebg-test.olympuschina.com/api/contact/insert',idList);
+    	Test.stopTest();
+    }*/
+    /*static testMethod void confirmFileTrans() {
+    	Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreatePIHelperHttpMock());
+    	Test.startTest();
+    	PIHelper.confirmFileTrans('module',1,'vadsjngrqvjca' ,'avgwshDFcxAS','DSAGSFBQdfdsoav','https://sfpi-mebg-test.olympuschina.com/api/contact/insert');
+    	Test.stopTest();
+    }*/
+	/*static testMethod void insertConfirmTrans() {
+    	Test.setMock(HttpCalloutMock.class, new TestDataUtility.CreatePIHelperHttpMock());
+    	Test.startTest();
+    	List<PIHelper.idList> idList = new List<PIHelper.idList>();
+    	PIHelper.idList pid = new PIHelper.idList();
+    	pid.awsId = 'vadsjngrqvjca';
+    	pid.sfRecordId = 'avgwshDFcxAS';
+    	idList.add(pid);
+    	PIHelper.insertConfirmTrans('module',1,'vadsjngrqvjca' ,'avgwshDFcxAS' ,0,'https://sfpi-mebg-test.olympuschina.com/api/contact/insert',idList);
+    	Test.stopTest();
+    }*/
+	
 }
\ No newline at end of file
diff --git a/force-app/main/default/classes/SearchContactController.cls b/force-app/main/default/classes/SearchContactController.cls
new file mode 100644
index 0000000..f657e3b
--- /dev/null
+++ b/force-app/main/default/classes/SearchContactController.cls
@@ -0,0 +1,68 @@
+/*
+ * Author: Bubba Li
+ * Created Date: 02/08/2022
+ * Purpose: SearchContactController
+ * Test Class: SearchContactController
+ * History: 
+ *      02/08/2022 - Bubba Li - Initial Code.
+ * 
+ * */
+public without sharing class SearchContactController {
+    public String searchKeyWord{set;get;}
+    public String staticResource {get; set;}
+    public String contactAWSIds {set;get;}
+    public String contactsInfo {set;get;}
+    public String PIPL_Search_Contact_Label{set;get;}
+    public SearchContactController() {
+        String accountId = ApexPages.currentPage().getParameters().get('accountId');
+        PIPL_Search_Contact_Label = Label.PIPL_Search_Contact_Label;
+        //1. Query Contact by accountId
+        List<Contact> conList = new List<Contact>();
+        system.debug('Account Id from Front-end:'+accountId);
+        if(String.isNotBlank(accountId) && String.isNotEmpty(accountId)){
+            String accountIdStr = '';
+            String[] accountIds = accountId.split(',');
+            List<String> accountIdList = new List<String>();
+            for(String s : accountIds){
+                accountIdList.add(s);
+            }
+            conList = new List<Contact>([select Id,AWS_Data_Id__c from Contact where AccountId in:accountIdList and AWS_Data_Id__c!='']);
+            System.debug('conList:'+conList);
+        }        
+        //2. Prepare the Contact Info
+        Map<String,Contact> awsIdToContactMap = new Map<String,Contact>();
+        List<String> conAWSIds = new List<String>();
+        for(Contact con:conList){
+            conAWSIds.add(con.AWS_Data_Id__c);
+            awsIdToContactMap.put(con.AWS_Data_Id__c,con);
+        }
+        contactsInfo = JSON.serialize(awsIdToContactMap);
+        contactAWSIds = JSON.serialize(conAWSIds);
+        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));        
+    }
+
+    @RemoteAction
+    public static Response searchContacts(String awsContactIds) {
+        Response resp = new Response();
+        resp.status = 'fail';
+        if(String.isBlank(awsContactIds)||String.isEmpty(awsContactIds)){
+            return resp;
+        }
+        List<String> awsDataIds = (List<String>) JSON.deserialize(awsContactIds, List<String>.class);
+        Map<String,Contact> awsIdToContactMapTemp = new Map<String,Contact>();
+        List<Contact> conListTemp = new List<Contact>([select Id,AWS_Data_Id__c from Contact where AWS_Data_Id__c in:awsDataIds]);
+        for(Contact con:conListTemp){
+            awsIdToContactMapTemp.put(con.AWS_Data_Id__c,con);
+        }
+        if(awsIdToContactMapTemp.keySet().size()>0){
+            resp.status = 'success';
+            resp.message = JSON.serialize(awsIdToContactMapTemp);
+        }
+        return resp;
+    }
+
+    public class Response{
+        public String message{set;get;}
+        public String status{set;get;}
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/SearchContactController.cls-meta.xml b/force-app/main/default/classes/SearchContactController.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/SearchContactController.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/SearchContactControllerTest.cls b/force-app/main/default/classes/SearchContactControllerTest.cls
new file mode 100644
index 0000000..092f899
--- /dev/null
+++ b/force-app/main/default/classes/SearchContactControllerTest.cls
@@ -0,0 +1,23 @@
+@isTest
+private class SearchContactControllerTest {
+    @TestSetup
+    static void makeData(){
+        
+    }
+    static testMethod void testMethod1() {
+        TestDataUtility.CreatePIPolicyConfiguration('Contact');
+        Contact con = TestDataUtility.CreateContacts(1)[0];
+        con.AWS_Data_Id__c = 'davdsvgrqcx';
+        update con;
+        List<String> awsList = new List<String>();
+        awsList.add(con.AWS_Data_Id__c);
+        String awsListJson = JSON.serialize(awsList);
+
+        String url = ApexPages.currentPage().getParameters().put('accountId',con.AccountId);
+        Test.startTest();
+        SearchContactController scc = new SearchContactController();
+        SearchContactController.searchContacts(awsListJson);
+        scc.searchKeyWord = 'test';
+        Test.stopTest();
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/SearchContactControllerTest.cls-meta.xml b/force-app/main/default/classes/SearchContactControllerTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/SearchContactControllerTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/SoqlHelper.cls b/force-app/main/default/classes/SoqlHelper.cls
new file mode 100644
index 0000000..446706f
--- /dev/null
+++ b/force-app/main/default/classes/SoqlHelper.cls
@@ -0,0 +1,136 @@
+public  class SoqlHelper {
+
+    public static string DistinctQueryFields(string sql)
+    {
+        string query_fields = sql;
+        if (query_fields == null) {
+            return null;
+        }
+        query_fields = query_fields.trim();
+        Integer sel_i = query_fields.indexOfIgnoreCase('select ');
+        string sel = 'select ';
+        
+        if ( sel_i < 0) {
+            sel = '';
+        }
+
+        string whe = '';
+        Integer whe_i = query_fields.indexOfIgnoreCase(' from ');
+        if ( whe_i >= 0) {
+            whe = query_fields.substring(whe_i);
+        }
+        string query = query_fields.substring(sel_i < 0 ? 0 : sel.length(), whe_i < 0 ? query_fields.length() : whe_i);
+        Set<string> ss = new Set<string>();
+        for(string f : query.split(',')){
+            string s = f.trim().toLowerCase();
+            //System.debug('s='+s);
+            ss.add(s);
+        }
+
+        return sel + QueryFields(ss) + whe;
+
+    }
+    
+    public static string WId(string wid){
+        return '\'' + wid + '\'';
+    }
+   
+    public static string QueryFields(Set<string> lo){
+        return QueryFields(new List<string>(lo));
+    }
+    
+    public static string QueryFields(List<object> lo){
+        return string.join(lo, ',');
+    }
+
+    public static string ToInCondition(List<AggregateResult> lar ,string key)
+    {
+        if(lar==null || lar.size() == 0)
+        {
+            return null;
+        }
+        
+        string ss = ' ( ';
+        boolean b = true;
+        for(AggregateResult ar : lar)
+        {
+            if(ar.get(key)==null)continue;
+            if( b )
+            {
+                b = false;
+                ss += '\''+ar.get(key)+'\'';
+            }
+            else
+            {
+                ss += ',\''+ar.get(key)+'\'';
+            }
+            
+        }
+        ss+=') ';
+        return ss;
+    }
+    
+    public static string ToInCondition(Set<string> so){
+        return ToInCondition(new List<string>(so));
+    }
+    
+    public static string ToInCondition(List<object> lo)
+    {
+        Set<object> so = new Set<object>(lo);
+        lo = new List<object>(so);
+        return '(\''+ string.join(lo, '\',\'')+'\')';
+    }
+    
+    public static void InsertList(List<Sobject> so_list)
+    {
+        if(so_list == null || so_list.size() == 0)return;
+        insert so_list;
+    }
+    
+    public static void UpdateList(List<Sobject> so_list)
+    {
+        if(so_list == null || so_list.size() == 0)return;
+        update so_list;
+    }
+    
+    /*public static Map<string,Database.UpsertResult> UpsertList(List<Sobject> so_list, Schema.SObjectField field)
+    {
+        Map<string,Database.UpsertResult> mid = new Map<string,Database.UpsertResult>();
+        if(so_list == null || so_list.size() == 0)return mid;
+        List<Database.UpsertResult> urList2 = Database.upsert( so_list, field, false);
+        
+        Set<String> accBasicRecordIdSet = new Set<String>();
+        integer index = 0;
+        string errorString = '';
+        string field_str = field.getDescribe().getName();
+        for(Database.UpsertResult ur : urList2){
+            if(!ur.IsSuccess()){
+                object fv = so_list[index].get(field_str);
+                
+                mid.put(fv+'',ur);
+                errorString = '';
+                for(Database.Error errs: ur.getErrors()){
+                    errorString += errs.getMessage() + ';';
+                }
+                //LogHelper.CreateRunTimeLog('runtime error', errorString, false, fv+'');
+            }
+            index++;
+        }
+        return mid;
+    }*/
+    
+    public static void DeleteList(List<Sobject> so_list)
+    {
+        if(so_list == null || so_list.size() == 0)return;
+        delete so_list;
+    }
+
+
+    @future
+    public static void DeleteListAsync(List<Id> id_list)
+    {
+        if(id_list == null || id_list.size() == 0)return;
+        Database.delete(id_list);
+    }
+    
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/SoqlHelper.cls-meta.xml b/force-app/main/default/classes/SoqlHelper.cls-meta.xml
new file mode 100644
index 0000000..dd61d1f
--- /dev/null
+++ b/force-app/main/default/classes/SoqlHelper.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/SoqlHelperTest.cls b/force-app/main/default/classes/SoqlHelperTest.cls
new file mode 100644
index 0000000..17195b3
--- /dev/null
+++ b/force-app/main/default/classes/SoqlHelperTest.cls
@@ -0,0 +1,46 @@
+@isTest
+private class SoqlHelperTest {
+    static testMethod void testMethod1() {
+    	String sql = 'SELECT Id,Name FROM Contact WHERE Name != null Limit 1';
+    	Account accupdate = TestDataUtility.CreateAccounts(1)[0];
+    	accupdate.Name = 'update1';
+    	List<Account> updateAccList = new List<Account>();
+
+    	//Profile p = [select Id from Profile where Name = 'System Administrator'];
+        Profile p = [select Id from Profile where Name = 'Chatter Free User'];
+    	User hpOwner = new User( LastName = 'TestUserA', FirstName = 'owner', Alias = 'hp', CommunityNickname = 'hpOwner', Email = 'olympus_hpowner@sunbridge.com', Username = 'olympus_hpowner@sunbridge.com', IsActive = true, EmailEncodingKey = 'ISO-2022-JP', TimeZoneSidKey = 'Asia/Tokyo', LocaleSidKey = 'ja_JP', LanguageLocaleKey = 'ja', ProfileId = p.id);
+    	List<User> userList = new List<User>();
+
+    	userList.add(hpOwner);
+
+    	Contact con = TestDataUtility.CreateContacts(1)[0];
+    	List<String> conidList = new List<String>();
+    	conidList.add(con.Id); 
+
+        Set<String> strSet = new Set<String>();
+        strSet.add('test1');
+        strSet.add('test2');
+        
+        List<AggregateResult> lartest = new List<AggregateResult>();
+        //Repair__c repair1 = new Repair__c();
+		//repair1.Name = 'test';
+        //repair1.RecordTypeId = '0120K000000wOGcQAM';
+		//insert repair1;
+        lartest = [select count(Id) total from Repair__c where RecordTypeId != null group by RecordTypeId];
+        system.debug('lartest:'+lartest);
+        String key = 'test';
+        Test.startTest();
+        //ToInCondition
+        //UpsertList
+        SoqlHelper.ToInCondition(strSet);
+        SoqlHelper.ToInCondition(lartest, key);
+        SoqlHelper.DistinctQueryFields(sql);
+        SoqlHelper.WId(sql);
+        SoqlHelper.InsertList(userList);
+        SoqlHelper.UpdateList(updateAccList);
+        SoqlHelper.DeleteList(updateAccList);
+        SoqlHelper.DeleteListAsync(conidList);
+        Test.stopTest();
+
+    }
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/SoqlHelperTest.cls-meta.xml b/force-app/main/default/classes/SoqlHelperTest.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/SoqlHelperTest.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/TSRepairController.cls b/force-app/main/default/classes/TSRepairController.cls
index 89300ae..d86c91b 100644
--- a/force-app/main/default/classes/TSRepairController.cls
+++ b/force-app/main/default/classes/TSRepairController.cls
@@ -6,6 +6,7 @@
     public String repairId {get; set;}
     public TS_Repair__c tsr {get; set;}
 
+
     public String datestr;
 
     public Integer num {get; set{ num = value;}} //娣诲姞浜у搧鏃朵娇鐢�
@@ -44,6 +45,9 @@
 
     public Map<String, List<BusinessActivity__c>> businessActivityListToMap;
 
+     
+    
+
     //  鐜嬮箯浼熷畾涔夊彉閲忓紑濮�
     // 鍓嶅彴鐐瑰嚮鎸夐挳淇敼鐘舵��
     public String status {get; set;}
@@ -51,6 +55,14 @@
     //onclickType=0鏃跺彧鑳界偣鍑昏崏妗堬紝鐢宠锛沷nclickType=1鏃跺彧鑳界偣鍑婚┏鍥烇紝鎵瑰噯
     public String onclickType {get; set;} //onclickType=0鏃�
     //  鐜嬮箯浼熷畾涔夊彉閲忕粨鏉�
+
+    
+    // Add by zhj for PIPL 20220309 Start
+    public String contactId{set;get;}//For Lookup field
+    public String staticResourceContact {get; set;}
+    public String contactNameValue{set;get;}
+    public String contactIdValue{set;get;}
+    // Add by zhj for PIPL 20220309 End
 
     public TSRepairController() {
         baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
@@ -75,6 +87,7 @@
         datestr =  System.currentPageReference().getParameters().get('date');
 
     }
+
 
     public PageReference init() {
         errorMessageMap  = new Map<String, List<String>>();
@@ -134,7 +147,8 @@
             }
 
         }
-
+        //contact淇℃伅锛堟悳绱㈡煡璇uery url鐢級
+        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
         return null;
     }
 
@@ -692,6 +706,7 @@
             updateUserFaultInfo.UserFaultInfoNextService__c = ba.BusinessANextService__c ;//涓嬫鏈嶅姟鏃堕棿
             updateUserFaultInfo.UFAccount__c = ba.BusinessAAccount__c ;//瀹㈡埛鍗曚綅(鏌ユ壘)
             updateUserFaultInfo.UserFaultInfoCustomerUnit__c = ba.BusinessACustomerUnit__c ;//瀹㈡埛鍗曚綅(鏂囨湰)
+            if(String.isNotBlank(contactIdValue)&&String.isNotEmpty(contactIdValue)){}
             updateUserFaultInfo.UFContact__c = ba.BusinessAContact__c ;//鑱旂郴浜�
             updateUserFaultInfo.UFPhone__c = ba.BusinessAPhone_F__c ;//鑱旂郴鐢佃瘽
 
diff --git a/force-app/main/default/classes/TestDataUtility.cls b/force-app/main/default/classes/TestDataUtility.cls
new file mode 100644
index 0000000..77ad44e
--- /dev/null
+++ b/force-app/main/default/classes/TestDataUtility.cls
@@ -0,0 +1,649 @@
+@isTest
+public class TestDataUtility {
+    public static void CreatePIPolicyConfiguration(){
+        CreatePIPolicyConfigurations(null);
+    }
+
+    public static void CreatePIPolicyConfiguration(string sobject_name){
+        CreatePIPolicyConfigurations(new string []{sobject_name});
+    }
+
+    public static void CreatePIPolicyConfigurations(List<String> sobjectTypes){
+        String piJson = '[{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XWzKAAW"},"Sobject_Type__c":"SWO__c","New_URL__c":"/ssbgapi/swo/insert","Read_URL__c":"/ssbgapi/swo/query","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/swo/undelete","Id":"a0x0l000001XWzKAAW","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XTYDAA4"},"Sobject_Type__c":"User_FaultInfo__c","New_URL__c":"/ssbgapi/userfaultinfo/insert","Read_URL__c":"/ssbgapi/userfaultinfo/query","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/userfaultinfo/undelete","Id":"a0x0l000001XTYDAA4","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XVeVAAW"},"Sobject_Type__c":"Order","New_URL__c":"/ssbgapi/order/insert","Read_URL__c":"/ssbgapi/order/query","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/order/undelete","Id":"a0x0l000001XVeVAAW","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XX2TAAW"},"Sobject_Type__c":"loaner_application__c","New_URL__c":"/ssbgapi/loanerapplication/insert","Read_URL__c":"/ssbgapi/loanerapplication/query","Search_URL__c":"/ssbgapi/loanerapplication/search","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/loanerapplication/undelete","Id":"a0x0l000001XX2TAAW","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XozZAAS"},"Sobject_Type__c":"SBG027","New_URL__c":"/ssbgapi/sbg/027","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Id":"a0x0l000001XozZAAS","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XxDXAA0"},"Sobject_Type__c":"Mail","New_URL__c":"/ssbgapi/mail/sendEmail","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Id":"a0x0l000001XxDXAA0","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XWzeAAG"},"Sobject_Type__c":"Quotes__c","New_URL__c":"/ssbgapi/quotes/insert","Read_URL__c":"/ssbgapi/quotes/query","Search_URL__c":"/ssbgapi/quotes/search","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/quotes/undelete","Id":"a0x0l000001XWzeAAG","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XswlAAC"},"Sobject_Type__c":"Mail_Merge__c","New_URL__c":"/ssbgapi/mail/sendEmail","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Id":"a0x0l000001XswlAAC","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XB50AAG"},"Sobject_Type__c":"Opportunity","New_URL__c":"/ssbgapi/opportunity/insert","Read_URL__c":"/ssbgapi/opportunity/query","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/opportunity/undelete","Id":"a0x0l000001XB50AAG","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XxD8AAK"},"Sobject_Type__c":"Document","New_URL__c":"/api/file/upload","Read_URL__c":"/api/file/preview?key=","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/api/file/download?key=","Id":"a0x0l000001XxD8AAK","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XlVuAAK"},"Sobject_Type__c":"Repair__c","New_URL__c":"/ssbgapi/repair/insert","Read_URL__c":"/ssbgapi/repair/query","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/repair/undelete","Id":"a0x0l000001XlVuAAK","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XlbnAAC"},"Sobject_Type__c":"loaner_user__c","New_URL__c":"/ssbgapi/loaneruser/insert","Read_URL__c":"/ssbgapi/loaneruser/query","Search_URL__c":"/ssbgapi/loaneruser/search","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/loaneruser/undelete","Id":"a0x0l000001XlbnAAC","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XlZNAA0"},"Sobject_Type__c":"SBG007","New_URL__c":"/ssbgapi/sbg/007","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Id":"a0x0l000001XlZNAA0","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XAcZAAW"},"Sobject_Type__c":"Contact","New_URL__c":"/ssbgapi/contact/insert","Read_URL__c":"/ssbgapi/contact/query","Search_URL__c":"/ssbgapi/contact/search","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Undelete_URL__c":"/ssbgapi/contact/undelete","Id":"a0x0l000001XAcZAAW","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Policy_Configuration__c","url":"/services/data/v54.0/sobjects/PI_Policy_Configuration__c/a0x0l000001XqaGAAS"},"Sobject_Type__c":"SBG001","New_URL__c":"/ssbgapi/sbg/001","TransactionURL__c":"https://sfpi-ssbg-test.olympuschina.com:8080/ssbgapi/tx/confirm","Id":"a0x0l000001XqaGAAS","CurrencyIsoCode":"CNY"}]';
+        List<PI_Policy_Configuration__c> piList = (List<PI_Policy_Configuration__c>)JSON.deserialize(piJson,List<PI_Policy_Configuration__c>.class);
+        List<PI_Policy_Configuration__c> insertPiList = new List<PI_Policy_Configuration__c>();
+
+        for(PI_Policy_Configuration__c pi : piList){
+            PI_Policy_Configuration__c ipi = new PI_Policy_Configuration__c();
+            ipi.Delete_URL__c = pi.Delete_URL__c;
+            ipi.Enable_Encrypt__c = pi.Enable_Encrypt__c;
+            ipi.New_URL__c = pi.New_URL__c;
+            ipi.Read_URL__c = pi.Read_URL__c;
+            ipi.Search_URL__c = pi.Search_URL__c;
+            ipi.Sobject_Type__c = pi.Sobject_Type__c;
+            ipi.Undelete_URL__c = pi.Undelete_URL__c;
+            ipi.Update_URL__c = pi.Update_URL__c;
+            //ipi.View_Unified_Contact_URL__c = pi.View_Unified_Contact_URL__c;
+            //ipi.Whether_Enable_Migration__c = pi.Whether_Enable_Migration__c;
+
+            if(sobjectTypes==null || sobjectTypes.contains(pi.Sobject_Type__c)){
+                insertPiList.add(ipi);
+            }
+            
+        }
+        insert insertPiList;
+        Map<String,String> typeIdMap = new Map<String,String>();//key: type value: id
+        for(PI_Policy_Configuration__c pi:insertPiList){
+            typeIdMap.put(pi.Sobject_Type__c,pi.Id);
+        }
+        String pidJson = '[{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gUcLAAU"},"PI_Policy_Configuration_Name__c":"User_FaultInfo__c","PI_Policy_Configuration__c":"a0x0l000001XTYDAA4","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"INBOUND_EMAIL_ADDRESS__c","AWS_Field_API__c":"inboundEmailAddress","Id":"a0y0l000001gUcLAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gc42AAA"},"PI_Policy_Configuration_Name__c":"Quotes__c","PI_Policy_Configuration__c":"a0x0l000001XWzeAAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"CONTACT_EMAIL__c","AWS_Field_API__c":"contactEmail","Id":"a0y0l000001gc42AAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpuDAAQ"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"from","AWS_Field_API__c":"FROM__c","Id":"a0y0l000001gpuDAAQ","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gb86AAA"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Shipping_Address_Text__c","AWS_Field_API__c":"shippingAddressText","Id":"a0y0l000001gb86AAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbEsAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_N_CONTACT__c","AWS_Field_API__c":"pdfNContact","Id":"a0y0l000001gbEsAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbCIAAY"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"SpecialDeliveryContact_D__c","AWS_Field_API__c":"specialDeliveryContactD","Id":"a0y0l000001gbCIAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbDBAAY"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_N_NotifyParty__c","AWS_Field_API__c":"pdfNNotifyParty","Id":"a0y0l000001gbDBAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbJyAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_F_ContactPerson__c","AWS_Field_API__c":"pdfFContactPerson","Id":"a0y0l000001gbJyAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gcK5AAI"},"PI_Policy_Configuration_Name__c":"loaner_application__c","PI_Policy_Configuration__c":"a0x0l000001XX2TAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Loaner_receive_staff__c","AWS_Field_API__c":"loanerReceiveStaff","Id":"a0y0l000001gcK5AAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gcKPAAY"},"PI_Policy_Configuration_Name__c":"loaner_application__c","PI_Policy_Configuration__c":"a0x0l000001XX2TAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"return_Number__c","AWS_Field_API__c":"returnNumber","Id":"a0y0l000001gcKPAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001ggpjAAA"},"PI_Policy_Configuration_Name__c":"SWO__c","PI_Policy_Configuration__c":"a0x0l000001XWzKAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"CONTACT_NAME_HIDDEN__c","AWS_Field_API__c":"contactNameHidden","Id":"a0y0l000001ggpjAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSexAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"OtherPhoneD__c","AWS_Field_API__c":"otherPhoneD","Id":"a0y0l000001gSexAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSbZAAU"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"LastName","AWS_Field_API__c":"lastName","Id":"a0y0l000001gSbZAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSduAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Title","AWS_Field_API__c":"title","Id":"a0y0l000001gSduAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSeJAAU"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Address1D__c","AWS_Field_API__c":"address1D","Id":"a0y0l000001gSeJAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSeTAAU"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Address3D__c","AWS_Field_API__c":"address3D","Id":"a0y0l000001gSeTAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSdpAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"TitleD__c","AWS_Field_API__c":"titleD","Id":"a0y0l000001gSdpAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSe4AAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"EnglishAddress__c","AWS_Field_API__c":"englishAddress","Id":"a0y0l000001gSe4AAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSe5AAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Address1__c","AWS_Field_API__c":"address1","Id":"a0y0l000001gSe5AAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSeYAAU"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Fax","AWS_Field_API__c":"fax","Id":"a0y0l000001gSeYAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSf7AAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"OtherPhone","AWS_Field_API__c":"otherPhone","Id":"a0y0l000001gSf7AAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gc47AAA"},"PI_Policy_Configuration_Name__c":"Quotes__c","PI_Policy_Configuration__c":"a0x0l000001XWzeAAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"BILL_TO__c","AWS_Field_API__c":"billTo","Id":"a0y0l000001gc47AAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gUcQAAU"},"PI_Policy_Configuration_Name__c":"User_FaultInfo__c","PI_Policy_Configuration__c":"a0x0l000001XTYDAA4","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"UFPhone__c","AWS_Field_API__c":"ufPhone","Id":"a0y0l000001gUcQAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gc3nAAA"},"PI_Policy_Configuration_Name__c":"Quotes__c","PI_Policy_Configuration__c":"a0x0l000001XWzeAAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"CONTACT_PHONE__c","AWS_Field_API__c":"contactPhone","Id":"a0y0l000001gc3nAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gc43AAA"},"PI_Policy_Configuration_Name__c":"Quotes__c","PI_Policy_Configuration__c":"a0x0l000001XWzeAAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"SHIP_TO__c","AWS_Field_API__c":"shipTo","Id":"a0y0l000001gc43AAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbLEAAY"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_Sign_Title__c","AWS_Field_API__c":"pdfSignTitle","Id":"a0y0l000001gbLEAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbL4AAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"SpecialDeliveryAddress__c","AWS_Field_API__c":"specialDeliveryAddress","Id":"a0y0l000001gbL4AAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gb5lAAA"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"SpecialDeliveryPhone_D__c","AWS_Field_API__c":"specialDeliveryPhoneD","Id":"a0y0l000001gb5lAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbKpAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_C_FAX__c","AWS_Field_API__c":"pdfCFax","Id":"a0y0l000001gbKpAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbBcAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"SpecialDeliveryContact__c","AWS_Field_API__c":"specialDeliveryContact","Id":"a0y0l000001gbBcAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gc3xAAA"},"PI_Policy_Configuration_Name__c":"Quotes__c","PI_Policy_Configuration__c":"a0x0l000001XWzeAAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"CONTACT_FAX__c","AWS_Field_API__c":"contactFax","Id":"a0y0l000001gc3xAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbLJAAY"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_Sign_Name__c","AWS_Field_API__c":"pdfSignName","Id":"a0y0l000001gbLJAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbKkAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_C_TEL__c","AWS_Field_API__c":"pdfCTel","Id":"a0y0l000001gbKkAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbKuAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_C_Consignee__c","AWS_Field_API__c":"pdfCConsignee","Id":"a0y0l000001gbKuAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbHcAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_F_TEL__c","AWS_Field_API__c":"pdfFTe","Id":"a0y0l000001gbHcAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbKfAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_C_THECONSIGNE__c","AWS_Field_API__c":"pdfCTheconsigne","Id":"a0y0l000001gbKfAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gb5gAAA"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"SpecialDeliveryPhone__c","AWS_Field_API__c":"specialDeliveryPhone","Id":"a0y0l000001gb5gAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gb6FAAQ"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"SpecialDeliveryContactText__c","AWS_Field_API__c":"specialDeliveryContactText","Id":"a0y0l000001gb6FAAQ","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbI8AAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_F_FAX__c","AWS_Field_API__c":"pdfFFax","Id":"a0y0l000001gbI8AAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbDuAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_N_FAX__c","AWS_Field_API__c":"dfNFax","Id":"a0y0l000001gbDuAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbGoAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_S_TEL__c","AWS_Field_API__c":"pdfSTel","Id":"a0y0l000001gbGoAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbLOAAY"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_By_Tel__c","AWS_Field_API__c":"pdfByTel","Id":"a0y0l000001gbLOAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbKzAAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_C_CONTACT__c","AWS_Field_API__c":"pdfCContact","Id":"a0y0l000001gbKzAAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbL9AAI"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"SpecialDeliveryAddress_D__c","AWS_Field_API__c":"specialDeliveryAddressD","Id":"a0y0l000001gbL9AAI","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gbLTAAY"},"PI_Policy_Configuration_Name__c":"Order","PI_Policy_Configuration__c":"a0x0l000001XVeVAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PDF_By_Add__c","AWS_Field_API__c":"pdfByAdd","Id":"a0y0l000001gbLTAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpotAAA"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"allMemberName","AWS_Field_API__c":"ALL_MEMBER_NAME_Encrypted__c","Id":"a0y0l000001gpotAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpouAAA"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"allMember","AWS_Field_API__c":"ALL_MEMBER_Encrypted__c","Id":"a0y0l000001gpouAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpovAAA"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"bcc","AWS_Field_API__c":"BCC_Encrypted__c","Id":"a0y0l000001gpovAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpowAAA"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"cc","AWS_Field_API__c":"CC_Encrypted__c","Id":"a0y0l000001gpowAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpoxAAA"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"recipient","AWS_Field_API__c":"RECIPIENT_Encrypted__c","Id":"a0y0l000001gpoxAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpoyAAA"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"bccName","AWS_Field_API__c":"bccName__c","Id":"a0y0l000001gpoyAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpozAAA"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"ccName","AWS_Field_API__c":"ccName__c","Id":"a0y0l000001gpozAAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gpp0AAA"},"PI_Policy_Configuration_Name__c":"Mail_Merge__c","PI_Policy_Configuration__c":"a0x0l000001XswlAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"toName","AWS_Field_API__c":"toName__c","Id":"a0y0l000001gpp0AAA","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gT5TAAU"},"PI_Policy_Configuration_Name__c":"Opportunity","PI_Policy_Configuration__c":"a0x0l000001XB50AAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Dealer_Sales_Staff_Name_D__c","AWS_Field_API__c":"dealerSalesStaffNameD","Id":"a0y0l000001gT5TAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gT5JAAU"},"PI_Policy_Configuration_Name__c":"Opportunity","PI_Policy_Configuration__c":"a0x0l000001XB50AAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Dealer_Service_D__c","AWS_Field_API__c":"dealerServiceD","Id":"a0y0l000001gT5JAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gcKKAAY"},"PI_Policy_Configuration_Name__c":"loaner_application__c","PI_Policy_Configuration__c":"a0x0l000001XX2TAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Return_Trake_Staff__c","AWS_Field_API__c":"returnTrakeStaff","Id":"a0y0l000001gcKKAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gcKZAAY"},"PI_Policy_Configuration_Name__c":"loaner_application__c","PI_Policy_Configuration__c":"a0x0l000001XX2TAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Loaner_Ser__c","AWS_Field_API__c":"loanerSer","Id":"a0y0l000001gcKZAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gcKAAAY"},"PI_Policy_Configuration_Name__c":"loaner_application__c","PI_Policy_Configuration__c":"a0x0l000001XX2TAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"direct_shippment_address__c","AWS_Field_API__c":"directShippmentAddress","Id":"a0y0l000001gcKAAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gcKFAAY"},"PI_Policy_Configuration_Name__c":"loaner_application__c","PI_Policy_Configuration__c":"a0x0l000001XX2TAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Loaner_receive_staff_phone__c","AWS_Field_API__c":"loanerReceiveStaffPhone","Id":"a0y0l000001gcKFAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gcKUAAY"},"PI_Policy_Configuration_Name__c":"loaner_application__c","PI_Policy_Configuration__c":"a0x0l000001XX2TAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Post_Code__c","AWS_Field_API__c":"postCode","Id":"a0y0l000001gcKUAAY","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gT5OAAU"},"PI_Policy_Configuration_Name__c":"Opportunity","PI_Policy_Configuration__c":"a0x0l000001XB50AAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"DealerService__c","AWS_Field_API__c":"dealerService","Id":"a0y0l000001gT5OAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gT5YAAU"},"PI_Policy_Configuration_Name__c":"Opportunity","PI_Policy_Configuration__c":"a0x0l000001XB50AAG","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"DealerSalesStaffName__c","AWS_Field_API__c":"dealerSalesStaffName","Id":"a0y0l000001gT5YAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gcrBAAQ"},"PI_Policy_Configuration_Name__c":"loaner_user__c","PI_Policy_Configuration__c":"a0x0l000001XlbnAAC","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"ContactNumber__c","AWS_Field_API__c":"contactNumber","Id":"a0y0l000001gcrBAAQ","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSeiAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"EmailD__c","AWS_Field_API__c":"emailD","Id":"a0y0l000001gSeiAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSbjAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PostcodeD__c","AWS_Field_API__c":"postcodeD","Id":"a0y0l000001gSbjAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSeEAAU"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Address3__c","AWS_Field_API__c":"address3","Id":"a0y0l000001gSeEAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSeOAAU"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Address2D__c","AWS_Field_API__c":"address2D","Id":"a0y0l000001gSeOAAU","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSesAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"MobilePhoneD__c","AWS_Field_API__c":"mobilePhoneD","Id":"a0y0l000001gSesAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSenAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Email","AWS_Field_API__c":"email","Id":"a0y0l000001gSenAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSbeAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Postcode__c","AWS_Field_API__c":"postcode","Id":"a0y0l000001gSbeAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSe9AAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Address2__c","AWS_Field_API__c":"address2","Id":"a0y0l000001gSe9AAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSf2AAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"PhoneD__c","AWS_Field_API__c":"phoneD","Id":"a0y0l000001gSf2AAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSf3AAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"MobilePhone","AWS_Field_API__c":"mobilePhone","Id":"a0y0l000001gSf3AAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSdzAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"ContactEnglishName__c","AWS_Field_API__c":"contactEnglishName","Id":"a0y0l000001gSdzAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSedAAE"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"FaxD__c","AWS_Field_API__c":"faxD","Id":"a0y0l000001gSedAAE","CurrencyIsoCode":"CNY"},{"attributes":{"type":"PI_Field_Policy_Detail__c","url":"/services/data/v54.0/sobjects/PI_Field_Policy_Detail__c/a0y0l000001gSfCAAU"},"PI_Policy_Configuration_Name__c":"Contact","PI_Policy_Configuration__c":"a0x0l000001XAcZAAW","Enable_Encrypt__c":true,"Field_Type__c":"String","SF_Field_API_Name__c":"Phone","AWS_Field_API__c":"phone","Id":"a0y0l000001gSfCAAU","CurrencyIsoCode":"CNY"}]';
+        List<PI_Field_Policy_Detail__c> pidList = (List<PI_Field_Policy_Detail__c>)JSON.deserialize(pidJson,List<PI_Field_Policy_Detail__c>.class);
+        List<PI_Field_Policy_Detail__c> insertPidList = new List<PI_Field_Policy_Detail__c>();
+        for(PI_Field_Policy_Detail__c pid:pidList){
+            if (!typeIdMap.containsKey((pid.PI_Policy_Configuration_Name__c))){
+                continue;
+            }
+
+            PI_Field_Policy_Detail__c ipid = new PI_Field_Policy_Detail__c();
+            ipid.Enable_Encrypt__c = pid.Enable_Encrypt__c;
+            ipid.Field_Type__c = pid.Field_Type__c;
+            //ipid.Order_Number__c = pid.Order_Number__c;
+            ipid.PI_Policy_Configuration__c = typeIdMap.get(pid.PI_Policy_Configuration_Name__c);
+            ipid.SF_Field_API_Name__c = pid.SF_Field_API_Name__c;
+            ipid.AWS_Field_API__c = pid.AWS_Field_API__c;
+            ipid.SF_Field_Encrypted_API__c = pid.SF_Field_Encrypted_API__c;
+            ipid.AWS_Encrypted_Field_API__c = pid.AWS_Encrypted_Field_API__c;
+            insertPidList.add(ipid);
+        }
+        insert insertPidList;
+    }
+    //create sample user
+    public static List<User> CreateUsers(Integer num){
+        Map<Id,Profile> profileList = new Map<Id, Profile>([SELECT Id, Name FROM Profile]) ;
+        Map<String, Profile> profileMap = new Map<String, Profile>();
+        Profile p = [select Id from Profile where Name = 'System Administrator'];
+        for(Profile profileTemp : profileList.values()){
+            profileMap.put(profileTemp.Name, profileTemp);
+        }
+        
+        List<User> userList=new List<User>();
+         for(Integer i = 0 ;i<num;i++){
+         	User u = new User( Alias = 'test',
+			                     Email = 'testuser'+i+'@olympus.com',
+			                     Emailencodingkey = 'UTF-8', 
+			                     Lastname = 'TestUser'+i, 
+			                     Languagelocalekey = 'zh_CN',
+			        			 Localesidkey = 'zh_CN', 
+			        			 Profileid = p.id, 
+			        			 Country = 'China',
+			        			 IsActive = true,
+			        			 Timezonesidkey = 'America/Sao_Paulo', 
+			                     Username = 'testuser'+i+'@olympus.com'
+                                 //,Job_Category__c = '閿�鍞湇鍔�'
+			);
+            userList.add(u);
+         }
+        insert userList;
+        //鏍规嵁绠�妗e悕鍙栧搴攗serList  Map<String,List<User>>
+        // Map<String, List<User>> sampleUserMap = new Map<String, List<User>>();
+        // for(User userTemp : userList){
+        //     String profileName = profileList.get(userTemp.Profileid).Name ;
+        //     if(sampleUserMap.containsKey(profileName)) {
+        //         sampleUserMap.get(profileName).add(userTemp);
+        //     }else{
+        //         List<User> userTempList = new List<User>();
+        //         userTempList.add(userTemp);
+        //         sampleUserMap.put(profileName, userTempList);
+        //     }
+        // }
+        // return sampleUserMap;
+        //鐩存帴杩斿洖userlist
+        return userList;
+    }
+    public static List<Account> CreateAccounts(Integer num){
+    	List<RecordType> rectIE = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Customer IE'];
+        
+        List<Account> acclist = new List<Account>();
+        String[] ieSubUse = new String[] {'LED','FPD','鍗婂浣�','鐢靛瓙閮ㄥ搧','鐢靛瓙绫籣鍏朵粬','閲戝睘','姹借溅','鐭虫补鍦拌川','浜旈噾妯″叿','閲嶅伐璁惧','鏉愭枡绫籣鍏朵粬'};
+        for (Integer i = 0; i < num; i++) {
+            Account acc1 = new Account();
+            acc1.Name = 'TestAccount'+String.valueOf(Datetime.now().minute())+String.valueOf(datetime.now().second())+i;
+            acc1.FacilityName__c = 'Account';
+            acc1.DivisionName__c = ieSubUse[i];
+            acc1.RecordTypeId = rectIE[0].Id;
+            acc1.ProductSegment__c = 'IE';
+            acc1.Sub_UseD__c = ieSubUse[i];
+            acc1.Sub_Use__c = ieSubUse[i];
+            acc1.PostCode__c = '000000';
+            acclist.add(acc1);
+        }
+        insert acclist;
+        return acclist;
+    }
+    public static List<Contact> CreateContacts(Integer num){
+    	List<Account> accList = new List<Account>();
+        accList = [Select id From Account];
+        if(accList.size()==0){
+            accList = CreateAccounts(1);
+        }
+    	List<Contact> conList = new List<Contact>();
+    	for(Integer i=0;i<num;i++){
+    		Contact con = new Contact();
+    		con.AccountId = accList[0].Id;
+	        con.FirstName = '璨换鑰�';
+	        con.LastName = 'test'+i+'鍖婚櫌';
+	        //con.Strategic_dept_Class__c = accList[0].Id;
+	        conList.add(con);
+    	}
+    	insert conList;
+    	return conList;
+    }
+    public static List<Opportunity> CreateOpportunitys(Integer num){
+        //new Contact
+        Account acc = new Account();
+        if([SELECT Id,Name FROM Account LIMIT 1].size()>0){
+            acc = [SELECT Id,Name FROM Account LIMIT 1];
+        }else{
+            acc = CreateAccounts(1)[0];
+        }
+    	List<Opportunity> oppList = new List<Opportunity>();
+        // List<RecordType> rectOpp = [select id from RecordType where IsActive = true and SobjectType = 'Opportunity'];
+    	for(Integer i=0;i<num;i++){
+    		Opportunity opp = new Opportunity(
+            Name = 'test opp',
+            AccountId = acc.Id,
+            RecordTypeId = System.Label.SSBD_Replacement,
+            OwnerId = UserInfo.getUserId(),
+            StageName = 'Phase3',//Prospect Created
+            CurrencyIsoCode = 'CNY',
+            ProductSegment__c = 'IE',
+            TradeType__c = 'Taxation',
+            // ForeignTradeCompany_D__c = acc.Id,
+            CloseDate = Date.today(),
+            NewInquiryDate__c = Date.today().addDays(-2),
+            ExpectedOrderDate__c = Date.today().addDays(2),
+            SalesChannel__c = 'direct'
+        );
+    		oppList.add(opp);
+    	}
+    	insert oppList;
+    	return oppList;
+    }
+    public static List<Task> CreateTasks(Integer num){
+    	List<Task> taList = new List<Task>();
+    	Account acc = CreateAccounts(1)[0];
+    	Opportunity opp = CreateOpportunitys(1)[0];
+    	for(Integer i=0;i<num;i++){
+    		Task ta = new Task();
+     		//ta.account__c = acc.id;
+			// ta.name = 'testTask'+i;
+			// ta.taskStatus__c = '01 鍒嗛厤';
+			// ta.assignee__c = UserInfo.getUserId();
+	        //ta.recordtypeId = Schema.SObjectType.task__c.getRecordTypeInfosByDeveloperName().get('OPD').getRecordTypeId();
+	        //ta.distributionCount__c = 1;
+	        //ta.taskDifferent__c = '琚姩浠诲姟';
+	        //ta.OpportunityId__c = opp.Id;
+     		//taList.add(ta);
+    	}
+    	insert taList;
+    	return taList;
+    }
+    public static List<Asset> CreateAssets(Integer num){
+    	// 鐪�
+        /*Address_Level__c al = new Address_Level__c();
+        al.Name = '鏉变含';
+        al.Level1_Code__c = 'CN-99';
+        al.Level1_Sys_No__c = '999999';
+        insert al;
+        // 甯�
+        Address_Level2__c al2 = new Address_Level2__c();
+        al2.Level1_Code__c = 'CN-99';
+        al2.Level1_Sys_No__c = '999999';
+        al2.Level1_Name__c = '鏉变含';
+        al2.Name = '娓嬭胺鍖�';
+        al2.Level2_Code__c = 'CN-9999';
+        al2.Level2_Sys_No__c = '9999999';
+        al2.Address_Level__c = al.id;
+        insert al2;*/
+
+        // 鐥呴櫌銈掍綔銈�
+        //ControllerUtil.EscapeNFM001Trigger = true;
+        //StaticParameter.EscapeNFM001Trigger = true;
+        //StaticParameter.EscapeAccountTrigger = true;
+        //StaticParameter.EscapeNFM001AgencyContractTrigger = true;
+
+        Account hospital = new Account();
+        hospital.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'HP'].id;
+        System.debug('鐥呴櫌瀹屼簡!');
+        hospital.Name = 'test hospital';
+        //hospital.Is_Active__c = '鏈夊姽';
+        //hospital.Attribute_Type__c = '鍗敓閮�';
+        //hospital.Speciality_Type__c = '缁煎悎鍖婚櫌';
+        //hospital.Grade__c = '涓�绾�';
+        //hospital.OCM_Category__c = 'SLTV';
+        //hospital.Is_Medical__c = '鍖荤枟鏈烘瀯';
+        //hospital.State_Master__c = al.id;
+        //hospital.City_Master__c = al2.id;
+        //hospital.Town__c = '涓滀含';
+        insert hospital;
+        System.debug('鐥呴櫌 insert 瀹屼簡!');
+
+        // 鎴︾暐绉戝銈掑緱銈�
+        Account strategicDep = new Account();
+        strategicDep.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'Department_Class_OTH'].id;
+        strategicDep.Name = 'Olympus绀惧唴 鍏朵粬';
+        //strategicDep.Department_Class_Label__c = '鍏朵粬';
+        //strategicDep.Hospital__c = hospital.Id;
+        strategicDep.ParentId = hospital.Id;
+        insert strategicDep;
+
+        // 瑷虹檪绉戙倰浣溿倠
+        Account dep = new Account();
+        dep.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'Department_OTH'].id;
+        dep.Name = 'test dep';
+        //dep.AgentCode_Ext__c = '99998';
+        dep.ParentId = strategicDep.Id;
+        //dep.Department_Class__c = strategicDep.Id;
+        //dep.Hospital__c = hospital.Id;
+        insert dep;
+        
+        System.debug('瑷虹檪绉� insert 瀹屼簡!');
+
+        // 浜у搧
+        Product2 pro1 = new Product2(Name='name01',IsActive=true,Family='GI');
+
+        insert new Product2[] {pro1};
+
+        List<Asset> asList = new List<Asset>();
+    	for(Integer i=0;i<num;i++){
+    		Asset assetA1 = new Asset();
+            //assetA1.RecordTypeId = System.Label.Asset_RecordType;
+            assetA1.SerialNumber = 'ass'+i;
+            assetA1.Name = 'ass'+i;
+            assetA1.AccountId = dep.Id;
+            //assetA1.Department_Class__c = strategicDep.Id;
+            //assetA1.Hospital__c = hospital.Id;
+            assetA1.Product2Id = pro1.Id;
+            assetA1.Quantity = 1;
+            assetA1.Status = '鏈夊簱瀛�';
+            //assetA1.Manage_type__c = '涓綋绠$悊';
+            //assetA1.Loaner_accsessary__c = false;
+            //assetA1.Out_of_wh__c = 0;
+            //assetA1.Salesdepartment__c = '1.鍗庡寳钀ヤ笟鏈儴';
+            //assetA1.Internal_asset_location__c = '鍖椾含 澶囧搧涓績';
+            //assetA1.Product_category__c = 'GI';
+            assetA1.Equipment_Type__c = '浜у搧璇曠敤';
+            //assetA1.SalesProvince__c = '鍖椾含';
+    		asList.add(assetA1);
+    	}
+    	insert asList;
+    	return asList;
+    }
+    public static List<loaner_application__c> CreateLoanerApplications(Integer num){
+        List<RecordType> rectLo = [select Id from RecordType where IsActive = true and SobjectType = 'loaner_application__c' and Name = 'IE'];   
+        List<loaner_application__c> laList = new List<loaner_application__c>();
+        for(Integer i =0;i<num;i++){
+            loaner_application__c loaner = new loaner_application__c();
+            loaner.Name = 'TEST'+i;
+            loaner.RecordTypeId = rectLo[0].id;
+            loaner.EC_CODE_1__C = 'DV2-CAMELEONS-CUBE';
+            loaner.DEMO_PURPOSE__C = '婕旂ず';
+            loaner.Request_shipping_Date__c = Date.today().addDays(10);
+            loaner.Request_return_Date__c = Date.today().addDays(10);
+            loaner.Status__c = '閮ㄥ垎鍙戣揣';
+            loaner.Return_Track_Company__c = '鐗╂祦鍏徃';
+            loaner.pickup_time__c  = Date.today();
+            loaner.Rental_Start_Date__c = Date.today().addDays(1);
+            loaner.Rental_End_Date__c  = Date.today().addDays(2);
+            //loaner.Return_Trake_Staff__c = '杩斿搧浜�';
+            laList.add(loaner);
+        }
+        insert laList;
+        return laList;
+    }
+    public static List<Loaner_Express__c> CreateLoanerExpresses(Integer num){
+        //new loaner_application__c
+        loaner_application__c la = new loaner_application__c();
+        if([SELECT Id FROM loaner_application__c LIMIT 1].size()>0){
+            la = [SELECT Id FROM loaner_application__c LIMIT 1];
+        }else{
+            la = Createloanerapplications(1)[0];
+        }
+        List<Loaner_Express__c> leList = new List<Loaner_Express__c>();
+        for(Integer i =0;i<num;i++){
+            Loaner_Express__c le = new Loaner_Express__c(
+                Name = 'test'+i,
+                loaner_application__c = la.Id,
+                NotReceivingNum__c = 3
+            );
+            leList.add(le);
+        }
+        insert leList;
+        return leList;
+    }
+    public static List<loaner_application_detail__c> CreateLoanerApplicationDetails(Integer num){
+        //new account
+        List<RecordType> rectCo = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Customer IE'];
+        Account acc = new Account();
+        acc.RecordTypeId = rectCo[0].Id;
+        acc.Name         = '瀹㈡埛銉嗐偣銉�1';
+        acc.DivisionName__c = 'DivisionName__c';
+        acc.FacilityName__c = 'FacilityName__c';
+        acc.PostCode__c='000000';
+        insert acc;
+        //new asset
+        Asset asset = new Asset();
+        asset.Name = '銉嗐偣銉堟鍣�1';
+        asset.AccountId = acc.Id;
+        asset.SerialNumber = 'testserial';
+        insert asset;
+        //new loaner_application__c
+        loaner_application__c la = new loaner_application__c();
+        if([SELECT Id FROM loaner_application__c LIMIT 1].size()>0){
+            la = [SELECT Id FROM loaner_application__c LIMIT 1];
+        }else{
+            la = Createloanerapplications(1)[0];
+        }
+        List<loaner_application_detail__c> ladList = new List<loaner_application_detail__c>();
+        for(Integer i =0;i<num;i++){
+            loaner_application_detail__c detail = new loaner_application_detail__c();
+            detail.loaner_application__c = la.Id;
+            detail.loaner__c = asset.id;
+            detail.name = 'Test'+i;
+            detail.RAESD_STATUS__C = '娆犲搧涓�';
+            //detail.Loaner_Express__c = le.id;
+            //loaner.Return_Trake_Staff__c = '杩斿搧浜�';
+            ladList.add(detail);
+        }
+        insert ladList;
+        return ladList;
+    }
+    public static List<User_FaultInfo__c> CreateUserFaultInfos(Integer num){
+        List<User_FaultInfo__c> ufList = new List<User_FaultInfo__c>();
+        for(Integer i=0;i<num;i++){
+            User_FaultInfo__c uf = new User_FaultInfo__c();
+            uf.ORIGIN__c = 'Web';
+            uf.SUBJECT__c = 'test'+i;
+            uf.OFFICE_OWNER__c = 'Beijing';
+            uf.Product_Type__c = 'NDT';
+            uf.TYPE__c = 'Service';
+            uf.LOGISTICS_SHIPMENT_TYPE__c = 'Domestic';
+            uf.STATUS__c = 'Not Started';
+            uf.PRIORITY__c = 'High';
+            ufList.add(uf);
+        }
+        insert ufList;
+        return ufList;
+    }
+    public static List<Quotes__c> CreateQuotes(Integer num){
+        List<Quotes__c> qList = new List<Quotes__c>();
+        for(Integer i=0;i<num;i++){
+            Quotes__c quotes = new Quotes__c();
+            quotes.QuotesType__c = '闆朵欢鎶ヤ环鍗�';
+            quotes.DATE__c = Date.today();
+            quotes.LEAD_TIME__c = '1 week';
+            quotes.STATUS__c = 'Qualifying';
+            quotes.LOCATION__c = 'China - Service';
+            quotes.TERMS__c = '1% 10 Net 30';
+            quotes.EXPIRES__c = Date.today();
+            quotes.EXP_CLOSE__c = Date.today();
+            quotes.ORDER_TYPE__c = 'LS Core Clinical';
+            qList.add(quotes);
+        }
+        insert qList;
+        return qList;
+    }
+    public static List<Repair__c> CreateRepairs (Integer num){
+        List<Repair__c> repList = new List<Repair__c>();
+        for(Integer i =0;i<num;i++){
+            Repair__c rep = new Repair__c();
+            rep.Name='test'+i;
+            rep.ServicePlace__c='鐜板満';
+            repList.add(rep);
+        }
+        insert repList;
+        return repList;
+    }
+    public static List<loaner_user__c> CreateLoanerUsers(Integer num){
+        //new Contact
+        Contact con = new Contact();
+        if([SELECT Id,Name,AccountId FROM Contact LIMIT 1].size()>0){
+            con = [SELECT Id,Name,AccountId FROM Contact LIMIT 1];
+        }else{
+            con = CreateContacts(1)[0];
+        }
+        //new loaner_application__c
+        loaner_application__c la = new loaner_application__c();
+        if([SELECT Id FROM loaner_application__c LIMIT 1].size()>0){
+            la = [SELECT Id FROM loaner_application__c LIMIT 1];
+        }else{
+            la = Createloanerapplications(1)[0];
+        }
+        List<loaner_user__c> luList = new List<loaner_user__c>();
+        for(Integer i=0;i<num;i++){
+            loaner_user__c lu = new loaner_user__c();
+            lu.Customer__c = con.AccountId;
+            lu.Contact__c = con.id;
+            lu.loaner_application__c = la.id;
+            lu.Remarks__c = 'Test'+i;
+            luList.add(lu);
+        }
+        insert luList;
+        return luList;
+    }
+    public static List<Order> CreateOrders(Integer num){
+        //new Contact
+        Contact con = new Contact();
+        if([SELECT Id,Name,AccountId FROM Contact LIMIT 1].size()>0){
+            con = [SELECT Id,Name,AccountId FROM Contact LIMIT 1];
+        }else{
+            con = CreateContacts(1)[0];
+        }
+        //new Opportunity
+        Opportunity opp = new Opportunity();
+        if([SELECT Id,Name FROM Opportunity LIMIT 1].size()>0){
+            opp = [SELECT Id,Name FROM Opportunity LIMIT 1];
+        }else{
+            opp = CreateOpportunitys(1)[0];
+        }
+        // opp.StageName = 'Phase3';
+        // update opp;
+        //new Order
+        List<Order> odList = new List<Order>();
+        for(Integer i=0;i<num;i++){
+            Order od = new Order(
+            Name = 'TestOrder'+i,
+            Status = 'Draft',
+            Status__c = 'Active',
+            AccountId = con.AccountId,
+            ApproveStatus__c = 'Draft',
+            OpportunityId = opp.Id,
+            // ForeignTradeCompany_D__c = con.AccountId,
+            EffectiveDate = Date.today(),
+            IE_SP5_D__c = true,
+            IE_SP8__c = true,
+            SpecialDeliveryAccount_D__c = con.AccountId,
+            SpecialDeliveryContact2_D__c = con.Id,
+            EndUser__c = con.Id
+        );
+            odList.add(od);
+        }
+        insert odList;
+        return odList;
+    }
+    public static List<CampaignMember> CreateCampaignMember(Integer num){
+    	List<CampaignMember> addList = new List<CampaignMember>();
+    	//Repair__c rp = CreateRepairs(1)[0];
+        Campaign Cam= new Campaign();
+        Cam.Name = '瀛︿細 鍩硅鍚嶇О';
+        //Cam.Live_Demo_report__c = '瀛︿細 鍩硅-娴嬭瘯鐢�';
+        //Cam.HostName__c = '灏忔槑鏄庢槑';//浼氳涓诲姙鏂�
+        //Cam.cooperatorCompany__c = '浼氳鎵垮姙鏂�';//浼氳鎵垮姙鏂�
+        insert Cam;
+    	Contact contact4= new Contact();
+        //contact4.AccountId = rp.Account__c;
+        contact4.FirstName = '灏忔槑鏄庢槑';
+        contact4.LastName = 'test4缁忛攢鍟�';
+        insert contact4;
+    	for(Integer i=0;i<num;i++){
+    		CampaignMember add = new CampaignMember();
+            
+			add.ContactId = contact4.id;//瀹㈡埛浜哄憳锛� Contact
+			//add.MobilePhone__c = '123123666'+i;
+            add.CampaignId = Cam.Id;
+			
+    		addList.add(add);
+    	}
+    	insert addList;
+    	return addList;
+    }
+    
+    public static List<case> CreateCase(Integer num){
+    	List<case> addList = new List<case>();
+    	//Repair__c rp = CreateRepairs(1)[0];
+        Account aC = CreateAccounts(1)[0];
+    	Contact contact5= new Contact();
+        //contact5.AccountId = rp.Account__c;
+        contact5.FirstName = '灏忔槑鏄庢槑鏄�';
+        contact5.LastName = 'test4缁忛攢鍟�';
+        insert contact5;
+    	for(Integer i=0;i<num;i++){
+    		case add = new case();
+            
+			add.ContactId = contact5.id;//瀹㈡埛浜哄憳濮撳悕锛� Contact
+            //add.Account__c = aC.Id;//瀹㈡埛鍚嶇О锛� Account
+			add.Subject = 'Test For Case'+i;
+			
+    		addList.add(add);
+    	}
+    	insert addList;
+    	return addList;
+    }
+    
+    public static List<Event> CreateEvent(Integer num){
+    	List<Event> addList = new List<Event>();
+    	for(Integer i=0;i<num;i++){
+    		Event add = new Event();
+            
+			add.Type = '闆昏┍';
+			add.Description = 'Test for Event'+i;
+            add.DurationInMinutes = 1;//鎸佺画鏃堕棿
+			add.ActivityDateTime = Datetime.valueOf('2022-03-17 00:00:00');
+    		addList.add(add);
+    	}
+    	insert addList;
+    	return addList;
+    }
+    
+
+    
+    public static List<Lead> CreateLead(Integer num){
+    	List<Lead> addList = new List<Lead>();
+		//Repair__c rp = CreateRepairs(1)[0];
+        
+        /*Asset ast = CreateAssets(1)[0];
+        Account strategicDep = new Account();
+        strategicDep.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'Department_Class_OTH'].id;
+        strategicDep.Name = 'Olympus绀惧唴 鍏朵粬';
+        strategicDep.Department_Class_Label__c = '鍏朵粬';
+        strategicDep.Hospital__c = ast.Hospital__c;
+        strategicDep.ParentId = ast.Hospital__c;
+        insert strategicDep;
+       鎴樼暐绉戝鍒嗙被瑕佸拰姣嶅叕鍙镐竴鏍�     鎻忚堪	Not(IsBlank(Hospital__c)) 
+                                            && Parent.Parent.RecordTypeId = '01210000000QemG' 
+                                            && Department_Class__c <> ParentId
+
+        涓嶈兘鏇存敼鎴樼暐绉戝鐨勫鎴峰悕              RecordTypeId != '01210000000QemG' && ISBLANK(Parent.ParentId) 
+                                      && Parent.RecordTypeId = '01210000000QemG' && ISCHANGED(Name) && !Sys_Dept_Name_Change_Chk__c
+        鎴樼暐绉戝鐨勫尰闄㈣鍜岀瀹ょ殑鍖婚櫌涓�鑷�        IF(Parent.Parent.RecordTypeId = '01210000000QemG',IF(Hospital__c <> Parent.ParentId,TRUE,FALSE),FALSE)
+	                                        
+*/
+        
+        Account aC = CreateAccounts(1)[0];
+        //Contact contactTest = CreateContacts(1)[0];
+        //aC.Department_Class__c = '0010l00001PQF0SAAX';
+        //aC.ParentId = '0010l00001PQF0SAAX';
+        //update aC;
+    	Contact contact12= new Contact();
+        contact12.AccountId = aC.Id;
+        contact12.FirstName = '灏忔槑鏄庢槑鏄�';
+        contact12.LastName = 'test12缁忛攢鍟�';
+        insert contact12;
+        Account acc = [SELECT Id,Name,parentId,Parent.Parent.RecordTypeId FROM Account WHERE Id =:contact12.AccountId ];
+        //acc.Department_Class__c = acc.parentId;
+        System.debug('acc-----------'+acc);
+        System.debug('acc.parentId-----------'+acc.parentId);
+        System.debug('acc.Parent.Parent.RecordTypeId-----------'+acc.Parent.Parent.RecordTypeId);
+        update acc;
+        //鎴樼暐绉戝鍒嗙被瑕佸拰姣嶅叕鍙镐竴鏍�: []
+        //Not(IsBlank(Hospital__c)) && Parent.Parent.RecordTypeId = '01210000000QemG' && Department_Class__c <> ParentId
+    	for(Integer i=0;i<num;i++){
+    		Lead add = new Lead();
+            
+			add.Phone = '123123666'+i;//鐢佃瘽
+			//add.Hospital_Name__c = acc.Id;//瀹㈡埛
+			//add.Contact_Name__c = contact12.Id;//瀹㈡埛濮撳悕
+            //add.Department_Class__c = acc.Department_Class__c;
+            //Hospital_Name__c = Contact_Name__r.AccountId   娼滃湪瀹㈡埛: 鍖婚櫌鍚� ID绛変簬瀹㈡埛濮撳悕: 瀹㈡埛鍚� ID   
+			//Hospital_Name__r.Department_Class__c != Department_Class__c
+			//LastName, Company
+			add.LastName = 'TestLName'+i;
+            add.Company = 'TestCompany';
+    		addList.add(add);
+    	}
+    	insert addList;
+        //	涓庡尰闄㈠悕鐨勬垬鐣ョ瀹ゅ垎绫讳笉涓�鑷�
+        //  AND(NOT(ISBLANK(Hospital_Name__c)),Hospital_Name__r.Department_Class__c != Department_Class__c, $User.Batch_User__c ==FALSE)
+        //Hospital_Name__c 涓嶄负绌� 鏃� 闇�瑕佽 Hospital_Name__r.Department_Class__c == Department_Class__c
+    	return addList;
+    }
+
+
+/*****************************/    
+    public class CreatePIHelperHttpMock implements HttpCalloutMock {
+        public HTTPResponse respond(HTTPRequest req) {
+            Map<String, Object> testMap = new Map<String, Object>();
+            testMap.put('Account',CreateAccounts(1)[0]);
+            testMap.put('success',true);
+            String mapJson = JSON.serialize(testMap);
+            HttpResponse res = new HttpResponse();
+            res.setHeader('Content-Type', 'text/html');
+            res.setBody(mapJson); 
+            res.setStatusCode(200);
+            return res;
+        }
+    }
+
+    public class CreateMetaDataUtilityHttpMock implements HttpCalloutMock {
+        public HTTPResponse respond(HTTPRequest req) {
+            HttpResponse res = new HttpResponse();
+            res.setHeader('Content-Type', 'text/html');
+            res.setBody('{"size":2,"totalSize":2,"done":true,"queryLocator":null,"entityTypeName":"ProfileLayout","records":[{"attributes":{"type":"ProfileLayout","url":"/services/data/v41.0/tooling/sobjects/ProfileLayout/01G1000000hlD1YEAU"},"Layout":{"attributes":{"type":"Layout","url":"/services/data/v41.0/tooling/sobjects/Layout/00h10000009iAb5AAE"},"Name":".瀹㈡埛浜哄憳銉偆銈€偊銉�","TableEnumOrId":"01I10000000er3hEAA"},"ProfileId":"00e10000000NawVAAS","Profile":{"attributes":{"type":"Profile","url":"/services/data/v41.0/tooling/sobjects/Profile/00e10000000NawVAAS"},"Name":"901_缁忛攢鍟嗙ぞ鍖烘櫘閫氭潈闄�"},"RecordTypeId":null},{"attributes":{"type":"ProfileLayout","url":"/services/data/v41.0/tooling/sobjects/ProfileLayout/01G1000000hlD7CEAU"},"Layout":{"attributes":{"type":"Layout","url":"/services/data/v41.0/tooling/sobjects/Layout/00h10000009iAb5AAE"},"Name":".瀹㈡埛浜哄憳銉偆銈€偊銉�","TableEnumOrId":"01I10000000er3hEAA"},"ProfileId":"00e10000000NawVAAS","Profile":{"attributes":{"type":"Profile","url":"/services/data/v41.0/tooling/sobjects/Profile/00e10000000NawVAAS"},"Name":"901_缁忛攢鍟嗙ぞ鍖烘櫘閫氭潈闄�"},"RecordTypeId":"012100000006KW5AAM"}]}'); 
+            res.setStatusCode(200);
+            res.setStatus('OK');
+            return res;
+        }
+    }
+
+    public class BaseHttpMock implements HttpCalloutMock {
+
+        String body ='';
+        String status = '';
+        String statusCode = '';
+        public BaseHttpMock(String body,String status,String statusCode){
+            this.body = body;
+            this.status = status;
+            this.statusCode = statusCode;
+        }
+
+        public HTTPResponse respond(HTTPRequest req) {
+            HttpResponse res = new HttpResponse();
+            res.setHeader('Content-Type', 'application/json');
+            res.setBody(body); 
+            res.setStatusCode(200);
+            res.setStatus('OK');
+            return res;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/force-app/main/default/classes/TestDataUtility.cls-meta.xml b/force-app/main/default/classes/TestDataUtility.cls-meta.xml
new file mode 100644
index 0000000..40d6793
--- /dev/null
+++ b/force-app/main/default/classes/TestDataUtility.cls-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <status>Active</status>
+</ApexClass>
diff --git a/force-app/main/default/classes/TydelikeAccControllerTest.cls b/force-app/main/default/classes/TydelikeAccControllerTest.cls
index 12d4a7c..9b2d9a0 100644
--- a/force-app/main/default/classes/TydelikeAccControllerTest.cls
+++ b/force-app/main/default/classes/TydelikeAccControllerTest.cls
@@ -1,60 +1,56 @@
 @isTest
-private class TydelikeAccControllerTest {
+public class TydelikeAccControllerTest {
     static testMethod void testMethod1() {
-        TydelikeAccount__c acc1 = new TydelikeAccount__c();
-            acc1.name = '**';
-            acc1.OwnerId = UserInfo.getUserId();
-            acc1.TyCity__c = '鍖椾含';
-            acc1.OfSkrap__c = false;
-            acc1.TyAddress__c = '11111';
-            acc1.TyPostCode__c = '123456';
-            acc1.AssetBS3D__c = '123456';
-            acc1.AssetBS2D__c = '123456';
-            acc1.OCNServiceStaff__c = UserInfo.getUserId();
-            acc1.AssetBS1D__c = '123456';
-            acc1.ManagementCode_Ext__c = '123456';
-            acc1.Sub_UseD__c = 'LED';
-            acc1.AssetBS4D__c = '123456';
-            acc1.EnglishNameD__c = '123456';
-            acc1.DepartmentNameD__c = '123456';
-            acc1.FacilityNameD__c = '123456';
-            acc1.IndustryCD__c = 'Education';
-            acc1.MarketVerticalsD__c = 'Education';
-            acc1.CancelReasonD__c = '123456';
-            acc1.ExportRegulatedCustomer__c = true;
-            acc1.Province__c = '鍖椾含';
-            acc1.Whether_OEM__c = true;
-            acc1.GlobalAccountName__c = '123456';
-            acc1.NationalEnterpriseUser__c = true;
-            acc1.DivisionName_D__c = '123456';
-            acc1.UseD__c = '(Education)Education';
-            acc1.UserType__c = 'OEM瀹㈡埛';
-            acc1.WebsiteD__c = 'http://1';
-            acc1.KeyAccount__c = 'Large Account';
-            acc1.ProductSegment__c = 'BS';
-            acc1.FaxD__c = '123456';
-            acc1.Remark__c = '123456';
-            acc1.DealerSelectOwner__c = UserInfo.getUserId();
-            acc1.PhoneD__c = '15555555555';
-        insert acc1;
-
-        TydelikeContact__c tycon1 = new TydelikeContact__c();
-        	tycon1.name = '*';
-        	tycon1.OfSkrap__c = false;
-        	tycon1.TydelikeAccount__c = acc1.Id;
-        	tycon1.TyAddress__c = '11111';
-        	tycon1.TyFaxD__c = '1111';
-        	tycon1.TyPhoneD__c = '15555555555';
-        	tycon1.TyPostcode__c = '111111';
-            tycon1.EnglishAddress__c = '111111';
-            tycon1.ContactEnglishName__c = '111111';
-        insert tycon1;
-        System.debug(tycon1);
-
-        PageReference page = new PageReference('/apex/TydelikeAcc?tyacId=' + acc1.Id + '&tycoId=' + tycon1.Id);
-        System.Test.setCurrentPage(page);
-        TydelikeAccController controller = new TydelikeAccController();
-        controller.init();
-        controller.save();
+        TydelikeAccount__c tyactest = new TydelikeAccount__c();
+        tyactest.Name = 'test';
+        tyactest.AssetBS3D__c = 'test';
+        tyactest.AssetBS2D__c = 'test';
+        tyactest.AssetBS1D__c = 'test';
+        tyactest.AssetBS5D__c = 'test';
+        tyactest.ManagementCode_Ext__c = 'test';
+        tyactest.Sub_UseD__c = 'LED';
+        tyactest.EnglishNameD__c = 'test';
+        tyactest.DepartmentNameD__c = 'test';
+        tyactest.FacilityNameD__c = 'test';
+        tyactest.MarketVerticalsD__c = 'Education';
+        tyactest.CancelReasonD__c = 'test';
+        tyactest.ExportRegulatedCustomer__c = false;
+        tyactest.Province__c = '鍖椾含';
+        tyactest.Whether_OEM__c = false;
+        tyactest.GlobalAccountName__c = 'test';
+        tyactest.DivisionName_D__c = 'test';
+        tyactest.UseD__c = 'IVF';
+        //tyactest.WebsiteD__c = '';
+        tyactest.TyCity__c = 'PII';
+        tyactest.TyAddress__c = 'PII';
+        tyactest.TyPostCode__c = 'PII';
+        tyactest.ProductSegment__c = 'BS';
+        tyactest.FaxD__c = 'test';
+        tyactest.Remark__c = 'PII';
+        //tyactest.DealerSelectOwner__c = 'OT-IT';
+        tyactest.PhoneD__c = '13455556666';
+        tyactest.NationalEnterpriseUser__c = false;
+        tyactest.AssetBS4D__c = 'test';
+        insert tyactest;
+        
+        TydelikeContact__c tycotest = new TydelikeContact__c();
+        tycotest.Name = 'test';
+        tycotest.TyAddress__c = 'test';
+        tycotest.TyFaxD__c = 'test';
+        tycotest.TyPhoneD__c = '13566667777';
+        tycotest.TyPostcode__c = '5000000';
+        tycotest.EnglishAddress__c = 'test';
+        tycotest.ContactEnglishName__c = 'test';
+        insert tycotest;
+        
+        String url = ApexPages.currentPage().getParameters().put('tyacId',tyactest.Id);
+        url = ApexPages.currentPage().getParameters().put('tycoId',tycotest.Id);
+        
+        Test.startTest();
+        TydelikeAccController scc = new TydelikeAccController();
+        scc.init();
+        scc.save();
+        Test.stopTest();
     }
+
 }
\ No newline at end of file
diff --git a/force-app/main/default/classes/TydelikeAccControllerTest.cls-meta.xml b/force-app/main/default/classes/TydelikeAccControllerTest.cls-meta.xml
index f3bac1f..40d6793 100644
--- a/force-app/main/default/classes/TydelikeAccControllerTest.cls-meta.xml
+++ b/force-app/main/default/classes/TydelikeAccControllerTest.cls-meta.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
-    <apiVersion>41.0</apiVersion>
+    <apiVersion>54.0</apiVersion>
     <status>Active</status>
 </ApexClass>
diff --git a/force-app/main/default/classes/TydelikeConControllerTest.cls b/force-app/main/default/classes/TydelikeConControllerTest.cls
index 8691ac1..ba003d8 100644
--- a/force-app/main/default/classes/TydelikeConControllerTest.cls
+++ b/force-app/main/default/classes/TydelikeConControllerTest.cls
@@ -1,236 +1,47 @@
 @isTest
-private class TydelikeConControllerTest {
+public class TydelikeConControllerTest {
     static testMethod void testMethod1() {
-        TydelikeAccount__c acc1 = new TydelikeAccount__c();
-            acc1.name = '**';
-            acc1.OwnerId = UserInfo.getUserId();
-            acc1.TyCity__c = '鍖椾含';
-            acc1.OfSkrap__c = false;
-            acc1.TyAddress__c = '11111';
-            acc1.TyPostCode__c = '123456';
-        insert acc1;
+        Account acctest = TestDataUtility.CreateAccounts(1)[0];
+        acctest.ProductSegment__c = 'BS';
+		update acctest;
+        
+        TydelikeContact__c tycotest = new TydelikeContact__c();
+        tycotest.Name = 'test';
+        tycotest.TyAddress__c = 'test';
+        tycotest.TyFaxD__c = 'test';
+        tycotest.TyPhoneD__c = '13566667777';
+        tycotest.TyPostcode__c = '5000000';
+        tycotest.EnglishAddress__c = 'test';
+        tycotest.ContactEnglishName__c = 'test';
+        insert tycotest;
+        
+        TydelikeAccount__c tyaccount = new TydelikeAccount__c();
 
-        TydelikeContact__c tycon1 = new TydelikeContact__c();
-        	tycon1.name = '*';
-        	tycon1.OfSkrap__c = false;
-        	tycon1.TydelikeAccount__c = acc1.Id;
-        	tycon1.TyAddress__c = '11111';
-        	tycon1.TyFaxD__c = '1111';
-        	tycon1.TyPhoneD__c = '15555555555';
-        	tycon1.TyPostcode__c = '111111';
-            tycon1.EnglishAddress__c = '111111';
-            tycon1.ContactEnglishName__c = '111111';
-        insert tycon1;
-        System.debug(tycon1);
-
-        List<RecordType> rectDealer = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Dealer'];
-        List<RecordType> rectBS = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Customer BS'];
-
-        Account buyer = new Account(
-            Name = '*',
-            FacilityName__c = 'buyer',
-            PostCode__c = '123456',
-            RecordTypeId = rectDealer[0].Id,
-            ProductSegment__c = 'BS'
-        );
-        insert buyer;
-        System.debug(buyer);
-        /*Account accBS = new Account(
-            Name = '12343',
-            RecordTypeId = rectBS[0].Id,
-            OwnerId = UserInfo.getUserId(),
-            DivisionName_D__c = '010',
-            FacilityNameD__c = '011',
-            DepartmentNameD__c = '001',
-            Province__c = '鍖椾含',
-            CityD__c = 'beijing',
-            Address1D__c = '7hao',
-            UserType__c = 'OEM瀹㈡埛',
-            MarketVerticalsD__c = 'Education',
-            IndustryBD__c = 'Education',
-            UseD__c = 'Education',
-
-            DivisionName__c = '010',
-            FacilityName__c = '011',
-            DepartmentName__c = '001',
-            City__c = 'beijing',
-            Address1__c = '7hao',
-            MarketVerticals__c = 'Education',
-            IndustryB__c = 'Education',
-            Use__c = 'Education',
-            ProductSegment__c = 'BS'
-        );
-        insert accBS;
-        System.debug(accBS);*/
-
-        PageReference page = new PageReference('/apex/TydelikeCon?accName=' + buyer.Name + '&tyacId=' + acc1.Id + '&tycoId=' + tycon1.Id);
-        System.Test.setCurrentPage(page);
-        TydelikeConController controller = new TydelikeConController();
-        controller.init();
-        controller.save();
+        String url = ApexPages.currentPage().getParameters().put('accName',acctest.Name);
+        url = ApexPages.currentPage().getParameters().put('tycoId',tycotest.Id);
+        url = ApexPages.currentPage().getParameters().put('tyacId',tyaccount.Id);
+        
+        
+    	Test.startTest();
+        TydelikeConController scc = new TydelikeConController();
+        scc.acc = acctest;
+        scc.tya = tyaccount;
+        scc.init();
+        scc.save();
+        acctest.ProductSegment__c = 'IE';
+        update acctest;
+        scc.init();
+        acctest.ProductSegment__c = 'NDT';
+        update acctest;
+        scc.init();
+        acctest.ProductSegment__c = 'ANI';
+        update acctest;
+        scc.init();
+        acctest.ProductSegment__c = 'RVI';
+        update acctest;
+        scc.init();
+        Test.stopTest();
     }
-
-     static testMethod void testMethod2() {
-        TydelikeAccount__c acc1 = new TydelikeAccount__c();
-            acc1.name = '**';
-            acc1.OwnerId = UserInfo.getUserId();
-            acc1.TyCity__c = '鍖椾含';
-            acc1.OfSkrap__c = false;
-            acc1.TyAddress__c = '11111';
-            acc1.TyPostCode__c = '123456';
-        insert acc1;
-
-        TydelikeContact__c tycon1 = new TydelikeContact__c();
-            tycon1.name = '*';
-            tycon1.OfSkrap__c = false;
-            tycon1.TydelikeAccount__c = acc1.Id;
-            tycon1.TyAddress__c = '11111';
-            tycon1.TyFaxD__c = '1111';
-            tycon1.TyPhoneD__c = '15555555555';
-            tycon1.TyPostcode__c = '111111';
-        insert tycon1;
-        System.debug(tycon1);
-
-        List<RecordType> rectDealer = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Dealer'];
-        List<RecordType> rectBS = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Customer BS'];
-
-        Account buyer = new Account(
-            Name = '*',
-            FacilityName__c = 'buyer',
-            PostCode__c = '123456',
-            RecordTypeId = rectDealer[0].Id,
-            ProductSegment__c = 'IE'
-        );
-        insert buyer;
-        System.debug(buyer);
-
-        PageReference page = new PageReference('/apex/TydelikeCon?accName=' + buyer.Name + '&tyacId=' + acc1.Id + '&tycoId=' + tycon1.Id);
-        System.Test.setCurrentPage(page);
-        TydelikeConController controller = new TydelikeConController();
-        controller.init();
-        controller.save();
-    }
-
-     static testMethod void testMethod3() {
-        TydelikeAccount__c acc1 = new TydelikeAccount__c();
-            acc1.name = '**';
-            acc1.OwnerId = UserInfo.getUserId();
-            acc1.TyCity__c = '鍖椾含';
-            acc1.OfSkrap__c = false;
-            acc1.TyAddress__c = '11111';
-            acc1.TyPostCode__c = '123456';
-        insert acc1;
-
-        TydelikeContact__c tycon1 = new TydelikeContact__c();
-            tycon1.name = '*';
-            tycon1.OfSkrap__c = false;
-            tycon1.TydelikeAccount__c = acc1.Id;
-            tycon1.TyAddress__c = '11111';
-            tycon1.TyFaxD__c = '1111';
-            tycon1.TyPhoneD__c = '15555555555';
-            tycon1.TyPostcode__c = '111111';
-        insert tycon1;
-        System.debug(tycon1);
-
-        List<RecordType> rectDealer = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Dealer'];
-        List<RecordType> rectBS = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Customer BS'];
-
-        Account buyer = new Account(
-            Name = '*',
-            FacilityName__c = 'buyer',
-            PostCode__c = '123456',
-            RecordTypeId = rectDealer[0].Id,
-            ProductSegment__c = 'NDT'
-        );
-        insert buyer;
-        System.debug(buyer);
-
-        PageReference page = new PageReference('/apex/TydelikeCon?accName=' + buyer.Name + '&tyacId=' + acc1.Id + '&tycoId=' + tycon1.Id);
-        System.Test.setCurrentPage(page);
-        TydelikeConController controller = new TydelikeConController();
-        controller.init();
-        controller.save();
-    }
-
-     static testMethod void testMethod4() {
-        TydelikeAccount__c acc1 = new TydelikeAccount__c();
-            acc1.name = '**';
-            acc1.OwnerId = UserInfo.getUserId();
-            acc1.TyCity__c = '鍖椾含';
-            acc1.OfSkrap__c = false;
-            acc1.TyAddress__c = '11111';
-            acc1.TyPostCode__c = '123456';
-        insert acc1;
-
-        TydelikeContact__c tycon1 = new TydelikeContact__c();
-            tycon1.name = '*';
-            tycon1.OfSkrap__c = false;
-            tycon1.TydelikeAccount__c = acc1.Id;
-            tycon1.TyAddress__c = '11111';
-            tycon1.TyFaxD__c = '1111';
-            tycon1.TyPhoneD__c = '15555555555';
-            tycon1.TyPostcode__c = '111111';
-        insert tycon1;
-        System.debug(tycon1);
-
-        List<RecordType> rectDealer = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Dealer'];
-        List<RecordType> rectBS = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Customer BS'];
-
-        Account buyer = new Account(
-            Name = '*',
-            FacilityName__c = 'buyer',
-            PostCode__c = '123456',
-            RecordTypeId = rectDealer[0].Id,
-            ProductSegment__c = 'ANI'
-        );
-        insert buyer;
-        System.debug(buyer);
-
-        PageReference page = new PageReference('/apex/TydelikeCon?accName=' + buyer.Name + '&tyacId=' + acc1.Id + '&tycoId=' + tycon1.Id);
-        System.Test.setCurrentPage(page);
-        TydelikeConController controller = new TydelikeConController();
-        controller.init();
-        controller.save();
-    }
-
-     static testMethod void testMethod5() {
-        TydelikeAccount__c acc1 = new TydelikeAccount__c();
-            acc1.name = '**';
-            acc1.OwnerId = UserInfo.getUserId();
-            acc1.TyCity__c = '鍖椾含';
-            acc1.OfSkrap__c = false;
-            acc1.TyAddress__c = '11111';
-            acc1.TyPostCode__c = '123456';
-        insert acc1;
-
-        TydelikeContact__c tycon1 = new TydelikeContact__c();
-            tycon1.name = '*';
-            tycon1.OfSkrap__c = false;
-            tycon1.TydelikeAccount__c = acc1.Id;
-            tycon1.TyAddress__c = '11111';
-            tycon1.TyFaxD__c = '1111';
-            tycon1.TyPhoneD__c = '15555555555';
-            tycon1.TyPostcode__c = '111111';
-        insert tycon1;
-        System.debug(tycon1);
-
-        List<RecordType> rectDealer = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Dealer'];
-        List<RecordType> rectBS = [select Id from RecordType where IsActive = true and SobjectType = 'Account' and Name = 'Customer BS'];
-
-        Account buyer = new Account(
-            Name = '*',
-            FacilityName__c = 'buyer',
-            PostCode__c = '123456',
-            RecordTypeId = rectDealer[0].Id,
-            ProductSegment__c = 'RVI'
-        );
-        insert buyer;
-        System.debug(buyer);
-
-        PageReference page = new PageReference('/apex/TydelikeCon?accName=' + buyer.Name + '&tyacId=' + acc1.Id + '&tycoId=' + tycon1.Id);
-        System.Test.setCurrentPage(page);
-        TydelikeConController controller = new TydelikeConController();
-        controller.init();
-        controller.save();
-    }
+   
+        
 }
\ No newline at end of file
diff --git a/force-app/main/default/classes/TydelikeConControllerTest.cls-meta.xml b/force-app/main/default/classes/TydelikeConControllerTest.cls-meta.xml
index f3bac1f..40d6793 100644
--- a/force-app/main/default/classes/TydelikeConControllerTest.cls-meta.xml
+++ b/force-app/main/default/classes/TydelikeConControllerTest.cls-meta.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
-    <apiVersion>41.0</apiVersion>
+    <apiVersion>54.0</apiVersion>
     <status>Active</status>
 </ApexClass>
diff --git a/force-app/main/default/pages/NewAndEditContact.page b/force-app/main/default/pages/NewAndEditContact.page
new file mode 100644
index 0000000..f624ed2
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditContact.page
@@ -0,0 +1,477 @@
+<!--
+@description       : 
+@author            : ChangeMeIn@UserSettingsUnder.SFDoc
+@group             : 
+@last modified on  : 03-08-2022
+@last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="Contact" extensions="NewAndEditContactController" id="page">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
+    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
+    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
+    <style>
+        .disabledbutton {
+            pointer-events: none;
+            opacity: 0.4;
+        }
+    </style>
+    <script>
+        
+        var config = {};
+        config = {
+            SobjectName : "{!SobjectName}",
+            ApiPrefix:"{!ApiPrefix}",
+            SaveAndNew:false,
+            AWSToSobjectMap:{!AWSToSobjectMapJson},
+            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
+            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
+            SobjectToAWSModel:function (sobjJson) {
+                let leadPayloadList = [];
+                let leadPIData = {};
+
+                for(let f in config.AWSToSobjectMap){
+                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
+                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
+                    }
+                    else{
+                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
+                    }
+                } 
+
+                leadPIData.medicalStaffFullName = leadPIData.lastName;// 瀹屾垚field update workflow
+                leadPIData.sfRecordId = '';
+                console.log('Sobject PI Data:' + leadPIData);
+                leadPayloadList.push(leadPIData);
+                console.log(JSON.stringify(leadPayloadList));
+                return JSON.stringify(leadPayloadList);
+            },
+            insertOrUpdateBack:function(payloadJson, r, isNewMode){
+                
+                for(let f in config.AWSToSobjectMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+
+                for(let f in config.AWSToSobjectEncryptedMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+                
+                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                if (isNewMode) {
+                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                } else {
+                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                }
+                return payloadJson;
+            },
+            queryBack:function (data) {
+                console.log('data = ' + data);
+                if(data.object){
+                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
+                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
+                        if(data.object.hasOwnProperty(f) && ele){
+                            
+                            // 澶氶�夌壒娈婂鐞�
+                            if(ele.type == 'select-multiple'){
+                            //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
+                            if(ele && data.object[f]){
+                                let arr = data.object[f].split(';');
+
+                                // 缁欓殣钘忕殑select璧嬪��
+                                for(let op of ele.options){
+                                    op.selected = arr.indexOf(op.value)>-1;
+                                }
+                                
+                                // 鍒╃敤鎸夐挳缁欐樉绀虹殑select璧嬪��
+                                let ra = document.getElementById(ele.id + '_right_arrow');
+                                if(ra){
+                                    ra.click();
+                                }
+                                
+                            }
+                            }else{
+                                ele.value = data.object[f];
+                            }
+
+                            if(ele.type.indexOf("select")>-1 && ele.value){
+                                jQuery(ele).change()
+                            }
+                            
+                        }
+                        else{
+                            console.log(f + 'is not in data.object');
+                        }
+                    }
+                }
+                else{
+                    console.log('data.object = ' + data.object);
+                }
+                
+
+                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                // document.querySelector("[data-id='Phone']").value = data.object.phone;
+                // document.querySelector("[data-id='Email']").value = data.object.email;
+            },
+            updateMethod:"NewAndEditContactController.saveContact",
+            insertMethod:"NewAndEditContactController.saveContact"
+        }
+    
+        AWSService.sfSessionId = '{!GETSESSIONID()}';
+        var staticResources = JSON.parse('{!staticResource}');
+        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
+        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
+        console.log('{!staticResource}');
+        var VLookUpFields = {! VLookUpFieldsJson};
+        function ProcessPI(sobjJson, payloadForNewPI) {
+            blockme();
+            if ({!isNewMode}) {
+                NewPIToAWS(sobjJson, payloadForNewPI)
+            }else {
+                UpdatePIToAWS(sobjJson, payloadForNewPI)
+            }
+        }
+
+        var GetEleByClass = function(class_name){
+            let eles = document.getElementsByClassName(class_name);
+            if(eles.length > 0) return eles[0];
+            return null;
+        }
+
+        var GetEleApiName = function(ele){
+            for(let c of ele.classList){
+                if(c.indexOf(config.ApiPrefix+'_')>-1){
+                    return c.replace(config.ApiPrefix+'_','');
+                }
+            }
+            return '';
+        }
+
+        function IsFormTag(tag_name){
+            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
+        }
+        
+        function IsFormElement(e){
+            return IsFormTag(e.tagName);
+        }
+
+        function getPIPayload(sobjJson) {
+            return config.SobjectToAWSModel(sobjJson);
+        }
+
+        function validateFieldValueFormate() {
+            let error_msg = '';
+            let textEmail = "[data-id='Email']";
+            let textPhone = "[data-id='MobilePhone']";
+            //Email
+            let email = document.querySelector(textEmail);
+            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
+                error_msg += ';閭欢鏍煎紡閿欒';
+            }
+            let phone = document.querySelector(textPhone);
+
+            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
+                error_msg += ';鐢佃瘽鍙风爜閿欒';
+            }
+
+            for(let e of document.getElementsByTagName('select')){
+                for(let op of e.options){
+                    if(op.value == "*****" && op.selected){
+                        error_msg += ';涓嬫媺妗嗕笉鑳戒富鍔ㄩ�夋嫨瀵嗘枃閫夐」';
+                    }
+                }
+            }
+
+            if(error_msg.length>0 && error_msg[0]== ';'){
+                error_msg = error_msg.substring(1);
+            }
+
+            return error_msg;
+        }
+
+        function getSobjectInformation() {
+            //api_id_map
+//let nodelist = document.getElementsByClassName(config.ApiPrefix);
+            let result = {}
+            for (let index in api_id_map) {
+                let ele = document.getElementById(api_id_map[index]);
+                let field_api_name = index;
+                let tag_name = ele.tagName.toLowerCase();
+                if(!IsFormTag(tag_name)){
+                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
+                    continue;
+                }
+
+                if (VLookUpFields.indexOf(field_api_name)>=0) {
+                    console.log(ele.id.indexOf('lkwgt'));
+                    if (ele.id.indexOf('lkwgt') == -1) {
+                        let vlookUpNodeId = ele.id + '_lkid';
+                        let vlook_ele = document.getElementById(vlookUpNodeId);
+                        let v = '';
+                        if(vlook_ele){
+                            v = vlook_ele.value;
+                        }else{
+                            v = ele.value;
+                        }
+
+                        if(v && v != "000000000000000"){
+                            result[field_api_name] = v;
+                        }
+                        
+                    }
+                } else if (ele.type == 'checkbox') {
+                    result[field_api_name] = ele.checked;
+                } else if (ele.type == 'select-multiple') {
+                    //field_api_name
+                    let multiple = field_api_name;
+                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
+                    targets = targets.replace(/\n/g, ";");
+                    console.log('targets = ' + targets);
+                    result[field_api_name] = targets;
+                } else {
+                    result[field_api_name] = ele.value;
+                }
+                
+                // let e1 = document.getElementById(api_id_map[field_api_name]);
+                // if(!result[field_api_name] && e1 && e1.value){
+                // 	result[field_api_name] = e1.value;
+                // }
+            }
+            return result;
+        }
+        function QuerySobjectFromAWS() {
+            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+        }
+        function queryBack(data) {
+            console.log('data = ' + data);
+            config.queryBack(data);
+            unblockUI();
+        };
+
+
+        function insertOrUpdateBack(payloadJson, result, isNewMode) {
+            console.log(result);
+            let r = result;
+            console.log('Result from AWS' + r);
+            console.log('payloadJson=' + payloadJson);
+            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
+        }
+
+        function redirectCallBack(sfId,errorMsg) {
+            unblockUI();
+            if(errorMsg){
+                alertErrorMessage(errorMsg);
+            }
+            else{
+                if(config.SaveAndNew){
+                    window.open('{! SaveAndNewButtonUrl }','_self');
+                }else{
+                    window.open('/' + sfId, '_self');
+                }
+            }
+            
+        }
+
+        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.updateMethod;
+            let obj = JSON.parse(payloadForNewPI);
+            obj[0].dataId = '{!AWSDataId}';
+            let payloadForNewPIJson = JSON.stringify(obj);
+            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
+            
+        }
+
+        function NewPIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.insertMethod;
+            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
+            
+        }
+        
+
+        function checkRequiredFieldMsg(formData) {
+            let blankRequiredFields = '';
+            for(i = 0;i<requiredFieldAPIList.length;i++){
+                if(formData[requiredFieldAPIList[i]]){
+                    continue;
+                }else{
+                    if(blankRequiredFields == ''){
+                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }else{
+                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }
+                    
+                }
+            }
+            return blankRequiredFields;
+        }
+        function saveSobjectProcess(save_and_new) {
+            if(save_and_new){
+                config.SaveAndNew = true;
+            }
+            
+            hiddenErrorMsgNode();
+            //1. Get Sobject Information from Form
+            let sobjJson = getSobjectInformation();
+            //2. Validate the Sobject field value formate, for example the email formate or phone formate
+
+            let validationResultMessage = validateFieldValueFormate();
+            console.log(validationResultMessage);
+            if (validationResultMessage) {
+                //Popup error message.  - To Do After POC
+                alertErrorMessage(validationResultMessage);
+                return
+            }
+            // Check Required Field
+            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
+            if (checkRequiredFieldMsgResult) {
+                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
+                return
+            }
+            // //3. Prepare the payload for New PI API To AWS - To Do
+            let payloadForNewPI = getPIPayload(sobjJson);
+
+            // //4. Get Authentication Information for AWS
+            // loadAWSAuthentication();
+
+            // //5. lead to AWS 
+            ProcessPI(sobjJson, payloadForNewPI);
+            // awsToken = TestToken;
+            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
+        }
+
+        function alertErrorMessage(errorMsg) {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = errorMsg;
+            errorMsgNode.className = 'pbError';
+        }
+        function hiddenErrorMsgNode() {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = '';
+            errorMsgNode.className = '';
+        }
+    </script>
+    <div class="bPageTitle">
+        <div class="ptBody">
+            <div class="content">
+                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
+                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
+                    <span class="titleSeparatingColon">:</span>
+                </h1>
+                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
+                <div class="blank">&nbsp;</div>
+            </div>
+            <div class="links">
+                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
+                    title="姝ら〉闈㈢殑甯姪 锛堟柊绐楀彛锛�">
+                    <span class="helpLink">姝ら〉闈㈢殑甯姪</span>
+                    <img src="/img/s.gif" alt="" class="helpIcon" />
+                </a>
+            </div>
+        </div>
+        <div class="ptBreadcrumb"></div>
+    </div>
+    <apex:form id="form">
+        
+        <apex:pageblock id="block">
+            <div class="pbHeader">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
+                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
+                            </td>
+                            <td class="pbButton" id="topButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+            <!-- Error Msg-->
+            <div style="text-align: center;">
+                <apex:outputPanel id="errorMsg">
+                    <apex:pageMessages id="msgContent" escape="false" />
+                </apex:outputPanel>
+            </div>
+            
+            <!-- Iterate the layoutSections, which is a list of sections -->
+            <apex:repeat value="{!layoutSections}" var="layoutSection">
+                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
+                    
+                    <!--Each section has layoutFields, let's iterate them as well-->
+                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
+                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Contact[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
+                                        required="{!layoutField.isRequired}" />
+                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
+                        </apex:pageblocksectionitem>
+                    </apex:repeat>
+                    
+                </apex:pageBlockSection>
+            </apex:repeat>
+            <script>
+            var init_nodes = document.getElementsByClassName("PIBackApi");
+            var api_id_map={};
+            for(let e of init_nodes){
+            if(IsFormElement(e)){
+                api_id_map[GetEleApiName(e)] = e.id;
+                }
+            }
+            console.log(api_id_map);
+            sfdcPage.appendToOnloadQueue(function () {
+                //1. Set Last Name label
+                //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '濮撳悕';
+                //2. Query AWS Data by dataId 
+                console.log('Mode for Sobject Page:' + {!isNewMode});
+                if (!{!isNewMode}) {
+                    blockme();
+                    QuerySobjectFromAWS();
+                }
+                //3. Set Readonly Attribute
+                document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
+                document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
+
+                if({!isNewMode}){
+                	document.getElementById("page:form:block:j_id50:0:j_id51:j_id52:0:j_id53_lkid").value = '{!account.Id}';
+                	document.getElementById("page:form:block:j_id50:0:j_id51:j_id52:0:j_id53_lkold").value = '{!account.Name}';
+                	document.getElementById("page:form:block:j_id50:0:j_id51:j_id52:0:j_id53").value = '{!account.Name}';
+                	document.getElementById("page:form:block:j_id50:0:j_id51:j_id52:5:j_id53").value = '{!account.PhoneD__c}';
+                	document.getElementById("page:form:block:j_id50:0:j_id51:j_id52:8:j_id53").value = '{!account.FaxD__c}';
+                	document.getElementById("page:form:block:j_id50:1:j_id51:j_id52:0:j_id53").value = '{!account.PostCodeD__c}';
+                	document.getElementById("page:form:block:j_id50:2:j_id51:j_id52:0:j_id53").value = '{!account.Address1D__c}';
+                }
+            });
+            </script>
+            <div class="pbBottomButtons">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
+                            <td class="pbButtonb" id="bottomButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </apex:pageblock>
+
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditContact.page-meta.xml b/force-app/main/default/pages/NewAndEditContact.page-meta.xml
new file mode 100644
index 0000000..031713f
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditContact.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditContact</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewAndEditLoanerAppDetail.page b/force-app/main/default/pages/NewAndEditLoanerAppDetail.page
new file mode 100644
index 0000000..41846c7
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditLoanerAppDetail.page
@@ -0,0 +1,6 @@
+<apex:page >
+  <!-- Begin Default Content REMOVE THIS -->
+  <h1>Congratulations</h1>
+  This is your new Page
+  <!-- End Default Content REMOVE THIS -->
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditLoanerAppDetail.page-meta.xml b/force-app/main/default/pages/NewAndEditLoanerAppDetail.page-meta.xml
new file mode 100644
index 0000000..3aa1b02
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditLoanerAppDetail.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditLoanerAppDetail</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewAndEditLoanerApplication.page b/force-app/main/default/pages/NewAndEditLoanerApplication.page
new file mode 100644
index 0000000..3d20ffc
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditLoanerApplication.page
@@ -0,0 +1,474 @@
+<!--
+  @description       : 
+  @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+  @group             : 
+  @last modified on  : 03-03-2022
+  @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="loaner_application__c" extensions="NewAndEditLoanerApplicationController" id="page">
+  <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
+    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
+    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
+    <style>
+        .disabledbutton {
+            pointer-events: none;
+            opacity: 0.4;
+        }
+    </style>
+    <script>
+        
+        var config = {};
+        config = {
+            SobjectName : "{!SobjectName}",
+            ApiPrefix:"{!ApiPrefix}",
+            SaveAndNew:false,
+            AWSToSobjectMap:{!AWSToSobjectMapJson},
+            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
+            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
+            SobjectToAWSModel:function (sobjJson) {
+                let leadPayloadList = [];
+                let leadPIData = {};
+
+                for(let f in config.AWSToSobjectMap){
+                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
+                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
+                    }
+                    else{
+                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
+                    }
+                } 
+
+                leadPIData.medicalStaffFullName = leadPIData.lastName;// 瀹屾垚field update workflow
+                leadPIData.sfRecordId = '';
+                console.log('Sobject PI Data:' + leadPIData);
+                leadPayloadList.push(leadPIData);
+                console.log(JSON.stringify(leadPayloadList));
+                return JSON.stringify(leadPayloadList);
+            },
+            insertOrUpdateBack:function(payloadJson, r, isNewMode){
+                
+                for(let f in config.AWSToSobjectMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+
+                for(let f in config.AWSToSobjectEncryptedMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+                
+                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                if (isNewMode) {
+                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                } else {
+                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                }
+                return payloadJson;
+            },
+            queryBack:function (data) {
+                console.log('data = ' + data);
+                if(data.object){
+                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
+                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
+                        if(data.object.hasOwnProperty(f) && ele){
+                            
+                            // 澶氶�夌壒娈婂鐞�
+                            if(ele.type == 'select-multiple'){
+                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
+                              if(ele && data.object[f]){
+                                  let arr = data.object[f].split(';');
+
+                                  // 缁欓殣钘忕殑select璧嬪��
+                                  for(let op of ele.options){
+                                      op.selected = arr.indexOf(op.value)>-1;
+                                  }
+                                  
+                                  // 鍒╃敤鎸夐挳缁欐樉绀虹殑select璧嬪��
+                                  let ra = document.getElementById(ele.id + '_right_arrow');
+                                  if(ra){
+                                      ra.click();
+                                  }
+                                  
+                              }
+                            }else{
+                                ele.value = data.object[f];
+                            }
+
+                            if(ele.type.indexOf("select")>-1 && ele.value){
+                                jQuery(ele).change()
+                            }
+                            
+                        }
+                        else{
+                            console.log(f + 'is not in data.object');
+                        }
+                    }
+                }
+                else{
+                    console.log('data.object = ' + data.object);
+                }
+                
+
+                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                // document.querySelector("[data-id='Phone']").value = data.object.phone;
+                // document.querySelector("[data-id='Email']").value = data.object.email;
+            },
+            updateMethod:"NewAndEditLoanerApplicationController.saveLoanerApplication",
+            insertMethod:"NewAndEditLoanerApplicationController.saveLoanerApplication"
+        }
+    
+        AWSService.sfSessionId = '{!GETSESSIONID()}';
+        var staticResources = JSON.parse('{!staticResource}');
+        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
+        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
+        console.log('{!staticResource}');
+        var VLookUpFields = {! VLookUpFieldsJson};
+        function ProcessPI(sobjJson, payloadForNewPI) {
+            blockme();
+            if ({!isNewMode}) {
+              NewPIToAWS(sobjJson, payloadForNewPI)
+            }else {
+              UpdatePIToAWS(sobjJson, payloadForNewPI)
+            }
+        }
+
+        var GetEleByClass = function(class_name){
+            let eles = document.getElementsByClassName(class_name);
+            if(eles.length > 0) return eles[0];
+            return null;
+        }
+
+        var GetEleApiName = function(ele){
+            for(let c of ele.classList){
+                if(c.indexOf(config.ApiPrefix+'_')>-1){
+                    return c.replace(config.ApiPrefix+'_','');
+                }
+            }
+            return '';
+        }
+
+        function IsFormTag(tag_name){
+            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
+        }
+    
+    function IsFormElement(e){
+            return IsFormTag(e.tagName);
+        }
+
+        function getPIPayload(sobjJson) {
+            return config.SobjectToAWSModel(sobjJson);
+        }
+
+        function validateFieldValueFormate() {
+            let error_msg = '';
+            // let textEmail = "[data-id='Email']";
+            let textReturnPhone = "[data-id='return_Number__c']";
+            let textPhone = "[data-id='Loaner_receive_staff_phone__c']";
+            //Email
+            // let email = document.querySelector(textEmail);
+            // if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
+            //     error_msg += ';閭欢鏍煎紡閿欒';
+            // }
+            let returnPhone = document.querySelector(textReturnPhone);
+
+            if(returnPhone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(returnPhone.value)){
+                error_msg += ';	杩斿搧浜虹數璇濆彿鐮侀敊璇�';
+            }
+
+            let phone = document.querySelector(textPhone);
+
+            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
+                error_msg += ';	鏀朵欢浜虹數璇濆彿鐮侀敊璇�';
+            }
+
+            for(let e of document.getElementsByTagName('select')){
+                for(let op of e.options){
+                    if(op.value == "*****" && op.selected){
+                        error_msg += ';涓嬫媺妗嗕笉鑳戒富鍔ㄩ�夋嫨瀵嗘枃閫夐」';
+                    }
+                }
+            }
+
+            if(error_msg.length>0 && error_msg[0]== ';'){
+                error_msg = error_msg.substring(1);
+            }
+
+            return error_msg;
+        }
+
+        function getSobjectInformation() {
+            //api_id_map
+//let nodelist = document.getElementsByClassName(config.ApiPrefix);
+            let result = {}
+            for (let index in api_id_map) {
+                let ele = document.getElementById(api_id_map[index]);
+                let field_api_name = index;
+                let tag_name = ele.tagName.toLowerCase();
+                if(!IsFormTag(tag_name)){
+                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
+                    continue;
+                }
+
+                if (VLookUpFields.indexOf(field_api_name)>=0) {
+                    console.log(ele.id.indexOf('lkwgt'));
+                    if (ele.id.indexOf('lkwgt') == -1) {
+                        let vlookUpNodeId = ele.id + '_lkid';
+                        let vlook_ele = document.getElementById(vlookUpNodeId);
+                        let v = '';
+                        if(vlook_ele){
+                            v = vlook_ele.value;
+                        }else{
+                            v = ele.value;
+                        }
+
+                        if(v && v != "000000000000000"){
+                            result[field_api_name] = v;
+                        }
+                        
+                    }
+                } else if (ele.type == 'checkbox') {
+                    result[field_api_name] = ele.checked;
+                } else if (ele.type == 'select-multiple') {
+                    //field_api_name
+                    let multiple = field_api_name;
+                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
+                    targets = targets.replace(/\n/g, ";");
+                    console.log('targets = ' + targets);
+                    result[field_api_name] = targets;
+                } else {
+                    result[field_api_name] = ele.value;
+                }
+                
+                // let e1 = document.getElementById(api_id_map[field_api_name]);
+                // if(!result[field_api_name] && e1 && e1.value){
+                // 	result[field_api_name] = e1.value;
+                // }
+            }
+            return result;
+        }
+        function QuerySobjectFromAWS() {
+            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+        }
+        function queryBack(data) {
+            console.log('data = ' + data);
+            config.queryBack(data);
+            unblockUI();
+        };
+
+
+        function insertOrUpdateBack(payloadJson, result, isNewMode) {
+            console.log(result);
+            let r = result;
+            console.log('Result from AWS' + r);
+            console.log('payloadJson=' + payloadJson);
+            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
+        }
+
+        function redirectCallBack(sfId,errorMsg) {
+            unblockUI();
+            if(errorMsg){
+                alertErrorMessage(errorMsg);
+            }
+            else{
+                if(config.SaveAndNew){
+                    window.open('{! SaveAndNewButtonUrl }','_self');
+                }else{
+                    window.open('/' + sfId, '_self');
+                }
+            }
+            
+        }
+
+        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.updateMethod;
+            let obj = JSON.parse(payloadForNewPI);
+            obj[0].dataId = '{!AWSDataId}';
+            let payloadForNewPIJson = JSON.stringify(obj);
+            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
+            
+        }
+
+        function NewPIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.insertMethod;
+            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
+            
+        }
+        
+
+        function checkRequiredFieldMsg(formData) {
+            let blankRequiredFields = '';
+            for(i = 0;i<requiredFieldAPIList.length;i++){
+                if(formData[requiredFieldAPIList[i]]){
+                    continue;
+                }else{
+                    if(blankRequiredFields == ''){
+                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }else{
+                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }
+                    
+                }
+            }
+            return blankRequiredFields;
+        }
+        function saveSobjectProcess(save_and_new) {
+            if(save_and_new){
+                config.SaveAndNew = true;
+            }
+            
+            hiddenErrorMsgNode();
+            //1. Get Sobject Information from Form
+            let sobjJson = getSobjectInformation();
+            //2. Validate the Sobject field value formate, for example the email formate or phone formate
+
+            let validationResultMessage = validateFieldValueFormate();
+            console.log(validationResultMessage);
+            if (validationResultMessage) {
+                //Popup error message.  - To Do After POC
+                alertErrorMessage(validationResultMessage);
+                return
+            }
+            // Check Required Field
+            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
+            if (checkRequiredFieldMsgResult) {
+                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
+                return
+            }
+            // //3. Prepare the payload for New PI API To AWS - To Do
+            let payloadForNewPI = getPIPayload(sobjJson);
+
+            // //4. Get Authentication Information for AWS
+            // loadAWSAuthentication();
+
+            // //5. lead to AWS 
+            ProcessPI(sobjJson, payloadForNewPI);
+            // awsToken = TestToken;
+            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
+        }
+
+        function alertErrorMessage(errorMsg) {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = errorMsg;
+            errorMsgNode.className = 'pbError';
+        }
+        function hiddenErrorMsgNode() {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = '';
+            errorMsgNode.className = '';
+        }
+    </script>
+    <div class="bPageTitle">
+        <div class="ptBody">
+            <div class="content">
+                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
+                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
+                    <span class="titleSeparatingColon">:</span>
+                </h1>
+                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
+                <div class="blank">&nbsp;</div>
+            </div>
+            <div class="links">
+                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
+                    title="姝ら〉闈㈢殑甯姪 锛堟柊绐楀彛锛�">
+                    <span class="helpLink">姝ら〉闈㈢殑甯姪</span>
+                    <img src="/img/s.gif" alt="" class="helpIcon" />
+                </a>
+            </div>
+        </div>
+        <div class="ptBreadcrumb"></div>
+    </div>
+    <apex:form id="form">
+        
+        <apex:pageblock id="block">
+            <div class="pbHeader">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
+                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
+                            </td>
+                            <td class="pbButton" id="topButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+            <!-- Error Msg-->
+            <div style="text-align: center;">
+                <apex:outputPanel id="errorMsg">
+                    <apex:pageMessages id="msgContent" escape="false" />
+                </apex:outputPanel>
+            </div>
+            
+            <!-- Iterate the layoutSections, which is a list of sections -->
+            <apex:repeat value="{!layoutSections}" var="layoutSection">
+                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
+                    
+                    <!--Each section has layoutFields, let's iterate them as well-->
+                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
+                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!loaner_application__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
+                                        required="{!layoutField.isRequired}" />
+                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
+                        </apex:pageblocksectionitem>
+                    </apex:repeat>
+                    
+                </apex:pageBlockSection>
+            </apex:repeat>
+            <script>
+                var init_nodes = document.getElementsByClassName("PIBackApi");
+                var api_id_map={};
+                for(let e of init_nodes){
+                if(IsFormElement(e)){
+                    api_id_map[GetEleApiName(e)] = e.id;
+                    }
+                }
+                console.log(api_id_map);
+                sfdcPage.appendToOnloadQueue(function () {
+                    //1. Set Last Name label
+                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '濮撳悕';
+                    //2. Query AWS Data by dataId 
+                    console.log('Mode for Sobject Page:' + {!isNewMode});
+                    if (!{!isNewMode}) {
+                        blockme();
+                        QuerySobjectFromAWS();
+                    }
+                    //3. Set Readonly Attribute
+                    document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
+                    document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
+                });
+            </script>
+            <div class="pbBottomButtons">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
+                            <td class="pbButtonb" id="bottomButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </apex:pageblock>
+
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditLoanerApplication.page-meta.xml b/force-app/main/default/pages/NewAndEditLoanerApplication.page-meta.xml
new file mode 100644
index 0000000..8873606
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditLoanerApplication.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditLoanerApplication</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewAndEditLoanerExpress.page b/force-app/main/default/pages/NewAndEditLoanerExpress.page
new file mode 100644
index 0000000..41846c7
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditLoanerExpress.page
@@ -0,0 +1,6 @@
+<apex:page >
+  <!-- Begin Default Content REMOVE THIS -->
+  <h1>Congratulations</h1>
+  This is your new Page
+  <!-- End Default Content REMOVE THIS -->
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditLoanerExpress.page-meta.xml b/force-app/main/default/pages/NewAndEditLoanerExpress.page-meta.xml
new file mode 100644
index 0000000..00b13ca
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditLoanerExpress.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditLoanerExpress</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewAndEditLoanerUser.page b/force-app/main/default/pages/NewAndEditLoanerUser.page
new file mode 100644
index 0000000..ecf637b
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditLoanerUser.page
@@ -0,0 +1,544 @@
+<!--
+  @description       : 
+  @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+  @group             : 
+  @last modified on  : 03-04-2022
+  @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="loaner_user__c" extensions="NewAndEditLoanerUserController" id="page">
+  <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
+    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
+    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
+    <style>
+        .disabledbutton {
+            pointer-events: none;
+            opacity: 0.4;
+        }
+    </style>
+    <script>
+        
+        var config = {};
+        config = {
+            SobjectName : "{!SobjectName}",
+            ApiPrefix:"{!ApiPrefix}",
+            SaveAndNew:false,
+            AWSToSobjectMap:{!AWSToSobjectMapJson},
+            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
+            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
+            SobjectToAWSModel:function (sobjJson) {
+                let leadPayloadList = [];
+                let leadPIData = {};
+
+                for(let f in config.AWSToSobjectMap){
+                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
+                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
+                    }
+                    else{
+                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
+                    }
+                } 
+
+                leadPIData.sfRecordId = '';
+                console.log('Sobject PI Data:' + leadPIData);
+                leadPayloadList.push(leadPIData);
+                console.log(JSON.stringify(leadPayloadList));
+                return JSON.stringify(leadPayloadList);
+            },
+            insertOrUpdateBack:function(payloadJson, r, isNewMode){
+                
+                for(let f in config.AWSToSobjectMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+
+                for(let f in config.AWSToSobjectEncryptedMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+                
+                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                if (isNewMode) {
+                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                } else {
+                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                }
+                return payloadJson;
+            },
+            queryBack:function (data) {
+                console.log('data = ' + data);
+                if(data.object){
+                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
+                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
+                        if(data.object.hasOwnProperty(f) && ele){
+                            
+                            // 澶氶�夌壒娈婂鐞�
+                            if(ele.type == 'select-multiple'){
+                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
+                               if(ele && data.object[f]){
+                                   let arr = data.object[f].split(';');
+
+                                   // 缁欓殣钘忕殑select璧嬪��
+                                   for(let op of ele.options){
+                                       op.selected = arr.indexOf(op.value)>-1;
+                                   }
+                                   
+                                   // 鍒╃敤鎸夐挳缁欐樉绀虹殑select璧嬪��
+                                   let ra = document.getElementById(ele.id + '_right_arrow');
+                                   if(ra){
+                                       ra.click();
+                                   }
+                                   
+                               }
+                            }else{
+                                ele.value = data.object[f];
+                            }
+
+                            if(ele.type.indexOf("select")>-1 && ele.value){
+                                jQuery(ele).change()
+                            }
+                            
+                        }
+                        else{
+                            console.log(f + 'is not in data.object');
+                        }
+                    }
+                }
+                else{
+                    console.log('data.object = ' + data.object);
+                }
+                
+
+                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                // document.querySelector("[data-id='Phone']").value = data.object.phone;
+                // document.querySelector("[data-id='Email']").value = data.object.email;
+            },
+            updateMethod:"NewAndEditLoanerUserController.saveLoanerUser",
+            insertMethod:"NewAndEditLoanerUserController.saveLoanerUser"
+        }
+    
+        AWSService.sfSessionId = '{!GETSESSIONID()}';
+        var staticResources = JSON.parse('{!staticResource}');
+        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
+        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
+        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
+        console.log('{!staticResource}');
+        var VLookUpFields = {! VLookUpFieldsJson};
+        function ProcessPI(sobjJson, payloadForNewPI) {
+            blockme();
+            if ({!isNewMode}) {
+            	NewPIToAWS(sobjJson, payloadForNewPI)
+            }else {
+                UpdatePIToAWS(sobjJson, payloadForNewPI)
+            }
+        }
+
+        var GetEleByClass = function(class_name){
+            let eles = document.getElementsByClassName(class_name);
+            if(eles.length > 0) return eles[0];
+            return null;
+        }
+
+        var GetEleApiName = function(ele){
+            for(let c of ele.classList){
+                if(c.indexOf(config.ApiPrefix+'_')>-1){
+                    return c.replace(config.ApiPrefix+'_','');
+                }
+            }
+            return '';
+        }
+
+        function IsFormTag(tag_name){
+            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
+        }
+    	
+    	function IsFormElement(e){
+            return IsFormTag(e.tagName);
+        }
+
+        function getPIPayload(sobjJson) {
+            return config.SobjectToAWSModel(sobjJson);
+        }
+
+        function validateFieldValueFormate() {
+            let error_msg = '';
+            // let textEmail = "[data-id='Email']";
+            let textPhone = "[data-id='ContactNumber__c']";
+            //Email
+            // let email = document.querySelector(textEmail);
+            // if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
+            //     error_msg += ';閭欢鏍煎紡閿欒';
+            // }
+            let phone = document.querySelector(textPhone);
+
+            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
+                error_msg += ';鑱旂郴鐢佃瘽鍙风爜閿欒';
+            }
+
+            for(let e of document.getElementsByTagName('select')){
+                for(let op of e.options){
+                    if(op.value == "*****" && op.selected){
+                        error_msg += ';涓嬫媺妗嗕笉鑳戒富鍔ㄩ�夋嫨瀵嗘枃閫夐」';
+                    }
+                }
+            }
+
+            if(error_msg.length>0 && error_msg[0]== ';'){
+                error_msg = error_msg.substring(1);
+            }
+
+            return error_msg;
+        }
+
+        function getSobjectInformation() {
+            //api_id_map
+//let nodelist = document.getElementsByClassName(config.ApiPrefix);
+            let result = {}
+            for (let index in api_id_map) {
+                let ele = document.getElementById(api_id_map[index]);
+                let field_api_name = index;
+                let tag_name = ele.tagName.toLowerCase();
+                if(!IsFormTag(tag_name)){
+                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
+                    continue;
+                }
+
+                if (VLookUpFields.indexOf(field_api_name)>=0) {
+                    console.log(ele.id.indexOf('lkwgt'));
+                    if (ele.id.indexOf('lkwgt') == -1) {
+                        let vlookUpNodeId = ele.id + '_lkid';
+                        let vlook_ele = document.getElementById(vlookUpNodeId);
+                        let v = '';
+                        if(vlook_ele){
+                            v = vlook_ele.value;
+                        }else{
+                            v = ele.value;
+                        }
+
+                        if(v && v != "000000000000000"){
+                            result[field_api_name] = v;
+                        }
+                        
+                    }
+                } else if (ele.type == 'checkbox') {
+                    result[field_api_name] = ele.checked;
+                } else if (ele.type == 'select-multiple') {
+                    //field_api_name
+                    let multiple = field_api_name;
+                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
+                    targets = targets.replace(/\n/g, ";");
+                    console.log('targets = ' + targets);
+                    result[field_api_name] = targets;
+                } else {
+                    result[field_api_name] = ele.value;
+                }
+            }
+            return result;
+        }
+        function QuerySobjectFromAWS() {
+            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+        }
+        function queryBack(data) {
+            console.log('data = ' + data);
+            config.queryBack(data);
+            unblockUI();
+        };
+
+
+        function insertOrUpdateBack(payloadJson, result, isNewMode) {
+            console.log(result);
+            let r = result;
+            console.log('Result from AWS' + r);
+            console.log('payloadJson=' + payloadJson);
+            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
+        }
+
+        function redirectCallBack(sfId,errorMsg) {
+            unblockUI();
+            if(errorMsg){
+                alertErrorMessage(errorMsg);
+            }
+            else{
+                if(config.SaveAndNew){
+                    window.open('{! SaveAndNewButtonUrl }','_self');
+                }else{
+                    window.open('/' + sfId, '_self');
+                }
+            }
+            
+        }
+
+        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.updateMethod;
+            let obj = JSON.parse(payloadForNewPI);
+            obj[0].dataId = '{!AWSDataId}';
+            let payloadForNewPIJson = JSON.stringify(obj);
+            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
+            
+        }
+
+        function NewPIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.insertMethod;
+            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
+            
+        }
+        
+
+        function checkRequiredFieldMsg(formData) {
+            let blankRequiredFields = '';
+            for(i = 0;i<requiredFieldAPIList.length;i++){
+                if(formData[requiredFieldAPIList[i]]){
+                    continue;
+                }else{
+                    if(blankRequiredFields == ''){
+                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }else{
+                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }
+                    
+                }
+            }
+            return blankRequiredFields;
+        }
+        
+        function saveSobjectProcess(save_and_new) {
+            if(save_and_new){
+                config.SaveAndNew = true;
+            }
+            
+            hiddenErrorMsgNode();
+            //1. Get Sobject Information from Form
+            let sobjJson = getSobjectInformation();
+            //2. Validate the Sobject field value formate, for example the email formate or phone formate
+
+            let validationResultMessage = validateFieldValueFormate();
+            console.log(validationResultMessage);
+            if (validationResultMessage) {
+                //Popup error message.  - To Do After POC
+                alertErrorMessage(validationResultMessage);
+                return
+            }
+            // Check Required Field
+            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
+            if (checkRequiredFieldMsgResult) {
+                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
+                return
+            }
+            // //3. Prepare the payload for New PI API To AWS - To Do
+            let payloadForNewPI = getPIPayload(sobjJson);
+
+            // //4. Get Authentication Information for AWS
+            // loadAWSAuthentication();
+
+            // //5. loaner_user__c to AWS 
+            ProcessPI(sobjJson, payloadForNewPI);
+            // awsToken = TestToken;
+            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
+        }
+
+        function alertErrorMessage(errorMsg) {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = errorMsg;
+            errorMsgNode.className = 'pbError';
+        }
+        function hiddenErrorMsgNode() {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = '';
+            errorMsgNode.className = '';
+        }
+
+        //鏇挎崲vlookup
+        // var newSearchContactWindow = null;  
+
+        // function replaceSearchContactLookup() {
+        //     if (!{!isNewMode}) {
+        //         //1. Query Contact from AWS by AWSDataId
+        //         queryContactName()
+        //     }           
+        //     if(document.querySelector("[data-id='Contact__c']") != null){
+        //         let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact('page:form:contactId')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+        //         let lookUpNode = htmlToElement(contactHtmlString);
+        //         console.log(lookUpNode);
+        //         let parentNode = document.querySelector("[data-id='Contact__c']").parentNode;
+        //         document.querySelector("[data-id='Contact__c']").removeAttribute("onchange");
+        //         parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Contact__c']").parentNode.children[2]);
+        //     }
+        // }
+
+        // function htmlToElement(html) {
+        //     var template = document.createElement('template');
+        //     html = html.trim(); // Never return a text node of whitespace as the result
+        //     template.innerHTML = html;
+        //     return template.content.firstChild;
+        // }
+
+        // function queryContactName() {
+        //     let sfId = document.getElementById(document.querySelector("[data-id='Contact__c']").id + '_lkid').value;
+        //     let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
+        //     let dataId = contactsInfo[sfId];
+        //     let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
+
+        //     fetch(url, {
+        //         method: 'GET',
+        //         headers: {
+        //             'Content-Type': 'application/json',
+        //             'pi-token': staticResources.token
+        //         }
+        //     }).then((data) => {
+        //         return data.json();
+        //     }).then((result) => {
+        //         document.querySelector("[data-id='Contact__c']").value = result.object.lastName;
+        //     })
+        // }
+
+        
+        // //鑷畾涔塴ookup鏌ヨ
+        // function searchContact(contactNodeId){
+        //     let accountValue = "";
+        //     if (document.querySelector("[data-id='AccountId']")) {
+        //         let accountNodeId = document.querySelector("[data-id='AccountId']").id + '_lkid';
+        //         accountValue = document.getElementById(accountNodeId).value;   
+        //     } 
+        //     console.log(accountValue);
+        //     if(accountValue !='000000000000000'){
+        //         let baseUrl = "/apex/SearchContactPage";
+        //         let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
+        //         let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+        //         newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+        //         if (window.focus) {
+        //             newSearchContactWindow.focus();
+        //         }
+        //         return false;
+        //     }else{
+        //         alertErrorMessage('{!PIPL_Input_Account_Error_Msg}');
+        //     }
+        // }
+
+        // function closePopupWindow() {
+        //     if (null != newSearchContactWindow) {
+        //         newSearchContactWindow.close();
+        //     }
+        //     let contactInfoStr = document.getElementById('page:form:contactId').value;
+        //     console.log('closePopup:'+contactInfoStr);
+        //     let contactInfo = JSON.parse(contactInfoStr);
+        //     let contactNodeId = document.querySelector("[data-id='Contact__c']").id + '_lkid';
+        //     document.getElementById(contactNodeId).value = contactInfo.ContactId;
+        //     document.querySelector("[data-id='Contact__c']").value = contactInfo.Name;     
+        // }
+    </script>
+    <div class="bPageTitle">
+        <div class="ptBody">
+            <div class="content">
+                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
+                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
+                    <span class="titleSeparatingColon">:</span>
+                </h1>
+                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
+                <div class="blank">&nbsp;</div>
+            </div>
+            <div class="links">
+                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
+                    title="姝ら〉闈㈢殑甯姪 锛堟柊绐楀彛锛�">
+                    <span class="helpLink">姝ら〉闈㈢殑甯姪</span>
+                    <img src="/img/s.gif" alt="" class="helpIcon" />
+                </a>
+            </div>
+        </div>
+        <div class="ptBreadcrumb"></div>
+    </div>
+    <apex:form id="form">
+        <!-- <apex:inputHidden value="{!contactId}" id="contactId"/> -->
+        <apex:pageblock id="block">
+            <div class="pbHeader">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
+                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
+                            </td>
+                            <td class="pbButton" id="topButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+            <!-- Error Msg-->
+            <div style="text-align: center;">
+                <apex:outputPanel id="errorMsg">
+                    <apex:pageMessages id="msgContent" escape="false" />
+                </apex:outputPanel>
+            </div>
+            
+            <!-- Iterate the layoutSections, which is a list of sections -->
+            <apex:repeat value="{!layoutSections}" var="layoutSection">
+                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
+                    
+                    <!--Each section has layoutFields, let's iterate them as well-->
+                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
+                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!loaner_user__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
+                                        required="{!layoutField.isRequired}" />
+                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
+                        </apex:pageblocksectionitem>
+                    </apex:repeat>
+                    
+                </apex:pageBlockSection>
+            </apex:repeat>
+            <script>
+            var init_nodes = document.getElementsByClassName("PIBackApi");
+            var api_id_map={};
+            for(let e of init_nodes){
+                if(IsFormElement(e)){
+                    api_id_map[GetEleApiName(e)] = e.id;
+                }
+            }
+            console.log(api_id_map);
+            sfdcPage.appendToOnloadQueue(function () {
+                //1. Set Last Name label
+                //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '濮撳悕';
+                //2. Query AWS Data by dataId 
+                console.log('Mode for Sobject Page:' + {!isNewMode});
+                if (!{!isNewMode}) {
+                    blockme();
+                    QuerySobjectFromAWS();
+                }
+                //Replace Vlookup Field
+                // replaceSearchContactLookup();
+                //3. Set Readonly Attribute
+                // document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
+                // document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
+            });
+            </script>
+            <div class="pbBottomButtons">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
+                            <td class="pbButtonb" id="bottomButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </apex:pageblock>
+
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditLoanerUser.page-meta.xml b/force-app/main/default/pages/NewAndEditLoanerUser.page-meta.xml
new file mode 100644
index 0000000..f8a6f0d
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditLoanerUser.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditLoanerUser</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewAndEditOpportunity.page b/force-app/main/default/pages/NewAndEditOpportunity.page
new file mode 100644
index 0000000..fbf90ea
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditOpportunity.page
@@ -0,0 +1,559 @@
+<!--
+    @description       : 
+    @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+    @group             : 
+    @last modified on  : 03-08-2022
+    @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="Opportunity" extensions="NewAndEditOpportunityController" id="page">
+  <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
+    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
+    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
+    <style>
+        .disabledbutton {
+            pointer-events: none;
+            opacity: 0.4;
+        }
+    </style>
+    <script>
+        
+        var config = {};
+        config = {
+            SobjectName : "{!SobjectName}",
+            ApiPrefix:"{!ApiPrefix}",
+            SaveAndNew:false,
+            AWSToSobjectMap:{!AWSToSobjectMapJson},
+            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
+            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
+            SobjectToAWSModel:function (sobjJson) {
+                let leadPayloadList = [];
+                let leadPIData = {};
+
+                for(let f in config.AWSToSobjectMap){
+                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
+                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
+                    }
+                    else{
+                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
+                    }
+                } 
+
+                leadPIData.sfRecordId = '';
+                console.log('Sobject PI Data:' + leadPIData);
+                leadPayloadList.push(leadPIData);
+                console.log(JSON.stringify(leadPayloadList));
+                return JSON.stringify(leadPayloadList);
+            },
+            insertOrUpdateBack:function(payloadJson, r, isNewMode){
+                
+                for(let f in config.AWSToSobjectMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+
+                for(let f in config.AWSToSobjectEncryptedMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+                
+                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                if (isNewMode) {
+                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                } else {
+                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                }
+                return payloadJson;
+            },
+            queryBack:function (data) {
+                console.log('data = ' + data);
+                if(data.object){
+                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
+                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
+                        if(data.object.hasOwnProperty(f) && ele){
+                            
+                            // 澶氶�夌壒娈婂鐞�
+                            if(ele.type == 'select-multiple'){
+                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
+                                if(ele && data.object[f]){
+                                    let arr = data.object[f].split(';');
+
+                                   // 缁欓殣钘忕殑select璧嬪��
+                                    for(let op of ele.options){
+                                        op.selected = arr.indexOf(op.value)>-1;
+                                    }
+                                    
+                                    // 鍒╃敤鎸夐挳缁欐樉绀虹殑select璧嬪��
+                                    let ra = document.getElementById(ele.id + '_right_arrow');
+                                    if(ra){
+                                        ra.click();
+                                    }
+                                    
+                                }
+                            }else{
+                                ele.value = data.object[f];
+                            }
+
+                            if(ele.type.indexOf("select")>-1 && ele.value){
+                                jQuery(ele).change()
+                            }
+                            
+                        }
+                        else{
+                            console.log(f + 'is not in data.object');
+                        }
+                    }
+                }
+                else{
+                    console.log('data.object = ' + data.object);
+                }
+                
+
+                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                // document.querySelector("[data-id='Phone']").value = data.object.phone;
+                // document.querySelector("[data-id='Email']").value = data.object.email;
+            },
+            updateMethod:"NewAndEditOpportunityController.saveOpportunity",
+            insertMethod:"NewAndEditOpportunityController.saveOpportunity"
+        }
+    
+        AWSService.sfSessionId = '{!GETSESSIONID()}';
+        var staticResources = JSON.parse('{!staticResource}');
+        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
+        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
+        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
+        console.log('{!staticResource}');
+        var VLookUpFields = {! VLookUpFieldsJson};
+        function ProcessPI(sobjJson, payloadForNewPI) {
+            blockme();
+            if ({!isNewMode}) {
+            	NewPIToAWS(sobjJson, payloadForNewPI)
+            }else {
+                UpdatePIToAWS(sobjJson, payloadForNewPI)
+            }
+        }
+
+        var GetEleByClass = function(class_name){
+            let eles = document.getElementsByClassName(class_name);
+            if(eles.length > 0) return eles[0];
+            return null;
+        }
+
+        var GetEleApiName = function(ele){
+            for(let c of ele.classList){
+                if(c.indexOf(config.ApiPrefix+'_')>-1){
+                    return c.replace(config.ApiPrefix+'_','');
+                }
+            }
+            return '';
+        }
+
+        function IsFormTag(tag_name){
+            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
+        }
+    	
+    	function IsFormElement(e){
+            return IsFormTag(e.tagName);
+        }
+
+        function getPIPayload(sobjJson) {
+            return config.SobjectToAWSModel(sobjJson);
+        }
+
+        function validateFieldValueFormate() {
+            let error_msg = '';
+            let textEmail = "[data-id='Email']";
+            let textPhone = "[data-id='MobilePhone']";
+            //Email
+            let email = document.querySelector(textEmail);
+            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
+                error_msg += ';閭欢鏍煎紡閿欒';
+            }
+            let phone = document.querySelector(textPhone);
+
+            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
+                error_msg += ';鐢佃瘽鍙风爜閿欒';
+            }
+
+            for(let e of document.getElementsByTagName('select')){
+                for(let op of e.options){
+                    if(op.value == "*****" && op.selected){
+                        error_msg += ';涓嬫媺妗嗕笉鑳戒富鍔ㄩ�夋嫨瀵嗘枃閫夐」';
+                    }
+                }
+            }
+
+            if(error_msg.length>0 && error_msg[0]== ';'){
+                error_msg = error_msg.substring(1);
+            }
+
+            return error_msg;
+        }
+
+        function getSobjectInformation() {
+            //api_id_map
+//let nodelist = document.getElementsByClassName(config.ApiPrefix);
+            let result = {}
+            for (let index in api_id_map) {
+                let ele = document.getElementById(api_id_map[index]);
+                let field_api_name = index;
+                let tag_name = ele.tagName.toLowerCase();
+                if(!IsFormTag(tag_name)){
+                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
+                    continue;
+                }
+
+                if (VLookUpFields.indexOf(field_api_name)>=0) {
+                    console.log(ele.id.indexOf('lkwgt'));
+                    if (ele.id.indexOf('lkwgt') == -1) {
+                        let vlookUpNodeId = ele.id + '_lkid';
+                        let vlook_ele = document.getElementById(vlookUpNodeId);
+                        let v = '';
+                        if(vlook_ele){
+                            v = vlook_ele.value;
+                        }else{
+                            v = ele.value;
+                        }
+
+                        if(v && v != "000000000000000"){
+                            result[field_api_name] = v;
+                        }
+                        
+                    }
+                } else if (ele.type == 'checkbox') {
+                    result[field_api_name] = ele.checked;
+                } else if (ele.type == 'select-multiple') {
+                    //field_api_name
+                    let multiple = field_api_name;
+                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
+                    targets = targets.replace(/\n/g, ";");
+                    console.log('targets = ' + targets);
+                    result[field_api_name] = targets;
+                } else {
+                    result[field_api_name] = ele.value;
+                }
+            }
+            return result;
+        }
+        function QuerySobjectFromAWS() {
+            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+        }
+        function queryBack(data) {
+            console.log('data = ' + data);
+            config.queryBack(data);
+            unblockUI();
+        };
+
+
+        function insertOrUpdateBack(payloadJson, result, isNewMode) {
+            console.log(result);
+            let r = result;
+            console.log('Result from AWS' + r);
+            console.log('payloadJson=' + payloadJson);
+            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
+        }
+
+        function redirectCallBack(sfId,errorMsg) {
+            unblockUI();
+            if(errorMsg){
+                alertErrorMessage(errorMsg);
+            }
+            else{
+                if(config.SaveAndNew){
+                    window.open('{! SaveAndNewButtonUrl }','_self');
+                }else{
+                    window.open('/' + sfId, '_self');
+                }
+            }
+            
+        }
+
+        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.updateMethod;
+            let obj = JSON.parse(payloadForNewPI);
+            obj[0].dataId = '{!AWSDataId}';
+            let payloadForNewPIJson = JSON.stringify(obj);
+            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
+            
+        }
+
+        function NewPIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.insertMethod;
+            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
+            
+        }
+        
+
+        function checkRequiredFieldMsg(formData) {
+            let blankRequiredFields = '';
+            for(i = 0;i<requiredFieldAPIList.length;i++){
+                if(formData[requiredFieldAPIList[i]]){
+                    continue;
+                }else{
+                    if(blankRequiredFields == ''){
+                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }else{
+                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }
+                    
+                }
+            }
+            return blankRequiredFields;
+        }
+        
+        function saveSobjectProcess(save_and_new) {
+            if(save_and_new){
+                config.SaveAndNew = true;
+            }
+            
+            hiddenErrorMsgNode();
+            //1. Get Sobject Information from Form
+            let sobjJson = getSobjectInformation();
+            //2. Validate the Sobject field value formate, for example the email formate or phone formate
+
+            let validationResultMessage = validateFieldValueFormate();
+            console.log(validationResultMessage);
+            if (validationResultMessage) {
+                //Popup error message.  - To Do After POC
+                alertErrorMessage(validationResultMessage);
+                return
+            }
+            // Check Required Field
+            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
+            if (checkRequiredFieldMsgResult) {
+                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
+                return
+            }
+            // //3. Prepare the payload for New PI API To AWS - To Do
+            let payloadForNewPI = getPIPayload(sobjJson);
+
+            // //4. Get Authentication Information for AWS
+            // loadAWSAuthentication();
+
+            // //5. opportunity to AWS 
+            ProcessPI(sobjJson, payloadForNewPI);
+            // awsToken = TestToken;
+            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
+        }
+
+        function alertErrorMessage(errorMsg) {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = errorMsg;
+            errorMsgNode.className = 'pbError';
+        }
+        function hiddenErrorMsgNode() {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = '';
+            errorMsgNode.className = '';
+        }
+
+        //鏇挎崲vlookup
+        var newSearchContactWindow = null;  
+        var closeField = '';
+
+        function replaceSearchContactLookup() {
+            if (!{!isNewMode}) {
+                //1. Query Contact from AWS by AWSDataId
+                queryContactName()
+            }           
+            if(document.querySelector("[data-id='EndUser__c']") != null){
+                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'EndUser__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='EndUser__c']").parentNode;
+                document.querySelector("[data-id='EndUser__c']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='EndUser__c']").parentNode.children[2]);
+            }
+            // if(document.querySelector("[data-id='Applicanter__c']") != null){
+            //     let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Applicanter__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+            //     let lookUpNode = htmlToElement(contactHtmlString);
+            //     console.log(lookUpNode);
+            //     let parentNode = document.querySelector("[data-id='Applicanter__c']").parentNode;
+            //     document.querySelector("[data-id='Applicanter__c']").removeAttribute("onchange");
+            //     parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Applicanter__c']").parentNode.children[2]);
+            // }
+        }
+
+        function htmlToElement(html) {
+            var template = document.createElement('template');
+            html = html.trim(); // Never return a text node of whitespace as the result
+            template.innerHTML = html;
+            return template.content.firstChild;
+        }
+
+        function queryContactName() {
+            let sfId = document.getElementById(document.querySelector("[data-id='EndUser__c']").id + '_lkid').value;
+            let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
+            let dataId = contactsInfo[sfId];
+            let queryContactBack = function(data){
+                //To Do later
+                console.log('ContactData = ' + data.object);
+                
+                document.querySelector("[data-id='EndUser__c']").value = data.object.lastName;
+            }
+            AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
+            // queryContactNameFetch(dataId, 'EndUser__c');
+        }
+        
+        // function queryContactNameFetch(dataId, filedId){
+        //     let queryContactBack = function(data){
+        //         //To Do later
+        //         console.log('ContactData = ' + data.object);
+                
+        //         document.querySelector("[data-id="+filedId+"]").value = data.object.lastName;
+        //     }
+        //     AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
+        // }
+
+        
+        //鑷畾涔塴ookup鏌ヨ
+        function searchContact(contactNodeId,field){
+            closeField = field;
+            let accountValue = "";
+            if (document.querySelector("[data-id='AccountId']")) {
+                let accountNodeId = document.querySelector("[data-id='AccountId']").id + '_lkid';
+                accountValue = document.getElementById(accountNodeId).value;   
+            } 
+            console.log(accountValue);
+            if(accountValue !='000000000000000'){
+                let baseUrl = "/apex/SearchContactPage";
+                let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
+                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                if (window.focus) {
+                    newSearchContactWindow.focus();
+                }
+                return false;
+            }else{
+                alertErrorMessage('{!PIPL_Input_Account_Error_Msg}');
+            }
+        }
+
+        function closePopupWindow() {
+            if (null != newSearchContactWindow) {
+                newSearchContactWindow.close();
+            }
+            let contactInfoStr = document.getElementById('page:form:contactId').value;
+            console.log('closePopup:'+contactInfoStr);
+            let contactInfo = JSON.parse(contactInfoStr);
+            let contactNodeId = document.querySelector("[data-id="+closeField+"]").id + '_lkid';
+            document.getElementById(contactNodeId).value = contactInfo.ContactId;
+            document.querySelector("[data-id="+closeField+"]").value = contactInfo.Name;     
+        }
+    </script>
+    <div class="bPageTitle">
+        <div class="ptBody">
+            <div class="content">
+                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
+                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
+                    <span class="titleSeparatingColon">:</span>
+                </h1>
+                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
+                <div class="blank">&nbsp;</div>
+            </div>
+            <div class="links">
+                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
+                    title="姝ら〉闈㈢殑甯姪 锛堟柊绐楀彛锛�">
+                    <span class="helpLink">姝ら〉闈㈢殑甯姪</span>
+                    <img src="/img/s.gif" alt="" class="helpIcon" />
+                </a>
+            </div>
+        </div>
+        <div class="ptBreadcrumb"></div>
+    </div>
+    <apex:form id="form">
+        <apex:inputHidden value="{!contactId}" id="contactId"/>
+        <apex:pageblock id="block">
+            <div class="pbHeader">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
+                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
+                            </td>
+                            <td class="pbButton" id="topButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+            <!-- Error Msg-->
+            <div style="text-align: center;">
+                <apex:outputPanel id="errorMsg">
+                    <apex:pageMessages id="msgContent" escape="false" />
+                </apex:outputPanel>
+            </div>
+            
+            <!-- Iterate the layoutSections, which is a list of sections -->
+            <apex:repeat value="{!layoutSections}" var="layoutSection">
+                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
+                    
+                    <!--Each section has layoutFields, let's iterate them as well-->
+                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
+                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Opportunity[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
+                                         required="{!layoutField.isRequired}" />
+                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
+                        </apex:pageblocksectionitem>
+                    </apex:repeat>
+                    
+                </apex:pageBlockSection>
+            </apex:repeat>
+            <script>
+            var init_nodes = document.getElementsByClassName("PIBackApi");
+            var api_id_map={};
+            for(let e of init_nodes){
+            	if(IsFormElement(e)){
+                	 api_id_map[GetEleApiName(e)] = e.id;
+                }
+            }
+            console.log(api_id_map);
+            sfdcPage.appendToOnloadQueue(function () {
+                //1. Set Last Name label
+                //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '濮撳悕';
+                //2. Query AWS Data by dataId 
+                console.log('Mode for Sobject Page:' + {!isNewMode});
+                if (!{!isNewMode}) {
+                    blockme();
+                    QuerySobjectFromAWS();
+                }
+                //Replace Vlookup Field
+                replaceSearchContactLookup();
+                //3. Set Readonly Attribute
+                document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
+                document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
+            });
+            </script>
+            <div class="pbBottomButtons">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
+                            <td class="pbButtonb" id="bottomButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </apex:pageblock>
+
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditOpportunity.page-meta.xml b/force-app/main/default/pages/NewAndEditOpportunity.page-meta.xml
new file mode 100644
index 0000000..d75751f
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditOpportunity.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditOpportunity</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewAndEditOrder.page b/force-app/main/default/pages/NewAndEditOrder.page
new file mode 100644
index 0000000..4153dd7
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditOrder.page
@@ -0,0 +1,728 @@
+<!--
+@description       : 
+@author            : ChangeMeIn@UserSettingsUnder.SFDoc
+@group             : 
+@last modified on  : 03-08-2022
+@last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="Order" extensions="NewAndEditOrderController" id="page">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
+    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
+    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
+    <style>
+        .disabledbutton {
+            pointer-events: none;
+            opacity: 0.4;
+        }
+    </style>
+    <script>
+        
+        var config = {};
+        config = {
+            SobjectName : "{!SobjectName}",
+            ApiPrefix:"{!ApiPrefix}",
+            SaveAndNew:false,
+            AWSToSobjectMap:{!AWSToSobjectMapJson},
+            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
+            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
+            SobjectToAWSModel:function (sobjJson) {
+                let leadPayloadList = [];
+                let leadPIData = {};
+
+                for(let f in config.AWSToSobjectMap){
+                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
+                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
+                    }
+                    else{
+                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
+                    }
+                } 
+
+                leadPIData.medicalStaffFullName = leadPIData.lastName;// 瀹屾垚field update workflow
+                leadPIData.sfRecordId = '';
+                console.log('Sobject PI Data:' + leadPIData);
+                leadPayloadList.push(leadPIData);
+                console.log(JSON.stringify(leadPayloadList));
+                return JSON.stringify(leadPayloadList);
+            },
+            insertOrUpdateBack:function(payloadJson, r, isNewMode){
+                
+                for(let f in config.AWSToSobjectMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+
+                for(let f in config.AWSToSobjectEncryptedMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+                
+                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                if (isNewMode) {
+                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                } else {
+                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                }
+                return payloadJson;
+            },
+            queryBack:function (data) {
+                console.log('data = ' + data);
+                if(data.object){
+                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
+                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
+                        if(data.object.hasOwnProperty(f) && ele){
+                            
+                            // 澶氶�夌壒娈婂鐞�
+                            if(ele.type == 'select-multiple'){
+                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
+                            if(ele && data.object[f]){
+                                let arr = data.object[f].split(';');
+
+                                // 缁欓殣钘忕殑select璧嬪��
+                                for(let op of ele.options){
+                                    op.selected = arr.indexOf(op.value)>-1;
+                                }
+                                
+                                // 鍒╃敤鎸夐挳缁欐樉绀虹殑select璧嬪��
+                                let ra = document.getElementById(ele.id + '_right_arrow');
+                                if(ra){
+                                    ra.click();
+                                }
+                                
+                            }
+                            }else{
+                                ele.value = data.object[f];
+                            }
+
+                            if(ele.type.indexOf("select")>-1 && ele.value){
+                                jQuery(ele).change()
+                            }
+                            
+                        }
+                        else{
+                            console.log(f + 'is not in data.object');
+                        }
+                    }
+                }
+                else{
+                    console.log('data.object = ' + data.object);
+                }
+                
+
+                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                // document.querySelector("[data-id='Phone']").value = data.object.phone;
+                // document.querySelector("[data-id='Email']").value = data.object.email;
+            },
+            updateMethod:"NewAndEditOrderController.saveOrder",
+            insertMethod:"NewAndEditOrderController.saveOrder"
+        }
+    
+        AWSService.sfSessionId = '{!GETSESSIONID()}';
+        var staticResources = JSON.parse('{!staticResource}');
+        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
+        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
+        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
+        console.log('{!staticResource}');
+        var VLookUpFields = {! VLookUpFieldsJson};
+        function ProcessPI(sobjJson, payloadForNewPI) {
+            blockme();
+            if ({!isNewMode}) {
+                NewPIToAWS(sobjJson, payloadForNewPI)
+            }else {
+                UpdatePIToAWS(sobjJson, payloadForNewPI)
+            }
+        }
+
+        var GetEleByClass = function(class_name){
+            let eles = document.getElementsByClassName(class_name);
+            if(eles.length > 0) return eles[0];
+            return null;
+        }
+
+        var GetEleApiName = function(ele){
+            for(let c of ele.classList){
+                if(c.indexOf(config.ApiPrefix+'_')>-1){
+                    return c.replace(config.ApiPrefix+'_','');
+                }
+            }
+            return '';
+        }
+
+        function IsFormTag(tag_name){
+            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
+        }
+        
+        function IsFormElement(e){
+            return IsFormTag(e.tagName);
+        }
+
+        function getPIPayload(sobjJson) {
+            return config.SobjectToAWSModel(sobjJson);
+        }
+
+        function validateFieldValueFormate() {
+            let error_msg = '';
+            let textEmail = "[data-id='Email']";
+            let textPhone = "[data-id='MobilePhone']";
+            //Email
+            let email = document.querySelector(textEmail);
+            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
+                error_msg += ';閭欢鏍煎紡閿欒';
+            }
+            let phone = document.querySelector(textPhone);
+
+            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
+                error_msg += ';鐢佃瘽鍙风爜閿欒';
+            }
+
+            for(let e of document.getElementsByTagName('select')){
+                for(let op of e.options){
+                    if(op.value == "*****" && op.selected){
+                        error_msg += ';涓嬫媺妗嗕笉鑳戒富鍔ㄩ�夋嫨瀵嗘枃閫夐」';
+                    }
+                }
+            }
+
+            if(error_msg.length>0 && error_msg[0]== ';'){
+                error_msg = error_msg.substring(1);
+            }
+
+            return error_msg;
+        }
+
+        function getSobjectInformation() {
+            //api_id_map
+//let nodelist = document.getElementsByClassName(config.ApiPrefix);
+            let result = {}
+            for (let index in api_id_map) {
+                let ele = document.getElementById(api_id_map[index]);
+                let field_api_name = index;
+                let tag_name = ele.tagName.toLowerCase();
+                if(!IsFormTag(tag_name)){
+                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
+                    continue;
+                }
+
+                if (VLookUpFields.indexOf(field_api_name)>=0) {
+                    console.log(ele.id.indexOf('lkwgt'));
+                    if (ele.id.indexOf('lkwgt') == -1) {
+                        let vlookUpNodeId = ele.id + '_lkid';
+                        let vlook_ele = document.getElementById(vlookUpNodeId);
+                        let v = '';
+                        if(vlook_ele){
+                            v = vlook_ele.value;
+                        }else{
+                            v = ele.value;
+                        }
+
+                        if(v && v != "000000000000000"){
+                            result[field_api_name] = v;
+                        }
+                        
+                    }
+                } else if (ele.type == 'checkbox') {
+                    result[field_api_name] = ele.checked;
+                } else if (ele.type == 'select-multiple') {
+                    //field_api_name
+                    let multiple = field_api_name;
+                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
+                    targets = targets.replace(/\n/g, ";");
+                    console.log('targets = ' + targets);
+                    result[field_api_name] = targets;
+                } else {
+                    result[field_api_name] = ele.value;
+                }
+                
+                // let e1 = document.getElementById(api_id_map[field_api_name]);
+                // if(!result[field_api_name] && e1 && e1.value){
+                //  result[field_api_name] = e1.value;
+                // }
+            }
+            return result;
+        }
+        function QuerySobjectFromAWS() {
+            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+        }
+        function queryBack(data) {
+            console.log('data = ' + data);
+            config.queryBack(data);
+            unblockUI();
+        };
+
+
+        function insertOrUpdateBack(payloadJson, result, isNewMode) {
+            console.log(result);
+            let r = result;
+            console.log('Result from AWS' + r);
+            console.log('payloadJson=' + payloadJson);
+            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
+        }
+
+        function redirectCallBack(sfId,errorMsg) {
+            unblockUI();
+            if(errorMsg){
+                alertErrorMessage(errorMsg);
+            }
+            else{
+                if(config.SaveAndNew){
+                    window.open('{! SaveAndNewButtonUrl }','_self');
+                }else{
+                    window.open('/' + sfId, '_self');
+                }
+            }
+            
+        }
+
+        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.updateMethod;
+            let obj = JSON.parse(payloadForNewPI);
+            obj[0].dataId = '{!AWSDataId}';
+            let payloadForNewPIJson = JSON.stringify(obj);
+            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
+            
+        }
+
+        function NewPIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.insertMethod;
+            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
+            
+        }
+        
+
+        function checkRequiredFieldMsg(formData) {
+            let blankRequiredFields = '';
+            for(i = 0;i<requiredFieldAPIList.length;i++){
+                if(formData[requiredFieldAPIList[i]]){
+                    continue;
+                }else{
+                    if(blankRequiredFields == ''){
+                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }else{
+                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }
+                    
+                }
+            }
+            return blankRequiredFields;
+        }
+        function saveSobjectProcess(save_and_new) {
+            if(save_and_new){
+                config.SaveAndNew = true;
+            }
+            
+            hiddenErrorMsgNode();
+            //1. Get Sobject Information from Form
+            let sobjJson = getSobjectInformation();
+            //2. Validate the Sobject field value formate, for example the email formate or phone formate
+
+            let validationResultMessage = validateFieldValueFormate();
+            console.log(validationResultMessage);
+            if (validationResultMessage) {
+                //Popup error message.  - To Do After POC
+                alertErrorMessage(validationResultMessage);
+                return
+            }
+            // Check Required Field
+            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
+            if (checkRequiredFieldMsgResult) {
+                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
+                return
+            }
+            // //3. Prepare the payload for New PI API To AWS - To Do
+            let payloadForNewPI = getPIPayload(sobjJson);
+
+            // //4. Get Authentication Information for AWS
+            // loadAWSAuthentication();
+
+            // //5. lead to AWS 
+            ProcessPI(sobjJson, payloadForNewPI);
+            // awsToken = TestToken;
+            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
+        }
+
+        function alertErrorMessage(errorMsg) {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = errorMsg;
+            errorMsgNode.className = 'pbError';
+        }
+        function hiddenErrorMsgNode() {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = '';
+            errorMsgNode.className = '';
+        }
+
+        //鏇挎崲vlookup
+        var newSearchContactWindow = null;
+        var closeField = '';
+
+        function replaceSearchContactLookup() {
+            let contactHtmlString = '';
+            if (!{!isNewMode}) {
+                //1. Query Contact from AWS by AWSDataId
+                queryContactName()
+            }           
+            if(document.querySelector("[data-id='EndUserD__c']") != null){
+                contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\', \'EndUserD__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='EndUserD__c']").parentNode;
+                document.querySelector("[data-id='EndUserD__c']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='EndUserD__c']").parentNode.children[2]);
+            }
+            if(document.querySelector("[data-id='EndUser__c']") != null){
+                contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\', \'EndUser__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='EndUser__c']").parentNode;
+                document.querySelector("[data-id='EndUser__c']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='EndUser__c']").parentNode.children[2]);
+            }
+            if(document.querySelector("[data-id='ShipToContactId']") != null){
+                contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\', \'ShipToContactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='ShipToContactId']").parentNode;
+                document.querySelector("[data-id='ShipToContactId']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='ShipToContactId']").parentNode.children[2]);
+            }
+            if(document.querySelector("[data-id='SpecialDeliveryContact2__c']") != null){
+                contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\', \'SpecialDeliveryContact2__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='SpecialDeliveryContact2__c']").parentNode;
+                document.querySelector("[data-id='SpecialDeliveryContact2__c']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='SpecialDeliveryContact2__c']").parentNode.children[2]);
+            }
+            if(document.querySelector("[data-id='SpecialDeliveryContact2_D__c']") != null){
+                contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\', \'SpecialDeliveryContact2_D__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='SpecialDeliveryContact2_D__c']").parentNode;
+                document.querySelector("[data-id='SpecialDeliveryContact2_D__c']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='SpecialDeliveryContact2_D__c']").parentNode.children[2]);
+            }
+        }
+
+        function htmlToElement(html) {
+            var template = document.createElement('template');
+            html = html.trim(); // Never return a text node of whitespace as the result
+            template.innerHTML = html;
+            return template.content.firstChild;
+        }
+
+        function queryContactName() { 
+            let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
+            if(document.querySelector("[data-id='EndUserD__c']") != null){
+                let sfId = document.getElementById(document.querySelector("[data-id='EndUserD__c']").id + '_lkid').value;
+                let dataId = contactsInfo[sfId];
+                let queryContactBack = function(data){
+                    console.log('ContactData = ' + data.object);//To Do later
+                    document.querySelector("[data-id='EndUserD__c']").value = data.object.lastName;
+                }
+                AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);   
+            }
+            if(document.querySelector("[data-id='EndUser__c']") != null){
+                let sfId = document.getElementById(document.querySelector("[data-id='EndUser__c']").id + '_lkid').value;
+                let dataId = contactsInfo[sfId];
+                let queryContactBack = function(data){
+                    console.log('ContactData = ' + data.object);//To Do later
+                    document.querySelector("[data-id='EndUser__c']").value = data.object.lastName;
+                }
+                AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);   
+            }
+            if(document.querySelector("[data-id='ShipToContactId']") != null){
+                let sfId = document.getElementById(document.querySelector("[data-id='ShipToContactId']").id + '_lkid').value;
+                let dataId = contactsInfo[sfId];
+                let queryContactBack = function(data){
+                    console.log('ContactData = ' + data.object);//To Do later
+                    document.querySelector("[data-id='ShipToContactId']").value = data.object.lastName;
+                }
+                AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);   
+            }
+            if(document.querySelector("[data-id='SpecialDeliveryContact2__c']") != null){
+                let sfId = document.getElementById(document.querySelector("[data-id='SpecialDeliveryContact2__c']").id + '_lkid').value;
+                let dataId = contactsInfo[sfId];
+                let queryContactBack = function(data){
+                    console.log('ContactData = ' + data.object);//To Do later
+                    document.querySelector("[data-id='SpecialDeliveryContact2__c']").value = data.object.lastName;
+                }
+                AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);   
+            }
+            if(document.querySelector("[data-id='SpecialDeliveryContact2_D__c']") != null){
+                let sfId = document.getElementById(document.querySelector("[data-id='SpecialDeliveryContact2_D__c']").id + '_lkid').value;
+                let dataId = contactsInfo[sfId];
+                let queryContactBack = function(data){
+                    console.log('ContactData = ' + data.object);//To Do later
+                    document.querySelector("[data-id='SpecialDeliveryContact2_D__c']").value = data.object.lastName;
+                }
+                AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);   
+            }
+        }
+       
+        
+        //鑷畾涔塴ookup鏌ヨ 
+        function searchContact(contactNodeId, field){
+            closeField = field;
+            if(field == 'SpecialDeliveryContact2__c'){
+                let accountValue = "";
+                let SpecialDeliveryAccountValue = "";
+                let SpecialDeliveryAccountNodeId = "";
+                let ForeignTradeCompanyValue = "";
+                let ForeignTradeCompanyNodeId = "";
+                if (document.querySelector("[data-id='SpecialDeliveryAccount__c']")) {
+                    SpecialDeliveryAccountNodeId = document.querySelector("[data-id='SpecialDeliveryAccount__c']").id + '_lkid';
+                    console.log('SpecialDeliveryAccountNodeId: ' + SpecialDeliveryAccountNodeId);
+                	SpecialDeliveryAccountValue = document.getElementById(SpecialDeliveryAccountNodeId).value;
+                	console.log(SpecialDeliveryAccountValue);
+                    if (SpecialDeliveryAccountValue!= '' && SpecialDeliveryAccountValue != '000000000000000'){
+                    	accountValue = ',' + SpecialDeliveryAccountValue;
+                    }
+                }
+                if (document.querySelector("[data-id='ForeignTradeCompany__c']")) {
+                    ForeignTradeCompanyNodeId = document.querySelector("[data-id='ForeignTradeCompany__c']").id + '_lkid';
+                    console.log('ForeignTradeCompanyNodeId: ' + ForeignTradeCompanyNodeId);
+                	ForeignTradeCompanyValue = document.getElementById(ForeignTradeCompanyNodeId).value;
+                	console.log(ForeignTradeCompanyValue);
+                    if (ForeignTradeCompanyValue!= '' && ForeignTradeCompanyValue != '000000000000000'){
+                    	accountValue += ','+ForeignTradeCompanyValue;
+                    }
+                    accountValue = accountValue.substring(1);
+                }
+                if (accountValue != ''){
+                    let baseUrl = "/apex/SearchContactPage";
+                    let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
+                    let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+                    newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                    if (window.focus) {
+                        newSearchContactWindow.focus();
+                    }
+                    return false;
+                }else{
+                    let accountValue = "";
+                    if (SpecialDeliveryAccountValue != '000000000000000'){
+                    	accountValue = SpecialDeliveryAccountValue;
+                    }else {
+                    	accountValue = ForeignTradeCompanyValue;
+                    }
+                    let baseUrl = "/apex/SearchContactPage";
+                    let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
+                    let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+                    newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                    if (window.focus) {
+                        newSearchContactWindow.focus();
+                    }
+                    return false;
+                }  
+            } else if (field == 'SpecialDeliveryContact2_D__c'){
+                let accountValueD = "";
+                let SpecialDeliveryAccountDValue = "";
+                let SpecialDeliveryAccountDNodeId = "";
+                let ForeignTradeCompanyDValue = "";
+                let ForeignTradeCompanyDNodeId = "";
+                if (document.querySelector("[data-id='SpecialDeliveryAccount_D__c']")) {
+                    SpecialDeliveryAccountDNodeId = document.querySelector("[data-id='SpecialDeliveryAccount_D__c']").id + '_lkid';
+                    console.log('SpecialDeliveryAccountDNodeId: ' + SpecialDeliveryAccountDNodeId);
+                	SpecialDeliveryAccountDValue = document.getElementById(SpecialDeliveryAccountDNodeId).value;
+                	console.log(SpecialDeliveryAccountDValue);
+                    if (SpecialDeliveryAccountDValue!= '' && SpecialDeliveryAccountDValue != '000000000000000'){
+                    	accountValueD = ',' + SpecialDeliveryAccountDValue;
+                    }
+                }
+                if (document.querySelector("[data-id='ForeignTradeCompany_D__c']")) {
+                    ForeignTradeCompanyDNodeId = document.querySelector("[data-id='ForeignTradeCompany_D__c']").id + '_lkid';
+                    console.log('ForeignTradeCompanyDNodeId: ' + ForeignTradeCompanyDNodeId);
+                	ForeignTradeCompanyDValue = document.getElementById(ForeignTradeCompanyDNodeId).value;
+                	console.log(ForeignTradeCompanyDValue);
+                    if (ForeignTradeCompanyDValue!= '' && ForeignTradeCompanyDValue != '000000000000000'){
+                    	accountValueD += ','+ForeignTradeCompanyDValue;
+                    }
+                    accountValueD = accountValueD.substring(1);
+                }
+                if (accountValueD != ''){
+                    let baseUrl = "/apex/SearchContactPage";
+                    let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValueD;
+                    let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+                    newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                    if (window.focus) {
+                        newSearchContactWindow.focus();
+                    }
+                    return false;
+                }else{
+                    let accountValueD = "";
+                    if (SpecialDeliveryAccountDValue != '000000000000000'){
+                    	accountValueD = SpecialDeliveryAccountDValue;
+                    }else {
+                    	accountValueD = ForeignTradeCompanyDValue;
+                    }
+                    let baseUrl = "/apex/SearchContactPage";
+                    let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValueD;
+                    let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+                    newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                    if (window.focus) {
+                        newSearchContactWindow.focus();
+                    }
+                    return false;
+                }  
+            } else {
+                let baseUrl = "/apex/SearchContactPage";
+                let suffixUrl = "?contactId="+contactNodeId;
+                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                if (window.focus) {
+                    newSearchContactWindow.focus();
+                }
+                return false;
+            }
+            
+        }
+
+        function closePopupWindow() {
+            if (null != newSearchContactWindow) {
+                newSearchContactWindow.close();
+            }
+            if(document.querySelector("[data-id='SpecialDeliveryContact2__c']") != null){
+                if (null != newSearchContactWindow) {
+                    newSearchContactWindow.close();
+                }
+                let contactInfoStr = document.getElementById('page:form:contactId').value;
+                console.log('closePopup:'+contactInfoStr);
+                let contactInfo = JSON.parse(contactInfoStr);
+                let contactNodeId = document.querySelector("[data-id="+closeField+"]").id + '_lkid';
+                document.getElementById(contactNodeId).value = contactInfo.ContactId;
+                document.querySelector("[data-id="+closeField+"]").value = contactInfo.Name;
+            } 
+            if(document.querySelector("[data-id='SpecialDeliveryContact2_D__c']") != null){
+                if (null != newSearchContactWindow) {
+                    newSearchContactWindow.close();
+                }
+                let contactInfoStr = document.getElementById('page:form:contactId').value;
+                console.log('closePopup:'+contactInfoStr);
+                let contactInfo = JSON.parse(contactInfoStr);
+                let contactNodeId = document.querySelector("[data-id="+closeField+"]").id + '_lkid';
+                document.getElementById(contactNodeId).value = contactInfo.ContactId;
+                document.querySelector("[data-id="+closeField+"]").value = contactInfo.Name;
+            } 
+        }
+
+        
+    </script>
+    <div class="bPageTitle">
+        <div class="ptBody">
+            <div class="content">
+                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
+                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
+                    <span class="titleSeparatingColon">:</span>
+                </h1>
+                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
+                <div class="blank">&nbsp;</div>
+            </div>
+            <div class="links">
+                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
+                    title="姝ら〉闈㈢殑甯姪 锛堟柊绐楀彛锛�">
+                    <span class="helpLink">姝ら〉闈㈢殑甯姪</span>
+                    <img src="/img/s.gif" alt="" class="helpIcon" />
+                </a>
+            </div>
+        </div>
+        <div class="ptBreadcrumb"></div>
+    </div>
+    <apex:form id="form">
+        <apex:inputHidden value="{!contactId}" id="contactId"/>
+        <apex:pageblock id="block">
+            <div class="pbHeader">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
+                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
+                            </td>
+                            <td class="pbButton" id="topButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+            <!-- Error Msg-->
+            <div style="text-align: center;">
+                <apex:outputPanel id="errorMsg">
+                    <apex:pageMessages id="msgContent" escape="false" />
+                </apex:outputPanel>
+            </div>
+            
+            <!-- Iterate the layoutSections, which is a list of sections -->
+            <apex:repeat value="{!layoutSections}" var="layoutSection">
+                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
+                    
+                    <!--Each section has layoutFields, let's iterate them as well-->
+                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
+                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Order[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
+                                        required="{!layoutField.isRequired}" />
+                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
+                        </apex:pageblocksectionitem>
+                    </apex:repeat>
+                    
+                </apex:pageBlockSection>
+            </apex:repeat>
+            <script>
+            var init_nodes = document.getElementsByClassName("PIBackApi");
+            var api_id_map={};
+            for(let e of init_nodes){
+                if(IsFormElement(e)){
+                    api_id_map[GetEleApiName(e)] = e.id;
+                }
+            }
+            console.log(api_id_map);
+            sfdcPage.appendToOnloadQueue(function () {
+                //1. Set Last Name label
+                //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '濮撳悕';
+                //2. Query AWS Data by dataId 
+                console.log('Mode for Sobject Page:' + {!isNewMode});
+                if (!{!isNewMode}) {
+                    blockme();
+                    QuerySobjectFromAWS();
+                }
+
+                //Replace Vlookup Field
+                replaceSearchContactLookup();
+                //3. Set Readonly Attribute
+                document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
+                document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
+                
+                
+            });
+            </script>
+            <div class="pbBottomButtons">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
+                            <td class="pbButtonb" id="bottomButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </apex:pageblock>
+
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditOrder.page-meta.xml b/force-app/main/default/pages/NewAndEditOrder.page-meta.xml
new file mode 100644
index 0000000..78872ae
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditOrder.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditOrder</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewAndEditQuotes.page b/force-app/main/default/pages/NewAndEditQuotes.page
new file mode 100644
index 0000000..0115141
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditQuotes.page
@@ -0,0 +1,547 @@
+<!--
+  @description       : 
+  @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+  @group             : 
+  @last modified on  : 03-04-2022
+  @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="Quotes__c" extensions="NewAndEditQuotesController" id="page">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
+    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
+    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
+    <style>
+        .disabledbutton {
+            pointer-events: none;
+            opacity: 0.4;
+        }
+    </style>
+    <script>
+        
+        var config = {};
+        config = {
+            SobjectName : "{!SobjectName}",
+            ApiPrefix:"{!ApiPrefix}",
+            SaveAndNew:false,
+            AWSToSobjectMap:{!AWSToSobjectMapJson},
+            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
+            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
+            SobjectToAWSModel:function (sobjJson) {
+                let leadPayloadList = [];
+                let leadPIData = {};
+
+                for(let f in config.AWSToSobjectMap){
+                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
+                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
+                    }
+                    else{
+                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
+                    }
+                } 
+
+                leadPIData.medicalStaffFullName = leadPIData.lastName;// 瀹屾垚field update workflow
+                leadPIData.sfRecordId = '';
+                console.log('Sobject PI Data:' + leadPIData);
+                leadPayloadList.push(leadPIData);
+                console.log(JSON.stringify(leadPayloadList));
+                return JSON.stringify(leadPayloadList);
+            },
+            insertOrUpdateBack:function(payloadJson, r, isNewMode){
+                
+                for(let f in config.AWSToSobjectMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+
+                for(let f in config.AWSToSobjectEncryptedMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+                
+                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                if (isNewMode) {
+                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                } else {
+                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                }
+                return payloadJson;
+            },
+            queryBack:function (data) {
+                console.log('data = ' + data);
+                if(data.object){
+                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
+                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
+                        if(data.object.hasOwnProperty(f) && ele){
+                            
+                            // 澶氶�夌壒娈婂鐞�
+                            if(ele.type == 'select-multiple'){
+                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
+                                if(ele && data.object[f]){
+                                    let arr = data.object[f].split(';');
+
+                                    // 缁欓殣钘忕殑select璧嬪��
+                                    for(let op of ele.options){
+                                        op.selected = arr.indexOf(op.value)>-1;
+                                    }
+                                    
+                                    // 鍒╃敤鎸夐挳缁欐樉绀虹殑select璧嬪��
+                                    let ra = document.getElementById(ele.id + '_right_arrow');
+                                    if(ra){
+                                        ra.click();
+                                    }
+                                    
+                                }
+                            }else{
+                                ele.value = data.object[f];
+                            }
+
+                            if(ele.type.indexOf("select")>-1 && ele.value){
+                                jQuery(ele).change()
+                            }
+                            
+                        }
+                        else{
+                            console.log(f + 'is not in data.object');
+                        }
+                    }
+                }
+                else{
+                    console.log('data.object = ' + data.object);
+                }
+                
+
+                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                // document.querySelector("[data-id='Phone']").value = data.object.phone;
+                // document.querySelector("[data-id='Email']").value = data.object.email;
+            },
+            updateMethod:"NewAndEditQuotesController.saveQuotes",
+            insertMethod:"NewAndEditQuotesController.saveQuotes"
+        }
+    
+        AWSService.sfSessionId = '{!GETSESSIONID()}';
+        var staticResources = JSON.parse('{!staticResource}');
+        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
+        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
+        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
+        console.log('{!staticResource}');
+        var VLookUpFields = {! VLookUpFieldsJson};
+        function ProcessPI(sobjJson, payloadForNewPI) {
+            blockme();
+            if ({!isNewMode}) {
+                NewPIToAWS(sobjJson, payloadForNewPI)
+            }else {
+                UpdatePIToAWS(sobjJson, payloadForNewPI)
+            }
+        }
+
+        var GetEleByClass = function(class_name){
+            let eles = document.getElementsByClassName(class_name);
+            if(eles.length > 0) return eles[0];
+            return null;
+        }
+
+        var GetEleApiName = function(ele){
+            for(let c of ele.classList){
+                if(c.indexOf(config.ApiPrefix+'_')>-1){
+                    return c.replace(config.ApiPrefix+'_','');
+                }
+            }
+            return '';
+        }
+
+        function IsFormTag(tag_name){
+            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
+        }
+        
+        function IsFormElement(e){
+            return IsFormTag(e.tagName);
+        }
+
+        function getPIPayload(sobjJson) {
+            return config.SobjectToAWSModel(sobjJson);
+        }
+
+        function validateFieldValueFormate() {
+            let error_msg = '';
+            let textEmail = "[data-id='Email']";
+            let textPhone = "[data-id='MobilePhone']";
+            //Email
+            let email = document.querySelector(textEmail);
+            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
+                error_msg += ';閭欢鏍煎紡閿欒';
+            }
+            let phone = document.querySelector(textPhone);
+
+            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
+                error_msg += ';鐢佃瘽鍙风爜閿欒';
+            }
+
+            for(let e of document.getElementsByTagName('select')){
+                for(let op of e.options){
+                    if(op.value == "*****" && op.selected){
+                        error_msg += ';涓嬫媺妗嗕笉鑳戒富鍔ㄩ�夋嫨瀵嗘枃閫夐」';
+                    }
+                }
+            }
+
+            if(error_msg.length>0 && error_msg[0]== ';'){
+                error_msg = error_msg.substring(1);
+            }
+
+            return error_msg;
+        }
+
+        function getSobjectInformation() {
+            //api_id_map
+//let nodelist = document.getElementsByClassName(config.ApiPrefix);
+            let result = {}
+            for (let index in api_id_map) {
+                let ele = document.getElementById(api_id_map[index]);
+                let field_api_name = index;
+                let tag_name = ele.tagName.toLowerCase();
+                if(!IsFormTag(tag_name)){
+                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
+                    continue;
+                }
+
+                if (VLookUpFields.indexOf(field_api_name)>=0) {
+                    console.log(ele.id.indexOf('lkwgt'));
+                    if (ele.id.indexOf('lkwgt') == -1) {
+                        let vlookUpNodeId = ele.id + '_lkid';
+                        let vlook_ele = document.getElementById(vlookUpNodeId);
+                        let v = '';
+                        if(vlook_ele){
+                            v = vlook_ele.value;
+                        }else{
+                            v = ele.value;
+                        }
+
+                        if(v && v != "000000000000000"){
+                            result[field_api_name] = v;
+                        }
+                        
+                    }
+                } else if (ele.type == 'checkbox') {
+                    result[field_api_name] = ele.checked;
+                } else if (ele.type == 'select-multiple') {
+                    //field_api_name
+                    let multiple = field_api_name;
+                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
+                    targets = targets.replace(/\n/g, ";");
+                    console.log('targets = ' + targets);
+                    result[field_api_name] = targets;
+                } else {
+                    result[field_api_name] = ele.value;
+                }
+                
+                // let e1 = document.getElementById(api_id_map[field_api_name]);
+                // if(!result[field_api_name] && e1 && e1.value){
+                //  result[field_api_name] = e1.value;
+                // }
+            }
+            return result;
+        }
+        function QuerySobjectFromAWS() {
+            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+        }
+        function queryBack(data) {
+            console.log('data = ' + data);
+            config.queryBack(data);
+            unblockUI();
+        };
+
+
+        function insertOrUpdateBack(payloadJson, result, isNewMode) {
+            console.log(result);
+            let r = result;
+            console.log('Result from AWS' + r);
+            console.log('payloadJson=' + payloadJson);
+            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
+        }
+
+        function redirectCallBack(sfId,errorMsg) {
+            unblockUI();
+            if(errorMsg){
+                alertErrorMessage(errorMsg);
+            }
+            else{
+                if(config.SaveAndNew){
+                    window.open('{! SaveAndNewButtonUrl }','_self');
+                }else{
+                    window.open('/' + sfId, '_self');
+                }
+            }
+            
+        }
+
+        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.updateMethod;
+            let obj = JSON.parse(payloadForNewPI);
+            obj[0].dataId = '{!AWSDataId}';
+            let payloadForNewPIJson = JSON.stringify(obj);
+            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
+            
+        }
+
+        function NewPIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.insertMethod;
+            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
+            
+        }
+		
+        function checkRequiredFieldMsg(formData) {
+            let blankRequiredFields = '';
+            for(i = 0;i<requiredFieldAPIList.length;i++){
+                if(formData[requiredFieldAPIList[i]]){
+                    continue;
+                }else{
+                    if(blankRequiredFields == ''){
+                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }else{
+                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }
+                    
+                }
+            }
+            return blankRequiredFields;
+        }
+        function saveSobjectProcess(save_and_new) {
+            if(save_and_new){
+                config.SaveAndNew = true;
+            }
+            
+            hiddenErrorMsgNode();
+            //1. Get Sobject Information from Form
+            let sobjJson = getSobjectInformation();
+            //2. Validate the Sobject field value formate, for example the email formate or phone formate
+
+            let validationResultMessage = validateFieldValueFormate();
+            console.log(validationResultMessage);
+            if (validationResultMessage) {
+                //Popup error message.  - To Do After POC
+                alertErrorMessage(validationResultMessage);
+                return
+            }
+            // Check Required Field
+            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
+            if (checkRequiredFieldMsgResult) {
+                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
+                return
+            }
+            // //3. Prepare the payload for New PI API To AWS - To Do
+            let payloadForNewPI = getPIPayload(sobjJson);
+
+            // //4. Get Authentication Information for AWS
+            // loadAWSAuthentication();
+
+            // //5. lead to AWS 
+            ProcessPI(sobjJson, payloadForNewPI);
+            // awsToken = TestToken;
+            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
+        }
+                
+        function alertErrorMessage(errorMsg) {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = errorMsg;
+            errorMsgNode.className = 'pbError';
+        }
+        function hiddenErrorMsgNode() {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = '';
+            errorMsgNode.className = '';
+        }
+
+        //鏇挎崲vlookup
+        var newSearchContactWindow = null;  
+        var closeField = '';
+
+        function replaceSearchContactLookup() {
+            if (!{!isNewMode}) {
+                //1. Query Contact from AWS by AWSDataId
+                queryContactName()
+            }           
+            if(document.querySelector("[data-id='CONTACT_NAME__c']") != null){
+                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='CONTACT_NAME__c']").parentNode;
+                document.querySelector("[data-id='CONTACT_NAME__c']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='CONTACT_NAME__c']").parentNode.children[2]);
+            }
+        }
+        function htmlToElement(html) {
+            var template = document.createElement('template');
+            html = html.trim(); // Never return a text node of whitespace as the result
+            template.innerHTML = html;
+            return template.content.firstChild;
+        }
+
+        function queryContactName() {
+            let sfId = document.getElementById(document.querySelector("[data-id='CONTACT_NAME__c']").id + '_lkid').value;
+            let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
+            let dataId = contactsInfo[sfId];
+            let queryContactBack = function(data){
+                //To Do later
+                console.log('ContactData = ' + data.object);
+                
+                document.querySelector("[data-id='CONTACT_NAME__c']").value = data.object.lastName;
+            }
+            AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
+        }
+
+        
+        //鑷畾涔塴ookup鏌ヨ
+        function searchContact(contactNodeId,field){
+            closeField = field;
+            let accountValue = "";
+            if (document.querySelector("[data-id='AccountId']")) {
+                let accountNodeId = document.querySelector("[data-id='AccountId']").id + '_lkid';
+                accountValue = document.getElementById(accountNodeId).value;   
+            } 
+            console.log(accountValue);
+            if(accountValue !='000000000000000'){
+                let baseUrl = "/apex/SearchContactPage";
+                let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
+                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                if (window.focus) {
+                    newSearchContactWindow.focus();
+                }
+                return false;
+            }else{
+                alertErrorMessage('{!PIPL_Input_Account_Error_Msg}');
+            }
+        }
+        function closePopupWindow() {
+            if (null != newSearchContactWindow) {
+                newSearchContactWindow.close();
+            }
+            let contactInfoStr = document.getElementById('page:form:contactId').value;
+            console.log('closePopup:'+contactInfoStr);
+            let contactInfo = JSON.parse(contactInfoStr);
+            let contactNodeId = document.querySelector("[data-id="+closeField+"]").id + '_lkid';
+            document.getElementById(contactNodeId).value = contactInfo.ContactId;
+            document.querySelector("[data-id="+closeField+"]").value = contactInfo.Name;     
+        }
+
+    </script>
+    <div class="bPageTitle">
+        <div class="ptBody">
+            <div class="content">
+                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
+                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
+                    <span class="titleSeparatingColon">:</span>
+                </h1>
+                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
+                <div class="blank">&nbsp;</div>
+            </div>
+            <div class="links">
+                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
+                    title="姝ら〉闈㈢殑甯姪 锛堟柊绐楀彛锛�">
+                    <span class="helpLink">姝ら〉闈㈢殑甯姪</span>
+                    <img src="/img/s.gif" alt="" class="helpIcon" />
+                </a>
+            </div>
+        </div>
+        <div class="ptBreadcrumb"></div>
+    </div>
+    <apex:form id="form">
+        <apex:inputHidden value="{!contactId}" id="contactId"/>
+        <apex:pageblock id="block">
+            <div class="pbHeader">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
+                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
+                            </td>
+                            <td class="pbButton" id="topButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+            <!-- Error Msg-->
+            <div style="text-align: center;">
+                <apex:outputPanel id="errorMsg">
+                    <apex:pageMessages id="msgContent" escape="false" />
+                </apex:outputPanel>
+            </div>
+            
+            <!-- Iterate the layoutSections, which is a list of sections -->
+            <apex:repeat value="{!layoutSections}" var="layoutSection">
+                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
+                    
+                    <!--Each section has layoutFields, let's iterate them as well-->
+                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
+                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Quotes__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
+                                        required="{!layoutField.isRequired}" />
+                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
+                        </apex:pageblocksectionitem>
+                    </apex:repeat>
+                    
+                </apex:pageBlockSection>
+            </apex:repeat>
+            <script>
+            var init_nodes = document.getElementsByClassName("PIBackApi");
+            var api_id_map={};
+            for(let e of init_nodes){
+                if(IsFormElement(e)){
+                    api_id_map[GetEleApiName(e)] = e.id;
+                }
+            }
+            console.log(api_id_map);
+            sfdcPage.appendToOnloadQueue(function () {
+                //1. Set Last Name label
+                //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '濮撳悕';
+                //2. Query AWS Data by dataId 
+                console.log('Mode for Sobject Page:' + {!isNewMode});
+                if (!{!isNewMode}) {
+                    blockme();
+                    QuerySobjectFromAWS();
+                }
+                
+                //Replace Vlookup Field
+                replaceSearchContactLookup();
+
+                //3. Set Readonly Attribute
+                document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
+                document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
+                
+                
+            });
+            </script>
+            <div class="pbBottomButtons">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
+                            <td class="pbButtonb" id="bottomButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </apex:pageblock>
+
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditQuotes.page-meta.xml b/force-app/main/default/pages/NewAndEditQuotes.page-meta.xml
new file mode 100644
index 0000000..34fc7ee
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditQuotes.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditQuotes</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewAndEditUserFaultInfo.page b/force-app/main/default/pages/NewAndEditUserFaultInfo.page
new file mode 100644
index 0000000..6f9aa94
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditUserFaultInfo.page
@@ -0,0 +1,579 @@
+<apex:page standardController="User_FaultInfo__c" extensions="NewAndEditUserFaultInfoController" id="page">
+  <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
+    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
+    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
+    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
+    <style>
+        .disabledbutton {
+            pointer-events: none;
+            opacity: 0.4;
+        }
+    </style>
+    <script>
+        
+        var config = {};
+        config = {
+            SobjectName : "{!SobjectName}",
+            ApiPrefix:"{!ApiPrefix}",
+            SaveAndNew:false,
+            AWSToSobjectMap:{!AWSToSobjectMapJson},
+            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
+            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
+            SobjectToAWSModel:function (sobjJson) {
+                let leadPayloadList = [];
+                let leadPIData = {};
+
+                for(let f in config.AWSToSobjectMap){
+                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
+                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
+                    }
+                    else{
+                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
+                    }
+                } 
+
+                leadPIData.sfRecordId = '';
+                console.log('Sobject PI Data:' + leadPIData);
+                leadPayloadList.push(leadPIData);
+                console.log(JSON.stringify(leadPayloadList));
+                return JSON.stringify(leadPayloadList);
+            },
+            insertOrUpdateBack:function(payloadJson, r, isNewMode){
+                
+                for(let f in config.AWSToSobjectMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+
+                for(let f in config.AWSToSobjectEncryptedMap){
+                    if(r.object[0].hasOwnProperty(f)){
+                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
+                    }
+                    else{
+                        console.log(f + 'is not in r.object[0]');
+                    }
+                }
+                
+                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                if (isNewMode) {
+                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
+                } else {
+                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
+                }
+                return payloadJson;
+            },
+            queryBack:function (data) {
+                console.log('data = ' + data);
+                if(data.object){
+                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
+                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
+                        if(data.object.hasOwnProperty(f) && ele){
+                            
+                            // 澶氶�夌壒娈婂鐞�
+                            if(ele.type == 'select-multiple'){
+                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
+                                if(ele && data.object[f]){
+                                    let arr = data.object[f].split(';');
+
+                                    // 缁欓殣钘忕殑select璧嬪��
+                                    for(let op of ele.options){
+                                        op.selected = arr.indexOf(op.value)>-1;
+                                    }
+                                    
+                                    // 鍒╃敤鎸夐挳缁欐樉绀虹殑select璧嬪��
+                                    let ra = document.getElementById(ele.id + '_right_arrow');
+                                    if(ra){
+                                        ra.click();
+                                    }
+                                    
+                                }
+                            }else{
+                                ele.value = data.object[f];
+                            }
+
+                            if(ele.type.indexOf("select")>-1 && ele.value){
+                                jQuery(ele).change()
+                            }
+                            
+                        }
+                        else{
+                            console.log(f + 'is not in data.object');
+                        }
+                    }
+                }
+                else{
+                    console.log('data.object = ' + data.object);
+                }
+                
+
+                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                // document.querySelector("[data-id='Phone']").value = data.object.phone;
+                // document.querySelector("[data-id='Email']").value = data.object.email;
+            },
+            updateMethod:"NewAndEditUserFaultInfoController.saveUserFaultInfo",
+            insertMethod:"NewAndEditUserFaultInfoController.saveUserFaultInfo"
+        }
+    
+        AWSService.sfSessionId = '{!GETSESSIONID()}';
+        var staticResources = JSON.parse('{!staticResource}');
+        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
+        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
+        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
+        console.log('{!staticResource}');
+        var VLookUpFields = {! VLookUpFieldsJson};
+        console.log('Vlookupfields:'+VLookUpFields);
+        function ProcessPI(sobjJson, payloadForNewPI) {
+            blockme();
+            if ({!isNewMode}) {
+                NewPIToAWS(sobjJson, payloadForNewPI)
+            }else {
+                UpdatePIToAWS(sobjJson, payloadForNewPI)
+            }
+        }
+
+        var GetEleByClass = function(class_name){
+            let eles = document.getElementsByClassName(class_name);
+            if(eles.length > 0) return eles[0];
+            return null;
+        }
+
+        var GetEleApiName = function(ele){
+            for(let c of ele.classList){
+                if(c.indexOf(config.ApiPrefix+'_')>-1){
+                    return c.replace(config.ApiPrefix+'_','');
+                }
+            }
+            return '';
+        }
+
+        function IsFormTag(tag_name){
+            return ['input','select','textarea','div'].indexOf(tag_name.toLowerCase())>-1;
+        }
+    
+        function IsFormElement(e){
+            return IsFormTag(e.tagName);
+        }
+
+        function getPIPayload(sobjJson) {
+            return config.SobjectToAWSModel(sobjJson);
+        }
+
+        function validateFieldValueFormate() {
+            let error_msg = '';
+            let textEmail = "[data-id='Email']";
+            let textPhone = "[data-id='UFPhone__c']";
+            //Email
+            let email = document.querySelector(textEmail);
+            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
+                error_msg += ';閭欢鏍煎紡閿欒';
+            }
+            let phone = document.querySelector(textPhone);
+
+            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
+                error_msg += ';鐢佃瘽鍙风爜閿欒';
+            }
+
+            for(let e of document.getElementsByTagName('select')){
+                for(let op of e.options){
+                    if(op.value == "*****" && op.selected){
+                        error_msg += ';涓嬫媺妗嗕笉鑳戒富鍔ㄩ�夋嫨瀵嗘枃閫夐」';
+                    }
+                }
+            }
+
+            if(error_msg.length>0 && error_msg[0]== ';'){
+                error_msg = error_msg.substring(1);
+            }
+
+            return error_msg;
+        }
+
+        function getSobjectInformation() {
+            //api_id_map
+//let nodelist = document.getElementsByClassName(config.ApiPrefix);
+            let result = {}
+            for (let index in api_id_map) {
+                let ele = document.getElementById(api_id_map[index]);
+                let field_api_name = index;
+                let tag_name = ele.tagName.toLowerCase();
+                if(!IsFormTag(tag_name)){
+                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
+                    continue;
+                }
+
+                if (VLookUpFields.indexOf(field_api_name)>=0) {
+                    console.log(ele.id.indexOf('lkwgt'));
+                    if (ele.id.indexOf('lkwgt') == -1) {
+                        if(field_api_name == 'ASSIGNED_TO__c'){
+                            ele.id = ele.id.substring(-1,ele.id.length-4);
+                        }
+                        let vlookUpNodeId = ele.id + '_lkid';
+                        let vlook_ele = document.getElementById(vlookUpNodeId);
+                        let v = '';
+                        if(vlook_ele){
+                            v = vlook_ele.value;
+                        }else{
+                            v = ele.value;
+                        }
+
+                        if(v && v != "000000000000000"){
+                            result[field_api_name] = v;
+                        }
+                        
+                    }
+                } else if (ele.type == 'checkbox') {
+                    result[field_api_name] = ele.checked;
+                } else if (ele.type == 'select-multiple') {
+                    //field_api_name
+                    let multiple = field_api_name;
+                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
+                    targets = targets.replace(/\n/g, ";");
+                    console.log('targets = ' + targets);
+                    result[field_api_name] = targets;
+                } else {
+                    result[field_api_name] = ele.value;
+                }
+            }
+            return result;
+        }
+        function QuerySobjectFromAWS() {
+            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+        }
+        function queryBack(data) {
+            console.log('data = ' + data);
+            config.queryBack(data);
+            unblockUI();
+        };
+
+
+        function insertOrUpdateBack(payloadJson, result, isNewMode) {
+            console.log(result);
+            let r = result;
+            console.log('Result from AWS' + r);
+            console.log('payloadJson=' + payloadJson);
+            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
+        }
+
+        function redirectCallBack(sfId,errorMsg) {
+            unblockUI();
+            if(errorMsg){
+                alertErrorMessage(errorMsg);
+            }
+            else{
+                if(config.SaveAndNew){
+                    window.open('{! SaveAndNewButtonUrl }','_self');
+                }else{
+                    window.open('/' + sfId, '_self');
+                }
+            }
+            
+        }
+
+        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.updateMethod;
+            let obj = JSON.parse(payloadForNewPI);
+            obj[0].dataId = '{!AWSDataId}';
+            let payloadForNewPIJson = JSON.stringify(obj);
+            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
+            
+        }
+
+        function NewPIToAWS(sobjJson, payloadForNewPI) {
+            let controllerSaveMethod = config.insertMethod;
+            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
+            
+        }
+        
+
+        function checkRequiredFieldMsg(formData) {
+            let blankRequiredFields = '';
+            for(i = 0;i<requiredFieldAPIList.length;i++){
+                if(formData[requiredFieldAPIList[i]]){
+                    continue;
+                }else{
+                    if(blankRequiredFields == ''){
+                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }else{
+                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
+                    }
+                    
+                }
+            }
+            return blankRequiredFields;
+        }
+        
+        function saveSobjectProcess(save_and_new) {
+            if(save_and_new){
+                config.SaveAndNew = true;
+            }
+            
+            hiddenErrorMsgNode();
+            //1. Get Sobject Information from Form
+            let sobjJson = getSobjectInformation();
+            //2. Validate the Sobject field value formate, for example the email formate or phone formate
+
+            let validationResultMessage = validateFieldValueFormate();
+            console.log(validationResultMessage);
+            if (validationResultMessage) {
+                //Popup error message.  - To Do After POC
+                alertErrorMessage(validationResultMessage);
+                return
+            }
+            // Check Required Field
+            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
+            if (checkRequiredFieldMsgResult) {
+                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
+                return
+            }
+            // //3. Prepare the payload for New PI API To AWS - To Do
+            let payloadForNewPI = getPIPayload(sobjJson);
+
+            // //4. Get Authentication Information for AWS
+            // loadAWSAuthentication();
+
+            // //5. User_FaultInfo__c to AWS 
+            ProcessPI(sobjJson, payloadForNewPI);
+            // awsToken = TestToken;
+            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
+        }
+
+        function alertErrorMessage(errorMsg) {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = errorMsg;
+            errorMsgNode.className = 'pbError';
+        }
+        function hiddenErrorMsgNode() {
+            let errorMsgNode = document.getElementById("page:form:block:msgContent");
+            errorMsgNode.innerText = '';
+            errorMsgNode.className = '';
+        }
+
+        //鏇挎崲vlookup
+        var newSearchContactWindow = null;  
+        var closeField = '';
+
+        function replaceSearchContactLookup() {
+            if (!{!isNewMode}) {
+                //1. Query Contact from AWS by AWSDataId
+                queryContactName()
+            }           
+            if(document.querySelector("[data-id='CONTACT__c']") != null){
+                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'CONTACT__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='CONTACT__c']").parentNode;
+                document.querySelector("[data-id='CONTACT__c']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='CONTACT__c']").parentNode.children[2]);
+            }
+            if(document.querySelector("[data-id='UFContact__c']") != null){
+                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'UFContact__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.querySelector("[data-id='UFContact__c']").parentNode;
+                document.querySelector("[data-id='UFContact__c']").removeAttribute("onchange");
+                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='UFContact__c']").parentNode.children[2]);
+            }
+        }
+
+        function htmlToElement(html) {
+            var template = document.createElement('template');
+            html = html.trim(); // Never return a text node of whitespace as the result
+            template.innerHTML = html;
+            return template.content.firstChild;
+        }
+
+        function queryContactName() {
+            if(document.querySelector("[data-id='CONTACT__c']") != null){
+                queryContactNameFetch('CONTACT__c');
+                // let sfId = document.getElementById(document.querySelector("[data-id='CONTACT__c']").id + '_lkid').value;
+                // if(sfId != '000000000000000'){
+                //     let dataId = contactsInfo[sfId];
+                //     let queryContactBack = function(data){
+                //         //To Do later
+                //         console.log('ContactData = ' + data.object);
+                        
+                //         document.querySelector("[data-id='CONTACT__c']").value = data.object.lastName;
+                //     }
+                //     AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
+                // }
+            }
+            if(document.querySelector("[data-id='UFContact__c']") != null){
+                queryContactNameFetch('UFContact__c');
+                
+            }
+        }
+        
+        function queryContactNameFetch(filedId){
+            let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
+            let sfId = document.getElementById(document.querySelector("[data-id='"+filedId+"']").id + '_lkid').value;
+            if(sfId != '000000000000000'){
+                let dataId = contactsInfo[sfId];
+                let queryContactBack = function(data){
+                    //To Do later
+                    console.log('ContactData = ' + data.object);
+                    
+                    document.querySelector("[data-id='"+filedId+"']").value = data.object.lastName;
+                }
+                AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
+            }
+        }
+
+        
+        //鑷畾涔塴ookup鏌ヨ
+        function searchContact(contactNodeId,field){
+            closeField = field;
+            let accountValue = "";
+            let baseUrl = "/apex/SearchContactPage";
+            let suffixUrl = "";
+            let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+            if (field = 'CONTACT__c') {
+                if (document.querySelector("[data-id='COMPANY__c']")) {
+                    let accountNodeId = document.querySelector("[data-id='COMPANY__c']").id + '_lkid';
+                    accountValue = document.getElementById(accountNodeId).value;   
+                } 
+                console.log('COMPANY__c accountValue ' + accountValue);
+                if(accountValue !='000000000000000'){
+                    
+                    suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
+                    newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                    if (window.focus) {
+                        newSearchContactWindow.focus();
+                    }
+                    return false;
+                } else {
+                    alertErrorMessage('璇疯緭鍏OMPANY !');
+                }
+            } else {
+                suffixUrl = "?contactId="+contactNodeId;
+                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+                if (window.focus) {
+                    newSearchContactWindow.focus();
+                }
+                return false;
+            }
+        }
+
+        function closePopupWindow() {
+            if (null != newSearchContactWindow) {
+                newSearchContactWindow.close();
+            }
+            let contactInfoStr = document.getElementById('page:form:contactId').value;
+            console.log('closePopup:'+contactInfoStr);
+            let contactInfo = JSON.parse(contactInfoStr);
+            let contactNodeId = document.querySelector("[data-id="+closeField+"]").id + '_lkid';
+            document.getElementById(contactNodeId).value = contactInfo.ContactId;
+            document.querySelector("[data-id="+closeField+"]").value = contactInfo.Name;     
+        }
+    </script>
+    <div class="bPageTitle">
+        <div class="ptBody">
+            <div class="content">
+                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
+                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
+                    <span class="titleSeparatingColon">:</span>
+                </h1>
+                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
+                <div class="blank">&nbsp;</div>
+            </div>
+            <div class="links">
+                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
+                    title="姝ら〉闈㈢殑甯姪 锛堟柊绐楀彛锛�">
+                    <span class="helpLink">姝ら〉闈㈢殑甯姪</span>
+                    <img src="/img/s.gif" alt="" class="helpIcon" />
+                </a>
+            </div>
+        </div>
+        <div class="ptBreadcrumb"></div>
+    </div>
+    <apex:form id="form">
+        <apex:inputHidden value="{!contactId}" id="contactId"/>
+        <apex:pageblock id="block">
+            <div class="pbHeader">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
+                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
+                            </td>
+                            <td class="pbButton" id="topButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+            <!-- Error Msg-->
+            <div style="text-align: center;">
+                <apex:outputPanel id="errorMsg">
+                    <apex:pageMessages id="msgContent" escape="false" />
+                </apex:outputPanel>
+            </div>
+            
+            <!-- Iterate the layoutSections, which is a list of sections -->
+            <apex:repeat value="{!layoutSections}" var="layoutSection">
+                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
+                    
+                    <!--Each section has layoutFields, let's iterate them as well-->
+                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
+                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!User_FaultInfo__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
+                                         required="{!layoutField.isRequired}" />
+                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
+                        </apex:pageblocksectionitem>
+                    </apex:repeat>
+                    
+                </apex:pageBlockSection>
+            </apex:repeat>
+            <script>
+            var init_nodes = document.getElementsByClassName("PIBackApi");
+            var api_id_map={};
+            for(let e of init_nodes){
+            	if(IsFormElement(e)){
+                	 api_id_map[GetEleApiName(e)] = e.id;
+                }
+            }
+            console.log(api_id_map);
+            sfdcPage.appendToOnloadQueue(function () {
+                //1. Set Last Name label
+                //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '濮撳悕';
+                //2. Query AWS Data by dataId 
+                console.log('Mode for Sobject Page:' + {!isNewMode});
+                if (!{!isNewMode}) {
+                    blockme();
+                    QuerySobjectFromAWS();
+                }
+                //Replace Vlookup Field
+                replaceSearchContactLookup();
+                //3. Set Readonly Attribute
+                document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
+                document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
+            });
+            </script>
+            <div class="pbBottomButtons">
+                <table cellspacing="0" cellpadding="0" border="0">
+                    <tbody>
+                        <tr>
+                            <td class="pbTitle">
+                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
+                            <td class="pbButtonb" id="bottomButtonRow">
+                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
+                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
+                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </apex:pageblock>
+
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/NewAndEditUserFaultInfo.page-meta.xml b/force-app/main/default/pages/NewAndEditUserFaultInfo.page-meta.xml
new file mode 100644
index 0000000..cdf1f28
--- /dev/null
+++ b/force-app/main/default/pages/NewAndEditUserFaultInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>NewAndEditUserFaultInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/NewOpportunity.page b/force-app/main/default/pages/NewOpportunity.page
index a31dc35..6fab793 100644
--- a/force-app/main/default/pages/NewOpportunity.page
+++ b/force-app/main/default/pages/NewOpportunity.page
@@ -1,12 +1,58 @@
 <apex:page id="Page" Controller="NewOpportunityController" sidebar="true" showHeader="true" action="{!init}">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
     <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
     <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
     <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
 
     <script>
+        var staticResource = JSON.parse('{!staticResource}');
+        var txId = '';
+        var DealerSalesStaffNameId = 'Page:mainForm:idSearchSetProduct:j_id53:j_id56:opp_DealerSalesStaffName';
+        var DealerServiceId = 'Page:mainForm:idSearchSetProduct:j_id53:j_id62:opp_DealerService';
+        var opportunityAWSDataId = 'Page:mainForm:idSearchSetProduct:j_id53:opportunityAWSDataId';
+        function getPIData(){
+            let opportunityPayloadList = [];
+            let opportunityPIData = new Object();
+            opportunityPIData.dealerSalesStaffName = document.getElementById(DealerSalesStaffNameId).value
+            opportunityPIData.dealerService = document.getElementById(DealerServiceId).value
+            opportunityPayloadList.push(opportunityPIData);
+            return JSON.stringify(opportunityPayloadList);
+        }
     function saveJs() {
         blockme();
-        saveBtn();
+        new Promise(function(resolve,reject){
+            //鍔犲瘑
+            let queryPostBack = function(data){
+                document.getElementById(DealerSalesStaffNameId).value = data.object[0].dealerSalesStaffName;
+                document.getElementById(DealerServiceId).value = data.object[0].dealerService;
+                document.getElementById(opportunityAWSDataId).value = data.object[0].dataId;
+                txId = data.txId;
+                resolve('success');
+            };
+            AWSService.post(staticResource.newUrl,getPIData(),queryPostBack,staticResource.token);
+        }).then(function(data){
+            saveBtn();
+            Trans();
+        })
+    }
+    //aws 纭
+    function Trans(){
+        let b = HasError();
+        if(b){
+            //娓呯┖浠g悊鍟嗛攢鍞媴褰撹�呭悕
+            document.getElementById(DealerSalesStaffNameId).value=''
+            document.getElementById(DealerServiceId).value=''
+        }
+        AWSService.post(staticResource.transactionUrl, JSON.stringify({
+                "txId":txId,
+                "isSuccess":b ? 0 : 1
+            }), function(result){
+                console.log('Trans result = '+ JSON.stringify(result));
+            }, staticResource.token);
+    }
+    function HasError(){
+        let e = document.getElementById("Page:mainForm:message");
+        return e.children[0]!=null;
     }
 
     function saveYesJs() {
@@ -154,6 +200,7 @@
                     <apex:outputLabel value="浠g悊鍟嗘湇鍔℃媴褰撹�呭悕" for="opp_DealerService"/>
                     <apex:inputField value="{!opp.DealerService__c}" id="opp_DealerService"/>
                 </apex:pageBlockSectionItem>
+                <apex:inputHidden id="opportunityAWSDataId" value="{!opp.AWS_Data_Id__c}"/>
             </apex:pageBlockSection>
 
             <apex:pageBlockSection title="绔炰簤鑰呬俊鎭�" columns="2">
@@ -335,6 +382,7 @@
                     <apex:outputLabel value="浠g悊鍟嗘湇鍔℃媴褰撹�呭悕." for="opp_DealerService"/>
                     <apex:inputField value="{!opp.Dealer_Service_D__c}" id="opp_DealerService"/>
                 </apex:pageBlockSectionItem>
+                <apex:inputHidden id="opportunityAWSDataId" value="{!opp.AWS_Data_Id__c}"/>
             </apex:pageBlockSection>
 
             <apex:pageBlockSection title="绔炰簤鑰呬俊鎭�" columns="2">
diff --git a/force-app/main/default/pages/NewReplacementOpportunity.page b/force-app/main/default/pages/NewReplacementOpportunity.page
index 9934402..0b04ed8 100644
--- a/force-app/main/default/pages/NewReplacementOpportunity.page
+++ b/force-app/main/default/pages/NewReplacementOpportunity.page
@@ -1,12 +1,54 @@
 <apex:page id="Page" Controller="NewReplacementOpportunityController" sidebar="true" showHeader="true" action="{!init}">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
 	<apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
     <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
     <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
 
     <script>
+        var staticResource = JSON.parse('{!staticResource}');
+        var txId = '';
+        function getPIData(){
+            let opportunityPayloadList = [];
+            let opportunityPIData = new Object();
+            opportunityPIData.dealerSalesStaffName = document.getElementById('Page:mainForm:idSearchSetProduct:j_id35:j_id38:opp_DealerSalesStaffName').value
+            opportunityPayloadList.push(opportunityPIData);
+            return JSON.stringify(opportunityPayloadList);
+        }
         function saveJs() {
             blockme();
-            saveBtn();
+            new Promise(function(resolve,reject){
+                //鍔犲瘑
+                let queryPostBack = function(data){
+                    document.getElementById('Page:mainForm:idSearchSetProduct:j_id35:j_id38:opp_DealerSalesStaffName').value = data.object[0].dealerSalesStaffName;
+                    document.getElementById('Page:mainForm:idSearchSetProduct:j_id35:opportunityAWSDataId').value = data.object[0].dataId;
+                    txId = data.txId;
+                    resolve('success');
+                };
+                AWSService.post(staticResource.newUrl,getPIData(),queryPostBack,staticResource.token);
+            }).then(function(data){
+                saveBtn();
+                Trans();
+            })
+        }
+
+        //aws 纭
+        function Trans(){
+            let b = HasError();
+            if(b){
+                //娓呯┖浠g悊鍟嗛攢鍞媴褰撹�呭悕
+                document.getElementById('Page:mainForm:idSearchSetProduct:j_id35:j_id38:opp_DealerSalesStaffName').value=''
+            }
+            AWSService.post(staticResource.transactionUrl, JSON.stringify({
+                    "txId":txId,
+                    "isSuccess":b ? 0 : 1
+                }), function(result){
+                    console.log('Trans result = '+ JSON.stringify(result));
+                }, staticResource.token);
+        }
+
+        function HasError(){
+            let e = document.getElementById("Page:mainForm:message");
+            return e.children[0]!=null;
         }
 
         function saveYesJs() {
@@ -30,7 +72,7 @@
     </script>
 
     <apex:form id="mainForm">
-        <apex:actionFunction action="{!saveBtn}" name="saveBtn" reRender="mainForm,message" oncomplete="unblockUI();"/>
+        <apex:actionFunction action="{!saveBtn}" name="saveBtn" reRender="mainForm,message" oncomplete="Trans();unblockUI();"/>
         <apex:actionFunction action="{!saveBtnYes}" name="saveBtnYes" reRender="mainForm,message" oncomplete="unblockUI();"/>
         <apex:actionFunction action="{!saveBtnNo}" name="saveBtnNo" reRender="mainForm,message" oncomplete="unblockUI();"/>
 
@@ -99,6 +141,7 @@
                     <apex:outputLabel value="浠g悊鍟嗛攢鍞媴褰撹�呭悕" for="opp_DealerSalesStaffName"/>
                     <apex:inputField value="{!opp.DealerSalesStaffName__c}" id="opp_DealerSalesStaffName" required="true"/>
             	</apex:pageBlockSectionItem>
+                <apex:inputHidden id="opportunityAWSDataId" value="{!opp.AWS_Data_Id__c}"/>
             </apex:pageBlockSection>
 
         </apex:pageBlock>
diff --git a/force-app/main/default/pages/SearchContactPage.page b/force-app/main/default/pages/SearchContactPage.page
new file mode 100644
index 0000000..e7f7624
--- /dev/null
+++ b/force-app/main/default/pages/SearchContactPage.page
@@ -0,0 +1,189 @@
+<apex:page controller="SearchContactController" showHeader="false" id="page">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
+
+    <head>
+    </head>
+    <style>
+        /* 1. 瀹氫箟琛ㄥ崟鏍峰紡 To Do Later*/
+
+        table {
+            border-collapse: collapse;
+            border-spacing: 0;
+            width: 98%;
+            margin-left: 5px;
+        }
+    </style>
+
+    <body id="body" class="lookupTab">
+        <script type="text/javascript">
+            var staticResources = JSON.parse('{!staticResource}');
+            var contactAWSIds = JSON.parse('{!contactAWSIds}');
+            var contactsInfo = JSON.parse('{!contactsInfo}');
+            var searchContactName = '';
+            queryLeadFromAWS();
+            function searchAWSContact(){
+                console.log('Search process!');
+                //1. reset table;             
+                resetTable();
+                //2. get contact name value 
+                searchContactName = document.getElementById('page:form:lksrch').value;
+                queryLeadFromAWS();
+
+            }
+            function resetTable(){
+                let queryResult = document.getElementById('QueryResult');
+                let table = document.getElementById('table');
+                if(table){
+                    queryResult.removeChild(table);
+                }               
+            }
+            function preparePayloadForSearchContact(){
+                let searchPayload = new Object();
+                searchPayload.dataIds = contactAWSIds;
+                searchPayload.contactName = searchContactName;
+                return JSON.stringify(searchPayload);
+            }
+            function queryLeadFromAWS() {
+                //1. Prepare the payload for contact search
+                let requestSearchPayload = preparePayloadForSearchContact();
+                console.log('request payload body:'+requestSearchPayload);
+                //2. Invoke AWS Service
+                fetch(staticResources.searchUrl, {
+                    method: 'POST',
+                    body: requestSearchPayload,
+                    headers: {
+                        'Content-Type': 'application/json',
+                        'pi-token': staticResources.token
+                    }
+                }).then((data) => {
+                    return data.json();
+                }).then((result) => {
+                    if(result.object&&result.object.length>0){
+                        initContactTable(result);
+                    }                   
+                })
+            }
+            
+            function redirectToParentPage(obj,Phone,awsDataId) {
+                var winMain = window.opener;
+                if (null == winMain) {
+                    winMain = window.parent.opener;
+                }
+                console.log('obj = ' + obj)
+                let value = obj.currentTarget.innerText;
+                let contactInfo = new Object();
+                contactInfo.Name = obj.currentTarget.innerText;
+                contactInfo.ContactId = obj.currentTarget.id;
+                contactInfo.Phone = Phone;
+                contactInfo.awsDataId = awsDataId;
+                var selectedContactNode = winMain.document.getElementById('{!JSENCODE($CurrentPage.parameters.contactId)}');
+                selectedContactNode.value = JSON.stringify(contactInfo);
+                closeWindow();
+            }
+
+            function closeWindow() {
+                var winMain = window.opener;
+                if (null == winMain) {
+                    winMain = window.parent.opener;
+                }
+                winMain.closePopupWindow();
+                window.close();
+            }
+            function refreshTable(cols,contactInfoList){
+                let myTableDiv = document.getElementById("QueryResult");
+                let table = document.createElement('TABLE');
+                table.border = '1';
+                table.id = 'table'
+                let tableBody = document.createElement('TBODY');
+                table.appendChild(tableBody);
+                let headerTR = document.createElement('TR');
+                tableBody.appendChild(headerTR);
+                for (let i = 0; i < cols.length; i++) {
+                    let td = document.createElement('TH');
+                    td.width = '75';
+                    td.appendChild(document.createTextNode(cols[i]));
+                    headerTR.appendChild(td);
+                }
+                //3. Init the AWS data
+                for (let i = 0; i < contactInfoList.length; i++) {
+                    let tr = document.createElement('TR');
+                    tableBody.appendChild(tr);
+                    let contactInfoTemp = contactInfoList[i]
+                    for (let j = 0; j < cols.length; j++) {
+                        let td = document.createElement('TD');
+                        td.width = '75';
+                        if(j == 0 && contactsInfo[contactInfoTemp.AWSDataId]){
+                            td.id = contactsInfo[contactInfoTemp.AWSDataId].Id;
+                        }                        
+                        td.appendChild(document.createTextNode(contactInfoTemp[cols[j]]!=null?contactInfoTemp[cols[j]]:''));
+                        if (cols[j] == 'Name') {
+                            td.addEventListener("click", function (obj) {
+                                console.log('contactInfoList[i] = ' + contactInfoList[i])
+                                redirectToParentPage(obj,contactInfoList[i].Phone,contactInfoList[i].AWSDataId);
+                            });
+                        }
+                        tr.appendChild(td);
+                    }
+                }
+                myTableDiv.appendChild(table);
+            }
+            function initContactTable(data) {            
+                let cols = ['Name', 'Email', 'Phone'];
+                let contactInfoList = [];
+                let awsDataIds = [];
+                for(var i=0;i<data.object.length;i++){
+                    if(data.object[i].dataId){
+                        let contactInfo = new Object();
+                        contactInfo.Name = data.object[i].lastName;
+                        contactInfo.Email = data.object[i].email;
+                        contactInfo.Phone = data.object[i].phone;
+                        contactInfo.AWSDataId = data.object[i].dataId;
+                        awsDataIds.push(contactInfo.AWSDataId);
+                        contactInfo.sfRecordId = '';
+                        contactInfoList.push(contactInfo);
+                    }                    
+                }
+                let AWSIdToSFIdMapValue = {};
+                console.log(awsDataIds);
+                //Invoke SF BackEnd
+                Visualforce.remoting.Manager.invokeAction(
+                    '{!$RemoteAction.SearchContactController.searchContacts}',
+                    JSON.stringify(awsDataIds),
+                    function (result, event) {
+                        if(event.status){
+                            if(result.status = 'success'){
+                                contactsInfo = JSON.parse(result.message.replace(/(&quot\;)/g,"\""));
+                                refreshTable(cols,contactInfoList);
+                            }else{
+                                console.log('No result');
+                            }                                               
+                        }
+                    },
+                    { escape: true }
+                );
+            }
+        </script>
+        <apex:form id="form">
+            <!-- Search Filter-->
+            <div class="lookup">
+                <div class="bPageTitle">
+                    <div class="ptBody secondaryPalette">
+                        <div class="content">
+                            <img src="/img/s.gif" alt="" class="pageTitleIcon" title="" />
+                            <h1>Lookup</h1>
+                        </div>
+                    </div>
+                </div>
+                <div class="pBody">
+                    <label class="assistiveText" for="lksrch">Search</label>
+                    <apex:inputText id="lksrch" html-placeholder="{!PIPL_Search_Contact_Label}" value="{!searchKeyWord}" />
+                    <input value=" Go! " type="Button"  onclick="searchAWSContact()" styleClass="btn" />
+                    <div class="bDescription">You can use "*" as a wildcard next to other characters to improve your search results.
+                    </div>
+                </div>
+            </div>
+            <div id="QueryResult">
+            </div>
+        </apex:form>
+    </body>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/SearchContactPage.page-meta.xml b/force-app/main/default/pages/SearchContactPage.page-meta.xml
new file mode 100644
index 0000000..2aeb2a4
--- /dev/null
+++ b/force-app/main/default/pages/SearchContactPage.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>SearchContactPage</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/TSRepair.page b/force-app/main/default/pages/TSRepair.page
index 0c54e4a..82b343c 100644
--- a/force-app/main/default/pages/TSRepair.page
+++ b/force-app/main/default/pages/TSRepair.page
@@ -8,6 +8,7 @@
     <apex:includeScript value="{!URLFOR($Resource.jquerysuggestjs)}"/>
     <apex:includeScript value="{!URLFOR($Resource.connection20)}"/>
     <apex:includeScript value="{!URLFOR($Resource.apex20)}"/>
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
     <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"/>
     <style type="text/css"> 
         /*.sfdcBody {position: absolute;
@@ -103,6 +104,11 @@
     <!-- JS 鏂规硶 -->
     <script>
         var j$ = jQuery.noConflict();
+        var closeField = '';
+        var closePhone = ''; 
+        var newSearchContactWindow = null; 
+        var staticResourceContact = JSON.parse('{!staticResourceContact}')
+         
 
         j$(document).ready(function() {
                 var status = '{!tsr.TSReportStatus__c}';
@@ -344,16 +350,137 @@
         }
 
 
+        //20220310 zhj PIPL start
+        function isError(){
+            let h = HasError()
+            if(h){
+                unblockUI();
+            }
+        }
+        function HasError(){
+            // if (IsAddmessage) {
+            //     return true;
+            // }
+            let e = document.getElementById("allPage:allForm:message");
+            if (!e) {
+                return false;
+            }
+
+            let divs = j$(e).find("div.message");
+            for (let i = 0; i < divs.length; i++) {
+                for (let j = 0; j < divs[i].classList.length; j++) {
+                    for(let cls of divs[i].classList){
+                        if (cls.indexOf('error')>-1) {
+                            return true;
+                        }
+                    }
+                    
+                }
+                
+            }
+            return false;
+        }
+
+        function alertErrorMessage(errorMsg) {
+            let errorMsgNode = document.getElementById("allPage:allForm:message");
+            errorMsgNode.innerText = errorMsg;
+            errorMsgNode.className = 'pbError';
+        }
+
+        function htmlToElement(html) {
+            var template = document.createElement('template');
+            html = html.trim(); // Never return a text node of whitespace as the result
+            template.innerHTML = html;
+            return template.content.firstChild;
+        }
+
+        var contactIdValue = '';
+        function searchContact(contactNodeId,field1,field2,field3){
+            closeField = field1;
+            closePhone = field2;
+            contactIdValue = field3;
+            let baseUrl = "/apex/SearchContactPage";
+            let suffixUrl = "?contactId="+contactNodeId;
+            let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
+            newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
+            if (window.focus) {
+                newSearchContactWindow.focus();
+            }
+            return false;
+        }
+
+        var currentLastName = '';
+        var currentPhoneId = '';
         
+        function replaceSearchContactLookup() {   
+            blockme();
+            sforce.connection.sessionId = '{!GETSESSIONID()}';
+            let queryContactBack = function(data,number){
+                document.getElementById(currentLastName).value = data.object.lastName;
+                document.getElementById(currentPhoneId).innerText = data.object.phone;
+                number++;
+                if(document.getElementById('allPage:allForm:RepairInfoList:'+number+':contactIdValue') != null && document.getElementById('allPage:allForm:RepairInfoList:'+number+':contactIdValue').value != ''){
+                    currentLastName = 'allPage:allForm:RepairInfoList:'+number+':Contacts__c';
+                    currentPhoneId = 'allPage:allForm:RepairInfoList:'+number+':j_id91';
+                    let sfId = document.getElementById('allPage:allForm:RepairInfoList:'+number+':contactIdValue').value;
+                    var queryStr = 'Select Id, AWS_Data_Id__c'
+                                    +' from Contact  where id = \''
+                                    + sfId +'\' ';
+                    var reports = sforce.connection.query(queryStr);
+                    var records = reports.getArray("records");
+                    var awsDataId = records[0].AWS_Data_Id__c;
+                    AWSService.queryTSRepair(staticResourceContact.queryUrl, awsDataId, queryContactBack, staticResourceContact.token,number);
+                }
+            }
+            for(var i = 0;i<3;i++){
+                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'allPage:allForm:contactId\',\'allPage:allForm:RepairInfoList:'+i+':Contacts__c\',\'allPage:allForm:RepairInfoList:'+i+':j_id91\',\'allPage:allForm:RepairInfoList:'+i+':contactIdValue\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
+                let lookUpNode = htmlToElement(contactHtmlString);
+                console.log(lookUpNode);
+                let parentNode = document.getElementById('allPage:allForm:RepairInfoList:'+i+':contactIdValue').parentNode;
+                parentNode.appendChild(lookUpNode);
+            }
+            if(document.getElementById('allPage:allForm:RepairInfoList:0:contactIdValue').value != ''){
+                currentLastName = 'allPage:allForm:RepairInfoList:0:Contacts__c';
+                currentPhoneId = 'allPage:allForm:RepairInfoList:0:j_id91';
+                //瑙e瘑
+                let sfId = document.getElementById('allPage:allForm:RepairInfoList:0:contactIdValue').value;
+                var queryStr = 'Select Id, AWS_Data_Id__c'
+                                +' from Contact  where id = \''
+                                + sfId +'\' ';
+                var reports = sforce.connection.query(queryStr);
+                var records = reports.getArray("records");
+                var awsDataId = records[0].AWS_Data_Id__c;
+                AWSService.queryTSRepair(staticResourceContact.queryUrl, awsDataId, queryContactBack, staticResourceContact.token,0);
+            }
+            unblockUI(); 
+        }
+
+
+        function closePopupWindow() {
+            console.log('closePopupWindow()')
+            if (null != newSearchContactWindow) {
+                newSearchContactWindow.close();
+            }
+            let contactInfoStr = document.getElementById('allPage:allForm:contactId').value;
+            console.log('closePopup:'+contactInfoStr);
+            let contactInfo = JSON.parse(contactInfoStr);
+            
+            document.getElementById(contactIdValue).value = contactInfo.ContactId;
+            document.getElementById(''+closeField).value = contactInfo.Name;
+            document.getElementById(''+closePhone).value = contactInfo.Phone;
+            document.getElementById(''+closePhone).innerText = contactInfo.Phone;
+        }
+        //20220310 zhj PIPL end
     </script>
         <apex:form id="allForm">
+            <apex:inputHidden value="{!contactId}" id="contactId"/>
              <!-- 鐜嬮箯浼� 鐐瑰嚮鎸夐挳鏇存柊鐘舵�佸紑濮� -->
             <apex:actionFunction name="setStatus" action="{!setStatus}" reRender="Activities,message,Activities1" oncomplete="unblockUI();">
            
                 <apex:param name="status" assignTo="{!status}" value="" />
             </apex:actionFunction>
             <!-- 鐜嬮箯浼� 鐐瑰嚮鎸夐挳鏇存柊鐘舵�佺粨鏉� -->
-            <apex:actionFunction name="updateServiceCategory" action="{!updateServiceCategory}" rerender="Activities" onComplete="unblockUI();">
+            <apex:actionFunction name="updateServiceCategory" action="{!updateServiceCategory}" rerender="Activities" onComplete="replaceSearchContactLookup();unblockUI();">
                 <apex:param name="num" assignTo="{!num}" value="" />
             </apex:actionFunction>
 
@@ -545,7 +672,13 @@
                                         <apex:inputField id="BusinessACustomerUnit" value="{!repairInfo.ba.BusinessAAccount__c}" />
                                     </td>
                                     <th style="text-align: center;">鑱旂郴浜�</th>
-                                    <td align="left" ><apex:inputField value="{!repairInfo.ba.BusinessAContact__c}" style="width: 80%"/></td>
+                                    <td align="left" >
+                                        <!-- <apex:inputField value="{!repairInfo.ba.BusinessAContact__c}" style="width: 80%"/> -->
+                                        <!-- Add By zhj for PIPL 20220309 Start -->
+                                        <apex:inputText value="{!contactNameValue}" id="Contacts__c" style="width: 80%"/>
+                                        <apex:inputHidden id="contactIdValue" value="{!repairInfo.ba.BusinessAContact__c}"/>
+                                        <!-- Add By zhj for PIPL 20220309 end -->
+                                    </td>
                                     <th style="text-align: center;">鑱旂郴鐢佃瘽</th>
                                     <td align="left" ><apex:outputField value="{!repairInfo.ba.BusinessAPhone_F__c}"/></td>
                                 </tr>
@@ -998,9 +1131,14 @@
                             <br/>
                             <br/>
                         </apex:repeat>
-
                 </apex:outputPanel>
+                <script>
+                    console.log('appendToOnloadQueue')
+                    sfdcPage.appendToOnloadQueue(function () {
+                        replaceSearchContactLookup();
+                    });
+                </script>
             <apex:commandButton id="test" onclick="blockme();" action="{!addBusinessActivity}" reRender="Activities" value="娣诲姞涓氬姟娲诲姩"  oncomplete="unblockUI();" disabled="{!If(tsr.TSReportStatus__c = '鐢宠涓�' || tsr.TSReportStatus__c = '纭' ,true , If((tsr.TSReportStatus__c = '鑽夋涓�' || tsr.TSReportStatus__c = '椹冲洖') && onclickType != '0',true,false))}"></apex:commandButton>
-            <apex:commandButton id="save" onclick="blockme();" action="{!save}" reRender="message,allPanel,allForm" value="淇濆瓨" style="width: 70px;" oncomplete="unblockUI();" disabled="{!If(tsr.TSReportStatus__c = '鐢宠涓�' || tsr.TSReportStatus__c = '纭',true , If((tsr.TSReportStatus__c = '鑽夋涓�' || tsr.TSReportStatus__c = '椹冲洖') && onclickType != '0',true,false))}"></apex:commandButton>
+            <apex:commandButton id="save" onclick="blockme();" action="{!save}" reRender="message,allPanel,allForm" value="淇濆瓨" style="width: 70px;" oncomplete="unblockUI();isError();" disabled="{!If(tsr.TSReportStatus__c = '鐢宠涓�' || tsr.TSReportStatus__c = '纭',true , If((tsr.TSReportStatus__c = '鑽夋涓�' || tsr.TSReportStatus__c = '椹冲洖') && onclickType != '0',true,false))}"></apex:commandButton>
         </apex:form>
 </apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/TestLabel.page b/force-app/main/default/pages/TestLabel.page
new file mode 100644
index 0000000..2138f18
--- /dev/null
+++ b/force-app/main/default/pages/TestLabel.page
@@ -0,0 +1,3 @@
+<apex:page >
+    <input class="btn" type="Button" value="test" />
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/TestLabel.page-meta.xml b/force-app/main/default/pages/TestLabel.page-meta.xml
new file mode 100644
index 0000000..ac29079
--- /dev/null
+++ b/force-app/main/default/pages/TestLabel.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>TestLabel</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewContactDecryptInfo.page b/force-app/main/default/pages/ViewContactDecryptInfo.page
new file mode 100644
index 0000000..a8fa01f
--- /dev/null
+++ b/force-app/main/default/pages/ViewContactDecryptInfo.page
@@ -0,0 +1,63 @@
+<!--
+  @description       : 
+  @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+  @group             : 
+  @last modified on  : 02-22-2022
+  @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="Contact" extensions="NewAndEditContactController" id="page">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
+    <apex:form id="form">
+        <apex:pageblock id="pageBlock">
+            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
+                <!--Each section has layoutFields, let's iterate them as well-->
+                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
+                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Contact[encryptedAPI]}" />
+                </apex:repeat>
+            </apex:pageBlockSection>
+            <script>
+                var config = {
+                    SobjectName : "{!SobjectName}",
+                    ApiPrefix:"{!ApiPrefix}",
+                    AWSToSobjectMap:{!AWSToSobjectMapJson},
+                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
+                };
+                var staticResources = JSON.parse('{!staticResource}');
+                function QuerySobjectFromAWS() {
+                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+                }
+                var queryBack = function queryBack(data) {
+                    if(!data.object){
+                        console.log('data.object is ' + data.object);
+                        return;
+                    }
+
+                    for(let f in config.AWSToSobjectNonEncryptedMap){
+                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
+                        let ele = document.querySelector(t);
+                        if(ele){
+                            ele.title = '';
+                            if(data.object.hasOwnProperty(f)){
+                                ele.innerHTML = data.object[f];
+                            }
+                            else{
+                                console.log(f + 'is not in data.object');
+                            }
+                        }else{
+                            console.log('selector='+t+' not found');
+                        }
+                        
+                    }
+                    // 褰撲笉鑳借嚜鍔ㄦ纭浛鎹㈠姞瀵嗘暟鎹椂闇�瑕佸湪姝ゅ娣诲姞js锛岀‖缂栫爜澶勭悊
+                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                };
+                sfdcPage.appendToOnloadQueue(function () {
+                    console.log('sfdcPage.appendToOnloadQueue')
+                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '濮撳悕'
+                    QuerySobjectFromAWS();
+                });
+            </script>
+        </apex:pageblock>
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewContactDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewContactDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..15e961b
--- /dev/null
+++ b/force-app/main/default/pages/ViewContactDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewContactDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewLoanerAppDetailDecryptInfo.page b/force-app/main/default/pages/ViewLoanerAppDetailDecryptInfo.page
new file mode 100644
index 0000000..41846c7
--- /dev/null
+++ b/force-app/main/default/pages/ViewLoanerAppDetailDecryptInfo.page
@@ -0,0 +1,6 @@
+<apex:page >
+  <!-- Begin Default Content REMOVE THIS -->
+  <h1>Congratulations</h1>
+  This is your new Page
+  <!-- End Default Content REMOVE THIS -->
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewLoanerAppDetailDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewLoanerAppDetailDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..dc71ae8
--- /dev/null
+++ b/force-app/main/default/pages/ViewLoanerAppDetailDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewLoanerAppDetailDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewLoanerApplicationDecryptInfo.page b/force-app/main/default/pages/ViewLoanerApplicationDecryptInfo.page
new file mode 100644
index 0000000..ffa9ee5
--- /dev/null
+++ b/force-app/main/default/pages/ViewLoanerApplicationDecryptInfo.page
@@ -0,0 +1,63 @@
+<!--
+  @description       : 
+  @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+  @group             : 
+  @last modified on  : 03-03-2022
+  @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="loaner_application__c" extensions="NewAndEditLoanerApplicationController" id="page">
+  <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
+    <apex:form id="form">
+        <apex:pageblock id="pageBlock">
+            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
+                <!--Each section has layoutFields, let's iterate them as well-->
+                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
+                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!loaner_application__c[encryptedAPI]}" />
+                </apex:repeat>
+            </apex:pageBlockSection>
+            <script>
+                var config = {
+                    SobjectName : "{!SobjectName}",
+                    ApiPrefix:"{!ApiPrefix}",
+                    AWSToSobjectMap:{!AWSToSobjectMapJson},
+                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
+                };
+                var staticResources = JSON.parse('{!staticResource}');
+                function QuerySobjectFromAWS() {
+                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+                }
+                var queryBack = function queryBack(data) {
+                    if(!data.object){
+                        console.log('data.object is ' + data.object);
+                        return;
+                    }
+
+                    for(let f in config.AWSToSobjectNonEncryptedMap){
+                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
+                        let ele = document.querySelector(t);
+                        if(ele){
+                            ele.title = '';
+                            if(data.object.hasOwnProperty(f)){
+                                ele.innerHTML = data.object[f];
+                            }
+                            else{
+                                console.log(f + 'is not in data.object');
+                            }
+                        }else{
+                            console.log('selector='+t+' not found');
+                        }
+                        
+                    }
+                    // 褰撲笉鑳借嚜鍔ㄦ纭浛鎹㈠姞瀵嗘暟鎹椂闇�瑕佸湪姝ゅ娣诲姞js锛岀‖缂栫爜澶勭悊
+                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                };
+                sfdcPage.appendToOnloadQueue(function () {
+                    console.log('sfdcPage.appendToOnloadQueue')
+                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '濮撳悕'
+                    QuerySobjectFromAWS();
+                });
+            </script>
+        </apex:pageblock>
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewLoanerApplicationDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewLoanerApplicationDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..713d347
--- /dev/null
+++ b/force-app/main/default/pages/ViewLoanerApplicationDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewLoanerApplicationDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewLoanerExpressDecryptInfo.page b/force-app/main/default/pages/ViewLoanerExpressDecryptInfo.page
new file mode 100644
index 0000000..41846c7
--- /dev/null
+++ b/force-app/main/default/pages/ViewLoanerExpressDecryptInfo.page
@@ -0,0 +1,6 @@
+<apex:page >
+  <!-- Begin Default Content REMOVE THIS -->
+  <h1>Congratulations</h1>
+  This is your new Page
+  <!-- End Default Content REMOVE THIS -->
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewLoanerExpressDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewLoanerExpressDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..d0bb9f5
--- /dev/null
+++ b/force-app/main/default/pages/ViewLoanerExpressDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewLoanerExpressDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewLoanerUserDecryptInfo.page b/force-app/main/default/pages/ViewLoanerUserDecryptInfo.page
new file mode 100644
index 0000000..ed026ab
--- /dev/null
+++ b/force-app/main/default/pages/ViewLoanerUserDecryptInfo.page
@@ -0,0 +1,64 @@
+<!--
+  @description       : 
+  @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+  @group             : 
+  @last modified on  : 03-03-2022
+  @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="loaner_user__c" extensions="NewAndEditLoanerUserController" id="page">
+  <!-- Begin Default Content REMOVE THIS -->
+  <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
+    <apex:form id="form">
+        <apex:pageblock id="pageBlock">
+            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
+                <!--Each section has layoutFields, let's iterate them as well-->
+                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
+                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!loaner_user__c[encryptedAPI]}" />
+                </apex:repeat>
+            </apex:pageBlockSection>
+            <script>
+                var config = {
+                    SobjectName : "{!SobjectName}",
+                    ApiPrefix:"{!ApiPrefix}",
+                    AWSToSobjectMap:{!AWSToSobjectMapJson},
+                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
+                };
+                var staticResources = JSON.parse('{!staticResource}');
+                function QuerySobjectFromAWS() {
+                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+                }
+                var queryBack = function queryBack(data) {
+                    if(!data.object){
+                        console.log('data.object is ' + data.object);
+                        return;
+                    }
+
+                    for(let f in config.AWSToSobjectNonEncryptedMap){
+                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
+                        let ele = document.querySelector(t);
+                        if(ele){
+                            ele.title = '';
+                            if(data.object.hasOwnProperty(f)){
+                                ele.innerHTML = data.object[f];
+                            }
+                            else{
+                                console.log(f + 'is not in data.object');
+                            }
+                        }else{
+                            console.log('selector='+t+' not found');
+                        }
+                        
+                    }
+                    // 褰撲笉鑳借嚜鍔ㄦ纭浛鎹㈠姞瀵嗘暟鎹椂闇�瑕佸湪姝ゅ娣诲姞js锛岀‖缂栫爜澶勭悊
+                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                };
+                sfdcPage.appendToOnloadQueue(function () {
+                    console.log('sfdcPage.appendToOnloadQueue')
+                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '濮撳悕'
+                    QuerySobjectFromAWS();
+                });
+            </script>
+        </apex:pageblock>
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewLoanerUserDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewLoanerUserDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..442da39
--- /dev/null
+++ b/force-app/main/default/pages/ViewLoanerUserDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewLoanerUserDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewOpportunityDecryptInfo.page b/force-app/main/default/pages/ViewOpportunityDecryptInfo.page
new file mode 100644
index 0000000..407fac6
--- /dev/null
+++ b/force-app/main/default/pages/ViewOpportunityDecryptInfo.page
@@ -0,0 +1,63 @@
+<!--
+  @description       : 
+  @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+  @group             : 
+  @last modified on  : 02-23-2022
+  @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="Opportunity" extensions="NewAndEditOpportunityController" id="page">
+  <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
+    <apex:form id="form">
+        <apex:pageblock id="pageBlock">
+            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
+                <!--Each section has layoutFields, let's iterate them as well-->
+                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
+                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Opportunity[encryptedAPI]}" />
+                </apex:repeat>
+            </apex:pageBlockSection>
+            <script>
+                var config = {
+                    SobjectName : "{!SobjectName}",
+                    ApiPrefix:"{!ApiPrefix}",
+                    AWSToSobjectMap:{!AWSToSobjectMapJson},
+                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
+                };
+                var staticResources = JSON.parse('{!staticResource}');
+                function QuerySobjectFromAWS() {
+                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+                }
+                var queryBack = function queryBack(data) {
+                    if(!data.object){
+                        console.log('data.object is ' + data.object);
+                        return;
+                    }
+
+                    for(let f in config.AWSToSobjectNonEncryptedMap){
+                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
+                        let ele = document.querySelector(t);
+                        if(ele){
+                            ele.title = '';
+                            if(data.object.hasOwnProperty(f)){
+                                ele.innerHTML = data.object[f];
+                            }
+                            else{
+                                console.log(f + 'is not in data.object');
+                            }
+                        }else{
+                            console.log('selector='+t+' not found');
+                        }
+                        
+                    }
+                    // 褰撲笉鑳借嚜鍔ㄦ纭浛鎹㈠姞瀵嗘暟鎹椂闇�瑕佸湪姝ゅ娣诲姞js锛岀‖缂栫爜澶勭悊
+                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                };
+                sfdcPage.appendToOnloadQueue(function () {
+                    console.log('sfdcPage.appendToOnloadQueue')
+                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '濮撳悕'
+                    QuerySobjectFromAWS();
+                });
+            </script>
+        </apex:pageblock>
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewOpportunityDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewOpportunityDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..ea36495
--- /dev/null
+++ b/force-app/main/default/pages/ViewOpportunityDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewOpportunityDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewOrderDecryptInfo.page b/force-app/main/default/pages/ViewOrderDecryptInfo.page
new file mode 100644
index 0000000..8d8d597
--- /dev/null
+++ b/force-app/main/default/pages/ViewOrderDecryptInfo.page
@@ -0,0 +1,56 @@
+<apex:page standardController="Order" extensions="NewAndEditOrderController" id="page">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
+    <apex:form id="form">
+        <apex:pageblock id="pageBlock">
+            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
+                <!--Each section has layoutFields, let's iterate them as well-->
+                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
+                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Order[encryptedAPI]}" />
+                </apex:repeat>
+            </apex:pageBlockSection>
+            <script>
+                var config = {
+                    SobjectName : "{!SobjectName}",
+                    ApiPrefix:"{!ApiPrefix}",
+                    AWSToSobjectMap:{!AWSToSobjectMapJson},
+                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
+                };
+                var staticResources = JSON.parse('{!staticResource}');
+                function QuerySobjectFromAWS() {
+                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+                }
+                var queryBack = function queryBack(data) {
+                    if(!data.object){
+                        console.log('data.object is ' + data.object);
+                        return;
+                    }
+
+                    for(let f in config.AWSToSobjectNonEncryptedMap){
+                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
+                        let ele = document.querySelector(t);
+                        if(ele){
+                            ele.title = '';
+                            if(data.object.hasOwnProperty(f)){
+                                ele.innerHTML = data.object[f];
+                            }
+                            else{
+                                console.log(f + 'is not in data.object');
+                            }
+                        }else{
+                            console.log('selector='+t+' not found');
+                        }
+                        
+                    }
+                    // 褰撲笉鑳借嚜鍔ㄦ纭浛鎹㈠姞瀵嗘暟鎹椂闇�瑕佸湪姝ゅ娣诲姞js锛岀‖缂栫爜澶勭悊
+                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                };
+                sfdcPage.appendToOnloadQueue(function () {
+                    console.log('sfdcPage.appendToOnloadQueue')
+                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '濮撳悕'
+                    QuerySobjectFromAWS();
+                });
+            </script>
+        </apex:pageblock>
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewOrderDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewOrderDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..ee41c9a
--- /dev/null
+++ b/force-app/main/default/pages/ViewOrderDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewOrderDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewQuotesDecryptInfo.page b/force-app/main/default/pages/ViewQuotesDecryptInfo.page
new file mode 100644
index 0000000..656bd19
--- /dev/null
+++ b/force-app/main/default/pages/ViewQuotesDecryptInfo.page
@@ -0,0 +1,56 @@
+<apex:page standardController="Quotes__c" extensions="NewAndEditQuotesController" id="page">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
+    <apex:form id="form">
+        <apex:pageblock id="pageBlock">
+            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
+                <!--Each section has layoutFields, let's iterate them as well-->
+                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
+                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Quotes__c[encryptedAPI]}" />
+                </apex:repeat>
+            </apex:pageBlockSection>
+            <script>
+                var config = {
+                    SobjectName : "{!SobjectName}",
+                    ApiPrefix:"{!ApiPrefix}",
+                    AWSToSobjectMap:{!AWSToSobjectMapJson},
+                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
+                };
+                var staticResources = JSON.parse('{!staticResource}');
+                function QuerySobjectFromAWS() {
+                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+                }
+                var queryBack = function queryBack(data) {
+                    if(!data.object){
+                        console.log('data.object is ' + data.object);
+                        return;
+                    }
+
+                    for(let f in config.AWSToSobjectNonEncryptedMap){
+                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
+                        let ele = document.querySelector(t);
+                        if(ele){
+                            ele.title = '';
+                            if(data.object.hasOwnProperty(f)){
+                                ele.innerHTML = data.object[f];
+                            }
+                            else{
+                                console.log(f + 'is not in data.object');
+                            }
+                        }else{
+                            console.log('selector='+t+' not found');
+                        }
+                        
+                    }
+                    // 褰撲笉鑳借嚜鍔ㄦ纭浛鎹㈠姞瀵嗘暟鎹椂闇�瑕佸湪姝ゅ娣诲姞js锛岀‖缂栫爜澶勭悊
+                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                };
+                sfdcPage.appendToOnloadQueue(function () {
+                    console.log('sfdcPage.appendToOnloadQueue')
+                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '濮撳悕'
+                    QuerySobjectFromAWS();
+                });
+            </script>
+        </apex:pageblock>
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewQuotesDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewQuotesDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..5a87d53
--- /dev/null
+++ b/force-app/main/default/pages/ViewQuotesDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewQuotesDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewRepairDecryptInfo.page b/force-app/main/default/pages/ViewRepairDecryptInfo.page
new file mode 100644
index 0000000..72e3047
--- /dev/null
+++ b/force-app/main/default/pages/ViewRepairDecryptInfo.page
@@ -0,0 +1,42 @@
+<apex:page standardController="Repair__c" extensions="NewAndEditRepairController" id="page">
+    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
+    <apex:form id="form">
+        <apex:pageblock id="pageBlock">
+            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
+                <!--Each section has layoutFields, let's iterate them as well-->
+                <apex:outputField value="{!Repair__c.Telephonen__c}" />
+                
+            </apex:pageBlockSection>
+            <script>
+                var config = {
+                    SobjectName : "{!SobjectName}",
+                    ApiPrefix:"{!ApiPrefix}",
+                    AWSToSobjectMap:{!AWSToSobjectMapJson},
+                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
+                };
+                var staticResources = JSON.parse('{!staticResource}');
+                var staticResourceContact = JSON.parse('{!staticResourceContact}');
+                function QuerySobjectFromAWS() {
+                    AWSService.query(staticResourceContact.queryUrl, '{!contactAWSDataId.AWS_Data_Id__c}', queryBack, staticResources.token);
+                }
+                var queryBack = function queryBack(data) {
+                    //if(!data.object){
+                    //    console.log('data.object is ' + data.object);
+                    //    return;
+                    //}
+                    console.log('data.object.Phone is ' + JSON.stringify(data.object));
+
+                    document.getElementById("page:form:pageBlock:pageBlockSection:j_id1").innerText = data.object.phone;
+                    // 褰撲笉鑳借嚜鍔ㄦ纭浛鎹㈠姞瀵嗘暟鎹椂闇�瑕佸湪姝ゅ娣诲姞js锛岀‖缂栫爜澶勭悊
+                    //document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                };
+                sfdcPage.appendToOnloadQueue(function () {
+                    console.log('sfdcPage.appendToOnloadQueue')
+                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '濮撳悕'
+                    QuerySobjectFromAWS();
+                });
+            </script>
+        </apex:pageblock>
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewRepairDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewRepairDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..fc8202e
--- /dev/null
+++ b/force-app/main/default/pages/ViewRepairDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>52.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewRepairDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/pages/ViewUserFaultInfoDecryptInfo.page b/force-app/main/default/pages/ViewUserFaultInfoDecryptInfo.page
new file mode 100644
index 0000000..a5e93a2
--- /dev/null
+++ b/force-app/main/default/pages/ViewUserFaultInfoDecryptInfo.page
@@ -0,0 +1,63 @@
+<!--
+  @description       : 
+  @author            : ChangeMeIn@UserSettingsUnder.SFDoc
+  @group             : 
+  @last modified on  : 02-28-2022
+  @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
+-->
+<apex:page standardController="User_FaultInfo__c" extensions="NewAndEditUserFaultInfoController" id="page">
+  <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
+    <apex:form id="form">
+        <apex:pageblock id="pageBlock">
+            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
+                <!--Each section has layoutFields, let's iterate them as well-->
+                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
+                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!User_FaultInfo__c[encryptedAPI]}" />
+                </apex:repeat>
+            </apex:pageBlockSection>
+            <script>
+                var config = {
+                    SobjectName : "{!SobjectName}",
+                    ApiPrefix:"{!ApiPrefix}",
+                    AWSToSobjectMap:{!AWSToSobjectMapJson},
+                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
+                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
+                };
+                var staticResources = JSON.parse('{!staticResource}');
+                function QuerySobjectFromAWS() {
+                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
+                }
+                var queryBack = function queryBack(data) {
+                    if(!data.object){
+                        console.log('data.object is ' + data.object);
+                        return;
+                    }
+
+                    for(let f in config.AWSToSobjectNonEncryptedMap){
+                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
+                        let ele = document.querySelector(t);
+                        if(ele){
+                            ele.title = '';
+                            if(data.object.hasOwnProperty(f)){
+                                ele.innerHTML = data.object[f];
+                            }
+                            else{
+                                console.log(f + 'is not in data.object');
+                            }
+                        }else{
+                            console.log('selector='+t+' not found');
+                        }
+                        
+                    }
+                    // 褰撲笉鑳借嚜鍔ㄦ纭浛鎹㈠姞瀵嗘暟鎹椂闇�瑕佸湪姝ゅ娣诲姞js锛岀‖缂栫爜澶勭悊
+                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
+                };
+                sfdcPage.appendToOnloadQueue(function () {
+                    console.log('sfdcPage.appendToOnloadQueue')
+                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '濮撳悕'
+                    QuerySobjectFromAWS();
+                });
+            </script>
+        </apex:pageblock>
+    </apex:form>
+</apex:page>
\ No newline at end of file
diff --git a/force-app/main/default/pages/ViewUserFaultInfoDecryptInfo.page-meta.xml b/force-app/main/default/pages/ViewUserFaultInfoDecryptInfo.page-meta.xml
new file mode 100644
index 0000000..00f23a4
--- /dev/null
+++ b/force-app/main/default/pages/ViewUserFaultInfoDecryptInfo.page-meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
+    <apiVersion>54.0</apiVersion>
+    <availableInTouch>false</availableInTouch>
+    <confirmationTokenRequired>false</confirmationTokenRequired>
+    <label>ViewUserFaultInfoDecryptInfo</label>
+</ApexPage>
diff --git a/force-app/main/default/staticresources/AWSService.resource-meta.xml b/force-app/main/default/staticresources/AWSService.resource-meta.xml
new file mode 100644
index 0000000..78e2716
--- /dev/null
+++ b/force-app/main/default/staticresources/AWSService.resource-meta.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
+    <cacheControl>Public</cacheControl>
+    <contentType>application/zip</contentType>
+</StaticResource>
diff --git a/force-app/main/default/staticresources/AWSService/AWSService.js b/force-app/main/default/staticresources/AWSService/AWSService.js
new file mode 100644
index 0000000..200d05c
--- /dev/null
+++ b/force-app/main/default/staticresources/AWSService/AWSService.js
@@ -0,0 +1,222 @@
+class AWSService {
+    static sfSessionId = '';
+    static insertModule = 'Insert AWS ';
+    static updateModule = 'Update AWS ';
+    static queryModule = 'Query AWS ';
+    static searchModule = 'Search AWS ';
+    static confirmTrans = 'Confirm Transaction To AWS';
+    static successStatus = 'success';
+    static failStatus = 'fail';
+    static insertCalloutLog(module,url,request,response,status){
+        if(this.sfSessionId){
+            sforce.connection.sessionId = this.sfSessionId;
+            let transLog = new sforce.SObject('Transaction_Log__c');
+            transLog.AWS_Data_Id__c = '';
+            transLog.Module__c = module;
+            transLog.Interface_URL__c = url;
+            transLog.Request__c = request;
+            transLog.Response__c = response;
+            transLog.Status__c = status;
+            let insertLogResult = sforce.connection.create([transLog]);     
+            if(insertLogResult[0].getBoolean(this.successStatus)) {
+                console.log('Insert Log Id: ' + insertLogResult[0].id);
+                return insertLogResult[0].id;
+            }else {
+                console.log('Faield to insert log');
+                return '';
+            }
+        }       
+    }
+    //Search Contact
+    static search(searchUrl,requestSearchPayload,searchBack,token) {
+        fetch(searchUrl, {
+            method: 'POST',
+            body: requestSearchPayload,
+            headers: {
+                'Content-Type': 'application/json',
+                'pi-token': token
+            }
+        }).then((data) => {
+            return data.json();
+        }).then((result) => {
+            this.insertCalloutLog(this.searchModule,searchUrl,JSON.stringify(requestSearchPayload),JSON.stringify(result),this.successStatus);
+            searchBack(result);      
+        }).catch(error => {
+            this.insertCalloutLog(this.searchModule,searchUrl,JSON.stringify(requestSearchPayload),JSON.stringify(error),this.failStatus);
+            console.log(error);
+        });
+    }
+
+    //query
+    static query(queryURL, awsDataId, queryback, token) {
+        fetch(queryURL + '?dataId=' + awsDataId, {
+            method: 'GET',
+            headers: {
+                'Content-Type': 'application/json',
+                'pi-token': token
+            }
+        }).then((data) => {         
+            return data.json();
+        }).then((data) => {
+            this.insertCalloutLog(this.queryModule,queryURL,queryURL + '?dataId=' + awsDataId,JSON.stringify(data),this.successStatus);
+            queryback(data);
+        }).catch(error => {
+            this.insertCalloutLog(this.queryModule,queryURL,queryURL + '?dataId=' + awsDataId,JSON.stringify(error),this.failStatus);
+            console.log(error);
+        });
+    }
+
+    //queryTSRepair
+    static queryTSRepair(queryURL, awsDataId, queryback, token,number) {
+        fetch(queryURL + '?dataId=' + awsDataId, {
+            method: 'GET',
+            headers: {
+                'Content-Type': 'application/json',
+                'pi-token': token
+            }
+        }).then((data) => {         
+            return data.json();
+        }).then((data) => {
+            this.insertCalloutLog(this.queryModule,queryURL,queryURL + '?dataId=' + awsDataId,JSON.stringify(data),this.successStatus);
+            queryback(data,number);
+        }).catch(error => {
+            this.insertCalloutLog(this.queryModule,queryURL,queryURL + '?dataId=' + awsDataId,JSON.stringify(error),this.failStatus);
+            console.log(error);
+        });
+    }
+
+    //insert
+    static insert(newURL, payloadJson, payloadForNewPI, controllerSaveMethod, token, transactionURL,isNewMode,insertOrUpdateBack,redirectCallBack) {
+        console.log('Process New PI Data');
+        console.log(JSON.stringify(payloadForNewPI));
+        fetch(newURL, {
+            method: 'POST',
+            body: payloadForNewPI,
+            headers: {
+                'Content-Type': 'application/json',
+                'pi-token': token
+            }
+        }).then((data) => {
+            console.log('data=' + JSON.stringify(data));
+            return data.json();
+        }).then((result) => {
+            this.insertCalloutLog(this.insertModule,newURL,JSON.stringify(payloadForNewPI),JSON.stringify(result),this.successStatus);
+            AWSService.back(result, payloadJson, transactionURL, token, controllerSaveMethod,isNewMode,insertOrUpdateBack,redirectCallBack);
+        }).catch(error => {
+            this.insertCalloutLog(this.insertModule,newURL,JSON.stringify(payloadForNewPI),JSON.stringify(error),this.failStatus);
+            console.log(error);
+        });
+    }
+
+    //update
+    static update(updateURL, payloadJson, payloadForNewPI, controllerSaveMethod, token, transactionURL,isNewMode,insertOrUpdateBack,redirectCallBack) {
+        console.log('Process New PI Data');
+        console.log(JSON.stringify(payloadForNewPI));
+        fetch(updateURL, {
+            method: 'POST',
+            body: payloadForNewPI,
+            headers: {
+                'Content-Type': 'application/json',
+                'pi-token': token
+            }
+        }).then((data) => {
+            console.log('data=' + JSON.stringify(data));
+            return data.json();
+        }).then((result) => {
+            this.insertCalloutLog(this.updateModule,updateURL,JSON.stringify(payloadForNewPI),JSON.stringify(result),this.successStatus);
+            AWSService.back(result, payloadJson, transactionURL, token, controllerSaveMethod,isNewMode,insertOrUpdateBack,redirectCallBack);
+        }).catch(error => {
+            this.insertCalloutLog(this.updateModule,updateURL,JSON.stringify(payloadForNewPI),JSON.stringify(error),this.failStatus);
+            console.log(error);
+        });
+    }
+
+    //update
+    static post(postURL, payloadForNewPI, callback, token) {
+        console.log('Process New PI Data');
+        console.log(JSON.stringify(payloadForNewPI));
+        fetch(postURL, {
+            method: 'POST',
+            body: payloadForNewPI,
+            headers: {
+                'Content-Type': 'application/json',
+                'pi-token': token
+            }
+        }).then((data) => {
+            console.log('data=' + JSON.stringify(data));
+            return data.json();
+        }).then((result) => {
+            this.insertCalloutLog(this.insertModule,postURL,JSON.stringify(payloadForNewPI),JSON.stringify(result),this.successStatus);
+            callback(result);
+        }).catch(error => {
+            this.insertCalloutLog(this.insertModule,postURL,JSON.stringify(payloadForNewPI),JSON.stringify(error),this.failStatus);
+            console.log(error);
+        });
+    }
+
+    static sfdcBack = function sfdcBack(event, result, transId, token, transactionURL,redirectCallBack) {
+        let sfId = '';
+        if (event.status) {
+            console.log('sf Id from SF Backend:' + JSON.stringify(result));
+            if (result.status == 'success') {
+                sfId = result.recordId;
+                let transParameters = {
+                    txId: transId,
+                    sfRecordId:sfId,
+                    isSuccess: 1
+                };
+                console.log(transParameters);
+                fetch(transactionURL, {
+                    method: 'POST',
+                    body: JSON.stringify(transParameters),
+                    headers: {
+                        'Content-Type': 'application/json',
+                        'pi-token': token
+                    }
+                }).then((result) => {
+                    this.insertCalloutLog(this.confirmTrans,transactionURL,JSON.stringify(transParameters),JSON.stringify(result),this.successStatus);
+                    redirectCallBack(sfId,'');
+                }).catch(error => {
+                    this.insertCalloutLog(this.confirmTrans,transactionURL,JSON.stringify(transParameters),JSON.stringify(error),this.failStatus);
+                    console.log(error);
+                });
+            } else {
+                let errorMsg = result.message;
+                let transParameters = {
+                    txId: transId,
+                    sfRecordId:sfId,
+                    isSuccess: 0
+                };
+                console.log(transParameters);
+                fetch(transactionURL, {
+                    method: 'POST',
+                    body: JSON.stringify(transParameters),
+                    headers: {
+                        'Content-Type': 'application/json',
+                        'pi-token': token
+                    }
+                }).then((result) => {
+                    this.insertCalloutLog(this.confirmTrans,transactionURL,JSON.stringify(transParameters),JSON.stringify(result),this.successStatus);
+                    redirectCallBack('',errorMsg);
+                }).catch(error => {
+                    this.insertCalloutLog(this.confirmTrans,transactionURL,JSON.stringify(transParameters),JSON.stringify(error),this.failStatus);
+                    console.log(error);
+                });
+            }
+        }
+    }
+
+    // AWSService.back(result, payloadJson, transactionURL, token, controllerSaveMethod);
+    static back = function back(result, payloadJson, transactionURL, token, controllerSaveMethod,isNewMode,insertOrUpdateBack,redirectCallBack) {
+        let payloadJsonStr = JSON.stringify(insertOrUpdateBack(payloadJson, result,isNewMode));
+        let transId = result.txId + '';
+        Visualforce.remoting.Manager.invokeAction(
+            controllerSaveMethod, // example '{!$RemoteAction.NewAndEditLeadController.saveLead}'
+            payloadJsonStr, transId, isNewMode,
+            function (result, event) {
+                AWSService.sfdcBack(event, result, transId, token, transactionURL,redirectCallBack);
+            },
+            { escape: true }
+        );
+    }
+};
\ No newline at end of file
diff --git a/force-app/main/default/staticresources/html2canvas.js b/force-app/main/default/staticresources/html2canvas.js
new file mode 100644
index 0000000..b2f5878
--- /dev/null
+++ b/force-app/main/default/staticresources/html2canvas.js
@@ -0,0 +1,10 @@
+/*
+  html2canvas 0.5.0-beta4 <http://html2canvas.hertzen.com>
+  Copyright (c) 2017 Niklas von Hertzen
+  2017-06-14 Custom build by Erik Koopmans, featuring latest bugfixes and features
+
+  Released under MIT License
+*/
+!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.html2canvas=a()}}(function(){var a;return function b(a,c,d){function e(g,h){if(!c[g]){if(!a[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};a[g][0].call(k.exports,function(b){var c=a[g][1][b];return e(c?c:b)},k,k.exports,b,a,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(b,c,d){(function(b){!function(e){function f(a){throw new RangeError(I[a])}function g(a,b){for(var c=a.length,d=[];c--;)d[c]=b(a[c]);return d}function h(a,b){var c=a.split("@"),d="";c.length>1&&(d=c[0]+"@",a=c[1]),a=a.replace(H,".");var e=a.split("."),f=g(e,b).join(".");return d+f}function i(a){for(var b,c,d=[],e=0,f=a.length;e<f;)b=a.charCodeAt(e++),b>=55296&&b<=56319&&e<f?(c=a.charCodeAt(e++),56320==(64512&c)?d.push(((1023&b)<<10)+(1023&c)+65536):(d.push(b),e--)):d.push(b);return d}function j(a){return g(a,function(a){var b="";return a>65535&&(a-=65536,b+=L(a>>>10&1023|55296),a=56320|1023&a),b+=L(a)}).join("")}function k(a){return a-48<10?a-22:a-65<26?a-65:a-97<26?a-97:x}function l(a,b){return a+22+75*(a<26)-((0!=b)<<5)}function m(a,b,c){var d=0;for(a=c?K(a/B):a>>1,a+=K(a/b);a>J*z>>1;d+=x)a=K(a/J);return K(d+(J+1)*a/(a+A))}function n(a){var b,c,d,e,g,h,i,l,n,o,p=[],q=a.length,r=0,s=D,t=C;for(c=a.lastIndexOf(E),c<0&&(c=0),d=0;d<c;++d)a.charCodeAt(d)>=128&&f("not-basic"),p.push(a.charCodeAt(d));for(e=c>0?c+1:0;e<q;){for(g=r,h=1,i=x;e>=q&&f("invalid-input"),l=k(a.charCodeAt(e++)),(l>=x||l>K((w-r)/h))&&f("overflow"),r+=l*h,n=i<=t?y:i>=t+z?z:i-t,!(l<n);i+=x)o=x-n,h>K(w/o)&&f("overflow"),h*=o;b=p.length+1,t=m(r-g,b,0==g),K(r/b)>w-s&&f("overflow"),s+=K(r/b),r%=b,p.splice(r++,0,s)}return j(p)}function o(a){var b,c,d,e,g,h,j,k,n,o,p,q,r,s,t,u=[];for(a=i(a),q=a.length,b=D,c=0,g=C,h=0;h<q;++h)p=a[h],p<128&&u.push(L(p));for(d=e=u.length,e&&u.push(E);d<q;){for(j=w,h=0;h<q;++h)p=a[h],p>=b&&p<j&&(j=p);for(r=d+1,j-b>K((w-c)/r)&&f("overflow"),c+=(j-b)*r,b=j,h=0;h<q;++h)if(p=a[h],p<b&&++c>w&&f("overflow"),p==b){for(k=c,n=x;o=n<=g?y:n>=g+z?z:n-g,!(k<o);n+=x)t=k-o,s=x-o,u.push(L(l(o+t%s,0))),k=K(t/s);u.push(L(l(k,0))),g=m(c,r,d==e),c=0,++d}++c,++b}return u.join("")}function p(a){return h(a,function(a){return F.test(a)?n(a.slice(4).toLowerCase()):a})}function q(a){return h(a,function(a){return G.test(a)?"xn--"+o(a):a})}var r="object"==typeof d&&d&&!d.nodeType&&d,s="object"==typeof c&&c&&!c.nodeType&&c,t="object"==typeof b&&b;t.global!==t&&t.window!==t&&t.self!==t||(e=t);var u,v,w=2147483647,x=36,y=1,z=26,A=38,B=700,C=72,D=128,E="-",F=/^xn--/,G=/[^\x20-\x7E]/,H=/[\x2E\u3002\uFF0E\uFF61]/g,I={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},J=x-y,K=Math.floor,L=String.fromCharCode;if(u={version:"1.4.1",ucs2:{decode:i,encode:j},decode:n,encode:o,toASCII:q,toUnicode:p},"function"==typeof a&&"object"==typeof a.amd&&a.amd)a("punycode",function(){return u});else if(r&&s)if(c.exports==r)s.exports=u;else for(v in u)u.hasOwnProperty(v)&&(r[v]=u[v]);else e.punycode=u}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],2:[function(a,b,c){function d(a,b,c){!a.defaultView||b===a.defaultView.pageXOffset&&c===a.defaultView.pageYOffset||a.defaultView.scrollTo(b,c)}function e(a,b){try{b&&(b.width=a.width,b.height=a.height,b.getContext("2d").putImageData(a.getContext("2d").getImageData(0,0,a.width,a.height),0,0))}catch(c){h("Unable to copy canvas content from",a,c)}}function f(a,b){for(var c=3===a.nodeType?document.createTextNode(a.nodeValue):a.cloneNode(!1),d=a.firstChild;d;)b!==!0&&1===d.nodeType&&"SCRIPT"===d.nodeName||c.appendChild(f(d,b)),d=d.nextSibling;return 1===a.nodeType&&(c._scrollTop=a.scrollTop,c._scrollLeft=a.scrollLeft,"CANVAS"===a.nodeName?e(a,c):"TEXTAREA"!==a.nodeName&&"SELECT"!==a.nodeName||(c.value=a.value)),c}function g(a){if(1===a.nodeType){a.scrollTop=a._scrollTop,a.scrollLeft=a._scrollLeft;for(var b=a.firstChild;b;)g(b),b=b.nextSibling}}var h=a("./log");b.exports=function(a,b,c,e,h,i,j){var k=f(a.documentElement,h.javascriptEnabled),l=b.createElement("iframe");return l.className="html2canvas-container",l.style.visibility="hidden",l.style.position="fixed",l.style.left="-10000px",l.style.top="0px",l.style.border="0",l.width=c,l.height=e,l.scrolling="no",b.body.appendChild(l),new Promise(function(b){var c=l.contentWindow.document;l.contentWindow.onload=l.onload=function(){var a=setInterval(function(){c.body.childNodes.length>0&&(g(c.documentElement),clearInterval(a),"view"===h.type&&(l.contentWindow.scrollTo(i,j),!/(iPad|iPhone|iPod)/g.test(navigator.userAgent)||l.contentWindow.scrollY===j&&l.contentWindow.scrollX===i||(c.documentElement.style.top=-j+"px",c.documentElement.style.left=-i+"px",c.documentElement.style.position="absolute")),b(l))},50)},c.open(),c.write("<!DOCTYPE html><html></html>"),d(a,i,j),c.replaceChild(c.adoptNode(k),c.documentElement),c.close()})}},{"./log":13}],3:[function(a,b,c){function d(a){this.r=0,this.g=0,this.b=0,this.a=null;this.fromArray(a)||this.namedColor(a)||this.rgb(a)||this.rgba(a)||this.hex6(a)||this.hex3(a)}d.prototype.darken=function(a){var b=1-a;return new d([Math.round(this.r*b),Math.round(this.g*b),Math.round(this.b*b),this.a])},d.prototype.isTransparent=function(){return 0===this.a},d.prototype.isBlack=function(){return 0===this.r&&0===this.g&&0===this.b},d.prototype.fromArray=function(a){return Array.isArray(a)&&(this.r=Math.min(a[0],255),this.g=Math.min(a[1],255),this.b=Math.min(a[2],255),a.length>3&&(this.a=a[3])),Array.isArray(a)};var e=/^#([a-f0-9]{3})$/i;d.prototype.hex3=function(a){var b=null;return null!==(b=a.match(e))&&(this.r=parseInt(b[1][0]+b[1][0],16),this.g=parseInt(b[1][1]+b[1][1],16),this.b=parseInt(b[1][2]+b[1][2],16)),null!==b};var f=/^#([a-f0-9]{6})$/i;d.prototype.hex6=function(a){var b=null;return null!==(b=a.match(f))&&(this.r=parseInt(b[1].substring(0,2),16),this.g=parseInt(b[1].substring(2,4),16),this.b=parseInt(b[1].substring(4,6),16)),null!==b};var g=/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/;d.prototype.rgb=function(a){var b=null;return null!==(b=a.match(g))&&(this.r=Number(b[1]),this.g=Number(b[2]),this.b=Number(b[3])),null!==b};var h=/^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d?\.?\d+)\s*\)$/;d.prototype.rgba=function(a){var b=null;return null!==(b=a.match(h))&&(this.r=Number(b[1]),this.g=Number(b[2]),this.b=Number(b[3]),this.a=Number(b[4])),null!==b},d.prototype.toString=function(){return null!==this.a&&1!==this.a?"rgba("+[this.r,this.g,this.b,this.a].join(",")+")":"rgb("+[this.r,this.g,this.b].join(",")+")"},d.prototype.namedColor=function(a){a=a.toLowerCase();var b=i[a];if(b)this.r=b[0],this.g=b[1],this.b=b[2];else if("transparent"===a)return this.r=this.g=this.b=this.a=0,!0;return!!b},d.prototype.isColor=!0;var i={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]};b.exports=d},{}],4:[function(b,c,d){function e(a,b){var c=v++;if(b=b||{},b.logging&&(p.options.logging=!0,p.options.start=Date.now()),b.async="undefined"==typeof b.async||b.async,b.allowTaint="undefined"!=typeof b.allowTaint&&b.allowTaint,b.removeContainer="undefined"==typeof b.removeContainer||b.removeContainer,b.javascriptEnabled="undefined"!=typeof b.javascriptEnabled&&b.javascriptEnabled,b.imageTimeout="undefined"==typeof b.imageTimeout?1e4:b.imageTimeout,b.renderer="function"==typeof b.renderer?b.renderer:l,b.strict=!!b.strict,"string"==typeof a){if("string"!=typeof b.proxy)return Promise.reject("Proxy must be used when rendering url");var d=null!=b.width?b.width:window.innerWidth,e=null!=b.height?b.height:window.innerHeight;return s(j(a),b.proxy,document,d,e,b).then(function(a){return g(a.contentWindow.document.documentElement,a,b,d,e)})}var h=(void 0===a?[document.documentElement]:a.length?a:[a])[0];return h.setAttribute(u+c,c),f(h.ownerDocument,b,h.ownerDocument.defaultView.innerWidth,h.ownerDocument.defaultView.innerHeight,c).then(function(a){return"function"==typeof b.onrendered&&(p("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"),b.onrendered(a)),a})}function f(a,b,c,d,e){return r(a,a,c,d,b,a.defaultView.pageXOffset,a.defaultView.pageYOffset).then(function(f){p("Document cloned");var h=u+e,i="["+h+"='"+e+"']";a.querySelector(i).removeAttribute(h);var j=f.contentWindow,k=j.document.querySelector(i),l="function"==typeof b.onclone?Promise.resolve(b.onclone(j.document)):Promise.resolve(!0);return l.then(function(){return g(k,f,b,c,d)})})}function g(a,b,c,d,e){var f=b.contentWindow,g=new k(f.document),j=new m(c,g),l=t(a),o="view"===c.type?d:l.right+1,q="view"===c.type?e:l.bottom+1,r=new c.renderer(o,q,j,c,document),s=new n(a,r,g,j,c);return s.ready.then(function(){p("Finished rendering");var d;if("view"===c.type)d=i(r.canvas,{width:r.canvas.width,height:r.canvas.height,top:0,left:0,x:0,y:0});else if(a===f.document.body||a===f.document.documentElement||null!=c.canvas)d=r.canvas;else if(c.scale){var e={width:null!=c.width?c.width:l.width,height:null!=c.height?c.height:l.height,top:l.top,left:l.left,x:0,y:0},g={};for(var j in e)e.hasOwnProperty(j)&&(g[j]=e[j]*c.scale);d=i(r.canvas,g),d.style.width=e.width+"px",d.style.height=e.height+"px"}else d=i(r.canvas,{width:null!=c.width?c.width:l.width,height:null!=c.height?c.height:l.height,top:l.top,left:l.left,x:0,y:0});return h(b,c),d})}function h(a,b){b.removeContainer&&(a.parentNode.removeChild(a),p("Cleaned up container"))}function i(a,b){var c=document.createElement("canvas"),d=Math.min(a.width-1,Math.max(0,b.left)),e=Math.min(a.width,Math.max(1,b.left+b.width)),f=Math.min(a.height-1,Math.max(0,b.top)),g=Math.min(a.height,Math.max(1,b.top+b.height));c.width=b.width,c.height=b.height;var h=e-d,i=g-f;return p("Cropping canvas at:","left:",b.left,"top:",b.top,"width:",h,"height:",i),p("Resulting crop with width",b.width,"and height",b.height,"with x",d,"and y",f),c.getContext("2d").drawImage(a,d,f,h,i,b.x,b.y,h,i),c}function j(a){var b=document.createElement("a");return b.href=a,b.href=b.href,b}var k=b("./support"),l=b("./renderers/canvas"),m=b("./imageloader"),n=b("./nodeparser"),o=b("./nodecontainer"),p=b("./log"),q=b("./utils"),r=b("./clone"),s=b("./proxy").loadUrlDocument,t=q.getBounds,u="data-html2canvas-node",v=0;e.CanvasRenderer=l,e.NodeContainer=o,e.log=p,e.utils=q;var w="undefined"==typeof document||"function"!=typeof Object.create||"function"!=typeof document.createElement("canvas").getContext?function(){return Promise.reject("No canvas support")}:e;c.exports=w,"function"==typeof a&&a.amd&&a("html2canvas",[],function(){return w})},{"./clone":2,"./imageloader":11,"./log":13,"./nodecontainer":14,"./nodeparser":15,"./proxy":16,"./renderers/canvas":20,"./support":22,"./utils":26}],5:[function(a,b,c){function d(a){if(this.src=a,e("DummyImageContainer for",a),!this.promise||!this.image){e("Initiating DummyImageContainer"),d.prototype.image=new Image;var b=this.image;d.prototype.promise=new Promise(function(a,c){b.onload=a,b.onerror=c,b.src=f(),b.complete===!0&&a(b)})}}var e=a("./log"),f=a("./utils").smallImage;b.exports=d},{"./log":13,"./utils":26}],6:[function(a,b,c){function d(a,b){var c,d,f=document.createElement("div"),g=document.createElement("img"),h=document.createElement("span"),i="Hidden Text";f.style.visibility="hidden",f.style.fontFamily=a,f.style.fontSize=b,f.style.margin=0,f.style.padding=0,document.body.appendChild(f),g.src=e(),g.width=1,g.height=1,g.style.margin=0,g.style.padding=0,g.style.verticalAlign="baseline",h.style.fontFamily=a,h.style.fontSize=b,h.style.margin=0,h.style.padding=0,h.appendChild(document.createTextNode(i)),f.appendChild(h),f.appendChild(g),c=g.offsetTop-h.offsetTop+1,f.removeChild(h),f.appendChild(document.createTextNode(i)),f.style.lineHeight="normal",g.style.verticalAlign="super",d=g.offsetTop-f.offsetTop+1,document.body.removeChild(f),this.baseline=c,this.lineWidth=1,this.middle=d}var e=a("./utils").smallImage;b.exports=d},{"./utils":26}],7:[function(a,b,c){function d(){this.data={}}var e=a("./font");d.prototype.getMetrics=function(a,b){return void 0===this.data[a+"-"+b]&&(this.data[a+"-"+b]=new e(a,b)),this.data[a+"-"+b]},b.exports=d},{"./font":6}],8:[function(a,b,c){function d(b,c,d){this.image=null,this.src=b;var e=this,g=f(b);this.promise=(c?new Promise(function(a){"about:blank"===b.contentWindow.document.URL||null==b.contentWindow.document.documentElement?b.contentWindow.onload=b.onload=function(){a(b)}:a(b)}):this.proxyLoad(d.proxy,g,d)).then(function(b){var c=a("./core");return c(b.contentWindow.document.documentElement,{type:"view",width:b.width,height:b.height,proxy:d.proxy,javascriptEnabled:d.javascriptEnabled,removeContainer:d.removeContainer,allowTaint:d.allowTaint,imageTimeout:d.imageTimeout/2})}).then(function(a){return e.image=a})}var e=a("./utils"),f=e.getBounds,g=a("./proxy").loadUrlDocument;d.prototype.proxyLoad=function(a,b,c){var d=this.src;return g(d.src,a,d.ownerDocument,b.width,b.height,c)},b.exports=d},{"./core":4,"./proxy":16,"./utils":26}],9:[function(a,b,c){function d(a){this.src=a.value,this.colorStops=[],this.type=null,this.x0=.5,this.y0=.5,this.x1=.5,this.y1=.5,this.promise=Promise.resolve(!0)}d.TYPES={LINEAR:1,RADIAL:2},d.REGEXP_COLORSTOP=/^\s*(rgba?\(\s*\d{1,3},\s*\d{1,3},\s*\d{1,3}(?:,\s*[0-9\.]+)?\s*\)|[a-z]{3,20}|#[a-f0-9]{3,6})(?:\s+(\d{1,3}(?:\.\d+)?)(%|px)?)?(?:\s|$)/i,b.exports=d},{}],10:[function(a,b,c){function d(a,b){this.src=a,this.image=new Image;var c=this;this.tainted=null,this.promise=new Promise(function(d,e){c.image.onload=d,c.image.onerror=e,b&&(c.image.crossOrigin="anonymous"),c.image.src=a,c.image.complete===!0&&d(c.image)})}b.exports=d},{}],11:[function(a,b,c){function d(a,b){this.link=null,this.options=a,this.support=b,this.origin=this.getOrigin(window.location.href)}var e=a("./log"),f=a("./imagecontainer"),g=a("./dummyimagecontainer"),h=a("./proxyimagecontainer"),i=a("./framecontainer"),j=a("./svgcontainer"),k=a("./svgnodecontainer"),l=a("./lineargradientcontainer"),m=a("./webkitgradientcontainer"),n=a("./utils").bind;d.prototype.findImages=function(a){var b=[];return a.reduce(function(a,b){switch(b.node.nodeName){case"IMG":return a.concat([{args:[b.node.src],method:"url"}]);case"svg":case"IFRAME":return a.concat([{args:[b.node],method:b.node.nodeName}])}return a},[]).forEach(this.addImage(b,this.loadImage),this),b},d.prototype.findBackgroundImage=function(a,b){return b.parseBackgroundImages().filter(this.hasImageBackground).forEach(this.addImage(a,this.loadImage),this),a},d.prototype.addImage=function(a,b){return function(c){c.args.forEach(function(d){this.imageExists(a,d)||(a.splice(0,0,b.call(this,c)),e("Added image #"+a.length,"string"==typeof d?d.substring(0,100):d))},this)}},d.prototype.hasImageBackground=function(a){return"none"!==a.method},d.prototype.loadImage=function(a){if("url"===a.method){var b=a.args[0];return!this.isSVG(b)||this.support.svg||this.options.allowTaint?b.match(/data:image\/.*;base64,/i)?new f(b.replace(/url\(['"]{0,}|['"]{0,}\)$/gi,""),(!1)):this.isSameOrigin(b)||this.options.allowTaint===!0||this.isSVG(b)?new f(b,(!1)):this.support.cors&&!this.options.allowTaint&&this.options.useCORS?new f(b,(!0)):this.options.proxy?new h(b,this.options.proxy):new g(b):new j(b)}return"linear-gradient"===a.method?new l(a):"gradient"===a.method?new m(a):"svg"===a.method?new k(a.args[0],this.support.svg):"IFRAME"===a.method?new i(a.args[0],this.isSameOrigin(a.args[0].src),this.options):new g(a)},d.prototype.isSVG=function(a){return"svg"===a.substring(a.length-3).toLowerCase()||j.prototype.isInline(a)},d.prototype.imageExists=function(a,b){return a.some(function(a){return a.src===b})},d.prototype.isSameOrigin=function(a){return this.getOrigin(a)===this.origin},d.prototype.getOrigin=function(a){var b=this.link||(this.link=document.createElement("a"));return b.href=a,b.href=b.href,b.protocol+b.hostname+b.port},d.prototype.getPromise=function(a){return this.timeout(a,this.options.imageTimeout)["catch"](function(){var b=new g(a.src);return b.promise.then(function(b){a.image=b})})},d.prototype.get=function(a){var b=null;return this.images.some(function(c){return(b=c).src===a})?b:null},d.prototype.fetch=function(a){return this.images=a.reduce(n(this.findBackgroundImage,this),this.findImages(a)),this.images.forEach(function(a,b){a.promise.then(function(){e("Succesfully loaded image #"+(b+1),a)},function(c){e("Failed loading image #"+(b+1),a,c)})}),this.ready=Promise.all(this.images.map(this.getPromise,this)),e("Finished searching images"),this},d.prototype.timeout=function(a,b){var c,d=Promise.race([a.promise,new Promise(function(d,f){c=setTimeout(function(){e("Timed out loading image",a),f(a)},b)})]).then(function(a){return clearTimeout(c),a});return d["catch"](function(){clearTimeout(c)}),d},b.exports=d},{"./dummyimagecontainer":5,"./framecontainer":8,"./imagecontainer":10,"./lineargradientcontainer":12,"./log":13,"./proxyimagecontainer":17,"./svgcontainer":23,"./svgnodecontainer":24,"./utils":26,"./webkitgradientcontainer":27}],12:[function(a,b,c){function d(a){e.apply(this,arguments),this.type=e.TYPES.LINEAR;var b=d.REGEXP_DIRECTION.test(a.args[0])||!e.REGEXP_COLORSTOP.test(a.args[0]);b?a.args[0].split(/\s+/).reverse().forEach(function(a,b){switch(a){case"left":this.x0=0,this.x1=1;break;case"top":this.y0=0,this.y1=1;break;case"right":this.x0=1,this.x1=0;break;case"bottom":this.y0=1,this.y1=0;break;case"to":var c=this.y0,d=this.x0;this.y0=this.y1,this.x0=this.x1,this.x1=d,this.y1=c;break;case"center":break;default:var e=.01*parseFloat(a,10);if(isNaN(e))break;0===b?(this.y0=e,this.y1=1-this.y0):(this.x0=e,this.x1=1-this.x0)}},this):(this.y0=0,this.y1=1),this.colorStops=a.args.slice(b?1:0).map(function(a){var b=a.match(e.REGEXP_COLORSTOP),c=+b[2],d=0===c?"%":b[3];return{color:new f(b[1]),stop:"%"===d?c/100:null}}),null===this.colorStops[0].stop&&(this.colorStops[0].stop=0),null===this.colorStops[this.colorStops.length-1].stop&&(this.colorStops[this.colorStops.length-1].stop=1),this.colorStops.forEach(function(a,b){null===a.stop&&this.colorStops.slice(b).some(function(c,d){return null!==c.stop&&(a.stop=(c.stop-this.colorStops[b-1].stop)/(d+1)+this.colorStops[b-1].stop,!0)},this)},this)}var e=a("./gradientcontainer"),f=a("./color");d.prototype=Object.create(e.prototype),d.REGEXP_DIRECTION=/^\s*(?:to|left|right|top|bottom|center|\d{1,3}(?:\.\d+)?%?)(?:\s|$)/i,b.exports=d},{"./color":3,"./gradientcontainer":9}],13:[function(a,b,c){var d=function(){d.options.logging&&window.console&&window.console.log&&Function.prototype.bind.call(window.console.log,window.console).apply(window.console,[Date.now()-d.options.start+"ms","html2canvas:"].concat([].slice.call(arguments,0)))};d.options={logging:!1},b.exports=d},{}],14:[function(a,b,c){function d(a,b){this.node=a,this.parent=b,this.stack=null,this.bounds=null,this.borders=null,this.clip=[],this.backgroundClip=[],this.offsetBounds=null,this.visible=null,this.computedStyles=null,this.colors={},this.styles={},this.backgroundImages=null,this.transformData=null,this.transformMatrix=null,this.isPseudoElement=!1,this.opacity=null}function e(a){var b=a.options[a.selectedIndex||0];return b?b.text||"":""}function f(a){if(a&&"matrix"===a[1])return a[2].split(",").map(function(a){return parseFloat(a.trim())});if(a&&"matrix3d"===a[1]){var b=a[2].split(",").map(function(a){return parseFloat(a.trim())});return[b[0],b[1],b[4],b[5],b[12],b[13]]}}function g(a){var b=a[0],c=a[2],d=a[4],e=a[1],f=a[3],g=a[5],h=b*f-c*e,i=[f,-e,-c,b,c*g-d*f,d*e-b*g].map(function(a){return a/h});return i}function h(a){return a.toString().indexOf("%")!==-1}function i(a){return a.replace("px","")}function j(a){return parseFloat(a)}var k=a("./color"),l=a("./utils"),m=l.getBounds,n=l.parseBackgrounds,o=l.offsetBounds;d.prototype.cloneTo=function(a){a.visible=this.visible,a.borders=this.borders,a.bounds=this.bounds,a.clip=this.clip,a.backgroundClip=this.backgroundClip,a.computedStyles=this.computedStyles,a.styles=this.styles,a.backgroundImages=this.backgroundImages,a.opacity=this.opacity},d.prototype.getOpacity=function(){return null===this.opacity?this.opacity=this.cssFloat("opacity"):this.opacity},d.prototype.assignStack=function(a){this.stack=a,a.children.push(this)},d.prototype.isElementVisible=function(){return this.node.nodeType===Node.TEXT_NODE?this.parent.visible:"none"!==this.css("display")&&"hidden"!==this.css("visibility")&&!this.node.hasAttribute("data-html2canvas-ignore")&&("INPUT"!==this.node.nodeName||"hidden"!==this.node.getAttribute("type"))},d.prototype.css=function(a){return this.computedStyles||(this.computedStyles=this.isPseudoElement?this.parent.computedStyle(this.before?":before":":after"):this.computedStyle(null)),this.styles[a]||(this.styles[a]=this.computedStyles[a])},d.prototype.prefixedCss=function(a){var b=["webkit","moz","ms","o"],c=this.css(a);return void 0===c&&b.some(function(b){return c=this.css(b+a.substr(0,1).toUpperCase()+a.substr(1)),void 0!==c},this),void 0===c?null:c},d.prototype.computedStyle=function(a){return this.node.ownerDocument.defaultView.getComputedStyle(this.node,a)},d.prototype.cssInt=function(a){var b=parseInt(this.css(a),10);return isNaN(b)?0:b},d.prototype.color=function(a){return this.colors[a]||(this.colors[a]=new k(this.css(a)))},d.prototype.cssFloat=function(a){var b=parseFloat(this.css(a));return isNaN(b)?0:b},d.prototype.fontWeight=function(){var a=this.css("fontWeight");switch(parseInt(a,10)){case 401:a="bold";break;case 400:a="normal"}return a},d.prototype.parseClip=function(){var a=this.css("clip").match(this.CLIP);return a?{top:parseInt(a[1],10),right:parseInt(a[2],10),bottom:parseInt(a[3],10),left:parseInt(a[4],10)}:null},d.prototype.parseBackgroundImages=function(){return this.backgroundImages||(this.backgroundImages=n(this.css("backgroundImage")))},d.prototype.cssList=function(a,b){var c=(this.css(a)||"").split(",");return c=c[b||0]||c[0]||"auto",c=c.trim().split(" "),1===c.length&&(c=[c[0],h(c[0])?"auto":c[0]]),c},d.prototype.parseBackgroundSize=function(a,b,c){var d,e,f=this.cssList("backgroundSize",c);if(h(f[0]))d=a.width*parseFloat(f[0])/100;else{if(/contain|cover/.test(f[0])){var g=a.width/a.height,i=b.width/b.height;return g<i^"contain"===f[0]?{width:a.height*i,height:a.height}:{width:a.width,height:a.width/i}}d=parseInt(f[0],10)}return e="auto"===f[0]&&"auto"===f[1]?b.height:"auto"===f[1]?d/b.width*b.height:h(f[1])?a.height*parseFloat(f[1])/100:parseInt(f[1],10),"auto"===f[0]&&(d=e/b.height*b.width),{width:d,height:e}},d.prototype.parseBackgroundPosition=function(a,b,c,d){var e,f,g=this.cssList("backgroundPosition",c);return e=h(g[0])?(a.width-(d||b).width)*(parseFloat(g[0])/100):parseInt(g[0],10),f="auto"===g[1]?e/b.width*b.height:h(g[1])?(a.height-(d||b).height)*parseFloat(g[1])/100:parseInt(g[1],10),"auto"===g[0]&&(e=f/b.height*b.width),{left:e,top:f}},d.prototype.parseBackgroundRepeat=function(a){return this.cssList("backgroundRepeat",a)[0]},d.prototype.parseTextShadows=function(){var a=this.css("textShadow"),b=[];if(a&&"none"!==a)for(var c=a.match(this.TEXT_SHADOW_PROPERTY),d=0;c&&d<c.length;d++){var e=c[d].match(this.TEXT_SHADOW_VALUES);b.push({color:new k(e[0]),offsetX:e[1]?parseFloat(e[1].replace("px","")):0,offsetY:e[2]?parseFloat(e[2].replace("px","")):0,blur:e[3]?e[3].replace("px",""):0})}return b},d.prototype.parseTransform=function(){if(!this.transformData)if(this.hasTransform()){var a=this.parseBounds(),b=this.prefixedCss("transformOrigin").split(" ").map(i).map(j);b[0]+=a.left,b[1]+=a.top,this.transformData={origin:b,matrix:this.parseTransformMatrix()}}else this.transformData={origin:[0,0],matrix:[1,0,0,1,0,0]};return this.transformData},d.prototype.parseTransformMatrix=function(){if(!this.transformMatrix){var a=this.prefixedCss("transform"),b=a?f(a.match(this.MATRIX_PROPERTY)):null;this.transformMatrix=b?b:[1,0,0,1,0,0]}return this.transformMatrix},d.prototype.inverseTransform=function(){var a=this.parseTransform();return{origin:a.origin,matrix:g(a.matrix)}},d.prototype.parseBounds=function(){return this.bounds||(this.bounds=this.hasTransform()?o(this.node):m(this.node))},d.prototype.hasTransform=function(){return"1,0,0,1,0,0"!==this.parseTransformMatrix().join(",")||this.parent&&this.parent.hasTransform()},d.prototype.getValue=function(){var a=this.node.value||"";return"SELECT"===this.node.tagName?a=e(this.node):"password"===this.node.type&&(a=Array(a.length+1).join("鈥�")),0===a.length?this.node.placeholder||"":a},d.prototype.MATRIX_PROPERTY=/(matrix|matrix3d)\((.+)\)/,d.prototype.TEXT_SHADOW_PROPERTY=/((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g,d.prototype.TEXT_SHADOW_VALUES=/(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g,d.prototype.CLIP=/^rect\((\d+)px,? (\d+)px,? (\d+)px,? (\d+)px\)$/,b.exports=d},{"./color":3,"./utils":26}],15:[function(a,b,c){function d(a,b,c,d,e){P("Starting NodeParser"),this.renderer=b,this.options=e,this.range=null,this.support=c,this.renderQueue=[],this.stack=new W((!0),1,a.ownerDocument,null);var f=new R(a,null);if(e.background&&b.rectangle(0,0,b.width,b.height,new V(e.background)),a===a.ownerDocument.documentElement){var g=new R(f.color("backgroundColor").isTransparent()?a.ownerDocument.body:a.ownerDocument.documentElement,null);b.rectangle(0,0,b.width,b.height,g.color("backgroundColor"))}f.visibile=f.isElementVisible(),this.createPseudoHideStyles(a.ownerDocument),this.disableAnimations(a.ownerDocument),this.nodes=K([f].concat(this.getChildren(f)).filter(function(a){return a.visible=a.isElementVisible()}).map(this.getPseudoElements,this)),this.fontMetrics=new U,P("Fetched nodes, total:",this.nodes.length),P("Calculate overflow clips"),this.calculateOverflowClips(),P("Start fetching images"),this.images=d.fetch(this.nodes.filter(C)),this.ready=this.images.ready.then(Y(function(){return P("Images loaded, starting parsing"),P("Creating stacking contexts"),this.createStackingContexts(),P("Sorting stacking contexts"),this.sortStackingContexts(this.stack),this.parse(this.stack),P("Render queue created with "+this.renderQueue.length+" items"),new Promise(Y(function(a){e.async?"function"==typeof e.async?e.async.call(this,this.renderQueue,a):this.renderQueue.length>0?(this.renderIndex=0,this.asyncRenderer(this.renderQueue,a)):a():(this.renderQueue.forEach(this.paint,this),a())},this))},this))}function e(a){return a.parent&&a.parent.clip.length}function f(a){return a.replace(/(\-[a-z])/g,function(a){return a.toUpperCase().replace("-","")})}function g(){}function h(a,b,c,d){var e={top:b.top+a[0].width/2,right:b.right-a[1].width/2,bottom:b.bottom-a[2].width/2,left:b.left+a[3].width/2};return a.map(function(f,g){if(f.width>0){var h=b.left,i=b.top,j=b.width,k=b.height-a[2].width;switch(g){case 0:k=a[0].width,f.args=l({c1:[h,i],c2:[h+j,i],c3:[h+j-a[1].width,i+k],c4:[h+a[3].width,i+k]},d[0],d[1],c.topLeftOuter,c.topLeftInner,c.topRightOuter,c.topRightInner),f.pathArgs=m({c1:[e.left,e.top],c2:[e.right,e.top]},d[0],d[1],c.topLeft,c.topRight);break;case 1:h=b.left+b.width-a[1].width,j=a[1].width,f.args=l({c1:[h+j,i],c2:[h+j,i+k+a[2].width],c3:[h,i+k],c4:[h,i+a[0].width]},d[1],d[2],c.topRightOuter,c.topRightInner,c.bottomRightOuter,c.bottomRightInner),f.pathArgs=m({c1:[e.right,e.top],c2:[e.right,e.bottom]},d[1],d[2],c.topRight,c.bottomRight);break;case 2:i=i+b.height-a[2].width,k=a[2].width,f.args=l({c1:[h+j,i+k],c2:[h,i+k],c3:[h+a[3].width,i],c4:[h+j-a[3].width,i]},d[2],d[3],c.bottomRightOuter,c.bottomRightInner,c.bottomLeftOuter,c.bottomLeftInner),f.pathArgs=m({c1:[e.right,e.bottom],c2:[e.left,e.bottom]},d[2],d[3],c.bottomRight,c.bottomLeft);break;case 3:j=a[3].width,f.args=l({c1:[h,i+k+a[2].width],c2:[h,i],c3:[h+j,i+a[0].width],c4:[h+j,i+k]},d[3],d[0],c.bottomLeftOuter,c.bottomLeftInner,c.topLeftOuter,c.topLeftInner),f.pathArgs=m({c1:[e.left,e.bottom],c2:[e.left,e.top]},d[3],d[0],c.bottomLeft,c.topLeft)}}return f})}function i(a,b,c,d){var e=4*((Math.sqrt(2)-1)/3),f=c*e,g=d*e,h=a+c,i=b+d;return{topLeft:k({x:a,y:i},{x:a,y:i-g},{x:h-f,y:b},{x:h,y:b}),topRight:k({x:a,y:b},{x:a+f,y:b},{x:h,y:i-g},{x:h,y:i}),bottomRight:k({x:h,y:b},{x:h,y:b+g},{x:a+f,y:i},{x:a,y:i}),bottomLeft:k({x:h,y:i},{x:h-f,y:i},{x:a,y:b+g},{x:a,y:b})}}function j(a,b,c){var d=a.left,e=a.top,f=a.width,g=a.height,h=b[0][0]<f/2?b[0][0]:f/2,j=b[0][1]<g/2?b[0][1]:g/2,k=b[1][0]<f/2?b[1][0]:f/2,l=b[1][1]<g/2?b[1][1]:g/2,m=b[2][0]<f/2?b[2][0]:f/2,n=b[2][1]<g/2?b[2][1]:g/2,o=b[3][0]<f/2?b[3][0]:f/2,p=b[3][1]<g/2?b[3][1]:g/2,q=f-k,r=g-n,s=f-m,t=g-p;
+return{topLeft:i(d+c[3].width/2,e+c[0].width/2,Math.max(0,h-c[3].width/2),Math.max(0,j-c[0].width/2)).topLeft.subdivide(.5),topRight:i(d+Math.min(q,f+c[3].width/2),e+c[0].width/2,q>f+c[3].width/2?0:k-c[3].width/2,l-c[0].width/2).topRight.subdivide(.5),bottomRight:i(d+Math.min(s,f-c[3].width/2),e+Math.min(r,g+c[0].width/2),Math.max(0,m-c[1].width/2),n-c[2].width/2).bottomRight.subdivide(.5),bottomLeft:i(d+c[3].width/2,e+t,Math.max(0,o-c[3].width/2),p-c[2].width/2).bottomLeft.subdivide(.5),topLeftOuter:i(d,e,h,j).topLeft.subdivide(.5),topLeftInner:i(d+c[3].width,e+c[0].width,Math.max(0,h-c[3].width),Math.max(0,j-c[0].width)).topLeft.subdivide(.5),topRightOuter:i(d+q,e,k,l).topRight.subdivide(.5),topRightInner:i(d+Math.min(q,f+c[3].width),e+c[0].width,q>f+c[3].width?0:k-c[3].width,l-c[0].width).topRight.subdivide(.5),bottomRightOuter:i(d+s,e+r,m,n).bottomRight.subdivide(.5),bottomRightInner:i(d+Math.min(s,f-c[3].width),e+Math.min(r,g+c[0].width),Math.max(0,m-c[1].width),n-c[2].width).bottomRight.subdivide(.5),bottomLeftOuter:i(d,e+t,o,p).bottomLeft.subdivide(.5),bottomLeftInner:i(d+c[3].width,e+t,Math.max(0,o-c[3].width),p-c[2].width).bottomLeft.subdivide(.5)}}function k(a,b,c,d){var e=function(a,b,c){return{x:a.x+(b.x-a.x)*c,y:a.y+(b.y-a.y)*c}};return{start:a,startControl:b,endControl:c,end:d,subdivide:function(f){var g=e(a,b,f),h=e(b,c,f),i=e(c,d,f),j=e(g,h,f),l=e(h,i,f),m=e(j,l,f);return[k(a,g,j,m),k(m,l,i,d)]},curveTo:function(a){a.push(["bezierCurve",b.x,b.y,c.x,c.y,d.x,d.y])},curveToReversed:function(d){d.push(["bezierCurve",c.x,c.y,b.x,b.y,a.x,a.y])}}}function l(a,b,c,d,e,f,g){var h=[];return b[0]>0||b[1]>0?(h.push(["line",d[1].start.x,d[1].start.y]),d[1].curveTo(h)):h.push(["line",a.c1[0],a.c1[1]]),c[0]>0||c[1]>0?(h.push(["line",f[0].start.x,f[0].start.y]),f[0].curveTo(h),h.push(["line",g[0].end.x,g[0].end.y]),g[0].curveToReversed(h)):(h.push(["line",a.c2[0],a.c2[1]]),h.push(["line",a.c3[0],a.c3[1]])),b[0]>0||b[1]>0?(h.push(["line",e[1].end.x,e[1].end.y]),e[1].curveToReversed(h)):h.push(["line",a.c4[0],a.c4[1]]),h}function m(a,b,c,d,e){var f=[];return b[0]>0||b[1]>0?(f.push(["line",d[1].start.x,d[1].start.y]),d[1].curveTo(f)):f.push(["line",a.c1[0],a.c1[1]]),c[0]>0||c[1]>0?(f.push(["line",e[0].start.x,e[0].start.y]),e[0].curveTo(f)):f.push(["line",a.c2[0],a.c2[1]]),f}function n(a,b,c,d,e,f,g){b[0]>0||b[1]>0?(a.push(["line",d[0].start.x,d[0].start.y]),d[0].curveTo(a),d[1].curveTo(a)):a.push(["line",f,g]),(c[0]>0||c[1]>0)&&a.push(["line",e[0].start.x,e[0].start.y])}function o(a){return a.cssInt("zIndex")<0}function p(a){return a.cssInt("zIndex")>0}function q(a){return 0===a.cssInt("zIndex")}function r(a){return["inline","inline-block","inline-table"].indexOf(a.css("display"))!==-1}function s(a){return a instanceof W}function t(a){return a.node.data.trim().length>0}function u(a){return/^(normal|none|0px)$/.test(a.parent.css("letterSpacing"))}function v(a){return["TopLeft","TopRight","BottomRight","BottomLeft"].map(function(b){var c=a.css("border"+b+"Radius"),d=c.split(" ");return d.length<=1&&(d[1]=d[0]),d.map(H)})}function w(a){return a.nodeType===Node.TEXT_NODE||a.nodeType===Node.ELEMENT_NODE}function x(a){var b=a.css("position"),c=["absolute","relative","fixed"].indexOf(b)!==-1?a.css("zIndex"):"auto";return"auto"!==c}function y(a){return"static"!==a.css("position")}function z(a){return"none"!==a.css("float")}function A(a){return["inline-block","inline-table"].indexOf(a.css("display"))!==-1}function B(a){var b=this;return function(){return!a.apply(b,arguments)}}function C(a){return a.node.nodeType===Node.ELEMENT_NODE}function D(a){return a.isPseudoElement===!0}function E(a){return a.node.nodeType===Node.TEXT_NODE}function F(a){return function(b,c){return b.cssInt("zIndex")+a.indexOf(b)/a.length-(c.cssInt("zIndex")+a.indexOf(c)/a.length)}}function G(a){return a.getOpacity()<1}function H(a){return parseInt(a,10)}function I(a){return a.width}function J(a){return a.node.nodeType!==Node.ELEMENT_NODE||["SCRIPT","HEAD","TITLE","OBJECT","BR","OPTION"].indexOf(a.node.nodeName)===-1}function K(a){return[].concat.apply([],a)}function L(a){var b=a.substr(0,1);return b===a.substr(a.length-1)&&b.match(/'|"/)?a.substr(1,a.length-2):a}function M(a){for(var b,c=[],d=0,e=!1;a.length;)N(a[d])===e?(b=a.splice(0,d),b.length&&c.push(Q.ucs2.encode(b)),e=!e,d=0):d++,d>=a.length&&(b=a.splice(0,d),b.length&&c.push(Q.ucs2.encode(b)));return c}function N(a){return[32,13,10,9,45].indexOf(a)!==-1}function O(a){return/[^\u0000-\u00ff]/.test(a)}var P=a("./log"),Q=a("punycode"),R=a("./nodecontainer"),S=a("./textcontainer"),T=a("./pseudoelementcontainer"),U=a("./fontmetrics"),V=a("./color"),W=a("./stackingcontext"),X=a("./utils"),Y=X.bind,Z=X.getBounds,$=X.parseBackgrounds,_=X.offsetBounds;d.prototype.calculateOverflowClips=function(){this.nodes.forEach(function(a){if(C(a)){D(a)&&a.appendToDOM(),a.borders=this.parseBorders(a);var b="hidden"===a.css("overflow")?[a.borders.clip]:[],c=a.parseClip();c&&["absolute","fixed"].indexOf(a.css("position"))!==-1&&b.push([["rect",a.bounds.left+c.left,a.bounds.top+c.top,c.right-c.left,c.bottom-c.top]]),a.clip=e(a)?a.parent.clip.concat(b):b,a.backgroundClip="hidden"!==a.css("overflow")?a.clip.concat([a.borders.clip]):a.clip,D(a)&&a.cleanDOM()}else E(a)&&(a.clip=e(a)?a.parent.clip:[]);D(a)||(a.bounds=null)},this)},d.prototype.asyncRenderer=function(a,b,c){c=c||Date.now(),this.paint(a[this.renderIndex++]),a.length===this.renderIndex?b():c+20>Date.now()?this.asyncRenderer(a,b,c):setTimeout(Y(function(){this.asyncRenderer(a,b)},this),0)},d.prototype.createPseudoHideStyles=function(a){this.createStyles(a,"."+T.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE+':before { content: "" !important; display: none !important; }.'+T.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER+':after { content: "" !important; display: none !important; }')},d.prototype.disableAnimations=function(a){this.createStyles(a,"* { -webkit-animation: none !important; -moz-animation: none !important; -o-animation: none !important; animation: none !important; -webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; transition: none !important;}")},d.prototype.createStyles=function(a,b){var c=a.createElement("style");c.innerHTML=b,a.body.appendChild(c)},d.prototype.getPseudoElements=function(a){var b=[[a]];if(a.node.nodeType===Node.ELEMENT_NODE){var c=this.getPseudoElement(a,":before"),d=this.getPseudoElement(a,":after");c&&b.push(c),d&&b.push(d)}return K(b)},d.prototype.getPseudoElement=function(a,b){var c=a.computedStyle(b);if(!c||!c.content||"none"===c.content||"-moz-alt-content"===c.content||"none"===c.display)return null;for(var d=L(c.content),e="url"===d.substr(0,3),g=document.createElement(e?"img":"html2canvaspseudoelement"),h=new T(g,a,b),i=c.length-1;i>=0;i--){var j=f(c.item(i));g.style[j]=c[j]}if(g.className=T.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE+" "+T.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER,e)return g.src=$(d)[0].args[0],[h];var k=document.createTextNode(d);return g.appendChild(k),[h,new S(k,h)]},d.prototype.getChildren=function(a){return K([].filter.call(a.node.childNodes,w).map(function(b){var c=[b.nodeType===Node.TEXT_NODE?new S(b,a):new R(b,a)].filter(J);return b.nodeType===Node.ELEMENT_NODE&&c.length&&"TEXTAREA"!==b.tagName?c[0].isElementVisible()?c.concat(this.getChildren(c[0])):[]:c},this))},d.prototype.newStackingContext=function(a,b){var c=new W(b,a.getOpacity(),a.node,a.parent);a.cloneTo(c);var d=b?c.getParentStack(this):c.parent.stack;d.contexts.push(c),a.stack=c},d.prototype.createStackingContexts=function(){this.nodes.forEach(function(a){C(a)&&(this.isRootElement(a)||G(a)||x(a)||this.isBodyWithTransparentRoot(a)||a.hasTransform())?this.newStackingContext(a,!0):C(a)&&(y(a)&&q(a)||A(a)||z(a))?this.newStackingContext(a,!1):a.assignStack(a.parent.stack)},this)},d.prototype.isBodyWithTransparentRoot=function(a){return"BODY"===a.node.nodeName&&a.parent.color("backgroundColor").isTransparent()},d.prototype.isRootElement=function(a){return null===a.parent},d.prototype.sortStackingContexts=function(a){a.contexts.sort(F(a.contexts.slice(0))),a.contexts.forEach(this.sortStackingContexts,this)},d.prototype.parseTextBounds=function(a){return function(b,c,d){if("none"!==a.parent.css("textDecoration").substr(0,4)||0!==b.trim().length){if(this.support.rangeBounds&&!a.parent.hasTransform()){var e=d.slice(0,c).join("").length;return this.getRangeBounds(a.node,e,b.length)}if(a.node&&"string"==typeof a.node.data){var f=a.node.splitText(b.length),g=this.getWrapperBounds(a.node,a.parent.hasTransform());return a.node=f,g}}else this.support.rangeBounds&&!a.parent.hasTransform()||(a.node=a.node.splitText(b.length));return{}}},d.prototype.getWrapperBounds=function(a,b){var c=a.ownerDocument.createElement("html2canvaswrapper"),d=a.parentNode,e=a.cloneNode(!0);c.appendChild(a.cloneNode(!0)),d.replaceChild(c,a);var f=b?_(c):Z(c);return d.replaceChild(e,c),f},d.prototype.getRangeBounds=function(a,b,c){var d=this.range||(this.range=a.ownerDocument.createRange());return d.setStart(a,b),d.setEnd(a,b+c),d.getBoundingClientRect()},d.prototype.parse=function(a){var b=a.contexts.filter(o),c=a.children.filter(C),d=c.filter(B(z)),e=d.filter(B(y)).filter(B(r)),f=c.filter(B(y)).filter(z),h=d.filter(B(y)).filter(r),i=a.contexts.concat(d.filter(y)).filter(q),j=a.children.filter(E).filter(t),k=a.contexts.filter(p);b.concat(e).concat(f).concat(h).concat(i).concat(j).concat(k).forEach(function(a){this.renderQueue.push(a),s(a)&&(this.parse(a),this.renderQueue.push(new g))},this)},d.prototype.paint=function(a){try{a instanceof g?this.renderer.ctx.restore():E(a)?(D(a.parent)&&a.parent.appendToDOM(),this.paintText(a),D(a.parent)&&a.parent.cleanDOM()):this.paintNode(a)}catch(b){if(P(b),this.options.strict)throw b}},d.prototype.paintNode=function(a){s(a)&&(this.renderer.setOpacity(a.opacity),this.renderer.ctx.save(),a.hasTransform()&&this.renderer.setTransform(a.parseTransform())),"INPUT"===a.node.nodeName&&"checkbox"===a.node.type?this.paintCheckbox(a):"INPUT"===a.node.nodeName&&"radio"===a.node.type?this.paintRadio(a):this.paintElement(a)},d.prototype.paintElement=function(a){var b=a.parseBounds();this.renderer.clip(a.backgroundClip,function(){this.renderer.renderBackground(a,b,a.borders.borders.map(I))},this,a),this.renderer.mask(a.backgroundClip,function(){this.renderer.renderShadows(a,a.borders.clip)},this,a),this.renderer.clip(a.clip,function(){this.renderer.renderBorders(a.borders.borders)},this,a),this.renderer.clip(a.backgroundClip,function(){switch(a.node.nodeName){case"svg":case"IFRAME":var c=this.images.get(a.node);c?this.renderer.renderImage(a,b,a.borders,c):P("Error loading <"+a.node.nodeName+">",a.node);break;case"IMG":var d=this.images.get(a.node.src);d?this.renderer.renderImage(a,b,a.borders,d):P("Error loading <img>",a.node.src);break;case"CANVAS":this.renderer.renderImage(a,b,a.borders,{image:a.node});break;case"SELECT":case"INPUT":case"TEXTAREA":this.paintFormValue(a)}},this,a)},d.prototype.paintCheckbox=function(a){var b=a.parseBounds(),c=Math.min(b.width,b.height),d={width:c-1,height:c-1,top:b.top,left:b.left},e=[3,3],f=[e,e,e,e],g=[1,1,1,1].map(function(a){return{color:new V("#A5A5A5"),width:a}}),i=j(d,f,g);this.renderer.clip(a.backgroundClip,function(){this.renderer.rectangle(d.left+1,d.top+1,d.width-2,d.height-2,new V("#DEDEDE")),this.renderer.renderBorders(h(g,d,i,f)),a.node.checked&&(this.renderer.font(new V("#424242"),"normal","normal","bold",c-3+"px","arial"),this.renderer.text("鉁�",d.left+c/6,d.top+c-1))},this,a)},d.prototype.paintRadio=function(a){var b=a.parseBounds(),c=Math.min(b.width,b.height)-2;this.renderer.clip(a.backgroundClip,function(){this.renderer.circleStroke(b.left+1,b.top+1,c,new V("#DEDEDE"),1,new V("#A5A5A5")),a.node.checked&&this.renderer.circle(Math.ceil(b.left+c/4)+1,Math.ceil(b.top+c/4)+1,Math.floor(c/2),new V("#424242"))},this,a)},d.prototype.paintFormValue=function(a){var b=a.getValue();if(b.length>0){var c=a.node.ownerDocument,d=c.createElement("html2canvaswrapper"),e=["lineHeight","textAlign","fontFamily","fontWeight","fontSize","color","paddingLeft","paddingTop","paddingRight","paddingBottom","width","height","borderLeftStyle","borderTopStyle","borderLeftWidth","borderTopWidth","boxSizing","whiteSpace","wordWrap"];e.forEach(function(b){try{d.style[b]=a.css(b)}catch(c){P("html2canvas: Parse: Exception caught in renderFormValue: "+c.message)}});var f=a.parseBounds();d.style.position="fixed",d.style.left=f.left+"px",d.style.top=f.top+"px",d.textContent=b,c.body.appendChild(d),this.paintText(new S(d.firstChild,a)),c.body.removeChild(d)}},d.prototype.paintText=function(a){a.applyTextTransform();var b=Q.ucs2.decode(a.node.data),c=(!this.options.letterRendering||u(a))&&!O(a.node.data),d=c?M(b):b.map(function(a){return Q.ucs2.encode([a])});c||(a.parent.node.style.fontVariantLigatures="none");var e=a.parent.fontWeight(),f=a.parent.css("fontSize"),g=a.parent.css("fontFamily"),h=a.parent.parseTextShadows();this.renderer.font(a.parent.color("color"),a.parent.css("fontStyle"),a.parent.css("fontVariant"),e,f,g),h.length?this.renderer.fontShadow(h[0].color,h[0].offsetX,h[0].offsetY,h[0].blur):this.renderer.clearShadow(),this.renderer.clip(a.parent.clip,function(){d.map(this.parseTextBounds(a),this).forEach(function(b,c){b&&(this.renderer.text(d[c],b.left,b.bottom),this.renderTextDecoration(a.parent,b,this.fontMetrics.getMetrics(g,f)))},this)},this,a.parent)},d.prototype.renderTextDecoration=function(a,b,c){switch(a.css("textDecoration").split(" ")[0]){case"underline":this.renderer.rectangle(b.left,Math.round(b.top+c.baseline+c.lineWidth),b.width,1,a.color("color"));break;case"overline":this.renderer.rectangle(b.left,Math.round(b.top),b.width,1,a.color("color"));break;case"line-through":this.renderer.rectangle(b.left,Math.ceil(b.top+c.middle+c.lineWidth),b.width,1,a.color("color"))}};var aa={inset:[["darken",.6],["darken",.1],["darken",.1],["darken",.6]]};d.prototype.parseBorders=function(a){var b=a.parseBounds(),c=v(a),d=["Top","Right","Bottom","Left"].map(function(b,c){var d=a.css("border"+b+"Style"),e=a.color("border"+b+"Color");"inset"===d&&e.isBlack()&&(e=new V([255,255,255,e.a]));var f=aa[d]?aa[d][c]:null;return{width:a.cssInt("border"+b+"Width"),color:f?e[f[0]](f[1]):e,style:d,pathArgs:null,args:null}}),e=j(b,c,d);return{clip:this.parseBackgroundClip(a,e,d,c,b),borders:h(d,b,e,c)}},d.prototype.parseBackgroundClip=function(a,b,c,d,e){var f=a.css("backgroundClip"),g=[];switch(f){case"content-box":case"padding-box":n(g,d[0],d[1],b.topLeftInner,b.topRightInner,e.left+c[3].width,e.top+c[0].width),n(g,d[1],d[2],b.topRightInner,b.bottomRightInner,e.left+e.width-c[1].width,e.top+c[0].width),n(g,d[2],d[3],b.bottomRightInner,b.bottomLeftInner,e.left+e.width-c[1].width,e.top+e.height-c[2].width),n(g,d[3],d[0],b.bottomLeftInner,b.topLeftInner,e.left+c[3].width,e.top+e.height-c[2].width);break;default:n(g,d[0],d[1],b.topLeftOuter,b.topRightOuter,e.left,e.top),n(g,d[1],d[2],b.topRightOuter,b.bottomRightOuter,e.left+e.width,e.top),n(g,d[2],d[3],b.bottomRightOuter,b.bottomLeftOuter,e.left+e.width,e.top+e.height),n(g,d[3],d[0],b.bottomLeftOuter,b.topLeftOuter,e.left,e.top+e.height)}return g},b.exports=d},{"./color":3,"./fontmetrics":7,"./log":13,"./nodecontainer":14,"./pseudoelementcontainer":18,"./stackingcontext":21,"./textcontainer":25,"./utils":26,punycode:1}],16:[function(a,b,c){function d(a,b,c){var d="withCredentials"in new XMLHttpRequest;if(!b)return Promise.reject("No proxy configured");var e=g(d),i=h(b,a,e);return d?k(i):f(c,i,e).then(function(a){return o(a.content)})}function e(a,b,c){var d="crossOrigin"in new Image,e=g(d),i=h(b,a,e);return d?Promise.resolve(i):f(c,i,e).then(function(a){return"data:"+a.type+";base64,"+a.content})}function f(a,b,c){return new Promise(function(d,e){var f=a.createElement("script"),g=function(){delete window.html2canvas.proxy[c],a.body.removeChild(f)};window.html2canvas.proxy[c]=function(a){g(),d(a)},f.src=b,f.onerror=function(a){g(),e(a)},a.body.appendChild(f)})}function g(a){return a?"":"html2canvas_"+Date.now()+"_"+ ++p+"_"+Math.round(1e5*Math.random())}function h(a,b,c){return a+"?url="+encodeURIComponent(b)+(c.length?"&callback=html2canvas.proxy."+c:"")}function i(a){return function(b){var c,d=new DOMParser;try{c=d.parseFromString(b,"text/html")}catch(e){m("DOMParser not supported, falling back to createHTMLDocument"),c=document.implementation.createHTMLDocument("");try{c.open(),c.write(b),c.close()}catch(f){m("createHTMLDocument write not supported, falling back to document.body.innerHTML"),c.body.innerHTML=b}}var g=c.querySelector("base");if(!g||!g.href.host){var h=c.createElement("base");h.href=a,c.head.insertBefore(h,c.head.firstChild)}return c}}function j(a,b,c,e,f,g){return new d(a,b,window.document).then(i(a)).then(function(a){return n(a,c,e,f,g,0,0)})}var k=a("./xhr"),l=a("./utils"),m=a("./log"),n=a("./clone"),o=l.decode64,p=0;c.Proxy=d,c.ProxyURL=e,c.loadUrlDocument=j},{"./clone":2,"./log":13,"./utils":26,"./xhr":28}],17:[function(a,b,c){function d(a,b){var c=document.createElement("a");c.href=a,a=c.href,this.src=a,this.image=new Image;var d=this;this.promise=new Promise(function(c,f){d.image.crossOrigin="Anonymous",d.image.onload=c,d.image.onerror=f,new e(a,b,document).then(function(a){d.image.src=a})["catch"](f)})}var e=a("./proxy").ProxyURL;b.exports=d},{"./proxy":16}],18:[function(a,b,c){function d(a,b,c){e.call(this,a,b),this.isPseudoElement=!0,this.before=":before"===c}var e=a("./nodecontainer");d.prototype.cloneTo=function(a){d.prototype.cloneTo.call(this,a),a.isPseudoElement=!0,a.before=this.before},d.prototype=Object.create(e.prototype),d.prototype.appendToDOM=function(){this.before?this.parent.node.insertBefore(this.node,this.parent.node.firstChild):this.parent.node.appendChild(this.node),this.parent.node.className+=" "+this.getHideClass()},d.prototype.cleanDOM=function(){this.node.parentNode.removeChild(this.node),this.parent.node.className=this.parent.node.className.replace(this.getHideClass(),"")},d.prototype.getHideClass=function(){return this["PSEUDO_HIDE_ELEMENT_CLASS_"+(this.before?"BEFORE":"AFTER")]},d.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE="___html2canvas___pseudoelement_before",d.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER="___html2canvas___pseudoelement_after",b.exports=d},{"./nodecontainer":14}],19:[function(a,b,c){function d(a,b,c,d,e){this.width=a,this.height=b,this.images=c,this.options=d,this.document=e}var e=a("./log");d.prototype.renderImage=function(a,b,c,d){var e=a.cssInt("paddingLeft"),f=a.cssInt("paddingTop"),g=a.cssInt("paddingRight"),h=a.cssInt("paddingBottom"),i=c.borders,j=b.width-(i[1].width+i[3].width+e+g),k=b.height-(i[0].width+i[2].width+f+h);this.drawImage(d,0,0,d.image.width||j,d.image.height||k,b.left+e+i[3].width,b.top+f+i[0].width,j,k)},d.prototype.renderBackground=function(a,b,c){b.height>0&&b.width>0&&(this.renderBackgroundColor(a,b),this.renderBackgroundImage(a,b,c))},d.prototype.renderBackgroundColor=function(a,b){var c=a.color("backgroundColor");c.isTransparent()||this.rectangle(b.left,b.top,b.width,b.height,c)},d.prototype.renderShadows=function(a,b){var c=a.css("boxShadow");if("none"!==c){var d=c.split(/,(?![^(]*\))/);this.shadow(b,d)}},d.prototype.renderBorders=function(a){a.forEach(this.renderBorder,this)},d.prototype.renderBorder=function(a){if(!a.color.isTransparent()&&null!==a.args)if("dashed"===a.style||"dotted"===a.style){var b="dashed"===a.style?3:a.width;this.ctx.setLineDash([b]),this.path(a.pathArgs),this.ctx.strokeStyle=a.color,this.ctx.lineWidth=a.width,this.ctx.stroke()}else this.drawShape(a.args,a.color)},d.prototype.renderBackgroundImage=function(a,b,c){var d=a.parseBackgroundImages();d.reverse().forEach(function(d,f,g){switch(d.method){case"url":var h=this.images.get(d.args[0]);h?this.renderBackgroundRepeating(a,b,h,g.length-(f+1),c):e("Error loading background-image",d.args[0]);break;case"linear-gradient":case"gradient":var i=this.images.get(d.value);i?this.renderBackgroundGradient(i,b,c):e("Error loading background-image",d.args[0]);break;case"none":break;default:e("Unknown background-image type",d.args[0])}},this)},d.prototype.renderBackgroundRepeating=function(a,b,c,d,e){var f=a.parseBackgroundSize(b,c.image,d),g=a.parseBackgroundPosition(b,c.image,d,f),h=a.parseBackgroundRepeat(d);switch(h){case"repeat-x":case"repeat no-repeat":this.backgroundRepeatShape(c,g,f,b,b.left+e[3],b.top+g.top+e[0],99999,f.height,e);break;case"repeat-y":case"no-repeat repeat":this.backgroundRepeatShape(c,g,f,b,b.left+g.left+e[3],b.top+e[0],f.width,99999,e);break;case"no-repeat":this.backgroundRepeatShape(c,g,f,b,b.left+g.left+e[3],b.top+g.top+e[0],f.width,f.height,e);break;default:this.renderBackgroundRepeat(c,g,f,{top:b.top,left:b.left},e[3],e[0])}},b.exports=d},{"./log":13}],20:[function(a,b,c){function d(a,b){f.apply(this,arguments),this.canvas=this.options.canvas||this.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.options.canvas||(this.options.dpi&&(this.options.scale=this.options.dpi/96),this.options.scale?(this.canvas.style.width=a+"px",this.canvas.style.height=b+"px",this.canvas.width=Math.floor(a*this.options.scale),this.canvas.height=Math.floor(b*this.options.scale),this.ctx.scale(this.options.scale,this.options.scale)):(this.canvas.width=a,this.canvas.height=b)),this.taintCtx=this.document.createElement("canvas").getContext("2d"),this.ctx.textBaseline="bottom",this.variables={},h("Initialized CanvasRenderer with size",a,"x",b)}function e(a){return a.length>0}var f=a("../renderer"),g=a("../lineargradientcontainer"),h=a("../log");d.prototype=Object.create(f.prototype),d.prototype.setFillStyle=function(a){return this.ctx.fillStyle="object"==typeof a&&a.isColor?a.toString():a,this.ctx},d.prototype.rectangle=function(a,b,c,d,e){this.setFillStyle(e).fillRect(a,b,c,d)},d.prototype.circle=function(a,b,c,d){this.setFillStyle(d),this.ctx.beginPath(),this.ctx.arc(a+c/2,b+c/2,c/2,0,2*Math.PI,!0),this.ctx.closePath(),this.ctx.fill()},d.prototype.circleStroke=function(a,b,c,d,e,f){this.circle(a,b,c,d),this.ctx.strokeStyle=f.toString(),this.ctx.stroke()},d.prototype.shadow=function(a,b){var c=function(a){var b={color:/^(#|rgb|hsl|(?!(inset|initial|inherit))\D+)/i,inset:/^inset/i,px:/px$/i},c=["x","y","blur","spread"],d=a.split(/ (?![^(]*\))/),e={};for(var f in b)e[f]=d.filter(b[f].test.bind(b[f])),e[f]=0===e[f].length?null:1===e[f].length?e[f][0]:e[f];for(var g=0;g<e.px.length;g++)e[c[g]]=parseInt(e.px[g]);return e},d=function(a){var b=c(a);b.inset||(e.shadowOffsetX=b.x,e.shadowOffsetY=b.y,e.shadowColor=b.color,e.shadowBlur=b.blur,e.fill())},e=this.setFillStyle("white");e.save(),this.shape(a),b.forEach(d,this),e.restore()},d.prototype.drawShape=function(a,b){this.shape(a),this.setFillStyle(b).fill()},d.prototype.taints=function(a){if(null===a.tainted){this.taintCtx.drawImage(a.image,0,0);try{this.taintCtx.getImageData(0,0,1,1),a.tainted=!1}catch(b){this.taintCtx=document.createElement("canvas").getContext("2d"),a.tainted=!0}}return a.tainted},d.prototype.drawImage=function(a,b,c,d,e,f,g,h,i){this.taints(a)&&!this.options.allowTaint||this.ctx.drawImage(a.image,b,c,d,e,f,g,h,i)},d.prototype.clip=function(a,b,c,d){this.ctx.save(),d&&d.hasTransform()?(this.setTransform(d.inverseTransform()),a.filter(e).forEach(function(a){this.shape(a).clip()},this),this.setTransform(d.parseTransform())):a.filter(e).forEach(function(a){this.shape(a).clip()},this),b.call(c),this.ctx.restore()},d.prototype.mask=function(a,b,c,d){var e=a[a.length-1];if(e&&e.length){var f=["rect",this.canvas.width,0,-this.canvas.width,this.canvas.height],g=[f].concat(e).concat([e[0]]);a=a.slice(0,-1).concat([g])}this.clip(a,b,c,d)},d.prototype.shape=function(a){return this.ctx.beginPath(),a.forEach(function(a,b){"rect"===a[0]?this.ctx.rect.apply(this.ctx,a.slice(1)):this.ctx[0===b?"moveTo":a[0]+"To"].apply(this.ctx,a.slice(1))},this),this.ctx.closePath(),this.ctx},d.prototype.path=function(a){return this.ctx.beginPath(),a.forEach(function(a,b){"rect"===a[0]?this.ctx.rect.apply(this.ctx,a.slice(1)):this.ctx[0===b?"moveTo":a[0]+"To"].apply(this.ctx,a.slice(1))},this),this.ctx},d.prototype.font=function(a,b,c,d,e,f){c=/^(normal|small-caps)$/i.test(c)?c:"",this.setFillStyle(a).font=[b,c,d,e,f].join(" ").split(",")[0]},d.prototype.fontShadow=function(a,b,c,d){this.setVariable("shadowColor",a.toString()).setVariable("shadowOffsetY",b).setVariable("shadowOffsetX",c).setVariable("shadowBlur",d)},d.prototype.clearShadow=function(){this.setVariable("shadowColor","rgba(0,0,0,0)")},d.prototype.setOpacity=function(a){this.ctx.globalAlpha=a},d.prototype.setTransform=function(a){this.ctx.translate(a.origin[0],a.origin[1]),this.ctx.transform.apply(this.ctx,a.matrix),this.ctx.translate(-a.origin[0],-a.origin[1])},d.prototype.setVariable=function(a,b){return this.variables[a]!==b&&(this.variables[a]=this.ctx[a]=b),this},d.prototype.text=function(a,b,c){this.ctx.fillText(a,b,c)},d.prototype.backgroundRepeatShape=function(a,b,c,d,e,f,g,h,i){var j=[["line",Math.round(e),Math.round(f)],["line",Math.round(e+g),Math.round(f)],["line",Math.round(e+g),Math.round(h+f)],["line",Math.round(e),Math.round(h+f)]];this.clip([j],function(){this.renderBackgroundRepeat(a,b,c,d,i[3],i[0])},this)},d.prototype.renderBackgroundRepeat=function(a,b,c,d,e,f){var g=Math.round(d.left+b.left+e),h=Math.round(d.top+b.top+f);this.setFillStyle(this.ctx.createPattern(this.resizeImage(a,c),"repeat")),this.ctx.translate(g,h),this.ctx.fill(),this.ctx.translate(-g,-h)},d.prototype.renderBackgroundGradient=function(a,b){if(a instanceof g){var c=this.ctx.createLinearGradient(b.left+b.width*a.x0,b.top+b.height*a.y0,b.left+b.width*a.x1,b.top+b.height*a.y1);a.colorStops.forEach(function(a){c.addColorStop(a.stop,a.color.toString())}),this.rectangle(b.left,b.top,b.width,b.height,c)}},d.prototype.resizeImage=function(a,b){var c=a.image;if(c.width===b.width&&c.height===b.height)return c;var d,e=document.createElement("canvas");return e.width=b.width,e.height=b.height,d=e.getContext("2d"),d.drawImage(c,0,0,c.width,c.height,0,0,b.width,b.height),e},b.exports=d},{"../lineargradientcontainer":12,"../log":13,"../renderer":19}],21:[function(a,b,c){function d(a,b,c,d){e.call(this,c,d),this.ownStacking=a,this.contexts=[],this.children=[],this.opacity=(this.parent?this.parent.stack.opacity:1)*b}var e=a("./nodecontainer");d.prototype=Object.create(e.prototype),d.prototype.getParentStack=function(a){var b=this.parent?this.parent.stack:null;return b?b.ownStacking?b:b.getParentStack(a):a.stack},b.exports=d},{"./nodecontainer":14}],22:[function(a,b,c){function d(a){this.rangeBounds=this.testRangeBounds(a),this.cors=this.testCORS(),this.svg=this.testSVG()}d.prototype.testRangeBounds=function(a){var b,c,d,e,f=!1;return a.createRange&&(b=a.createRange(),b.getBoundingClientRect&&(c=a.createElement("boundtest"),c.style.height="123px",c.style.display="block",a.body.appendChild(c),b.selectNode(c),d=b.getBoundingClientRect(),e=d.height,123===e&&(f=!0),a.body.removeChild(c))),f},d.prototype.testCORS=function(){return"undefined"!=typeof(new Image).crossOrigin},d.prototype.testSVG=function(){var a=new Image,b=document.createElement("canvas"),c=b.getContext("2d");a.src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>";try{c.drawImage(a,0,0),b.toDataURL()}catch(d){return!1}return!0},b.exports=d},{}],23:[function(a,b,c){function d(a){this.src=a,this.image=null;var b=this;this.promise=this.hasFabric().then(function(){return b.isInline(a)?Promise.resolve(b.inlineFormatting(a)):e(a)}).then(function(a){return new Promise(function(c){window.html2canvas.svg.fabric.loadSVGFromString(a,b.createCanvas.call(b,c))})})}var e=a("./xhr"),f=a("./utils").decode64;d.prototype.hasFabric=function(){return window.html2canvas.svg&&window.html2canvas.svg.fabric?Promise.resolve():Promise.reject(new Error("html2canvas.svg.js is not loaded, cannot render svg"))},d.prototype.inlineFormatting=function(a){return/^data:image\/svg\+xml;base64,/.test(a)?this.decode64(this.removeContentType(a)):this.removeContentType(a)},d.prototype.removeContentType=function(a){return a.replace(/^data:image\/svg\+xml(;base64)?,/,"")},d.prototype.isInline=function(a){return/^data:image\/svg\+xml/i.test(a)},d.prototype.createCanvas=function(a){var b=this;return function(c,d){var e=new window.html2canvas.svg.fabric.StaticCanvas("c");b.image=e.lowerCanvasEl,e.setWidth(d.width).setHeight(d.height).add(window.html2canvas.svg.fabric.util.groupSVGElements(c,d)).renderAll(),a(e.lowerCanvasEl)}},d.prototype.decode64=function(a){return"function"==typeof window.atob?window.atob(a):f(a)},b.exports=d},{"./utils":26,"./xhr":28}],24:[function(a,b,c){function d(a,b){this.src=a,this.image=null;var c=this;this.promise=b?new Promise(function(b,d){c.image=new Image,c.image.onload=b,c.image.onerror=d,c.image.src="data:image/svg+xml,"+(new XMLSerializer).serializeToString(a),c.image.complete===!0&&b(c.image)}):this.hasFabric().then(function(){return new Promise(function(b){window.html2canvas.svg.fabric.parseSVGDocument(a,c.createCanvas.call(c,b))})})}var e=a("./svgcontainer");d.prototype=Object.create(e.prototype),b.exports=d},{"./svgcontainer":23}],25:[function(a,b,c){function d(a,b){f.call(this,a,b)}function e(a,b,c){if(a.length>0)return b+c.toUpperCase()}var f=a("./nodecontainer");d.prototype=Object.create(f.prototype),d.prototype.applyTextTransform=function(){this.node.data=this.transform(this.parent.css("textTransform"))},d.prototype.transform=function(a){var b=this.node.data;switch(a){case"lowercase":return b.toLowerCase();case"capitalize":return b.replace(/(^|\s|:|-|\(|\))([a-z])/g,e);case"uppercase":return b.toUpperCase();default:return b}},b.exports=d},{"./nodecontainer":14}],26:[function(a,b,c){c.smallImage=function(){return"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"},c.bind=function(a,b){return function(){return a.apply(b,arguments)}},c.decode64=function(a){var b,c,d,e,f,g,h,i,j="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",k=a.length,l="";for(b=0;b<k;b+=4)c=j.indexOf(a[b]),d=j.indexOf(a[b+1]),e=j.indexOf(a[b+2]),f=j.indexOf(a[b+3]),g=c<<2|d>>4,h=(15&d)<<4|e>>2,i=(3&e)<<6|f,l+=64===e?String.fromCharCode(g):64===f||f===-1?String.fromCharCode(g,h):String.fromCharCode(g,h,i);return l},c.getBounds=function(a){if(a.getBoundingClientRect){var b=a.getBoundingClientRect(),c=null==a.offsetWidth?b.width:a.offsetWidth;return{top:b.top,bottom:b.bottom||b.top+b.height,right:b.left+c,left:b.left,width:c,height:null==a.offsetHeight?b.height:a.offsetHeight}}return{}},c.offsetBounds=function(a){var b=a.offsetParent?c.offsetBounds(a.offsetParent):{top:0,left:0};return{top:a.offsetTop+b.top,bottom:a.offsetTop+a.offsetHeight+b.top,right:a.offsetLeft+b.left+a.offsetWidth,left:a.offsetLeft+b.left,width:a.offsetWidth,height:a.offsetHeight}},c.parseBackgrounds=function(a){var b,c,d,e,f,g,h,i=" \r\n\t",j=[],k=0,l=0,m=function(){b&&('"'===c.substr(0,1)&&(c=c.substr(1,c.length-2)),c&&h.push(c),"-"===b.substr(0,1)&&(e=b.indexOf("-",1)+1)>0&&(d=b.substr(0,e),b=b.substr(e)),j.push({prefix:d,method:b.toLowerCase(),value:f,args:h,image:null})),h=[],b=d=c=f=""};return h=[],b=d=c=f="",a.split("").forEach(function(a){if(!(0===k&&i.indexOf(a)>-1)){switch(a){case'"':g?g===a&&(g=null):g=a;break;case"(":if(g)break;if(0===k)return k=1,void(f+=a);l++;break;case")":if(g)break;if(1===k){if(0===l)return k=0,f+=a,void m();l--}break;case",":if(g)break;if(0===k)return void m();if(1===k&&0===l&&!b.match(/^url$/i))return h.push(c),c="",void(f+=a)}f+=a,0===k?b+=a:c+=a}}),m(),j}},{}],27:[function(a,b,c){function d(a){e.apply(this,arguments),this.type="linear"===a.args[0]?e.TYPES.LINEAR:e.TYPES.RADIAL}var e=a("./gradientcontainer");d.prototype=Object.create(e.prototype),b.exports=d},{"./gradientcontainer":9}],28:[function(a,b,c){function d(a){return new Promise(function(b,c){var d=new XMLHttpRequest;d.open("GET",a),d.onload=function(){200===d.status?b(d.responseText):c(new Error(d.statusText))},d.onerror=function(){
+c(new Error("Network Error"))},d.send()})}b.exports=d},{}]},{},[4])(4)});
\ No newline at end of file
diff --git a/force-app/main/default/staticresources/html2canvas.resource-meta.xml b/force-app/main/default/staticresources/html2canvas.resource-meta.xml
new file mode 100644
index 0000000..02bbf8a
--- /dev/null
+++ b/force-app/main/default/staticresources/html2canvas.resource-meta.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
+    <cacheControl>Public</cacheControl>
+    <contentType>text/javascript</contentType>
+    <description>html2canvas</description>
+</StaticResource>
diff --git a/force-app/main/default/staticresources/jspdf.js b/force-app/main/default/staticresources/jspdf.js
new file mode 100644
index 0000000..c72711a
--- /dev/null
+++ b/force-app/main/default/staticresources/jspdf.js
@@ -0,0 +1,171 @@
+/** 
+ * jsPDF - PDF Document creation from JavaScript
+ * Version 1.0.272-git Built on 2014-09-29T15:09
+ *                           CommitID d4770725ca
+ *
+ * Copyright (c) 2010-2014 James Hall, https://github.com/MrRio/jsPDF
+ *               2010 Aaron Spike, https://github.com/acspike
+ *               2012 Willow Systems Corporation, willow-systems.com
+ *               2012 Pablo Hess, https://github.com/pablohess
+ *               2012 Florian Jenett, https://github.com/fjenett
+ *               2013 Warren Weckesser, https://github.com/warrenweckesser
+ *               2013 Youssef Beddad, https://github.com/lifof
+ *               2013 Lee Driscoll, https://github.com/lsdriscoll
+ *               2013 Stefan Slonevskiy, https://github.com/stefslon
+ *               2013 Jeremy Morel, https://github.com/jmorel
+ *               2013 Christoph Hartmann, https://github.com/chris-rock
+ *               2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
+ *               2014 James Makes, https://github.com/dollaruw
+ *               2014 Diego Casorran, https://github.com/diegocr
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Contributor(s):
+ *    siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango,
+ *    kim3er, mfo, alnorth,
+ */
+/**
+ * jsPDF addHTML PlugIn
+ * Copyright (c) 2014 Diego Casorran
+ * Licensed under the MIT License.
+ * http://opensource.org/licenses/mit-license
+ */
+/** 
+ * jsPDF addImage plugin
+ * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/
+ *               2013 Chris Dowling, https://github.com/gingerchris
+ *               2013 Trinh Ho, https://github.com/ineedfat
+ *               2013 Edwin Alejandro Perez, https://github.com/eaparango
+ *               2013 Norah Smith, https://github.com/burnburnrocket
+ *               2014 Diego Casorran, https://github.com/diegocr
+ *               2014 James Robb, https://github.com/jamesbrobb
+ */
+/**
+ * jsPDF Cell plugin
+ * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
+ *               2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
+ *               2013 Lee Driscoll, https://github.com/lsdriscoll
+ *               2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
+ *               2014 James Hall, james@parall.ax
+ *               2014 Diego Casorran, https://github.com/diegocr
+ */
+/** 
+ * jsPDF fromHTML plugin. BETA stage. API subject to change. Needs browser
+ * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
+ *               2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
+ *               2014 Diego Casorran, https://github.com/diegocr
+ *               2014 Daniel Husar, https://github.com/danielhusar
+ *               2014 Wolfgang Gassler, https://github.com/woolfg
+ */
+/** 
+ * jsPDF JavaScript plugin
+ * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
+ */
+/** 
+ * jsPDF PNG PlugIn
+ * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb
+ */
+/** 
+jsPDF Silly SVG plugin
+Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
+*/
+/** 
+ * jsPDF split_text_to_size plugin - MIT license.
+ * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
+ *               2014 Diego Casorran, https://github.com/diegocr
+ */
+/**  
+jsPDF standard_fonts_metrics plugin
+Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
+MIT license.
+*/
+/** 
+ * jsPDF total_pages plugin
+ * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
+ */
+/* Blob.js
+ * A Blob implementation.
+ * 2014-07-24
+ * By Eli Grey, http://eligrey.com
+ * By Devin Samarin, https://github.com/dsamarin
+ * License: X11/MIT
+ *   See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
+ */
+/* FileSaver.js
+ * A saveAs() FileSaver implementation.
+ * 2014-08-29
+ * By Eli Grey, http://eligrey.com
+ * License: X11/MIT
+ *   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
+ */
+/*
+ * Copyright (c) 2012 chick307 <chick307@gmail.com>
+ * Licensed under the MIT License.
+ * http://opensource.org/licenses/mit-license
+ */
+/*
+ Deflate.js - https://github.com/gildas-lormeau/zip.js
+ Copyright (c) 2013 Gildas Lormeau. All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright 
+ notice, this list of conditions and the following disclaimer in 
+ the documentation and/or other materials provided with the distribution.
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+# PNG.js
+# Copyright (c) 2011 Devon Govett
+# MIT LICENSE
+# 
+*/
+/*
+ * Extracted from pdf.js
+ * https://github.com/andreasgal/pdf.js
+ * Copyright (c) 2011 Mozilla Foundation
+ * Contributors: Andreas Gal <gal@mozilla.com>
+ *               Chris G Jones <cjones@mozilla.com>
+ *               Shaon Barman <shaon.barman@gmail.com>
+ *               Vivien Nicolas <21@vingtetun.org>
+ *               Justin D'Arcangelo <justindarc@gmail.com>
+ *               Yury Delendik
+ */
+/**
+ * JavaScript Polyfill functions for jsPDF
+ * Collected from public resources by
+ * https://github.com/diegocr
+ */
+!function(t,e){e["true"]=t;var n=function(t){"use strict";function e(e){var n={};this.subscribe=function(t,e,r){if("function"!=typeof e)return!1;n.hasOwnProperty(t)||(n[t]={});var s=Math.random().toString(35);return n[t][s]=[e,!!r],s},this.unsubscribe=function(t){for(var e in n)if(n[e][t])return delete n[e][t],!0;return!1},this.publish=function(r){if(n.hasOwnProperty(r)){var s=Array.prototype.slice.call(arguments,1),i=[];for(var o in n[r]){var a=n[r][o];try{a[0].apply(e,s)}catch(u){t.console&&console.error("jsPDF PubSub Error",u.message,u)}a[1]&&i.push(o)}i.length&&i.forEach(this.unsubscribe)}}}function n(a,u,c,l){var f={};"object"==typeof a&&(f=a,a=f.orientation,u=f.unit||u,c=f.format||c,l=f.compress||f.compressPdf||l),u=u||"mm",c=c||"a4",a=(""+(a||"P")).toLowerCase();var d,h,p,m,w,g,y,v,b,q=((""+c).toLowerCase(),!!l&&"function"==typeof Uint8Array),x=f.textColor||"0 g",k=f.drawColor||"0 G",_=f.fontSize||16,A=f.lineHeight||1.15,C=f.lineWidth||.200025,S=2,E=!1,z=[],T={},I={},B=0,O=[],P={},R=[],F=0,D=0,U=0,N={title:"",subject:"",author:"",keywords:"",creator:""},L={},j=new e(L),M=function(t){return t.toFixed(2)},H=function(t){return t.toFixed(3)},G=function(t){return("0"+parseInt(t)).slice(-2)},W=function(t){E?O[m].push(t):(U+=t.length+1,R.push(t))},V=function(){return S++,z[S]=U,W(S+" 0 obj"),S},J=function(t){W("stream"),W(t),W("endstream")},X=function(){var e,r,i,o,a,u,c,l,f;for(c=t.adler32cs||n.adler32cs,q&&"undefined"==typeof c&&(q=!1),e=1;B>=e;e++){if(V(),l=(w=P[e].width)*h,f=(g=P[e].height)*h,W("<</Type /Page"),W("/Parent 1 0 R"),W("/Resources 2 0 R"),W("/MediaBox [0 0 "+M(l)+" "+M(f)+"]"),W("/Contents "+(S+1)+" 0 R>>"),W("endobj"),r=O[e].join("\n"),V(),q){for(i=[],o=r.length;o--;)i[o]=r.charCodeAt(o);u=c.from(r),a=new s(6),a.append(new Uint8Array(i)),r=a.flush(),i=new Uint8Array(r.length+6),i.set(new Uint8Array([120,156])),i.set(r,2),i.set(new Uint8Array([255&u,u>>8&255,u>>16&255,u>>24&255]),r.length+2),r=String.fromCharCode.apply(null,i),W("<</Length "+r.length+" /Filter [/FlateDecode]>>")}else W("<</Length "+r.length+">>");J(r),W("endobj")}z[1]=U,W("1 0 obj"),W("<</Type /Pages");var d="/Kids [";for(o=0;B>o;o++)d+=3+2*o+" 0 R ";W(d+"]"),W("/Count "+B),W(">>"),W("endobj")},Y=function(t){t.objectNumber=V(),W("<</BaseFont/"+t.PostScriptName+"/Type/Font"),"string"==typeof t.encoding&&W("/Encoding/"+t.encoding),W("/Subtype/Type1>>"),W("endobj")},K=function(){for(var t in T)T.hasOwnProperty(t)&&Y(T[t])},Q=function(){j.publish("putXobjectDict")},$=function(){W("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]"),W("/Font <<");for(var t in T)T.hasOwnProperty(t)&&W("/"+t+" "+T[t].objectNumber+" 0 R");W(">>"),W("/XObject <<"),Q(),W(">>")},Z=function(){K(),j.publish("putResources"),z[2]=U,W("2 0 obj"),W("<<"),$(),W(">>"),W("endobj"),j.publish("postPutResources")},te=function(t,e,n){I.hasOwnProperty(e)||(I[e]={}),I[e][n]=t},ee=function(t,e,n,r){var s="F"+(Object.keys(T).length+1).toString(10),i=T[s]={id:s,PostScriptName:t,fontName:e,fontStyle:n,encoding:r,metadata:{}};return te(s,e,n),j.publish("addFont",i),s},ne=function(){for(var t="helvetica",e="times",n="courier",r="normal",s="bold",i="italic",o="bolditalic",a="StandardEncoding",u=[["Helvetica",t,r],["Helvetica-Bold",t,s],["Helvetica-Oblique",t,i],["Helvetica-BoldOblique",t,o],["Courier",n,r],["Courier-Bold",n,s],["Courier-Oblique",n,i],["Courier-BoldOblique",n,o],["Times-Roman",e,r],["Times-Bold",e,s],["Times-Italic",e,i],["Times-BoldItalic",e,o]],c=0,l=u.length;l>c;c++){var f=ee(u[c][0],u[c][1],u[c][2],a),d=u[c][0].split("-");te(f,d[0],d[1]||"")}j.publish("addFonts",{fonts:T,dictionary:I})},re=function(e){return e.foo=function(){try{return e.apply(this,arguments)}catch(n){var r=n.stack||"";~r.indexOf(" at ")&&(r=r.split(" at ")[1]);var s="Error in function "+r.split("\n")[0].split("<")[0]+": "+n.message;if(!t.console)throw new Error(s);t.console.error(s,n),t.alert&&alert(s)}},e.foo.bar=e,e.foo},se=function(t,e){var n,r,s,i,o,a,u,c,l;if(e=e||{},s=e.sourceEncoding||"Unicode",o=e.outputEncoding,(e.autoencode||o)&&T[d].metadata&&T[d].metadata[s]&&T[d].metadata[s].encoding&&(i=T[d].metadata[s].encoding,!o&&T[d].encoding&&(o=T[d].encoding),!o&&i.codePages&&(o=i.codePages[0]),"string"==typeof o&&(o=i[o]),o)){for(u=!1,a=[],n=0,r=t.length;r>n;n++)c=o[t.charCodeAt(n)],a.push(c?String.fromCharCode(c):t[n]),a[n].charCodeAt(0)>>8&&(u=!0);t=a.join("")}for(n=t.length;void 0===u&&0!==n;)t.charCodeAt(n-1)>>8&&(u=!0),n--;if(!u)return t;for(a=e.noBOM?[]:[254,255],n=0,r=t.length;r>n;n++){if(c=t.charCodeAt(n),l=c>>8,l>>8)throw new Error("Character at position "+n+" of string '"+t+"' exceeds 16bits. Cannot be encoded into UCS-2 BE");a.push(l),a.push(c-(l<<8))}return String.fromCharCode.apply(void 0,a)},ie=function(t,e){return se(t,e).replace(/\\/g,"\\\\").replace(/\(/g,"\\(").replace(/\)/g,"\\)")},oe=function(){W("/Producer (jsPDF "+n.version+")");for(var t in N)N.hasOwnProperty(t)&&N[t]&&W("/"+t.substr(0,1).toUpperCase()+t.substr(1)+" ("+ie(N[t])+")");var e=new Date,r=e.getTimezoneOffset(),s=0>r?"+":"-",i=Math.floor(Math.abs(r/60)),o=Math.abs(r%60),a=[s,G(i),"'",G(o),"'"].join("");W(["/CreationDate (D:",e.getFullYear(),G(e.getMonth()+1),G(e.getDate()),G(e.getHours()),G(e.getMinutes()),G(e.getSeconds()),a,")"].join(""))},ae=function(){switch(W("/Type /Catalog"),W("/Pages 1 0 R"),v||(v="fullwidth"),v){case"fullwidth":W("/OpenAction [3 0 R /FitH null]");break;case"fullheight":W("/OpenAction [3 0 R /FitV null]");break;case"fullpage":W("/OpenAction [3 0 R /Fit]");break;case"original":W("/OpenAction [3 0 R /XYZ null null 1]");break;default:var t=""+v;"%"===t.substr(t.length-1)&&(v=parseInt(v)/100),"number"==typeof v&&W("/OpenAction [3 0 R /XYZ null null "+M(v)+"]")}switch(b||(b="continuous"),b){case"continuous":W("/PageLayout /OneColumn");break;case"single":W("/PageLayout /SinglePage");break;case"two":case"twoleft":W("/PageLayout /TwoColumnLeft");break;case"tworight":W("/PageLayout /TwoColumnRight")}y&&W("/PageMode /"+y),j.publish("putCatalog")},ue=function(){W("/Size "+(S+1)),W("/Root "+S+" 0 R"),W("/Info "+(S-1)+" 0 R")},ce=function(t,e){var n="string"==typeof e&&e.toLowerCase();if("string"==typeof t){var r=t.toLowerCase();o.hasOwnProperty(r)&&(t=o[r][0]/h,e=o[r][1]/h)}if(Array.isArray(t)&&(e=t[1],t=t[0]),n){switch(n.substr(0,1)){case"l":e>t&&(n="s");break;case"p":t>e&&(n="s")}"s"===n&&(p=t,t=e,e=p)}E=!0,O[++B]=[],P[B]={width:Number(t)||w,height:Number(e)||g},fe(B)},le=function(){ce.apply(this,arguments),W(M(C*h)+" w"),W(k),0!==F&&W(F+" J"),0!==D&&W(D+" j"),j.publish("addPage",{pageNumber:B})},fe=function(t){t>0&&B>=t&&(m=t,w=P[t].width,g=P[t].height)},de=function(t,e){var n;t=void 0!==t?t:T[d].fontName,e=void 0!==e?e:T[d].fontStyle;try{n=I[t][e]}catch(r){}if(!n)throw new Error("Unable to look up font label for font '"+t+"', '"+e+"'. Refer to getFontList() for available fonts.");return n},he=function(){E=!1,S=2,R=[],z=[],W("%PDF-"+i),X(),Z(),V(),W("<<"),oe(),W(">>"),W("endobj"),V(),W("<<"),ae(),W(">>"),W("endobj");var t,e=U,n="0000000000";for(W("xref"),W("0 "+(S+1)),W(n+" 65535 f "),t=1;S>=t;t++)W((n+z[t]).slice(-10)+" 00000 n ");return W("trailer"),W("<<"),ue(),W(">>"),W("startxref"),W(e),W("%%EOF"),E=!0,R.join("\n")},pe=function(t){var e="S";return"F"===t?e="f":"FD"===t||"DF"===t?e="B":("f"===t||"f*"===t||"B"===t||"B*"===t)&&(e=t),e},me=function(){for(var t=he(),e=t.length,n=new ArrayBuffer(e),r=new Uint8Array(n);e--;)r[e]=t.charCodeAt(e);return n},we=function(){return new Blob([me()],{type:"application/pdf"})},ge=re(function(e,n){var s="dataur"===(""+e).substr(0,6)?"data:application/pdf;base64,"+btoa(he()):0;switch(e){case void 0:return he();case"save":if(navigator.getUserMedia&&(void 0===t.URL||void 0===t.URL.createObjectURL))return L.output("dataurlnewwindow");r(we(),n),"function"==typeof r.unload&&t.setTimeout&&setTimeout(r.unload,911);break;case"arraybuffer":return me();case"blob":return we();case"bloburi":case"bloburl":return t.URL&&t.URL.createObjectURL(we())||void 0;case"datauristring":case"dataurlstring":return s;case"dataurlnewwindow":var i=t.open(s);if(i||"undefined"==typeof safari)return i;case"datauri":case"dataurl":return t.document.location.href=s;default:throw new Error('Output type "'+e+'" is not supported.')}});switch(u){case"pt":h=1;break;case"mm":h=72/25.4;break;case"cm":h=72/2.54;break;case"in":h=72;break;case"px":h=96/72;break;case"pc":h=12;break;case"em":h=12;break;case"ex":h=6;break;default:throw"Invalid unit: "+u}L.internal={pdfEscape:ie,getStyle:pe,getFont:function(){return T[de.apply(L,arguments)]},getFontSize:function(){return _},getLineHeight:function(){return _*A},write:function(t){W(1===arguments.length?t:Array.prototype.join.call(arguments," "))},getCoordinateString:function(t){return M(t*h)},getVerticalCoordinateString:function(t){return M((g-t)*h)},collections:{},newObject:V,putStream:J,events:j,scaleFactor:h,pageSize:{get width(){return w},get height(){return g}},output:function(t,e){return ge(t,e)},getNumberOfPages:function(){return O.length-1},pages:O},L.addPage=function(){return le.apply(this,arguments),this},L.setPage=function(){return fe.apply(this,arguments),this},L.setDisplayMode=function(t,e,n){return v=t,b=e,y=n,this},L.text=function(t,e,n,r,s){function i(t){return t=t.split("	").join(Array(f.TabLen||9).join(" ")),ie(t,r)}"number"==typeof t&&(p=n,n=e,e=t,t=p),"string"==typeof t&&t.match(/[\n\r]/)&&(t=t.split(/\r\n|\r|\n/g)),"number"==typeof r&&(s=r,r=null);var o,a="",u="Td";if(s){s*=Math.PI/180;var c=Math.cos(s),l=Math.sin(s);a=[M(c),M(l),M(-1*l),M(c),""].join(" "),u="Tm"}if(r=r||{},"noBOM"in r||(r.noBOM=!0),"autoencode"in r||(r.autoencode=!0),"string"==typeof t)t=i(t);else{if(!(t instanceof Array))throw new Error('Type of text must be string or Array. "'+t+'" is not recognized.');for(var m=t.concat(),w=[],y=m.length;y--;)w.push(i(m.shift()));var v=Math.ceil((g-n)*h/(_*A));v>=0&&v<w.length+1&&(o=w.splice(v-1)),t=w.join(") Tj\nT* (")}return W("BT\n/"+d+" "+_+" Tf\n"+_*A+" TL\n"+x+"\n"+a+M(e*h)+" "+M((g-n)*h)+" "+u+"\n("+t+") Tj\nET"),o&&(this.addPage(),this.text(o,e,1.7*_/h)),this},L.lstext=function(t,e,n,r){for(var s=0,i=t.length;i>s;s++,e+=r)this.text(t[s],e,n)},L.line=function(t,e,n,r){return this.lines([[n-t,r-e]],t,e)},L.clip=function(){W("W"),W("S")},L.lines=function(t,e,n,r,s,i){var o,a,u,c,l,f,d,m,w,y,v;for("number"==typeof t&&(p=n,n=e,e=t,t=p),r=r||[1,1],W(H(e*h)+" "+H((g-n)*h)+" m "),o=r[0],a=r[1],c=t.length,y=e,v=n,u=0;c>u;u++)l=t[u],2===l.length?(y=l[0]*o+y,v=l[1]*a+v,W(H(y*h)+" "+H((g-v)*h)+" l")):(f=l[0]*o+y,d=l[1]*a+v,m=l[2]*o+y,w=l[3]*a+v,y=l[4]*o+y,v=l[5]*a+v,W(H(f*h)+" "+H((g-d)*h)+" "+H(m*h)+" "+H((g-w)*h)+" "+H(y*h)+" "+H((g-v)*h)+" c"));return i&&W(" h"),null!==s&&W(pe(s)),this},L.rect=function(t,e,n,r,s){pe(s);return W([M(t*h),M((g-e)*h),M(n*h),M(-r*h),"re"].join(" ")),null!==s&&W(pe(s)),this},L.triangle=function(t,e,n,r,s,i,o){return this.lines([[n-t,r-e],[s-n,i-r],[t-s,e-i]],t,e,[1,1],o,!0),this},L.roundedRect=function(t,e,n,r,s,i,o){var a=4/3*(Math.SQRT2-1);return this.lines([[n-2*s,0],[s*a,0,s,i-i*a,s,i],[0,r-2*i],[0,i*a,-(s*a),i,-s,i],[-n+2*s,0],[-(s*a),0,-s,-(i*a),-s,-i],[0,-r+2*i],[0,-(i*a),s*a,-i,s,-i]],t+s,e,[1,1],o),this},L.ellipse=function(t,e,n,r,s){var i=4/3*(Math.SQRT2-1)*n,o=4/3*(Math.SQRT2-1)*r;return W([M((t+n)*h),M((g-e)*h),"m",M((t+n)*h),M((g-(e-o))*h),M((t+i)*h),M((g-(e-r))*h),M(t*h),M((g-(e-r))*h),"c"].join(" ")),W([M((t-i)*h),M((g-(e-r))*h),M((t-n)*h),M((g-(e-o))*h),M((t-n)*h),M((g-e)*h),"c"].join(" ")),W([M((t-n)*h),M((g-(e+o))*h),M((t-i)*h),M((g-(e+r))*h),M(t*h),M((g-(e+r))*h),"c"].join(" ")),W([M((t+i)*h),M((g-(e+r))*h),M((t+n)*h),M((g-(e+o))*h),M((t+n)*h),M((g-e)*h),"c"].join(" ")),null!==s&&W(pe(s)),this},L.circle=function(t,e,n,r){return this.ellipse(t,e,n,n,r)},L.setProperties=function(t){for(var e in N)N.hasOwnProperty(e)&&t[e]&&(N[e]=t[e]);return this},L.setFontSize=function(t){return _=t,this},L.setFont=function(t,e){return d=de(t,e),this},L.setFontStyle=L.setFontType=function(t){return d=de(void 0,t),this},L.getFontList=function(){var t,e,n,r={};for(t in I)if(I.hasOwnProperty(t)){r[t]=n=[];for(e in I[t])I[t].hasOwnProperty(e)&&n.push(e)}return r},L.setLineWidth=function(t){return W((t*h).toFixed(2)+" w"),this},L.setDrawColor=function(t,e,n,r){var s;return s=void 0===e||void 0===r&&t===e===n?"string"==typeof t?t+" G":M(t/255)+" G":void 0===r?"string"==typeof t?[t,e,n,"RG"].join(" "):[M(t/255),M(e/255),M(n/255),"RG"].join(" "):"string"==typeof t?[t,e,n,r,"K"].join(" "):[M(t),M(e),M(n),M(r),"K"].join(" "),W(s),this},L.setFillColor=function(t,e,n,r){var s;return s=void 0===e||void 0===r&&t===e===n?"string"==typeof t?t+" g":M(t/255)+" g":void 0===r?"string"==typeof t?[t,e,n,"rg"].join(" "):[M(t/255),M(e/255),M(n/255),"rg"].join(" "):"string"==typeof t?[t,e,n,r,"k"].join(" "):[M(t),M(e),M(n),M(r),"k"].join(" "),W(s),this},L.setTextColor=function(t,e,n){if("string"==typeof t&&/^#[0-9A-Fa-f]{6}$/.test(t)){var r=parseInt(t.substr(1),16);t=r>>16&255,e=r>>8&255,n=255&r}return x=0===t&&0===e&&0===n||"undefined"==typeof e?H(t/255)+" g":[H(t/255),H(e/255),H(n/255),"rg"].join(" "),this},L.CapJoinStyles={0:0,butt:0,but:0,miter:0,1:1,round:1,rounded:1,circle:1,2:2,projecting:2,project:2,square:2,bevel:2},L.setLineCap=function(t){var e=this.CapJoinStyles[t];if(void 0===e)throw new Error("Line cap style of '"+t+"' is not recognized. See or extend .CapJoinStyles property for valid styles");return F=e,W(e+" J"),this},L.setLineJoin=function(t){var e=this.CapJoinStyles[t];if(void 0===e)throw new Error("Line join style of '"+t+"' is not recognized. See or extend .CapJoinStyles property for valid styles");return D=e,W(e+" j"),this},L.output=ge,L.save=function(t){L.output("save",t)};for(var ye in n.API)n.API.hasOwnProperty(ye)&&("events"===ye&&n.API.events.length?!function(t,e){var n,r,s;for(s=e.length-1;-1!==s;s--)n=e[s][0],r=e[s][1],t.subscribe.apply(t,[n].concat("function"==typeof r?[r]:r))}(j,n.API.events):L[ye]=n.API[ye]);return ne(),d="F1",le(c,a),j.publish("initialized"),L}var i="1.3",o={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89],a5:[419.53,595.28],a6:[297.64,419.53],a7:[209.76,297.64],a8:[147.4,209.76],a9:[104.88,147.4],a10:[73.7,104.88],b0:[2834.65,4008.19],b1:[2004.09,2834.65],b2:[1417.32,2004.09],b3:[1000.63,1417.32],b4:[708.66,1000.63],b5:[498.9,708.66],b6:[354.33,498.9],b7:[249.45,354.33],b8:[175.75,249.45],b9:[124.72,175.75],b10:[87.87,124.72],c0:[2599.37,3676.54],c1:[1836.85,2599.37],c2:[1298.27,1836.85],c3:[918.43,1298.27],c4:[649.13,918.43],c5:[459.21,649.13],c6:[323.15,459.21],c7:[229.61,323.15],c8:[161.57,229.61],c9:[113.39,161.57],c10:[79.37,113.39],dl:[311.81,623.62],letter:[612,792],"government-letter":[576,756],legal:[612,1008],"junior-legal":[576,360],ledger:[1224,792],tabloid:[792,1224],"credit-card":[153,243]};return n.API={events:[]},n.version="1.0.272-git 2014-09-29T15:09:diegocr","function"==typeof define&&define.amd?define("jsPDF",function(){return n}):t.jsPDF=n,n}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this);!function(t){"use strict";t.addHTML=function(t,e,n,r,s){if("undefined"==typeof html2canvas&&"undefined"==typeof rasterizeHTML)throw new Error("You need either https://github.com/niklasvh/html2canvas or https://github.com/cburgmer/rasterizeHTML.js");"number"!=typeof e&&(r=e,s=n),"function"==typeof r&&(s=r,r=null);var i=this.internal,o=i.scaleFactor,a=i.pageSize.width,u=i.pageSize.height;if(r=r||{},r.onrendered=function(t){e=parseInt(e)||0,n=parseInt(n)||0;var i=r.dim||{},c=i.h||0,l=i.w||Math.min(a,t.width/o)-e,f="JPEG";if(r.format&&(f=r.format),t.height>u&&r.pagesplit){var d=function(){for(var r=0;;){var i=document.createElement("canvas");i.width=Math.min(a*o,t.width),i.height=Math.min(u*o,t.height-r);var c=i.getContext("2d");c.drawImage(t,0,r,t.width,i.height,0,0,i.width,i.height);var d=[i,e,r?0:n,i.width/o,i.height/o,f,null,"SLOW"];if(this.addImage.apply(this,d),r+=i.height,r>=t.height)break;this.addPage()}s(l,r,null,d)}.bind(this);if("CANVAS"===t.nodeName){var h=new Image;h.onload=d,h.src=t.toDataURL("image/png"),t=h}else d()}else{var p=Math.random().toString(35),m=[t,e,n,l,c,f,p,"SLOW"];this.addImage.apply(this,m),s(l,c,p,m)}}.bind(this),"undefined"!=typeof html2canvas&&!r.rstz)return html2canvas(t,r);if("undefined"!=typeof rasterizeHTML){var c="drawDocument";return"string"==typeof t&&(c=/^http/.test(t)?"drawURL":"drawHTML"),r.width=r.width||a*o,rasterizeHTML[c](t,void 0,r).then(function(t){r.onrendered(t.image)},function(t){s(null,t)})}return null}}(n.API),function(t){"use strict";var e="addImage_",n=["jpeg","jpg","png"],r=function(t){var e=this.internal.newObject(),n=this.internal.write,s=this.internal.putStream;if(t.n=e,n("<</Type /XObject"),n("/Subtype /Image"),n("/Width "+t.w),n("/Height "+t.h),t.cs===this.color_spaces.INDEXED?n("/ColorSpace [/Indexed /DeviceRGB "+(t.pal.length/3-1)+" "+("smask"in t?e+2:e+1)+" 0 R]"):(n("/ColorSpace /"+t.cs),t.cs===this.color_spaces.DEVICE_CMYK&&n("/Decode [1 0 1 0 1 0 1 0]")),n("/BitsPerComponent "+t.bpc),"f"in t&&n("/Filter /"+t.f),"dp"in t&&n("/DecodeParms <<"+t.dp+">>"),"trns"in t&&t.trns.constructor==Array){for(var i="",o=0,a=t.trns.length;a>o;o++)i+=t.trns[o]+" "+t.trns[o]+" ";n("/Mask ["+i+"]")}if("smask"in t&&n("/SMask "+(e+1)+" 0 R"),n("/Length "+t.data.length+">>"),s(t.data),n("endobj"),"smask"in t){var u="/Predictor 15 /Colors 1 /BitsPerComponent "+t.bpc+" /Columns "+t.w,c={w:t.w,h:t.h,cs:"DeviceGray",bpc:t.bpc,dp:u,data:t.smask};"f"in t&&(c.f=t.f),r.call(this,c)}t.cs===this.color_spaces.INDEXED&&(this.internal.newObject(),n("<< /Length "+t.pal.length+">>"),s(this.arrayBufferToBinaryString(new Uint8Array(t.pal))),n("endobj"))},s=function(){var t=this.internal.collections[e+"images"];for(var n in t)r.call(this,t[n])},i=function(){var t,n=this.internal.collections[e+"images"],r=this.internal.write;for(var s in n)t=n[s],r("/I"+t.i,t.n,"0","R")},o=function(e){return e&&"string"==typeof e&&(e=e.toUpperCase()),e in t.image_compression?e:t.image_compression.NONE},a=function(){var t=this.internal.collections[e+"images"];return t||(this.internal.collections[e+"images"]=t={},this.internal.events.subscribe("putResources",s),this.internal.events.subscribe("putXobjectDict",i)),t},u=function(t){var e=0;return t&&(e=Object.keys?Object.keys(t).length:function(t){var e=0;for(var n in t)t.hasOwnProperty(n)&&e++;return e}(t)),e},c=function(t){return"undefined"==typeof t||null===t},l=function(e){return"string"==typeof e&&t.sHashCode(e)},f=function(t){return-1===n.indexOf(t)},d=function(e){return"function"!=typeof t["process"+e.toUpperCase()]},h=function(t){return"object"==typeof t&&1===t.nodeType},p=function(t,e,n){if("IMG"===t.nodeName&&t.hasAttribute("src")){var r=""+t.getAttribute("src");if(!n&&0===r.indexOf("data:image/"))return r;!e&&/\.png(?:[?#].*)?$/i.test(r)&&(e="png")}if("CANVAS"===t.nodeName)var s=t;else{var s=document.createElement("canvas");s.width=t.clientWidth||t.width,s.height=t.clientHeight||t.height;var i=s.getContext("2d");if(!i)throw"addImage requires canvas to be supported by browser.";if(n){var o,a,u,c,l,f,d,h,p=Math.PI/180;"object"==typeof n&&(o=n.x,a=n.y,u=n.bg,n=n.angle),h=n*p,c=Math.abs(Math.cos(h)),l=Math.abs(Math.sin(h)),f=s.width,d=s.height,s.width=d*l+f*c,s.height=d*c+f*l,isNaN(o)&&(o=s.width/2),isNaN(a)&&(a=s.height/2),i.clearRect(0,0,s.width,s.height),i.fillStyle=u||"white",i.fillRect(0,0,s.width,s.height),i.save(),i.translate(o,a),i.rotate(h),i.drawImage(t,-(f/2),-(d/2)),i.rotate(-h),i.translate(-o,-a),i.restore()}else i.drawImage(t,0,0,s.width,s.height)}return s.toDataURL("png"==(""+e).toLowerCase()?"image/png":"image/jpeg")},m=function(t,e){var n;if(e)for(var r in e)if(t===e[r].alias){n=e[r];break}return n},w=function(t,e,n){return t||e||(t=-96,e=-96),0>t&&(t=-1*n.w*72/t/this.internal.scaleFactor),0>e&&(e=-1*n.h*72/e/this.internal.scaleFactor),0===t&&(t=e*n.w/n.h),0===e&&(e=t*n.h/n.w),[t,e]},g=function(t,e,n,r,s,i,o){var a=w.call(this,n,r,s),u=this.internal.getCoordinateString,c=this.internal.getVerticalCoordinateString;n=a[0],r=a[1],o[i]=s,this.internal.write("q",u(n),"0 0",u(r),u(t),c(e+r),"cm /I"+s.i,"Do Q")};t.color_spaces={DEVICE_RGB:"DeviceRGB",DEVICE_GRAY:"DeviceGray",DEVICE_CMYK:"DeviceCMYK",CAL_GREY:"CalGray",CAL_RGB:"CalRGB",LAB:"Lab",ICC_BASED:"ICCBased",INDEXED:"Indexed",PATTERN:"Pattern",SEPERATION:"Seperation",DEVICE_N:"DeviceN"},t.decode={DCT_DECODE:"DCTDecode",FLATE_DECODE:"FlateDecode",LZW_DECODE:"LZWDecode",JPX_DECODE:"JPXDecode",JBIG2_DECODE:"JBIG2Decode",ASCII85_DECODE:"ASCII85Decode",ASCII_HEX_DECODE:"ASCIIHexDecode",RUN_LENGTH_DECODE:"RunLengthDecode",CCITT_FAX_DECODE:"CCITTFaxDecode"},t.image_compression={NONE:"NONE",FAST:"FAST",MEDIUM:"MEDIUM",SLOW:"SLOW"},t.sHashCode=function(t){return Array.prototype.reduce&&t.split("").reduce(function(t,e){return t=(t<<5)-t+e.charCodeAt(0),t&t},0)},t.isString=function(t){return"string"==typeof t},t.extractInfoFromBase64DataURI=function(t){return/^data:([\w]+?\/([\w]+?));base64,(.+?)$/g.exec(t)},t.supportsArrayBuffer=function(){return"undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array},t.isArrayBuffer=function(t){return this.supportsArrayBuffer()?t instanceof ArrayBuffer:!1},t.isArrayBufferView=function(t){return this.supportsArrayBuffer()?"undefined"==typeof Uint32Array?!1:t instanceof Int8Array||t instanceof Uint8Array||"undefined"!=typeof Uint8ClampedArray&&t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array:!1},t.binaryStringToUint8Array=function(t){for(var e=t.length,n=new Uint8Array(e),r=0;e>r;r++)n[r]=t.charCodeAt(r);return n},t.arrayBufferToBinaryString=function(t){this.isArrayBuffer(t)&&(t=new Uint8Array(t));for(var e="",n=t.byteLength,r=0;n>r;r++)e+=String.fromCharCode(t[r]);return e},t.arrayBufferToBase64=function(t){for(var e,n,r,s,i,o="",a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",u=new Uint8Array(t),c=u.byteLength,l=c%3,f=c-l,d=0;f>d;d+=3)i=u[d]<<16|u[d+1]<<8|u[d+2],e=(16515072&i)>>18,n=(258048&i)>>12,r=(4032&i)>>6,s=63&i,o+=a[e]+a[n]+a[r]+a[s];return 1==l?(i=u[f],e=(252&i)>>2,n=(3&i)<<4,o+=a[e]+a[n]+"=="):2==l&&(i=u[f]<<8|u[f+1],e=(64512&i)>>10,n=(1008&i)>>4,r=(15&i)<<2,o+=a[e]+a[n]+a[r]+"="),o},t.createImageInfo=function(t,e,n,r,s,i,o,a,u,c,l,f){var d={alias:a,w:e,h:n,cs:r,bpc:s,i:o,data:t};return i&&(d.f=i),u&&(d.dp=u),c&&(d.trns=c),l&&(d.pal=l),f&&(d.smask=f),d},t.addImage=function(t,e,r,s,i,w,y,v,b){if("string"!=typeof e){var q=w;w=i,i=s,s=r,r=e,e=q}if("object"==typeof t&&!h(t)&&"imageData"in t){var x=t;t=x.imageData,e=x.format||e,r=x.x||r||0,s=x.y||s||0,i=x.w||i,w=x.h||w,y=x.alias||y,v=x.compression||v,b=x.rotation||x.angle||b}if(isNaN(r)||isNaN(s))throw console.error("jsPDF.addImage: Invalid coordinates",arguments),new Error("Invalid coordinates passed to jsPDF.addImage");var k,_=a.call(this);if(!(k=m(t,_))){var A;if(h(t)&&(t=p(t,e,b)),c(y)&&(y=l(t)),!(k=m(y,_))){if(this.isString(t)){var C=this.extractInfoFromBase64DataURI(t);C?(e=C[2],t=atob(C[3])):137===t.charCodeAt(0)&&80===t.charCodeAt(1)&&78===t.charCodeAt(2)&&71===t.charCodeAt(3)&&(e="png")}if(e=(e||"JPEG").toLowerCase(),f(e))throw new Error("addImage currently only supports formats "+n+", not '"+e+"'");if(d(e))throw new Error("please ensure that the plugin for '"+e+"' support is added");if(this.supportsArrayBuffer()&&(A=t,t=this.binaryStringToUint8Array(t)),k=this["process"+e.toUpperCase()](t,u(_),y,o(v),A),!k)throw new Error("An unkwown error occurred whilst processing the image")}}return g.call(this,r,s,i,w,k,k.i,_),this};var y=function(t){var e,n,r;if(255===!t.charCodeAt(0)||216===!t.charCodeAt(1)||255===!t.charCodeAt(2)||224===!t.charCodeAt(3)||!t.charCodeAt(6)==="J".charCodeAt(0)||!t.charCodeAt(7)==="F".charCodeAt(0)||!t.charCodeAt(8)==="I".charCodeAt(0)||!t.charCodeAt(9)==="F".charCodeAt(0)||0===!t.charCodeAt(10))throw new Error("getJpegSize requires a binary string jpeg file");for(var s=256*t.charCodeAt(4)+t.charCodeAt(5),i=4,o=t.length;o>i;){if(i+=s,255!==t.charCodeAt(i))throw new Error("getJpegSize could not find the size of the image");if(192===t.charCodeAt(i+1)||193===t.charCodeAt(i+1)||194===t.charCodeAt(i+1)||195===t.charCodeAt(i+1)||196===t.charCodeAt(i+1)||197===t.charCodeAt(i+1)||198===t.charCodeAt(i+1)||199===t.charCodeAt(i+1))return n=256*t.charCodeAt(i+5)+t.charCodeAt(i+6),e=256*t.charCodeAt(i+7)+t.charCodeAt(i+8),r=t.charCodeAt(i+9),[e,n,r];i+=2,s=256*t.charCodeAt(i)+t.charCodeAt(i+1)}},v=function(t){var e=t[0]<<8|t[1];if(65496!==e)throw new Error("Supplied data is not a JPEG");for(var n,r,s,i,o=t.length,a=(t[4]<<8)+t[5],u=4;o>u;){if(u+=a,n=b(t,u),a=(n[2]<<8)+n[3],(192===n[1]||194===n[1])&&255===n[0]&&a>7)return n=b(t,u+5),r=(n[2]<<8)+n[3],s=(n[0]<<8)+n[1],i=n[4],{width:r,height:s,numcomponents:i};u+=2}throw new Error("getJpegSizeFromBytes could not find the size of the image")},b=function(t,e){return t.subarray(e,e+5)};t.processJPEG=function(t,e,n,r,s){var i,o=this.color_spaces.DEVICE_RGB,a=this.decode.DCT_DECODE,u=8;return this.isString(t)?(i=y(t),this.createImageInfo(t,i[0],i[1],1==i[3]?this.color_spaces.DEVICE_GRAY:o,u,a,e,n)):(this.isArrayBuffer(t)&&(t=new Uint8Array(t)),this.isArrayBufferView(t)?(i=v(t),t=s||this.arrayBufferToBinaryString(t),this.createImageInfo(t,i.width,i.height,1==i.numcomponents?this.color_spaces.DEVICE_GRAY:o,u,a,e,n)):null)},t.processJPG=function(){return this.processJPEG.apply(this,arguments)}}(n.API),function(t){"use strict";t.autoPrint=function(){var t;return this.internal.events.subscribe("postPutResources",function(){t=this.internal.newObject(),this.internal.write("<< /S/Named /Type/Action /N/Print >>","endobj")}),this.internal.events.subscribe("putCatalog",function(){this.internal.write("/OpenAction "+t+" 0 R")}),this}}(n.API),function(t){"use strict";var e,n,r,s,i=3,o=13,a={x:void 0,y:void 0,w:void 0,h:void 0,ln:void 0},u=1,c=function(t,e,n,r,s){a={x:t,y:e,w:n,h:r,ln:s}},l=function(){return a},f={left:0,top:0,bottom:0};t.setHeaderFunction=function(t){s=t},t.getTextDimensions=function(t){e=this.internal.getFont().fontName,n=this.table_font_size||this.internal.getFontSize(),r=this.internal.getFont().fontStyle;var s,i,o=19.049976/25.4;return i=document.createElement("font"),i.id="jsPDFCell",i.style.fontStyle=r,i.style.fontName=e,i.style.fontSize=n+"pt",i.textContent=t,document.body.appendChild(i),s={w:(i.offsetWidth+1)*o,h:(i.offsetHeight+1)*o},document.body.removeChild(i),s},t.cellAddPage=function(){var t=this.margins||f;this.addPage(),c(t.left,t.top,void 0,void 0),u+=1},t.cellInitialize=function(){a={x:void 0,y:void 0,w:void 0,h:void 0,ln:void 0},u=1},t.cell=function(t,e,n,r,s,a,u){var d=l();if(void 0!==d.ln)if(d.ln===a)t=d.x+d.w,e=d.y;else{var h=this.margins||f;d.y+d.h+r+o>=this.internal.pageSize.height-h.bottom&&(this.cellAddPage(),this.printHeaders&&this.tableHeaderRow&&this.printHeaderRow(a,!0)),e=l().y+l().h}if(void 0!==s[0])if(this.printingHeaderRow?this.rect(t,e,n,r,"FD"):this.rect(t,e,n,r),"right"===u){if(s instanceof Array)for(var p=0;p<s.length;p++){var m=s[p],w=this.getStringUnitWidth(m)*this.internal.getFontSize();this.text(m,t+n-w-i,e+this.internal.getLineHeight()*(p+1))}}else this.text(s,t+i,e+this.internal.getLineHeight());return c(t,e,n,r,a),this},t.arrayMax=function(t,e){var n,r,s,i=t[0];for(n=0,r=t.length;r>n;n+=1)s=t[n],e?-1===e(i,s)&&(i=s):s>i&&(i=s);return i},t.table=function(e,n,r,s,i){if(!r)throw"No data for PDF table";var o,c,l,d,h,p,m,w,g,y,v=[],b=[],q={},x={},k=[],_=[],A=!1,C=!0,S=12,E=f;if(E.width=this.internal.pageSize.width,i&&(i.autoSize===!0&&(A=!0),i.printHeaders===!1&&(C=!1),i.fontSize&&(S=i.fontSize),i.margins&&(E=i.margins)),this.lnMod=0,a={x:void 0,y:void 0,w:void 0,h:void 0,ln:void 0},u=1,this.printHeaders=C,this.margins=E,this.setFontSize(S),this.table_font_size=S,void 0===s||null===s)v=Object.keys(r[0]);else if(s[0]&&"string"!=typeof s[0]){var z=19.049976/25.4;for(c=0,l=s.length;l>c;c+=1)o=s[c],v.push(o.name),b.push(o.prompt),x[o.name]=o.width*z}else v=s;if(A)for(y=function(t){return t[o]},c=0,l=v.length;l>c;c+=1){for(o=v[c],q[o]=r.map(y),k.push(this.getTextDimensions(b[c]||o).w),p=q[o],m=0,d=p.length;d>m;m+=1)h=p[m],k.push(this.getTextDimensions(h).w);x[o]=t.arrayMax(k)}if(C){var T=this.calculateLineHeight(v,x,b.length?b:v);for(c=0,l=v.length;l>c;c+=1)o=v[c],_.push([e,n,x[o],T,String(b.length?b[c]:o)]);this.setTableHeaderRow(_),this.printHeaderRow(1,!1)}for(c=0,l=r.length;l>c;c+=1){var T;for(w=r[c],T=this.calculateLineHeight(v,x,w),m=0,g=v.length;g>m;m+=1)o=v[m],this.cell(e,n,x[o],T,w[o],c+2,o.align)}return this.lastCellPos=a,this.table_x=e,this.table_y=n,this},t.calculateLineHeight=function(t,e,n){for(var r,s=0,o=0;o<t.length;o++){r=t[o],n[r]=this.splitTextToSize(String(n[r]),e[r]-i);var a=this.internal.getLineHeight()*n[r].length+i;a>s&&(s=a)}return s},t.setTableHeaderRow=function(t){this.tableHeaderRow=t},t.printHeaderRow=function(t,e){if(!this.tableHeaderRow)throw"Property tableHeaderRow does not exist.";var n,r,i,o;if(this.printingHeaderRow=!0,void 0!==s){var a=s(this,u);c(a[0],a[1],a[2],a[3],-1)}this.setFontStyle("bold");var l=[];for(i=0,o=this.tableHeaderRow.length;o>i;i+=1)this.setFillColor(200,200,200),n=this.tableHeaderRow[i],e&&(n[1]=this.margins&&this.margins.top||0,l.push(n)),r=[].concat(n),this.cell.apply(this,r.concat(t));l.length>0&&this.setTableHeaderRow(l),this.setFontStyle("normal"),this.printingHeaderRow=!1}}(n.API),function(t){var e,n,r,s,i,o,a,u,c,l,f,d,h,p,m,w,g,y,v;e=function(){function t(){}return function(e){return t.prototype=e,new t}}(),c=function(t){var e,n,r,s,i,o,a;for(n=0,r=t.length,e=void 0,s=!1,o=!1;!s&&n!==r;)e=t[n]=t[n].trimLeft(),e&&(s=!0),n++;for(n=r-1;r&&!o&&-1!==n;)e=t[n]=t[n].trimRight(),e&&(o=!0),n--;for(i=/\s+$/g,a=!0,n=0;n!==r;)e=t[n].replace(/\s+/g," "),a&&(e=e.trimLeft()),e&&(a=i.test(e)),t[n]=e,n++;return t},l=function(t,e,n,r){return this.pdf=t,this.x=e,this.y=n,this.settings=r,this.watchFunctions=[],this.init(),this},f=function(t){var e,n,s;for(e=void 0,s=t.split(","),n=s.shift();!e&&n;)e=r[n.trim().toLowerCase()],n=s.shift();return e},d=function(t){t="auto"===t?"0px":t,t.indexOf("em")>-1&&!isNaN(Number(t.replace("em","")))&&(t=18.719*Number(t.replace("em",""))+"px"),t.indexOf("pt")>-1&&!isNaN(Number(t.replace("pt","")))&&(t=1.333*Number(t.replace("pt",""))+"px");var e,n,r;return n=void 0,e=16,(r=h[t])?r:(r={"xx-small":9,"x-small":11,small:13,medium:16,large:19,"x-large":23,"xx-large":28,auto:0}[{css_line_height_string:t}],r!==n?h[t]=r/e:(r=parseFloat(t))?h[t]=r/e:(r=t.match(/([\d\.]+)(px)/),h[t]=3===r.length?parseFloat(r[1])/e:1))},u=function(t){var e,n,r;return r=function(t){var e;return e=function(t){return document.defaultView&&document.defaultView.getComputedStyle?document.defaultView.getComputedStyle(t,null):t.currentStyle?t.currentStyle:t.style}(t),function(t){return t=t.replace(/-\D/g,function(t){return t.charAt(1).toUpperCase()}),e[t]}}(t),e={},n=void 0,e["font-family"]=f(r("font-family"))||"times",e["font-style"]=s[r("font-style")]||"normal",e["text-align"]=TextAlignMap[r("text-align")]||"left",n=i[r("font-weight")]||"normal","bold"===n&&(e["font-style"]="normal"===e["font-style"]?n:n+e["font-style"]),e["font-size"]=d(r("font-size"))||1,e["line-height"]=d(r("line-height"))||1,e.display="inline"===r("display")?"inline":"block",n="block"===e.display,e["margin-top"]=n&&d(r("margin-top"))||0,e["margin-bottom"]=n&&d(r("margin-bottom"))||0,e["padding-top"]=n&&d(r("padding-top"))||0,e["padding-bottom"]=n&&d(r("padding-bottom"))||0,e["margin-left"]=n&&d(r("margin-left"))||0,e["margin-right"]=n&&d(r("margin-right"))||0,e["padding-left"]=n&&d(r("padding-left"))||0,e["padding-right"]=n&&d(r("padding-right"))||0,e["float"]=o[r("cssFloat")]||"none",e.clear=a[r("clear")]||"none",e},p=function(t,e,n){var r,s,i,o,a;if(i=!1,s=void 0,o=void 0,a=void 0,r=n["#"+t.id])if("function"==typeof r)i=r(t,e);else for(s=0,o=r.length;!i&&s!==o;)i=r[s](t,e),s++;if(r=n[t.nodeName],!i&&r)if("function"==typeof r)i=r(t,e);else for(s=0,o=r.length;!i&&s!==o;)i=r[s](t,e),s++;return i},v=function(t,e){var n,r,s,i,o,a,u,c,l,f;
+for(n=[],r=[],s=0,f=t.rows[0].cells.length,c=t.clientWidth;f>s;)l=t.rows[0].cells[s],r[s]={name:l.textContent.toLowerCase().replace(/\s+/g,""),prompt:l.textContent.replace(/\r?\n/g,""),width:l.clientWidth/c*e.pdf.internal.pageSize.width},s++;for(s=1;s<t.rows.length;){for(a=t.rows[s],o={},i=0;i<a.cells.length;)o[r[i].name]=a.cells[i].textContent.replace(/\r?\n/g,""),i++;n.push(o),s++}return u={rows:n,headers:r}};var b={SCRIPT:1,STYLE:1,NOSCRIPT:1,OBJECT:1,EMBED:1,SELECT:1},q=1;n=function(t,e,r){var s,i,o,a,c,l,f,d,h;for(i=t.childNodes,s=void 0,o=u(t),c="block"===o.display,c&&(e.setBlockBoundary(),e.setBlockStyle(o)),f=19.049976/25.4,a=0,l=i.length;l>a;){if(s=i[a],"object"==typeof s){if(e.executeWatchFunctions(s),1===s.nodeType&&"HEADER"===s.nodeName){var w=s,g=e.pdf.margins_doc.top;e.pdf.internal.events.subscribe("addPage",function(){e.y=g,n(w,e,r),e.pdf.margins_doc.top=e.y+10,e.y+=10},!1)}if(8===s.nodeType&&"#comment"===s.nodeName)~s.textContent.indexOf("ADD_PAGE")&&(e.pdf.addPage(),e.y=e.pdf.margins_doc.top);else if(1!==s.nodeType||b[s.nodeName])if(3===s.nodeType){var y=s.nodeValue;if(s.nodeValue&&"LI"===s.parentNode.nodeName)if("OL"===s.parentNode.parentNode.nodeName)y=q++ +". "+y;else{var x=16*o["font-size"],k=2;x>20&&(k=3),h=function(t,e){this.pdf.circle(t,e,k,"FD")}}e.addText(y,o)}else"string"==typeof s&&e.addText(s,o);else{var _;if("IMG"===s.nodeName){var A=s.getAttribute("src");_=m[e.pdf.sHashCode(A)||A]}if(_){e.pdf.internal.pageSize.height-e.pdf.margins_doc.bottom<e.y+s.height&&e.y>e.pdf.margins_doc.top&&(e.pdf.addPage(),e.y=e.pdf.margins_doc.top,e.executeWatchFunctions(s));var C=u(s),S=e.x,E=12/e.pdf.internal.scaleFactor,z=(C["margin-left"]+C["padding-left"])*E,T=(C["margin-right"]+C["padding-right"])*E,I=(C["margin-top"]+C["padding-top"])*E,B=(C["margin-bottom"]+C["padding-bottom"])*E;S+=void 0!==C["float"]&&"right"===C["float"]?e.settings.width-s.width-T:z,e.pdf.addImage(_,S,e.y+I,s.width,s.height),_=void 0,"right"===C["float"]||"left"===C["float"]?(e.watchFunctions.push(function(t,n,r,s){return e.y>=n?(e.x+=t,e.settings.width+=r,!0):s&&1===s.nodeType&&!b[s.nodeName]&&e.x+s.width>e.pdf.margins_doc.left+e.pdf.margins_doc.width?(e.x+=t,e.y=n,e.settings.width+=r,!0):!1}.bind(this,"left"===C["float"]?-s.width-z-T:0,e.y+s.height+I+B,s.width)),e.watchFunctions.push(function(t,n,r){return e.y<t&&n===e.pdf.internal.getNumberOfPages()?1===r.nodeType&&"both"===u(r).clear?(e.y=t,!0):!1:!0}.bind(this,e.y+s.height,e.pdf.internal.getNumberOfPages())),e.settings.width-=s.width+z+T,"left"===C["float"]&&(e.x+=s.width+z+T)):e.y+=s.height+B}else if("TABLE"===s.nodeName)d=v(s,e),e.y+=10,e.pdf.table(e.x,e.y,d.rows,d.headers,{autoSize:!1,printHeaders:!0,margins:e.pdf.margins_doc}),e.y=e.pdf.lastCellPos.y+e.pdf.lastCellPos.h+20;else if("OL"===s.nodeName||"UL"===s.nodeName)q=1,p(s,e,r)||n(s,e,r),e.y+=10;else if("LI"===s.nodeName){var O=e.x;e.x+="UL"===s.parentNode.nodeName?22:10,e.y+=3,p(s,e,r)||n(s,e,r),e.x=O}else"BR"===s.nodeName?e.y+=o["font-size"]*e.pdf.internal.scaleFactor:p(s,e,r)||n(s,e,r)}}a++}return c?e.setBlockBoundary(h):void 0},m={},w=function(t,e,n,r){function s(){e.pdf.internal.events.publish("imagesLoaded"),r(o)}function i(t,n,r){if(t){var i=new Image;o=++c,i.crossOrigin="",i.onerror=i.onload=function(){if(i.complete&&(0===i.src.indexOf("data:image/")&&(i.width=n||i.width||0,i.height=r||i.height||0),i.width+i.height)){var o=e.pdf.sHashCode(t)||t;m[o]=m[o]||i}--c||s()},i.src=t}}for(var o,a=t.getElementsByTagName("img"),u=a.length,c=0;u--;)i(a[u].getAttribute("src"),a[u].width,a[u].height);return c||s()},g=function(t,e,r){var s=t.getElementsByTagName("footer");if(s.length>0){s=s[0];var i=e.pdf.internal.write,o=e.y;e.pdf.internal.write=function(){},n(s,e,r);var a=Math.ceil(e.y-o)+5;e.y=o,e.pdf.internal.write=i,e.pdf.margins_doc.bottom+=a;for(var u=function(t){var i=void 0!==t?t.pageNumber:1,o=e.y;e.y=e.pdf.internal.pageSize.height-e.pdf.margins_doc.bottom,e.pdf.margins_doc.bottom-=a;for(var u=s.getElementsByTagName("span"),c=0;c<u.length;++c)(" "+u[c].className+" ").replace(/[\n\t]/g," ").indexOf(" pageCounter ")>-1&&(u[c].innerHTML=i),(" "+u[c].className+" ").replace(/[\n\t]/g," ").indexOf(" totalPages ")>-1&&(u[c].innerHTML="###jsPDFVarTotalPages###");n(s,e,r),e.pdf.margins_doc.bottom+=a,e.y=o},c=s.getElementsByTagName("span"),l=0;l<c.length;++l)(" "+c[l].className+" ").replace(/[\n\t]/g," ").indexOf(" totalPages ")>-1&&e.pdf.internal.events.subscribe("htmlRenderingFinished",e.pdf.putTotalPages.bind(e.pdf,"###jsPDFVarTotalPages###"),!0);e.pdf.internal.events.subscribe("addPage",u,!1),u(),b.FOOTER=1}},y=function(t,e,r,s,i,o){if(!e)return!1;"string"==typeof e||e.parentNode||(e=""+e.innerHTML),"string"==typeof e&&(e=function(t){var e,n,r,s;return r="jsPDFhtmlText"+Date.now().toString()+(1e3*Math.random()).toFixed(0),s="position: absolute !important;clip: rect(1px 1px 1px 1px); /* IE6, IE7 */clip: rect(1px, 1px, 1px, 1px);padding:0 !important;border:0 !important;height: 1px !important;width: 1px !important; top:auto;left:-100px;overflow: hidden;",n=document.createElement("div"),n.style.cssText=s,n.innerHTML='<iframe style="height:1px;width:1px" name="'+r+'" />',document.body.appendChild(n),e=window.frames[r],e.document.body.innerHTML=t,e.document.body}(e.replace(/<\/?script[^>]*?>/gi,"")));var a,u=new l(t,r,s,i);return w.call(this,e,u,i.elementHandlers,function(t){g(e,u,i.elementHandlers),n(e,u,i.elementHandlers),u.pdf.internal.events.publish("htmlRenderingFinished"),a=u.dispose(),"function"==typeof o?o(a):t&&console.error("jsPDF Warning: rendering issues? provide a callback to fromHTML!")}),a||{x:u.x,y:u.y}},l.prototype.init=function(){return this.paragraph={text:[],style:[]},this.pdf.internal.write("q")},l.prototype.dispose=function(){return this.pdf.internal.write("Q"),{x:this.x,y:this.y,ready:!0}},l.prototype.executeWatchFunctions=function(t){var e=!1,n=[];if(this.watchFunctions.length>0){for(var r=0;r<this.watchFunctions.length;++r)this.watchFunctions[r](t)===!0?e=!0:n.push(this.watchFunctions[r]);this.watchFunctions=n}return e},l.prototype.splitFragmentsIntoLines=function(t,n){var r,s,i,o,a,u,c,l,f,d,h,p,m,w,g;for(s=12,h=this.pdf.internal.scaleFactor,a={},i=void 0,d=void 0,o=void 0,u=void 0,g=void 0,f=void 0,l=void 0,c=void 0,p=[],m=[p],r=0,w=this.settings.width;t.length;)if(u=t.shift(),g=n.shift(),u)if(i=g["font-family"],d=g["font-style"],o=a[i+d],o||(o=this.pdf.internal.getFont(i,d).metadata.Unicode,a[i+d]=o),f={widths:o.widths,kerning:o.kerning,fontSize:g["font-size"]*s,textIndent:r},l=this.pdf.getStringUnitWidth(u,f)*f.fontSize/h,r+l>w){for(c=this.pdf.splitTextToSize(u,w,f),p.push([c.shift(),g]);c.length;)p=[[c.shift(),g]],m.push(p);r=this.pdf.getStringUnitWidth(p[0][0],f)*f.fontSize/h}else p.push([u,g]),r+=l;if(void 0!==g["text-align"]&&("center"===g["text-align"]||"right"===g["text-align"]||"justify"===g["text-align"]))for(var y=0;y<m.length;++y){var v=this.pdf.getStringUnitWidth(m[y][0][0],f)*f.fontSize/h;y>0&&(m[y][0][1]=e(m[y][0][1]));var b=w-v;if("right"===g["text-align"])m[y][0][1]["margin-left"]=b;else if("center"===g["text-align"])m[y][0][1]["margin-left"]=b/2;else if("justify"===g["text-align"]){var q=m[y][0][0].split(" ").length-1;m[y][0][1]["word-spacing"]=b/q,y===m.length-1&&(m[y][0][1]["word-spacing"]=0)}}return m},l.prototype.RenderTextFragment=function(t,e){var n,r,s;s=0,n=12,this.pdf.internal.pageSize.height-this.pdf.margins_doc.bottom<this.y+this.pdf.internal.getFontSize()&&(this.pdf.internal.write("ET","Q"),this.pdf.addPage(),this.y=this.pdf.margins_doc.top,this.pdf.internal.write("q","BT 0 g",this.pdf.internal.getCoordinateString(this.x),this.pdf.internal.getVerticalCoordinateString(this.y),"Td"),s=Math.max(s,e["line-height"],e["font-size"]),this.pdf.internal.write(0,(-1*n*s).toFixed(2),"Td")),r=this.pdf.internal.getFont(e["font-family"],e["font-style"]),void 0!==e["word-spacing"]&&e["word-spacing"]>0&&this.pdf.internal.write(e["word-spacing"].toFixed(2),"Tw"),this.pdf.internal.write("/"+r.id,(n*e["font-size"]).toFixed(2),"Tf","("+this.pdf.internal.pdfEscape(t)+") Tj"),void 0!==e["word-spacing"]&&this.pdf.internal.write(0,"Tw")},l.prototype.renderParagraph=function(t){var e,n,r,s,i,o,a,u,l,f,d,h,p,m,w;if(s=c(this.paragraph.text),m=this.paragraph.style,e=this.paragraph.blockstyle,p=this.paragraph.blockstyle||{},this.paragraph={text:[],style:[],blockstyle:{},priorblockstyle:e},s.join("").trim()){u=this.splitFragmentsIntoLines(s,m),a=void 0,l=void 0,n=12,r=n/this.pdf.internal.scaleFactor,h=(Math.max((e["margin-top"]||0)-(p["margin-bottom"]||0),0)+(e["padding-top"]||0))*r,d=((e["margin-bottom"]||0)+(e["padding-bottom"]||0))*r,f=this.pdf.internal.write,i=void 0,o=void 0,this.y+=h,f("q","BT 0 g",this.pdf.internal.getCoordinateString(this.x),this.pdf.internal.getVerticalCoordinateString(this.y),"Td");for(var g=0;u.length;){for(a=u.shift(),l=0,i=0,o=a.length;i!==o;)a[i][0].trim()&&(l=Math.max(l,a[i][1]["line-height"],a[i][1]["font-size"]),w=7*a[i][1]["font-size"]),i++;var y=0;for(void 0!==a[0][1]["margin-left"]&&a[0][1]["margin-left"]>0&&(wantedIndent=this.pdf.internal.getCoordinateString(a[0][1]["margin-left"]),y=wantedIndent-g,g=wantedIndent),f(y,(-1*n*l).toFixed(2),"Td"),i=0,o=a.length;i!==o;)a[i][0]&&this.RenderTextFragment(a[i][0],a[i][1]),i++;if(this.y+=l*r,this.executeWatchFunctions(a[0][1])&&u.length>0){var v=[],b=[];u.forEach(function(t){for(var e=0,n=t.length;e!==n;)t[e][0]&&(v.push(t[e][0]+" "),b.push(t[e][1])),++e}),u=this.splitFragmentsIntoLines(c(v),b),f("ET","Q"),f("q","BT 0 g",this.pdf.internal.getCoordinateString(this.x),this.pdf.internal.getVerticalCoordinateString(this.y),"Td")}}return t&&"function"==typeof t&&t.call(this,this.x-9,this.y-w/2),f("ET","Q"),this.y+=d}},l.prototype.setBlockBoundary=function(t){return this.renderParagraph(t)},l.prototype.setBlockStyle=function(t){return this.paragraph.blockstyle=t},l.prototype.addText=function(t,e){return this.paragraph.text.push(t),this.paragraph.style.push(e)},r={helvetica:"helvetica","sans-serif":"helvetica","times new roman":"times",serif:"times",times:"times",monospace:"courier",courier:"courier"},i={100:"normal",200:"normal",300:"normal",400:"normal",500:"bold",600:"bold",700:"bold",800:"bold",900:"bold",normal:"normal",bold:"bold",bolder:"bold",lighter:"normal"},s={normal:"normal",italic:"italic",oblique:"italic"},TextAlignMap={left:"left",right:"right",center:"center",justify:"justify"},o={none:"none",right:"right",left:"left"},a={none:"none",both:"both"},h={normal:1},t.fromHTML=function(t,e,n,r,s,i){"use strict";return this.margins_doc=i||{top:0,bottom:0},r||(r={}),r.elementHandlers||(r.elementHandlers={}),y(this,t,isNaN(e)?4:e,isNaN(n)?4:n,r,s)}}(n.API),function(t){"use strict";var e,n,r;t.addJS=function(t){return r=t,this.internal.events.subscribe("postPutResources",function(){e=this.internal.newObject(),this.internal.write("<< /Names [(EmbeddedJS) "+(e+1)+" 0 R] >>","endobj"),n=this.internal.newObject(),this.internal.write("<< /S /JavaScript /JS (",r,") >>","endobj")}),this.internal.events.subscribe("putCatalog",function(){void 0!==e&&void 0!==n&&this.internal.write("/Names <</JavaScript "+e+" 0 R>>")}),this}}(n.API),function(t){"use strict";var e=function(){return"function"!=typeof PNG||"function"!=typeof o},n=function(e){return e!==t.image_compression.NONE&&r()},r=function(){var t="function"==typeof s;if(!t)throw new Error("requires deflate.js for compression");return t},i=function(e,n,r,i){var o=5,l=d;switch(i){case t.image_compression.FAST:o=3,l=f;break;case t.image_compression.MEDIUM:o=6,l=h;break;case t.image_compression.SLOW:o=9,l=p}e=c(e,n,r,l);var m=new Uint8Array(a(o)),w=u(e),g=new s(o),y=g.append(e),v=g.flush(),b=m.length+y.length+v.length,q=new Uint8Array(b+4);return q.set(m),q.set(y,m.length),q.set(v,m.length+y.length),q[b++]=w>>>24&255,q[b++]=w>>>16&255,q[b++]=w>>>8&255,q[b++]=255&w,t.arrayBufferToBinaryString(q)},a=function(t,e){var n=8,r=Math.LOG2E*Math.log(32768)-8,s=r<<4|n,i=s<<8,o=Math.min(3,(e-1&255)>>1);return i|=o<<6,i|=0,i+=31-i%31,[s,255&i&255]},u=function(t,e){for(var n,r=1,s=65535&r,i=r>>>16&65535,o=t.length,a=0;o>0;){n=o>e?e:o,o-=n;do s+=t[a++],i+=s;while(--n);s%=65521,i%=65521}return(i<<16|s)>>>0},c=function(t,e,n,r){for(var s,i,o,a=t.length/e,u=new Uint8Array(t.length+a),c=w(),l=0;a>l;l++){if(o=l*e,s=t.subarray(o,o+e),r)u.set(r(s,n,i),o+l);else{for(var f=0,d=c.length,h=[];d>f;f++)h[f]=c[f](s,n,i);var p=g(h.concat());u.set(h[p],o+l)}i=s}return u},l=function(t){var e=Array.apply([],t);return e.unshift(0),e},f=function(t,e){var n,r=[],s=0,i=t.length;for(r[0]=1;i>s;s++)n=t[s-e]||0,r[s+1]=t[s]-n+256&255;return r},d=function(t,e,n){var r,s=[],i=0,o=t.length;for(s[0]=2;o>i;i++)r=n&&n[i]||0,s[i+1]=t[i]-r+256&255;return s},h=function(t,e,n){var r,s,i=[],o=0,a=t.length;for(i[0]=3;a>o;o++)r=t[o-e]||0,s=n&&n[o]||0,i[o+1]=t[o]+256-(r+s>>>1)&255;return i},p=function(t,e,n){var r,s,i,o,a=[],u=0,c=t.length;for(a[0]=4;c>u;u++)r=t[u-e]||0,s=n&&n[u]||0,i=n&&n[u-e]||0,o=m(r,s,i),a[u+1]=t[u]-o+256&255;return a},m=function(t,e,n){var r=t+e-n,s=Math.abs(r-t),i=Math.abs(r-e),o=Math.abs(r-n);return i>=s&&o>=s?t:o>=i?e:n},w=function(){return[l,f,d,h,p]},g=function(t){for(var e,n,r,s=0,i=t.length;i>s;)e=y(t[s].slice(1)),(n>e||!n)&&(n=e,r=s),s++;return r},y=function(t){for(var e=0,n=t.length,r=0;n>e;)r+=Math.abs(t[e++]);return r};t.processPNG=function(t,r,s,o){var a,u,c,l,f,d,h=this.color_spaces.DEVICE_RGB,p=this.decode.FLATE_DECODE,m=8;if(this.isArrayBuffer(t)&&(t=new Uint8Array(t)),this.isArrayBufferView(t)){if(e())throw new Error("PNG support requires png.js and zlib.js");if(a=new PNG(t),t=a.imgData,m=a.bits,h=a.colorSpace,l=a.colors,-1!==[4,6].indexOf(a.colorType)){if(8===a.bits)for(var w,g,y=window["Uint"+a.pixelBitlength+"Array"],v=new y(a.decodePixels().buffer),b=v.length,q=new Uint8Array(b*a.colors),x=new Uint8Array(b),k=a.pixelBitlength-a.bits,_=0,A=0;b>_;_++){for(w=v[_],g=0;k>g;)q[A++]=w>>>g&255,g+=a.bits;x[_]=w>>>g&255}if(16===a.bits){for(var w,v=new Uint32Array(a.decodePixels().buffer),b=v.length,q=new Uint8Array(b*(32/a.pixelBitlength)*a.colors),x=new Uint8Array(b*(32/a.pixelBitlength)),C=a.colors>1,_=0,A=0,S=0;b>_;)w=v[_++],q[A++]=w>>>0&255,C&&(q[A++]=w>>>16&255,w=v[_++],q[A++]=w>>>0&255),x[S++]=w>>>16&255;m=8}n(o)?(t=i(q,a.width*a.colors,a.colors,o),d=i(x,a.width,1,o)):(t=q,d=x,p=null)}if(3===a.colorType&&(h=this.color_spaces.INDEXED,f=a.palette,a.transparency.indexed)){for(var E=a.transparency.indexed,z=0,_=0,b=E.length;b>_;++_)z+=E[_];if(z/=255,z===b-1&&-1!==E.indexOf(0))c=[E.indexOf(0)];else if(z!==b){for(var v=a.decodePixels(),x=new Uint8Array(v.length),_=0,b=v.length;b>_;_++)x[_]=E[v[_]];d=i(x,a.width,1)}}return u=p===this.decode.FLATE_DECODE?"/Predictor 15 /Colors "+l+" /BitsPerComponent "+m+" /Columns "+a.width:"/Colors "+l+" /BitsPerComponent "+m+" /Columns "+a.width,(this.isArrayBuffer(t)||this.isArrayBufferView(t))&&(t=this.arrayBufferToBinaryString(t)),(d&&this.isArrayBuffer(d)||this.isArrayBufferView(d))&&(d=this.arrayBufferToBinaryString(d)),this.createImageInfo(t,a.width,a.height,h,m,p,r,s,u,c,f,d)}throw new Error("Unsupported PNG image data, try using JPEG instead.")}}(n.API),function(t){"use strict";t.addSVG=function(t,e,n,r,s){function i(t,e){var n=e.createElement("style");n.type="text/css",n.styleSheet?n.styleSheet.cssText=t:n.appendChild(e.createTextNode(t)),e.getElementsByTagName("head")[0].appendChild(n)}function o(t){var e="childframe",n=t.createElement("iframe");return i(".jsPDF_sillysvg_iframe {display:none;position:absolute;}",t),n.name=e,n.setAttribute("width",0),n.setAttribute("height",0),n.setAttribute("frameborder","0"),n.setAttribute("scrolling","no"),n.setAttribute("seamless","seamless"),n.setAttribute("class","jsPDF_sillysvg_iframe"),t.body.appendChild(n),n}function a(t,e){var n=(e.contentWindow||e.contentDocument).document;return n.write(t),n.close(),n.getElementsByTagName("svg")[0]}function u(t){for(var e=parseFloat(t[1]),n=parseFloat(t[2]),r=[],s=3,i=t.length;i>s;)"c"===t[s]?(r.push([parseFloat(t[s+1]),parseFloat(t[s+2]),parseFloat(t[s+3]),parseFloat(t[s+4]),parseFloat(t[s+5]),parseFloat(t[s+6])]),s+=7):"l"===t[s]?(r.push([parseFloat(t[s+1]),parseFloat(t[s+2])]),s+=3):s+=1;return[e,n,r]}var c;if(e===c||n===c)throw new Error("addSVG needs values for 'x' and 'y'");var l=o(document),f=a(t,l),d=[1,1],h=parseFloat(f.getAttribute("width")),p=parseFloat(f.getAttribute("height"));h&&p&&(r&&s?d=[r/h,s/p]:r?d=[r/h,r/h]:s&&(d=[s/p,s/p]));var m,w,g,y,v=f.childNodes;for(m=0,w=v.length;w>m;m++)g=v[m],g.tagName&&"PATH"===g.tagName.toUpperCase()&&(y=u(g.getAttribute("d").split(" ")),y[0]=y[0]*d[0]+e,y[1]=y[1]*d[1]+n,this.lines.call(this,y[2],y[0],y[1],d));return this}}(n.API),function(t){"use strict";var e=t.getCharWidthsArray=function(t,e){e||(e={});var n,r,s,i=e.widths?e.widths:this.internal.getFont().metadata.Unicode.widths,o=i.fof?i.fof:1,a=e.kerning?e.kerning:this.internal.getFont().metadata.Unicode.kerning,u=a.fof?a.fof:1,c=0,l=i[0]||o,f=[];for(n=0,r=t.length;r>n;n++)s=t.charCodeAt(n),f.push((i[s]||l)/o+(a[s]&&a[s][c]||0)/u),c=s;return f},n=function(t){for(var e=t.length,n=0;e;)e--,n+=t[e];return n},r=t.getStringUnitWidth=function(t,r){return n(e.call(this,t,r))},s=function(t,e,n,r){for(var s=[],i=0,o=t.length,a=0;i!==o&&a+e[i]<n;)a+=e[i],i++;s.push(t.slice(0,i));var u=i;for(a=0;i!==o;)a+e[i]>r&&(s.push(t.slice(u,i)),a=0,u=i),a+=e[i],i++;return u!==i&&s.push(t.slice(u,i)),s},i=function(t,i,o){o||(o={});var a,u,c,l,f,d,h=[],p=[h],m=o.textIndent||0,w=0,g=0,y=t.split(" "),v=e(" ",o)[0];if(d=-1===o.lineIndent?y[0].length+2:o.lineIndent||0){var b=Array(d).join(" "),q=[];y.map(function(t){t=t.split(/\s*\n/),t.length>1?q=q.concat(t.map(function(t,e){return(e&&t.length?"\n":"")+t})):q.push(t[0])}),y=q,d=r(b,o)}for(c=0,l=y.length;l>c;c++){var x=0;if(a=y[c],d&&"\n"==a[0]&&(a=a.substr(1),x=1),u=e(a,o),g=n(u),m+w+g>i||x){if(g>i){for(f=s(a,u,i-(m+w),i),h.push(f.shift()),h=[f.pop()];f.length;)p.push([f.shift()]);g=n(u.slice(a.length-h[0].length))}else h=[a];p.push(h),m=g+d,w=v}else h.push(a),m+=w+g,w=v}if(d)var k=function(t,e){return(e?b:"")+t.join(" ")};else var k=function(t){return t.join(" ")};return p.map(k)};t.splitTextToSize=function(t,e,n){n||(n={});var r,s=n.fontSize||this.internal.getFontSize(),o=function(t){var e={0:1},n={};if(t.widths&&t.kerning)return{widths:t.widths,kerning:t.kerning};var r=this.internal.getFont(t.fontName,t.fontStyle),s="Unicode";return r.metadata[s]?{widths:r.metadata[s].widths||e,kerning:r.metadata[s].kerning||n}:{widths:e,kerning:n}}.call(this,n);r=Array.isArray(t)?t:t.split(/\r?\n/);var a=1*this.internal.scaleFactor*e/s;o.textIndent=n.textIndent?1*n.textIndent*this.internal.scaleFactor/s:0,o.lineIndent=n.lineIndent;var u,c,l=[];for(u=0,c=r.length;c>u;u++)l=l.concat(i(r[u],a,o));return l}}(n.API),function(t){"use strict";var e=function(t){for(var e="0123456789abcdef",n="klmnopqrstuvwxyz",r={},s=0;s<n.length;s++)r[n[s]]=e[s];var i,o,a,u,c,l={},f=1,d=l,h=[],p="",m="",w=t.length-1;for(s=1;s!=w;)c=t[s],s+=1,"'"==c?o?(u=o.join(""),o=i):o=[]:o?o.push(c):"{"==c?(h.push([d,u]),d={},u=i):"}"==c?(a=h.pop(),a[0][a[1]]=d,u=i,d=a[0]):"-"==c?f=-1:u===i?r.hasOwnProperty(c)?(p+=r[c],u=parseInt(p,16)*f,f=1,p=""):p+=c:r.hasOwnProperty(c)?(m+=r[c],d[u]=parseInt(m,16)*f,f=1,u=i,m=""):m+=c;return l},n={codePages:["WinAnsiEncoding"],WinAnsiEncoding:e("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")},r={Unicode:{Courier:n,"Courier-Bold":n,"Courier-BoldOblique":n,"Courier-Oblique":n,Helvetica:n,"Helvetica-Bold":n,"Helvetica-BoldOblique":n,"Helvetica-Oblique":n,"Times-Roman":n,"Times-Bold":n,"Times-BoldItalic":n,"Times-Italic":n}},s={Unicode:{"Courier-Oblique":e("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),"Times-BoldItalic":e("{'widths'{k3o2q4ycx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2r202m2n2n3m2o3m2p5n202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5n4l4m4m4m4n4m4o4s4p4m4q4m4r4s4s4y4t2r4u3m4v4m4w3x4x5t4y4s4z4s5k3x5l4s5m4m5n3r5o3x5p4s5q4m5r5t5s4m5t3x5u3x5v2l5w1w5x2l5y3t5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q2l6r3m6s3r6t1w6u1w6v3m6w1w6x4y6y3r6z3m7k3m7l3m7m2r7n2r7o1w7p3r7q2w7r4m7s3m7t2w7u2r7v2n7w1q7x2n7y3t202l3mcl4mal2ram3man3mao3map3mar3mas2lat4uau1uav3maw3way4uaz2lbk2sbl3t'fof'6obo2lbp3tbq3mbr1tbs2lbu1ybv3mbz3mck4m202k3mcm4mcn4mco4mcp4mcq5ycr4mcs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz2w203k6o212m6o2dw2l2cq2l3t3m3u2l17s3x19m3m}'kerning'{cl{4qu5kt5qt5rs17ss5ts}201s{201ss}201t{cks4lscmscnscoscpscls2wu2yu201ts}201x{2wu2yu}2k{201ts}2w{4qx5kx5ou5qx5rs17su5tu}2x{17su5tu5ou}2y{4qx5kx5ou5qx5rs17ss5ts}'fof'-6ofn{17sw5tw5ou5qw5rs}7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qs}3v{17su5tu5os5qs}7p{17su5tu}ck{4qu5kt5qt5rs17ss5ts}4l{4qu5kt5qt5rs17ss5ts}cm{4qu5kt5qt5rs17ss5ts}cn{4qu5kt5qt5rs17ss5ts}co{4qu5kt5qt5rs17ss5ts}cp{4qu5kt5qt5rs17ss5ts}6l{4qu5ou5qw5rt17su5tu}5q{ckuclucmucnucoucpu4lu}5r{ckuclucmucnucoucpu4lu}7q{cksclscmscnscoscps4ls}6p{4qu5ou5qw5rt17sw5tw}ek{4qu5ou5qw5rt17su5tu}el{4qu5ou5qw5rt17su5tu}em{4qu5ou5qw5rt17su5tu}en{4qu5ou5qw5rt17su5tu}eo{4qu5ou5qw5rt17su5tu}ep{4qu5ou5qw5rt17su5tu}es{17ss5ts5qs4qu}et{4qu5ou5qw5rt17sw5tw}eu{4qu5ou5qw5rt17ss5ts}ev{17ss5ts5qs4qu}6z{17sw5tw5ou5qw5rs}fm{17sw5tw5ou5qw5rs}7n{201ts}fo{17sw5tw5ou5qw5rs}fp{17sw5tw5ou5qw5rs}fq{17sw5tw5ou5qw5rs}7r{cksclscmscnscoscps4ls}fs{17sw5tw5ou5qw5rs}ft{17su5tu}fu{17su5tu}fv{17su5tu}fw{17su5tu}fz{cksclscmscnscoscps4ls}}}"),"Helvetica-Bold":e("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"),Courier:e("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),"Courier-BoldOblique":e("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),"Times-Bold":e("{'widths'{k3q2q5ncx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2l202m2n2n3m2o3m2p6o202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5x4l4s4m4m4n4s4o4s4p4m4q3x4r4y4s4y4t2r4u3m4v4y4w4m4x5y4y4s4z4y5k3x5l4y5m4s5n3r5o4m5p4s5q4s5r6o5s4s5t4s5u4m5v2l5w1w5x2l5y3u5z3m6k2l6l3m6m3r6n2w6o3r6p2w6q2l6r3m6s3r6t1w6u2l6v3r6w1w6x5n6y3r6z3m7k3r7l3r7m2w7n2r7o2l7p3r7q3m7r4s7s3m7t3m7u2w7v2r7w1q7x2r7y3o202l3mcl4sal2lam3man3mao3map3mar3mas2lat4uau1yav3maw3tay4uaz2lbk2sbl3t'fof'6obo2lbp3rbr1tbs2lbu2lbv3mbz3mck4s202k3mcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3rek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3m3u2l17s4s19m3m}'kerning'{cl{4qt5ks5ot5qy5rw17sv5tv}201t{cks4lscmscnscoscpscls4wv}2k{201ts}2w{4qu5ku7mu5os5qx5ru17su5tu}2x{17su5tu5ou5qs}2y{4qv5kv7mu5ot5qz5ru17su5tu}'fof'-6o7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qu}3v{17su5tu5os5qu}fu{17su5tu5ou5qu}7p{17su5tu5ou5qu}ck{4qt5ks5ot5qy5rw17sv5tv}4l{4qt5ks5ot5qy5rw17sv5tv}cm{4qt5ks5ot5qy5rw17sv5tv}cn{4qt5ks5ot5qy5rw17sv5tv}co{4qt5ks5ot5qy5rw17sv5tv}cp{4qt5ks5ot5qy5rw17sv5tv}6l{17st5tt5ou5qu}17s{ckuclucmucnucoucpu4lu4wu}5o{ckuclucmucnucoucpu4lu4wu}5q{ckzclzcmzcnzcozcpz4lz4wu}5r{ckxclxcmxcnxcoxcpx4lx4wu}5t{ckuclucmucnucoucpu4lu4wu}7q{ckuclucmucnucoucpu4lu}6p{17sw5tw5ou5qu}ek{17st5tt5qu}el{17st5tt5ou5qu}em{17st5tt5qu}en{17st5tt5qu}eo{17st5tt5qu}ep{17st5tt5ou5qu}es{17ss5ts5qu}et{17sw5tw5ou5qu}eu{17sw5tw5ou5qu}ev{17ss5ts5qu}6z{17sw5tw5ou5qu5rs}fm{17sw5tw5ou5qu5rs}fn{17sw5tw5ou5qu5rs}fo{17sw5tw5ou5qu5rs}fp{17sw5tw5ou5qu5rs}fq{17sw5tw5ou5qu5rs}7r{cktcltcmtcntcotcpt4lt5os}fs{17sw5tw5ou5qu5rs}ft{17su5tu5ou5qu}7m{5os}fv{17su5tu5ou5qu}fw{17su5tu5ou5qu}fz{cksclscmscnscoscps4ls}}}"),Helvetica:e("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}"),"Helvetica-BoldOblique":e("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"),"Courier-Bold":e("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),"Times-Italic":e("{'widths'{k3n2q4ycx2l201n3m201o5t201s2l201t2l201u2l201w3r201x3r201y3r2k1t2l2l202m2n2n3m2o3m2p5n202q5t2r1p2s2l2t2l2u3m2v4n2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w4n3x4n3y4n3z3m4k5w4l3x4m3x4n4m4o4s4p3x4q3x4r4s4s4s4t2l4u2w4v4m4w3r4x5n4y4m4z4s5k3x5l4s5m3x5n3m5o3r5p4s5q3x5r5n5s3x5t3r5u3r5v2r5w1w5x2r5y2u5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q1w6r3m6s3m6t1w6u1w6v2w6w1w6x4s6y3m6z3m7k3m7l3m7m2r7n2r7o1w7p3m7q2w7r4m7s2w7t2w7u2r7v2s7w1v7x2s7y3q202l3mcl3xal2ram3man3mao3map3mar3mas2lat4wau1vav3maw4nay4waz2lbk2sbl4n'fof'6obo2lbp3mbq3obr1tbs2lbu1zbv3mbz3mck3x202k3mcm3xcn3xco3xcp3xcq5tcr4mcs3xct3xcu3xcv3xcw2l2m2ucy2lcz2ldl4mdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr4nfs3mft3mfu3mfv3mfw3mfz2w203k6o212m6m2dw2l2cq2l3t3m3u2l17s3r19m3m}'kerning'{cl{5kt4qw}201s{201sw}201t{201tw2wy2yy6q-t}201x{2wy2yy}2k{201tw}2w{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}2x{17ss5ts5os}2y{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}'fof'-6o6t{17ss5ts5qs}7t{5os}3v{5qs}7p{17su5tu5qs}ck{5kt4qw}4l{5kt4qw}cm{5kt4qw}cn{5kt4qw}co{5kt4qw}cp{5kt4qw}6l{4qs5ks5ou5qw5ru17su5tu}17s{2ks}5q{ckvclvcmvcnvcovcpv4lv}5r{ckuclucmucnucoucpu4lu}5t{2ks}6p{4qs5ks5ou5qw5ru17su5tu}ek{4qs5ks5ou5qw5ru17su5tu}el{4qs5ks5ou5qw5ru17su5tu}em{4qs5ks5ou5qw5ru17su5tu}en{4qs5ks5ou5qw5ru17su5tu}eo{4qs5ks5ou5qw5ru17su5tu}ep{4qs5ks5ou5qw5ru17su5tu}es{5ks5qs4qs}et{4qs5ks5ou5qw5ru17su5tu}eu{4qs5ks5qw5ru17su5tu}ev{5ks5qs4qs}ex{17ss5ts5qs}6z{4qv5ks5ou5qw5ru17su5tu}fm{4qv5ks5ou5qw5ru17su5tu}fn{4qv5ks5ou5qw5ru17su5tu}fo{4qv5ks5ou5qw5ru17su5tu}fp{4qv5ks5ou5qw5ru17su5tu}fq{4qv5ks5ou5qw5ru17su5tu}7r{5os}fs{4qv5ks5ou5qw5ru17su5tu}ft{17su5tu5qs}fu{17su5tu5qs}fv{17su5tu5qs}fw{17su5tu5qs}}}"),"Times-Roman":e("{'widths'{k3n2q4ycx2l201n3m201o6o201s2l201t2l201u2l201w2w201x2w201y2w2k1t2l2l202m2n2n3m2o3m2p5n202q6o2r1m2s2l2t2l2u3m2v3s2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v1w3w3s3x3s3y3s3z2w4k5w4l4s4m4m4n4m4o4s4p3x4q3r4r4s4s4s4t2l4u2r4v4s4w3x4x5t4y4s4z4s5k3r5l4s5m4m5n3r5o3x5p4s5q4s5r5y5s4s5t4s5u3x5v2l5w1w5x2l5y2z5z3m6k2l6l2w6m3m6n2w6o3m6p2w6q2l6r3m6s3m6t1w6u1w6v3m6w1w6x4y6y3m6z3m7k3m7l3m7m2l7n2r7o1w7p3m7q3m7r4s7s3m7t3m7u2w7v3k7w1o7x3k7y3q202l3mcl4sal2lam3man3mao3map3mar3mas2lat4wau1vav3maw3say4waz2lbk2sbl3s'fof'6obo2lbp3mbq2xbr1tbs2lbu1zbv3mbz2wck4s202k3mcm4scn4sco4scp4scq5tcr4mcs3xct3xcu3xcv3xcw2l2m2tcy2lcz2ldl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek2wel2wem2wen2weo2wep2weq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr3sfs3mft3mfu3mfv3mfw3mfz3m203k6o212m6m2dw2l2cq2l3t3m3u1w17s4s19m3m}'kerning'{cl{4qs5ku17sw5ou5qy5rw201ss5tw201ws}201s{201ss}201t{ckw4lwcmwcnwcowcpwclw4wu201ts}2k{201ts}2w{4qs5kw5os5qx5ru17sx5tx}2x{17sw5tw5ou5qu}2y{4qs5kw5os5qx5ru17sx5tx}'fof'-6o7t{ckuclucmucnucoucpu4lu5os5rs}3u{17su5tu5qs}3v{17su5tu5qs}7p{17sw5tw5qs}ck{4qs5ku17sw5ou5qy5rw201ss5tw201ws}4l{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cm{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cn{4qs5ku17sw5ou5qy5rw201ss5tw201ws}co{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cp{4qs5ku17sw5ou5qy5rw201ss5tw201ws}6l{17su5tu5os5qw5rs}17s{2ktclvcmvcnvcovcpv4lv4wuckv}5o{ckwclwcmwcnwcowcpw4lw4wu}5q{ckyclycmycnycoycpy4ly4wu5ms}5r{cktcltcmtcntcotcpt4lt4ws}5t{2ktclvcmvcnvcovcpv4lv4wuckv}7q{cksclscmscnscoscps4ls}6p{17su5tu5qw5rs}ek{5qs5rs}el{17su5tu5os5qw5rs}em{17su5tu5os5qs5rs}en{17su5qs5rs}eo{5qs5rs}ep{17su5tu5os5qw5rs}es{5qs}et{17su5tu5qw5rs}eu{17su5tu5qs5rs}ev{5qs}6z{17sv5tv5os5qx5rs}fm{5os5qt5rs}fn{17sv5tv5os5qx5rs}fo{17sv5tv5os5qx5rs}fp{5os5qt5rs}fq{5os5qt5rs}7r{ckuclucmucnucoucpu4lu5os}fs{17sv5tv5os5qx5rs}ft{17ss5ts5qs}fu{17sw5tw5qs}fv{17sw5tw5qs}fw{17ss5ts5qs}fz{ckuclucmucnucoucpu4lu5os5rs}}}"),"Helvetica-Oblique":e("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}")}};
+t.events.push(["addFonts",function(t){var e,n,i,o,a,u="Unicode";for(n in t.fonts)t.fonts.hasOwnProperty(n)&&(e=t.fonts[n],i=s[u][e.PostScriptName],i&&(o=e.metadata[u]?e.metadata[u]:e.metadata[u]={},o.widths=i.widths,o.kerning=i.kerning),a=r[u][e.PostScriptName],a&&(o=e.metadata[u]?e.metadata[u]:e.metadata[u]={},o.encoding=a,a.codePages&&a.codePages.length&&(e.encoding=a.codePages[0])))}])}(n.API),function(t){"use strict";t.putTotalPages=function(t){for(var e=new RegExp(t,"g"),n=1;n<=this.internal.getNumberOfPages();n++)for(var r=0;r<this.internal.pages[n].length;r++)this.internal.pages[n][r]=this.internal.pages[n][r].replace(e,this.internal.getNumberOfPages());return this}}(n.API),function(t){"use strict";if(t.URL=t.URL||t.webkitURL,t.Blob&&t.URL)try{return void new Blob}catch(e){}var n=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||function(t){var e=function(t){return Object.prototype.toString.call(t).match(/^\[object\s(.*)\]$/)[1]},n=function(){this.data=[]},r=function(t,e,n){this.data=t,this.size=t.length,this.type=e,this.encoding=n},s=n.prototype,i=r.prototype,o=t.FileReaderSync,a=function(t){this.code=this[this.name=t]},u="NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR".split(" "),c=u.length,l=t.URL||t.webkitURL||t,f=l.createObjectURL,d=l.revokeObjectURL,h=l,p=t.btoa,m=t.atob,w=t.ArrayBuffer,g=t.Uint8Array,y=/^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/;for(r.fake=i.fake=!0;c--;)a.prototype[u[c]]=c+1;return l.createObjectURL||(h=t.URL=function(t){var e,n=document.createElementNS("http://www.w3.org/1999/xhtml","a");return n.href=t,"origin"in n||("data:"===n.protocol.toLowerCase()?n.origin=null:(e=t.match(y),n.origin=e&&e[1])),n}),h.createObjectURL=function(t){var e,n=t.type;return null===n&&(n="application/octet-stream"),t instanceof r?(e="data:"+n,"base64"===t.encoding?e+";base64,"+t.data:"URI"===t.encoding?e+","+decodeURIComponent(t.data):p?e+";base64,"+p(t.data):e+","+encodeURIComponent(t.data)):f?f.call(l,t):void 0},h.revokeObjectURL=function(t){"data:"!==t.substring(0,5)&&d&&d.call(l,t)},s.append=function(t){var n=this.data;if(g&&(t instanceof w||t instanceof g)){for(var s="",i=new g(t),u=0,c=i.length;c>u;u++)s+=String.fromCharCode(i[u]);n.push(s)}else if("Blob"===e(t)||"File"===e(t)){if(!o)throw new a("NOT_READABLE_ERR");var l=new o;n.push(l.readAsBinaryString(t))}else t instanceof r?"base64"===t.encoding&&m?n.push(m(t.data)):"URI"===t.encoding?n.push(decodeURIComponent(t.data)):"raw"===t.encoding&&n.push(t.data):("string"!=typeof t&&(t+=""),n.push(unescape(encodeURIComponent(t))))},s.getBlob=function(t){return arguments.length||(t=null),new r(this.data.join(""),t,"raw")},s.toString=function(){return"[object BlobBuilder]"},i.slice=function(t,e,n){var s=arguments.length;return 3>s&&(n=null),new r(this.data.slice(t,s>1?e:this.data.length),n,this.encoding)},i.toString=function(){return"[object Blob]"},i.close=function(){this.size=0,delete this.data},n}(t);t.Blob=function(t,e){var r=e?e.type||"":"",s=new n;if(t)for(var i=0,o=t.length;o>i;i++)s.append(t[i]);return s.getBlob(r)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content||this);var r=r||"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob&&navigator.msSaveOrOpenBlob.bind(navigator)||function(t){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var e=t.document,n=function(){return t.URL||t.webkitURL||t},r=e.createElementNS("http://www.w3.org/1999/xhtml","a"),s="download"in r,i=function(n){var r=e.createEvent("MouseEvents");r.initMouseEvent("click",!0,!1,t,0,0,0,0,0,!1,!1,!1,!1,0,null),n.dispatchEvent(r)},o=t.webkitRequestFileSystem,a=t.requestFileSystem||o||t.mozRequestFileSystem,u=function(e){(t.setImmediate||t.setTimeout)(function(){throw e},0)},c="application/octet-stream",l=0,f=10,d=function(e){var r=function(){"string"==typeof e?n().revokeObjectURL(e):e.remove()};t.chrome?r():setTimeout(r,f)},h=function(t,e,n){e=[].concat(e);for(var r=e.length;r--;){var s=t["on"+e[r]];if("function"==typeof s)try{s.call(t,n||t)}catch(i){u(i)}}},p=function(e,u){var f,p,m,w=this,g=e.type,y=!1,v=function(){h(w,"writestart progress write writeend".split(" "))},b=function(){if((y||!f)&&(f=n().createObjectURL(e)),p)p.location.href=f;else{var r=t.open(f,"_blank");void 0==r&&"undefined"!=typeof safari&&(t.location.href=f)}w.readyState=w.DONE,v(),d(f)},q=function(t){return function(){return w.readyState!==w.DONE?t.apply(this,arguments):void 0}},x={create:!0,exclusive:!1};return w.readyState=w.INIT,u||(u="download"),s?(f=n().createObjectURL(e),r.href=f,r.download=u,i(r),w.readyState=w.DONE,v(),void d(f)):(t.chrome&&g&&g!==c&&(m=e.slice||e.webkitSlice,e=m.call(e,0,e.size,c),y=!0),o&&"download"!==u&&(u+=".download"),(g===c||o)&&(p=t),a?(l+=e.size,void a(t.TEMPORARY,l,q(function(t){t.root.getDirectory("saved",x,q(function(t){var n=function(){t.getFile(u,x,q(function(t){t.createWriter(q(function(n){n.onwriteend=function(e){p.location.href=t.toURL(),w.readyState=w.DONE,h(w,"writeend",e),d(t)},n.onerror=function(){var t=n.error;t.code!==t.ABORT_ERR&&b()},"writestart progress write abort".split(" ").forEach(function(t){n["on"+t]=w["on"+t]}),n.write(e),w.abort=function(){n.abort(),w.readyState=w.DONE},w.readyState=w.WRITING}),b)}),b)};t.getFile(u,{create:!1},q(function(t){t.remove(),n()}),q(function(t){t.code===t.NOT_FOUND_ERR?n():b()}))}),b)}),b)):void b())},m=p.prototype,w=function(t,e){return new p(t,e)};return m.abort=function(){var t=this;t.readyState=t.DONE,h(t,"abort")},m.readyState=m.INIT=0,m.WRITING=1,m.DONE=2,m.error=m.onwritestart=m.onprogress=m.onwrite=m.onabort=m.onerror=m.onwriteend=null,w}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&null!==module&&(module.exports=r),void function(t,e){"object"==typeof module?module.exports=e():t.adler32cs=e()}(n,function(){var t="function"==typeof ArrayBuffer&&"function"==typeof Uint8Array,e=null,n=function(){if(!t)return function(){return!1};try{var n=require("buffer");"function"==typeof n.Buffer&&(e=n.Buffer)}catch(r){}return function(t){return t instanceof ArrayBuffer||null!==e&&t instanceof e}}(),r=function(){return null!==e?function(t){return new e(t,"utf8").toString("binary")}:function(t){return unescape(encodeURIComponent(t))}}(),s=65521,i=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;o>i;i++)n=(n+(255&e.charCodeAt(i)))%s,r=(r+n)%s;return(r<<16|n)>>>0},o=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;o>i;i++)n=(n+e[i])%s,r=(r+n)%s;return(r<<16|n)>>>0},a={},u=a.Adler32=function(){var e=function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(!isFinite(t=null==t?1:+t))throw new Error("First arguments needs to be a finite number.");this.checksum=t>>>0},s=e.prototype={};return s.constructor=e,e.from=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");this.checksum=i(1,t.toString())}),e.fromUtf8=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");var n=r(t.toString());this.checksum=i(1,n)}),t&&(e.fromBuffer=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(!n(t))throw new Error("First argument needs to be ArrayBuffer.");var r=new Uint8Array(t);return this.checksum=o(1,r)})),s.update=function(t){if(null==t)throw new Error("First argument needs to be a string.");return t=t.toString(),this.checksum=i(this.checksum,t)},s.updateUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=r(t.toString());return this.checksum=i(this.checksum,e)},t&&(s.updateBuffer=function(t){if(!n(t))throw new Error("First argument needs to be ArrayBuffer.");var e=new Uint8Array(t);return this.checksum=o(this.checksum,e)}),s.clone=function(){return new u(this.checksum)},e}();return a.from=function(t){if(null==t)throw new Error("First argument needs to be a string.");return i(1,t.toString())},a.fromUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=r(t.toString());return i(1,e)},t&&(a.fromBuffer=function(t){if(!n(t))throw new Error("First argument need to be ArrayBuffer.");var e=new Uint8Array(t);return o(1,e)}),a});var s=function(){function t(){function t(t){var e,n,s,i,a,u,c=r.dyn_tree,l=r.stat_desc.static_tree,f=r.stat_desc.extra_bits,h=r.stat_desc.extra_base,p=r.stat_desc.max_length,m=0;for(i=0;o>=i;i++)t.bl_count[i]=0;for(c[2*t.heap[t.heap_max]+1]=0,e=t.heap_max+1;d>e;e++)n=t.heap[e],i=c[2*c[2*n+1]+1]+1,i>p&&(i=p,m++),c[2*n+1]=i,n>r.max_code||(t.bl_count[i]++,a=0,n>=h&&(a=f[n-h]),u=c[2*n],t.opt_len+=u*(i+a),l&&(t.static_len+=u*(l[2*n+1]+a)));if(0!==m){do{for(i=p-1;0===t.bl_count[i];)i--;t.bl_count[i]--,t.bl_count[i+1]+=2,t.bl_count[p]--,m-=2}while(m>0);for(i=p;0!==i;i--)for(n=t.bl_count[i];0!==n;)s=t.heap[--e],s>r.max_code||(c[2*s+1]!=i&&(t.opt_len+=(i-c[2*s+1])*c[2*s],c[2*s+1]=i),n--)}}function e(t,e){var n=0;do n|=1&t,t>>>=1,n<<=1;while(--e>0);return n>>>1}function n(t,n,r){var s,i,a,u=[],c=0;for(s=1;o>=s;s++)u[s]=c=c+r[s-1]<<1;for(i=0;n>=i;i++)a=t[2*i+1],0!==a&&(t[2*i]=e(u[a]++,a))}var r=this;r.build_tree=function(e){var s,i,o,a=r.dyn_tree,u=r.stat_desc.static_tree,c=r.stat_desc.elems,l=-1;for(e.heap_len=0,e.heap_max=d,s=0;c>s;s++)0!==a[2*s]?(e.heap[++e.heap_len]=l=s,e.depth[s]=0):a[2*s+1]=0;for(;e.heap_len<2;)o=e.heap[++e.heap_len]=2>l?++l:0,a[2*o]=1,e.depth[o]=0,e.opt_len--,u&&(e.static_len-=u[2*o+1]);for(r.max_code=l,s=Math.floor(e.heap_len/2);s>=1;s--)e.pqdownheap(a,s);o=c;do s=e.heap[1],e.heap[1]=e.heap[e.heap_len--],e.pqdownheap(a,1),i=e.heap[1],e.heap[--e.heap_max]=s,e.heap[--e.heap_max]=i,a[2*o]=a[2*s]+a[2*i],e.depth[o]=Math.max(e.depth[s],e.depth[i])+1,a[2*s+1]=a[2*i+1]=o,e.heap[1]=o++,e.pqdownheap(a,1);while(e.heap_len>=2);e.heap[--e.heap_max]=e.heap[1],t(e),n(a,r.max_code,e.bl_count)}}function e(t,e,n,r,s){var i=this;i.static_tree=t,i.extra_bits=e,i.extra_base=n,i.elems=r,i.max_length=s}function n(t,e,n,r,s){var i=this;i.good_length=t,i.max_lazy=e,i.nice_length=n,i.max_chain=r,i.func=s}function r(t,e,n,r){var s=t[2*e],i=t[2*n];return i>s||s==i&&r[e]<=r[n]}function s(){function n(){var t;for(Te=2*Ce,Be[Pe-1]=0,t=0;Pe-1>t;t++)Be[t]=0;Je=N[Xe].max_lazy,Ke=N[Xe].good_length,Qe=N[Xe].nice_length,Ve=N[Xe].max_chain,Me=0,Ue=0,Ge=0,Ne=We=Z-1,je=0,Oe=0}function s(){var t;for(t=0;f>t;t++)$e[2*t]=0;for(t=0;a>t;t++)Ze[2*t]=0;for(t=0;u>t;t++)tn[2*t]=0;$e[2*h]=1,en.opt_len=en.static_len=0,un=ln=0}function i(){nn.dyn_tree=$e,nn.stat_desc=e.static_l_desc,rn.dyn_tree=Ze,rn.stat_desc=e.static_d_desc,sn.dyn_tree=tn,sn.stat_desc=e.static_bl_desc,dn=0,hn=0,fn=8,s()}function o(t,e){var n,r,s=-1,i=t[1],o=0,a=7,u=4;for(0===i&&(a=138,u=3),t[2*(e+1)+1]=65535,n=0;e>=n;n++)r=i,i=t[2*(n+1)+1],++o<a&&r==i||(u>o?tn[2*r]+=o:0!==r?(r!=s&&tn[2*r]++,tn[2*m]++):10>=o?tn[2*w]++:tn[2*g]++,o=0,s=r,0===i?(a=138,u=3):r==i?(a=6,u=3):(a=7,u=4))}function c(){var e;for(o($e,nn.max_code),o(Ze,rn.max_code),sn.build_tree(en),e=u-1;e>=3&&0===tn[2*t.bl_order[e]+1];e--);return en.opt_len+=3*(e+1)+5+5+4,e}function d(t){en.pending_buf[en.pending++]=t}function p(t){d(255&t),d(t>>>8&255)}function O(t){d(t>>8&255),d(255&t&255)}function ne(t,e){var n,r=e;hn>y-r?(n=t,dn|=n<<hn&65535,p(dn),dn=n>>>y-hn,hn+=r-y):(dn|=t<<hn&65535,hn+=r)}function re(t,e){var n=2*t;ne(65535&e[n],65535&e[n+1])}function se(t,e){var n,r,s=-1,i=t[1],o=0,a=7,u=4;for(0===i&&(a=138,u=3),n=0;e>=n;n++)if(r=i,i=t[2*(n+1)+1],!(++o<a&&r==i)){if(u>o){do re(r,tn);while(0!==--o)}else 0!==r?(r!=s&&(re(r,tn),o--),re(m,tn),ne(o-3,2)):10>=o?(re(w,tn),ne(o-3,3)):(re(g,tn),ne(o-11,7));o=0,s=r,0===i?(a=138,u=3):r==i?(a=6,u=3):(a=7,u=4)}}function ie(e,n,r){var s;for(ne(e-257,5),ne(n-1,5),ne(r-4,4),s=0;r>s;s++)ne(tn[2*t.bl_order[s]+1],3);se($e,e-1),se(Ze,n-1)}function oe(){16==hn?(p(dn),dn=0,hn=0):hn>=8&&(d(255&dn),dn>>>=8,hn-=8)}function ae(){ne(Q<<1,3),re(h,e.static_ltree),oe(),9>1+fn+10-hn&&(ne(Q<<1,3),re(h,e.static_ltree),oe()),fn=7}function ue(e,n){var r,s,i;if(en.pending_buf[cn+2*un]=e>>>8&255,en.pending_buf[cn+2*un+1]=255&e,en.pending_buf[on+un]=255&n,un++,0===e?$e[2*n]++:(ln++,e--,$e[2*(t._length_code[n]+l+1)]++,Ze[2*t.d_code(e)]++),0===(8191&un)&&Xe>2){for(r=8*un,s=Me-Ue,i=0;a>i;i++)r+=Ze[2*i]*(5+t.extra_dbits[i]);if(r>>>=3,ln<Math.floor(un/2)&&r<Math.floor(s/2))return!0}return un==an-1}function ce(e,n){var r,s,i,o,a=0;if(0!==un)do r=en.pending_buf[cn+2*a]<<8&65280|255&en.pending_buf[cn+2*a+1],s=255&en.pending_buf[on+a],a++,0===r?re(s,e):(i=t._length_code[s],re(i+l+1,e),o=t.extra_lbits[i],0!==o&&(s-=t.base_length[i],ne(s,o)),r--,i=t.d_code(r),re(i,n),o=t.extra_dbits[i],0!==o&&(r-=t.base_dist[i],ne(r,o)));while(un>a);re(h,e),fn=e[2*h+1]}function le(){hn>8?p(dn):hn>0&&d(255&dn),dn=0,hn=0}function fe(t,e,n){le(),fn=8,n&&(p(e),p(~e)),en.pending_buf.set(ze.subarray(t,t+e),en.pending),en.pending+=e}function de(t,e,n){ne((K<<1)+(n?1:0),3),fe(t,e,!0)}function he(t,n,r){var i,o,a=0;Xe>0?(nn.build_tree(en),rn.build_tree(en),a=c(),i=en.opt_len+3+7>>>3,o=en.static_len+3+7>>>3,i>=o&&(i=o)):i=o=n+5,i>=n+4&&-1!=t?de(t,n,r):o==i?(ne((Q<<1)+(r?1:0),3),ce(e.static_ltree,e.static_dtree)):(ne(($<<1)+(r?1:0),3),ie(nn.max_code+1,rn.max_code+1,a+1),ce($e,Ze)),s(),r&&le()}function pe(t){he(Ue>=0?Ue:-1,Me-Ue,t),Ue=Me,qe.flush_pending()}function me(){var t,e,n,r;do{if(r=Te-Ge-Me,0===r&&0===Me&&0===Ge)r=Ce;else if(-1==r)r--;else if(Me>=Ce+Ce-ee){ze.set(ze.subarray(Ce,Ce+Ce),0),He-=Ce,Me-=Ce,Ue-=Ce,t=Pe,n=t;do e=65535&Be[--n],Be[n]=e>=Ce?e-Ce:0;while(0!==--t);t=Ce,n=t;do e=65535&Ie[--n],Ie[n]=e>=Ce?e-Ce:0;while(0!==--t);r+=Ce}if(0===qe.avail_in)return;t=qe.read_buf(ze,Me+Ge,r),Ge+=t,Ge>=Z&&(Oe=255&ze[Me],Oe=(Oe<<De^255&ze[Me+1])&Fe)}while(ee>Ge&&0!==qe.avail_in)}function we(t){var e,n=65535;for(n>ke-5&&(n=ke-5);;){if(1>=Ge){if(me(),0===Ge&&t==k)return j;if(0===Ge)break}if(Me+=Ge,Ge=0,e=Ue+n,(0===Me||Me>=e)&&(Ge=Me-e,Me=e,pe(!1),0===qe.avail_out))return j;if(Me-Ue>=Ce-ee&&(pe(!1),0===qe.avail_out))return j}return pe(t==C),0===qe.avail_out?t==C?H:j:t==C?G:M}function ge(t){var e,n,r=Ve,s=Me,i=We,o=Me>Ce-ee?Me-(Ce-ee):0,a=Qe,u=Ee,c=Me+te,l=ze[s+i-1],f=ze[s+i];We>=Ke&&(r>>=2),a>Ge&&(a=Ge);do if(e=t,ze[e+i]==f&&ze[e+i-1]==l&&ze[e]==ze[s]&&ze[++e]==ze[s+1]){s+=2,e++;do;while(ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&c>s);if(n=te-(c-s),s=c-te,n>i){if(He=t,i=n,n>=a)break;l=ze[s+i-1],f=ze[s+i]}}while((t=65535&Ie[t&u])>o&&0!==--r);return Ge>=i?i:Ge}function ye(t){for(var e,n=0;;){if(ee>Ge){if(me(),ee>Ge&&t==k)return j;if(0===Ge)break}if(Ge>=Z&&(Oe=(Oe<<De^255&ze[Me+(Z-1)])&Fe,n=65535&Be[Oe],Ie[Me&Ee]=Be[Oe],Be[Oe]=Me),0!==n&&Ce-ee>=(Me-n&65535)&&Ye!=q&&(Ne=ge(n)),Ne>=Z)if(e=ue(Me-He,Ne-Z),Ge-=Ne,Je>=Ne&&Ge>=Z){Ne--;do Me++,Oe=(Oe<<De^255&ze[Me+(Z-1)])&Fe,n=65535&Be[Oe],Ie[Me&Ee]=Be[Oe],Be[Oe]=Me;while(0!==--Ne);Me++}else Me+=Ne,Ne=0,Oe=255&ze[Me],Oe=(Oe<<De^255&ze[Me+1])&Fe;else e=ue(0,255&ze[Me]),Ge--,Me++;if(e&&(pe(!1),0===qe.avail_out))return j}return pe(t==C),0===qe.avail_out?t==C?H:j:t==C?G:M}function ve(t){for(var e,n,r=0;;){if(ee>Ge){if(me(),ee>Ge&&t==k)return j;if(0===Ge)break}if(Ge>=Z&&(Oe=(Oe<<De^255&ze[Me+(Z-1)])&Fe,r=65535&Be[Oe],Ie[Me&Ee]=Be[Oe],Be[Oe]=Me),We=Ne,Le=He,Ne=Z-1,0!==r&&Je>We&&Ce-ee>=(Me-r&65535)&&(Ye!=q&&(Ne=ge(r)),5>=Ne&&(Ye==b||Ne==Z&&Me-He>4096)&&(Ne=Z-1)),We>=Z&&We>=Ne){n=Me+Ge-Z,e=ue(Me-1-Le,We-Z),Ge-=We-1,We-=2;do++Me<=n&&(Oe=(Oe<<De^255&ze[Me+(Z-1)])&Fe,r=65535&Be[Oe],Ie[Me&Ee]=Be[Oe],Be[Oe]=Me);while(0!==--We);if(je=0,Ne=Z-1,Me++,e&&(pe(!1),0===qe.avail_out))return j}else if(0!==je){if(e=ue(0,255&ze[Me-1]),e&&pe(!1),Me++,Ge--,0===qe.avail_out)return j}else je=1,Me++,Ge--}return 0!==je&&(e=ue(0,255&ze[Me-1]),je=0),pe(t==C),0===qe.avail_out?t==C?H:j:t==C?G:M}function be(t){return t.total_in=t.total_out=0,t.msg=null,en.pending=0,en.pending_out=0,xe=J,Ae=k,i(),n(),S}var qe,xe,ke,_e,Ae,Ce,Se,Ee,ze,Te,Ie,Be,Oe,Pe,Re,Fe,De,Ue,Ne,Le,je,Me,He,Ge,We,Ve,Je,Xe,Ye,Ke,Qe,$e,Ze,tn,en=this,nn=new t,rn=new t,sn=new t;en.depth=[];var on,an,un,cn,ln,fn,dn,hn;en.bl_count=[],en.heap=[],$e=[],Ze=[],tn=[],en.pqdownheap=function(t,e){for(var n=en.heap,s=n[e],i=e<<1;i<=en.heap_len&&(i<en.heap_len&&r(t,n[i+1],n[i],en.depth)&&i++,!r(t,s,n[i],en.depth));)n[e]=n[i],e=i,i<<=1;n[e]=s},en.deflateInit=function(t,e,n,r,s,i){return r||(r=Y),s||(s=R),i||(i=x),t.msg=null,e==v&&(e=6),1>s||s>P||r!=Y||9>n||n>15||0>e||e>9||0>i||i>q?T:(t.dstate=en,Se=n,Ce=1<<Se,Ee=Ce-1,Re=s+7,Pe=1<<Re,Fe=Pe-1,De=Math.floor((Re+Z-1)/Z),ze=new Uint8Array(2*Ce),Ie=[],Be=[],an=1<<s+6,en.pending_buf=new Uint8Array(4*an),ke=4*an,cn=Math.floor(an/2),on=3*an,Xe=e,Ye=i,_e=255&r,be(t))},en.deflateEnd=function(){return xe!=V&&xe!=J&&xe!=X?T:(en.pending_buf=null,Be=null,Ie=null,ze=null,en.dstate=null,xe==J?I:S)},en.deflateParams=function(t,e,n){var r=S;return e==v&&(e=6),0>e||e>9||0>n||n>q?T:(N[Xe].func!=N[e].func&&0!==t.total_in&&(r=t.deflate(_)),Xe!=e&&(Xe=e,Je=N[Xe].max_lazy,Ke=N[Xe].good_length,Qe=N[Xe].nice_length,Ve=N[Xe].max_chain),Ye=n,r)},en.deflateSetDictionary=function(t,e,n){var r,s=n,i=0;if(!e||xe!=V)return T;if(Z>s)return S;for(s>Ce-ee&&(s=Ce-ee,i=n-s),ze.set(e.subarray(i,i+s),0),Me=s,Ue=s,Oe=255&ze[0],Oe=(Oe<<De^255&ze[1])&Fe,r=0;s-Z>=r;r++)Oe=(Oe<<De^255&ze[r+(Z-1)])&Fe,Ie[r&Ee]=Be[Oe],Be[Oe]=r;return S},en.deflate=function(t,e){var n,r,s,i,o;if(e>C||0>e)return T;if(!t.next_out||!t.next_in&&0!==t.avail_in||xe==X&&e!=C)return t.msg=L[z-T],T;if(0===t.avail_out)return t.msg=L[z-B],B;if(qe=t,i=Ae,Ae=e,xe==V&&(r=Y+(Se-8<<4)<<8,s=(Xe-1&255)>>1,s>3&&(s=3),r|=s<<6,0!==Me&&(r|=W),r+=31-r%31,xe=J,O(r)),0!==en.pending){if(qe.flush_pending(),0===qe.avail_out)return Ae=-1,S}else if(0===qe.avail_in&&i>=e&&e!=C)return qe.msg=L[z-B],B;if(xe==X&&0!==qe.avail_in)return t.msg=L[z-B],B;if(0!==qe.avail_in||0!==Ge||e!=k&&xe!=X){switch(o=-1,N[Xe].func){case F:o=we(e);break;case D:o=ye(e);break;case U:o=ve(e)}if((o==H||o==G)&&(xe=X),o==j||o==H)return 0===qe.avail_out&&(Ae=-1),S;if(o==M){if(e==_)ae();else if(de(0,0,!1),e==A)for(n=0;Pe>n;n++)Be[n]=0;if(qe.flush_pending(),0===qe.avail_out)return Ae=-1,S}}return e!=C?S:E}}function i(){var t=this;t.next_in_index=0,t.next_out_index=0,t.avail_in=0,t.total_in=0,t.avail_out=0,t.total_out=0}var o=15,a=30,u=19,c=29,l=256,f=l+1+c,d=2*f+1,h=256,p=7,m=16,w=17,g=18,y=16,v=-1,b=1,q=2,x=0,k=0,_=1,A=3,C=4,S=0,E=1,z=2,T=-2,I=-3,B=-5,O=[0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29];t._length_code=[0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28],t.base_length=[0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224,0],t.base_dist=[0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576],t.d_code=function(t){return 256>t?O[t]:O[256+(t>>>7)]},t.extra_lbits=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],t.extra_dbits=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],t.extra_blbits=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],t.bl_order=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],e.static_ltree=[12,8,140,8,76,8,204,8,44,8,172,8,108,8,236,8,28,8,156,8,92,8,220,8,60,8,188,8,124,8,252,8,2,8,130,8,66,8,194,8,34,8,162,8,98,8,226,8,18,8,146,8,82,8,210,8,50,8,178,8,114,8,242,8,10,8,138,8,74,8,202,8,42,8,170,8,106,8,234,8,26,8,154,8,90,8,218,8,58,8,186,8,122,8,250,8,6,8,134,8,70,8,198,8,38,8,166,8,102,8,230,8,22,8,150,8,86,8,214,8,54,8,182,8,118,8,246,8,14,8,142,8,78,8,206,8,46,8,174,8,110,8,238,8,30,8,158,8,94,8,222,8,62,8,190,8,126,8,254,8,1,8,129,8,65,8,193,8,33,8,161,8,97,8,225,8,17,8,145,8,81,8,209,8,49,8,177,8,113,8,241,8,9,8,137,8,73,8,201,8,41,8,169,8,105,8,233,8,25,8,153,8,89,8,217,8,57,8,185,8,121,8,249,8,5,8,133,8,69,8,197,8,37,8,165,8,101,8,229,8,21,8,149,8,85,8,213,8,53,8,181,8,117,8,245,8,13,8,141,8,77,8,205,8,45,8,173,8,109,8,237,8,29,8,157,8,93,8,221,8,61,8,189,8,125,8,253,8,19,9,275,9,147,9,403,9,83,9,339,9,211,9,467,9,51,9,307,9,179,9,435,9,115,9,371,9,243,9,499,9,11,9,267,9,139,9,395,9,75,9,331,9,203,9,459,9,43,9,299,9,171,9,427,9,107,9,363,9,235,9,491,9,27,9,283,9,155,9,411,9,91,9,347,9,219,9,475,9,59,9,315,9,187,9,443,9,123,9,379,9,251,9,507,9,7,9,263,9,135,9,391,9,71,9,327,9,199,9,455,9,39,9,295,9,167,9,423,9,103,9,359,9,231,9,487,9,23,9,279,9,151,9,407,9,87,9,343,9,215,9,471,9,55,9,311,9,183,9,439,9,119,9,375,9,247,9,503,9,15,9,271,9,143,9,399,9,79,9,335,9,207,9,463,9,47,9,303,9,175,9,431,9,111,9,367,9,239,9,495,9,31,9,287,9,159,9,415,9,95,9,351,9,223,9,479,9,63,9,319,9,191,9,447,9,127,9,383,9,255,9,511,9,0,7,64,7,32,7,96,7,16,7,80,7,48,7,112,7,8,7,72,7,40,7,104,7,24,7,88,7,56,7,120,7,4,7,68,7,36,7,100,7,20,7,84,7,52,7,116,7,3,8,131,8,67,8,195,8,35,8,163,8,99,8,227,8],e.static_dtree=[0,5,16,5,8,5,24,5,4,5,20,5,12,5,28,5,2,5,18,5,10,5,26,5,6,5,22,5,14,5,30,5,1,5,17,5,9,5,25,5,5,5,21,5,13,5,29,5,3,5,19,5,11,5,27,5,7,5,23,5],e.static_l_desc=new e(e.static_ltree,t.extra_lbits,l+1,f,o),e.static_d_desc=new e(e.static_dtree,t.extra_dbits,0,a,o),e.static_bl_desc=new e(null,t.extra_blbits,0,u,p);var P=9,R=8,F=0,D=1,U=2,N=[new n(0,0,0,0,F),new n(4,4,8,4,D),new n(4,5,16,8,D),new n(4,6,32,32,D),new n(4,4,16,16,U),new n(8,16,32,32,U),new n(8,16,128,128,U),new n(8,32,128,256,U),new n(32,128,258,1024,U),new n(32,258,258,4096,U)],L=["need dictionary","stream end","","","stream error","data error","","buffer error","",""],j=0,M=1,H=2,G=3,W=32,V=42,J=113,X=666,Y=8,K=0,Q=1,$=2,Z=3,te=258,ee=te+Z+1;return i.prototype={deflateInit:function(t,e){var n=this;return n.dstate=new s,e||(e=o),n.dstate.deflateInit(n,t,e)},deflate:function(t){var e=this;return e.dstate?e.dstate.deflate(e,t):T},deflateEnd:function(){var t=this;if(!t.dstate)return T;var e=t.dstate.deflateEnd();return t.dstate=null,e},deflateParams:function(t,e){var n=this;return n.dstate?n.dstate.deflateParams(n,t,e):T},deflateSetDictionary:function(t,e){var n=this;return n.dstate?n.dstate.deflateSetDictionary(n,t,e):T},read_buf:function(t,e,n){var r=this,s=r.avail_in;return s>n&&(s=n),0===s?0:(r.avail_in-=s,t.set(r.next_in.subarray(r.next_in_index,r.next_in_index+s),e),r.next_in_index+=s,r.total_in+=s,s)},flush_pending:function(){var t=this,e=t.dstate.pending;e>t.avail_out&&(e=t.avail_out),0!==e&&(t.next_out.set(t.dstate.pending_buf.subarray(t.dstate.pending_out,t.dstate.pending_out+e),t.next_out_index),t.next_out_index+=e,t.dstate.pending_out+=e,t.total_out+=e,t.avail_out-=e,t.dstate.pending-=e,0===t.dstate.pending&&(t.dstate.pending_out=0))}},function(t){var e=this,n=new i,r=512,s=k,o=new Uint8Array(r);"undefined"==typeof t&&(t=v),n.deflateInit(t),n.next_out=o,e.append=function(t,e){var i,a,u=[],c=0,l=0,f=0;if(t.length){n.next_in_index=0,n.next_in=t,n.avail_in=t.length;do{if(n.next_out_index=0,n.avail_out=r,i=n.deflate(s),i!=S)throw"deflating: "+n.msg;n.next_out_index&&u.push(n.next_out_index==r?new Uint8Array(o):new Uint8Array(o.subarray(0,n.next_out_index))),f+=n.next_out_index,e&&n.next_in_index>0&&n.next_in_index!=c&&(e(n.next_in_index),c=n.next_in_index)}while(n.avail_in>0||0===n.avail_out);return a=new Uint8Array(f),u.forEach(function(t){a.set(t,l),l+=t.length}),a}},e.flush=function(){var t,e,s=[],i=0,a=0;do{if(n.next_out_index=0,n.avail_out=r,t=n.deflate(C),t!=E&&t!=S)throw"deflating: "+n.msg;r-n.avail_out>0&&s.push(new Uint8Array(o.subarray(0,n.next_out_index))),a+=n.next_out_index}while(n.avail_in>0||0===n.avail_out);return n.deflateEnd(),e=new Uint8Array(a),s.forEach(function(t){e.set(t,i),i+=t.length}),e}}}(this);!function(t){var e;e=function(){function e(t){var e,n,r,s,i,o,a,u,c,l,f,d,h,p,m;for(this.data=t,this.pos=8,this.palette=[],this.imgData=[],this.transparency={},this.animation=null,this.text={},o=null;;){switch(e=this.readUInt32(),l=function(){var t,e;for(e=[],a=t=0;4>t;a=++t)e.push(String.fromCharCode(this.data[this.pos++]));return e}.call(this).join("")){case"IHDR":this.width=this.readUInt32(),this.height=this.readUInt32(),this.bits=this.data[this.pos++],this.colorType=this.data[this.pos++],this.compressionMethod=this.data[this.pos++],this.filterMethod=this.data[this.pos++],this.interlaceMethod=this.data[this.pos++];break;case"acTL":this.animation={numFrames:this.readUInt32(),numPlays:this.readUInt32()||1/0,frames:[]};break;case"PLTE":this.palette=this.read(e);break;case"fcTL":o&&this.animation.frames.push(o),this.pos+=4,o={width:this.readUInt32(),height:this.readUInt32(),xOffset:this.readUInt32(),yOffset:this.readUInt32()},i=this.readUInt16(),s=this.readUInt16()||100,o.delay=1e3*i/s,o.disposeOp=this.data[this.pos++],o.blendOp=this.data[this.pos++],o.data=[];break;case"IDAT":case"fdAT":for("fdAT"===l&&(this.pos+=4,e-=4),t=(null!=o?o.data:void 0)||this.imgData,a=h=0;e>=0?e>h:h>e;a=e>=0?++h:--h)t.push(this.data[this.pos++]);break;case"tRNS":switch(this.transparency={},this.colorType){case 3:if(r=this.palette.length/3,this.transparency.indexed=this.read(e),this.transparency.indexed.length>r)throw new Error("More transparent colors than palette size");if(f=r-this.transparency.indexed.length,f>0)for(a=p=0;f>=0?f>p:p>f;a=f>=0?++p:--p)this.transparency.indexed.push(255);break;case 0:this.transparency.grayscale=this.read(e)[0];break;case 2:this.transparency.rgb=this.read(e)}break;case"tEXt":d=this.read(e),u=d.indexOf(0),c=String.fromCharCode.apply(String,d.slice(0,u)),this.text[c]=String.fromCharCode.apply(String,d.slice(u+1));break;case"IEND":return o&&this.animation.frames.push(o),this.colors=function(){switch(this.colorType){case 0:case 3:case 4:return 1;case 2:case 6:return 3}}.call(this),this.hasAlphaChannel=4===(m=this.colorType)||6===m,n=this.colors+(this.hasAlphaChannel?1:0),this.pixelBitlength=this.bits*n,this.colorSpace=function(){switch(this.colors){case 1:return"DeviceGray";case 3:return"DeviceRGB"}}.call(this),void(this.imgData=new Uint8Array(this.imgData));default:this.pos+=e}if(this.pos+=4,this.pos>this.data.length)throw new Error("Incomplete or corrupt PNG file")}}var n,r,s,i,a,u,c,l;e.load=function(t,n,r){var s;return"function"==typeof n&&(r=n),s=new XMLHttpRequest,s.open("GET",t,!0),s.responseType="arraybuffer",s.onload=function(){var t,i;return t=new Uint8Array(s.response||s.mozResponseArrayBuffer),i=new e(t),"function"==typeof(null!=n?n.getContext:void 0)&&i.render(n),"function"==typeof r?r(i):void 0},s.send(null)},i=0,s=1,a=2,r=0,n=1,e.prototype.read=function(t){var e,n,r;for(r=[],e=n=0;t>=0?t>n:n>t;e=t>=0?++n:--n)r.push(this.data[this.pos++]);return r},e.prototype.readUInt32=function(){var t,e,n,r;return t=this.data[this.pos++]<<24,e=this.data[this.pos++]<<16,n=this.data[this.pos++]<<8,r=this.data[this.pos++],t|e|n|r},e.prototype.readUInt16=function(){var t,e;return t=this.data[this.pos++]<<8,e=this.data[this.pos++],t|e},e.prototype.decodePixels=function(t){var e,n,r,s,i,a,u,c,l,f,d,h,p,m,w,g,y,v,b,q,x,k,_;if(null==t&&(t=this.imgData),0===t.length)return new Uint8Array(0);for(t=new o(t),t=t.getBytes(),h=this.pixelBitlength/8,g=h*this.width,p=new Uint8Array(g*this.height),a=t.length,w=0,m=0,n=0;a>m;){switch(t[m++]){case 0:for(s=b=0;g>b;s=b+=1)p[n++]=t[m++];break;case 1:for(s=q=0;g>q;s=q+=1)e=t[m++],i=h>s?0:p[n-h],p[n++]=(e+i)%256;break;case 2:for(s=x=0;g>x;s=x+=1)e=t[m++],r=(s-s%h)/h,y=w&&p[(w-1)*g+r*h+s%h],p[n++]=(y+e)%256;break;case 3:for(s=k=0;g>k;s=k+=1)e=t[m++],r=(s-s%h)/h,i=h>s?0:p[n-h],y=w&&p[(w-1)*g+r*h+s%h],p[n++]=(e+Math.floor((i+y)/2))%256;break;case 4:for(s=_=0;g>_;s=_+=1)e=t[m++],r=(s-s%h)/h,i=h>s?0:p[n-h],0===w?y=v=0:(y=p[(w-1)*g+r*h+s%h],v=r&&p[(w-1)*g+(r-1)*h+s%h]),u=i+y-v,c=Math.abs(u-i),f=Math.abs(u-y),d=Math.abs(u-v),l=f>=c&&d>=c?i:d>=f?y:v,p[n++]=(e+l)%256;break;default:throw new Error("Invalid filter algorithm: "+t[m-1])}w++}return p},e.prototype.decodePalette=function(){var t,e,n,r,s,i,o,a,u,c;for(r=this.palette,o=this.transparency.indexed||[],i=new Uint8Array((o.length||0)+r.length),s=0,n=r.length,t=0,e=a=0,u=r.length;u>a;e=a+=3)i[s++]=r[e],i[s++]=r[e+1],i[s++]=r[e+2],i[s++]=null!=(c=o[t++])?c:255;return i},e.prototype.copyToImageData=function(t,e){var n,r,s,i,o,a,u,c,l,f,d;if(r=this.colors,l=null,n=this.hasAlphaChannel,this.palette.length&&(l=null!=(d=this._decodedPalette)?d:this._decodedPalette=this.decodePalette(),r=4,n=!0),s=t.data||t,c=s.length,o=l||e,i=a=0,1===r)for(;c>i;)u=l?4*e[i/4]:a,f=o[u++],s[i++]=f,s[i++]=f,s[i++]=f,s[i++]=n?o[u++]:255,a=u;else for(;c>i;)u=l?4*e[i/4]:a,s[i++]=o[u++],s[i++]=o[u++],s[i++]=o[u++],s[i++]=n?o[u++]:255,a=u},e.prototype.decode=function(){var t;return t=new Uint8Array(this.width*this.height*4),this.copyToImageData(t,this.decodePixels()),t};try{c=t.document.createElement("canvas"),l=c.getContext("2d")}catch(f){return-1}return u=function(t){var e;return l.width=t.width,l.height=t.height,l.clearRect(0,0,t.width,t.height),l.putImageData(t,0,0),e=new Image,e.src=c.toDataURL(),e},e.prototype.decodeFrames=function(t){var e,n,r,s,i,o,a,c;if(this.animation){for(a=this.animation.frames,c=[],n=i=0,o=a.length;o>i;n=++i)e=a[n],r=t.createImageData(e.width,e.height),s=this.decodePixels(new Uint8Array(e.data)),this.copyToImageData(r,s),e.imageData=r,c.push(e.image=u(r));return c}},e.prototype.renderFrame=function(t,e){var n,i,o;return i=this.animation.frames,n=i[e],o=i[e-1],0===e&&t.clearRect(0,0,this.width,this.height),(null!=o?o.disposeOp:void 0)===s?t.clearRect(o.xOffset,o.yOffset,o.width,o.height):(null!=o?o.disposeOp:void 0)===a&&t.putImageData(o.imageData,o.xOffset,o.yOffset),n.blendOp===r&&t.clearRect(n.xOffset,n.yOffset,n.width,n.height),t.drawImage(n.image,n.xOffset,n.yOffset)},e.prototype.animate=function(t){var e,n,r,s,i,o,a=this;return n=0,o=this.animation,s=o.numFrames,r=o.frames,i=o.numPlays,(e=function(){var o,u;return o=n++%s,u=r[o],a.renderFrame(t,o),s>1&&i>n/s?a.animation._timeout=setTimeout(e,u.delay):void 0
+})()},e.prototype.stopAnimation=function(){var t;return clearTimeout(null!=(t=this.animation)?t._timeout:void 0)},e.prototype.render=function(t){var e,n;return t._png&&t._png.stopAnimation(),t._png=this,t.width=this.width,t.height=this.height,e=t.getContext("2d"),this.animation?(this.decodeFrames(e),this.animate(e)):(n=e.createImageData(this.width,this.height),this.copyToImageData(n,this.decodePixels()),e.putImageData(n,0,0))},e}(),t.PNG=e}("undefined"!=typeof window&&window||this);var i=function(){function t(){this.pos=0,this.bufferLength=0,this.eof=!1,this.buffer=null}return t.prototype={ensureBuffer:function(t){var e=this.buffer,n=e?e.byteLength:0;if(n>t)return e;for(var r=512;t>r;)r<<=1;for(var s=new Uint8Array(r),i=0;n>i;++i)s[i]=e[i];return this.buffer=s},getByte:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return this.buffer[this.pos++]},getBytes:function(t){var e=this.pos;if(t){this.ensureBuffer(e+t);for(var n=e+t;!this.eof&&this.bufferLength<n;)this.readBlock();var r=this.bufferLength;n>r&&(n=r)}else{for(;!this.eof;)this.readBlock();var n=this.bufferLength}return this.pos=n,this.buffer.subarray(e,n)},lookChar:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return String.fromCharCode(this.buffer[this.pos])},getChar:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return String.fromCharCode(this.buffer[this.pos++])},makeSubStream:function(t,e,n){for(var r=t+e;this.bufferLength<=r&&!this.eof;)this.readBlock();return new Stream(this.buffer,t,e,n)},skip:function(t){t||(t=1),this.pos+=t},reset:function(){this.pos=0}},t}(),o=function(){function t(t){throw new Error(t)}function e(e){var n=0,r=e[n++],s=e[n++];(-1==r||-1==s)&&t("Invalid header in flate stream"),8!=(15&r)&&t("Unknown compression method in flate stream"),((r<<8)+s)%31!=0&&t("Bad FCHECK in flate stream"),32&s&&t("FDICT bit set in flate stream"),this.bytes=e,this.bytesPos=n,this.codeSize=0,this.codeBuf=0,i.call(this)}if("undefined"==typeof Uint32Array)return void 0;var n=new Uint32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),r=new Uint32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),s=new Uint32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009,459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),o=[new Uint32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59e4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348,590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366,590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339,590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352,590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,590041,459022,524396,524332,590009,524300,524428,524364,590073,459009,524370,524306,524570,459025,524402,524338,590021,459017,524386,524322,589989,524290,524418,524354,590053,459013,524378,524314,589973,459029,524410,524346,590037,459021,524394,524330,590005,524298,524426,524362,590069,459011,524374,524310,524574,459027,524406,524342,590029,459019,524390,524326,589997,524294,524422,524358,590061,459015,524382,524318,589981,459031,524414,524350,590045,459023,524398,524334,590013,524302,524430,524366,590077,459008,524369,524305,524569,459024,524401,524337,590019,459016,524385,524321,589987,524289,524417,524353,590051,459012,524377,524313,589971,459028,524409,524345,590035,459020,524393,524329,590003,524297,524425,524361,590067,459010,524373,524309,524573,459026,524405,524341,590027,459018,524389,524325,589995,524293,524421,524357,590059,459014,524381,524317,589979,459030,524413,524349,590043,459022,524397,524333,590011,524301,524429,524365,590075,459009,524371,524307,524571,459025,524403,524339,590023,459017,524387,524323,589991,524291,524419,524355,590055,459013,524379,524315,589975,459029,524411,524347,590039,459021,524395,524331,590007,524299,524427,524363,590071,459011,524375,524311,524575,459027,524407,524343,590031,459019,524391,524327,589999,524295,524423,524359,590063,459015,524383,524319,589983,459031,524415,524351,590047,459023,524399,524335,590015,524303,524431,524367,590079]),9],a=[new Uint32Array([327680,327696,327688,327704,327684,327700,327692,327708,327682,327698,327690,327706,327686,327702,327694,0,327681,327697,327689,327705,327685,327701,327693,327709,327683,327699,327691,327707,327687,327703,327695,0]),5];return e.prototype=Object.create(i.prototype),e.prototype.getBits=function(e){for(var n,r=this.codeSize,s=this.codeBuf,i=this.bytes,o=this.bytesPos;e>r;)"undefined"==typeof(n=i[o++])&&t("Bad encoding in flate stream"),s|=n<<r,r+=8;return n=s&(1<<e)-1,this.codeBuf=s>>e,this.codeSize=r-=e,this.bytesPos=o,n},e.prototype.getCode=function(e){for(var n=e[0],r=e[1],s=this.codeSize,i=this.codeBuf,o=this.bytes,a=this.bytesPos;r>s;){var u;"undefined"==typeof(u=o[a++])&&t("Bad encoding in flate stream"),i|=u<<s,s+=8}var c=n[i&(1<<r)-1],l=c>>16,f=65535&c;return(0==s||l>s||0==l)&&t("Bad encoding in flate stream"),this.codeBuf=i>>l,this.codeSize=s-l,this.bytesPos=a,f},e.prototype.generateHuffmanTable=function(t){for(var e=t.length,n=0,r=0;e>r;++r)t[r]>n&&(n=t[r]);for(var s=1<<n,i=new Uint32Array(s),o=1,a=0,u=2;n>=o;++o,a<<=1,u<<=1)for(var c=0;e>c;++c)if(t[c]==o){for(var l=0,f=a,r=0;o>r;++r)l=l<<1|1&f,f>>=1;for(var r=l;s>r;r+=u)i[r]=o<<16|c;++a}return[i,n]},e.prototype.readBlock=function(){function e(t,e,n,r,s){for(var i=t.getBits(n)+r;i-->0;)e[k++]=s}var i=this.getBits(3);if(1&i&&(this.eof=!0),i>>=1,0==i){var u,c=this.bytes,l=this.bytesPos;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream");var f=u;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream"),f|=u<<8,"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream");var d=u;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream"),d|=u<<8,d!=(65535&~f)&&t("Bad uncompressed block length in flate stream"),this.codeBuf=0,this.codeSize=0;var h=this.bufferLength,p=this.ensureBuffer(h+f),m=h+f;this.bufferLength=m;for(var w=h;m>w;++w){if("undefined"==typeof(u=c[l++])){this.eof=!0;break}p[w]=u}return void(this.bytesPos=l)}var g,y;if(1==i)g=o,y=a;else if(2==i){for(var v=this.getBits(5)+257,b=this.getBits(5)+1,q=this.getBits(4)+4,x=Array(n.length),k=0;q>k;)x[n[k++]]=this.getBits(3);for(var _=this.generateHuffmanTable(x),A=0,k=0,C=v+b,S=new Array(C);C>k;){var E=this.getCode(_);16==E?e(this,S,2,3,A):17==E?e(this,S,3,3,A=0):18==E?e(this,S,7,11,A=0):S[k++]=A=E}g=this.generateHuffmanTable(S.slice(0,v)),y=this.generateHuffmanTable(S.slice(v,C))}else t("Unknown block type in flate stream");for(var p=this.buffer,z=p?p.length:0,T=this.bufferLength;;){var I=this.getCode(g);if(256>I)T+1>=z&&(p=this.ensureBuffer(T+1),z=p.length),p[T++]=I;else{if(256==I)return void(this.bufferLength=T);I-=257,I=r[I];var B=I>>16;B>0&&(B=this.getBits(B));var A=(65535&I)+B;I=this.getCode(y),I=s[I],B=I>>16,B>0&&(B=this.getBits(B));var O=(65535&I)+B;T+A>=z&&(p=this.ensureBuffer(T+A),z=p.length);for(var P=0;A>P;++P,++T)p[T]=p[T-O]}}},e}();!function(t){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";"undefined"==typeof t.btoa&&(t.btoa=function(t){var n,r,s,i,o,a,u,c,l=0,f=0,d="",h=[];if(!t)return t;do n=t.charCodeAt(l++),r=t.charCodeAt(l++),s=t.charCodeAt(l++),c=n<<16|r<<8|s,i=c>>18&63,o=c>>12&63,a=c>>6&63,u=63&c,h[f++]=e.charAt(i)+e.charAt(o)+e.charAt(a)+e.charAt(u);while(l<t.length);d=h.join("");var p=t.length%3;return(p?d.slice(0,p-3):d)+"===".slice(p||3)}),"undefined"==typeof t.atob&&(t.atob=function(t){var n,r,s,i,o,a,u,c,l=0,f=0,d="",h=[];if(!t)return t;t+="";do i=e.indexOf(t.charAt(l++)),o=e.indexOf(t.charAt(l++)),a=e.indexOf(t.charAt(l++)),u=e.indexOf(t.charAt(l++)),c=i<<18|o<<12|a<<6|u,n=c>>16&255,r=c>>8&255,s=255&c,h[f++]=64==a?String.fromCharCode(n):64==u?String.fromCharCode(n,r):String.fromCharCode(n,r,s);while(l<t.length);return d=h.join("")}),Array.prototype.map||(Array.prototype.map=function(t){if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;for(var e=Object(this),n=e.length>>>0,r=new Array(n),s=arguments.length>1?arguments[1]:void 0,i=0;n>i;i++)i in e&&(r[i]=t.call(s,e[i],i,e));return r}),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Array.prototype.forEach||(Array.prototype.forEach=function(t,e){"use strict";if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;for(var n=Object(this),r=n.length>>>0,s=0;r>s;s++)s in n&&t.call(e,n[s],s,n)}),Object.keys||(Object.keys=function(){"use strict";var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],r=n.length;return function(s){if("object"!=typeof s&&("function"!=typeof s||null===s))throw new TypeError;var i,o,a=[];for(i in s)t.call(s,i)&&a.push(i);if(e)for(o=0;r>o;o++)t.call(s,n[o])&&a.push(n[o]);return a}}()),String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),String.prototype.trimLeft||(String.prototype.trimLeft=function(){return this.replace(/^\s+/g,"")}),String.prototype.trimRight||(String.prototype.trimRight=function(){return this.replace(/\s+$/g,"")})}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this)}({},function(){return this}());
\ No newline at end of file
diff --git a/force-app/main/default/staticresources/jspdf.resource-meta.xml b/force-app/main/default/staticresources/jspdf.resource-meta.xml
new file mode 100644
index 0000000..13e64c6
--- /dev/null
+++ b/force-app/main/default/staticresources/jspdf.resource-meta.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
+    <cacheControl>Public</cacheControl>
+    <contentType>text/javascript</contentType>
+    <description>jspdf</description>
+</StaticResource>

--
Gitblit v1.9.1