Собственные отчеты.
Вы можете создавать собственные отчеты для приложения BGBilling Top Reports. Для этого создайте дин. класс потомок от MobileReport
В методе getReportType вам нужно передать параметры отчета по которым пользователь сможет производить выборку. В getData вам нужно вернуть данные для построения отчета. В getTypeGraf вам нужно вернуть тип графика который будет строиться по вашим данным(гистограмма, линейный график, круговой график или табличный отчет ). В методе getOptions можно вернуть дополнительные данные которые будут отображаться при построении графика или указывать способ отображения. Ниже примеры отчетов.
Круговой отчет
import
java.awt.Color;
import
import
java.awt.Color;
import
java.sql.Connection;
import
java.util.ArrayList;
import
java.util.List;
import
java.util.Map;
import
ru.bitel.bgbilling.common.BGIllegalArgumentException;
import
bitel.billing.server.reports.mobile.MobileParamType;
import
bitel.billing.server.reports.mobile.MobileReport;
import
bitel.billing.server.reports.mobile.MobileReportType;
import
bitel.billing.server.reports.mobile.Slice;
public
class
Test2
extends
MobileReport
{
@Override
public
MobileReportType getReportType( Connection con )
{
List<MobileParamType> list =
new
ArrayList<>();
// тут нам необходимо добавить параметры, по которым пользователь сможет регулировать выборку данных.
// расмотрим способ и типы параметров ниже
list.add(
new
MobileParamType(
"Date1"
, MobileParamType.DateType,
"От даты"
,
"11.12.2010"
) );
list.add(
new
MobileParamType(
"Date2"
, MobileParamType.DateType,
"До даты"
,
"03.03.2014"
) );
list.add(
new
MobileParamType(
"flag1"
, MobileParamType.BooleanType,
"По дням"
,
"false"
) );
return
new
MobileReportType(
"Test2"
, list );
}
@Override
public
List<Object> getData()
throws
BGIllegalArgumentException
{
ArrayList<Object> list =
new
ArrayList<>();
// Добавление в список значений. Для кругового и гистограммного отчета использовать класс Slice.
// Параметры: 1- Название, 2 - Цвет, 3 - Кол-во.
list.add(
new
Slice(
"Приходы"
,
new
Color(
101
,
214
,
86
),
23
) );
//цвет можно создать свой
list.add(
new
Slice(
"Расходы"
, getColor(),
34
) );
// или вытягивать по порядку предопределенные
list.add(
new
Slice(
"Наработка"
, getColor(
2
),
45
) );
// или по номеру
grafType = PieChartType;
// задание типа графика (PieChartType,HistogramChartType,LinearChartType,TableType)
return
list;
}
@Override
public
Map<String, Object> getOptions()
{
return
null
;
// Для круговых пока не предусмотрено особых опций.
}
}
Гистограммный отчет.
public
class
Test1
extends
MobileReport
{
@Override
public
MobileReportType getReportType( Connection con )
{
List<MobileParamType> list =
new
ArrayList<>();
list.add(
new
MobileParamType(
"flag1"
, MobileParamType.BooleanType,
"По дням"
,
"false"
) );
list.add(
new
MobileParamType(
"Date1"
, MobileParamType.DateType,
"От даты"
,
"01.09.2014"
) );
list.add(
new
MobileParamType(
"Date2"
, MobileParamType.DateType,
"До даты"
,
"07.09.2014"
) );
return
new
MobileReportType(
"Приходы( гистограмма )"
, list );
}
@Override
public
List<Object> getData()
throws
BGIllegalArgumentException
{
grafType = HistogramChartType;
try
{
boolean
flag1 = getBooleanParameter(
"flag1"
,
false
);
Date date1 = getDateParameter(
"Date1"
,
new
Date() );
// получение данных выбранных пользователем.
Date date2 = getDateParameter(
"Date2"
,
new
Date() );
// в первый раз передаются дефолтные значения
if
( date1 ==
null
|| date2 ==
null
&& TimeUtils.dateBefore( date1, date2 ) )
{
throw
new
BGIllegalArgumentException();
}
StringBuilder query =
new
StringBuilder(
"SELECT SUM(summa), DATE_FORMAT(dt, '"
);
String periodParam = getParameter(
"period"
,
"w"
);
if
( periodParam !=
null
)
{
String format =
""
;
Calendar time = Calendar.getInstance();
flag1 =
true
;
switch
( periodParam )
{
case
"w"
:
time.add( Calendar.DAY_OF_YEAR, -
7
);
format =
"%d.%m"
;
break
;
case
"m"
:
time.add( Calendar.MONTH, -
1
);
format =
"%d.%m.%y"
;
break
;
case
"q"
:
time.add( Calendar.MONTH, -
3
);
format =
"%d.%m.%y"
;
break
;
case
"y"
:
flag1 =
false
;
time.add( Calendar.YEAR, -
1
);
format =
"%m.%Y"
;
break
;
}
query.append( format );
date1 = time.getTime();
date2 =
new
Date();
}
else
{
query.append( flag1 ?
"%d.%m"
:
"%m %Y"
);
// если по дням, то года не выдаем.
}
query.append(
"'), COUNT(id) FROM contract_payment WHERE dt>=? AND dt<? GROUP BY YEAR(dt),MONTH(dt)"
);
query.append( flag1 ?
",DAY(dt)"
:
""
);
query.append(
" ORDER BY dt ASC"
);
PreparedStatement ps = con.prepareStatement( query.toString() );
// коннекшен просто берете и используете.
ps.setDate(
1
, TimeUtils.convertDateToSqlDate( date1 ) );
ps.setDate(
2
, TimeUtils.convertDateToSqlDate( date2 ) );
ArrayList<Object> dataList =
new
ArrayList<>();
ResultSet rs = ps.executeQuery();
int
count =
1
;
while
( rs.next() )
{
dataList.add(
new
Slice( rs.getString(
2
), getColor(), rs.getDouble(
1
) ) );
}
return
dataList;
}
catch
( SQLException e )
{
e.printStackTrace();
}
return
null
;
}
@Override
public
Map<String, Object> getOptions()
{
// Для гистограммного отчета есть возможность выставить панель быстрого вызова ниже графика.
// Для этого создаем мап для опций и мап для панели. Мап панели должен иметь значения для ключей id,values и titles.
// Где id - это ид по которому вы будет получать значения( как это было сделано выше - getParameter( "period", "w" ) ).
// values - код/значение которое пользователь может выбрать, и которое вы получите если он это сделает.
// titles - пользовательское описание кнопок панели.
HashMap<String, Object> map =
new
HashMap<>(), dateMap =
new
HashMap<>();
dateMap.put(
"id"
,
"period"
);
dateMap.put(
"values"
,
"w,m,q,y"
);
dateMap.put(
"titles"
,
"Неделя,Месяц,Квартал,Год"
);
// Далее кладём мап панели в мам опций с ключом dataToolbar.
map.put(
"dataToolbar"
, dateMap );
// С помощью ключа changeGrafHide, можно запретить возможность пользователю переключаться на круговой график.
// map.put( "changeGrafHide", "1" );
return
map;
}
}
Линейный график.
import
java.sql.Connection;
import
java.sql.PreparedStatement;
import
java.sql.ResultSet;
import
java.sql.SQLException;
import
java.util.ArrayList;
import
java.util.Date;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
ru.bitel.bgbilling.common.BGIllegalArgumentException;
import
bitel.billing.common.TimeUtils;
import
bitel.billing.server.reports.mobile.MobileParamType;
import
bitel.billing.server.reports.mobile.MobileReport;
import
bitel.billing.server.reports.mobile.MobileReportType;
public
class
PaymentsMobileReport
extends
MobileReport
{
private
ArrayList<String> descriptionList =
null
;
private
ArrayList<String> titleList =
null
;
@Override
public
MobileReportType getReportType( Connection con )
{
List<MobileParamType> list =
new
ArrayList<>();
list.add(
new
MobileParamType(
"Date1"
, MobileParamType.DateType,
"От даты"
,
"11.12.2010"
) );
list.add(
new
MobileParamType(
"Date2"
, MobileParamType.DateType,
"До даты"
,
"03.03.2014"
) );
list.add(
new
MobileParamType(
"flag1"
, MobileParamType.BooleanType,
"По дням"
,
"false"
) );
return
new
MobileReportType(
"Приходы( линейный )"
, list );
}
@Override
public
List<Object> getData()
throws
BGIllegalArgumentException
{
// Линейный график должен вернуть в качестве данных список double значений. Каждое значение это точка на графике.
grafType = LinearChartType;
try
{
boolean
flag1 = getBooleanParameter(
"flag1"
,
false
);
StringBuilder query =
new
StringBuilder(
"SELECT SUM(summa), DATE_FORMAT(dt, '"
);
query.append( flag1 ?
"%d.%m"
:
"%m %Y"
);
// если по дням, то года не выдаем.
query.append(
"'), COUNT(id) FROM contract_payment WHERE dt>=? AND dt<? GROUP BY YEAR(dt),MONTH(dt)"
);
query.append( flag1 ?
",DAY(dt)"
:
""
);
query.append(
" ORDER BY dt ASC"
);
PreparedStatement ps = con.prepareStatement( query.toString() );
Date date1 = getDateParameter(
"Date1"
,
new
Date() );
Date date2 = getDateParameter(
"Date2"
,
new
Date() );
if
( date1 ==
null
|| date2 ==
null
&& TimeUtils.dateBefore( date1, date2 ) )
{
throw
new
BGIllegalArgumentException();
}
ps.setDate(
1
, TimeUtils.convertDateToSqlDate( date1 ) );
ps.setDate(
2
, TimeUtils.convertDateToSqlDate( date2 ) );
ArrayList<Object> dataList =
new
ArrayList<>();
titleList =
new
ArrayList<>();
descriptionList =
new
ArrayList<>();
ResultSet rs = ps.executeQuery();
while
( rs.next() )
{
dataList.add( rs.getDouble(
1
) );
titleList.add( rs.getString(
2
) );
// то что будет отображаться по оси абсцисс
descriptionList.add(
"кол-во платежей: "
+ rs.getInt(
3
) );
// для доп. описания
}
return
dataList;
}
catch
( SQLException e )
{
e.printStackTrace();
}
return
null
;
}
@Override
public
Map>String, Object> getOptions()
{
HashMap<String, Object> map =
new
HashMap<>();
// Для линейного графика можно помимо точек передать описание каждой точки
if
( descriptionList !=
null
&& descriptionList.size() >
0
)
map.put(
"description"
, descriptionList );
// и заголовки с ключами description и titles соответственно.
if
( titleList !=
null
&& titleList.size() >
0
)
map.put(
"titles"
, titleList );
return
map.size() >
0
? map :
null
;
}
}
Табличный отчет.
@Override
public
List<Object> getData()
throws
BGIllegalArgumentException
{
// Табличный отчет должен вернуть список содержащий список значений ячеек.
// Изменение размерности запрещено, если у вас первая строка содержала 3 столбца, то и остальные должны содержать 3.
grafType = TableType;
ArrayList<Object> list =
new
ArrayList<>();
ArrayList<String> rowList1 =
new
ArrayList<>();
ArrayList<String> rowList2 =
new
ArrayList<>();
rowList1.add(
"Столбец 1 строка 1"
);
rowList1.add(
"Столбец 2 строка 1"
);
rowList1.add(
"Столбец 3 строка 1"
);
rowList2.add(
"Столбец 1 строка 2"
);
rowList2.add(
"Столбец 2 строка 2"
);
rowList2.add(
"Столбец 3 строка 2"
);
list.add(rowList1);
list.add(rowList2);
return
list;
}
@Override
public
Map<String, Object> getOptions()
{
// С ключом titles передаем название столбцов
HashMap<String, Object> map =
new
HashMap<>();
ArrayList<String> titles =
new
ArrayList<>();
titles.add(
"Название 1 колонки"
);
titles.add(
"Название 2 колонки"
);
titles.add(
"Название 3 колонки"
);
map.put(
"titles"
, titles );
return
map;
}
Рассмотрим параметры отчетов, по которым пользователь может регулировать выборку данных. Существует 5 типов параметров: Дата(DateType), Список(ListType), Число(NumberType), Список с возможностью выбрать несколько значений(MultiSelectListType), Логический(BooleanType).Ниже приведены примеры их создания в методе getReportType.
List<MobileParamType> list =
new
ArrayList<>();
// Дата
Calendar calendar = Calendar.getInstance();
list.add(
new
MobileParamType(
"d1"
, MobileParamType.DateType,
"От даты"
, TimeUtils.format( calendar, TimeUtils.DATE_FORMAT_PATTERN_DDMMYYYY ) ) );
// Список
LinkedHashMap<Integer, String> map =
new
LinkedHashMap<>();
map.put(
1
,
"10"
);
map.put(
2
,
"100"
);
map.put(
3
,
"1000"
);
list.add(
new
MobileParamType(
"limit"
, MobileParamType.ListType,
"Макс. размер табл."
,
"3"
, map ) );
// Число
list.add(
new
MobileParamType(
"Num1"
, MobileParamType.NumberType,
"Отсекать меньше"
,
"50"
) );
// Список с возможностью выбрать несколько значений
LinkedHashMap<Integer, String> fields =
new
LinkedHashMap<>();
fields.put(
1
,
"Договор"
);
fields.put(
2
,
"Комментарий"
);
fields.put(
3
,
"Пользователь"
);
fields.put(
4
,
"Сумма"
);
fields.put(
5
,
"Дата"
);
fields.put(
6
,
"Тип платежа"
);
fields.put(
7
,
"Примечание"
);
list.add(
new
MobileParamType(
"fields"
, MobileParamType.MultiSelectListType,
"Поля"
,
"1,2,3,4,5,6"
, fields ) );
// Логический
list.add(
new
MobileParamType(
"flag1"
, MobileParamType.BooleanType,
"По дням"
,
"false"
) );
После создания класса отчета вам необходимо прописать ваш класс в настройках вашего модуля.
reports.mobile.dinamic.
1
.title=Мои отчеты
reports.mobile.dinamic.
1
.classes=mobileReports.Test2,mobileReports.Test1
В параметре reports.mobile.dinamic.1.title должно содержаться название категории отчетов, а в reports.mobile.dinamic.1.classes через запятую полное название ваших классов. Если вы решите добавить еще одну категорию, то измените 1 на 2 и т.д.