#include "windows.h"
#include "flowControl.h"
#include "QsLog.h"
#include "DTools/dataManger.h"
#include "preDefine.h"
#include "DTools/configManger.h"
#include "Model/cashierObject.h"
#include <QJsonValue>
#include <QTimer>
#include <QDir>
#include <QApplication>
#include <QDateTime>
#include <QThread>
#include <QtConcurrent>
#include "configManger.h"
#include <QMultiMap>
#include <QMap>
#include <QFile>
#include <QJsonDocument>
#include <DTools/simProcOrderDB.h>
#include <DTools/printSumBillPosDB.h>
#include <DTools/getCaboxAReAuth.h>
#include <DTools/pmsGetStoreConfig.h>
#include <DTools/pmsOrdersData.h>
#include <QHostInfo>
#include <DTools/qtRedisClient.h>
#include "SocketCommunicate.h"

FlowControl &FlowControl::GetInstance()
{
   static FlowControl fc;
   return fc;
}

FlowControl::FlowControl()
{
    m_bLoginResult =false;
    m_loginErrorCount = 0;
    m_sendHeartErrorCount = 0;
    m_bCreateSelfCheckOrderError = false;
    m_openTcpChannel = false;
    m_bFirstRecvInfo = true;
    m_bFloatFromLockSt = false;

    m_initSimProcOrderDBRet = true;    //不使用顾默认赋值：true
    m_initPrintSumBillPosDBRet = true;  //不使用顾默认赋值：true
    m_initGetAuthPosDBRet = true;     //不使用顾默认赋值：true
    m_initPmsGetStoreConfigDBRet = false;
    m_initPmsOrdersDataRet = false;
    m_initPmsRedisRet = false;

    //初始化门店营业状态;
    m_eleStoreStatus = UNKNOWNSTORE;
    m_mopStoreStatus = UNKNOWNSTORE;
    m_modStoreStatus = UNKNOWNSTORE;
    m_mtModStoreStatus = UNKNOWNSTORE;
    m_existNoAckNotice = 0;
    //初始化上次心跳状态是否异常(false:代表心跳正常 | true:代表心跳异常);
    m_bLastHeartIsError = false;

    m_loginSocket = nullptr;
    m_pullOrderSocket = nullptr;
    m_reportOMSRecordOrderSocket = nullptr;
    m_procOrderSocket = nullptr;
    m_pullDishesSocket = nullptr;
    m_pullOrderListSocket = nullptr;
    m_orderCount = 0;
    m_o2ofulfillmentOrderCount = 0;
    m_serviceCallBackUrl = "";

    m_clearTimer=new QTimer(this);
    m_heartTimer=new QTimer(this);
    m_pullTimer=new QTimer(this);
    m_analysisTimer=new QTimer(this);
    m_reportOMSReocrdOrderTimer = new QTimer(this);
    m_loginTimer=new QTimer(this);
    m_notifyPmsPullTimer = new QTimer(this);
    m_notifyPmsUpdateTimer  = new QTimer(this);
    //m_cyclePullAllOrderTimer =  new QTimer(this);
    m_remindCasherBlinkFloatTimer = new QTimer(this);

    qRegisterMetaType<AlertForm::Type>("AlertForm::Type");

    connect(m_loginTimer,&QTimer::timeout,this,&FlowControl::_ClickToLogin);
    connect(m_notifyPmsPullTimer,&QTimer::timeout,this,&FlowControl::_NotifyPmsPullOrder);
    connect(m_notifyPmsUpdateTimer,&QTimer::timeout,this,&FlowControl::_NotifyPmsUpdateOrder);
    //connect(m_cyclePullAllOrderTimer,&QTimer::timeout,this,&FlowControl::_NotifyCyclePullAllOrder);
    connect(m_remindCasherBlinkFloatTimer,&QTimer::timeout,this,&FlowControl::_RemindCasherBlinkFloatForm);
    connect(m_pullTimer,&QTimer::timeout,this,&FlowControl::_PullOrderData);
    connect(m_analysisTimer, &QTimer::timeout, this, &FlowControl::_AnalysisOrderDetailData);
    connect(m_reportOMSReocrdOrderTimer,&QTimer::timeout,this,&FlowControl::_ReportOMSRecordOrderInfo);
    connect(m_clearTimer,&QTimer::timeout,this,&FlowControl::_CrondClearExpireOrder);
    connect(m_heartTimer,&QTimer::timeout,this,&FlowControl::_SendHeart);
    connect(this,&FlowControl::doConfirmOrder,this,&FlowControl::_ConfirmOrder,Qt::AutoConnection);
    connect(this,&FlowControl::doRefundOrder,this,&FlowControl::_RefundOrder,Qt::AutoConnection);

    // 不用将订单录入POS顾无需使用此表来标识 正向销售单 / 退货单 是否需要入机;
    // 两个数据库初始化 + 一个Redis初始化 转移到  _PmsMachineReqTryLogin()

    /*** 启动Http服务:用来响应Simphony_Script获取订单的请求***/
    localHttpServer = new LocalHttpServer();
    localHttpServer->run();

    //初始化登陆数据在登陆前;通过定时器触发登陆;
    _InitDataBeforeLogin();

   m_loginTimer->start(10*1000);
   m_notifyPmsPullTimer->start(1000*2);
   m_notifyPmsUpdateTimer->start(1000*2);

}

void FlowControl::_TestRedis(){
    /* Test Redis Function */
    QLOG_INFO() << QString::fromLocal8Bit("[<<<<---FM外卖插件 Beign  Test Redis:--->>>>]");
    QtRedisClient::getInstance().testOrderRedisExist(QString("1234"));
}

void FlowControl::_TestInsertOrderData(){
    /* Test Demo Insert Update Data Function */
    QLOG_INFO() << QString::fromLocal8Bit("[<<<<---FM外卖插件 Beign  Test Insert/Update Mysql DB:--->>>>]");
    QByteArray tempOrderByteArray ="{\"acceptedDate\": \"2019-02-19 10:45:52\",\"addressDetail\": \"房哥烧烤徐清公寓四栋二单元301\",\"arriveStoreDate\":"
                                   " \"2019-02-19 11:01:21\",\"birthday\": \"0000/08/00\",\"cancelReason\": \"0\",\"channel\": \"MOD\",\"completedDate\":"
                                   " \"2019-02-19 11:06:23\",\"confirmTime\": \"2019-02-19 10:40:49\",\"consigneeAddress\": \"房哥烧烤\",\"consigneeName\":"
                                   " \"魏丽娜\",\"consigneePhone\": \"*******8511\",\"createTime\": \"2019-02-19 10:40:39\",\"customerId\": \"1-1LKX6Z8T\","
                                   "\"customerSex\": \"女\",\"deliveryChannel\": \"fnps\",\"deliveryDate\": \"2019-02-19 11:01:26\",\"deliveryDiscount\": 300,"
                                   "\"deliveryPrice\": 900,\"deliveryStatus\": 4,\"deliveryTime\": \"2019-02-19 11:10:49\",\"estimation\": 30,\"finishTime\":"
                                   " \"2019-02-19 11:06:23\",\"firstName\": \"丽娜\",\"id\": \"72057594083578861\",\"invoiceUrl\":"
                                   " \"https://invoice.starbucks.com.cn/?ordertype=fA==&order=cmTADA5Rb0s7IQx5rM/Cqvc=\",\"lastName\": \"魏\",\"lastPayTime\":"
                                   " \"2019-02-19 10:44:39\",\"latitude\": \"30.584926\",\"longitude\": \"114.345404\",\"makeFinishDate\":"
                                   " \"2019-02-19 10:43:57\",\"msrNo\": \"6010753001229987\",\"orderDiscount\": 0,\"orderIndex\": \"8001\",\"orderStatus\":"
                                   " 5,\"orderType\": 1,\"packDiscount\": 0,\"packageFee\": 0,\"payStatus\": 2,\"payTime\": \"2019-02-19 10:40:49\","
                                   "\"payWay\": 1,\"payfmId\": \"19021910401000008472\",\"pickupCode\": \"8001\",\"posId\": \"http://10.194.132.163:24409\","
                                   "\"productPrice\": 3800,\"products\": [{\"addExtra\": [{\"code\": \"DefaultCoffee\",\"enProductName\": \"Standard\",\"id\": \"117599337611002173\",\"name\": \"标准\",\"price\": 0,\"qty\": 1},"
                                   "{\"code\": \"6411090\",\"enProductName\": \"No Foam\",\"id\": \"117599337590030649\",\"name\": \"去奶泡\",\"price\": 0,\"qty\": 1},"
                                   "{\"code\": \"DefaultMilk\",\"enProductName\": \"Whole milk\",\"id\": \"117599337648750855\",\"name\": \"全脂牛奶\",\"price\": 0,\"qty\": 1},"
                                   "{\"code\": \"DefaultSweentness\",\"enProductName\": \"Regular\",\"id\": \"117599337630925059\",\"name\": \"标准\",\"price\": 0,\"qty\": 1}],\"code\": \"1114105\",\"defaultImage\": "
                                   "\"https://pcmd.starbucks.com.cn/CoreMenuPics/59-MODCatalog-1-810x810-zh.jpg\",\"enProductName\": "
                                   "\"Vanilla Flavored Latte\",\"enSpecificationName\": \"HotVenti\",\"id\": \"117599337583739190\",\"name\":"
                                   " \"香草风味拿铁\",\"options\": \"9107824\",\"packagePrice\": 0,\"price\": 3800,\"promotionPrice\": 0,\"promotionQty\": 0,"
                                   "\"qty\": 1,\"specId\": \"117599337649799438\",\"specName\": \"热超大杯\"},{\"addExtra\": [{\"code\": \"DefaultCoffee\",\"enProductName\": \"Standard\",\"id\": \"117599337611002173\",\"name\": \"标准\",\"price\": 0,\"qty\": 1},"
                                   "{\"code\": \"6411090\",\"enProductName\": \"No Foam\",\"id\": \"117599337590030649\",\"name\": \"去奶泡\",\"price\": 0,\"qty\": 1},"
                                   "{\"code\": \"DefaultMilk\",\"enProductName\": \"Whole milk\",\"id\": \"117599337648750855\",\"name\": \"全脂牛奶\",\"price\": 0,\"qty\": 1},"
                                   "{\"code\": \"DefaultSweentness\",\"enProductName\": \"Regular\",\"id\": \"117599337630925059\",\"name\": \"标准\",\"price\": 0,\"qty\": 1}],\"code\": \"1114105\","
                                   "\"defaultImage\": \"https://pcmd.starbucks.com.cn/CoreMenuPics/59-MODCatalog-1-810x810-zh.jpg\",\"enProductName\": "
                                   "\"Vanilla Flavored Latte\",\"enSpecificationName\": \"HotVenti\",\"id\": \"117599337583739190\",\"name\": \"热拿铁\","
                                   "\"options\": \"9107824\",\"packagePrice\": 0,\"price\": 3600,\"promotionPrice\": 0,\"promotionQty\": 0,\"qty\": 1,"
                                   "\"specId\": \"117599337649799438\",\"specName\": \"热超大杯\"}],\"riderName\": \"张明宪\",\"riderPhone\": \"15072197137\","
                                   "\"storeAddress\": \"湖北省武汉市洪山区徐东大街31号徐东新世界百货一层09B号\",\"storeId\": \"17441\",\"storeName\": "
                                   "\"武汉徐东新世界店\",\"street\": \"徐清公寓四栋二单元301\",\"thirdPartyBatch\":\"2019021922001495141017833460\",\"totalPrice\":"
                                   " 4400,\"waybillId\": \"2100012951835222583\" }";
    QString tempOrderDoc = QString::fromLocal8Bit(tempOrderByteArray);
    QJsonParseError jsonError;
    QJsonObject tempOrderObj = QJsonDocument::fromJson(tempOrderDoc.toUtf8(), &jsonError).object();
    if(jsonError.error != QJsonParseError::NoError) {
        QLOG_INFO() << QString("[<<<<---FlowControl::_TestInsertOrderData() OrderJsonDoc Parse Failed:%1--->>>>]").arg( jsonError.errorString() );
    } else {
        OrderObject* testOrderObject = new OrderObject();
        testOrderObject->FromJson(tempOrderObj);
        m_FmOrdersMap.insert(testOrderObject->id, testOrderObject);
        m_simValidOrdersList.append(testOrderObject->id);
        QLOG_INFO() << QString("[<<<<---FlowControl::_TestInsertOrderData() m_simValidOrdersList Append Success:%1--->>>>]").arg(testOrderObject->id);

        QtRedisClient::getInstance().pushOrder2Redis(testOrderObject);
        QLOG_INFO() << QString("[<<<<---FlowControl::test pushOrder2Redis() orderId:%1  Success--->>>>]").arg(testOrderObject->id);

    }
}


bool FlowControl::_AppendOrderInfo2Redis(const OrderObject* orderObject) {
    QLOG_INFO() << QString("[<<<<---FlowControl:: _AppendOrderInfo2Redis() orderId:%1 Begin...... --->>>>]").arg(orderObject->id);
    return QtRedisClient::getInstance().pushOrder2Redis(orderObject);
}

void FlowControl::_GetIpAddress()
{
    std::string macAddress = "";
    std::string ipAddress = "";
    int getMacRet = MacTool::GetMacByAdaptersAddresses( macAddress , ipAddress);
    if ( !getMacRet) {
        QLOG_ERROR() << "FlowControl::_GetIpAddress  MacTool->GetMacByAdaptersAddresses Falied";
    }
    m_posMacAddress = macAddress.c_str();
    m_ipAddress = ipAddress.c_str();

    QHostInfo info = QHostInfo::fromName(QHostInfo::localHostName());
    m_posHostName = info.hostName();
    m_ipPortAddress = ipAddress.c_str() + QString(":") + QString::number(ConfigManger::GetInstance().GetHttpServerPort());

    QLOG_INFO()<<QString("[<<<<---FlowControl::_GetIpAddress Request Real IpAddress: %1, hostName: %2, macAddress: %3, ipPortAddress: %4 --->>>>]")
                 .arg(m_ipAddress).arg(m_posHostName).arg(m_posMacAddress).arg(m_ipPortAddress);
}


void FlowControl::_AddOrderPull(const QString &orderId, const QString &channel, const QString& callBackUrl, const int &pageNumber, const int &pageSize)
{
    bool btryLock = m_PullOrderDataMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
    if (btryLock) {
        /***组装从FM外卖service端的拉单请求参数***/
        PullOrderInfo* orderPull = new PullOrderInfo();
        orderPull->orderId=orderId;
        orderPull->channel=channel;
        orderPull->pageNumber=pageNumber;
        orderPull->pageSize=pageSize;
        orderPull->callBackUrl=callBackUrl;
        orderPull->skipPrint = false;
        orderPull->pushOptions = QJsonObject();
        orderPull->pullErrorCount = 0;
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_AddOrderPull orderId: %1 , callBackUrl: %2--->>>>]").arg(orderId).arg(callBackUrl);
        m_orderPullList.append(orderPull);
        m_PullOrderDataMutex.unlock();
    }else {
        QLOG_ERROR()<<QString::fromLocal8Bit("[<<<<---FlowControl::_AddOrderPull orderId:%1 tryLock Faild--->>>>]").arg(orderId);
    }
}


bool FlowControl::_TryAddOrderPull(const QString &orderId, const QString &channel, const QString &callBackUrl, const int &pageNumber, const int &pageSize)
{
    bool btryLock = m_PullOrderDataMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
    if (btryLock) {
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_TryAddOrderPull orderId:%1--->>>>]").arg(orderId);
        //调用此函数:_TryAddOrderPull() 的函数:_ResponseOMS11Request()没有能百分之百锁定住:插件正触发Simphony在录销售单时，插件立刻接受到OMS推送过来的退货单;
        if(!m_simValidOrdersList.isEmpty()) {
            //缩小锁住订单的条件范围: 服务端推单给插件程序且插件程序拒绝本次订单状态发生变化的请求
            if(orderId == m_simValidOrdersList.first() && m_bFloatFromLockSt) {
                QLOG_ERROR()<<QString::fromLocal8Bit("[<<<<---FlowControl::_TryAddOrderPull orderId:%1 当前订单正在录POS系统，请耐心等待--->>>>]").arg(orderId);
                m_PullOrderDataMutex.unlock();
                return false;
            }
        }
        /***组装从FM外卖service端的拉单请求参数***/
        //遍历 如果指定订单已经在待拉取订单列表中,则不需要在继续添加到列表中;
       PullOrderInfo* tempOrderPull = nullptr;
       if(!m_orderPullList.isEmpty()){
            QList<PullOrderInfo*>::iterator i;
            for (i = m_orderPullList.begin(); i != m_orderPullList.end(); ++i) {
                tempOrderPull = (*i);   //*i 使用*运算符获取遍历容器中所指的元素;
                if (orderId == tempOrderPull->orderId) {
                    //待拉取的订单详细列表已经存在,无需在添加;
                    m_PullOrderDataMutex.unlock();
                    return true;
                } else {
                    tempOrderPull = nullptr;
                }
            }
        }
        PullOrderInfo* orderPull = new PullOrderInfo();
        orderPull->orderId=orderId;
        orderPull->channel=channel;
        orderPull->callBackUrl = callBackUrl;
        orderPull->pageNumber=pageNumber;
        orderPull->pageSize=pageSize;
        orderPull->pullErrorCount = 0;
        orderPull->skipPrint = false;
        orderPull->pushOptions = QJsonObject();

        m_orderPullList.append(orderPull);
        m_PullOrderDataMutex.unlock();
    } else {
        QLOG_ERROR()<<QString::fromLocal8Bit("[<<<<---FlowControl::_TryAddOrderPull orderId:%1 Try Lock Error--->>>>]").arg(orderId);
    }
    return btryLock;
}


bool FlowControl::_TryAddOrderQueueAnalysis(const QString& orderId, const QJsonObject& orderDetailJson, const QString& callBackUrl, const QJsonObject& pushOptions)
{
    bool btryLock = m_analysisOrderDataMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
    if (btryLock) {
        QLOG_INFO()<<QString("[<<<<---FlowControl::_TryAddOrderQueueAnalysis orderId=%1 pushOptions= --->>>>]").arg(orderId) << pushOptions;
        //遍历如果指定订单已经在待解析列表中,则需要替换最新数据到列表中;
       AnalysisOrderInfo* tempOrderAnalysis = NULL;
       if ( !m_orderAnalysisList.isEmpty() ) {
            QList<AnalysisOrderInfo*>::iterator i;
            for ( i = m_orderAnalysisList.begin(); i != m_orderAnalysisList.end(); ++i ) {
                tempOrderAnalysis = (*i);   //*i 使用*运算符获取遍历容器中所指的元素;
                if ( orderId == tempOrderAnalysis->orderId ) {
                    tempOrderAnalysis->callBackUrl = callBackUrl;
                    tempOrderAnalysis->orderDetailJson = orderDetailJson;
                    tempOrderAnalysis->pushOptions = pushOptions;
                    m_analysisOrderDataMutex.unlock();
                    return true;
                } else {
                    tempOrderAnalysis = NULL;
                }
            }
        }

        AnalysisOrderInfo* orderAnalysis = new AnalysisOrderInfo();
        orderAnalysis->orderId=orderId;
        orderAnalysis->callBackUrl = callBackUrl;
        orderAnalysis->orderDetailJson = orderDetailJson;
        orderAnalysis->pushOptions = pushOptions;

        m_orderAnalysisList.append(orderAnalysis);
        m_analysisOrderDataMutex.unlock();
    } else {
        QLOG_ERROR()<<QString::fromLocal8Bit("[<<<<---FlowControl::_TryAddOrderQueueAnalysis orderId:%1 Try Lock Error--->>>>]").arg(orderId);
    }
    return btryLock;
}


//避免 此槽函数 与 拉单定时器触发的槽函数mutex阻塞挂住:因此不调用 emit doPullOrder函数;
//void FlowControl::_GetReadyForPullOrder(const QString &orderId, const QString &channel){}

void FlowControl::_ClickOMSAssignArea()
{
    /*
    // 由于星巴克POS存在两种屏幕[①大屏：1366*768 ②小屏：1024*768] 因此采用获取系统屏幕底部坐标减去一个相对距离来实现正确的点击事件(2018-08-13 初步设定：x-10，y-30)；
    // QPoint point=ConfigManger::GetInstance().GetOMSBtnPostion();
    int xOffset = ConfigManger::GetInstance().GetOMSBtnWidthOffset();
    int yOffset = ConfigManger::GetInstance().GetOMSBtnHeightOffset();
    QLOG_INFO()<<QString::fromLocal8Bit("(yOffset%1:,yOffset:%2)").arg(xOffset).arg(yOffset);
    int nWidth = GetSystemMetrics(SM_CXSCREEN) - xOffset;
    int nHeight = GetSystemMetrics(SM_CYSCREEN) - yOffset;
    SetCursorPos(nWidth,nHeight);
    mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
    mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---触发按钮点击事件：Simphony获取订单请求->坐标(x%1:,y:%2):--->>>>]").arg(nWidth).arg(nHeight);
    */
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---触发按钮点击事件：PMS 无需触发真实的点击:--->>>>]");
}

void FlowControl::_ClickToLogin()
{
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---触发按钮点击事件：_ClickToLogin: m_bLoginResult:%1 --->>>>>]").arg(m_bLoginResult);
    if(!m_bLoginResult)
    {
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_ClickToLogin() FM插件 现在尝试登录，若失败6s后再次尝试登陆--->>>>]");
        _PmsMachineReqTryLogin();
    }else{
        m_loginTimer->start(1000*60*2);
    }
}


void FlowControl::_SmartTriggerClickPosBtn(const bool bTimerTrigger)
{
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl:_SmartTriggerClickPosBtn: m_bFloatFromLockSt: --->>>>>]")<<m_bFloatFromLockSt<<QString::fromLocal8Bit(" bTimerTrigger:")<< bTimerTrigger;
    //判断当前插件是否锁定状态:如果是锁定状态:不做任何处理；  如果是未锁定状态:1：重置锁定标志；2：隐藏主窗体显示悬浮框；3：锁住悬浮框；4模拟点击POS机右下角button；
    if (bTimerTrigger) {
        _ClickOMSAssignArea();
    }else if (!m_bFloatFromLockSt) {
        //转移到 _ResponseSimReqFristOrderData() 实际触发录单请求时 才隐藏和锁定悬浮框;
        _ClickOMSAssignArea();
    }
}


void FlowControl::_NotifyPmsPullOrder()
{
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---：_NotifyPmsPullOrder: m_simValidOrdersList.isEmpty()=%1, m_simValidOrdersList.count()=%2--->>>>>]")
                 .arg( m_simValidOrdersList.isEmpty()?1:0 ).arg( m_simValidOrdersList.count() );
    if(!m_simValidOrdersList.isEmpty())
    {
        m_notifyPmsPullTimer->start(1000*2);
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FM插件 向PMS数据库插入数据; 并添加 Redis --->>>>]");

        QString listFirstOrderId = m_simValidOrdersList.takeFirst();
        OrderObject* orderObject = m_FmOrdersMap.value(listFirstOrderId);

        // 更新/ 插入结果;
        bool updateRet = false;
        bool insertRet = false;
        bool bExistOrder = false;
        if(orderObject) {
            //如果订单存在库中则更新订单状态;
            bExistOrder = PmsOrdersData::getInstance().isOrderExist(orderObject->id);
            if( bExistOrder ){
                updateRet = PmsOrdersData::getInstance().updateOrderStatus( orderObject, orderObject->orderStatus, orderObject->makeStatus );
            //不存在则插入;
            } else {
                QString pmsOrderRef;
                insertRet = PmsOrdersData::getInstance().insertOrderData(orderObject,pmsOrderRef);
            }
            QLOG_INFO()<<QString("[<<<<---FlowControl::_NotifyPmsPullOrder Insert Mysql DB  Order:%1 bExistOrder:%2  insertRet:%3  updateRet:%4--->>>>]")
                         .arg(orderObject->id).arg(bExistOrder?1:0).arg(insertRet?1:0).arg(updateRet?1:0);
            //如果订单 插入/更新 数据库成功后，向Redis中添加此订单信息;
            if ( insertRet || updateRet ) {
                for (int i=0;i<3;i++) {
                    if ( _AppendOrderInfo2Redis(orderObject) ) {
                        if (i) {
                            QLOG_INFO()<<QString("[<<<<---FlowControl::_NotifyPmsPullOrder  _AppendOrderInfo2Redis Success Try times:%1--->>>>]").arg(i);
                        }
                       //只有第一次插入DB成功，才会想OMS汇报入机情况；
                       // 将此订单添加汇报队列中; 参数2: "1":代表成功; "2":代表失败;  参数3:入机备注;
                       if(insertRet) {
                           _AddOrderInfo2ReportList(orderObject,QString("1"),QString::fromLocal8Bit("订单入PMS库成功并通知Redis成功"));
                       }
                       break;
                    } else {
                       QLOG_ERROR()<<QString("[<<<<---FlowControl::_NotifyPmsPullOrder  _AppendOrderInfo2Redis Failed, Try Again--->>>>]");
                       QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_NotifyPmsPullOrder() Begin  initQtRedisClient()--->>>>]");
                       m_initPmsRedisRet = QtRedisClient::getInstance().initQtRedisClient();
                       continue;
                    }
                }
            //如果订单插入/更新 数据库失败后;向服务端汇报订单落库情况;
            } else {
                QLOG_ERROR()<<QString("[<<<<---FlowControl::_NotifyPmsPullOrder Insert Mysql DB  Order:%1  Insert/Update Failed--->>>>]").arg(orderObject->id);
                //只有插入失败才 进行数据清理;防止与重新入机的订单数据出现重复; 删除 orders/order_item/order_item_condiments
                if(!bExistOrder && !insertRet) {
                    PmsOrdersData::getInstance().deleteOrderData(orderObject);
                }
                //将此订单添加汇报队列中; 参数2: "1":代表成功; "2":代表失败;  参数3:入机备注;
                _AddOrderInfo2ReportList(orderObject,QString("2"),QString::fromLocal8Bit("订单 插入/更新 PMS库数据失败"));
            }
        } else {
            QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_NotifyPmsPullOrder  Insert Mysql DB  orderObject Is Null:--->>>>]");
        }
    } else {
        //如果订单队列中没有待处理订单,定时器设定为3s;
        m_notifyPmsPullTimer->start(1000*3);
    }
}


void FlowControl::_NotifyPmsUpdateOrder()
{
    if ( !m_simValidOrdersList.isEmpty() ) {
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---_NotifyPmsUpdateOrder: m_simValidOrdersList.count()=%1,  m_waitUpdateOrderList.count()=%2, Priority Process Insert List--->>>>>]")
                     .arg( m_simValidOrdersList.count() ).arg( m_waitUpdateOrderList.count() );
        m_notifyPmsUpdateTimer->start(1000*3);
        return;
    }

    if(!m_waitUpdateOrderList.isEmpty())
    {
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---_NotifyPmsUpdateOrder: m_waitUpdateOrderList.isEmpty()=%1, m_waitUpdateOrderList.count()=%2--->>>>>]")
                     .arg( m_waitUpdateOrderList.isEmpty()?1:0 ).arg( m_waitUpdateOrderList.count() );

        m_notifyPmsUpdateTimer->start(1000*1);
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FM插件 向PMS数据库插入数据; 并添加 Redis --->>>>]");

        QString listFirstOrderId = m_waitUpdateOrderList.takeFirst();
        OrderObject* orderObject = m_FmOrdersMap.value(listFirstOrderId);

        // 更新/ 插入结果;
        bool updateRet = false;
        bool insertRet = false;
        bool bExistOrder = false;
        if(orderObject) {
            //如果订单存在库中则更新订单状态;
            bExistOrder = PmsOrdersData::getInstance().isOrderExist(orderObject->id);
            if( bExistOrder ){
                updateRet = PmsOrdersData::getInstance().updateOrderStatus( orderObject, orderObject->orderStatus, orderObject->makeStatus );
            //不存在则插入;
            } else {
                QString pmsOrderRef;
                insertRet = PmsOrdersData::getInstance().insertOrderData(orderObject,pmsOrderRef);
            }
            QLOG_INFO()<<QString("[<<<<---FlowControl::_NotifyPmsUpdateOrder Insert Mysql DB  Order:%1 bExistOrder:%2  insertRet:%3  updateRet:%4--->>>>]")
                         .arg(orderObject->id).arg(bExistOrder?1:0).arg(insertRet?1:0).arg(updateRet?1:0);
            //如果订单 插入/更新 数据库成功后，向Redis中添加此订单信息;
            if(insertRet || updateRet) {
                for (int i=0;i<3;i++) {
                    if( _AppendOrderInfo2Redis(orderObject) ) {
                        if ( i ) {
                            QLOG_INFO()<<QString("[<<<<---FlowControl::_NotifyPmsUpdateOrder  _AppendOrderInfo2Redis Success Try times:%1--->>>>]").arg(i);
                        }
                       //只有第一次插入DB成功，才会想OMS汇报入机情况；
                       // 将此订单添加汇报队列中; 参数2: "1":代表成功; "2":代表失败;  参数3:入机备注;
                       if(insertRet) {
                           _AddOrderInfo2ReportList(orderObject,QString("1"),QString::fromLocal8Bit("订单入PMS库成功并通知Redis成功"));
                       }
                       break;
                    } else {
                       QLOG_ERROR()<<QString("[<<<<---FlowControl::_NotifyPmsUpdateOrder  _AppendOrderInfo2Redis Failed, Try Again--->>>>]");
                       QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_NotifyPmsUpdateOrder() Begin  initQtRedisClient()--->>>>]");
                       m_initPmsRedisRet = QtRedisClient::getInstance().initQtRedisClient();
                       continue;
                    }
                }
            //如果订单插入/更新 数据库失败后;向服务端汇报订单落库情况;
            } else {
                QLOG_ERROR()<<QString("[<<<<---FlowControl::_NotifyPmsUpdateOrder Insert Mysql DB  Order:%1  Insert/Update Failed--->>>>]").arg(orderObject->id);
                //只有插入失败才 进行数据清理;防止与重新入机的订单数据出现重复; 删除 orders/order_item/order_item_condiments
                if(!bExistOrder && !insertRet) {
                    PmsOrdersData::getInstance().deleteOrderData(orderObject);
                }
                //将此订单添加汇报队列中; 参数2: "1":代表成功; "2":代表失败;  参数3:入机备注;
                _AddOrderInfo2ReportList(orderObject,QString("2"),QString::fromLocal8Bit("订单 插入/更新 PMS库数据失败"));
            }
        } else {
            QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_NotifyPmsUpdateOrder  Insert Mysql DB  orderObject Is Null:--->>>>]");
        }
    } else {
        m_notifyPmsUpdateTimer->start(1000*5);
    }
}


void FlowControl::_NotifyCyclePullAllOrder()
{
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<--- _NotifyCyclePullAllOrder: m_simValidOrdersList.count()==%1--->>>>>]").arg( m_simValidOrdersList.count() );

    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_NotifyCyclePullAllOrder  Call  onGetOMSAllOrders():--->>>>]");

    onGetOMSAllOrders();

    //定期拉取OMS门店全部有效订单 间隔为:10分钟;
    //m_cyclePullAllOrderTimer->start(1000*60*10);
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_NotifyCyclePullAllOrder Next Pull All Order Time: %1--->>>>]")
                 .arg(QDateTime::currentDateTime().addSecs(60*10).toString("yyyy-MM-dd hh:mm:ss"));

}


void FlowControl::_RemindCasherBlinkFloatForm()
{
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---_RemindCasherBlinkFloatForm: m_simValidOrdersList.isEmpty()=%1, m_simValidOrdersList.count()=%2--->>>>>]")
                 .arg( m_simValidOrdersList.isEmpty() ).arg( m_simValidOrdersList.count() );
    if(!m_simValidOrdersList.isEmpty())
    {
        m_remindCasherBlinkFloatTimer->start(1000*8);
        emit startRemind(REMIND_SIM_ORDERLIST_NOEMPTY);
    }else{
        m_remindCasherBlinkFloatTimer->start(1000*20);
    }
}



void FlowControl::_OrderAnalysis(const QJsonObject& jsonObject)
{
    OrderObject *orderObject = nullptr;
    bool  bRetOrderUpdateMutex = false;
    if ( ! jsonObject.contains(JSON_ID) ) {
        QLOG_ERROR() << QString("[<<<<---FlowControl::_OrderAnalysis: Json Object No Has Import Key -> OrderId , JsonObject Is Illegal , Abandon This Object --->>>>]") << jsonObject;
        return ;
    }
    orderObject = m_FmOrdersMap.value(jsonObject[JSON_ID].toString());
    /***<1>:FM插件维护的有效订单容器中不存在此订单：整合数据并插入到此订单容器中 ***/
    if(orderObject == nullptr)
    {
        orderObject = new OrderObject(this);
        //初始化数据;
        orderObject->orderIndex = 0;
        orderObject->disPlateformFee = 0;
        orderObject->orderDiscount = 0;
        orderObject->appointmentDayFlag = 0;
        orderObject->packageFee = 0;
        orderObject->packDiscount = 0;
        orderObject->deliveryPrice = 0;
        orderObject->deliveryDiscount = 0;
        orderObject->forwardPosStatus =0;
        orderObject->negativePosStatus =0;
        orderObject->businessType = "0";
        orderObject->inAdvanceTakemeal = 0;
        orderObject->globalServiceType = 0;
        orderObject->globalOrderType = 0;
        orderObject->isGiftitForward = 0 ;
        orderObject->callBackUrl = "";
        orderObject->pcsCallbackUrl = "";
        orderObject->deliveryAtProd = false;
        orderObject->packageFeeAtProduct = false;

        orderObject->FromJson(jsonObject);
        orderObject->pushOrderType=0;
        orderObject->orsPushOrderType = 0;
        orderObject->isPush = false;
        orderObject->isCancle = false;
        orderObject->isORSPush = false;
        orderObject->isORSCancle = false;
        //初始化订单在数据库中标志性数据:用于一次性读出；减少对数据库的加锁访问+数据库连接数;防止压测插件奔溃;
        orderObject->dataBaseIsOrderExistInt = 0;
        orderObject->dataBaseIsPushInt = 0;
        orderObject->dataBaseIsCancleInt = 0;
        orderObject->dataBaseIsORSPushInt = 0;
        orderObject->dataBaseIsORSCancleInt = 0;
        orderObject->dataBasePosOrderCheckNo = "";

        m_FmOrdersMap.insert(orderObject->id, orderObject);

        // 89 == orderType 标识订单是 ELE-权益卡单,无需存储与打印, 但是需要界面展示;
        if ( 89 != orderObject->orderType ) {
            //插件程序内存中没有此订单时需要从数据库中获取该订单标志数据;同时在接受到退单情况时，也需要从数据库中重新获取(防止内存中标志数据未更新[入机后未更新]);
            //查询此 订单+订单状态+制作状态+预约单提前到店 是否已经存在数据库中;
            bool pmsMakeStatusIsExistRet = true;
            int    pmsArriveAheadFlag = 0;
            bool pmsOrderStatusIsExistRet = PmsOrdersData::getInstance().isOrderAndStatusExist(orderObject->id, orderObject->orderStatus,
                                                                                               orderObject->makeStatus, pmsMakeStatusIsExistRet, pmsArriveAheadFlag );
            QLOG_INFO() << QString("[<<<<---FmTakeout Valid Orders Map:Insert New Order[ OrderId: %1   OrderDesc: %2   OrderStatus: %3 "
                                   " MakeStatus: %4  oldArriverAhead: %5 NewArriverAhead: %6 expectDate: %7 reserveMakeTime: %8 remindTicketTime: %9 "
                                   " reserveMakeTime: %10 ]--->>>>]")
                           .arg(orderObject->id).arg( orderObject->getOrderStatusDec() ).arg(orderObject->orderStatus)
                           .arg(orderObject->makeStatus).arg(pmsArriveAheadFlag).arg(orderObject->inAdvanceTakemeal)
                           .arg(orderObject->expectDate).arg(orderObject->reserveMakeTime).arg(orderObject->remindTicketTime)
                           .arg(orderObject->privacyPhone);

            if ( !pmsOrderStatusIsExistRet || !pmsMakeStatusIsExistRet || ( pmsArriveAheadFlag != orderObject->inAdvanceTakemeal ) ||  ( 3 == orderObject->inAdvanceTakemeal ) ) {
                //程序刚启动+量大+ 异步也无碍 顾无需加锁;
                m_simValidOrdersList.append(orderObject->id);
            }
        } else {
            QLOG_INFO() << QString::fromLocal8Bit("[<<<<---FmTakeout Valid Orders Map:Insert New Order[ OrderId: %1 (orderType=89 权益卡单Skip入库等操作)   OrderDesc: %2   OrderStatus: %3 "
                                   " MakeStatus: %4 ]--->>>>]").arg(orderObject->id).arg( orderObject->getOrderStatusDec() ).arg(orderObject->orderStatus) .arg(orderObject->makeStatus);
        }

        emit changeOrderStatus(orderObject);
    }
    /***<2>:FM插件维护的有效订单容器中存在此订单:更新订单容器中此订单的订单状态***/
    else {
        int oldStatus = orderObject->orderStatus;
        QString oldMakeStatus = orderObject->makeStatus;
        int oldArriverAhead = orderObject->inAdvanceTakemeal;

        orderObject->FromJson(jsonObject);
        QLOG_INFO() << QString("[<<<<---FmTakeout Valid Order Map:Update  orderId:%1 OldStatus:%2 curStatus:%3 "
                               "OldMakeStatus:%4 makeStatus:%5 OldArriverAhead:%6 NewArriverAhead:%7 expectDate: %8 reserveMakeTime: %9 remindTicketTime: %10 ]--->>>>]")
                       .arg(orderObject->id).arg(oldStatus).arg(orderObject->orderStatus)
                       .arg(oldMakeStatus).arg(orderObject->makeStatus).arg(oldArriverAhead).arg(orderObject->inAdvanceTakemeal)
                       .arg(orderObject->expectDate).arg(orderObject->reserveMakeTime).arg(orderObject->remindTicketTime);
        // 如果订单状态 或 制作状态 或 预约单提前到店 出现变化都需添加到队列;
        if(oldStatus != orderObject->orderStatus || oldMakeStatus != orderObject->makeStatus
                || ( oldArriverAhead != orderObject->inAdvanceTakemeal ) || ( 3 == orderObject->inAdvanceTakemeal ) ) {

            // 89 == orderType 标识订单是 ELE-权益卡单,无需存储(PCS无法控制打印指令,PCS无需给OMS上游提供入机回调结果) 与 打印, 但是需要界面展示;
            if ( 89 != orderObject->orderType ) {
                bRetOrderUpdateMutex =m_OrderUpdateMutex.tryLock(VALUE_TRYLOCKMEMTIMEOUT);
                if(!bRetOrderUpdateMutex) {
                    QLOG_INFO() << QString("[<<<<---FmTakeout _OrderAnalysis:orderId:%1 OrderStatus:%2 MakeStatus:%3 ArriverAhead:%4 Changed, But m_OrderUpdateMutex.tryLock Failed --->>>>]")
                                   .arg(orderObject->id).arg(orderObject->orderStatus).arg(orderObject->makeStatus).arg(orderObject->inAdvanceTakemeal);
                } else {
                    m_waitUpdateOrderList.append(orderObject->id);
                    m_OrderUpdateMutex.unlock();
                }
            }
            emit changeOrderStatus(orderObject, oldStatus);
        }

    }

    orderObject->updateTime=QDateTime::currentDateTime().toTime_t();
    if(OrderObject::RequestRefund==orderObject->orderStatus) {
        emit startRemind(REMIND_REQREFUND_ORDER);
    }

    switch (orderObject->orderStatus) {
    case OrderObject::NewOrder:
        break;
    case OrderObject::Confirmed:
        break;
    case OrderObject::Sendout:
        break;
    case OrderObject::Finished:
        break;
    case OrderObject::RequestRefund:
        // 星巴克：当客户同意退款时，外卖插件收到请求退款后，直接进行退款处理；
        _RefundOrder(orderObject->id,5,QString::fromLocal8Bit("同意退款"),QString());
        break;
    case OrderObject::AgreeRefund:
        break;
    case OrderObject::Refunded:
        break;
    default:
        break;
    }
}


void FlowControl::onGetNewStoreInfo()
{
    QLOG_INFO()<<"[<<<<---Get New Store Info:Openssl support--->>>>]:"<<QSslSocket::supportsSsl();
    m_loginSocket = new BillSocket(this);
    m_pullOrderSocket = new BillSocket(this);
    m_reportOMSRecordOrderSocket = new BillSocket(this);
    m_procOrderSocket = new BillSocket(this);
    m_pullDishesSocket = new BillSocket(this);
    m_pullOrderListSocket = new BillSocket(this);
    _GetStoreInfo();
    _Login();
    return ;
}

//鸡肋：没有用到此函数的实际功能【仅仅用来获取门店登陆用的密码:m_password】；
bool FlowControl::_GetStoreInfo()
{
    bool result=true;
    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在获取门店信息......"));
    QLOG_INFO() << QString("[<<<<---Get StoreInfo--->>>>]");
    QString tmp;
    ConfigManger::GetInstance().GetStoreInfo(tmp/*, m_posId, m_cashierId*/, m_password);
    return result;
}


void FlowControl::_GetFcMajorInfo(bool &loginResult, bool &openTcpChannel, QString &storeId, QString &posIp, QString &posHostName, QString &posWorkStationNum){
    loginResult = m_bLoginResult;
    openTcpChannel = m_openTcpChannel;
    storeId = m_storeId;
    posIp = m_ipAddress;
    posHostName = m_posHostName;
    posWorkStationNum = m_posWorkstationNum;
}

QString FlowControl::_GetCashierId()
{
    return m_cashierId;
}

QString FlowControl::_GetCashierName()
{
    return m_cashierName;
}

bool FlowControl::_SimValidOrdersListIsEmpty(){
    return m_simValidOrdersList.empty();
}


void FlowControl::_InitDataBeforeLogin(){
    QLOG_INFO()<<"[<<<<---FlowControl::_InitDataBeforeLogin:Openssl support--->>>>]:"<<QSslSocket::supportsSsl();
    m_loginSocket = new BillSocket(this);
    m_pullOrderSocket = new BillSocket(this);
    m_reportOMSRecordOrderSocket = new BillSocket(this);
    m_procOrderSocket = new BillSocket(this);
    m_pullDishesSocket = new BillSocket(this);
    m_pullOrderListSocket = new BillSocket(this);
    QString tmp;
    ConfigManger::GetInstance().GetStoreInfo(tmp/*, m_posId, m_cashierId*/, m_password);
}

bool FlowControl::_Login()
{
    //获取POS机的 [IP地址] + [IP+PORT地址] -> 更新到成员变量:m_ipAddress, m_ipPortAddress;
    //为了避免 127.0.0.1的地址出现，必须在每次登陆前获取一次ip地址;
    _GetIpAddress();

    QString error;
    QString url;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;
    m_puginVersionComments = ConfigManger::GetInstance().GetOrderServerUrl();

    sendJson = DataManger::GetInstance().GetLoginData(ConfigManger::GetInstance().GetPartnerId(),m_storeId,
                                                      m_password, m_posId, m_puginVersionComments,m_ipPortAddress,m_pmsMachineNo);

    // 登录新增Pos相关属性字段;
    sendJson.insert(JSON_POS_IP_ADDR, m_ipAddress);
    sendJson.insert(JSON_POS_WORKS_NUM, m_posWorkstationNum);
    sendJson.insert(JSON_POS_HOST_NAME, m_posHostName);
    sendJson.insert(JSON_POS_MAC_ADDRESS, m_posMacAddress);
    sendJson.insert(JSON_LOGIN_WITH_CONTAINS_ORDER_DETAIL, true);

    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在登录......"));

    if(ConfigManger::GetInstance().GetLoginSslConfig()) {
        m_loginSocket->SetSslConfig();
        QLOG_INFO() << QString("[<<<<---_Login Set ssl Config--->>>>]");
    }

    // 如果前3次使用初始地址登录失败 3 次, 则切换使用 备用地址 再尝试3次, 合计超过6次，则切回初始地址继续登录;
    if ( m_serviceCallBackUrl.length() && m_loginErrorCount > 2 && m_loginErrorCount < 6 ) {
        url = m_serviceCallBackUrl + "/pos/" + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_ILOGIN);
        sendJson.remove(JSON_PLUGINVERSIONCOMMENTS);
        sendJson.insert(JSON_PLUGINVERSIONCOMMENTS, m_serviceCallBackUrl);
    } else {
        url = ConfigManger::GetInstance().GetLoginServerUrl() + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_ILOGIN);
    }

    QUrl TempQUrl = url;
    m_loginSocket->SetUrl(TempQUrl);
    QLOG_INFO() << QString("[<<<<---_Login Qurl: %1 --->>>>][requestData: ]").arg(url) << sendJson;
    result = m_loginSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---Login Finshed--->>>>][result:%1][msg:%2][recvData:").arg(result).arg(error)<<recvJson;
    if(!result) {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("登录失败![网络错误]"));
        m_loginErrorCount++;
    } else {
        if(JSON_STATUSCODE_OK != recvJson[JSON_LOGINCODE].toInt()) {
            result = false;
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("登录失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
            m_loginErrorCount++;
        } else {
            m_storeName = recvJson[JSON_STORENAME].toString();
            m_openTcpChannel = recvJson[JSON_OPEN_TCP_CHANNEL].toBool();
            DataManger::GetInstance().SetToken(recvJson[JSON_DATA].toObject()[JSON_TOKEN].toString());
            DataManger::GetInstance().SetStoreId(m_storeId);
            DataManger::GetInstance().SetPosIpAddress(m_ipPortAddress);
            DataManger::GetInstance().SetPartnerId(ConfigManger::GetInstance().GetPartnerId());
            emit hideAlert();
            QLOG_INFO()<<QString("[<<<<---FlowControl::_Login  emit setStoreInfo setCashierInfo storeId:%1 cashierName:%2 --->>>>]").
                         arg(m_storeId).arg(m_cashierName);
            emit setStoreInfo(m_storeId);
            emit setCashierInfo(m_cashierName);
            emit setTerminalIp(m_ipAddress);

            //***********************登陆时获取门店的营业状态 begin ************************//
            m_eleStoreStatus = recvJson[JSON_ELESTORESTS].toInt();
            m_modStoreStatus = recvJson[JSON_MODSTORESTS].toInt();
            m_mopStoreStatus = recvJson[JSON_MOPSTORESTS].toInt();
            m_mtModStoreStatus = recvJson[JSON_MTMODSTORESTS].toInt();
            QLOG_INFO()<<QString("[<<<<---FlowControl::_Login eleStoreStatus: %1, modStoreStatus: %2, mopStoreStatus: %3, mtModStoreStatus: %4, existNoAckNotice:%5 --->>>>]")
                         .arg(m_eleStoreStatus).arg(m_modStoreStatus).arg(m_mopStoreStatus).arg(m_mtModStoreStatus).arg(m_existNoAckNotice);

            emit doUpdateStoreStatus( m_eleStoreStatus, m_modStoreStatus, m_mopStoreStatus, m_mtModStoreStatus, m_existNoAckNotice);
            //***********************登陆时获取门店的营业状态 end ************************//
            m_bLoginResult= true;
            m_loginErrorCount = 0;
            m_bFirstRecvInfo =false;
            m_clearTimer->start(1000*60*60*2); // 5分钟执行一次清理任务:正式上线需要两小时清理一次；
            //m_clearTimer->start(1000*60*5); // 5分钟执行一次清理任务:正式上线需要两小时清理一次；
            m_heartTimer->start(1000*60*5);
            m_pullTimer->start(1000*5);
            m_analysisTimer->start(1000*5);
            m_reportOMSReocrdOrderTimer->start(1000*5);
            m_notifyPmsPullTimer->start(3*1000);
            m_notifyPmsUpdateTimer->start(3*1000);
            m_remindCasherBlinkFloatTimer->start(5*1000);

            //m_cyclePullAllOrderTimer->start(1000*60*10);
            QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_Login  Next Pull All Order Time: %1--->>>>]")
                         .arg(QDateTime::currentDateTime().addSecs(60*10).toString("yyyy-MM-dd hh:mm:ss"));

            //在登陆时再次检查数据库连接是否都正常；
            if ( !m_initPmsGetStoreConfigDBRet ) {
                result = false;
                QLOG_INFO()<<QString("[<<<<---FlowControl::_Login() m_initPmsGetStoreConfigDBRet, m_initPmsOrdersDataRet:--->>>>]")
                          <<m_initPmsGetStoreConfigDBRet <<m_initPmsOrdersDataRet;
                emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("尝试打开PMS数据库(StoreConfig**)失败"));
            } else {

                // 获取原生链路的全量订单列表数据;
                _AddOrderPull( QString(), QString() );

                // 获取 o2ofulfillment 链路的全量订单列表数据;
                if ( ConfigManger::GetInstance().GetLoginServerUrl().contains(".stg") ) {
                    _AddOrderPull( QString(), QString(), GET_O2OFULFILLMENT_STG_CBL );
                } else if ( ConfigManger::GetInstance().GetLoginServerUrl().contains(".dev") ) {
                    _AddOrderPull( QString(), QString(), GET_O2OFULFILLMENT_DEV_CBL );
                } else if ( ConfigManger::GetInstance().GetLoginServerUrl().contains(".uat") ) {
                    _AddOrderPull( QString(), QString(), GET_O2OFULFILLMENT_UAT_CBL );
                } else {
                    _AddOrderPull( QString(), QString(), GET_O2OFULFILLMENT_PRO_CBL );
                }

            }
        }
    }

    if(!result) {
        QLOG_INFO() << QString("[<<<<---Login Retry--->>>>] %1 msec after login...").arg(VALUE_RELOGINTIME);
        QTimer::singleShot(VALUE_RELOGINTIME, this, &FlowControl::_Login);
    }

    QLOG_INFO() << QString("[<<<<---Login--->>>>][m_bLoginResult: %1, result: %2 ]").arg(m_bLoginResult?1:0).arg(result?1:0);

    // Http登录OMS成功后, 判断是否开启Socket Communicate Pipe. //优先取配置文件中的长连接开关: 配置为 false时以OMS返回开启标志为准;
    if ( ConfigManger::GetInstance().GetOpenTcpChannel() ){
        m_openTcpChannel = true;
    }

    if ( m_bLoginResult && m_openTcpChannel ) {
        QLOG_INFO() << QString("[<<<<---Login Success, Emit Signal To SocketCommunicate Begin Connect Tcp Socket --->>>>]");
        emit doLoginSuccess(true, m_openTcpChannel, m_storeId, m_ipAddress, m_posHostName, m_posWorkstationNum );
    }

    return result;
}

void FlowControl::_PullOrderData()
{
    if(m_orderPullList.isEmpty())
        return;

    emit hideAlert();
    QLOG_INFO()<<QString("[<<<<----_PullOrderData ListSize=%1, FirstOne: %2 ---->>>>>]").arg( m_orderPullList.size() ).arg( m_orderPullList.size()?m_orderPullList.first()->orderId:"" );

    bool btryLock = m_PullOrderDataMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
    if (!btryLock) {
        QLOG_ERROR()<<"[<<<<----_PullOrderData Try Lock Failed ---->>>>>]";
        return;
    }

    PullOrderInfo* info = m_orderPullList.takeFirst();

    if ( info->pullErrorCount > 2 ) {
        QLOG_INFO()<<QString( "[<<<<----_PullOrderData orderId:%1,Channel:%2,PullErrorCount:%3, CallBackUrl:%4, Pull Faild More Than 3 Times, Abandon This Item ---->>>>>]" )
                     .arg(info->orderId).arg(info->channel).arg(info->pullErrorCount).arg(info->callBackUrl);

        m_orderPullList.removeOne(info);

        // 获取 o2ofulfillment 订单列表数据失败3次,之后丢弃 此拉单列表请求 item, 不切换域名重试获取;
        if ( info->orderId.isEmpty() && info->callBackUrl.contains("o2ofulfillment") ) {
            QLOG_ERROR() << QString("[<<<<---_PullOrderData <o2ofulfillment> Error, And Don't Display Error--->>>>]");
            delete info;
            m_PullOrderDataMutex.unlock();
            return;
        }

        // 特殊处理: 获取订单列表接口, 默认接口地址拉取失败，则尝试一次从备用OMS 回调地址在此进行拉取;
        if ( info->orderId.isEmpty() && m_serviceCallBackUrl.length() && info->callBackUrl != m_serviceCallBackUrl ) {
            info->callBackUrl = m_serviceCallBackUrl;
            info->pullErrorCount = 0; // Pull Error Must Rest Zero, Or No Chance Goto Pull All Order;
            m_orderPullList.append(info);
        } else {
            delete info;
        }
        m_PullOrderDataMutex.unlock();
        return;
    }

    if(info->orderId.isEmpty()) {
        // 调换拉取订单列表频率 4S 一页 30笔;
        m_pullTimer->start(1000*4);

        if ( _PullOrderList( info->pageSize, info->pageNumber, info->callBackUrl ) ) {
            QLOG_INFO()<<"[<<<<----_PullOrderData  _PullOrderList successful---->>>>>]";
            m_orderPullList.removeOne(info);
            delete info;
        } else {
            QLOG_INFO()<<"[<<<<----_PullOrderData _PullOrderList failed---->>>>>]";
            m_orderPullList.removeOne(info);
            info->pullErrorCount++;
            m_orderPullList.append(info);
        }
    } else {
        if ( _PullOrderDetail( info->orderId, info->channel, info->callBackUrl, info->skipPrint, info->pushOptions ) ) {
             QLOG_INFO()<<"[<<<<----_PullOrderData  _PullOrderDetail successful---->>>>>]";
             m_orderPullList.removeOne(info);
             delete info;
        } else {
             QLOG_INFO()<<"[<<<<----_PullOrderData  _PullOrderDetail fail---->>>>>]";
             m_orderPullList.removeOne(info);
             info->pullErrorCount++;
             m_orderPullList.append(info);
        }
    }

    m_PullOrderDataMutex.unlock();
    return ;
}

bool FlowControl::_PullOrderDetail(const QString& orderId, const QString& channel, const QString &callBackUrl, const bool& skipPrint, const QJsonObject& pushOptins, const bool &skipErrorDisplay )
{
    if(m_pullOrderSocket==nullptr)
        m_pullOrderSocket =new BillSocket(this);
    QString error;
    QString url;
    bool result;
    QJsonObject recvJson;

    if(ConfigManger::GetInstance().GetOrderSslConfig()) {
        m_pullOrderSocket->SetSslConfig();  
    }

    if ( callBackUrl.length() ) {
        url = callBackUrl + "/order/" + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_PULLORDER);
    } else {
        url = ConfigManger::GetInstance().GetOrderServerUrl() + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_PULLORDER);
    }

    // 拉取订单详情接口:订单编号
    url.append(orderId);
    // 拉取订单详情接口: 新增 渠道 参数
    url.append(QString("&")+JSON_CHANNEL+QString("=")+channel);
    url.append(QString("&")+JSON_POSIPADDRESS+QString("=")+m_ipPortAddress);
    url.append(QString("&")+JSON_PMSMACHINENO+QString("=")+m_pmsMachineNo);
    QLOG_INFO() << QString("[<<<<---Pull Order Detail--->>>>][requestUrl:]")<<url;
    QUrl TempQUrl = url;
    m_pullOrderSocket->SetUrl(TempQUrl);
    result = m_pullOrderSocket->GetRequest(recvJson, error);
    QLOG_INFO() << QString("[<<<<---Pull Order Detail Finsh--->>>>][result:%1][msg:%2]").arg(result).arg(error)<<recvJson;
    if(!result) {
        if ( !skipErrorDisplay ) {
            emit setNetStatus(QString::fromLocal8Bit("<font color='#ff0000'>网络不稳定,正在重试</font>"));
        }
    } else {
        emit setNetStatus(QString::fromLocal8Bit("正常"));
        if(JSON_STATUSCODE_OK != recvJson[JSON_ERRCODE].toInt())
        {
            QString error = recvJson[JSON_ERRMSG].toString();
            QLOG_ERROR() << QString("[<<<<---Pull Order Detail Error--->>>>][msg->%1]").arg(error);
            if ( !skipErrorDisplay ) {
                emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取订单失败![%1]").arg(error));
            }
            result=false;
        } else {
            QJsonObject order = recvJson[JSON_DATA].toObject();
            // 服务端返回 code=100 , 但订单体中无订单详情数据;
            if ( !order.contains( JSON_ID ) ) {
                QLOG_ERROR()<<QString("[<<<<---Pull Order Detail Failed, OrderId= %1, Channel= %2  Code= 100, But 'data'  Is Empty --->>>>]").arg( orderId ).arg( channel );
                error = QString(" OrderId=%1, Code=100, But 'data' Is Empty ");
                result = false;
                if ( !skipErrorDisplay ) {
                    emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取订单失败![%1]").arg( error ) );
                }
                // 此种情况: 肯定服务端服务异常, 即使 result = false,下次拉单, 依旧还会失败, 顾再次放弃此订单详情的继续拉取;
            } else {
                if ( !order.contains( JSON_CALL_BACK_URL ) ) {
                    order.insert( JSON_CALL_BACK_URL, callBackUrl );
                }
                if ( !order.contains( JSON_SKIP_PRINT ) ) {
                    order.insert( JSON_SKIP_PRINT, skipPrint );
                }
                if ( !order.contains( JSON_PUSH_PLUGIN_OPTIONS ) ) {
                    order.insert( JSON_PUSH_PLUGIN_OPTIONS, pushOptins );
                }
                _OrderAnalysis(order);
            }

        }
    }
    /*解析json数据失败则20秒后重新拉单*/
    if(!result) {
        m_pullTimer->start(1000*20);
        // 如果某次拉订单列表出现失败；此函数的外层函数 _PullOrderData：会将本次拉单对象存起来，等待下次拉取;
    } else {
        m_pullTimer->start(1000*2);
    }

    QLOG_INFO() << QString("[<<<<---Pull Order Detail Final Result: %1 --->>>>]").arg( result ? 1 : 0);
    return result;
}

bool FlowControl::_PullOrderList(const int &pageSize, const int &pageNo, const QString &callBackUrl )
{
    if(m_pullOrderListSocket==nullptr) {
        m_pullOrderListSocket =new BillSocket(this);
    }
    QString error;
    QString url;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;
    int ordertotalSum;
    sendJson = DataManger::GetInstance().GetPullOrderListData( pageNo, pageSize, m_pmsMachineNo );

    QLOG_INFO() << QString("[<<<<---FlowControl::_PullOrderList: Pull Order List--->>>>][requestData:]")<<sendJson;
    if(ConfigManger::GetInstance().GetOrderSslConfig()) {
        m_pullOrderListSocket->SetSslConfig();
        QLOG_INFO()<<"FlowControl::_PullOrderList load ssl";
    }

    if ( callBackUrl.length() ) {
        url = callBackUrl + "/order/" + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_PULLORDERLIST);
    } else {
        url = ConfigManger::GetInstance().GetOrderServerUrl() + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_PULLORDERLIST);
    }

    QUrl TempQUrl = url;
    m_pullOrderListSocket->SetUrl( TempQUrl );
    QLOG_INFO()<< url << " requestData: " <<sendJson;

    result = m_pullOrderListSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---FlowControl::_PullOrderList:Pull Order List Finish.--->>>>][result:%1][msg:%2]").arg(result).arg(error)<<recvJson;

    if ( !result ) {

        if ( callBackUrl.length() && callBackUrl.contains("o2ofulfillment") ) {
            QLOG_ERROR() << QString("[<<<<---FlowControl::_PullOrderList:Pull Order List <o2ofulfillment> Error, And Don't Display Error--->>>>]");
        } else {
            emit setNetStatus(QString::fromLocal8Bit("<font color='#ff0000'>网络不稳定，正在重试</font>"));
        }

    } else {

        emit setNetStatus(QString::fromLocal8Bit("正常"));
        if(JSON_STATUSCODE_OK != recvJson[JSON_ERRCODE].toInt()) {
            QString error = recvJson[JSON_ERRMSG].toString();
            QLOG_ERROR() << QString("[<<<<---FlowControl::_PullOrderList:Pull Order List Error--->>>>][msg->%1]").arg(error);

            if ( callBackUrl.length() && callBackUrl.contains("o2ofulfillment") ) {
                QLOG_ERROR() << QString("[<<<<---FlowControl::_PullOrderList:Pull Order List <o2ofulfillment> Error, And Don't Display Error--->>>>]");
                m_o2ofulfillmentOrderCount = 0;
            } else {
                emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取订单失败![%1]").arg(error));
                m_orderCount = 0;
            }
            result=false;
        } else {
            QJsonArray orders = recvJson[JSON_DATA].toObject()[JSON_ORDERS].toArray();
            foreach(QJsonValue order, orders) {
                QJsonObject  orderObject = order.toObject();
                // 订单 JsonObject -> OrderObject 前数据安全检查;
                if ( orderObject.contains(JSON_ID) ) {
                    _OrderAnalysis( orderObject );
                }
            }
            ordertotalSum=recvJson[JSON_DATA].toObject()[JSON_COUNT].toInt();

            // 1、o2ofulfillment 地址获取订单列表分页操作;
            // 2、原生拉取订单列表分页操作;
            bool  bLocalPullOrderCountNotFull = false;
            if ( callBackUrl.length() && callBackUrl.contains("o2ofulfillment") ) {
                m_o2ofulfillmentOrderCount += orders.size();
                bLocalPullOrderCountNotFull  =  m_o2ofulfillmentOrderCount < ordertotalSum;
            } else {
                m_orderCount += orders.size();
                bLocalPullOrderCountNotFull  =  m_orderCount < ordertotalSum;
            }

            if ( bLocalPullOrderCountNotFull && orders.size() > 0 ) {
                //避免出现存在多页数据，导致出现死锁: 先调用定时器的timeout 触发槽函数:_PullOrderData,
                //_PullOrderData:内部会有加锁并且会调用分页获取订单函数_AddOrderPull(QString(),QString(),pageNo+1,pageSize): 内部也有加锁，所以导致死锁;
                //_AddOrderPull(QString(),QString(),pageNo+1,pageSize);
                /***组装从FM外卖service端的拉单请求参数***/
                PullOrderInfo* orderPull = new PullOrderInfo();
                orderPull->orderId=QString();
                orderPull->channel=QString();
                orderPull->pageNumber=pageNo+1;
                orderPull->pageSize=pageSize;
                orderPull->pullErrorCount = 0;
                orderPull->callBackUrl = callBackUrl;
                orderPull->skipPrint = false;
                orderPull->pushOptions = QJsonObject();
                QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PullOrderList: Next Page Order List :pageNo:%1 pageSize:%2--->>>>]").arg(pageNo+1).arg(pageSize);
                m_orderPullList.append(orderPull);
                //避免出现存在多页数据，导致出现死锁;
            } else {
                //分页拉取订单列表最后一页成功后,需要重置本地拉单计数缓存, 防止影响下一次获取订单列表判断;
                if ( callBackUrl.length() && callBackUrl.contains("o2ofulfillment") ) {
                    m_o2ofulfillmentOrderCount = 0;
                     QLOG_INFO()<<QString("[<<<<---FlowControl::_PullOrderList  < o2ofulfillment > Had Finished: The Last Request PageNo:%1, Last Get Orders =%2 --->>>>]").arg( pageNo ).arg( orders.size() );
                } else {
                    m_orderCount = 0;
                    QLOG_INFO()<<QString("[<<<<---FlowControl::_PullOrderList  Had Finished: The Last Request PageNo:%1, Last Get Orders =%2 --->>>>]").arg( pageNo ).arg( orders.size() );
                }
            }

        }
    }
    // 如果出现拉取订单列表失败，触发下一次拉门店有效订单的时间间隔变更为10(如果一开始就获取订单列表成功:时间间隔为2s)
    if(!result) {
        m_pullTimer->start(1000*10);
        // 如果某次拉订单列表出现失败；此函数的外层函数 _PullOrderData: 还会将本次拉单列表存起来等待下次拉取;
    }
    return result;
}


void FlowControl::_AnalysisOrderDetailData()
{
    QLOG_INFO()<<QString("[<<<<----_AnalysisOrderDetailData Begin ListSize=%1 ---->>>>>]").arg( m_orderAnalysisList.size() );

    if ( m_orderAnalysisList.isEmpty() ) {
        m_analysisTimer->start(1000*5);
        return;
    }

    QLOG_INFO()<<QString("[<<<<----_AnalysisOrderDetailData ListSize=%1, FirstOne: %2 ---->>>>>]").arg( m_orderAnalysisList.size() ).arg( m_orderAnalysisList.size()?m_orderAnalysisList.first()->orderId:"" );

    bool btryLock = m_analysisOrderDataMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
    if (!btryLock) {
        QLOG_ERROR()<<"[<<<<----_AnalysisOrderDetailData Try Lock Failed ---->>>>>]";
        m_analysisTimer->start(1000*8);
        return;
    }

    AnalysisOrderInfo* info = m_orderAnalysisList.takeFirst();
    m_analysisOrderDataMutex.unlock();

    if ( info ) {
        QLOG_INFO()<<QString( "[<<<<----_AnalysisOrderDetailData orderId:%1, CallBackUrl:%2, pushOptions:  ---->>>>>]" ).arg(info->orderId).arg(info->callBackUrl) << info->pushOptions;
        // 目前场景: 假设 _OrderAnalysis() 函数处理异常, 存在丢失订单详情数据的可能 [之前的模式也存在同样情况];
        if ( !info->orderDetailJson.contains( JSON_CALL_BACK_URL ) ) {
            info->orderDetailJson.insert( JSON_CALL_BACK_URL, info->callBackUrl );
        }
        if ( !info->orderDetailJson.contains( JSON_PUSH_PLUGIN_OPTIONS ) ) {
            info->orderDetailJson.insert( JSON_PUSH_PLUGIN_OPTIONS, info->pushOptions );
        }

        _OrderAnalysis(info->orderDetailJson);
        delete info;
    } else {
        QLOG_ERROR()<<"[<<<<----_AnalysisOrderDetailData:: AnalysisOrderInfo Pointer Is Null ---->>>>>]";
    }

    m_analysisTimer->start(1000*2);
    return;
}


bool FlowControl::_SendHeart()
{
    QString error;
    QString url;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;
    m_puginVersionComments = ConfigManger::GetInstance().GetOrderServerUrl();

    sendJson = DataManger::GetInstance().GetHeartData(m_password,m_posId,m_ipPortAddress,m_puginVersionComments,m_bLastHeartIsError,m_pmsMachineNo);
    sendJson.insert(JSON_POS_IP_ADDR, m_ipAddress);
    sendJson.insert(JSON_POS_WORKS_NUM, m_posWorkstationNum);
    sendJson.insert(JSON_POS_HOST_NAME, m_posHostName);
    sendJson.insert(JSON_POS_MAC_ADDRESS, m_posMacAddress);

    // 如果前3次使用初始地址心跳失败 3 次, 则切换使用 备用地址 再尝试3次, 合计超过6次，则切回初始地址继续心跳;
    if ( m_serviceCallBackUrl.length() && m_sendHeartErrorCount > 2 && m_sendHeartErrorCount < 6 ) {
        url = m_serviceCallBackUrl + "/pos/" + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_HEART);
        sendJson.remove(JSON_PLUGINVERSIONCOMMENTS);
        sendJson.insert(JSON_PLUGINVERSIONCOMMENTS, m_serviceCallBackUrl);
    } else {
        url = ConfigManger::GetInstance().GetLoginServerUrl() + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_HEART);
    }

    QUrl TempQUrl = url;

    m_loginSocket->SetUrl(TempQUrl);
    QLOG_INFO() << QString("[<<<<---Send Heart--->>>>][Url: %1, RequestData: ]").arg(url) << sendJson;
    result = m_loginSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---Send Heart Finish--->>>>][result:%1][msg:%2][recvData:%3]").arg(result).arg(error)<<recvJson;

    if( !result ) {
        m_bLastHeartIsError = true;
        m_sendHeartErrorCount++;
        emit setNetStatus(QString::fromLocal8Bit("<font color='#ff0000'>网络不稳定，正在重试</font>"));
        emit doUpdateStoreStatus(0, 0, 0, 0, m_existNoAckNotice);  //NetWork Is Error , Refresh Store Default Status;
    } else {
       QLOG_INFO() << QString("[<<<<---Send Heart Finish: code:%1--->>>>]").arg(recvJson[JSON_LOGINCODE].toInt());
       if(JSON_STATUSCODE_OK != recvJson[JSON_LOGINCODE].toInt())
       {
            result = false;
            m_bLastHeartIsError = true;
            m_sendHeartErrorCount++;
            emit setNetStatus(QString::fromLocal8Bit("<font color='#ff0000'>网络不稳定，正在重试</font>"));
            emit doUpdateStoreStatus(0, 0, 0, 0, m_existNoAckNotice);  //Interface Return Error , Refresh Store Default Status;
       } else {
           result = true;
           emit setNetStatus(QString::fromLocal8Bit("<font color='#f5f5f5'>正常</font>"));
           if( recvJson.contains(JSON_ELESTORESTS) ){
               m_eleStoreStatus = recvJson[JSON_ELESTORESTS].toInt();
           }
           if( recvJson.contains(JSON_MODSTORESTS) ){
               m_modStoreStatus = recvJson[JSON_MODSTORESTS].toInt();
           }
           if( recvJson.contains(JSON_MOPSTORESTS) ){
               m_mopStoreStatus = recvJson[JSON_MOPSTORESTS].toInt();
           }
           if ( recvJson.contains(JSON_MTMODSTORESTS) ) {
               m_mtModStoreStatus = recvJson[JSON_MTMODSTORESTS].toInt();
           }

           QLOG_INFO()<<QString("[<<<<---FlowControl::_SendHeart eleStoreStatus: %1, modStoreStatus: %2 , mopStoreStatus: %3 , mtModStoreStatus: %4, existNoAckNotice:%5 --->>>>]")
                        .arg(m_eleStoreStatus).arg(m_modStoreStatus).arg(m_mopStoreStatus).arg(m_mtModStoreStatus).arg(m_existNoAckNotice);
           emit doUpdateStoreStatus( m_eleStoreStatus, m_modStoreStatus, m_mopStoreStatus, m_mtModStoreStatus, m_existNoAckNotice );
           //还原并标记上一次心跳为正常状态;
           m_bLastHeartIsError = false;

           // 根据 心跳接口 判断是否存在漏单，如果存在漏单，则进行订单列表拉取 操作;
           if ( recvJson.contains(JSON_ORDERCOUNT) ) {
               int  OmsOrderCount = recvJson[JSON_ORDERCOUNT].toInt();
               if ( m_FmOrdersMap.count() <  OmsOrderCount ) {
                   QLOG_INFO()<<QString("[<<<<---FlowControl::_SendHeart  onGetOMSAllOrders()  Memory Order Count:%1; OMS Order Count:%2; --->>>>]")
                                .arg( m_FmOrdersMap.count() ).arg( OmsOrderCount );
                   onGetOMSAllOrders();
               }
           }

       }
    }
    return result;
}

bool FlowControl::_ConfirmOrder(const QString &orderId)
{
    QString error;
    bool result;
    QJsonObject recvJson;
    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在通信......"));
    if(ConfigManger::GetInstance().GetOrderSslConfig())
    {
        m_procOrderSocket->SetSslConfig();
    }
    QString url = ConfigManger::GetInstance().GetOrderServerUrl()+
            ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_CONFIRM);
    url.append(orderId);
    url.append(QString("&")+JSON_POSIPADDRESS+QString("=")+m_ipPortAddress);
    QLOG_INFO() << QString("[<<<<---Confirm Order Begin--->>>>][requestUrl:]")<<url;
    QUrl TempQUrl = url;
    m_procOrderSocket->SetUrl(TempQUrl);
    result = m_procOrderSocket->GetRequest(recvJson, error);
    QLOG_INFO() << QString("[<<<<---Confirm Order Finish--->>>>][result:%1][msg:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
    if(!result)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("接单失败![网络错误]"));
    }else
    {
        if(JSON_STATUSCODE_OK != recvJson[JSON_ERRCODE].toInt())
        {
            result = false;
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("接单失败![%1]").arg(recvJson[JSON_ERRMSG].toString()));
        }else
        {
            QJsonObject data = recvJson[JSON_DATA].toObject();
            int status = data[JSON_RECEIVINGSTATUS].toInt();
            if(1==status)
            {
                int orderStatus = data[JSON_ORDERSTATUS].toInt();
                OrderObject* orderObject = m_FmOrdersMap.value(orderId);
                int oldOrderStatus = orderObject->orderStatus;
                orderObject->orderStatus = orderStatus;
                emit changeOrderStatus(orderObject, oldOrderStatus);
                if (OrderObject::Confirmed == orderStatus){
                    //存在两种Case: 正常销售单没有入机成功 && 非预约日期(录配送费判断)/默认值是初始化0; ||  预约实物销售单没有入机成功 && 预约实物送达日期
                    if( (!orderObject->isPush && !orderObject->appointmentDayFlag) || (!orderObject->isORSPush && orderObject->appointmentDayFlag) )
                    {
                        if(orderObject->appointmentDayFlag){
                            orderObject->orsPushOrderType = 1;
                            orderObject->pushOrderType=1; //此处必须更新此标记为 非0;否则录单数据将变化成退预约配送费(bug: 此变量之前没有初始化发现);
                            orderObject->orsPushOrderTimes = 0;
                        }else{
                            orderObject->pushOrderType = 1;
                            orderObject->pushOrderTimes = 0;
                        }

                        m_OrderEntryMutex.lock();
                        if(!m_simValidOrdersList.contains(orderObject->id))
                        {
                            m_simValidOrdersList.append(orderObject->id);
                        }
                        m_OrderEntryMutex.unlock();
                        QLOG_INFO() << QString("[<<<<---FmTakeout _ConfirmOrder:  m_simValidOrdersList.num:%1 --->>>>]")<< m_simValidOrdersList.count();
                        QLOG_INFO() << QString("[<<<<---FmTakeout _ConfirmOrder:  m_simValidOrdersList:%1 --->>>>]")<< m_simValidOrdersList;
                    }
                }
            } else {
                emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("接单失败![%1]").arg(recvJson[JSON_ERRMSG].toString()));
            }
        }
    }
    return result;
}


bool FlowControl::_SendOrder(const QString& orderId)
{
    QString error;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;

    sendJson = DataManger::GetInstance().GetSendOrderData(orderId);

    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在通信......"));
    QLOG_INFO() << QString("[<<<<---Sendout Order Begin--->>>>][requestData:%1]")<<sendJson;
    result = m_procOrderSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---Sendout Order Finish--->>>>][result:%1][msg:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
    if(!result)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("送出失败![网络错误]"));
    }else
    {
        if(JSON_STATUSCODE_OK != recvJson[JSON_STATUSCODE].toInt())
        {
            result = false;
            emit showAlert(AlertForm::MSGERROR,  QString::fromLocal8Bit("送出失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
        }else
        {
            emit showAlert(AlertForm::SUCCESS, QString::fromLocal8Bit("送出成功!"));

            // 通知主界面移动订单
            OrderObject *orderObject = m_FmOrdersMap.value(orderId);
            int oldStatus = orderObject->orderStatus;
            orderObject->orderStatus = recvJson[JSON_STATUS].toInt();
            // TODO  服务器端现还未开发
            //orderObject->status_desc = recvJson[JSON_STATUSDESC].toString();
            emit changeOrderStatus(orderObject, oldStatus);
        }
    }

    return result;
}

bool FlowControl::_CompleteOrder(const QString& orderId)
{
    QString error;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;

    sendJson = DataManger::GetInstance().GetCompleteOrderData(orderId);

    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在通信......"));
    QLOG_INFO() << QString("[<<<<---Complete Order Begin--->>>>][requestData:%1]")<<sendJson;
    result = m_procOrderSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---Complete Order Finish--->>>>][result:%1][msg:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
    if(!result)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("完成失败![网络错误]"));
    }else
    {
        if(JSON_STATUSCODE_OK != recvJson[JSON_STATUSCODE].toInt())
        {
            result = false;
            emit showAlert(AlertForm::MSGERROR,    QString::fromLocal8Bit("完成失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
        }else
        {
            emit showAlert(AlertForm::SUCCESS, QString::fromLocal8Bit("完成成功!"));

            // 通知主界面移动订单
            OrderObject *orderObject = m_FmOrdersMap.value(orderId);
            int oldStatus = orderObject->orderStatus;
            orderObject->orderStatus = recvJson[JSON_STATUS].toInt();
            emit changeOrderStatus(orderObject, oldStatus);
        }
    }

    return result;
}


bool FlowControl::_RefundOrder(const QString &orderId,int reasonCode,const QString& reason,const QString& dishesListString)
{

    QLOG_INFO() << QString("[<<<<---FlowControl::_RefundOrder--->>>>][orderId:%1 reasonCode:%2 reason:%3 dishesListString:]").arg(orderId).arg(reasonCode).arg(reason).arg(dishesListString);
    QString error;
    QString url;
    QString callBackUrl = "";
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;
    sendJson = DataManger::GetInstance().GetRefundOrderData(reasonCode,reason,orderId,m_FmOrdersMap.value(orderId)->channel, dishesListString, m_cashierId, m_cashierName);
    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在通信......"));
    QLOG_INFO() << QString("[<<<<---Refund Order Begin--->>>>][requestData:%1]")<<sendJson;
    // 如果退款原因：商品已售完，使用下面接口; // 如果退款原因：其他，都同意使用一个接口；
    if ( m_FmOrdersMap.value(orderId) ) {
        callBackUrl = m_FmOrdersMap.value(orderId)->callBackUrl;
    }

    if ( callBackUrl.length() ) {
        url = callBackUrl + "/order/" + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_CANCLE);
    } else {
        url = ConfigManger::GetInstance().GetOrderServerUrl() + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_CANCLE);
    }

    QUrl TempQUrl = url;
    m_procOrderSocket->SetUrl(TempQUrl);
    QLOG_INFO() << QString("[<<<<<-----_RefundOrder: orderId:%1  URL: ----->>>>>]").arg(orderId)<< m_procOrderSocket->GetUrl();

    if(ConfigManger::GetInstance().GetOrderSslConfig()) {
        m_procOrderSocket->SetSslConfig();
        QLOG_INFO()<<"load ssl";
    } else {
        QLOG_INFO()<<"load not ssl";
    }
    QLOG_INFO() << QString("[<<<<---Refund Order Request: --->>>>]")<< m_procOrderSocket->GetUrl();
    result = m_procOrderSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---Refund Order Finish--->>>>][result:%1][msg:%2][recvData:]")
                   .arg(result).arg(error)<<recvJson;
    if(!result)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("退单失败![网络错误]"));
        return false;
    } else {
        if(JSON_STATUSCODE_OK != recvJson[JSON_ERRCODE].toInt())
        {
            result = false;
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("退单失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
            return false;
        } else {
            QJsonObject data = recvJson[JSON_DATA].toObject();
            int status = data[JSON_RECEIVINGSTATUS].toInt();
            if(1==status) {
                emit showAlert(AlertForm::SUCCESS, QString::fromLocal8Bit("退单成功"));
                //m_OrderEntryMutex.lock(); //必须提前加锁，否则后期订单ID会变更;
                //获取POS退单成功,OMS服务端返回的RefundFmId ( 此字段只有星巴克APP SVC卡支付的case,才会使用到 )
                QString refundFmIdTemp = data[JSON_REFUNDFMID].toString();
                int orderStatus = data[JSON_ORDERSTATUS].toInt();
                OrderObject* orderObject = m_FmOrdersMap.value(orderId);
                int oldOrderStatus = orderObject->orderStatus;
                orderObject->orderStatus = orderStatus;
                orderObject->refundFmId = refundFmIdTemp;
                emit changeOrderStatus(orderObject, oldOrderStatus);
                emit doHideMainShowFloatFrom();
                //退货订单，将此订单添加到simphony 模拟点单列表中；
                QLOG_INFO() << QString("[<<<<---FmTakeout _RefundOrder: orderObject->id:%1 , orderObject->orderStatus:%2 --->>>>]").arg(orderObject->id).arg(orderObject->orderStatus);
                QLOG_INFO() << QString("[<<<<---FmTakeout _RefundOrder: orderObject->id:%1 , orderObject->isCancle:%2 --->>>>]").arg(orderObject->id).arg(orderObject->isCancle);
                if (OrderObject::Refunded == orderObject->orderStatus && OrderObject::SimExceptSale != oldOrderStatus && OrderObject::SimExceptRefund != oldOrderStatus) {
                    //只有退单成功 且 是录POS 成功的才进行加锁；
                    //emit doLockFloatForm(); m_bFloatFromLockSt = true; //更新悬浮框的锁定状态 转移到响应action1：数据准备函数中;
                    //能退单成功就肯定能断言，此订单是没有录过退货的
                    // 判断Simphony 队列中的订单是否已经存在:不存在(Simphony已经点单完成后会移除)则添加； 如果存在(说明此订单还拟点单)，则需要直接向现存在Sim有效队列中的记录移除;没有模
                    m_OrderEntryMutex.lock();
                    if(!m_simValidOrdersList.contains(orderObject->id))   //不存在队列中，则将其加入到队列中；
                    {
                        QLOG_INFO() << QString("[<<<<---FmTakeout _RefundOrder: orderId:%1 ;(SimProcOrderDB::getInstance().isRefundOrder:--->>>>]").arg(orderObject->id)<<SimProcOrderDB::getInstance().isRefundOrder(orderObject->id);
                        //m_simValidOrdersList.append(orderObject->id);  //insert(0,orderObject->id) //POS容易遗漏录入退货订单
                        m_simValidOrdersList.insert(0,orderObject->id);
                        //原本应该根据 appointmentDayFlag 使用分支,但此时是退单接口,不允许使用退单:
                        orderObject->pushOrderType = 0;
                        orderObject->pushOrderTimes = 0;
                        orderObject->orsPushOrderType = 0;
                        orderObject->orsPushOrderTimes = 0;
                    }else{  //如果已经存在队列中，就是POS还没有录入销售订单成功；
                        m_simValidOrdersList.removeOne(orderObject->id);
                    }
                    QLOG_INFO() << QString("[<<<<---FmTakeout _RefundOrder:  m_simValidOrdersList.num:%1 --->>>>]")<< m_simValidOrdersList.count();
                    QLOG_INFO() << QString("[<<<<---FmTakeout _RefundOrder:  m_simValidOrdersList:%1 --->>>>]")<< m_simValidOrdersList;
                    m_OrderEntryMutex.unlock();
                    _ClickOMSAssignArea(); //必须执行，否则退货，点击取消后，就不会再提醒了；
                //录正向销售单报错的处理机制;
                } else if(OrderObject::SimExceptSale == oldOrderStatus) {
                    m_OrderEntryMutex.lock();
                    m_simValidOrdersList.removeOne(orderObject->id);
                    m_OrderEntryMutex.unlock();
                //正向单已经录入成功,录退单报错的的处理机制;
                } else if(OrderObject::SimExceptRefund == oldOrderStatus){
                    m_OrderEntryMutex.lock();
                    if(!m_simValidOrdersList.contains(orderObject->id))   //不存在队列中，则将其加入到队列中；
                    {
                        QLOG_INFO() << QString("[<<<<---FmTakeout _RefundOrder: SimExceptRefund : orderId:%1 ;(SimProcOrderDB::getInstance().isRefundOrder:--->>>>]").arg(orderObject->id)<<SimProcOrderDB::getInstance().isRefundOrder(orderObject->id);
                        m_simValidOrdersList.insert(0,orderObject->id);
                        //原本应该根据 appointmentDayFlag 使用分支,但此时是退单接口,不允许使用退单:
                        orderObject->pushOrderType = 0;
                        orderObject->pushOrderTimes = 0;
                        orderObject->orsPushOrderType = 0;
                        orderObject->orsPushOrderTimes = 0;
                    }
                    QLOG_INFO() << QString("[<<<<---FmTakeout _RefundOrder:SimExceptRefund :  m_simValidOrdersList.num:%1 --->>>>]")<< m_simValidOrdersList.count();
                    QLOG_INFO() << QString("[<<<<---FmTakeout _RefundOrder:SimExceptRefund :  m_simValidOrdersList:%1 --->>>>]")<< m_simValidOrdersList;
                    m_OrderEntryMutex.unlock();
                    _ClickOMSAssignArea(); //必须执行，否则退货，点击取消后，就不会再提醒了；
                }
                //m_OrderEntryMutex.unlock(); //必须放开锁的范围；否则会出错；
            } else {
                emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("退单失败![%1]").arg(recvJson[JSON_ERRMSG].toString()));
                return false;
            }
        }
    }
    return result;
}


void FlowControl::_AddOrderInfo2ReportList( const OrderObject* orderObject, const QString& operatStatus, const QString& remarkMessage )
{
    // 将订单 添加到 向OMS汇报入机情况的队列中: 防止出现 m_RepOMSRecordOrderMutex 把整个 FlowControl 主进程死锁;
    //m_RepOMSRecordOrderMutex.lock();
    bool btryLock = m_RepOMSRecordOrderMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
    if ( !btryLock ) {  //加锁失败后，直接return;
        return ;
    }

    RepOMSRecordOrderInfo* repOMSRecordOrder = nullptr;
    if(!m_orderRecordRepOMSList.isEmpty()){
        QList<RepOMSRecordOrderInfo*>::iterator i;
        for (i = m_orderRecordRepOMSList.begin(); i != m_orderRecordRepOMSList.end(); ++i) {
           repOMSRecordOrder = (*i);   //*i 使用*运算符获取遍历容器中所指的元素;
           if (orderObject->id == repOMSRecordOrder->orderNo) {
               break;
           } else {
               repOMSRecordOrder = nullptr;
           }
        }
    }
    if (!repOMSRecordOrder){
        repOMSRecordOrder = new RepOMSRecordOrderInfo();
        repOMSRecordOrder->reqResult = 0;
    } else {
        //不管之前入机是什么报错,目前入机成功，必须再次汇报;
        m_orderRecordRepOMSList.removeOne(repOMSRecordOrder); //剔除已经存在的，更新完数据后，在添加进来;
        repOMSRecordOrder->reqResult = 0;
    }
    repOMSRecordOrder->orderNo = orderObject->id;
    repOMSRecordOrder->channel = orderObject->channel;
    repOMSRecordOrder->type = QString::number(orderObject->orderStatus);
    repOMSRecordOrder->status = operatStatus;
    repOMSRecordOrder->opUser = m_cashierName;
    repOMSRecordOrder->recordDate = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    repOMSRecordOrder->storeId = m_storeId;
    repOMSRecordOrder->remark = remarkMessage;
    repOMSRecordOrder->checkNo = QString("PMSNoCheckNo");
    m_orderRecordRepOMSList.append(repOMSRecordOrder);
    m_RepOMSRecordOrderMutex.unlock();

}


void FlowControl::_ReportOMSRecordOrderInfo()
{
    if(m_orderRecordRepOMSList.isEmpty())
        return ;

    bool btryLock = m_RepOMSRecordOrderMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
    if(!btryLock){ //加锁失败后，直接return;
        return ;
    }
    RepOMSRecordOrderInfo* RepOMSRecOrderIn = nullptr;
    QList<RepOMSRecordOrderInfo*>::iterator i;
    for (i = m_orderRecordRepOMSList.begin(); i != m_orderRecordRepOMSList.end(); ++i) {
       RepOMSRecOrderIn = (*i);   //*i 使用*运算符获取遍历容器中所指的元素;
       if (1==RepOMSRecOrderIn->status.toInt() || (2==RepOMSRecOrderIn->status.toInt() && 0==RepOMSRecOrderIn->reqResult) ) {
           break;
       } else {
           RepOMSRecOrderIn = nullptr;
       }
    }

    //POST请求比较耗时，将会可能导致死锁，为避免，提前解锁;
    m_RepOMSRecordOrderMutex.unlock();

    if(!RepOMSRecOrderIn){
        QLOG_INFO()<<"[<<<<----FlowControl::_ReportOMSRecordOrderInfo  m_orderRecordRepOMSList size: ---->>>>>]"<< m_orderRecordRepOMSList.size();
        //上面的汇报OMS订单入机状态的汇报列表 遍历循环后：如果出现  RepOMSRecOrderIn == NULL;不能从List容器的头部移除已汇报成功结果【注意，必须是订单已经成功入机的订单，而非是入机失败，汇报OMS成功的订单】;
        return ;
    }
    //准备https请求,准备向OMS汇报订单的入机情况;
    if(m_reportOMSRecordOrderSocket==nullptr)
        m_reportOMSRecordOrderSocket =new BillSocket(this);
    QString error;
    QString url;
    QString callBackUrl;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;
    m_reportOMSRecordOrderSocket->SetSslConfig();
    //组装POST请求数据;
    sendJson.insert("orderNo",RepOMSRecOrderIn->orderNo);
    sendJson.insert("channel",RepOMSRecOrderIn->channel);
    sendJson.insert("type",RepOMSRecOrderIn->type);
    sendJson.insert("status",RepOMSRecOrderIn->status);
    sendJson.insert("opUser",RepOMSRecOrderIn->opUser);
    sendJson.insert("recordDate",RepOMSRecOrderIn->recordDate);
    sendJson.insert("storeId",RepOMSRecOrderIn->storeId);
    sendJson.insert("remark",RepOMSRecOrderIn->remark);
    sendJson.insert("checkNo",RepOMSRecOrderIn->checkNo);
    sendJson.insert(JSON_IP_ADDRESS, m_ipAddress);
    sendJson.insert(JSON_POS_WORKS_NUM, m_posWorkstationNum);
    sendJson.insert(JSON_POS_HOST_NAME, m_posHostName);
    sendJson.insert(JSON_POS_MAC_ADDRESS, m_posMacAddress);
    sendJson.insert(JSON_PCS_PLUGIN_VERSION,  APP_VERSION );
    sendJson.insert(JSON_PMSMACHINENO,m_pmsMachineNo);
    sendJson.insert(JSON_TCP_DEVICE_TYPE , "pcsPlugin");

    QString orderNoTemp = RepOMSRecOrderIn->orderNo;

    QLOG_INFO() << QString("[<<<<---_ReportOMSRecordOrderInfo:Begin--->>>>][requestData:%1]")<<sendJson;
    // 查找到 orderObject point 后，查找到 callBackUrl ;
    if ( m_FmOrdersMap.value( RepOMSRecOrderIn->orderNo ) ) {
        callBackUrl =  m_FmOrdersMap.value( RepOMSRecOrderIn->orderNo )->callBackUrl;
    }

    if ( callBackUrl.length() ) {
        url = callBackUrl + "/pos/" + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_REPORTOMSRECORDORDER);
    } else {
        url = ConfigManger::GetInstance().GetLoginServerUrl() + ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_REPORTOMSRECORDORDER);
    }

    QUrl TempQUrl = url;
    m_reportOMSRecordOrderSocket->SetUrl(TempQUrl);
    QLOG_INFO()<<QString("[<<<<---Report OMS Record Order Entry POS Info--->>>>][requestUrl:]") << url;
    result = m_reportOMSRecordOrderSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---Report OMS Record Order Entry POS Info Finish--->>>>][result:%1][msg:%2][orderId:%3]")
                   .arg(result).arg(error).arg(orderNoTemp)<<recvJson;
    if(!result) {
        emit setNetStatus(QString::fromLocal8Bit("<font color='#ff0000'>网络不稳定,正在重试</font>"));
    } else {

        if(!RepOMSRecOrderIn) {
            QLOG_INFO() << QString("[<<<<---Report OMS Record Order Entry POS Info Finish But RepOMSRecOrderIn Is Null--->>>>][orderId:%3]").arg(orderNoTemp);
            return ;
        }

        bool bResultTryLock = m_RepOMSRecordOrderMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
        if(!bResultTryLock ){ //加锁失败后，直接return;
            return ;
        }

        emit setNetStatus(QString::fromLocal8Bit("正常"));
        if(JSON_STATUSCODE_OK != recvJson[JSON_ERRCODE].toInt()) {
            QString error = recvJson[JSON_ERRMSG].toString();
            QLOG_ERROR()<< QString("[<<<<---Report OMS Record Order Entry POS Info Error--->>>>][msg->%1]").arg(error);
            result=false;
            m_orderRecordRepOMSList.removeOne(RepOMSRecOrderIn);
            m_orderRecordRepOMSList.append(RepOMSRecOrderIn);
        } else {
            //解析汇报订单入机POS状态成功;
            result=true;
            if(1==RepOMSRecOrderIn->status.toInt()){
                //只有订单成功入机的订单，才能将此订单从 List容器中移除;否则必须保留在此容器中 避免重复多次向OMS汇报;
                QLOG_INFO()<< QString("[<<<<---Report OMS Record Order Entry POS Info successful,Remove orderId:%1--->>>>][msg->%2]").arg(RepOMSRecOrderIn->orderNo).arg(RepOMSRecOrderIn->remark);
                m_orderRecordRepOMSList.removeOne(RepOMSRecOrderIn);
                delete RepOMSRecOrderIn;
            } else {
                //订单入机失败的订单，不能从 List容器中移除;否则 同笔订单的入机异常情况，会出现多次 或一直向oms回报的情况;
                RepOMSRecOrderIn->reqResult=1;
                QLOG_INFO()<< QString("[<<<<---Report OMS Record Order Entry POS Info successful,Reserve orderId:%1--->>>>][msg->%2]").arg(RepOMSRecOrderIn->orderNo).arg(RepOMSRecOrderIn->remark);
            }
        }

        m_RepOMSRecordOrderMutex.unlock();

    }
    //减少此锁的加锁时间范围;
    //m_RepOMSRecordOrderMutex.unlock();
}


QString FlowControl::_GetJsonStr(const QJsonObject &json)
{
    return QString(QJsonDocument(json).toJson(QJsonDocument::Compact)).replace("\"","");
}

QJsonObject FlowControl::_PackHttpReplyJson(const int status, const QString &msg, const QJsonObject &data, const int& iscontinue, const QString &orderId)
{
    QJsonObject rObj;
    rObj.insert("statusCode", status);
    rObj.insert("msg", msg);
    rObj.insert("iscontinue",iscontinue);
    rObj.insert("data", data);
    rObj.insert("orderId", orderId);
    return rObj;
}

void FlowControl::onPullDishes()
{
    if(!m_bLoginResult)
    {
        emit showAlert(AlertForm::MSGERROR,    QString::fromLocal8Bit("门店还未登录"));
        return ;
    }
    QString error;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;

    m_dishesMap.clear();

    sendJson = DataManger::GetInstance().GetStoreChannelInfoData();
    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在获取平台列表......"));
    QLOG_INFO() << QString("[<<<<---PullDishes:GetStoreChannelInfo Begin--->>>>][requestData:%1]")<<sendJson;
    result = m_pullDishesSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---PullDishes:GetStoreChannelInfo Finish--->>>>][result:%1][msg:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
    if(!result)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取平台列表失败![网络错误]"));
    }else
    {
        //recvJson = QJsonDocument::fromJson("{\"statusCode\":100,\"msg\":\"s\",\"channels\":[ {\"code\":\"bdwm\",\"name\":\"百度外卖\",\"status\":1},{\"code\":\"mtwm\",\"name\":\"美团外卖\",\"status\":0},{\"code\":\"eleme2\",\"name\":\"饿了么\",\"status\":1}]}").object();


        if(JSON_STATUSCODE_OK != recvJson[JSON_STATUSCODE].toInt())
        {
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取平台列表失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
        }else
        {
            // 分别获取每个平台的菜品信息
            QJsonArray jaChannels = recvJson[JSON_SHOPSTATUS].toArray();
            foreach(QJsonValue v, jaChannels)
            {
                QJsonObject channel =  v.toObject();
                QString channelName = channel["name"].toString();
                QString channelCode = channel["code"].toString();

                sendJson = DataManger::GetInstance().GetPullDishesData(channelCode);
                emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在获取[%1]产品信息......").arg(channelName));
                QLOG_INFO() << QString("[<<<<---PullDishes:Dishes %1  Begin--->>>>][requestData:%2]").arg(channelName)<<sendJson;
                result = m_pullDishesSocket->PostRequest(sendJson, recvJson, error);
                QLOG_INFO() << QString("[<<<<---PullDishes:Dishes Finish--->>>>][result:%1][msg:%2][recvData:%3]")
                               .arg(result).arg(error)<<recvJson;
                if(!result)
                {
                    emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取[%1]产品信息失败![网络超时]").arg(channelName));
                    break;
                }else
                {
                    if(JSON_STATUSCODE_OK != recvJson[JSON_STATUSCODE].toInt())
                    {
                    }else
                    {
                        QMultiMap<QString , dishesObject> tmpMap;
                        QJsonArray categoriesJA =recvJson["categories"].toArray();
                        foreach(QJsonValue jv, categoriesJA)
                        {
                            QJsonObject jo = jv.toObject();
                            QString categoryName = jo["name"].toString();
                            QString categoryRank = QString::number(jo["rank"].toInt());
                            QJsonArray dishesJA = jo["dishes"].toArray();
                            foreach(QJsonValue jv1, dishesJA)
                            {
                                QJsonObject jo1 = jv1.toObject();
                                dishesObject dishesObj;
                                dishesObj.FetchDataFromJson(jo1);
                                tmpMap.insert(categoryName+":"+categoryRank, dishesObj);
                            }
                        }
                        m_dishesMap.insert(channelName+":"+channelCode, tmpMap);
                    }
                }
            }
            if(!m_dishesMap.isEmpty())
            {
                emit hideAlert();
                emit iniDishesData(m_dishesMap);
            }else
            {
                emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("未获取到产品信息!"));
            }
        }
    }
}

void FlowControl::onUpdDishes(QString channelCode, QMap<QString, int> dishes)
{
    QString error;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;

    sendJson = DataManger::GetInstance().GetUpdDishesData(channelCode, dishes);

    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在同步产品销售状态......"));

    QLOG_INFO() << QString("[<<<<---UpdDishes:Begin--->>>>][requestData:%1]")<<sendJson;
    result = m_pullDishesSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---UpdDishes:Finish--->>>>][result:%1][message:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
    if(!result)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("同步产品销售状态失败![网络错误]"));
    }else
    {
        if(JSON_STATUSCODE_OK != recvJson[JSON_STATUSCODE].toInt())
        {
            result = false;
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("同步产品销售状态失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
        }else
        {
            emit hideAlert();
            emit processDishiesSuccssful(channelCode, dishes);
        }
    }
}

void FlowControl::onUpdDishesForRef(QString channelCode, QMap<QString, int> dishes)
{
    QString error;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;

    sendJson = DataManger::GetInstance().GetUpdDishesData(channelCode, dishes);

    QLOG_INFO() << QString("[<<<<---UpdDishesForRef:Begin--->>>>][requestData:%1]")<<sendJson;
    result = m_pullDishesSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---UpdDishesForRef:Finish--->>>>][result:%1][msg:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
}

void FlowControl::onSetStoreOperatingStatus(const QString &channelCode, const QString &channelName, int business_status)
{
    //TODO
    Q_UNUSED(channelName);
    return ;
    QString error;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;

    sendJson = DataManger::GetInstance().GetOperatingStatusData(channelCode, business_status);
    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在设置门店营业状态......"));
    QLOG_INFO() << QString("[<<<<---SetStoreOperatingStatus:Begin--->>>>][requestData:%1]")<<sendJson;
    QUrl TempQUrl = ConfigManger::GetInstance().GetStoreServerUrl()+
            ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_UPDATESTATE);
    m_pullDishesSocket->SetUrl(TempQUrl);
    qDebug()<<QUrl(ConfigManger::GetInstance().GetStoreServerUrl()+
                   ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_UPDATESTATE));
    result = m_pullDishesSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---SetStoreOperatingStatus:Finish--->>>>][result:%1][msg:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
    if(!result)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("设置门店营业状态失败![网络错误]"));
    }else
    {
        if(JSON_STATUSCODE_OK != recvJson[JSON_STATUSCODE].toInt())
        {
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("设置门店营业状态失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
        }else
        {
            emit hideAlert();
            emit setStoreOperatingStatusFinsh(channelCode);
        }
    }
}


void FlowControl::onSendSelfCheck()
{
    if(!m_bLoginResult)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("门店未登录"));
        return;
    }
    QString error;
    QString url;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;
    sendJson = DataManger::GetInstance().GetSelfCheckReqData();

    if(ConfigManger::GetInstance().GetOrderSslConfig())
    {
        m_procOrderSocket->SetSslConfig();
        QLOG_INFO()<<"load ssl";
    } else {
        QLOG_INFO()<<"load not ssl";
    }

    if ( m_serviceCallBackUrl.length() && m_bCreateSelfCheckOrderError ) {
        url = m_serviceCallBackUrl + "/order/"+ "pos/create/checkOrder";
    } else {
        url = ConfigManger::GetInstance().GetOrderServerUrl()+ "pos/create/checkOrder";
    }

    QLOG_INFO() << QString("[<<<<---FlowControl::onSendSelfCheck Begin--->>>>][ requestUrl:%1 ,  requestData:] ").arg(url) << sendJson;
    QUrl TempQUrl = url;
    m_procOrderSocket->SetUrl(TempQUrl);
    result = m_procOrderSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---Get onSendSelfCheck:Finish--->>>>][result:%1][msg:%2][recvData:%3]").arg(result).arg(error)<<recvJson;

    if ( !result ) {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("发送自测请求失败![网络错误]"));
        m_bCreateSelfCheckOrderError ? m_bCreateSelfCheckOrderError = false : m_bCreateSelfCheckOrderError = true; // 一次失败一次切换主备地址;
    } else {
        if(JSON_STATUSCODE_OK != recvJson[JSON_ERRCODE].toInt()) {
            result = false;
            m_bCreateSelfCheckOrderError ? m_bCreateSelfCheckOrderError = false : m_bCreateSelfCheckOrderError = true; // 一次失败一次切换主备地址;
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("发送自测请求失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
        } else {
            emit showAlert(AlertForm::SUCCESS, QString::fromLocal8Bit("发送自测请求成功"));
            m_bCreateSelfCheckOrderError = false;
        }
    }
}



void FlowControl::onDailyReport()
{
    if(!m_bLoginResult)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("门店未登录"));
        return;
    }
    QString error;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;
    QString m_business=QDateTime::currentDateTime().toString("yyyyMMdd");

    sendJson = DataManger::GetInstance().GetDayReportData(m_business);

    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在通信......"));

    QLOG_INFO() << QString("[<<<<---Get DailyReport:Begin--->>>>][requestData:%1]")<<sendJson;
    result = m_procOrderSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("[<<<<---Get DailyReport:Finish--->>>>][result:%1][msg:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
    if(!result)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取入账日结失败![网络错误]"));
    }else
    {
        if(JSON_STATUSCODE_OK != recvJson[JSON_STATUSCODE].toInt())
        {
            result = false;
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取入账日结失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
        }else
        {
            recvJson.insert(JSON_STORENAME,m_storeName);
            recvJson.insert(JSON_POSNO,m_posId);
            recvJson.insert(JSON_STOREID,m_storeId);
            recvJson.insert(JSON_USERID,m_cashierId);
            recvJson.insert(JSON_USERNAME,m_cashierName);
            recvJson.insert(JSON_BUSINESSDATE,m_business);
            emit hideAlert();
            emit showDailyReportData(recvJson);
        }
    }
}

void FlowControl::_CrondClearExpireOrder()
{
    //QDateTime currentDateTime= QDateTime::currentDateTime();  //--按秒数来验证ok--
    QDate currentDate= QDate::currentDate();
    //QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---_CrondClearExpireOrder: 清理内存中订单数据的清理日期：%1 --->>>>]").arg(currentDateTime.toString("yyyy-MM-dd hh:mm:ss")); //--按秒数来验证OK--
    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---_CrondClearExpireOrder: 清理内存中订单数据的清理日期：%1 --->>>>]").arg(currentDate.toString("yyyy-MM-dd"));
    OrderObject *order=nullptr;
    m_OrderEntryMutex.lock();
    foreach (order, m_FmOrdersMap.values()) {
        QDate createDate = QDate::fromString( (order->createTime).mid(0,10),"yyyy-MM-dd");
        // 如果是预约单 则需以预约日期为准，实现过期订单清理条件;
         if ( 7 == order->orderType || 11 == order->orderType ) {
             createDate = QDate::fromString( (order->expectDate).mid(0,10),"yyyy-MM-dd");
         }

        //QLOG_INFO()<<QString("[<<<<---_CrondClearExpireOrder-> order->createTime Or expectDate :%1--->>>>]").arg(order->createTime); //--按秒数来验证ok--
        QLOG_INFO()<<QString("[<<<<---_CrondClearExpireOrder-> order  createDate Or expectDate :%1--->>>>]").arg(createDate.toString("yyyy-MM-dd"));
        //qint64 seconds = createDateTime.secsTo(currentDateTime);  //--按秒数来验证ok--
        qint64 days = createDate.daysTo(currentDate);
        //QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---_CrondClearExpireOrder: ClearExpireOrder: 相差多少秒:%1--->>>>]").arg(seconds); //--按秒数来验证ok--
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---_CrondClearExpireOrder: ClearExpireOrder: 相差多少天:%1--->>>>]").arg(days);
        if(days>=1)
        {
            QLOG_INFO()<<QString("[<<<<---_CrondClearExpireOrder: ClearExpireOrder: Emit Signal:Clear Order  orderID:%1--->>>>]").arg(order->id);
            emit clearorder(order->id,order->orderStatus);
            m_FmOrdersMap.value(order->id)->deleteLater();
            m_FmOrdersMap.remove(order->id);
            // 任何情况情况下都不能清理 Simphony获取的有效队列【除非已经被simphony处理过的数据】;目前已经在POS 触发的Action1:_ResponseSimReqFristOrderData 中做数据清理了
            // m_simValidOrdersList.removeOne(order->id);
        }
    }
    m_OrderEntryMutex.unlock();

    // 清理汇报入机结果的列表;
    if ( !m_orderRecordRepOMSList.isEmpty() ) {
        bool btryLock = m_RepOMSRecordOrderMutex.tryLock(VALUE_TRYLOCKMEMTIMEOUT);
        if ( !btryLock ) {     //加锁失败后，直接return;
            QLOG_INFO()<<"[<<<<----FlowControl::_ReportOMSRecordOrderInfo tryLock Failed ---->>>>>]";
        } else {
            RepOMSRecordOrderInfo* RepOMSRecOrderIn = nullptr;
            foreach ( RepOMSRecOrderIn, m_orderRecordRepOMSList ) {
                if ( RepOMSRecOrderIn ) {
                    QDate recordDate = QDate::fromString( (RepOMSRecOrderIn->recordDate ).mid(0,10),"yyyy-MM-dd");
                    qint64 recordDays = recordDate.daysTo(currentDate);
                    QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---_CrondClearExpireOrder: ClearExpireRecordOrderInfo: 相差多少天:%1--->>>>]").arg(recordDays);
                    if ( recordDays >= 1 ) {
                        m_orderRecordRepOMSList.removeOne( RepOMSRecOrderIn );
                        delete RepOMSRecOrderIn;
                        RepOMSRecOrderIn = nullptr;
                    }
                } else {
                    m_orderRecordRepOMSList.removeOne( RepOMSRecOrderIn );
                }
            }

            m_RepOMSRecordOrderMutex.unlock();
        }
    }

    SimProcOrderDB::getInstance().deleteOrderRecord(QDate::currentDate().addDays(-45).toString("yyyyMMdd"));
}

bool FlowControl::_ResponseHttpRequest(const QJsonObject &content,QJsonObject &data, QString& error)
{
    QLOG_INFO()<<__FUNCTION__;
    bool result = true;
    /****校验Http请求参数有效性: 校验参数->actionId不存在****/
    if(!content.contains("actionId")) {
        error =QString::fromLocal8Bit("解析Http请求参数:参数中没有actionId");
        result = false;
    }/****校验Http请求参数有效性: 校验参数->actionId存在****/
    else {
        int actionId;
        if(content["actionId"].isString()){
            actionId=content["actionId"].toString().toInt();
        } else {
            actionId=content["actionId"].toInt();
        }
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---Http请求[action:%1] --->>>>]").arg(actionId);
        /****校验请求参数actionId的具体数值:****/
        switch (actionId) {
        case 1://simphony拉取订单
            result=_ResponseSimphony01Request(content,data,error);
            break;
        case 2://simphony确认接单
            result=_ResponseSimphony02Request(content,data,error);
            break;
        case 3://simphony取消接单
            result=_ResponseSimphony03Request(content,data,error);
            break;
        case 4://simphony汇报小票号信息回复
            result=_ResponseSimphony04Request(content,data,error);
            break;
        case 5://simphony更新订单数据到POS本地数据库以便POS打印小票及汇总单信息 回复
            result=_ResponseSimphony05Request(content,data,error);
            break;
        case 6://simphony汇报SIM录单异常 回复
            result=_ResponseSimphony06Request(content,data,error);
            break;
        case 11://FM OMS推送订单
            result=_ResponseOMS11Request(content,data,error);
            break;
        case 12://推送门店营业状态
            result=_ResponseOMS12Request(content,data,error);
            break;
        case 13: //推送 宣导提醒消息
            result=_ResponseOMS13Request(content,data,error);
            break;
        case 21://盒马生鲜 推送订单
            result=_ResponseHM21Request(content,data,error);
            break;
        default:
            error =QString::fromLocal8Bit("解析Http请求actionId值不在规定的接口文档内");
            result = false;
            break;
        }
    }
    return result;
}

bool FlowControl::_ResponseSimphony01Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    QLOG_INFO()<<__FUNCTION__;
    Q_UNUSED(content);
    Q_UNUSED(data);
    Q_UNUSED(error);
    return true;
}

bool FlowControl::_ResponseSimphony02Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    Q_UNUSED(content);
    Q_UNUSED(data);
    Q_UNUSED(error);
    return true;
}
bool FlowControl::_ResponseSimphony03Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    Q_UNUSED(content);
    Q_UNUSED(data);
    Q_UNUSED(error);
    return true;
}
bool FlowControl::_ResponseSimphony04Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    QLOG_INFO()<<__FUNCTION__;
    Q_UNUSED(content);
    Q_UNUSED(data);
    Q_UNUSED(error);
    return true;
}


bool FlowControl::_ResponseSimphony05Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    QLOG_INFO()<<__FUNCTION__;
    Q_UNUSED(content);
    Q_UNUSED(data);
    Q_UNUSED(error);
    return true;
}



bool FlowControl::_ResponseSimphony06Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    QLOG_INFO()<<__FUNCTION__;
    Q_UNUSED(content);
    Q_UNUSED(data);
    Q_UNUSED(error);
    return true;
}


bool FlowControl::_ResponseOMS11Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    Q_UNUSED(data);
    QLOG_INFO()<<__FUNCTION__;
    bool result=true;
    QString omsPushOrderId;

    if ( !m_bLoginResult ) {
        error = QString::fromLocal8Bit("FMOMS未登录");
        if ( content[JSON_CALL_BACK_URL].toString().length() ) {
            m_serviceCallBackUrl = content[JSON_CALL_BACK_URL].toString();  // https://delposserviceapi.starbucks.net/backstage  : 域名/backstage
        }
        return false;

    } else {
        if ( content[JSON_ORDER_ID].toString().isEmpty() ) {
            error =QString::fromLocal8Bit("订单号不能为空");
            return false;
        } else {

            QString omsCallBackUrl= content[JSON_CALL_BACK_URL].toString();  // https://delposserviceapi.starbucks.net/backstage  : 域名/backstage
            omsPushOrderId = content[JSON_ORDER_ID].toString();

            QJsonObject omsPushOptions;
            if ( content.contains(JSON_PUSH_OPTIONS) ) {
                omsPushOptions  = content[JSON_PUSH_OPTIONS].toObject();  // KEY -> options
            }

            if ( omsCallBackUrl.length() ) {
                m_serviceCallBackUrl = omsCallBackUrl;
            }

            // New Mode: Upstream Push Order Contain Order Detail Data;
            QJsonObject omsPushOrderDetail;
            if ( content.contains(JSON_PUSH_ORDER_DETAIL) ) {
                omsPushOrderDetail = content[JSON_PUSH_ORDER_DETAIL].toObject();

                if ( omsPushOrderDetail.contains(JSON_ID) ) {
                    // 如果O2O-fullfillment Push Order Contain Order Detail Data, Call _TryAddOrderQueueAnalysis(...), Then Direct Return;
                    QLOG_INFO() << QString("[<<<<---_ResponseOMS11Request: OrderId: %1 Use New Mode->Push&Contains Order Detail Data --->>>>]").arg(omsPushOrderId);
                    error = QString("Recv OrderId: %1 Data Success").arg(omsPushOrderId);
                    QLOG_INFO() << QString("[<<<<---_ResponseOMS11Request: Order Detail Data --->>>>]") << omsPushOrderDetail;
                    return _TryAddOrderQueueAnalysis(omsPushOrderId, omsPushOrderDetail, omsCallBackUrl, omsPushOptions);
                } else {
                    QLOG_ERROR() << QString("[<<<<---_ResponseOMS11Request: OrderId: %1 Contains Key:[orderDetail], But Not Contain More Data--->>>>]").arg(omsPushOrderId);
                    QLOG_ERROR() << QString("[<<<<---_ResponseOMS11Request: OrderId: %1 Will Continue Old Mode->Push&Pull, Get Order Detail--->>>>]").arg(omsPushOrderId);
                }
            }

            // 接受到非码oms 推过来的订单，进行向队列中进行添加；
            result =  _TryAddOrderPull( content[JSON_ORDER_ID].toString(), content[JSON_CHANNEL].toString(), omsCallBackUrl );
            /***组装从FM外卖service端的拉单请求参数***/
            if (result) {
                error = QString("Recv OrderId: %1 Data Success").arg(omsPushOrderId);
            } else {
                error = QString("Recv OrderId: %1 Data Failed").arg(omsPushOrderId);
            }

        }

    }
    return result;
}

bool FlowControl::_ResponseOMS12Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    QLOG_INFO()<<__FUNCTION__;
    Q_UNUSED(data);
    //判断当前POS插件是否登录成功: 如果没有登录成功，尝试在次登录;
    bool result = true;
    if(!m_bLoginResult&&content.contains("storeId")) {
        result=_ResponseSimReqTryLogin(content,error);
    }
    //如果登录成功 or 插件正在尝试登录中:则return true 并返回相应的错误信息;
    if(result){
        if(!content["storeId"].toString().compare(m_storeId)) {
            QLOG_INFO()<<"FlowControl::_ResponseOMS12Request:"<<content;
            m_eleStoreStatus = content[JSON_ELESTORESTS].toInt();
            m_modStoreStatus = content[JSON_MODSTORESTS].toInt();
            m_mopStoreStatus = content[JSON_MOPSTORESTS].toInt();
            m_mtModStoreStatus = content[JSON_MTMODSTORESTS].toInt();
            // m_existNoAckNotice = SaveNoticeMsgDB::getInstance().existNoAckNotice() ? 1 : 0;
            m_existNoAckNotice = 0;
            QLOG_INFO()<<QString("[<<<<---FlowControl::_ResponseOMS12Request eleStoreStatus: %1, modStoreStatus: %2 , mopStoreStatus: %3 , mtModStoreStatus: %4, existNoAckNotice:%5 --->>>>]").
                         arg(m_eleStoreStatus).arg(m_modStoreStatus).arg(m_mopStoreStatus).arg(m_mtModStoreStatus).arg(m_existNoAckNotice);

            emit doUpdateStoreStatus(m_eleStoreStatus, m_modStoreStatus, m_mopStoreStatus, m_mtModStoreStatus, m_existNoAckNotice);

            error=QString("success");
            result = true;
        } else {
            error=QString::fromLocal8Bit("门店信息不匹配");
            result = false;
        }
    }
    return result;
}


bool FlowControl::_ResponseOMS13Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    QLOG_INFO()<<__FUNCTION__;
    Q_UNUSED(data);
    //判断当前POS插件是否登录成功: 如果没有登录成功，尝试在次登录;
    QLOG_INFO()<<"FlowControl::_ResponseOMS13Request:"<<content;

    bool result = true;
    if ( !m_bLoginResult && content.contains("storeId") ) {
        result = _ResponseSimReqTryLogin(content,error);
    }

    //无论插件是否登录成功: 插件接受到消息 则 return true 同时返回有意义的错误信息;
    QString noticeTitle = content[JSON_NOTICE_TITLE].toString();
    QString noticeContent = content[JSON_NOTICE_CONTENT].toString();
    noticeTitle = QString::fromUtf8( noticeTitle.toUtf8() );
    noticeContent = QString::fromUtf8( noticeContent.toUtf8() );
    // emit showNotice(NoticeForm::ACK_MSG, noticeTitle, noticeContent);

    result = true;

    if ( !content["storeId"].toString().compare(m_storeId) ) {
        error=QString::fromLocal8Bit("插件接受消息成功, 插件目前登陆状态");
    } else {
        error=QString::fromLocal8Bit("插件接受消息成功, 但插件未登陆成功 或 门店号不匹配");
    }

    // 待完善, Plugin收到 门店通告消息 后,要想能够在oms侧进行统计，需要通过Plugin 向上游系统进汇报;

    return result;
}


bool FlowControl::_ResponseHM21Request(const QJsonObject &content, QJsonObject &data, QString &error)
{
    QLOG_INFO()<<__FUNCTION__;
    //判断当前POS插件是否登录成功: 如果没有登录成功，尝试在次登录;
    Q_UNUSED(data);
    bool result=true;
    if(!m_bLoginResult&&content.contains("storeId")) {
        result=_ResponseSimReqTryLogin(content,error);
    }
    //如果登录成功 or 插件正在尝试登录中:则return true 并返回相应的错误信息;
    if(result){
        //<1>:更新 OrderObject 中的数据;
        //获取门店营业状态
        //QString strOpeStatus=QString::fromLocal8Bit("开店");
        //emit setOpeStatus(strOpeStatus);
        //增加筛选条件,判断当前POS系统录单的订单是否还没录单完成:如果该订单录单没有完成,不返回100,务必让服务的等待;
        if(content[JSON_ORDER_ID].toString().isEmpty()) {
            error =QString::fromLocal8Bit("订单号不能为空");
            return false;
        } else {
            if(!m_simValidOrdersList.isEmpty()){
                QString simValidOrderListFirstOne = m_simValidOrdersList.first();
                //缩小锁住订单的条件范围: 服务端推单给插件程序且插件程序拒绝本次订单状态发生变化的请求
                if(content[JSON_ORDER_ID].toString() == simValidOrderListFirstOne && m_bFloatFromLockSt){
                    error =QString::fromLocal8Bit("当前订单正在录POS系统，请耐心等待");
                    return false;
                }
            }
        }

        QJsonObject hmOrderJson =  content["orderDetail"].toObject();
        QLOG_INFO()<<"FlowControl::_ResponseHM21Request:"<<hmOrderJson;
        if(!hmOrderJson.isEmpty()){
            result = true;
            error=QString::fromLocal8Bit("_ResponseHM21Request Action:21:accept HM Order Success");
             _OrderAnalysis(hmOrderJson);
        }else{
            result = false;
            error=QString::fromLocal8Bit("_ResponseHM21Request Action:21:accept HM Order empty");
        }
        //<2>:向simphony整合订单数据:准备向POS录单【_OrderAnalysis(hmOrderJson);函数会触发simphony录单动作(退单的情况也会存入队列中)】
        //result=_ResponseSimReqFristOrderData(content, data,error,content["orderId"].toString());
    } else {
        result = false;
        if(error.isEmpty()) {
            error=QString::fromLocal8Bit("Response Simphony_Script Request 01: Login Store Failed");
        }
    }
    return result;
}


bool FlowControl::_PmsMachineReqTryLogin()
{
    /********************* 从PMS Mysql数据库中读取门店信息 *****************************/
    if ( !m_initPmsGetStoreConfigDBRet ) {
        PmsGetStoreConfig::getInstance();
        m_initPmsGetStoreConfigDBRet = PmsGetStoreConfig::getInstance().initPmsStoreConfigDB();
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PmsMachineReqTryLogin() m_initPmsGetStoreConfigDBRet:--->>>>]") <<m_initPmsGetStoreConfigDBRet;
        if ( !m_initPmsGetStoreConfigDBRet )  {
            QLOG_ERROR()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PmsMachineReqTryLogin()  m_initPmsGetStoreConfigDBRet  Retry Still Failed, Wait Next...--->>>>>]");
            return false;
        }
    }

    if ( !m_initPmsOrdersDataRet ) {
        PmsOrdersData::getInstance();
        m_initPmsOrdersDataRet = PmsOrdersData::getInstance().initPmsOrdersData();
       QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PmsMachineReqTryLogin() m_initPmsOrdersDataRet:--->>>>]")<<m_initPmsOrdersDataRet;
       if ( !m_initPmsOrdersDataRet ) {
           QLOG_ERROR()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PmsMachineReqTryLogin()  m_initPmsOrdersDataRet  Retry Still Failed, Wait Next...--->>>>>]");
           return false;
       }
    }

    bool bGetStoreCnf = PmsGetStoreConfig::getInstance().GetStoreConfig(m_storeId,m_posId,m_cashierId,m_cashierName,m_pmsMachineNo);
    if ( !bGetStoreCnf ) {
        QLOG_ERROR()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PmsMachineReqTryLogin()  GetStoreConfig Still Failed, Wait Next...--->>>>>]");
        return false;  // Wait Next LoginTimer Trigger Check Connect DB Success;
    }

    if ( !m_initPmsRedisRet ) {
        Sleep(3*1000);
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PmsMachineReqTryLogin() Begin  initQtRedisClient()--->>>>]");
        m_initPmsRedisRet = QtRedisClient::getInstance().initQtRedisClient();
        QLOG_INFO()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PmsMachineReqTryLogin() m_initPmsRedisRet:--->>>>]")<<m_initPmsRedisRet;
        if ( !m_initPmsRedisRet ) {
            QLOG_ERROR()<<QString::fromLocal8Bit("[<<<<---FlowControl::_PmsMachineReqTryLogin()  m_initPmsRedisRet  Retry Still False, Wait Next...--->>>>>]");
            return false;  // Wait Next LoginTimer Trigger Check Connect Redis Success;
        }
    }

    //_TestRedis();
    //_TestInsertOrderData();

    // All Connect Success Will Login OMS;
    if(m_bFirstRecvInfo || !m_bLoginResult) {
        QString error = QString::fromLocal8Bit("FMOMS Plug-in Program Try Login On");
        _Login();
    }
    return true;
}

bool FlowControl::_ResponseSimReqTryLogin(const QJsonObject &content,QString &error)
{
    QLOG_INFO()<<__FUNCTION__;
    Q_UNUSED(content);
    Q_UNUSED(error);
    return true;
}

bool FlowControl::_ResponseSimReqFristOrderData(const QJsonObject &content, QJsonObject &data, QString &error, const QString &orderId)
{
    QLOG_INFO()<<__FUNCTION__<<error<<orderId;
    Q_UNUSED(content);
    Q_UNUSED(data);
    return false;
}


QString FlowControl::_Penny2Dollar(int penny)
{
    double dollar = static_cast<double>(penny/100);
    return QString::number(dollar,'f',1);
}

void FlowControl::onGetBusinessStatus()
{
    QLOG_INFO()<<__FUNCTION__;
    if(!m_bLoginResult)
    {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("门店还未登录"));
        return ;
    }
    QString error;
    bool result;
    QJsonObject sendJson;
    QJsonObject recvJson;

    sendJson = DataManger::GetInstance().GetStoreChannelInfoData();
    QUrl TempQUrl = ConfigManger::GetInstance().GetStoreServerUrl()+
            ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_GETSTORESTATE);
    m_pullDishesSocket->SetUrl(TempQUrl);
    QLOG_INFO()<<ConfigManger::GetInstance().GetStoreServerUrl()+ ConfigManger::GetInstance().GetInterfaceName(INI_INTERFACE_GETSTORESTATE);
    emit showAlert(AlertForm::LOADING, QString::fromLocal8Bit("正在获取平台营业状态......"));
    QLOG_INFO() << QString("[---GetStoreChannelInfo---]. [requestData:%1]")<<sendJson;
    result = m_pullDishesSocket->PostRequest(sendJson, recvJson, error);
    QLOG_INFO() << QString("GetStoreChannelInfo finsh. [result:%1][msg:%2][recvData:%3]")
                   .arg(result).arg(error)<<recvJson;
    if(!result) {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取平台营业状态失败![网络错误]"));
    } else {
        if(JSON_STATUSCODE_OK != recvJson[JSON_STATUSCODE].toInt()) {
            emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("获取平台营业状态失败![%1]").arg(recvJson[JSON_MESSAGE].toString()));
        } else {
            QJsonArray array=recvJson[JSON_DATA].toArray();
            QStringList strListChannels;
            foreach(QJsonValue v, array) {
                QJsonObject channel =  v.toObject();
                QString channelName = channel["channelname"].toString();
                QString channelCode = channel["channel"].toString();
                QString channelStatus = QString::number(channel["state"].toInt());
                qDebug()<<channelName<<"-"<<channelCode<<"-"<<channelStatus;
                strListChannels.append(channelCode+":"+channelName+":"+channelStatus);
            }

            if(!strListChannels.isEmpty()) {
                emit hideAlert();
                // 通知界面显示
                // emit initChannelsData(strListChannels);
            } else {
                emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("未获取到平台信息!"));
            }
         }
    }
}


void FlowControl::onGetOMSAllOrders()
{
    QLOG_INFO()<<__FUNCTION__;
    if(!m_bLoginResult) {
        emit showAlert(AlertForm::MSGERROR, QString::fromLocal8Bit("门店还未登录"));
        return ;
    }
    // 类登陆后的获取全部订单动作;
    QLOG_INFO() << QString(" FlowControl::onGetOMSAllOrders only _AddOrderPull begin.");

    // 获取原生链路的全量订单列表数据;
    _AddOrderPull( QString(), QString() );

    // 获取 o2ofulfillment 链路的全量订单列表数据;
    if ( ConfigManger::GetInstance().GetLoginServerUrl().contains(".stg") ) {
        _AddOrderPull( QString(), QString(), GET_O2OFULFILLMENT_STG_CBL );
    } else if ( ConfigManger::GetInstance().GetLoginServerUrl().contains(".dev") ) {
        _AddOrderPull( QString(), QString(), GET_O2OFULFILLMENT_DEV_CBL );
    } else if ( ConfigManger::GetInstance().GetLoginServerUrl().contains(".uat") ) {
        _AddOrderPull( QString(), QString(), GET_O2OFULFILLMENT_UAT_CBL );
    } else {
        _AddOrderPull( QString(), QString(), GET_O2OFULFILLMENT_PRO_CBL );
    }

     emit showAlert(AlertForm::SYNCDATA, QString::fromLocal8Bit("正在获取平台全部订单,稍后刷新......"));
    QLOG_INFO() << QString(" FlowControl::onGetOMSAllOrders only _AddOrderPull end.");
}


void FlowControl::onProcessOrder(const QString &operation, const QString &orderId)
{
    if(!operation.compare(OPERATION_GETDELIVERS))
    {
        //_GetDelivers(orderId);
        _ConfirmOrder(orderId);
    }else if(!operation.compare(OPERATION_CONFRIM))
    {
        _ConfirmOrder(orderId);
    }
    else if(!operation.compare(OPERATION_SENDOUT))
    {
        _SendOrder(orderId);
    }else if(!operation.compare(OPERATION_COMPLETE))
    {
        _CompleteOrder(orderId);
    }else if(!operation.compare(OPERATION_REFUSEREFUND))
    {
        // _RefuseRefund(orderId);
    }else if(!operation.compare(OPERATION_REFUNDORDER))
    {
        _RefundOrder(orderId,5,QString::fromLocal8Bit("同意退款"),QString());
    }
}


bool FlowControl::onRecvSocketPushedMsg(QByteArray &msgData, int & actionId) {
    bool recvRet = false;

    if ( 11 == actionId ) {
        QJsonDocument document = QJsonDocument::fromJson(msgData);
        if ( document.isNull() ) {
            QLOG_ERROR()<<QString("onRecvSocketPushedMsg  QJsonDocument::fromJson(*) Is Null , ActionId : %1").arg(actionId);
        } else {
            QJsonObject orderDataObject = document.object();
            QJsonObject unusedData;
            QString error;
            recvRet = _ResponseOMS11Request(orderDataObject, unusedData, error);
            QLOG_INFO()<<QString("onRecvSocketPushedMsg  recvRet: %1, error: %2").arg(recvRet?1:0).arg(error);
        }

    } else if ( 21 == actionId ) {
        QLOG_INFO() << "onRecvSocketPushedMsg::  ActionID: 21 , Wait Process";
    } else {
        QLOG_ERROR() << "onRecvSocketPushedMsg::  OMS Push Plugin Action Out Of Range";
    }

    return recvRet;
}


void FlowControl::onGetOrderDetails(const QString& orderId)
{
    emit hideAlert();
    emit showOrderDetails(m_FmOrdersMap.value(orderId));
}


void FlowControl::onGetEcMopOrderDetails(const QString& orderId, const QString& channel)
{
    // 入参非法校验;
    QString tempOrderId = orderId.trimmed();   // 返回一个字符串,移除从一开始到结尾的空白。也去掉头尾的空白【simplified】

    if ( tempOrderId.isEmpty() || channel.isEmpty() || tempOrderId.length() < 17 ||  tempOrderId.length() > 25 ) {
        QLOG_INFO() << QString("[<<<<---FlowControl::onGetEcMopOrderDetails: OrderId:%1 /  channel:%2  Is Empty / Error  --->>>>]").arg( tempOrderId ).arg( channel );
        emit showAlert(AlertForm::MSGERROR,  QString::fromLocal8Bit("扫描订单号异常") );
        return;
    } else {
        QString callBackUrl = "";
        // 入参有效;
        // 判断插件是否登录成功了，没有登录成功，弹框提示;
        if ( !m_bLoginResult  ) {
            emit showAlert(AlertForm::MSGERROR,  QString::fromLocal8Bit("插件程序还未成功登录") );
            return;
        }
        // 组装请求报文 [ 含门店编号:便于 OMS 校验此订单是否属于本门店 ] , 获取订单详情数据 ;[ 失败则弹框提示]

        if ( m_FmOrdersMap.value( tempOrderId ) ) {
            callBackUrl = m_FmOrdersMap.value( tempOrderId )->callBackUrl;
        }

        // 初步上线, 兼容现有环境, EC-MOP 如果拉取失败, 需要 跳过错误展示
        bool pullOrderDetailRet = _PullOrderDetail( tempOrderId, channel, callBackUrl, false, QJsonObject(), true );

        if ( !pullOrderDetailRet ) {

            if ( ConfigManger::GetInstance().GetOrderServerUrl().contains(".stg") ) {
                callBackUrl = GET_O2OFULFILLMENT_STG_CBL ;
            } else if ( ConfigManger::GetInstance().GetOrderServerUrl().contains(".dev") ) {
                callBackUrl = GET_O2OFULFILLMENT_DEV_CBL ;
            } else if ( ConfigManger::GetInstance().GetOrderServerUrl().contains(".uat") ) {
                callBackUrl = GET_O2OFULFILLMENT_UAT_CBL ;
            } else {
                callBackUrl = GET_O2OFULFILLMENT_PRO_CBL ;
            }

            pullOrderDetailRet =  _PullOrderDetail( tempOrderId, channel , callBackUrl );
        }

        if ( pullOrderDetailRet ) {
            // 展示跳转订单详情页面; // 同一线程, 理论无需 Sleep
            Sleep(1000*3);
            emit showOrderDetails( m_FmOrdersMap.value( tempOrderId ) );
        }
    }

}


void FlowControl::onSerachOrder(const QString &text)
{
    QLOG_INFO() << QString::fromLocal8Bit("[<<<<---FlowControl::onSerachOrder:输入的数字串:%1 --->>>>]").arg(text);
    QMap<QString,QString> orderMap;
    if(!text.isEmpty()) {
        QMap<QString, OrderObject*>::iterator order;
        for(order = m_FmOrdersMap.begin(); order!=m_FmOrdersMap.end(); order++) {
            QString orderId = order.key();
            QString phoneId = order.value()->consigneePhone;
            QString thirdPartyOrderId = order.value()->thirdPartyOrderId;
            while (!orderId.at(0).isDigit()) {
              orderId = orderId.mid(1);
            }
            if(orderId.startsWith(text)) {
                orderMap.insert(QString::fromLocal8Bit("订单号:")+orderId,QString::fromLocal8Bit("三方订单号:")+thirdPartyOrderId);
            }
            //移除手机号检索
            //新增第三方订单号检索;
            if(thirdPartyOrderId.startsWith(text)) {
                orderMap.insert(QString::fromLocal8Bit("订单号:")+orderId,QString::fromLocal8Bit("三方订单号:")+thirdPartyOrderId);
            }
        }
    }
    emit showSearchOrderResult(orderMap);
}


void FlowControl::onProcessRejectOrder(const QString &orderId, const int &reasonCode,const QString &reason)
{
    Q_UNUSED(orderId);
    Q_UNUSED(reasonCode);
    Q_UNUSED(reason);
}


void FlowControl::onProcessRepealOrder(const QString &orderId, const int &reasonCode,const QString &reason,const QString& dishesListString)
{
    QLOG_INFO() << QString("[<<<<---FlowControl::onProcessRepealOrder: --->>>>]");
    _RefundOrder(orderId,reasonCode,reason,dishesListString);
}


void FlowControl::onProcessRetryInputOrder(const QString &orderId)
{
    QLOG_INFO() << QString("[<<<<---FlowControl::onProcessRetryInputOrder: OrderId: %1 --->>>>]").arg(orderId);
    //先判断非码订单容器不为空;
    if ( !m_FmOrdersMap.isEmpty() ) {
        QMap<QString, OrderObject*>::iterator TempOrder;
        //遍历订单容器列表,找到指定订单;
        for( TempOrder = m_FmOrdersMap.begin(); TempOrder != m_FmOrdersMap.end(); TempOrder++ ) {
            if( TempOrder.key() == orderId) {

                OrderObject* TempOrderObject = TempOrder.value();
                bool btryLock = m_PullOrderDataMutex.tryLock(VALUE_TRYLOCKNETTIMEOUT);
                if (!btryLock) {
                    QLOG_ERROR()<<"[<<<<----FlowControl::onProcessRetryInputOrder Try Lock Failed ---->>>>>]";
                    return;
                }
                /***组装从FM外卖service端的拉单请求参数***/
                PullOrderInfo* orderPull = new PullOrderInfo();
                orderPull->orderId=orderId;
                orderPull->channel=TempOrderObject->channel;
                orderPull->pageNumber=1;
                orderPull->pageSize=30;
                orderPull->pullErrorCount = 0;
                orderPull->skipPrint = false;
                orderPull->pushOptions = QJsonObject();
                orderPull->callBackUrl = TempOrderObject->callBackUrl;

                m_orderPullList.append(orderPull);
                m_PullOrderDataMutex.unlock();
            }
        }
    } else {
        QLOG_INFO() << QString("[<<<<---FlowControl::onProcessRetryInputOrder: m_FmOrdersMap Is Empty --->>>>]");
    }
}
