如何在Android Studio中对Firebase实时数据库两节点做算术运算
Firebase实时数据库金额更新:应付款扣除已付款实现
需求说明
Firebase实时数据库包含Customers和Transaction两个节点,Transaction以Customer节点中的**车牌号(vehicleNumber)**作为节点键进行关联。需要实现逻辑:将指定客户的应付款金额减去对应交易记录中的已付款金额,并更新回数据库。
数据库节点结构
Customers节点数据
"Customers": { "-NFFTcWFGLXi063jCTcT": { "branch": "Rajeev Nagar", "currentDownPayment": "80000", "currentdueAmount": "20000.0", "customerAadharNumber": "123456", "customerAddress": "ANYWHERE", "customerName": "VIKASH", "customerPhoneNumber": "7481900892", "customerTenure": "12", "dateOfdelevry": "28/10/2022", "downPayment": "100000", "duePayment": "100000.0", "emiPerMonth": "8333", "emiStartDate": "26/10/2022", "granterName": "RATHI", "granterPhoneNumber": "7481900896", "localitymodal": "NEAR ME", "motorNumber": "QWERT", "outStandingAmount": "120000.0", "vehicleAmount": "200000", "vehicleBodyType": "Steel", "vehicleColour": "Gray", "vehicleNumber": "1234567890QWERTYU" } }
Transaction节点数据
"Transaction": { "1234567890QWERTYU": { "-NFFZLr7-9sTrZ1OlbjF": { "dateOfPayment": "27/10/2022", "discountGiven": "00", "discountRemarks": "8000", "lateFine": "no discount ", "paymentReceived": "500" } } }
现有代码片段
databasePaymentUpdate = FirebaseDatabase.getInstance().getReference("Customers"); databasePaymentUpdate.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()) { for (DataSnapshot ds : snapshot.getChildren()) { String VehicleNumber = ds.child("vehicleNumber").getValue(String.class); String vehNo = PaymentUpdateVehicleNumber.getText().toString().trim(); if (VehicleNumber.equals(vehNo)) { Toast.makeText(PaymentUpdate.this, "Welcome to Jyoti Motors", Toast.LENGTH_SHORT).show(); } } } } @Override public void onCancelled(@NonNull DatabaseError error) { // 处理数据库读取失败情况 Toast.makeText(PaymentUpdate.this, "数据库读取失败:" + error.getMessage(), Toast.LENGTH_SHORT).show(); } });
完整实现方案
在现有代码基础上,补充金额计算与更新逻辑:
databasePaymentUpdate = FirebaseDatabase.getInstance().getReference("Customers"); DatabaseReference transactionRef = FirebaseDatabase.getInstance().getReference("Transaction"); databasePaymentUpdate.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()) { String vehNo = PaymentUpdateVehicleNumber.getText().toString().trim(); for (DataSnapshot ds : snapshot.getChildren()) { String vehicleNumber = ds.child("vehicleNumber").getValue(String.class); if (vehicleNumber != null && vehicleNumber.equals(vehNo)) { // 1. 获取客户当前应付款金额(这里以currentdueAmount为例,可按需替换为duePayment或outStandingAmount) String currentDueStr = ds.child("currentdueAmount").getValue(String.class); if (currentDueStr == null) { Toast.makeText(PaymentUpdate.this, "未找到应付款数据", Toast.LENGTH_SHORT).show(); return; } double currentDue; try { currentDue = Double.parseDouble(currentDueStr); } catch (NumberFormatException e) { Toast.makeText(PaymentUpdate.this, "应付款格式错误", Toast.LENGTH_SHORT).show(); return; } // 2. 读取该车牌号对应的所有交易记录,累加已付款金额 transactionRef.child(vehNo).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot transactionSnapshot) { double totalPaid = 0.0; for (DataSnapshot transactionDs : transactionSnapshot.getChildren()) { String paymentReceivedStr = transactionDs.child("paymentReceived").getValue(String.class); if (paymentReceivedStr != null) { try { totalPaid += Double.parseDouble(paymentReceivedStr); } catch (NumberFormatException e) { // 跳过格式错误的交易记录 continue; } } } // 3. 计算更新后的应付款金额 double updatedDue = currentDue - totalPaid; // 4. 更新回Customer节点的对应字段 ds.getRef().child("currentdueAmount").setValue(String.valueOf(updatedDue)) .addOnSuccessListener(aVoid -> { Toast.makeText(PaymentUpdate.this, "金额更新成功", Toast.LENGTH_SHORT).show(); }) .addOnFailureListener(e -> { Toast.makeText(PaymentUpdate.this, "金额更新失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); }); } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(PaymentUpdate.this, "交易记录读取失败:" + error.getMessage(), Toast.LENGTH_SHORT).show(); } }); break; // 找到目标客户后跳出循环 } } } else { Toast.makeText(PaymentUpdate.this, "未找到客户数据", Toast.LENGTH_SHORT).show(); } } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(PaymentUpdate.this, "客户数据读取失败:" + error.getMessage(), Toast.LENGTH_SHORT).show(); } });
注意事项
- 数据类型安全:数据库中金额以字符串存储,需添加异常捕获处理格式转换错误,避免崩溃。
- 并发更新防护:如果存在多端同时修改同一客户金额的场景,建议使用Firebase事务更新(
runTransaction)替代直接setValue,防止数据不一致。 - 权限配置:确保Firebase数据库规则允许对
Customers和Transaction节点进行读写操作。
内容的提问来源于stack exchange,提问作者Vivek Kumar pandey
相关产品推荐
相关产品推荐

