/**
     * NFM001.triggerから呼び出す
     */
    public without sharing class NFM001Controller {
        //NFM001修改Rest start
        public static String status;
        public class NFM001 {
            public Endusers_element Endusers;
        }

        public class Endusers_element {
            public NFMUtil.Monitoring Monitoring;
            public Enduser_element[] Enduser;
        }

        public class Enduser_element {
            public String CompanyCode;          
            public String CompanyDescription;   
            public String DepartmentCode;       
            public String DepartmentDescription;
            public String CompanyDescription2;  
            public String CompanyAreaCode;     
            public String DepartmentPostalCode;
            public String DepartmentAddress;   
            public String CompanyCategory;     
            public String DepartmentTelephone;
            public String DepartmentFax;       
            public String DepartmentCategory;  
            public String DepartmentEffectiveDateTo;
            public String PurposeOfAdvice;
        }
        //NFM001修改Rest end
        public static boolean isRunning = false;
        public static String debug_msg = '';

        /**
         * NFM001の送信処理
         *
         * @param iflog_Id           ログテーブルのId
         * @param accIds             送信対象取引先
         * @param purposeOfAdviceMap 1:Delete 2:Add(Insert) 3:Change(Update)
         * @param needSendRectMap    送信対象のレコードタイプのmap
         */
        @future (callout=true)
        public static void callout(String iflog_Id, List<String> accIds, Map<String, String> purposeOfAdviceMap, Map<String, String> needSendRectMap) {
            calloutNotFuture(iflog_Id,accIds,purposeOfAdviceMap,needSendRectMap);
        }

        
        public static void calloutNotFuture(String iflog_Id, List<String> accIds, Map<String, String> purposeOfAdviceMap, Map<String, String> needSendRectMap) {
            if (accIds == null || accIds.size() == 0) {
                return;
            }
            /*Nfm001Sync.HTTPS_Port stub = new Nfm001Sync.HTTPS_Port();
            stub.timeout_x = 100000; // timeout in milliseconds
            stub.endpoint_x = NFMUtil.NFM001_ENDPOINT;
            stub.inputHttpHeaders_x = new Map<String, String>();
            stub.inputHttpHeaders_x.put('Authorization', NFMUtil.Authorization);*/
            
            /*if (NFMUtil.CLIENT_CERT_NAME != null) {
                stub.clientCertName_x = NFMUtil.CLIENT_CERT_NAME;
            }*/ 

            // MessageGroupNumber の取得
            List<BatchIF_Log__c> iflogList = [Select Id, Name, Log__c, ErrorLog__c from BatchIF_Log__c where Id = :iflog_Id];
            BatchIF_Log__c iflog = new BatchIF_Log__c();
            //BatchIF_Log__c iflog = null;
            if (iflogList.size() > 0) {
                iflog = iflogList.get(0);
                iflog.ErrorLog__c = '';
            } else {
                // データ取れってないとは、rollbackされていることです
                //return;
                iflog.Type__c = 'NFM001';
                iflog.ErrorLog__c = '';
                iflog.Log__c  = 'callout start\n';
            }
            String logstr = iflog.Log__c + ' ' + 'NumberOfRecord=' + accIds.size() + '\n';

            // Monitoringの設定
            Datetime nowDT = Datetime.now();
            String nowStr = nowDT.format('yyyyMMddHHmm');
            //NFM001修改Rest start
            //Nfm001Sync.Endusers_element endusers = new Nfm001Sync.Endusers_element();
            Endusers_element endusers = new Endusers_element();
            //NFM001修改Rest end
            endusers.Monitoring = new NFMUtil.Monitoring();
            endusers.Monitoring.Tag                  = 'MSGH';
            endusers.Monitoring.Sender               = '8402';
            endusers.Monitoring.Receiver             = '1330';
            endusers.Monitoring.MessageType          = 'NFM001';
            endusers.Monitoring.MessageGroupNumber   = iflog.Name;
            endusers.Monitoring.NumberOfRecord       = '' + accIds.size();
            endusers.Monitoring.TransmissionDateTime = nowStr;
            endusers.Monitoring.Text = '';

            BatchIF_Log__c rowData = null;
            // BatchIF転送表 から、コード変換のMapを作成
            Map<String, String> transferMap = new Map<String, String>();
            List<BatchIF_Transfer__c> transferList = [select Table__c,
                                                             Column__c,
                                                             External_value__c,
                                                             Internal_value__c
                                                        from BatchIF_Transfer__c
                                                       where Dropped_Flag__c = false
                                                         and Table__c = 'Account'];
            for (BatchIF_Transfer__c t : transferList) {
                transferMap.put(t.Column__c + t.Internal_value__c, t.External_value__c);
            }

            try {
                // 転送データを取得、参照先のデータがあるので、ここで検索必要です。
                List<Account> accList = [select Id, RecordTypeId, Management_Code__c,
                                                Name, Site, Department_Name__c,
                                                Phone, Fax,
                                                Is_Medical_F__c,
                                                Postal_Code__c, Address__c,
                                                OCM_Category__c,
                                                //NFM001修改Rest start
                                                Is_Active_Formula__c,
                                                //NFM001修改Rest end
                                                City_Master__r.Level2_Sys_No__c,
                                                Hospital__r.Name,
                                                Hospital__r.Management_Code__c,
                                                Hospital__r.Site,
                                                Hospital__r.City_Master__r.Level2_Sys_No__c,
                                                Hospital__r.Postal_Code__c,
                                                Hospital__r.Address__c,
                                                Hospital__r.OCM_Category__c,
                                                // HWAG-BBNBXK LHJ 20190429 Start
                                                Hospital__r.Is_Medical_F__c,
                                                // HWAG-BBNBXK LHJ 20190429 End
                                                // 契約の対応
                                                Parent.AgentCode_Ext__c,
                                                Parent.Name,
                                                Parent.Phone,
                                                Parent.Fax,
                                                Parent.Postal_Code__c,
                                                // 20190729 合同中的省，通过经销商抓取，传给SAP
                                                City_Master_TOSAP__c,
                                                Parent.Address_Together__c,
                                                AgencyContract_Management_Code__c,
                                                Parent.Ban_On_Use_Date__c
                                           from Account where Id IN :accIds All ROWS];
                System.debug(Logginglevel.DEBUG, 'NFM001_ accList.size()=' + accList.size());


                // Enduserのデータの設定
                //NFM001修改Rest start
                //endusers.Enduser = new List<Nfm001Sync.Enduser_element>();
                endusers.Enduser = new List<Enduser_element>();
                //NFM001修改Rest end
                for (Account acc : accList) {
                    System.debug('purposeOfAdviceMap='+purposeOfAdviceMap);
                    System.debug('needSendRectMap='+needSendRectMap);
                    System.debug('acc.RecordTypeId='+acc.RecordTypeId);
                    System.debug('needSendRectMap.get(acc.RecordTypeId)'+needSendRectMap.get(acc.RecordTypeId));
                    //NFM001修改Rest start
                    //Nfm001Sync.Enduser_element enduser = new Nfm001Sync.Enduser_element();
                    Enduser_element enduser = new Enduser_element();
                    endusers.Enduser.add(enduser);
                    //NFM001修改Rest end
                    if (needSendRectMap.get(acc.RecordTypeId) == '契約') {
                        System.debug('accList.size()=' + accList);
                        enduser.CompanyCode           = acc.AgencyContract_Management_Code__c;
                        enduser.CompanyDescription    = acc.Parent.Name + '（最终用户）';
                        enduser.DepartmentCode        = acc.AgencyContract_Management_Code__c;
                        enduser.DepartmentDescription = acc.Parent.Name;
                        enduser.CompanyDescription2   = acc.Parent.Name;
                        //enduser.CompanyAreaCode       = acc.City_Master__r.Level2_Sys_No__c;
                        enduser.CompanyAreaCode       = acc.City_Master_TOSAP__c;
                        enduser.DepartmentPostalCode  = null;
                        enduser.DepartmentAddress     = acc.Address__c;
                        enduser.CompanyCategory       = 'NORMAL(L)';
                        enduser.DepartmentTelephone   = acc.Parent.Phone;
                        enduser.DepartmentFax         = acc.Parent.Fax;
                        enduser.DepartmentCategory    = null;
                        enduser.DepartmentEffectiveDateTo = (acc.Parent.Ban_On_Use_Date__c == null) ? '99991231' : NFMUtil.formatDate2Str(acc.Parent.Ban_On_Use_Date__c);
                        enduser.PurposeOfAdvice       = purposeOfAdviceMap.get(acc.Id);
                    } else {
                        System.debug(acc.RecordTypeId);
                        if (needSendRectMap.get(acc.RecordTypeId) == '病院') {
                            enduser.CompanyCode           = acc.Management_Code__c;
                            enduser.CompanyDescription    = acc.Name;
                            enduser.DepartmentCode        = acc.Management_Code__c;
                            enduser.DepartmentDescription = acc.Name;
                            //--------CHAN-B3N9KB---------------AddStart------xinhonglu----------------------------------------
                            //wangweipeng   2021/10/08      如果是民营，那么传接口值为私立    start
                            enduser.CompanyDescription2   = acc.Site +','+ (acc.Is_Medical_F__c == '民营' ? '私立':acc.Is_Medical_F__c);
                            //wangweipeng   2021/10/08      如果是民营，那么传接口值为私立    end
                            //--------CHAN-B3N9KB---------------AddEnd------xinhonglu-----------------------------------------
                            enduser.CompanyAreaCode       = acc.City_Master__r.Level2_Sys_No__c;
                            enduser.DepartmentPostalCode  = acc.Postal_Code__c;
                            enduser.DepartmentAddress     = acc.Address__c;
                            enduser.CompanyCategory       = NFMUtil.getMapValue(transferMap, 'OCM_Category__c', acc.OCM_Category__c, iflog);
                        } else {
                            System.debug('accList.size()=' + accList);
                            enduser.CompanyCode           = acc.Hospital__r.Management_Code__c;
                            enduser.CompanyDescription    = acc.Hospital__r.Name;
                            enduser.DepartmentCode        = acc.Management_Code__c;
                            enduser.DepartmentDescription = acc.Department_Name__c;
                            // HWAG-BBNBXK LHJ 20190429 Start
                            //enduser.CompanyDescription2   = acc.Hospital__r.Site;
                            //wangweipeng   2021/10/08      如果是民营，那么传接口值为私立    start
                            enduser.CompanyDescription2   = acc.Hospital__r.Site +','+ (acc.Hospital__r.Is_Medical_F__c == '民营' ? '私立':acc.Hospital__r.Is_Medical_F__c);
                            //wangweipeng   2021/10/08      如果是民营，那么传接口值为私立    end
                            // HWAG-BBNBXK LHJ 20190429 End
                            enduser.CompanyAreaCode       = acc.Hospital__r.City_Master__r.Level2_Sys_No__c;
                            enduser.DepartmentPostalCode  = acc.Hospital__r.Postal_Code__c;
                            enduser.DepartmentAddress     = acc.Hospital__r.Address__c;
                            enduser.CompanyCategory       = NFMUtil.getMapValue(transferMap, 'OCM_Category__c', acc.Hospital__r.OCM_Category__c, iflog);
                        }
                        enduser.DepartmentTelephone = acc.Phone;
                        enduser.DepartmentFax       = acc.Fax;
                        enduser.DepartmentCategory = null;
                        // deleteがないので、有効終了 日に 99991231 をセットして更新
                        String purposeOfAdvice = purposeOfAdviceMap.get(acc.Id);
                        if (purposeOfAdvice == '1') {
                            enduser.DepartmentEffectiveDateTo = NFMUtil.formatDate2Str(System.today());
                            enduser.PurposeOfAdvice = '3';
                        } else {
                            enduser.DepartmentEffectiveDateTo = '99991231';
                            enduser.PurposeOfAdvice = purposeOfAdvice;
                        }
                    }
                    
                    logstr += enduser.DepartmentCode + '(' + enduser.PurposeOfAdvice + ')' + ' ';
                }

                if (EndUsers.Enduser.size() > 0) {

                    NFMUtil.Monitoring Monitoring   = new NFMUtil.Monitoring();
                    Monitoring.Tag                  = EndUsers.Monitoring.Tag;
                    Monitoring.Sender               = EndUsers.Monitoring.Sender;
                    Monitoring.Receiver             = EndUsers.Monitoring.Receiver;
                    Monitoring.MessageType          = EndUsers.Monitoring.MessageType;
                    Monitoring.MessageGroupNumber   = EndUsers.Monitoring.MessageGroupNumber;
                    Monitoring.NumberOfRecord       = EndUsers.Monitoring.NumberOfRecord;
                    Monitoring.TransmissionDateTime = EndUsers.Monitoring.TransmissionDateTime;
                    Monitoring.Text = '';
                    
                    // NFM001修改Rest 新增 start
                    NFM001 nfm001 = new NFM001();
                    nfm001.EndUsers = new EndUsers_element();
                    nfm001.EndUsers = EndUsers;
                    // NFM001修改Rest 新增 end
                      
                    //NFM001修改Rest start
                    rowData = NFMUtil.makeRowData(Monitoring, 'NFM001', nfm001);
                    //NFM001修改Rest end
                    execute(rowData, iflog);


                    if (System.Label.NFM001_IsOn == '1') {
                    //    Nfm001Sync.Endusers_element[] pEndusers = new Nfm001Sync.Endusers_element[] { endusers };
                        logstr += '\ncallout count=' + EndUsers.Enduser.size();
                    //    OlympusCoJpCommonMessage.LOG_element[] logs = stub.NFM001_Sync_BC2GPI(pEndusers);
                    } else {
                        iflog.ErrorLog__c += 'NFM001_IsOff';
                    }
                    // 原則非同期ですので、logsを確認する必要がないでしょう。
                }
                logstr += '\nend';
            } catch(Exception ex) {
                // エラーが発生した場合
                System.debug(Logginglevel.ERROR, 'NFM001_' + iflog.Name + ':' + ex.getMessage());
                System.debug(Logginglevel.ERROR, 'NFM001_' + iflog.Name + ':' + ex.getStackTraceString());
                logstr += ex.getMessage();
                iflog.ErrorLog__c += ex.getMessage() + '\n';
                iflog.ErrorLog__c += ex.getStackTraceString() + '\n';
            }
            if (rowData != null) {
                System.debug('+++++rowData+++++insert:' + rowData);
                insert rowData;
                System.debug('+++++rowData+++++afterinsert:' + rowData.Id);
            }

            System.debug(Logginglevel.DEBUG, 'NFM001_' + iflog.Name + ' end');
            iflog.Log__c = logstr;
            upsert iflog;
        }

        public static void execute(BatchIF_Log__c rowData, BatchIF_Log__c iflog) {

            Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
            String rowDataStr = NFMUtil.getRowDataStr(rowData);
            // NFM001修改Rest start
            //Nfm001Sync.Endusers_element endusers = (Nfm001Sync.Endusers_element) JSON.deserialize(rowDataStr, Nfm001Sync.Endusers_element.class);
            NFM001 nfm001 = (NFM001) JSON.deserialize(rowDataStr, NFM001.class);

            //String logstr = endusers.Monitoring.MessageGroupNumber + ' start\n';
            String logstr = nfm001.endusers.Monitoring.MessageGroupNumber + ' start\n';
            // NFM001修改Rest start end
            Boolean needUpdateIflog = false;
            if  (iflog == null) {
                needUpdateIflog = true;
                iflog = new BatchIF_Log__c();
                iflog.Type__c = 'NFM001';
                // NFM001修改Rest start
                iflog.MessageGroupNumber__c = nfm001.endusers.Monitoring.MessageGroupNumber;
                // NFM001修改Rest end
                iflog.Log__c = logstr;
                iflog.ErrorLog__c = '';
                //insert iflog;
                //iflog = [Select Id, Name, Log__c, ErrorLog__c from BatchIF_Log__c where Id = :iflog.Id];
            } else {
                logstr = iflog.Log__c;
            }

            try{
                //gaozw
                // NFM001修改Rest start
                /*Nfm001Sync.HTTPS_Port stub = new Nfm001Sync.HTTPS_Port();
                stub.timeout_x = 100000; // timeout in milliseconds
                stub.endpoint_x = NFMUtil.NFM001_ENDPOINT;
                stub.inputHttpHeaders_x = new Map<String, String>();
                stub.inputHttpHeaders_x.put('Authorization', NFMUtil.Authorization);
                if (NFMUtil.CLIENT_CERT_NAME != null) {
                    stub.clientCertName_x = NFMUtil.CLIENT_CERT_NAME;
                }
                Nfm001Sync.Endusers_element[] pEndusers = new Nfm001Sync.Endusers_element[] { endusers };
                NFM001Controller.debug_msg += ', execute()';
                OlympusCoJpCommonMessage.LOG_element[] logs = stub.NFM001_Sync_BC2GPI(pEndusers);*/
                // NFM001修改Rest end
                // 原則非同期ですので、logsを確認する必要がないでしょう。
                // NFM001修改Rest start
                status =NFMUtil.sendToSapRet(rowDataStr, NFMUtil.NFM001_ENDPOINT);
                if (status == 'OK') {
                    rowData.retry_cnt__c = 0;
                } else {
                    if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
                    if (rowData.retry_cnt__c < batch_retry_max_cnt) {
                        rowData.retry_cnt__c++;
                        LogAutoSendSchedule.assignOneMinute();
                    }
                    if (rowData.retry_cnt__c >= batch_retry_max_cnt) {
                        rowData.ErrorLog__c = 'status:' + status +
                                              '\n错误次数已经超过自动送信设定的最大次数，请手动送信';
                    }
                }
                // NFM001修改Rest end
            }catch(Exception ex) {
                // TODO IOException
                // エラーが発生した場合
                System.debug(Logginglevel.ERROR, 'NFM001_' + iflog.Name + ':' + ex.getMessage());
                System.debug(Logginglevel.ERROR, 'NFM001_' + iflog.Name + ':' + ex.getStackTraceString());
                logstr += ex.getMessage();
                iflog.ErrorLog__c += ex.getMessage() + '\n';
                iflog.ErrorLog__c += ex.getStackTraceString() + '\n';

                //---Gaozw---add
                if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
                if (rowData.retry_cnt__c < batch_retry_max_cnt){
                    rowData.retry_cnt__c++;
                    LogAutoSendSchedule.assignOneMinute();
                }
                if (rowData.retry_cnt__c >= batch_retry_max_cnt){
                    rowData.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + rowData.ErrorLog__c+'错误次数已经超过自动送信设定的最大次数，请手动送信';
                }
            }
            iflog.Log__c = logstr;
            System.debug('logdate2' + rowData);
            if (needUpdateIflog) {
                upsert iflog;
                upsert rowData;
            }
        }
    }