Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
haiphucnguyen committed Oct 25, 2024
1 parent 7715ef6 commit 5664299
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface ContactRepository extends JpaRepository<Contact, Long> {
public interface ContactRepository
extends JpaRepository<Contact, Long>, JpaSpecificationExecutor<Contact> {

Page<Contact> findByAccountId(Long accountId, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package io.flexwork.modules.crm.service;

import static io.flexwork.query.QueryUtils.createSpecification;

import io.flexwork.modules.crm.domain.Contact;
import io.flexwork.modules.crm.repository.ContactRepository;
import io.flexwork.modules.crm.service.dto.ContactDTO;
import io.flexwork.modules.crm.service.mapper.ContactMapper;
import io.flexwork.query.QueryDTO;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -14,18 +20,17 @@ public class ContactService {

private ContactRepository contactRepository;

public ContactService(ContactRepository contactRepository) {
private ContactMapper contactMapper;

public ContactService(ContactRepository contactRepository, ContactMapper contactMapper) {
this.contactRepository = contactRepository;
this.contactMapper = contactMapper;
}

public Page<Contact> findByAccountId(Long accountId, Pageable pageable) {
return contactRepository.findByAccountId(accountId, pageable);
}

public Page<Contact> getAllContacts(Pageable pageable) {
return contactRepository.findAll(pageable);
}

public Optional<Contact> getContactById(Long id) {
return contactRepository.findById(id);
}
Expand Down Expand Up @@ -58,4 +63,10 @@ public void deleteContact(Long id) {
public void deleteContacts(List<Long> ids) {
contactRepository.deleteAllByIdInBatch(ids);
}

@Transactional(readOnly = true)
public Page<ContactDTO> findContacts(Optional<QueryDTO> queryDTO, Pageable pageable) {
Specification<Contact> spec = createSpecification(queryDTO);
return contactRepository.findAll(spec, pageable).map(contactMapper::contactToContactDTO);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import io.flexwork.modules.crm.service.ContactService;
import io.flexwork.modules.crm.service.dto.ContactDTO;
import io.flexwork.modules.crm.service.mapper.ContactMapper;
import io.flexwork.query.QueryDTO;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

Expand All @@ -24,6 +27,13 @@ public ContactController(ContactService contactService, ContactMapper contactMap
this.contactMapper = contactMapper;
}

@PostMapping("/search")
public ResponseEntity<Page<ContactDTO>> findContacts(
@Valid @RequestBody Optional<QueryDTO> queryDTO, Pageable pageable) {
Page<ContactDTO> contacts = contactService.findContacts(queryDTO, pageable);
return new ResponseEntity<>(contacts, HttpStatus.OK);
}

@GetMapping("/account/{accountId}")
public Page<ContactDTO> getContacts(@PathVariable Long accountId, Pageable pageable) {
return contactService
Expand Down
1 change: 1 addition & 0 deletions server/src/main/java/io/flexwork/query/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
@Getter
@Setter
public class Filter {

@NotEmpty private String field;

@NotNull private String operator;
Expand Down
1 change: 1 addition & 0 deletions server/src/main/java/io/flexwork/query/QueryDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
@Getter
@Setter
public class QueryDTO {

private List<Filter> filters;
}
60 changes: 49 additions & 11 deletions server/src/main/java/io/flexwork/query/QueryUtils.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.flexwork.query;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import java.util.List;
Expand Down Expand Up @@ -30,17 +32,53 @@ public static <Entity> Specification<Entity> createSpecification(Optional<QueryD

private static <Entity> Predicate createPredicate(
Filter filter, Root<Entity> root, CriteriaBuilder cb) {
switch (filter.getOperator()) {
case "gt":
return cb.greaterThan(root.get(filter.getField()), (Comparable) filter.getValue());
case "lt":
return cb.lessThan(root.get(filter.getField()), (Comparable) filter.getValue());
case "eq":
return cb.equal(root.get(filter.getField()), filter.getValue());
case "in":
return root.get(filter.getField()).in((List<?>) filter.getValue());
default:
throw new IllegalArgumentException("Invalid operator: " + filter.getOperator());

String field = filter.getField();
Object value = filter.getValue();

// Check if the field requires a join
if (field.contains(".")) {
// Split the field by dot notation to get the join entity and target field
String[] pathParts = field.split("\\.");
String joinEntity = pathParts[0];
String targetField = pathParts[1];

// Perform the join dynamically
Join<Object, Object> join = root.join(joinEntity, JoinType.INNER);

// Create the predicate based on the operator
switch (filter.getOperator()) {
case "gt":
return cb.greaterThan(join.get(targetField), (Comparable) value);
case "lt":
return cb.lessThan(join.get(targetField), (Comparable) value);
case "eq":
return cb.equal(join.get(targetField), value);
case "in":
return join.get(targetField).in((List<?>) value);
default:
throw new IllegalArgumentException("Invalid operator: " + filter.getOperator());
}
} else {
// No join needed, access the field directly from the root
switch (filter.getOperator()) {
case "gt":
return cb.greaterThan(root.get(field), (Comparable) value);
case "lt":
return cb.lessThan(root.get(field), (Comparable) value);
case "eq":
return cb.equal(root.get(field), value);
case "in":
return root.get(field).in((List<?>) value);
default:
throw new IllegalArgumentException("Invalid operator: " + filter.getOperator());
}
}
}

private static boolean isJoinField(String field) {
// Define rules to detect join fields, e.g., fields that include a dot (.)
// indicating they are part of a related entity, like "account.id"
return field.contains(".");
}
}

0 comments on commit 5664299

Please sign in to comment.