Skip to content

Commit

Permalink
Merge branch 'main' into Contact
Browse files Browse the repository at this point in the history
  • Loading branch information
Frdrcpeter007 authored Oct 30, 2023
2 parents 815e505 + d40b205 commit f9b35e8
Show file tree
Hide file tree
Showing 18 changed files with 13,687 additions and 9,706 deletions.
4 changes: 2 additions & 2 deletions src/common/constants/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ export enum VoucherStatus {
CLAIMED = 'CLAIMED',
PENDING = 'PENDING',
BURNED = 'BURNED',
// SPLIT = 'SPLIT'
SPLIT = 'SPLIT'
}

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

export enum ReferralStatus {
Expand Down
4 changes: 4 additions & 0 deletions src/common/constants/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export const _403 = {
code: 'ONLY_PAYER_CAN_CHECK_HIS_KYC_STATUS',
description: 'Seul le payer peux check son status',
},
WRONG_VOUCHER_CURRENCY: {
code: 'WRONG_VOUCHER_CURRENCY',
description: 'Voucher currency is different from hospital accepted currency',
}
};

export const _404 = {
Expand Down
27 changes: 27 additions & 0 deletions src/helpers/common.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,30 @@ export const randomSixDigit = (): string => {
export const generateToken = (): string => {
return crypto.randomBytes(16).toString('hex');
};


/**
* This helper function will convert currency using the api
*/
export async function convertCurrency(from: string, amount: number, to: string ) {
try {
const Options = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
//this should be moved to env vars
apikey: `i6sKwItIpG9o1PLxB6nykJ5OFecFsW8X`,
},
};

const response = await fetch(
`https://api.apilayer.com/exchangerates_data/convert?to=${to}&from=${from}&amount=${amount}`,
Options,
);
const json = await response.json();

return json;
} catch (error) {
return error;
}
}
1 change: 1 addition & 0 deletions src/modules/payer-svc/payer-svc.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ describe('PayerService', () => {
id: '',
updatedAt: new Date(),
createdAt: new Date(),
vid: 1,
voucherHash: '',
shortenHash: '',
value: 1,
Expand Down
8 changes: 8 additions & 0 deletions src/modules/provider-svc/dto/provider.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ export class AuthorizeVoucherTransferDto {
@IsNotEmpty()
@IsString()
securityCode: string;

@IsNotEmpty()
@IsArray()
services: string[];

@IsNotEmpty()
@IsNumber()
total: number;
}

export class SearchTransactionDto {
Expand Down
1 change: 1 addition & 0 deletions src/modules/provider-svc/entities/package.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ export class Package extends BaseEntity {
provider: Provider;

@ManyToMany(() => Service, (service) => service.packages)
@JoinTable()
services: Service[];
}
4 changes: 3 additions & 1 deletion src/modules/provider-svc/provider-svc.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,13 @@ export class ProviderController {
providerAuthorizeVoucherTransfer(
@Body() payload: AuthorizeVoucherTransferDto,
): Promise<Record<string, any>> {
const { shortenHash, providerId, securityCode } = payload;
const { shortenHash, providerId, securityCode, services, total } = payload;
return this.providerService.authorizeVoucherTransfer(
shortenHash,
providerId,
securityCode,
services,
total
);
}

Expand Down
3 changes: 3 additions & 0 deletions src/modules/provider-svc/provider-svc.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ 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';
import { SmartContractService } from '../smart-contract/smart-contract.service';
import { SmartContractModule } from '../smart-contract/smart-contract.module';

@Module({
imports: [
Expand All @@ -27,6 +29,7 @@ import { Voucher } from '../smart-contract/entities/voucher.entity';
ObjectStorageModule,
MailModule,
SMSModule,
SmartContractModule
],
controllers: [ProviderController],
providers: [ProviderService],
Expand Down
65 changes: 59 additions & 6 deletions src/modules/provider-svc/provider-svc.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ 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';
import { SmartContractService } from '../smart-contract/smart-contract.service';
import Web3 from 'web3';

describe('ProviderService', () => {
let service: ProviderService;
Expand Down Expand Up @@ -54,6 +56,11 @@ describe('ProviderService', () => {
sendTransactionVerificationTokenBySmsToAPatient: jest.fn(),
} as unknown as SmsService;

const mockSmartContractService = {
burnVoucher: () => {},
mintVoucher: () => {}
} as unknown as SmartContractService;

// Mock entities
const mockProvider: Provider = {
id: 'id',
Expand Down Expand Up @@ -98,7 +105,7 @@ describe('ProviderService', () => {
updatedAt: new Date(),
name: 'name',
description: 'description',
price: 1,
price: 100,
provider: new Provider(),
packages: [mockPackage],
};
Expand All @@ -107,11 +114,11 @@ describe('ProviderService', () => {
id: 'id',
createdAt: new Date(),
updatedAt: new Date(),
senderAmount: 1,
senderAmount: 1000,
senderCurrency: 'senderCurrency',
amount: 1,
amount: 1000,
conversionRate: 1,
currency: 'currency',
currency: 'CDF',
senderId: 'senderId',
ownerId: 'ownerId',
hospitalId: null,
Expand Down Expand Up @@ -151,9 +158,10 @@ describe('ProviderService', () => {
id: 'id',
updatedAt: new Date(),
createdAt: new Date(),
vid: 1,
voucherHash: '',
shortenHash: '',
value: 1,
value: 1000,
senderId: mockProvider.id,
senderType: SenderType.PAYER,
receiverId: mockPatient.id,
Expand Down Expand Up @@ -224,6 +232,7 @@ describe('ProviderService', () => {
mockCachingService as CachingService,
mockMailService as MailService,
mockSmsService as SmsService,
mockSmartContractService as SmartContractService,
);
});

Expand Down Expand Up @@ -419,6 +428,7 @@ describe('ProviderService', () => {
const shortenHash = 'shortenHash';
const providerId = 'id';
const securityCode = 'securityCode';
const services = ['id'];
const cachedToken = `${APP_NAME}:transaction:${shortenHash}`;

// it('should authorize a voucher transfer', async () => {
Expand Down Expand Up @@ -475,11 +485,54 @@ describe('ProviderService', () => {
mockCachingService.get = jest.fn().mockResolvedValue('savedSecurityCode');

await expect(
service.authorizeVoucherTransfer(shortenHash, providerId, securityCode),
service.authorizeVoucherTransfer(shortenHash, providerId, securityCode, services, 1000 ),
).rejects.toThrow(
new ForbiddenException(_403.INVALID_VOUCHER_TRANSFER_VERIFICATION_CODE),
);
});

it('should throw an error if the voucher currency is not CDF', async () => {
transactionRepository.findOne = jest.fn().mockResolvedValue( {...mockTransaction, currency: 'USD'} );

await expect(
service.authorizeVoucherTransfer(shortenHash, providerId, securityCode, services, 1000 ),
).rejects.toThrow(
new ForbiddenException(_403.WRONG_VOUCHER_CURRENCY),
);
});

it('should split into 2 vouchers with values summing the first voucher', async () => {
mockCachingService.get = jest.fn().mockResolvedValue( securityCode );
const voucher1 = { value: 100 };
const voucher2 = { value: 900 };
transactionRepository.create = jest.fn().
mockImplementationOnce( ( obj ) => { return {value: obj.amount} } ).
mockImplementationOnce( ( obj ) => { return {value: obj.amount} } );

voucherRepository.findOne = jest.fn().mockResolvedValue( mockVoucher );
voucherRepository.create = jest.fn().mockResolvedValue(
{}
);
providerRepository.findOne = jest.fn().mockResolvedValue( mockProvider );
serviceRepository.find = jest.fn().mockResolvedValue( [ mockService ] );

const mockMintedVoucher = {
events: {
mintVoucherEvent: {
transactionHash: 'hash1',
returnValues: {
'0': 1,
'1': [100, 'CDF', 'ownerId', 'hospitalId', 'patientId', 'UNCLAIMED']
}
}
}
}
mockSmartContractService.mintVoucher = jest.fn().mockResolvedValue( mockMintedVoucher );

const result = await service.authorizeVoucherTransfer(shortenHash, providerId, securityCode, services, 1000 );
expect( transactionRepository.create ).toHaveNthReturnedWith( 1, voucher1 );
expect( transactionRepository.create ).toHaveNthReturnedWith( 2, voucher2 );
});
});

describe('getAllTransactions', () => {
Expand Down
Loading

0 comments on commit f9b35e8

Please sign in to comment.