示例#1
0
def get_day_prices(day):
    """ Returns the prices set for a day. """
    try:
        # This WILL fail when we either have no prices at all or conflicting ranges.
        return EnergySupplierPrice.objects.by_date(target_date=day)
    except (EnergySupplierPrice.DoesNotExist,
            EnergySupplierPrice.MultipleObjectsReturned):
        # Default to zero prices.
        return EnergySupplierPrice()
示例#2
0
def get_fallback_prices() -> EnergySupplierPrice:
    # Default to zero prices.
    return EnergySupplierPrice(
        description='Zero priced contract',
        electricity_delivered_1_price=0,
        electricity_delivered_2_price=0,
        gas_price=0,
        electricity_returned_1_price=0,
        electricity_returned_2_price=0,
        fixed_daily_cost=0,
    )
示例#3
0
    def get_context_data(self, **kwargs):
        context_data = super(ArchiveXhrSummary,
                             self).get_context_data(**kwargs)
        context_data[
            'capabilities'] = dsmr_backend.services.backend.get_capabilities()
        context_data['frontend_settings'] = FrontendSettings.get_solo()

        selected_datetime = timezone.make_aware(
            timezone.datetime.strptime(
                self.request.GET['date'],
                formats.get_format('DSMR_STRFTIME_DATE_FORMAT')))
        selected_level = self.request.GET['level']

        context_data['statistics'] = {
            'days':
            dsmr_stats.services.day_statistics(selected_datetime.date()),
            'months':
            dsmr_stats.services.month_statistics(selected_datetime.date()),
            'years':
            dsmr_stats.services.year_statistics(selected_datetime.date()),
        }[selected_level]

        context_data['title'] = {
            'days':
            formats.date_format(selected_datetime.date(),
                                'DSMR_GRAPH_LONG_DATE_FORMAT'),
            'months':
            formats.date_format(selected_datetime.date(),
                                'DSMR_DATEPICKER_MONTH'),
            'years':
            selected_datetime.date().year,
        }[selected_level]

        # Only day level allows some additional data.
        if selected_level == 'days':
            try:
                # This WILL fail when we either have no prices at all or conflicting ranges.
                context_data[
                    'energy_price'] = EnergySupplierPrice.objects.by_date(
                        target_date=selected_datetime.date())
            except (EnergySupplierPrice.DoesNotExist,
                    EnergySupplierPrice.MultipleObjectsReturned):
                # Default to zero prices.
                context_data['energy_price'] = EnergySupplierPrice()

            context_data['notes'] = Note.objects.filter(
                day=selected_datetime.date())

        context_data['selected_level'] = selected_level
        context_data['selected_datetime'] = selected_datetime
        context_data['django_date_format'] = 'DJANGO_DATE_FORMAT'
        return context_data
示例#4
0
def get_day_prices(day: datetime.date) -> EnergySupplierPrice:
    """ Returns the prices set for a day. Combines prices when multiple contracts are found. """
    contracts_found = EnergySupplierPrice.objects.filter(start__lte=day,
                                                         end__gte=day)

    if len(contracts_found) == 1:
        return contracts_found[0]

    combined_contract = get_fallback_prices()

    if not contracts_found:
        raise EnergySupplierPrice.DoesNotExist()

    # Multiple found, this is allowed, as long are there is no collision.
    PRICE_FIELDS = (
        'electricity_delivered_1_price',
        'electricity_delivered_2_price',
        'gas_price',
        'electricity_returned_1_price',
        'electricity_returned_2_price',
        'fixed_daily_cost',
    )

    for current_field in PRICE_FIELDS:
        prices = [
            getattr(x, current_field) for x in contracts_found
            if getattr(x, current_field) > 0
        ]

        # None set.
        if not prices:
            continue

        # Collision, use none since we cannot tell which one superseeds the other.
        if len(prices) > 1:
            continue

        setattr(combined_contract, current_field, prices[0])

    return combined_contract
示例#5
0
def day_consumption(day):
    """ Calculates the consumption of an entire day. """
    consumption = {'day': day}
    day_start = timezone.make_aware(
        timezone.datetime(year=day.year, month=day.month, day=day.day))
    day_end = day_start + timezone.timedelta(days=1)

    try:
        # This WILL fail when we either have no prices at all or conflicting ranges.
        daily_energy_price = EnergySupplierPrice.objects.by_date(
            target_date=day)
    except (EnergySupplierPrice.DoesNotExist,
            EnergySupplierPrice.MultipleObjectsReturned):
        # Default to zero prices.
        daily_energy_price = EnergySupplierPrice()

    electricity_readings, gas_readings = consumption_by_range(start=day_start,
                                                              end=day_end)

    if not electricity_readings.exists():
        raise LookupError("No electricity readings found for: {}".format(day))

    electricity_reading_count = electricity_readings.count()

    first_reading = electricity_readings[0]
    last_reading = electricity_readings[electricity_reading_count - 1]

    consumption['latest_consumption'] = last_reading
    consumption[
        'electricity1'] = last_reading.delivered_1 - first_reading.delivered_1
    consumption[
        'electricity2'] = last_reading.delivered_2 - first_reading.delivered_2
    consumption['electricity1_start'] = first_reading.delivered_1
    consumption['electricity1_end'] = last_reading.delivered_1
    consumption['electricity2_start'] = first_reading.delivered_2
    consumption['electricity2_end'] = last_reading.delivered_2
    consumption[
        'electricity1_returned'] = last_reading.returned_1 - first_reading.returned_1
    consumption[
        'electricity2_returned'] = last_reading.returned_2 - first_reading.returned_2
    consumption['electricity1_returned_start'] = first_reading.returned_1
    consumption['electricity1_returned_end'] = last_reading.returned_1
    consumption['electricity2_returned_start'] = first_reading.returned_2
    consumption['electricity2_returned_end'] = last_reading.returned_2
    consumption['electricity_merged'] = consumption[
        'electricity1'] + consumption['electricity2']
    consumption['electricity_returned_merged'] = \
        consumption['electricity1_returned'] + consumption['electricity2_returned']

    # Cost per tariff + direction.
    consumption['electricity1_cost'] = round_decimal(
        (consumption['electricity1'] *
         daily_energy_price.electricity_delivered_1_price) -
        (consumption['electricity1_returned'] *
         daily_energy_price.electricity_returned_1_price))
    consumption['electricity2_cost'] = round_decimal(
        (consumption['electricity2'] *
         daily_energy_price.electricity_delivered_2_price) -
        (consumption['electricity2_returned'] *
         daily_energy_price.electricity_returned_2_price))

    # Totals.
    consumption['electricity_cost_merged'] = consumption[
        'electricity1_cost'] + consumption['electricity2_cost']
    consumption['total_cost'] = round_decimal(
        consumption['electricity_cost_merged'])

    # Gas readings are optional, as not all meters support this.
    if gas_readings.exists():
        gas_reading_count = gas_readings.count()
        first_reading = gas_readings[0]
        last_reading = gas_readings[gas_reading_count - 1]
        consumption['gas'] = last_reading.delivered - first_reading.delivered
        consumption['gas_start'] = first_reading.delivered
        consumption['gas_end'] = last_reading.delivered
        consumption['gas_cost'] = round_decimal(consumption['gas'] *
                                                daily_energy_price.gas_price)
        consumption['total_cost'] += consumption['gas_cost']

    # Current prices as well.
    consumption[
        'energy_supplier_price_electricity_delivered_1'] = daily_energy_price.electricity_delivered_1_price
    consumption[
        'energy_supplier_price_electricity_delivered_2'] = daily_energy_price.electricity_delivered_2_price
    consumption[
        'energy_supplier_price_electricity_returned_1'] = daily_energy_price.electricity_returned_1_price
    consumption[
        'energy_supplier_price_electricity_returned_2'] = daily_energy_price.electricity_returned_2_price
    consumption['energy_supplier_price_gas'] = daily_energy_price.gas_price

    # Any notes of that day.
    consumption['notes'] = Note.objects.filter(day=day).values_list(
        'description', flat=True)

    # Temperature readings are not mandatory as well.
    temperature_readings = TemperatureReading.objects.filter(
        read_at__gte=day_start,
        read_at__lt=day_end,
    ).order_by('read_at')
    consumption['lowest_temperature'] = temperature_readings.aggregate(
        avg_temperature=Min('degrees_celcius'), )['avg_temperature'] or 0
    consumption['highest_temperature'] = temperature_readings.aggregate(
        avg_temperature=Max('degrees_celcius'), )['avg_temperature'] or 0
    consumption['average_temperature'] = temperature_readings.aggregate(
        avg_temperature=Avg('degrees_celcius'), )['avg_temperature'] or 0
    consumption['average_temperature'] = round_decimal(
        consumption['average_temperature'])

    return consumption