Used the wrong endpoint for populating species, changed to to the correct one
also added coupon option to sales
This commit is contained in:
@@ -47,6 +47,9 @@ public interface PetApi {
|
|||||||
@GET("api/v1/dropdowns/pets")
|
@GET("api/v1/dropdowns/pets")
|
||||||
Call<List<DropdownDTO>> getPetDropdowns();
|
Call<List<DropdownDTO>> getPetDropdowns();
|
||||||
|
|
||||||
|
@GET("api/v1/dropdowns/pet-species")
|
||||||
|
Call<List<DropdownDTO>> getPetSpeciesDropdowns();
|
||||||
|
|
||||||
// Get pet by id
|
// Get pet by id
|
||||||
@GET("api/v1/pets/{id}")
|
@GET("api/v1/pets/{id}")
|
||||||
Call<PetDTO> getPetById(@Path("id") Long id);
|
Call<PetDTO> getPetById(@Path("id") Long id);
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ public class SaleDTO {
|
|||||||
return couponId;
|
return couponId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCouponId(Long couponId) {
|
||||||
|
this.couponId = couponId;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getPointsEarned() {
|
public Integer getPointsEarned() {
|
||||||
return pointsEarned;
|
return pointsEarned;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,11 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
|
viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
|
||||||
binding.swipeRefreshPet.setRefreshing(loading);
|
binding.swipeRefreshPet.setRefreshing(loading);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
viewModel.getSpeciesOptions().observe(getViewLifecycleOwner(), options -> {
|
||||||
|
String[] arr = options.toArray(new String[0]);
|
||||||
|
SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerSpecies, arr, this::loadPetData);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupBulkDelete() {
|
private void setupBulkDelete() {
|
||||||
@@ -107,6 +112,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
loadPetData();
|
loadPetData();
|
||||||
|
viewModel.loadSpecies();
|
||||||
if (!isStaff()) viewModel.loadStores();
|
if (!isStaff()) viewModel.loadStores();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,8 +141,8 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupSpeciesFilter() {
|
private void setupSpeciesFilter() {
|
||||||
String[] species = {"All Species", "Dog", "Cat", "Bird", "Rabbit", "Fish", "Hamster"};
|
String[] initial = {"All Species"};
|
||||||
SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerSpecies, species, this::loadPetData);
|
SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerSpecies, initial, this::loadPetData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupStoreFilter() {
|
private void setupStoreFilter() {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import androidx.navigation.Navigation;
|
|||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.databinding.FragmentCouponDetailBinding;
|
import com.example.petstoremobile.databinding.FragmentCouponDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.CouponDTO;
|
import com.example.petstoremobile.dtos.CouponDTO;
|
||||||
|
import com.example.petstoremobile.utils.DateTimeUtils;
|
||||||
import com.example.petstoremobile.utils.InputValidator;
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
import com.example.petstoremobile.utils.UIUtils;
|
import com.example.petstoremobile.utils.UIUtils;
|
||||||
@@ -95,6 +96,9 @@ public class CouponDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadCouponDetails() {
|
private void loadCouponDetails() {
|
||||||
|
binding.tvCouponId.setText(DateTimeUtils.formatId(couponId));
|
||||||
|
binding.tvCouponId.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
viewModel.loadCoupon(couponId).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadCoupon(couponId).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
CouponDTO coupon = resource.data;
|
CouponDTO coupon = resource.data;
|
||||||
|
|||||||
@@ -48,11 +48,13 @@ public class SaleDetailFragment extends Fragment {
|
|||||||
|
|
||||||
if (viewModel.isViewOnly()) {
|
if (viewModel.isViewOnly()) {
|
||||||
binding.llAddItemRow.setVisibility(View.GONE);
|
binding.llAddItemRow.setVisibility(View.GONE);
|
||||||
|
binding.llCouponInput.setVisibility(View.GONE);
|
||||||
binding.btnSaveSale.setVisibility(View.GONE);
|
binding.btnSaveSale.setVisibility(View.GONE);
|
||||||
UIUtils.setViewsEnabled(false, binding.spinnerSaleStore, binding.spinnerSaleCustomer, binding.spinnerPaymentMethod);
|
UIUtils.setViewsEnabled(false, binding.spinnerSaleStore, binding.spinnerSaleCustomer, binding.spinnerPaymentMethod);
|
||||||
} else {
|
} else {
|
||||||
loadData();
|
loadData();
|
||||||
setupAddItem();
|
setupAddItem();
|
||||||
|
setupCoupon();
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.btnSaleBack.setOnClickListener(v -> navigateBack());
|
binding.btnSaleBack.setOnClickListener(v -> navigateBack());
|
||||||
@@ -206,6 +208,70 @@ public class SaleDetailFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupCoupon() {
|
||||||
|
binding.btnApplyCoupon.setOnClickListener(v -> {
|
||||||
|
String code = binding.etCouponCode.getText().toString().trim();
|
||||||
|
if (code.isEmpty()) {
|
||||||
|
Toast.makeText(getContext(), "Enter a coupon code", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
viewModel.lookupCoupon(code).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
|
CouponDTO coupon = resource.data;
|
||||||
|
if (Boolean.FALSE.equals(coupon.getActive())) {
|
||||||
|
showCouponError("This coupon is no longer active.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (coupon.getMinOrderAmount() != null &&
|
||||||
|
viewModel.calculateSubtotal().compareTo(coupon.getMinOrderAmount()) < 0) {
|
||||||
|
showCouponError("Minimum order of $" + coupon.getMinOrderAmount() + " required.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
viewModel.setAppliedCoupon(coupon);
|
||||||
|
applyAppliedCouponUI(coupon);
|
||||||
|
updateTotal();
|
||||||
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
|
showCouponError("Invalid coupon code.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.btnClearCoupon.setOnClickListener(v -> {
|
||||||
|
viewModel.clearCoupon();
|
||||||
|
binding.etCouponCode.setText("");
|
||||||
|
binding.tvCouponInfo.setVisibility(View.GONE);
|
||||||
|
binding.btnClearCoupon.setVisibility(View.GONE);
|
||||||
|
binding.btnApplyCoupon.setVisibility(View.VISIBLE);
|
||||||
|
binding.etCouponCode.setEnabled(true);
|
||||||
|
binding.llCouponDiscount.setVisibility(View.GONE);
|
||||||
|
updateTotal();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyAppliedCouponUI(CouponDTO coupon) {
|
||||||
|
String info;
|
||||||
|
if ("PERCENTAGE".equalsIgnoreCase(coupon.getDiscountType())) {
|
||||||
|
info = coupon.getDiscountValue().stripTrailingZeros().toPlainString() + "% off applied";
|
||||||
|
} else {
|
||||||
|
info = "$" + coupon.getDiscountValue() + " off applied";
|
||||||
|
}
|
||||||
|
binding.tvCouponInfo.setText(info);
|
||||||
|
binding.tvCouponInfo.setTextColor(0xFF4CAF50);
|
||||||
|
binding.tvCouponInfo.setVisibility(View.VISIBLE);
|
||||||
|
binding.btnClearCoupon.setVisibility(View.VISIBLE);
|
||||||
|
binding.btnApplyCoupon.setVisibility(View.GONE);
|
||||||
|
binding.etCouponCode.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showCouponError(String message) {
|
||||||
|
binding.tvCouponInfo.setText(message);
|
||||||
|
binding.tvCouponInfo.setTextColor(0xFFE53935);
|
||||||
|
binding.tvCouponInfo.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
private void setupAddItem() {
|
private void setupAddItem() {
|
||||||
binding.btnAddItem.setOnClickListener(v -> {
|
binding.btnAddItem.setOnClickListener(v -> {
|
||||||
if (!InputValidator.isSpinnerSelected(binding.spinnerSaleProduct, "Product")) return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerSaleProduct, "Product")) return;
|
||||||
@@ -271,8 +337,16 @@ public class SaleDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateTotal() {
|
private void updateTotal() {
|
||||||
BigDecimal total = viewModel.calculateSubtotal();
|
BigDecimal subtotal = viewModel.calculateSubtotal();
|
||||||
binding.tvSaleSubtotal.setText("$" + total);
|
BigDecimal discount = viewModel.calculateDiscount();
|
||||||
|
BigDecimal total = subtotal.subtract(discount);
|
||||||
|
binding.tvSaleSubtotal.setText("$" + subtotal);
|
||||||
|
if (discount.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
binding.llCouponDiscount.setVisibility(View.VISIBLE);
|
||||||
|
binding.tvSaleCouponDiscount.setText("-$" + discount);
|
||||||
|
} else {
|
||||||
|
binding.llCouponDiscount.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
binding.tvSaleDetailTotal.setText("Total: $" + total);
|
binding.tvSaleDetailTotal.setText("Total: $" + total);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,6 +367,7 @@ public class SaleDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SaleDTO dto = new SaleDTO(store.getId(), payment, viewModel.getCartItems().getValue(), false, null, customerId);
|
SaleDTO dto = new SaleDTO(store.getId(), payment, viewModel.getCartItems().getValue(), false, null, customerId);
|
||||||
|
dto.setCouponId(viewModel.getAppliedCouponId());
|
||||||
|
|
||||||
viewModel.createSale(dto).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.createSale(dto).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ public class CouponRepository extends BaseRepository {
|
|||||||
return executeCall(couponApi.getCouponById(id));
|
return executeCall(couponApi.getCouponById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<Resource<CouponDTO>> getCouponByCode(String code) {
|
||||||
|
return executeCall(couponApi.getCouponByCode(code));
|
||||||
|
}
|
||||||
|
|
||||||
public LiveData<Resource<CouponDTO>> createCoupon(CouponDTO coupon) {
|
public LiveData<Resource<CouponDTO>> createCoupon(CouponDTO coupon) {
|
||||||
return executeCall(couponApi.createCoupon(coupon));
|
return executeCall(couponApi.createCoupon(coupon));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ public class PetRepository extends BaseRepository {
|
|||||||
return executeCall(petApi.getPetDropdowns());
|
return executeCall(petApi.getPetDropdowns());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<Resource<List<DropdownDTO>>> getPetSpeciesDropdowns() {
|
||||||
|
return executeCall(petApi.getPetSpeciesDropdowns());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves available pets for a specific store.
|
* Retrieves available pets for a specific store.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class PetDetailViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
observeOnce(petRepository.getPetDropdowns(), resource -> {
|
observeOnce(petRepository.getPetSpeciesDropdowns(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
speciesList.setValue(resource.data);
|
speciesList.setValue(resource.data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData;
|
|||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import com.example.petstoremobile.dtos.BulkDeleteRequest;
|
import com.example.petstoremobile.dtos.BulkDeleteRequest;
|
||||||
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.PageResponse;
|
import com.example.petstoremobile.dtos.PageResponse;
|
||||||
import com.example.petstoremobile.dtos.PetDTO;
|
import com.example.petstoremobile.dtos.PetDTO;
|
||||||
import com.example.petstoremobile.dtos.StoreDTO;
|
import com.example.petstoremobile.dtos.StoreDTO;
|
||||||
@@ -28,6 +29,7 @@ public class PetListViewModel extends ViewModel {
|
|||||||
|
|
||||||
private final MutableLiveData<List<PetDTO>> pets = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<PetDTO>> pets = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<List<StoreDTO>> stores = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<StoreDTO>> stores = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
private final MutableLiveData<List<String>> speciesOptions = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -38,6 +40,7 @@ public class PetListViewModel extends ViewModel {
|
|||||||
|
|
||||||
public LiveData<List<PetDTO>> getPets() { return pets; }
|
public LiveData<List<PetDTO>> getPets() { return pets; }
|
||||||
public LiveData<List<StoreDTO>> getStores() { return stores; }
|
public LiveData<List<StoreDTO>> getStores() { return stores; }
|
||||||
|
public LiveData<List<String>> getSpeciesOptions() { return speciesOptions; }
|
||||||
public LiveData<Boolean> getIsLoading() { return isLoading; }
|
public LiveData<Boolean> getIsLoading() { return isLoading; }
|
||||||
|
|
||||||
public void loadPets(String query, String status, String species, Long storeId) {
|
public void loadPets(String query, String status, String species, Long storeId) {
|
||||||
@@ -57,6 +60,19 @@ public class PetListViewModel extends ViewModel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadSpecies() {
|
||||||
|
observeOnce(petRepository.getPetSpeciesDropdowns(), resource -> {
|
||||||
|
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
|
List<String> labels = new ArrayList<>();
|
||||||
|
labels.add("All Species");
|
||||||
|
for (DropdownDTO dto : resource.data) {
|
||||||
|
labels.add(dto.getLabel());
|
||||||
|
}
|
||||||
|
speciesOptions.setValue(labels);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void loadStores() {
|
public void loadStores() {
|
||||||
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
|
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import androidx.lifecycle.LiveData;
|
|||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
import com.example.petstoremobile.dtos.CouponDTO;
|
||||||
import com.example.petstoremobile.dtos.DropdownDTO;
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import com.example.petstoremobile.dtos.SaleDTO;
|
import com.example.petstoremobile.dtos.SaleDTO;
|
||||||
|
import com.example.petstoremobile.repositories.CouponRepository;
|
||||||
import com.example.petstoremobile.repositories.CustomerRepository;
|
import com.example.petstoremobile.repositories.CustomerRepository;
|
||||||
import com.example.petstoremobile.repositories.ProductRepository;
|
import com.example.petstoremobile.repositories.ProductRepository;
|
||||||
import com.example.petstoremobile.repositories.SaleRepository;
|
import com.example.petstoremobile.repositories.SaleRepository;
|
||||||
@@ -27,6 +29,7 @@ public class SaleDetailViewModel extends ViewModel {
|
|||||||
private final StoreRepository storeRepository;
|
private final StoreRepository storeRepository;
|
||||||
private final CustomerRepository customerRepository;
|
private final CustomerRepository customerRepository;
|
||||||
private final ProductRepository productRepository;
|
private final ProductRepository productRepository;
|
||||||
|
private final CouponRepository couponRepository;
|
||||||
|
|
||||||
private long saleId = -1;
|
private long saleId = -1;
|
||||||
private boolean viewOnly = false;
|
private boolean viewOnly = false;
|
||||||
@@ -35,15 +38,18 @@ public class SaleDetailViewModel extends ViewModel {
|
|||||||
private final MutableLiveData<List<DropdownDTO>> customerList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<DropdownDTO>> customerList = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<List<ProductDTO>> productList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<ProductDTO>> productList = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<List<SaleDTO.SaleItemDTO>> cartItems = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<SaleDTO.SaleItemDTO>> cartItems = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
private final MutableLiveData<CouponDTO> appliedCoupon = new MutableLiveData<>(null);
|
||||||
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SaleDetailViewModel(SaleRepository saleRepository, StoreRepository storeRepository,
|
public SaleDetailViewModel(SaleRepository saleRepository, StoreRepository storeRepository,
|
||||||
CustomerRepository customerRepository, ProductRepository productRepository) {
|
CustomerRepository customerRepository, ProductRepository productRepository,
|
||||||
|
CouponRepository couponRepository) {
|
||||||
this.saleRepository = saleRepository;
|
this.saleRepository = saleRepository;
|
||||||
this.storeRepository = storeRepository;
|
this.storeRepository = storeRepository;
|
||||||
this.customerRepository = customerRepository;
|
this.customerRepository = customerRepository;
|
||||||
this.productRepository = productRepository;
|
this.productRepository = productRepository;
|
||||||
|
this.couponRepository = couponRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSaleId(long id, boolean viewOnly) {
|
public void setSaleId(long id, boolean viewOnly) {
|
||||||
@@ -91,6 +97,38 @@ public class SaleDetailViewModel extends ViewModel {
|
|||||||
|
|
||||||
public LiveData<List<SaleDTO.SaleItemDTO>> getCartItems() { return cartItems; }
|
public LiveData<List<SaleDTO.SaleItemDTO>> getCartItems() { return cartItems; }
|
||||||
|
|
||||||
|
public LiveData<Resource<CouponDTO>> lookupCoupon(String code) {
|
||||||
|
return couponRepository.getCouponByCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppliedCoupon(CouponDTO coupon) {
|
||||||
|
appliedCoupon.setValue(coupon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCoupon() {
|
||||||
|
appliedCoupon.setValue(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<CouponDTO> getAppliedCoupon() {
|
||||||
|
return appliedCoupon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAppliedCouponId() {
|
||||||
|
CouponDTO coupon = appliedCoupon.getValue();
|
||||||
|
return coupon != null ? coupon.getCouponId() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal calculateDiscount() {
|
||||||
|
CouponDTO coupon = appliedCoupon.getValue();
|
||||||
|
if (coupon == null || coupon.getDiscountValue() == null) return BigDecimal.ZERO;
|
||||||
|
BigDecimal subtotal = calculateSubtotal();
|
||||||
|
if ("PERCENTAGE".equalsIgnoreCase(coupon.getDiscountType())) {
|
||||||
|
return subtotal.multiply(coupon.getDiscountValue()).divide(BigDecimal.valueOf(100), 2, java.math.RoundingMode.HALF_UP);
|
||||||
|
} else {
|
||||||
|
return coupon.getDiscountValue().min(subtotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal calculateSubtotal() {
|
public BigDecimal calculateSubtotal() {
|
||||||
BigDecimal total = BigDecimal.ZERO;
|
BigDecimal total = BigDecimal.ZERO;
|
||||||
List<SaleDTO.SaleItemDTO> items = cartItems.getValue();
|
List<SaleDTO.SaleItemDTO> items = cartItems.getValue();
|
||||||
|
|||||||
@@ -60,6 +60,17 @@
|
|||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:layout_marginBottom="16dp">
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvCouponId"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/text_light"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<!-- Coupon Code -->
|
<!-- Coupon Code -->
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -262,6 +262,66 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"/>
|
android:orientation="vertical"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llCouponInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginTop="12dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Coupon Code"
|
||||||
|
android:textColor="@color/text_dark"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etCouponCode"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="Enter coupon code"
|
||||||
|
android:inputType="textCapCharacters"
|
||||||
|
android:layout_marginEnd="8dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnApplyCoupon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Apply"
|
||||||
|
android:backgroundTint="@color/primary_medium"
|
||||||
|
android:textColor="@color/white"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnClearCoupon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Clear"
|
||||||
|
android:backgroundTint="@color/accent_coral"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvCouponInfo"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
|
|||||||
Reference in New Issue
Block a user