diff --git a/database/copy-prod-db-to-test.sh b/database/copy-prod-db-to-test.sh
new file mode 100644
index 0000000..bb8493f
--- /dev/null
+++ b/database/copy-prod-db-to-test.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+#====================================================================================
+# Script for copying the latest data from the prod database into the local database.
+#
+#
+# REQUIRES:
+# sudo apt install postgresql-client
+#====================================================================================
+
+# exit script on any error
+trap 'exit' ERR
+
+
+#------------------------------------------------------------------------------------
+# dump
+#------------------------------------------------------------------------------------
+SRC_HOST="localhost"
+SRC_PORT="5432"
+SRC_USERNAME="supercharge_user"
+SRC_DATABASE="postgres"
+SRC_SCHEMA="supercharge"
+OUT_SQL_DIR="/tmp/migration-dump-prod-$$"
+
+echo "**** Enter PROD password for ${SRC_USERNAME} on ${SRC_HOST}:${SRC_PORT}"
+pg_dump \
+ --host=${SRC_HOST} \
+ --port=${SRC_PORT} \
+ --encoding=UTF-8 \
+ --username=${SRC_USERNAME} \
+ --dbname=${SRC_DATABASE} \
+ --schema=${SRC_SCHEMA} \
+ --blobs \
+ --format=d \
+ --verbose \
+ --quote-all-identifiers \
+ --jobs=2 \
+ --file="${OUT_SQL_DIR}"
+
+
+#------------------------------------------------------------------------------------
+# restore
+#------------------------------------------------------------------------------------
+DST_USERNAME="supercharge_user_test"
+DST_HOST="localhost"
+DST_PORT="5432"
+DST_DATABASE="test"
+DST_SCHEMA="supercharge"
+
+
+echo "ALTER SCHEMA ${DST_SCHEMA} RENAME TO ${DST_SCHEMA}_$$" | psql --username="${DST_USERNAME}" --host="${DST_HOST}" --port="${DST_PORT}" "${DST_DATABASE}"
+
+echo "**** Enter password for ${DST_USERNAME} on TARGET database at ${DST_HOST}:${DST_PORT}"
+pg_restore \
+ --username="${DST_USERNAME}" \
+ --host="${DST_HOST}" \
+ --dbname="${DST_DATABASE}" \
+ --port="${DST_PORT}" \
+ --format=d \
+ --verbose \
+ --jobs=2 \
+ "${OUT_SQL_DIR}"
+
+
+echo "done"
diff --git a/database/sql/04-tables.sql b/database/sql/04-tables.sql
index fbb276e..f85817f 100644
--- a/database/sql/04-tables.sql
+++ b/database/sql/04-tables.sql
@@ -14,6 +14,7 @@ drop table if exists user_config;
drop table if exists user_reset;
drop table if exists changelog;
drop table if exists site_change;
+drop table if exists parking;
drop table if exists site;
drop table if exists address;
drop table if exists country;
@@ -40,12 +41,18 @@ alter sequence region_region_id_seq restart with 150;
-- -----------------------------------------------------------
create table country
(
- country_id serial primary key,
- name varchar(100) not null unique,
- code varchar(2) not null unique,
- region_id int not null,
- state_required boolean not null default false,
- modified_date timestamptz not null default current_timestamp,
+ country_id serial primary key,
+ name varchar(100) not null unique,
+ code varchar(2) not null unique,
+ region_id int not null,
+ state_required boolean not null default false,
+ modified_date timestamptz not null default current_timestamp,
+ plugs_tpc boolean not null default true,
+ plugs_nacs boolean not null default true,
+ plugs_ccs1 boolean not null default true,
+ plugs_ccs2 boolean not null default true,
+ plugs_type2 boolean not null default true,
+ plugs_gbt boolean not null default true,
foreign key (region_id) references region (region_id)
on update cascade
on delete cascade
@@ -75,40 +82,74 @@ create table address
);
alter sequence address_address_id_seq restart with 2000000;
+-- -----------------------------------------------------------
+-- PARKING - lookup table
+-- -----------------------------------------------------------
+create table parking
+(
+ parking_id serial primary key,
+ name varchar(100) not null,
+ description text null
+);
+
-- -----------------------------------------------------------
-- SITE
-- -----------------------------------------------------------
-create type site_status_type as enum ('CLOSED_PERM','CLOSED_TEMP', 'PERMIT', 'CONSTRUCTION', 'OPEN');
+create type site_status_type as enum ('CLOSED_PERM','CLOSED_TEMP', 'PERMIT', 'CONSTRUCTION', 'OPEN', 'VOTING', 'PLAN', 'EXPANDING');
create table site
(
- site_id serial not null,
- location_id varchar(300) null default null::character varying,
- "name" varchar(100) not null,
- status "site_status_type" not null,
- opened_date timestamptz null,
- hours varchar(100) null default null::character varying,
- enabled bool not null default true,
- counted bool not null,
- address_id int4 not null,
- gps_latitude float8 not null,
- gps_longitude float8 not null,
- elevation_meters int4 not null,
- url_discuss varchar(200) null default null::character varying,
- stall_count int4 null,
- power_kwatt int4 not null default 0,
- has_solar_canopy bool not null default false,
- has_battery bool not null default false,
- developer_notes varchar(1000) null default null::character varying,
- modified_date timestamptz not null default now(),
- "version" int4 not null default 1,
- other_evs bool not null default false,
+ site_id serial not null,
+ location_id varchar(300) null default null::character varying,
+ "name" varchar(100) not null,
+ status "site_status_type" not null,
+ opened_date timestamptz null,
+ hours varchar(100) null default null::character varying,
+ enabled bool not null default true,
+ counted bool not null,
+ address_id int4 not null,
+ gps_latitude float8 not null,
+ gps_longitude float8 not null,
+ elevation_meters int4 not null,
+ url_discuss varchar(200) null default null::character varying,
+ stall_count int4 null,
+ power_kwatt int4 not null default 0,
+ has_solar_canopy bool not null default false,
+ has_battery bool not null default false,
+ developer_notes varchar(1000) null default null::character varying,
+ modified_date timestamptz not null default now(),
+ "version" int4 not null default 1,
+ other_evs bool not null default false, -- TO BE DEPRECATED
+ stalls_urban int4 null,
+ stalls_v2 int4 null,
+ stalls_v3 int4 null,
+ stalls_v4 int4 null,
+ stalls_other int4 null,
+ stalls_accessible int4 null,
+ stalls_trailer int4 null,
+ plugs_tpc int4 null,
+ plugs_nacs int4 null,
+ plugs_ccs1 int4 null,
+ plugs_ccs2 int4 null,
+ plugs_type2 int4 null,
+ plugs_gbt int4 null,
+ plugs_other int4 null,
+ plugs_multi int4 null,
+ parking_id int4 null,
+ facility_name varchar(200) null default null::character varying,
+ facility_hours varchar(100) null default null::character varying,
+ access_notes varchar(1000) null default null::character varying,
+ address_notes varchar(1000) null default null::character varying,
+ plugshare_id int8 null,
+ osm_id int8 null,
constraint address_id_unique unique (address_id),
constraint name_unique unique (name),
constraint site_id_unique primary key (site_id)
);
alter table site
add constraint site_address_id_fkey foreign key (address_id) references address(address_id) on delete cascade on update cascade;
+alter table site
+ add constraint site_parking_id_fkey foreign key (parking_id) references parking(parking_id) on delete cascade on update cascade;
alter sequence site_site_id_seq restart with 100000;
-- -----------------------------------------------------------
diff --git a/database/sql/31-reference-countries.sql b/database/sql/31-reference-countries.sql
index 3d4a9a4..66839dd 100644
--- a/database/sql/31-reference-countries.sql
+++ b/database/sql/31-reference-countries.sql
@@ -62,3 +62,9 @@ INSERT INTO country (country_id,"name",code,region_id,state_required,modified_da
INSERT INTO country (country_id,"name",code,region_id,state_required,modified_date) VALUES (160,'Malaysia','MY',102,false,now());
INSERT INTO country (country_id,"name",code,region_id,state_required,modified_date) VALUES (161,'Qatar','QA',102,false,now());
INSERT INTO country (country_id,"name",code,region_id,state_required,modified_date) VALUES (162,'Chile','CL',103,false,now());
+
+-- pre-populate valid plug types per country
+UPDATE country SET plugs_gbt = false WHERE name != 'China';
+UPDATE country SET plugs_tpc = false, plugs_nacs = false, plugs_ccs1 = false WHERE region_id IN (101, 102) AND name NOT IN ('Japan', 'South Korea', 'Taiwan');
+UPDATE country SET plugs_type2 = false, plugs_ccs2 = false WHERE region_id = 100 OR name IN ('Japan', 'South Korea');
+UPDATE country SET plugs_ccs1 = false WHERE name IN ('Japan', 'Taiwan');
diff --git a/database/sql/32-reference-sites.sql b/database/sql/32-reference-sites.sql
index cff4130..a4a3867 100644
--- a/database/sql/32-reference-sites.sql
+++ b/database/sql/32-reference-sites.sql
@@ -7541,3 +7541,72 @@ COPY "supercharge"."site_change" ("site_id", "user_id", "version", "change_date"
-- PostgreSQL database dump complete
--
+-- Pre-populate stalls based on max power
+UPDATE site SET stalls_urban = stall_count WHERE power_kwatt <= 72;
+UPDATE site SET stalls_v2 = stall_count WHERE power_kwatt BETWEEN 73 AND 199;
+UPDATE site SET stalls_v3 = stall_count WHERE power_kwatt >= 200; -- a few of these are V4 at the time of release and will have to be updated manually
+
+-- Pre-populate plugs based on geography, max power, and existing other_evs flag
+
+-- All stalls in China are GB/T, except Hong Kong and Macau which are CCS2 (with one weird exception in Macau to be updated manually)
+UPDATE site s SET plugs_gbt = stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.name = 'China' AND a.state NOT IN ('Hong Kong', 'Macau');
+UPDATE site s SET plugs_ccs2 = stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.name = 'China' AND a.state IN ('Hong Kong', 'Macau');
+
+-- All stalls in Jordan are Type2
+UPDATE site s SET plugs_type2 = stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.name = 'Jordan';
+
+-- Taiwan is mostly dual-cable CCS2+TPC but some will have to be updated manually
+UPDATE site s SET plugs_ccs2 = s.stall_count, plugs_tpc = s.stall_count, plugs_multi = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.name = 'Taiwan';
+
+-- North America V2 + Urban, and all stalls in Japan + South Korea, are TPC if they're not already marked open to other EVs
+UPDATE site s SET plugs_tpc = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND ((s.power_kwatt < 200 AND c.region_id = 100) OR c.name IN ('Japan', 'South Korea')) AND NOT s.other_evs;
+
+-- North America + South Korea stalls that are already marked open to other EVs are all MagicDock (TPC+CCS1)
+UPDATE site s SET plugs_tpc = s.stall_count, plugs_ccs1 = s.stall_count, plugs_multi = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND (c.region_id = 100 OR c.name = 'South Korea') AND s.other_evs;
+
+-- North America V3 + V4 stalls are all NACS if they're not already marked open to other EVs
+UPDATE site s SET plugs_nacs = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.region_id = 100 AND s.power_kwatt = 250 AND NOT s.other_evs;
+
+-- Europe V2 stalls are dual-cable CCS2+Type2
+UPDATE site s SET plugs_ccs2 = s.stall_count, plugs_type2 = s.stall_count, plugs_multi = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.region_id = 101 AND s.power_kwatt BETWEEN 73 AND 199;
+
+-- Presume the rest of the world's V2 stalls have CCS2 plugs
+UPDATE site s SET plugs_ccs2 = stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.region_id != 100 AND c.name NOT IN ('China', 'Japan', 'Jordan', 'South Korea', 'Taiwan')
+AND NOT (c.region_id = 101 AND s.power_kwatt BETWEEN 73 AND 199);
+
+-- Pre-populate parking options
+INSERT INTO parking (name, description) VALUES
+ ('Free at all times', 'Unrestricted at all times with no fee to park'),
+ ('Free with validation', 'No fee to park for the first N minutes of parking with proof of purchase from certain merchants'),
+ ('Free initially', 'No fee to park for the first N minutes of parking'),
+ ('Free off-peak', 'No fee to park outside of peak hours/days (e.g. nights, weekends)'),
+ ('Paid - self parking', 'Fee to park at all times'),
+ ('Paid - valet parking', 'Fee to park at all times with valet assistance'),
+ ('Other - see notes', 'Details provided in "Access Notes"');
diff --git a/pom.xml b/pom.xml
index 48a80bb..80c20ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
info.supercharge.api
supercharge.info-api
- 5.0.3-SNAPSHOT
+ 5.1.1-SNAPSHOT
diff --git a/service-dao/pom.xml b/service-dao/pom.xml
index 00977d5..2739e02 100644
--- a/service-dao/pom.xml
+++ b/service-dao/pom.xml
@@ -3,7 +3,7 @@
info.supercharge.api
supercharge.info-api
- 5.0.3-SNAPSHOT
+ 5.1.1-SNAPSHOT
4.0.0
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/changelog/ChangeLog.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/changelog/ChangeLog.java
index 769800c..08f61cd 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/changelog/ChangeLog.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/changelog/ChangeLog.java
@@ -1,7 +1,9 @@
package com.redshiftsoft.tesla.dao.changelog;
import com.google.common.base.Preconditions;
+import com.redshiftsoft.tesla.dao.site.Plugs;
import com.redshiftsoft.tesla.dao.site.SiteStatus;
+import com.redshiftsoft.tesla.dao.site.Stalls;
import java.time.Instant;
import java.util.Collections;
@@ -35,7 +37,7 @@ public class ChangeLog implements Comparable {
// ADD, UPDATE
private ChangeType changeType;
- // PERMIT, CONSTRUCTION, OPEN
+ // PERMIT, CONSTRUCTION, OPEN, etc
private SiteStatus siteStatus;
private SiteStatus prevStatus;
@@ -47,7 +49,6 @@ public class ChangeLog implements Comparable {
public int getId() {
return id;
}
-
public void setId(int id) {
this.id = id;
}
@@ -55,7 +56,6 @@ public void setId(int id) {
public Instant getDate() {
return date;
}
-
public void setDate(Instant date) {
Preconditions.checkArgument(date != null);
this.date = date;
@@ -64,7 +64,6 @@ public void setDate(Instant date) {
public ChangeType getChangeType() {
return changeType;
}
-
public void setChangeType(ChangeType changeType) {
Preconditions.checkArgument(changeType != null);
this.changeType = changeType;
@@ -73,7 +72,6 @@ public void setChangeType(ChangeType changeType) {
public SiteStatus getSiteStatus() {
return siteStatus;
}
-
public void setSiteStatus(SiteStatus siteStatus) {
this.siteStatus = siteStatus;
}
@@ -81,7 +79,6 @@ public void setSiteStatus(SiteStatus siteStatus) {
public SiteStatus getPrevStatus() {
return prevStatus;
}
-
public void setPrevStatus(SiteStatus prevStatus) {
this.prevStatus = prevStatus;
}
@@ -89,7 +86,6 @@ public void setPrevStatus(SiteStatus prevStatus) {
public boolean getNotify() {
return notify;
}
-
public void setNotify(boolean notify) {
this.notify = notify;
}
@@ -97,7 +93,6 @@ public void setNotify(boolean notify) {
public int getStallCount() {
return stallCount;
}
-
public void setStallCount(int stallCount) {
this.stallCount = stallCount;
}
@@ -105,7 +100,6 @@ public void setStallCount(int stallCount) {
public int getPowerKilowatt() {
return powerKilowatt;
}
-
public void setPowerKilowatt(int powerKilowatt) {
this.powerKilowatt = powerKilowatt;
}
@@ -113,7 +107,6 @@ public void setPowerKilowatt(int powerKilowatt) {
public boolean isOtherEVs() {
return otherEVs;
}
-
public void setOtherEVs(boolean otherEVs) {
this.otherEVs = otherEVs;
}
@@ -121,7 +114,6 @@ public void setOtherEVs(boolean otherEVs) {
public int getSiteId() {
return siteId;
}
-
public void setSiteId(int siteId) {
this.siteId = siteId;
}
@@ -129,7 +121,6 @@ public void setSiteId(int siteId) {
public Instant getModifiedInstant() {
return modifiedInstant;
}
-
public void setModifiedInstant(Instant modifiedInstant) {
this.modifiedInstant = modifiedInstant;
}
@@ -137,7 +128,6 @@ public void setModifiedInstant(Instant modifiedInstant) {
public String getSiteName() {
return siteName;
}
-
public void setSiteName(String siteName) {
this.siteName = siteName;
}
@@ -145,7 +135,6 @@ public void setSiteName(String siteName) {
public int getRegionId() {
return regionId;
}
-
public void setRegionId(int regionId) {
this.regionId = regionId;
}
@@ -153,7 +142,6 @@ public void setRegionId(int regionId) {
public String getRegionName() {
return regionName;
}
-
public void setRegionName(String regionName) {
this.regionName = regionName;
}
@@ -161,7 +149,6 @@ public void setRegionName(String regionName) {
public int getCountryId() {
return countryId;
}
-
public void setCountryId(int countryId) {
this.countryId = countryId;
}
@@ -169,7 +156,6 @@ public void setCountryId(int countryId) {
public String getCountryName() {
return countryName;
}
-
public void setCountryName(String countryName) {
this.countryName = countryName;
}
@@ -177,7 +163,6 @@ public void setCountryName(String countryName) {
public String getState() {
return state;
}
-
public void setState(String state) {
this.state = state;
}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Country.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Country.java
index 31f3ce0..511cb3e 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Country.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Country.java
@@ -15,6 +15,13 @@ public class Country {
/* Is the state field required for addresses in this country. */
private boolean stateRequired;
+ private boolean plugTPC;
+ private boolean plugNACS;
+ private boolean plugCCS1;
+ private boolean plugCCS2;
+ private boolean plugType2;
+ private boolean plugGBT;
+
public Country() {
}
@@ -65,7 +72,6 @@ public String toString() {
public int getId() {
return id;
}
-
public void setId(int id) {
this.id = id;
}
@@ -73,7 +79,6 @@ public void setId(int id) {
public String getName() {
return name;
}
-
public void setName(String name) {
this.name = name;
}
@@ -81,7 +86,6 @@ public void setName(String name) {
public String getCode() {
return code;
}
-
public void setCode(String code) {
this.code = code;
}
@@ -89,7 +93,6 @@ public void setCode(String code) {
public int getRegionId() {
return regionId;
}
-
public void setRegionId(int regionId) {
this.regionId = regionId;
}
@@ -97,7 +100,6 @@ public void setRegionId(int regionId) {
public String getRegionName() {
return regionName;
}
-
public void setRegionName(String regionName) {
this.regionName = regionName;
}
@@ -105,8 +107,50 @@ public void setRegionName(String regionName) {
public boolean isStateRequired() {
return stateRequired;
}
-
public void setStateRequired(boolean stateRequired) {
this.stateRequired = stateRequired;
}
+
+ public boolean isPlugTPC() {
+ return plugTPC;
+ }
+ public void setPlugTPC(boolean plugTPC) {
+ this.plugTPC = plugTPC;
+ }
+
+ public boolean isPlugNACS() {
+ return plugNACS;
+ }
+ public void setPlugNACS(boolean plugNACS) {
+ this.plugNACS = plugNACS;
+ }
+
+ public boolean isPlugCCS1() {
+ return plugCCS1;
+ }
+ public void setPlugCCS1(boolean plugCCS1) {
+ this.plugCCS1 = plugCCS1;
+ }
+
+ public boolean isPlugCCS2() {
+ return plugCCS2;
+ }
+ public void setPlugCCS2(boolean plugCCS2) {
+ this.plugCCS2 = plugCCS2;
+ }
+
+ public boolean isPlugType2() {
+ return plugType2;
+ }
+ public void setPlugType2(boolean plugType2) {
+ this.plugType2 = plugType2;
+ }
+
+ public boolean isPlugGBT() {
+ return plugGBT;
+ }
+ public void setPlugGBT(boolean plugGBT) {
+ this.plugGBT = plugGBT;
+ }
+
}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/CountryRowMapper.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/CountryRowMapper.java
index ae68da7..26be111 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/CountryRowMapper.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/CountryRowMapper.java
@@ -30,6 +30,14 @@ public Country mapRow(ResultSet rs, int rowNum) throws SQLException {
country.setRegionId(rs.getInt(c++));
country.setStateRequired(rs.getBoolean(c++));
c++; // modified_date
+
+ country.setPlugTPC(rs.getBoolean(c++));
+ country.setPlugNACS(rs.getBoolean(c++));
+ country.setPlugCCS1(rs.getBoolean(c++));
+ country.setPlugCCS2(rs.getBoolean(c++));
+ country.setPlugType2(rs.getBoolean(c++));
+ country.setPlugGBT(rs.getBoolean(c++));
+
country.setRegionName(rs.getString(c));
return country;
}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Parking.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Parking.java
new file mode 100644
index 0000000..98e7ee9
--- /dev/null
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Parking.java
@@ -0,0 +1,76 @@
+package com.redshiftsoft.tesla.dao.site;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class Parking {
+
+ private int parkingId;
+ private String name;
+ private String description;
+
+ public Parking() {
+ }
+
+ public Parking(int parkingId, String name, String description) {
+ this.parkingId = parkingId;
+ this.name = name;
+ this.description = description;
+ }
+
+ // - - - - - - - - -
+ // java.lang.Object
+ // - - - - - - - - -
+
+ private List> getIdentityFields() {
+ return Arrays.asList(parkingId, name);
+ }
+
+ @Override
+ public int hashCode() {
+ return getIdentityFields().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return this == other || (other instanceof Parking) &&
+ this.getIdentityFields().equals(((Parking) other).getIdentityFields());
+ }
+
+ @Override
+ public String toString() {
+ return "Parking{" +
+ "id=" + parkingId +
+ ", name='" + name + "'" +
+ ", description='" + description + "'" +
+ "}";
+ }
+
+ // - - - - - - - - -
+ // getters/setters
+ // - - - - - - - - -
+
+ public int getParkingId() {
+ return parkingId;
+ }
+
+ public void setParkingId(int parkingId) {
+ this.parkingId = parkingId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/ParkingDAO.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/ParkingDAO.java
new file mode 100644
index 0000000..b729738
--- /dev/null
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/ParkingDAO.java
@@ -0,0 +1,46 @@
+package com.redshiftsoft.tesla.dao.site;
+
+import com.redshiftsoft.tesla.dao.BaseDAO;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Component;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.function.Supplier;
+
+@Component
+public class ParkingDAO extends BaseDAO implements Supplier> {
+
+ private static final ParkingRowMapper PARKING_ROW_MAPPER = new ParkingRowMapper();
+
+ public List getAll() {
+ return getJdbcTemplate().query(ParkingRowMapper.SELECT_ALL, PARKING_ROW_MAPPER);
+ }
+
+ @Override
+ public List get() {
+ return getAll();
+ }
+
+
+ public Parking getById(int parkingId) {
+ return getJdbcTemplate().queryForObject("SELECT * FROM parking WHERE parking_id=?", PARKING_ROW_MAPPER, parkingId);
+ }
+
+ private static class ParkingRowMapper implements RowMapper {
+
+ private static final String SELECT_ALL = "SELECT * FROM parking ORDER BY parking_id ASC";
+
+ @Override
+ public Parking mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Parking parking = new Parking();
+ int c = 1;
+ parking.setParkingId(rs.getInt(c++));
+ parking.setName(rs.getString(c++));
+ parking.setDescription(rs.getString(c));
+ return parking;
+ }
+ }
+
+}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Plugs.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Plugs.java
new file mode 100644
index 0000000..2969cee
--- /dev/null
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Plugs.java
@@ -0,0 +1,74 @@
+package com.redshiftsoft.tesla.dao.site;
+
+public class Plugs {
+
+ private Integer TPC;
+ private Integer NACS;
+ private Integer CCS1;
+ private Integer CCS2;
+ private Integer Type2;
+ private Integer GBT;
+ private Integer Other;
+ private Integer Multi;
+
+ public Plugs nullIfEmpty() {
+ return TPC == null && NACS == null && CCS1 == null && CCS2 == null && Type2 == null && GBT == null && Other == null && Multi == null ? null : this;
+ }
+
+ public Integer getTPC() {
+ return TPC;
+ }
+ public void setTPC(Integer TPC) {
+ this.TPC = TPC;
+ }
+
+ public Integer getNACS() {
+ return NACS;
+ }
+ public void setNACS(Integer NACS) {
+ this.NACS = NACS;
+ }
+
+ public Integer getCCS1() {
+ return CCS1;
+ }
+ public void setCCS1(Integer CCS1) {
+ this.CCS1 = CCS1;
+ }
+
+ public Integer getCCS2() {
+ return CCS2;
+ }
+ public void setCCS2(Integer CCS2) {
+ this.CCS2 = CCS2;
+ }
+
+ public Integer getType2() {
+ return Type2;
+ }
+ public void setType2(Integer Type2) {
+ this.Type2 = Type2;
+ }
+
+ public Integer getGBT() {
+ return GBT;
+ }
+ public void setGBT(Integer GBT) {
+ this.GBT = GBT;
+ }
+
+ public Integer getOther() {
+ return Other;
+ }
+ public void setOther(Integer Other) {
+ this.Other = Other;
+ }
+
+ public Integer getMulti() {
+ return Multi;
+ }
+ public void setMulti(Integer Multi) {
+ this.Multi = Multi;
+ }
+
+}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Site.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Site.java
index 1b0d5b8..2503a21 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Site.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Site.java
@@ -33,6 +33,16 @@ public class Site {
private boolean battery;
private boolean otherEVs;
+ private Stalls stalls = new Stalls();
+ private Plugs plugs = new Plugs();
+ private Integer parkingId;
+ private String facilityName;
+ private String facilityHours;
+ private String accessNotes;
+ private String addressNotes;
+ private Long plugshareId;
+ private Long osmId;
+
// - - - - - - - - - - - - - - - - - - - - - - -
// java.lang.Object
// - - - - - - - - - - - - - - - - - - - - - - -
@@ -90,7 +100,6 @@ public boolean isTempClosed() {
public int getId() {
return id;
}
-
public void setId(int id) {
this.id = id;
}
@@ -98,7 +107,6 @@ public void setId(int id) {
public String getName() {
return name;
}
-
public void setName(String name) {
this.name = name;
}
@@ -106,7 +114,6 @@ public void setName(String name) {
public SiteStatus getStatus() {
return status;
}
-
public void setStatus(SiteStatus status) {
this.status = status;
}
@@ -114,7 +121,6 @@ public void setStatus(SiteStatus status) {
public LocalDate getDateOpened() {
return dateOpened;
}
-
public void setDateOpened(LocalDate dateOpened) {
this.dateOpened = dateOpened;
}
@@ -122,7 +128,6 @@ public void setDateOpened(LocalDate dateOpened) {
public LocalDateTime getDateModified() {
return dateModified;
}
-
public void setDateModified(LocalDateTime dateModified) {
this.dateModified = dateModified;
}
@@ -130,7 +135,6 @@ public void setDateModified(LocalDateTime dateModified) {
public Address getAddress() {
return address;
}
-
public void setAddress(Address address) {
this.address = address;
}
@@ -138,7 +142,6 @@ public void setAddress(Address address) {
public SiteGPS getGps() {
return gps;
}
-
public void setGps(SiteGPS gps) {
this.gps = gps;
}
@@ -146,7 +149,6 @@ public void setGps(SiteGPS gps) {
public Integer getElevationMeters() {
return elevationMeters;
}
-
public void setElevationMeters(Integer elevationMeters) {
this.elevationMeters = elevationMeters;
}
@@ -154,7 +156,6 @@ public void setElevationMeters(Integer elevationMeters) {
public String getUrlDiscuss() {
return urlDiscuss;
}
-
public void setUrlDiscuss(String urlDiscuss) {
this.urlDiscuss = urlDiscuss;
}
@@ -162,7 +163,6 @@ public void setUrlDiscuss(String urlDiscuss) {
public int getStallCount() {
return stallCount;
}
-
public void setStallCount(int stallCount) {
this.stallCount = stallCount;
}
@@ -170,7 +170,6 @@ public void setStallCount(int stallCount) {
public boolean isCounted() {
return counted;
}
-
public void setCounted(boolean counted) {
this.counted = counted;
}
@@ -178,7 +177,6 @@ public void setCounted(boolean counted) {
public boolean isEnabled() {
return enabled;
}
-
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@@ -186,7 +184,6 @@ public void setEnabled(boolean enabled) {
public String getHours() {
return hours;
}
-
public void setHours(String hours) {
this.hours = hours;
}
@@ -194,7 +191,6 @@ public void setHours(String hours) {
public String getLocationId() {
return locationId;
}
-
public void setLocationId(String locationId) {
this.locationId = locationId;
}
@@ -202,7 +198,6 @@ public void setLocationId(String locationId) {
public int getPowerKilowatt() {
return powerKilowatt;
}
-
public void setPowerKilowatt(int powerKilowatt) {
this.powerKilowatt = powerKilowatt;
}
@@ -210,7 +205,6 @@ public void setPowerKilowatt(int powerKilowatt) {
public boolean isSolarCanopy() {
return solarCanopy;
}
-
public void setSolarCanopy(boolean solarCanopy) {
this.solarCanopy = solarCanopy;
}
@@ -218,7 +212,6 @@ public void setSolarCanopy(boolean solarCanopy) {
public boolean isBattery() {
return battery;
}
-
public void setBattery(boolean battery) {
this.battery = battery;
}
@@ -226,7 +219,6 @@ public void setBattery(boolean battery) {
public String getDeveloperNotes() {
return developerNotes;
}
-
public void setDeveloperNotes(String developerNotes) {
this.developerNotes = developerNotes;
}
@@ -234,7 +226,6 @@ public void setDeveloperNotes(String developerNotes) {
public int getVersion() {
return version;
}
-
public void setVersion(int version) {
this.version = version;
}
@@ -242,8 +233,71 @@ public void setVersion(int version) {
public boolean isOtherEVs() {
return otherEVs;
}
-
public void setOtherEVs(boolean otherEVs) {
this.otherEVs = otherEVs;
}
+
+ public Stalls getStalls() {
+ return stalls;
+ }
+ public void setStalls(Stalls stalls) {
+ this.stalls = stalls;
+ }
+
+ public Plugs getPlugs() {
+ return plugs;
+ }
+ public void setPlugs(Plugs plugs) {
+ this.plugs = plugs;
+ }
+
+ public Integer getParkingId() {
+ return parkingId;
+ }
+ public void setParkingId(Integer parkingId) {
+ this.parkingId = parkingId;
+ }
+
+ public String getFacilityName() {
+ return facilityName;
+ }
+ public void setFacilityName(String facilityName) {
+ this.facilityName = facilityName;
+ }
+
+ public String getFacilityHours() {
+ return facilityHours;
+ }
+ public void setFacilityHours(String facilityHours) {
+ this.facilityHours = facilityHours;
+ }
+
+ public String getAccessNotes() {
+ return accessNotes;
+ }
+ public void setAccessNotes(String accessNotes) {
+ this.accessNotes = accessNotes;
+ }
+
+ public String getAddressNotes() {
+ return addressNotes;
+ }
+ public void setAddressNotes(String addressNotes) {
+ this.addressNotes = addressNotes;
+ }
+
+ public Long getPlugshareId() {
+ return plugshareId;
+ }
+ public void setPlugshareId(Long plugshareId) {
+ this.plugshareId = plugshareId;
+ }
+
+ public Long getOsmId() {
+ return osmId;
+ }
+ public void setOsmId(Long osmId) {
+ this.osmId = osmId;
+ }
+
}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteInsertStatementCreator.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteInsertStatementCreator.java
index 5419d84..b66af94 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteInsertStatementCreator.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteInsertStatementCreator.java
@@ -2,16 +2,18 @@
import com.redshiftsoft.tesla.dao.LocalDateUtil;
import org.springframework.jdbc.core.PreparedStatementCreator;
+import org.springframework.jdbc.core.SqlTypeValue;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.sql.Types;
import static com.redshiftsoft.tesla.dao.DAOTools.string;
public class SiteInsertStatementCreator implements PreparedStatementCreator {
- private static final String SQL = "insert into site values (DEFAULT,?,?,?::SITE_STATUS_TYPE,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW(),?,?)";
+ private static final String SQL = "insert into site values (DEFAULT,?,?,?::SITE_STATUS_TYPE,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW(),?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
private final Site site;
public SiteInsertStatementCreator(Site site) {
@@ -50,10 +52,40 @@ public PreparedStatement createPreparedStatement(Connection con) throws SQLExcep
stat.setBoolean(c++, site.isBattery());
stat.setString(c++, string(site.getDeveloperNotes()));
stat.setInt(c++, site.getVersion());
- stat.setBoolean(c, site.isOtherEVs());
+ stat.setBoolean(c++, site.isOtherEVs());
+
+ // use setObject() instead of type-specific setX() for better null handling
+ Stalls stalls = site.getStalls();
+ if (stalls == null) stalls = new Stalls();
+ stat.setObject(c++, stalls.getUrban(), Types.INTEGER);
+ stat.setObject(c++, stalls.getV2(), Types.INTEGER);
+ stat.setObject(c++, stalls.getV3(), Types.INTEGER);
+ stat.setObject(c++, stalls.getV4(), Types.INTEGER);
+ stat.setObject(c++, stalls.getOther(), Types.INTEGER);
+ stat.setObject(c++, stalls.getAccessible(), Types.INTEGER);
+ stat.setObject(c++, stalls.getTrailerFriendly(), Types.INTEGER);
+
+ Plugs plugs = site.getPlugs();
+ if (plugs == null) plugs = new Plugs();
+
+ stat.setObject(c++, plugs.getTPC(), Types.INTEGER);
+ stat.setObject(c++, plugs.getNACS(), Types.INTEGER);
+ stat.setObject(c++, plugs.getCCS1(), Types.INTEGER);
+ stat.setObject(c++, plugs.getCCS2(), Types.INTEGER);
+ stat.setObject(c++, plugs.getType2(), Types.INTEGER);
+ stat.setObject(c++, plugs.getGBT(), Types.INTEGER);
+ stat.setObject(c++, plugs.getOther(), Types.INTEGER);
+ stat.setObject(c++, plugs.getMulti(), Types.INTEGER);
+
+ stat.setObject(c++, site.getParkingId(), Types.INTEGER);
+ stat.setString(c++, string(site.getFacilityName()));
+ stat.setString(c++, string(site.getFacilityHours()));
+ stat.setString(c++, string(site.getAccessNotes()));
+ stat.setString(c++, string(site.getAddressNotes()));
+ stat.setObject(c++, site.getPlugshareId(), Types.BIGINT);
+ stat.setObject(c++, site.getOsmId(), Types.BIGINT);
return stat;
}
-
}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteRowMapper.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteRowMapper.java
index 9273036..6d28923 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteRowMapper.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteRowMapper.java
@@ -52,6 +52,36 @@ public Site mapRow(ResultSet rs, int rowNum) throws SQLException {
site.setVersion(rs.getInt(c++));
site.setOtherEVs(rs.getBoolean(c++));
+ // Used typed getObject() instead of specific getX() for better null handling
+ Stalls stalls = new Stalls();
+ stalls.setUrban(rs.getObject(c++, Integer.class));
+ stalls.setV2(rs.getObject(c++, Integer.class));
+ stalls.setV3(rs.getObject(c++, Integer.class));
+ stalls.setV4(rs.getObject(c++, Integer.class));
+ stalls.setOther(rs.getObject(c++, Integer.class));
+ stalls.setAccessible(rs.getObject(c++, Integer.class));
+ stalls.setTrailerFriendly(rs.getObject(c++, Integer.class));
+ site.setStalls(stalls.nullIfEmpty());
+
+ Plugs plugs = new Plugs();
+ plugs.setTPC(rs.getObject(c++, Integer.class));
+ plugs.setNACS(rs.getObject(c++, Integer.class));
+ plugs.setCCS1(rs.getObject(c++, Integer.class));
+ plugs.setCCS2(rs.getObject(c++, Integer.class));
+ plugs.setType2(rs.getObject(c++, Integer.class));
+ plugs.setGBT(rs.getObject(c++, Integer.class));
+ plugs.setOther(rs.getObject(c++, Integer.class));
+ plugs.setMulti(rs.getObject(c++, Integer.class));
+ site.setPlugs(plugs.nullIfEmpty());
+
+ site.setParkingId(rs.getObject(c++, Integer.class));
+ site.setFacilityName(rs.getString(c++));
+ site.setFacilityHours(rs.getString(c++));
+ site.setAccessNotes(rs.getString(c++));
+ site.setAddressNotes(rs.getString(c++));
+ site.setPlugshareId(rs.getObject(c++, Long.class));
+ site.setOsmId(rs.getObject(c++, Long.class));
+
site.setAddress(new AddressRowMapper(c).mapRow(rs, rowNum));
return site;
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteStatus.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteStatus.java
index 6237283..ef60bc9 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteStatus.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteStatus.java
@@ -6,7 +6,10 @@ public enum SiteStatus {
CLOSED_TEMP,
PERMIT,
CONSTRUCTION,
- OPEN;
+ OPEN,
+ VOTING,
+ PLAN,
+ EXPANDING;
public boolean isClosedTemp() {
return CLOSED_TEMP == this;
@@ -27,4 +30,16 @@ public boolean isConstruction() {
public boolean isOpen() {
return OPEN == this;
}
+
+ public boolean isVoting() {
+ return VOTING == this;
+ }
+
+ public boolean isPlan() {
+ return PLAN == this;
+ }
+
+ public boolean isExpanding() {
+ return EXPANDING == this;
+ }
}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteUpdateStatementCreator.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteUpdateStatementCreator.java
index fe0c521..c97fb43 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteUpdateStatementCreator.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/SiteUpdateStatementCreator.java
@@ -6,6 +6,7 @@
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.sql.Types;
import static com.redshiftsoft.tesla.dao.DAOTools.string;
@@ -14,7 +15,10 @@ public class SiteUpdateStatementCreator implements PreparedStatementCreator {
private static final String SQL = "update site " +
"set location_id=?,name=?,status=?::SITE_STATUS_TYPE,opened_date=?,hours=?,enabled=?,counted=?," +
"gps_latitude=?,gps_longitude=?,elevation_meters=?,url_discuss=?,stall_count=?,power_kwatt=?," +
- "has_solar_canopy=?,has_battery=?,developer_notes=?,modified_date=now(),version=version+1,other_evs=?" +
+ "has_solar_canopy=?,has_battery=?,developer_notes=?,modified_date=now(),version=version+1,other_evs=?," +
+ "stalls_urban=?,stalls_v2=?,stalls_v3=?,stalls_v4=?,stalls_other=?,stalls_accessible=?,stalls_trailer=?," +
+ "plugs_tpc=?,plugs_nacs=?,plugs_ccs1=?,plugs_ccs2=?,plugs_type2=?,plugs_gbt=?,plugs_other=?,plugs_multi=?," +
+ "parking_id=?,facility_name=?,facility_hours=?,access_notes=?,address_notes=?,plugshare_id=?,osm_id=?" +
" where site_id=?";
private final Site site;
@@ -54,6 +58,36 @@ public PreparedStatement createPreparedStatement(Connection con) throws SQLExcep
stat.setString(c++, string(site.getDeveloperNotes()));
stat.setBoolean(c++, site.isOtherEVs());
+ // use setObject() instead of type-specific setX() for better null handling
+ Stalls stalls = site.getStalls();
+ if (stalls == null) stalls = new Stalls();
+ stat.setObject(c++, stalls.getUrban(), Types.INTEGER);
+ stat.setObject(c++, stalls.getV2(), Types.INTEGER);
+ stat.setObject(c++, stalls.getV3(), Types.INTEGER);
+ stat.setObject(c++, stalls.getV4(), Types.INTEGER);
+ stat.setObject(c++, stalls.getOther(), Types.INTEGER);
+ stat.setObject(c++, stalls.getAccessible(), Types.INTEGER);
+ stat.setObject(c++, stalls.getTrailerFriendly(), Types.INTEGER);
+
+ Plugs plugs = site.getPlugs();
+ if (plugs == null) plugs = new Plugs();
+ stat.setObject(c++, plugs.getTPC(), Types.INTEGER);
+ stat.setObject(c++, plugs.getNACS(), Types.INTEGER);
+ stat.setObject(c++, plugs.getCCS1(), Types.INTEGER);
+ stat.setObject(c++, plugs.getCCS2(), Types.INTEGER);
+ stat.setObject(c++, plugs.getType2(), Types.INTEGER);
+ stat.setObject(c++, plugs.getGBT(), Types.INTEGER);
+ stat.setObject(c++, plugs.getOther(), Types.INTEGER);
+ stat.setObject(c++, plugs.getMulti(), Types.INTEGER);
+
+ stat.setObject(c++, site.getParkingId(), Types.INTEGER);
+ stat.setString(c++, string(site.getFacilityName()));
+ stat.setString(c++, string(site.getFacilityHours()));
+ stat.setString(c++, string(site.getAccessNotes()));
+ stat.setString(c++, string(site.getAddressNotes()));
+ stat.setObject(c++, site.getPlugshareId(), Types.BIGINT);
+ stat.setObject(c++, site.getOsmId(), Types.BIGINT);
+
stat.setInt(c, site.getId());
return stat;
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Stalls.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Stalls.java
new file mode 100644
index 0000000..b0305da
--- /dev/null
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/site/Stalls.java
@@ -0,0 +1,66 @@
+package com.redshiftsoft.tesla.dao.site;
+
+public class Stalls {
+
+ private Integer urban;
+ private Integer v2;
+ private Integer v3;
+ private Integer v4;
+ private Integer other;
+ private Integer accessible;
+ private Integer trailerFriendly;
+
+ public Stalls nullIfEmpty() {
+ return urban == null && v2 == null && v3 == null && v4 == null && other == null && accessible == null && trailerFriendly == null ? null : this;
+ }
+
+ public Integer getUrban() {
+ return urban;
+ }
+ public void setUrban(Integer urban) {
+ this.urban = urban;
+ }
+
+ public Integer getV2() {
+ return v2;
+ }
+ public void setV2(Integer v2) {
+ this.v2 = v2;
+ }
+
+ public Integer getV3() {
+ return v3;
+ }
+ public void setV3(Integer v3) {
+ this.v3 = v3;
+ }
+
+ public Integer getV4() {
+ return v4;
+ }
+ public void setV4(Integer v4) {
+ this.v4 = v4;
+ }
+
+ public Integer getOther() {
+ return other;
+ }
+ public void setOther(Integer other) {
+ this.other = other;
+ }
+
+ public Integer getAccessible() {
+ return accessible;
+ }
+ public void setAccessible(Integer accessible) {
+ this.accessible = accessible;
+ }
+
+ public Integer getTrailerFriendly() {
+ return trailerFriendly;
+ }
+ public void setTrailerFriendly(Integer trailerFriendly) {
+ this.trailerFriendly = trailerFriendly;
+ }
+
+}
diff --git a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/validation/Validations.java b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/validation/Validations.java
index 04b177f..d09ba1f 100644
--- a/service-dao/src/main/java/com/redshiftsoft/tesla/dao/validation/Validations.java
+++ b/service-dao/src/main/java/com/redshiftsoft/tesla/dao/validation/Validations.java
@@ -17,14 +17,14 @@ public static Collection getValidations() {
new Validation(SUPERCHARGER, "open date consistent with status", "" +
"SELECT * " +
"FROM site " +
- "WHERE (status = 'OPEN' AND opened_date IS NULL) OR (status != 'OPEN' AND opened_date IS NOT NULL)")
+ "WHERE (status IN ('OPEN', 'EXPANDING') AND opened_date IS NULL) OR (status NOT IN ('OPEN', 'EXPANDING') AND opened_date IS NOT NULL)")
);
validationMap.add(
new Validation(SUPERCHARGER, "Tesla location id is not null for OPEN site", "" +
"SELECT * " +
"FROM site " +
- "WHERE status = 'OPEN' AND location_id IS NULL")
+ "WHERE status IN ('OPEN', 'EXPANDING') AND location_id IS NULL")
);
validationMap.add(
@@ -34,10 +34,10 @@ public static Collection getValidations() {
);
validationMap.add(
- new Validation(SUPERCHARGER, "stall count non zero for OPEN sites", "" +
+ new Validation(SUPERCHARGER, "stall count non zero for OPEN/EXPANDING sites", "" +
"SELECT * " +
"FROM site " +
- "WHERE status = 'OPEN' AND (stall_count IS NULL OR stall_count = 0)")
+ "WHERE status IN ('OPEN', 'EXPANDING') AND (stall_count IS NULL OR stall_count = 0)")
);
validationMap.add(
@@ -47,6 +47,43 @@ public static Collection getValidations() {
"GROUP BY name HAVING count(*) > 1")
);
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | STALLS
+
+ validationMap.add(
+ new Validation(SUPERCHARGER, "total stall count not equal to sum of individual stall types", "" +
+ "SELECT * " +
+ "FROM site " +
+ "WHERE stall_count != COALESCE(stalls_urban, 0) + COALESCE(stalls_v2, 0) + COALESCE(stalls_v3, 0) + COALESCE(stalls_v4, 0) + COALESCE(stalls_other, 0)")
+ );
+
+ validationMap.add(
+ new Validation(SUPERCHARGER, "accessible and/or trailer-friendly stall counts exceed total", "" +
+ "SELECT * " +
+ "FROM site " +
+ "WHERE COALESCE(stalls_accessible, 0) > stall_count " +
+ "OR COALESCE(stalls_trailer, 0) > stall_count")
+ );
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | PLUGS
+
+ validationMap.add(
+ new Validation(SUPERCHARGER, "total stall count not equal to sum of individual plug counts (with no multi-plug stalls)", "" +
+ "SELECT * " +
+ "FROM site " +
+ "WHERE COALESCE(plugs_multi, 0) = 0 AND stall_count != " +
+ "COALESCE(plugs_tpc, 0) + COALESCE(plugs_nacs, 0) + COALESCE(plugs_ccs1, 0) + COALESCE(plugs_ccs2, 0) + " +
+ "COALESCE(plugs_type2, 0) + COALESCE(plugs_gbt, 0) + COALESCE(plugs_other, 0)")
+ );
+
+ validationMap.add(
+ new Validation(SUPERCHARGER, "total stall count more than expected (with multi-plug stalls)", "" +
+ "SELECT * " +
+ "FROM site " +
+ "WHERE COALESCE(plugs_multi, 0) > 0 AND stall_count > " +
+ "COALESCE(plugs_tpc, 0) + COALESCE(plugs_nacs, 0) + COALESCE(plugs_ccs1, 0) + COALESCE(plugs_ccs2, 0) + " +
+ "COALESCE(plugs_type2, 0) + COALESCE(plugs_gbt, 0) + COALESCE(plugs_other, 0) - plugs_multi")
+ );
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ADDRESS
validationMap.add(
diff --git a/service-dao/src/main/sql/schema-changes.sql b/service-dao/src/main/sql/schema-changes.sql
index ca153cc..f292bf3 100644
--- a/service-dao/src/main/sql/schema-changes.sql
+++ b/service-dao/src/main/sql/schema-changes.sql
@@ -1,4 +1,126 @@
-- ============================================================================
-- File for SQL that will change the schema. Clear this file after prod deploy.
-- ============================================================================
-CREATE INDEX changelog_site_id_change_date ON changelog (site_id, change_date);
+alter type site_status_type add value 'VOTING';
+alter type site_status_type add value 'PLAN';
+alter type site_status_type add value 'EXPANDING';
+
+create table parking
+(
+ parking_id serial primary key,
+ name varchar(100) not null,
+ description text null
+);
+-- not sure why this needs to be done separately/explicitly, considering the contents of 03-permissions.sql
+grant all privileges on parking to supercharge_user;
+
+alter table site
+ add column stalls_urban int4 null,
+ add column stalls_v2 int4 null,
+ add column stalls_v3 int4 null,
+ add column stalls_v4 int4 null,
+ add column stalls_other int4 null,
+ add column stalls_accessible int4 null,
+ add column stalls_trailer int4 null,
+ add column plugs_tpc int4 null,
+ add column plugs_nacs int4 null,
+ add column plugs_ccs1 int4 null,
+ add column plugs_ccs2 int4 null,
+ add column plugs_type2 int4 null,
+ add column plugs_gbt int4 null,
+ add column plugs_other int4 null,
+ add column plugs_multi int4 null,
+ add column parking_id int4 null,
+ add column facility_name varchar(200) null default null::character varying,
+ add column facility_hours varchar(100) null default null::character varying,
+ add column access_notes varchar(1000) null default null::character varying,
+ add column address_notes varchar(1000) null default null::character varying,
+ add column plugshare_id int8 null,
+ add column osm_id int8 null;
+
+alter table site
+ add constraint site_parking_id_fkey foreign key (parking_id) references parking(parking_id) on delete cascade on update cascade;
+
+alter table country
+ add column plugs_tpc boolean not null default true,
+ add column plugs_nacs boolean not null default true,
+ add column plugs_ccs1 boolean not null default true,
+ add column plugs_ccs2 boolean not null default true,
+ add column plugs_type2 boolean not null default true,
+ add column plugs_gbt boolean not null default true;
+
+-- pre-populate valid plug types per country
+UPDATE country SET plugs_gbt = false WHERE name != 'China';
+UPDATE country SET plugs_tpc = false, plugs_nacs = false, plugs_ccs1 = false WHERE region_id IN (101, 102) AND name NOT IN ('Japan', 'South Korea', 'Taiwan');
+UPDATE country SET plugs_type2 = false, plugs_ccs2 = false WHERE region_id = 100 OR name IN ('Japan', 'South Korea');
+UPDATE country SET plugs_ccs1 = false WHERE name IN ('Japan', 'Taiwan');
+
+-- Pre-populate stalls based on max power
+UPDATE site SET stalls_urban = stall_count WHERE power_kwatt <= 72;
+UPDATE site SET stalls_v2 = stall_count WHERE power_kwatt BETWEEN 73 AND 199;
+UPDATE site SET stalls_v3 = stall_count WHERE power_kwatt >= 200; -- a few of these are V4 at the time of release and will have to be updated manually
+
+-- Pre-populate plugs based on geography, max power, and existing other_evs flag
+
+-- All stalls in China are GB/T, except Hong Kong and Macau which are CCS2 (with one weird exception in Macau to be updated manually)
+UPDATE site s SET plugs_gbt = stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.name = 'China' AND a.state NOT IN ('Hong Kong', 'Macau');
+UPDATE site s SET plugs_ccs2 = stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.name = 'China' AND a.state IN ('Hong Kong', 'Macau');
+
+-- All stalls in Jordan are Type2
+UPDATE site s SET plugs_type2 = stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.name = 'Jordan';
+
+-- Taiwan is mostly dual-cable CCS2+TPC but some will have to be updated manually
+UPDATE site s SET plugs_ccs2 = s.stall_count, plugs_tpc = s.stall_count, plugs_multi = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.name = 'Taiwan';
+
+-- North America V2 + Urban, and all stalls in Japan + South Korea, are TPC if they're not already marked open to other EVs
+UPDATE site s SET plugs_tpc = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND ((s.power_kwatt < 200 AND c.region_id = 100) OR c.name IN ('Japan', 'South Korea')) AND NOT s.other_evs;
+
+-- North America + South Korea stalls that are already marked open to other EVs are all MagicDock (NACS+CCS1)
+UPDATE site s SET plugs_nacs = s.stall_count, plugs_ccs1 = s.stall_count, plugs_multi = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND (c.region_id = 100 OR c.name = 'South Korea') AND s.other_evs;
+
+-- North America V3 + V4 stalls are all NACS if they're not already marked open to other EVs
+UPDATE site s SET plugs_nacs = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.region_id = 100 AND s.power_kwatt = 250 AND NOT s.other_evs;
+
+-- Europe V2 stalls are dual-cable CCS2+Type2
+UPDATE site s SET plugs_ccs2 = s.stall_count, plugs_type2 = s.stall_count, plugs_multi = s.stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.region_id = 101 AND s.power_kwatt BETWEEN 73 AND 199;
+
+-- Presume the rest of the world's V2 stalls have CCS2 plugs
+UPDATE site s SET plugs_ccs2 = stall_count
+FROM address a, country c
+WHERE s.address_id = a.address_id AND a.country_id = c.country_id
+AND c.region_id != 100 AND c.name NOT IN ('China', 'Japan', 'Jordan', 'South Korea', 'Taiwan')
+AND NOT (c.region_id = 101 AND s.power_kwatt BETWEEN 73 AND 199);
+
+-- Pre-populate parking options
+INSERT INTO parking (name, description) VALUES
+ ('Free at all times', 'Unrestricted at all times with no fee to park'),
+ ('Free with validation', 'No fee to park for the first N minutes of parking with proof of purchase from certain merchants'),
+ ('Free initially', 'No fee to park for the first N minutes of parking'),
+ ('Free off-peak', 'No fee to park outside of peak hours/days (e.g. nights, weekends)'),
+ ('Paid - self parking', 'Fee to park at all times'),
+ ('Paid - valet parking', 'Fee to park at all times with valet assistance'),
+ ('Other - see notes', 'Details provided in "Access Notes"');
diff --git a/service-dao/src/test/java/com/redshiftsoft/tesla/dao/validation/ValidationDAO_UT.java b/service-dao/src/test/java/com/redshiftsoft/tesla/dao/validation/ValidationDAO_UT.java
index 7b54247..c52adba 100644
--- a/service-dao/src/test/java/com/redshiftsoft/tesla/dao/validation/ValidationDAO_UT.java
+++ b/service-dao/src/test/java/com/redshiftsoft/tesla/dao/validation/ValidationDAO_UT.java
@@ -25,6 +25,6 @@ public class ValidationDAO_UT {
public void doValidations() {
Collection results = validationDAO.doValidations();
- assertEquals(17, results.size());
+ assertEquals(21, results.size());
}
}
diff --git a/service-war/pom.xml b/service-war/pom.xml
index 8a4f5c9..bc39d75 100644
--- a/service-war/pom.xml
+++ b/service-war/pom.xml
@@ -3,7 +3,7 @@
info.supercharge.api
supercharge.info-api
- 5.0.3-SNAPSHOT
+ 5.1.1-SNAPSHOT
4.0.0
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/country/CountryDTO.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/country/CountryDTO.java
index d5eb4ae..3f6868c 100644
--- a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/country/CountryDTO.java
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/country/CountryDTO.java
@@ -14,10 +14,16 @@ public class CountryDTO {
private String region;
private int regionId;
+ private boolean plugTPC;
+ private boolean plugNACS;
+ private boolean plugCCS1;
+ private boolean plugCCS2;
+ private boolean plugType2;
+ private boolean plugGBT;
+
public int getId() {
return id;
}
-
public void setId(int id) {
this.id = id;
}
@@ -25,7 +31,6 @@ public void setId(int id) {
public String getName() {
return name;
}
-
public void setName(String name) {
this.name = name;
}
@@ -33,7 +38,6 @@ public void setName(String name) {
public String getCode() {
return code;
}
-
public void setCode(String code) {
this.code = code;
}
@@ -41,7 +45,6 @@ public void setCode(String code) {
public String getRegion() {
return region;
}
-
public void setRegion(String region) {
this.region = region;
}
@@ -49,8 +52,50 @@ public void setRegion(String region) {
public int getRegionId() {
return regionId;
}
-
public void setRegionId(int regionId) {
this.regionId = regionId;
}
+
+ public boolean isPlugTPC() {
+ return plugTPC;
+ }
+ public void setPlugTPC(boolean plugTPC) {
+ this.plugTPC = plugTPC;
+ }
+
+ public boolean isPlugNACS() {
+ return plugNACS;
+ }
+ public void setPlugNACS(boolean plugNACS) {
+ this.plugNACS = plugNACS;
+ }
+
+ public boolean isPlugCCS1() {
+ return plugCCS1;
+ }
+ public void setPlugCCS1(boolean plugCCS1) {
+ this.plugCCS1 = plugCCS1;
+ }
+
+ public boolean isPlugCCS2() {
+ return plugCCS2;
+ }
+ public void setPlugCCS2(boolean plugCCS2) {
+ this.plugCCS2 = plugCCS2;
+ }
+
+ public boolean isPlugType2() {
+ return plugType2;
+ }
+ public void setPlugType2(boolean plugType2) {
+ this.plugType2 = plugType2;
+ }
+
+ public boolean isPlugGBT() {
+ return plugGBT;
+ }
+ public void setPlugGBT(boolean plugGBT) {
+ this.plugGBT = plugGBT;
+ }
+
}
\ No newline at end of file
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/country/CountryDTOFunction.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/country/CountryDTOFunction.java
index c8ff5f1..ba4f66f 100644
--- a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/country/CountryDTOFunction.java
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/country/CountryDTOFunction.java
@@ -15,7 +15,13 @@ public CountryDTO apply(Country country) {
countryDTO.setCode(country.getCode());
countryDTO.setRegionId(country.getRegionId());
countryDTO.setRegion(country.getRegionName());
-
+ countryDTO.setPlugTPC(country.isPlugTPC());
+ countryDTO.setPlugNACS(country.isPlugNACS());
+ countryDTO.setPlugCCS1(country.isPlugCCS1());
+ countryDTO.setPlugCCS2(country.isPlugCCS2());
+ countryDTO.setPlugType2(country.isPlugType2());
+ countryDTO.setPlugGBT(country.isPlugGBT());
+
return countryDTO;
}
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/parking/ParkingController.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/parking/ParkingController.java
new file mode 100644
index 0000000..ac113ff
--- /dev/null
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/parking/ParkingController.java
@@ -0,0 +1,37 @@
+package com.redshiftsoft.tesla.web.mvc.parking;
+
+import com.redshiftsoft.tesla.dao.dbinfo.DBInfoDAO;
+import com.redshiftsoft.tesla.dao.site.Parking;
+import com.redshiftsoft.tesla.dao.site.ParkingDAO;
+import com.redshiftsoft.tesla.web.mvc.CachingHandler;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.List;
+
+@Controller
+public class ParkingController {
+
+ @Resource
+ private ParkingDAO parkingDAO;
+ @Resource
+ private DBInfoDAO dbInfoDAO;
+
+ private CachingHandler cachingHandler;
+
+ @PostConstruct
+ public void postConstruct() {
+ cachingHandler = new CachingHandler<>(dbInfoDAO, "parking", parkingDAO);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/parking")
+ @ResponseBody
+ public List parking() {
+ return cachingHandler.getValues();
+ }
+
+}
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/PlugsDTO.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/PlugsDTO.java
new file mode 100644
index 0000000..bca36c3
--- /dev/null
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/PlugsDTO.java
@@ -0,0 +1,91 @@
+package com.redshiftsoft.tesla.web.mvc.site;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PlugsDTO {
+
+ private Integer TPC;
+ private Integer NACS;
+ private Integer CCS1;
+ private Integer CCS2;
+ private Integer Type2;
+ private Integer GBT;
+ private Integer Other;
+ private Integer Multi;
+
+ public PlugsDTO nullIfEmpty() {
+ return TPC == null && NACS == null && CCS1 == null && CCS2 == null && Type2 == null && GBT == null && Other == null && Multi == null ? null : this;
+ }
+
+ @JsonIgnore
+ public int getTotal() {
+ int total = 0;
+ if (TPC != null) total += TPC;
+ if (NACS != null) total += NACS;
+ if (CCS1 != null) total += CCS1;
+ if (CCS2 != null) total += CCS2;
+ if (Type2 != null) total += Type2;
+ if (GBT != null) total += GBT;
+ if (Other != null) total += Other;
+ return total;
+ }
+
+ public Integer getTPC() {
+ return TPC;
+ }
+ public void setTPC(Integer TPC) {
+ this.TPC = TPC;
+ }
+
+ public Integer getNACS() {
+ return NACS;
+ }
+ public void setNACS(Integer NACS) {
+ this.NACS = NACS;
+ }
+
+ public Integer getCCS1() {
+ return CCS1;
+ }
+ public void setCCS1(Integer CCS1) {
+ this.CCS1 = CCS1;
+ }
+
+ public Integer getCCS2() {
+ return CCS2;
+ }
+ public void setCCS2(Integer CCS2) {
+ this.CCS2 = CCS2;
+ }
+
+ public Integer getType2() {
+ return Type2;
+ }
+ public void setType2(Integer Type2) {
+ this.Type2 = Type2;
+ }
+
+ public Integer getGBT() {
+ return GBT;
+ }
+ public void setGBT(Integer GBT) {
+ this.GBT = GBT;
+ }
+
+ public Integer getOther() {
+ return Other;
+ }
+ public void setOther(Integer Other) {
+ this.Other = Other;
+ }
+
+ public Integer getMulti() {
+ return Multi;
+ }
+ public void setMulti(Integer Multi) {
+ this.Multi = Multi;
+ }
+
+}
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/PlugsDTOFunctions.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/PlugsDTOFunctions.java
new file mode 100644
index 0000000..0828222
--- /dev/null
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/PlugsDTOFunctions.java
@@ -0,0 +1,62 @@
+package com.redshiftsoft.tesla.web.mvc.site;
+
+import com.redshiftsoft.tesla.dao.site.Plugs;
+
+import java.util.function.Function;
+
+public class PlugsDTOFunctions {
+
+ private static final PlugsFunction PLUGS_FUNCTION = new PlugsFunction();
+ private static final PlugsDTOFunction PLUGS_DTO_FUNCTION = new PlugsDTOFunction();
+
+ public static Plugs transform(PlugsDTO plugsDTO) {
+ return PLUGS_FUNCTION.apply(plugsDTO);
+ }
+
+ public static PlugsDTO transform(Plugs plugs) {
+ return PLUGS_DTO_FUNCTION.apply(plugs);
+ }
+
+ private static class PlugsDTOFunction implements Function {
+
+ @Override
+ public PlugsDTO apply(Plugs plugs) {
+ if (plugs == null) return null;
+
+ PlugsDTO plugsDTO = new PlugsDTO();
+
+ plugsDTO.setTPC(plugs.getTPC());
+ plugsDTO.setNACS(plugs.getNACS());
+ plugsDTO.setCCS1(plugs.getCCS1());
+ plugsDTO.setCCS2(plugs.getCCS2());
+ plugsDTO.setType2(plugs.getType2());
+ plugsDTO.setGBT(plugs.getGBT());
+ plugsDTO.setOther(plugs.getOther());
+ plugsDTO.setMulti(plugs.getMulti());
+
+ return plugsDTO.nullIfEmpty();
+ }
+ }
+
+ private static class PlugsFunction implements Function {
+
+ @Override
+ public Plugs apply(PlugsDTO plugsDTO) {
+ if (plugsDTO == null) return null;
+
+ Plugs plugs = new Plugs();
+
+ plugs.setTPC(plugsDTO.getTPC());
+ plugs.setNACS(plugsDTO.getNACS());
+ plugs.setCCS1(plugsDTO.getCCS1());
+ plugs.setCCS2(plugsDTO.getCCS2());
+ plugs.setType2(plugsDTO.getType2());
+ plugs.setGBT(plugsDTO.getGBT());
+ plugs.setOther(plugsDTO.getOther());
+ plugs.setMulti(plugsDTO.getMulti());
+
+ return plugs.nullIfEmpty();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/SiteDTO.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/SiteDTO.java
index 037663d..68b1a97 100644
--- a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/SiteDTO.java
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/SiteDTO.java
@@ -40,7 +40,7 @@ public class SiteDTO {
private boolean enabled;
private Integer elevationMeters;
- // /* Power in kW */
+ /* Power in kW */
private int powerKilowatt;
private boolean solarCanopy;
private boolean battery;
@@ -51,6 +51,12 @@ public class SiteDTO {
/* True if there is one, false otherwise */
private boolean urlDiscuss;
+ private StallsDTO stalls = null;
+ private PlugsDTO plugs = null;
+
+ private Integer parkingId;
+ private String facilityName, facilityHours, accessNotes, addressNotes;
+ private Long plugshareId, osmId;
// - - - - - - - - - - - - - - - - - - - - - - -
// java.lang.Object
@@ -77,7 +83,6 @@ private List> getIdentityFields() {
public int getId() {
return id;
}
-
public void setId(int id) {
this.id = id;
}
@@ -85,7 +90,6 @@ public void setId(int id) {
public String getName() {
return name;
}
-
public void setName(String name) {
this.name = name;
}
@@ -93,7 +97,6 @@ public void setName(String name) {
public SiteStatus getStatus() {
return status;
}
-
public void setStatus(SiteStatus status) {
this.status = status;
}
@@ -103,7 +106,6 @@ public void setStatus(SiteStatus status) {
public LocalDate getDateOpened() {
return dateOpened;
}
-
public void setDateOpened(LocalDate dateOpened) {
this.dateOpened = dateOpened;
}
@@ -111,7 +113,6 @@ public void setDateOpened(LocalDate dateOpened) {
public AddressDTO getAddress() {
return address;
}
-
public void setAddress(AddressDTO address) {
this.address = address;
}
@@ -119,7 +120,6 @@ public void setAddress(AddressDTO address) {
public SiteGPS getGps() {
return gps;
}
-
public void setGps(SiteGPS gps) {
this.gps = gps;
}
@@ -127,7 +127,6 @@ public void setGps(SiteGPS gps) {
public Integer getElevationMeters() {
return elevationMeters;
}
-
public void setElevationMeters(Integer elevationMeters) {
this.elevationMeters = elevationMeters;
}
@@ -135,7 +134,6 @@ public void setElevationMeters(Integer elevationMeters) {
public boolean getUrlDiscuss() {
return urlDiscuss;
}
-
public void setUrlDiscuss(boolean urlDiscuss) {
this.urlDiscuss = urlDiscuss;
}
@@ -143,7 +141,6 @@ public void setUrlDiscuss(boolean urlDiscuss) {
public int getStallCount() {
return stallCount;
}
-
public void setStallCount(int stallCount) {
this.stallCount = stallCount;
}
@@ -151,7 +148,6 @@ public void setStallCount(int stallCount) {
public boolean isCounted() {
return counted;
}
-
public void setCounted(boolean counted) {
this.counted = counted;
}
@@ -161,7 +157,6 @@ public void setCounted(boolean counted) {
public boolean isEnabled() {
return enabled;
}
-
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@@ -169,7 +164,6 @@ public void setEnabled(boolean enabled) {
public String getHours() {
return hours;
}
-
public void setHours(String hours) {
this.hours = hours;
}
@@ -177,7 +171,6 @@ public void setHours(String hours) {
public String getLocationId() {
return locationId;
}
-
public void setLocationId(String locationId) {
this.locationId = locationId;
}
@@ -185,7 +178,6 @@ public void setLocationId(String locationId) {
public int getStatusDays() {
return statusDays;
}
-
public void setStatusDays(int statusDays) {
this.statusDays = statusDays;
}
@@ -193,7 +185,6 @@ public void setStatusDays(int statusDays) {
public int getPowerKilowatt() {
return powerKilowatt;
}
-
public void setPowerKilowatt(int powerKilowatt) {
this.powerKilowatt = powerKilowatt;
}
@@ -201,7 +192,6 @@ public void setPowerKilowatt(int powerKilowatt) {
public boolean isSolarCanopy() {
return solarCanopy;
}
-
public void setSolarCanopy(boolean solarCanopy) {
this.solarCanopy = solarCanopy;
}
@@ -209,7 +199,6 @@ public void setSolarCanopy(boolean solarCanopy) {
public boolean isBattery() {
return battery;
}
-
public void setBattery(boolean battery) {
this.battery = battery;
}
@@ -217,8 +206,70 @@ public void setBattery(boolean battery) {
public boolean isOtherEVs() {
return otherEVs;
}
-
public void setOtherEVs(boolean otherEVs) {
this.otherEVs = otherEVs;
}
+
+ public StallsDTO getStalls() {
+ return stalls;
+ }
+ public void setStalls(StallsDTO stalls) {
+ this.stalls = stalls;
+ }
+
+ public PlugsDTO getPlugs() {
+ return plugs;
+ }
+ public void setPlugs(PlugsDTO plugs) {
+ this.plugs = plugs;
+ }
+
+ public Integer getParkingId() {
+ return parkingId;
+ }
+ public void setParkingId(Integer parkingId) {
+ this.parkingId = parkingId;
+ }
+
+ public String getFacilityName() {
+ return facilityName;
+ }
+ public void setFacilityName(String facilityName) {
+ this.facilityName = facilityName;
+ }
+
+ public String getFacilityHours() {
+ return facilityHours;
+ }
+ public void setFacilityHours(String facilityHours) {
+ this.facilityHours = facilityHours;
+ }
+
+ public String getAccessNotes() {
+ return accessNotes;
+ }
+ public void setAccessNotes(String accessNotes) {
+ this.accessNotes = accessNotes;
+ }
+
+ public String getAddressNotes() {
+ return addressNotes;
+ }
+ public void setAddressNotes(String addressNotes) {
+ this.addressNotes = addressNotes;
+ }
+
+ public Long getPlugshareId() {
+ return plugshareId;
+ }
+ public void setPlugshareId(Long plugshareId) {
+ this.plugshareId = plugshareId;
+ }
+
+ public Long getOsmId() {
+ return osmId;
+ }
+ public void setOsmId(Long osmId) {
+ this.osmId = osmId;
+ }
}
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/SiteDTOFunction.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/SiteDTOFunction.java
index d803e9a..f2f7eda 100644
--- a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/SiteDTOFunction.java
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/SiteDTOFunction.java
@@ -28,6 +28,15 @@ public SiteDTO apply(Site site) {
siteDTO.setSolarCanopy(site.isSolarCanopy());
siteDTO.setBattery(site.isBattery());
siteDTO.setOtherEVs(site.isOtherEVs());
+ siteDTO.setStalls(StallsDTOFunctions.transform(site.getStalls()));
+ siteDTO.setPlugs(PlugsDTOFunctions.transform(site.getPlugs()));
+ siteDTO.setParkingId(site.getParkingId());
+ siteDTO.setFacilityName(site.getFacilityName());
+ siteDTO.setFacilityHours(site.getFacilityHours());
+ siteDTO.setAccessNotes(site.getAccessNotes());
+ siteDTO.setAddressNotes(site.getAddressNotes());
+ siteDTO.setPlugshareId(site.getPlugshareId());
+ siteDTO.setOsmId(site.getOsmId());
return siteDTO;
}
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/StallsDTO.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/StallsDTO.java
new file mode 100644
index 0000000..1554197
--- /dev/null
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/StallsDTO.java
@@ -0,0 +1,82 @@
+package com.redshiftsoft.tesla.web.mvc.site;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.redshiftsoft.tesla.dao.site.Stalls;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class StallsDTO {
+
+ private Integer urban;
+ private Integer v2;
+ private Integer v3;
+ private Integer v4;
+ private Integer other;
+ private Integer accessible;
+ private Integer trailerFriendly;
+
+ public StallsDTO nullIfEmpty() {
+ return urban == null && v2 == null && v3 == null && v4 == null && other == null && accessible == null && trailerFriendly == null ? null : this;
+ }
+
+ @JsonIgnore
+ public int getTotal() {
+ int total = 0;
+ if (urban != null) total += urban;
+ if (v2 != null) total += v2;
+ if (v3 != null) total += v3;
+ if (v4 != null) total += v4;
+ if (other != null) total += other;
+ return total;
+ }
+
+ public Integer getUrban() {
+ return urban;
+ }
+ public void setUrban(Integer urban) {
+ this.urban = urban;
+ }
+
+ public Integer getV2() {
+ return v2;
+ }
+ public void setV2(Integer v2) {
+ this.v2 = v2;
+ }
+
+ public Integer getV3() {
+ return v3;
+ }
+ public void setV3(Integer v3) {
+ this.v3 = v3;
+ }
+
+ public Integer getV4() {
+ return v4;
+ }
+ public void setV4(Integer v4) {
+ this.v4 = v4;
+ }
+
+ public Integer getOther() {
+ return other;
+ }
+ public void setOther(Integer other) {
+ this.other = other;
+ }
+
+ public Integer getAccessible() {
+ return accessible;
+ }
+ public void setAccessible(Integer accessible) {
+ this.accessible = accessible;
+ }
+
+ public Integer getTrailerFriendly() {
+ return trailerFriendly;
+ }
+ public void setTrailerFriendly(Integer trailerFriendly) {
+ this.trailerFriendly = trailerFriendly;
+ }
+
+}
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/StallsDTOFunctions.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/StallsDTOFunctions.java
new file mode 100644
index 0000000..a95b757
--- /dev/null
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/site/StallsDTOFunctions.java
@@ -0,0 +1,60 @@
+package com.redshiftsoft.tesla.web.mvc.site;
+
+import com.redshiftsoft.tesla.dao.site.Stalls;
+
+import java.util.function.Function;
+
+public class StallsDTOFunctions {
+
+ private static final StallsFunction STALLS_FUNCTION = new StallsFunction();
+ private static final StallsDTOFunction STALLS_DTO_FUNCTION = new StallsDTOFunction();
+
+ public static Stalls transform(StallsDTO stallsDTO) {
+ return STALLS_FUNCTION.apply(stallsDTO);
+ }
+
+ public static StallsDTO transform(Stalls stalls) {
+ return STALLS_DTO_FUNCTION.apply(stalls);
+ }
+
+ private static class StallsDTOFunction implements Function {
+
+ @Override
+ public StallsDTO apply(Stalls stalls) {
+ if (stalls == null) return null;
+
+ StallsDTO stallsDTO = new StallsDTO();
+
+ stallsDTO.setUrban(stalls.getUrban());
+ stallsDTO.setV2(stalls.getV2());
+ stallsDTO.setV3(stalls.getV3());
+ stallsDTO.setV4(stalls.getV4());
+ stallsDTO.setOther(stalls.getOther());
+ stallsDTO.setAccessible(stalls.getAccessible());
+ stallsDTO.setTrailerFriendly(stalls.getTrailerFriendly());
+
+ return stallsDTO.nullIfEmpty();
+ }
+ }
+
+ private static class StallsFunction implements Function {
+
+ @Override
+ public Stalls apply(StallsDTO stallsDTO) {
+ if (stallsDTO == null) return null;
+
+ Stalls stalls = new Stalls();
+
+ stalls.setUrban(stallsDTO.getUrban());
+ stalls.setV2(stallsDTO.getV2());
+ stalls.setV3(stallsDTO.getV3());
+ stalls.setV4(stallsDTO.getV4());
+ stalls.setOther(stallsDTO.getOther());
+ stalls.setAccessible(stallsDTO.getAccessible());
+ stalls.setTrailerFriendly(stallsDTO.getTrailerFriendly());
+
+ return stalls.nullIfEmpty();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteDiffLogger.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteDiffLogger.java
index 356f166..02d91b7 100644
--- a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteDiffLogger.java
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteDiffLogger.java
@@ -1,6 +1,8 @@
package com.redshiftsoft.tesla.web.mvc.siteadmin;
+import com.redshiftsoft.tesla.dao.site.Plugs;
import com.redshiftsoft.tesla.dao.site.Site;
+import com.redshiftsoft.tesla.dao.site.Stalls;
import com.redshiftsoft.tesla.dao.sitechanges.SiteChange;
import com.redshiftsoft.tesla.dao.sitechanges.SiteChangeBuilder;
import com.redshiftsoft.tesla.dao.sitechanges.SiteChangeDAO;
@@ -33,6 +35,13 @@ public boolean record(User user, Site oldSite, Site newSite) {
int nextVersion = oldSite.getVersion() + 1;
SiteChangeBuilder builder = new SiteChangeBuilder(oldSite.getId(), user.getId(), nextVersion, Instant.now());
+ Stalls oldStalls = oldSite.getStalls(), newStalls = newSite.getStalls();
+ if (oldStalls == null) oldStalls = new Stalls();
+ if (newStalls == null) newStalls = new Stalls();
+ Plugs oldPlugs = oldSite.getPlugs(), newPlugs = newSite.getPlugs();
+ if (oldPlugs == null) oldPlugs = new Plugs();
+ if (newPlugs == null) newPlugs = new Plugs();
+
diff(builder, "locationId", oldSite.getLocationId(), newSite.getLocationId());
diff(builder, "name", oldSite.getName(), newSite.getName());
diff(builder, "status", oldSite.getStatus(), newSite.getStatus());
@@ -51,6 +60,31 @@ public boolean record(User user, Site oldSite, Site newSite) {
diff(builder, "otherEVs", oldSite.isOtherEVs(), newSite.isOtherEVs());
diff(builder, "developerNotes", oldSite.getDeveloperNotes(), newSite.getDeveloperNotes());
+ diff(builder, "stallsUrban", oldStalls.getUrban(), newStalls.getUrban());
+ diff(builder, "stallsV2", oldStalls.getV2(), newStalls.getV2());
+ diff(builder, "stallsV3", oldStalls.getV3(), newStalls.getV3());
+ diff(builder, "stallsV4", oldStalls.getV4(), newStalls.getV4());
+ diff(builder, "stallsOther", oldStalls.getOther(), newStalls.getOther());
+ diff(builder, "stallsAccessible", oldStalls.getAccessible(), newStalls.getAccessible());
+ diff(builder, "stallsTrailerFriendly", oldStalls.getTrailerFriendly(), newStalls.getTrailerFriendly());
+
+ diff(builder, "plugsTPC", oldPlugs.getTPC(), newPlugs.getTPC());
+ diff(builder, "plugsNACS", oldPlugs.getNACS(), newPlugs.getNACS());
+ diff(builder, "plugsCCS1", oldPlugs.getCCS1(), newPlugs.getCCS1());
+ diff(builder, "plugsCCS2", oldPlugs.getCCS2(), newPlugs.getCCS2());
+ diff(builder, "plugsType2", oldPlugs.getType2(), newPlugs.getType2());
+ diff(builder, "plugsGBT", oldPlugs.getGBT(), newPlugs.getGBT());
+ diff(builder, "plugsOther", oldPlugs.getOther(), newPlugs.getOther());
+ diff(builder, "plugsMulti", oldPlugs.getMulti(), newPlugs.getMulti());
+
+ diff(builder, "parkingId", oldSite.getParkingId(), newSite.getParkingId());
+ diff(builder, "facilityName", oldSite.getFacilityName(), newSite.getFacilityName());
+ diff(builder, "facilityHours", oldSite.getFacilityHours(), newSite.getFacilityHours());
+ diff(builder, "accessNotes", oldSite.getAccessNotes(), newSite.getAccessNotes());
+ diff(builder, "addressNotes", oldSite.getAddressNotes(), newSite.getAddressNotes());
+ diff(builder, "plugshareId", oldSite.getPlugshareId(), newSite.getPlugshareId());
+ diff(builder, "osmId", oldSite.getOsmId(), newSite.getOsmId());
+
diff(builder, "address.street", oldSite.getAddress().getStreet(), newSite.getAddress().getStreet());
diff(builder, "address.city", oldSite.getAddress().getCity(), newSite.getAddress().getCity());
diff(builder, "address.state", oldSite.getAddress().getState(), newSite.getAddress().getState());
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditDTO.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditDTO.java
index b0ae664..6512280 100644
--- a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditDTO.java
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditDTO.java
@@ -10,6 +10,8 @@
import com.redshiftsoft.tesla.web.json.LocalDateSerializer;
import com.redshiftsoft.tesla.web.json.LocalDateTimeSerializer;
import com.redshiftsoft.tesla.web.mvc.site.AddressDTO;
+import com.redshiftsoft.tesla.web.mvc.site.PlugsDTO;
+import com.redshiftsoft.tesla.web.mvc.site.StallsDTO;
import java.time.LocalDate;
import java.time.LocalDateTime;
@@ -46,6 +48,13 @@ public class SiteEditDTO {
private boolean battery;
private boolean otherEVs;
+ private StallsDTO stalls = new StallsDTO();
+ private PlugsDTO plugs = new PlugsDTO();
+
+ private Integer parkingId;
+ private String facilityName, facilityHours, accessNotes, addressNotes;
+ private Long plugshareId, osmId;
+
// - - - - - - - - - - - - - - - - - - - - - - -
// java.lang.Object
// - - - - - - - - - - - - - - - - - - - - - - -
@@ -96,11 +105,9 @@ public boolean isOpen() {
// getters/setters
// - - - - - - - - - - - - - - - - - - - - - - -
-
public int getId() {
return id;
}
-
public void setId(int id) {
this.id = id;
}
@@ -108,7 +115,6 @@ public void setId(int id) {
public String getName() {
return name;
}
-
public void setName(String name) {
this.name = name;
}
@@ -116,7 +122,6 @@ public void setName(String name) {
public SiteStatus getStatus() {
return status;
}
-
public void setStatus(SiteStatus status) {
this.status = status;
}
@@ -126,7 +131,6 @@ public void setStatus(SiteStatus status) {
public LocalDate getDateOpened() {
return dateOpened;
}
-
public void setDateOpened(LocalDate dateOpened) {
this.dateOpened = dateOpened;
}
@@ -135,7 +139,6 @@ public void setDateOpened(LocalDate dateOpened) {
public LocalDateTime getDateModified() {
return dateModified;
}
-
public void setDateModified(LocalDateTime dateModified) {
this.dateModified = dateModified;
}
@@ -143,7 +146,6 @@ public void setDateModified(LocalDateTime dateModified) {
public AddressDTO getAddress() {
return address;
}
-
public void setAddress(AddressDTO address) {
this.address = address;
}
@@ -151,7 +153,6 @@ public void setAddress(AddressDTO address) {
public SiteGPS getGps() {
return gps;
}
-
public void setGps(SiteGPS gps) {
this.gps = gps;
}
@@ -159,7 +160,6 @@ public void setGps(SiteGPS gps) {
public Integer getElevationMeters() {
return elevationMeters;
}
-
public void setElevationMeters(Integer elevationMeters) {
this.elevationMeters = elevationMeters;
}
@@ -167,7 +167,6 @@ public void setElevationMeters(Integer elevationMeters) {
public String getUrlDiscuss() {
return urlDiscuss;
}
-
public void setUrlDiscuss(String urlDiscuss) {
this.urlDiscuss = urlDiscuss;
}
@@ -175,7 +174,6 @@ public void setUrlDiscuss(String urlDiscuss) {
public int getStallCount() {
return stallCount;
}
-
public void setStallCount(int stallCount) {
this.stallCount = stallCount;
}
@@ -183,7 +181,6 @@ public void setStallCount(int stallCount) {
public boolean isCounted() {
return counted;
}
-
public void setCounted(boolean counted) {
this.counted = counted;
}
@@ -193,7 +190,6 @@ public void setCounted(boolean counted) {
public boolean isEnabled() {
return enabled;
}
-
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@@ -201,7 +197,6 @@ public void setEnabled(boolean enabled) {
public String getHours() {
return hours;
}
-
public void setHours(String hours) {
this.hours = hours;
}
@@ -209,7 +204,6 @@ public void setHours(String hours) {
public String getLocationId() {
return locationId;
}
-
public void setLocationId(String locationId) {
this.locationId = locationId;
}
@@ -217,7 +211,6 @@ public void setLocationId(String locationId) {
public int getPowerKiloWatt() {
return powerKiloWatt;
}
-
public void setPowerKiloWatt(int powerKiloWatt) {
this.powerKiloWatt = powerKiloWatt;
}
@@ -225,7 +218,6 @@ public void setPowerKiloWatt(int powerKiloWatt) {
public NotifyEnum getNotify() {
return notify;
}
-
public void setNotify(NotifyEnum notify) {
this.notify = notify;
}
@@ -233,7 +225,6 @@ public void setNotify(NotifyEnum notify) {
public boolean isSolarCanopy() {
return solarCanopy;
}
-
public void setSolarCanopy(boolean solarCanopy) {
this.solarCanopy = solarCanopy;
}
@@ -241,7 +232,6 @@ public void setSolarCanopy(boolean solarCanopy) {
public boolean isBattery() {
return battery;
}
-
public void setBattery(boolean battery) {
this.battery = battery;
}
@@ -249,7 +239,6 @@ public void setBattery(boolean battery) {
public String getDeveloperNotes() {
return developerNotes;
}
-
public void setDeveloperNotes(String developerNotes) {
this.developerNotes = developerNotes;
}
@@ -257,7 +246,6 @@ public void setDeveloperNotes(String developerNotes) {
public int getVersion() {
return version;
}
-
public void setVersion(int version) {
this.version = version;
}
@@ -265,11 +253,73 @@ public void setVersion(int version) {
public boolean isOtherEVs() {
return otherEVs;
}
-
public void setOtherEVs(boolean otherEVs) {
this.otherEVs = otherEVs;
}
+ public StallsDTO getStalls() {
+ return stalls;
+ }
+ public void setStalls(StallsDTO stalls) {
+ this.stalls = stalls;
+ }
+
+ public PlugsDTO getPlugs() {
+ return plugs;
+ }
+ public void setPlugs(PlugsDTO plugs) {
+ this.plugs = plugs;
+ }
+
+ public Integer getParkingId() {
+ return parkingId;
+ }
+ public void setParkingId(Integer parkingId) {
+ this.parkingId = parkingId;
+ }
+
+ public String getFacilityName() {
+ return facilityName;
+ }
+ public void setFacilityName(String facilityName) {
+ this.facilityName = facilityName;
+ }
+
+ public String getFacilityHours() {
+ return facilityHours;
+ }
+ public void setFacilityHours(String facilityHours) {
+ this.facilityHours = facilityHours;
+ }
+
+ public String getAccessNotes() {
+ return accessNotes;
+ }
+ public void setAccessNotes(String accessNotes) {
+ this.accessNotes = accessNotes;
+ }
+
+ public String getAddressNotes() {
+ return addressNotes;
+ }
+ public void setAddressNotes(String addressNotes) {
+ this.addressNotes = addressNotes;
+ }
+
+ public Long getPlugshareId() {
+ return plugshareId;
+ }
+ public void setPlugshareId(Long plugshareId) {
+ this.plugshareId = plugshareId;
+ }
+
+ public Long getOsmId() {
+ return osmId;
+ }
+ public void setOsmId(Long osmId) {
+ this.osmId = osmId;
+ }
+
public enum NotifyEnum {
yes, log, no
}
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditDTOFunctions.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditDTOFunctions.java
index c25e451..a711b5a 100644
--- a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditDTOFunctions.java
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditDTOFunctions.java
@@ -2,6 +2,10 @@
import com.redshiftsoft.tesla.dao.site.Site;
import com.redshiftsoft.tesla.web.mvc.site.AddressDTOFunctions;
+import com.redshiftsoft.tesla.web.mvc.site.PlugsDTO;
+import com.redshiftsoft.tesla.web.mvc.site.PlugsDTOFunctions;
+import com.redshiftsoft.tesla.web.mvc.site.SiteDTOFunction;
+import com.redshiftsoft.tesla.web.mvc.site.StallsDTOFunctions;
import java.util.Collection;
import java.util.List;
@@ -56,6 +60,15 @@ public SiteEditDTO apply(Site site) {
siteDTO.setSolarCanopy(site.isSolarCanopy());
siteDTO.setBattery(site.isBattery());
siteDTO.setOtherEVs(site.isOtherEVs());
+ siteDTO.setStalls(StallsDTOFunctions.transform(site.getStalls()));
+ siteDTO.setPlugs(PlugsDTOFunctions.transform(site.getPlugs()));
+ siteDTO.setParkingId(site.getParkingId());
+ siteDTO.setFacilityName(site.getFacilityName());
+ siteDTO.setFacilityHours(site.getFacilityHours());
+ siteDTO.setAccessNotes(site.getAccessNotes());
+ siteDTO.setAddressNotes(site.getAddressNotes());
+ siteDTO.setPlugshareId(site.getPlugshareId());
+ siteDTO.setOsmId(site.getOsmId());
siteDTO.setDeveloperNotes(site.getDeveloperNotes());
return siteDTO;
@@ -89,6 +102,15 @@ public Site apply(SiteEditDTO siteDTO) {
site.setSolarCanopy(siteDTO.isSolarCanopy());
site.setBattery(siteDTO.isBattery());
site.setOtherEVs(siteDTO.isOtherEVs());
+ site.setStalls(StallsDTOFunctions.transform(siteDTO.getStalls()));
+ site.setPlugs(PlugsDTOFunctions.transform(siteDTO.getPlugs()));
+ site.setParkingId(siteDTO.getParkingId());
+ site.setFacilityName(siteDTO.getFacilityName());
+ site.setFacilityHours(siteDTO.getFacilityHours());
+ site.setAccessNotes(siteDTO.getAccessNotes());
+ site.setAddressNotes(siteDTO.getAddressNotes());
+ site.setPlugshareId(siteDTO.getPlugshareId());
+ site.setOsmId(siteDTO.getOsmId());
site.setDeveloperNotes(siteDTO.getDeveloperNotes());
return site;
diff --git a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditValidation.java b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditValidation.java
index 97c2eda..3fa1686 100644
--- a/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditValidation.java
+++ b/service-war/src/main/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditValidation.java
@@ -3,6 +3,9 @@
import com.google.common.collect.Lists;
import com.redshiftsoft.tesla.dao.site.*;
import com.redshiftsoft.tesla.web.mvc.site.AddressDTO;
+import com.redshiftsoft.tesla.web.mvc.site.PlugsDTO;
+import com.redshiftsoft.tesla.web.mvc.site.StallsDTO;
+
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@@ -67,9 +70,9 @@ private void validateCommon(SiteEditDTO site, List errorMessages) {
//
// Date Opened
//
- if (SiteStatus.OPEN.equals(site.getStatus())) {
+ if (SiteStatus.OPEN.equals(site.getStatus()) || SiteStatus.EXPANDING.equals(site.getStatus())) {
if (site.getDateOpened() == null) {
- errorMessages.add("missing open date for OPEN site");
+ errorMessages.add("missing open date for OPEN or EXPANDING site");
}
} else {
if (site.getDateOpened() != null) {
@@ -111,12 +114,36 @@ private void validateCommon(SiteEditDTO site, List errorMessages) {
}
//
- // stall count
+ // stall/plug counts
//
if (site.getStallCount() <= 0) {
errorMessages.add("stall count must be at least 1");
}
+ StallsDTO stalls = site.getStalls();
+ if (stalls == null) stalls = new StallsDTO();
+ PlugsDTO plugs = site.getPlugs();
+ if (plugs == null) plugs = new PlugsDTO();
+
+ if (site.getStallCount() != stalls.getTotal()) {
+ errorMessages.add("stall count must equal total of individual stall type counts");
+ }
+ if (stalls.getAccessible() != null && stalls.getAccessible() > site.getStallCount()) {
+ errorMessages.add("# of accessible stalls cannot be more than total stall count");
+ }
+ if (stalls.getTrailerFriendly() != null && stalls.getTrailerFriendly() > site.getStallCount()) {
+ errorMessages.add("# of trailer-friendly stalls cannot be more than total stall count");
+ }
+ if (site.getStallCount() != plugs.getTotal() && (plugs.getMulti() == null || plugs.getMulti() == 0)) {
+ errorMessages.add("stall count must equal total of individual plug type counts (unless any stalls are multi-plug)");
+ }
+ if (plugs.getMulti() != null && plugs.getMulti() > 0 && site.getStallCount() > plugs.getTotal() - plugs.getMulti()) {
+ errorMessages.add("stall count cannot exceed total of individual plug type counts minus multi-plug count");
+ }
+
+ //
+ // power
+ //
if (site.getPowerKiloWatt() < 0 || site.getPowerKiloWatt() > 500) {
errorMessages.add("power must be in range [0,500]");
}
@@ -144,6 +171,20 @@ private void validateCommon(SiteEditDTO site, List errorMessages) {
}
}
+ //
+ // China-specific logic: Hong Kong is CCS2 only, Macau is CCS2 or GB/T, the rest of China is GB/T only
+ //
+ if (address.getCountry() == "China") {
+ if (address.getState().toLowerCase() == "hong kong") {
+ if (plugs.getGBT() > 0) {
+ errorMessages.add("Hong Kong does not use GB/T plugs");
+ }
+ } else if (address.getState().toLowerCase() != "macau") {
+ if (plugs.getCCS2() > 0) {
+ errorMessages.add("China locations (except Hong Kong and Macau) only use GB/T plugs");
+ }
+ }
+ }
}
}
diff --git a/service-war/src/test/java/com/redshiftsoft/tesla/web/mvc/site/SiteEditValidation_UT.java b/service-war/src/test/java/com/redshiftsoft/tesla/web/mvc/site/SiteEditValidation_UT.java
index be99832..cfe00b0 100644
--- a/service-war/src/test/java/com/redshiftsoft/tesla/web/mvc/site/SiteEditValidation_UT.java
+++ b/service-war/src/test/java/com/redshiftsoft/tesla/web/mvc/site/SiteEditValidation_UT.java
@@ -48,6 +48,10 @@ private SiteEditDTO createTestSite() {
site.setDateOpened(LocalDate.now());
site.setGps(new SiteGPS(1, 2));
site.setStallCount(4);
+ site.setStalls(new StallsDTO());
+ site.getStalls().setV3(4);
+ site.setPlugs(new PlugsDTO());
+ site.getPlugs().setNACS(4);
site.setElevationMeters(1000);
site.setAddress(address);
return site;
diff --git a/service-war/src/test/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditController_IT.java b/service-war/src/test/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditController_IT.java
index 7a40194..5f63761 100644
--- a/service-war/src/test/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditController_IT.java
+++ b/service-war/src/test/java/com/redshiftsoft/tesla/web/mvc/siteadmin/SiteEditController_IT.java
@@ -111,7 +111,13 @@ public void edit_requires_editor_role() throws Exception {
// then
- Assertions.assertEquals("{\"result\":\"FAIL\",\"messages\":[\"gps is required\",\"elevation is required\",\"street is required\",\"city is required\",\"country is required\"]}", response);
+ Assertions.assertEquals("{" +
+ "\"result\":\"FAIL\",\"messages\":[" +
+ "\"gps is required\",\"elevation is required\"," +
+ "\"stall count must equal total of individual stall type counts\"," +
+ "\"stall count must equal total of individual plug type counts (unless any stalls are multi-plug)\"," +
+ "\"street is required\",\"city is required\",\"country is required\"" +
+ "]}", response);
}
}
diff --git a/web-scrape/pom.xml b/web-scrape/pom.xml
index 9ea127e..938aaec 100644
--- a/web-scrape/pom.xml
+++ b/web-scrape/pom.xml
@@ -3,7 +3,7 @@
info.supercharge.api
supercharge.info-api
- 5.0.3-SNAPSHOT
+ 5.1.1-SNAPSHOT
4.0.0