updated sales to have new backend data

This commit is contained in:
Alex
2026-04-08 03:19:16 -06:00
parent 4ad94a318f
commit a76dfe4d9c
4 changed files with 214 additions and 57 deletions

View File

@@ -12,9 +12,16 @@ public class SaleDTO {
private Long storeId; private Long storeId;
private String storeName; private String storeName;
private BigDecimal totalAmount; private BigDecimal totalAmount;
private BigDecimal subtotalAmount;
private BigDecimal couponDiscountAmount;
private BigDecimal employeeDiscountAmount;
private String paymentMethod; private String paymentMethod;
private String channel;
private Boolean isRefund; private Boolean isRefund;
private Long originalSaleId; private Long originalSaleId;
private Long cartId;
private Long couponId;
private Integer pointsEarned;
private List<SaleItemDTO> items; private List<SaleItemDTO> items;
private String createdAt; private String createdAt;
@@ -60,10 +67,26 @@ public class SaleDTO {
return totalAmount; return totalAmount;
} }
public BigDecimal getSubtotalAmount() {
return subtotalAmount;
}
public BigDecimal getCouponDiscountAmount() {
return couponDiscountAmount;
}
public BigDecimal getEmployeeDiscountAmount() {
return employeeDiscountAmount;
}
public String getPaymentMethod() { public String getPaymentMethod() {
return paymentMethod; return paymentMethod;
} }
public String getChannel() {
return channel;
}
public Boolean getIsRefund() { public Boolean getIsRefund() {
return isRefund; return isRefund;
} }
@@ -72,6 +95,18 @@ public class SaleDTO {
return originalSaleId; return originalSaleId;
} }
public Long getCartId() {
return cartId;
}
public Long getCouponId() {
return couponId;
}
public Integer getPointsEarned() {
return pointsEarned;
}
public List<SaleItemDTO> getItems() { public List<SaleItemDTO> getItems() {
return items; return items;
} }
@@ -118,4 +153,4 @@ public class SaleDTO {
return unitPrice; return unitPrice;
} }
} }
} }

View File

@@ -31,7 +31,7 @@ public class RefundFragment extends Fragment {
// Items user has added to refund cart // Items user has added to refund cart
private List<RefundItem> refundCart = new ArrayList<>(); private List<RefundItem> refundCart = new ArrayList<>();
private final String[] PAYMENT_METHODS = {"Cash", "Card", "Debit"}; private final String[] PAYMENT_METHODS = {"Cash", "Card"};
// Inner class to track refund items // Inner class to track refund items
static class RefundItem { static class RefundItem {

View File

@@ -12,6 +12,9 @@ import com.example.petstoremobile.R;
import com.example.petstoremobile.databinding.FragmentSaleDetailBinding; import com.example.petstoremobile.databinding.FragmentSaleDetailBinding;
import com.example.petstoremobile.dtos.*; import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.viewmodels.*; import com.example.petstoremobile.viewmodels.*;
import com.example.petstoremobile.utils.SpinnerUtils;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.Resource;
import dagger.hilt.android.AndroidEntryPoint; import dagger.hilt.android.AndroidEntryPoint;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
@@ -33,7 +36,7 @@ public class SaleDetailFragment extends Fragment {
private List<ProductDTO> productList = new ArrayList<>(); private List<ProductDTO> productList = new ArrayList<>();
private List<SaleDTO.SaleItemDTO> cartItems = new ArrayList<>(); private List<SaleDTO.SaleItemDTO> cartItems = new ArrayList<>();
private final String[] PAYMENT_METHODS = { "Cash", "Credit Card", "Debit Card", "Online" }; private final String[] PAYMENT_METHODS = { "Cash", "Card"};
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
@@ -45,8 +48,7 @@ public class SaleDetailFragment extends Fragment {
customerViewModel = new ViewModelProvider(this).get(CustomerViewModel.class); customerViewModel = new ViewModelProvider(this).get(CustomerViewModel.class);
productViewModel = new ViewModelProvider(this).get(ProductViewModel.class); productViewModel = new ViewModelProvider(this).get(ProductViewModel.class);
binding.spinnerPaymentMethod.setAdapter(new ArrayAdapter<>(requireContext(), SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerPaymentMethod, PAYMENT_METHODS);
android.R.layout.simple_spinner_item, PAYMENT_METHODS));
handleArguments(); handleArguments();
@@ -81,9 +83,8 @@ public class SaleDetailFragment extends Fragment {
binding.spinnerSaleStore.setEnabled(false); binding.spinnerSaleStore.setEnabled(false);
binding.spinnerSaleCustomer.setEnabled(false); binding.spinnerSaleCustomer.setEnabled(false);
binding.spinnerPaymentMethod.setEnabled(false); binding.spinnerPaymentMethod.setEnabled(false);
binding.spinnerSaleProduct.setEnabled(false); binding.llAddItemRow.setVisibility(View.GONE);
binding.etSaleQuantity.setEnabled(false); binding.llExtraInfo.setVisibility(View.VISIBLE);
binding.btnAddItem.setEnabled(false);
} }
// Load sale details // Load sale details
@@ -92,6 +93,7 @@ public class SaleDetailFragment extends Fragment {
binding.tvSaleMode.setText("New Sale"); binding.tvSaleMode.setText("New Sale");
binding.tvSaleDetailId.setVisibility(View.GONE); binding.tvSaleDetailId.setVisibility(View.GONE);
binding.btnRefundSale.setVisibility(View.GONE); binding.btnRefundSale.setVisibility(View.GONE);
binding.llExtraInfo.setVisibility(View.GONE);
} }
} }
@@ -102,27 +104,18 @@ public class SaleDetailFragment extends Fragment {
} }
private void loadStores() { private void loadStores() {
storeViewModel.getAllStores(0, 50).observe(getViewLifecycleOwner(), resource -> { storeViewModel.getAllStores(0, 50).observe(getViewLifecycleOwner(), resource -> {
if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.SUCCESS && resource.data != null) { if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
storeList = resource.data.getContent(); storeList = resource.data.getContent();
List<String> names = new ArrayList<>();
names.add("-- Select Store --");
for (StoreDTO s : storeList) names.add(s.getStoreName());
if (binding != null) { if (binding != null) {
binding.spinnerSaleStore.setAdapter(new ArrayAdapter<>(requireContext(), SpinnerUtils.populateSpinner(requireContext(), binding.spinnerSaleStore, storeList,
android.R.layout.simple_spinner_item, names)); StoreDTO::getStoreName, "-- Select Store --", -1L, StoreDTO::getStoreId);
} }
} else if (storeList.isEmpty()) { } else if (storeList.isEmpty()) {
// Fallback if failed or empty storeList = Collections.singletonList(new StoreDTO(1L, "Downtown Branch"));
storeList = new ArrayList<>();
storeList.add(new StoreDTO(1L, "Downtown Branch"));
List<String> names = new ArrayList<>();
names.add("-- Select Store --");
names.add("Downtown Branch");
if (binding != null) { if (binding != null) {
binding.spinnerSaleStore.setAdapter(new ArrayAdapter<>(requireContext(), SpinnerUtils.populateSpinner(requireContext(), binding.spinnerSaleStore, storeList,
android.R.layout.simple_spinner_item, names)); StoreDTO::getStoreName, "-- Select Store --", -1L, StoreDTO::getStoreId);
} }
} }
}); });
@@ -130,15 +123,11 @@ public class SaleDetailFragment extends Fragment {
private void loadCustomers() { private void loadCustomers() {
customerViewModel.getAllCustomers(0, 200).observe(getViewLifecycleOwner(), resource -> { customerViewModel.getAllCustomers(0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.SUCCESS && resource.data != null) { if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
customerList = resource.data.getContent(); customerList = resource.data.getContent();
List<String> names = new ArrayList<>();
names.add("-- No Customer --");
for (CustomerDTO cu : customerList)
names.add(cu.getFirstName() + " " + cu.getLastName());
if (binding != null) { if (binding != null) {
binding.spinnerSaleCustomer.setAdapter(new ArrayAdapter<>(requireContext(), SpinnerUtils.populateSpinner(requireContext(), binding.spinnerSaleCustomer, customerList,
android.R.layout.simple_spinner_item, names)); CustomerDTO::getFullName, "-- No Customer --", -1L, CustomerDTO::getCustomerId);
} }
} }
}); });
@@ -146,15 +135,11 @@ public class SaleDetailFragment extends Fragment {
private void loadProducts() { private void loadProducts() {
productViewModel.getAllProducts(null, null, 0, 200, null).observe(getViewLifecycleOwner(), resource -> { productViewModel.getAllProducts(null, null, 0, 200, null).observe(getViewLifecycleOwner(), resource -> {
if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.SUCCESS && resource.data != null) { if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
productList = resource.data.getContent(); productList = resource.data.getContent();
List<String> names = new ArrayList<>();
names.add("-- Select Product --");
for (ProductDTO p : productList)
names.add(p.getProdName());
if (binding != null) { if (binding != null) {
binding.spinnerSaleProduct.setAdapter(new ArrayAdapter<>(requireContext(), SpinnerUtils.populateSpinner(requireContext(), binding.spinnerSaleProduct, productList,
android.R.layout.simple_spinner_item, names)); ProductDTO::getProdName, "Select Product", -1L, ProductDTO::getProdId);
} }
} }
}); });
@@ -162,10 +147,31 @@ public class SaleDetailFragment extends Fragment {
private void loadSaleDetails() { private void loadSaleDetails() {
saleViewModel.getSaleById(saleId).observe(getViewLifecycleOwner(), resource -> { saleViewModel.getSaleById(saleId).observe(getViewLifecycleOwner(), resource -> {
if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.SUCCESS && resource.data != null) { if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
SaleDTO sale = resource.data; SaleDTO sale = resource.data;
if (binding != null) { if (binding != null) {
binding.tvSaleDetailTotal.setText("Total: $" + sale.getTotalAmount()); binding.tvSaleDetailTotal.setText("Total: $" + sale.getTotalAmount());
binding.tvSaleSubtotal.setText("$" + (sale.getSubtotalAmount() != null ? sale.getSubtotalAmount() : sale.getTotalAmount()));
if (sale.getCouponDiscountAmount() != null && sale.getCouponDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
binding.llCouponDiscount.setVisibility(View.VISIBLE);
binding.tvSaleCouponDiscount.setText("-$" + sale.getCouponDiscountAmount());
} else {
binding.llCouponDiscount.setVisibility(View.GONE);
}
if (sale.getEmployeeDiscountAmount() != null && sale.getEmployeeDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
binding.llEmployeeDiscount.setVisibility(View.VISIBLE);
binding.tvSaleEmployeeDiscount.setText("-$" + sale.getEmployeeDiscountAmount());
} else {
binding.llEmployeeDiscount.setVisibility(View.GONE);
}
binding.tvSaleChannel.setText(sale.getChannel() != null ? sale.getChannel() : "");
binding.tvSalePoints.setText(String.valueOf(sale.getPointsEarned() != null ? sale.getPointsEarned() : 0));
SpinnerUtils.setSelectionByValue(binding.spinnerPaymentMethod, sale.getPaymentMethod());
// Display items // Display items
if (sale.getItems() != null) { if (sale.getItems() != null) {
binding.llSaleItems.removeAllViews(); binding.llSaleItems.removeAllViews();
@@ -255,6 +261,7 @@ public class SaleDetailFragment extends Fragment {
} }
} }
} }
binding.tvSaleSubtotal.setText("$" + total);
binding.tvSaleDetailTotal.setText("Total: $" + total); binding.tvSaleDetailTotal.setText("Total: $" + total);
} }
@@ -295,7 +302,7 @@ public class SaleDetailFragment extends Fragment {
break; break;
case ERROR: case ERROR:
Log.e("SALE_SAVE", "Error: " + resource.message); Log.e("SALE_SAVE", "Error: " + resource.message);
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_LONG).show(); DialogUtils.showInfoDialog(requireContext(), "Save Error", resource.message);
break; break;
} }
} }
@@ -303,9 +310,12 @@ public class SaleDetailFragment extends Fragment {
} }
private void showRefundDialog() { private void showRefundDialog() {
Bundle args = new Bundle(); DialogUtils.showConfirmDialog(requireContext(), "Process Refund",
args.putLong("saleId", saleId); "Are you sure you want to process a refund for this sale?", () -> {
NavHostFragment.findNavController(this).navigate(R.id.nav_refund, args); Bundle args = new Bundle();
args.putLong("saleId", saleId);
NavHostFragment.findNavController(this).navigate(R.id.nav_refund, args);
});
} }
private void navigateBack() { private void navigateBack() {

View File

@@ -46,7 +46,6 @@
android:orientation="vertical" android:orientation="vertical"
android:padding="24dp"> android:padding="24dp">
<!-- Sale Info Card -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -65,7 +64,6 @@
android:layout_gravity="end" android:layout_gravity="end"
android:layout_marginBottom="8dp"/> android:layout_marginBottom="8dp"/>
<!-- Store -->
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -80,7 +78,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dp"/> android:layout_marginBottom="16dp"/>
<!-- Customer (optional) -->
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -110,6 +107,54 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dp"/> android:layout_marginBottom="16dp"/>
<LinearLayout
android:id="@+id/llExtraInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Channel"
android:textColor="@color/text_dark"
android:textSize="12sp"/>
<TextView
android:id="@+id/tvSaleChannel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="—"
android:textSize="14sp"
android:layout_marginTop="4dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Points Earned"
android:textColor="@color/text_dark"
android:textSize="12sp"/>
<TextView
android:id="@+id/tvSalePoints"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="14sp"
android:layout_marginTop="4dp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout> </LinearLayout>
<!-- Items Card --> <!-- Items Card -->
@@ -130,8 +175,8 @@
android:textStyle="bold" android:textStyle="bold"
android:layout_marginBottom="12dp"/> android:layout_marginBottom="12dp"/>
<!-- Item row -->
<LinearLayout <LinearLayout
android:id="@+id/llAddItemRow"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
@@ -164,24 +209,91 @@
</LinearLayout> </LinearLayout>
<!-- Items list container -->
<LinearLayout <LinearLayout
android:id="@+id/llSaleItems" android:id="@+id/llSaleItems"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"/> android:orientation="vertical"/>
<!-- Total --> <View
<TextView android:layout_width="match_parent"
android:id="@+id/tvSaleDetailTotal" android:layout_height="1dp"
android:layout_width="wrap_content" android:background="#EEEEEE"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Total: $0.00" android:orientation="vertical">
android:textSize="18sp"
android:textStyle="bold" <LinearLayout
android:textColor="@color/accent_coral" android:layout_width="match_parent"
android:layout_gravity="end" android:layout_height="wrap_content"
android:layout_marginTop="12dp"/> android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Subtotal:"/>
<TextView
android:id="@+id/tvSaleSubtotal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="$0.00"/>
</LinearLayout>
<LinearLayout
android:id="@+id/llCouponDiscount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="4dp"
android:visibility="gone">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Coupon Discount:"/>
<TextView
android:id="@+id/tvSaleCouponDiscount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-$0.00"
android:textColor="@color/status_adopted"/>
</LinearLayout>
<LinearLayout
android:id="@+id/llEmployeeDiscount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="4dp"
android:visibility="gone">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Employee Discount:"/>
<TextView
android:id="@+id/tvSaleEmployeeDiscount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-$0.00"
android:textColor="@color/status_adopted"/>
</LinearLayout>
<TextView
android:id="@+id/tvSaleDetailTotal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total: $0.00"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/accent_coral"
android:layout_gravity="end"
android:layout_marginTop="12dp"/>
</LinearLayout>
</LinearLayout> </LinearLayout>