@@ -16,6 +16,7 @@ import (
1616 "github.com/google/uuid"
1717 commonpb "github.com/meridianhub/meridian/api/proto/meridian/common/v1"
1818 pb "github.com/meridianhub/meridian/api/proto/meridian/current_account/v1"
19+ quantityv1 "github.com/meridianhub/meridian/api/proto/meridian/quantity/v1"
1920 "github.com/meridianhub/meridian/services/current-account/adapters/persistence"
2021 "github.com/meridianhub/meridian/services/current-account/domain"
2122 "github.com/meridianhub/meridian/services/reference-data/cache"
@@ -658,6 +659,229 @@ func TestExecuteDepositCurrencyMismatch(t *testing.T) {
658659 }
659660}
660661
662+ func TestExecuteDeposit_InstrumentAmountInput_KWH (t * testing.T ) {
663+ db , ctx , cleanup := setupTestDB (t )
664+ defer cleanup ()
665+
666+ repo := persistence .NewRepository (db )
667+ // Mock PK returns 1500 minor units (1500 KWH with precision 0)
668+ svc := mustNewServiceWithPositionKeeping (t , repo , nil , map [string ]int64 {
669+ "ACC-KWH-001" : 1500 ,
670+ })
671+
672+ // Create KWH energy account (precision 0 = whole kWh units)
673+ account , err := domain .NewCurrentAccountWithDimension (
674+ "ACC-KWH-001" , "KWH-IDENT-001" , uuid .New ().String (), "KWH" , "ENERGY" , 0 ,
675+ )
676+ require .NoError (t , err )
677+ require .NoError (t , repo .Save (ctx , account ))
678+
679+ // Deposit 8.5 KWH using InstrumentAmount input field
680+ req := & pb.ExecuteDepositRequest {
681+ AccountId : "ACC-KWH-001" ,
682+ Description : "Meter read 2026-03-20: 8.50 kWh" ,
683+ Input : & quantityv1.InstrumentAmount {
684+ Amount : "8.5" ,
685+ InstrumentCode : "KWH" ,
686+ Version : 1 ,
687+ },
688+ }
689+
690+ resp , err := svc .ExecuteDeposit (ctx , req )
691+ require .NoError (t , err , "KWH deposit via InstrumentAmount should succeed" )
692+
693+ require .Equal (t , "ACC-KWH-001" , resp .AccountId )
694+ require .NotEmpty (t , resp .TransactionId )
695+ require .Equal (t , pb .TransactionStatus_TRANSACTION_STATUS_COMPLETED , resp .Status )
696+ }
697+
698+ func TestExecuteDeposit_InstrumentAmountInput_InstrumentMismatch (t * testing.T ) {
699+ db , ctx , cleanup := setupTestDB (t )
700+ defer cleanup ()
701+
702+ repo := persistence .NewRepository (db )
703+ svc := mustNewService (t , repo , nil )
704+
705+ // Create GBP account
706+ account , err := domain .NewCurrentAccount ("ACC-001" , "ACC-001" , uuid .New ().String (), "GBP" )
707+ require .NoError (t , err )
708+ require .NoError (t , repo .Save (ctx , account ))
709+
710+ // Try to deposit KWH to a GBP account
711+ req := & pb.ExecuteDepositRequest {
712+ AccountId : "ACC-001" ,
713+ Input : & quantityv1.InstrumentAmount {
714+ Amount : "100" ,
715+ InstrumentCode : "KWH" ,
716+ Version : 1 ,
717+ },
718+ }
719+
720+ _ , err = svc .ExecuteDeposit (ctx , req )
721+ require .Error (t , err )
722+
723+ st , ok := status .FromError (err )
724+ require .True (t , ok )
725+ require .Equal (t , codes .InvalidArgument , st .Code ())
726+ require .Contains (t , st .Message (), "instrument mismatch" )
727+ }
728+
729+ func TestExecuteDeposit_InstrumentAmountInput_InvalidAmount (t * testing.T ) {
730+ db , ctx , cleanup := setupTestDB (t )
731+ defer cleanup ()
732+
733+ repo := persistence .NewRepository (db )
734+ svc := mustNewService (t , repo , nil )
735+
736+ // Create KWH account
737+ account , err := domain .NewCurrentAccountWithDimension (
738+ "ACC-KWH-001" , "KWH-IDENT-001" , uuid .New ().String (), "KWH" , "ENERGY" , 0 ,
739+ )
740+ require .NoError (t , err )
741+ require .NoError (t , repo .Save (ctx , account ))
742+
743+ // Non-positive amount
744+ req := & pb.ExecuteDepositRequest {
745+ AccountId : "ACC-KWH-001" ,
746+ Input : & quantityv1.InstrumentAmount {
747+ Amount : "-5" ,
748+ InstrumentCode : "KWH" ,
749+ Version : 1 ,
750+ },
751+ }
752+
753+ _ , err = svc .ExecuteDeposit (ctx , req )
754+ require .Error (t , err )
755+
756+ st , ok := status .FromError (err )
757+ require .True (t , ok )
758+ require .Equal (t , codes .InvalidArgument , st .Code ())
759+ require .Contains (t , st .Message (), "positive" )
760+ }
761+
762+ func TestExecuteDeposit_InstrumentAmountInput_MalformedAmount (t * testing.T ) {
763+ db , ctx , cleanup := setupTestDB (t )
764+ defer cleanup ()
765+
766+ repo := persistence .NewRepository (db )
767+ svc := mustNewService (t , repo , nil )
768+
769+ // Create KWH account
770+ account , err := domain .NewCurrentAccountWithDimension (
771+ "ACC-KWH-001" , "KWH-IDENT-001" , uuid .New ().String (), "KWH" , "ENERGY" , 0 ,
772+ )
773+ require .NoError (t , err )
774+ require .NoError (t , repo .Save (ctx , account ))
775+
776+ // Malformed amount string
777+ req := & pb.ExecuteDepositRequest {
778+ AccountId : "ACC-KWH-001" ,
779+ Input : & quantityv1.InstrumentAmount {
780+ Amount : "not-a-number" ,
781+ InstrumentCode : "KWH" ,
782+ Version : 1 ,
783+ },
784+ }
785+
786+ _ , err = svc .ExecuteDeposit (ctx , req )
787+ require .Error (t , err )
788+
789+ st , ok := status .FromError (err )
790+ require .True (t , ok )
791+ require .Equal (t , codes .InvalidArgument , st .Code ())
792+ }
793+
794+ func TestExecuteDeposit_LegacyMoneyAmount_StillWorks (t * testing.T ) {
795+ db , ctx , cleanup := setupTestDB (t )
796+ defer cleanup ()
797+
798+ repo := persistence .NewRepository (db )
799+ svc := mustNewServiceWithPositionKeeping (t , repo , nil , map [string ]int64 {
800+ "ACC-GBP-001" : 10050 ,
801+ })
802+
803+ // Create GBP account
804+ account , err := domain .NewCurrentAccount ("ACC-GBP-001" , "ACC-GBP-001" , uuid .New ().String (), "GBP" )
805+ require .NoError (t , err )
806+ require .NoError (t , repo .Save (ctx , account ))
807+
808+ // Legacy path: use MoneyAmount (backwards compat)
809+ req := & pb.ExecuteDepositRequest {
810+ AccountId : "ACC-GBP-001" ,
811+ Amount : & commonpb.MoneyAmount {
812+ Amount : & money.Money {
813+ CurrencyCode : "GBP" ,
814+ Units : 100 ,
815+ Nanos : 500000000 ,
816+ },
817+ },
818+ Description : "Legacy GBP deposit" ,
819+ }
820+
821+ resp , err := svc .ExecuteDeposit (ctx , req )
822+ require .NoError (t , err , "legacy MoneyAmount deposit should still work" )
823+ require .Equal (t , "ACC-GBP-001" , resp .AccountId )
824+ require .Equal (t , pb .TransactionStatus_TRANSACTION_STATUS_COMPLETED , resp .Status )
825+ }
826+
827+ func TestExecuteDeposit_InputTakesPrecedenceOverAmount (t * testing.T ) {
828+ db , ctx , cleanup := setupTestDB (t )
829+ defer cleanup ()
830+
831+ repo := persistence .NewRepository (db )
832+ svc := mustNewServiceWithPositionKeeping (t , repo , nil , map [string ]int64 {
833+ "ACC-KWH-002" : 500 ,
834+ })
835+
836+ // Create KWH account
837+ account , err := domain .NewCurrentAccountWithDimension (
838+ "ACC-KWH-002" , "KWH-IDENT-002" , uuid .New ().String (), "KWH" , "ENERGY" , 0 ,
839+ )
840+ require .NoError (t , err )
841+ require .NoError (t , repo .Save (ctx , account ))
842+
843+ // Both input and amount provided - input should take precedence
844+ req := & pb.ExecuteDepositRequest {
845+ AccountId : "ACC-KWH-002" ,
846+ Amount : & commonpb.MoneyAmount {
847+ Amount : & money.Money {
848+ CurrencyCode : "GBP" , // wrong instrument - should be ignored
849+ Units : 999 ,
850+ },
851+ },
852+ Input : & quantityv1.InstrumentAmount {
853+ Amount : "10" ,
854+ InstrumentCode : "KWH" ,
855+ Version : 1 ,
856+ },
857+ }
858+
859+ resp , err := svc .ExecuteDeposit (ctx , req )
860+ require .NoError (t , err , "input field should take precedence over amount field" )
861+ require .Equal (t , "ACC-KWH-002" , resp .AccountId )
862+ require .Equal (t , pb .TransactionStatus_TRANSACTION_STATUS_COMPLETED , resp .Status )
863+ }
864+
865+ func TestExecuteDeposit_NeitherInputNorAmount_ReturnsError (t * testing.T ) {
866+ db , ctx , cleanup := setupTestDB (t )
867+ defer cleanup ()
868+
869+ repo := persistence .NewRepository (db )
870+ svc := mustNewService (t , repo , nil )
871+
872+ req := & pb.ExecuteDepositRequest {
873+ AccountId : "ACC-001" ,
874+ // Neither amount nor input provided
875+ }
876+
877+ _ , err := svc .ExecuteDeposit (ctx , req )
878+ require .Error (t , err )
879+
880+ st , ok := status .FromError (err )
881+ require .True (t , ok )
882+ require .Equal (t , codes .InvalidArgument , st .Code ())
883+ }
884+
661885func TestInitiateCurrentAccountUnsupportedCurrency (t * testing.T ) {
662886 db , ctx , cleanup := setupTestDB (t )
663887 defer cleanup ()
0 commit comments