Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
fmp_vip
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhenfei.zhang
fmp_vip
Commits
ed18036b
Commit
ed18036b
authored
Sep 20, 2017
by
gujin.wang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
初步完成大鼓米线会员支付功能
parent
3193ea90
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
150 additions
and
96 deletions
+150
-96
fmp_vip.pro
+0
-0
fmp_vip_server.cpp
+40
-9
fmp_vip_server.h
+1
-2
global.h
+9
-6
task/fmtask.cpp
+33
-15
task/fmtask.h
+3
-2
task/taskfinal.cpp
+15
-36
task/taskfinal.h
+2
-2
task/tasklogin.cpp
+6
-1
task/taskothers.cpp
+23
-18
task/taskpay.cpp
+0
-0
task/taskpay.h
+1
-0
windows/forms/fmviporder.ui
+17
-5
No files found.
fmp_vip.pro
View file @
ed18036b
fmp_vip_server.cpp
View file @
ed18036b
...
...
@@ -29,9 +29,43 @@ void FMPVipServer::Listen(quint16 port)
void
FMPVipServer
::
Write
(
const
QByteArray
&
data
)
{
if
(
!
socket
||
socket
->
write
(
data
)
==
-
1
)
{
FMP_ERROR
()
<<
"Write error: "
<<
(
socket
?
socket
->
errorString
()
:
"connection closed."
);
qDebug
()
<<
data
;
QTcpSocket
client
;
//client.connectToHost("172.16.13.191", 23771);
client
.
connectToHost
(
"127.0.0.1"
,
23771
);
if
(
!
client
.
waitForConnected
())
{
FMP_ERROR
()
<<
"Connect monitor failed. "
<<
client
.
errorString
();
return
;
}
//添加消息头
FMSOCKEHEADER
header
=
{
0
,
0
,
0
};
header
.
flag
=
FMSOCKFLAG
;
header
.
ver
=
0x2
;
header
.
len
=
data
.
length
();
int
len
=
sizeof
(
FMSOCKEHEADER
)
+
data
.
length
();
char
*
reply
=
new
char
[
len
];
memset
(
reply
,
0
,
len
);
memcpy
(
reply
,
&
header
,
sizeof
(
header
));
memcpy
(
reply
+
sizeof
(
header
),
data
.
data
(),
data
.
length
());
if
(
client
.
write
(
reply
,
len
)
==
-
1
)
{
FMP_ERROR
()
<<
"Write error: "
<<
client
.
errorString
();
return
;
}
if
(
!
client
.
waitForBytesWritten
())
{
FMP_ERROR
()
<<
"Write failed: "
<<
client
.
errorString
();
}
client
.
disconnectFromHost
();
if
(
client
.
state
()
==
QAbstractSocket
::
ConnectedState
)
client
.
waitForDisconnected
();
client
.
close
();
delete
[]
reply
;
reply
=
nullptr
;
}
void
FMPVipServer
::
SetPluginContext
(
ctkPluginContext
*
ctx
)
...
...
@@ -50,15 +84,17 @@ void FMPVipServer::onNewConnection()
void
FMPVipServer
::
onDisconnected
()
{
FMP_DEBUG
()
<<
"Socket disconnected."
;
socket
->
close
();
}
void
FMPVipServer
::
onReadyRead
()
{
QByteArray
recvData
=
socket
->
readAll
();
socket
->
close
();
socket
->
deleteLater
();
socket
=
nullptr
;
if
(
isNeedSocketHeader
)
{
FMSOCKEHEADER
header
=
{
0
};
FMSOCKEHEADER
header
=
{
0
,
0
,
0
};
memcpy
(
&
header
,
recvData
.
data
(),
sizeof
(
FMSOCKEHEADER
));
if
(
header
.
flag
!=
FMSOCKFLAG
)
{
FMP_WARN
()
<<
"Incompatible protocol."
;
...
...
@@ -71,9 +107,4 @@ void FMPVipServer::onReadyRead()
dispatcher
->
doTask
(
recvData
,
rspData
);
Write
(
rspData
);
socket
->
waitForBytesWritten
();
socket
->
close
();
socket
->
deleteLater
();
socket
=
nullptr
;
}
fmp_vip_server.h
View file @
ed18036b
...
...
@@ -2,7 +2,6 @@
#define FMP_VIP_SERVER_H
#include <QTcpServer>
#define FMSOCKFLAG 0x4d46
class
FMVipDispatcher
;
...
...
@@ -23,7 +22,7 @@ public:
void
Write
(
const
QByteArray
&
data
);
void
SetPluginContext
(
ctkPluginContext
*
ctx
);
//signals:
private
slots
:
void
onNewConnection
();
void
onDisconnected
();
...
...
global.h
View file @
ed18036b
...
...
@@ -11,12 +11,15 @@
//#define KEY_CODE "a35e33c8-e6f2-4107-8670-a69a85adf85b"
//#define PARTNER_ID "f92b8997-40c7-4622-af3b-512fd49d6113"
////! 一茶一座
#define APP_ID "T014"
#define KEY_CODE "a440d553-87d3-4fcd-b59a-5ec9ce7c4157"
#define PARTNER_ID "df2f90b0-eece-402c-820d-ba8ac56c4687"
//! 一茶一座
//#define APP_ID "T014"
//#define KEY_CODE "a440d553-87d3-4fcd-b59a-5ec9ce7c4157"
//#define PARTNER_ID "df2f90b0-eece-402c-820d-ba8ac56c4687"
//! 大鼓米线
#define APP_ID "T017"
#define KEY_CODE "838cd505-1a97-43b3-b521-3b37caa0ab1a"
#define PARTNER_ID "fcce79cf-ba55-4ff8-bde4-684ca26c0ff0"
// 请求类型的枚举值
enum
FM_TYPE
{
...
...
task/fmtask.cpp
View file @
ed18036b
...
...
@@ -106,20 +106,16 @@ bool FMTask::sendToServer(bool isShowMsg)
serverReqJsonObj
[
PosProps
.
AppId
]
=
APP_ID
;
serverReqJsonObj
[
PosProps
.
PartnerId
]
=
PARTNER_ID
;
serverReqJsonObj
[
PosProps
.
T
]
=
QString
::
number
(
QDateTime
::
currentMSecsSinceEpoch
());
serverReqJsonObj
[
ServerProps
(
PosProps
.
Fm_cmd
)]
=
QString
::
number
(
FM_Type
());
serverReqJsonObj
[
PosProps
.
Sign
]
=
sign
();
packageServerReq
();
serverReqJsonObj
[
PosProps
.
Sign
]
=
sign
();
QJsonDocument
json
(
serverReqJsonObj
);
QByteArray
data
=
json
.
toJson
(
QJsonDocument
::
Compact
);
url
=
FMPVipSettings
::
instance
()
->
getServerUrl
()
+
"/"
+
ReqUrl
.
at
(
FM_Type
());
// if(FM_Type() == FM_Coupon) {
// url = "http://172.16.16.42:8732/pos/member/ordercoupon";
// }
QByteArray
rspData
;
QByteArray
rspData
;
FMNetwork
net
;
net
.
send
(
url
,
data
,
rspData
);
...
...
@@ -150,7 +146,7 @@ bool FMTask::sendToServer(bool isShowMsg)
}
bool
isOk
=
(
error
()
==
FM_API_SUCCESS
);
if
(
!
isOk
&&
isShowMsg
)
if
(
!
isOk
&&
isShowMsg
&&
FM_Type
()
!=
FM_Coupon
)
{
FMMsgWnd
::
FailureWnd
(
errorString
(),
_window
);
}
...
...
@@ -158,32 +154,54 @@ bool FMTask::sendToServer(bool isShowMsg)
return
isOk
;
}
QJsonValue
FMTask
::
searchJson
Value
(
QJsonObject
&
searchJson
,
QString
searchKey
)
QJsonValue
FMTask
::
searchJson
Object
(
QJsonObject
&
searchJson
,
QString
searchKey
)
{
QJsonValue
value
;
if
(
searchJson
.
contains
(
searchKey
))
{
return
searchJson
[
searchKey
];
value
=
searchJson
[
searchKey
];
}
else
{
foreach
(
QString
key
,
searchJson
.
keys
())
{
if
(
searchJson
[
key
].
isObject
())
{
QJsonObject
ob
=
searchJson
[
key
].
toObject
();
QJsonValue
value
=
searchJsonValue
(
ob
,
searchKey
);
if
(
!
value
.
isNull
()){
return
value
;
value
=
searchJsonObject
(
ob
,
searchKey
);
}
else
if
(
searchJson
[
key
].
isArray
())
{
QJsonArray
arr
=
searchJson
[
key
].
toArray
();
value
=
searchJsonArray
(
arr
,
searchKey
);
}
}
}
return
value
;
}
QJsonValue
FMTask
::
searchJsonArray
(
QJsonArray
&
searchJson
,
QString
searchKey
)
{
QJsonValue
value
;
for
(
int
i
=
0
;
i
<
searchJson
.
size
();
i
++
)
{
if
(
searchJson
[
i
].
isObject
())
{
QJsonObject
ob
=
searchJson
[
i
].
toObject
();
value
=
searchJsonObject
(
ob
,
searchKey
);
}
else
if
(
searchJson
[
i
].
isArray
())
{
QJsonArray
arr
=
searchJson
[
i
].
toArray
();
value
=
searchJsonArray
(
arr
,
searchKey
);
}
}
return
QJsonValue
()
;
return
value
;
}
QJsonValue
FMTask
::
getServerJsonValue
(
const
QString
prop
)
{
return
searchJson
Value
(
serverRspJsonObj
,
ServerProps
(
prop
));
return
searchJson
Object
(
serverRspJsonObj
,
ServerProps
(
prop
));
}
QJsonValue
FMTask
::
getPosJsonValue
(
const
QString
prop
)
{
return
searchJson
Value
(
posReqJsonObj
,
prop
);
return
searchJson
Object
(
posReqJsonObj
,
prop
);
}
QString
FMTask
::
sign
()
const
...
...
task/fmtask.h
View file @
ed18036b
...
...
@@ -23,7 +23,8 @@ public:
Session
*
session
()
const
{
return
_session
;}
QJsonValue
searchJsonValue
(
QJsonObject
&
searchJson
,
QString
searchKey
);
QJsonValue
searchJsonObject
(
QJsonObject
&
searchJson
,
QString
searchKey
);
QJsonValue
searchJsonArray
(
QJsonArray
&
searchJson
,
QString
searchKey
);
QJsonValue
getServerJsonValue
(
const
QString
prop
);
QJsonValue
getPosJsonValue
(
const
QString
prop
);
...
...
@@ -50,7 +51,7 @@ protected:
FMTask
*
preTask
;
pr
ivate
:
pr
otected
:
QString
sign
()
const
;
/**
...
...
task/taskfinal.cpp
View file @
ed18036b
...
...
@@ -14,6 +14,15 @@ TaskFinal::TaskFinal(QJsonObject &jsonObj, Session *session, QObject *parent)
{
}
QByteArray
TaskFinal
::
doTask
()
{
serverReqJsonObj
=
posReqJsonObj
;
sendToServer
(
false
);
packagePOSRsp
();
QJsonDocument
json
(
posRspJsonObj
);
return
json
.
toJson
(
QJsonDocument
::
Compact
);
}
void
TaskFinal
::
packageServerReq
()
{
isUseVipPay
=
false
;
...
...
@@ -36,33 +45,14 @@ void TaskFinal::packageServerReq()
int
price
=
p
.
toObject
()[
"price"
].
toInt
();
product
[
"price"
]
=
price
;
product
[
"productId"
]
=
p
.
toObject
()[
"pid"
];
product
[
"disAmount"
]
=
p
.
toObject
()[
"dis_amount"
].
toInt
();
products
.
append
(
product
);
}
transData
[
"productList"
]
=
products
;
int
orderAmount
=
getPosJsonValue
(
PosProps
.
OrderAmount
).
toInt
();
int
paidAmount
=
getPosJsonValue
(
PosProps
.
PaidAmount
).
toInt
();
transData
[
"totalAmount"
]
=
getPosJsonValue
(
PosProps
.
OrderAmount
).
toInt
();
transData
[
"payAmount"
]
=
getPosJsonValue
(
PosProps
.
PaidAmount
).
toInt
();
QJsonArray
payList
;
QString
fmId
=
getPosJsonValue
(
PosProps
.
Fm_id
).
toString
();
QByteArray
orderContent
=
FMBackup
::
instance
()
->
getOrderByFmId
(
fmId
);
QJsonObject
orderObject
=
QJsonDocument
::
fromJson
(
orderContent
).
object
();
QJsonArray
payArray
=
searchJsonValue
(
orderObject
,
"payList"
).
toArray
();
foreach
(
auto
pay_v
,
payArray
)
{
QJsonObject
pay_ob
=
pay_v
.
toObject
();
if
(
pay_ob
[
"typeModeFlag"
].
toString
()
==
"20003"
)
{
payList
.
append
(
pay_ob
);
isUseVipPay
=
true
;
int
pay_amount
=
pay_ob
[
"amount"
].
toInt
();
orderAmount
+=
pay_amount
;
paidAmount
+=
pay_amount
;
}
}
transData
[
ServerProps
(
PosProps
.
OrderAmount
)]
=
orderAmount
;
transData
[
ServerProps
(
PosProps
.
PaidAmount
)]
=
paidAmount
;
foreach
(
auto
p
,
getPosJsonValue
(
PosProps
.
Pay_ids
).
toArray
())
{
QJsonObject
pay
;
...
...
@@ -71,28 +61,14 @@ void TaskFinal::packageServerReq()
pay
[
"code"
]
=
p
.
toObject
()[
"code"
].
toString
();
pay
[
ServerProps
(
PosProps
.
TransId
)]
=
getPosJsonValue
(
PosProps
.
TransId
);
QString
typeModeFlag
=
p
.
toObject
()[
"pay_id"
].
toString
();
if
(
typeModeFlag
==
"0101"
)
{
//现金支付
pay
[
"typeModeFlag"
]
=
"20005"
;
}
else
if
(
typeModeFlag
==
"0301"
)
{
pay
[
"typeModeFlag"
]
=
"10011"
;
}
else
if
(
typeModeFlag
==
"0302"
)
{
pay
[
"typeModeFlag"
]
=
"10011"
;
}
else
if
(
typeModeFlag
==
"0303"
)
{
pay
[
"typeModeFlag"
]
=
"10011"
;
}
else
{
pay
[
"typeModeFlag"
]
=
typeModeFlag
;
}
if
(
typeModeFlag
.
compare
(
"20001"
)
==
0
||
typeModeFlag
.
compare
(
"20002"
)
==
0
||
typeModeFlag
.
compare
(
"20003"
)
==
0
)
{
isUseVipPay
=
true
;
}
payList
.
append
(
pay
);
}
transData
[
"payList"
]
=
payList
;
serverReqJsonObj
[
"data"
]
=
transData
;
}
...
...
@@ -117,6 +93,7 @@ bool TaskFinal::sendToServer(bool isShowMsg)
}
}
}
bool
isOk
=
(
error
()
==
FM_API_SUCCESS
);
if
(
!
isOk
)
{
...
...
@@ -131,6 +108,8 @@ void TaskFinal::packagePOSRsp()
posRspJsonObj
[
PosProps
.
Msg
]
=
getServerJsonValue
(
PosProps
.
Msg
);
posRspJsonObj
[
PosProps
.
Fm_id
]
=
getServerJsonValue
(
PosProps
.
Fm_id
);
posRspJsonObj
[
PosProps
.
Prompt
]
=
1
;
posRspJsonObj
[
PosProps
.
TransId
]
=
getPosJsonValue
(
ServerProps
(
PosProps
.
TransId
)).
toString
();
posRspJsonObj
[
PosProps
.
Pay_id
]
=
"1003"
;
}
QString
TaskFinal
::
backup
()
...
...
task/taskfinal.h
View file @
ed18036b
#ifndef TASKFINAL_H
#
ifndef
TASKFINAL_H
#define TASKFINAL_H
#include "fmtasknownd.h"
...
...
@@ -7,7 +7,7 @@ class TaskFinal : public FMTaskNoWnd
Q_OBJECT
public
:
explicit
TaskFinal
(
QJsonObject
&
jsonObj
,
Session
*
session
=
0
,
QObject
*
parent
=
0
);
virtual
QByteArray
doTask
();
void
packageServerReq
();
bool
sendToServer
(
bool
isShowMsg
=
true
);
void
packagePOSRsp
();
...
...
task/tasklogin.cpp
View file @
ed18036b
#
include
"tasklogin.h"
#include "fmviplogin.h"
#include "fmp_home_i.h"
#include "fmp_vip_settings.h"
#include "fmnetwork.h"
#include <QJsonDocument>
#include <QSettings>
TaskLogin
::
TaskLogin
(
QJsonObject
&
jsonObj
,
Session
*
session
,
QObject
*
parent
)
:
FMTask
(
jsonObj
,
FM_Login
,
session
,
parent
)
...
...
@@ -19,7 +21,9 @@ void TaskLogin::setWindow()
_window
=
new
FMVipLogin
;
connect
(
qobject_cast
<
FMVipLogin
*>
(
_window
),
&
FMVipLogin
::
login
,
this
,
&
TaskLogin
::
onLogin
);
session
()
->
addData
(
"store_id"
,
getPosJsonValue
(
"store_id"
));
QSettings
settings
(
qApp
->
applicationDirPath
()
+
"/FreemudPOS.ini"
,
QSettings
::
IniFormat
);
QString
storeId
=
settings
.
value
(
FMP_INIKEY_LOGINSTOREID
).
toString
();
session
()
->
addData
(
PosProps
.
StoreId
,
storeId
);
session
()
->
addData
(
"pos_id"
,
getPosJsonValue
(
"pos_id"
));
session
()
->
addData
(
"operator_id"
,
getPosJsonValue
(
"operator_id"
));
session
()
->
addData
(
"business_date"
,
getPosJsonValue
(
"business_date"
));
...
...
@@ -30,6 +34,7 @@ void TaskLogin::packageServerReq()
QJsonObject
code
;
code
[
ServerProps
(
PosProps
.
Member_sign
)]
=
session
()
->
data
(
PosProps
.
Member_sign
).
toString
();
serverReqJsonObj
[
"data"
]
=
code
;
serverReqJsonObj
[
ServerProps
(
PosProps
.
StoreId
)]
=
session
()
->
data
(
"store_id"
).
toString
();
}
void
TaskLogin
::
packagePOSRsp
()
...
...
task/taskothers.cpp
View file @
ed18036b
...
...
@@ -10,26 +10,27 @@ void TaskCoupon::packageServerReq()
{
QJsonObject
data
;
data
[
ServerProps
(
PosProps
.
Fm_open_id
)]
=
session
()
->
data
(
PosProps
.
Fm_open_id
).
toString
();
// data[ServerProps(PosProps.Fm_open_id)] = "6524402960";
// 产品列表
QJsonArray
pro
p
ducts
;
QJsonArray
products
;
foreach
(
QJsonValue
pValue
,
getPosJsonValue
(
PosProps
.
Products
).
toArray
())
{
QJsonObject
po
=
pValue
.
toObject
();
QJsonObject
spo
;
spo
[
"product_code"
]
=
po
[
PosProps
.
ProductId
];
spo
[
"quantity"
]
=
po
[
PosProps
.
ConsumeNum
];
spo
[
ServerProps
(
PosProps
.
Price
)]
=
po
[
PosProps
.
Price
];
spo
[
"price"
]
=
po
[
PosProps
.
Price
];
spo
[
"brand_code"
]
=
""
;
spo
[
"category_code"
]
=
""
;
pro
p
ducts
.
append
(
spo
);
products
.
append
(
spo
);
}
data
[
ServerProps
(
PosProps
.
Products
)]
=
prop
ducts
;
data
[
"products"
]
=
pro
ducts
;
serverReqJsonObj
[
"data"
]
=
data
;
serverReqJsonObj
[
ServerProps
(
PosProps
.
StoreId
)]
=
session
()
->
data
(
PosProps
.
StoreId
).
toString
();
}
void
TaskCoupon
::
packagePOSRsp
()
{
int
canDisAmount
=
session
()
->
data
(
PosProps
.
OrderAmount
).
toInt
()
-
session
()
->
data
(
PosProps
.
PaidAmount
).
toInt
()
-
session
()
->
data
(
PosProps
.
UndisAmount
).
toInt
();
//
int canDisAmount = session()->data(PosProps.OrderAmount).toInt() - session()->data(PosProps.PaidAmount).toInt() - session()->data(PosProps.UndisAmount).toInt();
QMap
<
QString
,
QVariant
>
couponMap
;
foreach
(
auto
value
,
getServerJsonValue
(
PosProps
.
CouponList
).
toArray
())
...
...
@@ -41,22 +42,26 @@ void TaskCoupon::packagePOSRsp()
int
type
=
couponOb
[
ServerProps
(
PosProps
.
Coupon_type
)].
toInt
();
QString
limitTime
=
couponOb
[
"expiration_date"
].
toString
();
double
disAmount
=
qRound
((
1
-
amount
)
*
canDisAmount
/
100
);
if
(
amount
<
1
)
// 折扣券
{
Coupon
c
(
desc
,
code
,
"discount"
,
disAmount
,
0
,
limitTime
,
false
);
c
.
setDiscountFactor
(
amount
*
10
);
QVariant
v
;
v
.
setValue
(
c
);
couponMap
[
code
]
=
v
;
}
else
{
Coupon
c
(
desc
,
code
,
QString
::
number
(
type
),
amount
,
0
,
limitTime
,
false
);
// double disAmount = qRound((1-amount)*canDisAmount/100);
// if(amount<1) // 折扣券
// {
// Coupon c(desc, code, "discount", disAmount , 0, limitTime, false);
// c.setDiscountFactor(amount*10);
// QVariant v;
// v.setValue(c);
// couponMap[code] = v;
// } else {
// Coupon c(desc, code, QString::number(type), amount, 0, limitTime, false);
// QVariant v;
// v.setValue(c);
// couponMap[code] = v;
// }
Coupon
c
(
desc
,
code
,
QString
::
number
(
type
),
amount
,
0
,
limitTime
,
true
);
QVariant
v
;
v
.
setValue
(
c
);
couponMap
[
code
]
=
v
;
}
}
session
()
->
addData
(
PosProps
.
CouponMap
,
couponMap
);
}
...
...
task/taskpay.cpp
View file @
ed18036b
This diff is collapsed.
Click to expand it.
task/taskpay.h
View file @
ed18036b
...
...
@@ -24,6 +24,7 @@ private slots:
private
:
TaskCouponThread
*
couponThread
;
int
payAmount
;
};
// 加载代金券的线程类
...
...
windows/forms/fmviporder.ui
View file @
ed18036b
...
...
@@ -7,7 +7,7 @@
<x>
0
</x>
<y>
0
</y>
<width>
786
</width>
<height>
62
4
</height>
<height>
62
6
</height>
</rect>
</property>
<property
name=
"maximumSize"
>
...
...
@@ -746,6 +746,12 @@
</property>
<item>
<widget
class=
"QLabel"
name=
"pay_max"
>
<property
name=
"minimumSize"
>
<size>
<width>
259
</width>
<height>
30
</height>
</size>
</property>
<property
name=
"text"
>
<string>
余额最多支付 0.00 元
</string>
</property>
...
...
@@ -799,8 +805,8 @@
</property>
<property
name=
"maximumSize"
>
<size>
<width>
0
</width>
<height>
0
</height>
<width>
283
</width>
<height>
47
</height>
</size>
</property>
<property
name=
"text"
>
...
...
@@ -813,10 +819,16 @@
</item>
<item>
<widget
class=
"QLabel"
name=
"score_label"
>
<property
name=
"minimumSize"
>
<size>
<width>
259
</width>
<height>
30
</height>
</size>
</property>
<property
name=
"maximumSize"
>
<size>
<width>
0
</width>
<height>
0
</height>
<width>
259
</width>
<height>
3
0
</height>
</size>
</property>
<property
name=
"text"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment