123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- from marshmallow import (
- fields,
- ValidationError,
- validates_schema,
- validate,
- post_load,
- validates,
- )
- from flexmeasures.data.schemas.reporting import (
- ReporterConfigSchema,
- ReporterParametersSchema,
- )
- from flexmeasures.data.schemas.io import Input
- from flexmeasures.data.schemas.sensors import SensorIdField
- from flexmeasures.utils.unit_utils import is_currency_unit
- class ProfitOrLossReporterConfigSchema(ReporterConfigSchema):
- """Schema for the ProfitOrLossReporter configuration
- Example:
- .. code-block:: json
- {
- "production-price-sensor" : 1,
- "consumption-price-sensor" : 2,
- "loss_is_positive" : True
- }
- """
- consumption_price_sensor = SensorIdField(required=False)
- production_price_sensor = SensorIdField(required=False)
- # set this to True to get the losses as positive values, otherwise, profit is positive.
- loss_is_positive = fields.Bool(
- load_default=False, dump_default=True, required=False
- )
- @validates_schema
- def validate_price_sensors(self, data, **kwargs):
- """check that at least one of the price sensors is given"""
- if (
- "consumption_price_sensor" not in data
- and "production_price_sensor" not in data
- ):
- raise ValidationError(
- "At least one of the two price sensors, consumption or production, is required."
- )
- @post_load
- def complete_price_sensors(self, data, **kwargs):
- if "consumption_price_sensor" not in data:
- data["consumption_price_sensor"] = data["production_price_sensor"]
- if "production_price_sensor" not in data:
- data["production_price_sensor"] = data["consumption_price_sensor"]
- return data
- @validates("consumption_price_sensor")
- def validate_consumption_price_units(self, value):
- if not value.measures_energy_price:
- raise ValidationError(
- f"`consumption_price_sensor` has wrong units. Expected `Energy / Currency` but got `{value.unit}`"
- )
- @validates("production_price_sensor")
- def validate_production_price_units(self, value):
- if not value.measures_energy_price:
- raise ValidationError(
- f"`production_price_sensor` has wrong units. Expected `Energy / Currency` but got `{value.unit}`"
- )
- class ProfitOrLossReporterParametersSchema(ReporterParametersSchema):
- """Schema for the ProfitOrLossReporter parameters
- Example:
- .. code-block:: json
- {
- "input": [
- {
- "sensor": 1,
- },
- ],
- "output": [
- {
- "sensor": 2,
- }
- ],
- "start" : "2023-01-01T00:00:00+00:00",
- "end" : "2023-01-03T00:00:00+00:00",
- }
- """
- # redefining output to restrict the input length to 1
- input = fields.List(fields.Nested(Input()), validate=validate.Length(min=1, max=1))
- @validates("input")
- def validate_input_measures_power_energy(self, value):
- if not (
- value[0]["sensor"].measures_power or value[0]["sensor"].measures_energy
- ):
- raise ValidationError(
- "Input sensor can only contain power or energy values."
- )
- @validates("output")
- def validate_output_unit_currency(self, value):
- for output_description in value:
- if not is_currency_unit(output_description["sensor"].unit):
- raise ValidationError(
- "Output sensor unit can only be a currency, e.g. EUR."
- )
|