public with sharing class RepairPCLController {
    public List<RepairInfo> oppRecords { get; set; }
    // ページレイアウトの情報を取得
    private Map<String, String> DESC_RW = null;
    
    /*****************検索用******************/
    public Contact con1 { get; set; }
    public Contact con2 { get; set; }
    
    public String accSearch { get; set; }
    public String ownerSearch { get; set; }
    
    public List<SelectOption> dateOpts { get; private set; }
    public List<SelectOption> textOpts { get; private set; }
    public List<SelectOption> equalOpts { get; private set; }
    public List<SelectOption> textOpts2 { get; private set; }
    public List<SelectOption> equalOpts2 { get; private set; }
    public List<SelectOption> textOpts3 { get; private set; }
    public List<SelectOption> equalOpts3 { get; private set; }
    public List<SelectOption> limitOpts { get; private set; }
    
    public String dateField { get; set; }
    
    public String text { get; set; }
    public String condition { get; set; }
    public String value { get; set; }
    
    public String text2 { get; set; }
    public String condition2 { get; set; }
    public String value2 { get; set; }
    
    public String text3 { get; set; }
    public String condition3 { get; set; }
    public String value3 { get; set; }
    
    public String limits { get; set; }
    
    /*****************画面表示Bean******************/
    public Integer oppCount { get; set; }
    public String saveType { get; set; }
    
    /*****************金額合計******************/
    // TODO 名前見直す
//    public Decimal salesAmountSumTaxF { get; private set; }
//    public Decimal listPriceSum { get; private set; }
//    public Decimal salesAmountSumWithoutTaxF { get; private set; }
    
    /*****************ソートキー******************/
    public String sortKey { get; set; }
    public String preSortKey { get; set; }
    public Boolean sortOrderAsc { get; set; }
    public String[] sortOrder { get; set; }
    public String[] columus = new String[]{'Id'};
    public Set<String> columusSet = new Set<String> {'Id'};
    
    // 项目set 字段标签
    public List<String> titleLeft { get; private set; }
    public List<String> titleRight { get; private set; }
    // 项目set 字段名
    public List<List<String>> columnsLeftApi { get; private set; }         // 参照項目用
    public List<List<String>> columnsRightApi { get; private set; }        // 参照項目用
    public List<String> columnLeftCss { get; private set; }               // css 用
    public List<String> columnRightCss { get; private set; }              // css 用
    public Map<String, String> columnLeftRW { get; private set; }              // r,w,wm用
    public Map<String, String> columnRightRW { get; private set; }             // r,w,wm用
    private String strColumus;

    /***************** Rating表示ラベル（動的対応） ******************/
/*    private static Integer todayM = Date.today().month();
    public Integer rl1 { get; private set; }
    public Integer rl2 { get; private set; }
    public Integer rl3 { get; private set; }
    public Integer rl4 { get; private set; }
    public Integer rl5 { get; private set; }
    public Integer rl6 { get; private set; }
    public Integer rl7 { get; private set; }
    public Integer rl8 { get; private set; }
    public Integer rl9 { get; private set; }
    public Integer rl10 { get; private set; }
    public Integer rl11 { get; private set; }
    public Integer rl12 { get; private set; }
    
    /***************** Ratingソート番号（動的対応） ******************/
/*    public Integer rs1 { get; private set; }
    public Integer rs2 { get; private set; }
    public Integer rs3 { get; private set; }
    public Integer rs4 { get; private set; }
    public Integer rs5 { get; private set; }
    public Integer rs6 { get; private set; }
    public Integer rs7 { get; private set; }
    public Integer rs8 { get; private set; }
    public Integer rs9 { get; private set; }
    public Integer rs10 { get; private set; }
    public Integer rs11 { get; private set; }
    public Integer rs12 { get; private set; }
    
    /*****************ソート時再検索条件（画面からの入力条件を無視するため）******************/
    private String hpForSort = null;
    private String ownerForSort = null;
    private String datefieldForSort = null;
    private Date fromdForSort = null;
    private Date todForSort = null;
    private String textForSort = null;
    private String conditionForSort = null;
    private String valueForSort = null;
    private String textForSort2 = null;
    private String conditionForSort2 = null;
    private String valueForSort2 = null;
    private String textForSort3 = null;
    private String conditionForSort3 = null;
    private String valueForSort3 = null;
    private String limitForSort = null;

    private static Integer oppLimit = 1000;
    private Boolean isForMoneyFlg = false;
    
    public RepairPCLController() {
        DESC_RW = SoapApi.getEditLayoutItemRW('Repair__c', new String[]{System.label.Repaire_pclc}).get(System.label.Repaire_pclc);// niwu  -01210000000QmS9AAK
        oppRecords = new List<RepairInfo>();
        
        // 日付検索条件のCalendar用
        con1 = new Contact();
        con2 = new Contact();
        
        dateOpts = new List<SelectOption>();
        dateOpts.add(new SelectOption('', '--无--'));
        dateOpts.add(new SelectOption('Failure_Occurrence_Date__c', '故障发生日'));
        dateOpts.add(new SelectOption('StatusUpdateDate__c', '状态更新日期'));

        textOpts = new List<SelectOption>();
        textOpts.add(new SelectOption('','--无--'));
        textOpts.add(new SelectOption('S:Name','SFDC修理No.'));
        textOpts.add(new SelectOption('S:HP_Name__c','医院'));
        textOpts.add(new SelectOption('S:Delivered_Product__r.Name','设备型号'));
        //textOpts.add(new SelectOption('S:Category1__c','第1分类'));
        //textOpts.add(new SelectOption('S:Category2__c','第2分类'));
        //textOpts.add(new SelectOption('S:Category3__c','第3分类'));
        //textOpts.add(new SelectOption('S:category4__c','第4分类'));
        //textOpts.add(new SelectOption('S:category5__c','第5分类'));
        textOpts.add(new SelectOption('S:OwnershipMachine_No__c','产品型号(略称)'));
        textOpts.add(new SelectOption('S:SerialNumber__c','机身号码'));
        textOpts.add(new SelectOption('S:Incharge_Staff__r.Name','修理委托者'));
        textOpts.add(new SelectOption('S:Status1__c','状态1'));
        
        textOpts2 = textOpts;
        textOpts3 = textOpts;
        
        equalOpts = new List<SelectOption>();
        equalOpts.add(new SelectOption('equals','等于'));
        equalOpts.add(new SelectOption('notequals','不等于'));
        equalOpts.add(new SelectOption('<','<'));
        equalOpts.add(new SelectOption('>','>'));
        equalOpts.add(new SelectOption('<=','<='));
        equalOpts.add(new SelectOption('>=','>='));
        equalOpts.add(new SelectOption('contains','包含'));
        equalOpts.add(new SelectOption('notcontains','不包含'));
        equalOpts.add(new SelectOption('starts with','起始字符'));
        
        equalOpts2 = equalOpts;
        equalOpts3 = equalOpts;
        
        limitOpts = new List<SelectOption>();
        limitOpts.add(new SelectOption('20','20'));
        limitOpts.add(new SelectOption('50','50'));
        limitOpts.add(new SelectOption('100','100'));
        limitOpts.add(new SelectOption('200','200'));
        limitOpts.add(new SelectOption('500','500'));
        limitOpts.add(new SelectOption('' + (oppLimit + 1), '全部'));
        
        limits = '50';
    }
    
    public PageReference init() {
        //20140822　追加 by katsu start
        String uidParam = System.currentPageReference().getParameters().get('uid');
        if (uidParam != null){
            User u = [select Id, FirstName, LastName from User where Id = :uidParam];
            ownerSearch = u.LastName + ' ' + u.FirstName;
        }
        String hpidParam = System.currentPageReference().getParameters().get('hpid');
        if(hpidParam != null){
            List<Account> hpAcc = ControllerUtil.selectAccountForTrigger(new String[] {hpidParam});
            if (hpAcc.size() > 0) {
                accSearch = hpAcc[0].name;
            }
        }
        //20140822　追加 by katsu end
        
        searchOppSetParam();
        setLayoutRWInfo();
        this.sortOrderAsc = true;
        this.sortOrder = new String[columus.size()];
        for (Integer i = 0; i < columus.size(); i++) this.sortOrder[i] = '　';
        searchOppInner();
        return null;
    }
    
    private void searchOppSetParam() {
//        if (accTypeForSort != accType) {
//            this.sortOrder = null;
//        }
        hpForSort = accSearch;
        ownerForSort = ownerSearch;
        datefieldForSort = dateField;
        fromdForSort = con1.Birthdate;
        todForSort = con2.Birthdate;
        textForSort = text;
        conditionForSort = condition;
        valueForSort = value;
        textForSort2 = text2;
        conditionForSort2 = condition2;
        valueForSort2 = value2;
        textForSort3 = text3;
        conditionForSort3 = condition3;
        valueForSort3 = value3;
        limitForSort = limits;
    }

    private void setLayoutRWInfo() {
        if (this.sortOrder == null) {
            // 获得项目set
            Map<String, Schema.FieldSet> fsMap = Schema.getGlobalDescribe().get('Repair__c').getDescribe().fieldSets.getMap();
            // 左 固定
            Schema.FieldSet fs = fsMap.get('Repair_PCL_L');
            // 获得项目set中的所有项目
            List<FieldSetMember> fsmList = fs.getFields();
            // 获得字段标签和字段名
            titleLeft = new List<String>();
            List<String> columnLeft = new List<String>();
            columnLeftCss = new List<String>();
            columnsLeftApi = new List<List<String>>();
            columnLeftRW = new Map<String, String>();
            for (FieldSetMember fsm : fsmList) {
                titleLeft.add(fsm.getLabel());
                columnLeft.add(fsm.getFieldPath());
                List<String> splitFieldPath = fsm.getFieldPath().split('\\.');
                columnsLeftApi.add(splitFieldPath);
                if (DESC_RW == null) {
                    columnLeftRW.put(fsm.getFieldPath(), 'r');
                } else if (splitFieldPath.size() == 1) {
                    String rw = DESC_RW.get(fsm.getFieldPath());
                    if (rw != null) {
                        columnLeftRW.put(fsm.getFieldPath(), rw);
                    } else {
                        columnLeftRW.put(fsm.getFieldPath(), 'r');
                    }
                } else {
                    columnLeftRW.put(fsm.getFieldPath(), 'r');
                }
            }
            for (String s : columnLeft) {
                if (columusSet.contains(s) == false) {
                    columus.add(s);
                    columusSet.add(s);
                }
                columnLeftCss.add(s.replace('.','_'));
            }
            fs = fsMap.get('Repair_PCL');
            // 获得项目set中的所有项目
            fsmList = fs.getFields();
            // 获得字段标签和字段名
            titleRight = new List<String>();
            List<String> columnRight = new List<String>();
            columnRightCss = new List<String>();
            columnsRightApi = new List<List<String>>();
            columnRightRW = new Map<String, String>();
            for (FieldSetMember fsm : fsmList) {
                titleRight.add(fsm.getLabel());
                columnRight.add(fsm.getFieldPath());
                List<String> splitFieldPath = fsm.getFieldPath().split('\\.');
                columnsRightApi.add(splitFieldPath);
                if (DESC_RW == null) {
                    columnRightRW.put(fsm.getFieldPath(), 'r');
                } else if (splitFieldPath.size() == 1) {
                    String rw = DESC_RW.get(fsm.getFieldPath());
                    if (rw != null) {
                        columnRightRW.put(fsm.getFieldPath(), rw);
                    } else {
                        columnRightRW.put(fsm.getFieldPath(), 'r');
                    }
                } else {
                    columnRightRW.put(fsm.getFieldPath(), 'r');
                }
            }
            for (String s : columnRight) {
                if (columusSet.contains(s) == false) {
                    columus.add(s);
                    columusSet.add(s);
                }
                columnRightCss.add(s.replace('.','_'));
            }
            strColumus = String.join(columus, ',');
            this.sortOrderAsc = true;
            this.sortOrder = new String[columus.size()];
            for (Integer i = 0; i < columus.size(); i++) this.sortOrder[i] = '　';
            system.debug('=====strColumus:' + strColumus);
        }
    }

    private void searchOppInner() {
        oppRecords = new List<RepairInfo>();

        String soql = this.makeSoql(false, hpForSort, ownerForSort, //deptForSort, rankForSort, conForSort,
                                    datefieldForSort, fromdForSort, todForSort, textForSort, conditionForSort, valueForSort,
                                    textForSort2, conditionForSort2, valueForSort2,
                                    textForSort3, conditionForSort3, valueForSort3);
        String userId = UserInfo.getUserId();
        String profileId = UserInfo.getProfileId();
        if (!profileId.left(15).equals(System.Label.Repaire_pclc_2)  //niwu 00e10000000xnpb
            && !profileId.left(15).equals(System.label.getProfileId_CU) //niwu 00e10000000Y3o5
            && !profileId.left(15).equals(System.label.Repaire_pclc_3)) { //niwu 00e10000000xnpC
            soql += ' and Incharge_Staff__c = \'' + userId + '\'';
        }

        // 状态1 为[0.删除]和[5.完毕]的不显示
        soql += ' and Status1__c != \'5.完毕\' and Status1__c != \'0.删除\' ';

        if (String.isBlank(this.sortKey)) {
            soql += ' order by LastModifiedDate desc limit ' + Integer.valueOf(limits);
        } else {
            soql += ' order by ' + this.columus[Integer.valueOf(this.sortKey)] + ' ' + (this.sortOrderAsc == true ? 'asc nulls first' : 'desc nulls last') + ' limit ' + Integer.valueOf(limits);
        }
        
        List<Repair__c> queryList = Database.query(soql);
        
        this.makeOppRecordsForView(queryList);
        
        oppCount = oppRecords.size();
        if (String.isBlank(this.sortKey)) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '取得最近的 ' + oppCount + ' 条数据'));
        } else {
            if (oppCount > oppLimit) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '数据超过' + oppLimit + '件，只显示前' + oppLimit + '件'));
            } else {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '共有 ' + oppCount + ' 条数据'));
            }
        }
    }

    public PageReference searchOpp() {
        searchOppSetParam();
        setLayoutRWInfo();
        searchOppInner();
        return null;
    }
    
    public PageReference sortTable() {
        oppRecords = new List<RepairInfo>();
        
        if (this.sortKey == this.preSortKey) {
            if (String.isBlank(this.sortKey) == false) {
                // 方向が変わるのみ
                this.sortOrderAsc = !this.sortOrderAsc;
                this.sortOrder[Integer.valueOf(this.sortKey)] = (this.sortOrderAsc == true ? '↑' : '↓');
            }
        } else {
            this.sortOrderAsc = true;
            if (String.isBlank(this.preSortKey) == false) {
                this.sortOrder[Integer.valueOf(this.preSortKey)] = '　';
            }
            this.sortOrder[Integer.valueOf(this.sortKey)] = (this.sortOrderAsc == true ? '↑' : '↓');
        }
        this.preSortKey = this.sortKey;
        
        setLayoutRWInfo();
        searchOppInner();
        return null;
    }
    
    public PageReference save() {
        try {
            List<Repair__c> updOpps = new List<Repair__c>();
            
            for (RepairInfo oi : oppRecords) {
                // 変更チェック
                if (oi.changeFlg == '1') {
                    oi.changeFlg = '0';
                    updOpps.add(oi.repair);
                }
            }
            
            if (updOpps.size() > 0) update updOpps;
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '保存完了'));
        } catch (Exception ex) {
            ApexPages.addMessages(ex);
            return null;
        }
        
        if (saveType == '1') {
            searchOpp();
            saveType = '';
        } else if (saveType == '2') {
            sortTable();
            saveType = '';
        } else {
        }
        return null;
    }
    
    public PageReference cancel() {
        return new PageReference('/home/home.jsp');
    }
    
    private String makeSoql(Boolean isforMoneyFlg, String accStr, String ownerStr, //String dept, String rank, Boolean consumable,
                            String datefield, Date fromd, Date tod, String txt, String con, String val,
                            String txt2, String con2, String val2,
                            String txt3, String con3, String val3) {
        String soql ='';
        if (isforMoneyFlg == false) {
            soql += 'select ' + strColumus
                + ' from Repair__c where RecordTypeId = \''+ System.label.Repaire_pclc+ '\'';
        } else {
 /*           soql += 'select Id, Name, Hospital__r.Name, Hospital__c, StageName__c, Status_Formula__c,'
                + ' Opportunity_No__c, AccountId, Account.Name, OwnerId, Owner.Name, Opportunity_Category__c,'
                + ' convertCurrency(Estimation_List_Price__c), Estimation_Id__c, Estimation_No__c, Last_Shipping_Scheduled_Date__c,  Last_Shipping_Date__c,'
                + ' Last_Follow_Up_Date__c, CreatedDate, LastModified_Day__c, Closing_Bid_Date__c, Important_Rroduct_Flg__c,'//Owner.Brief_Name__c,
                + ' Rating01__c, Rating02__c, Rating03__c, Rating04__c, Rating05__c, Rating06__c,'
                + ' Rating07__c, Rating08__c, Rating09__c, Rating10__c, Rating11__c, Rating12__c,'
                + ' HP_Name__c, Sales_incharge__c, convertCurrency(Wholesale_Price_F__c), Agency1__c, '//Estimation_List_Price_Formula__c, OCM_Agent1_Price_Formula__c,
                + ' Segment__c, Opp_Code__c, Open_Quotation__c, Competitor__c, Bid_Planned_Date__c,'
                + ' Close_Forecasted_Date__c, CloseDate, Follow_up_comment__c, Department_Name__c, '
                + ' Next_Action__c, Create_Activity__c, Nunber_of_visit__c, Number_of_OPD__c, Rating__c, '//Quotation_Number_SAP__c,,  Discount_Rate__c
                + ' OCM__c, convertCurrency(Amount_Without_Tax_F__c), Key_tipics_last_update_day__c, Update_situation__c , Last_opd_date__c,'
                + ' Stage2_last_update_day__c, Follow_up_plan_last_update__c, Closing_Bid_date_last_update_day__c, OPP_rank_Last_update_day__c, Situation_last_update_day__c, '
                + ' Opp_forecast_day_last_update_day__c, Tender_data_last_update_day__c, Forecast_amount_last_update_day__c, Forecast_shipping_day_last_update__c, Created_Day__c, '
                + ' Agency_Contract_Date1__c, Sales_Shop_Hospital_Contract__c, Manager_feedback__c, Forecast_this_month__c,'
                + ' Manager_feedback_last_update__c, Agency_Contract_Date_last_update__c, Agent_Hospital_Contract_day_last_update__c,'
                + ' Bid_Date__c, Bid_date_last_update_day__c, Collect_Customer_sign__c, Lapsed_Days__c,'
                + ' Owner.Salesdepartment__c, Owner.Province__c, Owner.Group__c'
                + ' from Opportunity where (RecordType.DeveloperName = \'Opportunity\')';// and (stageName = \'引合\')';*/
        }
        if (!String.isBlank(accStr)) {
            //soql += ' and Hospital__c = \'' + accStr + '\'';
            String[] vals = accStr.split(' ');
            for (String v : vals) {
                soql += ' and Hospital__r.Name like \'%' + String.escapeSingleQuotes(v.replaceAll('%', '\\%')) + '%\'';
            }
        }
        if (!String.isBlank(ownerStr)) {
            //soql += ' and OwnerId = \'' + ownerStr + '\'';
            String[] vals = ownerStr.split(' ');
            for (String v : vals) {
                soql += ' and CreatedBy.Name like \'%' + String.escapeSingleQuotes(v.replaceAll('%', '\\%')) + '%\'';
            }
        }
        
        if (!String.isBlank(datefield)) {
            if (fromd != null) {
                soql += ' and ' +  datefield + ' >= ' + String.valueOf(fromd).substring(0, 10);
            }
            if (tod != null) {
                soql += ' and (' +  datefield + ' <= ' + String.valueOf(tod).substring(0, 10) + ' OR ' + datefield + ' = null)';
            }
        }
        
        // xudan 20140507 検索ロジック修正
        soql += this.makeTextSql(txt, con, val);
        soql += this.makeTextSql(txt2, con2, val2);
        soql += this.makeTextSql(txt3, con3, val3);
        
        system.debug(soql);
        return soql;
    }
    
    private void makeOppRecordsForView(List<Repair__c> queryList) {
        Savepoint sp = Database.setSavepoint();
        // TODO queryList について、最初のoppLimitだけ更新すればOKです。
        Database.SaveResult[] results = Database.update(queryList, false);
        // 強制ロールバック
        Database.rollback(sp);
        
        for (Integer i = 0; i < queryList.size(); i++) {
            // limitを超えた場合前limit件のみを出す
            if (i == oppLimit + 1) {
                // TODO メッセージ表示
                continue;
            }
            oppRecords.add(new RepairInfo(queryList[i]));
            oppRecords[oppRecords.size() - 1].lineNo = oppRecords.size() - 1;
            if (!results[i].isSuccess()) {
                oppRecords[oppRecords.size() - 1].canEdit = false;
                // 空更新失敗の場合、編集できないとみなす
                // xudan 20140624 更新権限のエラーのみロック
                if (results[i].getErrors()[0].getStatusCode() != null) {
                    if (String.valueOf(results[i].getErrors()[0].getStatusCode()) == 'INSUFFICIENT_ACCESS_OR_READONLY') {
                        oppRecords[oppRecords.size() - 1].hasError = true;
                    // xudan 20140624 更新権限エラーとほかのエラーを区別
                    } else {
                        oppRecords[oppRecords.size() - 1].hasFieldError = true;
                    }
                }
            }
        }
    }
    
    private String makeTextSql(String txt1, String con, String val) {
        String soql = '';
        // containsの場合、日報画面の病院検索を真似し、spaceで分けて、and検索
        // equalsの場合、SF標準の検索を真似し、「,」で分けて、or検索
        if (!String.isBlank(txt1)) {
            if ((con == 'contains' || con == 'notcontains') && val.contains(' ')) {
                String[] vals = val.split(' ');
                String cSql = '';
                for (String v : vals) {
                    cSql += this.makeTextSqlStr(txt1, con, v);
                }
                if (con == 'contains') {
                    soql += cSql;
                } else {
                    // notcontains
                    cSql = cSql.replaceAll(' and ', ') and (NOT ');
                    soql += cSql.substring(1) + ') ';
                }
            } else if ((con == 'equals' || con == 'notequals') && val.contains(',')) {
                String[] vals = val.split(',');
                if (vals.size() > 0) {
                    String txt = txt1.substring(2);     // S:Name 、最初の２文字がタイプです
                    soql += ' and ( ';
                    for (String v : vals) {
                        if (con == 'equals') {
                            soql += txt + ' = \'' + v + '\' or ';
                        } else {
                            // notequals
                            soql += txt + ' <> \'' + v + '\' and ';
                        }
                    }
                    soql = soql.substring(0, soql.length() - 4);
                    soql += ')';
                }
            } else {
                String cSql = this.makeTextSqlStr(txt1, con, val);
                if (con != 'notcontains') {
                    soql += this.makeTextSqlStr(txt1, con, val);
                } else {
                    // notcontains
                    cSql = cSql.substring(5);       // ' and ' の5文字を外す
                    soql += ' and (NOT ' + cSql + ') ';
                }
            }
        }
        return soql;
    }
    
    /**
     * 文字列検索文を作成
     */ 
    private String makeTextSqlStr(String txt1, String con, String val) {
        String soql = '';
        if (!String.isBlank(txt1)) {
            String txt = txt1.substring(2);
            String colType = txt1.substring(0, 2);
            String tmpVal = val;
            // 空白の場合''にする
            if (String.isBlank(tmpVal)) {
                if (con == 'equals') {
                    //soql += ' and ' + txt + ' = ' + tmpVal;
                    soql += ' and ' + txt + ' = null';
                } else if (con == 'notequals') {
                    soql += ' and ' + txt + ' <> null';
                } else {
                    // 空白の場合、contains, notcontains と starts withは無視
                }
            } else {
                soql += ' and ' + txt;
                if (con == 'equals') {
                    if (colType == 'S:') {
                        soql += ' = \'' + tmpVal + '\'';
                    } else {
                        soql += ' = ' + tmpVal + ' ';
                    }
                } else if (con == 'notequals') {
                    if (colType == 'S:') {
                        soql += ' <> \'' + tmpVal + '\'';
                    } else {
                        soql += ' <> ' + tmpVal + ' ';
                    }
                } else if (con == 'contains' || con == 'notcontains') {
                    soql += ' like \'%' + String.escapeSingleQuotes(tmpVal.replaceAll('%', '\\%')) + '%\'';
                } else if (con == 'starts with') {
                    soql += ' like \'' + String.escapeSingleQuotes(tmpVal.replaceAll('%', '\\%')) + '%\'';
                } else {
                    if (colType == 'S:') {
                        soql += ' ' + con + '\'' + tmpVal + '\'';
                    } else {
                        soql += ' ' + con + ' ' + tmpVal + ' ';
                    }
                }
            }
        }
        return soql;
    }
    
    /**
     * 現在の月にて、表示すべきラベル名を作成
     */
/*    private Integer makeRatingLabel(Integer idx) {
        Integer m = Date.today().month();
        
        Integer val = idx - 1 + m;
        if (val > 12) {
            val = val - 12;
        }
        return val;
    }*/
    
    /**
     * 現在の月にて、Ratingのソート番号を作成
     */
/*    private Integer makeRatingSortIdx(Integer idx) {
        Integer m = Date.today().month();
        
        Integer val = idx - 1 + m;
        if (val > 29) {
            val = val - 12;
        }
        return val;
    }*/
    
    class RepairInfo {
        public Repair__c repair { get; set; }
        public Boolean canEdit { get; private set; }
        public Boolean hasError { get; private set; }
        public Boolean hasFieldError { get; private set; }
        public Integer lineNo { get; private set; }
        public String changeFlg { get; set; }
        
        public RepairInfo(Repair__c record) {
            repair = record;
            canEdit = true;
            hasError = false;
            hasFieldError = false;
            lineNo = 0;
            changeFlg = '0';
        }
    }
}