From 41f653775f4159afde5c31d8778331376af6dd4d Mon Sep 17 00:00:00 2001 From: Stephan D Date: Fri, 23 Jan 2026 02:48:10 +0100 Subject: [PATCH] fixed ledger account listing + quotation listing --- api/billing/fees/go.mod | 2 +- api/billing/fees/go.sum | 4 +- api/discovery/go.mod | 2 +- api/discovery/go.sum | 4 +- api/fx/ingestor/go.mod | 2 +- api/fx/ingestor/go.sum | 4 +- api/fx/oracle/go.mod | 2 +- api/fx/oracle/go.sum | 4 +- api/gateway/chain/go.mod | 2 +- api/gateway/chain/go.sum | 4 +- api/gateway/mntx/go.mod | 2 +- api/gateway/mntx/go.sum | 4 +- api/gateway/tgsettle/go.mod | 2 +- api/gateway/tgsettle/go.sum | 4 +- api/ledger/go.mod | 2 +- api/ledger/go.sum | 4 +- api/notification/go.mod | 2 +- api/notification/go.sum | 4 +- api/payments/orchestrator/go.mod | 2 +- api/payments/orchestrator/go.sum | 4 +- .../storage/mongo/store/quotes.go | 2 +- api/pkg/go.mod | 2 +- api/pkg/go.sum | 4 +- api/server/go.mod | 2 +- api/server/go.sum | 4 +- api/server/interface/api/sresponse/ledger.go | 30 +++-- .../balance_mask/ledger_accounts.dart | 46 +++++++ .../lib/controllers/balance_mask/wallets.dart | 106 +++++++++++++++ frontend/pshared/lib/controllers/wallets.dart | 124 ------------------ .../pshared/lib/data/dto/ledger/account.dart | 6 +- .../pshared/lib/data/dto/ledger/status.dart | 31 +++++ .../pshared/lib/data/dto/ledger/type.dart | 39 ++++++ .../lib/data/mapper/ledger/account.dart | 3 +- frontend/pshared/lib/provider/ledger.dart | 2 +- .../payment/quotation/intent_builder.dart | 61 ++++++--- .../provider/payment/quotation/quotation.dart | 5 +- .../pweb/lib/app/router/payout_shell.dart | 6 +- frontend/pweb/lib/l10n/en.arb | 8 ++ frontend/pweb/lib/l10n/ru.arb | 8 ++ frontend/pweb/lib/main.dart | 7 +- .../buttons/balance/add/constants.dart | 1 - .../dashboard/buttons/balance/add/dialog.dart | 75 +++++------ .../dashboard/buttons/balance/add/form.dart | 4 +- .../dashboard/buttons/balance/add/owner.dart | 10 +- .../dashboard/buttons/balance/amount.dart | 18 +-- .../dashboard/buttons/balance/balance.dart | 2 +- .../pages/dashboard/buttons/balance/card.dart | 6 +- .../dashboard/buttons/balance/ledger.dart | 50 ++++++- .../payouts/quote_status/quote_status.dart | 2 +- .../dashboard/payouts/summary/widget.dart | 2 +- .../pweb/lib/pages/payment_methods/page.dart | 2 +- .../payment_methods/payment_page/content.dart | 2 +- .../payment_page/method_selector.dart | 2 +- .../lib/pages/payout_page/wallet/card.dart | 6 +- .../payout_page/wallet/edit/buttons/send.dart | 2 +- .../wallet/edit/buttons/top_up.dart | 2 +- .../pages/payout_page/wallet/edit/fields.dart | 4 +- .../pages/payout_page/wallet/edit/header.dart | 2 +- .../pages/payout_page/wallet/edit/page.dart | 2 +- .../pweb/lib/pages/wallet_top_up/page.dart | 2 +- 60 files changed, 469 insertions(+), 283 deletions(-) create mode 100644 frontend/pshared/lib/controllers/balance_mask/ledger_accounts.dart create mode 100644 frontend/pshared/lib/controllers/balance_mask/wallets.dart delete mode 100644 frontend/pshared/lib/controllers/wallets.dart diff --git a/api/billing/fees/go.mod b/api/billing/fees/go.mod index f3a3ddc1..93a8bb33 100644 --- a/api/billing/fees/go.mod +++ b/api/billing/fees/go.mod @@ -49,6 +49,6 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect google.golang.org/protobuf v1.36.11 ) diff --git a/api/billing/fees/go.sum b/api/billing/fees/go.sum index ba370437..32bb0530 100644 --- a/api/billing/fees/go.sum +++ b/api/billing/fees/go.sum @@ -212,8 +212,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/discovery/go.mod b/api/discovery/go.mod index eb34c035..46c2836e 100644 --- a/api/discovery/go.mod +++ b/api/discovery/go.mod @@ -45,7 +45,7 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect google.golang.org/grpc v1.78.0 // indirect google.golang.org/protobuf v1.36.11 // indirect ) diff --git a/api/discovery/go.sum b/api/discovery/go.sum index ba370437..32bb0530 100644 --- a/api/discovery/go.sum +++ b/api/discovery/go.sum @@ -212,8 +212,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/fx/ingestor/go.mod b/api/fx/ingestor/go.mod index 2b08ed60..69074627 100644 --- a/api/fx/ingestor/go.mod +++ b/api/fx/ingestor/go.mod @@ -49,7 +49,7 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect google.golang.org/grpc v1.78.0 // indirect google.golang.org/protobuf v1.36.11 // indirect ) diff --git a/api/fx/ingestor/go.sum b/api/fx/ingestor/go.sum index ba370437..32bb0530 100644 --- a/api/fx/ingestor/go.sum +++ b/api/fx/ingestor/go.sum @@ -212,8 +212,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/fx/oracle/go.mod b/api/fx/oracle/go.mod index df303c7d..4b63235f 100644 --- a/api/fx/oracle/go.mod +++ b/api/fx/oracle/go.mod @@ -50,5 +50,5 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect ) diff --git a/api/fx/oracle/go.sum b/api/fx/oracle/go.sum index ba370437..32bb0530 100644 --- a/api/fx/oracle/go.sum +++ b/api/fx/oracle/go.sum @@ -212,8 +212,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/gateway/chain/go.mod b/api/gateway/chain/go.mod index 87379de3..fd50fa5a 100644 --- a/api/gateway/chain/go.mod +++ b/api/gateway/chain/go.mod @@ -86,5 +86,5 @@ require ( golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect golang.org/x/time v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect ) diff --git a/api/gateway/chain/go.sum b/api/gateway/chain/go.sum index fa546651..985ff18b 100644 --- a/api/gateway/chain/go.sum +++ b/api/gateway/chain/go.sum @@ -362,8 +362,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/gateway/mntx/go.mod b/api/gateway/mntx/go.mod index a3ceae91..a2c53136 100644 --- a/api/gateway/mntx/go.mod +++ b/api/gateway/mntx/go.mod @@ -50,5 +50,5 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect ) diff --git a/api/gateway/mntx/go.sum b/api/gateway/mntx/go.sum index a42f4d43..2a614846 100644 --- a/api/gateway/mntx/go.sum +++ b/api/gateway/mntx/go.sum @@ -214,8 +214,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/gateway/tgsettle/go.mod b/api/gateway/tgsettle/go.mod index dfa5dac9..10eb195a 100644 --- a/api/gateway/tgsettle/go.mod +++ b/api/gateway/tgsettle/go.mod @@ -47,5 +47,5 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect ) diff --git a/api/gateway/tgsettle/go.sum b/api/gateway/tgsettle/go.sum index ba370437..32bb0530 100644 --- a/api/gateway/tgsettle/go.sum +++ b/api/gateway/tgsettle/go.sum @@ -212,8 +212,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/ledger/go.mod b/api/ledger/go.mod index ddab3789..621653bd 100644 --- a/api/ledger/go.mod +++ b/api/ledger/go.mod @@ -51,5 +51,5 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect ) diff --git a/api/ledger/go.sum b/api/ledger/go.sum index f796ca0a..369a2e18 100644 --- a/api/ledger/go.sum +++ b/api/ledger/go.sum @@ -214,8 +214,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/notification/go.mod b/api/notification/go.mod index 0a7357c1..528f64c5 100644 --- a/api/notification/go.mod +++ b/api/notification/go.mod @@ -52,7 +52,7 @@ require ( golang.org/x/net v0.49.0 // indirect golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect google.golang.org/grpc v1.78.0 // indirect google.golang.org/protobuf v1.36.11 // indirect ) diff --git a/api/notification/go.sum b/api/notification/go.sum index cac11a22..ef515237 100644 --- a/api/notification/go.sum +++ b/api/notification/go.sum @@ -229,8 +229,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/payments/orchestrator/go.mod b/api/payments/orchestrator/go.mod index 1fee0596..878e1d51 100644 --- a/api/payments/orchestrator/go.mod +++ b/api/payments/orchestrator/go.mod @@ -62,5 +62,5 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect ) diff --git a/api/payments/orchestrator/go.sum b/api/payments/orchestrator/go.sum index c4e4356b..9feb0211 100644 --- a/api/payments/orchestrator/go.sum +++ b/api/payments/orchestrator/go.sum @@ -215,8 +215,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/payments/orchestrator/storage/mongo/store/quotes.go b/api/payments/orchestrator/storage/mongo/store/quotes.go index 1ef97b30..605a50b3 100644 --- a/api/payments/orchestrator/storage/mongo/store/quotes.go +++ b/api/payments/orchestrator/storage/mongo/store/quotes.go @@ -48,7 +48,7 @@ func NewQuotes(logger mlogger.Logger, repo repository.Repository, retention time }, Unique: true, Name: "payment_quotes_org_idempotency_key", - PartialFilter: repository.Query().Comparison(repository.Field("idempotencyKey"), builder.Ne, ""), + PartialFilter: repository.Query().Comparison(repository.Field("idempotencyKey"), builder.Exists, true), }, { Keys: []ri.Key{{Field: "organizationRef", Sort: ri.Asc}}, diff --git a/api/pkg/go.mod b/api/pkg/go.mod index 9eaf1a42..adba63de 100644 --- a/api/pkg/go.mod +++ b/api/pkg/go.mod @@ -93,6 +93,6 @@ require ( golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/api/pkg/go.sum b/api/pkg/go.sum index 2aa3b943..32a8f7bb 100644 --- a/api/pkg/go.sum +++ b/api/pkg/go.sum @@ -269,8 +269,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda h1:+2XxjfsAu6vqFxwGBRcHiMaDCuZiqXGDUDVWVtrFAnE= google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/server/go.mod b/api/server/go.mod index d1169167..90438667 100644 --- a/api/server/go.mod +++ b/api/server/go.mod @@ -139,6 +139,6 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect google.golang.org/grpc v1.78.0 // indirect ) diff --git a/api/server/go.sum b/api/server/go.sum index 95db3ce4..cdf05d36 100644 --- a/api/server/go.sum +++ b/api/server/go.sum @@ -361,8 +361,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda h1:+2XxjfsAu6vqFxwGBRcHiMaDCuZiqXGDUDVWVtrFAnE= google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/api/server/interface/api/sresponse/ledger.go b/api/server/interface/api/sresponse/ledger.go index 028542d1..0a74fc7a 100644 --- a/api/server/interface/api/sresponse/ledger.go +++ b/api/server/interface/api/sresponse/ledger.go @@ -6,23 +6,25 @@ import ( "github.com/tech/sendico/pkg/api/http/response" "github.com/tech/sendico/pkg/mlogger" + "github.com/tech/sendico/pkg/model" moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1" ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1" ) type ledgerAccount struct { - LedgerAccountRef string `json:"ledgerAccountRef"` - OrganizationRef string `json:"organizationRef"` - OwnerRef string `json:"ownerRef,omitempty"` - AccountCode string `json:"accountCode"` - AccountType string `json:"accountType"` - Currency string `json:"currency"` - Status string `json:"status"` - AllowNegative bool `json:"allowNegative"` - IsSettlement bool `json:"isSettlement"` - Metadata map[string]string `json:"metadata,omitempty"` - CreatedAt time.Time `json:"createdAt,omitempty"` - UpdatedAt time.Time `json:"updatedAt,omitempty"` + model.Describable `bson:",inline" json:",inline"` + LedgerAccountRef string `json:"ledgerAccountRef"` + OrganizationRef string `json:"organizationRef"` + OwnerRef string `json:"ownerRef,omitempty"` + AccountCode string `json:"accountCode"` + AccountType string `json:"accountType"` + Currency string `json:"currency"` + Status string `json:"status"` + AllowNegative bool `json:"allowNegative"` + IsSettlement bool `json:"isSettlement"` + Metadata map[string]string `json:"metadata,omitempty"` + CreatedAt time.Time `json:"createdAt,omitempty"` + UpdatedAt time.Time `json:"updatedAt,omitempty"` } type ledgerAccountsResponse struct { @@ -82,6 +84,10 @@ func toLedgerAccount(acc *ledgerv1.LedgerAccount) ledgerAccount { return ledgerAccount{} } return ledgerAccount{ + Describable: model.Describable{ + Name: acc.GetDescribable().GetName(), + Description: acc.GetDescribable().Description, + }, LedgerAccountRef: acc.GetLedgerAccountRef(), OrganizationRef: acc.GetOrganizationRef(), OwnerRef: acc.GetOwnerRef(), diff --git a/frontend/pshared/lib/controllers/balance_mask/ledger_accounts.dart b/frontend/pshared/lib/controllers/balance_mask/ledger_accounts.dart new file mode 100644 index 00000000..73af49fa --- /dev/null +++ b/frontend/pshared/lib/controllers/balance_mask/ledger_accounts.dart @@ -0,0 +1,46 @@ +import 'package:flutter/foundation.dart'; + +import 'package:pshared/provider/ledger.dart'; + + +class LedgerBalanceMaskController with ChangeNotifier { + String? _orgRef; + final Set _maskedBalanceRefs = {}; + Set _knownAccountRefs = {}; + + void update(LedgerAccountsProvider accountsProvider) { + final nextOrgRef = accountsProvider.organizationRef; + final orgChanged = nextOrgRef != _orgRef; + + if (orgChanged) { + _orgRef = nextOrgRef; + _maskedBalanceRefs.clear(); + _knownAccountRefs = {}; + } + + final refs = accountsProvider.accounts.map((a) => a.ledgerAccountRef).toSet(); + _maskedBalanceRefs.removeWhere((id) => !refs.contains(id)); + + final newRefs = refs.difference(_knownAccountRefs); + if (newRefs.isNotEmpty) { + _maskedBalanceRefs.addAll(newRefs); + } + _knownAccountRefs = refs; + + notifyListeners(); + } + + bool isBalanceMasked(String ledgerAccountRef) => _maskedBalanceRefs.contains(ledgerAccountRef); + bool isBalanceVisible(String ledgerAccountRef) => !isBalanceMasked(ledgerAccountRef); + + void toggleBalanceMask(String ledgerAccountRef) { + final existed = _maskedBalanceRefs.remove(ledgerAccountRef); + if (!existed) _maskedBalanceRefs.add(ledgerAccountRef); + notifyListeners(); + } + + void unmaskAllBalances() { + _maskedBalanceRefs.clear(); + notifyListeners(); + } +} diff --git a/frontend/pshared/lib/controllers/balance_mask/wallets.dart b/frontend/pshared/lib/controllers/balance_mask/wallets.dart new file mode 100644 index 00000000..80994dac --- /dev/null +++ b/frontend/pshared/lib/controllers/balance_mask/wallets.dart @@ -0,0 +1,106 @@ +import 'package:flutter/foundation.dart'; + +import 'package:collection/collection.dart'; + +import 'package:pshared/models/payment/wallet.dart'; +import 'package:pshared/provider/payment/wallets.dart'; + + +class WalletsController with ChangeNotifier { + late WalletsProvider _wallets; + + String? _orgRef; + + /// UI-only: wallet refs with masked balances + final Set _maskedBalanceWalletRefs = {}; + Set _knownWalletRefs = {}; + + String? _selectedWalletRef; + + bool get isLoading => _wallets.isLoading; + Exception? get error => _wallets.error; + + void update(WalletsProvider wallets) { + _wallets = wallets; + + final nextOrgRef = wallets.organizationRef; + final orgChanged = nextOrgRef != _orgRef; + + if (orgChanged) { + _orgRef = nextOrgRef; + _maskedBalanceWalletRefs.clear(); + _knownWalletRefs = {}; + _selectedWalletRef = null; + } + + // Remove ids that no longer exist + final ids = wallets.wallets.map((w) => w.id).toSet(); + _maskedBalanceWalletRefs.removeWhere((id) => !ids.contains(id)); + + final newIds = ids.difference(_knownWalletRefs); + if (newIds.isNotEmpty) { + _maskedBalanceWalletRefs.addAll(newIds); + } + _knownWalletRefs = ids; + + _selectedWalletRef = _resolveSelectedId( + currentRef: _selectedWalletRef, + wallets: wallets.wallets, + ); + + notifyListeners(); + } + + List get wallets => _wallets.wallets; + + bool isBalanceMasked(String walletRef) => _maskedBalanceWalletRefs.contains(walletRef); + bool isBalanceVisible(String walletRef) => !isBalanceMasked(walletRef); + + List get unmaskedWallets => + wallets.where((w) => !_maskedBalanceWalletRefs.contains(w.id)).toList(growable: false); + + Wallet? get selectedWallet { + final id = _selectedWalletRef; + if (id == null) return null; + return wallets.firstWhereOrNull((w) => w.id == id); + } + + String? get selectedWalletRef => _selectedWalletRef; + + void selectWallet(Wallet wallet) => selectWalletByRef(wallet.id); + + void selectWalletByRef(String walletRef) { + if (_selectedWalletRef == walletRef) return; + + _selectedWalletRef = walletRef; + notifyListeners(); + } + + /// Toggle wallet balance masking + void toggleBalanceMask(String walletRef) { + final existed = _maskedBalanceWalletRefs.remove(walletRef); + if (!existed) _maskedBalanceWalletRefs.add(walletRef); + notifyListeners(); + } + + /// Unmask balances for all wallets (bulk action) + void unmaskAllBalances() { + _maskedBalanceWalletRefs.clear(); + notifyListeners(); + } + + String? _resolveSelectedId({ + required String? currentRef, + required List wallets, + }) { + if (wallets.isEmpty) return null; + + // Keep current selection if it still exists + if (currentRef != null && wallets.any((w) => w.id == currentRef)) { + return currentRef; + } + + // Fallback to the first wallet + return wallets.first.id; + } +} diff --git a/frontend/pshared/lib/controllers/wallets.dart b/frontend/pshared/lib/controllers/wallets.dart deleted file mode 100644 index 56e3d11a..00000000 --- a/frontend/pshared/lib/controllers/wallets.dart +++ /dev/null @@ -1,124 +0,0 @@ -import 'package:flutter/foundation.dart'; - -import 'package:collection/collection.dart'; - -import 'package:pshared/models/payment/wallet.dart'; -import 'package:pshared/provider/payment/wallets.dart'; - - -class WalletsController with ChangeNotifier { - late WalletsProvider _wallets; - - String? _orgRef; - - /// UI-only: which wallets are allowed to be visible - final Set _visibleWalletRefs = {}; - - String? _selectedWalletRef; - - bool get isLoading => _wallets.isLoading; - Exception? get error => _wallets.error; - - void update(WalletsProvider wallets) { - _wallets = wallets; - - final nextOrgRef = wallets.organizationRef; - final orgChanged = nextOrgRef != _orgRef; - - if (orgChanged) { - _orgRef = nextOrgRef; - _visibleWalletRefs.clear(); // All wallets hidden on org change - _selectedWalletRef = null; - } - - // Remove ids that no longer exist - final ids = wallets.wallets.map((w) => w.id).toSet(); - _visibleWalletRefs.removeWhere((id) => !ids.contains(id)); - - _selectedWalletRef = _resolveSelectedId( - currentRef: _selectedWalletRef, - wallets: wallets.wallets, - visibleRefs: _visibleWalletRefs, - ); - - notifyListeners(); - } - - List get wallets => _wallets.wallets; - - bool isVisible(String walletRef) => _visibleWalletRefs.contains(walletRef); - bool isHidden(String walletRef) => !isVisible(walletRef); - - List get visibleWallets => - wallets.where((w) => _visibleWalletRefs.contains(w.id)).toList(growable: false); - - Wallet? get selectedWallet { - final id = _selectedWalletRef; - if (id == null) return null; - return wallets.firstWhereOrNull((w) => w.id == id); - } - - String? get selectedWalletRef => _selectedWalletRef; - - void selectWallet(Wallet wallet, {bool allowHidden = false}) => - selectWalletByRef(wallet.id, allowHidden: allowHidden); - - void selectWalletByRef(String walletRef, {bool allowHidden = false}) { - if (_selectedWalletRef == walletRef) return; - - // Prevent selecting a hidden wallet - if (!allowHidden && !_visibleWalletRefs.contains(walletRef)) return; - - _selectedWalletRef = walletRef; - notifyListeners(); - } - - /// Toggle wallet visibility - void toggleVisibility(String accountRef) { - final existed = _visibleWalletRefs.remove(accountRef); - if (!existed) _visibleWalletRefs.add(accountRef); - - _selectedWalletRef = _resolveSelectedId( - currentRef: _selectedWalletRef, - wallets: wallets, - visibleRefs: _visibleWalletRefs, - ); - - notifyListeners(); - } - - /// Show all wallets (bulk action) - void showAll() { - final allRefs = wallets.map((w) => w.id); - _visibleWalletRefs - ..clear() - ..addAll(allRefs); - - _selectedWalletRef = _resolveSelectedId( - currentRef: _selectedWalletRef, - wallets: wallets, - visibleRefs: _visibleWalletRefs, - ); - - notifyListeners(); - } - - String? _resolveSelectedId({ - required String? currentRef, - required List wallets, - required Set visibleRefs, - }) { - if (wallets.isEmpty) return null; - - // Keep current selection if it still exists and is visible - if (currentRef != null && - visibleRefs.contains(currentRef) && - wallets.any((w) => w.id == currentRef)) { - return currentRef; - } - - // Select the first visible wallet - final firstVisible = wallets.firstWhereOrNull((w) => visibleRefs.contains(w.id)); - return firstVisible?.id; - } -} diff --git a/frontend/pshared/lib/data/dto/ledger/account.dart b/frontend/pshared/lib/data/dto/ledger/account.dart index eb13d6e7..566f6cd8 100644 --- a/frontend/pshared/lib/data/dto/ledger/account.dart +++ b/frontend/pshared/lib/data/dto/ledger/account.dart @@ -14,8 +14,10 @@ class LedgerAccountDTO { final String organizationRef; final String? ownerRef; final String accountCode; + @JsonKey(fromJson: ledgerAccountTypeFromJson, toJson: ledgerAccountTypeToJson) final LedgerAccountTypeDTO accountType; final String currency; + @JsonKey(fromJson: ledgerAccountStatusFromJson, toJson: ledgerAccountStatusToJson) final LedgerAccountStatusDTO status; final bool allowNegative; final bool isSettlement; @@ -23,7 +25,7 @@ class LedgerAccountDTO { final DateTime? createdAt; final DateTime? updatedAt; - final DescribableDTO describable; + final DescribableDTO? describable; final LedgerBalanceDTO? balance; @@ -40,7 +42,7 @@ class LedgerAccountDTO { this.metadata, this.createdAt, this.updatedAt, - required this.describable, + this.describable, this.balance, }); diff --git a/frontend/pshared/lib/data/dto/ledger/status.dart b/frontend/pshared/lib/data/dto/ledger/status.dart index b12ca7dd..0daa70b8 100644 --- a/frontend/pshared/lib/data/dto/ledger/status.dart +++ b/frontend/pshared/lib/data/dto/ledger/status.dart @@ -11,3 +11,34 @@ enum LedgerAccountStatusDTO { @JsonValue('frozen') frozen, } + +LedgerAccountStatusDTO ledgerAccountStatusFromJson(Object? value) { + final raw = value?.toString() ?? ''; + var normalized = raw.trim().toLowerCase(); + const prefix = 'account_status_'; + if (normalized.startsWith(prefix)) { + normalized = normalized.substring(prefix.length); + } + switch (normalized) { + case 'active': + return LedgerAccountStatusDTO.active; + case 'frozen': + return LedgerAccountStatusDTO.frozen; + case 'unspecified': + case '': + return LedgerAccountStatusDTO.unspecified; + default: + return LedgerAccountStatusDTO.unspecified; + } +} + +String ledgerAccountStatusToJson(LedgerAccountStatusDTO value) { + switch (value) { + case LedgerAccountStatusDTO.active: + return 'active'; + case LedgerAccountStatusDTO.frozen: + return 'frozen'; + case LedgerAccountStatusDTO.unspecified: + return 'unspecified'; + } +} diff --git a/frontend/pshared/lib/data/dto/ledger/type.dart b/frontend/pshared/lib/data/dto/ledger/type.dart index 8da0f2b6..7051cdfc 100644 --- a/frontend/pshared/lib/data/dto/ledger/type.dart +++ b/frontend/pshared/lib/data/dto/ledger/type.dart @@ -17,3 +17,42 @@ enum LedgerAccountTypeDTO { @JsonValue('expense') expense, } + +LedgerAccountTypeDTO ledgerAccountTypeFromJson(Object? value) { + final raw = value?.toString() ?? ''; + var normalized = raw.trim().toLowerCase(); + const prefix = 'account_type_'; + if (normalized.startsWith(prefix)) { + normalized = normalized.substring(prefix.length); + } + switch (normalized) { + case 'asset': + return LedgerAccountTypeDTO.asset; + case 'liability': + return LedgerAccountTypeDTO.liability; + case 'revenue': + return LedgerAccountTypeDTO.revenue; + case 'expense': + return LedgerAccountTypeDTO.expense; + case 'unspecified': + case '': + return LedgerAccountTypeDTO.unspecified; + default: + return LedgerAccountTypeDTO.unspecified; + } +} + +String ledgerAccountTypeToJson(LedgerAccountTypeDTO value) { + switch (value) { + case LedgerAccountTypeDTO.asset: + return 'asset'; + case LedgerAccountTypeDTO.liability: + return 'liability'; + case LedgerAccountTypeDTO.revenue: + return 'revenue'; + case LedgerAccountTypeDTO.expense: + return 'expense'; + case LedgerAccountTypeDTO.unspecified: + return 'unspecified'; + } +} diff --git a/frontend/pshared/lib/data/mapper/ledger/account.dart b/frontend/pshared/lib/data/mapper/ledger/account.dart index 488d98ae..eb6bc2c6 100644 --- a/frontend/pshared/lib/data/mapper/ledger/account.dart +++ b/frontend/pshared/lib/data/mapper/ledger/account.dart @@ -3,6 +3,7 @@ import 'package:pshared/data/mapper/describable.dart'; import 'package:pshared/data/mapper/ledger/balance.dart'; import 'package:pshared/data/mapper/ledger/status.dart'; import 'package:pshared/data/mapper/ledger/type.dart'; +import 'package:pshared/models/describable.dart'; import 'package:pshared/models/ledger/account.dart'; @@ -20,7 +21,7 @@ extension LedgerAccountDTOMapper on LedgerAccountDTO { metadata: metadata, createdAt: createdAt, updatedAt: updatedAt, - describable: describable.toDomain(), + describable: describable?.toDomain() ?? newDescribable(name: '', description: null), balance: balance?.toDomain(), ); } diff --git a/frontend/pshared/lib/provider/ledger.dart b/frontend/pshared/lib/provider/ledger.dart index f70c6d5a..a955f029 100644 --- a/frontend/pshared/lib/provider/ledger.dart +++ b/frontend/pshared/lib/provider/ledger.dart @@ -24,7 +24,7 @@ class LedgerAccountsProvider with ChangeNotifier { Resource> _resource = Resource(data: []); Resource> get resource => _resource; - List get accounts => _resource.data ?? []; + List get accounts => (_resource.data ?? []).whereNot((la)=> la.isSettlement).toList(); bool get isLoading => _resource.isLoading; Exception? get error => _resource.error; diff --git a/frontend/pshared/lib/provider/payment/quotation/intent_builder.dart b/frontend/pshared/lib/provider/payment/quotation/intent_builder.dart index eb4072ff..631b6760 100644 --- a/frontend/pshared/lib/provider/payment/quotation/intent_builder.dart +++ b/frontend/pshared/lib/provider/payment/quotation/intent_builder.dart @@ -1,12 +1,14 @@ -import 'package:collection/collection.dart'; - -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/models/payment/currency_pair.dart'; import 'package:pshared/models/payment/customer.dart'; import 'package:pshared/models/payment/fx/intent.dart'; import 'package:pshared/models/payment/fx/side.dart'; import 'package:pshared/models/payment/kind.dart'; +import 'package:pshared/models/payment/methods/card.dart'; +import 'package:pshared/models/payment/methods/data.dart'; +import 'package:pshared/models/payment/methods/iban.dart'; import 'package:pshared/models/payment/methods/managed_wallet.dart'; +import 'package:pshared/models/payment/methods/russian_bank.dart'; import 'package:pshared/models/payment/methods/type.dart'; import 'package:pshared/models/money.dart'; import 'package:pshared/models/payment/settlement_mode.dart'; @@ -15,7 +17,6 @@ import 'package:pshared/models/recipient/recipient.dart'; import 'package:pshared/provider/payment/amount.dart'; import 'package:pshared/provider/payment/flow.dart'; import 'package:pshared/provider/recipient/provider.dart'; -import 'package:pshared/provider/recipient/pmethods.dart'; import 'package:pshared/utils/currency.dart'; @@ -25,15 +26,16 @@ class QuotationIntentBuilder { required WalletsController wallets, required PaymentFlowProvider flow, required RecipientsProvider recipients, - required PaymentMethodsProvider methods, }) { final selectedWallet = wallets.selectedWallet; - final method = methods.methods.firstWhereOrNull((m) => m.type == flow.selectedType); - if (selectedWallet == null || method == null) return null; + final paymentData = flow.selectedPaymentData; + final selectedMethod = flow.selectedMethod; + if (selectedWallet == null || paymentData == null) return null; final customer = _buildCustomer( recipient: recipients.currentObject, - method: method, + method: selectedMethod, + data: paymentData, ); final amount = Money( amount: payment.amount.toString(), @@ -50,7 +52,7 @@ class QuotationIntentBuilder { return PaymentIntent( kind: PaymentKind.payout, amount: amount, - destination: method.data, + destination: paymentData, source: ManagedWalletPaymentMethod( managedWalletRef: selectedWallet.id, ), @@ -85,11 +87,19 @@ class QuotationIntentBuilder { return amount.currency; } - Customer _buildCustomer({ + Customer? _buildCustomer({ required Recipient? recipient, - required PaymentMethod method, + required PaymentMethod? method, + required PaymentMethodData? data, }) { - final name = _resolveCustomerName(method, recipient); + final id = recipient?.id ?? method?.recipientRef; + if (id == null || id.isEmpty) return null; + + final name = _resolveCustomerName( + method: method, + data: data, + recipient: recipient, + ); final parts = name == null || name.trim().isEmpty ? const [] : name.trim().split(RegExp(r'\s+')); @@ -99,26 +109,31 @@ class QuotationIntentBuilder { parts.length > 2 ? parts.sublist(1, parts.length - 1).join(' ') : null; return Customer( - id: recipient?.id ?? method.recipientRef, + id: id, firstName: firstName, middleName: middleName, lastName: lastName, - country: method.cardData?.country, + country: _resolveCustomerCountry(method: method, data: data), ); } - String? _resolveCustomerName(PaymentMethod method, Recipient? recipient) { - final card = method.cardData; + String? _resolveCustomerName({ + required PaymentMethod? method, + required PaymentMethodData? data, + required Recipient? recipient, + }) { + final card = method?.cardData ?? (data is CardPaymentMethod ? data : null); if (card != null) { - return '${card.firstName} ${card.lastName}'.trim(); + final fullName = '${card.firstName} ${card.lastName}'.trim(); + if (fullName.isNotEmpty) return fullName; } - final iban = method.ibanData; + final iban = method?.ibanData ?? (data is IbanPaymentMethod ? data : null); if (iban != null && iban.accountHolder.trim().isNotEmpty) { return iban.accountHolder.trim(); } - final bank = method.bankAccountData; + final bank = method?.bankAccountData ?? (data is RussianBankAccountPaymentMethod ? data : null); if (bank != null && bank.recipientName.trim().isNotEmpty) { return bank.recipientName.trim(); } @@ -126,4 +141,12 @@ class QuotationIntentBuilder { final recipientName = recipient?.name.trim(); return recipientName?.isNotEmpty == true ? recipientName : null; } + + String? _resolveCustomerCountry({ + required PaymentMethod? method, + required PaymentMethodData? data, + }) { + final card = method?.cardData ?? (data is CardPaymentMethod ? data : null); + return card?.country; + } } diff --git a/frontend/pshared/lib/provider/payment/quotation/quotation.dart b/frontend/pshared/lib/provider/payment/quotation/quotation.dart index 3a275b38..d2a72e27 100644 --- a/frontend/pshared/lib/provider/payment/quotation/quotation.dart +++ b/frontend/pshared/lib/provider/payment/quotation/quotation.dart @@ -7,7 +7,7 @@ import 'package:logging/logging.dart'; import 'package:uuid/uuid.dart'; import 'package:pshared/api/requests/payment/quote.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/data/mapper/payment/intent/payment.dart'; import 'package:pshared/models/asset.dart'; import 'package:pshared/models/payment/intent.dart'; @@ -38,7 +38,7 @@ class QuotationProvider extends ChangeNotifier { WalletsController wallets, PaymentFlowProvider flow, RecipientsProvider recipients, - PaymentMethodsProvider methods, + PaymentMethodsProvider _methods, ) { _organizations = venue; final intent = _intentBuilder.build( @@ -46,7 +46,6 @@ class QuotationProvider extends ChangeNotifier { wallets: wallets, flow: flow, recipients: recipients, - methods: methods, ); if (intent == null) return; final intentKey = _buildIntentKey(intent); diff --git a/frontend/pweb/lib/app/router/payout_shell.dart b/frontend/pweb/lib/app/router/payout_shell.dart index a40abd6d..1eced15c 100644 --- a/frontend/pweb/lib/app/router/payout_shell.dart +++ b/frontend/pweb/lib/app/router/payout_shell.dart @@ -4,7 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/models/payment/type.dart'; import 'package:pshared/models/recipient/recipient.dart'; import 'package:pshared/provider/organizations.dart'; @@ -279,7 +279,7 @@ void _openWalletEdit( Wallet wallet, { required PayoutDestination returnTo, }) { - context.read().selectWallet(wallet, allowHidden: true); + context.read().selectWallet(wallet); context.pushToEditWallet(returnTo: returnTo); } @@ -288,7 +288,7 @@ void _openWalletTopUp( Wallet wallet, { required PayoutDestination returnTo, }) { - context.read().selectWallet(wallet, allowHidden: true); + context.read().selectWallet(wallet); context.pushToWalletTopUp(returnTo: returnTo); } diff --git a/frontend/pweb/lib/l10n/en.arb b/frontend/pweb/lib/l10n/en.arb index 0275b3db..3f58ce6d 100644 --- a/frontend/pweb/lib/l10n/en.arb +++ b/frontend/pweb/lib/l10n/en.arb @@ -116,6 +116,14 @@ "@colDataOwner": { "description": "Column header for who manages the payout data" }, + "assetOwner": "Owner", + "@assetOwner": { + "description": "Label for selecting the owner of a wallet or ledger account" + }, + "organizationOwned": "Organization-owned", + "@organizationOwned": { + "description": "Option label for assets owned by the organization" + }, "colAvatar": "Avatar", "@colAvatar": { diff --git a/frontend/pweb/lib/l10n/ru.arb b/frontend/pweb/lib/l10n/ru.arb index e34181b3..829cb907 100644 --- a/frontend/pweb/lib/l10n/ru.arb +++ b/frontend/pweb/lib/l10n/ru.arb @@ -116,6 +116,14 @@ "@colDataOwner": { "description": "Заголовок столбца для указания, кто управляет данными о выплатах" }, + "assetOwner": "Владелец", + "@assetOwner": { + "description": "Метка выбора владельца кошелька или счета" + }, + "organizationOwned": "Организация", + "@organizationOwned": { + "description": "Опция для активов, принадлежащих организации" + }, "colAvatar": "Аватар", "@colAvatar": { diff --git a/frontend/pweb/lib/main.dart b/frontend/pweb/lib/main.dart index e3867b89..ae9e0278 100644 --- a/frontend/pweb/lib/main.dart +++ b/frontend/pweb/lib/main.dart @@ -8,7 +8,8 @@ import 'package:provider/provider.dart'; import 'package:logging/logging.dart'; import 'package:pshared/config/constants.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/ledger_accounts.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/provider/locale.dart'; import 'package:pshared/provider/permissions.dart'; import 'package:pshared/provider/account.dart'; @@ -102,6 +103,10 @@ void main() async { create: (_) => LedgerAccountsProvider(LedgerService()), update: (context, organizations, provider) => provider!..update(organizations), ), + ChangeNotifierProxyProvider( + create: (_) => LedgerBalanceMaskController(), + update: (context, ledger, controller) => controller!..update(ledger), + ), ChangeNotifierProxyProvider( create: (_) => WalletsController(), update: (_, wallets, controller) => controller!..update(wallets), diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/add/constants.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/add/constants.dart index e7927fe4..6be2eb2e 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/add/constants.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/add/constants.dart @@ -2,7 +2,6 @@ import 'package:pshared/models/currency.dart'; import 'package:pshared/models/payment/chain_network.dart'; -const String orgOwnerRef = ''; const Currency managedCurrencyDefault = Currency.usdt; const Currency ledgerCurrencyDefault = Currency.rub; const ChainNetwork managedNetworkDefault = ChainNetwork.tronMainnet; diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/add/dialog.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/add/dialog.dart index a7c4ce62..ee1a6960 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/add/dialog.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/add/dialog.dart @@ -11,7 +11,6 @@ import 'package:pshared/models/payment/type.dart'; import 'package:pshared/models/wallet/chain_asset.dart'; import 'package:pshared/provider/accounts/employees.dart'; import 'package:pshared/provider/ledger.dart'; -import 'package:pshared/provider/organizations.dart'; import 'package:pshared/provider/payment/wallets.dart'; import 'package:pshared/utils/currency.dart'; @@ -42,7 +41,7 @@ class _AddBalanceDialogState extends State { final _descriptionController = TextEditingController(); PaymentType _assetType = PaymentType.managedWallet; - String _ownerRef = orgOwnerRef; + String? _ownerRef; Currency _managedCurrency = managedCurrencyDefault; ChainNetwork _network = managedNetworkDefault; Currency _ledgerCurrency = ledgerCurrencyDefault; @@ -59,10 +58,7 @@ class _AddBalanceDialogState extends State { setState(() => _assetType = value); } - void _setOwnerRef(String? value) { - if (value == null) return; - setState(() => _ownerRef = value); - } + void _setOwnerRef(String? value) => setState(() => _ownerRef = value); void _setManagedCurrency(Currency? value) { if (value == null) return; @@ -87,13 +83,17 @@ class _AddBalanceDialogState extends State { final name = _nameController.text.trim(); final description = _descriptionController.text.trim(); final employees = context.read().employees; - final effectiveOwnerRef = employees.any((employee) => employee.id == _ownerRef) ? _ownerRef : orgOwnerRef; - final isOrgWallet = effectiveOwnerRef == orgOwnerRef; - final owner = isOrgWallet ? null : employees.firstWhereOrNull((employee) => employee.id == effectiveOwnerRef); + final effectiveOwnerRef = employees.any((employee) => employee.id == _ownerRef) + ? _ownerRef + : null; + final isOrgWallet = effectiveOwnerRef == null; + final owner = isOrgWallet + ? null + : employees.firstWhereOrNull((employee) => employee.id == effectiveOwnerRef); final errorMessage = _assetType == PaymentType.managedWallet - ? l10n.errorCreateManagedWallet - : l10n.errorCreateLedgerAccount; + ? l10n.errorCreateManagedWallet + : l10n.errorCreateLedgerAccount; final result = await executeActionWithNotification( context: context, @@ -124,18 +124,18 @@ class _AddBalanceDialogState extends State { @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; - final orgName = context.select( - (provider) => provider.isOrganizationSet ? provider.current.name : null, - ); + final screenWidth = MediaQuery.of(context).size.width; + final maxWidth = (screenWidth - 48).clamp(0.0, double.infinity); + final dialogWidth = maxWidth >= 360.0 ? (maxWidth > 520.0 ? 520.0 : maxWidth) : maxWidth; final employeesProvider = context.watch(); final employees = employeesProvider.employees; final isSaving = context.watch().isLoading || context.watch().isLoading; - final ownerItems = >[ + final ownerItems = >[ DropdownMenuItem( - value: orgOwnerRef, - child: Text(orgName ?? l10n.companyName), + value: null, + child: Text(l10n.organizationOwned), ), ...employees.map((employee) => DropdownMenuItem( value: employee.id, @@ -143,29 +143,30 @@ class _AddBalanceDialogState extends State { )), ]; - final resolvedOwnerRef = ownerItems.any((item) => item.value == _ownerRef) - ? _ownerRef - : orgOwnerRef; + final resolvedOwnerRef = ownerItems.any((item) => item.value == _ownerRef) ? _ownerRef : null; return AlertDialog( title: Text(l10n.actionAddNew), - content: AddBalanceForm( - formKey: _formKey, - assetType: _assetType, - isSaving: isSaving, - ownerItems: ownerItems, - ownerValue: resolvedOwnerRef, - onAssetTypeChanged: _setAssetType, - onOwnerChanged: _setOwnerRef, - nameController: _nameController, - descriptionController: _descriptionController, - managedCurrency: _managedCurrency, - network: _network, - ledgerCurrency: _ledgerCurrency, - onManagedCurrencyChanged: _setManagedCurrency, - onNetworkChanged: _setNetwork, - onLedgerCurrencyChanged: _setLedgerCurrency, - showEmployeesLoading: employeesProvider.isLoading, + content: SizedBox( + width: dialogWidth, + child: AddBalanceForm( + formKey: _formKey, + assetType: _assetType, + isSaving: isSaving, + ownerItems: ownerItems, + ownerValue: resolvedOwnerRef, + onAssetTypeChanged: _setAssetType, + onOwnerChanged: _setOwnerRef, + nameController: _nameController, + descriptionController: _descriptionController, + managedCurrency: _managedCurrency, + network: _network, + ledgerCurrency: _ledgerCurrency, + onManagedCurrencyChanged: _setManagedCurrency, + onNetworkChanged: _setNetwork, + onLedgerCurrencyChanged: _setLedgerCurrency, + showEmployeesLoading: employeesProvider.isLoading, + ), ), actions: [ DialogCancelButton( diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/add/form.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/add/form.dart index c8ce9b85..7b67dda2 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/add/form.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/add/form.dart @@ -17,8 +17,8 @@ class AddBalanceForm extends StatelessWidget { final GlobalKey formKey; final PaymentType assetType; final bool isSaving; - final List> ownerItems; - final String ownerValue; + final List> ownerItems; + final String? ownerValue; final ValueChanged onAssetTypeChanged; final ValueChanged onOwnerChanged; final TextEditingController nameController; diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/add/owner.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/add/owner.dart index e370a55b..e3523e05 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/add/owner.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/add/owner.dart @@ -6,8 +6,8 @@ import 'package:pweb/generated/i18n/app_localizations.dart'; class OwnerField extends StatelessWidget { - final String value; - final List> items; + final String? value; + final List> items; final ValueChanged? onChanged; const OwnerField({ @@ -18,9 +18,9 @@ class OwnerField extends StatelessWidget { }); @override - Widget build(BuildContext context) => DropdownButtonFormField( - initialValue: value, - decoration: getInputDecoration(context, AppLocalizations.of(context)!.colDataOwner, true), + Widget build(BuildContext context) => DropdownButtonFormField( + value: value, + decoration: getInputDecoration(context, AppLocalizations.of(context)!.assetOwner, true), items: items, onChanged: onChanged, ); diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/amount.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/amount.dart index 2d2af3de..3871379d 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/amount.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/amount.dart @@ -2,19 +2,19 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/models/payment/wallet.dart'; import 'package:pshared/utils/currency.dart'; class BalanceAmount extends StatelessWidget { final Wallet wallet; - final VoidCallback onToggleVisibility; + final VoidCallback onToggleMask; const BalanceAmount({ super.key, required this.wallet, - required this.onToggleVisibility, + required this.onToggleMask, }); static const double _iconSpacing = 12.0; @@ -25,13 +25,13 @@ class BalanceAmount extends StatelessWidget { final textTheme = Theme.of(context).textTheme; final colorScheme = Theme.of(context).colorScheme; final currencyBalance = currencyCodeToSymbol(wallet.currency); - final wallets = context.read(); + final wallets = context.watch(); + final isMasked = wallets.isBalanceMasked(wallet.id); return Row( children: [ Text( - - wallets.isHidden(wallet.id) ? '•••• $currencyBalance' : '${amountToString(wallet.balance)} $currencyBalance', + isMasked ? '•••• $currencyBalance' : '${amountToString(wallet.balance)} $currencyBalance', style: textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: colorScheme.onSurface, @@ -39,9 +39,9 @@ class BalanceAmount extends StatelessWidget { ), const SizedBox(width: _iconSpacing), GestureDetector( - onTap: onToggleVisibility, + onTap: onToggleMask, child: Icon( - wallets.isHidden(wallet.id) ? Icons.visibility_off : Icons.visibility, + isMasked ? Icons.visibility_off : Icons.visibility, size: _iconSize, color: colorScheme.onSurface, ), @@ -49,4 +49,4 @@ class BalanceAmount extends StatelessWidget { ], ); } -} \ No newline at end of file +} diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/balance.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/balance.dart index 0b303c16..eb88511d 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/balance.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/balance.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/provider/ledger.dart'; import 'package:pshared/models/payment/wallet.dart'; diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart index fc255063..b8cb4a25 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/models/payment/wallet.dart'; import 'package:pshared/models/payment/chain_network.dart'; import 'package:pshared/utils/l10n/chain.dart'; @@ -56,8 +56,8 @@ class WalletCard extends StatelessWidget { children: [ BalanceAmount( wallet: wallet, - onToggleVisibility: () { - context.read().toggleVisibility(wallet.id); + onToggleMask: () { + context.read().toggleBalanceMask(wallet.id); }, ), WalletBalanceRefreshButton( diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/ledger.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/ledger.dart index b4defe51..980d2b3c 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/ledger.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/ledger.dart @@ -1,13 +1,17 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'package:pshared/controllers/balance_mask/ledger_accounts.dart'; import 'package:pshared/models/ledger/account.dart'; import 'package:pshared/utils/currency.dart'; -import 'package:pweb/generated/i18n/app_localizations.dart'; import 'package:pweb/pages/dashboard/buttons/balance/config.dart'; import 'package:pweb/pages/dashboard/buttons/balance/header.dart'; import 'package:pweb/widgets/refresh_balance/ledger.dart'; +import 'package:pweb/generated/i18n/app_localizations.dart'; + class LedgerAccountCard extends StatelessWidget { final LedgerAccount account; @@ -38,6 +42,20 @@ class LedgerAccountCard extends StatelessWidget { } } + String _formatMaskedBalance() { + final currency = account.currency.trim(); + if (currency.isEmpty) return '••••'; + try { + final symbol = currencyCodeToSymbol(currencyStringToCode(currency)); + if (symbol.trim().isEmpty) { + return '•••• $currency'; + } + return '•••• $symbol'; + } catch (_) { + return '•••• $currency'; + } + } + @override Widget build(BuildContext context) { final textTheme = Theme.of(context).textTheme; @@ -64,12 +82,30 @@ class LedgerAccountCard extends StatelessWidget { ), Row( children: [ - Text( - _formatBalance(), - style: textTheme.headlineSmall?.copyWith( - fontWeight: FontWeight.bold, - color: colorScheme.onSurface, - ), + Consumer( + builder: (context, controller, _) { + final isMasked = controller.isBalanceMasked(account.ledgerAccountRef); + return Row( + children: [ + Text( + isMasked ? _formatMaskedBalance() : _formatBalance(), + style: textTheme.headlineSmall?.copyWith( + fontWeight: FontWeight.bold, + color: colorScheme.onSurface, + ), + ), + const SizedBox(width: 12), + GestureDetector( + onTap: () => controller.toggleBalanceMask(account.ledgerAccountRef), + child: Icon( + isMasked ? Icons.visibility_off : Icons.visibility, + size: 24, + color: colorScheme.onSurface, + ), + ), + ], + ); + }, ), const SizedBox(width: 12), LedgerBalanceRefreshButton( diff --git a/frontend/pweb/lib/pages/dashboard/payouts/quote_status/quote_status.dart b/frontend/pweb/lib/pages/dashboard/payouts/quote_status/quote_status.dart index 1eccad99..328952bf 100644 --- a/frontend/pweb/lib/pages/dashboard/payouts/quote_status/quote_status.dart +++ b/frontend/pweb/lib/pages/dashboard/payouts/quote_status/quote_status.dart @@ -3,9 +3,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:pshared/models/payment/quote/status_type.dart'; -import 'package:pweb/providers/quotation/quotation.dart'; import 'package:pweb/pages/dashboard/payouts/quote_status/widgets/body.dart'; +import 'package:pweb/providers/quotation/quotation.dart'; import 'package:pweb/utils/quote_duration_format.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; diff --git a/frontend/pweb/lib/pages/dashboard/payouts/summary/widget.dart b/frontend/pweb/lib/pages/dashboard/payouts/summary/widget.dart index 34dd2287..a0dc5257 100644 --- a/frontend/pweb/lib/pages/dashboard/payouts/summary/widget.dart +++ b/frontend/pweb/lib/pages/dashboard/payouts/summary/widget.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/utils/currency.dart'; import 'package:pweb/pages/dashboard/payouts/summary/fee.dart'; diff --git a/frontend/pweb/lib/pages/payment_methods/page.dart b/frontend/pweb/lib/pages/payment_methods/page.dart index 62facda0..2cfd9729 100644 --- a/frontend/pweb/lib/pages/payment_methods/page.dart +++ b/frontend/pweb/lib/pages/payment_methods/page.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/models/payment/type.dart'; import 'package:pshared/models/recipient/recipient.dart'; import 'package:pshared/provider/payment/flow.dart'; diff --git a/frontend/pweb/lib/pages/payment_methods/payment_page/content.dart b/frontend/pweb/lib/pages/payment_methods/payment_page/content.dart index 195627ad..1932138d 100644 --- a/frontend/pweb/lib/pages/payment_methods/payment_page/content.dart +++ b/frontend/pweb/lib/pages/payment_methods/payment_page/content.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/models/payment/wallet.dart'; import 'package:pshared/models/recipient/recipient.dart'; import 'package:pshared/provider/recipient/provider.dart'; diff --git a/frontend/pweb/lib/pages/payment_methods/payment_page/method_selector.dart b/frontend/pweb/lib/pages/payment_methods/payment_page/method_selector.dart index 6686dc1f..3d6fdc08 100644 --- a/frontend/pweb/lib/pages/payment_methods/payment_page/method_selector.dart +++ b/frontend/pweb/lib/pages/payment_methods/payment_page/method_selector.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/models/payment/wallet.dart'; import 'package:pweb/utils/payment/dropdown.dart'; diff --git a/frontend/pweb/lib/pages/payout_page/wallet/card.dart b/frontend/pweb/lib/pages/payout_page/wallet/card.dart index 8ea9e08f..4c69ae19 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/card.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/card.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/utils/currency.dart'; import 'package:pshared/models/payment/wallet.dart'; @@ -50,8 +50,8 @@ class WalletCard extends StatelessWidget { children: [ BalanceAmount( wallet: wallet, - onToggleVisibility: () { - context.read().toggleVisibility(wallet.id); + onToggleMask: () { + context.read().toggleBalanceMask(wallet.id); }, ), WalletBalanceRefreshButton( diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/send.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/send.dart index 223238a0..29d64956 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/send.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/send.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pshared/models/payment/type.dart'; import 'package:pweb/app/router/payout_routes.dart'; diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/top_up.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/top_up.dart index ef377052..f7573dad 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/top_up.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/top_up.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pweb/app/router/payout_routes.dart'; import 'package:pweb/widgets/sidebar/destinations.dart'; diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/fields.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/fields.dart index 31770b04..530ad26e 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/fields.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/fields.dart @@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pweb/pages/dashboard/buttons/balance/amount.dart'; import 'package:pweb/widgets/refresh_balance/wallet.dart'; @@ -30,7 +30,7 @@ class WalletEditFields extends StatelessWidget { Expanded( child: BalanceAmount( wallet: wallet, - onToggleVisibility: () => controller.toggleVisibility(wallet.id), + onToggleMask: () => controller.toggleBalanceMask(wallet.id), ), ), WalletBalanceRefreshButton(walletRef: wallet.id), diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart index 61175599..a725efad 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/page.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/page.dart index 0a778a6f..949202d5 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/page.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/page.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pweb/pages/payout_page/wallet/edit/buttons/buttons.dart'; import 'package:pweb/pages/payout_page/wallet/edit/fields.dart'; diff --git a/frontend/pweb/lib/pages/wallet_top_up/page.dart b/frontend/pweb/lib/pages/wallet_top_up/page.dart index 6e0e30c3..934cf716 100644 --- a/frontend/pweb/lib/pages/wallet_top_up/page.dart +++ b/frontend/pweb/lib/pages/wallet_top_up/page.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/controllers/wallets.dart'; +import 'package:pshared/controllers/balance_mask/wallets.dart'; import 'package:pweb/pages/wallet_top_up/content.dart';