Commit 89923fc3 authored by Mattias Lundmark's avatar Mattias Lundmark Committed by Benjamin Rokseth
Browse files

Payment receipt on email, wip

parent 57d3b2e0
......@@ -165,4 +165,36 @@ module.exports = (app) => {
response.sendStatus(500)
}
})
app.put('/api/v1/checkouts/email-receipt', jsonParser, async (request, response) => {
const transactionId = request.body.transactionId
const email = request.body.email
try {
if (!/^[^@ ]+@[^@ ]+$/i.test(email)) {
const errors = Object.assign({})
errors['email'] = 'invalidEmail'
response.status(400).send({ errors: errors })
return
}
const kohaRes = await fetch(`http://xkoha:8081/api/v1/payments/payment-receipt`, {
method: 'PUT',
headers: {
'Accept': 'application/json, application/xml, text/plain, text/html, *.*',
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
},
body: `nets_id=${encodeURIComponent(transactionId)}`
})
const kohaResJson = await kohaRes.json()
console.log(kohaResJson)
response.send({
})
} catch (error) {
console.log(error)
response.sendStatus(500)
}
})
}
......@@ -3,6 +3,7 @@ import * as types from '../constants/ActionTypes'
import { requireLoginBeforeAction } from './LoginActions'
import { fetchProfileLoans } from './ProfileActions'
import Errors from '../constants/Errors'
import { action, errorAction } from './GenericActions'
export function startExtendLoan (checkoutId) {
return requireLoginBeforeAction(extendLoan(checkoutId))
......@@ -212,3 +213,42 @@ export function processFinePayment (transactionId, responseCode) {
}
}
}
export const requestSendEmailReceipt = () => action(types.REQUEST_SEND_EMAIL_PAYMENT_RECEIPT)
export const sendPaymentReceiptError = (error) => errorAction(types.SEND_PAYMENT_RECEIPT_ERROR, error)
export const sendPaymentReceiptSuccess = () => action(types.SEND_PAYMENT_RECEIPT_SUCCESS)
export function sendReceiptForm (successAction) {
return (dispatch, getState) => {
const { sendReceipt: { values: { email, transactionId } } } = getState().form
dispatch(sendEmailReceipt(email, transactionId, successAction))
}
}
export function sendEmailReceipt (email, transactionId, successAction) {
const url = '/api/v1/checkouts/email-receipt'
return dispatch => {
dispatch(requestSendEmailReceipt())
return fetch(url, {
method: 'put',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email: email, transactionId: transactionId })
})
.then(response => {
if (response.status === 200) {
dispatch(sendPaymentReceiptSuccess())
if (successAction) {
dispatch(successAction)
}
} else {
throw Error(Errors.profile.SEND_PAYMENT_RECEIPT_ERROR)
}
})
.catch(error => dispatch(sendPaymentReceiptError(error)))
}
}
......@@ -56,6 +56,9 @@ export const REQUEST_START_PROCESS_PAYMENT = 'REQUEST_START_PROCESS_PAYMENT'
export const PAYMENT_SUCCESS = 'PAYMENT_SUCCESS'
export const PROCESS_PAYMENT_CANCELLED = 'PROCESS_PAYMENT_CANCELLED'
export const PROCESS_PAYMENT_FAILURE = 'PROCESS_PAYMENT_FAILURE'
export const REQUEST_SEND_EMAIL_PAYMENT_RECEIPT = 'REQUEST_SEND_EMAIL_PAYMENT_RECEIPT'
export const SEND_PAYMENT_RECEIPT_ERROR = 'SEND_PAYMENT_RECEIPT_ERROR'
export const SEND_PAYMENT_RECEIPT_SUCCESS = 'SEND_PAYMENT_RECEIPT_SUCCESS'
export const REQUEST_CANCEL_RESERVATION = 'REQUEST_CANCEL_RESERVATION'
export const CANCEL_RESERVATION_SUCCESS = 'CANCEL_RESERVATION_SUCCESS'
......
......@@ -8,6 +8,7 @@ import {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-int
import QueryString from 'query-string'
import {formatDate} from '../utils/dateFormatter'
import Constants from '../constants/Constants'
import EmailReceiptForm from './forms/EmailReceiptForm'
import * as LoanActions from '../actions/LoanActions'
......@@ -185,6 +186,9 @@ class PaymentResponse extends React.Component {
</section>
}
<div>
{/*
<EmailReceiptForm transactionId={this.props.transactionId} sendPaymentReceiptSuccess={this.props.sendPaymentReceiptSuccess} />
*/}
<Link to="/profile/loans" >
<FormattedMessage {...messages.paymentReturnToMypage} />
</Link >
......@@ -284,6 +288,11 @@ export const messages = defineMessages({
id: 'UserLoans.patronHasOverdue',
description: 'Message when patron with overdues is trying to renew material.',
defaultMessage: 'Overdue material - cannot renew.'
},
sendPaymentReceiptSuccess: {
id: 'UserLoans.sendPaymentReceiptSuccess',
description: 'Your receipt was sent.',
defaultMessage: 'Your receipt was sent.'
}
})
......@@ -298,6 +307,7 @@ PaymentResponse.propTypes = {
successfulExtends: PropTypes.array.isRequired,
location: PropTypes.object.isRequired,
intl: intlShape.isRequired,
sendPaymentReceiptSuccess: PropTypes.bool.isRequired,
isRequestingLoansAndReservations: PropTypes.bool.isRequired
}
......@@ -309,6 +319,7 @@ function mapStateToProps (state) {
isPaymentCancelled: state.loan.isPaymentCancelled,
isPaymentFailed: state.loan.isPaymentFailed,
successfulExtends: state.loan.successfulExtends,
sendPaymentReceiptSuccess: state.loan.sendPaymentReceiptSuccess,
isRequestingLoansAndReservations: state.profile.isRequestingLoansAndReservations
}
}
......
import PropTypes from 'prop-types'
import React from 'react'
import { reduxForm, reset } from 'redux-form'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { injectIntl, intlShape, defineMessages, FormattedMessage } from 'react-intl'
import FormInputField from '../../components/FormInputField'
import * as LoanActions from '../../actions/LoanActions'
const formName = 'sendReceipt'
class EmailReceiptForm extends React.Component {
constructor (props) {
super(props)
this.handleSendReceipt = this.handleSendReceipt.bind(this)
this.getValidator = this.getValidator.bind(this)
}
handleSendReceipt () {
this.props.loanActions.sendReceiptForm(reset('requestReceipt'))
}
getValidator (field) {
if (field && field.meta.touched && field.meta.error) {
return <div style={{ color: 'red', fontSize: '12px' }}>{this.props.intl.formatMessage(field.meta.error)}</div>
}
}
render () {
const {
submitting,
handleSubmit
} = this.props
return (
<form onChange={this.handleChange} onSubmit={handleSubmit(this.handleSendReceipt)}>
<section className="email-receipt">
<div className="email-receipt-fields">
<FormInputField name="email"
message={messages.email}
headerType=""
type="text"
formName={formName}
getValidator={this.getValidator} />
{!this.props.sendPaymentReceiptSuccess &&
<button className="blue-btn" type="submit" disabled={submitting} data-automation-id="emailReceiptForm_button">
<FormattedMessage {...messages.sendPaymentReceipt} /><br />
</button>
}
{this.props.sendPaymentReceiptSuccess ? <div data-automation-id="emailReceiptForm_success" style={{ color: 'green' }}>
<FormattedMessage {...messages.sendPaymentReceiptSuccess} />
</div> : null}
{this.props.sendPaymentReceiptError ? <div data-automation-id="emailReceiptForm_success" style={{ color: 'red' }}>
<FormattedMessage {...messages.sendPaymentReceiptError} />
</div> : null}
</div>
</section>
</form>
)
}
}
export const messages = defineMessages({
email: {
id: 'UserLoans.email',
description: 'The label for the email',
defaultMessage: 'Email:'
},
sendPaymentReceipt: {
id: 'UserLoans.sendPaymentReceipt',
description: 'Send payment receipt',
defaultMessage: 'Send receipt on email'
},
sendPaymentReceiptSuccess: {
id: 'UserLoans.sendPaymentReceiptSuccess',
description: 'Receipt was sent ok',
defaultMessage: 'Your receipt was sent.'
},
sendPaymentReceiptError: {
id: 'UserLoans.sendPaymentReceiptError',
description: 'Receipt was not sent ok',
defaultMessage: 'Your receipt could not be sent.'
},
emailRequired: {
id: 'UserLoans.sendPaymentReceiptEmailRequired',
description: 'Email is required',
defaultMessage: 'Email is required'
}
})
EmailReceiptForm.propTypes = {
dispatch: PropTypes.func.isRequired,
loanActions: PropTypes.object.isRequired,
sendPaymentReceiptSuccess: PropTypes.bool.isRequired,
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
intl: intlShape.isRequired,
sendPaymentReceiptError: PropTypes.object,
transactionId: PropTypes.string.isRequired
}
function mapStateToProps (state) {
return {
sendPaymentReceiptError: state.loan.sendPaymentReceiptError,
sendPaymentReceiptSuccess: state.loan.sendPaymentReceiptSuccess,
initialValues: state.profile.personalInformation,
fields: state.form.sendReceipt ? state.form.sendReceipt : {}
}
}
function mapDispatchToProps (dispatch) {
return {
dispatch: dispatch,
loanActions: bindActionCreators(LoanActions, dispatch)
}
}
const validate = (values, props) => {
const errors = {}
if (!values.email) {
errors.email = messages.sendPaymentReceiptEmailRequired
}
console.log('validating', errors)
return errors
}
const intlEmailReceiptForm = injectIntl(EmailReceiptForm)
export { intlEmailReceiptForm as EmailReceiptForm }
export default connect(
mapStateToProps,
mapDispatchToProps
)(reduxForm({ form: formName, validate })(intlEmailReceiptForm))
......@@ -390,6 +390,10 @@ export default {
'UserLoans.paymentFailedText': 'Gå tilbake til {myPageLink} for å prøve igjen eller kontakt ditt lokale bibliotek. ',
'UserLoans.paymentReturnToMypage': 'Tilbake til Min Side',
'UserLoans.paymentLoansUpdatedHeader': 'Se over disse lånene',
'UserLoans.sendPaymentReceipt': 'Send kvittering på mail',
'UserLoans.sendPaymentReceiptSuccess': 'Din kvittering ble sendt.',
'UserLoans.sendPaymentReceiptError': 'Din kvittering kunne ikke sendes.',
'UserLoans.email': 'Epost:',
'UserSettings.alerts': 'Varslinger',
'UserSettings.byEmail': 'På epost',
'UserSettings.bySms': 'På SMS',
......
......@@ -6,7 +6,9 @@ import {
REQUEST_START_PROCESS_PAYMENT,
PAYMENT_SUCCESS,
PROCESS_PAYMENT_CANCELLED,
PROCESS_PAYMENT_FAILURE
PROCESS_PAYMENT_FAILURE,
SEND_PAYMENT_RECEIPT_ERROR,
SEND_PAYMENT_RECEIPT_SUCCESS
} from '../constants/ActionTypes'
const initialState = {
......@@ -18,7 +20,10 @@ const initialState = {
isPaymentSaved: false,
isPaymentCancelled: false,
isPaymentFailed: false,
successfulExtends: []
sendPaymentReceiptSuccess: false,
sendPaymentReceiptError: null,
successfulExtends: [],
transactionId: null
}
export default function loan (state = initialState, action) {
......@@ -34,13 +39,17 @@ export default function loan (state = initialState, action) {
case REQUEST_START_PROCESS_PAYMENT:
return { ...state, isSavingPayment: true, isPaymentSaved: false }
case PAYMENT_SUCCESS:
return { ...state, isSavingPayment: false, isPaymentSaved: true, isPaymentCancelled: false, successfulExtends: action.payload.successfulExtends }
return { ...state, isSavingPayment: false, isPaymentSaved: true, isPaymentCancelled: false, successfulExtends: action.payload.successfulExtends, transactionId: action.payload.transactionId }
case PROCESS_PAYMENT_CANCELLED:
return { ...state, isSavingPayment: false, isPaymentSaved: false, isPaymentCancelled: true }
case PROCESS_PAYMENT_FAILURE:
return Object.assign({}, state, {
isSavingPayment: false, isPaymentSaved: false, isPaymentCancelled: false, isPaymentFailed: true
})
case SEND_PAYMENT_RECEIPT_SUCCESS:
return { ...state, sendPaymentReceiptSuccess: true, sendPaymentReceiptError: null }
case SEND_PAYMENT_RECEIPT_ERROR:
return { ...state, sendPaymentReceiptError: action.payload }
default:
return state
}
......
......@@ -2996,6 +2996,35 @@ input[type="checkbox"]:checked + label i.checkbox-unchecked {
max-width: 4em;
}
.email-receipt-fields {
@include container;
@include span(12);
@include clearfix;
margin-top: $rhythm4;
margin-bottom: $rhythm4;
}
.email-receipt-fields .form-item {
@include container;
@include span(12);
@include clearfix;
}
.email-receipt-fields label {
@include container;
@include span(12);
margin-top: $rhythm2;
}
.email-receipt-fields input {
@include container;
@include span(12);
font-size: $rhythm3;
margin-top: $rhythm2;
max-width: 24em;
margin-bottom: $rhythm2;
}
@include breakpoint($small) {
.user-settings footer .disclaimer {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment