Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/main/java/com/iemr/flw/controller/SammelanController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.iemr.flw.controller;

import com.iemr.flw.dto.iemr.*;
import com.iemr.flw.service.SammelanService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@RestController
@RequestMapping("sammelans")
public class SammelanController {
@Autowired
private SammelanService service;



@RequestMapping(value = "saveAll",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<SammelanResponseDTO> create(
@RequestPart("payload") @Valid SammelanRequestDTO payload,
@RequestPart(value = "files", required = false) MultipartFile[] files) {


SammelanResponseDTO resp = service.submitSammelan(payload);
return ResponseEntity.status(HttpStatus.CREATED).body(resp);
}


@RequestMapping(value = "getAll")
public List<SammelanResponseDTO> sammelanlist(@RequestParam Integer ashaId) {
return service.getSammelanHistory(ashaId);
}
}

28 changes: 28 additions & 0 deletions src/main/java/com/iemr/flw/domain/iemr/SammelanAttachment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.iemr.flw.domain.iemr;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "sammelan_attachment")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SammelanAttachment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sammelan_id", nullable = false)
private SammelanRecord sammelanRecord;


private String fileName;
private String fileType;
private Long fileSize;
private String storagePath;
}
52 changes: 52 additions & 0 deletions src/main/java/com/iemr/flw/domain/iemr/SammelanRecord.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.iemr.flw.domain.iemr;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "sammelan_record",
uniqueConstraints = @UniqueConstraint(name = "uk_asha_month", columnNames = {"asha_id", "meeting_date"}))
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SammelanRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


@Column(name = "asha_id", nullable = false)
private Integer ashaId;


@Column(name = "meeting_date", nullable = false)
private Timestamp meetingDate;


@Column(nullable = false)
private String place;


@Column(nullable = false, name = "participants")
private int participants;


@Column(columnDefinition = "TEXT", name = "remarks")
private String remarks;

@Column(name = "created_by")
private String createdBy;

@Column(name = "created_date")
private Timestamp createdDate;

@OneToMany(mappedBy = "sammelanRecord", cascade = CascadeType.ALL, orphanRemoval = true)
private List<SammelanAttachment> attachments = new ArrayList<>();
}
41 changes: 41 additions & 0 deletions src/main/java/com/iemr/flw/dto/iemr/AttachmentDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.iemr.flw.dto.iemr;

public class AttachmentDTO {

private String fileName; // e.g. "meeting_photo1.jpg"
private String fileType; // e.g. "image/jpeg", "image/png", "application/pdf"
private Long fileSize; // size in bytes

public AttachmentDTO() {
}

public AttachmentDTO(String fileName, String fileType, Long fileSize) {
this.fileName = fileName;
this.fileType = fileType;
this.fileSize = fileSize;
}

public String getFileName() {
return fileName;
}

public void setFileName(String fileName) {
this.fileName = fileName;
}

public String getFileType() {
return fileType;
}

public void setFileType(String fileType) {
this.fileType = fileType;
}

public Long getFileSize() {
return fileSize;
}

public void setFileSize(Long fileSize) {
this.fileSize = fileSize;
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/iemr/flw/dto/iemr/SammelanRequestDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.iemr.flw.dto.iemr;

import lombok.Data;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.List;
@Data
public class SammelanRequestDTO {

private Integer ashaId; // ASHA worker ID
private Timestamp date; // Meeting date
private String place; // Dropdown: HWC / Anganwadi Centre / Community Center
private Integer participants; // Number of participants attended
private List<AttachmentDTO> attachments; // Min 2, Max 5 files

}
19 changes: 19 additions & 0 deletions src/main/java/com/iemr/flw/dto/iemr/SammelanResponseDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.iemr.flw.dto.iemr;

import lombok.Data;

import java.sql.Timestamp;
import java.time.LocalDate;
@Data
public class SammelanResponseDTO {

private Long id;
private Integer ashaId;
private Timestamp date;
private String place;
private Integer participants;
private Double incentiveAmount;
private String incentiveStatus;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.iemr.flw.repo.iemr;

import com.iemr.flw.domain.iemr.SammelanAttachment;
import com.iemr.flw.domain.iemr.SammelanRecord;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface SammelanAttachmentRepository extends JpaRepository<SammelanAttachment, Long> {

List<SammelanAttachment> findBySammelanRecord(SammelanRecord record);
}
18 changes: 18 additions & 0 deletions src/main/java/com/iemr/flw/repo/iemr/SammelanRecordRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.iemr.flw.repo.iemr;

import com.iemr.flw.domain.iemr.SammelanRecord;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.util.List;

@Repository
public interface SammelanRecordRepository extends JpaRepository<SammelanRecord, Long> {

// Check if ASHA has already submitted record in same month
boolean existsByAshaIdAndMeetingDateBetween(Integer ashaId, LocalDate startDate, LocalDate endDate);

// Fetch history
List<SammelanRecord> findByAshaIdOrderByMeetingDateDesc(Integer ashaId);
}
25 changes: 25 additions & 0 deletions src/main/java/com/iemr/flw/service/SammelanService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.iemr.flw.service;

import com.iemr.flw.dto.iemr.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

public interface SammelanService {
/**
* Submit a new Saas Bahu Sammelan record
* @param dto request data
* @return saved SammelanResponseDTO with incentive details
*/
SammelanResponseDTO submitSammelan(SammelanRequestDTO dto);

/**
* Fetch Sammelan history for given ASHA worker
* @param ashaId ASHA worker ID
* @return list of past SammelanResponseDTO
*/
List<SammelanResponseDTO> getSammelanHistory(Integer ashaId);

}
121 changes: 121 additions & 0 deletions src/main/java/com/iemr/flw/service/impl/SammelanServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package com.iemr.flw.service.impl;

import com.iemr.flw.domain.iemr.SammelanAttachment;
import com.iemr.flw.domain.iemr.SammelanRecord;
import com.iemr.flw.dto.iemr.*;
import com.iemr.flw.repo.iemr.SammelanAttachmentRepository;
import com.iemr.flw.repo.iemr.SammelanRecordRepository;
import com.iemr.flw.service.SammelanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SammelanServiceImpl implements SammelanService {
@Autowired
private SammelanRecordRepository recordRepo;
@Autowired
private SammelanAttachmentRepository attachmentRepo;

private SammelanRecord record;



@Override
public SammelanResponseDTO submitSammelan(SammelanRequestDTO dto) {
validateRequest(dto);
LocalDate localDate = dto.getDate().toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();

YearMonth ym = YearMonth.from(localDate);

// Check for existing record in same month
boolean exists = recordRepo.existsByAshaIdAndMeetingDateBetween(
dto.getAshaId(),
ym.atDay(1),
ym.atEndOfMonth()
);
if (exists) {
throw new IllegalArgumentException("Sammelan already submitted for this month.");
}

// Save Sammelan record
record = new SammelanRecord();
record.setAshaId(dto.getAshaId());
record.setMeetingDate(dto.getDate());
record.setPlace(dto.getPlace());
record.setParticipants(dto.getParticipants());
record = recordRepo.save(record);

// Save Attachments
if (dto.getAttachments() != null) {
List<SammelanAttachment> attachments = dto.getAttachments().stream().map(a -> {
SammelanAttachment att = new SammelanAttachment();
att.setSammelanRecord(record);
att.setFileName(a.getFileName());
att.setFileType(a.getFileType());
att.setFileSize(a.getFileSize());
return att;
}).collect(Collectors.toList());
attachmentRepo.saveAll(attachments);
record.setAttachments(attachments);
}

// Save incentive audit


// Prepare Response DTO
SammelanResponseDTO response = new SammelanResponseDTO();
response.setId(record.getId());
response.setAshaId(record.getAshaId());
response.setDate(record.getMeetingDate());
response.setPlace(record.getPlace());
response.setParticipants(record.getParticipants());

return response;
}

@Override
public List<SammelanResponseDTO> getSammelanHistory(Integer ashaId) {
List<SammelanRecord> records = recordRepo.findByAshaIdOrderByMeetingDateDesc(ashaId);
return records.stream().map(record -> {
SammelanResponseDTO dto = new SammelanResponseDTO();
dto.setId(record.getId());
dto.setAshaId(record.getAshaId());
dto.setDate(record.getMeetingDate());
dto.setPlace(record.getPlace());
dto.setParticipants(record.getParticipants());

return dto;
}).collect(Collectors.toList());
}

private void validateRequest(SammelanRequestDTO dto) {
LocalDate date = dto.getDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

if (date == null) {
throw new IllegalArgumentException("Date is mandatory.");
}
if (date.isAfter(LocalDate.now())) {
throw new IllegalArgumentException("Date cannot be in future.");
}
if (date.isBefore(LocalDate.now().minusMonths(2))) {
throw new IllegalArgumentException("Backdate not allowed beyond 2 months.");
}
if (dto.getParticipants() < 0 || dto.getParticipants() > 999) {
throw new IllegalArgumentException("Participants must be between 0–999.");
}
if (dto.getAttachments() == null || dto.getAttachments().size() < 2) {
throw new IllegalArgumentException("Minimum 2 attachments required.");
}
if (dto.getAttachments().size() > 5) {
throw new IllegalArgumentException("Maximum 5 attachments allowed.");
}
}
}