def get_pf_chart_data_web(sic_code, report_year, benchmark_year, comparison_type, demand_type, g):
    """
    Gets and calculates all data needed for powerfactor charts
    :param sic_code: sic code to find data for
    :param report_year: report year
    :param benchmark_year: benchmark year
    :param comparison_type: 'temp'/'dewpt'/'enthalpy'
    :param demand_type: 'all'/'peak'/'offpeak'
    :param g:
    :return: data for the charts
    """

    data_list = []

    sic_obj = g.uow.sic.get_by_code(sic_code)
    descendants = g.uow.sic.get_group_descendants(sic_code)
    accounts = []

    # get all accounts of group descendants of sic code
    for gr in descendants:
        accounts += SharedReporting.get_accounts_for_group(gr, 'Electric', report_year, comparison_type, demand_type, g)
        accounts += SharedReporting.get_accounts_for_group(gr, 'Electric', benchmark_year, comparison_type, demand_type, g)

    # get the benchmark data for the accounts to avoid looping through benchmark data multiple times
    report_data = g.uow.compiled_energy_records.get_compiled_energy_records_for_report(accounts, data_field_name='sum_kvar')

    # create a copy of the benchmark records
    account_group = defaultdict(list)
    for d in report_data:
        account_group[d['group']['value']].append(d)

    calculated_totals = calculate_pf_data(account_group, report_year, benchmark_year, report_year == benchmark_year)

    return calculated_totals
def generate_kvarh_report(config, y_units, y_unit_map, total_energy_chart_info, submitted_by_user, submitted_to, g):
    """
    Gathers data for the kVar report and generates it's PDF
    :param config: report configuration
    :param y_units: y units
    :param y_unit_map: database column name for y unit
    :param total_energy_chart_info: TotalEnergyChartInfo object to hold data
    :param submitted_by_user: user who submitted the report
    :param submitted_to: group who the report what submitted to
    :param g: g
    :return: path to the report PDF
    """
    for code in config.entity_ids:
        sic_code = g.uow.sic.get_by_code(code)

        # get data associated with each account in the sic code
        accounts = []
        group_descendants = g.uow.sic.get_group_descendants(code)
        for gr in group_descendants:
            accounts += SharedReporting.get_accounts_for_group(gr, 'Electric', config.report_year, config.comparison_type, config.demand_type, g)
        data = SharedReporting.get_total_energy_chart_data_pdf(accounts, config.report_year, config.benchmark_year, config.demand_type, y_units, y_unit_map, g)
        total_energy_chart_info.data.append({'entity': sic_code["name"], 'data': data})

    # Generate consumption report with data
    report_path = DataReports.generate_kvarh_report(config.report_year, config.benchmark_year, total_energy_chart_info, submitted_by_user, submitted_to)
    return report_path
def get_syrx_data(config):
    """
    Gets the data for the syrx number in config and returns a kendo-formatted object of the data
    :param config: EquipmentReport
    :return:
    """
    report_series_dict = {}
    benchmark_series_dict = {}

    if len(config.syrx_nums) > 1:
        target_unit = "mmbtu"
    else:
        target_unit = None

    for syrx_num in config.syrx_nums:
        # get the equipment point
        ep = g.uow.equipment.get_equipment_point_by_syrx_num(syrx_num)

        if not target_unit:
            target_unit = ep['units'].lower()

        conversion_factor = SharedReporting.get_component_point_conversion(ep['units'].lower(), 'mmbtu')

        syrx_series = get_consumption_data_for_year(syrx_num, config.report_year, config.start_month, config.end_month,
                                                    conversion_factor)
        # add to the existing series
        add_to_new_series_data(report_series_dict, syrx_series[0]['data'])

        syrx_series_benchmark = get_consumption_data_for_year(syrx_num, config.comparison_year, config.start_month,
                                                              config.end_month, conversion_factor)

        # add to the existing series
        add_to_new_series_data(benchmark_series_dict, syrx_series_benchmark[0]['data'])

    report_difference_list, benchmark_difference_list = calculate_difference_equipment_report(report_series_dict,
                                                                                              benchmark_series_dict)

    consumption_series_list = convert_dict_to_list(report_series_dict)
    consumption_series_list[0]['name'] = 'Reported Consumption'
    benchmark_series_list = convert_dict_to_list(benchmark_series_dict)
    consumption_series_list += benchmark_series_list
    consumption_series_list[1]['name'] = 'Benchmark Consumption'

    difference_series_list = convert_dict_to_list(report_difference_list)
    difference_series_list[0]['name'] = 'Reported Consumption'
    difference_series_list += convert_dict_to_list(benchmark_difference_list)
    difference_series_list[1]['name'] = 'Benchmark Consumption'

    chart_info = ComponentDifferenceDataContainer()
    chart_info.component_description = ""
    chart_info.title = "Intensity"
    chart_info.consumption_data = consumption_series_list
    chart_info.difference_data = difference_series_list
    chart_info.x_axis_label = "Temperature (F)"
    chart_info.y_axis_label = "Energy Consumption (" + SharedReporting.get_y_unit_label(target_unit.lower()) + ")"
    return chart_info
def get_comparison_chart_data(config):
    """
    Gets a list of the series used for the comparison report charts
    :param config: ComponentReportingComparisonConfiguration
    :return: TotalEnergyDataContainer that holds all information for the chart
    """
    series_list = []
    for entity in config.component_ids:
        # get label from the entity
        label = get_label_for_entity(entity)

        # get actual component_id from the list
        syrx_nums = get_syrx_nums_from_entity(entity)

        # combine the comparison year with the historical mode years
        all_years = list(set([config.comparison_year] + config.historical_years))
        for year in all_years:
            new_series_data = {}
            for syrx_num in syrx_nums:
                # get the equipment point by syrx num
                ep = g.uow.equipment.get_equipment_point_by_syrx_num(syrx_num)

                # get the series data for each point
                syrx_series = g.uow.compiled_point_records.get_data_for_syrx_nums([syrx_num], year, 1, 12)

                if len(syrx_series) > 0:
                    # convert the data to the new values
                    conversion_factor = SharedReporting.get_component_point_conversion(ep['units'].lower(), config.unit)

                    convert_data_to_btu_unit(syrx_series[0]['data'], conversion_factor)

                    # add to the new_series_data
                    add_to_new_series_data(new_series_data, syrx_series[0]['data'])

            if len(new_series_data) > 0:
                new_series_data_list = []
                # change the data from a dictionary to list
                for key in sorted(new_series_data.keys()):
                    new_series_data_list.append([key, new_series_data[key]])

                # overwrite the point name with the component name
                new_series = [{"name": None,
                               "data": new_series_data_list}]
                new_series[0]["name"] = label + " - " + str(year)

                series_list += new_series

    chart_info = TotalEnergyDataContainer()
    chart_info.title = "Intensity"
    chart_info.data = series_list
    chart_info.x_axis_label = "Temperature (F)"
    chart_info.y_axis_label = "Energy Consumption (" + SharedReporting.get_y_unit_label(config.unit) + ")"

    return chart_info
def generate_consumption_report(config, y_units, y_unit_map, total_energy_chart_info, submitted_by_user, submitted_to, g):
    """
    Gathers data and generates a pdf from it
    :param config:
    :param y_units:
    :param y_unit_map:
    :param total_energy_chart_info:
    :param submitted_by_user:
    :param submitted_to:
    :param g:
    :return:
    """
    # collect information for intensity chart
    intensity_chart_info = get_intensity_chart_data(config.entity_ids, config.account_type, config.report_year,
                                                    config.comparison_type, config.demand_type, g)

    year_group_grouping = {}
    # loop through every SIC code in the configuration and get their consumption chart data
    for code in config.entity_ids:
        # get the sic code and it's group descendants
        sic_code = g.uow.sic.get_by_code(code)
        group_descendants = g.uow.sic.get_group_descendants(code)

        # get all accounts for the SIC code
        accounts = []
        for gr in group_descendants:
            accounts += SharedReporting.get_accounts_for_group(gr, config.account_type, config.report_year,
                                                               config.comparison_type, config.demand_type, g)

        # get data associated with each account
        data = SharedReporting.get_total_energy_chart_data_pdf(accounts, config.report_year, config.benchmark_year, config.demand_type,
                                               y_units, y_unit_map, g)
        total_energy_chart_info.data.append({'entity': sic_code['name'], 'data': data['chart_data']})

        for year in data['year_data']:
            # check if the year has not been added to the group before
            if not year in year_group_grouping:
                # the year hasn't been added to the grouping, so just create a new entry in the dictionary
                year_group_grouping[year] = [{'entity': sic_code['name'] + ' (' + str(year) + ')',
                                              'data': data['year_data'][year]}]
            else:
                # append the entry
                year_group_grouping[year].append({'entity': sic_code['name'] + ' (' + str(year) + ')',
                                                  'data': data['year_data'][year]})

    # generate report data and get the report path
    report_path = DataReports.generate_consumption_report(config.report_year, config.benchmark_year,
                                                          intensity_chart_info, total_energy_chart_info,
                                                          year_group_grouping, submitted_by_user, submitted_to,
                                                          SharedReporting.get_y_unit_label(y_units))
    return report_path
def get_y_axis_and_conversion_factor(config):
    """
    Gets the y axis unit and conversion factor
    :param config: EquipmentReport
    :return: y_axis_unit, conversion_factor
    """
    y_axis_units = "Btu"

    same_unit = g.uow.equipment.all_of_same_unit(config.syrx_nums)

    # if all equipment points have the same unit, then we will use that unit as the y axis
    if same_unit:
        y_axis_units = g.uow.equipment.get_equipment_point_by_syrx_num(config.syrx_nums[0])

        if 'units' in y_axis_units:
            y_axis_units = y_axis_units['units']
        else:
            y_axis_units = "Binary"

        # if the unit is kWh then have a conversion factor, otherwise it will be 1
        if y_axis_units.lower() == "kwh":
            conversion_factor = SharedReporting.get_factor('kwh', 'sum_btu')
        else:
            conversion_factor = 1.0
    else:
        # otherwise, we keep the units in Btu
        conversion_factor = 1.0

    return y_axis_units, conversion_factor
def get_paragraph_report():
    model = request.get_json()
    equipments = [{"equipment": g.uow.equipment.get_by_id(equipment_id).__dict__,
                   "paragraphs": g.uow.equipment.get_all_paragraphs_for_equipment(equipment_id)}
                  for equipment_id in model["equipment_ids"]]

    report_config = {"equipments": equipments}

    submitted_by = g.uow.users.get_user_by_id(session["current_user"]["id"])
    submitted_to = model["submitted_to"]

    # get the submitted by and submitted to
    submitted_by, submitted_to = SharedReporting.get_submitted_contacts(submitted_by, submitted_to, g)

    report_path = generate_paragraph_report(report_config, submitted_to, submitted_by)

    return send_file(report_path, mimetype='application/pdf')
def get_intensity_chart_data(sic_codes, account_type, report_year, comparison_type, demand_type, g):
    # Set the x units for the intensity chart on the consumption report
    x_units = "F"
    x_axis_label = "Temperature (" + x_units + ")"
    if comparison_type == "enthalpy":
        x_axis_label = "Enthalpy"

    final_data = []

    # get all accounts for sic code and it's descendants
    for nc in sic_codes:
        data_insert = []
        accounts = []
        sic_code = g.uow.sic.get_by_code(nc)
        group_descendants = g.uow.sic.get_group_descendants(nc)
        for desc in group_descendants:
            accounts += SharedReporting.get_accounts_for_group(desc, account_type, report_year, comparison_type, demand_type, g)

        consider_demand_type = False
        if demand_type != 'all':
            consider_demand_type = True

        if len(accounts) > 0:
            # get data for the consumption report
            intensity_data = g.uow.compiled_energy_records.get_compiled_energy_records_for_report(accounts, consider_demand_type=consider_demand_type)
        else:
            intensity_data = []

        # loop through and adjust the values based on size normalization
        for entry in intensity_data:
            data_insert.append([entry['group']['value'],
                                entry['reduction']['sum_btu'] / entry['reduction']['sum_size_normalization']])

        # add to the final data
        final_data.append({"name": sic_code["name"], "data": data_insert})

    # set the metadata for the consumption report
    intensity_chart_info = ReportChartInformation()
    intensity_chart_info.title = "Intensity"
    intensity_chart_info.y_axis_label = "Energy Intensity (BTU/sqft)"
    intensity_chart_info.x_axis_label = x_axis_label
    intensity_chart_info.data = final_data
    return intensity_chart_info
def get_comparison_pdf_report(config):
    if not config.submitted_to:
        return abort(409)

    submitted_by = g.uow.users.get_user_by_id(session["current_user"]["id"])
    submitted_to = config.submitted_to

    # get the submitted by and submitted to
    submitted_by, submitted_to = SharedReporting.get_submitted_contacts(submitted_by, submitted_to, g)

    total_energy_chart_info = TotalEnergyDataContainer()

    report_name = "Component Comparison Report"
    total_energy_chart_info.y_axis_label = "Energy Consumption (BTU)"
    total_energy_chart_info.title = "Intensity"
    comparison_data = get_comparison_chart_data(config)
    comparison_table_data = get_comparison_table_data(config, config.comparison_year)
    report_path = generate_comparison_pdf(config, comparison_data, comparison_table_data, submitted_by, submitted_to)

    return send_file(report_path, mimetype='application/pdf', as_attachment=True, attachment_filename=report_name + '.pdf')
def get_standards_pdf_report(config):
    if not config.submitted_to:
        return abort(409)

    submitted_by = g.uow.users.get_user_by_id(session["current_user"]["id"])
    submitted_to = config.submitted_to

    # get the submitted by and submitted to
    submitted_by, submitted_to = SharedReporting.get_submitted_contacts(submitted_by, submitted_to, g)

    total_energy_chart_info = TotalEnergyDataContainer()

    report_name = "Component Standards Report"
    total_energy_chart_info.y_axis_label = "Energy Consumption (BTU/sqft)"
    total_energy_chart_info.title = "Intensity"
    standards_data = get_standards_chart_data(config)
    standards_table_data = get_standards_table_data(config)
    report_path = generate_standards_pdf(config, standards_data, standards_table_data, submitted_by, submitted_to)

    # send file back out to user for download
    return send_file(report_path, mimetype='application/pdf', as_attachment=True, attachment_filename=report_name + '.pdf')
def find_price_for_equipment_points(units, equipment_id):
    """
    Finds the price/unit of the equipment points based on unit
    :param units: 'kwh'/'btu'/'mcf'
    :param equipment_id: Equipment id to find price based on
    :return:
    """
    # find the equipment, which will help find the group
    equipment = g.uow.equipment.get_by_id(equipment_id)

    if units == 'kwh':
        acct = 'electric'
    else:
        acct = 'gas'
    account = SharedReporting.get_first_account_for_group_of_type(equipment.group_id, acct, g.uow)
    price = g.uow.price_normalizations.get_most_recent_for_account(account['id'])
    # ensure the price was found
    if price:
        price = price.value
    else:
        price = 0
    return price
def construct_row(syrx_num, component_values, unit):
    """
    Constructs a row for the table
    :param syrx_num: syrx_num that is being reported on
    :param component_values: dictionary containing ppsn, sum_value, and sum_hours_in_record
    :param unit: Unit the result should be in
    :return:
    """
    equipment_point = g.uow.equipment.get_equipment_point_by_syrx_num(syrx_num)
    equipment = g.uow.equipment.get_by_id(equipment_point['equipment_id'])
    component = g.uow.components.get_by_id(equipment_point['component_id'])
    row_dict = {
        'row': {
            'equipment_name':equipment.name, 'component_id': component.num,
            'description': equipment_point['point_code'],
            'units': SharedReporting.get_y_unit_label(unit)
        },
        'ppsn': component_values['ppsn'],
        'hours': component_values['sum_hours_in_record'],
        'consumption': component_values['sum_value'],
        'component_id': component.id,
        'syrx_num': syrx_num,
        'conversion_factor': None}
    return row_dict
def generate_group_text_report(config):
    return json.dumps(SharedReporting.generate_consumptiontext_report(config, 'groups', g))
def get_total_energy_data(config):
    # determine the x units
    x_units = "F"
    x_axis_label = "Temperature (" + x_units + ")"
    if config.comparison_type == "dewpt":
        x_units = "Dewpt"
        x_axis_label = "Dewpt"
    elif config.comparison_type == "enthalpy":
        x_units = "Enthalpy"
        x_axis_label = "Enthalpy"

    # get actual y units to send back, and get their equivalent column in the database
    if config.report_type == "consumption":
        if config.account_type.lower() == "electric":
            y_units = config.electric_units
            y_unit_map = 'sum_btu'
            title = "Total Energy Usage - Electric"
        elif config.account_type.lower() == "gas":
            y_units = config.gas_units
            y_unit_map = 'sum_btu'
            title = "Total Energy Usage - Gas"
        else:
            y_units = config.btu_units
            y_unit_map = "sum_btu"
            title = "Total Energy Usage"
        y_axis_label = "Average Energy Usage (" + SharedReporting.get_y_unit_label(y_units) + ")"
    elif config.report_type == "kvar":
        y_units = "kvar"
        y_unit_map = "sum_kvar"
        y_axis_label = "Average Electric Usage (kVar)"
        title = "kVar"
    elif config.report_type == "kva":
        y_units = "kva"
        y_unit_map = "kva"
        y_axis_label = "Average Electric Usage (kVa)"
        title = "kVa"
    elif config.report_type == "powerfactor":
        y_units = "pf"
        y_unit_map = "pf"
        y_axis_label = "Average Power Factor"
        title = "Power Factor"
    else:
        abort(409)

    # make sure data exists, otherwise return an empty object
    if len(config.entity_ids) < 1 or config.entity_ids[0] is None:
        return_obj = [
            {
                'consumption-chart': [
                    {
                        'name': 'Reported Consumption',
                        'data': []
                    },
                    {
                        'name': 'Benchmark Consumption',
                        'data': []
                    }
                ],
                'difference-chart': [
                    {
                        'name': 'Reported Consumption',
                        'data': []
                    },
                    {
                        'name': 'Benchmark Consumption',
                        'data': []
                    }
                ],
                'yunits': y_units,
                'y_axis_label': y_axis_label,
                'xunits': x_units,
                'x_axis_label': x_axis_label,
                'title': title
            }
        ]
        return json.dumps(return_obj)

    # check to see if config is asking for a powerfactor report, as it requires a different function
    if config.report_type == 'powerfactor':
        data = get_pf_chart_data_web(config.entity_ids[0], config.report_year, config.benchmark_year, config.comparison_type, config.demand_type, g)
    else:
        # we only care about the first entity id since the configuration is being formatted before the request as [entity_id]
        data = get_total_energy_chart_data_web(config.entity_ids[0], config.report_year, config.benchmark_year,
                                               config.account_type, config.comparison_type, config.demand_type,
                                               y_units, y_unit_map, g)

    return_obj = [
        {
            'consumption-chart': [
                {
                    'name': 'Reported Consumption',
                    'data': data.reported_consumption
                },
                {
                    'name': 'Benchmark Consumption',
                    'data': data.benchmark_consumption
                }
            ],
            'difference-chart': [
                {
                    'name': 'Reported Consumption',
                    'data': data.diff
                },
                {
                    'name': 'Benchmark Consumption',
                    'data': data.benchmark_diff
                }
            ],
            'yunits': y_units,
            'y_axis_label': y_axis_label,
            'xunits': x_units,
            'x_axis_label': x_axis_label,
            'title': title
        }
    ]
    return json.dumps(return_obj)
def get_comparison_table_data(config, year):
    """
    Gets the rows for the data table after the chart
    :param config: ComponentReportingComparisonConfiguration
    :param year: year for the report
    :return: list of rows
    """
    rows = []
    row_dict_list = []
    bic_syrx_num = None
    bic_value = None
    bic_hours = None
    bic_ppsn = None

    syrx_nums_used = set()

    # get price for reporting group
    price = get_comparison_price('btu', config.submitted_to)

    for entity in config.component_ids:
        # since the application allows for groups, equipment, and equipment points to be selected, we need to get
        # the syrx nums for whatever the current reporting entity is.

        # only get the syrx nums which haven't been used yet
        syrx_nums = get_syrx_nums_from_entity(entity)
        syrx_nums = list(set(syrx_nums) - syrx_nums_used)

        # update list of used syrx nums
        syrx_nums_used |= set(syrx_nums)

        for syrx_num in syrx_nums:
            # get PPSN for the entity
            component_values = g.uow.compiled_point_records.get_ppsn([syrx_num], year)

            # convert the values
            units = g.uow.equipment.get_equipment_point_by_syrx_num(syrx_num)['units']
            conversion_factor = SharedReporting.get_component_point_conversion(units, config.unit)

            component_values['sum_value'] *= conversion_factor
            component_values['ppsn'] *= conversion_factor

            # add a dictionary of row data to the row_dict
            row_dict = construct_row(syrx_num, component_values, config.unit)

            row_dict['conversion_factor'] = conversion_factor

            # set the bic value if it has not yet been set
            if not bic_value:
                bic_syrx_num = syrx_num
                bic_ppsn = row_dict['ppsn']
                bic_value = row_dict['consumption']
                bic_hours = row_dict['hours']
            elif row_dict['ppsn'] < bic_ppsn:
                bic_syrx_num = syrx_num
                bic_ppsn = row_dict['ppsn']
                bic_value = row_dict['consumption']
                bic_hours = row_dict['hours']

            row_dict_list.append(row_dict)

    # using the bic_syrx_num, find the difference for each other component
    for row in row_dict_list:
        new_row = calculate_final_row_values(bic_syrx_num, bic_value, bic_hours, row, price)
        # update final rows value
        rows.append(new_row)

    return rows
def generate_consumptiontext_report(config, submitted_by_user, g):
    """
    Gathers data for consumption text report and generates it's PDF
    :param config: report configuration
    :param submitted_by_user: user who submitted the report
    :param g: g
    :return: report path
    """
    report_path = DataReports.generate_consumptiontext_report(config.report_year, config.benchmark_year, SharedReporting.generate_consumptiontext_report(config, 'sic', g), submitted_by_user, config.account_type)
    return report_path
def generate_variance_report(config, y_units, y_unit_map, submitted_by_user, submitted_to, g):
    """
    Gathers data for variance report and generates it's PDF
    :param config: report configuration
    :param y_units: y units
    :param y_unit_map: database column name for y units
    :param submitted_by_user: user who submitted the report
    :param submitted_to: group who the report is addressed to
    :param g: g
    :return: path to PDF of report
    """
    total_data = []
    for code in config.entity_ids:
        sic_code = g.uow.sic.get_by_code(code)

        # get all accounts for sic code
        group_descendants = g.uow.sic.get_group_descendants(code)
        accounts = []

        # check to make sure we should get electric accounts
        if config.account_type.lower() != 'gas':
            # get all electric accounts
            for desc in group_descendants:
                accounts += SharedReporting.get_accounts_for_group(desc, 'Electric', config.report_year, config.comparison_type, config.demand_type, g)
                accounts += SharedReporting.get_accounts_for_group(desc, 'Electric', config.benchmark_year, config.comparison_type, config.demand_type, g)

            # get all month utility, actual, benchmark, plan, variance ($), and variance (%) for every month in the report year
            electric_data = SharedReporting.get_variance_report_data(accounts, 'electric', config.report_year, config.benchmark_year, config.demand_type, y_units, y_unit_map, g)
        else:
            # create blank template so no null errors are thrown later
            electric_data = {"sitedata": [
                {"label": "",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "Variance ($)",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "Variance (%)",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}
            ]}

        accounts = []
        if config.account_type.lower() != 'electric':
            # get all gas accounts
            for desc in group_descendants:
                accounts += SharedReporting.get_accounts_for_group(desc, 'Gas', config.report_year, config.comparison_type, config.demand_type, g)
                accounts += SharedReporting.get_accounts_for_group(desc, 'Gas', config.benchmark_year, config.comparison_type, config.demand_type, g)

            # get gas data
            gas_data = SharedReporting.get_variance_report_data(accounts, 'gas', config.report_year, config.benchmark_year, config.demand_type, y_units, y_unit_map, g)
        else:
            # create blank template so no null errors are thrown later
            gas_data = {"sitedata": [
                {"label": "",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "Variance ($)",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
                {"label": "Variance (%)",
                 "data": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}
            ]}

        data = {"entity_name": sic_code["name"], "sitedata": [
            {"label": "",
             "data": []},
            {"label": "",
             "data": []},
            {"label": "",
             "data": []},
            {"label": "",
             "data": []},
            {"label": "Variance ($)",
             "data": []},
            {"label": "Variance (%)",
             "data": []}
        ]}

        # determine which site labels to use
        if config.account_type.lower() != 'electric':
            labels = [gas_data["sitedata"][0]["label"], gas_data["sitedata"][1]["label"], gas_data["sitedata"][2]["label"], gas_data["sitedata"][3]["label"]]
        else:
            labels = [electric_data["sitedata"][0]["label"], electric_data["sitedata"][1]["label"], electric_data["sitedata"][2]["label"], electric_data["sitedata"][3]["label"]]

        data["sitedata"][0]["label"] = labels[0]
        data["sitedata"][1]["label"] = labels[1]
        data["sitedata"][2]["label"] = labels[2]
        data["sitedata"][3]["label"] = labels[3]

        # add gas data to electric data
        utility_list = [a+b for a,b in zip(electric_data["sitedata"][0]["data"], gas_data["sitedata"][0]["data"])]
        actual_list = [a+b for a,b in zip(electric_data["sitedata"][1]["data"], gas_data["sitedata"][1]["data"])]
        benchmark_list = [a+b for a,b in zip(electric_data["sitedata"][2]["data"], gas_data["sitedata"][2]["data"])]
        plan_list = [a+b for a,b in zip(electric_data["sitedata"][3]["data"], gas_data["sitedata"][3]["data"])]
        cost_variance_list = [a+b for a,b in zip(electric_data["sitedata"][4]["data"], gas_data["sitedata"][4]["data"])]
        percent_variance_list = [a+b for a,b in zip(electric_data["sitedata"][5]["data"], gas_data["sitedata"][5]["data"])]

        # format all data to be used in the javascript
        utility_list = ["{:,d}".format(entry) for entry in utility_list]
        actual_list = ["{:,d}".format(entry) for entry in actual_list]
        benchmark_list = ["{:,d}".format(entry) for entry in benchmark_list]
        plan_list = ["{:,d}".format(entry) for entry in plan_list]
        percent_variance_list = ["{:,.2f}%".format(entry) for entry in percent_variance_list]

        locale.setlocale(locale.LC_ALL, '')
        cost_variance_list = [locale.currency(entry, grouping=True) for entry in cost_variance_list]

        # set the final data values
        data["entity_name"] = sic_code["name"]
        data["sitedata"][0]["data"] = utility_list
        data["sitedata"][1]["data"] = actual_list
        data["sitedata"][2]["data"] = benchmark_list
        data["sitedata"][3]["data"] = plan_list
        data["sitedata"][4]["data"] = cost_variance_list
        data["sitedata"][5]["data"] = percent_variance_list
        total_data.append(data)
    report_path = DataReports.generate_variance_report(total_data, config.report_year, config.benchmark_year, submitted_by_user, submitted_to)
    return report_path
def get_equipment_report_table(config):
    # get the reporting points (that can be converted to btu)
    equipment_points = g.uow.equipment.get_equipment_reporting_points(config.equipment_id)

    ret_obj = {
        'report_consumption_month': 0,
        'benchmark_consumption_month': 0,
        'report_consumption_year': 0,
        'benchmark_consumption_year': 0,
        'difference_month': 0,
        'difference_year': 0,
        'percent_month': 0,
        'percent_year': 0,
        'cost_month': 0,
        'cost_year': 0
    }

    # get the price for calculating cost savings
    price = find_price_for_equipment_points('mmbtu', config.equipment_id)

    # if they are all the same, find the price/unit
    for equipment_point in equipment_points:
        ep = g.uow.equipment.get_equipment_point_by_syrx_num(equipment_point['id'])
        conversion_factor = SharedReporting.get_component_point_conversion(ep['units'].lower(), 'mmbtu')

        temp_obj = calculate_totals_for_report(config, ep['units'], price, ep, conversion_factor)

        # update the ret_obj with the values
        ret_obj['report_consumption_month'] += temp_obj['report_consumption_month']
        ret_obj['benchmark_consumption_month'] += temp_obj['benchmark_consumption_month']
        ret_obj['report_consumption_year'] += temp_obj['report_consumption_year']
        ret_obj['benchmark_consumption_year'] += temp_obj['benchmark_consumption_year']
        ret_obj['cost_month'] += temp_obj['cost_month']
        ret_obj['cost_year'] += temp_obj['cost_year']

    # calculate final difference and percent difference
    ret_obj['difference_month'] = ret_obj['benchmark_consumption_month'] - ret_obj['report_consumption_month']
    ret_obj['difference_year'] = ret_obj['benchmark_consumption_year'] - ret_obj['report_consumption_year']

    if ret_obj['benchmark_consumption_month'] == 0:
        ret_obj['percent_month'] = "{:.2f}".format(0.0)
    else:
        ret_obj['percent_month'] = "{:.2f}".format((ret_obj['difference_month'] * 1.0 /
                                                    ret_obj['benchmark_consumption_month']) * 100.0)

    if ret_obj['benchmark_consumption_year'] == 0:
        ret_obj['percent_year'] = "{:.2f}".format(0.0)
    else:
        ret_obj['percent_year'] = "{:.2f}".format((ret_obj['difference_year'] * 1.0 /
                                                   ret_obj['benchmark_consumption_year']) * 100.0)

    # format the cost savings
    ret_obj['cost_month'] = "${:,.2f}".format(ret_obj['cost_month'])
    ret_obj['cost_year'] = "${:,.2f}".format(ret_obj['cost_year'])

    # format consumption numbers
    ret_obj['report_consumption_month'] = "{:,.2f}".format(ret_obj['report_consumption_month'])
    ret_obj['report_consumption_year'] = "{:,.2f}".format(ret_obj['report_consumption_year'])
    ret_obj['benchmark_consumption_month'] = "{:,.2f}".format(ret_obj['benchmark_consumption_month'])
    ret_obj['benchmark_consumption_year'] = "{:,.2f}".format(ret_obj['benchmark_consumption_year'])
    ret_obj['difference_month'] = "{:,.2f}".format(ret_obj['difference_month'])
    ret_obj['difference_year'] = "{:,.2f}".format(ret_obj['difference_year'])

    return json.dumps(ret_obj)
def get_total_energy_chart_data_web(sic_code, report_year, benchmark_year, account_type, comparison_type, demand_type,
                                    y_units, y_unit_map, g):
    """
    Gets the data for the energy consumption chart
    :param sic_code: sic code being reported on
    :param report_year: report year from configuration
    :param benchmark_year: benchmark year from configuration
    :param account_type: 'electric'/'gas'/'all'
    :param comparison_type: 'temp'/'dewpt'/'enthalpy'
    :param demand_type: 'all'/'peak'/'offpeak'
    :param y_units: y units used for reporting 'btu, mcf, etc'
    :param y_unit_map: mapping column for database (often 'sum_btu')
    :param g: g
    :return: object containing all necessary information
    """

    # determine if demand will be included in query
    consider_demand_type = False
    if demand_type != 'all':
        consider_demand_type = True

    same_year = report_year == benchmark_year

    # get unit factor for the selected y units
    unit_factor = SharedReporting.get_factor(y_units, y_unit_map)
    data = TotalEnergyData()

    # get group descendants of sic code
    descendants = g.uow.sic.get_group_descendants(sic_code)
    accounts = []

    # get all accounts for each group for the desired year
    for gr in descendants:
        accounts += SharedReporting.get_accounts_for_group(gr, account_type, report_year, comparison_type, demand_type, g)
        if not same_year:
            accounts += SharedReporting.get_accounts_for_group(gr, account_type, benchmark_year, comparison_type, demand_type, g)

    if len(accounts) < 1:
        benchmark_data = []
    else:
        benchmark_data = g.uow.compiled_energy_records.get_compiled_energy_records_for_report(accounts, data_field_name=y_unit_map, consider_demand_type=consider_demand_type)

    # group the data by value
    grouped = defaultdict(list)

    for d in benchmark_data:
        grouped[d['group']['value']].append(d)

    reported_consumption = []
    diff = []
    benchmark_diff = []
    benchmark_consumption = []

    # get the distinct values for the group
    grouped_keys = list(grouped.keys())
    grouped_keys.sort()

    # if the report year and benchmark year are the same, it will be handled differently
    if same_year:
        for value in grouped_keys:
            entry = grouped[value]
            record_value = entry[0]['reduction'][y_unit_map] * unit_factor / entry[0]['reduction']['sum_hours_in_record']
            reported_consumption.append([value, round(record_value, 5)])
            diff.append([value, 0])
            benchmark_consumption.append([value, round(record_value, 5)])
            benchmark_diff.append([value, 0])
    else:
        # loop through every distinct value and get all of the records for it
        for value in grouped_keys:
            entry = grouped[value]
            if len(entry) > 1:
                report_record = 0
                benchmark_record = 0
                report_avg_size = 0
                benchmark_avg_size = 0
                benchmark_record_hours = 0
                for record in entry:
                    if record['group']['year'] == report_year:
                        report_record_hours = record['reduction']['sum_hours_in_record']

                        # normalize the values
                        report_record = round(record['reduction'][y_unit_map] * unit_factor / report_record_hours, 5)
                        reported_consumption.append([value, report_record])

                        report_avg_size = record['reduction']['sum_size_normalization'] * 1.0 / report_record_hours
                    elif record['group']['year'] == benchmark_year:
                        benchmark_record_hours = record['reduction']['sum_hours_in_record']

                        # get the size and record value to be normalized later
                        benchmark_avg_size = record['reduction']['sum_size_normalization'] * 1.0 / benchmark_record_hours
                        benchmark_record = record['reduction'][y_unit_map] * unit_factor

                # normalize the benchmark value
                size_ratio = report_avg_size * 1.0 / benchmark_avg_size
                benchmark_record *= size_ratio
                benchmark_record /= benchmark_record_hours

                # add normalized value to charts
                benchmark_consumption.append([value, round(benchmark_record, 5)])
                benchmark_diff.append([value, 0])
                diff.append([value, benchmark_record - report_record])

        data.reported_consumption = reported_consumption
        data.benchmark_consumption = benchmark_consumption
        data.diff = diff
        data.benchmark_diff = benchmark_diff
        return data
def generate_sic_report(config):
    return json.dumps(SharedReporting.generate_consumptiontext_report(config, 'sic', g))
def get_report(config):
    report_name = "DefaultReportName"
    report_path = ""

    # make sure submitted_to isn't empty
    if not config.submitted_to:
        abort(400)

    submitted_by_user = g.uow.users.get_user_by_id(session["current_user"]["id"])
    submitted_to = config.submitted_to

    # get submitted_by and submitted_to
    submitted_by_user, submitted_to = SharedReporting.get_submitted_contacts(submitted_by_user, submitted_to, g)

    total_energy_chart_info = TotalEnergyDataContainer()

    # determine the x units
    x_units = "F"
    total_energy_chart_info.x_axis_label = "Temperature (" + x_units + ")"
    if config.comparison_type == "dewpt":
        x_units = "Dewpt"
        total_energy_chart_info.x_axis_label = "Dewpt"
    elif config.comparison_type == "enthalpy":
        x_units = "Enthalpy"
        total_energy_chart_info.x_axis_label = "Enthalpy"

    # get actual y units to send back, and get their equivalent column in the database
    # then call the proper report function determined by config.report_type
    if config.report_type == "consumption":
        report_name = "Consumption_Report"
        if config.account_type.lower() == "electric":
            y_units = config.electric_units
            y_unit_map = 'sum_btu'
            total_energy_chart_info.title = 'Total Energy Usage - Electric'
        elif config.account_type.lower() == 'gas':
            y_units = config.gas_units
            y_unit_map = 'sum_btu'
            total_energy_chart_info.title = 'Total Energy Usage - Gas'
        else:
            y_units = config.btu_units
            y_unit_map = "sum_btu"
            total_energy_chart_info.title = 'Total Energy Usage'
        total_energy_chart_info.y_axis_label = 'Average Energy Usage (' + SharedReporting.get_y_unit_label(y_units) + ')'

        # generate consumption report
        report_path = generate_consumption_report(config, y_units, y_unit_map, total_energy_chart_info, submitted_by_user, submitted_to, g)
    elif config.report_type == "variance":
        report_name = "Variance Report"
        if config.account_type == "electric":
            y_units = config.electric_units
        elif config.account_type == "gas":
            y_units = config.gas_units
        else:
            y_units = config.btu_units
        y_unit_map = "sum_btu"
        report_path = generate_variance_report(config, y_units, y_unit_map, submitted_by_user, submitted_to, g)
    elif config.report_type == "kvar":
        report_name = "kVArh"
        y_units = "kvar"
        y_unit_map = "sum_kvar"
        total_energy_chart_info.y_axis_label = "Average Electric Usage (kVar)"
        total_energy_chart_info.title = "kVar"
        report_path = generate_kvarh_report(config, y_units, y_unit_map, total_energy_chart_info, submitted_by_user, submitted_to, g)
    elif config.report_type == "text":
        report_name = "Consumption Text Report"
        report_path = generate_consumptiontext_report(config, submitted_by_user, g)
    elif config.report_type == "kva":
        report_name = "kVah"
        y_units = "kva"
        y_unit_map = "kva"
        total_energy_chart_info.y_axis_label = "Average Electric Usage (kVa)"
        total_energy_chart_info.title = "kVa"
        report_path = generate_kvah_report(config, y_units, y_unit_map, total_energy_chart_info, submitted_by_user, submitted_to, g)
    elif config.report_type == "powerfactor":
        report_name = "Power Factor"
        y_units = "pf"
        y_unit_map = "pf"
        total_energy_chart_info.y_axis_label = "Average Power Factor"
        total_energy_chart_info.title = "Power Factor"
        report_path = generate_powerfactor_report(config, y_units, y_unit_map, total_energy_chart_info, submitted_by_user, submitted_to, g)
    elif config.report_type == "peak":
        report_name = "Peak Report"
        report_path = generate_peak_report(config, submitted_by_user, submitted_to, g)

    return send_file(report_path, mimetype='application/pdf', as_attachment=True, attachment_filename=report_name + '.pdf')
def generate_naics_report(config):
    return json.dumps(SharedReporting.generate_consumptiontext_report(config, 'naics', g))
def calculate_pf_data(account_group, report_year, benchmark_year, same_year):
    """
    Calculates the powerfactor data for the account
    :param account_group: data for the account grouped by value
    :param report_year: current year for the report data
    :param benchmark_year: benchmark year to compare it to
    :param same_year: boolean value stating whether report_year == benchmark_year
    :return: TotalEnergyData
    """
    # initialize all variables for this account/year combination
    reported_consumption = []
    diff = []
    benchmark_diff = []
    benchmark_consumption = []

    grouped_keys = list(account_group.keys())
    grouped_keys.sort()

    kwh_unit_factor = SharedReporting.get_factor('kwh', 'sum_btu')

    # if the benchmark year and current year are the same they will be handled differently
    if same_year:
        for value in grouped_keys:
            entry = account_group[value][0]

            # calculate powerfactor
            record_kwh = entry["reduction"]["sum_btu"] * kwh_unit_factor
            record_kvar = math.sqrt(math.pow(record_kwh, 2) + math.pow(entry['reduction']['sum_kvar'], 2))
            record_pf = record_kwh * 1.0 / record_kvar

            # update lists of data
            reported_consumption.append([value, round(record_pf, 5)])
            diff.append([value, 0])
            benchmark_consumption.append([value, round(record_pf, 5)])
            benchmark_diff.append([value, 0])
    else:
        # loop through each entry in the keys
        for value in grouped_keys:
            entry = account_group[value]

            # if the data exists for both years
            if len(entry) > 1:
                record_pf = 0
                reported_avg_size = 0
                benchmark_avg_size = 0
                benchmark_record_btu_normalized = 0
                benchmark_record_kvar_normalized = 0
                for record in entry:
                    if record['group']['year'] == report_year:
                        # calculate powerfactor
                        record_kwh = record['reduction']['sum_btu'] * kwh_unit_factor
                        record_kvar = math.sqrt(math.pow(record_kwh, 2) + math.pow(record['reduction']['sum_kvar'], 2))
                        record_pf = record_kwh * 1.0 / record_kvar

                        report_record_hours = record['reduction']['sum_hours_in_record']
                        reported_avg_size = record['reduction']['sum_size_normalization'] * 1.0 / report_record_hours

                        # update list
                        reported_consumption.append([value, round(record_pf, 5)])
                    elif record['group']['year'] == benchmark_year:
                        benchmark_avg_size = record['reduction']['sum_size_normalization'] * 1.0 / record['reduction']['sum_hours_in_record']
                        benchmark_record_btu_normalized = record['reduction']['sum_btu']
                        benchmark_record_kvar_normalized = record['reduction']['sum_kvar']

                # normalize the btu and kvar to properly calculate pf
                size_ratio = reported_avg_size * 1.0 / benchmark_avg_size
                benchmark_record_btu_normalized *= size_ratio
                benchmark_record_kvar_normalized *= size_ratio
                benchmark_kwh = benchmark_record_btu_normalized * kwh_unit_factor
                benchmark_kvar = math.sqrt(math.pow(benchmark_kwh, 2) + math.pow(benchmark_record_kvar_normalized, 2))
                benchmark_pf = benchmark_kwh * 1.0 / benchmark_kvar

                # update lists
                benchmark_consumption.append([value, round(benchmark_pf, 5)])
                benchmark_diff.append([value, 0])
                diff.append([value, round(benchmark_pf - record_pf, 5)])

    # create a new data object to be returned
    data = TotalEnergyData()

    data.reported_consumption = reported_consumption
    data.benchmark_consumption = benchmark_consumption
    data.diff = diff
    data.benchmark_diff = benchmark_diff

    return data