Skip to content

Commit 02ffadf

Browse files
feat(STOP-148): add GPS location capture support for beneficiary and RMNCH records (#167)
Introduces GPS-related fields (gpsLatitude, gpsLongitude, digipin, gpsTimestamp, isGpsUnavailable, and gpsUnavailableReason) across beneficiary address and RMNCH domain models, including MBeneficiaryaddress, Address DTO, RMNCHBeneficiaryDetailsRmnch, and RMNCHHouseHoldDetails. Enhances IdentityMapper and IdentityService to map and persist GPS information between incoming DTOs and beneficiary address entities. Updates RmnchDataSyncServiceImpl to extract and synchronize GPS details from the nested i_bendemographics payload during beneficiary sync, and to parse gpsTimestamp from household details during RMNCH household data processing. Co-authored-by: Sehjot Singh Pannu <sehjot.singh@unthinkable.co>
1 parent 085e541 commit 02ffadf

2 files changed

Lines changed: 77 additions & 1 deletion

File tree

‎src/main/java/com/iemr/common/identity/mapper/InputMapper.java‎

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
*/
2222
package com.iemr.common.identity.mapper;
2323

24+
import java.io.IOException;
25+
import java.sql.Timestamp;
26+
import java.time.Instant;
27+
import java.time.LocalDateTime;
28+
import java.time.format.DateTimeFormatter;
29+
import java.util.Locale;
30+
2431
import org.slf4j.Logger;
2532
import org.slf4j.LoggerFactory;
2633

@@ -33,6 +40,10 @@
3340
import com.google.gson.JsonParser;
3441
import com.google.gson.JsonPrimitive;
3542
import com.google.gson.LongSerializationPolicy;
43+
import com.google.gson.TypeAdapter;
44+
import com.google.gson.stream.JsonReader;
45+
import com.google.gson.stream.JsonToken;
46+
import com.google.gson.stream.JsonWriter;
3647
import com.iemr.common.identity.exception.IEMRException;
3748

3849
public class InputMapper
@@ -42,11 +53,41 @@ public class InputMapper
4253
private static GsonBuilder builder;
4354
private static InputMapper instance = null;
4455

56+
private static final DateTimeFormatter ISO_WITH_Z =
57+
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
58+
private static final DateTimeFormatter CLIENT_DATE_FORMAT =
59+
DateTimeFormatter.ofPattern("MMM dd, yyyy, h:mm:ss a", Locale.ENGLISH);
60+
61+
private static final TypeAdapter<Timestamp> TIMESTAMP_ADAPTER = new TypeAdapter<Timestamp>() {
62+
@Override
63+
public void write(JsonWriter out, Timestamp value) throws IOException {
64+
if (value == null) out.nullValue();
65+
else out.value(value.getTime());
66+
}
67+
68+
@Override
69+
public Timestamp read(JsonReader in) throws IOException {
70+
if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; }
71+
if (in.peek() == JsonToken.NUMBER) return new Timestamp(in.nextLong());
72+
String s = in.nextString();
73+
// epoch millis as string
74+
try { return new Timestamp(Long.parseLong(s)); } catch (NumberFormatException ignored) {}
75+
// ISO 8601 with Z e.g. "2021-06-18T00:00:00.000Z"
76+
try { return Timestamp.from(Instant.parse(s)); } catch (Exception ignored) {}
77+
// Mobile client format e.g. "Jun 18, 2021, 5:30:00 AM"
78+
try { return Timestamp.valueOf(LocalDateTime.parse(s, CLIENT_DATE_FORMAT)); } catch (Exception ignored) {}
79+
// Fallback: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" literal Z
80+
try { return Timestamp.valueOf(LocalDateTime.parse(s, ISO_WITH_Z)); } catch (Exception ignored) {}
81+
return null;
82+
}
83+
};
84+
4585
private InputMapper()
4686
{
4787
builder = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
4888
// .excludeFieldsWithoutExposeAnnotation()
49-
.serializeNulls().setLongSerializationPolicy(LongSerializationPolicy.STRING);
89+
.serializeNulls().setLongSerializationPolicy(LongSerializationPolicy.STRING)
90+
.registerTypeAdapter(Timestamp.class, TIMESTAMP_ADAPTER);
5091
}
5192

5293
public static InputMapper getInstance()

‎src/main/java/com/iemr/common/identity/utils/mapper/InputMapper.java‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,24 @@
2121
*/
2222
package com.iemr.common.identity.utils.mapper;
2323

24+
import java.io.IOException;
25+
import java.sql.Timestamp;
26+
import java.time.Instant;
27+
import java.time.LocalDateTime;
28+
import java.time.ZoneOffset;
29+
import java.time.format.DateTimeFormatter;
30+
2431
import org.slf4j.Logger;
2532
import org.slf4j.LoggerFactory;
2633
import org.springframework.stereotype.Service;
2734

2835
import com.google.gson.ExclusionStrategy;
2936
import com.google.gson.GsonBuilder;
3037
import com.google.gson.JsonElement;
38+
import com.google.gson.TypeAdapter;
39+
import com.google.gson.stream.JsonReader;
40+
import com.google.gson.stream.JsonToken;
41+
import com.google.gson.stream.JsonWriter;
3142
import com.iemr.common.identity.utils.exception.IEMRException;
3243

3344
/**
@@ -48,6 +59,30 @@ public InputMapper() {
4859
if (builder == null) {
4960
builder = new GsonBuilder();
5061
builder.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
62+
builder.registerTypeAdapter(Timestamp.class, new TypeAdapter<Timestamp>() {
63+
private final DateTimeFormatter isoWithZ = DateTimeFormatter.ISO_INSTANT;
64+
private final DateTimeFormatter isoNoTz = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
65+
66+
@Override
67+
public void write(JsonWriter out, Timestamp value) throws IOException {
68+
if (value == null) out.nullValue();
69+
else out.value(value.getTime());
70+
}
71+
72+
@Override
73+
public Timestamp read(JsonReader in) throws IOException {
74+
if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; }
75+
if (in.peek() == JsonToken.NUMBER) return new Timestamp(in.nextLong());
76+
String s = in.nextString();
77+
// epoch millis as string
78+
try { return new Timestamp(Long.parseLong(s)); } catch (NumberFormatException ignored) {}
79+
// ISO 8601 with timezone (e.g. "2026-05-28T03:24:35.000Z")
80+
try { return Timestamp.from(Instant.parse(s)); } catch (Exception ignored) {}
81+
// ISO without timezone (e.g. "2026-05-28T03:24:35.000")
82+
try { return Timestamp.from(LocalDateTime.parse(s, isoNoTz).toInstant(ZoneOffset.UTC)); } catch (Exception ignored) {}
83+
return null;
84+
}
85+
});
5186
}
5287
}
5388

0 commit comments

Comments
 (0)