Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mytime
Project
Project
Details
Activity
Releases
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Narendar Vakiti
mytime
Commits
75c2d0cc
Commit
75c2d0cc
authored
Jun 10, 2019
by
Md Suleman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bar chart report by account wise is updated and some dashboard changes
parent
9f7a9675
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
184 additions
and
75 deletions
+184
-75
ReportsController.java
...n/java/com/nisum/myteam/controller/ReportsController.java
+15
-56
ReportVo.java
src/main/java/com/nisum/myteam/model/vo/ReportVo.java
+9
-9
IAccountService.java
src/main/java/com/nisum/myteam/service/IAccountService.java
+2
-0
IDashboardService.java
...main/java/com/nisum/myteam/service/IDashboardService.java
+2
-1
IProjectService.java
src/main/java/com/nisum/myteam/service/IProjectService.java
+2
-0
IReportService.java
src/main/java/com/nisum/myteam/service/IReportService.java
+9
-0
IResourceService.java
src/main/java/com/nisum/myteam/service/IResourceService.java
+2
-0
AccountService.java
...in/java/com/nisum/myteam/service/impl/AccountService.java
+5
-0
DashboardService.java
.../java/com/nisum/myteam/service/impl/DashboardService.java
+10
-9
ProjectService.java
...in/java/com/nisum/myteam/service/impl/ProjectService.java
+7
-0
ReportService.java
...ain/java/com/nisum/myteam/service/impl/ReportService.java
+116
-0
ResourceService.java
...n/java/com/nisum/myteam/service/impl/ResourceService.java
+5
-0
No files found.
src/main/java/com/nisum/myteam/controller/ReportsController.java
View file @
75c2d0cc
...
@@ -16,6 +16,7 @@ import java.util.List;
...
@@ -16,6 +16,7 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
com.nisum.myteam.service.IReportService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.domain.Sort
;
import
org.springframework.data.domain.Sort
;
import
org.springframework.data.mongodb.core.MongoTemplate
;
import
org.springframework.data.mongodb.core.MongoTemplate
;
...
@@ -47,6 +48,8 @@ import com.nisum.myteam.service.IAccountService;
...
@@ -47,6 +48,8 @@ import com.nisum.myteam.service.IAccountService;
import
com.nisum.myteam.service.IEmployeeService
;
import
com.nisum.myteam.service.IEmployeeService
;
import
com.nisum.myteam.service.IResourceService
;
import
com.nisum.myteam.service.IResourceService
;
import
javax.ws.rs.QueryParam
;
//import com.nisum.myteam.model.dao.Resource;
//import com.nisum.myteam.model.dao.Resource;
@RestController
@RestController
...
@@ -66,7 +69,10 @@ public class ReportsController {
...
@@ -66,7 +69,10 @@ public class ReportsController {
@Autowired
@Autowired
private
IAccountService
accountService
;
private
IAccountService
accountService
;
//Ok Response
@Autowired
private
IReportService
reportService
;
//Ok Response
@RequestMapping
(
value
=
"/getEmployeesByFunctionalGroup1"
,
@RequestMapping
(
value
=
"/getEmployeesByFunctionalGroup1"
,
method
=
RequestMethod
.
GET
,
method
=
RequestMethod
.
GET
,
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
...
@@ -320,62 +326,13 @@ public class ReportsController {
...
@@ -320,62 +326,13 @@ public class ReportsController {
return
new
ResponseEntity
<>(
empList
,
HttpStatus
.
OK
);
return
new
ResponseEntity
<>(
empList
,
HttpStatus
.
OK
);
}
}
@RequestMapping
(
value
=
"/
billabilityByFunctionalGroup
"
,
@RequestMapping
(
value
=
"/
getBarChartReport
"
,
method
=
RequestMethod
.
GET
,
method
=
RequestMethod
.
GET
,
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
public
ReportVo
billabilityReportByFunctionalGroup
(){
public
ReportVo
billabilityReportByFunctionalGroup
(
@RequestParam
(
"byType"
)
String
byType
)
throws
MyTeamException
{
ReportVo
reportVo
=
new
ReportVo
();
Map
<
String
,
Object
>
billableData
=
new
HashMap
();
return
reportService
.
getBarChartReport
(
byType
);
Map
<
String
,
Object
>
nonBillableData
=
new
HashMap
();
Map
<
String
,
Object
>
traineeData
=
new
HashMap
();
List
<
Object
>
billableCount
=
new
ArrayList
<>();
List
<
Object
>
nonBillableCount
=
new
ArrayList
<>();
List
<
Object
>
traineeCount
=
new
ArrayList
<>();
billableData
.
put
(
"name"
,
"Billable"
);
nonBillableData
.
put
(
"name"
,
"Non-Billable"
);
traineeData
.
put
(
"name"
,
"Trainee"
);
for
(
String
functionalGroup:
reportVo
.
getCategoriesList
()){
Map
<
String
,
Object
>
billableObj
=
new
HashMap
();
Map
<
String
,
Object
>
nonbillableObj
=
new
HashMap
();
// Map<String,Object> traineeObj = new HashMap();
Integer
billableC
=
0
;
Integer
nonBillableC
=
0
;
Integer
traineeC
=
0
;
// float traineePer;
float
billper
;
float
nonBillPer
;
List
<
Employee
>
employeeList
=
employeeService
.
getEmployeesByFunctionalGrp
(
functionalGroup
);
for
(
Employee
employee:
employeeList
){
Resource
resource
=
resourceService
.
getLatestResourceByEmpId
(
employee
.
getEmployeeId
());
if
(
resource
!=
null
&&
resource
.
getBillableStatus
().
equals
(
"Billable"
)){
billableC
++;
}
else
if
(
resource
!=
null
&&
resource
.
getBillableStatus
().
equals
(
"Trainee"
))
{
traineeC
++;
}
else
{
nonBillableC
++;
}
}
billper
=
((
billableC
/
(
float
)(
employeeList
.
size
()
-
traineeC
))*
100
);
nonBillPer
=
nonBillableC
/(
float
)
(
employeeList
.
size
()-
traineeC
)*
100
;
// traineePer = traineeC / (float) employeeList.size()*100;
billableObj
.
put
(
"percent"
,
billper
);
billableObj
.
put
(
"y"
,
billableC
);
nonbillableObj
.
put
(
"percent"
,
nonBillPer
);
nonbillableObj
.
put
(
"y"
,
nonBillableC
);
// traineeObj.put("percent", traineePer);
// traineeObj.put("y", traineeC);
billableCount
.
add
(
billableObj
);
nonBillableCount
.
add
(
nonbillableObj
);
traineeCount
.
add
(
traineeC
);
}
billableData
.
put
(
"data"
,
billableCount
);
nonBillableData
.
put
(
"data"
,
nonBillableCount
);
traineeData
.
put
(
"data"
,
traineeCount
);
reportVo
.
getSeriesDataList
().
add
(
billableData
);
reportVo
.
getSeriesDataList
().
add
(
nonBillableData
);
reportVo
.
getSeriesDataList
().
add
(
traineeData
);
return
reportVo
;
}
}
...
@@ -403,7 +360,7 @@ public class ReportsController {
...
@@ -403,7 +360,7 @@ public class ReportsController {
// Convert the aggregation result into a List
// Convert the aggregation result into a List
AggregationResults
<
ColumnChartData
>
groupResults
=
mongoTemplate
.
aggregate
(
aggregate
,
Resource
.
class
,
AggregationResults
<
ColumnChartData
>
groupResults
=
mongoTemplate
.
aggregate
(
aggregate
,
Resource
.
class
,
ColumnChartData
.
class
);
ColumnChartData
.
class
);
List
<
ColumnChartData
>
result
=
groupResults
.
getMappedResults
();
List
<
ColumnChartData
>
result
=
groupResults
.
getMappedResults
();
List
<
String
>
statusList
=
new
ArrayList
();
List
<
String
>
statusList
=
new
ArrayList
();
statusList
.
add
(
"Billable"
);
statusList
.
add
(
"Billable"
);
...
@@ -456,4 +413,6 @@ public class ReportsController {
...
@@ -456,4 +413,6 @@ public class ReportsController {
}
}
}
}
src/main/java/com/nisum/myteam/model/vo/ReportVo.java
View file @
75c2d0cc
...
@@ -15,13 +15,13 @@ public class ReportVo {
...
@@ -15,13 +15,13 @@ public class ReportVo {
List
<
String
>
categoriesList
=
new
ArrayList
();
List
<
String
>
categoriesList
=
new
ArrayList
();
List
<
Map
<
String
,
Object
>>
seriesDataList
=
new
ArrayList
();
List
<
Map
<
String
,
Object
>>
seriesDataList
=
new
ArrayList
();
public
ReportVo
(){
//
public ReportVo(){
categoriesList
.
add
(
"ES"
);
//
categoriesList.add("ES");
categoriesList
.
add
(
"CI"
);
//
categoriesList.add("CI");
categoriesList
.
add
(
"APPS"
);
//
categoriesList.add("APPS");
categoriesList
.
add
(
"ACI - QE"
);
//
categoriesList.add("ACI - QE");
categoriesList
.
add
(
"ACI - DevOps"
);
//
categoriesList.add("ACI - DevOps");
categoriesList
.
add
(
"ACI - Support"
);
//
categoriesList.add("ACI - Support");
categoriesList
.
add
(
"I&A"
);
//
categoriesList.add("I&A");
}
//
}
}
}
src/main/java/com/nisum/myteam/service/IAccountService.java
View file @
75c2d0cc
...
@@ -29,4 +29,6 @@ public interface IAccountService {
...
@@ -29,4 +29,6 @@ public interface IAccountService {
Account
deleteAccount
(
String
accountId
)
throws
MyTeamException
;
Account
deleteAccount
(
String
accountId
)
throws
MyTeamException
;
public
Account
getAccountByName
(
String
name
);
}
}
src/main/java/com/nisum/myteam/service/IDashboardService.java
View file @
75c2d0cc
package
com
.
nisum
.
myteam
.
service
;
package
com
.
nisum
.
myteam
.
service
;
import
com.nisum.myteam.exception.handler.MyTeamException
;
import
com.nisum.myteam.model.vo.EmployeeDashboardVO
;
import
com.nisum.myteam.model.vo.EmployeeDashboardVO
;
import
java.util.List
;
import
java.util.List
;
public
interface
IDashboardService
{
public
interface
IDashboardService
{
public
List
<
EmployeeDashboardVO
>
getEmployeesDashBoard
();
public
List
<
EmployeeDashboardVO
>
getEmployeesDashBoard
();
public
List
<
EmployeeDashboardVO
>
getDashBoardData
();
public
List
<
EmployeeDashboardVO
>
getDashBoardData
()
throws
MyTeamException
;
}
}
src/main/java/com/nisum/myteam/service/IProjectService.java
View file @
75c2d0cc
...
@@ -60,5 +60,7 @@ public interface IProjectService {
...
@@ -60,5 +60,7 @@ public interface IProjectService {
List
<
Resource
>
getResourcesUnderProject
(
String
empId
);
List
<
Resource
>
getResourcesUnderProject
(
String
empId
);
public
List
<
Project
>
getProjectsByAccountId
(
String
accId
);
}
}
src/main/java/com/nisum/myteam/service/IReportService.java
0 → 100644
View file @
75c2d0cc
package
com
.
nisum
.
myteam
.
service
;
import
com.nisum.myteam.exception.handler.MyTeamException
;
import
com.nisum.myteam.model.vo.ReportVo
;
public
interface
IReportService
{
public
ReportVo
getBarChartReport
(
String
byType
)
throws
MyTeamException
;
}
src/main/java/com/nisum/myteam/service/IResourceService.java
View file @
75c2d0cc
...
@@ -67,6 +67,8 @@ public interface IResourceService {
...
@@ -67,6 +67,8 @@ public interface IResourceService {
Set
<
Resource
>
findByBillableStatus
(
String
billableStatus
);
Set
<
Resource
>
findByBillableStatus
(
String
billableStatus
);
public
List
<
Resource
>
getResourceByProjectId
(
String
projectId
);
// List<Resource> getAllResourcesForProject(String projectId, String status);
// List<Resource> getAllResourcesForProject(String projectId, String status);
...
...
src/main/java/com/nisum/myteam/service/impl/AccountService.java
View file @
75c2d0cc
...
@@ -163,6 +163,11 @@ public class AccountService implements IAccountService {
...
@@ -163,6 +163,11 @@ public class AccountService implements IAccountService {
return
updatedAccount
;
return
updatedAccount
;
}
}
@Override
public
Account
getAccountByName
(
String
name
)
{
return
accountRepo
.
findByAccountNameIgnoreCase
(
name
);
}
// generating the account id.
// generating the account id.
// accountId format is "Acc001"
// accountId format is "Acc001"
private
String
generateAccountId
()
throws
MyTeamException
{
private
String
generateAccountId
()
throws
MyTeamException
{
...
...
src/main/java/com/nisum/myteam/service/impl/DashboardService.java
View file @
75c2d0cc
package
com
.
nisum
.
myteam
.
service
.
impl
;
package
com
.
nisum
.
myteam
.
service
.
impl
;
import
com.nisum.myteam.exception.handler.MyTeamException
;
import
com.nisum.myteam.model.dao.Account
;
import
com.nisum.myteam.model.dao.Account
;
import
com.nisum.myteam.model.dao.Domain
;
import
com.nisum.myteam.model.dao.Domain
;
import
com.nisum.myteam.model.dao.Employee
;
import
com.nisum.myteam.model.dao.Employee
;
...
@@ -110,19 +111,19 @@ public class DashboardService implements IDashboardService {
...
@@ -110,19 +111,19 @@ public class DashboardService implements IDashboardService {
}
}
@Override
@Override
public
List
<
EmployeeDashboardVO
>
getDashBoardData
(){
public
List
<
EmployeeDashboardVO
>
getDashBoardData
()
throws
MyTeamException
{
List
<
EmployeeDashboardVO
>
employeeDashboard
List
=
new
ArrayList
<>();
List
<
EmployeeDashboardVO
>
employeeDashboard
=
new
ArrayList
<>();
List
<
Employee
>
allEmployees
List
=
employeeService
.
getAll
Employees
();
List
<
Employee
>
allEmployees
=
employeeService
.
getActive
Employees
();
List
<
ResourceVO
>
resources
List
=
resourceService
.
getAllResourcesVO
();
List
<
ResourceVO
>
resources
=
resourceService
.
getAllResourcesVO
();
for
(
Employee
employee:
allEmployees
List
){
for
(
Employee
employee:
allEmployees
){
EmployeeDashboardVO
employeeDashboardVO
=
new
EmployeeDashboardVO
();
EmployeeDashboardVO
employeeDashboardVO
=
new
EmployeeDashboardVO
();
BeanUtils
.
copyProperties
(
employee
,
employeeDashboardVO
);
BeanUtils
.
copyProperties
(
employee
,
employeeDashboardVO
);
employeeDashboard
List
.
add
(
employeeDashboardVO
);
employeeDashboard
.
add
(
employeeDashboardVO
);
}
}
employeeDashboard
List
.
stream
().
forEach
(
emp
->
{
employeeDashboard
.
stream
().
forEach
(
emp
->
{
List
<
ResourceVO
>
latestResourceList
=
resources
List
.
stream
().
List
<
ResourceVO
>
latestResourceList
=
resources
.
stream
().
filter
(
res
->
(
res
.
getEmployeeId
().
equals
(
emp
.
getEmployeeId
())&&
res
.
getBillingEndDate
().
after
(
new
Date
()))).
collect
(
Collectors
.
toList
());
filter
(
res
->
(
res
.
getEmployeeId
().
equals
(
emp
.
getEmployeeId
())&&
res
.
getBillingEndDate
().
after
(
new
Date
()))).
collect
(
Collectors
.
toList
());
if
(!
latestResourceList
.
isEmpty
()){
if
(!
latestResourceList
.
isEmpty
()){
ResourceVO
latestResource
=
latestResourceList
.
get
(
0
);
ResourceVO
latestResource
=
latestResourceList
.
get
(
0
);
...
@@ -139,6 +140,6 @@ public class DashboardService implements IDashboardService {
...
@@ -139,6 +140,6 @@ public class DashboardService implements IDashboardService {
}
}
}
}
});
});
return
employeeDashboard
List
;
return
employeeDashboard
;
}
}
}
}
src/main/java/com/nisum/myteam/service/impl/ProjectService.java
View file @
75c2d0cc
...
@@ -233,6 +233,13 @@ public class ProjectService implements IProjectService {
...
@@ -233,6 +233,13 @@ public class ProjectService implements IProjectService {
}
}
@Override
public
List
<
Project
>
getProjectsByAccountId
(
String
accId
)
{
return
projectRepo
.
findByAccountId
(
accId
);
}
@Override
@Override
public
List
<
Project
>
getProjectsUnderDeliveryLead
(
String
deliveryLeadId
)
throws
MyTeamException
{
public
List
<
Project
>
getProjectsUnderDeliveryLead
(
String
deliveryLeadId
)
throws
MyTeamException
{
...
...
src/main/java/com/nisum/myteam/service/impl/ReportService.java
0 → 100644
View file @
75c2d0cc
package
com
.
nisum
.
myteam
.
service
.
impl
;
import
com.nisum.myteam.exception.handler.MyTeamException
;
import
com.nisum.myteam.model.dao.Employee
;
import
com.nisum.myteam.model.dao.Project
;
import
com.nisum.myteam.model.dao.Resource
;
import
com.nisum.myteam.model.vo.ReportVo
;
import
com.nisum.myteam.service.IReportService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.*
;
import
java.util.stream.Collectors
;
@Service
public
class
ReportService
implements
IReportService
{
@Autowired
private
EmployeeService
employeeService
;
@Autowired
private
ResourceService
resourceService
;
@Autowired
private
AccountService
accountService
;
@Autowired
private
ProjectService
projectService
;
@Autowired
private
FunctionalGroupService
functionalGroupService
;
public
ReportVo
getBarChartReport
(
String
byType
)
throws
MyTeamException
{
ReportVo
reportVo
=
new
ReportVo
();
if
(
byType
.
equals
(
"FunctionalGroup"
))
{
functionalGroupService
.
getAllFunctionalGroups
().
forEach
(
f
->
reportVo
.
getCategoriesList
().
add
(
f
.
getName
()));
}
else
{
accountService
.
getAllAccounts
().
forEach
(
a
->
reportVo
.
getCategoriesList
().
add
(
a
.
getAccountName
()));
}
Map
<
String
,
Object
>
billableData
=
new
HashMap
();
Map
<
String
,
Object
>
nonBillableData
=
new
HashMap
();
Map
<
String
,
Object
>
traineeData
=
new
HashMap
();
List
<
Object
>
billableCount
=
new
ArrayList
<>();
List
<
Object
>
nonBillableCount
=
new
ArrayList
<>();
List
<
Object
>
traineeCount
=
new
ArrayList
<>();
billableData
.
put
(
"name"
,
"Billable"
);
nonBillableData
.
put
(
"name"
,
"Non-Billable"
);
traineeData
.
put
(
"name"
,
"Trainee"
);
for
(
String
category:
reportVo
.
getCategoriesList
()){
Map
<
String
,
Object
>
billableObj
=
new
HashMap
();
Map
<
String
,
Object
>
nonbillableObj
=
new
HashMap
();
// Map<String,Object> traineeObj = new HashMap();
Integer
billableC
=
0
;
Integer
nonBillableC
=
0
;
Integer
traineeC
=
0
;
// float traineePer;
float
billper
;
float
nonBillPer
;
List
<
Employee
>
employeeList
=
new
ArrayList
<>();
if
(
byType
.
equals
(
"FunctionalGroup"
))
{
employeeList
=
getEmployeesByFunctionalGroup
(
category
);
}
else
{
employeeList
=
getEmployeeByAccounts
(
category
);
}
// .getAllEmployees().stream().
// filter(e -> e.getFunctionalGroup().equals(functionalGroup)).collect(Collectors.toList());
for
(
Employee
employee:
employeeList
){
Resource
resource
=
resourceService
.
getLatestResourceByEmpId
(
employee
.
getEmployeeId
());
if
(
resource
!=
null
&&
resource
.
getBillableStatus
().
equals
(
"Billable"
)){
billableC
++;
}
else
if
(
resource
!=
null
&&
resource
.
getBillableStatus
().
equals
(
"Trainee"
))
{
traineeC
++;
}
else
{
nonBillableC
++;
}
}
billper
=
((
billableC
/
(
float
)(
employeeList
.
size
()
-
traineeC
))*
100
);
nonBillPer
=
nonBillableC
/(
float
)
(
employeeList
.
size
()-
traineeC
)*
100
;
// traineePer = traineeC / (float) employeeList.size()*100;
billableObj
.
put
(
"percent"
,
billper
);
billableObj
.
put
(
"y"
,
billableC
);
nonbillableObj
.
put
(
"percent"
,
nonBillPer
);
nonbillableObj
.
put
(
"y"
,
nonBillableC
);
// traineeObj.put("percent", traineePer);
// traineeObj.put("y", traineeC);
billableCount
.
add
(
billableObj
);
nonBillableCount
.
add
(
nonbillableObj
);
traineeCount
.
add
(
traineeC
);
}
billableData
.
put
(
"data"
,
billableCount
);
nonBillableData
.
put
(
"data"
,
nonBillableCount
);
traineeData
.
put
(
"data"
,
traineeCount
);
reportVo
.
getSeriesDataList
().
add
(
billableData
);
reportVo
.
getSeriesDataList
().
add
(
nonBillableData
);
reportVo
.
getSeriesDataList
().
add
(
traineeData
);
return
reportVo
;
}
private
List
<
Employee
>
getEmployeesByFunctionalGroup
(
String
functionalGroup
){
return
employeeService
.
getEmployeesByFunctionalGrp
(
functionalGroup
);
}
private
List
<
Employee
>
getEmployeeByAccounts
(
String
accountName
){
List
<
Employee
>
employeeList
=
new
ArrayList
<>();
List
<
Project
>
projects
=
projectService
.
getProjectsByAccountId
(
accountService
.
getAccountByName
(
accountName
).
getAccountId
());
projects
.
stream
().
forEach
(
p
->
{
resourceService
.
getResourceByProjectId
(
p
.
getProjectId
()).
stream
().
filter
(
r
->
r
.
getBillingEndDate
().
after
(
new
Date
())).
forEach
(
r
->
employeeList
.
add
(
employeeService
.
getEmployeeById
(
r
.
getEmployeeId
())));
});
return
employeeList
;
}
}
src/main/java/com/nisum/myteam/service/impl/ResourceService.java
View file @
75c2d0cc
...
@@ -737,6 +737,11 @@ public class ResourceService implements IResourceService {
...
@@ -737,6 +737,11 @@ public class ResourceService implements IResourceService {
}
}
@Override
public
List
<
Resource
>
getResourceByProjectId
(
String
projectId
){
return
resourceRepo
.
findByProjectId
(
projectId
);
}
public
List
<
ChangedResourceVO
>
getChangedResourceByDate
(
String
fromDatestr
,
String
toDatestr
)
{
public
List
<
ChangedResourceVO
>
getChangedResourceByDate
(
String
fromDatestr
,
String
toDatestr
)
{
// List<ChangedResourceVO> changedResourceVOList = new ArrayList();
// List<ChangedResourceVO> changedResourceVOList = new ArrayList();
...
...
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