public without sharing class NewQuoteEntryController {
    public Integer quoteEntryMaxLine {get; private set;}
    public Integer quoteEntryMaxSet {get; private set;}

    public Id oppId { get; set; }
    public Id quoId {get;set;}
    public Id pricebook2Id {get;set;}
    public Id accountId {get;set;}
    public String currencyIsoCode {get;set;}

    public boolean specialerrorflg {get;set;}
    public boolean errorflg {get;set;}
    public String errorMessage {get;set;}

    public boolean Messageflg {get;set;}
    public String Message {get;set;}
    
    public Quote quo {get;set;}
    public Decimal discount {get;set;}
    public List<QELine> activities {get;set;}
    private List<QELine> activitiesbk;
    public List<QELine> tmpactivities = new List<QELine>();
    public QELine active_activity;
    public Boolean productStatusUpdated;
    public List<Boolean> hidFlg {get;set;}
    public String excel_text { get; set; }
    public String baseUrl { get; set; }
    public String rtUrl { get; set; }

    public boolean decideFlg { get; set; }
    public boolean isdecide { get; set; }
    public boolean printFlg { get; set; }
    private boolean doDecide { get; set; }
    public String productSegment { get; set; }
    public boolean isAdmin { get; set; }

    public String fileName { get; set; }
    public String strExpirationDate { get; set; }
    public List<QELine> csv_activities {get;set;}
    public Blob contentFile { get; set; }
    public String nameFile { get; set; }

    public String openType { get; set; }
    public boolean isService { get; set; }
    public boolean is_Parts_direct { get; set; }
    public boolean is_Parts_dealer { get; set; }
    public boolean is_hidden_user { get; set; }
    public boolean is_dealer_user { get; set; }

    public boolean is_hidden_all { get; set; }
    public Decimal dealer_coefficient { get; set; }

    public Boolean specialDealer { get; set; }
    //XHL-20190426-AddStart
    public String setProduct_text { get; set; }
    public Integer activitiesSize {get;set;}
    public Integer singleNo {get;set;}
    public Map<String,String> errorMap {get;set;}
    public String singleProduct {get; private set;}
    public Map<String,String> quoteLineSetNameDiscountMap {get; private set;}
    public String quoteLineSetNameDiscountJson {get; private set;}
    //XHL-20190426-AddEnd
    public Opportunity opp {get;set;}

    // WLIG-BTA8C2 XHL 20200925 -Start
    public String initStringConcatenation;
    public String saveStringConcatenation;
    public Boolean verifyProductValidFlag;
    // WLIG-BTA8C2 XHL 20200925 -End
    private static Map<String, String> paymentTermsMap = new Map<String, String> {
        'Z001' => '预收款/预付款',
        'Z002' => '立即付款',
        'Z003' => '月结30天内付款',
        'Z004' => '月结60天内付款',
        'Z005' => '月结90天内付款',
        'Z006' => '月结120天内付款',
        'Z007' => '月结25天内付款',
        'Z008' => '月结55天内付款',
        'Z009' => '月结85天内付款',
        'Z010' => '月结115天内付款',
        'Z011' => '月结175天内付款',
        'Z012' => '月结205天内付款',
        'Z013' => '半月结，15日之前发货，当月15日到期',
        'Z014' => '月结30天内付款',
        'Z015' => '验收后15天电汇',
        'Z020' => '100%发货后30天内支付',
        'Z021' => '100%发货后60天内电汇支付',
        'Z030' => '收到发票后30天内电汇',
        'Z045' => '月结45天内付款',
        'Z060' => '收到发票后60天内电汇',
        'Z075' => '收到发票后75天内电汇',
        'Z090' => '收到发票后90天内电汇',
        'Z0LC' => '100% L/C (90/10)',
        'Z120' => '收到发票后120天内电汇',
        'Z1LC' => '100% L/C (80/20)',
        'Z1TT' => '90%TT ADV，10%TT AFTER',
        'Z2LC' => '100% L/C (70/30)',
        'Z2TT' => '80%TT ADV，20%TT AFTER',
        'Z30E' => '下月末',
        'Z3LC' => '100% L/C 90 days',
        'Z3TT' => '70%TT ADV，30%TT AFTER',
        'Z4LC' => '90%L/CTransfer 10%TT AFTER',
        'Z4TT' => '100% TT AFTER',
        'Z5LC' => '100%L/C at sight Transfer',
        'Z5TT' => '30% TT ADV，50% TT AT SIGHT，20% TT AFTER',
        'Z60E' => '下2个月末',
        'Z6LC' => '100%L/C (85/15)',
        'Z6TT' => '30% TT ADV，60% TT AT SIGHT，10% TT AFTER',
        'Z7LC' => '100% L/C (60/40)',
        'Z7TT' => '100％TT AFTER(80/20)',
        'Z8TT' => '100% TT AFTER（70/30）',
        'Z9TT' => '100%TT发货后20天内支付',
        'ZCOD' => 'C.O.D.',
        'ZD60' => '立即应付的 到期净值',
        'ZFR1' => '半月结，15日之前发货，当月15日到期',
        'ZL6T' => '90% LC 60 days，10% TT AFTER',
        'ZL95' => '95% L/C AFTER,5% L/C AFTER 6M FROM ACCEPTANCE DATE',
        'ZLC1' => '100% L/C (90/10) Transfer',
        'ZLC2' => '100% L/C AT SIGHT (95/5)',
        'ZLT1' => '90%LC，10%TT',
        'ZLT2' => '80%LC，20%TT',
        'ZLT3' => '70%LC，30%TT',
        'ZLT4' => '95%LC，5%TT',
        'ZLT5' => '50%L/C，50%TT after',
        'ZT20' => '20% T/T ADV,80% T/T AFTER',
        'ZT30' => '30% T/T ADV, 70%T/T AFTER',
        'ZT35' => '35% TT ADV，65% TT AFTER',
        'ZT40' => '40% TT ADV，60% TT AFTER',
        'ZT50' => '50% TT ADV，50% TT AFTER',
        'ZT55' => '95%TT ADV，5%TT AFTER',
        'ZT90' => '验收合格后T/T支付90%，设备正常运行三个月T/T支付10%',
        'ZTT1' => 'TT AFTER DELIVERY 45 DAY',
        'ZTT2' => 'TT AFTER DELIVERY 120 DAY',
        'ZTT3' => '100%TT发货后15个工作日内支付',
        'ZTT4' => '验收合格后T/T支付80%，设备正常运行三个月T/T支付20%',
        'ZZ60' => '60 DAYS AFTER ISSUING INVOICE',
        'ZZ95' => '95% L/C AFTER,5% T/T AFTER 6M FROM ACCEPTANCE DATE',
        'ZZLC' => '100% L/C AT SIGHT',
        'ZZTT' => '100% TT IN ADVANCE',
        'Z022' => '100% T/T WITHIN 90 DAYS AFTER SHIPMENT'
    };

    public NewQuoteEntryController() {

        initStringConcatenation = '';
        saveStringConcatenation = '';
        verifyProductValidFlag = false;


        singleProduct  = System.Label.SingleProduct;
        quoteEntryMaxLine = Integer.valueOf(System.Label.QuoteEntryMaxLine);
        quoteEntryMaxSet = Integer.valueOf(System.Label.QuoteEntryMaxSet);
        hidFlg = new List<Boolean>(30);
        for (Integer i = 0; i < 30; i++) {
            if (i<quoteEntryMaxSet) {
                hidFlg[i] = true;
            } else {
                hidFlg[i] = false;
            }
        }

        productStatusUpdated = false;
        baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
        String path = URL.getCurrentRequestUrl().getPath();
        if (path.indexOf('/apex') > 0) {
            baseUrl += path.substring(0,path.indexOf('/apex'));
        } else if (path.indexOf('production/') > 0) {
            baseUrl += '/production';
        }
        rtUrl = System.currentPageReference().getParameters().get('retURL');
        System.debug('path: ' + path);
        System.debug('baseUrl: ' + baseUrl);
        System.debug('rtUrl: ' + rtUrl);
        if (rtUrl == null || rtUrl == 'null') {
            rtUrl = '';
        }

        //system.debug('22222222222222' + quo);
    }

    public NewQuoteEntryController(ApexPages.StandardController controller) {
        this();
    }

    public void init () {
        specialerrorflg = false ;
        activitiesSize = 0;
        errorflg = false;
        errormessage = null;

        decideFlg = false;
        isdecide = false;
        printFlg = false;
        doDecide = false;
        productSegment = '';
        errorMap = new Map<String,String>();
        quoteLineSetNameDiscountMap = new Map<String,String>();
        quoteLineSetNameDiscountJson = '';
        isAdmin = false;
        String profileId = UserInfo.getProfileId();
        profileId = profileId.substring(0, 15);

        //新的获取简档ID  calendarUtil.getMemberProfileID  这里用到的人员ID 和获取到的简档ID都是15位的
        String new_profileId = calendarUtil.getMemberProfileID(UserInfo.getUserId().subString(0,15));

        //system.debug('profileId_20190517_' + profileId);
        String userid = UserInfo.getUserId();
        User loginUser = [select id, CanCancelDecideQuote__c from user where Id = :userid];
        if (new_profileId == System.Label.SystemAdmin || new_profileId == System.Label.SystemAdmin2 
            || new_profileId == System.Label.SystemAdmin || new_profileId == System.Label.SystemAdmin2
            || loginUser.CanCancelDecideQuote__c == true) {
            isAdmin = true;
        }

        openType = System.currentPageReference().getParameters().get('openType');
        isService = openType == 'service' ? true : false;
        is_Parts_direct = false;
        is_Parts_dealer = false;
        is_hidden_user = false;

        if (profileId == System.Label.RT_BS_No_Price || new_profileId == System.Label.RT_BS_No_Price) {// || profileId == System.Label.SystemAdmin) {
            is_hidden_user = true;
            //system.debug('is_hidden_user_1_1_1_1_' + is_hidden_user);
        }
        is_dealer_user = false;
        //system.debug('UserInfo.getUserType()__20190517_'+UserInfo.getUserType());
        //system.debug('UserInfo.getUserId()__20190517_1_'+UserInfo.getUserId().substring(0, 15));

        if (UserInfo.getUserType() == 'PowerPartner' || UserInfo.getUserId().substring(0, 15) == '00528000002PBPf') {
            is_dealer_user = true;
            //system.debug('is_dealer_user_1_1_1_1_' + is_dealer_user);
        }

        is_hidden_all = false;
        specialDealer = false;

        //Quote
        
        //system.debug('quo---cccc: '+quo);
        quo = new Quote();
        quo.Quote_Type__c = 'sales';
        if (isService == true) {
            quo.Quote_Type__c = 'service';
        }
        quo.Comment__c  = '1)  The payment terms are - .\n';
        quo.Comment__c += '付款方式 - 。\n';
        quo.Comment__c += '2)  Quoation valid until - .\n';
        quo.Comment__c += '报价有效期到 - 。\n';
        quo.Comment__c += '3)  All the commodoties come with - year\'s manufacturer warranty.\n';
        quo.Comment__c += '所有商品含 - 年厂家保修。\n';
        if (isService == false) {
            quo.Comment__c += '4)  The above quotations are - prices, Commodoties shipped to the clien\'s requirements.\n';
            quo.Comment__c += '上述报价为 - 价，商品送至客户指定地点。\n';
            quo.Comment__c += '5)  The above quotations are all - .\n';
            quo.Comment__c += '上述报价均为 - 价。\n';
            quo.Comment__c += '6)  Configuration as per attached.\n';
            quo.Comment__c += '配置清单详见附件。';
        } else {
            quo.Comment__c += '4)  The above quotations are all - .\n';
            quo.Comment__c += '上述报价均为 - 价。\n';
            quo.Comment__c += '5)  Configuration as per attached.\n';
            quo.Comment__c += '配置清单详见附件。';
        }

        if (isService == true) {
            quo.SetName1__c = '零件费用';
            quo.SetQty1__c = 1;
            quo.SetName2__c = '维修费';
            quo.SetQty2__c = 1;
            quo.SetName3__c = '其他费用';
            quo.SetQty3__c = 1;
        }
       
        quo = new Quote();
        quo.Quote_Type__c = 'sales';
        if (isService == true) {
            quo.Quote_Type__c = 'service';
        }
        quo.Comment__c  = '1)  The payment terms are - .\n';
        quo.Comment__c += '付款方式 - 。\n';
        quo.Comment__c += '2)  Quoation valid until - .\n';
        quo.Comment__c += '报价有效期到 - 。\n';
        quo.Comment__c += '3)  All the commodoties come with - year\'s manufacturer warranty.\n';
        quo.Comment__c += '所有商品含 - 年厂家保修。\n';
        if (isService == false) {
            quo.Comment__c += '4)  The above quotations are - prices, Commodoties shipped to the clien\'s requirements.\n';
            quo.Comment__c += '上述报价为 - 价，商品送至客户指定地点。\n';
            quo.Comment__c += '5)  The above quotations are all - .\n';
            quo.Comment__c += '上述报价均为 - 价。\n';
            quo.Comment__c += '6)  Configuration as per attached.\n';
            quo.Comment__c += '配置清单详见附件。';
        } else {
            quo.Comment__c += '4)  The above quotations are all - .\n';
            quo.Comment__c += '上述报价均为 - 价。\n';
            quo.Comment__c += '5)  Configuration as per attached.\n';
            quo.Comment__c += '配置清单详见附件。';
        }

        if (isService == true) {
            quo.SetName1__c = '零件费用';
            quo.SetQty1__c = 1;
            quo.SetName2__c = '维修费';
            quo.SetQty2__c = 1;
            quo.SetName3__c = '其他费用';
            quo.SetQty3__c = 1;
        }

        //Opportunityid
        Opportunity oppRecord = null;
        if (oppId==null) {
            oppId = System.currentPageReference().getParameters().get('oppid');

            if (oppId==Null) {
                quoId = System.currentPageReference().getParameters().get('Id');

                List<Quote> ql = New List<Quote>();
                ql = [select Id,OpportunityId From Quote Where Id =:quoId];
                if (ql.size()>0) {
                    oppId = ql[0].OpportunityId;
                }
            } 

            List<Opportunity> oppList = New List<Opportunity>();
            oppList = [select Id,Pricebook2Id,CurrencyIsoCode,AccountId,Is_Decided__c,ProductSegment__c,Machine_Parts__c,SalesChannel__c,Dealer__r.DummyDealer__c,
                              IE_Discount_Normal__c,Subuse__c,IE_Discount_Special__c,Dealer_Code__c,Province__c,Dealer_Rank__c,Dealer__r.ParentId,Account.MarketVerticals__c,Trade_Type_D__c,
                              DealerId__c 
                         From Opportunity Where Id =:oppId];

            if (oppList.size()>0) {
                opp = oppList[0];
                oppRecord = oppList[0];
                pricebook2Id = oppList[0].Pricebook2Id;
                currencyIsoCode = oppList[0].CurrencyIsoCode;
                accountId = oppList[0].AccountId;
                decideFlg = oppList[0].Is_Decided__c;
                productSegment = oppList[0].ProductSegment__c;
                if (oppList[0].Machine_Parts__c == 'Parts' && oppList[0].SalesChannel__c == 'direct') {
                    is_Parts_direct = true;
                } else if (oppList[0].Machine_Parts__c == 'Parts' && oppList[0].SalesChannel__c == 'dealer') {
                    is_Parts_dealer = true;
                }
               
                //if(specialdealer == true){
                   //is_hidden_all = true;
                //}
            }
        }
        //specialDealer = StaticParameter.specialDealerMap.containsKey(((String)opp.DealerId__c).substring(0,15));
        //specialDealer = IfspecialDealer(opp.DealerId__c);
        if (opp != null) {
            specialDealer = IfspecialDealer(opp.DealerId__c);
            if(specialDealer == true){
                is_hidden_all = true;
            }
        }
        Boolean updateOrCopy = false;
        quoId = System.currentPageReference().getParameters().get('Id');

        if (quoId==null){
            quoId = System.currentPageReference().getParameters().get('copyid');
            if (quoId!=null){ 
                updateOrCopy = true;
            }
        } else {
            updateOrCopy = false;
        }

        Integer i;
        
        if (quoId==null){

            List<Quote> qlCk = New List<Quote>();
                qlCk = [select Id,OpportunityId,Opportunity.DealerId__c,OrderIsChange__c From Quote Where OpportunityId =:oppId];
            if (qlCk.size()>0) {
                //specialDealer =  StaticParameter.specialDealerMap.containsKey(qlCk[0].Opportunity.DealerId__c);
                specialDealer = IfspecialDealer(qlCk[0].Opportunity.DealerId__c);
                if(specialDealer == true){
                    is_hidden_all = true;
                }
                if (activities==null){
                    activities = new List<QELine>();
                    for (i=0;i<quoteEntryMaxLine;i++){
                        QELine active_activity = new QELine(i);
                        activities.add(active_activity);
                    }
                }

            } else {
                Integer k;
                List<OpportunityLineItem> oppItemList = New List<OpportunityLineItem>();
                oppItemList = [select Id,Product2Id,ProductCode,Product2.Product_ECCode__c,Product2.Name,Quantity,UnitPrice,Description,PricebookEntryId,
                                      PricebookEntry.SalesPrice__c,PricebookEntry.SalesPriceA__c,PricebookEntry.SalesPriceB__c,
                                      PricebookEntry.SalesPriceC__c,Product2.ProductModels__c,PricebookEntry.Hidden_flag__c,
                                      Opportunity.DealerId__c
                                 From OpportunityLineItem
                                Where OpportunityId =:oppId];
                if (oppItemList.size()>0) {
                    k = oppItemList.size();
                } else {
                    k = 0;
                }
                //新規リストコントローラの取得
                if (activities==null){
                    activities = new List<QELine>();
                    for (i=0;i<quoteEntryMaxLine;i++){
                        QELine active_activity = new QELine(i);
                        if (i<k) {
                            active_activity.productName = oppItemList[i].Product2.Name;
                            active_activity.productCode = oppItemList[i].ProductCode;
                            active_activity.productEC = oppItemList[i].Product2.Product_ECCode__c;
                            active_activity.pageObject.Quantity = oppItemList[i].Quantity;
                            active_activity.pageObject.UnitPrice = oppItemList[i].UnitPrice;
                            active_activity.pageObject.Description = oppItemList[i].Description;
                            active_activity.totalPrice = oppItemList[i].Quantity * oppItemList[i].UnitPrice;
                            if (isService == true) {
                                active_activity.setName = '零件费用';
                            } else {
                                active_activity.setName = '单品';
                            }
                            active_activity.pageObject.Set__c = '单品';
                            active_activity.pageObject.SingleProduct__c = true;
                            active_activity.pageObject.PricebookEntryId = oppItemList[i].PricebookEntryId;
                            active_activity.salesPrice = oppItemList[i].PricebookEntry.SalesPrice__c;
                            active_activity.salesPriceA = oppItemList[i].PricebookEntry.SalesPriceA__c;
                            active_activity.salesPriceB = oppItemList[i].PricebookEntry.SalesPriceB__c;
                            active_activity.salesPriceC = oppItemList[i].PricebookEntry.SalesPriceC__c;

                            active_activity.isProductModel = oppItemList[i].Product2.ProductModels__c;

                            active_activity.hiddenflg = oppItemList[i].PricebookEntry.Hidden_flag__c;
                            //StaticParameter.specialGroupMap.
                            //specialDealer =  StaticParameter.specialDealerMap.containsKey(oppItemList[i].Opportunity.DealerId__c);
                            specialDealer = IfspecialDealer(oppItemList[i].Opportunity.DealerId__c);
                            if(specialDealer == true){
                                is_hidden_all = true;
                            }
                            //system.debug();
                            //ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '请选择目标客户---->'+oppItemList[i].Opportunity.DealerId__c));
                            if (specialDealer || is_hidden_user == true || is_dealer_user == true && oppItemList[i].PricebookEntry.Hidden_flag__c == true) {
                                active_activity.pageObject.UnitPrice = 0;
                                active_activity.totalPrice = 0;
                                system.debug('<---is_hidden_all--->03' + is_hidden_all);
                                is_hidden_all = true;
                                discount = 0;
                            }
                        }
                        activities.add(active_activity);
                    }
                }
            }
            
        } else {
            system.debug('○○○○○○○○○○○○Welcome to edit class!!○○○○○○○○○○○○');

            String accountid;

            List<Quote> quoList = 
                [ SELECT Id,Name,QuoteNumber,Account.Name,ExpirationDate,Subtotal,Discount,TotalPrice,GrandTotal,PrintPrice__c,ShippingHandling,
                    DeliveryLeadTime__c,PaymentTerms__c,ValidDate__c,Warranty__c,SetName1__c,Is_Decided__c,Shipment_Term__c,Shipment_Term2__c,
                    SetName2__c,SetName3__c,SetName4__c,SetName5__c,SetName6__c,SetName7__c,SetName8__c,SetName9__c,SetName10__c,
                    SetName11__c,SetName12__c,SetName13__c,SetName14__c,SetName15__c,SetName16__c,SetName17__c,SetName18__c,SetName19__c,
                    SetName20__c,SetName21__c,SetName22__c,SetName23__c,SetName24__c,SetName25__c,SetName26__c,SetName27__c,SetName28__c,SetName29__c,
                    SetName30__c,SetQty1__c,SetQty2__c,SetQty3__c,SetQty4__c,SetQty5__c,SetQty6__c,SetQty7__c,SetQty8__c,SetQty9__c,SetQty10__c,SetQty11__c,
                    SetQty12__c,SetQty13__c,SetQty14__c,SetQty15__c,SetQty16__c,SetQty17__c,SetQty18__c,SetQty19__c,SetQty20__c,SetQty21__c,SetQty22__c,SetQty23__c,
                    SetQty24__c,SetQty25__c,SetQty26__c,SetQty27__c,SetQty28__c,SetQty29__c,SetQty30__c,Comment__c,Custom_Price_Total__c,Custom_Price_Total_Text__c,Quote_Type__c,
                    Main_Model__c,Main_Serial_Number__c,Service_Type__c,Contract_Number__c,Service_Date__c,Service_Finish_Date__c,Service_Engineer_Sign__c,
                    Service_Pickup_Sign__c,Service_Check_Sign__c,Service_Location__c,Service_Status__c,Service_Content__c, Is_upload__c, Total_Price_Text__c,
                    Discount_Normal__c,Discount_Special__c,OrderIsChange__c 
                    FROM Quote Where Id =:quoId];
            List<QuoteLineItem> items = 
                [Select Id,Product2Id,Product2.Name,Product2.ProductCode,Product2.Product_ECCode__c,Quantity,Subtotal,Discount,TotalPrice,PricebookEntryId,UnitPrice,Description,Set__c,Custom_Price__c,
                        PricebookEntry.SalesPrice__c,PricebookEntry.SalesPriceA__c,PricebookEntry.SalesPriceB__c,PricebookEntry.SalesPriceC__c,Product2.ProductModels__c,PricebookEntry.Hidden_flag__c,
                        SingleProduct__c,SetName__c,
                        Quote.Opportunity.DealerId__c
                   From QuoteLineItem where Quoteid = :quoId Order by Id];

            //system.debug('quoList==========>'+quoList);
            //system.debug('items==========>'+items);

            if (quoList.size() > 0) {
                if (updateOrCopy) {

                    quo = quoList[0];
                    quo.Id = null;
                    quo.name = null;
                    quo.Is_Decided__c = false;
                    quo.Is_upload__c = false;
                } else {
                    quo = quoList[0];
                }
                isdecide = quo.Is_Decided__c;
            }

            if (updateOrCopy) {
                quoId = null;
            }
            quoteLineSetNameDiscountMap = new Map<String,String>();
            activities = new List<QELine>();
            i=0;
            QELine c = new QELine(i);

            if (items.size()>0) {
                for (QuoteLineItem o:items) {

                    if (String.isNotBlank(o.SetName__c)) {
                        quoteLineSetNameDiscountMap.put(o.SetName__c,String.valueOf(o.Discount));
                    }
                    String setName = o.Set__c;
                    Integer qty = 1;
                    if (setName != null) {
                        //XHL-20190426-UpdateStart
                        if (!o.SingleProduct__c) {
                            
                            String fieldName = setName.substring(3);
                            fieldName = fieldName.indexOf('0') == 0 ? fieldName.substring(1) : fieldName;
                            Decimal d_qty = (Decimal) quo.get('SetQty' + fieldName + '__c');
                            qty = d_qty == null ? 1 : d_qty.intValue();
                        }
                        //XHL-20190426-UpdateEnd 
                        
                    }
                    c = new QELine(isService,o,i,o.Product2.Name,o.Product2.ProductCode,o.Product2.Product_ECCode__c,qty,o.Product2.ProductModels__c,o.SingleProduct__c,o.SetName__c);
                    //specialDealer =  StaticParameter.specialDealerMap.containsKey(o.Quote.Opportunity.DealerId__c);
                    specialDealer = IfspecialDealer(o.Quote.Opportunity.DealerId__c);
                    if(specialDealer == true){
                        is_hidden_all = true;
                    }
                    //ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '请选择目标客户----2>'+o.Quote.Opportunity.DealerId__c));
                    //ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '请选择目标客户----n>'+specialDealer));

                    if ( specialDealer || is_hidden_user == true || is_dealer_user == true && c.hiddenflg == true) {
                        c.pageObject.UnitPrice = 0;
                        c.totalPrice = 0;
                        c.customPrice = 0;
                        system.debug('<---is_hidden_all---04>' + is_hidden_all);
                        is_hidden_all = true;
                        discount = 0;
                    }
                    activities.add(c);
                    i++;

                    if (quo.OrderIsChange__c) {
                        String productCode = o.Product2.ProductCode;
                        if (String.isNotBlank(productCode)) {
                             
                            initStringConcatenation += productCode + '|' + o.Quantity;
                        }
                        
                    }
                }

                for (integer j=i;j<quoteEntryMaxLine;j++) {
                    c = new QELine(j);
                    activities.add(c);
                }
                quoteLineSetNameDiscountJson(quoteLineSetNameDiscountMap);
                
            } else {
                activities = new List<QELine>();
                for (i=0;i<quoteEntryMaxLine;i++) {
                    QELine active_activity = new QELine(i);
                    activities.add(active_activity);
                }
            }

system.debug('=====is_hidden_all:' + is_hidden_all);
            if (is_hidden_all) {
                discount = quo.totalPrice.setScale(2, System.RoundingMode.HALF_UP);
            } else {
                discount = quo.Discount == null ? 0 : quo.Discount;

                discount = discount.setScale(2, System.RoundingMode.HALF_UP);
            }
system.debug('=====discount:' + discount);

            if (quoId != null) {
                printFlg = true;
            }

            system.debug('○○○○○○○○○○○○ edit class  End!!○○○○○○○○○○○○');
        }

        Map<String, Decimal> ddMap = new Map<String, Decimal>();
        String key1 = '';
        String key2 = '';
        List<Dealer_Discount__c> ddList = [select id, Dealer_Rank_F__c,Product_Segment__c, DimensionField1__c, DimensionField2__c, DimensionValue1__c, DimensionValue2__c, Dealer_Rank__c from Dealer_Discount__c where Product_Segment__c = :productSegment];
        for (Dealer_Discount__c dd : ddList) {
            ddMap.put(dd.DimensionValue1__c + '|' + dd.DimensionValue2__c, dd.Dealer_Rank_F__c);
            key1 = dd.DimensionField1__c == null ? '' : dd.DimensionField1__c;
            key2 = dd.DimensionField2__c == null ? '' : dd.DimensionField2__c;
        }

        String keyF = ((key1 == '' || oppRecord.get(key1) == null) ? 'null' : oppRecord.get(key1)) + '|' + ((key2 == '' || oppRecord.get(key2) == null) ? 'null' : oppRecord.get(key2));

        quo.Discount_Normal__c = 100 - (ddMap.get(keyF) == null ? 100.0 : ddMap.get(keyF));
        dealer_coefficient = quo.Discount_Normal__c;
system.debug('=====keyF:' + keyF);
system.debug('=====Discount_Normal__c:' + quo.Discount_Normal__c);
        activitiesSize = activities.size();

        system.debug(specialDealer);
    }

    public PageReference Refresh() {

        List<Id> Idlist = New List<Id>();
        for (QELine t:activities) {
            Idlist.add(t.pageObject.PricebookEntryId);
        }

        if (Idlist.size()==0) {
            errorflg = true;
            errormessage = System.Label.Error_Message01;
            return null;
        }

        //List<PricebookEntry> pbes = [
        //            select Id,Product2Id,ProductCode,Product2.Product_ECCode__c,SalesPrice__c,SalesPriceA__c,SalesPriceB__c,SalesPriceC__c,Hidden_flag__c,Product2.ProductStatus__c
        //            FROM PricebookEntry where Id in :Idlist];
        //20191113-XHL---Start-将产品状态用产品状态(公式)替换
        List<PricebookEntry> pbes = [
                    select Id,Product2Id,ProductCode,Product2.Product_ECCode__c,SalesPrice__c,SalesPriceA__c,SalesPriceB__c,SalesPriceC__c,Hidden_flag__c,Product2.ProductStatus__c,Product2.ProductStatusFormula__c
                    FROM PricebookEntry where Id in :Idlist];
        //20191113-XHL---End-将产品状态用产品状态(公式)替换
        if (pbes.size()==0) {
            errorflg = true;
            errormessage = System.Label.Error_Message01;
            return null;
        }

        Map<String, PricebookEntry> tempMap = new Map<String, PricebookEntry>();

        for (PricebookEntry pbe:pbes) {
            tempMap.put(pbe.Id, pbe);
        }
        system.debug('<---is_hidden_all---05>' + is_hidden_all);
        is_hidden_all = false;
        for (QELine t:activities) {
            PricebookEntry tmpPbe = tempMap.get(t.pageObject.PricebookEntryId);
            if (tmpPbe != null) {
                if (tmpPbe.SalesPrice__c != null && tmpPbe.Product2.ProductStatus__c == '1' && ( specialDealer == false && is_hidden_user == false && (is_dealer_user == false || tmpPbe.Hidden_flag__c == false))) {
                //20191113-XHL---将产品状态用产品状态(公式)替换
                //if (tmpPbe.SalesPrice__c != null && tmpPbe.Product2.ProductStatusFormula__c == '1' && (is_hidden_user == false && (is_dealer_user == false || tmpPbe.Hidden_flag__c == false))) {
                    t.pageObject.UnitPrice = tmpPbe.SalesPrice__c;
                    t.salesPrice = tmpPbe.SalesPrice__c;
                    t.salesPriceA = tmpPbe.SalesPriceA__c;
                    t.salesPriceB = tmpPbe.SalesPriceB__c;
                    t.salesPriceC = tmpPbe.SalesPriceC__c;
                } else if (tmpPbe.SalesPrice__c != null && tmpPbe.Product2.ProductStatus__c == '0' && ( specialDealer == false && is_hidden_user == false && (is_dealer_user == false || tmpPbe.Hidden_flag__c == false))) {
                //20191113-XHL---将产品状态用产品状态(公式)替换
                //} else if (tmpPbe.SalesPrice__c != null && tmpPbe.Product2.ProductStatusFormula__c == '0' && (is_hidden_user == false && (is_dealer_user == false || tmpPbe.Hidden_flag__c == false))) {
                    t.pageObject.UnitPrice = 0;
                    t.salesPrice = 0;
                    t.salesPriceA = 0;
                    t.salesPriceB = 0;
                    t.salesPriceC = 0;
                } else {
                    t.pageObject.UnitPrice = 0;
                    t.salesPrice = 0;
                    t.salesPriceA = 0;
                    t.salesPriceB = 0;
                    t.salesPriceC = 0;

                    is_hidden_all = true;
                    discount = 0;
                }
            }
        }

        return null;
    }

    //excelImport
    public PageReference excelImport() {
/*        system.debug('○○○○○○○○○○○○○○○Welcome to excelImport!!');
        system.debug('▼▼▼▼▼excel_text:' + excel_text);
        //oppに画面の値を設定
        setOppFromOppInfo();

        errorflg = false;
        errormessage = null;

        //既存データ数の確認
        Integer j = 0;
        for (QELine s:activities) {
            if ((s.productName==null) || (s.productName=='')) {
                break;
            }
            j++;
        }

        //=======Temporary=====
        tmpactivities = activities;

        //=======Initialize=========
        activities = new List<QELine>();
        Integer i = 0;
        Integer xlscnt = 0;
        Integer rightcnt = 0; // 成功した数をカウント

        string[] xlslists = excel_text.split('\n',-1);
        List<string> xlslist = New list<string>();
        List<string> codelist = New List<string>();
        List<Integer> Quantitylist = New List<Integer>();
        List<string> setlist = New List<string>();

        Map<String, Integer> mp = new Map<String, Integer>();
        string xlscode;
        Integer xlsQuantity;
        string xlset;

        try {
            for (string xls:xlslists) {
                if (xls==null || xls=='') {
                    //null
                } else {
                    xlscode = null;
                    xlsQuantity = null;
                    xlset = null;
                    xlslist = xls.split('\t',-1);
                    Integer iCount = 0;
                    for (String s:xlslist) {
                        if (iCount== 1) {
                            if (s=='' || s==null) {
                                errorflg = true;
                                errormessage = System.Label.Error_Message02;
                                activities = tmpactivities;
                                return null;
                            } else {
                                s = s.trim();
                                xlsQuantity = Integer.valueOf(s);
                                Quantitylist.add(xlsQuantity);
                            }
                        } else if (iCount== 2) {
                            if (s=='' || s==null) {
                                errorflg = true;
                                errormessage = System.Label.Error_Message02;
                                activities = tmpactivities;
                                return null;
                            } else {
                                s = s.trim();
                                setlist.add(s);
                                xlset = s;
                            }

                        } else {
                            if (s=='' || s==null) {
                                errorflg = true;
                                errormessage = System.Label.Error_Message02;
                                activities = tmpactivities;
                                return null;
                            } else {
                                s = s.trim();
                                codelist.add(s);
                                xlscode = s;
                            }
                        }
                        iCount++;
                        if (iCount == 3) {
                            iCount = 0;
                        }
                    }
                    //mp.put(xlscode, xlsQuantity);
                    xlscnt++;
                }
            }
        } catch(Exception ex) {
            activities = tmpactivities;
            errorflg = true;
            errormessage = System.Label.Error_Message02;
            return null;
        }

system.debug('codelist:::::'+codelist.size());
system.debug('xlscnt:::::' + xlscnt);

        if (codelist.size()==0 || Quantitylist.size()==0 || setlist.size()==0) {
            activities = tmpactivities;
            errorflg = true;
            errormessage = System.Label.Error_Message02;
            return null;
        }

        xlscnt = j + xlscnt;
        if (xlscnt>quoteEntryMaxLine) {
            activities = tmpactivities;
            errorflg = true;
            errormessage = System.Label.Error_Message03;
            return null;
        }

        i = 0;
        boolean lineflg = false;
        for (QELine t:tmpactivities) {
            if (i==j) {
                Map<String, Product_Search__c> mpProduct2 = new Map<String, Product_Search__c>();                     // keyがProductCodeです。
                //List<Product_Search__c> items = [select Id,Name,ProductCode__c,
                //      ProductDescription__c,ProductStatus__c,Pricebook__c,Product__c 
                //      FROM Product_Search__c Where Pricebook__c = :pricebook2Id and ProductCode__c In :codelist];
                List<Product_Search__c> items = [select Id,Name,ProductCode__c,
                        ProductDescription__c,ProductStatus__c,Product__c 
                        FROM Product_Search__c Where ProductCode__c In :codelist];
                List<String> forSelect = new List<String>();
                for (Product_Search__c prd:items) {
                    mpProduct2.put(prd.ProductCode__c, prd);
                    forSelect.add(prd.Product__c);
                }

                Map<String, PricebookEntry> entries = new Map<String, PricebookEntry>();            // keyがProductCodeです。
                List<PricebookEntry> pbes = [
                    select Id,Product2Id,ProductCode,SalesPrice__c,SalesPriceA__c,SalesPriceB__c,SalesPriceC__c
                      FROM PricebookEntry where Pricebook2Id = :pricebook2Id
                       and CurrencyIsoCode =:currencyIsoCode and Product2Id in : forSelect];

                Map<String, String> tempMap = new Map<String, String>();

                for (PricebookEntry pbe:pbes) {
                    entries.put(pbe.ProductCode, pbe);
                    tempMap.put(pbe.Product2Id,pbe.Id);
                }

                for (Integer l=0;l<codelist.size();l++) {
                    Product_Search__c prd = mpProduct2.get(codelist[l]);
                    if (prd != null) {
                        PricebookEntry pbe = entries.get(codelist[l]);
                        QELine c = null;
                        if (pbe != null) {
                            Decimal sp0 = pbe.SalesPrice__c;
                            Decimal sp1 = pbe.SalesPriceA__c;
                            Decimal sp2 = pbe.SalesPriceB__c;
                            Decimal sp3 = pbe.SalesPriceC__c;
                            c = new QELine(isService, i, prd.Name, prd.ProductCode__c, pbe.Id, pbe.Product2Id, Quantitylist[l],setlist[l], sp0, sp1, sp2, sp3);
                        } else {
                            continue;
                        }
                        activities.add(c);
                        i++;
                        rightcnt++;
                        lineflg = true;
                    }
                }
                if (lineflg==true) {
                    i--;
                } else {
                    QELine a = New QELine(t, i);
                    activities.add(a);
                }
            } else {
                QELine a = New QELine(t, i);
                activities.add(a);
            }
            i++;
            if (i>149) {
                break;
            }
        }
        // messageを出す
        errorflg = true;
        errormessage = '数据导入结束，导入 ' + codelist.size() + ' 件，成功' + rightcnt + ' 件';
*/
        return null;

    }

     //BackButton
    public PageReference BackBtn() {
        String url = baseUrl;
        if (rtUrl != null && rtUrl.length() > 0) {
            url += rtUrl.replace('/production', '');
        } else {
            url += '\\' + oppid;
        }
        return new Pagereference(url);
    }

    public PageReference Save() {

        system.debug('○○○○○○○○○○○○Welcome to Save class!!○○○○○○○○○○○○');
        //system.debug('=====save discount:' + discount);

        errorflg = false;
        errormessage = null;
        Savepoint sp = Database.setSavepoint();

        try {

            //データチェック
            if (dataCheck() ==false) {
                return null;
            }

            String url = baseUrl;
            if (rtUrl != null && rtUrl.length() > 0) {
                url += rtUrl.replace('/production', '');
            } else {
                url += '\\' + oppid;
            }
            system.debug('url++++++' + url);
            PageReference pageRef = new Pagereference(url);

            if (dataEntry()==false) {
                //msg
                return null;
            } else {
                errorflg = true;
                if (specialerrorflg) {
                    errorMessage = String.isBlank(errorMessage) ?System.Label.Info_Message01:System.Label.Info_Message01 +errorMessage;
                } else {
                    // errorMessage = System.Label.Info_Message01 ;

                    errorMessage = String.isBlank(errorMessage) ?System.Label.Info_Message01:System.Label.Info_Message01 +errorMessage;
                    // ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, '注意！！！'+errorMessage));
                }
                //system.debug('errorMessage20190524' + errorMessage);
                
                return null;
            }

        } catch (DmlException de) {
            Database.rollback(sp);
            errorflg = true;
            errormessage = de.getDmlMessage(0);           // １件目のエラーのみ表示
            system.debug(Logginglevel.ERROR, de.getMessage());
            system.debug(Logginglevel.ERROR, de.getStackTraceString());
        } catch (Exception e) {
            Database.rollback(sp);
            errorflg = true;
            errormessage = e.getMessage();
            system.debug(Logginglevel.ERROR, e.getMessage());
            system.debug(Logginglevel.ERROR, e.getStackTraceString());
        }

        return null;

    }

    //OppReflection button
    public PageReference OppReflection() {
        //oppに画面の値を設定
        setOppFromOppInfo();
        Savepoint sp = Database.setSavepoint();
        try {
            errorflg = false;
            errormessage = null;

            //データチェック
            if (dataCheck() ==false) {
                return null;
            }

            String url = baseUrl;
            if (rtUrl != null && rtUrl.length() > 0) {
                url += rtUrl.replace('/production', '');
            } else {
                url += '\\' + oppid;
            }
            PageReference pageRef = new Pagereference(url);
            if (dataEntry()==false) {
                //msg
                return null;
            } else {
                //msg
                return pageRef;
            }
        } catch (DmlException de) {
            Database.rollback(sp);
            errorflg = true;
            errormessage = de.getDmlMessage(0);        
            system.debug(Logginglevel.ERROR, de.getMessage());
            system.debug(Logginglevel.ERROR, de.getStackTraceString());
        } catch (Exception e) {
            Database.rollback(sp);
            errorflg = true;
            errormessage = e.getMessage();
            system.debug(Logginglevel.ERROR, e.getMessage());
            system.debug(Logginglevel.ERROR, e.getStackTraceString());
        }
        
        return null;
    }

    public PageReference Decide() {
        system.debug('○○○○○○○○○○○○Welcome to Decide class!!○○○○○○○○○○○○');

        if (quo.Is_upload__c == true) {
            errorflg = true;
            errorMessage = '报价已经上传，不能再次决定。请再报价后，决定并上传新的报价。';
            return null;
        }

        boolean hasDetail = false;
        if (activities.size()>0) {
            for (QELine s:activities) {
                if (s.pageObject.PricebookEntryId != null && s.productName != null && s.productName != '') {
                    hasDetail = true;
                    break;
                }
            }
        }

        if (hasDetail == false) {
            errorflg = true;
            errorMessage = '不能决定没有产品明细的报价。';
            return null;
        }
        doDecide = true;
        Save();
        decideORundecideQuote(quo.Id,true);
        
        String url = baseUrl + '/apex/NewQuoteDevide?Id=' + quoId + '&retURL=' + rtUrl;
        PageReference pageRef = new Pagereference(url);

        if (errorflg == false || errorMessage.startsWith(System.Label.Info_Message01)) {
            return pageRef;
        }
        
        return null;
    }

    public PageReference UnDecide() {
        system.debug('○○○○○○○○○○○○Welcome to unDecide class!!○○○○○○○○○○○○');
        errorflg = false;
        errormessage = null;
        Savepoint sp = Database.setSavepoint();

        try {
            Quote q = New Quote();
            q.Id = quo.Id;
            q.Is_Decided__c = false;

            Opportunity o = New Opportunity();
            List<Opportunity> os = [select Id From Opportunity Where Id =:oppid];
            if (os.size()>0) {
                o = os[0];
                o.Is_Decided__c = false;
                o.Quote_Decide_User__c = null;
            }

            update q;
            update o;
            decideORundecideQuote(q.Id,true);
            String url = baseUrl + '/apex/NewQuoteDevide?Id=' + quoId + '&retURL=' + rtUrl;
            PageReference pageRef = new Pagereference(url);
            if (errorflg == false) {
                return pageRef;
            }
        } catch (DmlException de) {
            Database.rollback(sp);
            errorflg = true;
            errormessage = de.getDmlMessage(0);           // １件目のエラーのみ表示
            system.debug(Logginglevel.ERROR, de.getMessage());
            system.debug(Logginglevel.ERROR, de.getStackTraceString());
        } catch (Exception e) {
            Database.rollback(sp);
            errorflg = true;
            errormessage = e.getMessage();
            system.debug(Logginglevel.ERROR, e.getMessage());
            system.debug(Logginglevel.ERROR, e.getStackTraceString());
        }

        return null;
    }

    public boolean dataEntry() {

        system.debug('○○○○○○○○○○○○Welcome to dataEntry class!!○○○○○○○○○○○○');

        Boolean error = false;
        Boolean detail = true;

        //Quote-------------------------------------------------------------
        //List<Quote> maxQuote_No = [select QuoteNumber From Quote Where OpportunityId = :oppid order by QuoteNumber desc NULLS LAST limit 1];
        //String oppNo;
        //Integer l = 1;
        //if (maxQuote_No.size()>0) {
        //    try {
        //        oppNo = maxQuote_No[0].QuoteNumber;
        //        l = Integer.valueOf(oppNo) + 1;
        //    } catch (System.TypeException e) {
        //        system.debug('maxQuote_No Error: quote.id=' + maxQuote_No[0].id);
        //    }
        //} else {
        //    system.debug('first Quote');
        //}
        //oppNo = String.valueof(l);

        //while (oppNo.length() < 8){
        //    oppNo = '0' + oppNo;
        //}

        Quote q = New Quote();

        if (quoId==null) {
            q = quo.clone();
            q.OpportunityId = oppId;

            if (detail == true) {
                if (pricebook2Id==null) {
                    errormessage = System.Label.Error_Message04;
                    errorflg = true;
                    return false;
                } else {
                    q.Pricebook2Id = pricebook2Id;
                }
            }
            
        } else {

            q = quo.clone();
            q.Id = quoId;
            if (q.Pricebook2Id ==null) {
                if (detail == true) {
                    if (pricebook2Id==null) {
                        errormessage = System.Label.Error_Message04;
                        errorflg = true;
                         return false;
                    } else {
                        q.Pricebook2Id = pricebook2Id;
                    }
                }
            }
        }

        if (quoId==null) {
            //q.PriceRefreshDate__c = Date.today();
        }
        if (productStatusUpdated) {
            //q.PriceRefreshDate__c = Date.today();
        }
        
        q.Name = quo.name;
        system.debug(opp.Account.MarketVerticals__c +'@@@@@@@@'+opp.Trade_Type_D__c);
        if (doDecide == true) {
            List<Quote> decideQuote = new List<Quote>();
            //不能决定多个报价，戴宇
            decideQuote=[SELECT id FROM Quote WHERE OpportunityId = :opp.Id AND Is_Decided__c = true];
            if(decideQuote.size() > 0){
                errorflg = true;
                errorMessage = '已存在决定的报价，不能决定新的报价';
                return false;
            }
            q.Is_Decided__c = true;
            if(opp.Account.MarketVerticals__c == 'Clinical'&&opp.Trade_Type_D__c == 'Taxation'){
                if(opp.Dealer__r.DummyDealer__c == true){
                    String backStr = LicenseCheckUtil.LicenseCheck(opp.AccountId);
                    system.debug('DummyDealer__c ' + backStr);
                    if(backStr != '1'){
                        errorflg = true;
                        errorMessage = backStr + '，不能决定报价。';
                        return false;
                    }
                }else{
                    String backStr = LicenseCheckUtil.LicenseCheck(opp.Dealer__r.ParentID);
                    system.debug('Parent' + backStr);
                    if(backStr != '1'){
                        errorflg = true;
                        errorMessage = backStr + '，不能决定报价。';
                        return false;
                    }
                }
            }
        }else{
             if(opp.Account.MarketVerticals__c == 'Clinical'&&opp.Trade_Type_D__c == 'Taxation'){
                if(opp.Dealer__r.DummyDealer__c == true){
                    String backStr = LicenseCheckUtil.LicenseCheck(opp.AccountId);
                    system.debug('DummyDealer__c' + backStr);
                    if(backStr != '1'){
                        errorMessage = backStr;
                        specialerrorflg = true;

                    }
                }else{
                    String backStr = LicenseCheckUtil.LicenseCheck(opp.Dealer__r.ParentID);
                    system.debug('Parent' + backStr);
                    if(backStr != '1'){
                        errorMessage = backStr;
                        specialerrorflg = true;

                    }
                }
            }
        }
        String quoId1 = '';
        if (quoId==null) {
            insert q;
            quoId1 = q.Id;
            printFlg = true;
        } else {
            
            update q;
            quoId1 = q.Id;
        }

        List<QuoteLineItem> qlist = New List<QuoteLineItem>();
        qlist=[Select Id From QuoteLineItem Where QuoteId =:quoId1];
        if (qlist.size()>0) {
            delete qlist;
        }

        qlist = New List<QuoteLineItem>();
        List<QuoteLineItem> singleProductList = new List<QuoteLineItem>();
        Integer i=1;

        if (activities.size()>0) {
            Decimal all_price = 0.0;
            Decimal all_discount = 0.0;
            for (QELine s:activities) {
                if (is_hidden_all || is_hidden_user == true || is_dealer_user == true && s.hiddenflg == true) {
                    if (s.pageObject.PricebookEntryId != null &&  s.productName != null && s.productName != '') {
                        if (String.isBlank(s.pageObject.PricebookEntryId) == false) {
                            String setName = s.pageObject.Set__c;
                            Integer qty = 1 ;
                            //XHL-20190426-UpdateStart
                            if (!s.pageObject.SingleProduct__c ){

                                String fieldName = setName.substring(3);
                                fieldName = fieldName.indexOf('0') == 0 ? fieldName.substring(1) : fieldName;
                                Decimal d_qty = (Decimal) quo.get('SetQty' + fieldName + '__c');
                                // qty = d_qty == null ? 1 : d_qty.intValue();
                            }
                            //XHL-20190426-UpdateEnd
                            
                            all_price += s.salesPrice * s.pageObject.Quantity * qty;
                        }
                    }
                }

                if (quo.OrderIsChange__c) {
                    String productCode = s.pageObject.Product2.ProductCode;
                    if (String.isNotBlank(productCode)) {
                         
                        saveStringConcatenation += productCode + '|' +s.pageObject.Quantity;
                    }
                    
                }
            }


            if (all_price > 0) {
                system.debug('all_price---->'+all_price);
                all_discount = (all_price - quo.Total_Price_Text__c) * 100 / all_price;
                system.debug('all_discount---->'+all_discount);
            }

            if (quo.OrderIsChange__c) {
                if (initStringConcatenation != saveStringConcatenation) {
                    verifyProductValidFlag = true;
                }
            }

            // 产品首营状态Z5(停产) ---XHL 2021/02/07 Start
            Map<String,Decimal> productIdQuantityMap = new  Map<String,Decimal>();
            List<String> productIdList = new List<String>();
            String productSegmentZ5 = opp.ProductSegment__c == 'BS' ? 'LS':opp.ProductSegment__c;
            // String productSegment = opp.ProductSegment__c == 'BS' ? 'LS':opp.ProductSegment__c;

            String FGSPStr = 'Machine'.equals(opp.Machine_Parts__c) ? 'FG':'SP';
            // 产品首营状态Z5(停产) ---XHL 2021/02/07 End
            for (QELine s:activities) {
                if (s.pageObject.PricebookEntryId != null &&  s.productName != null && s.productName != '') {
                    if (String.isBlank(s.pageObject.PricebookEntryId) == false) {
                        String setName = s.pageObject.Set__c;
                        Integer qty = 1;
                        //XHL-20190426-UpdateStart
                        if (!s.pageObject.SingleProduct__c && String.isNotBlank(setName)){
                            String fieldName = setName.substring(3);
                            fieldName = fieldName.indexOf('0') == 0 ? fieldName.substring(1) : fieldName;
                            Decimal d_qty = (Decimal) quo.get('SetQty' + fieldName + '__c');
                            qty = d_qty == null ? 1 : d_qty.intValue();
                        } 
                        //XHL-20190426-UpdateEnd
                        QuoteLineItem ql = s.pageObject.clone();
                        ql.QuoteId = q.Id;
                        ql.Quantity = ql.Quantity ;
                        if (is_hidden_all || is_hidden_user == true || is_dealer_user == true && s.hiddenflg == true) {
                            ql.UnitPrice = s.salesPrice;
                            ql.Discount = all_discount;
                            if (s.customPrice != 0) {
                                ql.Custom_Price__c = s.customPrice;
                            }
                        }
                        ql.Custom_Price__c = ql.Custom_Price__c == null ? 0 : ql.Custom_Price__c;// * qty;
                        ql.quoLiVerifyProductValid__c = verifyProductValidFlag;
                        if (s.pageObject.SingleProduct__c) {
                            singleProductList.add(ql);
                        } else {
                            qlist.add(ql);  
                        }                        
                        productIdList.add(s.pageObject.Product2Id);
                        // 产品首营状态Z5(停产) ---XHL 2021/02/07 Start
                        Decimal quantity = ql.Quantity;
                        if (productIdQuantityMap.containsKey(s.pageObject.Product2Id)) {
                            quantity += productIdQuantityMap.get(s.pageObject.Product2Id);
                        }
                        productIdQuantityMap.put(s.pageObject.Product2Id,quantity);
                        // 产品首营状态Z5(停产) ---XHL 2021/02/07 End

                        i++;
                    }
                }
            }
            if (productIdList.size() > 0) {
                // 产品首营状态Z5(停产) ---XHL 2021/02/07 Start
                Map<String,Decimal> productQuantityMap = new  Map<String,Decimal>();
                List<Product2> getProductList = [SELECT Id,Name,ProductCode,NMPAStatus__c,ProductStatusFormula__c FROM Product2 WHERE Id IN:productIdList AND NMPAStatus__c = '停产' AND ProductStatusFormula__c = '1'];

                for (Product2 pro:getProductList) {

                    Decimal productQuantity = productIdQuantityMap.get(pro.Id);
                    String key = pro.ProductCode +'_'+ productSegmentZ5 +'_'+ FGSPStr;
                    // String key = pro.ProductCode +'_'+ productSegment +'_'+ FGSPStr;
                    

                    productQuantityMap.put(key, productQuantity);
                }
                if (productQuantityMap.size() > 0) {
                    String result = OrderWebService.ProductInventoryCheck(productQuantityMap);
                    if (result != '1') {
                        if (String.isBlank(errorMessage)) {
                            errorMessage = '注意！！！ '+ result;
                        } else {
                            errorMessage += result; 
                        }
                    }    
                }
                // 产品首营状态Z5(停产) ---XHL 2021/02/07 End
                
            }
            if (singleProductList.size() >0 ){
                insert singleProductList;
            }

            if (qlist.size()>0) {
                insert qlist;
            }
            
            Quote quoUpd = [select id, Discount, Discount_Normal__c, Discount_Special__c,OrderIsChange__c from Quote where Id = : quoId1];
            Decimal quoDis = quoUpd.Discount == null ? 0 : quoUpd.Discount;
            Decimal quoDisN = quoUpd.Discount_Normal__c == null ? 0 : quoUpd.Discount_Normal__c;
            if (productSegment == 'BS') {
                system.debug('quoDis---->'+quoDis);
                system.debug('quoDisN---->'+quoDisN);
                quoUpd.Discount_Special__c = quoDis - quoDisN;
                system.debug('quoUpd.Discount_Special__c---->'+quoUpd.Discount_Special__c);
            } else {
                quoUpd.Discount_Special__c = (quoDis - quoDisN) / (1 - quoDisN / 100);
            }

            quoUpd.QuoVerifyProductValid__c = verifyProductValidFlag;

            update quoUpd;

            List<QuoteLineItem> itemsRe = 
                [Select Id,Product2Id,Product2.Name,Product2.ProductCode,Product2.Product_ECCode__c,Quantity,Subtotal,Discount,TotalPrice,PricebookEntryId,UnitPrice,Description,Set__c,Custom_Price__c,
                        PricebookEntry.SalesPrice__c,PricebookEntry.SalesPriceA__c,PricebookEntry.SalesPriceB__c,PricebookEntry.SalesPriceC__c,Product2.ProductModels__c,PricebookEntry.Hidden_flag__c,
                        Quote.Discount_Normal__c,SingleProduct__c,SetName__c,DontSingleProduct__c,
                        Quote.Opportunity.DealerId__c
                   From QuoteLineItem where Quoteid = :quoId1 Order by Id];
            activities = new List<QELine>();
            i=0;
            QELine c = new QELine(i);

            String includeEspecialProduct = '';
            is_hidden_all = false;
            if (itemsRe.size()>0) {
                for (QuoteLineItem o:itemsRe) {

                    if (o.DontSingleProduct__c != '1') {
                        if (String.isBlank(includeEspecialProduct)) {

                            includeEspecialProduct = o.DontSingleProduct__c;
                        } else {
                            includeEspecialProduct += ',' + o.DontSingleProduct__c;
                        }
                        specialerrorflg = true;
                    }
                    String setName = o.Set__c;
                    Integer qty = 1;
                    //XHL-20190426-UpdateStart
                    if (!o.SingleProduct__c && String.isNotBlank(setName)) {
                        String fieldName = setName.substring(3);
                        fieldName = fieldName.indexOf('0') == 0 ? fieldName.substring(1) : fieldName;
                        Decimal d_qty = (Decimal) quo.get('SetQty' + fieldName + '__c');
                        qty = d_qty == null ? 1 : d_qty.intValue();
                    } 
                    //XHL-20190426-UpdateEnd
                    c = new QELine(isService, o,i,o.Product2.Name,o.Product2.ProductCode,o.Product2.Product_ECCode__c,qty,o.Product2.ProductModels__c,o.SingleProduct__c,o.SetName__c);
                    //c = new QELine(isService, o,i,o.Product2.Name,o.Product2.ProductCode,o.Product2.Product_ECCode__c,qty,o.Product2.ProductModels__c,quo.Discount_Normal__c);
                    //specialDealer =  StaticParameter.specialDealerMap.containsKey(o.Quote.Opportunity.DealerId__c);
                    specialDealer = IfspecialDealer(o.Quote.Opportunity.DealerId__c);
                    //ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '请选择目标客户----3>'+o.Quote.Opportunity.DealerId__c));
                    if (specialDealer || is_hidden_user == true || is_dealer_user == true && c.hiddenflg == true) {
                        c.pageObject.UnitPrice = 0;
                        c.totalPrice = 0;
                        c.customPrice = 0;
                        system.debug('<---is_hidden_all---01>' + is_hidden_all);
                        is_hidden_all = true;
                        discount = 0;
                    }
                    activities.add(c);
                    i++;

                }
            }
            if (String.isNotBlank(includeEspecialProduct) && specialerrorflg) {
                if(!StaticParameter.specialDealerMap1.containsKey(opp.DealerId__c)) {
                    errormessage += '注意！！！ 报价产品中包含特殊的单品产品[ ' +includeEspecialProduct+ ' ]';
                }
                //system.debug('errormessage__20190523__' + errormessage);
            }

            for (integer j=i;j<quoteEntryMaxLine;j++) {
                c = new QELine(j);
                activities.add(c);
            }

        }
        if (quo.OrderIsChange__c) {
            if (initStringConcatenation != saveStringConcatenation) {
                verifyProductValidFlag = true;
            }
        }

        List<Quote> quoListRe = 
                [ SELECT Id,Name,QuoteNumber,Account.name,ExpirationDate,Subtotal,Discount,TotalPrice,GrandTotal,PrintPrice__c,ShippingHandling,
                    DeliveryLeadTime__c,PaymentTerms__c,ValidDate__c,Warranty__c,SetName1__c,Shipment_Term__c,Shipment_Term2__c,
                    SetName2__c,SetName3__c,SetName4__c,SetName5__c,SetName6__c,SetName7__c,SetName8__c,SetName9__c,SetName10__c,
                    SetName11__c,SetName12__c,SetName13__c,SetName14__c,SetName15__c,SetName16__c,SetName17__c,SetName18__c,SetName19__c,
                    SetName20__c,SetName21__c,SetName22__c,SetName23__c,SetName24__c,SetName25__c,SetName26__c,SetName27__c,SetName28__c,SetName29__c,
                    SetName30__c,SetQty1__c,SetQty2__c,SetQty3__c,SetQty4__c,SetQty5__c,SetQty6__c,SetQty7__c,SetQty8__c,SetQty9__c,SetQty10__c,SetQty11__c,
                    SetQty12__c,SetQty13__c,SetQty14__c,SetQty15__c,SetQty16__c,SetQty17__c,SetQty18__c,SetQty19__c,SetQty20__c,SetQty21__c,SetQty22__c,SetQty23__c,
                    SetQty24__c,SetQty25__c,SetQty26__c,SetQty27__c,SetQty28__c,SetQty29__c,SetQty30__c,Comment__c,Custom_Price_Total__c,Custom_Price_Total_Text__c,Quote_Type__c,
                    Main_Model__c,Main_Serial_Number__c,Service_Type__c,Contract_Number__c,Service_Date__c,Service_Finish_Date__c,Service_Engineer_Sign__c,
                    Service_Pickup_Sign__c,Service_Check_Sign__c,Service_Location__c,Service_Status__c,Service_Content__c, Is_upload__c, Total_Price_Text__c,
                    Discount_Normal__c,Discount_Special__c,OrderIsChange__c
                    FROM Quote Where Id =:quoId1];
        if (quoListRe.size() > 0) {
            quo = quoListRe[0];
        }

system.debug('=====is_hidden_all:' + is_hidden_all);
        if (is_hidden_all) {
            discount = quo.totalPrice.setScale(2, System.RoundingMode.HALF_UP);
        } else {
            discount = quo.Discount == null ? 0 : quo.Discount;
            //discount = quo.Discount_Special__c == null ? 0 : quo.Discount_Special__c;
            discount = discount.setScale(2, System.RoundingMode.HALF_UP);
        }

system.debug('○○○○○○○○○○○○Welcome Opportunity class!!○○○○○○○○○○○○');

        //Opportunity--------------------------------------------
        Opportunity o = New Opportunity();
        List<Opportunity> os = New List<Opportunity>();
        os = [select Id From Opportunity Where Id =:oppid];
        if (os.size()>0) {
            o = os[0];
            if (decideFlg == false) {
                o.SyncedQuoteId = quoId1;
                o.Quote_PaymentTerms_Text__c = paymentTermsMap.get(quo.PaymentTerms__c);
                o.is_hidden__c = is_hidden_all || specialDealer;
                if (doDecide == true) {
                    o.Is_Decided__c = true;
                    o.Quote_Decide_User__c = UserInfo.getUserId();
                }
                o.IE_Discount_Normal__c = quo.Discount_Normal__c;
                o.IE_Discount_Special__c = quo.Discount_Special__c;
                system.debug('IE_Discount_Special__c--->'+o.IE_Discount_Special__c);
                update o;
            }
       
        }
if (quoId == null) {
    quoId = quoId1;//q.Id;
}
        return true;
    }

    //oppに画面の値を設定
    private void setOppFromOppInfo() {

    }

    public PageReference csvExport() {
        if (fileName == null || fileName == '') {
            errorflg = true;
            errormessage = '请输入配置导出文件名。';
            return null;
        }
        Date dExpirationDate = quo.ExpirationDate;
        strExpirationDate = dExpirationDate == null ? '' : dExpirationDate.format();
        csv_activities = new List<QELine>();
        for (QELine s : activities) {
            if (s.pageObject.PricebookEntryId != null &&  s.productName != null && s.productName != '') {
                csv_activities.add(s);
            }
        }
        PageReference pr = page.QuoteCSVExport;
        return pr;
    }

    public PageReference csvRead() {

        String strFile = '';
        List<String> listFile = new List<String>();
        errorflg = false;
        errormessage = null;
try {
        if (contentFile != null) {
            strFile = contentFile.toString();
            listFile = strFile.split('\n');
system.debug('=====strFile:' + strFile);
        } else {
            errorflg = true;
            errormessage = '读取内容为空。';
            return null;
        }
} catch (Exception ex) {
    errorflg = true;
    errormessage = System.Label.Error_Message02;
    return null;
}
for (Integer i = 0; i < listFile.size(); i++) {
    system.debug('=====listFile_' + i + ':' + listFile[i]);
}
        List<String[]> arrayFile = new List<String[]>();
        String firstline = listFile[0];
        if (firstline.indexOf('套装/单品') < 0) {
            errorflg = true;
            errormessage = '读取内容格式不正确。';
            return null;
        } else {
            String strReplace = '';
            List<String> temp = strFile.split('"');
            for (Integer i = 0; i < temp.size(); i++) {
                if (math.mod(i, 2) == 1) {
                    temp[i] = temp[i].replace(',', '#%&');
                }
                strReplace += temp[i];
            }
system.debug('=====strReplace:' + strReplace);
            List<String> listReplace = strReplace.split('\n');
            for (String replace : listReplace) {
system.debug('=====replace:' + replace);
                if (replace != '\r' && replace.length() > 0) {
                    replace = replace.replace('\r', '');
                    String[] a = replace.split(',', -1);
                    for (Integer i = 0; i < a.size(); i++) {
                        if (a[i].indexOf('#%&') > 0) {
                            a[i] = a[i].replace('#%&', ',');
                        }
                    }
                    if (specialDealer) {
                        if (a.size() != 4) {
                            errorflg = true;
                            errormessage = '读取内容格式不正确。Line:' + arrayFile.size();
                            return null;
                        }
                    }  else {
                        if (a.size() != 5) {
                            errorflg = true;
                            errormessage = '读取内容格式不正确。Line:' + arrayFile.size();
                            return null;
                        }

                    }
                    //if (a.size() != 5) {
                    //    errorflg = true;
                    //    errormessage = '读取内容格式不正确。Line:' + arrayFile.size();
                    //    return null;
                    //}
                    arrayFile.add(a);
                }
            }
        }

        List<String> prdCodeList = new List<String>();

        //XHL-20190426-UpdateStart
        Map<String,String> productSetCodeMap = new Map<String,String>();

        for (Integer i = 1; i < arrayFile.size(); i++) {

            if (arrayFile[i] != null && arrayFile[i].size() > 1 && arrayFile[i][0] != '') {
                try {
                    if (String.isNotBlank(arrayFile[i][3])) {
                        Decimal quantity1 = Decimal.valueOf(arrayFile[i][3]);
                    }
                    if (!specialDealer) {
                        if (String.isNotBlank(arrayFile[i][4])) {
                            Decimal discount1 = Decimal.valueOf(arrayFile[i][4]);
                        }
                    }

                } catch (Exception e) {
                    errorflg = true;
                    if (arrayFile[i][0] != singleProduct ) {
                        errorMap.put(arrayFile[i][1],'[' + arrayFile[i][1] +']配套的数量或折扣存在非数字，请确认;');    
                    } else {
                        errorMap.put(arrayFile[i][1],'[' + arrayFile[i][1] +']产品的数量或折扣存在非数字，请确认;');
                    } 
                    continue;
                }
                
                if (arrayFile[i][0] != singleProduct ) {

                    productSetCodeMap.put(arrayFile[i][1], arrayFile[i][3] + ';'+arrayFile[i][4]);    
                } else {

                    String tmp = '00000000000' + arrayFile[i][1];
                    prdCodeList.add(tmp);
                    prdCodeList.add(arrayFile[i][1]);
                }
                
            }
        }

        activities = new List<QELine>();
        Integer no =0;
        emptyData();
        if (productSetCodeMap.size() > 0) {
            
            acquireProductSetId(productSetCodeMap);
            no =  singleNo == null ? 0 : singleNo;
        } 
        //XHL-20190426-UpdateEnd
        

        

system.debug('=====prdCodeList:' + prdCodeList);
        //return null;
        Map<String, Product_Search__c> psMap = new Map<String, Product_Search__c>(); // keyがProductCodeです。
        List<String> forSelect = new List<String>();
        List<Product_Search__c> psList = [
            select Id, Name, ProductCode__c, Product_ECCode__c, ProductDescription__c, ProductStatus__c, Product__c, ProductModels1__c
              from Product_Search__c
             where ProductCode__c in :prdCodeList];
        String errProduct = '';
        Map<String,String> errProductMap = new Map<String,String>();
        for (Product_Search__c ps : psList) {
            String pc = ps.ProductCode__c;
            if (pc.startsWith('00000000000')) {
                pc = pc.substring(11);
                psMap.put(pc, ps);
            }
            psMap.put(ps.ProductCode__c, ps);
            forSelect.add(ps.Product__c);
            //system.debug(ps.ProductCode__c + ps.ProductStatus__c+'@@@@@@@->>>');
            if(ps.ProductStatus__c == '0'){
                system.debug(ps.ProductCode__c + ps.ProductStatus__c+'@@@@@@@');
                errorflg = true;
                errProduct += ps.ProductCode__c + ',';
                errProductMap.put(ps.ProductCode__c,ps.ProductCode__c);
            }
        }

        if (errorflg == true && errProduct != '') {
            errProduct = errProduct.substring(0, errProduct.length() - 1);
            errorMessage = '产品状态为无效，不能使用。产品：' + errProduct + '请确认;';
            errorMap.put(errorMessage,errorMessage);
            //return null;
        }
        system.debug('errorflg---->11111'+errorMessage);
        Map<String, PricebookEntry> pbeMap = new Map<String, PricebookEntry>(); // keyがProductCodeです。
        List<PricebookEntry> pbeList = [
            select Id, Product2Id, ProductCode, Product2.Product_ECCode__c, Product2.Dummy__c, CostPrice__c, SalesPrice__c, SalesPriceA__c, SalesPriceB__c, SalesPriceC__c, Hidden_flag__c
              from PricebookEntry
             where Pricebook2Id = :pricebook2Id
               and CurrencyIsoCode = :currencyIsoCode
               and Product2.ManualHidden__c = false
               and Product2Id in :forSelect];
        system.debug('forSelect_1_1_1_1_1_' + forSelect);
        system.debug('pbeList_2_2_2_2_2_2_2_' + pbeList);
        
        for (PricebookEntry pbe : pbeList) {
            String pc = pbe.ProductCode;
            if ((pbe.CostPrice__c == 0 && pbe.Product2.Dummy__c == false) || pbe.SalesPrice__c == 0) {
                errorflg = true;
                errProduct += pbe.productCode + ',';
            } else {
                if (pc.startsWith('00000000000')) {
                    pc = pc.substring(11);
                    pbeMap.put(pc, pbe);
                }
                pbeMap.put(pbe.ProductCode, pbe);
            }
        }

        if (arrayFile.size() > 1) {
            //XHL-20190426-UpdateStart
            for (Integer line = 1; line < arrayFile.size(); line++) {
                
                if (arrayFile[line][0] == singleProduct) {

                    Product_Search__c ps = psMap.get(arrayFile[line][1]);
                    PricebookEntry pbe = pbeMap.get(arrayFile[line][1]);
                    if (ps == null || pbe == null) {
                        errorflg = true;
                        errProduct += arrayFile[line][1] + ',';
                        errorMap.put(arrayFile[line][2],errProduct);
                    }    
                }
                
            }
            
            if (errorflg) {
                system.debug('errorflg---->22222'+errorMessage);
                errorMessage = '';
                String intermediateVariable = '';

                for (String errorKey :errorMap.keySet()) {

                    errProduct = errorMap.get(errorKey).substring(0, errorMap.get(errorKey).length()-1);
                    system.debug('ceshi------>' + errProduct);
                    if (errProduct.endsWith('!!!')) {
                        errorMessage += errorMap.get(errorKey);
                    } else if(errProduct.startsWith('error')){
                        errorMessage += errorMap.get(errorKey);
                    }else if(errProduct.endsWith('请确认')){
                        errorMessage += errorMap.get(errorKey);
                    }else {
                        if (String.isBlank(intermediateVariable)) {
                            intermediateVariable = errorKey;
                        } else {
                            intermediateVariable += ',' + errorKey;
                        }
                        
                    }
                       
                }
                if (String.isNotBlank(intermediateVariable)) {
                    errorMessage += '[' + intermediateVariable + ']的产品价格信息不正确，不能使用;'; 
                }
                //return null ;
            }
            
            QELine c = new QELine(no);
            is_hidden_all = false;
            boolean isSingleProduct = false;
            for (Integer line = 1; line < arrayFile.size(); line++) {
                if (arrayFile[line][0] == singleProduct ){
                    if (errorMap.containsKey(arrayFile[line][2])) {
                        continue;
                    }

                    isSingleProduct = true;
                    Product_Search__c ps = psMap.get(arrayFile[line][1]);
                    PricebookEntry pbe = pbeMap.get(arrayFile[line][1]);
                    system.debug('=====key:' + arrayFile[line][1]);
                    system.debug('=====ps:' + ps);
                    system.debug('=====pbe:' + pbe);
                    system.debug('ps.ProductCode__c--->'+ps.ProductCode__c );
                    system.debug('ps.Product__c--->'+ps.Product__c);
                    //c = new QELine(isService, no, arrayFile[line][0], ps.Name, ps.ProductCode__c, ps.Product_ECCode__c, ps.Product__c, pbe, arrayFile[line][3], arrayFile[line][4], ps.ProductModels1__c, quo.Discount_Normal__c);
                    if (errProductMap != null && errProductMap.size() > 0) {
                        if (errProductMap.containsKey(arrayFile[line][1])) {
                            continue;
                        }
                    }
                    if (specialDealer) {
                        c = new QELine(isService, no, singleProduct, ps.Name, ps.ProductCode__c, ps.Product_ECCode__c, ps.Product__c, pbe, arrayFile[line][3],'', ps.ProductModels1__c, isSingleProduct, ps.ProductDescription__c, '');
                    } else {
                        c = new QELine(isService, no, singleProduct, ps.Name, ps.ProductCode__c, ps.Product_ECCode__c, ps.Product__c, pbe, arrayFile[line][3], arrayFile[line][4], ps.ProductModels1__c, isSingleProduct, ps.ProductDescription__c, '');
                    }
                    //c = new QELine(isService, no, singleProduct, ps.Name, ps.ProductCode__c, ps.Product_ECCode__c, ps.Product__c, pbe, arrayFile[line][3], arrayFile[line][4], ps.ProductModels1__c,isSingleProduct,ps.ProductDescription__c,'');
                    if (specialDealer || is_hidden_user == true || is_dealer_user == true && c.hiddenflg == true) {
                        c.pageObject.UnitPrice = 0;
                        c.totalPrice = 0;
                        system.debug('<---is_hidden_all--->02' + is_hidden_all);
                        is_hidden_all = true;
                        discount = 0;
                    }
                    activities.add(c);
                    
                    no++;  

                }
                
            }
            //XHL-20190426-UpdateEnd
            for (integer j = no; j < quoteEntryMaxLine; j++) {
                c = new QELine(j);
                activities.add(c);
            }

        } else {
            for (no = 0; no < quoteEntryMaxLine; no++) {
                QELine active_activity = new QELine(no);
                activities.add(active_activity);
            }
        }
        system.debug('quoName: '+quo.Name);
        return null;
    }

    public boolean dataCheck() {
        system.debug('○○○○○○○○○○○○Welcome to dataCheck class!!○○○○○○○○○○○○');
        errorflg = false;
        errormessage = null;
        Boolean error = false;
        List<String> product2Ids = New List<String>();
        Map<String,String> mapSet = new Map<String,String> ();
        Map<Id, Product_Search__c> prd2LatestValMap = new Map<Id, Product_Search__c>();

        //报价优化 2021-05-08 start
        String shter = quo.Shipment_Term__c;
        if(String.isBlank(shter) && opp.Trade_Type_D__c =='Tax Exemption'){
            errorflg = true;
            errorMessage = '国际贸易条件不能为空！';
            return false;
        }

        String shter2 = quo.Shipment_Term2__c;
        if(String.isBlank(shter2) && opp.Trade_Type_D__c =='Tax Exemption'){
            errorflg = true;
            errorMessage = '国际贸易条件2不能为空！';
            return false;
        }
        //报价优化 2021-05-08 end

        String qname = quo.Name;
        if (qname == null || qname.trim().length() == 0) {
            errorflg = true;
            errorMessage = '请输入报价名称！';
            return false;
        }
        String qpaymentTerms = quo.PaymentTerms__c;
        if (qpaymentTerms == null || qpaymentTerms.trim().length() == 0) {
            errorflg = true;
            errorMessage = '请输入付款条件！';
            return false;
        }
        Decimal qdeliveryLeadTime = quo.DeliveryLeadTime__c;
        if (qdeliveryLeadTime == null || qdeliveryLeadTime <= 0) {
            errorflg = true;
            errorMessage = '请输入交货周期！';
            return false;
        }
        Decimal qwarranty = quo.Warranty__c;
        if (qwarranty == null || qwarranty <= 0) {
            errorflg = true;
            errorMessage = '请输入保修期！';
            return false;
        }
        Date qexpirationDate = quo.ExpirationDate;
        if (qexpirationDate == null) {
            errorflg = true;
            errorMessage = '请输入报价到期日期！';
            return false;
        }
        Decimal qcustomPriceTotal = quo.Custom_Price_Total_Text__c;
        if (qcustomPriceTotal == null || qcustomPriceTotal == 0) {
            errorflg = true;
            errorMessage = '请输入客户总价';
            return false;
        }

        if (is_hidden_all) {
            quo.Total_Price_Text__c = discount;
            system.debug('discount----->123'+discount);
        }
system.debug('=====quo.Total_Price_Text__c:' + quo.Total_Price_Text__c);
        if (is_hidden_all && (quo.Total_Price_Text__c == null || quo.Total_Price_Text__c <= 0)) {
            errorflg = true;
            errorMessage = '总价不正确，请确认！';
            return false;
        }

        if (activities.size()>0) {
            for (QELine a:activities){
                if (String.isBlank(a.pageObject.Product2Id) == false) {
                    product2Ids.add(a.pageObject.Product2Id);
                }
                String tmpSet = a.pageObject.Set__c;
                if (tmpSet != null && tmpSet != '') {
                    String tmpSetId = tmpSet.substring(2);
                    if (!mapSet.containsKey(tmpSetId)) {
                        mapSet.put(tmpSetId,tmpSet);
                    }
                }
            }

            Map<String,String> mapHeaderSet = new Map<String,String> ();
            Map<String,Decimal> mapHeaderQty = new Map<String,Decimal> ();
            for (Integer i = 1; i <= 30; i++) {
                String field = String.valueOf(i);
                field = '00' + field;
                field = field.substring(field.length() - 2);
                mapHeaderSet.put('set' + field, (String) quo.get('SetName' + i + '__c'));
                mapHeaderQty.put('set' + field, (Decimal) quo.get('SetQty' + i + '__c'));
            }

            system.debug('mapSet class========>' + mapSet);
            system.debug('mapSet class========>' + mapSet.size());
            system.debug('mapHeaderSet class========>' + mapHeaderSet);
            system.debug('mapHeaderQty class========>' + mapHeaderQty);

            Map<String,String> mapErrSet = new Map<String,String> ();


        }
        
        if (error==true) {
            errorflg = true;
            return false;
        }

        errorflg = false;
        errorMessage = null;
        return true;
    }

    public PageReference reloadPage() {
        if (is_hidden_all) {
            discount = 0;
        } else {
            discount = quo.Discount == null ? 0 : quo.Discount;
            discount = discount.setScale(2, System.RoundingMode.HALF_UP);
        }
        return null;
    }


    //导入数据时，根据产品配套的Code查找产品配套
    public void acquireProductSetId(Map<String,String> productSetCodeMap) {
        errorflg = false;
        errormessage = null;
        system.debug('<---productSetCodeMap--->' + productSetCodeMap );
        Map<String,Integer> productSetID_QuantityMap = new Map<String,Integer>();
        List<productSet__c> productSetList;  //= new List<productSet__c>();
        Map<String,String> codeMap = new Map<String,String>();

        if (productSetCodeMap.size() > 0 ) {

            productSetList = [select Id,Name,Code__c from productSet__c where Code__c in: productSetCodeMap.keyset()];
        }
        system.debug('<---productSetList--->' + productSetList.size() );
        if (productSetList.size() > 0) {

            for (productSet__c productSet :productSetList) {

                codeMap.put(productSet.Code__c, productSet.Code__c);
                Integer quantity = Integer.valueOf(productSetCodeMap.get(productSet.Code__c).split(';')[0]);
                productSetID_QuantityMap.put(productSet.Id,quantity);

            }

            queSetNameSetQty(productSetID_QuantityMap,productSetCodeMap);
            
        } else {

            for (String keyset : productSetCodeMap.keyset()) { 
                
                errorflg = true;    
                errorMap.put(keyset,'[' + keyset +']配套不存在，请确认!!!!;');
            }
        }
        String errorInformation = '';

        for (String keyset : productSetCodeMap.keyset()) { 

            if (!codeMap.containsKey(keyset)) {
                
                errorMap.put(keyset,'[' + keyset +']配套不存在，请确认!!!!;');

            }
        }
         
    }

    //选择产品配套
    public PageReference setProductEntry () {

        errorflg = false;
        errormessage = null;

        Map<String,Integer> productSetID_QuantityMap = new Map<String,Integer>();
        Map<String,String> productSetID_DiscountMap = new Map<String,String>();
        //当setProduct_text为空时，认为删除该报价所有的产品配套
        if (String.isBlank(setProduct_text)) {

            List<QELine> singleProductSuitList = new List<QELine>();
            for (QELine q :activities) {
                
                if ( String.isBlank(q.pageObject.Product2Id) == false && q.pageObject.SingleProduct__c  == true) {

                    singleProductSuitList.add(q);
                } 
                
            }

            activities = new List<QELine>();

            emptyData();

            //将单品套装放在产品配套套装的下面
            Integer singleNo = 0;
            QELine qeline = new QELine(singleNo);

            for (QELine q :singleProductSuitList) {
                
                q.lineNo = singleNo;
                activities.add(q);
                singleNo++;
            }
            
            for (integer j = singleNo; j < quoteEntryMaxLine; j++) {

                qeline = new QELine(j);
                activities.add(qeline);
            }

            return null;
        } else {
            List<String> productSetIdList = new List<String>();
            Map<String,String> productSetMap = new Map<String,String>();
            for (String str : setProduct_text.split(';')) {
                productSetIdList.add(str.split(',')[0]);
            }
            if (productSetIdList.size() > 0) {
                for (productSet__c proSet  :[select Id,Name,Code__c from productSet__c where Id in :productSetIdList]) {
                    productSetMap.put(proSet.Id, proSet.Code__c);
                }
            }
            for (String str : setProduct_text.split(';')) {

                if (String.isBlank(str.split(',')[1]) == false) {

                    productSetID_QuantityMap.put(str.split(',')[0], Integer.valueOf(str.split(',')[1]));
                    productSetID_DiscountMap.put(productSetMap.get(str.split(',')[0]), str.split(',')[1]+';'+str.split(',')[2]);
                    system.debug('productSetID_DiscountMap____' + productSetID_DiscountMap);

                }
                
            }
        }

       //queSetNameSetQty(productSetID_QuantityMap,null);
       queSetNameSetQty(productSetID_QuantityMap,productSetID_DiscountMap);
        
        for (integer j = singleNo; j < quoteEntryMaxLine; j++) {

            QELine qeline = new QELine(j);
            activities.add(qeline);
        }

        return null;
    }

    

    public class QELine {
        public Integer lineNo { get; set; }
        public String productName { get; set; }
        public String productCode { get; set; }
        public String productEC { get; set; }
        public QuoteLineItem pageObject { get; set; }
        public String setName { get; set; }
        public String productSetNameReference { get; set; }
        public Double totalPrice { get; set; }

        public Decimal salesPrice { get; set; }
        public Decimal salesPriceA { get; set; }
        public Decimal salesPriceB { get; set; }
        public Decimal salesPriceC { get; set; }

        public boolean isProductModel { get; set; }

        public boolean hiddenflg { get; set; }
        public Decimal customPrice { get; set; }

        //public Decimal discount { get; set; }
        private Map<String, String> setNameMap;
        private void setMap() {
            Integer quoteEntryMaxSet = Integer.valueOf(System.Label.QuoteEntryMaxSet);
            String singleProduct  = System.Label.SingleProduct;
            setNameMap = new Map<String, String>();
            for (Integer i = 0; i < quoteEntryMaxSet; i++) {
                if (i < 9) {
                    setNameMap.put('set0'+ String.valueOf(i+1),'套装0'+ String.valueOf(i+1));
                } else {
                    setNameMap.put('set'+ String.valueOf(i+1),'套装'+ String.valueOf(i+1));
                }
            }
           
            setNameMap.put(singleProduct,singleProduct);
        }
        private void setMap2() {
            setNameMap = new Map<String, String>();
            setNameMap.put('set01','零件费用');
            setNameMap.put('set02','服务费');
            setNameMap.put('set03','其他费用');
        }

        public QELine(Integer i) {
            this.pageObject = New QuoteLineItem();
            this.lineNo = i;
            this.totalPrice = 0;

            this.salesPrice = 0;
            this.salesPriceA = 0;
            this.salesPriceB = 0;
            this.salesPriceC = 0;

            this.isProductModel = true;

            this.hiddenflg = false;
        }

        //public QELine(boolean isService, QuoteLineItem tmp, Integer i, String pdtName, String pdtCode, String pdtEC, Integer sQty, boolean ispm, Decimal discount_n) {
        //XHL-20190428-Update isSingleProduct,在报价行项目上增加SingleProduct__c字段，区分是套装还是单品
        public QELine(boolean isService, QuoteLineItem tmp, Integer i, String pdtName, String pdtCode, String pdtEC, Integer sQty, boolean ispm, boolean isSingleProduct,String productSetName) {
            //system.debug('1234567_____');
            this.pageObject = tmp;
            //this.pageObject.Quantity = tmp.quantity / sQty;
            this.pageObject.Quantity = tmp.quantity ;
            this.pageObject.Custom_Price__c = tmp.Custom_Price__c == null ? 0 : tmp.Custom_Price__c;// / sQty;
            this.pageObject.SetName__c = productSetName;
            //this.totalPrice = tmp.TotalPrice / sQty;
            this.totalPrice = tmp.TotalPrice ;
            this.lineNo = i;
            this.productName = pdtName;
            this.productCode = pdtCode.startsWith('0000000000') ? pdtCode.substring(10) : pdtCode;
            this.productEC = pdtEC;
            if (isService == true) {
                setMap2();
            } else {
                setMap();
            }
            this.setName = setNameMap.get(tmp.Set__c);
            //this.setName = tmp.Set__c;

            this.salesPrice = tmp.PriceBookEntry.SalesPrice__c;
            this.salesPriceA = tmp.PriceBookEntry.SalesPriceA__c;
            this.salesPriceB = tmp.PriceBookEntry.SalesPriceB__c;
            this.salesPriceC = tmp.PriceBookEntry.SalesPriceC__c;

            this.isProductModel = ispm;

            this.hiddenflg = tmp.PricebookEntry.Hidden_flag__c;
            system.debug('hiddenflg__'+i+'__'+hiddenflg);
            this.customPrice = this.pageObject.Custom_Price__c;
            this.pageObject.SingleProduct__c  = isSingleProduct;
        }

        //XHL-20190428-Update isSingleProduct,在报价行项目上增加SingleProduct__c字段，区分是套装还是单品
        public QELine(boolean isService, Integer i, String setStr, String strName, String strCode, String strEC, String strId, PricebookEntry pbe, String quantity, String discount, boolean ispm, boolean isSingleProduct,String description,String productSetName) {
            this.lineNo = i;
            this.productSetNameReference = productSetName;
            if (isService == true) {
                setMap2();
            } else {
                setMap();
            }
            this.setName = setNameMap.get(setStr);
            this.productName = strName;
            String pCode = strCode;
            this.productCode = pCode.startsWith('0000000000') ? pCode.substring(10) : pCode;
            this.productEC = strEC;

            pageObject = new QuoteLineItem();
            this.pageObject.Product2Id = strId;
            this.pageObject.PricebookEntryId = pbe.Id;
            this.pageObject.Set__c = setStr;
            this.pageObject.UnitPrice = pbe.SalesPrice__c;
            this.pageObject.Quantity = quantity == '' ? 0 : Decimal.valueOf(quantity);
            this.pageObject.Discount = discount == '' ? 0 : Decimal.valueOf(discount);
            system.debug('this.pageObject.Discount---->'+this.pageObject.Discount);
            this.pageObject.SingleProduct__c = isSingleProduct;
            this.pageObject.Description = description;
            this.pageObject.SetName__c = productSetName;
/*            this.discount = discount == '' ? 0 : Decimal.valueOf(discount);
            this.discount = this.discount.setScale(2, System.RoundingMode.HALF_UP);
            discount_n = discount_n == null ? 0 : discou;nt_n;
            this.pageObject.Discount = discount_n + (100 - discount_n) * this.discount / 100;*/
            //this.pageObject.Custom_Price__c = customPrice == '' ? 0 : Decimal.valueOf(customPrice);
            //this.pageObject.Description = description;
            Decimal discount2 =  100-this.pageObject.Discount;
            //this.totalPrice = discount2 * this.pageObject.Quantity * this.pageObject.UnitPrice/100;
            this.totalPrice = this.pageObject.Quantity * this.pageObject.UnitPrice * (1 - this.pageObject.Discount / 100);
            system.debug('this.totalPrice----><'+this.totalPrice);
            this.salesPrice = pbe.SalesPrice__c;
            this.salesPriceA = pbe.SalesPriceA__c;
            this.salesPriceB = pbe.SalesPriceB__c;
            this.salesPriceC = pbe.SalesPriceC__c;

            this.isProductModel = ispm;

            this.hiddenflg = pbe.Hidden_flag__c;
        }
        

    }
    public void quoteLineSetNameDiscountJson(Map<String,String> quoteLineSetNameDiscountMap){
        if (quoteLineSetNameDiscountMap.size() > 0) {
            quoteLineSetNameDiscountJson =  JSON.serializePretty(quoteLineSetNameDiscountMap);
        }
    }
    //决定报价与取消报价时增加和删除相关的"决定报价产品配套"
    public void decideORundecideQuote(String quoteId,Boolean flag){

        if (String.isBlank(quoteId)) {
            return;
        } 

        if (flag) {
            
            List<DecideQuoteProductSet__c> undecideList = new List<DecideQuoteProductSet__c>();
            undecideList = [select Id from DecideQuoteProductSet__c where DecideOpportunity__c = :oppId];
            
            if(undecideList.size() > 0 ){

                delete undecideList;
            }
        }

        system.debug('quoteId_1_2_3_4_' + quoteId);
        List<Quote>  decideQuoteList = [select Id,Name,QuoteNumber,Is_Decided__c,OpportunityId,
                                            SetName1__c,SetQty1__c,SetName2__c,SetQty2__c,SetName3__c,SetQty3__c,
                                            SetName4__c,SetQty4__c,SetName5__c,SetQty5__c,SetName6__c,SetQty6__c,
                                            SetName7__c,SetQty7__c,SetName8__c,SetQty8__c,SetName9__c,SetQty9__c,
                                            SetName10__c,SetQty10__c,
                                            SetName11__c,SetQty11__c,SetName12__c,SetQty12__c,SetName13__c,SetQty13__c,
                                            SetName14__c,SetQty14__c,SetName15__c,SetQty15__c,SetName16__c,SetQty16__c,
                                            SetName17__c,SetQty17__c,SetName18__c,SetQty18__c,SetName19__c,SetQty19__c,
                                            SetName20__c,SetQty20__c,
                                            SetName21__c,SetQty21__c,SetName22__c,SetQty22__c,SetName23__c,SetQty23__c,
                                            SetName24__c,SetQty24__c,SetName25__c,SetQty25__c,SetName26__c,SetQty26__c,
                                            SetName27__c,SetQty27__c,SetName28__c,SetQty28__c,SetName29__c,SetQty29__c,
                                            SetName30__c,SetQty30__c,OrderIsChange__c
                                             
                                        from Quote
                                        where Id = :quoteId]; 

        if (decideQuoteList[0].Is_Decided__c) {

            Map<String,Integer> quoteProductSetMap = new Map<String,Integer>();
            List<DecideQuoteProductSet__c> decideList = new List<DecideQuoteProductSet__c>();

            for (Integer i = 1; i <= 30; i++) {

                String setName = String.valueOf(decideQuoteList[0].get('SetName'+i+'__c')) ;
                Integer setQty =  Integer.valueOf(decideQuoteList[0].get('SetQty'+i+'__c')) ;

                if(setName != null && setName != ''){

                    quoteProductSetMap.put(setName, setQty);
                }
            }
            system.debug('quoteProductSetMap__0522__' + quoteProductSetMap);
            List<productSet__c> productSetList = [select Id,Name,Code__c
                                                  from productSet__c 
                                                  where Name in : quoteProductSetMap.keyset()];

                                              
            List<QuoteLineItem> items = 
                [Select Id,Product2Id,Product2.Name,Product2.ProductCode,Product2.Product_ECCode__c,Quantity,Subtotal,Discount,TotalPrice,PricebookEntryId,UnitPrice,Description,Set__c,Custom_Price__c,
                        PricebookEntry.SalesPrice__c,PricebookEntry.SalesPriceA__c,PricebookEntry.SalesPriceB__c,PricebookEntry.SalesPriceC__c,Product2.ProductModels__c,PricebookEntry.Hidden_flag__c,
                        SingleProduct__c,SetName__c ,QuoteId
                   From QuoteLineItem where SetName__c in: quoteProductSetMap.keyset() and QuoteId = :quoteId  Order by Id];
            List<Order> ordList = [Select id from Order where OpportunityId = : oppId and Status__c = 'Active'];

            system.debug('items11111_22222' + items);
            Decimal unitPrice = 0;
            Map<String,Decimal>  unitPriceMap  = new  Map<String,Decimal>();
            Map<String,Decimal>  discountMap  = new  Map<String,Decimal>();
            for (QuoteLineItem item :items) {

                if(unitPriceMap.containsKey(item.SetName__c)) {
                   unitPriceMap.put(item.SetName__c,unitPriceMap.get(item.SetName__c)+item.UnitPrice * item.Quantity);
                } else {
                    unitPriceMap.put(item.SetName__c, item.UnitPrice * item.Quantity);
                }
                system.debug('Discount_1_1_1_' + item.Discount + '(-)' + item.SetName__c);
                discountMap.put(item.SetName__c, item.Discount);
                //unitPriceMap.put(item.SetName__c, ANY value)
            }
            system.debug('20190531____'+discountMap);
            for (productSet__c productSet : productSetList) {
                system.debug('20190531__1__'+discountMap);
                DecideQuoteProductSet__c  decideProductSet = new  DecideQuoteProductSet__c();
                decideProductSet.DecideProductSetName__c = productSet.Name;
                decideProductSet.DecideProductSetCode__c = productSet.Code__c;
                decideProductSet.DecideProductSetCount__c = quoteProductSetMap.get(productSet.Name);
                decideProductSet.DecideProductSet__c = productSet.Id;
                decideProductSet.DecideOpportunity__c = decideQuoteList[0].OpportunityId;
                decideProductSet.DecideQuote__c = quoteId;
                decideProductSet.DecideProductSetUnivalence__c = unitPriceMap.get(productSet.Name) / quoteProductSetMap.get(productSet.Name);
                decideProductSet.DecideProductSetTotalprice__c = unitPriceMap.get(productSet.Name);
                //decideProductSet.DecideProductSetDiscount__c = 56;
                decideProductSet.DecideProductSetDiscount__c = discountMap.get(productSet.Name);
                if( ordList.size() > 0 ){
                    
                    decideProductSet.DecideOrder__c = ordList[0].id;
                }
                decideList.add(decideProductSet);
            }
            system.debug('items11111_3333' + items);
            if (decideList.size() > 0) {

                Insert decideList;
            }
        } 
        //else {

        //    List<DecideQuoteProductSet__c> undecideList = new List<DecideQuoteProductSet__c>();
        //    undecideList = [select Id from DecideQuoteProductSet__c where DecideQuote__c = :quoteId];
            
        //    if(undecideList.size() > 0 ){

        //        delete undecideList;
        //    }
        //}
        

        
    }

    //给报价的相关套装字段进行赋值
    public void queSetNameSetQty(Map<String,Integer> productSetID_QuantityMap,Map<String,String> productSetCodeMap){

        if (ProductSetCodeMap == null ){
            errorMap.clear();
        } 
        
        List<productSet__c> ListProductSet = new List<productSet__c>();
        List<productSetItem__c> ListproductSetItem = new List<productSetItem__c>();
        List<String> productSetCodeList = new  List<String>();

        //获取"产品配套"的名称
        ListProductSet = [select Id,Name,Code__c
                          from productSet__c 
                          where Id in :productSetID_QuantityMap.keyset() 
                          order by Name];

        //获取"产品配套明细"中产品的Id
        ListproductSetItem = [select Id,Name,product__c,productSet__c,
                                product__r.Name,product__r.ProductCode,
                                product__r.Product_ECCode__c,productSet__r.Name,
                                Count__c,productSet__r.Code__c
                              from productSetItem__c 
                              where productSet__c in :productSetID_QuantityMap.keyset() 
                              order by productSet__r.Name];
          
        system.debug('ListproductSetItem___++++__' + ListproductSetItem);                    
        for (productSetItem__c productSetItem : ListproductSetItem) {

            productSetCodeList.add(productSetItem.product__r.ProductCode);
        }

       
        Map<String, Product_Search__c> psMap = new Map<String, Product_Search__c>(); // keyがProductCodeです。
        List<String> forSelect = new List<String>();
        
        //查找"产品检索"
        List<Product_Search__c> psList = [
            select Id, Name, ProductCode__c, Product_ECCode__c, ProductDescription__c,
                     ProductStatus__c, Product__c, ProductModels1__c
              from Product_Search__c
             where ProductCode__c in :productSetCodeList];
        
        for (Product_Search__c ps : psList) {

            String pc = ps.ProductCode__c;
            if (pc.startsWith('00000000000')) {

                pc = pc.substring(11);
                psMap.put(pc, ps);
            }

            psMap.put(ps.ProductCode__c, ps);
            forSelect.add(ps.Product__c);
        }

        //根据询价的价格手册的Id和产品Id查找价格手册条目
        List<PricebookEntry> pbeList = [
            select Id, Product2Id, ProductCode, Product2.Product_ECCode__c, Product2.Dummy__c, 
                    CostPrice__c, SalesPrice__c, SalesPriceA__c, SalesPriceB__c, SalesPriceC__c,
                    Hidden_flag__c
              from PricebookEntry
             where Pricebook2Id = :pricebook2Id
               and CurrencyIsoCode = :currencyIsoCode
               and Product2.ManualHidden__c = false
               and Product2Id in :forSelect];
        
        Map<String, PricebookEntry> pbeMap = new Map<String, PricebookEntry>();
        String errProduct = '';
        
        for (PricebookEntry pbe : pbeList) {

            String pc = pbe.ProductCode;

            if ((pbe.CostPrice__c == 0 && pbe.Product2.Dummy__c == false) || pbe.SalesPrice__c == 0) {
                
                errorflg = true;
                errProduct += pbe.productCode + ',';
            } else {

                if (pc.startsWith('00000000000')) {

                    pc = pc.substring(11);
                    pbeMap.put(pc, pbe);
                }
                pbeMap.put(pbe.ProductCode, pbe);
            }
        }

        Integer no = 0 ;    String productSetName;  PricebookEntry pbe;     
        String setNames;
        String errorProductSetName = '';
        
        Map<String,QELine> existQELineMap = new Map<String,QELine>();
        List<QELine> singleProductSuitList = new List<QELine>();
        QELine qeline = new QELine(no);

        //将报价行项目中单品获取出来放入singleProductSuitList中
        for (QELine q :activities) {
            
            if ( String.isBlank(q.pageObject.Product2Id) == false && q.pageObject.SingleProduct__c == true) {

                singleProductSuitList.add(q);
            } 
            
        }

        activities = new List<QELine>();

        //找出"产品配套"中
        Map<String,String> errorproductSetMap = new Map<String,String>();
        for (productSetItem__c productSetItem : ListproductSetItem) {

            Product_Search__c ps = psMap.get(productSetItem.product__r.ProductCode);
            pbe = pbeMap.get(productSetItem.product__r.ProductCode);

            if (ps == null || pbe == null) {

                errorProductSetName = productSetItem.productSet__r.Name ;
                errorproductSetMap.put(errorProductSetName, errorProductSetName);
                errorflg = true;
                
                errProduct += productSetItem.product__r.ProductCode + ',';
                errorMap.put(errorProductSetName, 'error['+errorProductSetName+']产品配套内含有产品价格信息不正确，该产品配套不能使用。产品：' + errProduct);

                continue;
            }

        }

        Map<String,String> matchingProductSetItemMap = new  Map<String,String>();
        Map<String,String> productsetNameMap = new  Map<String,String>();
        Integer productSetNo = 1;

        //system.debug('errorMap____' + errorMap);
        for (productSet__c productSet : ListProductSet) {

            if (errorMap.containsKey(productSet.Name)) {

                continue;
            }

            if (!matchingProductSetItemMap.containsKey(productSet.Code__c)) {

                if (!errorproductSetMap.containsKey(productSet.Name)) {

                    matchingProductSetItemMap.put(productSet.Code__c, 'set0' + productSetNo);
                    productsetNameMap.put(productSet.Code__c, productSet.Name);
                    productSetNo++;
                }
                
            } 

        }

        //system.debug('matchingProductSetItemMap_1111___' + matchingProductSetItemMap);
        

        //system.debug('errorMap20190521__' + errorMap);
        for (productSetItem__c productSetItem : ListproductSetItem) {

            errorProductSetName = productSetItem.productSet__r.Name ;
            //system.debug('errorproductSetMap_2061_' + errorproductSetMap);
            //system.debug('errorProductSetName_2062_' + errorProductSetName);
            if (errorproductSetMap.containsKey(errorProductSetName)) {

                continue;
            }
            
            Product_Search__c ps = psMap.get(productSetItem.product__r.ProductCode);
            pbe = pbeMap.get(productSetItem.product__r.ProductCode);
            //quantity1 = String.valueOf(productSetID_QuantityMap.get(productSetItem.productSet__c) * productSetItem.Count__c);
            String quantity = String.valueOf(productSetID_QuantityMap.get(productSetItem.productSet__c) * productSetItem.Count__c);
            //String quantity = String.valueOf(productSetItem.Count__c);
            String productSetCode =productSetItem.productSet__r.Code__c;
            String qty = '0';
            boolean isSingleProduct = false;

            if (ps == null || pbe == null) {

                errorflg = true;
                errProduct += productSetItem.product__r.ProductCode + ',';
                errorMap.put(errorProductSetName, errProduct);

                continue;
            }
            if (matchingProductSetItemMap.containsKey(productSetItem.productSet__r.Code__c)) {

                setNames = matchingProductSetItemMap.get(productSetItem.productSet__r.Code__c); 
                productSetName = productsetNameMap.get(productSetItem.productSet__r.Code__c);       
            } else {
                continue;    
            }
            
            
            if (productSetCodeMap != null && productSetCodeMap.containsKey(productSetCode)) {
                qty = productSetCodeMap.get(productSetCode).split(';')[1];
            } 

            qeline = new QELine(isService,no,setNames,ps.Name,ps.ProductCode__c,ps.Product_ECCode__c,ps.Product__c,pbe,quantity, qty, ps.ProductModels1__c,isSingleProduct,ps.ProductDescription__c,productSetName);
            if (String.isNotBlank(qeline.pageObject.SetName__c)) {
                quoteLineSetNameDiscountMap.put(qeline.pageObject.SetName__c,String.valueOf(qeline.pageObject.Discount));
            }
            quoteLineSetNameDiscountJson(quoteLineSetNameDiscountMap);
            //quoteLineSetNameDiscountJson =  JSON.serializePretty(quoteLineSetNameDiscountMap);
            activities.add(qeline);
            no++;
            //productSetNo++;
            
        }
        
        //将单品套装放在产品配套套装的下面
        singleNo = no;

        for (QELine q :singleProductSuitList) {

            q.lineNo = singleNo;
            activities.add(q);
            singleNo++;
        }
                
        emptyData();
        
        for (productSet__c productSet : ListProductSet) {

            if (errorMap.containsKey(productSet.Name)) {
                continue;
            }

            if (errorproductSetMap.containsKey(productSet.Name)) {
                continue;
            }

            Boolean flag = productSetID_QuantityMap.containsKey(productSet.Id);
            Integer quantity ;
            if (flag) {

                quantity = productSetID_QuantityMap.get(productSet.Id);
            }
            
            if (flag && quo.SetName1__c == null ) {

                quo.SetName1__c = productSet.Name ;
                quo.SetQty1__c = quantity;
            } else if (flag && quo.SetName2__c == null){

                quo.SetName2__c = productSet.Name ;
                quo.SetQty2__c = quantity;
            } else if (flag && quo.SetName3__c == null){

                quo.SetName3__c = productSet.Name ;
                quo.SetQty3__c = quantity;
            } else if (flag && quo.SetName4__c == null){

                quo.SetName4__c = productSet.Name ;
                quo.SetQty4__c = quantity;
            } else if (flag && quo.SetName5__c == null){

                quo.SetName5__c = productSet.Name ;
                quo.SetQty5__c = quantity;
            } else if (flag && quo.SetName6__c == null){

                quo.SetName6__c = productSet.Name ;
                quo.SetQty6__c = quantity;
            } else if (flag && quo.SetName7__c == null){

                quo.SetName7__c = productSet.Name ;
                quo.SetQty7__c = quantity;
            } else if (flag && quo.SetName8__c == null){

                quo.SetName8__c = productSet.Name ;
                quo.SetQty8__c = quantity;
            } else if (flag && quo.SetName9__c == null){

                quo.SetName9__c = productSet.Name ;
                quo.SetQty9__c = quantity;
            } else if (flag && quo.SetName10__c == null){

                quo.SetName10__c = productSet.Name ;
                quo.SetQty10__c = quantity;
            } else if (flag && quo.SetName11__c == null){

                quo.SetName11__c = productSet.Name ;
                quo.SetQty11__c = quantity;
            } else if (flag && quo.SetName12__c == null){

                quo.SetName12__c = productSet.Name ;
                quo.SetQty12__c = quantity;
            } else if (flag && quo.SetName13__c == null){

                quo.SetName13__c = productSet.Name ;
                quo.SetQty13__c = quantity;
            } else if (flag && quo.SetName14__c == null){

                quo.SetName14__c = productSet.Name ;
                quo.SetQty14__c = quantity;
            } else if (flag && quo.SetName15__c == null){

                quo.SetName15__c = productSet.Name ;
                quo.SetQty15__c = quantity;
            } else if (flag && quo.SetName16__c == null){

                quo.SetName16__c = productSet.Name ;
                quo.SetQty16__c = quantity;
            } else if (flag && quo.SetName17__c == null){

                quo.SetName17__c = productSet.Name ;
                quo.SetQty17__c = quantity;
            } else if (flag && quo.SetName18__c == null){

                quo.SetName18__c = productSet.Name ;
                quo.SetQty18__c = quantity;
            } else if (flag && quo.SetName19__c == null){

                quo.SetName19__c = productSet.Name ;
                quo.SetQty19__c = quantity;
            } else if (flag && quo.SetName20__c == null){

                quo.SetName20__c = productSet.Name ;
                quo.SetQty20__c = quantity;
            } else if (flag && quo.SetName21__c == null){

                quo.SetName21__c = productSet.Name ;
                quo.SetQty21__c = quantity;
            } else if (flag && quo.SetName22__c == null){

                quo.SetName22__c = productSet.Name ;
                quo.SetQty22__c = quantity;
            } else if (flag && quo.SetName23__c == null){

                quo.SetName23__c = productSet.Name ;
                quo.SetQty23__c = quantity;
            } else if (flag && quo.SetName24__c == null){

                quo.SetName24__c = productSet.Name ;
                quo.SetQty24__c = quantity;
            } else if (flag && quo.SetName25__c == null){

                quo.SetName25__c = productSet.Name ;
                quo.SetQty25__c = quantity;
            } else if (flag && quo.SetName26__c == null){

                quo.SetName26__c = productSet.Name ;
                quo.SetQty26__c = quantity;
            } else if (flag && quo.SetName27__c == null){

                quo.SetName27__c = productSet.Name ;
                quo.SetQty27__c = quantity;
            } else if (flag && quo.SetName28__c == null){

                quo.SetName28__c = productSet.Name ;
                quo.SetQty28__c = quantity;
            } else if (flag && quo.SetName29__c == null){

                quo.SetName29__c = productSet.Name ;
                quo.SetQty29__c = quantity;
            } else if (flag && quo.SetName30__c == null){
                
                quo.SetName30__c = productSet.Name ;
                quo.SetQty30__c = quantity;
            }
            
            
        } 
        //system.debug('errorMap1231111_'+errorMap);
        if (errorflg) {
            errorMessage = '';
            for (String errorKey :errorMap.keySet()) {
                errProduct = errorMap.get(errorKey).substring(0, errorMap.get(errorKey).length()-1);
                errorMessage += errProduct + ';';  
            }
        
        }

             
    }

    //清空页面套装名称和数量
    public void emptyData(){

        quo.SetName1__c = null ;
        quo.SetQty1__c = null;
        quo.SetName2__c = null ;
        quo.SetQty2__c = null;
        quo.SetName3__c = null;
        quo.SetQty3__c = null;
        quo.SetName4__c = null ;
        quo.SetQty4__c = null;
        quo.SetName5__c = null ;
        quo.SetQty5__c = null;
        quo.SetName6__c = null ;
        quo.SetQty6__c = null;
        quo.SetName7__c = null;
        quo.SetQty7__c = null;
        quo.SetName8__c = null ;
        quo.SetQty8__c = null;
        quo.SetName9__c = null ;
        quo.SetQty9__c = null;
        quo.SetName10__c = null ;
        quo.SetQty10__c = null;
        quo.SetName11__c = null;
        quo.SetQty11__c = null;
        quo.SetName12__c = null ;
        quo.SetQty12__c = null;
        quo.SetName13__c = null ;
        quo.SetQty13__c = null;
        quo.SetName14__c = null ;
        quo.SetQty14__c = null;
        quo.SetName15__c = null ;
        quo.SetQty15__c = null;
        quo.SetName16__c = null ;
        quo.SetQty16__c = null;
        quo.SetName17__c = null ;
        quo.SetQty17__c = null;
        quo.SetName18__c = null ;
        quo.SetQty18__c = null;
        quo.SetName19__c = null ;
        quo.SetQty19__c = null;
        quo.SetName20__c = null ;
        quo.SetQty20__c = null;
        quo.SetName21__c = null ;
        quo.SetQty21__c = null;
        quo.SetName22__c = null ;
        quo.SetQty22__c = null;
        quo.SetName23__c = null ;
        quo.SetQty23__c = null;
        quo.SetName24__c = null ;
        quo.SetQty24__c = null;
        quo.SetName25__c = null ;
        quo.SetQty25__c = null;
        quo.SetName26__c = null ;
        quo.SetQty26__c = null;
        quo.SetName27__c = null ;
        quo.SetQty27__c = null;
        quo.SetName28__c = null ;
        quo.SetQty28__c = null;
        quo.SetName29__c = null ;
        quo.SetQty29__c = null;
        quo.SetName30__c = null ;
        quo.SetQty30__c = null;
    
    }
    public static Boolean IfspecialDealer(String oppDealerId){
        if ( String.isBlank(oppDealerId)) {
            return false;
        }
        return StaticParameter.specialDealerMap.containsKey(oppDealerId.substring(0,15));
    }

    public void dummy2(){
        
    }

    @TestVisible private void testI() {
        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++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
         i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
    }


}