Sales bug fix
This commit is contained in:
@@ -19,6 +19,7 @@ public interface SaleApi {
|
||||
@Query("q") String query,
|
||||
@Query("paymentMethod") String paymentMethod,
|
||||
@Query("storeId") Long storeId,
|
||||
@Query("isRefund") Boolean isRefund,
|
||||
@Query("sort") String sort);
|
||||
|
||||
@GET("api/v1/sales/{id}")
|
||||
|
||||
@@ -9,6 +9,8 @@ public class SaleDTO {
|
||||
private String saleDate;
|
||||
private Long employeeId;
|
||||
private String employeeName;
|
||||
private Long customerId;
|
||||
private String customerName;
|
||||
private Long storeId;
|
||||
private String storeName;
|
||||
private BigDecimal totalAmount;
|
||||
@@ -25,9 +27,6 @@ public class SaleDTO {
|
||||
private List<SaleItemDTO> items;
|
||||
private String createdAt;
|
||||
|
||||
// Request fields
|
||||
private Long customerId;
|
||||
|
||||
// Constructor for create request
|
||||
public SaleDTO(Long storeId, String paymentMethod, List<SaleItemDTO> items,
|
||||
Boolean isRefund, Long originalSaleId, Long customerId) {
|
||||
@@ -119,6 +118,10 @@ public class SaleDTO {
|
||||
return customerId;
|
||||
}
|
||||
|
||||
public String getCustomerName() {
|
||||
return customerName;
|
||||
}
|
||||
|
||||
// Nested SaleItemDTO
|
||||
public static class SaleItemDTO {
|
||||
private Long saleItemId;
|
||||
|
||||
@@ -51,6 +51,7 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
||||
setupSearch();
|
||||
setupStoreFilter();
|
||||
setupPaymentMethodFilter();
|
||||
setupRefundStatusFilter();
|
||||
setupSwipeRefresh();
|
||||
setupFilterToggle();
|
||||
observeViewModel();
|
||||
@@ -75,7 +76,7 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
||||
|
||||
viewModel.getStores().observe(getViewLifecycleOwner(), list -> {
|
||||
SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerStore, list,
|
||||
StoreDTO::getStoreName, "Stores", null, StoreDTO::getStoreId);
|
||||
StoreDTO::getStoreName, "All Stores", null, StoreDTO::getStoreId);
|
||||
});
|
||||
|
||||
viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
|
||||
@@ -91,7 +92,7 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
||||
|
||||
private void setupFilterToggle() {
|
||||
UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchSale,
|
||||
binding.spinnerPaymentMethod, binding.spinnerStore);
|
||||
binding.spinnerPaymentMethod, binding.spinnerStore, binding.spinnerRefundStatus);
|
||||
}
|
||||
|
||||
private void setupStoreFilter() {
|
||||
@@ -99,10 +100,15 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
||||
}
|
||||
|
||||
private void setupPaymentMethodFilter() {
|
||||
String[] paymentMethods = {"Payments", "Cash", "Card"};
|
||||
String[] paymentMethods = {"All Payments", "Cash", "Card"};
|
||||
SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerPaymentMethod, paymentMethods, () -> loadSales(true));
|
||||
}
|
||||
|
||||
private void setupRefundStatusFilter() {
|
||||
String[] refundStatuses = {"All Status", "Sale", "Refund"};
|
||||
SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerRefundStatus, refundStatuses, () -> loadSales(true));
|
||||
}
|
||||
|
||||
private void setupRecyclerView() {
|
||||
adapter = new SaleAdapter(saleList, this);
|
||||
binding.recyclerViewSales.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
@@ -149,7 +155,12 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
||||
storeId = stores.get(binding.spinnerStore.getSelectedItemPosition() - 1).getStoreId();
|
||||
}
|
||||
|
||||
viewModel.loadSales(reset, query, paymentMethod, storeId);
|
||||
Boolean isRefund = null;
|
||||
if (binding.spinnerRefundStatus.getSelectedItemPosition() > 0) {
|
||||
isRefund = binding.spinnerRefundStatus.getSelectedItemPosition() == 2;
|
||||
}
|
||||
|
||||
viewModel.loadSales(reset, query, paymentMethod, storeId, isRefund);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,6 +170,7 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
||||
Bundle args = new Bundle();
|
||||
if (sale.getSaleId() != null) {
|
||||
args.putLong("saleId", sale.getSaleId());
|
||||
args.putBoolean("viewOnly", true);
|
||||
}
|
||||
if (sale.getIsRefund() != null) {
|
||||
args.putBoolean("isRefund", sale.getIsRefund());
|
||||
|
||||
@@ -40,7 +40,11 @@ public class SaleDetailFragment extends Fragment {
|
||||
observeViewModel();
|
||||
handleArguments();
|
||||
|
||||
if (!viewModel.isViewOnly()) {
|
||||
if (viewModel.isViewOnly()) {
|
||||
binding.llAddItemRow.setVisibility(View.GONE);
|
||||
binding.btnSaveSale.setVisibility(View.GONE);
|
||||
UIUtils.setViewsEnabled(false, binding.spinnerSaleStore, binding.spinnerSaleCustomer, binding.spinnerPaymentMethod);
|
||||
} else {
|
||||
loadData();
|
||||
setupAddItem();
|
||||
}
|
||||
@@ -84,8 +88,9 @@ public class SaleDetailFragment extends Fragment {
|
||||
binding.tvSaleMode.setText("Sale #" + saleId);
|
||||
binding.tvSaleDetailId.setText("ID: " + saleId);
|
||||
|
||||
if (!a.getBoolean("isRefund", false)) {
|
||||
binding.btnRefundSale.setVisibility(View.VISIBLE);
|
||||
boolean isRefund = a.getBoolean("isRefund", false);
|
||||
if (isRefund) {
|
||||
binding.btnRefundSale.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (viewOnly) {
|
||||
@@ -96,6 +101,16 @@ public class SaleDetailFragment extends Fragment {
|
||||
binding.spinnerPaymentMethod);
|
||||
binding.llAddItemRow.setVisibility(View.GONE);
|
||||
binding.llExtraInfo.setVisibility(View.VISIBLE);
|
||||
binding.llCustomerInfo.setVisibility(View.VISIBLE);
|
||||
binding.tvCustomerLabel.setVisibility(View.GONE);
|
||||
binding.spinnerSaleCustomer.setVisibility(View.GONE);
|
||||
binding.spinnerSaleStore.setVisibility(View.GONE);
|
||||
binding.spinnerPaymentMethod.setVisibility(View.GONE);
|
||||
binding.tvSaleStore.setVisibility(View.VISIBLE);
|
||||
binding.tvSalePaymentMethod.setVisibility(View.VISIBLE);
|
||||
|
||||
// Show refund button only if it's not already a refund
|
||||
binding.btnRefundSale.setVisibility(isRefund ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
loadSaleDetails();
|
||||
@@ -157,6 +172,13 @@ public class SaleDetailFragment extends Fragment {
|
||||
|
||||
binding.tvSaleChannel.setText(sale.getChannel() != null ? sale.getChannel() : "—");
|
||||
binding.tvSalePoints.setText(String.valueOf(sale.getPointsEarned() != null ? sale.getPointsEarned() : 0));
|
||||
binding.tvSaleStore.setText(sale.getStoreName() != null ? sale.getStoreName() : "—");
|
||||
binding.tvSaleCustomer.setText(sale.getCustomerName() != null ? sale.getCustomerName() : "No Customer");
|
||||
binding.tvSalePaymentMethod.setText(sale.getPaymentMethod() != null ? sale.getPaymentMethod() : "—");
|
||||
|
||||
if (sale.getIsRefund() != null && sale.getIsRefund()) {
|
||||
binding.btnRefundSale.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
SpinnerUtils.setSelectionByValue(binding.spinnerPaymentMethod, sale.getPaymentMethod());
|
||||
|
||||
|
||||
@@ -73,7 +73,9 @@ public class StaffDetailFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void refreshStoreSpinner() {
|
||||
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerStaffStore, viewModel.getStoreList().getValue(),
|
||||
List<DropdownDTO> list = viewModel.getStoreList().getValue();
|
||||
if (list == null) return;
|
||||
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerStaffStore, list,
|
||||
DropdownDTO::getLabel, "-- Select Store --",
|
||||
preselectedStoreId, DropdownDTO::getId);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ public class SaleRepository extends BaseRepository {
|
||||
this.saleApi = saleApi;
|
||||
}
|
||||
|
||||
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size, String query, String paymentMethod, Long storeId, String sortBy) {
|
||||
return executeCall(saleApi.getAllSales(page, size, query, paymentMethod, storeId, sortBy));
|
||||
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size, String query, String paymentMethod, Long storeId, Boolean isRefund, String sortBy) {
|
||||
return executeCall(saleApi.getAllSales(page, size, query, paymentMethod, storeId, isRefund, sortBy));
|
||||
}
|
||||
|
||||
public LiveData<Resource<SaleDTO>> getSaleById(Long id) {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class AnalyticsViewModel extends ViewModel {
|
||||
public void loadAnalytics() {
|
||||
isLoading.setValue(true);
|
||||
errorMessage.setValue(null);
|
||||
saleRepository.getAllSales(0, 2000, null, null, null, "saleDate,desc").observeForever(resource -> {
|
||||
saleRepository.getAllSales(0, 2000, null, null, null, null, "saleDate,desc").observeForever(resource -> {
|
||||
if (resource != null) {
|
||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||
cachedSales = resource.data.getContent();
|
||||
|
||||
@@ -34,7 +34,7 @@ public class RefundViewModel extends ViewModel {
|
||||
}
|
||||
|
||||
public LiveData<Resource<PageResponse<SaleDTO>>> loadAllSales() {
|
||||
return saleRepository.getAllSales(0, 1000, null, null, null, "saleDate,desc");
|
||||
return saleRepository.getAllSales(0, 1000, null, null, null, null, "saleDate,desc");
|
||||
}
|
||||
|
||||
public void setAllSales(List<SaleDTO> sales) {
|
||||
|
||||
@@ -42,7 +42,7 @@ public class SaleListViewModel extends ViewModel {
|
||||
public LiveData<Boolean> getIsLoading() { return isLoading; }
|
||||
public boolean isLastPage() { return isLastPage; }
|
||||
|
||||
public void loadSales(boolean reset, String query, String paymentMethod, Long storeId) {
|
||||
public void loadSales(boolean reset, String query, String paymentMethod, Long storeId, Boolean isRefund) {
|
||||
if (isLoading.getValue() != null && isLoading.getValue() && !reset) return;
|
||||
|
||||
if (reset) {
|
||||
@@ -51,7 +51,7 @@ public class SaleListViewModel extends ViewModel {
|
||||
}
|
||||
|
||||
isLoading.setValue(true);
|
||||
saleRepository.getAllSales(currentPage, PAGE_SIZE, query, paymentMethod, storeId, "saleDate,desc").observeForever(resource -> {
|
||||
saleRepository.getAllSales(currentPage, PAGE_SIZE, query, paymentMethod, storeId, isRefund, "saleDate,desc").observeForever(resource -> {
|
||||
if (resource != null) {
|
||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||
List<SaleDTO> currentList = reset ? new ArrayList<>() : new ArrayList<>(sales.getValue());
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.example.petstoremobile.repositories.EmployeeRepository;
|
||||
import com.example.petstoremobile.repositories.StoreRepository;
|
||||
import com.example.petstoremobile.utils.Resource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -20,7 +21,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel;
|
||||
public class StaffDetailViewModel extends ViewModel {
|
||||
private final EmployeeRepository repository;
|
||||
private final StoreRepository storeRepository;
|
||||
private final MutableLiveData<List<DropdownDTO>> storeList = new MutableLiveData<>();
|
||||
private final MutableLiveData<List<DropdownDTO>> storeList = new MutableLiveData<>(new ArrayList<>());
|
||||
private long employeeId = -1;
|
||||
private boolean isEditing = false;
|
||||
|
||||
|
||||
@@ -117,8 +117,25 @@
|
||||
android:background="@drawable/bg_spinner"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="4dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerRefundStatus"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_spinner"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_marginEnd="4dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnOpenRefund"
|
||||
|
||||
@@ -83,6 +83,40 @@
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSaleStore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/text_dark"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llCustomerInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Customer"
|
||||
android:textColor="@color/text_dark"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSaleCustomer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/text_dark"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvCustomerLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Customer (Optional)"
|
||||
@@ -111,6 +145,15 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSalePaymentMethod"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/text_dark"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llExtraInfo"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
Reference in New Issue
Block a user