Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.crimeLink.analyzer.controller;

import com.crimeLink.analyzer.dto.BulletAddDTO;
import com.crimeLink.analyzer.dto.BulletResponseDTO;
import com.crimeLink.analyzer.dto.BulletUpdateDTO;
import com.crimeLink.analyzer.entity.Bullet;
import com.crimeLink.analyzer.service.BulletService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/bullet")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
public class BulletController {

private final BulletService bulletService;

@PostMapping("/add-bullet")
public ResponseEntity<?> addBullet(@RequestBody BulletAddDTO dto) {
try {
Bullet bullet = bulletService.addBullet(dto);
return ResponseEntity.status(HttpStatus.CREATED).body(bullet);
} catch (RuntimeException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(createErrorResponse(e.getMessage()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(createErrorResponse("An unexpected error occurred"));
}
}

@PutMapping("/bullet-update/{bulletId}")
public ResponseEntity<?> updateBullet(
@PathVariable Integer bulletId,
@RequestBody BulletUpdateDTO dto) {
try {
Bullet bullet = bulletService.updateBullet(bulletId, dto);
return ResponseEntity.ok(bullet);
} catch (RuntimeException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(createErrorResponse(e.getMessage()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(createErrorResponse("An unexpected error occurred"));
}
}

@GetMapping("/all")
public ResponseEntity<?> getAllBullets() {
try {
List<Bullet> bullets = bulletService.getAllBullets();
return ResponseEntity.ok(bullets);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(createErrorResponse("Failed to fetch bullets"));
}
}

@GetMapping("/all-with-details")
public ResponseEntity<?> getAllBulletsWithDetails() {
try {
List<BulletResponseDTO> bullets = bulletService.getAllBulletsWithDetails();
return ResponseEntity.ok(bullets);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(createErrorResponse("Failed to fetch bullets with details: " + e.getMessage()));
}
Comment on lines +71 to +75

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception handler calls e.printStackTrace() and also returns e.getMessage() to clients. This can leak implementation details and makes logs inconsistent with the rest of the app; prefer structured logging (e.g., SLF4J logger) and return a generic error message while logging the full exception server-side.

Copilot uses AI. Check for mistakes.
}

@GetMapping("/{bulletId}")
public ResponseEntity<?> getBulletById(@PathVariable Integer bulletId) {
try {
Bullet bullet = bulletService.getBulletById(bulletId);
return ResponseEntity.ok(bullet);
} catch (RuntimeException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(createErrorResponse(e.getMessage()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(createErrorResponse("Failed to fetch bullet"));
}
}

private Map<String, String> createErrorResponse(String message) {
Map<String, String> response = new HashMap<>();
response.put("error", message);
return response;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.crimeLink.analyzer.controller;


import com.crimeLink.analyzer.entity.User;
import com.crimeLink.analyzer.service.UserService;
import com.crimeLink.analyzer.service.WeaponIssueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
Expand All @@ -19,11 +16,13 @@ public UserController(UserService service) {
this.service = service;
}

@GetMapping("/field-officers")
public List<User> getFieldOfficers() {
return service.getFieldOfficers();
}
Comment on lines 18 to 21

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getFieldOfficers() no longer has any Spring mapping annotation, so /api/users/field-officers (or any route) won’t be exposed and the method becomes dead code. Re-add the intended @GetMapping (or remove the method entirely if it’s intentionally deprecated).

Copilot uses AI. Check for mistakes.

@GetMapping("/all-officers")
public List<User> getAllOfficers() {
return service.getAllOfficers();
}

}

10 changes: 10 additions & 0 deletions src/main/java/com/crimeLink/analyzer/dto/BulletAddDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.crimeLink.analyzer.dto;

import lombok.Data;

@Data
public class BulletAddDTO {
private String bulletType;
private Integer numberOfMagazines;
private String remarks;
}
16 changes: 16 additions & 0 deletions src/main/java/com/crimeLink/analyzer/dto/BulletResponseDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.crimeLink.analyzer.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BulletResponseDTO {
private Integer bulletId;
private String bulletType;
private Integer numberOfMagazines;
private String remarks;
private String registerDate;
}
10 changes: 10 additions & 0 deletions src/main/java/com/crimeLink/analyzer/dto/BulletUpdateDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.crimeLink.analyzer.dto;

import lombok.Data;

@Data
public class BulletUpdateDTO {
private String bulletType;
private Integer numberOfMagazines;
private String remarks;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ public class IssueWeaponRequestDTO {
private Integer handedOverById;
private LocalDate dueDate;
private String issueNote;

// Bullet details (optional - can issue weapon without bullets)
private String bulletType;
private Integer numberOfMagazines;
private String bulletRemarks;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ public class ReturnWeaponRequestDTO {
private String weaponSerial;
private Integer receivedByUserId;
private String returnNote;

// Bullet return details (optional)
private Integer returnedMagazines;
private Integer usedBullets;
private String bulletCondition;
private String bulletRemarks;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ public class WeaponResponseDTO {
private String issuedDate;
private String dueDate;
private String issueNote;

// Bullet details (if issued with bullets)
private String issuedBulletType;
private Integer issuedMagazines;
}

This file was deleted.

47 changes: 47 additions & 0 deletions src/main/java/com/crimeLink/analyzer/entity/Bullet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.crimeLink.analyzer.entity;

import jakarta.persistence.*;
import lombok.*;

import java.time.LocalDateTime;

@Entity
@Table(name = "bullets")
@Data
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Bullet {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "bullet_id")
private Integer bulletId;

@Column(name = "bullet_type", nullable = false)
private String bulletType;

@Column(name = "number_of_magazines", nullable = false)
private Integer numberOfMagazines;

@Column(name = "register_date", updatable = false)
private LocalDateTime registerDate;

@Column(name = "updated_date")
private LocalDateTime updatedDate;

@Column(name = "remarks")
private String remarks;

@PrePersist
void onCreate() {
registerDate = LocalDateTime.now();
updatedDate = LocalDateTime.now();
}

@PreUpdate
void onUpdate() {
updatedDate = LocalDateTime.now();
}
}
22 changes: 21 additions & 1 deletion src/main/java/com/crimeLink/analyzer/entity/WeaponIssue.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;


@Entity
@Table(name = "weapon_issues")
Expand Down Expand Up @@ -48,4 +48,24 @@ public class WeaponIssue {

@Enumerated(EnumType.STRING)
private WeaponStatus status;


// ===== INTEGRATED BULLET TRACKING =====
@Column(name = "bullet_type")
private String bulletType;

@Column(name = "issued_magazines")
private Integer issuedMagazines;

@Column(name = "returned_magazines")
private Integer returnedMagazines;

@Column(name = "used_bullets")
private Integer usedBullets;

@Column(name = "bullet_condition")
private String bulletCondition;

@Column(name = "bullet_remarks")
private String bulletRemarks;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.crimeLink.analyzer.repository;

import com.crimeLink.analyzer.entity.Bullet;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface BulletRepository extends JpaRepository<Bullet, Integer> {

Optional<Bullet> findByBulletType(String bulletType);

boolean existsByBulletTypeIgnoreCase(String bulletType);
Comment on lines +10 to +14

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repository provides only a case-sensitive findByBulletType(...), but service logic treats bullet types as case-insensitive (see existsByBulletTypeIgnoreCase). Add a case-insensitive finder (e.g., findByBulletTypeIgnoreCase) and prefer it in issue/return flows to avoid casing-related failures.

Copilot uses AI. Check for mistakes.
}
16 changes: 16 additions & 0 deletions src/main/java/com/crimeLink/analyzer/service/BulletService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.crimeLink.analyzer.service;

import com.crimeLink.analyzer.dto.BulletAddDTO;
import com.crimeLink.analyzer.dto.BulletResponseDTO;
import com.crimeLink.analyzer.dto.BulletUpdateDTO;
import com.crimeLink.analyzer.entity.Bullet;

import java.util.List;

public interface BulletService {
Bullet addBullet(BulletAddDTO dto);
Bullet updateBullet(Integer bulletId, BulletUpdateDTO dto);
List<Bullet> getAllBullets();
List<BulletResponseDTO> getAllBulletsWithDetails();
Bullet getBulletById(Integer bulletId);
}
4 changes: 4 additions & 0 deletions src/main/java/com/crimeLink/analyzer/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ public UserService(UserRepository repo) {
public List<User> getFieldOfficers() {
return repo.findByRole("FieldOfficer");
}

public List<User> getAllOfficers() {
return repo.findAll();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import java.util.List;

public interface WeaponIssueService {
List<WeaponAddDTO> getAllActiveWeapons();
List<WeaponAddDTO> getAvailableWeapons();
void issueWeapon(IssueWeaponRequestDTO dto);
void returnWeapon(ReturnWeaponRequestDTO dto);
List<WeaponAddDTO> getAllActiveWeapons();
List<WeaponAddDTO> getAvailableWeapons();
List<OfficerDTO> getAllOfficers();
}
Loading
Loading