Search in sources :

Example 1 with TransactionDetails

use of de.rwth.idsg.steve.repository.dto.TransactionDetails in project steve by RWTH-i5-IDSG.

the class TransactionRepositoryImpl method getDetails.

@Override
public TransactionDetails getDetails(int transactionPk) {
    // -------------------------------------------------------------------------
    // Step 1: Collect general data about transaction
    // -------------------------------------------------------------------------
    TransactionQueryForm form = new TransactionQueryForm();
    form.setTransactionPk(transactionPk);
    form.setType(TransactionQueryForm.QueryType.ALL);
    form.setPeriodType(TransactionQueryForm.QueryPeriodType.ALL);
    Record11<Integer, String, Integer, String, DateTime, String, DateTime, String, String, Integer, Integer> transaction = getInternal(form).fetchOne();
    if (transaction == null) {
        throw new SteveException("There is no transaction with id '%s'", transactionPk);
    }
    DateTime startTimestamp = transaction.value5();
    DateTime stopTimestamp = transaction.value7();
    String stopValue = transaction.value8();
    String chargeBoxId = transaction.value2();
    int connectorId = transaction.value3();
    // -------------------------------------------------------------------------
    // Step 2: Collect intermediate meter values
    // -------------------------------------------------------------------------
    Condition timestampCondition;
    if (stopTimestamp == null && stopValue == null) {
        // active transaction
        timestampCondition = CONNECTOR_METER_VALUE.VALUE_TIMESTAMP.greaterOrEqual(startTimestamp);
    } else {
        // finished transaction
        timestampCondition = CONNECTOR_METER_VALUE.VALUE_TIMESTAMP.between(startTimestamp, stopTimestamp);
    }
    // Case 1: Ideal and most accurate case. Station sends meter values with transaction id set.
    // 
    SelectQuery<ConnectorMeterValueRecord> transactionQuery = ctx.selectFrom(CONNECTOR_METER_VALUE).where(CONNECTOR_METER_VALUE.TRANSACTION_PK.eq(transactionPk)).getQuery();
    // Case 2: Fall back to filtering according to time windows
    // 
    SelectQuery<ConnectorMeterValueRecord> timestampQuery = ctx.selectFrom(CONNECTOR_METER_VALUE).where(CONNECTOR_METER_VALUE.CONNECTOR_PK.eq(ctx.select(CONNECTOR.CONNECTOR_PK).from(CONNECTOR).where(CONNECTOR.CHARGE_BOX_ID.eq(chargeBoxId)).and(CONNECTOR.CONNECTOR_ID.eq(connectorId)))).and(timestampCondition).getQuery();
    // Actually, either case 1 applies or 2. If we retrieved values using 1, case 2 is should not be
    // executed (best case). In worst case (1 returns empty list and we fall back to case 2) though,
    // we make two db calls. Alternatively, we can pass both queries in one go, and make the db work.
    // 
    // UNION removes all duplicate records
    // 
    Table<ConnectorMeterValueRecord> t1 = transactionQuery.union(timestampQuery).asTable("t1");
    // -------------------------------------------------------------------------
    // Step 3: Charging station might send meter vales at fixed intervals (e.g.
    // every 15 min) regardless of the fact that connector's meter value did not
    // change (e.g. vehicle is fully charged, but cable is still connected). This
    // yields multiple entries in db with the same value but different timestamp.
    // We are only interested in the first arriving entry.
    // -------------------------------------------------------------------------
    Field<DateTime> dateTimeField = DSL.min(t1.field(2, DateTime.class)).as("min");
    List<TransactionDetails.MeterValues> values = ctx.select(dateTimeField, t1.field(3, String.class), t1.field(4, String.class), t1.field(5, String.class), t1.field(6, String.class), t1.field(7, String.class), t1.field(8, String.class), t1.field(9, String.class)).from(t1).groupBy(t1.field(3), t1.field(4), t1.field(5), t1.field(6), t1.field(7), t1.field(8), t1.field(9)).orderBy(dateTimeField).fetch().map(r -> TransactionDetails.MeterValues.builder().valueTimestamp(r.value1()).value(r.value2()).readingContext(r.value3()).format(r.value4()).measurand(r.value5()).location(r.value6()).unit(r.value7()).phase(r.value8()).build());
    return new TransactionDetails(new TransactionMapper().map(transaction), values);
}
Also used : Condition(org.jooq.Condition) ConnectorMeterValueRecord(jooq.steve.db.tables.records.ConnectorMeterValueRecord) TransactionDetails(de.rwth.idsg.steve.repository.dto.TransactionDetails) DateTime(org.joda.time.DateTime) TransactionQueryForm(de.rwth.idsg.steve.web.dto.TransactionQueryForm) SteveException(de.rwth.idsg.steve.SteveException)

Aggregations

SteveException (de.rwth.idsg.steve.SteveException)1 TransactionDetails (de.rwth.idsg.steve.repository.dto.TransactionDetails)1 TransactionQueryForm (de.rwth.idsg.steve.web.dto.TransactionQueryForm)1 ConnectorMeterValueRecord (jooq.steve.db.tables.records.ConnectorMeterValueRecord)1 DateTime (org.joda.time.DateTime)1 Condition (org.jooq.Condition)1