Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/common/constants/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,35 @@ export enum UserType {
PROVIDER = 'PROVIDER',
}

export enum SenderType {
PAYER = 'PAYER',
PATIENT = 'PATIENT',
PROVIDER = 'PROVIDER',
}

export enum ReceiverType {
PATIENT = 'PATIENT',
PROVIDER = 'PROVIDER',
WII_QARE = 'WII_QARE',
}

export enum VoucherStatus {
CLAIMED = 'CLAIMED',
UNCLAIMED = 'UNCLAIMED',
CLAIMED = 'CLAIMED',
PENDING = 'PENDING',
BURNED = 'BURNED',
}

export enum TransactionStatus {
PENDING = 'PENDING',
FAILED = 'FAILED',
SUCCESSFUL = 'SUCCESSFUL',
PAID_OUT = 'PAID_OUT',
}

export enum ReferralStatus {
REDEEMED = 'REDEEMED',
NOT_REDEEMED = 'NOT_REDEEMED',
}

export enum InviteType {
Expand Down
8 changes: 4 additions & 4 deletions src/modules/patient-svc/patient-svc.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { User } from '../session/entities/user.entity';
import { Transaction } from '../smart-contract/entities/transaction.entity';
import { CreatePatientDto, PatientResponseDto } from './dto/patient.dto';
import {
ReceiverType,
TransactionStatus,
UserRole,
UserStatus,
UserType,
Expand Down Expand Up @@ -54,10 +56,8 @@ describe('PatientSvcService', () => {
amount: 1,
conversionRate: 1,
currency: 'FC',
ownerType: UserType.PATIENT,
status: VoucherStatus.UNCLAIMED,
transactionHash: 'transactionHash1',
shortenHash: 'shortenHash1',
ownerType: ReceiverType.PATIENT,
status: TransactionStatus.PENDING,
stripePaymentId: 'stripePaymentId1',
voucher: { voucher: 'voucher1' },
};
Expand Down
3 changes: 2 additions & 1 deletion src/modules/payer-svc/payer-svc.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import { SMSModule } from '../sms/sms.module';
import { Payer } from './entities/payer.entity';
import { PayerSvcController } from './payer-svc.controller';
import { PayerService } from './payer.service';
import { Voucher } from '../smart-contract/entities/voucher.entity';

@Module({
imports: [
TypeOrmModule.forFeature([Payer, User, Patient, Transaction]),
TypeOrmModule.forFeature([Payer, User, Patient, Transaction, Voucher]),
forwardRef(() => SessionModule),
MailModule,
PatientSvcModule,
Expand Down
32 changes: 28 additions & 4 deletions src/modules/payer-svc/payer-svc.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import { Payer } from './entities/payer.entity';
import { User } from '../session/entities/user.entity';
import { Transaction } from '../smart-contract/entities/transaction.entity';
import { Patient } from '../patient-svc/entities/patient.entity';
import { Voucher } from '../smart-contract/entities/voucher.entity';
import {
InviteType,
ReceiverType,
SenderType,
TransactionStatus,
UserRole,
UserStatus,
UserType,
Expand All @@ -22,12 +26,14 @@ import {
} from '@nestjs/common';
import { _400, _404, _403 } from '../../common/constants/errors';


describe('PayerService', () => {
let service: PayerService;
let payerRepository: Repository<Payer>;
let transactionRepository: Repository<Transaction>;
let patientRepository: Repository<Patient>;
let userRepository: Repository<User>;
let voucherRepository: Repository<Voucher>;

// Mock services
const mockMailService = {
Expand Down Expand Up @@ -88,14 +94,27 @@ describe('PayerService', () => {
senderId: mockPayer.id,
ownerId: mockPayer.id,
hospitalId: null,
ownerType: UserType.PAYER,
status: VoucherStatus.UNCLAIMED,
transactionHash: 'transactionHash',
shortenHash: 'shortenHash',
ownerType: ReceiverType.PROVIDER,
status: TransactionStatus.PENDING,
stripePaymentId: 'stripePaymentId',
voucher: { voucher: 'voucher' },
};

const mockVoucher: Voucher = {
id: '',
updatedAt: new Date(),
createdAt: new Date(),
voucherHash: '',
shortenHash: '',
value: 1,
senderId: mockPayer.id,
senderType: SenderType.PAYER,
receiverId: mockPatient.id,
receiverType: ReceiverType.PATIENT,
status: VoucherStatus.PENDING,
transaction: mockTransaction.id
}

beforeEach(async () => {
jest.clearAllMocks();

Expand Down Expand Up @@ -123,11 +142,16 @@ describe('PayerService', () => {
findOne: jest.fn().mockResolvedValue(mockTransaction),
} as unknown as Repository<Transaction>;

voucherRepository = {
findOne: jest.fn().mockResolvedValue(mockVoucher),
} as unknown as Repository<Voucher>;

service = new PayerService(
patientRepository,
payerRepository,
userRepository,
transactionRepository,
voucherRepository,
mockMailService as MailService,
mockSmsService as SmsService,
);
Expand Down
16 changes: 10 additions & 6 deletions src/modules/payer-svc/payer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Transaction } from '../smart-contract/entities/transaction.entity';
import { SmsService } from '../sms/sms.service';
import { CreatePayerAccountDto, SendInviteDto } from './dto/payer.dto';
import { Payer } from './entities/payer.entity';
import { Voucher } from '../smart-contract/entities/voucher.entity';

@Injectable()
export class PayerService {
Expand All @@ -31,6 +32,8 @@ export class PayerService {
private readonly userRepository: Repository<User>,
@InjectRepository(Transaction)
private readonly transactionRepository: Repository<Transaction>,
@InjectRepository(Voucher)
private readonly voucherRepository: Repository<Voucher>,
private readonly mailService: MailService,
private readonly smsService: SmsService,
) {}
Expand Down Expand Up @@ -158,31 +161,32 @@ export class PayerService {
shortenHash: string,
authUser: JwtClaimsDataDto,
): Promise<void> {
const [payer, transaction] = await Promise.all([
const [payer, voucher] = await Promise.all([
this.payerRepository
.createQueryBuilder('payer')
.leftJoinAndSelect('payer.user', 'user')
.where('user.id = :userId', { userId: authUser.sub })
.getOne(),
this.transactionRepository.findOne({ where: { shortenHash } }),
this.voucherRepository.findOne({ where: { shortenHash } }),
]);
const transaction = await this.transactionRepository.findOne({ where: { id: voucher.transaction }});

if (!payer) throw new NotFoundException(_404.PAYER_NOT_FOUND);

if (!transaction)
if (!voucher)
throw new NotFoundException(_404.INVALID_TRANSACTION_HASH);

if (transaction.senderId !== authUser.sub)
if (voucher.senderId !== authUser.sub)
throw new ForbiddenException(_403.ONLY_OWNER_CAN_SEND_VOUCHER);

const patient = await this.patientRepository.findOne({
where: { id: transaction.ownerId },
where: { id: voucher.receiverId },
});

if (!patient) throw new NotFoundException(_404.PATIENT_NOT_FOUND);

await this.smsService.sendVoucherAsAnSMS(
transaction.shortenHash,
voucher.shortenHash,
patient.phoneNumber,
authUser.names,
transaction.amount,
Expand Down
2 changes: 2 additions & 0 deletions src/modules/provider-svc/provider-svc.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Provider } from './entities/provider.entity';
import { Service } from './entities/service.entity';
import { ProviderController } from './provider-svc.controller';
import { ProviderService } from './provider-svc.service';
import { Voucher } from '../smart-contract/entities/voucher.entity';

@Module({
imports: [
Expand All @@ -21,6 +22,7 @@ import { ProviderService } from './provider-svc.service';
Patient,
Package,
Service,
Voucher
]),
ObjectStorageModule,
MailModule,
Expand Down
38 changes: 32 additions & 6 deletions src/modules/provider-svc/provider-svc.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ import {
VoucherStatus,
UserRole,
UserStatus,
ReceiverType,
TransactionStatus,
SenderType,
} from '../../common/constants/enums';
import { ForbiddenException, NotFoundException } from '@nestjs/common';
import { _403, _404 } from '../../common/constants/errors';
import { APP_NAME, DAY, HOUR } from '../../common/constants/constants';
import { RegisterProviderDto } from './dto/provider.dto';
import { Voucher } from '../smart-contract/entities/voucher.entity';

describe('ProviderService', () => {
let service: ProviderService;
Expand All @@ -30,6 +34,7 @@ describe('ProviderService', () => {
let userRepository: Repository<User>;
let packageRepository: Repository<Package>;
let serviceRepository: Repository<Service>;
let voucherRepository: Repository<Voucher>;

// Mock services
const mockObjectStorageService = {
Expand Down Expand Up @@ -110,10 +115,8 @@ describe('ProviderService', () => {
senderId: 'senderId',
ownerId: 'ownerId',
hospitalId: 'hospitalId',
ownerType: UserType.PATIENT,
status: VoucherStatus.UNCLAIMED,
transactionHash: 'transactionHash',
shortenHash: 'shortenHash',
ownerType: ReceiverType.PATIENT,
status: TransactionStatus.PENDING,
stripePaymentId: 'stripePaymentId',
voucher: { voucher: 'voucher' },
};
Expand Down Expand Up @@ -144,6 +147,21 @@ describe('ProviderService', () => {
country: 'country',
};

const mockVoucher: Voucher = {
id: '',
updatedAt: new Date(),
createdAt: new Date(),
voucherHash: '',
shortenHash: '',
value: 1,
senderId: mockProvider.id,
senderType: SenderType.PAYER,
receiverId: mockPatient.id,
receiverType: ReceiverType.PATIENT,
status: VoucherStatus.PENDING,
transaction: mockTransaction.id
}

// Mock relations
mockProvider.user = mockUser;
mockPackage.services = [mockService];
Expand All @@ -166,6 +184,15 @@ describe('ProviderService', () => {
getMany: jest.fn().mockResolvedValue([mockTransaction]),
}),
} as unknown as Repository<Transaction>;
voucherRepository = {
findOne: jest.fn().mockResolvedValue(mockVoucher),
save: jest.fn().mockResolvedValue(mockVoucher),
createQueryBuilder: jest.fn().mockReturnValue({
where: jest.fn().mockReturnThis(),
andWhere: jest.fn().mockReturnThis(),
getMany: jest.fn().mockResolvedValue([mockVoucher]),
}),
} as unknown as Repository<Voucher>;
patientRepository = {
findOne: jest.fn().mockResolvedValue(mockPatient),
save: jest.fn().mockResolvedValue(mockPatient),
Expand All @@ -187,6 +214,7 @@ describe('ProviderService', () => {
userRepository,
packageRepository,
serviceRepository,
voucherRepository,
mockObjectStorageService as ObjectStorageService,
mockCachingService as CachingService,
mockMailService as MailService,
Expand Down Expand Up @@ -354,8 +382,6 @@ describe('ProviderService', () => {
mockTransaction,
);
expect(result).toEqual({
hash: mockTransaction.transactionHash,
shortenHash: mockTransaction.shortenHash,
amount: mockTransaction.amount,
currency: mockTransaction.currency,
patientNames: `${mockPatient.firstName} ${mockPatient.lastName}`,
Expand Down
Loading