From 3f189f5975fcb20968b218520cb07cb9180bc124 Mon Sep 17 00:00:00 2001 From: riz081 Date: Thu, 5 Jun 2025 16:19:46 +0700 Subject: [PATCH] implement menu settlement --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 4 + .../com/example/bdkipoc/MainActivity.java | 2 +- .../com/example/bdkipoc/ReceiptActivity.java | 61 +-- .../example/bdkipoc/SettlementActivity.java | 354 ++++++++++++++++++ .../example/bdkipoc/TransactionActivity.java | 35 +- .../example/bdkipoc/TransactionAdapter.java | 6 + .../main/res/layout/activity_settlement.xml | 160 ++++++++ app/src/main/res/layout/item_settlement.xml | 70 ++++ 9 files changed, 642 insertions(+), 51 deletions(-) create mode 100644 app/src/main/java/com/example/bdkipoc/SettlementActivity.java create mode 100644 app/src/main/res/layout/activity_settlement.xml create mode 100644 app/src/main/res/layout/item_settlement.xml diff --git a/app/build.gradle b/app/build.gradle index 6f930f6..6e550a3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,6 +35,7 @@ dependencies { implementation libs.activity implementation libs.constraintlayout implementation libs.cardview + implementation 'androidx.recyclerview:recyclerview:1.3.0' testImplementation libs.junit androidTestImplementation libs.ext.junit androidTestImplementation libs.espresso.core diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8933381..f293eee 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,6 +17,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.BDKIPOC" + android:usesCleartextTraffic="true" tools:targetApi="31"> + \ No newline at end of file diff --git a/app/src/main/java/com/example/bdkipoc/MainActivity.java b/app/src/main/java/com/example/bdkipoc/MainActivity.java index 1a3db64..89854f3 100644 --- a/app/src/main/java/com/example/bdkipoc/MainActivity.java +++ b/app/src/main/java/com/example/bdkipoc/MainActivity.java @@ -168,7 +168,7 @@ public class MainActivity extends AppCompatActivity { } else if (cardId == R.id.card_cetak_ulang) { startActivity(new Intent(MainActivity.this, TransactionActivity.class)); } else if (cardId == R.id.card_settlement) { - Toast.makeText(this, "Settlement - Coming Soon", Toast.LENGTH_SHORT).show(); + startActivity(new Intent(MainActivity.this, SettlementActivity.class)); } else if (cardId == R.id.card_histori) { Toast.makeText(this, "Histori - Coming Soon", Toast.LENGTH_SHORT).show(); } else if (cardId == R.id.card_bantuan) { diff --git a/app/src/main/java/com/example/bdkipoc/ReceiptActivity.java b/app/src/main/java/com/example/bdkipoc/ReceiptActivity.java index 1d49e2a..bf98eb6 100644 --- a/app/src/main/java/com/example/bdkipoc/ReceiptActivity.java +++ b/app/src/main/java/com/example/bdkipoc/ReceiptActivity.java @@ -109,7 +109,7 @@ public class ReceiptActivity extends AppCompatActivity { private void loadTransactionData() { Intent intent = getIntent(); if (intent != null) { - // Load transaction data from intent + // Data dari TransactionActivity String amount = intent.getStringExtra("transaction_amount"); String merchantNameStr = intent.getStringExtra("merchant_name"); String merchantLocationStr = intent.getStringExtra("merchant_location"); @@ -117,60 +117,35 @@ public class ReceiptActivity extends AppCompatActivity { String transactionDateStr = intent.getStringExtra("transaction_date"); String paymentMethodStr = intent.getStringExtra("payment_method"); String cardTypeStr = intent.getStringExtra("card_type"); - String taxPercentageStr = intent.getStringExtra("tax_percentage"); - String serviceFeeStr = intent.getStringExtra("service_fee"); - // Set merchant info - if (!TextUtils.isEmpty(merchantNameStr)) { - merchantName.setText(merchantNameStr); - } - if (!TextUtils.isEmpty(merchantLocationStr)) { - merchantLocation.setText(merchantLocationStr); - } + // Set data ke view + merchantName.setText(merchantNameStr != null ? merchantNameStr : "TOKO KLONTONG PAK EKO"); + merchantLocation.setText(merchantLocationStr != null ? merchantLocationStr : "Ciputat Baru, Tangsel"); + transactionNumber.setText(transactionId != null ? transactionId : "3429483635"); + transactionDate.setText(transactionDateStr != null ? transactionDateStr : "13 Januari 2025 13:46"); + paymentMethod.setText(paymentMethodStr != null ? paymentMethodStr : "Kartu Kredit"); + cardType.setText(cardTypeStr != null ? cardTypeStr : "BCA"); - // Set transaction details - if (!TextUtils.isEmpty(transactionId)) { - transactionNumber.setText(transactionId); - } - if (!TextUtils.isEmpty(transactionDateStr)) { - transactionDate.setText(transactionDateStr); - } - if (!TextUtils.isEmpty(paymentMethodStr)) { - paymentMethod.setText(paymentMethodStr); - } - if (!TextUtils.isEmpty(cardTypeStr)) { - cardType.setText(cardTypeStr); - } - if (!TextUtils.isEmpty(taxPercentageStr)) { - taxPercentage.setText(taxPercentageStr); - } - if (!TextUtils.isEmpty(serviceFeeStr)) { - serviceFee.setText(serviceFeeStr); - } - - // Calculate and set amounts - if (!TextUtils.isEmpty(amount)) { + // Format nominal + if (amount != null) { try { long amountValue = Long.parseLong(amount); - String formattedAmount = formatCurrency(amountValue); + transactionTotal.setText(formatCurrency(amountValue)); - transactionTotal.setText(formattedAmount); + // Hitung total akhir (contoh: tambah pajak 11% dan biaya layanan 500) + long tax = (long) (amountValue * 0.11); + long serviceFeeValue = 500; + long total = amountValue + tax + serviceFeeValue; - // Calculate total with tax and service fee - long serviceFeeLong = TextUtils.isEmpty(serviceFeeStr) ? 0 : Long.parseLong(serviceFeeStr); - long totalWithFee = amountValue + serviceFeeLong; - - finalTotal.setText(formatCurrency(totalWithFee)); + taxPercentage.setText(formatCurrency(tax) + " (11%)"); + serviceFee.setText(formatCurrency(serviceFeeValue)); + finalTotal.setText(formatCurrency(total)); } catch (NumberFormatException e) { transactionTotal.setText(amount); finalTotal.setText(amount); } } - - // Set MID and TID (you can customize these) - midText.setText("1234567890"); - tidText.setText("1234567890"); } } diff --git a/app/src/main/java/com/example/bdkipoc/SettlementActivity.java b/app/src/main/java/com/example/bdkipoc/SettlementActivity.java new file mode 100644 index 0000000..ad1f83d --- /dev/null +++ b/app/src/main/java/com/example/bdkipoc/SettlementActivity.java @@ -0,0 +1,354 @@ +package com.example.bdkipoc; + +import android.os.AsyncTask; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class SettlementActivity extends AppCompatActivity { + + private TextView tvTotalAmount; + private TextView tvTotalTransactions; + private RecyclerView recyclerView; + private SettlementAdapter adapter; + private List settlementList; + private ImageView btnBack; + + private String API_URL = "https://be-edc.msvc.app/transactions/performa-chanel-pembayaran?from_date=2025-01-01&to_date=2025-06-04&location_id=0&merchant_id=0"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_settlement); + + initViews(); + setupRecyclerView(); + fetchApiData(); + setupClickListeners(); + } + + private void fetchApiData() { + // Execute network call in background thread + new ApiTask().execute(API_URL); + } + + private void processApiData(JSONArray dataArray) { + try { + settlementList.clear(); + + final long[] totalAmountArray = {0}; // Using array to make it effectively final + final int[] totalTransactionsArray = {0}; // Using array to make it effectively final + + // Process each channel individually (no grouping) + for (int i = 0; i < dataArray.length(); i++) { + JSONObject item = dataArray.getJSONObject(i); + + String channelCode = item.getString("channel_code"); + int transactions = item.getInt("total_transactions"); + long maxAmount = item.getLong("max_transastions"); + + // Use channel code directly as display name with some formatting + String displayName = formatChannelName(channelCode); + int iconResource = getChannelIcon(channelCode); + + settlementList.add(new SettlementItem( + displayName, + maxAmount, + transactions, + iconResource + )); + + totalAmountArray[0] += maxAmount; + totalTransactionsArray[0] += transactions; + } + + // Update UI on main thread + runOnUiThread(new Runnable() { + @Override + public void run() { + updateSummary(totalAmountArray[0], totalTransactionsArray[0]); + adapter.notifyDataSetChanged(); + } + }); + + } catch (JSONException e) { + e.printStackTrace(); + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(SettlementActivity.this, "Error parsing data", Toast.LENGTH_SHORT).show(); + loadSampleData(); // Fallback to sample data + } + }); + } + } + + private void updateSummary(long totalAmount, int totalTransactions) { + tvTotalAmount.setText(formatCurrency(totalAmount)); + tvTotalTransactions.setText(String.valueOf(totalTransactions)); + } + + private void initViews() { + tvTotalAmount = findViewById(R.id.tv_total_amount); + tvTotalTransactions = findViewById(R.id.tv_total_transactions); + recyclerView = findViewById(R.id.recycler_view); + btnBack = findViewById(R.id.btn_back); + + settlementList = new ArrayList<>(); + } + + private void setupRecyclerView() { + adapter = new SettlementAdapter(settlementList); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(adapter); + } + + private void setupClickListeners() { + btnBack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } + + private void loadSampleData() { + // Sample data as fallback + settlementList.clear(); + + settlementList.add(new SettlementItem("Kartu Kredit", 200000, 13, android.R.drawable.ic_menu_recent_history)); + settlementList.add(new SettlementItem("Kartu Debit", 200000, 13, android.R.drawable.ic_menu_manage)); + settlementList.add(new SettlementItem("Transfer", 200000, 13, android.R.drawable.ic_menu_send)); + settlementList.add(new SettlementItem("Uang Elektronik", 200000, 13, android.R.drawable.ic_menu_gallery)); + settlementList.add(new SettlementItem("QRIS", 200000, 13, android.R.drawable.ic_menu_camera)); + + // Update summary + tvTotalAmount.setText(formatCurrency(3506500)); + tvTotalTransactions.setText("65"); + + adapter.notifyDataSetChanged(); + } + + private String formatChannelName(String channelCode) { + // Format channel code to be more readable + switch (channelCode) { + case "GO-PAY": + return "GoPay"; + case "SHOPEEPAY": + return "ShopeePay"; + case "LINKAJA": + return "LinkAja"; + case "MASTERCARD": + return "Mastercard"; + case "VISA": + return "Visa"; + case "QRIS": + return "QRIS"; + case "DANA": + return "Dana"; + case "OVO": + return "OVO"; + case "DEBIT": + return "Kartu Debit"; + case "GPN": + return "GPN"; + case "OTHER": + return "Lainnya"; + default: + // Capitalize first letter and make rest lowercase + return channelCode.substring(0, 1).toUpperCase() + + channelCode.substring(1).toLowerCase(); + } + } + + private String getChannelDisplayName(String channelCode) { + // Deprecated - keeping for backward compatibility + return formatChannelName(channelCode); + } + + private int getChannelIcon(String channelCode) { + // Dynamic icon assignment based on channel type + switch (channelCode) { + case "DEBIT": + return android.R.drawable.ic_menu_manage; + case "VISA": + case "MASTERCARD": + return android.R.drawable.ic_menu_recent_history; + case "QRIS": + return android.R.drawable.ic_menu_camera; + case "DANA": + case "GO-PAY": + case "OVO": + case "SHOPEEPAY": + case "LINKAJA": + return android.R.drawable.ic_menu_gallery; + case "GPN": + return android.R.drawable.ic_menu_send; + case "OTHER": + return android.R.drawable.ic_menu_info_details; + default: + return android.R.drawable.ic_menu_help; + } + } + + private String formatCurrency(long amount) { + NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID")); + return formatter.format(amount); + } + + // Deprecated helper class - no longer needed + // private static class ChannelData { ... } + + // AsyncTask for API call + private class ApiTask extends AsyncTask { + @Override + protected String doInBackground(String... urls) { + try { + URL url = new URL(urls[0]); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(5000); + connection.setReadTimeout(5000); + + int responseCode = connection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + StringBuilder response = new StringBuilder(); + String line; + + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + return response.toString(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(String result) { + if (result != null) { + try { + JSONObject jsonResponse = new JSONObject(result); + if (jsonResponse.getInt("status") == 200) { + JSONArray dataArray = jsonResponse.getJSONArray("data"); + processApiData(dataArray); + } else { + Toast.makeText(SettlementActivity.this, "API Error", Toast.LENGTH_SHORT).show(); + loadSampleData(); + } + } catch (JSONException e) { + e.printStackTrace(); + Toast.makeText(SettlementActivity.this, "JSON Parse Error", Toast.LENGTH_SHORT).show(); + loadSampleData(); + } + } else { + Toast.makeText(SettlementActivity.this, "Network Error", Toast.LENGTH_SHORT).show(); + loadSampleData(); + } + } + } +} + +// SettlementItem class - combined in same file +class SettlementItem { + private String channelName; + private long amount; + private int transactionCount; + private int iconResource; + + public SettlementItem() {} + + public SettlementItem(String channelName, long amount, int transactionCount, int iconResource) { + this.channelName = channelName; + this.amount = amount; + this.transactionCount = transactionCount; + this.iconResource = iconResource; + } + + // Getters and Setters + public String getChannelName() { return channelName; } + public void setChannelName(String channelName) { this.channelName = channelName; } + public long getAmount() { return amount; } + public void setAmount(long amount) { this.amount = amount; } + public int getTransactionCount() { return transactionCount; } + public void setTransactionCount(int transactionCount) { this.transactionCount = transactionCount; } + public int getIconResource() { return iconResource; } + public void setIconResource(int iconResource) { this.iconResource = iconResource; } +} + +// SettlementAdapter class - combined in same file +class SettlementAdapter extends RecyclerView.Adapter { + + private List settlementList; + + public SettlementAdapter(List settlementList) { + this.settlementList = settlementList; + } + + @NonNull + @Override + public SettlementViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_settlement, parent, false); + return new SettlementViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull SettlementViewHolder holder, int position) { + SettlementItem item = settlementList.get(position); + + holder.ivIcon.setImageResource(item.getIconResource()); + holder.tvChannelName.setText(item.getChannelName()); + holder.tvAmount.setText("Rp. " + formatCurrency(item.getAmount())); + holder.tvTransactionCount.setText(item.getTransactionCount() + " Transaksi"); + } + + @Override + public int getItemCount() { + return settlementList.size(); + } + + private String formatCurrency(long amount) { + NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID")); + return formatter.format(amount); + } + + static class SettlementViewHolder extends RecyclerView.ViewHolder { + ImageView ivIcon; + TextView tvChannelName; + TextView tvAmount; + TextView tvTransactionCount; + + public SettlementViewHolder(@NonNull View itemView) { + super(itemView); + ivIcon = itemView.findViewById(R.id.iv_icon); + tvChannelName = itemView.findViewById(R.id.tv_channel_name); + tvAmount = itemView.findViewById(R.id.tv_amount); + tvTransactionCount = itemView.findViewById(R.id.tv_transaction_count); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bdkipoc/TransactionActivity.java b/app/src/main/java/com/example/bdkipoc/TransactionActivity.java index 66678bc..7fde404 100644 --- a/app/src/main/java/com/example/bdkipoc/TransactionActivity.java +++ b/app/src/main/java/com/example/bdkipoc/TransactionActivity.java @@ -10,6 +10,7 @@ import android.widget.EditText; import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.Toast; +import android.content.Intent; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; @@ -30,6 +31,9 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; public class TransactionActivity extends AppCompatActivity implements TransactionAdapter.OnPrintClickListener { private RecyclerView recyclerView; @@ -287,16 +291,33 @@ public class TransactionActivity extends AppCompatActivity implements Transactio @Override public void onPrintClick(Transaction transaction) { - // Handle print button click - Toast.makeText(this, "Cetak Ulang: " + transaction.referenceId, Toast.LENGTH_SHORT).show(); + // Buka ReceiptActivity dengan data transaksi + Intent intent = new Intent(this, ReceiptActivity.class); - // Implement your print logic here - // For example, you might want to: - // 1. Generate receipt - // 2. Send to printer - // 3. Show print preview + // Format data sesuai kebutuhan ReceiptActivity + intent.putExtra("transaction_id", transaction.referenceId); + intent.putExtra("transaction_amount", transaction.amount.replace("Rp. ", "").replace(".", "")); + intent.putExtra("transaction_date", formatDate(transaction.createdAt)); // Format tanggal jika perlu + intent.putExtra("payment_method", "Kartu " + transaction.channelCode); // Contoh: "Kartu BCA" + intent.putExtra("card_type", transaction.channelCategory); + intent.putExtra("merchant_name", transaction.merchantName); + intent.putExtra("merchant_location", "Lokasi Merchant"); // Tambahkan jika ada di data + + startActivity(intent); } + private String formatDate(String rawDate) { + try { + SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); + SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMMM yyyy HH:mm", new Locale("id", "ID")); + Date date = inputFormat.parse(rawDate); + return outputFormat.format(date); + } catch (Exception e) { + return rawDate; // Fallback ke format asli jika parsing gagal + } + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { diff --git a/app/src/main/java/com/example/bdkipoc/TransactionAdapter.java b/app/src/main/java/com/example/bdkipoc/TransactionAdapter.java index 39f93cc..54e2c98 100644 --- a/app/src/main/java/com/example/bdkipoc/TransactionAdapter.java +++ b/app/src/main/java/com/example/bdkipoc/TransactionAdapter.java @@ -52,6 +52,12 @@ public class TransactionAdapter extends RecyclerView.Adapter { + if (printClickListener != null) { + printClickListener.onPrintClick(t); + } + }); + // Set click listener for print button holder.printSection.setOnClickListener(v -> { if (printClickListener != null) { diff --git a/app/src/main/res/layout/activity_settlement.xml b/app/src/main/res/layout/activity_settlement.xml new file mode 100644 index 0000000..6ba7257 --- /dev/null +++ b/app/src/main/res/layout/activity_settlement.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +