changed backend so can sortBy productName and added search to productSupplier
This commit is contained in:
@@ -10,7 +10,11 @@ public interface ProductSupplierApi {
|
|||||||
@GET("api/v1/product-suppliers")
|
@GET("api/v1/product-suppliers")
|
||||||
Call<PageResponse<ProductSupplierDTO>> getAllProductSuppliers(
|
Call<PageResponse<ProductSupplierDTO>> getAllProductSuppliers(
|
||||||
@Query("page") int page,
|
@Query("page") int page,
|
||||||
@Query("size") int size);
|
@Query("size") int size,
|
||||||
|
@Query("q") String query,
|
||||||
|
@Query("productId") Long productId,
|
||||||
|
@Query("supplierId") Long supplierId,
|
||||||
|
@Query("sort") String sort);
|
||||||
|
|
||||||
@GET("api/v1/product-suppliers/{productId}/{supplierId}")
|
@GET("api/v1/product-suppliers/{productId}/{supplierId}")
|
||||||
Call<ProductSupplierDTO> getProductSupplierById(
|
Call<ProductSupplierDTO> getProductSupplierById(
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
* Configures the status filter spinner.
|
* Configures the status filter spinner.
|
||||||
*/
|
*/
|
||||||
private void setupStatusFilter() {
|
private void setupStatusFilter() {
|
||||||
String[] statuses = {"All Statuses", "Available", "Adopted"};
|
String[] statuses = {"All Statuses", "Available", "Adopted", "Owned"};
|
||||||
WhiteTextArrayAdapter<String> adapter = new WhiteTextArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, statuses);
|
WhiteTextArrayAdapter<String> adapter = new WhiteTextArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, statuses);
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
binding.spinnerStatus.setAdapter(adapter);
|
binding.spinnerStatus.setAdapter(adapter);
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
package com.example.petstoremobile.fragments.listfragments;
|
package com.example.petstoremobile.fragments.listfragments;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.*;
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.*;
|
import android.view.LayoutInflater;
|
||||||
import android.widget.*;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
@@ -15,11 +20,18 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.ProductSupplierAdapter;
|
import com.example.petstoremobile.adapters.ProductSupplierAdapter;
|
||||||
import com.example.petstoremobile.databinding.FragmentProductSupplierBinding;
|
import com.example.petstoremobile.databinding.FragmentProductSupplierBinding;
|
||||||
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import com.example.petstoremobile.dtos.ProductSupplierDTO;
|
import com.example.petstoremobile.dtos.ProductSupplierDTO;
|
||||||
|
import com.example.petstoremobile.dtos.SupplierDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
|
import com.example.petstoremobile.utils.Resource;
|
||||||
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
import com.example.petstoremobile.viewmodels.ProductSupplierViewModel;
|
import com.example.petstoremobile.viewmodels.ProductSupplierViewModel;
|
||||||
|
import com.example.petstoremobile.viewmodels.ProductViewModel;
|
||||||
|
import com.example.petstoremobile.viewmodels.SupplierViewModel;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
|
|
||||||
@@ -29,17 +41,23 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
|
|
||||||
private FragmentProductSupplierBinding binding;
|
private FragmentProductSupplierBinding binding;
|
||||||
private List<ProductSupplierDTO> psList = new ArrayList<>();
|
private List<ProductSupplierDTO> psList = new ArrayList<>();
|
||||||
private List<ProductSupplierDTO> filteredList = new ArrayList<>();
|
private List<ProductDTO> productList = new ArrayList<>();
|
||||||
|
private List<SupplierDTO> supplierList = new ArrayList<>();
|
||||||
|
|
||||||
private ProductSupplierAdapter adapter;
|
private ProductSupplierAdapter adapter;
|
||||||
private ProductSupplierViewModel viewModel;
|
private ProductSupplierViewModel viewModel;
|
||||||
|
private ProductViewModel productViewModel;
|
||||||
|
private SupplierViewModel supplierViewModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the fragment and its associated ProductSupplierViewModel.
|
* Initializes the fragment and its associated ViewModels.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
viewModel = new ViewModelProvider(this).get(ProductSupplierViewModel.class);
|
viewModel = new ViewModelProvider(this).get(ProductSupplierViewModel.class);
|
||||||
|
productViewModel = new ViewModelProvider(this).get(ProductViewModel.class);
|
||||||
|
supplierViewModel = new ViewModelProvider(this).get(SupplierViewModel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,8 +70,10 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
|
|
||||||
setupRecyclerView();
|
setupRecyclerView();
|
||||||
setupSearch();
|
setupSearch();
|
||||||
|
setupProductFilter();
|
||||||
|
setupSupplierFilter();
|
||||||
setupSwipeRefresh();
|
setupSwipeRefresh();
|
||||||
loadData();
|
setupFilterToggle();
|
||||||
|
|
||||||
binding.fabAddPS.setOnClickListener(v -> openDetail(-1));
|
binding.fabAddPS.setOnClickListener(v -> openDetail(-1));
|
||||||
|
|
||||||
@@ -76,11 +96,41 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
binding = null;
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads data every time the fragment becomes visible.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
loadData();
|
||||||
|
loadFilterData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the filter toggle button to show/hide the filter layout.
|
||||||
|
*/
|
||||||
|
private void setupFilterToggle() {
|
||||||
|
binding.btnToggleFilter.setOnClickListener(v -> {
|
||||||
|
if (binding.layoutFilter.getVisibility() == View.GONE) {
|
||||||
|
binding.layoutFilter.setVisibility(View.VISIBLE);
|
||||||
|
binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel);
|
||||||
|
} else {
|
||||||
|
binding.layoutFilter.setVisibility(View.GONE);
|
||||||
|
binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search);
|
||||||
|
|
||||||
|
// Reset filters when closing
|
||||||
|
binding.etSearchPS.setText("");
|
||||||
|
binding.spinnerProduct.setSelection(0);
|
||||||
|
binding.spinnerSupplier.setSelection(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView with a layout manager and adapter for product-supplier data.
|
* Initializes the RecyclerView with a layout manager and adapter for product-supplier data.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView() {
|
private void setupRecyclerView() {
|
||||||
adapter = new ProductSupplierAdapter(filteredList, this);
|
adapter = new ProductSupplierAdapter(psList, this);
|
||||||
binding.recyclerViewPS.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewPS.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
binding.recyclerViewPS.setAdapter(adapter);
|
binding.recyclerViewPS.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
@@ -90,10 +140,57 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
*/
|
*/
|
||||||
private void setupSearch() {
|
private void setupSearch() {
|
||||||
binding.etSearchPS.addTextChangedListener(new TextWatcher() {
|
binding.etSearchPS.addTextChangedListener(new TextWatcher() {
|
||||||
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
|
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
public void afterTextChanged(Editable s) {}
|
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
public void onTextChanged(CharSequence s, int a, int b, int c) {
|
loadData();
|
||||||
filter(s.toString());
|
}
|
||||||
|
@Override public void afterTextChanged(Editable s) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the product filter spinner.
|
||||||
|
*/
|
||||||
|
private void setupProductFilter() {
|
||||||
|
binding.spinnerProduct.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
@Override public void onNothingSelected(AdapterView<?> parent) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the supplier filter spinner.
|
||||||
|
*/
|
||||||
|
private void setupSupplierFilter() {
|
||||||
|
binding.spinnerSupplier.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
@Override public void onNothingSelected(AdapterView<?> parent) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches products and suppliers to populate the filters.
|
||||||
|
*/
|
||||||
|
private void loadFilterData() {
|
||||||
|
productViewModel.getAllProducts(null, null, 0, 100, "prodName").observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
|
productList = resource.data.getContent();
|
||||||
|
SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerProduct, productList,
|
||||||
|
ProductDTO::getProdName, "All Products", -1L, ProductDTO::getProdId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
supplierViewModel.getAllSuppliers(0, 100, null, "supCompany").observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
|
supplierList = resource.data.getContent();
|
||||||
|
SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerSupplier, supplierList,
|
||||||
|
SupplierDTO::getSupCompany, "All Suppliers", -1L, SupplierDTO::getSupId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -106,30 +203,23 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the product-supplier list based on the search query.
|
* Fetches product-supplier data from the server through the ViewModel with search query and filters.
|
||||||
*/
|
|
||||||
private void filter(String query) {
|
|
||||||
filteredList.clear();
|
|
||||||
if (query.isEmpty()) {
|
|
||||||
filteredList.addAll(psList);
|
|
||||||
} else {
|
|
||||||
String lower = query.toLowerCase();
|
|
||||||
for (ProductSupplierDTO ps : psList) {
|
|
||||||
if ((ps.getProductName() != null && ps.getProductName().toLowerCase().contains(lower))
|
|
||||||
|| (ps.getSupplierName() != null && ps.getSupplierName().toLowerCase().contains(lower))) {
|
|
||||||
filteredList.add(ps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches all product-supplier data from the server through the ViewModel.
|
|
||||||
*/
|
*/
|
||||||
private void loadData() {
|
private void loadData() {
|
||||||
//Load all product suppliers from the backend using viewModel
|
String query = binding.etSearchPS.getText().toString().trim();
|
||||||
viewModel.getAllProductSuppliers(0, 100).observe(getViewLifecycleOwner(), resource -> {
|
if (query.isEmpty()) query = null;
|
||||||
|
|
||||||
|
Long productId = null;
|
||||||
|
if (binding.spinnerProduct.getSelectedItemPosition() > 0 && !productList.isEmpty()) {
|
||||||
|
productId = productList.get(binding.spinnerProduct.getSelectedItemPosition() - 1).getProdId();
|
||||||
|
}
|
||||||
|
|
||||||
|
Long supplierId = null;
|
||||||
|
if (binding.spinnerSupplier.getSelectedItemPosition() > 0 && !supplierList.isEmpty()) {
|
||||||
|
supplierId = supplierList.get(binding.spinnerSupplier.getSelectedItemPosition() - 1).getSupId();
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.getAllProductSuppliers(0, 100, query, productId, supplierId, "productName").observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
|
||||||
// Check the status to see if the resource is loaded and display the data
|
// Check the status to see if the resource is loaded and display the data
|
||||||
@@ -144,7 +234,7 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
psList.clear();
|
psList.clear();
|
||||||
psList.addAll(resource.data.getContent());
|
psList.addAll(resource.data.getContent());
|
||||||
filter(binding.etSearchPS != null ? binding.etSearchPS.getText().toString() : "");
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
@@ -163,7 +253,7 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
private void openDetail(int position) {
|
private void openDetail(int position) {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
if (position != -1) {
|
if (position != -1) {
|
||||||
ProductSupplierDTO ps = filteredList.get(position);
|
ProductSupplierDTO ps = psList.get(position);
|
||||||
args.putLong("productId", ps.getProductId());
|
args.putLong("productId", ps.getProductId());
|
||||||
args.putLong("supplierId", ps.getSupplierId());
|
args.putLong("supplierId", ps.getSupplierId());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ public class ProductSupplierRepository extends BaseRepository {
|
|||||||
/**
|
/**
|
||||||
* Retrieves a paginated list of all product-supplier relationships from the API.
|
* Retrieves a paginated list of all product-supplier relationships from the API.
|
||||||
*/
|
*/
|
||||||
public LiveData<Resource<PageResponse<ProductSupplierDTO>>> getAllProductSuppliers(int page, int size) {
|
public LiveData<Resource<PageResponse<ProductSupplierDTO>>> getAllProductSuppliers(int page, int size, String query, Long productId, Long supplierId, String sort) {
|
||||||
return executeCall(api.getAllProductSuppliers(page, size));
|
return executeCall(api.getAllProductSuppliers(page, size, query, productId, supplierId, sort));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public class ProductSupplierViewModel extends ViewModel {
|
|||||||
/**
|
/**
|
||||||
* Fetches a paginated list of all product-supplier relationships.
|
* Fetches a paginated list of all product-supplier relationships.
|
||||||
*/
|
*/
|
||||||
public LiveData<Resource<PageResponse<ProductSupplierDTO>>> getAllProductSuppliers(int page, int size) {
|
public LiveData<Resource<PageResponse<ProductSupplierDTO>>> getAllProductSuppliers(int page, int size, String query, Long productId, Long supplierId, String sort) {
|
||||||
return repository.getAllProductSuppliers(page, size);
|
return repository.getAllProductSuppliers(page, size, query, productId, supplierId, sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,27 +28,100 @@
|
|||||||
android:contentDescription="Open menu"/>
|
android:contentDescription="Open menu"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
android:text="Product Suppliers"
|
android:text="Product Suppliers"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold"/>
|
android:textStyle="bold"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnToggleFilter"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:src="@android:drawable/ic_menu_search"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
app:tint="@color/white"
|
||||||
|
android:contentDescription="Toggle filter"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<EditText
|
<LinearLayout
|
||||||
android:id="@+id/etSearchPS"
|
android:id="@+id/layoutFilter"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:orientation="vertical"
|
||||||
android:hint="Search by product or supplier..."
|
android:paddingStart="12dp"
|
||||||
android:inputType="text"
|
android:paddingEnd="12dp"
|
||||||
android:drawableStart="@android:drawable/ic_menu_search"
|
android:paddingTop="10dp"
|
||||||
android:drawablePadding="8dp"
|
android:paddingBottom="10dp"
|
||||||
android:background="@android:color/white"
|
android:visibility="gone"
|
||||||
android:padding="12dp"
|
android:background="@color/primary_dark"
|
||||||
android:textColor="@color/text_dark"/>
|
android:elevation="4dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:background="@drawable/bg_search_bar"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
android:src="@android:drawable/ic_menu_search"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:contentDescription="Search icon"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etSearchPS"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:hint="Search by product or supplier..."
|
||||||
|
android:inputType="text"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:textColor="@color/text_dark"
|
||||||
|
android:textColorHint="#99000000"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="8dp">
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinnerProduct"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_spinner"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="8dp"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="0dp"/>
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinnerSupplier"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_spinner"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="8dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/swipeRefreshPS"
|
android:id="@+id/swipeRefreshPS"
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ public class ProductSupplierController {
|
|||||||
@GetMapping
|
@GetMapping
|
||||||
public ResponseEntity<Page<ProductSupplierResponse>> getAllProductSuppliers(
|
public ResponseEntity<Page<ProductSupplierResponse>> getAllProductSuppliers(
|
||||||
@RequestParam(required = false) String q,
|
@RequestParam(required = false) String q,
|
||||||
|
@RequestParam(required = false) Long productId,
|
||||||
|
@RequestParam(required = false) Long supplierId,
|
||||||
Pageable pageable) {
|
Pageable pageable) {
|
||||||
return ResponseEntity.ok(productSupplierService.getAllProductSuppliers(q, pageable));
|
return ResponseEntity.ok(productSupplierService.getAllProductSuppliers(q, productId, supplierId, pageable));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{productId}/{supplierId}")
|
@GetMapping("/{productId}/{supplierId}")
|
||||||
|
|||||||
@@ -12,7 +12,13 @@ import org.springframework.stereotype.Repository;
|
|||||||
public interface ProductSupplierRepository extends JpaRepository<ProductSupplier, ProductSupplier.ProductSupplierId> {
|
public interface ProductSupplierRepository extends JpaRepository<ProductSupplier, ProductSupplier.ProductSupplierId> {
|
||||||
|
|
||||||
@Query("SELECT ps FROM ProductSupplier ps WHERE " +
|
@Query("SELECT ps FROM ProductSupplier ps WHERE " +
|
||||||
"LOWER(ps.product.prodName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
"(:q IS NULL OR (LOWER(ps.product.prodName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
"LOWER(ps.supplier.supCompany) LIKE LOWER(CONCAT('%', :q, '%'))")
|
"LOWER(ps.supplier.supCompany) LIKE LOWER(CONCAT('%', :q, '%')))) AND " +
|
||||||
Page<ProductSupplier> searchProductSuppliers(@Param("q") String query, Pageable pageable);
|
"(:productId IS NULL OR ps.product.prodId = :productId) AND " +
|
||||||
|
"(:supplierId IS NULL OR ps.supplier.supId = :supplierId)")
|
||||||
|
Page<ProductSupplier> searchProductSuppliers(
|
||||||
|
@Param("q") String query,
|
||||||
|
@Param("productId") Long productId,
|
||||||
|
@Param("supplierId") Long supplierId,
|
||||||
|
Pageable pageable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,15 @@ import com.petshop.backend.repository.ProductRepository;
|
|||||||
import com.petshop.backend.repository.ProductSupplierRepository;
|
import com.petshop.backend.repository.ProductSupplierRepository;
|
||||||
import com.petshop.backend.repository.SupplierRepository;
|
import com.petshop.backend.repository.SupplierRepository;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ProductSupplierService {
|
public class ProductSupplierService {
|
||||||
|
|
||||||
@@ -28,13 +33,10 @@ public class ProductSupplierService {
|
|||||||
this.supplierRepository = supplierRepository;
|
this.supplierRepository = supplierRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<ProductSupplierResponse> getAllProductSuppliers(String query, Pageable pageable) {
|
public Page<ProductSupplierResponse> getAllProductSuppliers(String query, Long productId, Long supplierId, Pageable pageable) {
|
||||||
Page<ProductSupplier> productSuppliers;
|
String normalizedQuery = normalizeFilter(query);
|
||||||
if (query != null && !query.trim().isEmpty()) {
|
Pageable mappedPageable = mapSortProperties(pageable);
|
||||||
productSuppliers = productSupplierRepository.searchProductSuppliers(query, pageable);
|
Page<ProductSupplier> productSuppliers = productSupplierRepository.searchProductSuppliers(normalizedQuery, productId, supplierId, mappedPageable);
|
||||||
} else {
|
|
||||||
productSuppliers = productSupplierRepository.findAll(pageable);
|
|
||||||
}
|
|
||||||
return productSuppliers.map(this::mapToResponse);
|
return productSuppliers.map(this::mapToResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +97,33 @@ public class ProductSupplierService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String normalizeFilter(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String trimmed = value.trim();
|
||||||
|
return trimmed.isEmpty() ? null : trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pageable mapSortProperties(Pageable pageable) {
|
||||||
|
if (pageable.getSort().isUnsorted()) {
|
||||||
|
return pageable;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Sort.Order> orders = new ArrayList<>();
|
||||||
|
for (Sort.Order order : pageable.getSort()) {
|
||||||
|
String property = order.getProperty();
|
||||||
|
if ("productName".equalsIgnoreCase(property)) {
|
||||||
|
orders.add(new Sort.Order(order.getDirection(), "product.prodName"));
|
||||||
|
} else if ("supplierName".equalsIgnoreCase(property)) {
|
||||||
|
orders.add(new Sort.Order(order.getDirection(), "supplier.supCompany"));
|
||||||
|
} else {
|
||||||
|
orders.add(order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by(orders));
|
||||||
|
}
|
||||||
|
|
||||||
private ProductSupplierResponse mapToResponse(ProductSupplier productSupplier) {
|
private ProductSupplierResponse mapToResponse(ProductSupplier productSupplier) {
|
||||||
return new ProductSupplierResponse(
|
return new ProductSupplierResponse(
|
||||||
productSupplier.getProduct().getProdId(),
|
productSupplier.getProduct().getProdId(),
|
||||||
|
|||||||
Reference in New Issue
Block a user