Browse Source

added elcot oc files upload option

master
yoga-agoy 4 months ago
parent
commit
d09ba49e93
  1. 15
      .env
  2. 41
      src/main/java/com/adjustment_file_management_system/springboot/controller/OCFileDataController.java
  3. 47
      src/main/java/com/adjustment_file_management_system/springboot/mapper/OCFileDataMapper.java
  4. 7
      src/main/java/com/adjustment_file_management_system/springboot/model/FileData.java
  5. 118
      src/main/java/com/adjustment_file_management_system/springboot/model/OCFileData.java
  6. 4
      src/main/java/com/adjustment_file_management_system/springboot/repository/FileDataRepository.java
  7. 11
      src/main/java/com/adjustment_file_management_system/springboot/repository/OCFileDataRepository.java
  8. 25
      src/main/java/com/adjustment_file_management_system/springboot/request_dto/AddOCFileDataRequestDTO.java
  9. 21
      src/main/java/com/adjustment_file_management_system/springboot/request_dto/OCFileDataRequestDTO.java
  10. 27
      src/main/java/com/adjustment_file_management_system/springboot/response_dto/OCFileDataResponseDTO.java
  11. 48
      src/main/java/com/adjustment_file_management_system/springboot/rest_controller/OCFileDataRestController.java
  12. 16
      src/main/java/com/adjustment_file_management_system/springboot/service/FileDataService.java
  13. 195
      src/main/java/com/adjustment_file_management_system/springboot/service/OCFileDataService.java
  14. 4
      src/main/resources/application.properties
  15. 51
      src/main/resources/static/js/add-oc-file-script.js
  16. 16
      src/main/resources/static/js/view-file-script.js
  17. 211
      src/main/resources/static/js/view-oc-file-script.js
  18. 14
      src/main/resources/templates/file/reports.html
  19. 14
      src/main/resources/templates/file/view-file.html
  20. 4
      src/main/resources/templates/fragments/navbar.html
  21. 4
      src/main/resources/templates/home/home.html
  22. 78
      src/main/resources/templates/oc-file/add-oc-file.html
  23. 139
      src/main/resources/templates/oc-file/view-oc-file.html

15
.env

@ -1,9 +1,10 @@
# DB_URL=jdbc:oracle:thin:@10.1.0.14:1521:chncorp
DB_URL=jdbc:oracle:thin:@10.1.0.14:1521:chncorp
DB_USERNAME=fileadjust
DB_PASSWORD=fileadjust
FORCE_HTTPS=false
##### testing db connection #####
# DB_URL=jdbc:oracle:thin:@//localhost:1522/XEPDB1
# DB_USERNAME=fileadjust # DB_USERNAME=fileadjust
# DB_PASSWORD=fileadjust
# DB_PASSWORD=root
# FORCE_HTTPS=false # FORCE_HTTPS=false
DB_URL=jdbc:oracle:thin:@//localhost:1522/XEPDB1
DB_USERNAME=system
DB_PASSWORD=root
FORCE_HTTPS=false

41
src/main/java/com/adjustment_file_management_system/springboot/controller/OCFileDataController.java

@ -0,0 +1,41 @@
package com.adjustment_file_management_system.springboot.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.adjustment_file_management_system.springboot.response_dto.FileDataResponseDTO;
import com.adjustment_file_management_system.springboot.response_dto.OCFileDataResponseDTO;
import com.adjustment_file_management_system.springboot.service.FileDataService;
import com.adjustment_file_management_system.springboot.service.OCFileDataService;
@Controller
@RequestMapping("/oc-file")
public class OCFileDataController {
@Autowired
FileDataService fileDataSer;
@Autowired
OCFileDataService ocFileDataSer;
@GetMapping("/view-oc-file")
public String ocFile(Model model) {
List<OCFileDataResponseDTO> ocFileDataList = ocFileDataSer.getAllOcFileData();
model.addAttribute("ocFileDataList", ocFileDataList);
model.addAttribute("curPage", "view-oc-file");
return "oc-file/view-oc-file";
}
@GetMapping("/add-oc-file")
public String addOcFile(Model model) {
List<FileDataResponseDTO> fileDataResDTOs = fileDataSer.getAllFileData();
model.addAttribute("fileDatum", fileDataResDTOs);
return "oc-file/add-oc-file";
}
}

47
src/main/java/com/adjustment_file_management_system/springboot/mapper/OCFileDataMapper.java

@ -0,0 +1,47 @@
package com.adjustment_file_management_system.springboot.mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.adjustment_file_management_system.springboot.model.OCFileData;
import com.adjustment_file_management_system.springboot.repository.FileDataRepository;
import com.adjustment_file_management_system.springboot.request_dto.OCFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.response_dto.OCFileDataResponseDTO;
@Component
public class OCFileDataMapper {
@Autowired
private FileDataRepository fileDataRepo;
public OCFileData toOcFileDataEnt(OCFileDataRequestDTO ocFileDataRequestDTO, Long fileDataId) {
OCFileData ocFileData = new OCFileData();
ocFileData.setOcFileSub(ocFileDataRequestDTO.getOcFileSub());
ocFileData.setOcFileUplDate(ocFileDataRequestDTO.getOcFileUplDate());
ocFileData.setOcFilePath(ocFileDataRequestDTO.getOcFilePath());
ocFileData.setFileData(fileDataRepo.findById(fileDataId).get());
return ocFileData;
}
public OCFileDataResponseDTO toOcFileDataResDTO(OCFileData ocFileData) {
OCFileDataResponseDTO dto = new OCFileDataResponseDTO();
dto.setOcFileDataId(ocFileData.getOcFileDataId());
dto.setOcFileSub(ocFileData.getOcFileSub());
dto.setOcFilePath(ocFileData.getOcFilePath());
dto.setOcFileUplDate(ocFileData.getOcFileUplDate());
if (ocFileData.getFileData() != null) {
dto.setFileDataId(ocFileData.getFileData().getFileDataId());
dto.setFileDataNum(ocFileData.getFileData().getFileDataNum());
dto.setFinYear(ocFileData.getFileData().getFinYear());
if (ocFileData.getFileData().getAdvType() != null) {
dto.setAdvType(ocFileData.getFileData().getAdvType().getAdvType());
}
if (ocFileData.getFileData().getFundType() != null) {
dto.setFundType(ocFileData.getFileData().getFundType().getFundType());
}
dto.setVendName(ocFileData.getFileData().getVendName());
}
return dto;
}
}

7
src/main/java/com/adjustment_file_management_system/springboot/model/FileData.java

@ -8,6 +8,7 @@ import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners; import jakarta.persistence.EntityListeners;
@ -17,6 +18,7 @@ import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrePersist; import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate; import jakarta.persistence.PreUpdate;
import jakarta.persistence.SequenceGenerator; import jakarta.persistence.SequenceGenerator;
@ -36,7 +38,7 @@ import lombok.ToString;
@Getter @Getter
@Setter @Setter
@ToString(doNotUseGetters = true, includeFieldNames = true, exclude = { "advType", "fundType", "createdBy", @ToString(doNotUseGetters = true, includeFieldNames = true, exclude = { "advType", "fundType", "createdBy",
"updatedBy" })
"updatedBy", "ocFileData" })
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
// For local DB Server // For local DB Server
@ -169,6 +171,9 @@ public class FileData {
@NotBlank @NotBlank
private String vendName; private String vendName;
@OneToOne(mappedBy = "fileData", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private OCFileData ocFileData;
@CreatedBy @CreatedBy
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "created_by_usr_id", referencedColumnName = "usr_id", updatable = false, nullable = false) @JoinColumn(name = "created_by_usr_id", referencedColumnName = "usr_id", updatable = false, nullable = false)

118
src/main/java/com/adjustment_file_management_system/springboot/model/OCFileData.java

@ -0,0 +1,118 @@
package com.adjustment_file_management_system.springboot.model;
import java.util.Date;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Entity
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true, exclude = { "fileData", "createdBy",
"updatedBy" })
@AllArgsConstructor
@NoArgsConstructor
// For local DB Server
/* @Table(name = "tbl_file_data_det", schema = "GCC") */
// For Production DB Server
@Table(name = "tbl_oc_file_data_det", schema = "fileadjust")
public class OCFileData {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "oc_file_data_seq")
/*
* @SequenceGenerator(name = "oc_file_data_seq", sequenceName =
* "oc_file_data_id_seq",
* allocationSize = 1, schema = "GCC")
*/
@SequenceGenerator(name = "oc_file_data_seq", sequenceName = "oc_file_data_id_seq", allocationSize = 1, schema = "fileadjust")
@Column(name = "oc_file_data_id", nullable = false, updatable = false)
private Long ocFileDataId;
@Column(name = "oc_file_sub", nullable = false, length = 1000)
@NotBlank
private String ocFileSub;
@Column(name = "oc_file_path", nullable = false, length = 1000)
@NotBlank
private String ocFilePath;
@Column(name = "oc_file_upl_date", nullable = false)
@Temporal(TemporalType.DATE)
@NotNull
private Date ocFileUplDate;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "file_data_id", referencedColumnName = "file_data_id", nullable = false, unique = true)
private FileData fileData;
@CreatedBy
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "created_by_usr_id", referencedColumnName = "usr_id", updatable = false, nullable = false)
private AppUser createdBy;
@LastModifiedBy
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "updated_by_usr_id", referencedColumnName = "usr_id", nullable = false)
private AppUser updatedBy;
// User timestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "usr_created_timestamp", nullable = false, updatable = false)
private Date usrCreatedTimestamp;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "usr_updated_timestamp", nullable = false)
private Date usrUpdatedTimestamp;
// DB-managed timestamps
@CreatedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false, nullable = false, name = "db_created_timestamp")
private Date dbCreatedTimestamp;
@LastModifiedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable = false, name = "db_updated_timestamp")
private Date dbUpdatedTimestamp;
@PrePersist
public void onCreate() {
this.usrCreatedTimestamp = new Date();
this.usrUpdatedTimestamp = new Date();
}
@PreUpdate
public void onUpdate() {
this.usrUpdatedTimestamp = new Date();
}
}

4
src/main/java/com/adjustment_file_management_system/springboot/repository/FileDataRepository.java

@ -2,6 +2,7 @@ package com.adjustment_file_management_system.springboot.repository;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import com.adjustment_file_management_system.springboot.model.FileData; import com.adjustment_file_management_system.springboot.model.FileData;
@ -12,4 +13,7 @@ public interface FileDataRepository extends JpaRepository<FileData, Long> {
@Query(value = "SELECT fd FROM FileData fd WHERE fd.fileDataNum = ?1") @Query(value = "SELECT fd FROM FileData fd WHERE fd.fileDataNum = ?1")
FileData findFileDataByFileDataNum(String fileDataNum); FileData findFileDataByFileDataNum(String fileDataNum);
@Query(value = "SELECT file_data_id FROM TBL_FILE_DATA_DET WHERE file_data_num = :fileNum", nativeQuery = true)
Long findFileDataIdByFileNum(@Param("fileNum") String fileNum);
} }

11
src/main/java/com/adjustment_file_management_system/springboot/repository/OCFileDataRepository.java

@ -0,0 +1,11 @@
package com.adjustment_file_management_system.springboot.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.adjustment_file_management_system.springboot.model.OCFileData;
@Repository
public interface OCFileDataRepository extends JpaRepository<OCFileData, Long> {
}

25
src/main/java/com/adjustment_file_management_system/springboot/request_dto/AddOCFileDataRequestDTO.java

@ -0,0 +1,25 @@
package com.adjustment_file_management_system.springboot.request_dto;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.multipart.MultipartFile;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
public class AddOCFileDataRequestDTO {
private MultipartFile ocFile;
@DateTimeFormat(pattern = "dd-MM-yyyy")
private Date ocFileUplDate;
private String ocFileSub;
private String fileNum;
}

21
src/main/java/com/adjustment_file_management_system/springboot/request_dto/OCFileDataRequestDTO.java

@ -0,0 +1,21 @@
package com.adjustment_file_management_system.springboot.request_dto;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@NoArgsConstructor
@AllArgsConstructor
public class OCFileDataRequestDTO {
private String fileNum;
private Date ocFileUplDate;
private String ocFileSub;
private String ocFilePath;
}

27
src/main/java/com/adjustment_file_management_system/springboot/response_dto/OCFileDataResponseDTO.java

@ -0,0 +1,27 @@
package com.adjustment_file_management_system.springboot.response_dto;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(doNotUseGetters = true, includeFieldNames = true)
@AllArgsConstructor
@NoArgsConstructor
public class OCFileDataResponseDTO {
private Long ocFileDataId;
private String ocFileSub;
private String ocFilePath;
private Date ocFileUplDate;
private Long fileDataId;
private String fileDataNum;
private String finYear;
private String advType;
private String fundType;
private String vendName;
}

48
src/main/java/com/adjustment_file_management_system/springboot/rest_controller/OCFileDataRestController.java

@ -0,0 +1,48 @@
package com.adjustment_file_management_system.springboot.rest_controller;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.adjustment_file_management_system.springboot.request_dto.AddOCFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.response_dto.ServiceResponseDTO;
import com.adjustment_file_management_system.springboot.service.OCFileDataService;
@RestController
@RequestMapping("/api/oc-file")
public class OCFileDataRestController {
@Autowired
private OCFileDataService OcFileDataSer;
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
sdf.setLenient(false);
// true = allow empty string to be converted to null
binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
binder.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, true));
}
@PostMapping("/add-oc-file")
public ResponseEntity<ServiceResponseDTO> addFile(@ModelAttribute AddOCFileDataRequestDTO addOcFileDataReqDTO) {
ServiceResponseDTO serResDTO = OcFileDataSer.addOcFileData(addOcFileDataReqDTO);
if (serResDTO.isResStat()) {
return ResponseEntity.ok(serResDTO);
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(serResDTO);
}
}
}

16
src/main/java/com/adjustment_file_management_system/springboot/service/FileDataService.java

@ -33,6 +33,7 @@ import com.adjustment_file_management_system.springboot.repository.AdvanceTypeRe
import com.adjustment_file_management_system.springboot.repository.FileDataRepository; import com.adjustment_file_management_system.springboot.repository.FileDataRepository;
import com.adjustment_file_management_system.springboot.repository.FundTypeRepository; import com.adjustment_file_management_system.springboot.repository.FundTypeRepository;
import com.adjustment_file_management_system.springboot.request_dto.AddFileDataRequestDTO; import com.adjustment_file_management_system.springboot.request_dto.AddFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.AddOCFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.AdvanceTypeRequestDTO; import com.adjustment_file_management_system.springboot.request_dto.AdvanceTypeRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.FileDataRequestDTO; import com.adjustment_file_management_system.springboot.request_dto.FileDataRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.UpdateFileDataRequestDTO; import com.adjustment_file_management_system.springboot.request_dto.UpdateFileDataRequestDTO;
@ -75,7 +76,7 @@ public class FileDataService {
private static final Date placeHolderDate = new Date(0); private static final Date placeHolderDate = new Date(0);
// Clean file if error occurrs while adding file // Clean file if error occurrs while adding file
private void cleanUpFiles(String... paths) {
public void cleanUpFiles(String... paths) {
for (String path : paths) { for (String path : paths) {
folderSer.deleteFileIfExists(path); folderSer.deleteFileIfExists(path);
} }
@ -107,7 +108,7 @@ public class FileDataService {
/** /**
* Helper method for file uploads, tracks uploaded files automatically. * Helper method for file uploads, tracks uploaded files automatically.
*/ */
private void handleFileUpload(String fileNum, String type, Date date, MultipartFile file,
public void handleFileUpload(String fileNum, String type, Date date, MultipartFile file,
Consumer<String> pathSetter, List<String> uploadedFiles) throws IOException { Consumer<String> pathSetter, List<String> uploadedFiles) throws IOException {
if (file == null || file.isEmpty()) { if (file == null || file.isEmpty()) {
return; return;
@ -123,7 +124,7 @@ public class FileDataService {
/** /**
* Utility method for choosing first non-null value. * Utility method for choosing first non-null value.
*/ */
private <T> T firstNonNull(T a, T b) {
public <T> T firstNonNull(T a, T b) {
return (a != null) ? a : b; return (a != null) ? a : b;
} }
@ -159,7 +160,7 @@ public class FileDataService {
/** /**
* Returns the file from Respective File Data Request DTO by type * Returns the file from Respective File Data Request DTO by type
*/ */
private MultipartFile getFileByType(Object obj, String type) {
public MultipartFile getFileByType(Object obj, String type) {
if (obj instanceof AddFileDataRequestDTO addFileDataReqDTO) { if (obj instanceof AddFileDataRequestDTO addFileDataReqDTO) {
return switch (type) { return switch (type) {
case "AS" -> addFileDataReqDTO.getAsFile(); case "AS" -> addFileDataReqDTO.getAsFile();
@ -175,6 +176,11 @@ public class FileDataService {
case "TC" -> updFileDataReqDTO.getTcFile(); case "TC" -> updFileDataReqDTO.getTcFile();
default -> null; default -> null;
}; };
} else if (obj instanceof AddOCFileDataRequestDTO addOcFileDataReqDTO) {
return switch (type) {
case "OC" -> addOcFileDataReqDTO.getOcFile();
default -> null;
};
} }
return null; return null;
} }
@ -244,7 +250,7 @@ public class FileDataService {
} }
switch (fileType) { switch (fileType) {
case "AS", "PI", "RTGS", "PO", "DC", "SR", "IR", "EJV-Number", "AS-Final", "FI", "TC" -> {
case "AS", "PI", "RTGS", "PO", "DC", "SR", "IR", "EJV-Number", "AS-Final", "FI", "TC", "OC" -> {
// Remove duplicate prefix from filePath if present // Remove duplicate prefix from filePath if present
if (filePath.startsWith("/uploads/file-data/")) { if (filePath.startsWith("/uploads/file-data/")) {

195
src/main/java/com/adjustment_file_management_system/springboot/service/OCFileDataService.java

@ -0,0 +1,195 @@
package com.adjustment_file_management_system.springboot.service;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.adjustment_file_management_system.springboot.mapper.FileDataMapper;
import com.adjustment_file_management_system.springboot.mapper.OCFileDataMapper;
import com.adjustment_file_management_system.springboot.repository.FileDataRepository;
import com.adjustment_file_management_system.springboot.repository.OCFileDataRepository;
import com.adjustment_file_management_system.springboot.repository.AdvanceTypeRepository;
import com.adjustment_file_management_system.springboot.repository.FundTypeRepository;
import com.adjustment_file_management_system.springboot.model.FileData;
import com.adjustment_file_management_system.springboot.model.AdvanceType;
import com.adjustment_file_management_system.springboot.model.FundType;
import com.adjustment_file_management_system.springboot.request_dto.AddOCFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.request_dto.OCFileDataRequestDTO;
import com.adjustment_file_management_system.springboot.response_dto.FileDataResponseDTO;
import com.adjustment_file_management_system.springboot.response_dto.OCFileDataResponseDTO;
import com.adjustment_file_management_system.springboot.response_dto.ServiceResponseDTO;
import java.util.Calendar;
@Service
public class OCFileDataService {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
private static final Logger logger = LoggerFactory.getLogger(FileDataService.class);
private static final Date placeHolderDate = new Date(0);
@Autowired
private FileDataService fileDataSer;
@Autowired
private FileDataMapper fileDataMap;
@Autowired
private FileDataRepository fileDataRepo;
@Autowired
private OCFileDataRepository ocFileDataRepo;
@Autowired
private AdvanceTypeRepository advTypeRepo;
@Autowired
private FundTypeRepository fundTypeRepo;
@Autowired
private OCFileDataMapper ocFileDataMap;
@Transactional(rollbackFor = Exception.class)
public ServiceResponseDTO addOcFileData(AddOCFileDataRequestDTO addOcFileDataReqDTO) {
List<String> uploadedFiles = new ArrayList<String>(); // Track uploaded file paths
try {
String fileNum = addOcFileDataReqDTO.getFileNum().trim();
Long fileDataId = fileDataRepo.findFileDataIdByFileNum(fileNum);
if (fileDataId == null) {
// Create parent FileData entity
FileData newFileData = new FileData();
newFileData.setFileDataNum(fileNum);
newFileData.setFinYear(determineFinYear(fileNum));
// Get or create AdvanceType
AdvanceType advType = advTypeRepo.findAdvTypeByAdvType("ELCOT")
.orElseGet(() -> advTypeRepo.findAdvTypeByAdvType("OTHER")
.orElseGet(() -> {
List<AdvanceType> all = advTypeRepo.findAll();
if (!all.isEmpty()) return all.get(0);
AdvanceType newType = new AdvanceType();
newType.setAdvType("ELCOT");
return advTypeRepo.save(newType);
}));
newFileData.setAdvType(advType);
// Get or create FundType
FundType fundType = fundTypeRepo.findAll().stream().findFirst().orElseGet(() -> {
FundType newType = new FundType();
newType.setFundType("GENERAL FUND");
return fundTypeRepo.save(newType);
});
newFileData.setFundType(fundType);
newFileData.setVendName("ELCOT");
newFileData.setAsFilePath("-");
newFileData.setAsFileGenDate(placeHolderDate);
newFileData.setPiFilePath("-");
newFileData.setPiFileGenDate(placeHolderDate);
newFileData.setPiAmt(0.0);
newFileData.setFiFilePath("-");
newFileData.setFiAmt(0.0);
newFileData.setFiFileGenDate(placeHolderDate);
newFileData.setBalAmt(0.0);
newFileData.setRtgsFilePath("-");
newFileData.setPoFilePath("-");
newFileData.setDcFilePath("-");
newFileData.setSrFilePath("-");
newFileData.setIrFilePath("-");
newFileData.setAsFinalFilePath("-");
newFileData.setAsFinalFileGenDate(placeHolderDate);
newFileData.setEjvNum("-");
newFileData.setEjvNumFilePath("-");
newFileData.setEjvNumFileGenDate(placeHolderDate);
newFileData.setTcFilePath("-");
newFileData.setTcFileGenDate(placeHolderDate);
newFileData.setFileRmrk("-");
FileData savedFileData = fileDataRepo.save(newFileData);
fileDataId = savedFileData.getFileDataId();
}
Date ocFileUplDate = addOcFileDataReqDTO.getOcFileUplDate() != null
? addOcFileDataReqDTO.getOcFileUplDate()
: placeHolderDate;
String ocFileSub = (addOcFileDataReqDTO.getOcFileSub() != null
&& !addOcFileDataReqDTO.getOcFileSub().trim().isEmpty())
? addOcFileDataReqDTO.getOcFileSub().trim()
: "-";
// Prepare DTO
OCFileDataRequestDTO ocFileDataRequestDTO = new OCFileDataRequestDTO();
ocFileDataRequestDTO.setFileNum(fileNum);
ocFileDataRequestDTO.setOcFileUplDate(ocFileUplDate);
ocFileDataRequestDTO.setOcFileSub(ocFileSub);
// Handle file uploads
Map<String, MultipartFile> files = new HashMap<String, MultipartFile>();
if (addOcFileDataReqDTO.getOcFile() != null) {
files.put("OC", addOcFileDataReqDTO.getOcFile());
}
Map<String, Consumer<String>> pathSetters = Map.of("OC", ocFileDataRequestDTO::setOcFilePath);
for (String type : files.keySet()) {
MultipartFile file = files.get(type);
// use the dates already set
fileDataSer.handleFileUpload(fileNum, type, "OC".equals(type) ? ocFileUplDate : ocFileUplDate, file,
pathSetters.get(type), uploadedFiles);
}
// Save to DB
ocFileDataRepo.save(ocFileDataMap.toOcFileDataEnt(ocFileDataRequestDTO, fileDataId));
logger.info("OC File saved for file number: {}", fileNum);
return new ServiceResponseDTO(true, "OC File added successfully");
} catch (IOException ioe) {
logger.error("Exception occurred in file upload part: {}", ioe.getMessage(), ioe);
ioe.printStackTrace();
fileDataSer.cleanUpFiles(uploadedFiles.toArray(new String[0])); // Delete all uploaded files
return new ServiceResponseDTO(false, "Failed to add the file. Error in file upload: "
+ ioe.getMessage());
} catch (Exception e) {
logger.error("Exception occurred: {}", e.getMessage(), e);
e.printStackTrace();
fileDataSer.cleanUpFiles(uploadedFiles.toArray(new String[0])); // Delete all uploaded files
return new ServiceResponseDTO(false, "Failed to add the file. Error: " + e.getMessage());
}
}
private String determineFinYear(String fileNum) {
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\b(20\\d{2})\\b");
java.util.regex.Matcher matcher = pattern.matcher(fileNum);
if (matcher.find()) {
int year = Integer.parseInt(matcher.group(1));
return year + "-" + (year + 1);
}
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
if (month >= Calendar.APRIL) {
return year + "-" + (year + 1);
} else {
return (year - 1) + "-" + year;
}
}
@Transactional(readOnly = true)
public List<OCFileDataResponseDTO> getAllOcFileData() {
return ocFileDataRepo.findAll().stream()
.map(ocFileDataMap::toOcFileDataResDTO)
.toList();
}
}

4
src/main/resources/application.properties

@ -24,9 +24,9 @@ spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
# JPA / Hibernate Config # JPA / Hibernate Config
# =============================== # ===============================
# spring.jpa.database-platform=org.hibernate.dialect.OracleDialect # spring.jpa.database-platform=org.hibernate.dialect.OracleDialect
# spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true spring.jpa.show-sql=true
# spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.open-in-view=true spring.jpa.open-in-view=true
logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.SQL=DEBUG
# logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE # logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

51
src/main/resources/static/js/add-oc-file-script.js

@ -0,0 +1,51 @@
// Initialize date pickers
["ocFileUplDate"].forEach(id => {
flatpickr("#" + id, {
dateFormat: "d-m-Y",
enableTime: false,
noCalendar: false,
allowInput: true
});
});
document.addEventListener("DOMContentLoaded", function () {
const form = document.getElementById("frm-oc-file-det");
// Existing form submission logic...
form.addEventListener("submit", function (e) {
e.preventDefault(); // Prevent default form submission
const formData = new FormData(form);
fetch(form.getAttribute("action"), {
method: "POST",
body: formData
})
.then(response => {
if (!response.ok) {
throw new Error("Network response was not ok: " + response.statusText);
}
return response.json();
})
.then(data => {
if (data.resStat) {
alert("Success: " + data.res);
form.reset();
// Reset flatpickr
if (flatpickr) {
["#ocFileUplDate"].forEach(selector => {
const fp = document.querySelector(selector)?._flatpickr;
if (fp) fp.clear();
});
}
} else {
alert("Failed: " + data.res);
}
})
.catch(error => {
console.error("Error submitting file:", error);
alert("Error submitting file. Please try again.");
});
});
});

16
src/main/resources/static/js/view-file-script.js

@ -32,7 +32,10 @@ $(document).ready(function () {
if (column === 0) { if (column === 0) {
return row + 1; // row is 0-based index of **visible filtered rows** return row + 1; // row is 0-based index of **visible filtered rows**
} }
return data; // leave other columns unchanged
// Remove HTML tags from all columns
return $('<div>').html(data).text().trim();
//return data; // leave other columns unchanged
} }
} }
} }
@ -43,11 +46,14 @@ $(document).ready(function () {
// --- SEQUENTIAL S.NO FIX --- // --- SEQUENTIAL S.NO FIX ---
table.on('order.dt search.dt draw.dt', function () { table.on('order.dt search.dt draw.dt', function () {
var pageInfo = table.page.info(); // get current page info
table.column(0, { search: 'applied', order: 'applied' }).nodes().each(function (cell, i) {
cell.innerHTML = i + 1 + pageInfo.start; // keep numbering continuous across pages
var pageInfo = table.page.info();
table.column(0, { page: 'current' }).nodes().each(function (cell, i) {
cell.innerHTML = pageInfo.start + i + 1;
}); });
}).draw();
}).draw()
// Move DataTable controls to custom container // Move DataTable controls to custom container
$('#custom-pagination').html($('.dataTables_paginate')); $('#custom-pagination').html($('.dataTables_paginate'));

211
src/main/resources/static/js/view-oc-file-script.js

@ -0,0 +1,211 @@
$(document).ready(function () {
// Initialize DataTable
var table = $('#oc-file-det-tbl').DataTable({
paging: true,
searching: true,
ordering: true,
lengthChange: true,
pageLength: 10,
language: {
emptyTable: "No data available",
lengthMenu: "Display _MENU_ records per page",
info: "Showing _START_ to _END_ of _TOTAL_ entries",
infoEmpty: "No records to show",
infoFiltered: "(filtered from _MAX_ total records)"
},
columnDefs: [
{
orderable: false,
targets: [0, 5] // S.No and OC File columns
}
],
buttons: [
{
extend: 'excelHtml5',
title: "OC File Details",
filename: "OC File Details",
exportOptions: {
columns: ':visible:not(:eq(5))', // exclude OC File column
format: {
body: function (data, row, column, node) {
if (column === 0) {
return row + 1;
}
return $('<div>').html(data).text().trim();
}
}
}
},
'pdfHtml5'
]
});
// --- SEQUENTIAL S.NO FIX ---
table.on('order.dt search.dt draw.dt', function () {
var pageInfo = table.page.info();
table.column(0, { page: 'current' }).nodes().each(function (cell, i) {
cell.innerHTML = pageInfo.start + i + 1;
});
}).draw();
// Move DataTable controls to custom containers
$('#custom-pagination').html($('.dataTables_paginate'));
$('#custom-info').html($('.dataTables_info'));
$('#custom-length').html($('.dataTables_length'));
$('.dataTables_filter').hide(); // hide default search
// Custom search / filtering on the datatable
$('#export-excel').on('click', function () {
table.button('.buttons-excel').trigger();
});
$('#export-pdf').on('click', function () {
var originalLength = table.page.len();
table.one('draw', function () {
var tableClone = $('#oc-file-det-tbl').clone();
tableClone.removeClass('dataTable');
tableClone.find('thead, tbody, tfoot').removeAttr('style');
// Remove "OC File" column (6th col = index 5)
tableClone.find('tr').each(function () {
$(this).find('th:eq(5), td:eq(5)').remove();
});
var pdfContainer = $('#pdf-print-container');
if (!pdfContainer.length) {
$('body').append('<div id="pdf-print-container" style="display:none;"></div>');
pdfContainer = $('#pdf-print-container');
}
pdfContainer.html('<h2 style="text-align:center;">OC File Details</h2>');
pdfContainer.append(tableClone).css({ display: 'block', padding: '20px' });
tableClone.css({ width: '100%', borderCollapse: 'collapse' });
tableClone.find('th, td').css({
border: '1px solid #ccc',
padding: '5px',
fontSize: '10px',
textAlign: 'left',
verticalAlign: 'top'
});
tableClone.find('tr').css({ pageBreakInside: 'avoid', breakInside: 'avoid', webkitBreakInside: 'avoid' });
html2pdf().set({
margin: 0.5,
filename: 'OC File Details.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2, useCORS: true },
jsPDF: { unit: 'in', format: 'a3', orientation: 'landscape' }
}).from(pdfContainer[0]).save().then(function () {
table.page.len(originalLength).draw();
pdfContainer.hide();
});
});
table.page.len(-1).draw(); // show all rows for PDF
});
function populateFilters() {
var numSet = {}, vendSet = {};
table.rows().every(function () {
var data = this.data();
var fileNum = data[1] ? $('<div>').html(data[1]).text().trim() : '';
var vendName = data[2] ? $('<div>').html(data[2]).text().trim() : '';
if (fileNum) numSet[fileNum] = true;
if (vendName) vendSet[vendName] = true;
});
Object.keys(numSet).sort().forEach(val => $('#file-num-list').append(`<option value="${val}">`));
Object.keys(vendSet).sort().forEach(val => $('#vend-name-list').append(`<option value="${val}">`));
}
populateFilters();
function applyFilters() {
var fileNum = $('#filter-file-num').val();
var vendName = $('#filter-vend-name').val();
table.columns().search(''); // reset all
if (fileNum) table.column(1).search('^' + $.fn.dataTable.util.escapeRegex(fileNum) + '$', true, false);
if (vendName) table.column(2).search('^' + $.fn.dataTable.util.escapeRegex(vendName) + '$', true, false);
table.draw();
}
// Event bindings for filters
$('#filter-file-num').on('input', applyFilters);
$('#filter-vend-name').on('input', applyFilters);
});
// Function to view Supporting Document in modal
function viewFileInModal(fileNum, fileType, filePath) {
var pdfModal = new bootstrap.Modal(document.getElementById('pdf-modal'));
var modalTitle = document.getElementById('pdf-modal-label');
var pdfContainer = document.getElementById('pdf-container');
pdfContainer.innerHTML = ''; // Clear previous pages
pdfContainer.scrollTop = 0; // Scroll to the first page (top)
var decodedFilePath = decodeURIComponent(filePath);
var fileName = decodedFilePath.split(/[\\/]/).pop();
modalTitle.textContent = fileType + " File (" + fileName + ")";
var params = new URLSearchParams();
params.append('file-type', fileType);
params.append('file-path', decodedFilePath);
params.append('file-num', fileNum);
fetch('/api/file/view-supp-docs', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params.toString()
}).then(function (response) {
if (!response.ok) {
throw new Error('Failed to fetch PDF: ' + response.statusText);
}
return response.arrayBuffer();
}).then(function (pdfData) {
console.log(pdfData);
var blob = new Blob([pdfData], { type: 'application/pdf' });
var blobUrl = URL.createObjectURL(blob);
// Set download link
var downloadBtn = document.getElementById('download-pdf-btn');
downloadBtn.href = blobUrl;
downloadBtn.download = fileName;
return pdfjsLib.getDocument({ data: pdfData }).promise;
}).then(function (pdf) {
let renderPage = function (pageNum) {
return pdf.getPage(pageNum).then(function (page) {
var viewport = page.getViewport({ scale: 1.5 });
var canvas = document.createElement('canvas');
canvas.classList.add('mb-3');
var ctx = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = { canvasContext: ctx, viewport: viewport };
pdfContainer.appendChild(canvas);
return page.render(renderContext).promise;
});
};
// Render all pages sequentially
let sequence = Promise.resolve();
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
sequence = sequence.then(() => renderPage(pageNum));
}
return sequence;
}).then(function () {
var modalElement = document.getElementById('pdf-modal');
modalElement.addEventListener('shown.bs.modal', function onShown() {
pdfContainer.scrollTop = 0; // Reset scroll position
modalElement.scrollTop = 0; // Reset modal scroll
modalElement.removeEventListener('shown.bs.modal', onShown); // Clean up listener
});
pdfModal.show();
}).catch(function (error) {
alert('Error loading PDF: ' + error.message);
});
}

14
src/main/resources/templates/file/reports.html

@ -124,6 +124,9 @@
<th>Advance Type</th> <th>Advance Type</th>
<th>Fund Type</th> <th>Fund Type</th>
<th>Vendor Name</th> <th>Vendor Name</th>
<th>Proforma Invoice Amount</th>
<th>Final Invoice Amount</th>
<th>Balance Amount</th>
<th>File Status</th> <th>File Status</th>
<th>Days Past</th> <th>Days Past</th>
<th>Updated date</th> <th>Updated date</th>
@ -147,6 +150,17 @@
<td <td
th:text="${fileData.vendName != null and fileData.vendName != '-' ? fileData.vendName : 'None'}"> th:text="${fileData.vendName != null and fileData.vendName != '-' ? fileData.vendName : 'None'}">
</td> </td>
<!-- Proforma Invoice Amount -->
<td th:with="piAmtFormatted=${#numbers.formatDecimal(fileData.piAmt, 1, 'COMMA', 2, 'POINT')}"
th:text="${fileData.piAmt != null} ? |₹ ${piAmtFormatted}| : 0">
</td>
<!-- Final Invoice Amount -->
<td th:with="fiAmtFormatted=${#numbers.formatDecimal(fileData.fiAmt, 1, 'COMMA', 2, 'POINT')}"
th:text="${fileData.fiAmt != null} ? |₹ ${fiAmtFormatted}| : 0">
</td>
<td th:with="balAmtFormatted=${#numbers.formatDecimal(fileData.balAmt, 1, 'COMMA', 2, 'POINT')}"
th:text="${fileData.balAmt != null} ? |₹ ${balAmtFormatted}| : 0">
</td>
<!-- File Status --> <!-- File Status -->
<td class="status-cell"> <td class="status-cell">
<span th:with="ejvNum=${fileData.ejvNum}, ejvNumFile=${fileData.ejvNumFilePath}" <span th:with="ejvNum=${fileData.ejvNum}, ejvNumFile=${fileData.ejvNumFilePath}"

14
src/main/resources/templates/file/view-file.html

@ -124,6 +124,9 @@
<th>Advance Type</th> <th>Advance Type</th>
<th>Fund Type</th> <th>Fund Type</th>
<th>Vendor Name</th> <th>Vendor Name</th>
<th>Proforma Invoice Amount</th>
<th>Final Invoice Amount</th>
<th>Balance Amount</th>
<th>File Status</th> <th>File Status</th>
<th>Days Past</th> <th>Days Past</th>
<th>Updated Date</th> <th>Updated Date</th>
@ -147,6 +150,17 @@
<td <td
th:text="${fileData.vendName != null and fileData.vendName != '-' ? fileData.vendName : 'None'}"> th:text="${fileData.vendName != null and fileData.vendName != '-' ? fileData.vendName : 'None'}">
</td> </td>
<!-- Proforma Invoice Amount -->
<td th:with="piAmtFormatted=${#numbers.formatDecimal(fileData.piAmt, 1, 'COMMA', 2, 'POINT')}"
th:text="${fileData.piAmt != null} ? |₹ ${piAmtFormatted}| : 0">
</td>
<!-- Final Invoice Amount -->
<td th:with="fiAmtFormatted=${#numbers.formatDecimal(fileData.fiAmt, 1, 'COMMA', 2, 'POINT')}"
th:text="${fileData.fiAmt != null} ? |₹ ${fiAmtFormatted}| : 0">
</td>
<td th:with="balAmtFormatted=${#numbers.formatDecimal(fileData.balAmt, 1, 'COMMA', 2, 'POINT')}"
th:text="${fileData.balAmt != null} ? |₹ ${balAmtFormatted}| : 0">
</td>
<!-- File Status --> <!-- File Status -->
<td class="status-cell"> <td class="status-cell">
<span th:with="ejvNum=${fileData.ejvNum}, ejvNumFile=${fileData.ejvNumFilePath}" <span th:with="ejvNum=${fileData.ejvNum}, ejvNumFile=${fileData.ejvNumFilePath}"

4
src/main/resources/templates/fragments/navbar.html

@ -25,6 +25,10 @@
<i class="fa-solid fa-file-lines"></i> Existing File <i class="fa-solid fa-file-lines"></i> Existing File
Details Details
</a></li> </a></li>
<li class="nav-item"><a class="nav-link" th:href="@{/oc-file/view-oc-file}"
th:if="${curPage != 'view-oc-file'}"> <i class="fa-solid fa-file-lines"></i>
OC File Details
</a></li>
</ul> </ul>
<!--Navigation item on the right--> <!--Navigation item on the right-->
<ul class=" navbar-nav ms-auto" th:if="${curPage == 'home'}"> <ul class=" navbar-nav ms-auto" th:if="${curPage == 'home'}">

4
src/main/resources/templates/home/home.html

@ -33,6 +33,10 @@
<button type="button" th:onclick="|window.location.href='@{/file/view-file}'|" class="custom-button"> <button type="button" th:onclick="|window.location.href='@{/file/view-file}'|" class="custom-button">
Existing File Details Existing File Details
</button> </button>
<button type="button" th:onclick="|window.location.href='@{/oc-file/view-oc-file}'|"
class="custom-button">
Elcot OC Copies Details
</button>
</div> </div>
<br /> <br />
<div class="row mb-3 justify-content-center"> <div class="row mb-3 justify-content-center">

78
src/main/resources/templates/oc-file/add-oc-file.html

@ -0,0 +1,78 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Adjustment File Management System</title>
<!-- Include CSS -->
<link rel="stylesheet" type="text/css" th:href="@{/css/body-form-styles.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/home-styles.css}">
<!-- CSRF Tokens -->
<meta name="_csrf" th:content="${_csrf.token}" />
<meta name="_csrf_header" th:content="${_csrf.headerName}" />
<!-- Header Fragment -->
<th:block th:replace="~{fragments/header :: header}"></th:block>
</head>
<body>
<!-- Navigation -->
<th:block th:replace="~{fragments/navbar :: navbar(${curPage})}"></th:block>
<div class="container">
<div class="form-container">
<div class="header-row">
<button class="back-button" onclick="goBack()">&#8592; Back</button>
</div>
<h2 class="form-title">Add New Elcot Remainder OC File</h2>
<form method="post" enctype="multipart/form-data" style="font-size: 14px" class="frm"
th:action="@{/api/oc-file/add-oc-file}" id="frm-oc-file-det" name="frm-oc-file-det">
<div class="form-row">
<!-- File Number (always enabled) -->
<div class="form-group">
<label for="fileNum">File Number : <span class="required">*</span></label>
<input class="form-control" list="fileNumList" id="fileNum" name="fileNum" required
placeholder="Type or choose file number">
<datalist id="fileNumList">
<th:block th:each="file : ${fileDatum}">
<option th:value="${file.fileDataNum}"></option>
</th:block>
</datalist>
</div>
<div class="form-group">
<label for="ocFileUplDate">Date : <span class="required">*</span></label>
<input type="text" name="ocFileUplDate" id="ocFileUplDate" class="form-control"
placeholder="Select Date" autocomplete="off" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="ocFileSub">Subject : <span class="required">*</span></label>
<textarea name="ocFileSub" id="ocFileSub" class="form-control" rows="4" required
placeholder="Enter subject"></textarea>
</div>
<div class="form-group">
<label for="ocFile">OC File : <span class="required">*</span></label>
<input type="file" name="ocFile" id="ocFile" class="form-control" required accept=".pdf">
</div>
</div>
<div class="submit-btn">
<input type="submit" value="Submit">
</div>
</form>
</div>
</div>
<!-- Footer Fragment -->
<th:block th:replace="~{fragments/footer :: footer}"></th:block>
<!-- Custom JS -->
<script th:src="@{/js/add-oc-file-script.js}" type="text/javascript"></script>
</body>
</html>

139
src/main/resources/templates/oc-file/view-oc-file.html

@ -0,0 +1,139 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Adjustment File Management System</title>
<!-- Include CSS -->
<link rel="stylesheet" type="text/css" th:href="@{/css/body-form-styles.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/datatable-styles.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/home-styles.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/view-file-styles.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/btn-secondary-styles.css}">
<!-- CSRF Tokens -->
<meta name="_csrf" th:content="${_csrf.token}" />
<meta name="_csrf_header" th:content="${_csrf.headerName}" />
<!-- Header Fragment -->
<th:block th:replace="~{fragments/header :: header}"></th:block>
</head>
<body>
<!-- Navigation -->
<th:block th:replace="~{fragments/navbar :: navbar(${curPage})}"></th:block>
<div class="container">
<div class="form-container">
<div class="header-row">
<button class="back-button" onclick="goBack()">&#8592; Back</button>
</div>
<h2 class="form-title">Elcot OC Remainders Details</h2>
<!-- Button and Filter Bar -->
<div class="row mb-3">
<!-- Adds spacing and a responsive layout -->
<div class="col-12 col-md-8 mb-2 mb-md-0">
<!-- Buttons on the left -->
<div class="btn-group" role="group" aria-label="Options">
<button type="button" th:onclick="|window.location.href='@{/oc-file/add-oc-file}'|"
class="btn btn-secondary">
<i class="fa-solid fa-file-pen"></i> Add OC File
</button>
<button class="btn btn-secondary" id="export-excel" name="export-excel">
<i class="fas fa-file-excel"></i> Export Excel
</button>
<button class="btn btn-secondary" id="export-pdf" name="export-pdf">
<i class="fas fa-file-pdf"></i> Export PDF
</button>
</div>
</div>
<!-- <div class="col-12 col-md-8 mb-2 mb-md-0" style="padding-top:5px">
</div> -->
</div>
<div class="row mb-3">
<div class="col-md-6 form-group">
<label for="filter-file-num" id="filter-file-num-lbl">Filter By File Number : </label>
<input list="file-num-list" class="form-control" id="filter-file-num" name="filter-file-num"
autocomplete="off" placeholder="Select File Number">
<datalist id="file-num-list">
<!-- Options will be filled by JavaScript -->
</datalist>
</div>
<div class="col-md-6 form-group">
<label for="filter-vend-name" id="filter-vend-name-lbl">Filter By Vendor Name : </label>
<input list="vend-name-list" class="form-control" id="filter-vend-name" name="filter-vend-name"
autocomplete="off" placeholder="Select Vendor Name">
<datalist id="vend-name-list">
<!-- Options will be filled by JavaScript -->
</datalist>
</div>
</div>
<div class="row mb-3">
<div class="col-md-4" id="custom-length"></div>
</div>
<div class="table-responsive">
<table class="det-table" id="oc-file-det-tbl">
<thead>
<tr class="table-header">
<th>S.No</th>
<th class="text-center">File Number</th>
<th class="text-center">Vendor Name</th>
<th class="text-center">Subject</th>
<th class="text-center">Upload Date</th>
<th class="text-center">OC File</th>
</tr>
</thead>
<tbody>
<tr th:each="ocFile : ${ocFileDataList}" th:attr="data-file-num=${ocFile.fileDataNum}">
<!-- <tr th:each="ocFile : ${ocFileDataList}" th:attr="data-file-num=${ocFile.fileDataNum}"
onclick="if(!event.target.closest('button')) window.location.href='/file/view-file-det?file-num=' + this.dataset.fileNum"
style="cursor: pointer;"> -->
<td></td>
<!-- File Number -->
<td class="text-center" th:text="${ocFile.fileDataNum}"></td>
<!-- Vendor Name -->
<td
th:text="${ocFile.vendName != null and ocFile.vendName != '-' ? ocFile.vendName : 'None'}">
</td>
<!-- Subject -->
<td th:text="${ocFile.ocFileSub}"></td>
<!-- Upload Date -->
<td th:with="uplDate=${#dates.format(ocFile.ocFileUplDate, 'dd-MM-yyyy')}"
th:text="${ocFile.ocFileUplDate != null and uplDate != '01-01-1970' ? uplDate : 'N/A'}">
</td>
<!-- OC File Link -->
<td class="text-center">
<button th:attr="data-path=${ocFile.ocFilePath}, data-file-num=${ocFile.fileDataNum}"
onclick="viewFileInModal(this.dataset.fileNum, 'OC', this.dataset.path)" class="btn"
type="button">
<i class="fas fa-light fa-eye" style="cursor: pointer"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<br />
<div class="row mb-3">
<div class="col-md-4 text-center" id="custom-info"></div>
<div class="col-md-8" id="custom-pagination"></div>
</div>
<th:block th:replace="~{fragments/export-pdf :: export-pdf}"></th:block>
</div>
</div>
<th:block th:replace="~{modal/pdf-modal :: pdf-modal}"></th:block>
<!-- Footer Fragment -->
<th:block th:replace="~{fragments/footer :: footer}"></th:block>
<!-- Custom JS -->
<script th:src="@{/js/view-oc-file-script.js}" type="text/javascript"></script>
</body>
</html>
Loading…
Cancel
Save