Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Kunto
/
backoffice
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit f4ce41d3
authored
Jan 29, 2020
by
musthofads
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
history transaksi
1 parent
8692bacf
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
578 additions
and
1 deletions
src/agratek/api/merchant/scripts/data/routes.csv
src/agratek/api/merchant/views/history_transaksi.py
src/agratek/api/merchant/views/templates/base.pt
src/agratek/api/merchant/views/templates/history_transaksi/list.pt
src/agratek/api/merchant/views/templates/history_transaksi/view.pt
src/agratek/api/merchant/scripts/data/routes.csv
View file @
f4ce41d
...
...
@@ -92,4 +92,8 @@ pay-form,/pay/{pay_token},Metode Pembayaran,1,0
pay-info,/pay_info/{pay_token}/{state}/,Informasi Pembayaran,1,0
pay-request,/pay_request,Pembayaran,1,0
pay-request-resp,/pay_request_resp,Respon Request Pembayaran,1,0
tangkap-response,/tangkap_response,tes_dong,1,0
\ No newline at end of file
tangkap-response,/tangkap_response,tes_dong,1,0
history-transaksi-list,/history/transaksi/list,List History Transaksi,1,0
history-transaksi-act,/history/transaksi/{act}/act,Act History Transaksi,1,0
history-transaksi-view,/history/transaksi/{id}/view,View History Transaksi,1,0
\ No newline at end of file
src/agratek/api/merchant/views/history_transaksi.py
0 → 100644
View file @
f4ce41d
import
colander
from
datatables
import
ColumnDT
from
deform
import
widget
,
Form
,
ValidationFailure
from
opensipkd.base.views
import
DataTables
from
opensipkd.base.tools.report
import
csv_response
from
pyramid.httpexceptions
import
HTTPFound
from
pyramid.view
import
view_config
from
sqlalchemy
import
case
from
sqlalchemy.orm
import
aliased
from
.
import
BaseView
from
..models
import
(
DBSession
,
H2hArInvoice
,
H2hArInvoiceDet
,
Partner
,
Produk
)
from
opensipkd.base.tools
import
format_json
from
datetime
import
datetime
from
sqlalchemy
import
cast
,
Time
,
String
,
func
,
Date
status_purchase
=
(
(
9999
,
'--Semua--'
),
(
0
,
'Pending'
),
(
1
,
'Sukses'
),
(
2
,
'Batal'
),
)
# invoice_type = (
# (0, '--Semua--'),
# (1, 'Payment'),
# (2, 'Register'),
# )
def
query_csv
(
request
,
status
):
vendor
=
aliased
(
Partner
,
name
=
'vendor'
)
customer
=
aliased
(
Partner
,
name
=
'customer'
)
query
=
DBSession
.
query
(
H2hArInvoice
.
cust_inv_no
.
label
(
'Nomor_Invoice'
),
H2hArInvoice
.
created
.
label
(
'Tanggal'
),
H2hArInvoiceDet
.
id_pel
.
label
(
'ID.Pel'
),
customer
.
nama
.
label
(
'Nama_Customer'
),
vendor
.
nama
.
label
(
'Nama_Vendor'
),
Produk
.
nama
.
label
(
'Nama_Produk'
),
H2hArInvoiceDet
.
amt_buy
.
label
(
'Harga_Beli'
),
H2hArInvoiceDet
.
amt_sell
.
label
(
'Harga_Jual'
),
case
(
[
(
H2hArInvoiceDet
.
status
<=
0
,
0
)
],
else_
=
H2hArInvoiceDet
.
status
)
.
label
(
'Status'
)
)
.
\
join
(
H2hArInvoiceDet
,
H2hArInvoiceDet
.
ar_invoice_id
==
H2hArInvoice
.
id
)
\
.
join
(
customer
,
customer
.
id
==
H2hArInvoice
.
customer_id
)
\
.
join
(
vendor
,
vendor
.
id
==
H2hArInvoiceDet
.
vendor_id
)
\
.
join
(
Produk
,
Produk
.
id
==
H2hArInvoiceDet
.
produk_id
)
if
status
!=
9999
:
if
status
<=
0
:
query
=
query
.
filter
(
H2hArInvoiceDet
.
status
<=
status
)
else
:
query
=
query
.
filter
(
H2hArInvoiceDet
.
status
==
status
)
filter_tanggal
(
request
,
query
,
H2hArInvoice
.
created
)
return
query
def
form_validator
(
form
,
value
):
pass
class
ViewData
(
BaseView
):
@view_config
(
route_name
=
'history-transaksi-list'
,
permission
=
"history-transaksi-list"
,
renderer
=
'templates/history_transaksi/list.pt'
)
def
view_list
(
self
):
class
ToolbarSchema
(
colander
.
Schema
):
# inv_type = colander.SchemaNode(
# colander.Integer(),
# default=1,
# oid="inv_type",
# widget=widget.SelectWidget(values=invoice_type, css_class='form-toolbar'),
# title="Jenis"
# )
status
=
colander
.
SchemaNode
(
colander
.
String
(),
oid
=
"status"
,
widget
=
widget
.
SelectWidget
(
values
=
status_purchase
,
css_class
=
'form-toolbar'
),
title
=
"Status"
)
awal
=
colander
.
SchemaNode
(
colander
.
String
(),
oid
=
"awal"
,
title
=
"Tgl."
)
akhir
=
colander
.
SchemaNode
(
colander
.
String
(),
oid
=
"akhir"
,
title
=
"-"
)
toolbar
=
ToolbarSchema
(
Validator
=
form_validator
)
toolbar
.
request
=
self
.
req
form
=
Form
(
schema
=
toolbar
)
params
=
{
'form'
:
form
,
# 'invoice_type': [k and s or '-' for k, s in invoice_type],
'status_purchase'
:
[
s
for
k
,
s
in
status_purchase
if
k
!=
9999
],
'columns'
:
[
dict
(
title
=
"ID"
),
dict
(
title
=
"No.Invoice"
),
dict
(
title
=
"Tanggal"
),
dict
(
title
=
"ID.Pel"
),
dict
(
title
=
"Produk"
),
dict
(
title
=
"Harga"
),
dict
(
title
=
"Status"
),
],
'column_data'
:
[
dict
(
data
=
"id"
,
width
=
"0px"
),
dict
(
data
=
"nomor"
,
width
=
"150px"
),
dict
(
data
=
"created"
),
dict
(
data
=
"id_pel"
,
width
=
"150px"
),
dict
(
data
=
"produk"
),
dict
(
data
=
"harga"
,
width
=
"100px"
),
dict
(
data
=
"status"
,
width
=
"100px"
),
],
'buttons'
:
[
# dict(id="btn_view", cls="btn btn btn-primary", title="View"),
dict
(
id
=
"btn_close"
,
cls
=
"btn btn-danger"
,
title
=
"Tutup"
),
# dict(id="btn_csv", cls="btn btn-primary", title="CSV"),
],
'route'
:
"/api/purchase"
,
'scripts'
:
"""
$("#btn_close").click(function() {
window.location = '/api/merchant';
return false;
});
"""
}
return
dict
(
params
=
params
)
@view_config
(
route_name
=
'history-transaksi-act'
,
renderer
=
'json'
,
permission
=
"history-transaksi-list"
)
def
view_act
(
self
):
request
=
self
.
req
url_dict
=
request
.
matchdict
act
=
url_dict
[
'act'
]
def
filter_tanggal
(
request
,
query
,
field
):
awal
=
request
.
session
[
'awal'
]
+
' 00:00:00'
#None
akhir
=
request
.
session
[
'akhir'
]
+
' 23:59:59'
#None
if
awal
and
akhir
:
tglawal
=
datetime
.
strptime
(
awal
,
'
%
d-
%
m-
%
Y
%
H:
%
M:
%
S'
)
tglakhir
=
datetime
.
strptime
(
akhir
,
'
%
d-
%
m-
%
Y
%
H:
%
M:
%
S'
)
query
=
query
.
filter
(
field
.
between
(
tglawal
,
tglakhir
))
return
query
if
act
==
"grid"
:
# jenis = 'jenis' in request.params and request.params['jenis'] and int(request.params['jenis']) or None
status
=
9999
if
'status'
in
request
.
params
:
status
=
int
(
request
.
params
[
'status'
])
vendor
=
aliased
(
Partner
,
name
=
'vendor'
)
customer
=
aliased
(
Partner
,
name
=
'customer'
)
columns
=
[
ColumnDT
(
H2hArInvoiceDet
.
id
,
mData
=
'id'
),
ColumnDT
(
H2hArInvoice
.
cust_inv_no
,
mData
=
'nomor'
),
# ColumnDT(func.concat_ws(' ', func.to_char(cast(H2hArInvoice.created, Date), ), func.left(cast(cast(H2hArInvoice.created, Time), String), 5)), mData = 'created'),
ColumnDT
(
func
.
to_char
(
H2hArInvoice
.
created
,
'dd-mm-yyyy HH24:MI'
),
mData
=
'created'
),
ColumnDT
(
H2hArInvoiceDet
.
id_pel
,
mData
=
'id_pel'
),
ColumnDT
(
customer
.
nama
,
mData
=
'customer'
),
ColumnDT
(
vendor
.
nama
,
mData
=
'vendor'
),
ColumnDT
(
Produk
.
nama
,
mData
=
'produk'
),
ColumnDT
(
H2hArInvoiceDet
.
amt_buy
,
mData
=
'harga_beli'
),
ColumnDT
(
H2hArInvoiceDet
.
amt_sell
,
mData
=
'harga'
),
ColumnDT
(
case
(
[
(
H2hArInvoiceDet
.
status
<=
0
,
0
)
],
else_
=
H2hArInvoiceDet
.
status
),
mData
=
'status'
),
]
query
=
DBSession
.
query
()
.
select_from
(
H2hArInvoice
)
\
.
join
(
H2hArInvoiceDet
,
H2hArInvoiceDet
.
ar_invoice_id
==
H2hArInvoice
.
id
)
\
.
join
(
customer
,
customer
.
id
==
H2hArInvoice
.
customer_id
)
\
.
join
(
vendor
,
vendor
.
id
==
H2hArInvoiceDet
.
vendor_id
)
\
.
join
(
Produk
,
Produk
.
id
==
H2hArInvoiceDet
.
produk_id
)
# query = query.filter(H2hArInvoice.cust_inv_type == jenis)
if
status
!=
9999
:
if
status
<=
0
:
query
=
query
.
filter
(
H2hArInvoiceDet
.
status
<=
status
)
else
:
query
=
query
.
filter
(
H2hArInvoiceDet
.
status
==
status
)
query
=
filter_tanggal
(
request
,
query
,
H2hArInvoice
.
created
)
row_table
=
DataTables
(
request
.
GET
,
query
,
columns
)
return
row_table
.
output_result
()
elif
act
==
"csv"
:
status
=
9999
if
'status'
in
request
.
params
:
status
=
int
(
request
.
params
[
'status'
])
query
=
query_csv
(
request
,
status
)
row
=
query
.
first
()
if
row
==
None
:
header
=
[
'Nomor_Invoice'
,
'Tanggal'
,
'ID.Pel'
,
'Nama_Customer'
,
'Nama_Produk'
,
'Harga_Beli'
,
'Harga_Jual'
,
'Status'
]
else
:
header
=
row
.
keys
()
rows
=
[]
for
item
in
query
.
all
():
rows
.
append
(
list
(
item
))
filename
=
'list_purchase.csv'
value
=
{
'header'
:
header
,
'rows'
:
rows
,
}
return
csv_response
(
request
,
value
,
filename
)
@view_config
(
route_name
=
'history-transaksi-view'
,
permission
=
"history-transaksi-list"
,
renderer
=
'templates/history_transaksi/view.pt'
)
def
view_detail
(
self
):
request
=
self
.
req
url_dict
=
request
.
matchdict
view_id
=
url_dict
[
'id'
]
data
=
H2hArInvoiceDet
.
query_id
(
id
=
view_id
)
.
first
()
params
=
dict
(
form
=
None
)
if
data
:
invoice
=
data
.
h2h_ar_invoice
customer
=
invoice
.
customer
produk
=
data
.
produk
form_list
=
(
(
'invoice_no'
,
invoice
.
cust_inv_no
or
''
,
'text'
),
(
'customer'
,
customer
.
nama
,
'text'
),
(
'vendor'
,
data
.
vendor
.
nama
,
'text'
),
(
'denom'
,
produk
.
kode
,
'text'
),
(
'produk'
,
produk
.
nama
,
'text'
),
(
'id_pel'
,
data
.
id_pel
,
'text'
),
(
'harga'
,
data
.
amt_sell
or
0
,
'text'
),
(
'inquiry'
,
format_json
(
data
.
inquiry
),
'textarea'
),
(
'purchase'
,
format_json
(
data
.
payment
),
'textarea'
),
(
'advice'
,
format_json
(
data
.
advice
),
'textarea'
),
(
'notify'
,
format_json
(
data
.
notify
),
'textarea'
),
)
sm
=
colander
.
Schema
()
values
=
{}
for
f
in
form_list
:
k
=
f
[
0
]
v
=
f
[
1
]
wg
=
f
[
2
]
==
'textarea'
and
widget
.
TextAreaWidget
(
rows
=
5
,
css_class
=
"readonly"
)
or
\
widget
.
TextInputWidget
(
readonly
=
True
)
sm
.
add
(
colander
.
SchemaNode
(
colander
.
String
(),
name
=
k
,
oid
=
k
,
widget
=
wg
))
values
.
update
({
k
:
v
})
form
=
Form
(
sm
)
form
.
render
(
values
)
params
[
'form'
]
=
form
return
dict
(
params
=
params
)
src/agratek/api/merchant/views/templates/base.pt
View file @
f4ce41d
...
...
@@ -67,5 +67,11 @@
</a>
</li>
<li>
<a
href=
"${request._host}/history/transaksi/list"
>
<i
class=
"fa fa-lg fa-fw fa-list"
></i>
<span
class=
"menu-item-parent"
>
History Transaksi
</span>
</a>
</li>
</ul>
</html>
src/agratek/api/merchant/views/templates/history_transaksi/list.pt
0 → 100644
View file @
f4ce41d
<html>
<div
metal:use-macro=
"load: ../base.pt"
>
<!-- content -->
<div
metal:fill-slot=
"content"
>
<style
type=
"text/css"
>
#content-payment-view
{
height
:
100%
;
overflow-y
:
auto
;
}
</style>
<div
id=
"tmp-toolbar"
style=
"display: inline-block;"
>
<span
tal:repeat=
"f params.form"
tal:omit-tag=
""
>
<label
for=
"${f.oid}"
class=
"control-label"
>
${f.title}
</label>
${structure:f.serialize()}
</span>
</div>
<div
class=
"jarviswidget"
style=
"border-top:1px solid #ccc!important"
>
<div
role=
"content"
>
<table
id=
"table1"
class=
"table table-bordered table-hover table-condensed nowrap"
>
<thead>
<tr>
<th
tal:repeat=
"f params.columns"
>
${f.title}
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<!-- Modal -->
<div
id=
"payment-view"
class=
"modal fade"
role=
"dialog"
>
<div
class=
"modal-dialog modal-lg"
>
<!-- Modal content-->
<div
class=
"modal-content"
>
<div
class=
"modal-header"
>
<button
type=
"button"
class=
"close"
data-dismiss=
"modal"
>
×
</button>
<h4
class=
"modal-title"
>
View Detail
<span
style=
"margin-left: 10px"
id=
"payment-view-title"
></span>
</h4>
</div>
<div
class=
"modal-body"
id=
"content-payment-view"
>
&nbps;
</div>
<div
class=
"modal-footer"
>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
OK
</button>
</div>
</div>
</div>
</div>
</div>
<!-- end content -->
<script
type=
"text/javascript"
metal:fill-slot=
"scripts"
>
var
mID
;
var
oTable
;
var
oTableUri
=
"${request._host}${params.route}"
var
oTableUrl
=
oTableUri
+
"/grid/act"
;
function
getDataUrl
()
{
var
opt
=
$
(
'select#status'
).
val
();
var
param
=
''
;
var
awalControl
=
$
(
'#awal'
);
var
akhirControl
=
$
(
'#akhir'
);
var
awal
=
awalControl
.
val
();
var
akhir
=
akhirControl
.
val
();
var
tgl
=
new
Date
();
var
tgl_indo
=
tgl
.
getDate
()
+
'-'
+
(
tgl
.
getMonth
()
+
1
)
+
'-'
+
tgl
.
getFullYear
();
if
(
awal
==
''
||
awal
==
undefined
){
awalControl
.
val
(
tgl_indo
)
}
if
(
akhir
==
''
||
akhir
==
undefined
){
akhirControl
.
val
(
tgl_indo
)
}
if
(
awal
!=
''
&&
awal
!=
undefined
)
{
param
+=
'&awal='
+
awal
;
}
if
(
akhir
!=
''
&&
akhir
!=
undefined
)
{
param
+=
'&akhir='
+
akhir
;
}
return
oTableUrl
+
'?status='
+
opt
.
toString
()
+
param
;
}
function
getViewUrl
(
vid
)
{
return
oTableUri
+
"/"
+
vid
.
toString
()
+
"/view"
;
}
$
(
document
).
ready
(
function
()
{
oTable
=
$
(
'#table1'
).
DataTable
({
dom
:
'<"row"<"col-md-8"<"toolbar">l><"col-md-4"f>>rtip'
,
processing
:
true
,
serverSide
:
true
,
ajax
:
getDataUrl
(),
stateSave
:
true
,
//scrollCollapse: true,
//sort: true,
//info: false,
scrollX
:
true
,
filter
:
true
,
autoWidth
:
false
,
paginate
:
true
,
paginationType
:
"full_numbers"
,
lengthMenu
:
[
[
10
,
25
,
50
,
100
],
[
10
,
25
,
50
,
100
]
],
columns
:
[
{
'data'
:
'id'
,
'width'
:
'0px'
},
{
'data'
:
'nomor'
,
'width'
:
'150px'
},
{
'data'
:
'created'
,
'width'
:
'60px'
},
{
'data'
:
'id_pel'
,
'width'
:
'150px'
},
{
'data'
:
'customer'
,
'width'
:
'80px'
},
{
'data'
:
'vendor'
,
'width'
:
'80px'
},
{
'data'
:
'produk'
,
'width'
:
'150px'
},
{
'data'
:
'harga_beli'
,
'width'
:
'70px'
},
{
'data'
:
'harga'
,
'width'
:
'70px'
},
{
'data'
:
'status'
,
'width'
:
'70px'
,
'render'
:
function
(
data
,
type
,
full
,
meta
)
{
var
st
=
$
{
params
.
status_purchase
};
return
st
[
data
];
}
}
],
//columns: ${params.column_data},
columnDefs
:
[{
searchable
:
false
,
visible
:
false
,
targets
:
[
0
]
}],
"language"
:
{
"search"
:
"Cari : "
,
"paginate"
:
{
"first"
:
"Pertama "
,
"last"
:
"Akhir "
,
"previous"
:
""
,
"next"
:
""
,
},
"lengthMenu"
:
"Tampil _MENU_ baris "
},
});
var
buttons
=
$
{
params
.
buttons
};
var
tb_array
=
[];
tb_array
.
push
(
'<div class="btn-group pull-left">'
);
for
(
i
=
0
;
i
<
buttons
.
length
;
i
++
){
tb_array
.
push
(
'<button id="'
+
buttons
[
i
].
id
+
'" class="'
+
buttons
[
i
].
cls
+
'" type="button">'
+
buttons
[
i
].
title
+
'</button>'
)
}
tb_array
.
push
(
' '
);
tb_array
.
push
(
'</div>'
);
var
tb
=
tb_array
.
join
(
' '
);
$
(
"div.toolbar"
).
html
(
tb
)
.
attr
(
'style'
,
'display:block; float: left; margin-bottom:6px; line-height:16px;'
);
$
(
'#tmp-toolbar'
).
appendTo
(
$
(
"div.toolbar"
));
//events
$
(
'#table1 tbody'
).
on
(
'click'
,
'tr'
,
function
()
{
if
(
$
(
this
).
hasClass
(
'selected'
))
{
$
(
this
).
removeClass
(
'selected'
);
}
else
{
var
aData
=
oTable
.
row
(
this
).
data
();
oTable
.
$
(
'tr.selected'
).
removeClass
(
'selected'
);
$
(
this
).
addClass
(
'selected'
);
mID
=
aData
.
id
;
// console.log(mID);
oTable
.
$
(
'tr.row_selected'
).
removeClass
(
'row_selected'
);
$
(
this
).
addClass
(
'row_selected'
);
}
});
$
{
params
.
scripts
}
$
(
'#btn_view'
).
click
(
function
()
{
if
(
mID
)
{
$
(
'#payment-view'
).
modal
(
'show'
);
}
else
{
$
.
SmartMessageBox
({
title
:
"View"
,
content
:
"Pilih Baris yang akan di lihat..."
,
buttons
:
'[Oke]'
});
}
});
$
(
"#payment-view"
).
on
(
'show.bs.modal'
,
function
(){
var
content
=
''
;
var
view_container
=
$
(
'#content-payment-view'
);
view_container
.
empty
();
if
(
mID
)
{
var
vUrl
=
getViewUrl
(
mID
);
view_container
.
load
(
vUrl
,
function
()
{
$
(
'.readonly'
).
attr
(
'readonly'
,
true
);
});
}
});
$
(
'select#status'
).
on
(
'change'
,
function
()
{
mID
=
0
;
oTable
.
ajax
.
url
(
getDataUrl
()).
load
();
});
$
(
'#awal,#akhir'
).
datepicker
({
format
:
'dd-mm-yyyy'
,
autoclose
:
true
});
$
(
'#awal,#akhir'
).
on
(
'changeDate'
,
function
(
e
)
{
oTable
.
ajax
.
url
(
getDataUrl
()).
load
();
});
$
(
'#awal, #akhir'
).
css
(
'width'
,
'98px'
);
var
el
=
$
(
'#table1_length'
).
parent
();
el
.
addClass
(
'col-md-9'
);
el
.
removeClass
(
'col-md-8'
);
var
el
=
$
(
'#table1_filter'
).
parent
();
el
.
addClass
(
'col-md-3'
);
el
.
removeClass
(
'col-md-4'
);
function
getCSV_url
(){
var
csvUrl
=
oTableUri
+
"/csv/act"
;
var
opt
=
$
(
'select#status'
).
val
();
var
param
=
''
;
var
awalControl
=
$
(
'#awal'
);
var
akhirControl
=
$
(
'#akhir'
);
var
awal
=
awalControl
.
val
();
var
akhir
=
akhirControl
.
val
();
var
tgl
=
new
Date
();
var
tgl_indo
=
tgl
.
getDate
()
+
'-'
+
(
tgl
.
getMonth
()
+
1
)
+
'-'
+
tgl
.
getFullYear
();
if
(
awal
==
''
||
awal
==
undefined
){
awalControl
.
val
(
tgl_indo
)
}
if
(
akhir
==
''
||
akhir
==
undefined
){
akhirControl
.
val
(
tgl_indo
)
}
if
(
awal
!=
''
&&
awal
!=
undefined
)
{
param
+=
'&awal='
+
awal
;
}
if
(
akhir
!=
''
&&
akhir
!=
undefined
)
{
param
+=
'&akhir='
+
akhir
;
}
return
csvUrl
+
'?status='
+
opt
.
toString
()
+
param
;
}
$
(
'#btn_csv'
).
click
(
function
()
{
console
.
log
(
getCSV_url
());
window
.
open
(
getCSV_url
());
});
});
</script>
</div>
</html>
\ No newline at end of file
src/agratek/api/merchant/views/templates/history_transaksi/view.pt
0 → 100644
View file @
f4ce41d
<div tal:condition="params.form" tal:omit-tag="">
<div class="form-horizontal">
<div tal:repeat="f params.form" class="row">
<div class="form-group">
<label for="${f.oid}" class="control-label col-md-3" id="req-${f.oid}">
${f.title}
</label>
<div class="col-md-9">
${structure:f.serialize()}
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
Write
Preview
Markdown
is supported
Attach a file
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 post a comment