Display used and reserved limits capacity
This commit is contained in:
1 parent
ec43d34b4b
commit
2e81c43091
14 files changed
+287
-5
No files matched your search
@@ -36,3 +36,8 @@ Photo selection uses Flutter's [file_selector](https://pub.dev/packages/file_sel
|
||||
and [image metadata decoding](https://pub.dev/documentation/image/latest/image/Decoder-class.html).
|
||||
For native macOS consumers enable the user-selected read-only file entitlement;
|
||||
iOS/Android camera permissions are not required for this file-picker-only flow.
|
||||
|
||||
Visible limit rows also expose `usedMinor` (committed activity) and `reservedMinor`
|
||||
(pending holds). `remainingMinor` is independently provided by the backend and
|
||||
must not be inferred as cap minus those fields. The display-only occupied ratio
|
||||
includes used plus reserved and is bounded for progress rendering.
|
||||
@@ -10,6 +10,8 @@ class VisibleLimit {
|
||||
required this.verifiedMinor,
|
||||
required this.currentMinor,
|
||||
required this.remainingMinor,
|
||||
required this.usedMinor,
|
||||
required this.reservedMinor,
|
||||
});
|
||||
final LimitPeriod period;
|
||||
final String currency;
|
||||
@@ -17,6 +19,13 @@ class VisibleLimit {
|
||||
final int verifiedMinor;
|
||||
final int currentMinor;
|
||||
final int remainingMinor;
|
||||
final int usedMinor;
|
||||
final int reservedMinor;
|
||||
|
||||
/// Presentation only: remaining capacity and payment authorization stay server-owned.
|
||||
double get occupiedFraction => currentMinor <= 0
|
||||
? 0
|
||||
: ((usedMinor + reservedMinor) / currentMinor).clamp(0.0, 1.0);
|
||||
}
|
||||
|
||||
class Limits {
|
||||
|
||||
@@ -76,7 +76,9 @@ class DummyLimitsService implements LimitsService {
|
||||
10000,
|
||||
250000,
|
||||
approved ? 250000 : 10000,
|
||||
approved ? 250000 : 10000,
|
||||
(approved ? 250000 : 10000) - 4000,
|
||||
3000,
|
||||
1000,
|
||||
),
|
||||
LimitDTO(
|
||||
'month',
|
||||
@@ -84,7 +86,9 @@ class DummyLimitsService implements LimitsService {
|
||||
50000,
|
||||
1000000,
|
||||
approved ? 1000000 : 50000,
|
||||
approved ? 1000000 : 50000,
|
||||
(approved ? 1000000 : 50000) - 19000,
|
||||
18000,
|
||||
1000,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -38,10 +38,12 @@ class LimitDTO {
|
||||
this.verified,
|
||||
this.current,
|
||||
this.remaining,
|
||||
this.used,
|
||||
this.reserved,
|
||||
);
|
||||
final String period;
|
||||
final String currency;
|
||||
final int basic, verified, current, remaining;
|
||||
final int basic, verified, current, remaining, used, reserved;
|
||||
}
|
||||
|
||||
class LimitsMapper {
|
||||
@@ -57,6 +59,8 @@ class LimitsMapper {
|
||||
verifiedMinor: r.verified,
|
||||
currentMinor: r.current,
|
||||
remainingMinor: r.remaining,
|
||||
usedMinor: r.used,
|
||||
reservedMinor: r.reserved,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:sxchnge_kyc/sxchnge_kyc.dart';
|
||||
import 'package:sxchnge_kyc/src/transport/contracts.dart';
|
||||
|
||||
void main() {
|
||||
test('mapping preserves backend usage and independent remaining value', () {
|
||||
final data = LimitsMapper.fromDTO(
|
||||
const LimitsDTO(
|
||||
tier: 'basic',
|
||||
simulated: false,
|
||||
rows: [LimitDTO('day', 'EUR', 10000, 250000, 10000, 5500, 3000, 1000)],
|
||||
),
|
||||
);
|
||||
final row = data.rows.single;
|
||||
expect(row.usedMinor, 3000);
|
||||
expect(row.reservedMinor, 1000);
|
||||
expect(row.remainingMinor, 5500);
|
||||
expect(row.occupiedFraction, 0.4);
|
||||
});
|
||||
test('capacity visualization handles unused, exhausted and zero caps', () {
|
||||
VisibleLimit row(int cap, int used, int reserved) => VisibleLimit(
|
||||
period: LimitPeriod.day,
|
||||
currency: 'EUR',
|
||||
basicMinor: cap,
|
||||
verifiedMinor: cap,
|
||||
currentMinor: cap,
|
||||
remainingMinor: 0,
|
||||
usedMinor: used,
|
||||
reservedMinor: reserved,
|
||||
);
|
||||
expect(row(10000, 0, 0).occupiedFraction, 0);
|
||||
expect(row(10000, 8000, 2000).occupiedFraction, 1);
|
||||
expect(row(10000, 12000, 2000).occupiedFraction, 1);
|
||||
expect(row(0, 0, 0).occupiedFraction, 0);
|
||||
});
|
||||
test('stub provides nonzero daily and monthly usage', () async {
|
||||
final identity = DummyIdentityService(delay: Duration.zero);
|
||||
final service = DummyLimitsService(identity);
|
||||
final data = await service.fetch();
|
||||
expect(data.rows.first.usedMinor, 3000);
|
||||
expect(data.rows.first.reservedMinor, 1000);
|
||||
expect(data.rows.first.remainingMinor, 6000);
|
||||
expect(data.rows.last.usedMinor, 18000);
|
||||
expect(data.rows.last.remainingMinor, 31000);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user