From 8d654959f1bb86aa90554570c8724c91031fbc16 Mon Sep 17 00:00:00 2001 From: "victorine.osewe" Date: Wed, 25 Aug 2021 08:36:03 +0300 Subject: [PATCH] chore:remove ussd --- .gitignore | 3 +- pkg/onboarding/application/dto/input.go | 12 +- pkg/onboarding/application/dto/ussd.go | 9 - .../application/exceptions/custom_errors.go | 9 - .../application/exceptions/error_messages.go | 4 - pkg/onboarding/application/utils/helpers.go | 10 - .../application/utils/validators.go | 55 -- .../application/utils/validators_test.go | 80 -- pkg/onboarding/domain/model/models_gen.go | 4 +- pkg/onboarding/domain/models.go | 16 - .../infrastructure/database/fb/firebase.go | 336 -------- .../database/fb/firebase_integration_test.go | 471 ----------- .../database/fb/firebase_test.go | 219 ----- pkg/onboarding/presentation/config.go | 9 +- .../presentation/graph/enums.graphql | 1 - .../presentation/graph/generated/generated.go | 1 - .../presentation/interactor/interactor.go | 4 - pkg/onboarding/presentation/rest/handlers.go | 36 - .../presentation/rest/handlers_test.go | 159 +--- pkg/onboarding/repository/mock/onboarding.go | 86 -- pkg/onboarding/repository/onboarding.go | 25 - pkg/onboarding/usecases/login_test.go | 8 +- pkg/onboarding/usecases/ussd/login.go | 114 --- .../usecases/ussd/login_integration_test.go | 146 ---- .../usecases/ussd/login_unit_test.go | 170 ---- pkg/onboarding/usecases/ussd/main.go | 138 ---- .../usecases/ussd/main_integration_test.go | 308 ------- .../usecases/ussd/main_unit_test.go | 107 --- pkg/onboarding/usecases/ussd/pin.go | 384 --------- .../usecases/ussd/pin_integration_test.go | 561 ------------- pkg/onboarding/usecases/ussd/pin_unit_test.go | 349 -------- pkg/onboarding/usecases/ussd/profile.go | 59 -- .../usecases/ussd/profile_unit_test.go | 147 ---- pkg/onboarding/usecases/ussd/register.go | 327 -------- .../ussd/register_integration_test.go | 303 ------- .../usecases/ussd/registration_unit_test.go | 128 --- pkg/onboarding/usecases/ussd/session.go | 195 ----- .../usecases/ussd/session_unit_test.go | 755 ------------------ pkg/onboarding/usecases/ussd/sub_menu.go | 79 -- tests/config_test.go | 11 - tests/ussd_acceptance_test.go | 128 --- 41 files changed, 7 insertions(+), 5959 deletions(-) delete mode 100644 pkg/onboarding/application/dto/ussd.go delete mode 100644 pkg/onboarding/usecases/ussd/login.go delete mode 100644 pkg/onboarding/usecases/ussd/login_integration_test.go delete mode 100644 pkg/onboarding/usecases/ussd/login_unit_test.go delete mode 100644 pkg/onboarding/usecases/ussd/main.go delete mode 100644 pkg/onboarding/usecases/ussd/main_integration_test.go delete mode 100644 pkg/onboarding/usecases/ussd/main_unit_test.go delete mode 100644 pkg/onboarding/usecases/ussd/pin.go delete mode 100644 pkg/onboarding/usecases/ussd/pin_integration_test.go delete mode 100644 pkg/onboarding/usecases/ussd/pin_unit_test.go delete mode 100644 pkg/onboarding/usecases/ussd/profile.go delete mode 100644 pkg/onboarding/usecases/ussd/profile_unit_test.go delete mode 100644 pkg/onboarding/usecases/ussd/register.go delete mode 100644 pkg/onboarding/usecases/ussd/register_integration_test.go delete mode 100644 pkg/onboarding/usecases/ussd/registration_unit_test.go delete mode 100644 pkg/onboarding/usecases/ussd/session.go delete mode 100644 pkg/onboarding/usecases/ussd/session_unit_test.go delete mode 100644 pkg/onboarding/usecases/ussd/sub_menu.go delete mode 100644 tests/ussd_acceptance_test.go diff --git a/.gitignore b/.gitignore index 5c1275d5..a5b415ce 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,4 @@ coverage.html coverage.json coverage_report.txt install-misspell.sh -.vscode/ -/pkg/onboarding/usecases/ussd/profile_integration_test.go \ No newline at end of file +.vscode/ \ No newline at end of file diff --git a/pkg/onboarding/application/dto/input.go b/pkg/onboarding/application/dto/input.go index f7858142..58be0216 100644 --- a/pkg/onboarding/application/dto/input.go +++ b/pkg/onboarding/application/dto/input.go @@ -335,15 +335,6 @@ type SupplierPubSubMessagePayload struct { UID string `json:"uid"` } -// USSDEvent records any USSD event(e.g. entering firstname, lastname etc.) that happens for every session and the time -type USSDEvent struct { - SessionID string `firestore:"sessionID"` - PhoneNumber string `firestore:"phoneNumber"` - USSDEventDateTime *time.Time `firestore:"ussdEventDateTime"` - Level int `firestore:"level"` - USSDEventName string `firestore:"ussdEventName"` -} - // AssignRolePayload is the payload used to assign a role to a user type AssignRolePayload struct { UserID string `json:"userID"` @@ -352,7 +343,8 @@ type AssignRolePayload struct { // DeleteRolePayload is the payload used to delete a role type DeleteRolePayload struct { - Name string `json:"name"` + Name string `json:"name"` + RoleID string `json:"roleID"` } diff --git a/pkg/onboarding/application/dto/ussd.go b/pkg/onboarding/application/dto/ussd.go deleted file mode 100644 index 96049b06..00000000 --- a/pkg/onboarding/application/dto/ussd.go +++ /dev/null @@ -1,9 +0,0 @@ -package dto - -//SessionDetails input for ussd -type SessionDetails struct { - SessionID string `json:"sessionID"` - PhoneNumber *string `json:"phoneNumber"` - Level int `json:"level"` - Text string `json:"text"` -} diff --git a/pkg/onboarding/application/exceptions/custom_errors.go b/pkg/onboarding/application/exceptions/custom_errors.go index 7a66a4e1..0a346b95 100644 --- a/pkg/onboarding/application/exceptions/custom_errors.go +++ b/pkg/onboarding/application/exceptions/custom_errors.go @@ -440,15 +440,6 @@ func RecordDoesNotExistError(err error) error { } } -// SessionIDError return an error when a ussd sessionId is not provided -func SessionIDError(err error) error { - return &errorcodeutil.CustomError{ - Err: err, - Message: SessionIDErrMsg, - Code: int(errorcodeutil.Internal), - } -} - // RoleNotValid return an error when a user does not have the required role func RoleNotValid(err error) error { return &errorcodeutil.CustomError{ diff --git a/pkg/onboarding/application/exceptions/error_messages.go b/pkg/onboarding/application/exceptions/error_messages.go index f42d2d9b..13f01de9 100644 --- a/pkg/onboarding/application/exceptions/error_messages.go +++ b/pkg/onboarding/application/exceptions/error_messages.go @@ -163,10 +163,6 @@ const ( // the database RecordDoesNotExistErrMsg = "the record cannot be found in the database" - //SessionIDErrMsg is an error message displayed when a sessionId is not provided in - // in the USSD details - SessionIDErrMsg = "sessionID not provided" - //RoleNotValidMsg is an error message displayed when the provided role is not valid // and the user doesn't have permissions to perform an action RoleNotValidMsg = "user role is not valid" diff --git a/pkg/onboarding/application/utils/helpers.go b/pkg/onboarding/application/utils/helpers.go index 47a6188c..cf6d5e34 100644 --- a/pkg/onboarding/application/utils/helpers.go +++ b/pkg/onboarding/application/utils/helpers.go @@ -5,7 +5,6 @@ import ( "fmt" "log" "regexp" - "strconv" "github.com/savannahghi/converterandformatter" "github.com/savannahghi/feedlib" @@ -131,15 +130,6 @@ func FindItem(slice []string, value string) (int, bool) { return -1, false } -// ParseUSSDDateInput ... -func ParseUSSDDateInput(date string) string { - dayEntered, _ := strconv.Atoi(date[0:2]) - monthEntered, _ := strconv.Atoi(date[2:4]) - yearEntered, _ := strconv.Atoi(date[4:8]) - - return fmt.Sprintf("%v-%v-%v", dayEntered, monthEntered, yearEntered) -} - // UniquePermissionsArray removes duplicate permissions in an array of permissions func UniquePermissionsArray(arr []profileutils.PermissionType) []profileutils.PermissionType { occurred := map[profileutils.PermissionType]bool{} diff --git a/pkg/onboarding/application/utils/validators.go b/pkg/onboarding/application/utils/validators.go index c4b7934a..64c7bf84 100644 --- a/pkg/onboarding/application/utils/validators.go +++ b/pkg/onboarding/application/utils/validators.go @@ -112,52 +112,6 @@ func ValidateAficasTalkingSMSData(input *dto.AfricasTalkingMessage) (*dto.Africa }, nil } -//ValidateUSSDEvent validates a USSD event -func ValidateUSSDEvent(input *dto.USSDEvent) (*dto.USSDEvent, error) { - if input.SessionID == "" { - return nil, fmt.Errorf("ussd event's session id cannot be empty") - } - - if input.PhoneNumber == "" { - return nil, fmt.Errorf("ussd event's phone number cannot be empty") - } - - if input.USSDEventDateTime == nil { - return nil, fmt.Errorf("ussd event's date and time cannot be empty") - } - - if input.USSDEventName == "" { - return nil, fmt.Errorf("ussd event's name cannot be empty") - } - - return &dto.USSDEvent{ - SessionID: input.SessionID, - PhoneNumber: input.PhoneNumber, - USSDEventDateTime: input.USSDEventDateTime, - Level: input.Level, - USSDEventName: input.USSDEventName, - }, nil -} - -//ValidateUSSDDetails checks if the phonenumber supplied is valid , that a session ID is provided -// and returns valid USSD session details. -func ValidateUSSDDetails(payload *dto.SessionDetails) (*dto.SessionDetails, error) { - phone, err := converterandformatter.NormalizeMSISDN(*payload.PhoneNumber) - if err != nil { - return nil, exceptions.NormalizeMSISDNError(err) - } - if payload.SessionID == "" { - err := fmt.Errorf("expected sessionid to be defined") - return nil, exceptions.SessionIDError(err) - } - return &dto.SessionDetails{ - PhoneNumber: phone, - SessionID: payload.SessionID, - Level: payload.Level, - Text: payload.Text, - }, nil -} - // ValidatePIN ... func ValidatePIN(pin string) error { validatePINErr := ValidatePINLength(pin) @@ -181,15 +135,6 @@ func ValidatePINLength(pin string) error { return nil } -// ValidateUSSDInput ... -func ValidateUSSDInput(text string) error { - if text == "" { - return fmt.Errorf("invalid input") - } - - return nil -} - // IsLetter ... func IsLetter(s string) bool { for _, r := range s { diff --git a/pkg/onboarding/application/utils/validators_test.go b/pkg/onboarding/application/utils/validators_test.go index 5e5c3b45..7bf76a19 100644 --- a/pkg/onboarding/application/utils/validators_test.go +++ b/pkg/onboarding/application/utils/validators_test.go @@ -269,83 +269,3 @@ func TestValidateSMSData(t *testing.T) { }) } } - -func TestValidateUSSDDetails(t *testing.T) { - phone := "+254711223344" - sessionId := "1235678" - text := "" - - alphanumericPhone := "+254-not-valid-123" - emptySessionId := "" - badPhone := "+254712" - - type args struct { - input *dto.SessionDetails - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "success: return a valid output", - args: args{ - input: &dto.SessionDetails{ - PhoneNumber: &phone, - SessionID: sessionId, - Text: text, - }, - }, - wantErr: false, - }, - { - name: "failure: bad phone number provided", - args: args{ - input: &dto.SessionDetails{ - PhoneNumber: &badPhone, - SessionID: sessionId, - Text: text, - }, - }, - wantErr: true, - }, - { - name: "failure: alphanumeric phone number provided", - args: args{ - input: &dto.SessionDetails{ - PhoneNumber: &alphanumericPhone, - SessionID: sessionId, - Text: text, - }, - }, - wantErr: true, - }, - { - name: "failure: empty Ussd SessionId", - args: args{ - input: &dto.SessionDetails{ - PhoneNumber: &phone, - SessionID: emptySessionId, - Text: text, - }, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - validInput, err := utils.ValidateUSSDDetails(tt.args.input) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateUSSDDetails() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && validInput != nil { - t.Errorf("expected a nil valid input since an error :%v occurred", err) - } - - if err == nil && validInput == nil { - t.Errorf("expected a valid input %v since no error occurred", validInput) - } - }) - } -} diff --git a/pkg/onboarding/domain/model/models_gen.go b/pkg/onboarding/domain/model/models_gen.go index e6577751..da8e68ad 100644 --- a/pkg/onboarding/domain/model/models_gen.go +++ b/pkg/onboarding/domain/model/models_gen.go @@ -50,19 +50,17 @@ type ChannelOfContact string const ( ChannelOfContactApp ChannelOfContact = "APP" - ChannelOfContactUssd ChannelOfContact = "USSD" ChannelOfContactShortcode ChannelOfContact = "SHORTCODE" ) var AllChannelOfContact = []ChannelOfContact{ ChannelOfContactApp, - ChannelOfContactUssd, ChannelOfContactShortcode, } func (e ChannelOfContact) IsValid() bool { switch e { - case ChannelOfContactApp, ChannelOfContactUssd, ChannelOfContactShortcode: + case ChannelOfContactApp, ChannelOfContactShortcode: return true } return false diff --git a/pkg/onboarding/domain/models.go b/pkg/onboarding/domain/models.go index 15a6618f..61ec71be 100644 --- a/pkg/onboarding/domain/models.go +++ b/pkg/onboarding/domain/models.go @@ -6,7 +6,6 @@ import ( "github.com/savannahghi/enumutils" "github.com/savannahghi/firebasetools" "github.com/savannahghi/profileutils" - "github.com/savannahghi/scalarutils" ) // Branch represents a Slade 360 Charge Master branch @@ -101,21 +100,6 @@ type NHIFDetails struct { NHIFCardPhotoID string `json:"nhifCardPhotoID" firestore:"nhifCardPhotoID"` } -//USSDLeadDetails represents ussd user session details -type USSDLeadDetails struct { - ID string `json:"id" firestore:"id"` - Level int `json:"level" firestore:"level"` - PhoneNumber string `json:"phoneNumber" firestore:"phoneNumber"` - SessionID string `json:"sessionID" firestore:"sessionID"` - FirstName string `json:"firstName" firestore:"firstName"` - LastName string `json:"lastName" firestore:"lastName"` - DateOfBirth scalarutils.Date `json:"dob" firestore:"dob"` - IsRegistered bool `json:"isRegistered" firestore:"isRegistered"` - ContactChannel string `json:"contactChannel" firestore:"contactChannel"` - WantCover bool `json:"wantCover" firestore:"wantCover"` - PIN string `json:"pin" firestore:"pin"` -} - // CRMContact represents a stored CRM contact type CRMContact struct { FirstName string `json:"first_name,omitempty"` diff --git a/pkg/onboarding/infrastructure/database/fb/firebase.go b/pkg/onboarding/infrastructure/database/fb/firebase.go index ddf0e144..6f8c8a15 100644 --- a/pkg/onboarding/infrastructure/database/fb/firebase.go +++ b/pkg/onboarding/infrastructure/database/fb/firebase.go @@ -46,10 +46,8 @@ const ( nhifDetailsCollectionName = "nhif_details" communicationsSettingsCollectionName = "communications_settings" smsCollectionName = "incoming_sms" - ussdDataCollectioName = "ussd_data" firebaseExchangeRefreshTokenURL = "https://securetoken.googleapis.com/v1/token?key=" marketingDataCollectionName = "marketing_data" - ussdEventsCollectionName = "ussd_events" rolesRevocationCollectionName = "role_revocations" rolesCollectionName = "user_roles" ) @@ -137,18 +135,6 @@ func (fr Repository) GetSMSCollectionName() string { return suffixed } -//GetUSSDDataCollectionName gets the collection from firestore -func (fr Repository) GetUSSDDataCollectionName() string { - suffixed := firebasetools.SuffixCollection(ussdDataCollectioName) - return suffixed -} - -//GetUSSDEventsCollectionName ... -func (fr Repository) GetUSSDEventsCollectionName() string { - suffixed := firebasetools.SuffixCollection(ussdEventsCollectionName) - return suffixed -} - // GetMarketingDataCollectionName ... func (fr Repository) GetMarketingDataCollectionName() string { suffixed := firebasetools.SuffixCollection(marketingDataCollectionName) @@ -3491,103 +3477,6 @@ func (fr *Repository) PersistIncomingSMSData( } -// SaveUSSDEvent saves the USSD event that has taken place while interacting with the USSD -func (fr *Repository) SaveUSSDEvent( - ctx context.Context, - input *dto.USSDEvent, -) (*dto.USSDEvent, error) { - ctx, span := tracer.Start(ctx, "SaveUSSDEvent") - defer span.End() - - ussdEvent := &dto.USSDEvent{ - SessionID: input.SessionID, - PhoneNumber: input.PhoneNumber, - USSDEventDateTime: input.USSDEventDateTime, - Level: input.Level, - USSDEventName: input.USSDEventName, - } - - validatesUSSDEvent, err := utils.ValidateUSSDEvent(ussdEvent) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - createCommand := &CreateCommand{ - CollectionName: fr.GetUSSDEventsCollectionName(), - Data: validatesUSSDEvent, - } - - docRef, err := fr.FirestoreClient.Create(ctx, createCommand) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - - getUSSDEventsQuery := &GetSingleQuery{ - CollectionName: fr.GetUSSDEventsCollectionName(), - Value: docRef.ID, - } - - docsnapshot, err := fr.FirestoreClient.Get(ctx, getUSSDEventsQuery) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - - event := &dto.USSDEvent{} - err = docsnapshot.DataTo(event) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - - return event, nil -} - -// AddAITSessionDetails saves diallers session details in the database -func (fr *Repository) AddAITSessionDetails( - ctx context.Context, - input *dto.SessionDetails, -) (*domain.USSDLeadDetails, error) { - ctx, span := tracer.Start(ctx, "AddAITSessionDetails") - defer span.End() - - validateDetails, err := utils.ValidateUSSDDetails(input) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - sessionDetails := &domain.USSDLeadDetails{ - ID: uuid.New().String(), - Level: validateDetails.Level, - PhoneNumber: *validateDetails.PhoneNumber, - SessionID: validateDetails.SessionID, - IsRegistered: false, - ContactChannel: "USSD", - WantCover: false, - } - - createCommand := &CreateCommand{ - CollectionName: fr.GetUSSDDataCollectionName(), - Data: sessionDetails, - } - - _, err = fr.FirestoreClient.Create(ctx, createCommand) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - - sessionDetails, err = fr.GetAITSessionDetails(ctx, validateDetails.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - - return sessionDetails, nil -} - // ListUserProfiles fetches all users with the specified role from the database func (fr *Repository) ListUserProfiles( ctx context.Context, @@ -3621,231 +3510,6 @@ func (fr *Repository) ListUserProfiles( return profiles, nil } -// GetAITSessionDetails gets Africa's Talking session details -func (fr *Repository) GetAITSessionDetails( - ctx context.Context, - sessionID string, -) (*domain.USSDLeadDetails, error) { - ctx, span := tracer.Start(ctx, "GetAITSessionDetails") - defer span.End() - - validatedSessionID, err := utils.CheckEmptyString(sessionID) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - - query := &GetAllQuery{ - CollectionName: fr.GetUSSDDataCollectionName(), - FieldName: "sessionID", - Value: validatedSessionID, - Operator: "==", - } - - docs, err := fr.FirestoreClient.GetAll(ctx, query) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - - if len(docs) == 0 { - return nil, nil - } - - sessionDet := &domain.USSDLeadDetails{} - err = docs[0].DataTo(sessionDet) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - return sessionDet, nil - -} - -// UpdateSessionLevel updates user interaction level whike they interact with USSD -func (fr *Repository) UpdateSessionLevel( - ctx context.Context, - sessionID string, - level int, -) (*domain.USSDLeadDetails, error) { - ctx, span := tracer.Start(ctx, "UpdateSessionLevel") - defer span.End() - - validSessionID, err := utils.CheckEmptyString(sessionID) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - sessionDetails, err := fr.GetAITSessionDetails(ctx, *validSessionID) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - collectionName := fr.GetUSSDDataCollectionName() - query := &GetAllQuery{ - CollectionName: collectionName, - FieldName: "sessionID", - Value: sessionID, - Operator: "==", - } - docs, err := fr.FirestoreClient.GetAll(ctx, query) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - sessionDetails.Level = level - - updateCommand := &UpdateCommand{ - CollectionName: collectionName, - ID: docs[0].Ref.ID, - Data: sessionDetails, - } - err = fr.FirestoreClient.Update(ctx, updateCommand) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - return sessionDetails, nil -} - -// UpdateSessionPIN updates current user's session PIN when signing up or changing PIN -func (fr *Repository) UpdateSessionPIN( - ctx context.Context, - sessionID string, - pin string, -) (*domain.USSDLeadDetails, error) { - ctx, span := tracer.Start(ctx, "UpdateSessionPIN") - defer span.End() - - sessionDetails, err := fr.GetAITSessionDetails(ctx, sessionID) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - collectionName := fr.GetUSSDDataCollectionName() - query := &GetAllQuery{ - CollectionName: collectionName, - FieldName: "sessionID", - Value: sessionID, - Operator: "==", - } - docs, err := fr.FirestoreClient.GetAll(ctx, query) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - sessionDetails.PIN = pin - - updateCommand := &UpdateCommand{ - CollectionName: collectionName, - ID: docs[0].Ref.ID, - Data: sessionDetails, - } - err = fr.FirestoreClient.Update(ctx, updateCommand) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - return sessionDetails, nil -} - -// GetAITDetails retrieves session details from the database -func (fr *Repository) GetAITDetails( - ctx context.Context, - phoneNumber string, -) (*domain.USSDLeadDetails, error) { - ctx, span := tracer.Start(ctx, "GetAITDetails") - defer span.End() - - validPhoneNumber, err := utils.CheckEmptyString(phoneNumber) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - query := &GetAllQuery{ - CollectionName: fr.GetUSSDDataCollectionName(), - FieldName: "phoneNumber", - Value: validPhoneNumber, - Operator: "==", - } - - docs, err := fr.FirestoreClient.GetAll(ctx, query) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.InternalServerError(err) - } - - if len(docs) == 0 { - return nil, nil - } - - ussdLead := &domain.USSDLeadDetails{} - err = docs[0].DataTo(ussdLead) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - return ussdLead, nil - -} - -// UpdateAITSessionDetails updates session details using phone number -func (fr *Repository) UpdateAITSessionDetails( - ctx context.Context, - phoneNumber string, - contactLead *domain.USSDLeadDetails, -) error { - ctx, span := tracer.Start(ctx, "UpdateAITSessionDetails") - defer span.End() - - validPhoneNumber, err := utils.CheckEmptyString(phoneNumber) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - - contactDetails, err := fr.GetAITDetails(ctx, *validPhoneNumber) - if err != nil { - return err - } - - collectionName := fr.GetUSSDDataCollectionName() - query := &GetAllQuery{ - CollectionName: collectionName, - FieldName: "phoneNumber", - Value: phoneNumber, - Operator: "==", - } - docs, err := fr.FirestoreClient.GetAll(ctx, query) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - contactDetails.FirstName = contactLead.FirstName - contactDetails.LastName = contactLead.LastName - contactDetails.DateOfBirth = contactLead.DateOfBirth - contactDetails.IsRegistered = contactLead.IsRegistered - - updateCommand := &UpdateCommand{ - CollectionName: collectionName, - ID: docs[0].Ref.ID, - Data: contactDetails, - } - err = fr.FirestoreClient.Update(ctx, updateCommand) - if err != nil { - utils.RecordSpanError(span, err) - return exceptions.InternalServerError(err) - } - return nil -} - // CreateRole creates a new role and persists it to the database func (fr *Repository) CreateRole( ctx context.Context, diff --git a/pkg/onboarding/infrastructure/database/fb/firebase_integration_test.go b/pkg/onboarding/infrastructure/database/fb/firebase_integration_test.go index b4065d88..d1defa0e 100644 --- a/pkg/onboarding/infrastructure/database/fb/firebase_integration_test.go +++ b/pkg/onboarding/infrastructure/database/fb/firebase_integration_test.go @@ -17,7 +17,6 @@ import ( "time" - "github.com/brianvoe/gofakeit" "github.com/google/uuid" "github.com/savannahghi/enumutils" "github.com/savannahghi/feedlib" @@ -91,7 +90,6 @@ func TestMain(m *testing.M) { r.GetNHIFDetailsCollectionName(), r.GetProfileNudgesCollectionName(), r.GetSMSCollectionName(), - r.GetUSSDDataCollectionName(), r.GetRolesCollectionName(), } for _, collection := range collections { @@ -3683,165 +3681,6 @@ func TestRepository_PersistIncomingSMSData(t *testing.T) { } } -func TestRepository_AddAITSessionDetails(t *testing.T) { - ctx := context.Background() - fsc, fbc := InitializeTestFirebaseClient(ctx) - if fsc == nil { - t.Errorf("failed to initialize test FireStore client") - return - } - if fbc == nil { - t.Errorf("failed to initialize test FireBase client") - return - } - firestoreExtension := fb.NewFirestoreClientExtension(fsc) - firestoreDB := fb.NewFirebaseRepository(firestoreExtension, fbc) - - phoneNumber := "+254700100200" - SessionID := "151515" - Level := 0 - Text := "" - - sessionDet := &dto.SessionDetails{ - SessionID: SessionID, - PhoneNumber: &phoneNumber, - Level: Level, - Text: Text, - } - - invalidsessionDet := &dto.SessionDetails{ - SessionID: "", - PhoneNumber: &phoneNumber, - Level: Level, - } - - type args struct { - ctx context.Context - input *dto.SessionDetails - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - input: sessionDet, - }, - wantErr: false, - }, - - { - name: "Sad case", - args: args{ - ctx: ctx, - input: invalidsessionDet, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "Happy case" { - _, err := utils.ValidateUSSDDetails(sessionDet) - if err != nil { - t.Errorf("an error occurred") - } - } - - if tt.name == "Sad case" { - _, err := utils.ValidateUSSDDetails(sessionDet) - if err != nil { - t.Errorf("an error occurred") - return - } - } - - got, err := firestoreDB.AddAITSessionDetails(tt.args.ctx, tt.args.input) - if (err != nil) != tt.wantErr { - t.Errorf( - "Repository.AddAITSessionDetails() error = %v, wantErr %v", - err, - tt.wantErr, - ) - return - } - if tt.wantErr && got != nil { - t.Errorf("the error was not expected") - return - } - }) - } -} - -func TestRepository_GetAITSessionDetailss(t *testing.T) { - ctx := context.Background() - fsc, fbc := InitializeTestFirebaseClient(ctx) - if fsc == nil { - t.Errorf("failed to initialize test FireStore client") - return - } - if fbc == nil { - t.Errorf("failed to initialize test FireBase client") - return - } - firestoreExtension := fb.NewFirestoreClientExtension(fsc) - firestoreDB := fb.NewFirebaseRepository(firestoreExtension, fbc) - - sessionID := "151515" - - type args struct { - ctx context.Context - sessionID string - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - sessionID: sessionID, - }, - wantErr: false, - }, - { - name: "Sad case", - args: args{ - ctx: ctx, - sessionID: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - _, err := firestoreDB.GetAITSessionDetails(tt.args.ctx, tt.args.sessionID) - if (err != nil) != tt.wantErr { - t.Errorf( - "Repository.GetAITSessionDetails() error = %v, wantErr %v", - err, - tt.wantErr, - ) - return - } - if !tt.wantErr && err != nil { - t.Errorf("error was not expected but got error: %v", err) - return - } - }) - } -} - func TestRepository_UpdatePIN_IntegrationTest(t *testing.T) { ctx := context.Background() fsc, fbc := InitializeTestFirebaseClient(ctx) @@ -3938,316 +3777,6 @@ func TestRepository_UpdatePIN_IntegrationTest(t *testing.T) { } } -func TestRepository_UpdateSessionLevel(t *testing.T) { - ctx := context.Background() - fsc, fbc := InitializeTestFirebaseClient(ctx) - if fsc == nil { - t.Errorf("failed to initialize test FireStore client") - return - } - if fbc == nil { - t.Errorf("failed to initialize test FireBase client") - return - } - firestoreExtension := fb.NewFirestoreClientExtension(fsc) - firestoreDB := fb.NewFirebaseRepository(firestoreExtension, fbc) - - phoneNumber := "+254702215783" - - sessionDet := &dto.SessionDetails{ - SessionID: "b9839ed4-ad97-4cff-8b36-7afb0c7bf3ae", - PhoneNumber: &phoneNumber, - Level: 1, - Text: "Test", - } - - sessionDetails, err := firestoreDB.AddAITSessionDetails(ctx, sessionDet) - if err != nil { - t.Errorf("unable to add data") - } - - type args struct { - ctx context.Context - sessionID string - level int - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - sessionID: sessionDetails.SessionID, - level: 1, - }, - wantErr: false, - }, - { - name: "Sad case", - args: args{ - ctx: ctx, - sessionID: "", - level: 1, - }, - want: &domain.USSDLeadDetails{}, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - got, err := firestoreDB.UpdateSessionLevel( - tt.args.ctx, - tt.args.sessionID, - tt.args.level, - ) - if (err != nil) != tt.wantErr { - t.Errorf("Repository.UpdateSessionLevel() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !tt.wantErr && got == nil { - t.Errorf("Repository.UpdateSessionLevel() error = %v, wantErr %v", err, tt.wantErr) - return - } - }) - } -} - -func TestRepository_SaveUSSDEvent_IntegrationTest(t *testing.T) { - ctx := context.Background() - fsc, fbc := InitializeTestFirebaseClient(ctx) - if fsc == nil { - t.Errorf("failed to initialize test FireStore client") - return - } - if fbc == nil { - t.Errorf("failed to initialize test FireBase client") - return - } - firestoreExtension := fb.NewFirestoreClientExtension(fsc) - firestoreDB := fb.NewFirebaseRepository(firestoreExtension, fbc) - - currentTime := time.Now() - - type args struct { - ctx context.Context - input *dto.USSDEvent - } - tests := []struct { - name string - args args - want *dto.USSDEvent - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - input: &dto.USSDEvent{ - SessionID: "0001000", - PhoneNumber: "+254700000000", - USSDEventDateTime: ¤tTime, - Level: 10, - USSDEventName: "chose to reset PIN", - }, - }, - wantErr: false, - }, - - { - name: "Sad case", - args: args{ - ctx: ctx, - input: &dto.USSDEvent{ - SessionID: "", - PhoneNumber: "+254700000000", - USSDEventDateTime: ¤tTime, - Level: 10, - USSDEventName: "chose to reset PIN", - }, - }, - want: &dto.USSDEvent{}, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := firestoreDB.SaveUSSDEvent(tt.args.ctx, tt.args.input) - if (err != nil) != tt.wantErr { - t.Errorf("Repository.SaveUSSDEvent() error = %v, wantErr %v", err, tt.wantErr) - return - } - - if !tt.wantErr && got == nil { - t.Errorf("Repository.SaveUSSDEvent() error = %v, wantErr %v", err, tt.wantErr) - return - } - }) - } -} - -func TestRepository_GetAITDetails_Integration(t *testing.T) { - ctx := context.Background() - fsc, fbc := InitializeTestFirebaseClient(ctx) - if fsc == nil { - t.Errorf("failed to initialize test FireStore client") - return - } - if fbc == nil { - t.Errorf("failed to initialize test FireBase client") - return - } - firestoreExtension := fb.NewFirestoreClientExtension(fsc) - firestoreDB := fb.NewFirebaseRepository(firestoreExtension, fbc) - - phoneNumber := "+254700100200" - - sessionDet := &dto.SessionDetails{ - SessionID: uuid.NewString(), - PhoneNumber: &phoneNumber, - Level: 0, - Text: "", - } - - _, err := firestoreDB.AddAITSessionDetails(ctx, sessionDet) - if err != nil { - t.Errorf("unable to add session details") - return - } - - type args struct { - ctx context.Context - phoneNumber string - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - phoneNumber: phoneNumber, - }, - wantErr: false, - }, - { - name: "Sad case", - args: args{ - ctx: ctx, - phoneNumber: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - got, err := firestoreDB.GetAITDetails(tt.args.ctx, tt.args.phoneNumber) - if (err != nil) != tt.wantErr { - t.Errorf("Repository.GetAITDetails() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !tt.wantErr && got == nil { - t.Errorf("Repository.GetAITDetails() error = %v, wantErr %v", err, tt.wantErr) - return - } - }) - } -} - -func TestRepository_UpdateAITSessionDetails_Integration(t *testing.T) { - ctx := context.Background() - fsc, fbc := InitializeTestFirebaseClient(ctx) - if fsc == nil { - t.Errorf("failed to initialize test FireStore client") - return - } - if fbc == nil { - t.Errorf("failed to initialize test FireBase client") - return - } - firestoreExtension := fb.NewFirestoreClientExtension(fsc) - firestoreDB := fb.NewFirebaseRepository(firestoreExtension, fbc) - - phoneNumber := "+254700100200" - - contact := &domain.USSDLeadDetails{ - ID: uuid.NewString(), - Level: 0, - PhoneNumber: phoneNumber, - SessionID: uuid.NewString(), - FirstName: gofakeit.FirstName(), - LastName: gofakeit.LastName(), - DateOfBirth: scalarutils.Date{}, - IsRegistered: false, - ContactChannel: "USSD", - WantCover: false, - PIN: "1237", - } - - sessionDet := &dto.SessionDetails{ - SessionID: uuid.NewString(), - PhoneNumber: &phoneNumber, - Level: 0, - Text: "", - } - - _, err := firestoreDB.AddAITSessionDetails(ctx, sessionDet) - if err != nil { - t.Errorf("unable to add session details") - return - } - - type args struct { - ctx context.Context - phoneNumber string - contactLead *domain.USSDLeadDetails - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - phoneNumber: phoneNumber, - contactLead: contact, - }, - wantErr: false, - }, - { - name: "Sad case", - args: args{ - ctx: ctx, - phoneNumber: "", - contactLead: contact, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := firestoreDB.UpdateAITSessionDetails(tt.args.ctx, tt.args.phoneNumber, tt.args.contactLead); (err != nil) != tt.wantErr { - t.Errorf( - "Repository.UpdateAITSessionDetails() error = %v, wantErr %v", - err, - tt.wantErr, - ) - } - }) - } -} - func TestRepository_GetUserProfileByPhoneOrEmail_Integration(t *testing.T) { ctx := context.Background() fsc, fbc := InitializeTestFirebaseClient(ctx) diff --git a/pkg/onboarding/infrastructure/database/fb/firebase_test.go b/pkg/onboarding/infrastructure/database/fb/firebase_test.go index a729177f..4b7aea3d 100644 --- a/pkg/onboarding/infrastructure/database/fb/firebase_test.go +++ b/pkg/onboarding/infrastructure/database/fb/firebase_test.go @@ -15,7 +15,6 @@ import ( "github.com/savannahghi/interserviceclient" "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" "github.com/savannahghi/onboarding/pkg/onboarding/application/exceptions" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" "github.com/savannahghi/onboarding/pkg/onboarding/domain" "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/database/fb" extMock "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/database/fb/mock" @@ -1155,224 +1154,6 @@ func TestRepository_ListAgentUserProfiles(t *testing.T) { } } -func TestRepository_AddAITSessionDetails_Unittest(t *testing.T) { - ctx := context.Background() - var fireStoreClientExt fb.FirestoreClientExtension = &fakeFireStoreClientExt - repo := fb.NewFirebaseRepository(fireStoreClientExt, fireBaseClientExt) - - phoneNumber := "+254700100200" - SessionID := uuid.New().String() - Level := 0 - Text := "" - - sessionDet := &dto.SessionDetails{ - SessionID: SessionID, - PhoneNumber: &phoneNumber, - Level: Level, - Text: Text, - } - - type args struct { - ctx context.Context - input *dto.SessionDetails - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - input: sessionDet, - }, - wantErr: false, - }, - - { - name: "Sad case", - args: args{ - ctx: ctx, - input: sessionDet, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "Happy case" { - fakeFireStoreClientExt.GetAllFn = func(ctx context.Context, query *fb.GetAllQuery) ([]*firestore.DocumentSnapshot, error) { - docs := []*firestore.DocumentSnapshot{} - return docs, nil - } - - fakeFireStoreClientExt.CreateFn = func(ctx context.Context, command *fb.CreateCommand) (*firestore.DocumentRef, error) { - return &firestore.DocumentRef{ID: "c9d62c7e-93e5-44a6-b503-6fc159c1782f"}, nil - } - } - - if tt.name == "Sad case" { - _, err := utils.ValidateUSSDDetails(sessionDet) - if err != nil { - t.Errorf("an error occurred") - return - } - - fakeFireStoreClientExt.CreateFn = func(ctx context.Context, command *fb.CreateCommand) (*firestore.DocumentRef, error) { - return nil, fmt.Errorf("error") - } - - } - - got, err := repo.AddAITSessionDetails(tt.args.ctx, tt.args.input) - if (err != nil) != tt.wantErr { - t.Errorf( - "Repository.AddAITSessionDetails() error = %v, wantErr %v", - err, - tt.wantErr, - ) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Repository.AddAITSessionDetails() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestRepository_GetAITSessionDetails_Unittests(t *testing.T) { - ctx := context.Background() - var fireStoreClientExt fb.FirestoreClientExtension = &fakeFireStoreClientExt - repo := fb.NewFirebaseRepository(fireStoreClientExt, fireBaseClientExt) - - SessionID := uuid.New().String() - - type args struct { - ctx context.Context - sessionID string - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - sessionID: SessionID, - }, - wantErr: false, - }, - { - name: "Sad case", - args: args{ - ctx: ctx, - sessionID: SessionID, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "Happy case" { - fakeFireStoreClientExt.GetAllFn = func(ctx context.Context, query *fb.GetAllQuery) ([]*firestore.DocumentSnapshot, error) { - docs := []*firestore.DocumentSnapshot{} - return docs, nil - } - } - - if tt.name == "Sad case" { - fakeFireStoreClientExt.GetAllFn = func(ctx context.Context, query *fb.GetAllQuery) ([]*firestore.DocumentSnapshot, error) { - return nil, fmt.Errorf("an error occurred") - } - } - - got, err := repo.GetAITSessionDetails(tt.args.ctx, tt.args.sessionID) - if (err != nil) != tt.wantErr { - t.Errorf( - "Repository.GetAITSessionDetails() error = %v, wantErr %v", - err, - tt.wantErr, - ) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Repository.GetAITSessionDetails() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestRepository_GetAITDetails_Unnittest(t *testing.T) { - ctx := context.Background() - var fireStoreClientExt fb.FirestoreClientExtension = &fakeFireStoreClientExt - repo := fb.NewFirebaseRepository(fireStoreClientExt, fireBaseClientExt) - - phoneNumber := "+254700100200" - - type args struct { - ctx context.Context - phoneNumber string - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - phoneNumber: phoneNumber, - }, - wantErr: false, - }, - { - name: "Sad case", - args: args{ - ctx: ctx, - phoneNumber: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case" { - fakeFireStoreClientExt.GetAllFn = func(ctx context.Context, query *fb.GetAllQuery) ([]*firestore.DocumentSnapshot, error) { - docs := []*firestore.DocumentSnapshot{} - return docs, nil - } - } - - if tt.name == "Sad case" { - fakeFireStoreClientExt.GetAllFn = func(ctx context.Context, query *fb.GetAllQuery) ([]*firestore.DocumentSnapshot, error) { - return nil, fmt.Errorf("an error occurred") - } - } - - got, err := repo.GetAITDetails(tt.args.ctx, tt.args.phoneNumber) - if (err != nil) != tt.wantErr { - t.Errorf("Repository.GetAITDetails() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Repository.GetAITDetails() = %v, want %v", got, tt.want) - } - }) - } -} - func TestRepository_CreateRole(t *testing.T) { ctx := context.Background() var fireStoreClientExt fb.FirestoreClientExtension = &fakeFireStoreClientExt diff --git a/pkg/onboarding/presentation/config.go b/pkg/onboarding/presentation/config.go index 30b5dbb1..1ff8dbba 100644 --- a/pkg/onboarding/presentation/config.go +++ b/pkg/onboarding/presentation/config.go @@ -9,7 +9,6 @@ import ( "os" "time" - "github.com/savannahghi/onboarding/pkg/onboarding/usecases/ussd" "gitlab.slade360emr.com/go/apiclient" "go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux" @@ -139,7 +138,6 @@ func Router(ctx context.Context) (*mux.Router, error) { userpin := usecases.NewUserPinUseCase(repo, profile, baseExt, pinExt, engage) su := usecases.NewSignUpUseCases(repo, profile, userpin, supplier, baseExt, engage, pubSub) nhif := usecases.NewNHIFUseCases(repo, profile, baseExt, engage) - aitUssd := ussd.NewUssdUsecases(repo, baseExt, profile, userpin, su, pinExt, pubSub, crmExt) sms := usecases.NewSMSUsecase(repo, baseExt) role := usecases.NewRoleUseCases(repo, baseExt) adminSrv := adminSrv.NewService(baseExt) @@ -147,7 +145,7 @@ func Router(ctx context.Context) (*mux.Router, error) { i, err := interactor.NewOnboardingInteractor( profile, su, supplier, login, survey, userpin, engage, mes, nhif, pubSub, - sms, aitUssd, adminSrv, crmExt, + sms, adminSrv, crmExt, role, ) if err != nil { @@ -170,11 +168,6 @@ func Router(ctx context.Context) (*mux.Router, error) { // Add Middleware that records the metrics for HTTP routes r.Use(serverutils.CustomHTTPRequestMetricsMiddleware()) - //USSD routes - r.Path("/ait_ussd"). - Methods(http.MethodPost, http.MethodOptions). - HandlerFunc(h.IncomingUSSDHandler()) - // Unauthenticated routes r.Path("/optout").Methods(http.MethodPost, http.MethodOptions).HandlerFunc(h.OptOut()) r.Path("/switch_flagged_features").Methods( diff --git a/pkg/onboarding/presentation/graph/enums.graphql b/pkg/onboarding/presentation/graph/enums.graphql index 3f2bc36e..c52517c7 100644 --- a/pkg/onboarding/presentation/graph/enums.graphql +++ b/pkg/onboarding/presentation/graph/enums.graphql @@ -129,7 +129,6 @@ enum Payor { enum ChannelOfContact { APP - USSD SHORTCODE } diff --git a/pkg/onboarding/presentation/graph/generated/generated.go b/pkg/onboarding/presentation/graph/generated/generated.go index 736eb549..dee38e00 100644 --- a/pkg/onboarding/presentation/graph/generated/generated.go +++ b/pkg/onboarding/presentation/graph/generated/generated.go @@ -3677,7 +3677,6 @@ enum Payor { enum ChannelOfContact { APP - USSD SHORTCODE } diff --git a/pkg/onboarding/presentation/interactor/interactor.go b/pkg/onboarding/presentation/interactor/interactor.go index e44caa2d..8514859c 100644 --- a/pkg/onboarding/presentation/interactor/interactor.go +++ b/pkg/onboarding/presentation/interactor/interactor.go @@ -10,7 +10,6 @@ import ( pubsubmessaging "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/pubsub" "github.com/savannahghi/onboarding/pkg/onboarding/usecases" "github.com/savannahghi/onboarding/pkg/onboarding/usecases/admin" - "github.com/savannahghi/onboarding/pkg/onboarding/usecases/ussd" ) // Interactor represents an assemble of all use cases into a single object that can be instantiated anywhere @@ -26,7 +25,6 @@ type Interactor struct { NHIF usecases.NHIFUseCases PubSub pubsubmessaging.ServicePubSub SMS usecases.SMSUsecase - AITUSSD ussd.Usecase AdminSrv admin.Usecase CrmExt crm.ServiceCrm Role usecases.RoleUseCase @@ -45,7 +43,6 @@ func NewOnboardingInteractor( nhif usecases.NHIFUseCases, pubsub pubsubmessaging.ServicePubSub, sms usecases.SMSUsecase, - aitussd ussd.Usecase, admin admin.Usecase, crmExt crm.ServiceCrm, role usecases.RoleUseCase, @@ -63,7 +60,6 @@ func NewOnboardingInteractor( NHIF: nhif, PubSub: pubsub, SMS: sms, - AITUSSD: aitussd, AdminSrv: admin, CrmExt: crmExt, Role: role, diff --git a/pkg/onboarding/presentation/rest/handlers.go b/pkg/onboarding/presentation/rest/handlers.go index 8c6d1559..ffcae965 100644 --- a/pkg/onboarding/presentation/rest/handlers.go +++ b/pkg/onboarding/presentation/rest/handlers.go @@ -48,9 +48,7 @@ type HandlersInterfaces interface { RemoveRoleToUser() http.HandlerFunc UpdateUserProfile() http.HandlerFunc IncomingATSMS() http.HandlerFunc - IncomingUSSDHandler() http.HandlerFunc SwitchFlaggedFeaturesHandler() http.HandlerFunc - // USSDEndNotificationHandler() http.HandlerFunc PollServices() http.HandlerFunc CheckHasPermission() http.HandlerFunc @@ -1113,40 +1111,6 @@ func (h *HandlersInterfacesImpl) IncomingATSMS() http.HandlerFunc { } } -//IncomingUSSDHandler is a REST endpoint that is ussd create USSD -//The Content-Type from AIT is x-www-form-urlencoded -//To get the x-www-form-urlencoded request body we need to first call the below function on the request object -//It parses the query string present in the URL and populates the Form field of the request object -//https://golangbyexample.com/url-encoded-body-golang/ -func (h *HandlersInterfacesImpl) IncomingUSSDHandler() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - - p := &dto.SessionDetails{} - - err := r.ParseForm() - if err != nil { - errorcodeutil.ReportErr(w, err, http.StatusBadRequest) - return - } - - p.SessionID = r.PostForm.Get("sessionId") - phone := r.PostForm.Get("phoneNumber") - p.PhoneNumber = &phone - p.Text = r.PostForm.Get("text") - sessionDetails, err := utils.ValidateUSSDDetails(p) - if err != nil { - errorcodeutil.ReportErr(w, err, http.StatusBadRequest) - return - } - resp := h.interactor.AITUSSD.HandleResponseFromUSSDGateway( - ctx, - sessionDetails, - ) - fmt.Fprintf(w, "%s", resp) - } -} - // SwitchFlaggedFeaturesHandler flips the user as opt-in or opt-out to flagged features func (h *HandlersInterfacesImpl) SwitchFlaggedFeaturesHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/onboarding/presentation/rest/handlers_test.go b/pkg/onboarding/presentation/rest/handlers_test.go index f245deb5..16edc041 100644 --- a/pkg/onboarding/presentation/rest/handlers_test.go +++ b/pkg/onboarding/presentation/rest/handlers_test.go @@ -10,7 +10,6 @@ import ( "net/http" "net/http/httptest" "net/url" - "strconv" "strings" "testing" "time" @@ -40,7 +39,6 @@ import ( mockRepo "github.com/savannahghi/onboarding/pkg/onboarding/repository/mock" "github.com/savannahghi/onboarding/pkg/onboarding/usecases" adminSrv "github.com/savannahghi/onboarding/pkg/onboarding/usecases/admin" - "github.com/savannahghi/onboarding/pkg/onboarding/usecases/ussd" hubspotRepo "gitlab.slade360emr.com/go/commontools/crm/pkg/infrastructure/database/fs" hubspotUsecases "gitlab.slade360emr.com/go/commontools/crm/pkg/usecases" ) @@ -81,14 +79,13 @@ func InitializeFakeOnboardingInteractor() (*interactor.Interactor, error) { sms := usecases.NewSMSUsecase(r, ext) role := usecases.NewRoleUseCases(r, ext) - aitUssd := ussd.NewUssdUsecases(r, ext, profile, userpin, su, pinExt, ps, crmExt) adminSrv := adminSrv.NewService(ext) i, err := interactor.NewOnboardingInteractor( profile, su, supplier, login, survey, userpin, engagementSvc, messagingSvc, nhif, ps, sms, - aitUssd, adminSrv, crmExt, + adminSrv, crmExt, role, ) if err != nil { @@ -253,17 +250,6 @@ func composeSMSMessageDataPayload( return smspayload } -func composeUssdPayload(t *testing.T, payload *dto.SessionDetails) *strings.Reader { - data := url.Values{} - data.Set("phoneNumber", *payload.PhoneNumber) - data.Set("sessionId", payload.SessionID) - data.Set("text", payload.Text) - data.Set("level", strconv.Itoa(payload.Level)) - - ussdPayload := strings.NewReader(data.Encode()) - return ussdPayload -} - func TestHandlersInterfacesImpl_VerifySignUpPhoneNumber(t *testing.T) { i, err := InitializeFakeOnboardingInteractor() @@ -3577,149 +3563,6 @@ func TestHandlersInterfacesImpl_IncomingATSMS(t *testing.T) { } } -func TestHandlersInterfacesImpl_USSDHandler(t *testing.T) { - - i, err := InitializeFakeOnboardingInteractor() - if err != nil { - t.Errorf("failed to initialize onboarding interactor: %v", err) - return - } - h := rest.NewHandlersInterfaces(i) - - USSDPhoneNumber := "+254711445566" - invalidUSSDPhoneNumber := "" - sessionId := "123456778" - invalidSessionId := "" - text := "1" - level := 0 - - validPayload := &dto.SessionDetails{ - SessionID: sessionId, - PhoneNumber: &USSDPhoneNumber, - Level: level, - Text: text, - } - - invalidPayload := &dto.SessionDetails{ - SessionID: invalidSessionId, - PhoneNumber: &invalidUSSDPhoneNumber, - Level: level, - Text: text, - } - - validUSSDPayload := composeUssdPayload(t, validPayload) - invalidUSSDPayload := composeUssdPayload(t, invalidPayload) - - type args struct { - url string - httpMethod string - body io.Reader - } - tests := []struct { - name string - args args - wantStatus int - wantErr bool - }{ - { - name: "valid:_successful_USSD", - args: args{ - url: fmt.Sprintf("%s/ait_ussd", serverUrl), - httpMethod: http.MethodPost, - body: validUSSDPayload, - }, - wantStatus: http.StatusOK, - wantErr: false, - }, - { - name: "Invalid:_unsuccessful_USSD", - args: args{ - url: fmt.Sprintf("%s/ait_ussd", serverUrl), - httpMethod: http.MethodPost, - body: invalidUSSDPayload, - }, - wantStatus: http.StatusBadRequest, - wantErr: true, - }, - { - name: "Invalid:_nil_body", - args: args{ - url: fmt.Sprintf("%s/ait_ussd", serverUrl), - httpMethod: http.MethodPost, - body: nil, - }, - wantStatus: http.StatusBadRequest, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - req, err := http.NewRequest(tt.args.httpMethod, tt.args.url, tt.args.body) - if err != nil { - t.Errorf("can't create new request: %v", err) - return - } - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - response := httptest.NewRecorder() - if tt.name == "valid:_successful_USSD" { - fakeBaseExt.NormalizeMSISDNFn = func(msisdn string) (*string, error) { - phone := "+254721026491" - return &phone, nil - } - - fakeRepo.AddAITSessionDetailsFn = func(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{ - ID: uuid.New().String(), - SessionID: input.SessionID, - PhoneNumber: *input.PhoneNumber, - Level: input.Level, - }, nil - } - - fakeRepo.UpdateSessionLevelFn = func(ctx context.Context, sessionID string, level int) (*domain.USSDLeadDetails, error) { - return nil, nil - } - - fakeRepo.GetAITSessionDetailsFn = func(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{ - Level: 2, - }, nil - } - - fakeRepo.CheckIfPhoneNumberExistsFn = func(ctx context.Context, phone string) (bool, error) { - return true, nil - } - fakeRepo.UpdateSessionPINFn = func(ctx context.Context, sessionID, pin string) (*domain.USSDLeadDetails, error) { - return nil, nil - } - } - if tt.name == "Invalid:_unsuccessful_USSD" { - fakeBaseExt.NormalizeMSISDNFn = func(msisdn string) (*string, error) { - return nil, fmt.Errorf("empty phone number") - } - } - svr := h.IncomingUSSDHandler() - svr.ServeHTTP(response, req) - - if tt.wantStatus != response.Code { - t.Errorf("expected status %d, got %d", tt.wantStatus, response.Code) - return - } - - dataResponse, err := ioutil.ReadAll(response.Body) - if err != nil { - t.Errorf("can't read response body: %v", err) - return - } - if dataResponse == nil { - t.Errorf("nil response body data") - return - } - - }) - } -} - func TestHandlers_PollServices(t *testing.T) { i, err := InitializeFakeOnboardingInteractor() if err != nil { diff --git a/pkg/onboarding/repository/mock/onboarding.go b/pkg/onboarding/repository/mock/onboarding.go index 0267f744..c995a90e 100644 --- a/pkg/onboarding/repository/mock/onboarding.go +++ b/pkg/onboarding/repository/mock/onboarding.go @@ -146,11 +146,6 @@ type FakeOnboardingRepository struct { PersistIncomingSMSDataFn func(ctx context.Context, input *dto.AfricasTalkingMessage) error - AddAITSessionDetailsFn func(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) - GetAITSessionDetailsFn func(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) - UpdateSessionLevelFn func(ctx context.Context, sessionID string, level int) (*domain.USSDLeadDetails, error) - UpdateSessionPINFn func(ctx context.Context, sessionID string, pin string) (*domain.USSDLeadDetails, error) - UpdateCustomerProfileFn func( ctx context.Context, profileID string, @@ -176,13 +171,8 @@ type FakeOnboardingRepository struct { UpdateAddressesFn func(ctx context.Context, id string, address profileutils.Address, addressType enumutils.AddressType) error ListUserProfilesFn func(ctx context.Context, role profileutils.RoleType) ([]*profileutils.UserProfile, error) UpdateOptOutFn func(ctx context.Context, option string, phoneNumber string) error - UpdateAITSessionDetailsFn func(ctx context.Context, phoneNumber string, contactLead *domain.USSDLeadDetails) error UpdateFavNavActionsFn func(ctx context.Context, id string, favActions []string) error GetUserMarketingDataFn func(ctx context.Context, phoneNumber string) (*dto.Segment, error) - HandleResponseFromUSSDGatewayFn func(context context.Context, input *dto.SessionDetails) string - SetUSSDUserPinFn func(ctx context.Context, phoneNumber string, PIN string) error - SaveUSSDEventFn func(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) - GetAITDetailsFn func(ctx context.Context, phoneNumber string) (*domain.USSDLeadDetails, error) //roles CreateRoleFn func(ctx context.Context, profileID string, role dto.RoleInput) (*profileutils.Role, error) @@ -778,40 +768,6 @@ func (f *FakeOnboardingRepository) PersistIncomingSMSData( return f.PersistIncomingSMSDataFn(ctx, input) } -//AddAITSessionDetails ... -func (f *FakeOnboardingRepository) AddAITSessionDetails( - ctx context.Context, - input *dto.SessionDetails, -) (*domain.USSDLeadDetails, error) { - return f.AddAITSessionDetailsFn(ctx, input) -} - -//GetAITSessionDetails ... -func (f *FakeOnboardingRepository) GetAITSessionDetails( - ctx context.Context, - sessionID string, -) (*domain.USSDLeadDetails, error) { - return f.GetAITSessionDetailsFn(ctx, sessionID) -} - -//UpdateSessionLevel ... -func (f *FakeOnboardingRepository) UpdateSessionLevel( - ctx context.Context, - sessionID string, - level int, -) (*domain.USSDLeadDetails, error) { - return f.UpdateSessionLevelFn(ctx, sessionID, level) -} - -//UpdateSessionPIN ... -func (f *FakeOnboardingRepository) UpdateSessionPIN( - ctx context.Context, - sessionID string, - pin string, -) (*domain.USSDLeadDetails, error) { - return f.UpdateSessionPINFn(ctx, sessionID, pin) -} - // ListUserProfiles ... func (f *FakeOnboardingRepository) ListUserProfiles( ctx context.Context, @@ -838,23 +794,6 @@ func (f *FakeOnboardingRepository) CreateDetailedSupplierProfile( return f.CreateDetailedSupplierProfileFn(ctx, profileID, supplier) } -// UpdateAITSessionDetails ... -func (f *FakeOnboardingRepository) UpdateAITSessionDetails( - ctx context.Context, - phoneNumber string, - contactLead *domain.USSDLeadDetails, -) error { - return f.UpdateAITSessionDetailsFn(ctx, phoneNumber, contactLead) -} - -// GetAITDetails ... -func (f *FakeOnboardingRepository) GetAITDetails( - ctx context.Context, - phoneNumber string, -) (*domain.USSDLeadDetails, error) { - return f.GetAITDetailsFn(ctx, phoneNumber) -} - // UpdateFavNavActions ... func (f *FakeOnboardingRepository) UpdateFavNavActions( ctx context.Context, @@ -872,31 +811,6 @@ func (f *FakeOnboardingRepository) GetUserMarketingData( return f.GetUserMarketingDataFn(ctx, phoneNumber) } -// HandleResponseFromUSSDGateway ... -func (f *FakeOnboardingRepository) HandleResponseFromUSSDGateway( - context context.Context, - input *dto.SessionDetails, -) string { - return f.HandleResponseFromUSSDGatewayFn(context, input) -} - -// SetUSSDUserPin ... -func (f *FakeOnboardingRepository) SetUSSDUserPin( - ctx context.Context, - phoneNumber string, - PIN string, -) error { - return f.SetUSSDUserPinFn(ctx, phoneNumber, PIN) -} - -// SaveUSSDEvent ... -func (f *FakeOnboardingRepository) SaveUSSDEvent( - ctx context.Context, - input *dto.USSDEvent, -) (*dto.USSDEvent, error) { - return f.SaveUSSDEventFn(ctx, input) -} - //CreateRole ... func (f *FakeOnboardingRepository) CreateRole( ctx context.Context, diff --git a/pkg/onboarding/repository/onboarding.go b/pkg/onboarding/repository/onboarding.go index c7da31e7..c400a05a 100644 --- a/pkg/onboarding/repository/onboarding.go +++ b/pkg/onboarding/repository/onboarding.go @@ -243,31 +243,6 @@ type OnboardingRepository interface { allowWhatsApp *bool, allowTextSms *bool, allowPush *bool, allowEmail *bool) (*profileutils.UserCommunicationsSetting, error) PersistIncomingSMSData(ctx context.Context, input *dto.AfricasTalkingMessage) error - - AddAITSessionDetails( - ctx context.Context, - input *dto.SessionDetails, - ) (*domain.USSDLeadDetails, error) - GetAITSessionDetails(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) - UpdateSessionLevel( - ctx context.Context, - sessionID string, - level int, - ) (*domain.USSDLeadDetails, error) - UpdateSessionPIN( - ctx context.Context, - sessionID string, - pin string, - ) (*domain.USSDLeadDetails, error) - - UpdateAITSessionDetails( - ctx context.Context, - phoneNumber string, - payload *domain.USSDLeadDetails, - ) error - GetAITDetails(ctx context.Context, phoneNumber string) (*domain.USSDLeadDetails, error) - - SaveUSSDEvent(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) } // UserProfileRepository interface that provide access to all persistent storage operations for user profile diff --git a/pkg/onboarding/usecases/login_test.go b/pkg/onboarding/usecases/login_test.go index 06416034..59e25eee 100644 --- a/pkg/onboarding/usecases/login_test.go +++ b/pkg/onboarding/usecases/login_test.go @@ -24,7 +24,6 @@ import ( "github.com/savannahghi/onboarding/pkg/onboarding/presentation/interactor" "github.com/savannahghi/onboarding/pkg/onboarding/repository" "github.com/savannahghi/onboarding/pkg/onboarding/usecases" - "github.com/savannahghi/onboarding/pkg/onboarding/usecases/ussd" "github.com/savannahghi/profileutils" "github.com/savannahghi/serverutils" "gitlab.slade360emr.com/go/commontools/crm/pkg/infrastructure/services/hubspot" @@ -96,7 +95,6 @@ func TestMain(m *testing.M) { r.GetNHIFDetailsCollectionName(), r.GetProfileNudgesCollectionName(), r.GetSMSCollectionName(), - r.GetUSSDDataCollectionName(), r.GetRolesCollectionName(), } for _, collection := range collections { @@ -217,8 +215,6 @@ func InitializeTestService(ctx context.Context) (*interactor.Interactor, error) nhif := usecases.NewNHIFUseCases(repo, profile, ext, engage) sms := usecases.NewSMSUsecase(repo, ext) - aitUssd := ussd.NewUssdUsecases(repo, ext, profile, userpin, su, pinExt, ps, crmExt) - return &interactor.Interactor{ Onboarding: profile, Signup: su, @@ -230,7 +226,6 @@ func InitializeTestService(ctx context.Context) (*interactor.Interactor, error) NHIF: nhif, PubSub: ps, SMS: sms, - AITUSSD: aitUssd, CrmExt: crmExt, }, nil } @@ -464,7 +459,6 @@ func InitializeFakeOnboardingInteractor() (*interactor.Interactor, error) { userpin := usecases.NewUserPinUseCase(r, profile, ext, pinExt, engagementSvc) su := usecases.NewSignUpUseCases(r, profile, userpin, supplier, ext, engagementSvc, ps) nhif := usecases.NewNHIFUseCases(r, profile, ext, engagementSvc) - aitUssd := ussd.NewUssdUsecases(r, ext, profile, userpin, su, pinExt, ps, crmExt) adminSrv := adminSrv.NewService(ext) sms := usecases.NewSMSUsecase(r, ext) role := usecases.NewRoleUseCases(r, ext) @@ -473,7 +467,7 @@ func InitializeFakeOnboardingInteractor() (*interactor.Interactor, error) { profile, su, supplier, login, survey, userpin, engagementSvc, messagingSvc, nhif, ps, sms, - aitUssd, adminSrv, crmExt, + adminSrv, crmExt, role, ) if err != nil { diff --git a/pkg/onboarding/usecases/ussd/login.go b/pkg/onboarding/usecases/ussd/login.go deleted file mode 100644 index 12f4034a..00000000 --- a/pkg/onboarding/usecases/ussd/login.go +++ /dev/null @@ -1,114 +0,0 @@ -package ussd - -import ( - "context" - "time" - - "github.com/savannahghi/feedlib" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "go.opentelemetry.io/otel" -) - -const ( - //USSDLoginDialEvent ... - USSDLoginDialEvent = "dialled to login" -) - -var tracer = otel.Tracer("github.com/savannahghi/onboarding/pkg/onboarding/usecases/ussd") - -// HandleLogin represents the workflow for authenticating a user -func (u *Impl) HandleLogin(ctx context.Context, session *domain.USSDLeadDetails, userResponse string) string { - ctx, span := tracer.Start(ctx, "HandleLogin") - defer span.End() - - time := time.Now() - - switch userResponse { - case EmptyInput: - resp := "CON Welcome to Be.Well.Please enter\r\n" - resp += "your PIN to continue(enter 00 if\r\n" - resp += "you forgot your PIN)\r\n" - // Capture login event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - USSDEventName: USSDLoginDialEvent, - }); err != nil { - return "END Something went wrong. Please try again." - } - return resp - - case ForgotPINInput: - err := u.UpdateSessionLevel(ctx, ForgotPINVerifyDate, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - resp := "CON Please enter your date of birth in\r\n" - resp += "DDMMYYYY format e.g 14031996 for\r\n" - resp += "14th March 1996\r\n" - resp += "to be able to reset PIN\r\n" - return resp - - default: - isLoggedIn, err := u.LoginInUser(ctx, session.PhoneNumber, userResponse, feedlib.FlavourConsumer) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - if !isLoggedIn { - resp := "CON The PIN you entered is not correct\r\n" - resp += "Please try again (enter 00 if you\r\n" - resp += "forgot your PIN)" - return resp - } - err = u.UpdateSessionLevel(ctx, HomeMenuState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - userResponse := "" - return u.HandleHomeMenu(ctx, HomeMenuState, session, userResponse) - } - -} - -// LoginInUser authenticates a user to allow them proceed to the home menu -func (u *Impl) LoginInUser( - ctx context.Context, - phone string, - PIN string, - flavour feedlib.Flavour, -) (bool, error) { - ctx, span := tracer.Start(ctx, "LoginInUser") - defer span.End() - - profile, err := u.onboardingRepository.GetUserProfileByPrimaryPhoneNumber( - ctx, - phone, - false, - ) - if err != nil { - utils.RecordSpanError(span, err) - return false, err - } - - PINData, err := u.onboardingRepository.GetPINByProfileID(ctx, profile.ID) - if err != nil { - utils.RecordSpanError(span, err) - return false, err - } - if PINData == nil { - return false, err - } - matched := u.pinExt.ComparePIN(PIN, PINData.Salt, PINData.PINNumber, nil) - if !matched { - return false, nil - - } - return true, nil - -} diff --git a/pkg/onboarding/usecases/ussd/login_integration_test.go b/pkg/onboarding/usecases/ussd/login_integration_test.go deleted file mode 100644 index 4520da80..00000000 --- a/pkg/onboarding/usecases/ussd/login_integration_test.go +++ /dev/null @@ -1,146 +0,0 @@ -package ussd_test - -import ( - "context" - "testing" - - "github.com/brianvoe/gofakeit" - "github.com/google/uuid" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/scalarutils" -) - -const ( - // EmptyInput is used to load a default menu when user has not supplied any input - EmptyInput = "" - // ForgotPINInput indicates the user has forgotten their PIN and would like to reset it - ForgotPINInput = "00" - //ForgotPINVerifyDate indicates the state when a use wants to reset PIN - ForgotPINVerifyDate = 15 -) - -func TestImpl_HandleLogin_Integration_Test(t *testing.T) { - ctx := context.Background() - u, err := InitializeTestService(ctx) - if err != nil { - t.Errorf("unable to initialize service %v", err) - return - } - - phoneNumber := "+254700100200" - PIN := "1234" - FirstName := gofakeit.LastName() - LastName := gofakeit.LastName() - SessionID := uuid.New().String() - Level := 0 - - ussdDet := &domain.USSDLeadDetails{ - ID: gofakeit.UUID(), - Level: Level, - PhoneNumber: phoneNumber, - SessionID: SessionID, - FirstName: FirstName, - LastName: LastName, - DateOfBirth: scalarutils.Date{}, - PIN: PIN, - } - - sessionDet := &dto.SessionDetails{ - SessionID: SessionID, - PhoneNumber: &phoneNumber, - Level: Level, - Text: "", - } - - sessionDetails, err := u.AITUSSD.AddAITSessionDetails(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - type args struct { - ctx context.Context - session *domain.USSDLeadDetails - userResponse string - } - tests := []struct { - name string - args args - want string - }{ - { - name: "Happy case : empty input", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: EmptyInput, - }, - want: "CON Welcome to Be.Well.Please enter\r\n" + - "your PIN to continue(enter 00 if\r\n" + - "you forgot your PIN)\r\n", - }, - - { - name: "Happy case : forgot PIN", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: ForgotPINInput, - }, - want: "CON Please enter your date of birth in\r\n" + - "DDMMYYYY format e.g 14031996 for\r\n" + - "14th March 1996\r\n" + - "to be able to reset PIN\r\n", - }, - - { - name: "Sad case : forgot PIN", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "01", - }, - want: "END Something went wrong. Please try again.", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case : empty input" { - - err = u.AITUSSD.UpdateSessionLevel(ctx, HomeMenuState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Happy case : forgot PIN" { - err = u.AITUSSD.UpdateSessionLevel(ctx, ForgotPINVerifyDate, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Sad case : forgot PIN" { - err = u.AITUSSD.UpdateSessionLevel(ctx, HomeMenuState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - session, err := u.AITUSSD.GetOrCreateSessionState(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - login := u - got := login.AITUSSD.HandleLogin(tt.args.ctx, session, tt.args.userResponse) - if got != tt.want { - t.Errorf("Impl.HandleLogin() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/login_unit_test.go b/pkg/onboarding/usecases/ussd/login_unit_test.go deleted file mode 100644 index d34b906f..00000000 --- a/pkg/onboarding/usecases/ussd/login_unit_test.go +++ /dev/null @@ -1,170 +0,0 @@ -package ussd_test - -import ( - "context" - "testing" - - "github.com/brianvoe/gofakeit" - "github.com/google/uuid" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/extension" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/profileutils" - "github.com/savannahghi/scalarutils" -) - -func TestUSSDImpl_HandleLogin_Unittest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("unable to initialize service %v", err) - return - } - - phoneNumber := "+254700100200" - PIN := "1234" - FirstName := gofakeit.LastName() - LastName := gofakeit.LastName() - SessionID := uuid.New().String() - Level := 0 - - ussdDet := &domain.USSDLeadDetails{ - ID: gofakeit.UUID(), - Level: Level, - PhoneNumber: phoneNumber, - SessionID: SessionID, - FirstName: FirstName, - LastName: LastName, - DateOfBirth: scalarutils.Date{}, - PIN: PIN, - } - - sessionDet := &dto.SessionDetails{ - SessionID: SessionID, - PhoneNumber: &phoneNumber, - Level: Level, - Text: "", - } - - type args struct { - ctx context.Context - session *domain.USSDLeadDetails - userResponse string - } - tests := []struct { - name string - args args - want string - }{ - { - name: "Happy case : empty input", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: EmptyInput, - }, - want: "CON Welcome to Be.Well.Please enter\r\n" + - "your PIN to continue(enter 00 if\r\n" + - "you forgot your PIN)\r\n", - }, - - { - name: "Sad case : bad login PIN", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "1", - }, - want: "CON The PIN you entered is not correct\r\n" + - "Please try again (enter 00 if you\r\n" + - "forgot your PIN)", - }, - - { - name: "Sad case : bad login PIN longer than 4 digits", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "12345", - }, - want: "CON The PIN you entered is not correct\r\n" + - "Please try again (enter 00 if you\r\n" + - "forgot your PIN)", - }, - - { - name: "Sad case : invalid input", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "hello", - }, - want: "CON The PIN you entered is not correct\r\n" + - "Please try again (enter 00 if you\r\n" + - "forgot your PIN)", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case : empty input" { - fakeRepo.AddAITSessionDetailsFn = func(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{}, nil - } - - fakeRepo.GetAITSessionDetailsFn = func(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{}, nil - } - - fakeRepo.SaveUSSDEventFn = func(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) { - return &dto.USSDEvent{}, nil - } - } - - if tt.name == "Sad case : bad login PIN" { - fakeRepo.GetUserProfileByPrimaryPhoneNumberFn = func(ctx context.Context, phoneNumber string, suspended bool) (*profileutils.UserProfile, error) { - return &profileutils.UserProfile{}, nil - } - - fakeRepo.GetPINByProfileIDFn = func(ctx context.Context, ProfileID string) (*domain.PIN, error) { - return nil, err - } - - fakePinExt.ComparePINFn = func(rawPwd, salt, encodedPwd string, options *extension.Options) bool { - return false - } - } - - if tt.name == "Sad case : bad login PIN longer than 4 digits" { - fakeRepo.GetPINByProfileIDFn = func(ctx context.Context, ProfileID string) (*domain.PIN, error) { - return nil, err - } - - fakePinExt.ComparePINFn = func(rawPwd, salt, encodedPwd string, options *extension.Options) bool { - return false - } - } - - if tt.name == "Sad case : invalid input" { - - fakeRepo.GetPINByProfileIDFn = func(ctx context.Context, ProfileID string) (*domain.PIN, error) { - return nil, err - } - - fakePinExt.ComparePINFn = func(rawPwd, salt, encodedPwd string, options *extension.Options) bool { - return false - } - } - - session, err := u.AITUSSD.GetOrCreateSessionState(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - if got := u.AITUSSD.HandleLogin(tt.args.ctx, session, tt.args.userResponse); got != tt.want { - t.Errorf("Impl.HandleLogin() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/main.go b/pkg/onboarding/usecases/ussd/main.go deleted file mode 100644 index 0a121152..00000000 --- a/pkg/onboarding/usecases/ussd/main.go +++ /dev/null @@ -1,138 +0,0 @@ -package ussd - -import ( - "context" - - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/onboarding/pkg/onboarding/usecases" - "github.com/savannahghi/profileutils" - - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/extension" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/crm" - pubsubmessaging "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/pubsub" - "github.com/savannahghi/onboarding/pkg/onboarding/repository" -) - -const ( - // LoginUserState handles workflow required to authenticate/login a user - LoginUserState = 0 - //HomeMenuState represents inner submenu once user is logged in - HomeMenuState = 5 - // ChangeUserPINState represents workflows required to set a user PIN - ChangeUserPINState = 50 - // UserPINResetState represents workflows required to reset a forgotten user PIN - UserPINResetState = 10 - // EmptyInput is used to load a default menu when user has not supplied any input - EmptyInput = "" - // GoBackHomeInput represents the user intention to go back to the main menu - GoBackHomeInput = "0" -) - -//Usecase represent the logic involved in processing USSD requests -type Usecase interface { - HandleResponseFromUSSDGateway(context context.Context, input *dto.SessionDetails) string - HandleUserRegistration(ctx context.Context, sessionDetails *domain.USSDLeadDetails, userResponse string) string - HandleHomeMenu(ctx context.Context, level int, session *domain.USSDLeadDetails, userResponse string) string - CreateUsddUserProfile(ctx context.Context, phoneNumber string, PIN string, userProfile *dto.UserProfileInput) error - HandleLogin(ctx context.Context, session *domain.USSDLeadDetails, userResponse string) string - // session usecases - GetOrCreateSessionState(ctx context.Context, payload *dto.SessionDetails) (*domain.USSDLeadDetails, error) - AddAITSessionDetails(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) - UpdateSessionLevel(ctx context.Context, level int, sessionID string) error - UpdateSessionPIN(ctx context.Context, pin string, sessionID string) (*domain.USSDLeadDetails, error) - // USSD PIN usecases - HandleChangePIN(ctx context.Context, session *domain.USSDLeadDetails, userResponse string) string - HandlePINReset(ctx context.Context, session *domain.USSDLeadDetails, userResponse string) string - SetUSSDUserPin(ctx context.Context, phoneNumber string, PIN string) error - ChangeUSSDUserPIN(ctx context.Context, phone string, pin string) (bool, error) - - // Onboarding - GetOrCreatePhoneNumberUser(ctx context.Context, phone string) (*dto.CreatedUserResponse, error) - CreateUserProfile(ctx context.Context, phoneNumber, uid string) (*profileutils.UserProfile, error) - CreateEmptyCustomerProfile(ctx context.Context, profileID string) (*profileutils.Customer, error) - UpdateBioData(ctx context.Context, id string, data profileutils.BioData) error - GetUserProfileByPrimaryPhoneNumber(ctx context.Context, phoneNumber string, suspend bool) (*profileutils.UserProfile, error) - RemoveUserByPhoneNumber(ctx context.Context, phone string) error - SetUserPIN(ctx context.Context, pin string, profileID string) (bool, error) - //USSD Metrics Event - SaveUSSDEvent(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) -} - -//Impl represents usecase implementation -type Impl struct { - baseExt extension.BaseExtension - onboardingRepository repository.OnboardingRepository - profile usecases.ProfileUseCase - pinUsecase usecases.UserPINUseCases - signUp usecases.SignUpUseCases - pinExt extension.PINExtension - pubsub pubsubmessaging.ServicePubSub - crm crm.ServiceCrm -} - -//NewUssdUsecases returns a new USSD usecase -func NewUssdUsecases( - repository repository.OnboardingRepository, - ext extension.BaseExtension, - profileUsecase usecases.ProfileUseCase, - pinUsecase usecases.UserPINUseCases, - signUp usecases.SignUpUseCases, - pinExt extension.PINExtension, - pubsub pubsubmessaging.ServicePubSub, - crm crm.ServiceCrm, -) Usecase { - return &Impl{ - baseExt: ext, - onboardingRepository: repository, - profile: profileUsecase, - pinUsecase: pinUsecase, - signUp: signUp, - pinExt: pinExt, - pubsub: pubsub, - crm: crm, - } -} - -//HandleResponseFromUSSDGateway receives and processes the USSD response from the USSD gateway -func (u *Impl) HandleResponseFromUSSDGateway(ctx context.Context, payload *dto.SessionDetails) string { - ctx, span := tracer.Start(ctx, "HandleResponseFromUSSDGateway") - defer span.End() - - sessionDetails, err := u.GetOrCreateSessionState(ctx, payload) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - - userResponse := utils.GetUserResponse(payload.Text) - - exists, err := u.profile.CheckPhoneExists(ctx, *payload.PhoneNumber) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - - if !exists { - return u.HandleUserRegistration(ctx, sessionDetails, userResponse) - } - - switch { - case sessionDetails.Level == LoginUserState: - return u.HandleLogin(ctx, sessionDetails, userResponse) - - case sessionDetails.Level == HomeMenuState: - return u.HandleHomeMenu(ctx, HomeMenuState, sessionDetails, userResponse) - - case sessionDetails.Level >= ChangeUserPINState: - return u.HandleChangePIN(ctx, sessionDetails, userResponse) - - case sessionDetails.Level >= UserPINResetState: - return u.HandlePINReset(ctx, sessionDetails, userResponse) - - default: - return "END Something went wrong. Please try again." - } - -} diff --git a/pkg/onboarding/usecases/ussd/main_integration_test.go b/pkg/onboarding/usecases/ussd/main_integration_test.go deleted file mode 100644 index 0e79268b..00000000 --- a/pkg/onboarding/usecases/ussd/main_integration_test.go +++ /dev/null @@ -1,308 +0,0 @@ -package ussd_test - -import ( - "context" - "fmt" - "log" - "testing" - - "cloud.google.com/go/pubsub" - "github.com/google/uuid" - "github.com/savannahghi/firebasetools" - "github.com/savannahghi/interserviceclient" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/extension" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/database/fb" - "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/engagement" - "github.com/savannahghi/serverutils" - "gitlab.slade360emr.com/go/commontools/crm/pkg/infrastructure/services/hubspot" - - "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/messaging" - pubsubmessaging "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/pubsub" - "github.com/savannahghi/onboarding/pkg/onboarding/presentation/interactor" - "github.com/savannahghi/onboarding/pkg/onboarding/repository" - "github.com/savannahghi/onboarding/pkg/onboarding/usecases" - "github.com/savannahghi/onboarding/pkg/onboarding/usecases/ussd" - - mockCrm "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/crm/mock" - mockRepo "github.com/savannahghi/onboarding/pkg/onboarding/repository/mock" - - extMock "github.com/savannahghi/onboarding/pkg/onboarding/application/extension/mock" - engagementMock "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/engagement/mock" - - crmExt "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/crm" - messagingMock "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/messaging/mock" - pubsubmessagingMock "github.com/savannahghi/onboarding/pkg/onboarding/infrastructure/services/pubsub/mock" - adminSrv "github.com/savannahghi/onboarding/pkg/onboarding/usecases/admin" - hubspotRepo "gitlab.slade360emr.com/go/commontools/crm/pkg/infrastructure/database/fs" - hubspotUsecases "gitlab.slade360emr.com/go/commontools/crm/pkg/usecases" -) - -const ( - otpService = "otp" - engagementService = "engagement" -) - -func InitializeTestService(ctx context.Context) (*interactor.Interactor, error) { - fc := firebasetools.FirebaseClient{} - fa, err := fc.InitFirebase() - if err != nil { - log.Fatalf("unable to initialize Firestore for the Feed: %s", err) - } - - fsc, err := fa.Firestore(ctx) - if err != nil { - log.Fatalf("unable to initialize Firestore: %s", err) - } - - fbc, err := fa.Auth(ctx) - if err != nil { - log.Panicf("can't initialize Firebase auth when setting up profile service: %s", err) - } - - var repo repository.OnboardingRepository - - if serverutils.MustGetEnvVar(domain.Repo) == domain.FirebaseRepository { - firestoreExtension := fb.NewFirestoreClientExtension(fsc) - repo = fb.NewFirebaseRepository(firestoreExtension, fbc) - } - - projectID, err := serverutils.GetEnvVar(serverutils.GoogleCloudProjectIDEnvVarName) - if err != nil { - return nil, fmt.Errorf( - "can't get projectID from env var `%s`: %w", - serverutils.GoogleCloudProjectIDEnvVarName, - err, - ) - } - pubSubClient, err := pubsub.NewClient(ctx, projectID) - if err != nil { - return nil, fmt.Errorf("unable to initialize pubsub client: %w", err) - } - - ext := extension.NewBaseExtensionImpl(&firebasetools.FirebaseClient{}) - - // Initialize ISC clients - engagementClient := utils.NewInterServiceClient(engagementService, ext) - - hubspotService := hubspot.NewHubSpotService() - hubspotfr, err := hubspotRepo.NewHubSpotFirebaseRepository(context.Background(), hubspotService) - if err != nil { - return nil, fmt.Errorf("failed to initialize hubspot crm repository: %w", err) - } - hubspotUsecases := hubspotUsecases.NewHubSpotUsecases(hubspotfr) - crmExt := crmExt.NewCrmService(hubspotUsecases) - engage := engagement.NewServiceEngagementImpl(engagementClient, ext) - ps, err := pubsubmessaging.NewServicePubSubMessaging( - pubSubClient, - ext, - crmExt, - repo, - ) - if err != nil { - return nil, fmt.Errorf("unable to initialize new pubsub messaging service: %w", err) - } - mes := messaging.NewServiceMessagingImpl(ext) - pinExt := extension.NewPINExtensionImpl() - profile := usecases.NewProfileUseCase(repo, ext, engage, ps, crmExt) - - supplier := usecases.NewSupplierUseCases(repo, profile, engage, mes, ext, ps) - login := usecases.NewLoginUseCases(repo, profile, ext, pinExt) - survey := usecases.NewSurveyUseCases(repo, ext) - userpin := usecases.NewUserPinUseCase(repo, profile, ext, pinExt, engage) - su := usecases.NewSignUpUseCases(repo, profile, userpin, supplier, ext, engage, ps) - nhif := usecases.NewNHIFUseCases(repo, profile, ext, engage) - sms := usecases.NewSMSUsecase(repo, ext) - - aitUssd := ussd.NewUssdUsecases(repo, ext, profile, userpin, su, pinExt, ps, crmExt) - - return &interactor.Interactor{ - Onboarding: profile, - Signup: su, - Supplier: supplier, - Login: login, - Survey: survey, - UserPIN: userpin, - Engagement: engage, - NHIF: nhif, - PubSub: ps, - SMS: sms, - AITUSSD: aitUssd, - CrmExt: crmExt, - }, nil -} - -// InitializeFakeOnboaridingInteractor represents a fakeonboarding interactor -func InitializeFakeOnboardingInteractor() (*interactor.Interactor, error) { - var r repository.OnboardingRepository = &fakeRepo - - var engagementSvc engagement.ServiceEngagement = &fakeEngagementSvs - var messagingSvc messaging.ServiceMessaging = &fakeMessagingSvc - var ext extension.BaseExtension = &fakeBaseExt - var pinExt extension.PINExtension = &fakePinExt - var ps pubsubmessaging.ServicePubSub = &fakePubSub - - hubspotService := hubspot.NewHubSpotService() - hubspotfr, err := hubspotRepo.NewHubSpotFirebaseRepository(context.Background(), hubspotService) - if err != nil { - return nil, fmt.Errorf("failed to initialize hubspot crm repository: %w", err) - } - hubspotUsecases := hubspotUsecases.NewHubSpotUsecases(hubspotfr) - crmExt := crmExt.NewCrmService(hubspotUsecases) - profile := usecases.NewProfileUseCase(r, ext, engagementSvc, ps, crmExt) - login := usecases.NewLoginUseCases(r, profile, ext, pinExt) - survey := usecases.NewSurveyUseCases(r, ext) - supplier := usecases.NewSupplierUseCases( - r, profile, engagementSvc, messagingSvc, ext, ps, - ) - userpin := usecases.NewUserPinUseCase(r, profile, ext, pinExt, engagementSvc) - su := usecases.NewSignUpUseCases(r, profile, userpin, supplier, ext, engagementSvc, ps) - nhif := usecases.NewNHIFUseCases(r, profile, ext, engagementSvc) - sms := usecases.NewSMSUsecase(r, ext) - role := usecases.NewRoleUseCases(r, ext) - - aitUssd := ussd.NewUssdUsecases(r, ext, profile, userpin, su, pinExt, ps, crmExt) - adminSrv := adminSrv.NewService(ext) - - i, err := interactor.NewOnboardingInteractor( - profile, su, supplier, login, - survey, userpin, - engagementSvc, messagingSvc, nhif, ps, sms, aitUssd, adminSrv, crmExt, - role, - ) - if err != nil { - return nil, fmt.Errorf("can't instantiate service : %w", err) - } - return i, nil - -} - -func TestImpl_HandleResponseFromUSSDGateway(t *testing.T) { - ctx := context.Background() - - u, err := InitializeTestService(ctx) - if err != nil { - t.Errorf("unable to initialize service") - return - } - - unregisteredPhoneNumber := "0723456756" - registeredPhoneNumber := interserviceclient.TestUserPhoneNumber - - unregisteredValidPayload := &dto.SessionDetails{ - SessionID: uuid.New().String(), - PhoneNumber: &unregisteredPhoneNumber, - } - - // registeredValidPayload := &dto.SessionDetails{ - // SessionID: uuid.New().String(), - // PhoneNumber: ®isteredPhoneNumber, - // } - - invalidPayload := &dto.SessionDetails{ - SessionID: "", - PhoneNumber: ®isteredPhoneNumber, - } - - type args struct { - ctx context.Context - payload *dto.SessionDetails - } - tests := []struct { - name string - args args - want string - }{ - { - name: "Happy case ):_Success case_Unregistered_user", - args: args{ - ctx: ctx, - payload: unregisteredValidPayload, - }, - want: "CON Welcome to Be.Well\r\n" + - "1. Register\r\n" + - "2. Opt Out\r\n", - }, - // { - // name: "Happy case ):_Success case_Registered_user", - // args: args{ - // ctx: ctx, - // payload: registeredValidPayload, - // }, - // want: "CON Welcome to Be.Well.Please enter\r\n" + - // "your PIN to continue(enter 00 if\r\n" + - // "you forgot your PIN)\r\n", - // }, - { - name: "SAD case ):Fail case_invalid_sessionID", - args: args{ - ctx: ctx, - payload: invalidPayload, - }, - want: "END Something went wrong. Please try again.", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ussd := u - got := ussd.AITUSSD.HandleResponseFromUSSDGateway(tt.args.ctx, tt.args.payload) - if got != tt.want { - t.Errorf("Impl.HandleResponseFromUSSDGateway() = %v, want %v", got, tt.want) - } - }) - } -} - -var fakeRepo mockRepo.FakeOnboardingRepository -var fakeBaseExt extMock.FakeBaseExtensionImpl -var fakePinExt extMock.PINExtensionImpl -var fakeEngagementSvs engagementMock.FakeServiceEngagement -var fakeMessagingSvc messagingMock.FakeServiceMessaging -var fakePubSub pubsubmessagingMock.FakeServicePubSub -var fakeCrm mockCrm.FakeServiceCrm - -// InitializeFakeUSSDTestService represents a fakeussd interactor -func InitializeFakeUSSDTestService() (*interactor.Interactor, error) { - var r repository.OnboardingRepository = &fakeRepo - var engagementSvc engagement.ServiceEngagement = &fakeEngagementSvs - var messagingSvc messaging.ServiceMessaging = &fakeMessagingSvc - var ext extension.BaseExtension = &fakeBaseExt - var pinExt extension.PINExtension = &fakePinExt - var ps pubsubmessaging.ServicePubSub = &fakePubSub - var crmSvc crmExt.ServiceCrm = &fakeCrm - - hubspotService := hubspot.NewHubSpotService() - hubspotfr, err := hubspotRepo.NewHubSpotFirebaseRepository(context.Background(), hubspotService) - if err != nil { - return nil, fmt.Errorf("failed to initialize hubspot crm repository: %w", err) - } - hubspotUsecases := hubspotUsecases.NewHubSpotUsecases(hubspotfr) - crmExt := crmExt.NewCrmService(hubspotUsecases) - profile := usecases.NewProfileUseCase(r, ext, engagementSvc, ps, crmExt) - login := usecases.NewLoginUseCases(r, profile, ext, pinExt) - survey := usecases.NewSurveyUseCases(r, ext) - supplier := usecases.NewSupplierUseCases( - r, profile, engagementSvc, messagingSvc, ext, ps, - ) - userpin := usecases.NewUserPinUseCase(r, profile, ext, pinExt, engagementSvc) - su := usecases.NewSignUpUseCases(r, profile, userpin, supplier, ext, engagementSvc, ps) - nhif := usecases.NewNHIFUseCases(r, profile, ext, engagementSvc) - sms := usecases.NewSMSUsecase(r, ext) - role := usecases.NewRoleUseCases(r, ext) - aitUssd := ussd.NewUssdUsecases(r, ext, profile, userpin, su, pinExt, ps, crmSvc) - adminSrv := adminSrv.NewService(ext) - - i, err := interactor.NewOnboardingInteractor( - profile, su, supplier, login, - survey, userpin, - engagementSvc, messagingSvc, nhif, ps, sms, aitUssd, adminSrv, crmExt, - role, - ) - if err != nil { - return nil, fmt.Errorf("can't instantiate service : %w", err) - } - return i, nil - -} diff --git a/pkg/onboarding/usecases/ussd/main_unit_test.go b/pkg/onboarding/usecases/ussd/main_unit_test.go deleted file mode 100644 index 74b7e547..00000000 --- a/pkg/onboarding/usecases/ussd/main_unit_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package ussd_test - -import ( - "context" - "testing" - - "github.com/google/uuid" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" -) - -func TestImpl_HandleResponseFromUSSDGateway_Unittest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeTestService(ctx) - if err != nil { - t.Errorf("unable to initialize service") - return - } - - sessionID := uuid.New().String() - unregisteredPhoneNumber := "0723456756" - registeredPhoneNumber := "+254700100200" - - unregisteredValidPayload := &dto.SessionDetails{ - SessionID: sessionID, - PhoneNumber: &unregisteredPhoneNumber, - } - - registeredValidPayload := &dto.SessionDetails{ - SessionID: sessionID, - PhoneNumber: ®isteredPhoneNumber, - } - - invalidPayload := &dto.SessionDetails{ - SessionID: "", - PhoneNumber: ®isteredPhoneNumber, - } - - type args struct { - ctx context.Context - payload *dto.SessionDetails - } - tests := []struct { - name string - args args - response string - }{ - { - name: "Happy case ):_Success case_Unregistered_user", - args: args{ - ctx: ctx, - payload: unregisteredValidPayload, - }, - response: "CON Welcome to Be.Well\r\n" + - "1. Register\r\n" + - "2. Opt Out\r\n", - }, - { - name: "Happy case ):_Success case_Registered_user", - args: args{ - ctx: ctx, - payload: registeredValidPayload, - }, - response: "CON Welcome to Be.Well\r\n" + - "1. Register\r\n" + - "2. Opt Out\r\n", - }, - { - name: "SAD case ):Fail case_invalid_sessionID", - args: args{ - ctx: ctx, - payload: invalidPayload, - }, - response: "END Something went wrong. Please try again.", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "Happy case ):_Success case_Unregistered_user" { - fakeRepo.HandleResponseFromUSSDGatewayFn = func(context context.Context, input *dto.SessionDetails) string { - return "CON Welcome to Be.Well\r\n" + - "1. Register\r\n" + - "2. Opt Out\r\n" - } - } - - if tt.name == "Happy case ):_Success case_Registered_user" { - fakeRepo.HandleResponseFromUSSDGatewayFn = func(context context.Context, input *dto.SessionDetails) string { - return "CON Welcome to Be.Well\r\n" + - "1. Opt out from marketing messages\r\n" + - "2. Change PIN" - } - } - - if tt.name == "SAD case ):Fail case_invalid_sessionID" { - fakeRepo.HandleResponseFromUSSDGatewayFn = func(context context.Context, input *dto.SessionDetails) string { - return "END Something went wrong. Please try again." - } - } - - if gotresp := u.AITUSSD.HandleResponseFromUSSDGateway(tt.args.ctx, tt.args.payload); gotresp != tt.response { - t.Errorf("Impl.HandleResponseFromUSSDGateway() = %v, want %v", gotresp, tt.response) - } - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/pin.go b/pkg/onboarding/usecases/ussd/pin.go deleted file mode 100644 index 566446a1..00000000 --- a/pkg/onboarding/usecases/ussd/pin.go +++ /dev/null @@ -1,384 +0,0 @@ -package ussd - -import ( - "context" - "reflect" - "strconv" - "time" - - "github.com/google/uuid" - "github.com/savannahghi/feedlib" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/exceptions" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/scalarutils" -) - -const ( - // ChangePINInput indicates the user intention to change their PIN - ChangePINInput = "2" - // ForgotPINInput indicates the user has forgotten their PIN and would like to reset it - ForgotPINInput = "00" - // ChangePINEnterNewPINState indicates the state at which user wants to set a new PIN - ChangePINEnterNewPINState = 51 - // ChangePINProcessNewPINState indicates the state when the supplied PIN is being processed - ChangePINProcessNewPINState = 52 - // ConfirmNewPINState indicates the state when a user is confirming a pin update - ConfirmNewPINState = 53 - // PINResetEnterNewPINState indicates the state when the user wants to reset their PIN - PINResetEnterNewPINState = 10 - // PINResetProcessState represents the state when the user has provided a wrong PIN - PINResetProcessState = 11 - //ForgetPINResetState indicates the state when a use wants to reset PIN - ForgetPINResetState = 13 - //ForgotPINVerifyDate indicates the state when a use wants to reset PIN - ForgotPINVerifyDate = 15 - - //USSDChooseToChangePIN indicates user chose to change PIN - USSDChooseToChangePIN = "chose to change PIN" - //USSDEnterOldPIN is the event when user enters their old PIN - USSDEnterOldPIN = "entered old PIN" - //USSDEnterNewPIN ... - USSDEnterNewPIN = "entered a new 4 digit PIN" - //USSDConfirmChangePIN ... - USSDConfirmChangePIN = "confirmed new PIN" - //USSDChooseToGoBackHome ... - USSDChooseToGoBackHome = "chose to go back home" - - //USSDChooseToResetPIN ... - USSDChooseToResetPIN = "chose to reset PIN" - //USSDChooseToConfirmResetPIN ... - USSDChooseToConfirmResetPIN = "confirm reset PIN" - //USSDPINResetVerifyDate ... - USSDPINResetVerifyDate = "verify date of birth" -) - -// HandleChangePIN represents workflow used to change a user PIN -func (u *Impl) HandleChangePIN(ctx context.Context, session *domain.USSDLeadDetails, userResponse string) string { - ctx, span := tracer.Start(ctx, "HandleChangePIN") - defer span.End() - - time := time.Now() - - if userResponse == EmptyInput || userResponse == ChangePINInput { - err := u.UpdateSessionLevel(ctx, ChangePINEnterNewPINState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - // Capture choose to change PIN - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: ChangePINEnterNewPINState, - USSDEventName: USSDChooseToChangePIN, - }); err != nil { - return "END Something went wrong. Please try again." - } - resp := "CON Enter your old PIN to continue\r\n" - resp += "0. Go back home\r\n" - - return resp - } - - if userResponse == GoBackHomeInput { - isLoggedInUser, err := u.LoginInUser(ctx, session.PhoneNumber, session.PIN, feedlib.FlavourConsumer) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - if !isLoggedInUser { - return "CON Invalid PIN. Please try again" - } - err = u.UpdateSessionLevel(ctx, HomeMenuState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - // Capture go back home event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: HomeMenuState, - USSDEventName: USSDChooseToGoBackHome, - }); err != nil { - return "END Something went wrong. Please try again." - } - userResponse := "" - return u.HandleHomeMenu(ctx, HomeMenuState, session, userResponse) - } - - if session.Level == ChangePINEnterNewPINState { - isLoggedInUser, err := u.LoginInUser(ctx, session.PhoneNumber, userResponse, feedlib.FlavourConsumer) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - if !isLoggedInUser { - return "CON Invalid PIN. Please try again" - } - err = u.UpdateSessionLevel(ctx, ConfirmNewPINState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - - resp := "CON Enter a new four digit PIN\r\n" - return resp - } - if session.Level == ConfirmNewPINState { - err := utils.ValidatePIN(userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "CON The PIN you entered is invalid. Please try again" - } - _, err = u.onboardingRepository.UpdateSessionPIN(ctx, session.SessionID, userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - err = u.UpdateSessionLevel(ctx, ChangePINProcessNewPINState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return err.Error() - } - - // Capture enter new PIN event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: ChangePINEnterNewPINState, - USSDEventName: USSDEnterNewPIN, - }); err != nil { - return "END Something went wrong. Please try again." - } - - return "CON Please enter a 4 digit PIN again to confirm" - } - - if session.Level == ChangePINProcessNewPINState { - if userResponse != session.PIN { - resp := "CON The PIN you entered does not match\r\n" - resp += "Please enter a 4 digit PIN that matches your PIN\r\n" - return resp - } - _, err := u.ChangeUSSDUserPIN(ctx, session.PhoneNumber, userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - err = u.UpdateSessionLevel(ctx, HomeMenuState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - - // Capture confirm new PIN - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: ConfirmNewPINState, - USSDEventName: USSDConfirmChangePIN, - }); err != nil { - return "END Something went wrong. Please try again." - } - - return u.ResetPinMenu() - } - - if userResponse != GoBackHomeInput && userResponse != EmptyInput && userResponse != ChangePINInput { - resp := "CON Invalid choice. Please try again." - return resp - } - - return "END invalid input" -} - -// HandlePINReset represents workflow used to reset to a user PIN -func (u *Impl) HandlePINReset(ctx context.Context, session *domain.USSDLeadDetails, userResponse string) string { - ctx, span := tracer.Start(ctx, "HandlePINReset") - defer span.End() - - time := time.Now() - - if session.Level == ForgetPINResetState { - resp := "CON Please enter a new 4 digit PIN to\r\n" - resp += "secure your account\r\n" - err := u.UpdateSessionLevel(ctx, PINResetEnterNewPINState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - return resp - } - - if session.Level == PINResetEnterNewPINState { - - err := utils.ValidatePIN(userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "CON The PIN you entered is invalid. Please try again" - } - _, err = u.onboardingRepository.UpdateSessionPIN(ctx, session.SessionID, userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - err = u.UpdateSessionLevel(ctx, PINResetProcessState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - - // Capture reset PIN - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: PINResetEnterNewPINState, - USSDEventName: USSDChooseToResetPIN, - }); err != nil { - return "END Something went wrong. Please try again." - } - - resp := "CON Please enter a 4 digit PIN again to\r\n" - resp += "confirm.\r\n" - return resp - } - if session.Level == PINResetProcessState { - if userResponse != session.PIN { - resp := "CON The PIN you entered does not match\r\n" - resp += "Please enter a 4 digit PIN to\r\n" - resp += "secure your account\r\n" - return resp - } - _, err := u.ChangeUSSDUserPIN(ctx, session.PhoneNumber, userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - err = u.UpdateSessionLevel(ctx, HomeMenuState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - - // Capture confirm reset PIN - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: PINResetProcessState, - USSDEventName: USSDChooseToConfirmResetPIN, - }); err != nil { - return "END Something went wrong. Please try again." - } - - return u.ResetPinMenu() - } - if session.Level == ForgotPINVerifyDate { - profile, err := u.onboardingRepository.GetUserProfileByPrimaryPhoneNumber(ctx, session.PhoneNumber, false) - if err != nil { - utils.RecordSpanError(span, err) - return "END something wrong it happened" - } - date := userResponse - day, _ := strconv.Atoi(date[0:2]) - month, _ := strconv.Atoi(date[2:4]) - year, _ := strconv.Atoi(date[4:8]) - dateofBirth := &scalarutils.Date{ - Month: month, - Day: day, - Year: year, - } - if !reflect.DeepEqual(profile.UserBioData.DateOfBirth, dateofBirth) { - return "CON Date of birth entered does not match the date of birth on record. Please enter your valid date of birth" - } - err = u.UpdateSessionLevel(ctx, UserPINResetState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - - // Capture verify DOB - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: ForgotPINVerifyDate, - USSDEventName: USSDPINResetVerifyDate, - }); err != nil { - return "END Something went wrong. Please try again." - } - - session.Level = ForgetPINResetState - return u.HandlePINReset(ctx, session, userResponse) - } - return "END something went wrong" -} - -//SetUSSDUserPin sets user pin when a user registers via USSD -func (u *Impl) SetUSSDUserPin(ctx context.Context, phoneNumber string, PIN string) error { - ctx, span := tracer.Start(ctx, "SetUSSDUserPin") - defer span.End() - - profile, err := u.onboardingRepository.GetUserProfileByPrimaryPhoneNumber( - ctx, - phoneNumber, - false, - ) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - - _, err = u.pinUsecase.SetUserPIN( - ctx, - PIN, - profile.ID, - ) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - return nil -} - -// ChangeUSSDUserPIN updates user's pin with the newly supplied pin via USSD -func (u *Impl) ChangeUSSDUserPIN( - ctx context.Context, - phone string, - pin string, -) (bool, error) { - ctx, span := tracer.Start(ctx, "ChangeUSSDUserPIN") - defer span.End() - - profile, err := u.onboardingRepository.GetUserProfileByPrimaryPhoneNumber( - ctx, - phone, - false, - ) - if err != nil { - utils.RecordSpanError(span, err) - return false, err - } - - salt, encryptedPin := u.pinExt.EncryptPIN(pin, nil) - pinPayload := &domain.PIN{ - ID: uuid.New().String(), - ProfileID: profile.ID, - PINNumber: encryptedPin, - Salt: salt, - } - _, err = u.onboardingRepository.UpdatePIN(ctx, profile.ID, pinPayload) - if err != nil { - utils.RecordSpanError(span, err) - return false, exceptions.InternalServerError(err) - } - return true, nil -} diff --git a/pkg/onboarding/usecases/ussd/pin_integration_test.go b/pkg/onboarding/usecases/ussd/pin_integration_test.go deleted file mode 100644 index 439106c8..00000000 --- a/pkg/onboarding/usecases/ussd/pin_integration_test.go +++ /dev/null @@ -1,561 +0,0 @@ -package ussd_test - -import ( - "context" - "fmt" - "testing" - - "github.com/brianvoe/gofakeit" - "github.com/google/uuid" - "github.com/savannahghi/interserviceclient" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/exceptions" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/scalarutils" -) - -const ( - // ChangePINEnterNewPINState indicates the state at which user wants to set a new PIN - ChangePINEnterNewPINState = 51 - // ChangePINInput indicates the user intention to change their PIN - ChangePINInput = "2" - // GoBackHomeInput represents the user intention to go back to the main menu - GoBackHomeInput = "0" - //ConfirmNewPInState indicates the state when a user is confirming a pin update - ConfirmNewPINState = 53 - // PINResetEnterNewPINState indicates the state when the user wants to reset their PIN - PINResetEnterNewPINState = 10 - //ForgetPINResetState indicates the state when a use wants to reset PIN - ForgetPINResetState = 13 - // PINResetProcessState represents the state when the user has provided a wrong PIN - PINResetProcessState = 11 - // UserPINResetState represents workflows required to reset a forgotten user PIN - UserPINResetState = 10 -) - -func TestImpl_HandleChangePIN_IntegrationTest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeTestService(ctx) - if err != nil { - t.Errorf("unable to initialize service") - return - } - - phoneNumber := "+254750100200" - PIN := "1234" - FirstName := gofakeit.LastName() - LastName := gofakeit.LastName() - SessionID := uuid.New().String() - Level := 0 - - ussdDet := &domain.USSDLeadDetails{ - ID: gofakeit.UUID(), - Level: Level, - PhoneNumber: phoneNumber, - SessionID: SessionID, - FirstName: FirstName, - LastName: LastName, - DateOfBirth: scalarutils.Date{}, - PIN: PIN, - } - - sessionDet := &dto.SessionDetails{ - SessionID: SessionID, - PhoneNumber: &phoneNumber, - Level: Level, - Text: "", - } - - sessionDetails, err := u.AITUSSD.AddAITSessionDetails(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - type args struct { - ctx context.Context - session *domain.USSDLeadDetails - userResponse string - } - tests := []struct { - name string - args args - want string - }{ - { - name: "Happy case : empty input", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: EmptyInput, - }, - want: "CON Enter your old PIN to continue\r\n" + - "0. Go back home\r\n", - }, - - { - name: "Happy case :_Change PIN_selected", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: ChangePINInput, - }, - want: "CON Enter your old PIN to continue\r\n" + - "0. Go back home\r\n", - }, - - { - name: "Sad case :bad choice selected", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "90", - }, - want: "CON Invalid choice. Please try again.", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "Happy case : empty input" { - err = u.AITUSSD.UpdateSessionLevel(ctx, ChangePINEnterNewPINState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Happy case :_Change PIN_selected" { - err = u.AITUSSD.UpdateSessionLevel(ctx, ChangePINEnterNewPINState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Sad case :bad choice selected" { - err = u.AITUSSD.UpdateSessionLevel(ctx, HomeMenuState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - session, err := u.AITUSSD.GetOrCreateSessionState(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - if got := u.AITUSSD.HandleChangePIN(tt.args.ctx, session, tt.args.userResponse); got != tt.want { - t.Errorf("Impl.HandleChangePIN() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestImpl_HandlePINReset(t *testing.T) { - ctx := context.Background() - - u, err := InitializeTestService(ctx) - if err != nil { - t.Errorf("unable to initialize service") - return - } - - phoneNumber := "+254733333333" - PIN := "1234" - FirstName := gofakeit.LastName() - LastName := gofakeit.LastName() - SessionID := uuid.New().String() - Level := 15 - - ussdDet := &domain.USSDLeadDetails{ - ID: gofakeit.UUID(), - Level: Level, - PhoneNumber: phoneNumber, - SessionID: SessionID, - FirstName: FirstName, - LastName: LastName, - DateOfBirth: scalarutils.Date{}, - PIN: PIN, - } - - sessionDet := &dto.SessionDetails{ - SessionID: SessionID, - PhoneNumber: &phoneNumber, - Level: Level, - Text: "", - } - - sessionDetails, err := u.AITUSSD.AddAITSessionDetails(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - type args struct { - ctx context.Context - session *domain.USSDLeadDetails - userResponse string - } - tests := []struct { - name string - args args - want string - }{ - { - name: "Happy case : Reset PIN_new_PIN", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "00", - }, - want: "CON Please enter a new 4 digit PIN to\r\n" + - "secure your account\r\n", - }, - - { - name: "Happy case : Reset Confirm new_PIN", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "1234", - }, - want: "CON Please enter a 4 digit PIN again to\r\n" + - "confirm.\r\n", - }, - - { - name: "Sad case : Reset Confirm invalid_PIN", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "12", - }, - want: "CON The PIN you entered is invalid. Please try again", - }, - - { - name: "Sad case : Reset Confirm PIN do not match", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "4321", - }, - want: "CON The PIN you entered does not match\r\n" + - "Please enter a 4 digit PIN to\r\n" + - "secure your account\r\n", - }, - - { - name: "Sad case : Forgot PIN verify date", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "14032000", - }, - want: "CON Date of birth entered does not match the date of birth on record. Please enter your valid date of birth", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "Happy case : Reset PIN_new_PIN" { - err = u.AITUSSD.UpdateSessionLevel(ctx, ForgetPINResetState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Happy case : Reset Confirm new_PIN" { - err = u.AITUSSD.UpdateSessionLevel(ctx, PINResetEnterNewPINState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Sad case : Reset Confirm invalid_PIN" { - err = u.AITUSSD.UpdateSessionLevel(ctx, PINResetEnterNewPINState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Sad case : Reset Confirm PIN do not match" { - err = u.AITUSSD.UpdateSessionLevel(ctx, PINResetProcessState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Sad case : Forgot PIN verify date" { - - user, err := u.AITUSSD.GetOrCreatePhoneNumberUser(ctx, phoneNumber) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - userProfile, err := u.AITUSSD.CreateUserProfile(ctx, user.PhoneNumber, user.UID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - _, err = u.AITUSSD.SetUserPIN(ctx, ussdDet.PIN, userProfile.ID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - _, err = u.AITUSSD.GetUserProfileByPrimaryPhoneNumber(ctx, *userProfile.PrimaryPhone, false) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - err = u.AITUSSD.UpdateSessionLevel(ctx, ForgotPINVerifyDate, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - } - - session, err := u.AITUSSD.GetOrCreateSessionState(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - if got := u.AITUSSD.HandlePINReset(tt.args.ctx, session, tt.args.userResponse); got != tt.want { - t.Errorf("Impl.HandlePINReset() = %v, want %v", got, tt.want) - } - - }) - } - err = u.AITUSSD.RemoveUserByPhoneNumber(ctx, phoneNumber) - if err != nil { - t.Errorf("removing user: an error occurred %v", err) - return - } -} - -func TestImpl_SetUSSDUserPin(t *testing.T) { - ctx := context.Background() - - u, err := InitializeTestService(ctx) - if err != nil { - t.Errorf("unable to initialize service") - return - } - - phone := "+254700100200" - pin := "4321" - - type args struct { - ctx context.Context - phoneNumber string - PIN string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Happy case: Reset PIN successfully", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: pin, - }, - wantErr: false, - }, - - { - name: "Sad case: Unable to Reset PIN", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: "pin", - }, - wantErr: true, - }, - - { - name: "Sad case: empty PIN", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: "pin", - }, - wantErr: true, - }, - - { - name: "Sad case: invalid PIN", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: "12345", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case: Reset PIN successfully" { - err := utils.ValidatePINLength("12345") - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - return - } - - userResponse, err := u.AITUSSD.GetOrCreatePhoneNumberUser(ctx, phone) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - userProfile, err := u.AITUSSD.CreateUserProfile(ctx, userResponse.PhoneNumber, userResponse.UID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - _, err = u.AITUSSD.GetUserProfileByPrimaryPhoneNumber(ctx, *userProfile.PrimaryPhone, false) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - } - - if tt.name == "Sad case: Unable to Reset PIN" { - err := utils.ValidatePINLength("12345") - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - return - } - } - - if tt.name == "Sad case: empty PIN" { - err := utils.ValidatePINLength("12345") - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - return - } - } - - if tt.name == "Sad case: invalid PIN" { - err := utils.ValidatePINLength("12345") - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - return - } - } - - if err := u.AITUSSD.SetUSSDUserPin(tt.args.ctx, tt.args.phoneNumber, tt.args.PIN); (err != nil) != tt.wantErr { - t.Errorf("Impl.SetUSSDUserPin() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestImpl_ChangeUSSDUserPIN(t *testing.T) { - ctx := context.Background() - - u, err := InitializeTestService(ctx) - if err != nil { - t.Errorf("unable to initialize service") - return - } - - phoneNumber := "+254700100200" - PIN := "4321" - invalidPIN := "321" - - type args struct { - ctx context.Context - phone string - pin string - } - tests := []struct { - name string - args args - want bool - wantErr bool - }{ - { - name: "Happy case: Change user PIN successfully", - args: args{ - ctx: ctx, - phone: phoneNumber, - pin: PIN, - }, - want: true, - wantErr: false, - }, - - { - name: "Sad case: Unable to Change user PIN", - args: args{ - ctx: ctx, - phone: interserviceclient.TestUserPhoneNumber, - pin: invalidPIN, - }, - want: false, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case: Change user PIN successfully" { - err := utils.ValidatePINLength(invalidPIN) - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - return - } - userResp, err := u.AITUSSD.GetOrCreatePhoneNumberUser(ctx, phoneNumber) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - userprofile, err := u.AITUSSD.CreateUserProfile(ctx, phoneNumber, userResp.UID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - _, err = u.AITUSSD.GetUserProfileByPrimaryPhoneNumber(ctx, *userprofile.PrimaryPhone, false) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Sad case: Unable to Change user PIN" { - err := utils.ValidatePINLength(invalidPIN) - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - return - } - } - - got, err := u.AITUSSD.ChangeUSSDUserPIN(tt.args.ctx, tt.args.phone, tt.args.pin) - if (err != nil) != tt.wantErr { - t.Errorf("Impl.ChangeUSSDUserPIN() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("Impl.ChangeUSSDUserPIN() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/pin_unit_test.go b/pkg/onboarding/usecases/ussd/pin_unit_test.go deleted file mode 100644 index 3bfb592a..00000000 --- a/pkg/onboarding/usecases/ussd/pin_unit_test.go +++ /dev/null @@ -1,349 +0,0 @@ -package ussd_test - -import ( - "context" - "fmt" - "testing" - - "github.com/brianvoe/gofakeit" - "github.com/google/uuid" - "github.com/savannahghi/interserviceclient" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/exceptions" - "github.com/savannahghi/onboarding/pkg/onboarding/application/extension" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/profileutils" - "github.com/savannahghi/scalarutils" -) - -func TestImpl_HandleChangePIN_Unittest(t *testing.T) { - ctx := context.Background() - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("unable to initialize service") - return - } - - phoneNumber := "+254700100200" - PIN := "1234" - FirstName := gofakeit.LastName() - LastName := gofakeit.LastName() - SessionID := uuid.New().String() - Level := 0 - - ussdDet := &domain.USSDLeadDetails{ - ID: gofakeit.UUID(), - Level: Level, - PhoneNumber: phoneNumber, - SessionID: SessionID, - FirstName: FirstName, - LastName: LastName, - DateOfBirth: scalarutils.Date{}, - PIN: PIN, - } - - type args struct { - ctx context.Context - session *domain.USSDLeadDetails - userResponse string - } - tests := []struct { - name string - args args - want string - }{ - { - name: "change pin", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: EmptyInput, - }, - want: "CON Enter your old PIN to continue\r\n" + - "0. Go back home\r\n", - }, - - { - name: "go back home", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: GoBackHomeInput, - }, - want: "CON Welcome to Be.Well\r\n" + - "1. Opt out from marketing messages\r\n" + - "2. Change PIN", - }, - - { - name: "change pin option 2 selected", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "2", - }, - want: "CON Enter your old PIN to continue\r\n" + - "0. Go back home\r\n", - }, - - { - name: "Sad case :invalid input", - args: args{ - ctx: ctx, - session: ussdDet, - userResponse: "90", - }, - want: "CON Invalid choice. Please try again.", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "change pin" { - fakeRepo.UpdateSessionLevelFn = func(ctx context.Context, sessionID string, level int) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{}, nil - } - fakeRepo.SaveUSSDEventFn = func(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) { - return &dto.USSDEvent{}, nil - } - } - if tt.name == "go back home" { - fakeRepo.GetUserProfileByPrimaryPhoneNumberFn = func(ctx context.Context, phoneNumber string, suspended bool) (*profileutils.UserProfile, error) { - return &profileutils.UserProfile{}, nil - } - fakeRepo.GetPINByProfileIDFn = func(ctx context.Context, ProfileID string) (*domain.PIN, error) { - return &domain.PIN{}, nil - } - fakePinExt.ComparePINFn = func(rawPwd, salt, encodedPwd string, options *extension.Options) bool { - return true - } - fakeRepo.UpdateSessionLevelFn = func(ctx context.Context, sessionID string, level int) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{}, nil - } - } - if tt.name == "change pin option 2 selected" { - fakeRepo.GetUserProfileByPrimaryPhoneNumberFn = func(ctx context.Context, phoneNumber string, suspended bool) (*profileutils.UserProfile, error) { - return &profileutils.UserProfile{}, nil - } - fakeRepo.GetPINByProfileIDFn = func(ctx context.Context, ProfileID string) (*domain.PIN, error) { - return &domain.PIN{}, nil - } - fakePinExt.ComparePINFn = func(rawPwd, salt, encodedPwd string, options *extension.Options) bool { - return true - } - fakeRepo.UpdateSessionLevelFn = func(ctx context.Context, sessionID string, level int) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{}, nil - } - } - - if tt.name == "Sad case :invalid input" { - fakeRepo.GetUserProfileByPrimaryPhoneNumberFn = func(ctx context.Context, phoneNumber string, suspended bool) (*profileutils.UserProfile, error) { - return nil, fmt.Errorf("an error occurred: %v", err) - } - } - - if got := u.AITUSSD.HandleChangePIN(tt.args.ctx, tt.args.session, tt.args.userResponse); got != tt.want { - t.Errorf("Impl.HandleChangePIN() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestImpl_SetUSSDUserPin_Unittest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("unable to initialize service") - return - } - - phone := "+254700100200" - pin := "4321" - - type args struct { - ctx context.Context - phoneNumber string - PIN string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Happy case: Reset PIN successfully", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: pin, - }, - wantErr: false, - }, - - { - name: "Sad case: Unable to Reset PIN", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: "pin", - }, - wantErr: true, - }, - - { - name: "Sad case: empty PIN", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: "pin", - }, - wantErr: true, - }, - - { - name: "Sad case: invalid PIN", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: "12345", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "Happy case: Reset PIN successfully" { - fakeRepo.GetUserProfileByPrimaryPhoneNumberFn = func(ctx context.Context, phoneNumber string, suspended bool) (*profileutils.UserProfile, error) { - return &profileutils.UserProfile{}, nil - } - - fakePinExt.EncryptPINFn = func(rawPwd string, options *extension.Options) (string, string) { - return "pin", "pin" - } - - fakeRepo.SavePINFn = func(ctx context.Context, pin *domain.PIN) (bool, error) { - return true, nil - } - } - - if tt.name == "Sad case: Unable to Reset PIN" { - fakeRepo.SetUSSDUserPinFn = func(ctx context.Context, phoneNumber, PIN string) error { - return err - } - } - - if tt.name == "Sad case: empty PIN" { - fakeRepo.SetUSSDUserPinFn = func(ctx context.Context, phoneNumber, PIN string) error { - return err - } - } - - if tt.name == "Sad case: invalid PIN" { - err := utils.ValidatePINLength("12345") - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - return - } - fakeRepo.SetUSSDUserPinFn = func(ctx context.Context, phoneNumber, PIN string) error { - return err - } - } - - if err := u.AITUSSD.SetUSSDUserPin(tt.args.ctx, tt.args.phoneNumber, tt.args.PIN); (err != nil) != tt.wantErr { - t.Errorf("Impl.SetUSSDUserPin() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestImpl_ChangeUSSDUserPIN_Unittest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("unable to initialize service") - return - } - - phoneNumber := "+254700100200" - PIN := "4321" - invalidPIN := "321" - - type args struct { - ctx context.Context - phone string - pin string - } - tests := []struct { - name string - args args - want bool - wantErr bool - }{ - { - name: "Happy case: Change user PIN successfully", - args: args{ - ctx: ctx, - phone: phoneNumber, - pin: PIN, - }, - want: true, - wantErr: false, - }, - - { - name: "Sad case: Unable to Change user PIN", - args: args{ - ctx: ctx, - phone: interserviceclient.TestUserPhoneNumber, - pin: invalidPIN, - }, - want: false, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case: Change user PIN successfully" { - fakeRepo.GetUserProfileByPrimaryPhoneNumberFn = func(ctx context.Context, phoneNumber string, suspended bool) (*profileutils.UserProfile, error) { - return &profileutils.UserProfile{}, nil - } - - fakePinExt.EncryptPINFn = func(rawPwd string, options *extension.Options) (string, string) { - return "pin", "pin" - } - - fakeRepo.UpdatePINFn = func(ctx context.Context, id string, pin *domain.PIN) (bool, error) { - return true, nil - } - } - - if tt.name == "Sad case: Unable to Change user PIN" { - err := utils.ValidatePINLength(invalidPIN) - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - - return - } - fakeRepo.GetUserProfileByPrimaryPhoneNumberFn = func(ctx context.Context, phoneNumber string, suspended bool) (*profileutils.UserProfile, error) { - return &profileutils.UserProfile{}, nil - } - - fakeRepo.UpdatePINFn = func(ctx context.Context, id string, pin *domain.PIN) (bool, error) { - return false, err - } - } - - got, err := u.AITUSSD.ChangeUSSDUserPIN(tt.args.ctx, tt.args.phone, tt.args.pin) - if (err != nil) != tt.wantErr { - t.Errorf("Impl.ChangeUSSDUserPIN() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("Impl.ChangeUSSDUserPIN() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/profile.go b/pkg/onboarding/usecases/ussd/profile.go deleted file mode 100644 index 7a577a7a..00000000 --- a/pkg/onboarding/usecases/ussd/profile.go +++ /dev/null @@ -1,59 +0,0 @@ -package ussd - -import ( - "context" - - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/exceptions" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/profileutils" -) - -//CreateUsddUserProfile creates and updates a user profile -func (u *Impl) CreateUsddUserProfile(ctx context.Context, phoneNumber string, PIN string, userProfile *dto.UserProfileInput) error { - ctx, span := tracer.Start(ctx, "CreateUsddUserProfile") - defer span.End() - - user, err := u.onboardingRepository.GetOrCreatePhoneNumberUser(ctx, phoneNumber) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - profile, err := u.onboardingRepository.CreateUserProfile( - ctx, - phoneNumber, - user.UID, - ) - if err != nil { - utils.RecordSpanError(span, err) - return exceptions.InternalServerError(err) - } - _, err = u.pinUsecase.SetUserPIN( - ctx, - PIN, - profile.ID, - ) - - if err != nil { - utils.RecordSpanError(span, err) - return err - } - _, err = u.onboardingRepository.CreateEmptyCustomerProfile(ctx, profile.ID) - if err != nil { - utils.RecordSpanError(span, err) - return exceptions.InternalServerError(err) - } - - data := profileutils.BioData{ - FirstName: &userFirstName, - LastName: &userLastName, - DateOfBirth: userProfile.DateOfBirth, - } - err = u.onboardingRepository.UpdateBioData(ctx, profile.ID, data) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - return nil - -} diff --git a/pkg/onboarding/usecases/ussd/profile_unit_test.go b/pkg/onboarding/usecases/ussd/profile_unit_test.go deleted file mode 100644 index e9fb22e2..00000000 --- a/pkg/onboarding/usecases/ussd/profile_unit_test.go +++ /dev/null @@ -1,147 +0,0 @@ -package ussd_test - -import ( - "context" - "fmt" - "testing" - - "github.com/brianvoe/gofakeit" - "github.com/savannahghi/enumutils" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/exceptions" - "github.com/savannahghi/onboarding/pkg/onboarding/application/extension" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/profileutils" - "github.com/savannahghi/scalarutils" -) - -func TestImpl_CreateUsddUserProfile_Unittest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("unable to initialize service") - return - } - - date := &scalarutils.Date{ - Year: 2000, - Month: 10, - Day: 01, - } - gender := enumutils.GenderMale - firstname := gofakeit.FirstName() - lastname := gofakeit.LastName() - phone := "+254700100200" - pin := "4321" - - userP := &dto.UserProfileInput{ - DateOfBirth: date, - Gender: &gender, - FirstName: &firstname, - LastName: &lastname, - } - - type args struct { - ctx context.Context - phoneNumber string - PIN string - userProfile *dto.UserProfileInput - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: pin, - userProfile: userP, - }, - wantErr: false, - }, - - { - name: "Sad case:_Non_digit_PIN", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: "pin", - userProfile: userP, - }, - wantErr: false, - }, - - { - name: "Sad case:_Longer_than_4_digit_PIN", - args: args{ - ctx: ctx, - phoneNumber: phone, - PIN: "12345", - userProfile: userP, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case" { - fakeRepo.GetOrCreatePhoneNumberUserFn = func(ctx context.Context, phone string) (*dto.CreatedUserResponse, error) { - return &dto.CreatedUserResponse{}, nil - } - - fakeRepo.CreateUserProfileFn = func(ctx context.Context, phoneNumber, uid string) (*profileutils.UserProfile, error) { - return &profileutils.UserProfile{}, nil - } - - fakeRepo.CreateEmptyCustomerProfileFn = func(ctx context.Context, profileID string) (*profileutils.Customer, error) { - return &profileutils.Customer{}, nil - } - - fakeRepo.UpdateBioDataFn = func(ctx context.Context, id string, data profileutils.BioData) error { - return nil - } - - fakePinExt.EncryptPINFn = func(rawPwd string, options *extension.Options) (string, string) { - return "pin", "pin" - } - - fakeRepo.SavePINFn = func(ctx context.Context, pin *domain.PIN) (bool, error) { - return true, nil - } - } - - if tt.name == "Sad case:_Non_digit_PIN" { - err := utils.ValidatePIN(tt.args.PIN) - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("pin should be a valid number")) - return - } - - fakeRepo.GetOrCreatePhoneNumberUserFn = func(ctx context.Context, phone string) (*dto.CreatedUserResponse, error) { - return nil, err - } - } - - if tt.name == "Sad case:_Longer_than_4_digit_PIN" { - err := utils.ValidatePIN(tt.args.PIN) - if err != nil { - exceptions.ValidatePINLengthError(fmt.Errorf("PIN should be of 4 digits")) - return - } - - fakeRepo.GetOrCreatePhoneNumberUserFn = func(ctx context.Context, phone string) (*dto.CreatedUserResponse, error) { - return nil, err - } - } - - if err := u.AITUSSD.CreateUsddUserProfile(tt.args.ctx, tt.args.phoneNumber, tt.args.PIN, tt.args.userProfile); (err != nil) != tt.wantErr { - t.Errorf("Impl.CreateUsddUserProfile() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/register.go b/pkg/onboarding/usecases/ussd/register.go deleted file mode 100644 index f09eca58..00000000 --- a/pkg/onboarding/usecases/ussd/register.go +++ /dev/null @@ -1,327 +0,0 @@ -package ussd - -import ( - "context" - "strconv" - "time" - - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/scalarutils" -) - -const ( - // InitialState ... - InitialState = 0 - // GetFirstNameState ... - GetFirstNameState = 1 - // GetLastNameState ... - GetLastNameState = 2 - // GetDOBState ... - GetDOBState = 3 - // GetPINState ... - GetPINState = 4 - // SaveRecordState ... - SaveRecordState = 5 - // RegisterInput ... - RegisterInput = "1" - //RegOptOutInput ... - RegOptOutInput = "2" - //RegChangePINInput ... - RegChangePINInput = "2" - - //USSDDialled ... - USSDDialled = "dialled" - //USSDSelectRegister ... - USSDSelectRegister = "select register" - //USSDEnterFirstname ... - USSDEnterFirstname = "entered firstname" - //USSDEnterLastname ... - USSDEnterLastname = "entered lastname" - //USSDEnterDOB ... - USSDEnterDOB = "entered date of birth" - //USSDEnterPIN ... - USSDEnterPIN = "entered PIN" - //USSDConfirmPIN ... - USSDConfirmPIN = "confirmed PIN" - //USSDOptOut ... - USSDOptOut = "opted out" -) - -var userFirstName string -var userLastName string -var date string - -// HandleUserRegistration ... -func (u *Impl) HandleUserRegistration(ctx context.Context, session *domain.USSDLeadDetails, userResponse string) string { - ctx, span := tracer.Start(ctx, "HandleUserRegistration") - defer span.End() - - time := time.Now() - - if userResponse == EmptyInput || userResponse == GoBackHomeInput && session.Level == InitialState { - - // Capture dialling event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: InitialState, - USSDEventName: USSDDialled, - }); err != nil { - return "END Something went wrong. Please try again." - } - - resp := "CON Welcome to Be.Well\r\n" - resp += "1. Register\r\n" - resp += "2. Opt Out\r\n" - return resp - } - - if userResponse == RegOptOutInput && session.Level == InitialState { - _, err := u.crm.OptOut(ctx, session.PhoneNumber) - if err != nil { - return "END Something went wrong. Please try again." - } - - // Capture opt out event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: InitialState, - USSDEventName: USSDOptOut, - }); err != nil { - return "END Something went wrong. Please try again." - } - - resp := "CON We have successfully opted you\r\n" - resp += "out of marketing messages\r\n" - resp += "0. Go back home" - return resp - } - - if userResponse == RegisterInput && session.Level == InitialState { - // Capture opt out event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: InitialState, - USSDEventName: USSDSelectRegister, - }); err != nil { - return "END Something went wrong. Please try again." - } - err := u.UpdateSessionLevel(ctx, GetFirstNameState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - resp := "CON Please enter your firstname(e.g.\r\n" - resp += "John).\r\n" - return resp - } - - if session.Level == GetFirstNameState { - err := utils.ValidateUSSDInput(userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "CON Invalid name. Please enter a valid name (e.g John)" - } - - isLetter := utils.IsLetter(userResponse) - if !isLetter { - return "CON Invalid name. Please enter a valid name (e.g John)" - } - userFirstName = userResponse - - err = u.UpdateSessionLevel(ctx, GetLastNameState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - - // Capture first name event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: GetFirstNameState, - USSDEventName: USSDEnterFirstname, - }); err != nil { - return "END Something went wrong. Please try again." - } - - resp := "CON Please enter your lastname(e.g.\r\n" - resp += "Doe)\r\n" - return resp - - } - if session.Level == GetLastNameState { - err := utils.ValidateUSSDInput(userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "CON Invalid name. Please enter a valid name (e.g Doe)" - } - - isLetter := utils.IsLetter(userResponse) - if !isLetter { - return "CON Invalid name. Please enter a valid name (e.g Doe)" - } - - userLastName = userResponse - - err = u.UpdateSessionLevel(ctx, GetDOBState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return err.Error() - } - - // Capture last name event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: GetLastNameState, - USSDEventName: USSDEnterLastname, - }); err != nil { - return "END Something went wrong. Please try again." - } - - resp := "CON Please enter your date of birth in\r\n" - resp += "DDMMYYYY format e.g 14031996 for\r\n" - resp += "14th March 1996\r\n" - return resp - } - - if session.Level == GetDOBState { - err := utils.ValidateDateDigits(userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "CON The date of birth you entered is not valid, please try again in DDMMYYYY format e.g 14031996" - } - - err = utils.ValidateDateLength(userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "CON The date of birth you entered is not valid, please try again in DDMMYYYY format e.g 14031996" - } - resp := utils.ValidateYearOfBirth(userResponse) - if resp != "" { - return resp - } - - date = userResponse - - err = u.UpdateSessionLevel(ctx, GetPINState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return err.Error() - } - - // Capture date of birth event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: GetDOBState, - USSDEventName: USSDEnterDOB, - }); err != nil { - return "END Something went wrong. Please try again." - } - - return "CON Please enter a 4 digit PIN to secure your account" - } - - if session.Level == GetPINState { - err := utils.ValidatePIN(userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "CON The PIN you entered in not correct please enter a 4 digit PIN" - } - _, err = u.onboardingRepository.UpdateSessionPIN(ctx, session.SessionID, userResponse) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - err = u.UpdateSessionLevel(ctx, SaveRecordState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return err.Error() - } - - // Capture PIN entry event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: GetPINState, - USSDEventName: USSDEnterPIN, - }); err != nil { - return "END Something went wrong. Please try again." - } - - return "CON Please enter a 4 digit PIN again to confirm" - - } - - if session.Level == SaveRecordState { - if userResponse != session.PIN { - resp := "CON The PIN you entered does not match\r\n" - resp += "Please enter a 4 digit PIN to secure your account\r\n" - return resp - } - day, _ := strconv.Atoi(date[0:2]) - month, _ := strconv.Atoi(date[2:4]) - year, _ := strconv.Atoi(date[4:8]) - dateofBirth := &scalarutils.Date{ - Month: month, - Day: day, - Year: year, - } - updateInput := &dto.UserProfileInput{ - DateOfBirth: dateofBirth, - FirstName: &userFirstName, - LastName: &userLastName, - } - - err := u.CreateUsddUserProfile(ctx, session.PhoneNumber, session.PIN, updateInput) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - - contactLead := &domain.USSDLeadDetails{ - FirstName: userFirstName, - LastName: userLastName, - DateOfBirth: *dateofBirth, - IsRegistered: true, - } - _ = u.onboardingRepository.UpdateAITSessionDetails(ctx, session.PhoneNumber, contactLead) - - err = u.UpdateSessionLevel(ctx, HomeMenuState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - - // Capture confirm PIN entry event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - Level: SaveRecordState, - USSDEventName: USSDConfirmPIN, - }); err != nil { - return "END Something went wrong. Please try again." - } - - userResponse := "" - return u.HandleHomeMenu(ctx, HomeMenuState, session, userResponse) - } - resp := "CON Invalid choice. Try again.\r\n" - resp += "1. Register\r\n" - resp += "2. Opt Out\r\n" - return resp -} diff --git a/pkg/onboarding/usecases/ussd/register_integration_test.go b/pkg/onboarding/usecases/ussd/register_integration_test.go deleted file mode 100644 index 4fc5ab0b..00000000 --- a/pkg/onboarding/usecases/ussd/register_integration_test.go +++ /dev/null @@ -1,303 +0,0 @@ -package ussd_test - -import ( - "context" - "testing" - - "github.com/brianvoe/gofakeit" - "github.com/google/uuid" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/scalarutils" - - CRMDomain "gitlab.slade360emr.com/go/commontools/crm/pkg/domain" -) - -const ( - // // InitialState ... - InitialState = 0 - // GetFirstNameState ... - GetFirstNameState = 1 - // GetLastNameState ... - GetLastNameState = 2 - // GetDOBState ... - GetDOBState = 3 - // GetPINState ... - GetPINState = 4 - // SaveRecordState ... - SaveRecordState = 5 - // RegisterInput ... - RegisterInput = "1" - //RegOptOutInput ... - RegOptOutInput = "2" - //RegChangePINInput ... - RegChangePINInput = "2" - //HomeMenuState represents inner submenu once user is logged in - HomeMenuState = 5 -) - -func TestImpl_HandleUserRegistration(t *testing.T) { - ctx := context.Background() - - u, err := InitializeTestService(ctx) - if err != nil { - t.Errorf("unable to initialize service %v", err) - return - } - - phoneNumber := "+254700100200" - PIN := "1234" - FirstName := gofakeit.FirstName() - LastName := gofakeit.LastName() - DateOfBirth := scalarutils.Date{ - Day: 0, - Month: 0, - Year: 0, - } - WantCover := false - ContactChannel := "USSD" - IsRegistered := false - - SessionID := uuid.New().String() - Level := 0 - Text := "" - - sessionDet := &dto.SessionDetails{ - SessionID: SessionID, - PhoneNumber: &phoneNumber, - Level: Level, - Text: Text, - } - - sessionDetails, err := u.AITUSSD.AddAITSessionDetails(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - validUSSDLeadDetails := &domain.USSDLeadDetails{ - ID: uuid.New().String(), - Level: InitialState, - PhoneNumber: phoneNumber, - SessionID: SessionID, - FirstName: FirstName, - LastName: LastName, - DateOfBirth: DateOfBirth, - IsRegistered: IsRegistered, - ContactChannel: ContactChannel, - WantCover: WantCover, - PIN: PIN, - } - - // create a contact - _, err = u.CrmExt.CreateHubSpotContact(ctx, &CRMDomain.CRMContact{ - Properties: CRMDomain.ContactProperties{ - Phone: phoneNumber, - }, - }) - if err != nil { - t.Errorf("failed to create test contact: %w", err) - return - } - - type args struct { - ctx context.Context - session *domain.USSDLeadDetails - userResponse string - } - tests := []struct { - name string - args args - want string - }{ - // { - // name: "Happy_case:optout", - // args: args{ - // ctx: ctx, - // session: validUSSDLeadDetails, - // userResponse: RegOptOutInput, - // }, - // want: "CON We have successfully opted you\r\n" + - // "out of marketing messages\r\n" + - // "0. Go back home", - // }, - { - name: "Happy_case:_firstname", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: gofakeit.FirstName(), - }, - want: "CON Please enter your lastname(e.g.\r\n" + - "Doe)\r\n", - }, - - { - name: "Happy_case:_lastname", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: gofakeit.LastName(), - }, - want: "CON Please enter your date of birth in\r\n" + - "DDMMYYYY format e.g 14031996 for\r\n" + - "14th March 1996\r\n", - }, - - { - name: "Happy_case:_dob", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: "12122000", - }, - want: "CON Please enter a 4 digit PIN to secure your account", - }, - - { - name: "Happy_case:_pin_one", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: "1234", - }, - want: "CON Please enter a 4 digit PIN again to confirm", - }, - - //Bad cases - - { - name: "Sad_case:_invalid_firstname", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: "1234", - }, - want: "CON Invalid name. Please enter a valid name (e.g John)", - }, - - { - name: "Sad_case:_invalid_lastname", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: "1234", - }, - want: "CON Invalid name. Please enter a valid name (e.g Doe)", - }, - - { - name: "Sad_case:_invalid_dob", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: "hello", - }, - want: "CON The date of birth you entered is not valid, please try again in DDMMYYYY format e.g 14031996", - }, - - { - name: "Sad case:_invalid_pin_one", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: "hello", - }, - want: "CON The PIN you entered in not correct please enter a 4 digit PIN", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy_case:optout" { - err = u.AITUSSD.UpdateSessionLevel(ctx, InitialState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Happy_case:_firstname" { - //Get firstname state - err = u.AITUSSD.UpdateSessionLevel(ctx, GetFirstNameState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - } - - if tt.name == "Happy_case:_lastname" { - //Get last state - err = u.AITUSSD.UpdateSessionLevel(ctx, GetLastNameState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - } - - if tt.name == "Happy_case:_dob" { - //Get dob state - err = u.AITUSSD.UpdateSessionLevel(ctx, GetDOBState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Happy_case:_pin_one" { - //Get pin state - err = u.AITUSSD.UpdateSessionLevel(ctx, GetPINState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Sad_case:_invalid_firstname" { - err = u.AITUSSD.UpdateSessionLevel(ctx, GetFirstNameState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - } - - if tt.name == "Sad_case:_invalid_lastname" { - err = u.AITUSSD.UpdateSessionLevel(ctx, GetLastNameState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - } - - if tt.name == "Sad_case:_invalid_dob" { - err = u.AITUSSD.UpdateSessionLevel(ctx, GetDOBState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - if tt.name == "Sad case:_invalid_pin_one" { - err = u.AITUSSD.UpdateSessionLevel(ctx, GetPINState, sessionDetails.SessionID) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - } - - updatedSession, err := u.AITUSSD.GetOrCreateSessionState(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - got := u.AITUSSD.HandleUserRegistration(tt.args.ctx, updatedSession, tt.args.userResponse) - if got != tt.want { - t.Errorf("Impl.HandleUserRegistration() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/registration_unit_test.go b/pkg/onboarding/usecases/ussd/registration_unit_test.go deleted file mode 100644 index 83141fc3..00000000 --- a/pkg/onboarding/usecases/ussd/registration_unit_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package ussd_test - -import ( - "context" - "fmt" - "testing" - - "github.com/brianvoe/gofakeit" - "github.com/google/uuid" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/scalarutils" - - hubspotDomain "gitlab.slade360emr.com/go/commontools/crm/pkg/domain" -) - -func TestImpl_HandleUserRegistration_Unittest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("unable to initialize service %v", err) - return - } - - phoneNumber := "+254700200210" - DateOfBirth := scalarutils.Date{ - Day: 0, - Month: 0, - Year: 0, - } - PIN := "1234" - FirstName := gofakeit.FirstName() - LastName := gofakeit.LastName() - - SessionID := uuid.New().String() - Level := 2 - Text := "" - - sessionDet := &dto.SessionDetails{ - SessionID: SessionID, - PhoneNumber: &phoneNumber, - Level: Level, - Text: Text, - } - - validUSSDLeadDetails := &domain.USSDLeadDetails{ - ID: uuid.New().String(), - Level: InitialState, - PhoneNumber: phoneNumber, - SessionID: SessionID, - FirstName: FirstName, - LastName: LastName, - DateOfBirth: DateOfBirth, - PIN: PIN, - } - - type args struct { - ctx context.Context - session *domain.USSDLeadDetails - userResponse string - } - tests := []struct { - name string - args args - want string - }{ - { - name: "Happy_case:optout", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: RegOptOutInput, - }, - want: "CON We have successfully opted you\r\n" + - "out of marketing messages\r\n" + - "0. Go back home", - }, - - { - name: "Sad_case:optout", - args: args{ - ctx: ctx, - session: validUSSDLeadDetails, - userResponse: "12", - }, - want: "CON Invalid choice. Try again.\r\n" + - "1. Register\r\n" + - "2. Opt Out\r\n", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy_case:optout" { - fakeRepo.GetAITSessionDetailsFn = func(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{}, nil - } - - fakeCrm.OptOutFn = func(ctx context.Context, phoneNumber string) (*hubspotDomain.CRMContact, error) { - return &hubspotDomain.CRMContact{ContactID: uuid.NewString()}, nil - } - - fakeRepo.SaveUSSDEventFn = func(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) { - return &dto.USSDEvent{ - SessionID: uuid.NewString(), - }, nil - } - } - - if tt.name == "Sad_case:optout" { - fakeCrm.OptOutFn = func(ctx context.Context, phoneNumber string) (*hubspotDomain.CRMContact, error) { - return nil, fmt.Errorf("an error occurred %w", err) - } - } - - updatedSession, err := u.AITUSSD.GetOrCreateSessionState(ctx, sessionDet) - if err != nil { - t.Errorf("an error occurred %v", err) - return - } - - if gotresp := u.AITUSSD.HandleUserRegistration(tt.args.ctx, updatedSession, tt.args.userResponse); gotresp != tt.want { - t.Errorf("Impl.HandleUserRegistration() = %v, want %v", gotresp, tt.want) - } - - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/session.go b/pkg/onboarding/usecases/ussd/session.go deleted file mode 100644 index 1aa1e1dc..00000000 --- a/pkg/onboarding/usecases/ussd/session.go +++ /dev/null @@ -1,195 +0,0 @@ -package ussd - -import ( - "context" - - "github.com/savannahghi/converterandformatter" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/exceptions" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/profileutils" -) - -// UpdateSessionLevel updates user current level of interaction with USSD -func (u *Impl) UpdateSessionLevel(ctx context.Context, level int, sessionID string) error { - ctx, span := tracer.Start(ctx, "UpdateSessionLevel") - defer span.End() - - validSessionID, err := utils.CheckEmptyString(sessionID) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - - _, err = u.onboardingRepository.UpdateSessionLevel(ctx, *validSessionID, level) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - return nil - -} - -// UpdateSessionPIN updates user current session PIN -func (u *Impl) UpdateSessionPIN(ctx context.Context, pin string, sessionID string) (*domain.USSDLeadDetails, error) { - ctx, span := tracer.Start(ctx, "UpdateSessionLevel") - defer span.End() - - validSessionID, err := utils.CheckEmptyString(sessionID) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - ussdLead, err := u.onboardingRepository.UpdateSessionPIN(ctx, *validSessionID, pin) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - return ussdLead, nil - -} - -// GetUserProfileByPrimaryPhoneNumber ... -func (u *Impl) GetUserProfileByPrimaryPhoneNumber(ctx context.Context, phoneNumber string, suspend bool) (*profileutils.UserProfile, error) { - profile, err := u.onboardingRepository.GetUserProfileByPrimaryPhoneNumber(ctx, phoneNumber, false) - if err != nil { - return nil, err - } - return profile, err -} - -//AddAITSessionDetails persists USSD details -func (u *Impl) AddAITSessionDetails(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) { - ctx, span := tracer.Start(ctx, "AddAITSessionDetails") - defer span.End() - - phone, err := converterandformatter.NormalizeMSISDN(*input.PhoneNumber) - if err != nil { - utils.RecordSpanError(span, err) - return nil, exceptions.NormalizeMSISDNError(err) - } - sessionDetails := &dto.SessionDetails{ - PhoneNumber: phone, - SessionID: input.SessionID, - Level: input.Level, - } - result, err := u.onboardingRepository.AddAITSessionDetails(ctx, sessionDetails) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - return result, nil -} - -// GetOrCreateSessionState is used to set or return a user session -func (u *Impl) GetOrCreateSessionState(ctx context.Context, payload *dto.SessionDetails) (*domain.USSDLeadDetails, error) { - ctx, span := tracer.Start(ctx, "GetOrCreateSessionState") - defer span.End() - - sessionDetails, err := u.onboardingRepository.GetAITSessionDetails(ctx, payload.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - if sessionDetails == nil { - payload.Level = 0 - sessionDetails, err = u.AddAITSessionDetails(ctx, payload) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - } - return sessionDetails, nil -} - -// GetOrCreatePhoneNumberUser ... -func (u *Impl) GetOrCreatePhoneNumberUser(ctx context.Context, phone string) (*dto.CreatedUserResponse, error) { - ctx, span := tracer.Start(ctx, "GetOrCreatePhoneNumberUser") - defer span.End() - - user, err := u.onboardingRepository.GetOrCreatePhoneNumberUser(ctx, phone) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - return user, nil -} - -// CreateUserProfile ... -func (u *Impl) CreateUserProfile(ctx context.Context, phoneNumber string, uid string) (*profileutils.UserProfile, error) { - ctx, span := tracer.Start(ctx, "GetOrCreatePhoneNumberUser") - defer span.End() - - userProfile, err := u.onboardingRepository.CreateUserProfile(ctx, phoneNumber, uid) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - return userProfile, nil -} - -// CreateEmptyCustomerProfile ... -func (u *Impl) CreateEmptyCustomerProfile(ctx context.Context, profileID string) (*profileutils.Customer, error) { - ctx, span := tracer.Start(ctx, "GetOrCreatePhoneNumberUser") - defer span.End() - - customer, err := u.onboardingRepository.CreateEmptyCustomerProfile(ctx, profileID) - if err != nil { - utils.RecordSpanError(span, err) - return nil, err - } - - return customer, nil -} - -// UpdateBioData ... -func (u *Impl) UpdateBioData(ctx context.Context, id string, data profileutils.BioData) error { - ctx, span := tracer.Start(ctx, "GetOrCreatePhoneNumberUser") - defer span.End() - - validID, err := utils.CheckEmptyString(id) - if err != nil { - return err - } - - err = u.onboardingRepository.UpdateBioData(ctx, *validID, data) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - - return nil -} - -// RemoveUserByPhoneNumber ... -func (u *Impl) RemoveUserByPhoneNumber(ctx context.Context, phone string) error { - ctx, span := tracer.Start(ctx, "PurgeUserByPhoneNumber") - defer span.End() - err := u.signUp.RemoveUserByPhoneNumber(ctx, phone) - if err != nil { - utils.RecordSpanError(span, err) - return err - } - return nil -} - -// SetUserPIN ... -func (u *Impl) SetUserPIN(ctx context.Context, pin string, profileID string) (bool, error) { - ctx, span := tracer.Start(ctx, "SetUserPIN") - defer span.End() - setPIN, err := u.pinUsecase.SetUserPIN(ctx, pin, profileID) - if err != nil { - utils.RecordSpanError(span, err) - return false, err - } - return setPIN, nil -} - -// SaveUSSDEvent saves USSD event in the database -func (u *Impl) SaveUSSDEvent(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) { - return u.onboardingRepository.SaveUSSDEvent(ctx, input) -} diff --git a/pkg/onboarding/usecases/ussd/session_unit_test.go b/pkg/onboarding/usecases/ussd/session_unit_test.go deleted file mode 100644 index 849e9085..00000000 --- a/pkg/onboarding/usecases/ussd/session_unit_test.go +++ /dev/null @@ -1,755 +0,0 @@ -package ussd_test - -import ( - "context" - "fmt" - "reflect" - "testing" - "time" - - "github.com/brianvoe/gofakeit" - "github.com/google/uuid" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" - "github.com/savannahghi/profileutils" - "github.com/savannahghi/pubsubtools" - "github.com/savannahghi/scalarutils" -) - -func TestImpl_AddAITSessionDetailsUnittest(t *testing.T) { - - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("failed to initialize test service") - return - } - - validSessionId := uuid.New().String() - phoneNumber := "+254707756919" - level := 1 - text := "1*gabriel*were" - - validUSSDLeadDetails := &domain.USSDLeadDetails{ - ID: "0", - SessionID: validSessionId, - PhoneNumber: phoneNumber, - Level: level, - } - - validData := &dto.SessionDetails{ - SessionID: validSessionId, - PhoneNumber: &phoneNumber, - Level: level, - Text: text, - } - - type args struct { - ctx context.Context - input *dto.SessionDetails - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - //test cases. - { - name: "successful_persist_data", - args: args{ - ctx: ctx, - input: validData, - }, - wantErr: false, - want: validUSSDLeadDetails, - }, - { - name: "failed_persist_data", - args: args{ - ctx: ctx, - input: validData, - }, - wantErr: true, - }, - { - name: "failed_msisdn_normalize", - args: args{ - ctx: ctx, - input: validData, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "successful_persist_data" { - fakeBaseExt.NormalizeMSISDNFn = func(msisdn string) (*string, error) { - return &phoneNumber, nil - } - - fakeRepo.AddAITSessionDetailsFn = func(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) { - return validUSSDLeadDetails, nil - } - } - - if tt.name == "failed_persist_data" { - fakeBaseExt.NormalizeMSISDNFn = func(msisdn string) (*string, error) { - return &phoneNumber, nil - } - - fakeRepo.AddAITSessionDetailsFn = func(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) { - return nil, fmt.Errorf("failed to add session details") - } - - } - if tt.name == "failed_msisdn_normalize" { - fakeBaseExt.NormalizeMSISDNFn = func(msisdn string) (*string, error) { - return nil, fmt.Errorf("failed to normalize msisdn number") - } - - } - - got, err := u.AITUSSD.AddAITSessionDetails(tt.args.ctx, tt.args.input) - if (err != nil) != tt.wantErr { - t.Errorf("Impl.AddAITSessionDetails() error = %v, wantErr %v", err, tt.wantErr) - } - - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Impl.AddAITSessionDetails() = %v,want %v\n", got, tt.want) - } - - if tt.wantErr { - if err == nil { - t.Errorf("Expected an error but did not get one") - return - } - } - - if !tt.wantErr { - if err != nil { - t.Errorf("Did not expect an error but got one %v\n", err) - return - } - } - - }) - } -} - -func TestImpl_GetOrCreateSessionStateUnittest(t *testing.T) { - - ctx := context.Background() - u, err := InitializeFakeUSSDTestService() - - if err != nil { - t.Errorf("failed to initialize test service") - return - } - validSessionId := uuid.New().String() - phoneNumber := "+254707756919" - level := 0 - text := "1*gabriel*were" - - validUSSDLeadDetails := &domain.USSDLeadDetails{ - ID: "0", - SessionID: validSessionId, - PhoneNumber: phoneNumber, - Level: level, - } - - validSessionDetails := &dto.SessionDetails{ - SessionID: validSessionId, - PhoneNumber: &phoneNumber, - Level: level, - Text: text, - } - - type args struct { - ctx context.Context - payload *dto.SessionDetails - } - tests := []struct { - name string - args args - want *domain.USSDLeadDetails - wantErr bool - }{ - //test cases. - { - name: "successful_return_session", - args: args{ - ctx: ctx, - payload: validSessionDetails, - }, - wantErr: false, - want: validUSSDLeadDetails, - }, - { - name: "failed_return_session", - args: args{ - ctx: ctx, - payload: validSessionDetails, - }, - wantErr: true, - }, - { - name: "successful_set_session", - args: args{ - ctx: ctx, - payload: validSessionDetails, - }, - want: &domain.USSDLeadDetails{ - Level: 0, - ID: "0", - SessionID: validSessionId, - PhoneNumber: phoneNumber, - }, - wantErr: false, - }, - { - name: "failed_set_session", - args: args{ - ctx: ctx, - payload: validSessionDetails, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "successful_return_session" { - fakeRepo.GetAITSessionDetailsFn = func(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) { - return validUSSDLeadDetails, nil - } - } - - if tt.name == "failed_return_session" { - fakeRepo.GetAITSessionDetailsFn = func(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) { - return nil, fmt.Errorf("failed to get session details") - } - } - - if tt.name == "successful_set_session" { - fakeRepo.GetAITSessionDetailsFn = func(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) { - return nil, nil - } - fakeRepo.AddAITSessionDetailsFn = func(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{ - Level: 0, - ID: "0", - SessionID: validSessionId, - PhoneNumber: phoneNumber, - }, nil - } - } - - if tt.name == "failed_set_session" { - fakeRepo.GetAITSessionDetailsFn = func(ctx context.Context, sessionID string) (*domain.USSDLeadDetails, error) { - return nil, nil - } - - fakeRepo.AddAITSessionDetailsFn = func(ctx context.Context, input *dto.SessionDetails) (*domain.USSDLeadDetails, error) { - return nil, fmt.Errorf("failed to add session details") - } - } - - got, err := u.AITUSSD.GetOrCreateSessionState(tt.args.ctx, tt.args.payload) - if (err != nil) != tt.wantErr { - t.Errorf("Impl.GetOrCreateSessionState() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Impl.GetOrCreateSessionState() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestImpl_GetOrCreatePhoneNumberUserUnittest(t *testing.T) { - - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("failed to initialize test service") - return - } - - UID := uuid.New().String() - displayName := gofakeit.Name() - email := gofakeit.Email() - phoneNumber := "+254702215783" - photoURL := uuid.New().String() - providerId := uuid.New().String() - - createdUserResponse := dto.CreatedUserResponse{ - UID: UID, - DisplayName: displayName, - Email: email, - PhoneNumber: phoneNumber, - PhotoURL: photoURL, - ProviderID: providerId, - } - - type args struct { - ctx context.Context - phone string - } - tests := []struct { - name string - args args - want *dto.CreatedUserResponse - wantErr bool - }{ - //test cases. - { - name: "successful_get_or_create", - args: args{ - ctx: ctx, - phone: phoneNumber, - }, - wantErr: false, - want: &createdUserResponse, - }, - { - name: "failed_get_or_create", - args: args{ - ctx: ctx, - phone: "", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "successful_get_or_create" { - fakeRepo.GetOrCreatePhoneNumberUserFn = func(ctx context.Context, phone string) (*dto.CreatedUserResponse, error) { - return &createdUserResponse, nil - } - } - - if tt.name == "failed_get_or_create" { - fakeRepo.GetOrCreatePhoneNumberUserFn = func(ctx context.Context, phone string) (*dto.CreatedUserResponse, error) { - return nil, fmt.Errorf("failed to get or create user") - } - } - - got, err := u.AITUSSD.GetOrCreatePhoneNumberUser(tt.args.ctx, tt.args.phone) - if (err != nil) != tt.wantErr { - t.Errorf("Impl.GetOrCreatePhoneNumberUser() error = %v, wantErr %v", err, tt.wantErr) - - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Impl.GetOrCreatePhoneNumberUser() = %v, want %v", got, tt.want) - } - if tt.wantErr { - if err == nil { - t.Errorf("Expected an error but did not get one\n") - return - } - } - - if !tt.wantErr { - if err != nil { - t.Errorf("Did not expect an error but we got one\n") - return - } - } - }) - } -} - -func TestImpl_CreateUserProfileUnittest(t *testing.T) { - - ctx := context.Background() - u, err := InitializeFakeUSSDTestService() - - if err != nil { - t.Errorf("failed to initialize test service") - return - } - - profileID := uuid.New().String() - username := gofakeit.Name() - phoneNumber := "+254702215783" - termsAccepted := true - suspended := false - uid := uuid.New().String() - - userProfile := profileutils.UserProfile{ - ID: profileID, - UserName: &username, - PrimaryPhone: &phoneNumber, - TermsAccepted: termsAccepted, - Suspended: suspended, - VerifiedIdentifiers: []profileutils.VerifiedIdentifier{ - { - UID: uid, - LoginProvider: profileutils.LoginProviderTypePhone, - Timestamp: time.Now().In(pubsubtools.TimeLocation), - }, - }, - VerifiedUIDS: []string{uid}, - } - - type args struct { - ctx context.Context - phoneNumber string - uid string - } - tests := []struct { - name string - args args - want *profileutils.UserProfile - wantErr bool - }{ - //test cases. - { - name: "success_create_user_profile", - args: args{ - ctx: ctx, - phoneNumber: phoneNumber, - uid: uid, - }, - wantErr: false, - want: &userProfile, - }, - { - name: "failed_create_user_profile", - args: args{ - ctx: ctx, - phoneNumber: "", - uid: uid, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "success_create_user_profile" { - fakeRepo.CreateUserProfileFn = func(ctx context.Context, phoneNumber, uid string) (*profileutils.UserProfile, error) { - return &userProfile, nil - } - } - - if tt.name == "failed_create_user_profile" { - fakeRepo.CreateUserProfileFn = func(ctx context.Context, phoneNumber, uid string) (*profileutils.UserProfile, error) { - return nil, fmt.Errorf("failed to create user profile") - } - } - - got, err := u.AITUSSD.CreateUserProfile(tt.args.ctx, tt.args.phoneNumber, tt.args.uid) - if (err != nil) != tt.wantErr { - t.Errorf("Impl.CreateUserProfile() error = %v, wantErr %v", err, tt.wantErr) - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Impl.CreateUserProfile() = %v, want %v", got, tt.want) - } - - if tt.wantErr { - if err == nil { - t.Errorf("Expected an error but did not get one") - return - } - } - - if !tt.wantErr { - if err != nil { - t.Errorf("Did not expect an error but we got one") - return - } - } - }) - } -} - -func TestImpl_CreateEmptyCustomerProfileUnittest(t *testing.T) { - - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - if err != nil { - t.Errorf("failed to initialize test service") - return - } - - id := uuid.New().String() - profileId := uuid.New().String() - - customer := profileutils.Customer{ - ID: id, - ProfileID: &profileId, - } - - type args struct { - ctx context.Context - profileID string - } - tests := []struct { - name string - args args - want *profileutils.Customer - wantErr bool - }{ - //test cases. - { - name: "success_create_empty_customer_profile", - args: args{ - ctx: ctx, - profileID: profileId, - }, - want: &customer, - wantErr: false, - }, - { - name: "failed_create_empty_customer_profile", - args: args{ - ctx: ctx, - profileID: profileId, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if tt.name == "success_create_empty_customer_profile" { - fakeRepo.CreateEmptyCustomerProfileFn = func(ctx context.Context, profileID string) (*profileutils.Customer, error) { - return &customer, nil - } - } - if tt.name == "failed_create_empty_customer_profile" { - fakeRepo.CreateEmptyCustomerProfileFn = func(ctx context.Context, profileID string) (*profileutils.Customer, error) { - return nil, fmt.Errorf("failed to create empy customer profile") - } - } - - got, err := u.AITUSSD.CreateEmptyCustomerProfile(tt.args.ctx, tt.args.profileID) - if (err != nil) != tt.wantErr { - t.Errorf("Impl.CreateEmptyCustomerProfile() error = %v, wantErr %v", err, tt.wantErr) - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Impl.CreateEmptyCustomerProfile() = %v, want %v", got, tt.want) - } - - if tt.wantErr { - if err == nil { - t.Errorf("Expected an error but did not get one\n") - return - } - } - - if !tt.wantErr { - if err != nil { - t.Errorf("Did not expect an error but we got one\n") - return - } - } - }) - } -} - -func TestImpl_UpdateSessionLevel_UnitTest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - - if err != nil { - t.Errorf("failed to initialize test service") - return - } - - type args struct { - ctx context.Context - level int - sessionID string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - level: 50, - sessionID: "f44496b5-4f73-48f8-9f59-0ab79d3d571b", - }, - wantErr: false, - }, - { - name: "Sad case", - args: args{ - ctx: ctx, - level: 50, - sessionID: "", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case" { - fakeRepo.UpdateSessionLevelFn = func(ctx context.Context, sessionID string, level int) (*domain.USSDLeadDetails, error) { - return &domain.USSDLeadDetails{}, nil - } - } - - if tt.name == "Sad case" { - fakeRepo.UpdateSessionLevelFn = func(ctx context.Context, sessionID string, level int) (*domain.USSDLeadDetails, error) { - return nil, err - } - } - - if err := u.AITUSSD.UpdateSessionLevel(tt.args.ctx, tt.args.level, tt.args.sessionID); (err != nil) != tt.wantErr { - t.Errorf("Impl.UpdateSessionLevel() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestImpl_UpdateBioData_Unittest(t *testing.T) { - ctx := context.Background() - - u, err := InitializeFakeUSSDTestService() - - if err != nil { - t.Errorf("failed to initialize test service") - return - } - firstname := gofakeit.FirstName() - lastname := gofakeit.LastName() - - biodata := &profileutils.BioData{ - FirstName: &firstname, - LastName: &lastname, - DateOfBirth: &scalarutils.Date{}, - Gender: "Male", - } - - type args struct { - ctx context.Context - id string - data profileutils.BioData - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - id: "a51b1767-ee98-40d7-bc96-24e6f1c3e8b6", - data: *biodata, - }, - wantErr: false, - }, - { - name: "Sad case", - args: args{ - ctx: ctx, - id: "", - data: *biodata, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case" { - fakeRepo.UpdateBioDataFn = func(ctx context.Context, id string, data profileutils.BioData) error { - return nil - } - } - - if tt.name == "Sad case" { - fakeRepo.UpdateBioDataFn = func(ctx context.Context, id string, data profileutils.BioData) error { - return err - } - } - if err := u.AITUSSD.UpdateBioData(tt.args.ctx, tt.args.id, tt.args.data); (err != nil) != tt.wantErr { - t.Errorf("Impl.UpdateBioData() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestImpl_SaveUSSDEvent_Unittest(t *testing.T) { - ctx := context.Background() - currentTime := time.Now() - - u, err := InitializeFakeUSSDTestService() - - if err != nil { - t.Errorf("failed to initialize test service") - return - } - - type args struct { - ctx context.Context - input *dto.USSDEvent - } - tests := []struct { - name string - args args - want *dto.USSDEvent - wantErr bool - }{ - { - name: "Happy case", - args: args{ - ctx: ctx, - input: &dto.USSDEvent{ - SessionID: "0001000", - PhoneNumber: "+254700000000", - USSDEventDateTime: ¤tTime, - Level: 10, - USSDEventName: "chose to reset PIN", - }, - }, - wantErr: false, - }, - - { - name: "Sad case", - args: args{ - ctx: ctx, - input: nil, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name == "Happy case" { - fakeRepo.SaveUSSDEventFn = func(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) { - return &dto.USSDEvent{}, nil - } - } - if tt.name == "Sad case" { - fakeRepo.SaveUSSDEventFn = func(ctx context.Context, input *dto.USSDEvent) (*dto.USSDEvent, error) { - return nil, fmt.Errorf("an error occurred %v", err) - } - } - got, err := u.AITUSSD.SaveUSSDEvent(tt.args.ctx, tt.args.input) - if (err != nil) != tt.wantErr { - t.Errorf("Impl.SaveUSSDEvent() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !tt.wantErr && got == nil { - t.Errorf("Impl.SaveUSSDEvent() error = %v, wantErr %v", err, tt.wantErr) - return - } - }) - } -} diff --git a/pkg/onboarding/usecases/ussd/sub_menu.go b/pkg/onboarding/usecases/ussd/sub_menu.go deleted file mode 100644 index 814f9730..00000000 --- a/pkg/onboarding/usecases/ussd/sub_menu.go +++ /dev/null @@ -1,79 +0,0 @@ -package ussd - -import ( - "context" - "time" - - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" - "github.com/savannahghi/onboarding/pkg/onboarding/application/utils" - "github.com/savannahghi/onboarding/pkg/onboarding/domain" -) - -const ( - // OptOutFromMarketingInput indicates users who don't want to be send marketing sms(messages) - OptOutFromMarketingInput = "1" -) - -// WelcomeMenu represents the default welcome submenu -func (u *Impl) WelcomeMenu() string { - resp := "CON Welcome to Be.Well\r\n" - resp += "1. Opt out from marketing messages\r\n" - resp += "2. Change PIN" - return resp -} - -// ResetPinMenu ... -func (u *Impl) ResetPinMenu() string { - resp := "CON Your PIN was reset successfully.\r\n" - resp += "1. Opt out from marketing messages\r\n" - resp += "2. Change PIN" - return resp -} - -// HandleHomeMenu represents the default home menu -func (u *Impl) HandleHomeMenu(ctx context.Context, level int, session *domain.USSDLeadDetails, userResponse string) string { - ctx, span := tracer.Start(ctx, "HandleHomeMenu") - defer span.End() - - time := time.Now() - - if userResponse == EmptyInput || userResponse == GoBackHomeInput { - return u.WelcomeMenu() - - } else if userResponse == OptOutFromMarketingInput { - _, err := u.crm.OptOut(ctx, session.PhoneNumber) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again." - } - - // Capture enter old PIN event - if _, err := u.onboardingRepository.SaveUSSDEvent(ctx, &dto.USSDEvent{ - SessionID: session.SessionID, - PhoneNumber: session.PhoneNumber, - USSDEventDateTime: &time, - USSDEventName: USSDOptOut, - }); err != nil { - return "END Something went wrong. Please try again." - } - - resp := "CON We have successfully opted you\r\n" - resp += "out of marketing messages\r\n" - resp += "0. Go back home" - return resp - - } else if userResponse == ChangePINInput { - err := u.UpdateSessionLevel(ctx, ChangeUserPINState, session.SessionID) - if err != nil { - utils.RecordSpanError(span, err) - return "END Something went wrong. Please try again" - } - return u.HandleChangePIN(ctx, session, userResponse) - - } else { - resp := "CON Invalid choice. Try again.\r\n" - resp += "1. Opt out from marketing messages\r\n" - resp += "2. Change PIN" - return resp - } -} diff --git a/tests/config_test.go b/tests/config_test.go index 41996bab..db5e09cc 100644 --- a/tests/config_test.go +++ b/tests/config_test.go @@ -227,16 +227,6 @@ func composeSMSMessageDataPayload( return smspayload } -func composeUSSDPayload(t *testing.T, payload *dto.SessionDetails) *strings.Reader { - data := url.Values{} - data.Set("sessionId", payload.SessionID) - data.Set("phoneNumber", *payload.PhoneNumber) - data.Set("text", payload.Text) - - smspayload := strings.NewReader(data.Encode()) - return smspayload -} - func CreateTestUserByPhone(t *testing.T, phone string) (*profileutils.UserResponse, error) { validPayload, err := composeValidUserPayload(t, phone) if err != nil { @@ -630,7 +620,6 @@ func TestMain(m *testing.M) { r.GetNHIFDetailsCollectionName(), r.GetProfileNudgesCollectionName(), r.GetSMSCollectionName(), - r.GetUSSDDataCollectionName(), r.GetRolesCollectionName(), } for _, collection := range collections { diff --git a/tests/ussd_acceptance_test.go b/tests/ussd_acceptance_test.go deleted file mode 100644 index e4f113ff..00000000 --- a/tests/ussd_acceptance_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package tests - -import ( - "fmt" - "io" - "io/ioutil" - "net/http" - "testing" - - "github.com/savannahghi/interserviceclient" - "github.com/savannahghi/onboarding/pkg/onboarding/application/dto" -) - -func TestGenerateUSSD_acceptance_tests(t *testing.T) { - client := http.DefaultClient - - level := 0 - phoneNumber := interserviceclient.TestUserPhoneNumber - sessionID := "123456" - - // valid payload - payload := &dto.SessionDetails{ - SessionID: sessionID, - PhoneNumber: &phoneNumber, - Level: level, - Text: "", - } - - payload2 := &dto.SessionDetails{ - SessionID: "", - PhoneNumber: &phoneNumber, - Level: level, - Text: "Test Text", - } - - validPayload := composeUSSDPayload(t, payload) - emptySessionIDPayload := composeUSSDPayload(t, payload2) - - type args struct { - url string - httpMethod string - body io.Reader - } - tests := []struct { - name string - args args - wantStatus int - wantErr bool - }{ - { - name: "Success: receive ussd data with valid payload", - args: args{ - url: fmt.Sprintf("%s/ait_ussd", baseURL), - httpMethod: http.MethodPost, - body: validPayload, - }, - wantStatus: http.StatusOK, - wantErr: false, - }, - { - name: "Fail: receive ussd data with an empty sessionID", - args: args{ - url: fmt.Sprintf("%s/ait_ussd", baseURL), - httpMethod: http.MethodPost, - body: emptySessionIDPayload, - }, - wantStatus: http.StatusBadRequest, - wantErr: true, - }, - { - name: "Fail: receive ussd data with a nil payload", - args: args{ - url: fmt.Sprintf("%s/ait_ussd", baseURL), - httpMethod: http.MethodPost, - body: nil, - }, - wantStatus: http.StatusBadRequest, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - r, err := http.NewRequest( - tt.args.httpMethod, - tt.args.url, - tt.args.body, - ) - r.Header.Add("Content-Type", "application/x-www-form-urlencoded") - - if err != nil { - t.Errorf("can't create a new request: %v", err) - return - } - - if r == nil { - t.Errorf("nil request") - return - } - - for k, v := range interserviceclient.GetDefaultHeaders(t, baseURL, "profile") { - r.Header.Add(k, v) - } - - resp, err := client.Do(r) - if err != nil { - t.Errorf("HTTP error: %v", err) - return - } - - if tt.wantStatus != resp.StatusCode { - t.Errorf("expected status %d, got %d", tt.wantStatus, resp.StatusCode) - return - } - - dataResponse, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Errorf("can't read response body: %v", err) - return - } - - if dataResponse == nil { - t.Errorf("nil response body data") - return - } - }) - } - -}