Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Z
zhichan
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
蒋勇
zhichan
Commits
8bbcd700
Commit
8bbcd700
authored
Jun 17, 2020
by
宋毅
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tj
parent
fad4d1b5
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
305 additions
and
29 deletions
+305
-29
brg-queue-center/app/base/api/impl/icAction/icQuery.js
+35
-0
brg-queue-center/app/base/api/impl/queueAction/producer.js
+2
-2
brg-queue-center/app/base/api/impl/uploadAction/txCos.js
+3
-3
brg-queue-center/app/base/service/impl/utilsSve/utilsIcSve.js
+142
-0
brg-queue-center/app/base/utils/esUtils.js
+24
-22
brg-queue-center/readme.txt
+99
-2
No files found.
brg-queue-center/app/base/api/impl/icAction/icQuery.js
0 → 100755
View file @
8bbcd700
var
APIBase
=
require
(
"../../api.base"
);
var
system
=
require
(
"../../../system"
);
class
IcQueryAPI
extends
APIBase
{
constructor
()
{
super
();
this
.
utilsIcSve
=
system
.
getObject
(
"service.utilsSve.utilsIcSve"
);
}
/**
* 接口跳转-POST请求
* actionType 执行的功能模块
* actionBody 执行的参数
*/
async
springBoard
(
pobj
,
qobj
,
req
)
{
if
(
!
pobj
.
actionType
)
{
return
system
.
getResult
(
null
,
"actionType参数不能为空"
);
}
var
result
=
await
this
.
opActionType
(
pobj
,
pobj
.
actionType
,
req
);
return
result
;
}
async
opActionType
(
pobj
,
actionType
,
req
)
{
var
opResult
=
null
;
switch
(
actionType
)
{
case
"getListByLikeCompanyName"
:
opResult
=
await
this
.
utilsIcSve
.
getListByLikeCompanyName
(
pobj
.
actionBody
);
break
;
default
:
opResult
=
system
.
getResult
(
null
,
"actionType参数错误"
);
break
;
}
return
opResult
;
}
}
module
.
exports
=
IcQueryAPI
;
\ No newline at end of file
brg-queue-center/app/base/api/impl/queueAction/producer.js
View file @
8bbcd700
...
@@ -9,8 +9,8 @@ class ProducerAPI extends APIBase {
...
@@ -9,8 +9,8 @@ class ProducerAPI extends APIBase {
}
}
/**
/**
* 接口跳转-POST请求
* 接口跳转-POST请求
* action
_t
ype 执行的功能模块
* action
T
ype 执行的功能模块
* action
_b
ody 执行的参数
* action
B
ody 执行的参数
*/
*/
async
springBoard
(
pobj
,
qobj
,
req
)
{
async
springBoard
(
pobj
,
qobj
,
req
)
{
if
(
!
pobj
.
actionType
)
{
if
(
!
pobj
.
actionType
)
{
...
...
brg-queue-center/app/base/api/impl/uploadAction/txCos.js
View file @
8bbcd700
var
APIBase
=
require
(
"../../api.base"
);
var
APIBase
=
require
(
"../../api.base"
);
var
system
=
require
(
"../../../system"
);
var
system
=
require
(
"../../../system"
);
class
Producer
API
extends
APIBase
{
class
TxCos
API
extends
APIBase
{
constructor
()
{
constructor
()
{
super
();
super
();
this
.
utilsTxCosSve
=
system
.
getObject
(
"service.utilsSve.utilsTxCosSve"
);
this
.
utilsTxCosSve
=
system
.
getObject
(
"service.utilsSve.utilsTxCosSve"
);
...
@@ -11,4 +11,4 @@ class ProducerAPI extends APIBase {
...
@@ -11,4 +11,4 @@ class ProducerAPI extends APIBase {
return
result
;
return
result
;
}
}
}
}
module
.
exports
=
ProducerAPI
;
module
.
exports
=
TxCosAPI
;
\ No newline at end of file
\ No newline at end of file
brg-queue-center/app/base/service/impl/utilsSve/utilsIcSve.js
0 → 100755
View file @
8bbcd700
const
system
=
require
(
"../../../system"
);
const
AppServiceBase
=
require
(
"../../app.base"
);
const
settings
=
require
(
"../../../../config/settings"
);
const
moment
=
require
(
'moment'
);
//用户权限操作
class
UtilsIcService
extends
AppServiceBase
{
constructor
()
{
super
();
this
.
esUtils
=
system
.
getObject
(
"util.esUtils"
);
}
/**
* 接口跳转-POST请求
* action_type 执行的类型
* action_body 执行的参数
*/
async
getListByLikeCompanyName
(
actionBody
)
{
if
(
!
actionBody
.
companyName
)
{
return
system
.
getResult
(
null
,
"查询的公司名称不能为空"
);
}
actionBody
.
companyName
=
await
this
.
getConvertSemiangleStr
(
actionBody
.
companyName
);
var
pageSize
=
!
actionBody
.
pageSize
?
15
:
Number
(
actionBody
.
pageSize
);
if
(
pageSize
<
0
)
{
pageSize
=
15
;
}
var
from
=
!
actionBody
.
currentPage
?
0
:
Number
((
actionBody
.
currentPage
-
1
)
*
pageSize
);
if
(
from
<
0
)
{
from
=
0
;
}
var
esIndexName
=
"tx_ic_bigdata_business_index/_search"
;
var
params
=
{
"query"
:
{
"bool"
:
{
"must"
:
[
{
"query_string"
:
{
"default_field"
:
"company_name"
,
"query"
:
'
\
"'
+
actionBody
.
companyName
+
'
\
"'
}
}
]
}
},
"from"
:
from
,
"size"
:
pageSize
,
"_source"
:
[
"company_name"
,
//公司名称
"company_org_type"
,
//公司类型
"credit_code"
,
//统一社会信用代码
"legal_person"
,
//法人姓名
"from_time"
,
//营业期限开始日期
"to_time"
,
//营业期限结束日期
"estiblish_time"
,
//成立时间
"reg_status"
,
//公司状态
"reg_number"
,
//注册号
"org_number"
,
//组织机构代码
"reg_location"
,
//公司地址
"reg_capital"
,
//注册资本
"business_scope"
,
//公司经营范围
"reg_institute"
,
//登记机关
"company_province"
,
//公司省份
"company_city"
,
//公司二级市
"company_cate_1"
,
//行业分类一级分类
"company_cate_2"
,
//行业分类二级分类
"company_cate_3"
//行业分类三级分类
]
// ,
// "sort": [
// {
// "reg_capital": "desc"
// }
// ]
}
var
resultData
=
null
;
try
{
resultData
=
await
this
.
esUtils
.
execPostEs
(
settings
.
queuedName
,
params
,
esIndexName
);
var
sources
=
[];
var
data
=
{
"totalCount"
:
resultData
.
data
.
hits
.
total
,
"pageSize"
:
pageSize
,
"currentPage"
:
actionBody
.
currentPage
-
1
,
"list"
:
sources
};
if
(
!
resultData
.
data
.
hits
)
{
return
system
.
getResultSuccess
();
}
if
(
!
resultData
.
data
.
hits
.
hits
)
{
return
system
.
getResultSuccess
();
}
resultData
.
data
.
hits
.
hits
.
forEach
(
function
(
c
)
{
if
(
c
.
_source
.
estibish_time
!=
null
)
{
var
time
=
new
Date
(
c
.
_source
.
estibish_time
*
1000
);
c
.
_source
.
estibish_time
=
time
.
toLocaleDateString
();
}
var
source
=
{
"companyName"
:
c
.
_source
.
company_name
,
//公司名称
"companyOrgType"
:
c
.
_source
.
company_org_type
||
""
,
//公司类型
"creditCode"
:
c
.
_source
.
credit_code
||
""
,
//统一社会信用代码
"legalPerson"
:
c
.
_source
.
legal_person
,
//法人姓名
"fromTime"
:
c
.
_source
.
from_time
?
moment
(
c
.
_source
.
from_time
*
1000
).
format
(
"YYYY-MM-DD"
)
:
""
,
//营业期限开始日期
"toTime"
:
c
.
_source
.
to_time
?
moment
(
c
.
_source
.
to_time
*
1000
).
format
(
"YYYY-MM-DD"
)
:
""
,
//营业期限结束日期
"estiblishTime"
:
c
.
_source
.
estiblish_time
?
moment
(
c
.
_source
.
estiblish_time
*
1000
).
format
(
"YYYY-MM-DD"
)
:
""
,
//成立时间
"regStatus"
:
c
.
_source
.
reg_status
||
""
,
//公司状态
"regNumber"
:
c
.
_source
.
reg_number
||
""
,
//注册号
"orgNumber"
:
c
.
_source
.
org_number
||
""
,
//组织机构代码
"regLocation"
:
c
.
_source
.
reg_location
||
""
,
//公司地址
"regCapital"
:
c
.
_source
.
reg_capital
||
""
,
//注册资本
"businessScope"
:
c
.
_source
.
business_scope
||
""
,
//公司经营范围
"regInstitute"
:
c
.
_source
.
reg_institute
||
""
,
//登记机关
"companyProvince"
:
c
.
_source
.
company_province
||
""
,
//公司省份
"companyCity"
:
c
.
_source
.
company_city
||
""
,
//公司二级市
"companyCate1"
:
c
.
_source
.
company_cate_1
||
""
,
//行业分类一级分类
"companyCate2"
:
c
.
_source
.
company_cate_2
||
""
,
//行业分类二级分类
"companyCate3"
:
c
.
_source
.
company_cate_3
||
""
//行业分类三级分类
};
sources
.
push
(
source
);
});
// j.hits.hits = data;
return
system
.
getResultSuccess
(
data
);
}
catch
(
e
)
{
return
{
status
:
-
1
,
msg
:
"操作失败"
,
data
:
null
};
}
}
async
getConvertSemiangleStr
(
str
)
{
var
result
=
""
;
str
=
str
.
replace
(
/
\s
+/g
,
""
);
var
len
=
str
.
length
;
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
var
cCode
=
str
.
charCodeAt
(
i
);
//全角与半角相差(除空格外):65248(十进制)
cCode
=
(
cCode
>=
0xFF01
&&
cCode
<=
0xFF5E
)
?
(
cCode
-
65248
)
:
cCode
;
//处理空格
cCode
=
(
cCode
==
0x03000
)
?
0x0020
:
cCode
;
result
+=
String
.
fromCharCode
(
cCode
);
}
return
result
;
}
}
module
.
exports
=
UtilsIcService
;
brg-queue-center/app/base/utils/esUtils.js
View file @
8bbcd700
...
@@ -15,21 +15,8 @@ class EsUtils {
...
@@ -15,21 +15,8 @@ class EsUtils {
* @param {*} actionBody 日志信息
* @param {*} actionBody 日志信息
*/
*/
async
addEsLogs
(
queuedName
,
actionBody
)
{
async
addEsLogs
(
queuedName
,
actionBody
)
{
var
configInfoResult
=
await
this
.
configInfoDao
.
getList
();
var
esIndexName
=
queuedName
+
(
actionBody
.
identifyCode
?
"-"
+
actionBody
.
identifyCode
:
""
);
if
(
configInfoResult
.
status
!=
1
)
{
esIndexName
=
esIndexName
.
toLocaleLowerCase
()
+
"/_doc?pretty"
;
this
.
errorLogDao
.
addOpErrorLogs
(
"publicLogsConsumer,configInfo list is empty"
,
actionBody
,
null
,
null
,
1
);
return
system
.
getResultSuccess
();
}
var
publicLogsEsName
=
configInfoResult
.
data
.
filter
(
f
=>
f
.
c_key
===
"publicLogsEsName"
);
var
publicLogsEsPwd
=
configInfoResult
.
data
.
filter
(
f
=>
f
.
c_key
===
"publicLogsEsPwd"
);
var
publicLogsEsReqUrl
=
configInfoResult
.
data
.
filter
(
f
=>
f
.
c_key
===
"publicLogsEsReqUrl"
);
if
(
!
publicLogsEsName
||
!
publicLogsEsPwd
||
!
publicLogsEsReqUrl
)
{
this
.
errorLogDao
.
addOpErrorLogs
(
"publicLogsConsumer,es account info is empty"
,
actionBody
,
null
,
null
,
1
);
return
system
.
getResultSuccess
();
}
var
esIndexName
=
queuedName
+
"-"
+
actionBody
.
identifyCode
||
""
;
var
reqUrl
=
publicLogsEsReqUrl
[
0
].
c_value
+
esIndexName
.
toLocaleLowerCase
()
+
"/_doc?pretty"
;
actionBody
.
resultInfo
=
typeof
actionBody
.
resultInfo
===
'object'
?
JSON
.
stringify
(
actionBody
.
resultInfo
)
:
actionBody
.
resultInfo
;
actionBody
.
resultInfo
=
typeof
actionBody
.
resultInfo
===
'object'
?
JSON
.
stringify
(
actionBody
.
resultInfo
)
:
actionBody
.
resultInfo
;
actionBody
.
errorInfo
=
typeof
actionBody
.
errorInfo
===
'object'
?
JSON
.
stringify
(
actionBody
.
errorInfo
)
:
actionBody
.
errorInfo
;
actionBody
.
errorInfo
=
typeof
actionBody
.
errorInfo
===
'object'
?
JSON
.
stringify
(
actionBody
.
errorInfo
)
:
actionBody
.
errorInfo
;
var
params
=
{
var
params
=
{
...
@@ -40,17 +27,32 @@ class EsUtils {
...
@@ -40,17 +27,32 @@ class EsUtils {
errorInfo
:
actionBody
.
errorInfo
||
""
,
errorInfo
:
actionBody
.
errorInfo
||
""
,
requestId
:
actionBody
.
requestId
requestId
:
actionBody
.
requestId
}
}
var
execResult
=
await
this
.
execPostEs
(
queuedName
,
params
,
reqUrl
,
publicLogsEsName
[
0
].
c_value
,
publicLogsEsPwd
[
0
].
c_valu
e
);
var
execResult
=
await
this
.
execPostEs
(
queuedName
,
params
,
esIndexNam
e
);
return
execResult
;
return
execResult
;
}
}
/**
/**
* post日志到Es
* post日志到Es
* @param {*} queuedName 队列名称
* @param {*} params 参数
* @param {*} params 参数
* @param {*}
url 地址
* @param {*}
esIndexName es索引名称
*/
*/
async
execPostEs
(
queuedName
,
params
,
reqUrl
,
esName
,
esPwd
)
{
async
execPostEs
(
queuedName
,
params
,
esIndexName
)
{
try
{
try
{
var
configInfoResult
=
await
this
.
configInfoDao
.
getList
();
if
(
configInfoResult
.
status
!=
1
)
{
this
.
errorLogDao
.
addOpErrorLogs
(
"publicLogsConsumer,configInfo list is empty"
,
actionBody
,
null
,
null
,
1
);
return
system
.
getResultSuccess
();
}
var
publicLogsEsName
=
configInfoResult
.
data
.
filter
(
f
=>
f
.
c_key
===
"publicLogsEsName"
);
var
publicLogsEsPwd
=
configInfoResult
.
data
.
filter
(
f
=>
f
.
c_key
===
"publicLogsEsPwd"
);
var
publicLogsEsReqUrl
=
configInfoResult
.
data
.
filter
(
f
=>
f
.
c_key
===
"publicLogsEsReqUrl"
);
if
(
!
publicLogsEsName
||
!
publicLogsEsPwd
||
!
publicLogsEsReqUrl
)
{
this
.
errorLogDao
.
addOpErrorLogs
(
"publicLogsConsumer,es account info is empty"
,
actionBody
,
null
,
null
,
1
);
return
system
.
getResultSuccess
();
}
var
reqUrl
=
publicLogsEsReqUrl
[
0
].
c_value
+
esIndexName
if
(
settings
.
env
===
"dev"
)
{
if
(
settings
.
env
===
"dev"
)
{
let
result
=
await
axios
({
let
result
=
await
axios
({
// headers: {'Content-Type': 'application/x-www-form-urlencoded'},
// headers: {'Content-Type': 'application/x-www-form-urlencoded'},
...
@@ -70,18 +72,18 @@ class EsUtils {
...
@@ -70,18 +72,18 @@ class EsUtils {
return
system
.
getResult
(
null
,
"执行execPostEs存在错误"
);
return
system
.
getResult
(
null
,
"执行execPostEs存在错误"
);
}
}
//方式二
//方式二
var
result
=
await
this
.
execClient
.
execPostEs
(
params
,
reqUrl
,
esName
,
esPwd
);
var
result
=
await
this
.
execClient
.
execPostEs
(
params
,
reqUrl
,
publicLogsEsName
[
0
].
c_value
,
publicLogsEsPwd
[
0
].
c_value
);
if
(
!
result
||
!
result
.
stdout
)
{
if
(
!
result
||
!
result
.
stdout
)
{
this
.
errorLogDao
.
addOpErrorLogs
(
queuedName
+
"执行execPostEs存在错误"
,
params
,
result
,
null
,
3
);
this
.
errorLogDao
.
addOpErrorLogs
(
queuedName
+
"执行execPostEs存在错误"
,
params
,
result
,
null
,
3
);
return
system
.
getResult
(
null
,
"执行execPostEs存在错误"
);
return
system
.
getResult
(
null
,
"执行execPostEs存在错误"
);
return
system
.
getResult
(
null
,
"execPostTimeOut data is empty"
);
return
system
.
getResult
(
null
,
"execPostTimeOut data is empty"
);
}
}
var
stdoutInfo
=
JSON
.
parse
(
result
.
stdout
);
var
stdoutInfo
=
JSON
.
parse
(
result
.
stdout
);
if
(
stdoutInfo
.
error
)
{
if
(
stdoutInfo
.
error
)
{
this
.
errorLogDao
.
addOpErrorLogs
(
queuedName
+
"执行execPostEs存在错误"
,
params
,
result
,
null
,
3
);
this
.
errorLogDao
.
addOpErrorLogs
(
queuedName
+
"执行execPostEs存在错误"
,
params
,
result
,
null
,
3
);
return
system
.
getResult
(
null
,
"执行execPostEs存在错误"
);
return
system
.
getResult
(
null
,
"执行execPostEs存在错误"
);
}
}
return
system
.
getResultSuccess
();
return
system
.
getResultSuccess
(
stdoutInfo
);
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
log
(
error
.
stack
,
"......execPostEs....error....."
);
console
.
log
(
error
.
stack
,
"......execPostEs....error....."
);
this
.
errorLogDao
.
addOpErrorLogs
(
queuedName
+
"执行execPostEs存在异常"
,
params
,
null
,
error
.
stack
,
3
);
this
.
errorLogDao
.
addOpErrorLogs
(
queuedName
+
"执行execPostEs存在异常"
,
params
,
null
,
error
.
stack
,
3
);
...
...
brg-queue-center/readme.txt
View file @
8bbcd700
...
@@ -91,4 +91,101 @@
...
@@ -91,4 +91,101 @@
"resultInfo":"",//返回信息
"resultInfo":"",//返回信息
"errorInfo": ""//错误信息
"errorInfo": ""//错误信息
}
}
}
}
\ No newline at end of file
返回参数:
{
status: 1, //1为成功,否则为失败
msg: "测试成功",
data: null
}
三.业务查询接口
1.tx cos 信息获取
地址:http://60.205.209.94:4018/api/uploadAction/txCos/getCosInfo
请求方式:get
参数:无
返回参数:
{
"status": 1,//1成功,否则失败
"message": "success",
"data": {
"expiredTime": 1592400959,
"expiration": "2020-06-17T13:35:59Z",
"credentials": {
"sessionToken": "PoKzACX299C52uF2ZEm9DvHR5KKRIH2i6702448bfee8f3dacbb2be6d3cfd6904MsCx-g2RTRyhKe7FxRhpfffuUqHPV8paOomljLr5zKBMH8EYunXiAaOghJTuZCzZwYGrJqZ8lmJFg3HBnTvRHSh3WImZ5D8Itylq9JQM7C5Ia2rxw9r3gkPLWrxWeUvovAwXqOCpzXl8eZEsdtPJJUb086uyKnjKwQ6rV61Tu7wl1MKUne4TDl1QJrL-uiB7otDZze4SYY6pZWkJByjCyKaLE6K-Xtky01pS8vAxR9vbKjyVan6fM_us8eoEjp_lrPeiCXOBBbo26FmSFvBoPMDBFYLv_0I4A0g4t0B0mrzHE8AtCu8tXt3sQ-iw7kgfCQ2XfZonNsqO8g-KXrEGEKpZDqDGSvIHYvHPboHp2ZfcKohi12vLcQ0e5zmysqCmq-NViRXLoZRcIP_Nx2orQkDHV2UZtEDRbPdCe1fakqtbIOMSoDh8z3308pf-hl-rr1w_5JNrn_aO-ieNMNYSGO7U3R51whungjZCvJkXIVtE6kbd224l4GHq-Ozcgw2V",
"tmpSecretId": "AKIDEnTeKjjfFtycc7cxYUEJcNIA4PsrAe270UcAoEq2qDd3j2g6RnUVh7rciY4mSR_M",
"tmpSecretKey": "Z7qbmpzQRvIxv0bmIji3eH7HrGgONDe+USpqy/zuGUs=",
"tmpBucket": "test-1258715722",
"tmpRegion": "ap-beijing"
},
"requestId": "0e672c45-dc70-437d-93f5-cf2091487d38",
"startTime": 1592399159
},
"requestId": "SCZ202006172105Wz6yF"
}
2.企业模糊查询信息
地址:http://60.205.209.94:4018/api/icAction/icQuery/springBoard
请求方式:get
参数:
{
"actionType":"getListByLikeCompanyName",
"actionBody":{
"companyName":"玉实业有限公司"
}
}
返回参数:
{
"status": 1,
"message": "success",
"data": {
"totalCount": 3,
"pageSize": 15,
"currentPage": null,
"list": [
{
"companyName": "上海汉玉实业有限公司",
"companyOrgType": "有限责任公司",
"creditCode": null,
"legalPerson": "曹雪静",
"fromTime": "2008-03-20",
"toTime": "2018-03-19",
"estiblishTime": "2008-03-20",
"regStatus": "注销",
"regNumber": "310228001075786",
"orgNumber": " ",
"regLocation": "上海市金山区卫昌路229号2幢220室",
"regCapital": "3.000",
"businessScope": "化妆品,日用百货,服装鞋帽,健身器材销售,投资咨询、商务咨询(除经纪)(涉及行政许可的凭许可证经营)。",
"regInstitute": "金山区市场监管局",
"companyProvince": "上海",
"companyCity": "金山区",
"companyCate1": "批发和零售业",
"companyCate2": "批发业",
"companyCate3": "纺织、服装及家庭用品批发"
}
]
},
"requestId": "SCZ202006172233xV7el"
}
参数说明:
"companyName": "上海汉玉实业有限公司",//公司名称
"companyOrgType": "有限责任公司",//公司类型
"creditCode": "",//统一社会信用代码
"legalPerson": "曹雪静",//法人姓名
"fromTime": "2008-03-20",//营业期限开始日期
"toTime": "2018-03-19",//营业期限结束日期
"estiblishTime": "2008-03-20",//成立时间
"regStatus": "注销",//公司状态
"regNumber": "310228001075786",//注册号
"orgNumber": " ",//组织机构代码
"regLocation": "上海市金山区卫昌路229号2幢220室",//公司地址
"regCapital": "3.000",//注册资本
"businessScope": "化妆品,日用百货,服装鞋帽,健身器材销售,投资咨询、商务咨询(除经纪)(涉及行政许可的凭许可证经营)。",//公司经营范围
"regInstitute": "金山区市场监管局",//登记机关
"companyProvince": "上海",//公司省份
"companyCity": "金山区",//公司二级市
"companyCate1": "批发和零售业",//行业分类一级分类
"companyCate2": "批发业",//行业分类二级分类
"companyCate3": "纺织、服装及家庭用品批发"//行业分类三级分类
\ No newline at end of file
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