LifeSports Application(ReactNative & Nest.js) - 18. payment-service, UI

64632 ワード

#1支払ページ


決済ページを作成しましょう支払ページは、次の場合に使用できます.
1)管理職データ作成後直ちに支払う
2)大管データ生成後の次の日に支払う方法、次の日にデータを削除する方法
上記の例を考慮して、UIおよびRidexモジュールを最初に実装し、支払い-サービスおよびリース-サービスを変更します.

#2冗長モジュール


以前に作成した文書からrentalIdをPaymentScreenに移行したので、この値を受け入れ、拡張データを受信するモジュールを作成します.
  • ./src.lib/api/rental.js
  • import client from './client';
    
    export const rental = ({ 
        price,
        borrower,
        tel,
        userId,
        date,
        time,
        mapId,
        mapName
    }) => client.post('http://10.0.2.2:8000/rental-service/rental', {
        price,
        borrower,
        tel,
        userId,
        date,
        time,
        mapId,
        mapName
    });
    
    export const getRental = rentalId => client.get(`http://10.0.2.2:8000/rental-service/${rentalId}/rental`);
    
    export const getRentals = userId => client.get(`http://10.0.2.2:8000/rental-service/${userId}/rentals`);
  • ./src/modules/rentals.js
  • import { createAction, handleActions } from "redux-actions";
    import createRequestSaga, { createRequestActionTypes } from "../lib/createRequestSaga";
    import * as rentalAPI from '../lib/api/rental';
    import { takeLatest } from "@redux-saga/core/effects";
    
    const INITIALIZE = 'rental/INITIALIZE';
    
    const [
        GET_RENTAL,
        GET_RENTAL_SUCCESS,
        GET_RENTAL_FAILURE,
    ] = createRequestActionTypes('rental/GET_RENTAL');
    
    const [
        GET_RENTALS,
        GET_RENTALS_SUCCESS,
        GET_RENTALS_FAILURE
    ] = createRequestActionTypes('rental/GET_RENTALS');
    
    export const getRental = createAction(GET_RENTAL, rentalId => rentalId);
    
    export const getRentals = createAction(GET_RENTALS, userId => userId);
    
    const getRentalSaga = createRequestSaga(GET_RENTAL, rentalAPI.getRental);
    
    const getRentalsSaga = createRequestSaga(GET_RENTALS, rentalAPI.getRentals);
    
    export function* rentalsSaga() {
        yield takeLatest(GET_RENTAL, getRentalSaga);
        yield takeLatest(GET_RENTALS, getRentalsSaga);
    }
    
    const initialState = {
        rental: null,
        rentals: null,
        error: null,
    };
    
    const rentals = handleActions(
        {
            [INITIALIZE]: (state => initialState),
            [GET_RENTAL_SUCCESS]: (state, { payload: rental }) => ({
                ...state,
                rental
            }),
            [GET_RENTAL_FAILURE]: (state, { payload: error }) => ({
                ...state,
                error
            }),
            [GET_RENTALS_SUCCESS]: (state, { payload: rentals }) => ({
                ...state,
                rentals,
            }),
            [GET_RENTALS_FAILURE]: (state, { payload: error }) => ({
                ...state,
                error,
            }),
        },
        initialState,
    );
    
    export default rentals;
    rentalIdをメディアとして拡張データをロードし、userIdをメディアとしてユーザーの拡張データをロードするモジュール.支払いモジュールを完了し、UIを作成します.
  • ./src/lib/api/payment.js
  • import client from './client';
    
    export const requestPayment = ({
        paymentName,
        payer,
        rentalId,
        price
    }) => client.post('http://10.0.2.2:8000/payment-service/payment', {
        paymentName,
        payer,
        rentalId,
        price
    });
    
    export const getPayments = payer => client.get(`http://10.0.2.2:8000/payment-service/${payer}/payments`);
    
    export const getPayment = paymentId => client.get(`http://10.0.2.2:8000/payment-service/${paymentId}/payment`);
    これは支払請求モジュールです.
  • ./src/modules/payment.js
  • import { createAction, handleActions } from "redux-actions";
    import createRequestSaga, { createRequestActionTypes } from "../lib/createRequestSaga";
    import * as paymentAPI from '../lib/api/payment';
    import { takeLatest } from "@redux-saga/core/effects";
    
    const CHANGE_FIELD = 'payment/CHANGE_FIELD';
    const INITIAILIZE = 'payment/INITIALIZE';
    const [
        REQUEST_PAYMENT,
        REQUEST_PAYMENT_SUCCESS,
        REQUEST_PAYMENT_FAILURE,
    ] = createRequestActionTypes('payment/REQUEST_PAYMENT');
    
    export const changeField = createAction(CHANGE_FIELD, ({
        key,
        value
    }) => ({
        key,
        value
    }));
    
    export const initialize = createAction(INITIAILIZE);
    
    export const requestPayment = createAction(REQUEST_PAYMENT, ({
        paymentName,
        payer,
        rentalId,
        price
    }) => ({
        paymentName,
        payer,
        rentalId,
        price
    }));
    
    const requestPaymentSaga = createRequestSaga(REQUEST_PAYMENT, paymentAPI.requestPayment);
    
    export function* paymentSaga() {
        yield takeLatest(REQUEST_PAYMENT, requestPaymentSaga);
    }
    
    const intialState = {
        paymentName: null,
        payer: null,
        rentalId: null,
        price: null,
        payment: null,
        paymentError: null,
    };
    
    const payment = handleActions(
        {
            [INITIAILIZE]: state => intialState,
            [CHANGE_FIELD]: (state, { payload: { key, value }}) => ({
                ...state,
                [key]: value
            }),
            [REQUEST_PAYMENT_SUCCESS]: (state, { payload: payment }) => ({
                ...state,
                payment
            }),
            [REQUEST_PAYMENT_FAILURE]: (state, { payload: paymentError }) => ({
                ...state,
                paymentError
            }),
        },
        intialState,
    );
    
    export default payment;
    またpaymentモジュールを作成して、支払データをインポートします.
  • ./src/modules/payments.js
  • import { createAction, handleActions } from "redux-actions";
    import createRequestSaga, { createRequestActionTypes } from "../lib/createRequestSaga";
    import * as paymentAPI from '../lib/api/payment';
    import { takeLatest } from "@redux-saga/core/effects";
    
    const INITIALIZE = 'payment/INITIALIZE';
    
    const [
        GET_PAYMENT,
        GET_PAYMENT_SUCCESS,
        GET_PAYMENT_FAILURE,
    ] = createRequestActionTypes('payment/GET_PAYMENT');
    
    const [
        GET_PAYMENTS,
        GET_PAYMENTS_SUCCESS,
        GET_PAYMENTS_FAILURE
    ] = createRequestActionTypes('payment/GET_PAYMENTS');
    
    export const initialize = createAction(INITIALIZE);
    
    export const getPayment = createAction(GET_PAYMENT, paymentId => paymentId);
    
    export const getPayments = createAction(GET_PAYMENTS, payer => payer);
    
    const getPaymentSaga = createRequestSaga(GET_PAYMENT, paymentAPI.getPayment);
    
    const getPaymentsSaga = createRequestSaga(GET_PAYMENTS, paymentAPI.getPayments);
    
    export function* paymentsSaga() {
        yield takeLatest(GET_PAYMENT, getPaymentSaga);
        yield takeLatest(GET_PAYMENTS, getPaymentsSaga);
    }
    
    const initialState = {
        payment: null,
        payments: null,
        error: null,
    };
    
    const payments = handleActions(
        {
            [INITIALIZE]: (state => initialState),
            [GET_PAYMENT_SUCCESS]: (state, { payload: payment }) => ({
                ...state,
                payment
            }),
            [GET_PAYMENT_FAILURE]: (state, { payload: error }) => ({
                ...state,
                error
            }),
            [GET_PAYMENTS_SUCCESS]: (state, { payload: payments }) => ({
                ...state,
                payments,
            }),
            [GET_PAYMENTS_FAILURE]: (state, { payload: error }) => ({
                ...state,
                error,
            }),
        },
        initialState,
    );
    
    export default payments;
    payment、rentalsモジュールが完了しました.支払いページUIを完了しましょう.

    #3 UI

  • ./src/pages/payment/components/PaymentFragment.js
  • import React, { useEffect } from 'react';
    import { useNavigation, useRoute } from '@react-navigation/native';
    import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
    import { useDispatch, useSelector } from 'react-redux';
    import { changeField, initialize, requestPayment } from '../../../modules/payment';
    import StyledTextInput from '../../../styles/common/StyledTextInput';
    import palette from '../../../styles/palette';
    import { getRental } from '../../../modules/rentals';
    import Loading from '../../../styles/common/Loading';
    
    const PaymentFragment = () => {
        const dispatch = useDispatch();
        const route = useRoute();
        const navigation = useNavigation();
        const { 
            paymentName,
            payer,
            rentalId,
            price,
            payment,
            paymentError,
            rental,
            error 
        } = useSelector(({ 
            rentals,
            payment,
        }) => ({ 
            paymentName: payment.paymentName,
            payer: payment.payer,
            rentalId: payment.rentalId,
            price: payment.price,
            payment: payment.payment,
            paymentError: payment.paymentError,
            rental: rentals.rental 
        }));
        const onPayment = () => {
            dispatch(requestPayment({
                paymentName,
                payer,
                rentalId,
                price
            }));
        };
    
        useEffect(() => {
            dispatch(getRental(route.params.rentalId));
        }, [dispatch, route]);
    
        useEffect(() => {
            dispatch(changeField({
                key: 'paymentName',
                value: rental.mapName
            }))
        }, [dispatch, rental]);
    
        useEffect(() => {
            dispatch(changeField({
                key: 'payer',
                value: rental.borrower
            }))
        }, [dispatch, rental]);
    
        useEffect(() => {
            dispatch(changeField({
                key: 'rentalId',
                value: rental.rentalId
            }))
        }, [dispatch, rental]);
    
        useEffect(() => {
            dispatch(changeField({
                key: 'price',
                value: rental.price
            }))
        }, [dispatch, rental]);
    
        useEffect(() => {
            if(payment) {
                navigation.goBack();
    
                dispatch(initialize())
            }
    
            if(paymentError) {
                // setError
            }
        }, [dispatch, payment]);
    
        useEffect(() => {
            if(error) {
                // setError
            }
        }, [error]);
    
        return(
            rental ?
            <View style={ styles.container }>
                <View style={ styles.row } >
                    <Text style={ styles.label } >
                        대관 번호
                    </Text>
                    <StyledTextInput placeholderTextColor={ palette.black[0] }
                                    value={ rental.rentalId }
                    />
                </View>
                <View style={ styles.row }>
                    <Text style={ styles.label }>
                        결제 내역
                    </Text>
                    <StyledTextInput placeholderTextColor={ palette.gray[3] }
                                    value={ rental.mapName }
                    />
                </View>
                <View style={ styles.row }>
                    <Text style={ styles.label }>
                        결제 금액
                    </Text>
                    <StyledTextInput placeholderTextColor={ palette.gray[3] }
                                    value={ rental.price.toString() }
                    />
                </View>
                <View style={ styles.row }>
                    <Text style={ styles.label } >
                        사용자명
                    </Text>
                    <StyledTextInput placeholderTextColor={ palette.gray[3] }
                                    value={ rental.borrower }
                    />
                </View>
                <View style={ styles.row } >
                    <Text style={ styles.label }>
                        체육관 전화번호
                    </Text>
                    <StyledTextInput placeholderTextColor={ palette.gray[3] }
                                    value={ rental.tel }
                    />
                </View>
                <View style={ styles.row } >
                    <Text style={ styles.label } >
                        대관 날짜
                    </Text>
                    <StyledTextInput placeholderTextColor={ palette.gray[3] }
                                    value={ rental.date + "\t" + rental.time }
                    />
                </View>
                <View style={ styles.button_container }>
                    <TouchableOpacity style={ styles.shape }
                                    onPress={ onPayment }
                    >
                        <Text style={ styles.font }>
                            결제하기
                        </Text>
                    </TouchableOpacity>
                </View>
            </View> : <Loading />
        );
    };
    
    const styles = StyleSheet.create({
        container: {
            flexDirection: 'column',
            width: '90%',
            height: '90%',
            backgroundColor: palette.white[0],
        },
        row: {
            flexDirection: 'row',
            alignItems: 'center',
            overflow: 'hidden'
        },
        label: {
            fontWeight: 'bold',
            padding: 10,
        },
        button_container: {
            justifyContent: 'center',
            alignItems: 'center',
            marginTop: 30
        },
        shape: {
            justifyContent: 'center',
            alignItems: 'center',
            width: '80%',
            height: 70,
            backgroundColor: palette.blue[2]
        },
        font: {
            justifyContent: 'center',
            alignItems: 'center',
            fontWeight: 'bold',
            fontSize: 20,
            color: palette.white[0]
        }
    });
    
    export default PaymentFragment;
    PaymentFragmentは、前ページから取得したrentalIdをメディアとして使用して、拡張データを取得する.次に、管理データがstateに格納されている場合は、useEffect hookを使用して支払いに必要なstate値を保存します.したがって、ステータス値を使用して支払いを行うことができます.
  • ./src/pages/payment/PaymentScreen.js
  • import React from 'react';
    import { StyleSheet, View } from 'react-native';
    import PaymentContent from './components/PaymentFragment';
    
    const PaymentScreen = () => {
        return(
            <View style={ styles.container }>
                <PaymentContent />
            </View>
        );
    };
    
    const styles = StyleSheet.create({
        container: {
            flex: 1,
            alignItems: 'center',
            justifyContent: 'center'
        }
    });
    
    export default PaymentScreen;
  • ./src/styles/common/StyledTextInput.js
  • import React from 'react';
    import { StyleSheet, TextInput } from 'react-native';
    import palette from '../palette';
    
    const StyledTextInput = ({
        inputAccessoryViewID,
        placeholder,
        placeholderTextColor,
        onChange,
        value
    }) => {
        return(
            <TextInput style={ styles.input }
                       placeholder={ placeholder }
                       placeholderTextColor={ placeholderTextColor }
                       inputAccessoryViewID={ inputAccessoryViewID }
                       onChange={ onChange }
                       value={ value }
            />
        );
    };
    
    const styles = StyleSheet.create({
        input: {
            width: 300,
            height: 40,
            borderRadius: 4,
            justifyContent: 'center',
            alignItems: 'center',
            backgroundColor: palette.white[0],
            color: palette.black[0],
            fontSize: 15,
            margin: 10,
        },
    });
    
    export default StyledTextInput;
  • ./src/navigator/map/MapStackNaivigation.js
  • import 'react-native-gesture-handler';
    import React from 'react';
    import { createStackNavigator } from '@react-navigation/stack';
    import MapScreen from '../../pages/map/MapScreen';
    import DetailScreen from '../../pages/map/DetailScreen';
    import PaymentScreen from '../../pages/payment/PaymentScreen';
    
    const Stack = createStackNavigator();
    
    const MapStackNavigation = () => {
        return(
            <Stack.Navigator>
                <Stack.Screen name="Map"
                              component={ MapScreen }
                              options={{
                                  headerShown: false,
                              }}
                />
                <Stack.Screen name="Detail"
                              component={ DetailScreen }
                />
                <Stack.Screen name="Payment"
                              component={ PaymentScreen }
                />
            </Stack.Navigator>
        );
    };
    
    export default MapStackNavigation;
    私のページで詳細を拡大します.管理履歴のデータには、決済済みのデータと未決済のデータが含まれます.TCP層を介して支払いサービスと通信し,支払いデータと支払いデータを共にユーザに表示する.
  • ./src/pages/user/MyRentalScreen.js
  • import React from 'react';
    import {
        StyleSheet,
        View,
        Text
    } from 'react-native';
    import palette from '../../styles/palette';
    import MyRentalFramgment from './components/MyRentalFramgent';
    
    const MyRentalScreen = () => {
        return(
            <View style={ styles.container }>
                <MyRentalFramgment />
            </View>
        );
    };
    
    const styles = StyleSheet.create({
        container: {
            flex: 1,
            backgroundColor: palette.white[0],      
        },
    });
    
    export default MyRentalScreen;
  • ./src/pages/user/components/MyRentalFragment.js
  • import React, { useEffect } from 'react';
    import { StyleSheet, View } from 'react-native';
    import { useDispatch, useSelector } from 'react-redux';
    import { getRentals } from '../../../modules/rentals';
    import Loading from '../../../styles/common/Loading';
    import palette from '../../../styles/palette';
    import MyRenalCard from './MyRentalCard';
    
    const MyRentalFramgment = () => {
        const dispatch = useDispatch();
        const { 
            userId,
            rentals
        } = useSelector(({ 
            user,
            rentals
        }) => ({
            userId: user.user.userId, 
            rentals: rentals.rentals 
        }));
        
        useEffect(() => {
            dispatch(getRentals(userId));
        }, [dispatch]);
    
        return(
            <View style={ styles.container }>
                {
                    rentals ?
                    rentals.map((item, i) => {
                        return <MyRenalCard i={ i }
                                            item={ item }
                                />
                    }) : <Loading />
                }
            </View>
        );
    };
    
    const styles = StyleSheet.create({
        container: {
            flex: 1,
            backgroundColor: palette.gray[2],
        }
    });
    
    export default MyRentalFramgment;
  • ./src/pages/user/components/MyRentalCard.js
  • import React from 'react';
    import { StyleSheet, Text, View } from 'react-native';
    import palette from '../../../styles/palette';
    
    const MyRenalCard = ({ item }) => {
        return(
            <View style={ styles.container }>
                <Text style={ styles.font }>
                    { item.date + " " + item.time }
                </Text>
                <Text style={ styles.font }>
                    { item.mapName }
                </Text>
            </View>
        );
    };
    
    const styles = StyleSheet.create({
        container: {
            alignItems: 'center',
            justifyContent: 'center',
            width: 350,
            height: 50,
            marginLeft: 30,
            marginTop: 15,
            marginBottom: 5,
            borderRadius: 30,
            backgroundColor: palette.gray[3]
        },
        font: {
            fontWeight: 'bold',
            fontSize: 15
        }
    });
    
    export default MyRenalCard;
    react本機の実施部分はすでに完了しており、レンタル-サービス、支払い-サービスをさらに実施します.

    #4 rental-service, payment-service


    リース-サービスの応答.rental.tsvoクラスとレンタル.dto.tsdtoクラスに次のように追加します.
  • ./src/vo/reponse.rental.ts
  • import { IsNumber, IsObject, IsString } from "class-validator";
    
    export class ResponseRental {
        ...
    
        payment: any;
    }
  • ./src/dto/rental.dto.ts
  • import { IsNumber, IsObject, IsString } from "class-validator";
    
    export class RentalDto {
        ...
    
        payment: any;
    }
    大文字データとともに支払データも呼び出されるため、支払データを格納するための列である.
    axiosライブラリを使用して、他のサービスからデータを呼び出します.
    npm install --save @nestjs/axios
  • ./src/rental/rental.module.ts
  • import { Module } from '@nestjs/common';
    import { ClientsModule, Transport } from '@nestjs/microservices';
    import { MongooseModule } from '@nestjs/mongoose';
    import { Rental, RentalSchema } from 'src/schema/rental.schema';
    import { RentalService } from './rental.service';
    
    @Module({
      imports: [
        MongooseModule.forFeature([{
          name: Rental.name,
          schema: RentalSchema,
        }]),
        HttpModule,
      ],
      providers: [RentalService],
      exports: [RentalService],
    })
    export class RentalModule {}
  • ./src/app.controller.ts
  • import { Body, Controller, Delete, Get, HttpStatus, Param, Patch, Post } from "@nestjs/common";
    import { statusConstants } from "./constants/status.constant";
    import { RentalService } from "./rental/rental.service";
    import { RequestRental } from "./vo/request.rental";
    import { ResponseRental } from "./vo/response.rental";
    import { Builder } from 'builder-pattern';
    import { RentalDto } from "./dto/rental.dto";
    import { EventPattern } from "@nestjs/microservices";
    
    @Controller('rental-service')
    export class AppController {
        constructor(private readonly rentalService: RentalService) {}
    
        @Post('rental')
        public async rental(@Body() vo: RequestRental): Promise<any> {
            try {
                const result: any = await this.rentalService.create(Builder(RentalDto).price(vo.price)
                                                                                      .borrower(vo.borrower)
                                                                                      .tel(vo.tel)
                                                                                      .userId(vo.userId)
                                                                                      .date(vo.date)
                                                                                      .time(vo.time)
                                                                                      .mapId(vo.mapId)
                                                                                      .mapName(vo.mapName)
                                                                                      .build());
    
                if(result.status === statusConstants.ERROR) {
                    return await Object.assign({
                        statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
                        payload: null,
                        message: result.message
                    });
                }
    
                return await Object.assign({
                    statusCode: HttpStatus.CREATED,
                    payload: Builder(ResponseRental).rentalId(result.payload.rentalId)
                                                    .price(result.payload.price)
                                                    .borrower(result.payload.borrower)
                                                    .tel(result.payload.tel)
                                                    .userId(result.payload.userId)
                                                    .date(result.payload.date)
                                                    .time(result.payload.time)
                                                    .mapId(result.payload.mapId)
                                                    .mapName(result.payload.mapName)
                                                    .status(result.payload.status)
                                                    .build(),
                    message: "Successfully rental"
                });
            } catch(err) {
                return await Object.assign({
                    statusCode: HttpStatus.BAD_REQUEST,
                    payload: null,
                    message: "Error message: " + err
                });
            }
        } 
    
        @Get(':rentalId/rental')
        public async getRental(@Param('rentalId') rentalId: string) {
            try {
                const result: any = await this.rentalService.getOne(rentalId);
    
                if(result.status === statusConstants.ERROR) {
                    return await Object.assign({
                        statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
                        payload: null,
                        message: result.message
                    });
                }
    
                return await Object.assign({
                    statusCode: HttpStatus.OK,
                    payload: Builder(ResponseRental).rentalId(result.payload.rentalId)
                                                    .price(result.payload.price)
                                                    .borrower(result.payload.borrower)
                                                    .tel(result.payload.tel)
                                                    .userId(result.payload.userId)
                                                    .date(result.payload.date)
                                                    .time(result.payload.time)
                                                    .mapId(result.payload.mapId)
                                                    .mapName(result.payload.mapName)
                                                    .status(result.payload.status)
                                                    .build(),
                    message: "Get rental by rentalId"
                });
            } catch(e) {
                return await Object.assign({
                    statusCode: HttpStatus.BAD_REQUEST,
                    payload: null,
                    message: e
                });
            }
        }
    
        @Get(':userId/rentals')
        public async getRentals(@Param('userId') userId: string) {
            try {
                const result: any = await this.rentalService.getRentals(userId);
                
                if(result.status === statusConstants.ERROR) {
                    return await Object.assign({
                        statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
                        payload: null,
                        message: result.message
                    });
                }
    
                const responseRentals: Array<ResponseRental> = [];
    
                for(const el of result.payload) {
                    responseRentals.push(el);
                }
    
                return await Object.assign({
                    status: HttpStatus.OK,
                    payload: responseRentals,
                    message: "Get list by userId"
                });
            } catch(err) {
                return await Object.assign({
                    status: HttpStatus.BAD_REQUEST,
                    payload: null,
                    message: "Error message: " + err
                });
            }
        }
    
        @Patch(':rentalId/rental')
        public async expiredRental(@Param('rentalId') rentalId: string) {
            try {
                const result: any = await this.rentalService.expiredRental(rentalId);
    
                if(result.status === statusConstants.ERROR) {
                    return await Object.assign({
                        statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
                        payload: null,
                        message: result.message
                    });
                }
    
                return await Object.assign({
                    statusCode: HttpStatus.OK,
                    payload: null,
                    message: "Successfully rental"
                });
            } catch(e) {
                return await Object.assign({
                    statusCode: HttpStatus.BAD_REQUEST,
                    payload: null,
                    message: e
                });
            }
        }
    
        @EventPattern('PAYMENT_RESPONSE')
        public async responsePayment(data: any): Promise<any> {
            try {
                if(data === 'FAILURE_PAYMENT') {
                    const result: any = await this.rentalService.deleteRental(Builder(RentalDto).rentalId(data.rentalId)
                                                                                                .build());
    
                    if(result.status === statusConstants.ERROR) {
                        return await Object.assign({
                            status: HttpStatus.INTERNAL_SERVER_ERROR,
                            payload: null,
                            message: "Error message: " + result.message
                        });
                    }
    
                    return await Object.assign({
                        status: HttpStatus.INTERNAL_SERVER_ERROR,
                        payload: null,
                        message: "Error message: " + data
                    });
                }
    
                const result: any = await this.rentalService.completeRental(Builder(RentalDto).rentalId(data.rentalId)
                                                                                              .build());
    
                if(result.status === statusConstants.ERROR) {
                    return await Object.assign({
                        status: HttpStatus.INTERNAL_SERVER_ERROR,
                        payload: null,
                        message: "Error message: " + result.message
                    });
                }
    
                return await Object.assign({
                   status: HttpStatus.OK,
                   payload: null,
                   message: "Successful complete rental!" 
                });
            } catch(err) {
                return await Object.assign({
                    status: HttpStatus.INTERNAL_SERVER_ERROR,
                    payload: null,
                    message: "Error message: " + err
                });
            }
        }
    }
    次にRentalServiceのgetRentalsメソッドを追加します.getRentalsは「拡大」リストにロードされ、id値に一致する支払データがdtoオブジェクトに含まれます.
  • ./src/rental/service/rental.service.ts
  • import { Inject, Injectable } from '@nestjs/common';
    import { InjectModel } from '@nestjs/mongoose';
    import { Model } from 'mongoose';
    import { statusConstants } from 'src/constants/status.constant';
    import { RentalDto } from 'src/dto/rental.dto';
    import { Rental, RentalDocument } from 'src/schema/rental.schema';
    import { Builder } from 'builder-pattern';
    import { v4 as uuid } from 'uuid';
    import { ResponseRental } from 'src/vo/response.rental';
    import { status } from 'src/constants/rental.status';
    import { HttpService } from '@nestjs/axios';
    import { map, Observable } from 'rxjs';
    import { AxiosResponse } from 'axios';
    import { response } from 'express';
    
    @Injectable()
    export class RentalService {
        constructor(
            @InjectModel(Rental.name) private rentalModel: Model<RentalDocument>,
            private httpService: HttpService    
        ) {}
    
        public async create(dto: RentalDto): Promise<any> {
            try {
                const entity: any = await new this.rentalModel(Builder(Rental).rentalId(uuid())
                                                                              .price(dto.price)
                                                                              .borrower(dto.borrower)
                                                                              .tel(dto.tel)
                                                                              .userId(dto.userId)
                                                                              .date(dto.date)
                                                                              .time(dto.time)
                                                                              .mapId(dto.mapId)
                                                                              .mapName(dto.mapName)
                                                                              .status(status.PENDING)
                                                                              .createdAt(new Date().toDateString())
                                                                              .build())
                                                                              .save();
    
                if(!entity) {
                    return await Object.assign({
                        status: statusConstants.ERROR,
                        payload: null,
                        message: "rental-service: database error" 
                    });
                }
    
                return await Object.assign({
                    status: statusConstants.SUCCESS,
                    payload: Builder(RentalDto).rentalId(entity.rentalId)
                                               .price(entity.price)
                                               .borrower(entity.borrower)
                                               .tel(entity.tel)
                                               .userId(entity.userId)
                                               .date(entity.date)
                                               .time(entity.time)
                                               .mapId(entity.mapId)
                                               .mapName(entity.mapName)
                                               .status(entity.status)
                                               .createdAt(entity.createdAt)
                                               .build(),
                    message: "Successful transaction"
                });
            } catch(err) {
                return Object.assign({
                    status: statusConstants.ERROR,
                    payload: null,
                    message: "rental-service: " + err
                });
            }
        }
    
        public async getOne(rentalId: string): Promise<any> {
            try {
                const result: any = await this.rentalModel.findOne({ rentalId: rentalId });
    
                if(!result) {
                    return await Object.assign({
                        statusCode: statusConstants.ERROR,
                        payload: null,
                        message: "Not rental data"
                    });
                }
    
                return await Object.assign({
                    statusCode: statusConstants.SUCCESS,
                    payload: Builder(RentalDto).rentalId(result.rentalId)
                                               .price(result.price)
                                               .borrower(result.borrower)
                                               .tel(result.tel)
                                               .userId(result.userId)
                                               .date(result.date)
                                               .time(result.time)
                                               .mapId(result.mapId)
                                               .mapName(result.mapName)
                                               .status(result.status)
                                               .createdAt(result.createdAt)
                                               .build(),
                    message: "Success transcation",
                });
            } catch(err) {
                return await Object.assign({
                    statusCode: statusConstants.ERROR,
                    payload: null,
                    message: "map-service database: " + err,
                });
            }
        }
    
        public async getRentals(userId: string): Promise<any> {
            try {
                const result: any = await this.rentalModel.find({ userId: userId });
    
                if(!result) {
                    return await Object.assign({
                        statusCode: statusConstants.ERROR,
                        payload: null,
                        message: "Not rental datas"
                    });
                }
                
                const dtoRentals: Array<ResponseRental> = [];
    
                for(const el of result) {
                    const payment = await this.httpService.get(`http://localhost:8000/payment-service/${el.rentalId}/payment-from-rental`)
                                                          .toPromise();
                    
                    const dto = Builder(RentalDto).rentalId(el.rentalId)
                                                  .price(el.price)
                                                  .borrower(el.borrower)
                                                  .tel(el.tel)
                                                  .userId(el.userId)
                                                  .date(el.date)
                                                  .time(el.time)
                                                  .mapId(el.mapId)
                                                  .mapName(el.mapName)
                                                  .status(el.status)
                                                  .createdAt(el.createdAt)
                                                  .payment(payment.data.payload)
                                                  .build();
                    
                    dtoRentals.push(dto);
                }
    
                return await Object.assign({
                    statusCode: statusConstants.SUCCESS,
                    payload: dtoRentals,
                    message: "Success transcation",
                });
            } catch(err) {
                return await Object.assign({
                    statusCode: statusConstants.ERROR,
                    payload: null,
                    message: "map-service database: " + err,
                });
            }
        }
    
        public async expiredRental(rentalId): Promise<any> {
            try {
                const result  = await this.rentalModel.updateOne({ rentalId: rentalId }, { $set: { status: status.EXPIRED }});
                
                if(!result) {
                    return await Object.assign({
                        statusCode: statusConstants.ERROR,
                        payload: null,
                        message: "Not exist data",
                    });
                }
    
                return await Object.assign({
                    statusCode: statusConstants.SUCCESS,
                    payload: null,
                    message: "Success delete"
                });
            } catch(err) {
                return await Object.assign({
                    statusCode: statusConstants.ERROR,
                    payload: null,
                    message: "rental-service database: " + err,
                });
            }
        }
    
        public async deleteRental(dto: RentalDto): Promise<any> {
            try {
                const result  = await this.rentalModel.deleteOne({ rentalId: dto.rentalId });
                
                if(!result) {
                    return await Object.assign({
                        statusCode: statusConstants.ERROR,
                        payload: null,
                        message: "Not exist data",
                    });
                }
    
                return await Object.assign({
                    statusCode: statusConstants.SUCCESS,
                    payload: null,
                    message: "Success delete"
                });
            } catch(err) {
                return await Object.assign({
                    statusCode: statusConstants.ERROR,
                    payload: null,
                    message: "rental-service database: " + err,
                });
            }
        }
    
        public async completeRental(dto: RentalDto): Promise<any> {
            try {
                const result  = await this.rentalModel.updateOne({ rentalId: dto.rentalId }, { $set: { status: status.BEING }});
                
                if(!result) {
                    return await Object.assign({
                        statusCode: statusConstants.ERROR,
                        payload: null,
                        message: "Not exist data",
                    });
                }
    
                return await Object.assign({
                    statusCode: statusConstants.SUCCESS,
                    payload: null,
                    message: "Success update"
                });
            } catch(err) {
                return await Object.assign({
                    statusCode: statusConstants.ERROR,
                    payload: null,
                    message: "rental-service database: " + err,
                });
            }
        }
    }
    payment-serviceはgetRentalsメソッドのためにhttp://localhost:8000/payment-service/${el.rentalId}/payment-from-rental endpointを作成します.
  • ./src/app.controller.ts
  • ...
    
    @Controller('payment-service')
    export class AppController {
        ...
    
        @Get(':rentalId/payment-from-rental')
        public async getPaymentFromRental(@Param('rentalId') rentalId: string): Promise<any> {
            try {
                const result: any = await this.paymentService.getPaymentFromRental(rentalId);
    
                console.log(result);
    
                if(result.status === statusConstants.ERROR) {
                    return await Object.assign({
                        status: HttpStatus.INTERNAL_SERVER_ERROR,
                        payload: null,
                        message: "Error message: " + result.message
                    });
                }
    
                if(!result.payload) {
                    return await Object.assign({
                        status: HttpStatus.OK,
                        payload: null,
                        message: "Success get data"
                    });
                }
    
                return await Object.assign({
                    status: HttpStatus.OK,
                    payload: Builder(ResponsePayment).paymentName(result.payload.paymentName)
                                                     .payer(result.payload.payer)
                                                     .rentalId(result.payload.rentalId)
                                                     .paymentId(result.payload.paymentId)
                                                     .price(result.payload.price)
                                                     .createdAt(result.payload.createdAt)
                                                     .build(),
                    message: "Success get data"
                });
            } catch(err) {
                return await Object.assign({
                    status: HttpStatus.BAD_GATEWAY,
                    payload: null,
                    message: "Error message: " + err,
                });
            }
        }
    }
  • ./src/payment/payment.service.ts
  • import { Inject, Injectable } from '@nestjs/common';
    import { ClientProxy } from '@nestjs/microservices';
    import { InjectModel } from '@nestjs/mongoose';
    import { Builder } from 'builder-pattern';
    import { Model } from 'mongoose';
    import { statusConstants } from 'src/constants/status.constants';
    import { PaymentDto } from 'src/dto/payment.dto';
    import { Payment, PaymentDocument } from 'src/schema/payment.schema';
    import { v4 as uuid } from 'uuid';
    
    @Injectable()
    export class PaymentService {
        ...
    
        public async getPaymentFromRental(data: any) {
            try {
                const entity: any = await this.paymentModel.findOne({ rentalId: data });
    
                if(!entity) {
                    return await Object.assign({
                        status: statusConstants.SUCCESS,
                        payload: null,
                        message: "Not exist data"
                    });
                }
    
                return await Object.assign({
                    status: statusConstants.SUCCESS,
                    payload: Builder(PaymentDto).paymentId(entity.paymentId)
                                                .paymentName(entity.paymentName)
                                                .payer(entity.payer)
                                                .price(entity.price)
                                                .rentalId(entity.rentalId)
                                                .createdAt(entity.createdAt)
                                                .build(),
                    message: "Successful transaction"
                });
            } catch(err) {
                return await Object.assign({
                    status: statusConstants.ERROR,
                    payload: null,
                    message: err
                });
            }
        }
    }
    コードの作成が完了しました.payment-サービスのデータインポート状況をテストしましょう.

    試験は、userIdb 49 cad 9−1 d 76−41 b 2−abad−7 a 27 c 4394 ca、78 e 834 ff−f 270−4 a 9 e−9 b 30−1 a 44 daff 9469を基準として行った.
    1) bb49cad9-1d76-41b2-abad-7a271c4394ca

    このuserIdの場合、貸出ステータスはBEINGであり、支払データが存在することを示す.したがって、この場合、支払を支払済みと見なし、「大文字データ」履歴の支払完了に分類します.
    2) 78e834ff-f270-4a9e-9b30-1a44daff9469

    このuserIdの場合、借用ステータスはPENDINGであり、この場合、支払が行われていないとみなされ、「大管データ履歴」の「未決」に分類される.
    簡単なテストを行い、次の記事では、管理者の履歴をより詳細なUI作成と関連付けます.