Skip to content

Commit 49fde1f

Browse files
authored
Merge pull request #1808 from steve-community/1807-add-query-filter-to-users-and-ocpp-tags-to-express-association-variants
Add query filter to users (and ocpp tags) to express association variants
2 parents 98e7bdf + f3a306c commit 49fde1f

File tree

7 files changed

+92
-16
lines changed

7 files changed

+92
-16
lines changed

src/main/java/de/rwth/idsg/steve/repository/dto/OcppTag.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ public static final class OcppTagOverview {
4242
@Schema(description = "The OCPP tag")
4343
private final String idTag;
4444

45+
@Schema(description = "PK of the user this OCPP tag belongs to (if any)")
46+
private final Integer userPk;
47+
4548
@Schema(description = "PK of the parent OCPP tag of this OCPP tag")
4649
private final Integer parentOcppTagPk;
4750

src/main/java/de/rwth/idsg/steve/repository/impl/OcppTagRepositoryImpl.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
import de.rwth.idsg.steve.web.dto.OcppTagForm;
2525
import de.rwth.idsg.steve.web.dto.OcppTagQueryForm;
2626
import jooq.steve.db.tables.OcppTagActivity;
27+
import jooq.steve.db.tables.UserOcppTag;
2728
import jooq.steve.db.tables.records.OcppTagActivityRecord;
2829
import jooq.steve.db.tables.records.OcppTagRecord;
2930
import lombok.extern.slf4j.Slf4j;
3031
import org.joda.time.DateTime;
3132
import org.jooq.DSLContext;
3233
import org.jooq.JoinType;
33-
import org.jooq.Record10;
34+
import org.jooq.Record11;
3435
import org.jooq.RecordMapper;
3536
import org.jooq.Result;
3637
import org.jooq.SelectQuery;
@@ -43,7 +44,6 @@
4344
import java.util.List;
4445
import java.util.stream.Collectors;
4546

46-
import static de.rwth.idsg.steve.repository.impl.RepositoryUtils.ocppTagByUserIdQuery;
4747
import static de.rwth.idsg.steve.utils.CustomDSL.includes;
4848
import static de.rwth.idsg.steve.utils.DateTimeUtils.humanize;
4949
import static jooq.steve.db.tables.OcppTag.OCPP_TAG;
@@ -72,6 +72,7 @@ public List<OcppTagOverview> getOverview(OcppTagQueryForm form) {
7272
selectQuery.addFrom(OCPP_TAG_ACTIVITY);
7373

7474
OcppTagActivity parentTable = OCPP_TAG_ACTIVITY.as("parent");
75+
UserOcppTag userOcppTagTable = USER_OCPP_TAG.as("user_ocpp_tag");
7576

7677
selectQuery.addSelect(
7778
OCPP_TAG_ACTIVITY.OCPP_TAG_PK,
@@ -83,10 +84,12 @@ public List<OcppTagOverview> getOverview(OcppTagQueryForm form) {
8384
OCPP_TAG_ACTIVITY.BLOCKED,
8485
OCPP_TAG_ACTIVITY.MAX_ACTIVE_TRANSACTION_COUNT,
8586
OCPP_TAG_ACTIVITY.ACTIVE_TRANSACTION_COUNT,
86-
OCPP_TAG_ACTIVITY.NOTE
87+
OCPP_TAG_ACTIVITY.NOTE,
88+
userOcppTagTable.USER_PK
8789
);
8890

8991
selectQuery.addJoin(parentTable, JoinType.LEFT_OUTER_JOIN, parentTable.ID_TAG.eq(OCPP_TAG_ACTIVITY.PARENT_ID_TAG));
92+
selectQuery.addJoin(userOcppTagTable, JoinType.LEFT_OUTER_JOIN, userOcppTagTable.OCPP_TAG_PK.eq(OCPP_TAG_ACTIVITY.OCPP_TAG_PK));
9093

9194
if (form.isOcppTagPkSet()) {
9295
selectQuery.addConditions(OCPP_TAG_ACTIVITY.OCPP_TAG_PK.eq(form.getOcppTagPk()));
@@ -101,14 +104,24 @@ public List<OcppTagOverview> getOverview(OcppTagQueryForm form) {
101104
}
102105

103106
if (form.isUserIdSet()) {
104-
var query = ocppTagByUserIdQuery(ctx, form.getUserId());
105-
selectQuery.addConditions(OCPP_TAG_ACTIVITY.ID_TAG.in(query));
107+
selectQuery.addConditions(userOcppTagTable.USER_PK.eq(form.getUserId()));
106108
}
107109

108110
if (form.isNoteSet()) {
109111
selectQuery.addConditions(includes(OCPP_TAG_ACTIVITY.NOTE, form.getNote()));
110112
}
111113

114+
switch (form.getUserFilter()) {
115+
case OnlyTagsWithUser:
116+
selectQuery.addConditions(userOcppTagTable.USER_PK.isNotNull());
117+
break;
118+
case OnlyTagsWithoutUser:
119+
selectQuery.addConditions(userOcppTagTable.USER_PK.isNull());
120+
break;
121+
default:
122+
break;
123+
}
124+
112125
switch (form.getExpired()) {
113126
case ALL:
114127
break;
@@ -274,9 +287,9 @@ private void processBooleanType(SelectQuery selectQuery,
274287
}
275288

276289
private static class UserMapper
277-
implements RecordMapper<Record10<Integer, Integer, String, String, DateTime, Boolean, Boolean, Integer, Long, String>, OcppTagOverview> {
290+
implements RecordMapper<Record11<Integer, Integer, String, String, DateTime, Boolean, Boolean, Integer, Long, String, Integer>, OcppTagOverview> {
278291
@Override
279-
public OcppTagOverview map(Record10<Integer, Integer, String, String, DateTime, Boolean, Boolean, Integer, Long, String> r) {
292+
public OcppTagOverview map(Record11<Integer, Integer, String, String, DateTime, Boolean, Boolean, Integer, Long, String, Integer> r) {
280293
return OcppTagOverview.builder()
281294
.ocppTagPk(r.value1())
282295
.parentOcppTagPk(r.value2())
@@ -289,6 +302,7 @@ public OcppTagOverview map(Record10<Integer, Integer, String, String, DateTime,
289302
.maxActiveTransactionCount(r.value8())
290303
.activeTransactionCount(r.value9())
291304
.note(r.value10())
305+
.userPk(r.value11())
292306
.build();
293307
}
294308
}

src/main/java/de/rwth/idsg/steve/repository/impl/UserRepositoryImpl.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,39 @@ public class UserRepositoryImpl implements UserRepository {
6464
@Override
6565
public List<User.Overview> getOverview(UserQueryForm form) {
6666
var ocppTagsPerUser = getOcppTagsInternal(form.getUserPk(), form.getOcppIdTag());
67+
var userResults = getOverviewInternal(form);
68+
69+
List<User.Overview> userOverviews = new ArrayList<>();
70+
for (var r : userResults) {
71+
var tags = ocppTagsPerUser.getOrDefault(r.value1(), List.of());
72+
73+
var user = User.Overview.builder()
74+
.userPk(r.value1())
75+
.name(r.value2() + " " + r.value3())
76+
.phone(r.value4())
77+
.email(r.value5())
78+
.ocppTagEntries(tags)
79+
.build();
80+
81+
// TODO: Improve later. This is not efficient, because we filter after fetching all results. However, this
82+
// should be acceptable since the number of users (and tags) are usually not very high, and this
83+
// overview query will probably not be in the hot path.
84+
switch (form.getOcppTagFilter()) {
85+
case OnlyUsersWithTags -> {
86+
if (!tags.isEmpty()) {
87+
userOverviews.add(user);
88+
}
89+
}
90+
case OnlyUsersWithoutTags -> {
91+
if (tags.isEmpty()) {
92+
userOverviews.add(user);
93+
}
94+
}
95+
default -> userOverviews.add(user);
96+
}
97+
}
6798

68-
return getOverviewInternal(form)
69-
.map(r -> User.Overview.builder()
70-
.userPk(r.value1())
71-
.name(r.value2() + " " + r.value3())
72-
.phone(r.value4())
73-
.email(r.value5())
74-
.ocppTagEntries(ocppTagsPerUser.getOrDefault(r.value1(), List.of()))
75-
.build()
76-
);
99+
return userOverviews;
77100
}
78101

79102
@Override

src/main/java/de/rwth/idsg/steve/web/dto/OcppTagQueryForm.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public class OcppTagQueryForm {
6060
@Schema(description = "Query by the note associated with the OCPP tag. The value of this field does not have to exactly match the note. A substring is also accepted.")
6161
private String note;
6262

63+
@Schema(description = "Filter by whether the OCPP tag is associated with a user or not. Defaults to All")
64+
private UserFilter userFilter = UserFilter.All;
65+
6366
@Schema(hidden = true)
6467
public boolean isOcppTagPkSet() {
6568
return ocppTagPk != null;
@@ -123,6 +126,12 @@ public static BooleanType fromValue(String v) {
123126
}
124127
}
125128

129+
public enum UserFilter {
130+
All,
131+
OnlyTagsWithUser,
132+
OnlyTagsWithoutUser
133+
}
134+
126135
@ToString(callSuper = true)
127136
public static class OcppTagQueryFormForApi extends OcppTagQueryForm {
128137

src/main/java/de/rwth/idsg/steve/web/dto/UserQueryForm.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public class UserQueryForm {
3939
private String name;
4040
private String email;
4141

42+
private OcppTagFilter ocppTagFilter = OcppTagFilter.All;
43+
4244
public boolean isSetUserPk() {
4345
return userPk != null;
4446
}
@@ -54,4 +56,11 @@ public boolean isSetName() {
5456
public boolean isSetEmail() {
5557
return email != null;
5658
}
59+
60+
public enum OcppTagFilter {
61+
All,
62+
OnlyUsersWithTags,
63+
OnlyUsersWithoutTags
64+
}
65+
5766
}

src/main/resources/webapp/WEB-INF/views/data-man/ocppTags.jsp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@
9595
<td>User ID:</td>
9696
<td><form:input path="userId"/></td>
9797
</tr>
98+
<tr>
99+
<td>User Relationship:</td>
100+
<td>
101+
<form:select path="userFilter">
102+
<form:options items="${userFilter}"/>
103+
</form:select>
104+
</td>
105+
</tr>
98106
<tr>
99107
<td>Expired?:</td>
100108
<td><form:select path="expired">
@@ -133,6 +141,7 @@
133141
<thead>
134142
<tr>
135143
<th data-sort="string">ID Tag</th>
144+
<th data-sort="int">User ID</th>
136145
<th data-sort="string">Parent ID Tag</th>
137146
<th data-sort="date">Expiry Date/Time</th>
138147
<th data-sort="string">In Transaction?</th>
@@ -148,6 +157,7 @@
148157
<c:forEach items="${ocppTagList}" var="item">
149158
<tr>
150159
<td><a href="${ctxPath}/manager/ocppTags/details/${item.ocppTagPk}">${item.idTag}</a></td>
160+
<td><a href="${ctxPath}/manager/users/details/${item.userPk}">${item.userPk}</a></td>
151161
<td>
152162
<c:if test="${not empty item.parentIdTag}">
153163
<a href="${ctxPath}/manager/ocppTags/details/${item.parentOcppTagPk}">${item.parentIdTag}</a>

src/main/resources/webapp/WEB-INF/views/data-man/users.jsp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@
3636
<td>Ocpp ID Tag:</td>
3737
<td><form:input path="ocppIdTag"/></td>
3838
</tr>
39+
<tr>
40+
<td>Ocpp ID Tag Relationship:</td>
41+
<td>
42+
<form:select path="ocppTagFilter">
43+
<form:options items="${ocppTagFilter}"/>
44+
</form:select>
45+
</td>
46+
</tr>
3947
<tr>
4048
<td>Name:</td>
4149
<td><form:input path="name"/></td>

0 commit comments

Comments
 (0)