Собственные отчеты.
Вы можете создавать собственные отчеты для приложения BGBilling Top Reports. Для этого создайте дин. класс потомок от MobileReport
В методе getReportType вам нужно передать параметры отчета по которым пользователь сможет производить выборку. В getData вам нужно вернуть данные для построения отчета. В getTypeGraf вам нужно вернуть тип графика который будет строиться по вашим данным(гистограмма, линейный график, круговой график или табличный отчет ). В методе getOptions можно вернуть дополнительные данные которые будут отображаться при построении графика или указывать способ отображения. Ниже примеры отчетов.
Круговой отчет
import java.awt.Color; importimport 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 и т.д.