Commit 853fc522 by wuyang.zou

<1> 支持插件开启长连接模式功能 开关[openTcpChannel]

<2> 支持插件通过长连接模式接受订单状态变更数据;
<3> 支持插件扫码查找 ECMOP 订单并展示订单详情,支持此渠道订单的退款请求;
<4> 支持插件四轮车标识功能
<5> 支持插件汇报入机/入库错误码回调OMS
<6> 入库前商品 PosKey 的有效性检查;

Version: 2.2021.8.12
parent fcd5b593
Pipeline #35710 failed with stage
in 17 seconds
......@@ -33,6 +33,7 @@ SocketCommunicate::SocketCommunicate(ThreadSocket *parent) : ThreadSocket(parent
_domainName.clear();
_isTimeout = true;
_reconnectTimes = 0;
_networkErrIndex = 0;
}
......@@ -297,7 +298,7 @@ void SocketCommunicate::acceptTcpSvrSendMsg()
{
_socketHeartTimer = new QTimer(this);
connect(_socketHeartTimer,&QTimer::timeout,this,&SocketCommunicate::sendSocketHeart);
_socketHeartTimer->start(1000*60*5);
_socketHeartTimer->start(1000*80);
while(!_stopFlag && !_needTcpLogin)
{
......@@ -309,12 +310,21 @@ void SocketCommunicate::acceptTcpSvrSendMsg()
connect(this, &SocketCommunicate::quit, &loop, &QEventLoop::quit);
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
connect(this, &SocketCommunicate::readReady, &loop, &QEventLoop::quit);
timer.start(180*1000);
timer.start(150*1000);
loop.exec();
}
if(_isTimeout)
break ;
if(_isTimeout) {
QDateTime tmpCurDateTime = QDateTime::currentDateTime();
int seconds = tmpCurDateTime.secsTo(_socketHeartBeatDateTime);
if ( abs(seconds) > 90 ) {
QLOG_ERROR() << "acceptTcpSvrSendMsg:: Nothing Recv, Timeout , Wait Retry Connect Server...... ";
break;
} else {
QLOG_INFO() << "acceptTcpSvrSendMsg:: Nothing Recv, Continue Wait Recv Msg Because Diff Last HeartBeat Stamps < 90 , Value: " << abs(seconds);
continue;
}
}
// <1> Read Socket Msg Head;
QByteArray headByteData = _sslSocket->read(sizeof(Data_Head));
......@@ -580,9 +590,9 @@ bool SocketCommunicate::sendSocketHeart()
// <0.1> Long Time No Recv PosAgnet Push Socket Heart Beat Request, Then PosPlugin Will Send HeartBeat By Self.
QDateTime tmpCurDateTime = QDateTime::currentDateTime();
int seconds = tmpCurDateTime.secsTo(_socketHeartBeatDateTime);
if ( abs(seconds) < 1000*60*2 ) {
QLOG_INFO() << "sendSocketHeart:: No Need Send HeartBeat By Self , currentDateTime(): "
<< tmpCurDateTime.toString("yyyy-MM-dd hh:mm:ss")<< " seconds Diff: "<<abs(seconds) ;
if ( abs(seconds) < 60 ) {
QLOG_INFO() << "sendSocketHeart:: No Need Send HeartBeat By Plugin , currentDateTime(): "
<< tmpCurDateTime.toString("yyyy-MM-dd hh:mm:ss")<< " Seconds Diff From Server Send Heart Time: "<<abs(seconds);
return true;
}
......@@ -742,7 +752,7 @@ void SocketCommunicate::threadStart()
}
// <2> 向目标 IP + 端口发起长连接 与 登录请求, 登录成功后接受 Server Response Msg;
while(!_stopFlag) {
while(!_stopFlag && _reconnectTimes < 10 ) {
do {
// <2.1> Connect Svr , Establish Connection;
......@@ -760,7 +770,7 @@ void SocketCommunicate::threadStart()
QLOG_ERROR() << "threadStart:: loginTcpSvr Failed";
break ;
} else {
QLOG_INFO() << "threadStart:: loginTcpSvr Success, Will Accept Tcp Svr Send Msg......";
QLOG_INFO() << "threadStart:: loginTcpSvr Success, Will Accept Tcp Svr Send Msg...... _reconnectTimes: "<< _reconnectTimes;
}
_needTcpLogin = 0;
......@@ -769,6 +779,7 @@ void SocketCommunicate::threadStart()
acceptTcpSvrSendMsg();
networkOuttime(true);
_reconnectTimes++;
} while(0);
//网络异常断开重连, 释放资源 _sslSocket;
......
......@@ -164,6 +164,8 @@ public:
//超时标识
bool _isTimeout;
//发起长连接重连次数;
int _reconnectTimes;
//长连接套接字
QSslSocket *_sslSocket;
//获取服务器列表地址
......
......@@ -92,6 +92,7 @@ private:
QString storeId; //门店编号
QString remark; //备注:入机出错信息
QString checkNo; //小票号:入机成功时的小票号;
QString failCode; // 入机/存储 错误码 (成功时都给 "");
QString posPluginVersion; //该订单入机后, 汇报给OMS对应程序的版本号;
int reqResult; //向OMS请求汇报结果;
}RepOMSRecordOrderInfo;
......@@ -387,13 +388,6 @@ private slots:
void _AddItemToReportOmsList(const OrderObject* orderPoint, const int& msgType, const int& msgRet, const QString& chkNum, const QString& msgDesc);
/* 功能:往 向OMS汇报POS订单入机状态的队列 添加新项 或 更新队列中数据;
* 参数:NULL
* 返回:NULL
* */
void _AddOrUpdateReportOmsList(const QString &orderId, const QString &channel, const QString &repType, const QString &status, const QString &chkNum, const QString &error);
/* 功能:获取Json对象的字符
* 参数:NULL
* 返回:Json字符串
......@@ -451,6 +445,13 @@ public slots:
* */
void onProcessOrder(const QString& operation, const QString& orderId);
/* 功能:往 向OMS汇报POS订单入机状态的队列 添加新项 或 更新队列中数据;
* 参数:NULL
* 返回:NULL
* */
void _AddOrUpdateReportOmsList(const QString &orderId, const QString &channel, const QString &repType, const QString &status, const QString &chkNum,
const QString &error, const QString &errorCode);
/* 功能: 接受长连接推送消息数据
* 参数:[1]字节数组格式 报文 [2] 消息类型ID
* 返回: 处理成功;
......
......@@ -120,7 +120,19 @@ PrintCupStickPosDB &PrintCupStickPosDB::getInstance()
return printCupStickPosDB;
}
bool PrintCupStickPosDB::insertOrderProduct(OrderObject* orderObj,const QString& posCheckNo){
bool PrintCupStickPosDB::insertOrderProduct(OrderObject* orderObj,const QString& posCheckNo, bool &checkProductValidRet) {
// WSG-杯贴祝福-商品券号关联数据;
if ( "WSG-MOD" == orderObj->channel && "4" == orderObj->platformSource ) {
checkProductValidRet = checkCouponProdAllVaild(orderObj);
} else { // All Channel 商品关联数据;
checkProductValidRet = checkNormalProdAllVaild(orderObj);
}
if ( !checkProductValidRet ) {
QLOG_ERROR()<<"insertOrderProduct:: Before Insert Normal Product Or Coupon Product Db, Check PosKey Is Invalid Or Qty Is 0";
return false;
}
QMutexLocker mutex(&m_mutex);
if(!m_sqlDb.open()) {
QLOG_ERROR()<<"[<<<<---SqlServer Database:Open Failed--->>>>]"<<m_sqlDb.lastError().text();
......@@ -153,6 +165,10 @@ bool PrintCupStickPosDB::insertOrderProduct(OrderObject* orderObj,const QString&
QLOG_ERROR()<<"[<<<<---insertOrderProduct::insertOrderProduct: Begin Rollback Failed--->>>>]"<<m_sqlDb.lastError().text();
}
}
} else {
if ( !query.exec( "rollback" ) ) {
QLOG_ERROR()<<"[<<<<---insertOrderProduct::insertOrderProduct: Begin Rollback Failed--->>>>]"<<m_sqlDb.lastError().text();
}
}
m_sqlDb.close();
......@@ -327,6 +343,56 @@ bool PrintCupStickPosDB::insertCouponSubProd(OrderObject* orderObj, const int ma
}
bool PrintCupStickPosDB::checkCouponProdAllVaild(OrderObject* orderObj) {
if (!orderObj) {
QLOG_ERROR()<<"checkCouponProdAllVaild Order Obj Point Is Null";
return false;
}
for (int i=0; i < orderObj->coupList.count(); i++) {
CouponsObject* coupon = orderObj->coupList.at(i);
QString tmpPosKey = "";
int tmpQty = 0;
QString error = "";
for ( int j = 0; j < coupon->skus.count(); j++ ) {
tmpPosKey = coupon->skus[j]->code;
tmpQty = coupon->skus[j]->qty;
// 检查: ①主商品属性:code中含有Default字符串(不区分大小写) + ②code中以非数字开头 + ③商品数量是0 + ④PosKey长度在 [3~9] 之间;
QString tempPosKeyLeftHead = tmpPosKey.left(1);
// 校验券-主商品;
if ( 0 == j ) {
if (tmpPosKey.contains("Default",Qt::CaseInsensitive) || (tempPosKeyLeftHead<QString('0') || tempPosKeyLeftHead>QString('9'))
|| !tmpQty || tmpPosKey.length()<3 || tmpPosKey.length()>9 ) {
error = QString::fromLocal8Bit("This Order Has PosKey Is Combo Error Or Default* Or qty Is Zore Or Sku Length < 3 Or Sku Length > 9");
QString requestType = orderObj->orderStatus==6?QString::fromLocal8Bit("6"):QString::fromLocal8Bit("3");
FlowControl::GetInstance()._AddOrUpdateReportOmsList(orderObj->id, orderObj->channel,requestType, QString("2"), QString(""), error, QString("1010"));
return false;
}
}
// 校验券-子商品;
else {
if( tmpPosKey.contains("Default",Qt::CaseInsensitive) ) {
continue;
} else {
if ( tempPosKeyLeftHead<QString('0') || tempPosKeyLeftHead>QString('9') || !tmpQty || tmpPosKey.length()<3 || tmpPosKey.length()>9 ) {
error = QString::fromLocal8Bit("This Order SubProduct PosKey Is String And No Default* Or qty Is Zore Or Sku Length < 3 Or Sku Length > 9 ");
QString requestType = orderObj->orderStatus==6?QString::fromLocal8Bit("6"):QString::fromLocal8Bit("3");
FlowControl::GetInstance()._AddOrUpdateReportOmsList(orderObj->id, orderObj->channel,requestType, QString("2"), QString(""), error, QString("1011") );
return false;
}
}
}
}
}
return true;
}
bool PrintCupStickPosDB::insertNormalProd(OrderObject* orderObj, const QString& posCheckNo){
int inProdSucNum = 0;
......@@ -336,6 +402,11 @@ bool PrintCupStickPosDB::insertNormalProd(OrderObject* orderObj, const QString&
QSqlQuery query(m_sqlDb);
QDateTime qdaTi = QDateTime::currentDateTimeUtc();
if (!orderObj) {
QLOG_ERROR()<<"insertNormalProd:: orderObj Is Null";
return false;
}
for (int i=0; i < orderObj->proList.count(); i++) {
dishesObject* dish=orderObj->proList.at(i);
query.prepare("INSERT INTO tb_main_prod_refinfo(chk_num, order_id, order_status, create_datetime, "
......@@ -479,6 +550,58 @@ bool PrintCupStickPosDB::insertNormalSubProd(OrderObject* orderObj, const int ma
}
bool PrintCupStickPosDB::checkNormalProdAllVaild(OrderObject* orderObj){
if (!orderObj) {
QLOG_ERROR()<<"checkNormalProdAllVaild Order Obj Point Is Null";
return false;
}
QString tmpPosKey = "";
QString tempPosKeyLeftHead = "";
int tmpQty = 0;
QString error = "";
for (int i=0; i < orderObj->proList.count(); i++) {
dishesObject* dish=orderObj->proList.at(i);
tmpPosKey = dish->code;
tmpQty = dish->qty;
// 检查主商品: ①主商品属性:code中含有Default字符串(不区分大小写) + ②code中以非数字开头 + ③商品数量是0 + ④PosKey长度在 [3~9] 之间;
tempPosKeyLeftHead = tmpPosKey.left(1);
if (tmpPosKey.contains("Default",Qt::CaseInsensitive) || (tempPosKeyLeftHead<QString('0') || tempPosKeyLeftHead>QString('9'))
|| !tmpQty || tmpPosKey.length()<3 || tmpPosKey.length()>9 ) {
error = QString::fromLocal8Bit("This Order Has PosKey Is Combo Error Or Default* Or qty Is Zore Or Sku Length < 3 Or Sku Length > 9");
QString requestType = orderObj->orderStatus==6?QString::fromLocal8Bit("6"):QString::fromLocal8Bit("3");
FlowControl::GetInstance()._AddOrUpdateReportOmsList(orderObj->id, orderObj->channel,requestType, QString("2"), QString(""), error, QString("1010"));
return false;
}
for ( int j = 0; j < dish->sub_products.count(); j++ ) {
dishesObject* subDish=dish->sub_products.at(j);
tmpPosKey = subDish->code;
tmpQty = subDish->qty;
tempPosKeyLeftHead = tmpPosKey.left(1);
// 检查子商品: ①允许子商品{code中含有Default字符串,不区分大小写} 属性: ①code中以非数字开头 + ②商品数量是0 + ③PosKey长度在 [3~9] 之间;
if( tmpPosKey.contains("Default",Qt::CaseInsensitive) ) {
continue;
} else {
if ( tempPosKeyLeftHead<QString('0') || tempPosKeyLeftHead>QString('9') || !tmpQty || tmpPosKey.length()<3 || tmpPosKey.length()>9 ) {
error = QString::fromLocal8Bit("This Order SubProduct PosKey Is String And No Default* Or qty Is Zore Or Sku Length < 3 Or Sku Length > 9 ");
QString requestType = orderObj->orderStatus==6?QString::fromLocal8Bit("6"):QString::fromLocal8Bit("3");
FlowControl::GetInstance()._AddOrUpdateReportOmsList(orderObj->id, orderObj->channel,requestType, QString("2"), QString(""), error, QString("1011") );
return false;
}
}
}
}
return true;
}
bool PrintCupStickPosDB::insertDeliveryPackageAndPack(OrderObject* orderObj, const QString& posCheckNo){
bool insertPackRet = true ;
int insertPackPlaceHolderSeq = 0;
......
......@@ -40,7 +40,7 @@ public:
*参数:[1]订单对象指针 [2]小票号
*返回:true操作成功,false失败
**/
bool insertOrderProduct(OrderObject* orderObj, const QString& posCheckNo);
bool insertOrderProduct(OrderObject* orderObj, const QString& posCheckNo, bool &checkProductValidRet);
/**
*功能:插入订单 券 商品列表到pos本地数据库中;
......@@ -56,6 +56,15 @@ public:
**/
bool insertCouponSubProd(OrderObject* orderObj, const int mainProdIndex, QList<SingleProductObject*> &couponSubProdList, const QString& posCheckNo);
/**
*功能:检查券商品(含客制化) 数据有效性;
*参数:[1]
*返回: true:有效, false: 无效;
**/
bool checkCouponProdAllVaild(OrderObject* orderObj);
/**
*功能:插入订单 正常 商品列表到pos本地数据库中;
*参数:[1]订单对象指针 [2]小票号
......@@ -70,6 +79,15 @@ public:
**/
bool insertNormalSubProd(OrderObject* orderObj, const int mainProdIndex, QList<dishesObject*> &subProdList, const QString& posCheckNo);
/**
*功能:检查正常商品(含客制化) 数据有效性;
*参数:[1]
*返回: true:有效, false: 无效;
**/
bool checkNormalProdAllVaild(OrderObject* orderObj);
/**
*功能:插入订单 配送费+打包费+打包属性到pos本地数据库中;
*参数:[1] [2]
......
......@@ -52,6 +52,14 @@ public:
bool alterTablePrintSumBillPosDB20();
/**
*功能:新增pos本地数据库打印小票信息表中字段;
*参数:[无]
*返回:true:新增成功,false:新增字段失败
**/
bool alterTablePrintSumBillPosDB21();
/**
*功能:变更pos本地数据库打印小票信息表中 store_name store_address 两个字段 长度;
*参数:[无]
*返回:true: 变更成功,false: 变更失败
......
......@@ -101,6 +101,8 @@ class OrderObject : public QObject
Q_PROPERTY (int globalServiceType READ getGlobalServiceType WRITE setGlobalServiceType)
Q_PROPERTY (int globalOrderType READ getGlobalOrderType WRITE setGlobalOrderType)
Q_PROPERTY (int extendType READ getExtendType WRITE setExtendType)
public:
OrderObject(QObject *parent=0)
:QObject(parent){}
......@@ -215,6 +217,7 @@ public:
int globalServiceType; // 全链路服务类型: globalServiceType【新增字段:int】
int globalOrderType; // 全链路订单类型: globalOrderType 【新增字段:int】
int extendType; // 20 四轮车(履约方式的一种)
int forwardPosStatus; // 正向单入机状态: 0:未知 1: 成功 2:失败;
int negativePosStatus; // 负向单同上;
int deliveryStatus;
......@@ -494,6 +497,9 @@ public:
inline int getGlobalOrderType()const{return globalOrderType;}
inline void setGlobalOrderType(const int& v){globalOrderType = v;}
inline int getExtendType()const{return extendType;}
inline void setExtendType(const int& v){extendType = v;}
};
#endif // ORDEROBJECT_H
......@@ -7,8 +7,8 @@ IDI_ICON ICON DISCARDABLE "logo.ico"
#endif
VS_VERSION_INFO VERSIONINFO
//***每次修改后编译发版必须变更版本号(preDefine.h中APP_VERSION 需要一致)***//
FILEVERSION 2,2021,7,12
PRODUCTVERSION 2,2021,7,12
FILEVERSION 2,2021,8,12
PRODUCTVERSION 2,2021,8,12
//*************************************************************************//
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
......@@ -31,8 +31,8 @@ VS_VERSION_INFO VERSIONINFO
VALUE "OriginalFilename", "fmTakeout.exe"
VALUE "ProductName", "Delivery Order Plugin"
//***每次修改后编译发版必须变更版本号(preDefine.h中APP_VERSION 需要一致)***//
VALUE "ProductVersion", "2.2021.7.12"
VALUE "FileVersion", "2.2021.7.12"
VALUE "ProductVersion", "2.2021.8.12"
VALUE "FileVersion", "2.2021.8.12"
//*************************************************************************//
END
END
......
......@@ -37,7 +37,7 @@
//#define APP_VERSION "2.2021.2.26"
//#define APP_VERSION "2.2021.4.19"
//#define APP_VERSION "2.2021.5.11"
#define APP_VERSION "2.2021.7.12"
#define APP_VERSION "2.2021.8.12"
//修正版本号时,切记修正 FmTakeout.rc 中的版本号
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment