Skip to content

Commit 3065953

Browse files
committed
feat(series import): extract release day and month from dates in dd.mm.yyyy format.
Fix #1287
1 parent bc3504e commit 3065953

18 files changed

+229
-30
lines changed

src/main/java/ru/mystamps/web/feature/series/SeriesValidation.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
@SuppressWarnings("PMD.CommentDefaultAccessModifier")
2323
public final class SeriesValidation {
2424

25+
public static final int MAX_DAYS_IN_MONTH = 31;
26+
public static final int MAX_MONTHS_IN_YEAR = 12;
27+
2528
public static final int MIN_STAMPS_IN_SERIES = 1;
2629
public static final int MAX_STAMPS_IN_SERIES = 150;
2730
public static final int MIN_RELEASE_YEAR = 1840;
@@ -30,9 +33,6 @@ public final class SeriesValidation {
3033
static final String CATALOG_NUMBERS_AND_LETTERS_REGEXP = "[1-9][0-9]{0,3}[a-z]?(,[1-9][0-9]{0,3}[a-z]?)*";
3134
static final int MAX_SERIES_COMMENT_LENGTH = Series.COMMENT_LENGTH;
3235

33-
static final int MAX_DAYS_IN_MONTH = 31;
34-
static final int MAX_MONTHS_IN_YEAR = 12;
35-
3636
private SeriesValidation() {
3737
}
3838

src/main/java/ru/mystamps/web/feature/series/importing/AddSeriesParsedDataDbDto.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public class AddSeriesParsedDataDbDto {
3030
private Integer categoryId;
3131
private Integer countryId;
3232
private String imageUrl;
33+
private Integer releaseDay;
34+
private Integer releaseMonth;
3335
private Integer releaseYear;
3436
private Integer quantity;
3537
private Boolean perforated;

src/main/java/ru/mystamps/web/feature/series/importing/ImportSeriesForm.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import lombok.Getter;
2121
import lombok.Setter;
22+
import org.hibernate.validator.constraints.Range;
2223
import org.hibernate.validator.constraints.URL;
2324
import org.springframework.web.multipart.MultipartFile;
2425
import ru.mystamps.web.common.LinkEntityDto;
@@ -34,10 +35,16 @@
3435
import javax.validation.constraints.NotNull;
3536
import java.math.BigDecimal;
3637

38+
import static ru.mystamps.web.feature.series.SeriesValidation.MAX_DAYS_IN_MONTH;
39+
import static ru.mystamps.web.feature.series.SeriesValidation.MAX_MONTHS_IN_YEAR;
3740
import static ru.mystamps.web.feature.series.SeriesValidation.MAX_STAMPS_IN_SERIES;
3841
import static ru.mystamps.web.feature.series.SeriesValidation.MIN_RELEASE_YEAR;
3942
import static ru.mystamps.web.feature.series.SeriesValidation.MIN_STAMPS_IN_SERIES;
4043

44+
// @todo #1287 /series/import/request/{id}: add integration tests for release day and month
45+
// @todo #1287 /series/import/request/{id}: month is required when day is specified
46+
// @todo #1287 /series/import/request/{id}: year is required when month is specified
47+
// @todo #1287 /series/import/request/{id}: release date should be in past
4148
@Getter
4249
@Setter
4350
public class ImportSeriesForm implements AddSeriesDto, NullableImageUrl {
@@ -68,6 +75,14 @@ public class ImportSeriesForm implements AddSeriesDto, NullableImageUrl {
6875
@URL
6976
private String imageUrl;
7077

78+
// @todo #1287 /series/import/request/{id}(day): add integration test for invalid day
79+
@Range(min = 1, max = MAX_DAYS_IN_MONTH, message = "{day.invalid}")
80+
private Integer day;
81+
82+
// @todo #1287 /series/import/request/{id}(month): add integration test for invalid month
83+
@Range(min = 1, max = MAX_MONTHS_IN_YEAR, message = "{month.invalid}")
84+
private Integer month;
85+
7186
// @todo #709 /series/import/request/{id}(year): add validation for min value
7287
// @todo #709 /series/import/request/{id}(year): add validation for year in future
7388
@Min(value = MIN_RELEASE_YEAR, message = "{series.too-early-release-year}")
@@ -108,16 +123,6 @@ public MultipartFile getImage() {
108123
return downloadedImage;
109124
}
110125

111-
@Override
112-
public Integer getDay() {
113-
return null;
114-
}
115-
116-
@Override
117-
public Integer getMonth() {
118-
return null;
119-
}
120-
121126
@Override
122127
public BigDecimal getMichelPrice() {
123128
return null;

src/main/java/ru/mystamps/web/feature/series/importing/JdbcSeriesImportDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ public void addParsedData(Integer requestId, AddSeriesParsedDataDbDto data) {
193193
params.put("category_id", data.getCategoryId());
194194
params.put("country_id", data.getCountryId());
195195
params.put("image_url", data.getImageUrl());
196+
params.put("release_day", data.getReleaseDay());
197+
params.put("release_month", data.getReleaseMonth());
196198
params.put("release_year", data.getReleaseYear());
197199
params.put("created_at", data.getCreatedAt());
198200
params.put("updated_at", data.getUpdatedAt());

src/main/java/ru/mystamps/web/feature/series/importing/RowMappers.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ private RowMappers() {
5858
);
5959

6060
String imageUrl = rs.getString("image_url");
61+
Integer releaseDay = JdbcUtils.getInteger(rs, "release_day");
62+
Integer releaseMonth = JdbcUtils.getInteger(rs, "release_month");
6163
Integer releaseYear = JdbcUtils.getInteger(rs, "release_year");
6264
Integer quantity = JdbcUtils.getInteger(rs, "quantity");
6365
Boolean perforated = JdbcUtils.getBoolean(rs, "perforated");
@@ -67,6 +69,8 @@ private RowMappers() {
6769
category,
6870
country,
6971
imageUrl,
72+
releaseDay,
73+
releaseMonth,
7074
releaseYear,
7175
quantity,
7276
perforated,

src/main/java/ru/mystamps/web/feature/series/importing/SeriesExtractedInfo.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@
2626

2727
@Getter
2828
@RequiredArgsConstructor
29+
@SuppressWarnings("PMD.TooManyFields")
2930
public class SeriesExtractedInfo {
3031
private final List<Integer> categoryIds;
3132
private final List<Integer> countryIds;
33+
private final Integer releaseDay;
34+
private final Integer releaseMonth;
3235
private final Integer releaseYear;
3336
private final Integer quantity;
3437
private final Boolean perforated;

src/main/java/ru/mystamps/web/feature/series/importing/SeriesImportController.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ public String showRequestAndImportSeriesForm(
153153
form.setCategory(series.getCategory());
154154
form.setCountry(series.getCountry());
155155
form.setImageUrl(series.getImageUrl());
156+
form.setDay(series.getIssueDay());
157+
form.setMonth(series.getIssueMonth());
156158
form.setYear(series.getIssueYear());
157159
form.setQuantity(series.getQuantity());
158160
if (series.getPerforated() != null) {

src/main/java/ru/mystamps/web/feature/series/importing/SeriesImportServiceImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ public void saveParsedData(Integer requestId, SeriesExtractedInfo seriesInfo, St
189189
seriesParsedData.setUpdatedAt(now);
190190
seriesParsedData.setCategoryId(categoryId);
191191
seriesParsedData.setCountryId(countryId);
192+
seriesParsedData.setReleaseDay(seriesInfo.getReleaseDay());
193+
seriesParsedData.setReleaseMonth(seriesInfo.getReleaseMonth());
192194
seriesParsedData.setReleaseYear(seriesInfo.getReleaseYear());
193195
seriesParsedData.setQuantity(seriesInfo.getQuantity());
194196
seriesParsedData.setPerforated(seriesInfo.getPerforated());

src/main/java/ru/mystamps/web/feature/series/importing/SeriesInfoExtractorServiceImpl.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.net.URL;
3535
import java.util.Arrays;
3636
import java.util.Collections;
37+
import java.util.HashMap;
3738
import java.util.LinkedHashSet;
3839
import java.util.List;
3940
import java.util.Map;
@@ -55,7 +56,7 @@ public class SeriesInfoExtractorServiceImpl implements SeriesInfoExtractorServic
5556
// Year should be in range within 1840 and 2099 inclusive.
5657
// CheckStyle: ignore LineLength for next 2 lines
5758
private static final Pattern RELEASE_DATE_REGEXP =
58-
Pattern.compile("([0-9]{2}\\.[0-9]{2}\\.)?(?<year>18[4-9][0-9]|19[0-9]{2}|20[0-9]{2})(г(од|\\.)?)?");
59+
Pattern.compile("((?<day>[0-9]{2})\\.(?<month>[0-9]{2})\\.)?(?<year>18[4-9][0-9]|19[0-9]{2}|20[0-9]{2})(г(од|\\.)?)?");
5960

6061
// Regular expression matches number of the stamps in a series (from 1 to 999).
6162
// CheckStyle: ignore LineLength for next 2 lines
@@ -119,6 +120,8 @@ public SeriesExtractedInfo extract(String pageUrl, RawParsedDataDto data) {
119120
return new SeriesExtractedInfo(
120121
categoryIds,
121122
countryIds,
123+
releaseDate.get("day"),
124+
releaseDate.get("month"),
122125
releaseDate.get("year"),
123126
quantity,
124127
perforated,
@@ -216,6 +219,7 @@ public SeriesExtractedInfo extract(String pageUrl, RawParsedDataDto data) {
216219
return Collections.emptyList();
217220
}
218221

222+
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
219223
/* default */ Map<String, Integer> extractIssueDate(String fragment) {
220224
if (StringUtils.isBlank(fragment)) {
221225
return Collections.emptyMap();
@@ -233,7 +237,20 @@ public SeriesExtractedInfo extract(String pageUrl, RawParsedDataDto data) {
233237
try {
234238
Integer year = Integer.valueOf(matcher.group("year"));
235239
log.debug("Release year is {}", year);
236-
return Collections.singletonMap("year", year);
240+
241+
String day = matcher.group("day");
242+
String month = matcher.group("month");
243+
244+
Map<String, Integer> result = new HashMap<>();
245+
result.put("year", year);
246+
247+
if (day != null && month != null) {
248+
// @todo #1287 SeriesInfoExtractorServiceImpl.extractIssueDate():
249+
// filter out invalid day/month
250+
result.put("day", Integer.valueOf(day));
251+
result.put("month", Integer.valueOf(month));
252+
}
253+
return result;
237254

238255
} catch (NumberFormatException ignored) { // NOPMD: EmptyCatchBlock
239256
// continue with the next element

src/main/java/ru/mystamps/web/feature/series/importing/SeriesParsedDataDto.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public class SeriesParsedDataDto {
2727
private final LinkEntityDto category;
2828
private final LinkEntityDto country;
2929
private final String imageUrl;
30+
private final Integer issueDay;
31+
private final Integer issueMonth;
3032
private final Integer issueYear;
3133
private final Integer quantity;
3234
private final Boolean perforated;

src/main/resources/liquibase/version/0.4.3.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
<include file="0.4.3/2020-03-11--cleanup_togglz_features.xml" relativeToChangelogFile="true" />
1111
<include file="0.4.3/2020-03-11--fix-nullable-series_import_requests-url.xml" relativeToChangelogFile="true" />
1212
<include file="0.4.3/2020-03-12--michel_catalog_code_length.xml" relativeToChangelogFile="true" />
13+
<include file="0.4.3/2020-03-21--add_release_day_to_series_import_parsed_data.xml" relativeToChangelogFile="true" />
1314

1415
</databaseChangeLog>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<databaseChangeLog
3+
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
6+
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
7+
8+
<changeSet id="add-release-day-to-series_import_parsed_data" author="php-coder" context="scheme">
9+
10+
<addColumn tableName="series_import_parsed_data">
11+
<!--
12+
We can't use beforeColumn="release_year" as it doesn't work in MySQL.
13+
We add the field after "updated_at" because we expect that "release_year" is the next field.
14+
-->
15+
<column name="release_day" type="INTEGER" afterColumn="updated_at" />
16+
<column name="release_month" type="INTEGER" afterColumn="release_day" />
17+
</addColumn>
18+
19+
</changeSet>
20+
21+
</databaseChangeLog>

src/main/resources/sql/series_import_request_dao_queries.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ INSERT \
8787
, category_id \
8888
, country_id \
8989
, image_url \
90+
, release_day \
91+
, release_month \
9092
, release_year \
9193
, quantity \
9294
, perforated \
@@ -99,6 +101,8 @@ VALUES \
99101
, :category_id \
100102
, :country_id \
101103
, :image_url \
104+
, :release_day \
105+
, :release_month \
102106
, :release_year \
103107
, :quantity \
104108
, :perforated \
@@ -115,6 +119,8 @@ series_import_requests.find_series_parsed_data_by_request_id = \
115119
, count.id AS country_id \
116120
, count.slug AS country_slug \
117121
, CASE WHEN 'ru' = :lang THEN COALESCE(count.name_ru, count.name) ELSE count.name END AS country_name \
122+
, pd.release_day \
123+
, pd.release_month \
118124
, pd.release_year \
119125
, pd.quantity \
120126
, pd.perforated \

src/main/webapp/WEB-INF/views/series/import/info.html

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,89 @@ <h3 th:text="#{t_gathered_data}">
275275
</td>
276276
</tr>
277277

278+
<tr th:if="${importSeriesForm.day != null}" th:classappend="${#fields.hasErrors('day') ? 'has-error' : ''}">
279+
<th>
280+
<label for="day" class="control-label" th:text="#{t_day}">
281+
Day
282+
</label>
283+
</th>
284+
<td>
285+
<select id="day" class="form-control" th:field="*{day}" th:disabled="${disabled}">
286+
<option value=""></option>
287+
<option value="1">1</option>
288+
<option value="2">2</option>
289+
<option value="3">3</option>
290+
<option value="4">4</option>
291+
<option value="5">5</option>
292+
<option value="6">6</option>
293+
<option value="7">7</option>
294+
<option value="8">8</option>
295+
<option value="9" selected="selected">9</option>
296+
<option value="10">10</option>
297+
<option value="11">11</option>
298+
<option value="12">12</option>
299+
<option value="13">13</option>
300+
<option value="14">14</option>
301+
<option value="15">15</option>
302+
<option value="16">16</option>
303+
<option value="17">17</option>
304+
<option value="18">18</option>
305+
<option value="19">19</option>
306+
<option value="20">20</option>
307+
<option value="21">21</option>
308+
<option value="22">22</option>
309+
<option value="23">23</option>
310+
<option value="24">24</option>
311+
<option value="25">25</option>
312+
<option value="26">26</option>
313+
<option value="27">27</option>
314+
<option value="28">28</option>
315+
<option value="29">29</option>
316+
<option value="30">30</option>
317+
<option value="31">31</option>
318+
</select>
319+
<!--/*/
320+
<span id="day.errors"
321+
class="help-block"
322+
th:if="${#fields.hasErrors('day')}"
323+
th:each="error : ${#fields.errors('day')}"
324+
th:text="${error}"></span>
325+
/*/-->
326+
</td>
327+
</tr>
328+
329+
<tr th:if="${importSeriesForm.month != null}" th:classappend="${#fields.hasErrors('month') ? 'has-error' : ''}">
330+
<th>
331+
<label for="month" class="control-label" th:text="#{t_month}">
332+
Month
333+
</label>
334+
</th>
335+
<td>
336+
<select id="month" class="form-control" th:field="*{month}" th:disabled="${disabled}">
337+
<option value=""></option>
338+
<option value="1">1</option>
339+
<option value="2">2</option>
340+
<option value="3">3</option>
341+
<option value="4">4</option>
342+
<option value="5">5</option>
343+
<option value="6">6</option>
344+
<option value="7">7</option>
345+
<option value="8">8</option>
346+
<option value="9">9</option>
347+
<option value="10">10</option>
348+
<option value="11" selected="selected">11</option>
349+
<option value="12">12</option>
350+
</select>
351+
<!--/*/
352+
<span id="month.errors"
353+
class="help-block"
354+
th:if="${#fields.hasErrors('month')}"
355+
th:each="error : ${#fields.errors('month')}"
356+
th:text="${error}"></span>
357+
/*/-->
358+
</td>
359+
</tr>
360+
278361
<tr th:if="${importSeriesForm.year != null}" th:classappend="${#fields.hasErrors('year') ? 'has-error' : ''}">
279362
<th>
280363
<label for="year" class="control-label" th:text="#{t_year}">

0 commit comments

Comments
 (0)