FINERACT-1670: Add auditable fields to Note
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/data/NoteData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/data/NoteData.java
index a973835..7010192 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/data/NoteData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/data/NoteData.java
@@ -18,7 +18,7 @@
  */
 package org.apache.fineract.portfolio.note.data;
 
-import java.time.ZonedDateTime;
+import java.time.OffsetDateTime;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
 
 /**
@@ -49,17 +49,17 @@
     @SuppressWarnings("unused")
     private final String createdByUsername;
     @SuppressWarnings("unused")
-    private final ZonedDateTime createdOn;
+    private final OffsetDateTime createdOn;
     @SuppressWarnings("unused")
     private final Long updatedById;
     @SuppressWarnings("unused")
     private final String updatedByUsername;
     @SuppressWarnings("unused")
-    private final ZonedDateTime updatedOn;
+    private final OffsetDateTime updatedOn;
 
     public NoteData(final Long id, final Long clientId, final Long groupId, final Long loanId, final Long transactionId,
             final Long depositAccountId, final Long savingAccountId, final EnumOptionData noteType, final String note,
-            final ZonedDateTime createdDate, final Long createdById, final String createdByUsername, final ZonedDateTime lastModifiedDate,
+            final OffsetDateTime createdDate, final Long createdById, final String createdByUsername, final OffsetDateTime lastModifiedDate,
             final Long lastModifiedById, final String updatedByUsername) {
         this.id = id;
         this.clientId = clientId;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/domain/Note.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/domain/Note.java
index f52a7d9..5f28806 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/domain/Note.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/domain/Note.java
@@ -27,7 +27,7 @@
 import javax.persistence.Table;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
-import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
+import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
 import org.apache.fineract.portfolio.client.domain.Client;
 import org.apache.fineract.portfolio.group.domain.Group;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
@@ -38,7 +38,7 @@
 
 @Entity
 @Table(name = "m_note")
-public class Note extends AbstractAuditableCustom {
+public class Note extends AbstractAuditableWithUTCDateTimeCustom {
 
     @ManyToOne
     @JoinColumn(name = "client_id", nullable = true)
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
index f5610e0..3af2701 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
@@ -20,7 +20,8 @@
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.time.ZonedDateTime;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -28,6 +29,7 @@
 import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
 import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.portfolio.note.data.NoteData;
 import org.apache.fineract.portfolio.note.domain.NoteType;
 import org.apache.fineract.portfolio.note.exception.NoteNotFoundException;
@@ -47,9 +49,10 @@
 
         public String schema() {
             return " select n.id as id, n.client_id as clientId, n.group_id as groupId, n.loan_id as loanId, n.loan_transaction_id as transactionId, "
-                    + " n.note_type_enum as noteTypeEnum, n.note as note, n.created_date as createdDate, n.createdby_id as createdById, "
-                    + " cb.username as createdBy, n.lastmodified_date as lastModifiedDate, n.lastmodifiedby_id as lastModifiedById, mb.username as modifiedBy "
-                    + " from m_note n left join m_appuser cb on cb.id=n.createdby_id left join m_appuser mb on mb.id=n.lastmodifiedby_id ";
+                    + " n.note_type_enum as noteTypeEnum, n.note as note, n.created_date as createdDate, n.created_by as createdById, "
+                    + "  n.created_on_utc as createdDateUtc, n.last_modified_on_utc as lastModifiedDateUtc, "
+                    + " cb.username as createdBy, n.lastmodified_date as lastModifiedDate, n.last_modified_by as lastModifiedById, mb.username as modifiedBy "
+                    + " from m_note n left join m_appuser cb on cb.id=n.created_by left join m_appuser mb on mb.id=n.last_modified_by ";
         }
 
         @Override
@@ -67,12 +70,21 @@
             final Integer noteTypeId = JdbcSupport.getInteger(rs, "noteTypeEnum");
             final EnumOptionData noteType = NoteEnumerations.noteType(noteTypeId);
             final String note = rs.getString("note");
-            final ZonedDateTime createdDate = JdbcSupport.getDateTime(rs, "createdDate");
+            final LocalDateTime createdDateLocal = JdbcSupport.getLocalDateTime(rs, "createdDate");
+            final OffsetDateTime createdDateUtc = JdbcSupport.getOffsetDateTime(rs, "createdDateUtc");
             final Long createdById = JdbcSupport.getLong(rs, "createdById");
-            final ZonedDateTime lastModifiedDate = JdbcSupport.getDateTime(rs, "lastModifiedDate");
+            final LocalDateTime lastModifiedDateLocal = JdbcSupport.getLocalDateTime(rs, "lastModifiedDate");
+            final OffsetDateTime lastModifiedDateUtc = JdbcSupport.getOffsetDateTime(rs, "lastModifiedDateUtc");
             final Long lastModifiedById = JdbcSupport.getLong(rs, "lastModifiedById");
             final String createdByUsername = rs.getString("createdBy");
             final String updatedByUsername = rs.getString("modifiedBy");
+            final OffsetDateTime createdDate = createdDateUtc != null ?
+                    createdDateUtc :
+                    OffsetDateTime.of(createdDateLocal, DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(createdDateLocal));
+            final OffsetDateTime lastModifiedDate = lastModifiedDateUtc != null ?
+                    lastModifiedDateUtc :
+                    OffsetDateTime.of(lastModifiedDateLocal,
+                            DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(lastModifiedDateLocal));
             return new NoteData(id, clientId, groupId, loanId, transactionId, null, null, noteType, note, createdDate, createdById,
                     createdByUsername, lastModifiedDate, lastModifiedById, updatedByUsername);
         }
diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0033_add_audit_entries_to_note.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0033_add_audit_entries_to_note.xml
new file mode 100644
index 0000000..19f519c
--- /dev/null
+++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0033_add_audit_entries_to_note.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
+    <changeSet author="fineract" id="note-1" context="mysql">
+        <addColumn tableName="m_note">
+            <column name="created_on_utc" type="DATETIME"/>
+            <column name="last_modified_on_utc" type="DATETIME"/>
+        </addColumn>
+    </changeSet>
+    <changeSet author="fineract" id="note-1" context="postgresql">
+        <addColumn tableName="m_note">
+            <column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
+            <column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
+        </addColumn>
+    </changeSet>
+
+    <changeSet id="note-2" author="fineract">
+        <dropNotNullConstraint tableName="m_note" columnName="created_date" columnDataType="datetime"/>
+        <dropNotNullConstraint tableName="m_note" columnName="lastmodified_date" columnDataType="datetime"/>
+    </changeSet>
+    <changeSet id="note-3" author="fineract">
+        <renameColumn tableName="m_note" oldColumnName="createdby_id" newColumnName="created_by" columnDataType="BIGINT"/>
+        <renameColumn tableName="m_note" oldColumnName="lastmodifiedby_id" newColumnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet author="fineract" id="note-4">
+        <addForeignKeyConstraint baseColumnNames="created_by" baseTableName="m_note"
+                                 constraintName="FK_note_created_by" deferrable="false" initiallyDeferred="false"
+                                 onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="id"
+                                 referencedTableName="m_appuser" validate="true"/>
+        <addForeignKeyConstraint baseColumnNames="last_modified_by" baseTableName="m_note"
+                                 constraintName="FK_note_last_modified_by" deferrable="false" initiallyDeferred="false"
+                                 onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="id"
+                                 referencedTableName="m_appuser" validate="true"/>
+    </changeSet>
+    <changeSet id="note-5" author="fineract" context="mysql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from m_note</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_note" columnName="created_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_note" columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+    </changeSet>
+    <changeSet id="note-5" author="fineract" context="postgresql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from m_note</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_note" columnName="created_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_note" columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+    </changeSet>
+    <changeSet id="note-6" author="fineract">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from m_note where created_by is null or last_modified_by is null</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_note" columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_note" columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+</databaseChangeLog>