Example #1
0
def process_site(
        sess, site, month_start, month_finish, forecast_date, tmp_file):
    site_code = site.code
    associates = []
    sources = set()
    generator_types = set()
    metering_type = 'no-supply'
    problem = ''
    month_data = {}

    for stream_name in [
            'import-net', 'export-net', 'import-gen', 'export-gen',
            'import-3rd-party', 'export-3rd-party', 'msp', 'used',
            'used-3rd-party']:
        month_data[stream_name + '-kwh'] = 0
        month_data[stream_name + '-gbp'] = 0

    billed_gbp = 0
    billed_kwh = 0

    for group in site.groups(sess, month_start, month_finish, False):
        for cand_site in group.sites:
            cand_site_code = cand_site.code
            if cand_site_code != site_code and \
                    cand_site_code not in associates:
                associates.append(cand_site_code)
        for cand_supply in group.supplies:
            sources.add(cand_supply.source.code)
            if cand_supply.generator_type is not None:
                generator_types.add(cand_supply.generator_type.code)
            for cand_era in cand_supply.find_eras(
                    sess, group.start_date, group.finish_date):
                if metering_type != 'hh':
                    if cand_era.pc.code == '00':
                        metering_type = 'hh'
                    elif metering_type != 'amr':
                        if len(cand_era.channels) > 0:
                            metering_type = 'amr'
                        elif metering_type != 'nhh':
                            if cand_era.mtc.meter_type.code not in [
                                    'UM', 'PH']:
                                metering_type = 'nhh'
                            else:
                                metering_type = 'unmetered'

    for group in site.groups(sess, month_start, month_finish, True):
        if group.start_date > start_date:
            chunk_start = group.start_date
        else:
            chunk_start = start_date

        if group.finish_date > finish_date:
            chunk_finish = finish_date
        else:
            chunk_finish = group.finish_date

        for supply in group.supplies:
            source_code = supply.source.code

            for era in sess.query(Era).filter(
                    Era.supply == supply, Era.start_date <= chunk_finish,
                    or_(
                        Era.finish_date == null(),
                        Era.finish_date >= chunk_start)):
                tmp_file.write(' ')

                # GBP

                if era.start_date > chunk_start:
                    bill_start = era.start_date
                else:
                    bill_start = chunk_start
                if hh_after(era.finish_date, chunk_finish):
                    bill_finish = chunk_finish
                else:
                    bill_finish = era.finish_date

                supply_source = None
                supplier_contract = era.imp_supplier_contract
                if supplier_contract is not None:
                    supply_source = computer.SupplySource(
                        sess, bill_start, bill_finish, forecast_date, era,
                        True, tmp_file, caches)
                    if supply_source.measurement_type not in ['hh', 'amr']:
                        kwh = sum(
                            hh['msp-kwh'] for hh in supply_source.hh_data)
                        if source_code in ('net', 'gen-net'):
                            month_data['import-net-kwh'] += kwh
                        elif source_code in ('3rd-party', '3rd-party-reverse'):
                            month_data['import-3rd-party-kwh'] += kwh

                    import_vb_function = computer.contract_func(
                        caches, supplier_contract, 'virtual_bill', tmp_file)
                    if import_vb_function is None:
                        problem += "Can't find the virtual_bill function in " \
                            "the supplier contract. "
                    else:
                        import_vb_function(supply_source)
                        v_bill = supply_source.supplier_bill

                        if 'problem' in v_bill and len(v_bill['problem']) > 0:
                            problem += 'Supplier Problem: ' + v_bill['problem']

                        try:
                            gbp = v_bill['net-gbp']
                        except KeyError:
                            problem += 'For the supply ' + \
                                supply_source.mpan_core + \
                                ' the virtual bill ' + str(v_bill) + \
                                ' from the contract ' + \
                                supplier_contract.getName() + \
                                ' does not contain the net-gbp key.'
                        if source_code in ('net', 'gen-net'):
                            month_data['import-net-gbp'] += gbp
                        elif source_code in ('3rd-party', '3rd-party-reverse'):
                            month_data['import-3rd-party-gbp'] += gbp

                if supply_source is None:
                    supply_source = computer.SupplySource(
                        sess, bill_start, bill_finish, forecast_date, era,
                        False, tmp_file, caches)
                dc_contract = era.hhdc_contract
                supply_source.contract_func(
                    dc_contract, 'virtual_bill')(supply_source)
                dc_bill = supply_source.dc_bill
                dc_gbp = dc_bill['net-gbp']
                if 'problem' in dc_bill and len(dc_bill['problem']) > 0:
                    problem += 'DC Problem: ' + dc_bill['problem']

                mop_contract = era.mop_contract
                mop_bill_function = supply_source.contract_func(
                    mop_contract, 'virtual_bill')
                mop_bill_function(supply_source)
                mop_bill = supply_source.mop_bill
                mop_gbp = mop_bill['net-gbp']
                if 'problem' in mop_bill and len(mop_bill['problem']) > 0:
                    problem += 'MOP Problem: ' + mop_bill['problem']

                if source_code in ('3rd-party', '3rd-party-reverse'):
                    month_data['import-3rd-party-gbp'] += dc_gbp + mop_gbp
                else:
                    month_data['import-net-gbp'] += dc_gbp + mop_gbp

            for bill in sess.query(Bill).filter(
                    Bill.supply == supply, Bill.start_date <= chunk_finish,
                    Bill.finish_date >= chunk_start):
                bill_start = bill.start_date
                bill_finish = bill.finish_date
                bill_duration = totalseconds(bill_finish - bill_start) + \
                    (30 * 60)
                overlap_duration = totalseconds(
                    min(bill_finish, chunk_finish) -
                    max(bill_start, chunk_start)) + (30 * 60)
                overlap_proportion = float(overlap_duration) / bill_duration
                billed_gbp += overlap_proportion * float(bill.net)
                billed_kwh += overlap_proportion * float(bill.kwh)

        displaced_era = computer.displaced_era(
            sess, group, chunk_start, chunk_finish)
        site_ds = computer.SiteSource(
            sess, site, chunk_start, chunk_finish, forecast_date, tmp_file,
            caches, displaced_era)
        if displaced_era is not None:
            computer.contract_func(
                caches, displaced_era.imp_supplier_contract,
                'displaced_virtual_bill', tmp_file)(site_ds)
            month_data['msp-gbp'] += site_ds.supplier_bill['net-gbp']

        for stream_name in (
                'import-3rd-party', 'export-3rd-party', 'import-net',
                'export-net', 'import-gen', 'export-gen', 'msp'):
            name = stream_name + '-kwh'
            month_data[name] += sum(hh[name] for hh in site_ds.hh_data)

    month_data['used-3rd-party-kwh'] = \
        month_data['import-3rd-party-kwh'] - \
        month_data['export-3rd-party-kwh']
    month_data['used-3rd-party-gbp'] = month_data['import-3rd-party-gbp']
    month_data['used-gbp'] += \
        month_data['import-net-gbp'] + month_data['msp-gbp'] + \
        month_data['used-3rd-party-gbp']

    month_data['used-kwh'] += month_data['msp-kwh'] + \
        month_data['used-3rd-party-kwh'] + month_data['import-net-kwh']

    result = [
        site.code, site.name, ','.join(associates),
        ','.join(sorted(list(sources))),
        '.'.join(sorted(list(generator_types))),
        hh_format(month_finish), month_data['import-net-kwh'],
        month_data['msp-kwh'], month_data['export-net-kwh'],
        month_data['used-kwh'], month_data['export-gen-kwh'],
        month_data['import-gen-kwh'], month_data['import-3rd-party-kwh'],
        month_data['export-3rd-party-kwh'], month_data['import-net-gbp'],
        month_data['msp-gbp'], 0, month_data['used-gbp'],
        month_data['used-3rd-party-gbp'], billed_kwh, billed_gbp,
        metering_type, problem]
    return result
Example #2
0
def content():
    global scenario_props
    sess = None
    try:
        sess = db.session()
        if scenario_props is None:
            scenario_contract = Contract.get_supplier_by_id(sess, scenario_id)
            scenario_props = scenario_contract.make_properties()
            base_name.append(scenario_contract.name)

        for contract in sess.query(Contract).join(MarketRole).filter(
                MarketRole.code == 'Z'):
            try:
                props = scenario_props[contract.name]
            except KeyError:
                continue

            try:
                rate_start = props['start_date']
            except KeyError:
                raise UserException(
                    "In " + scenario_contract.name + " for the rate " +
                    contract.name + " the start_date is missing.")

            if rate_start is not None:
                rate_start = rate_start.replace(tzinfo=pytz.utc)

            lib = globals()[contract.name]

            if hasattr(lib, 'create_future_func'):
                future_funcs[contract.id] = {
                    'start_date': rate_start,
                    'func': lib.create_future_func(
                        props['multiplier'], props['constant'])}

        start_date = scenario_props['scenario_start']
        if start_date is None:
            start_date = datetime.datetime(
                now.year, now.month, 1, tzinfo=pytz.utc)
        else:
            start_date = start_date.replace(tzinfo=pytz.utc)

        base_name.append(
            hh_format(start_date).replace(' ', '_').replace(':', '').
            replace('-', ''))
        months = scenario_props['scenario_duration']
        base_name.append('for')
        base_name.append(str(months))
        base_name.append('months')
        finish_date = start_date + relativedelta(months=months)

        if 'kwh_start' in scenario_props:
            kwh_start = scenario_props['kwh_start']
        else:
            kwh_start = None

        if kwh_start is None:
            kwh_start = computer.forecast_date()
        else:
            kwh_start = kwh_start.replace(tzinfo=pytz.utc)

        sites = sess.query(Site).join(SiteEra).join(Era).filter(
            Era.start_date <= finish_date,
            or_(
                Era.finish_date == null(),
                Era.finish_date >= start_date)).distinct()
        if site_id is not None:
            site = Site.get_by_id(sess, site_id)
            sites = sites.filter(Site.id == site.id)
            base_name.append('site')
            base_name.append(site.code)
        if supply_id is not None:
            supply = Supply.get_by_id(sess, supply_id)
            base_name.append('supply')
            base_name.append(str(supply.id))
            sites = sites.filter(Era.supply == supply)

        running_name, finished_name = dloads.make_names(
            '_'.join(base_name) + '.ods', user)

        rf = open(running_name, "wb")
        f = odswriter.writer(rf, '1.1')
        group_tab = f.new_sheet("Site Level")
        sup_tab = f.new_sheet("Supply Level")
        changes = defaultdict(list, {})

        try:
            kw_changes = scenario_props['kw_changes']
        except KeyError:
            kw_changes = ''

        for row in csv.reader(StringIO.StringIO(kw_changes)):
            if len(''.join(row).strip()) == 0:
                continue
            if len(row) != 4:
                raise UserException(
                    "Can't interpret the row " + str(row) + " it should be of "
                    "the form SITE_CODE, USED / GENERATED, DATE, MULTIPLIER")
            site_code, typ, date_str, kw_str = row
            date = datetime.datetime.strptime(
                date_str.strip(), "%Y-%m-%d").replace(tzinfo=pytz.utc)
            changes[site_code.strip()].append(
                {
                    'type': typ.strip(), 'date': date,
                    'multiplier': float(kw_str)})

        sup_header_titles = [
            'imp-mpan-core', 'exp-mpan-core', 'metering-type', 'source',
            'generator-type', 'supply-name', 'msn', 'pc', 'site-id',
            'site-name', 'associated-site-ids', 'month']
        site_header_titles = [
            'site-id', 'site-name', 'associated-site-ids', 'month',
            'metering-type', 'sources', 'generator-types']
        summary_titles = [
            'import-net-kwh', 'export-net-kwh', 'import-gen-kwh',
            'export-gen-kwh', 'import-3rd-party-kwh', 'export-3rd-party-kwh',
            'displaced-kwh', 'used-kwh', 'used-3rd-party-kwh',
            'import-net-gbp', 'export-net-gbp', 'import-gen-gbp',
            'export-gen-gbp', 'import-3rd-party-gbp', 'export-3rd-party-gbp',
            'displaced-gbp', 'used-gbp', 'used-3rd-party-gbp',
            'billed-import-net-kwh', 'billed-import-net-gbp']

        title_dict = {}
        for cont_type, con_attr in (
                ('mop', Era.mop_contract), ('dc', Era.hhdc_contract),
                ('imp-supplier', Era.imp_supplier_contract),
                ('exp-supplier', Era.exp_supplier_contract)):
            titles = []
            title_dict[cont_type] = titles
            conts = sess.query(Contract).join(con_attr) \
                .join(Era.supply).join(Source).filter(
                    Era.start_date <= start_date,
                    or_(
                        Era.finish_date == null(),
                        Era.finish_date >= start_date),
                    Source.code.in_(('net', '3rd-party'))
                ).distinct().order_by(Contract.id)
            if supply_id is not None:
                conts = conts.filter(Era.supply_id == supply_id)
            for cont in conts:
                title_func = computer.contract_func(
                    report_context, cont, 'virtual_bill_titles', None)
                if title_func is None:
                    raise Exception(
                        "For the contract " + cont.name +
                        " there doesn't seem to be a "
                        "'virtual_bill_titles' function.")
                for title in title_func():
                    if title not in titles:
                        titles.append(title)

        sup_tab.writerow(
            sup_header_titles + summary_titles + [None] +
            ['mop-' + t for t in title_dict['mop']] +
            [None] + ['dc-' + t for t in title_dict['dc']] + [None] +
            ['imp-supplier-' + t for t in title_dict['imp-supplier']] +
            [None] + ['exp-supplier-' + t for t in title_dict['exp-supplier']])
        group_tab.writerow(site_header_titles + summary_titles)

        sites = sites.all()
        month_start = start_date
        while month_start < finish_date:
            month_finish = month_start + relativedelta(months=1) - HH
            for site in sites:
                site_changes = changes[site.code]
                site_associates = set()
                site_category = None
                site_sources = set()
                site_gen_types = set()
                site_month_data = defaultdict(int)
                for group in site.groups(
                        sess, month_start, month_finish, False):
                    site_associates.update(
                        set(
                            s.code for s in group.sites
                            if s.code != site.code))
                    for cand_supply in group.supplies:
                        site_sources.add(cand_supply.source.code)
                        if cand_supply.generator_type is not None:
                            site_gen_types.add(cand_supply.generator_type.code)
                        for cand_era in cand_supply.find_eras(
                                sess, group.start_date, group.finish_date):
                            if site_category != 'hh':
                                if cand_era.pc.code == '00':
                                    site_category = 'hh'
                                elif site_category != 'amr':
                                    if len(cand_era.channels) > 0:
                                        site_category = 'amr'
                                    elif site_category != 'nhh':
                                        if cand_era.mtc.meter_type.code \
                                                not in ['UM', 'PH']:
                                            site_category = 'nhh'
                                        else:
                                            site_category = 'unmetered'

                for group in site.groups(
                        sess, month_start, month_finish, True):
                    calcs = []
                    deltas = defaultdict(int)
                    group_associates = set(
                        s.code for s in group.sites if s.code != site.code)
                    for supply in group.supplies:
                        if supply_id is not None and supply.id != supply_id:
                            continue
                        for era in sess.query(Era).join(Supply) \
                                .join(Source).filter(
                                    Era.supply == supply,
                                    Era.start_date <= group.finish_date, or_(
                                        Era.finish_date == null(),
                                        Era.finish_date >= group.start_date)):

                            if era.start_date > group.start_date:
                                ss_start = era.start_date
                            else:
                                ss_start = group.start_date

                            if hh_before(era.finish_date, group.finish_date):
                                ss_finish = era.finish_date
                            else:
                                ss_finish = group.finish_date

                            if era.imp_mpan_core is None:
                                imp_ss = None
                            else:
                                imp_ss = SupplySource(
                                    sess, ss_start, ss_finish, kwh_start, era,
                                    True, None, report_context)

                            if era.exp_mpan_core is None:
                                exp_ss = None
                                measurement_type = imp_ss.measurement_type
                            else:
                                exp_ss = SupplySource(
                                    sess, ss_start, ss_finish, kwh_start, era,
                                    False, None, report_context)
                                measurement_type = exp_ss.measurement_type

                            order = meter_order[measurement_type]
                            calcs.append(
                                (
                                    order, era.imp_mpan_core,
                                    era.exp_mpan_core, imp_ss, exp_ss))

                            if imp_ss is not None and len(era.channels) == 0:
                                for hh in imp_ss.hh_data:
                                    deltas[hh['start-date']] += hh['msp-kwh']

                    imp_net_delts = defaultdict(int)
                    exp_net_delts = defaultdict(int)
                    imp_gen_delts = defaultdict(int)

                    displaced_era = computer.displaced_era(
                        sess, group, group.start_date, group.finish_date)
                    site_ds = computer.SiteSource(
                        sess, site, group.start_date, group.finish_date,
                        kwh_start, None, report_context, displaced_era)

                    for hh in site_ds.hh_data:
                        try:
                            delta = deltas[hh['start-date']]
                            hh['import-net-kwh'] += delta
                            hh['used-kwh'] += delta
                        except KeyError:
                            pass

                    for hh in site_ds.hh_data:
                        for change in site_changes:
                            if change['type'] == 'used' and \
                                    change['date'] <= hh['start-date']:
                                used = change['multiplier'] * hh['used-kwh']
                                exp_net = max(
                                    0, hh['import-gen-kwh'] -
                                    hh['export-gen-kwh'] -
                                    used)
                                exp_net_delt = exp_net - hh['export-net-kwh']
                                exp_net_delts[hh['start-date']] += exp_net_delt
                                displaced = hh['import-gen-kwh'] - \
                                    hh['export-gen-kwh'] - exp_net
                                imp_net = used - displaced
                                imp_delt = imp_net - hh['import-net-kwh']
                                imp_net_delts[hh['start-date']] += imp_delt

                                hh['import-net-kwh'] = imp_net
                                hh['used-kwh'] = used
                                hh['export-net-kwh'] = exp_net
                                hh['msp-kwh'] = displaced
                            elif change['type'] == 'generated' and \
                                    change['date'] <= hh['start-date']:
                                imp_gen = change['multiplier'] * \
                                    hh['import-gen-kwh']
                                imp_gen_delt = imp_gen - hh['import-gen-kwh']
                                exp_net = max(
                                    0, imp_gen - hh['export-gen-kwh'] -
                                    hh['used-kwh'])
                                exp_net_delt = exp_net - hh['export-net-kwh']
                                exp_net_delts[hh['start-date']] += exp_net_delt

                                displaced = imp_gen - hh['export-gen-kwh'] - \
                                    exp_net

                                imp_net = hh['used-kwh'] - displaced
                                imp_net_delt = imp_net - hh['import-net-kwh']
                                imp_net_delts[hh['start-date']] += imp_net_delt

                                imp_gen_delts[hh['start-date']] += imp_gen_delt

                                hh['import-net-kwh'] = imp_net
                                hh['export-net-kwh'] = exp_net
                                hh['import-gen-kwh'] = imp_gen
                                hh['msp-kwh'] = displaced

                    if displaced_era is not None and supply_id is None:
                        month_data = {}
                        for sname in (
                                'import-net', 'export-net', 'import-gen',
                                'export-gen', 'import-3rd-party',
                                'export-3rd-party', 'msp', 'used',
                                'used-3rd-party', 'billed-import-net'):
                            for xname in ('kwh', 'gbp'):
                                month_data[sname + '-' + xname] = 0

                        month_data['used-kwh'] = \
                            month_data['displaced-kwh'] = \
                            sum(hh['msp-kwh'] for hh in site_ds.hh_data)

                        disp_supplier_contract = \
                            displaced_era.imp_supplier_contract
                        disp_vb_function = computer.contract_func(
                            report_context, disp_supplier_contract,
                            'displaced_virtual_bill', None)
                        if disp_vb_function is None:
                            raise UserException(
                                "The supplier contract " +
                                disp_supplier_contract.name +
                                " doesn't have the displaced_virtual_bill() "
                                "function.")
                        disp_vb_function(site_ds)
                        disp_supplier_bill = site_ds.supplier_bill

                        try:
                            gbp = disp_supplier_bill['net-gbp']
                        except KeyError:
                            disp_supplier_bill['problem'] += \
                                'For the supply ' + \
                                site_ds.mpan_core + \
                                ' the virtual bill ' + \
                                str(disp_supplier_bill) + \
                                ' from the contract ' + \
                                disp_supplier_contract.name + \
                                ' does not contain the net-gbp key.'

                        month_data['used-gbp'] = \
                            month_data['displaced-gbp'] = \
                            site_ds.supplier_bill['net-gbp']

                        out = [
                            None, None, displaced_era.make_meter_category(),
                            'displaced', None, None, None, None, site.code,
                            site.name,
                            ','.join(sorted(list(group_associates))),
                            month_finish] + \
                            [month_data[t] for t in summary_titles]

                        sup_tab.writerow(out)
                        for k, v in month_data.iteritems():
                            site_month_data[k] += v
                    for i, (
                            order, imp_mpan_core, exp_mpan_core, imp_ss,
                            exp_ss) in enumerate(sorted(calcs)):
                        if imp_ss is None:
                            era = exp_ss.era
                        else:
                            era = imp_ss.era
                        supply = era.supply
                        source = supply.source
                        source_code = source.code
                        site_sources.add(source_code)
                        month_data = {}
                        for name in (
                                'import-net', 'export-net', 'import-gen',
                                'export-gen', 'import-3rd-party',
                                'export-3rd-party', 'displaced', 'used',
                                'used-3rd-party', 'billed-import-net'):
                            for sname in ('kwh', 'gbp'):
                                month_data[name + '-' + sname] = 0

                        if source_code == 'net':
                            delts = imp_net_delts
                        elif source_code == 'gen':
                            delts = imp_gen_delts
                        else:
                            delts = []

                        if len(delts) > 0 and imp_ss is not None:
                            for hh in imp_ss.hh_data:
                                diff = hh['msp-kwh'] + delts[hh['start-date']]
                                if diff < 0:
                                    hh['msp-kwh'] = 0
                                    hh['msp-kw'] = 0
                                    delts[hh['start-date']] -= hh['msp-kwh']
                                else:
                                    hh['msp-kwh'] += delts[hh['start-date']]
                                    hh['msp-kw'] += hh['msp-kwh'] / 2
                                    del delts[hh['start-date']]

                            left_kwh = sum(delts.values())
                            if left_kwh > 0:
                                first_hh = imp_ss.hh_data[0]
                                first_hh['msp-kwh'] += left_kwh
                                first_hh['msp-kw'] += left_kwh / 2

                        imp_supplier_contract = era.imp_supplier_contract
                        if imp_supplier_contract is not None:
                            import_vb_function = computer.contract_func(
                                report_context, imp_supplier_contract,
                                'virtual_bill', None)
                            if import_vb_function is None:
                                raise UserException(
                                    "The supplier contract " +
                                    imp_supplier_contract.name +
                                    " doesn't have the virtual_bill() "
                                    "function.")
                            import_vb_function(imp_ss)
                            imp_supplier_bill = imp_ss.supplier_bill

                            try:
                                gbp = imp_supplier_bill['net-gbp']
                            except KeyError:
                                imp_supplier_bill['problem'] += \
                                    'For the supply ' + \
                                    imp_ss.mpan_core + \
                                    ' the virtual bill ' + \
                                    str(imp_supplier_bill) + \
                                    ' from the contract ' + \
                                    imp_supplier_contract.name + \
                                    ' does not contain the net-gbp key.'
                            if source_code in ('net', 'gen-net'):
                                month_data['import-net-gbp'] += gbp
                                month_data['used-gbp'] += gbp
                            elif source_code == '3rd-party':
                                month_data['import-3rd-party-gbp'] += gbp
                                month_data['used-gbp'] += gbp
                            elif source_code == '3rd-party-reverse':
                                month_data['export-3rd-party-gbp'] += gbp
                                month_data['used-gbp'] -= gbp

                            kwh = sum(
                                hh['msp-kwh'] for hh in imp_ss.hh_data)

                            if source_code in ('net', 'gen-net'):
                                month_data['import-net-kwh'] += kwh
                                month_data['used-kwh'] += kwh
                            elif source_code == '3rd-party':
                                month_data['import-3rd-party-kwh'] += kwh
                                month_data['used-kwh'] += kwh
                            elif source_code == '3rd-party-reverse':
                                month_data['export-3rd-party-kwh'] += kwh
                                month_data['used-kwh'] -= kwh
                            elif source_code in ('gen', 'gen-net'):
                                month_data['import-gen-kwh'] += kwh

                        exp_supplier_contract = era.exp_supplier_contract
                        if exp_supplier_contract is None:
                            kwh = sess.query(
                                func.coalesce(
                                    func.sum(
                                        cast(HhDatum.value, Float)), 0)). \
                                join(Channel).filter(
                                    Channel.era == era,
                                    Channel.channel_type == 'ACTIVE',
                                    Channel.imp_related == false()).scalar()
                            if source_code == 'gen':
                                month_data['export-net-kwh'] += kwh
                        else:
                            export_vb_function = computer.contract_func(
                                report_context, exp_supplier_contract,
                                'virtual_bill', None)
                            export_vb_function(exp_ss)

                            exp_supplier_bill = exp_ss.supplier_bill
                            try:
                                gbp = exp_supplier_bill['net-gbp']
                            except KeyError:
                                exp_supplier_bill['problem'] += \
                                    'For the supply ' + \
                                    imp_ss.mpan_core + \
                                    ' the virtual bill ' + \
                                    str(imp_supplier_bill) + \
                                    ' from the contract ' + \
                                    imp_supplier_contract.name + \
                                    ' does not contain the net-gbp key.'

                            kwh = sum(hh['msp-kwh'] for hh in exp_ss.hh_data)

                            if source_code in ('net', 'gen-net'):
                                month_data['export-net-kwh'] += kwh
                                month_data['export-net-gbp'] += gbp
                            elif source_code in \
                                    ('3rd-party', '3rd-party-reverse'):
                                month_data['export-3rd-party-kwh'] += kwh
                                month_data['export-3rd-party-gbp'] += gbp
                                month_data['used-kwh'] -= kwh
                                month_data['used-gbp'] -= gbp
                            elif source_code == 'gen':
                                month_data['export-gen-kwh'] += kwh

                        sss = exp_ss if imp_ss is None else imp_ss
                        dc_contract = era.hhdc_contract
                        sss.contract_func(
                            dc_contract, 'virtual_bill')(sss)
                        dc_bill = sss.dc_bill
                        gbp = dc_bill['net-gbp']

                        mop_contract = era.mop_contract
                        mop_bill_function = sss.contract_func(
                            mop_contract, 'virtual_bill')
                        mop_bill_function(sss)
                        mop_bill = sss.mop_bill
                        gbp += mop_bill['net-gbp']

                        if source_code in ('3rd-party', '3rd-party-reverse'):
                            month_data['import-3rd-party-gbp'] += gbp
                        else:
                            month_data['import-net-gbp'] += gbp
                        month_data['used-gbp'] += gbp

                        if source_code in ('gen', 'gen-net'):
                            generator_type = supply.generator_type.code
                            site_gen_types.add(generator_type)
                        else:
                            generator_type = None

                        sup_category = era.make_meter_category()
                        if CATEGORY_ORDER[site_category] < \
                                CATEGORY_ORDER[sup_category]:
                            site_category = sup_category

                        for bill in sess.query(Bill).filter(
                                Bill.supply == supply,
                                Bill.start_date <= sss.finish_date,
                                Bill.finish_date >= sss.start_date):
                            bill_start = bill.start_date
                            bill_finish = bill.finish_date
                            bill_duration = totalseconds(
                                bill_finish - bill_start) + (30 * 60)
                            overlap_duration = totalseconds(
                                min(bill_finish, sss.finish_date) -
                                max(bill_start, sss.start_date)) + (30 * 60)
                            overlap_proportion = \
                                float(overlap_duration) / bill_duration
                            month_data['billed-import-net-kwh'] += \
                                overlap_proportion * float(bill.kwh)
                            month_data['billed-import-net-gbp'] += \
                                overlap_proportion * float(bill.net)

                        out = [
                            era.imp_mpan_core, era.exp_mpan_core,
                            sup_category, source_code,
                            generator_type, supply.name, era.msn, era.pc.code,
                            site.code, site.name,
                            ','.join(sorted(list(site_associates))),
                            month_finish] + [
                            month_data[t] for t in summary_titles] + [None] + [
                            (mop_bill[t] if t in mop_bill else None)
                            for t in title_dict['mop']] + [None] + \
                            [(dc_bill[t] if t in dc_bill else None)
                                for t in title_dict['dc']]
                        if imp_supplier_contract is None:
                            out += [None] * \
                                (len(title_dict['imp-supplier']) + 1)
                        else:
                            out += [None] + [
                                (
                                    imp_supplier_bill[t]
                                    if t in imp_supplier_bill else None)
                                for t in title_dict['imp-supplier']]
                        if exp_supplier_contract is not None:
                            out += [None] + [
                                (
                                    exp_supplier_bill[t]
                                    if t in exp_supplier_bill else None)
                                for t in title_dict['exp-supplier']]

                        for k, v in month_data.iteritems():
                            site_month_data[k] += v
                        sup_tab.writerow(out)

                    sess.rollback()

                group_tab.writerow(
                    [
                        site.code, site.name,
                        ''.join(sorted(list(site_associates))),
                        month_finish, site_category,
                        ', '.join(sorted(list(site_sources))),
                        ', '.join(sorted(list(site_gen_types)))] +
                    [site_month_data[k] for k in summary_titles])

            month_start += relativedelta(months=1)
    except:
        msg = traceback.format_exc()
        sys.stderr.write(msg + '\n')
        group_tab.writerow(["Problem " + msg])
    finally:
        try:
            f.close()
            rf.close()
            os.rename(running_name, finished_name)
            if sess is not None:
                sess.close()
        except:
            msg = traceback.format_exc()
            r_name, f_name = dloads.make_names('error.txt', user)
            ef = open(r_name, "wb")
            ef.write(msg + '\n')
            ef.close()
Example #3
0
def content():
    sess = None
    try:
        sess = db.session()

        yield ','.join(
            (
                'Site Code', 'Site Name', 'Associated Site Ids', 'From', 'To',
                'Gen Types', 'CHP kWh', 'LM kWh', 'Turbine kWh', 'PV kWh'))

        finish_date = datetime.datetime(
            end_year, end_month, 1, tzinfo=pytz.utc) + \
            relativedelta(months=1) - HH

        start_date = datetime.datetime(
            end_year, end_month, 1, tzinfo=pytz.utc) - \
            relativedelta(months=months-1)

        forecast_date = computer.forecast_date()

        contract = Contract.get_supplier_by_id(sess, contract_id)
        sites = sess.query(Site).join(SiteEra).join(Era).join(Supply). \
            join(Source).filter(
                or_(Era.finish_date == null(), Era.finish_date >= start_date),
                Era.start_date <= finish_date,
                or_(
                    Source.code.in_(('gen', 'gen-net')),
                    Era.exp_mpan_core != null())).distinct()
        bill_titles = computer.contract_func(
            caches, contract, 'displaced_virtual_bill_titles', None)()

        for title in bill_titles:
            if title == 'total-msp-kwh':
                title = 'total-displaced-msp-kwh'
            yield ',' + title
        yield '\n'

        for site in sites:
            month_start = start_date
            month_finish = month_start + relativedelta(months=1) - HH
            while not month_finish > finish_date:
                for site_group in site.groups(
                        sess, month_start, month_finish, True):
                    if site_group.start_date > month_start:
                        chunk_start = site_group.start_date
                    else:
                        chunk_start = month_start
                    if site_group.finish_date > month_finish:
                        chunk_finish = month_finish
                    else:
                        chunk_finish = site_group.finish_date

                    displaced_era = computer.displaced_era(
                        sess, site_group, chunk_start, chunk_finish)
                    if displaced_era is None:
                        continue
                    supplier_contract = displaced_era.imp_supplier_contract
                    if contract is not None and contract != supplier_contract:
                        continue

                    linked_sites = ','.join(
                        a_site.code for a_site in site_group.sites
                        if not a_site == site)
                    generator_types = ' '.join(
                        sorted(
                            [
                                supply.generator_type.code for supply in
                                site_group.supplies
                                if supply.generator_type is not None]))

                    yield ','.join(
                        '"' + value + '"' for value in [
                            site.code, site.name, linked_sites,
                            hh_format(chunk_start), hh_format(chunk_finish),
                            generator_types])

                    total_gen_breakdown = {}

                    results = iter(
                        sess.execute(
                            "select supply.id, hh_datum.value, "
                            "hh_datum.start_date, channel.imp_related, "
                            "source.code, generator_type.code as "
                            "gen_type_code from hh_datum, channel, source, "
                            "era, supply left outer join generator_type on "
                            "supply.generator_type_id = generator_type.id "
                            "where hh_datum.channel_id = channel.id and "
                            "channel.era_id = era.id and era.supply_id = "
                            "supply.id and supply.source_id = source.id and "
                            "channel.channel_type = 'ACTIVE' and not "
                            "(source.code = 'net' and channel.imp_related "
                            "is true) and hh_datum.start_date >= "
                            ":chunk_start and hh_datum.start_date "
                            "<= :chunk_finish and "
                            "supply.id = any(:supply_ids) order "
                            "by hh_datum.start_date, supply.id",
                            params={
                                'chunk_start': chunk_start,
                                'chunk_finish': chunk_finish,
                                'supply_ids': [
                                    s.id for s in site_group.supplies]}))
                    try:
                        res = results.next()
                        hhChannelValue = res.value
                        hhChannelStartDate = res.start_date
                        imp_related = res.imp_related
                        source_code = res.code
                        gen_type = res.gen_type_code
                        hh_date = chunk_start

                        while hh_date <= finish_date:
                            gen_breakdown = {}
                            exported = 0
                            while hhChannelStartDate == hh_date:
                                if not imp_related and source_code in (
                                        'net', 'gen-net'):
                                    exported += hhChannelValue
                                if (imp_related and source_code == 'gen') or \
                                        (not imp_related and
                                            source_code == 'gen-net'):
                                    gen_breakdown[gen_type] = \
                                        gen_breakdown.setdefault(
                                            gen_type, 0) + hhChannelValue

                                if (
                                        not imp_related and
                                        source_code == 'gen') or (
                                        imp_related and
                                        source_code == 'gen-net'):
                                    gen_breakdown[gen_type] = \
                                        gen_breakdown.setdefault(
                                            gen_type, 0) - hhChannelValue

                                try:
                                    res = results.next()
                                    source_code = res.code
                                    hhChannelValue = res.value
                                    hhChannelStartDate = res.start_date
                                    imp_related = res.imp_related
                                    gen_type = res.gen_type_code
                                except StopIteration:
                                    hhChannelStartDate = None

                            displaced = sum(gen_breakdown.itervalues()) - \
                                exported
                            added_so_far = 0
                            for key in sorted(gen_breakdown.iterkeys()):
                                kwh = gen_breakdown[key]
                                if kwh + added_so_far > displaced:
                                    total_gen_breakdown[key] = \
                                        total_gen_breakdown.get(key, 0) + \
                                        displaced - added_so_far
                                    break
                                else:
                                    total_gen_breakdown[key] = \
                                        total_gen_breakdown.get(key, 0) + kwh
                                    added_so_far += kwh

                            hh_date += HH
                    except StopIteration:
                        pass

                    for title in ['chp', 'lm', 'turb', 'pv']:
                        yield ',' + str(total_gen_breakdown.get(title, ''))

                    site_ds = computer.SiteSource(
                        sess, site, chunk_start, chunk_finish, forecast_date,
                        None, caches, displaced_era)
                    disp_func = computer.contract_func(
                        caches, supplier_contract, 'displaced_virtual_bill',
                        None)
                    disp_func(site_ds)
                    bill = site_ds.supplier_bill
                    for title in bill_titles:
                        if title in bill:
                            val = bill[title]
                            if isinstance(val, datetime.datetime):
                                val = hh_format(val)
                            else:
                                val = str(val)
                            yield ',"' + val + '"'
                            del bill[title]
                        else:
                            yield ',""'

                    keys = bill.keys()
                    keys.sort()
                    for k in keys:
                        yield ',"' + k + '","' + str(bill[k]) + '"'
                    yield '\n'

                month_start += relativedelta(months=1)
                month_finish = month_start + relativedelta(months=1) - HH
    except:
        yield traceback.format_exc()
    finally:
        if sess is not None:
            sess.close()
Example #4
0
def content():
    sess = None
    try:
        sess = db.session()

        march_finish = datetime.datetime(year, 4, 1, tzinfo=pytz.utc) - HH
        march_start = datetime.datetime(year, 3, 1, tzinfo=pytz.utc)

        yield ", ".join(
            (
                "Site Code",
                "Site Name",
                "Displaced TRIAD 1 Date",
                "Displaced TRIAD 1 MSP kW",
                "Displaced TRIAD LAF",
                "Displaced TRIAD 1 GSP kW",
                "Displaced TRIAD 2 Date",
                "Displaced TRIAD 2 MSP kW",
                "Displaced TRIAD 2 LAF",
                "Displaced TRIAD 2 GSP kW",
                "Displaced TRIAD 3 Date",
                "Displaced TRIAD 3 MSP kW",
                "Displaced TRIAD 3 LAF",
                "Displaced TRIAD 3 GSP kW",
                "Displaced GSP kW",
                "Displaced Rate GBP / kW",
                "GBP",
            )
        ) + "\n"

        forecast_date = computer.forecast_date()

        if site_id is None:
            sites = (
                sess.query(Site)
                .join(SiteEra)
                .join(Era)
                .join(Supply)
                .join(Source)
                .filter(
                    Source.code.in_(("gen", "gen-net")),
                    Era.start_date <= march_finish,
                    or_(Era.finish_date == null(), Era.finish_date >= march_start),
                )
                .distinct()
            )
        else:
            site = Site.get_by_id(sess, site_id)
            sites = sess.query(Site).filter(Site.id == site.id)

        for site in sites:
            for site_group in site.groups(sess, march_start, march_finish, True):
                if site_group.start_date > march_start:
                    chunk_start = site_group.start_date
                else:
                    chunk_start = march_start

                if not site_group.finish_date < march_finish:
                    chunk_finish = march_finish
                else:
                    continue

                yield '"' + site.code + '","' + site.name + '"'

                displaced_era = computer.displaced_era(sess, site_group, chunk_start, chunk_finish)
                if displaced_era is None:
                    continue

                site_ds = computer.SiteSource(
                    sess, site, chunk_start, chunk_finish, forecast_date, None, caches, displaced_era
                )
                duos.duos_vb(site_ds)
                triad.triad_bill(site_ds)

                bill = site_ds.supplier_bill
                values = []
                for i in range(1, 4):
                    triad_prefix = "triad-actual-" + str(i)
                    for suffix in ["-date", "-msp-kw", "-laf", "-gsp-kw"]:
                        values.append(bill[triad_prefix + suffix])

                values += [bill["triad-actual-" + suf] for suf in ["gsp-kw", "rate", "gbp"]]

                for value in values:
                    if isinstance(value, datetime.datetime):
                        yield "," + hh_format(value)
                    else:
                        yield "," + str(value)
                yield "\n"
    except:
        yield traceback.format_exc()
    finally:
        if sess is not None:
            sess.close()