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()
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, )
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
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
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