Merge pull request #444 from sharetribe/tx-state-to-last-transition

Use transaction lastTransition instead of state
This commit is contained in:
Kimmo Puputti 2017-10-02 16:13:45 +03:00 committed by GitHub
commit 3757177d17
21 changed files with 3395 additions and 254 deletions

View file

@ -22,7 +22,6 @@ const exampleTransaction = params => {
createdAt: created,
lastTransitionedAt: created,
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
state: propTypes.TX_STATE_PREAUTHORIZED,
// payinTotal, payoutTotal, and lineItems required in params
...params,
@ -160,12 +159,69 @@ export const ProviderSaleSingleNight = {
},
};
export const ProviderSalePreauthorized = {
component: BookingBreakdown,
props: {
userRole: 'provider',
transaction: exampleTransaction({
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
payinTotal: new Money(4500, 'USD'),
payoutTotal: new Money(2500, 'USD'),
lineItems: [
{
code: 'line-item/night',
quantity: new Decimal(1),
unitPrice: new Money(4500, 'USD'),
lineTotal: new Money(4500, 'USD'),
},
{
code: 'line-item/provider-commission',
unitPrice: new Money(-2000, 'USD'),
lineTotal: new Money(-2000, 'USD'),
},
],
}),
booking: exampleBooking({
start: new Date(Date.UTC(2017, 3, 14)),
end: new Date(Date.UTC(2017, 3, 15)),
}),
},
};
export const ProviderSaleAccepted = {
component: BookingBreakdown,
props: {
userRole: 'provider',
transaction: exampleTransaction({
lastTransition: propTypes.TX_TRANSITION_ACCEPT,
payinTotal: new Money(4500, 'USD'),
payoutTotal: new Money(2500, 'USD'),
lineItems: [
{
code: 'line-item/night',
quantity: new Decimal(1),
unitPrice: new Money(4500, 'USD'),
lineTotal: new Money(4500, 'USD'),
},
{
code: 'line-item/provider-commission',
unitPrice: new Money(-2000, 'USD'),
lineTotal: new Money(-2000, 'USD'),
},
],
}),
booking: exampleBooking({
start: new Date(Date.UTC(2017, 3, 14)),
end: new Date(Date.UTC(2017, 3, 15)),
}),
},
};
export const ProviderSaleRejected = {
component: BookingBreakdown,
props: {
userRole: 'provider',
transaction: exampleTransaction({
state: propTypes.TX_STATE_REJECTED,
lastTransition: propTypes.TX_TRANSITION_REJECT,
payinTotal: new Money(4500, 'USD'),
payoutTotal: new Money(2500, 'USD'),
@ -190,12 +246,40 @@ export const ProviderSaleRejected = {
},
};
export const ProviderSaleAutoRejected = {
component: BookingBreakdown,
props: {
userRole: 'provider',
transaction: exampleTransaction({
lastTransition: propTypes.TX_TRANSITION_AUTO_REJECT,
payinTotal: new Money(4500, 'USD'),
payoutTotal: new Money(2500, 'USD'),
lineItems: [
{
code: 'line-item/night',
quantity: new Decimal(1),
unitPrice: new Money(4500, 'USD'),
lineTotal: new Money(4500, 'USD'),
},
{
code: 'line-item/provider-commission',
unitPrice: new Money(-2000, 'USD'),
lineTotal: new Money(-2000, 'USD'),
},
],
}),
booking: exampleBooking({
start: new Date(Date.UTC(2017, 3, 14)),
end: new Date(Date.UTC(2017, 3, 15)),
}),
},
};
export const ProviderSaleDelivered = {
component: BookingBreakdown,
props: {
userRole: 'provider',
transaction: exampleTransaction({
state: propTypes.TX_STATE_DELIVERED,
lastTransition: propTypes.TX_TRANSITION_MARK_DELIVERED,
payinTotal: new Money(4500, 'USD'),
payoutTotal: new Money(2500, 'USD'),

View file

@ -111,9 +111,9 @@ export const BookingBreakdownComponent = props => {
}
let providerTotalMessageId = 'BookingBreakdown.providerTotalDefault';
if (transaction.attributes.state === propTypes.TX_STATE_DELIVERED) {
if (propTypes.txIsDelivered(transaction)) {
providerTotalMessageId = 'BookingBreakdown.providerTotalDelivered';
} else if (transaction.attributes.state === propTypes.TX_STATE_REJECTED) {
} else if (propTypes.txIsRejectedOrAutorejected(transaction)) {
providerTotalMessageId = 'BookingBreakdown.providerTotalRejected';
}

View file

@ -1,6 +1,6 @@
import React from 'react';
import Decimal from 'decimal.js';
import { fakeIntl } from '../../util/test-data';
import { fakeIntl, createBooking } from '../../util/test-data';
import { renderDeep } from '../../util/test-helpers';
import { types } from '../../util/sdkLoader';
import * as propTypes from '../../util/propTypes';
@ -8,14 +8,6 @@ import { BookingBreakdownComponent } from './BookingBreakdown';
const { UUID, Money } = types;
const exampleBooking = attributes => {
return {
id: new UUID('example-booking'),
type: 'booking',
attributes,
};
};
const exampleTransaction = params => {
const created = new Date(Date.UTC(2017, 1, 1));
return {
@ -25,7 +17,6 @@ const exampleTransaction = params => {
createdAt: created,
lastTransitionedAt: created,
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
state: propTypes.TX_STATE_PREAUTHORIZED,
// payinTotal, payoutTotal, and lineItems required in params
...params,
@ -50,7 +41,7 @@ describe('BookingBreakdown', () => {
},
],
})}
booking={exampleBooking({
booking={createBooking('example-booking', {
start: new Date(Date.UTC(2017, 3, 14)),
end: new Date(Date.UTC(2017, 3, 16)),
})}
@ -76,7 +67,7 @@ describe('BookingBreakdown', () => {
},
],
})}
booking={exampleBooking({
booking={createBooking('example-booking', {
start: new Date(Date.UTC(2017, 3, 14)),
end: new Date(Date.UTC(2017, 3, 16)),
})}
@ -107,7 +98,7 @@ describe('BookingBreakdown', () => {
},
],
})}
booking={exampleBooking({
booking={createBooking('example-booking', {
start: new Date(Date.UTC(2017, 3, 14)),
end: new Date(Date.UTC(2017, 3, 16)),
})}

View file

@ -21,92 +21,89 @@ const breakdown = transaction => {
: null;
};
const orderTitle = (orderState, listingLink, customerName, lastTransition) => {
const rejectedTranslationId = lastTransition === propTypes.TX_TRANSITION_AUTO_REJECT
? 'OrderDetailsPanel.orderAutoRejectedTitle'
: 'OrderDetailsPanel.orderRejectedTitle';
switch (orderState) {
case propTypes.TX_STATE_PREAUTHORIZED:
return (
<span>
<span className={css.mainTitle}>
<FormattedMessage
id="OrderDetailsPanel.orderPreauthorizedTitle"
values={{ customerName }}
/>
</span>
const orderTitle = (transaction, listingLink, customerName) => {
if (propTypes.txIsPreauthorized(transaction)) {
return (
<span>
<span className={css.mainTitle}>
<FormattedMessage
id="OrderDetailsPanel.orderPreauthorizedSubtitle"
values={{ listingLink }}
id="OrderDetailsPanel.orderPreauthorizedTitle"
values={{ customerName }}
/>
</span>
);
case propTypes.TX_STATE_ACCEPTED:
return (
<span>
<span className={css.mainTitle}>
<FormattedMessage id="OrderDetailsPanel.orderAcceptedTitle" values={{ customerName }} />
</span>
<FormattedMessage id="OrderDetailsPanel.orderAcceptedSubtitle" values={{ listingLink }} />
<FormattedMessage
id="OrderDetailsPanel.orderPreauthorizedSubtitle"
values={{ listingLink }}
/>
</span>
);
} else if (propTypes.txIsAccepted(transaction)) {
return (
<span>
<span className={css.mainTitle}>
<FormattedMessage id="OrderDetailsPanel.orderAcceptedTitle" values={{ customerName }} />
</span>
);
case propTypes.TX_STATE_REJECTED:
return <FormattedMessage id={rejectedTranslationId} values={{ listingLink }} />;
case propTypes.TX_STATE_DELIVERED:
return (
<FormattedMessage id="OrderDetailsPanel.orderDeliveredTitle" values={{ listingLink }} />
);
default:
return null;
<FormattedMessage id="OrderDetailsPanel.orderAcceptedSubtitle" values={{ listingLink }} />
</span>
);
} else if (propTypes.txIsRejected(transaction)) {
return <FormattedMessage id="OrderDetailsPanel.orderRejectedTitle" values={{ listingLink }} />;
} else if (propTypes.txIsAutorejected(transaction)) {
return (
<FormattedMessage id="OrderDetailsPanel.orderAutoRejectedTitle" values={{ listingLink }} />
);
} else if (propTypes.txIsDelivered(transaction)) {
return <FormattedMessage id="OrderDetailsPanel.orderDeliveredTitle" values={{ listingLink }} />;
} else {
return null;
}
};
const orderMessage = (
orderState,
listingTitle,
providerName,
lastTransitionedAt,
lastTransition
) => {
const orderMessage = (transaction, listingTitle, providerName) => {
const transitionDate = (
<span className={css.transitionDate}>
<FormattedDate value={lastTransitionedAt} year="numeric" month="short" day="numeric" />
<FormattedDate
value={transaction.attributes.lastTransitionedAt}
year="numeric"
month="short"
day="numeric"
/>
</span>
);
const rejectedTranslationId = lastTransition === propTypes.TX_TRANSITION_AUTO_REJECT
? 'OrderDetailsPanel.orderAutoRejectedStatus'
: 'OrderDetailsPanel.orderRejectedStatus';
switch (orderState) {
case propTypes.TX_STATE_PREAUTHORIZED:
return (
<FormattedMessage
id="OrderDetailsPanel.orderPreauthorizedStatus"
values={{ providerName }}
/>
);
case propTypes.TX_STATE_ACCEPTED:
return (
<FormattedMessage
id="OrderDetailsPanel.orderAcceptedStatus"
values={{ providerName, transitionDate }}
/>
);
case propTypes.TX_STATE_REJECTED:
return (
<FormattedMessage id={rejectedTranslationId} values={{ providerName, transitionDate }} />
);
case propTypes.TX_STATE_DELIVERED:
return (
<FormattedMessage
id="OrderDetailsPanel.orderDeliveredStatus"
values={{ providerName, transitionDate }}
/>
);
default:
return null;
if (propTypes.txIsPreauthorized(transaction)) {
return (
<FormattedMessage id="OrderDetailsPanel.orderPreauthorizedStatus" values={{ providerName }} />
);
} else if (propTypes.txIsAccepted(transaction)) {
return (
<FormattedMessage
id="OrderDetailsPanel.orderAcceptedStatus"
values={{ providerName, transitionDate }}
/>
);
} else if (propTypes.txIsRejected(transaction)) {
return (
<FormattedMessage
id="OrderDetailsPanel.orderRejectedStatus"
values={{ providerName, transitionDate }}
/>
);
} else if (propTypes.txIsAutorejected(transaction)) {
return (
<FormattedMessage
id="OrderDetailsPanel.orderAutoRejectedStatus"
values={{ providerName, transitionDate }}
/>
);
} else if (propTypes.txIsDelivered(transaction)) {
return (
<FormattedMessage
id="OrderDetailsPanel.orderDeliveredStatus"
values={{ providerName, transitionDate }}
/>
);
} else {
return null;
}
};
@ -140,9 +137,6 @@ export const OrderDetailsPanelComponent = props => {
const authorDisplayName = userDisplayName(currentProvider, bannedUserDisplayName);
const customerDisplayName = userDisplayName(currentCustomer, bannedUserDisplayName);
const transactionState = currentTransaction.attributes.state;
const lastTransitionedAt = currentTransaction.attributes.lastTransitionedAt;
const lastTransition = currentTransaction.attributes.lastTransitione;
let listingLink = null;
@ -163,21 +157,10 @@ export const OrderDetailsPanelComponent = props => {
: currentListing.attributes.title;
const bookingInfo = breakdown(currentTransaction);
const orderHeading = orderTitle(
transactionState,
listingLink,
customerDisplayName,
lastTransition
);
const orderHeading = orderTitle(currentTransaction, listingLink, customerDisplayName);
const message = listingDeleted
? orderMessageDeletedListing
: orderMessage(
transactionState,
listingLink,
authorDisplayName,
lastTransitionedAt,
lastTransition
);
: orderMessage(currentTransaction, listingLink, authorDisplayName);
const firstImage = currentListing.images && currentListing.images.length > 0
? currentListing.images[0]
@ -255,7 +238,6 @@ export const OrderDetailsPanelComponent = props => {
OrderDetailsPanelComponent.defaultProps = {
rootClassName: null,
className: null,
lastTransition: null,
};
const { string } = PropTypes;

View file

@ -4,32 +4,89 @@ import { types } from '../../util/sdkLoader';
import { createBooking, createListing, createUser, createTransaction } from '../../util/test-data';
import { renderShallow } from '../../util/test-helpers';
import { fakeIntl } from '../../util/test-data';
import * as propTypes from '../../util/propTypes';
import { BookingBreakdown } from '../../components';
import { OrderDetailsPanelComponent } from './OrderDetailsPanel.js';
const { Money } = types;
const baseTxAttrs = {
total: new Money(16500, 'USD'),
booking: createBooking('booking1', {
start: new Date(Date.UTC(2017, 5, 10)),
end: new Date(Date.UTC(2017, 5, 13)),
}),
listing: createListing('listing1'),
provider: createUser('provider'),
customer: createUser('customer'),
};
const txPreauthorized = createTransaction({
id: 'order-preauthorized',
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
...baseTxAttrs,
});
const txAccepted = createTransaction({
id: 'order-accepted',
lastTransition: propTypes.TX_TRANSITION_ACCEPT,
...baseTxAttrs,
});
const txRejected = createTransaction({
id: 'order-rejected',
lastTransition: propTypes.TX_TRANSITION_REJECT,
...baseTxAttrs,
});
const txAutoRejected = createTransaction({
id: 'order-autorejected',
lastTransition: propTypes.TX_TRANSITION_AUTO_REJECT,
...baseTxAttrs,
});
const txDelivered = createTransaction({
id: 'order-delivered',
lastTransition: propTypes.TX_TRANSITION_MARK_DELIVERED,
...baseTxAttrs,
});
describe('OrderDetailsPanel', () => {
it('matches snapshot', () => {
const { Money } = types;
const tx = createTransaction({
id: 'order-tx',
state: 'state/preauthorized',
total: new Money(16500, 'USD'),
booking: createBooking('booking1', {
start: new Date(Date.UTC(2017, 5, 10)),
end: new Date(Date.UTC(2017, 5, 13)),
}),
listing: createListing('listing1'),
provider: createUser('provider'),
customer: createUser('customer'),
});
const tree = renderShallow(<OrderDetailsPanelComponent transaction={tx} intl={fakeIntl} />);
it('preauthorized matches snapshot', () => {
const tree = renderShallow(
<OrderDetailsPanelComponent transaction={txPreauthorized} intl={fakeIntl} />
);
expect(tree).toMatchSnapshot();
});
it('accepted matches snapshot', () => {
const tree = renderShallow(
<OrderDetailsPanelComponent transaction={txAccepted} intl={fakeIntl} />
);
expect(tree).toMatchSnapshot();
});
it('rejected matches snapshot', () => {
const tree = renderShallow(
<OrderDetailsPanelComponent transaction={txRejected} intl={fakeIntl} />
);
expect(tree).toMatchSnapshot();
});
it('autorejected matches snapshot', () => {
const tree = renderShallow(
<OrderDetailsPanelComponent transaction={txAutoRejected} intl={fakeIntl} />
);
expect(tree).toMatchSnapshot();
});
it('delivered matches snapshot', () => {
const tree = renderShallow(
<OrderDetailsPanelComponent transaction={txDelivered} intl={fakeIntl} />
);
expect(tree).toMatchSnapshot();
});
it('renders correct total price', () => {
const { Money } = types;
const tx = createTransaction({
id: 'order-tx',
state: 'state/preauthorized',
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
total: new Money(16500, 'USD'),
booking: createBooking('booking1', {
start: new Date(Date.UTC(2017, 5, 10)),

View file

@ -28,46 +28,52 @@ const breakdown = transaction => {
: null;
};
const saleTitle = (saleState, listingLink, customerName) => {
switch (saleState) {
case propTypes.TX_STATE_PREAUTHORIZED:
return (
<FormattedMessage
id="SaleDetailsPanel.listingRequestedTitle"
values={{ customerName, listingLink }}
/>
);
case propTypes.TX_STATE_ACCEPTED:
return (
<FormattedMessage
id="SaleDetailsPanel.listingAcceptedTitle"
values={{ customerName, listingLink }}
/>
);
case propTypes.TX_STATE_REJECTED:
return (
<FormattedMessage
id="SaleDetailsPanel.listingRejectedTitle"
values={{ customerName, listingLink }}
/>
);
case propTypes.TX_STATE_DELIVERED:
return (
<FormattedMessage
id="SaleDetailsPanel.listingDeliveredTitle"
values={{ customerName, listingLink }}
/>
);
default:
return null;
const saleTitle = (transaction, listingLink, customerName) => {
if (propTypes.txIsPreauthorized(transaction)) {
return (
<FormattedMessage
id="SaleDetailsPanel.listingRequestedTitle"
values={{ customerName, listingLink }}
/>
);
} else if (propTypes.txIsAccepted(transaction)) {
return (
<FormattedMessage
id="SaleDetailsPanel.listingAcceptedTitle"
values={{ customerName, listingLink }}
/>
);
} else if (propTypes.txIsRejected(transaction)) {
return (
<FormattedMessage
id="SaleDetailsPanel.listingRejectedTitle"
values={{ customerName, listingLink }}
/>
);
} else if (propTypes.txIsAutorejected(transaction)) {
return (
<FormattedMessage
id="SaleDetailsPanel.listingRejectedTitle"
values={{ customerName, listingLink }}
/>
);
} else if (propTypes.txIsDelivered(transaction)) {
return (
<FormattedMessage
id="SaleDetailsPanel.listingDeliveredTitle"
values={{ customerName, listingLink }}
/>
);
} else {
return null;
}
};
const saleMessage = (saleState, customerName, lastTransitionedAt, lastTransition) => {
const saleMessage = (transaction, customerName) => {
const formattedDate = (
<span className={css.nowrap}>
<FormattedDate
value={lastTransitionedAt}
value={transaction.attributes.lastTransitionedAt}
year="numeric"
month="short"
day="numeric"
@ -75,27 +81,22 @@ const saleMessage = (saleState, customerName, lastTransitionedAt, lastTransition
/>
</span>
);
const rejectedStatusTranslationId = lastTransition === propTypes.TX_TRANSITION_AUTO_REJECT
? 'SaleDetailsPanel.saleAutoRejectedStatus'
: 'SaleDetailsPanel.saleRejectedStatus';
switch (saleState) {
case propTypes.TX_STATE_PREAUTHORIZED:
return (
<FormattedMessage id="SaleDetailsPanel.saleRequestedStatus" values={{ customerName }} />
);
case propTypes.TX_STATE_ACCEPTED: {
return (
<FormattedMessage id="SaleDetailsPanel.saleAcceptedStatus" values={{ formattedDate }} />
);
}
case propTypes.TX_STATE_REJECTED:
return <FormattedMessage id={rejectedStatusTranslationId} values={{ formattedDate }} />;
case propTypes.TX_STATE_DELIVERED:
return (
<FormattedMessage id="SaleDetailsPanel.saleDeliveredStatus" values={{ formattedDate }} />
);
default:
return null;
if (propTypes.txIsPreauthorized(transaction)) {
return <FormattedMessage id="SaleDetailsPanel.saleRequestedStatus" values={{ customerName }} />;
} else if (propTypes.txIsAccepted(transaction)) {
return <FormattedMessage id="SaleDetailsPanel.saleAcceptedStatus" values={{ formattedDate }} />;
} else if (propTypes.txIsRejected(transaction)) {
return <FormattedMessage id="SaleDetailsPanel.saleRejectedStatus" values={{ formattedDate }} />;
} else if (propTypes.txIsAutorejected(transaction)) {
return (
<FormattedMessage id="SaleDetailsPanel.saleAutoRejectedStatus" values={{ formattedDate }} />
);
} else if (propTypes.txIsDelivered(transaction)) {
return (
<FormattedMessage id="SaleDetailsPanel.saleDeliveredStatus" values={{ formattedDate }} />
);
} else {
return null;
}
};
@ -123,9 +124,6 @@ export const SaleDetailsPanelComponent = props => {
});
const customerDisplayName = userDisplayName(currentCustomer, bannedUserDisplayName);
const transactionState = currentTransaction.attributes.state;
const lastTransitionedAt = currentTransaction.attributes.lastTransitionedAt;
const lastTransition = currentTransaction.attributes.lastTransition;
let listingLink = null;
@ -141,21 +139,19 @@ export const SaleDetailsPanelComponent = props => {
const bookingInfo = breakdown(currentTransaction);
const title = saleTitle(transactionState, listingLink, customerDisplayName, lastTransition);
const title = saleTitle(currentTransaction, listingLink, customerDisplayName);
const message = isCustomerBanned
? intl.formatMessage({
id: 'SaleDetailsPanel.customerBannedStatus',
})
: saleMessage(transactionState, customerDisplayName, lastTransitionedAt, lastTransition);
: saleMessage(currentTransaction, customerDisplayName);
const listingTitle = currentListing.attributes.title;
const firstImage = currentListing.images && currentListing.images.length > 0
? currentListing.images[0]
: null;
const isPreauthorizedState = currentTransaction.attributes.state ===
propTypes.TX_STATE_PREAUTHORIZED;
const canShowButtons = isPreauthorizedState && !isCustomerBanned;
const canShowButtons = propTypes.txIsPreauthorized(currentTransaction) && !isCustomerBanned;
const buttonsDisabled = acceptInProgress || rejectInProgress;
const acceptErrorMessage = acceptSaleError
@ -260,7 +256,6 @@ export const SaleDetailsPanelComponent = props => {
SaleDetailsPanelComponent.defaultProps = {
rootClassName: null,
className: null,
lastTransition: null,
acceptSaleError: null,
rejectSaleError: null,
};

View file

@ -4,29 +4,107 @@ import { types } from '../../util/sdkLoader';
import { createTransaction, createBooking, createListing, createUser } from '../../util/test-data';
import { renderShallow } from '../../util/test-helpers';
import { fakeIntl } from '../../util/test-data';
import * as propTypes from '../../util/propTypes';
import { BookingBreakdown } from '../../components';
import { SaleDetailsPanelComponent } from './SaleDetailsPanel.js';
const noop = () => null;
const { Money } = types;
const baseTxAttrs = {
total: new Money(16500, 'USD'),
commission: new Money(1000, 'USD'),
booking: createBooking('booking1', {
start: new Date(Date.UTC(2017, 5, 10)),
end: new Date(Date.UTC(2017, 5, 13)),
}),
listing: createListing('listing1'),
customer: createUser('customer1'),
lastTransitionedAt: new Date(Date.UTC(2017, 5, 10)),
};
const txPreauthorized = createTransaction({
id: 'sale-preauthorized',
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
...baseTxAttrs,
});
const txAccepted = createTransaction({
id: 'sale-accepted',
lastTransition: propTypes.TX_TRANSITION_ACCEPT,
...baseTxAttrs,
});
const txRejected = createTransaction({
id: 'sale-rejected',
lastTransition: propTypes.TX_TRANSITION_REJECT,
...baseTxAttrs,
});
const txAutoRejected = createTransaction({
id: 'sale-autorejected',
lastTransition: propTypes.TX_TRANSITION_AUTO_REJECT,
...baseTxAttrs,
});
const txDelivered = createTransaction({
id: 'sale-delivered',
lastTransition: propTypes.TX_TRANSITION_MARK_DELIVERED,
...baseTxAttrs,
});
describe('SaleDetailsPanel', () => {
it('matches snapshot', () => {
const { Money } = types;
const transaction = createTransaction({
id: 'sale-tx',
state: 'state/preauthorized',
total: new Money(16500, 'USD'),
commission: new Money(1000, 'USD'),
booking: createBooking('booking1', {
start: new Date(Date.UTC(2017, 5, 10)),
end: new Date(Date.UTC(2017, 5, 13)),
}),
listing: createListing('listing1'),
customer: createUser('customer1'),
lastTransitionedAt: new Date(Date.UTC(2017, 5, 10)),
});
it('preauthorized matches snapshot', () => {
const props = {
transaction,
transaction: txPreauthorized,
onAcceptSale: noop,
onRejectSale: noop,
acceptInProgress: false,
rejectInProgress: false,
intl: fakeIntl,
};
const tree = renderShallow(<SaleDetailsPanelComponent {...props} />);
expect(tree).toMatchSnapshot();
});
it('accepted matches snapshot', () => {
const props = {
transaction: txAccepted,
onAcceptSale: noop,
onRejectSale: noop,
acceptInProgress: false,
rejectInProgress: false,
intl: fakeIntl,
};
const tree = renderShallow(<SaleDetailsPanelComponent {...props} />);
expect(tree).toMatchSnapshot();
});
it('rejected matches snapshot', () => {
const props = {
transaction: txRejected,
onAcceptSale: noop,
onRejectSale: noop,
acceptInProgress: false,
rejectInProgress: false,
intl: fakeIntl,
};
const tree = renderShallow(<SaleDetailsPanelComponent {...props} />);
expect(tree).toMatchSnapshot();
});
it('autorejected matches snapshot', () => {
const props = {
transaction: txAutoRejected,
onAcceptSale: noop,
onRejectSale: noop,
acceptInProgress: false,
rejectInProgress: false,
intl: fakeIntl,
};
const tree = renderShallow(<SaleDetailsPanelComponent {...props} />);
expect(tree).toMatchSnapshot();
});
it('delivered matches snapshot', () => {
const props = {
transaction: txDelivered,
onAcceptSale: noop,
onRejectSale: noop,
acceptInProgress: false,
@ -37,10 +115,9 @@ describe('SaleDetailsPanel', () => {
expect(tree).toMatchSnapshot();
});
it('renders correct total price', () => {
const { Money } = types;
const transaction = createTransaction({
id: 'sale-tx',
state: 'state/preauthorized',
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
total: new Money(16500, 'USD'),
commission: new Money(1000, 'USD'),
booking: createBooking('booking1', {

View file

@ -40,7 +40,6 @@ const estimatedNightlyTransaction = (bookingStart, bookingEnd, unitPrice) => {
createdAt: now,
lastTransitionedAt: now,
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
state: propTypes.TX_STATE_PREAUTHORIZED,
payinTotal: totalPrice,
payoutTotal: totalPrice,
lineItems: [

View file

@ -50,7 +50,6 @@ describe('BookingDatesForm', () => {
expect(booking.attributes.start).toEqual(startDate);
expect(booking.attributes.end).toEqual(endDate);
expect(transaction.attributes.lastTransition).toEqual(propTypes.TX_TRANSITION_PREAUTHORIZE);
expect(transaction.attributes.state).toEqual(propTypes.TX_STATE_PREAUTHORIZED);
expect(transaction.attributes.payinTotal).toEqual(new Money(2198, 'USD'));
expect(transaction.attributes.payoutTotal).toEqual(new Money(2198, 'USD'));
expect(transaction.attributes.lineItems).toEqual([

View file

@ -39,8 +39,7 @@ const formatDate = (intl, date) => {
// Translated name of the state of the given transaction
const txState = (intl, tx, isOrder) => {
const { attributes: { state } } = tx;
if (state === propTypes.TX_STATE_ACCEPTED) {
if (propTypes.txIsAccepted(tx)) {
return {
nameClassName: css.nameAccepted,
bookingClassName: css.bookingAccepted,
@ -50,7 +49,7 @@ const txState = (intl, tx, isOrder) => {
id: 'InboxPage.stateAccepted',
}),
};
} else if (state === propTypes.TX_STATE_REJECTED) {
} else if (propTypes.txIsRejectedOrAutorejected(tx)) {
return {
nameClassName: css.nameDeclined,
bookingClassName: css.bookingDeclined,
@ -60,7 +59,7 @@ const txState = (intl, tx, isOrder) => {
id: 'InboxPage.stateDeclined',
}),
};
} else if (state === propTypes.TX_STATE_DELIVERED) {
} else if (propTypes.txIsDelivered(tx)) {
return {
nameClassName: css.nameDelivered,
bookingClassName: css.bookingDelivered,
@ -101,7 +100,7 @@ export const InboxItem = props => {
const otherUserDisplayName = userDisplayName(otherUser, bannedUserDisplayName);
const stateData = txState(intl, tx, isOrder);
const isSaleNotification = !isOrder && tx.attributes.state === propTypes.TX_STATE_PREAUTHORIZED;
const isSaleNotification = !isOrder && propTypes.txIsPreauthorized(tx);
const rowNotificationDot = isSaleNotification ? <div className={css.notificationDot} /> : null;
const lastTransitionedAt = formatDate(intl, tx.attributes.lastTransitionedAt);
const bookingStart = formatDate(intl, booking.attributes.start);

View file

@ -5,6 +5,7 @@ import { fakeIntl, createUser, createTransaction, createBooking } from '../../ut
import { InboxPageComponent, InboxItem } from './InboxPage';
import routesConfiguration from '../../routesConfiguration';
import { flattenRoutes } from '../../util/routes';
import { TX_TRANSITION_PREAUTHORIZE } from '../../util/propTypes';
const noop = () => null;
@ -39,14 +40,14 @@ describe('InboxPage', () => {
transactions: [
createTransaction({
id: 'order-1',
state: 'state/preauthorized',
lastTransition: TX_TRANSITION_PREAUTHORIZE,
provider,
lastTransitionedAt: new Date(Date.UTC(2017, 0, 15)),
booking: booking1,
}),
createTransaction({
id: 'order-2',
state: 'state/preauthorized',
lastTransition: TX_TRANSITION_PREAUTHORIZE,
provider,
lastTransitionedAt: new Date(Date.UTC(2016, 0, 15)),
booking: booking2,
@ -86,14 +87,14 @@ describe('InboxPage', () => {
transactions: [
createTransaction({
id: 'sale-1',
state: 'state/preauthorized',
lastTransition: TX_TRANSITION_PREAUTHORIZE,
customer,
lastTransitionedAt: new Date(Date.UTC(2017, 0, 15)),
booking: booking1,
}),
createTransaction({
id: 'sale-2',
state: 'state/preauthorized',
lastTransition: TX_TRANSITION_PREAUTHORIZE,
customer,
lastTransitionedAt: new Date(Date.UTC(2016, 0, 15)),
booking: booking2,

View file

@ -127,7 +127,6 @@ exports[`InboxPage matches snapshot 1`] = `
"amount": 900,
"currency": "USD",
},
"state": "state/preauthorized",
},
"booking": Object {
"attributes": Object {
@ -215,7 +214,6 @@ exports[`InboxPage matches snapshot 1`] = `
"amount": 900,
"currency": "USD",
},
"state": "state/preauthorized",
},
"booking": Object {
"attributes": Object {
@ -437,7 +435,6 @@ exports[`InboxPage matches snapshot 3`] = `
"amount": 900,
"currency": "USD",
},
"state": "state/preauthorized",
},
"booking": Object {
"attributes": Object {
@ -525,7 +522,6 @@ exports[`InboxPage matches snapshot 3`] = `
"amount": 900,
"currency": "USD",
},
"state": "state/preauthorized",
},
"booking": Object {
"attributes": Object {

View file

@ -8,6 +8,7 @@ import {
fakeIntl,
} from '../../util/test-data';
import { renderShallow } from '../../util/test-helpers';
import { TX_TRANSITION_PREAUTHORIZE } from '../../util/propTypes';
import { OrderPageComponent } from './OrderPage';
const noop = () => null;
@ -17,7 +18,7 @@ describe('OrderPage', () => {
const txId = 'tx-order-1';
const transaction = createTransaction({
id: txId,
state: 'state/preauthorized',
lastTransition: TX_TRANSITION_PREAUTHORIZE,
booking: createBooking('booking1', {
start: new Date(Date.UTC(2017, 5, 10)),
end: new Date(Date.UTC(2017, 5, 13)),

View file

@ -86,7 +86,6 @@ exports[`OrderPage matches snapshot 1`] = `
"amount": 900,
"currency": "USD",
},
"state": "state/preauthorized",
},
"booking": Object {
"attributes": Object {

View file

@ -8,6 +8,7 @@ import {
fakeIntl,
} from '../../util/test-data';
import { renderShallow } from '../../util/test-helpers';
import { TX_TRANSITION_PREAUTHORIZE } from '../../util/propTypes';
import { SalePageComponent } from './SalePage';
const noop = () => null;
@ -17,7 +18,7 @@ describe('SalePage', () => {
const txId = 'tx-sale-1';
const transaction = createTransaction({
id: txId,
state: 'state/preauthorized',
lastTransition: TX_TRANSITION_PREAUTHORIZE,
booking: createBooking('booking1', {
start: new Date(Date.UTC(2017, 5, 10)),
end: new Date(Date.UTC(2017, 5, 13)),

View file

@ -93,7 +93,6 @@ exports[`SalePage matches snapshot 1`] = `
"amount": 900,
"currency": "USD",
},
"state": "state/preauthorized",
},
"booking": Object {
"attributes": Object {

View file

@ -1,5 +1,4 @@
import { updatedEntities, denormalisedEntities } from '../util/data';
import { TX_STATE_PREAUTHORIZED } from '../util/propTypes';
// ================ Action types ================ //
@ -299,7 +298,14 @@ export const fetchCurrentUserNotifications = () =>
const apiQueryParams = {
only: 'sale',
states: [TX_STATE_PREAUTHORIZED],
// TODO: Currently the API supports only filtering by tx
// state. However, the state will be removed and support for
// filtering by last transitions is added. The code below should
// be changed at that point.
states: ['state/preauthorized'],
// last_transitions: [TX_TRANSITION_PREAUTHORIZE],
page: 1,
per_page: NOTIFICATION_PAGE_SIZE,
};

View file

@ -20,6 +20,7 @@
import { PropTypes } from 'react';
import Decimal from 'decimal.js';
import { types as sdkTypes } from './sdkLoader';
import { ensureTransaction } from './data';
const { UUID, LatLng, LatLngBounds, Money } = sdkTypes;
const { arrayOf, bool, func, instanceOf, number, oneOf, shape, string } = PropTypes;
@ -135,18 +136,6 @@ export const booking = shape({
}),
});
export const TX_STATE_ACCEPTED = 'state/accepted';
export const TX_STATE_REJECTED = 'state/rejected';
export const TX_STATE_PREAUTHORIZED = 'state/preauthorized';
export const TX_STATE_DELIVERED = 'state/delivered';
export const TX_STATES = [
TX_STATE_ACCEPTED,
TX_STATE_REJECTED,
TX_STATE_PREAUTHORIZED,
TX_STATE_DELIVERED,
];
// When the customer requests a booking, a transaction is created. The
// initial state is preauthorized that is transitioned with the
// initial preauthorize transition. The customer can see this
@ -175,6 +164,20 @@ export const TX_TRANSITIONS = [
TX_TRANSITION_MARK_DELIVERED,
];
const txLastTransition = tx => ensureTransaction(tx).attributes.lastTransition;
export const txIsPreauthorized = tx => txLastTransition(tx) === TX_TRANSITION_PREAUTHORIZE;
export const txIsAccepted = tx => txLastTransition(tx) === TX_TRANSITION_ACCEPT;
export const txIsRejected = tx => txLastTransition(tx) === TX_TRANSITION_REJECT;
export const txIsAutorejected = tx => txLastTransition(tx) === TX_TRANSITION_AUTO_REJECT;
export const txIsRejectedOrAutorejected = tx => txIsRejected(tx) || txIsAutorejected(tx);
export const txIsDelivered = tx => txLastTransition(tx) === TX_TRANSITION_MARK_DELIVERED;
// Denormalised transaction object
export const transaction = shape({
id: uuid.isRequired,
@ -183,7 +186,6 @@ export const transaction = shape({
createdAt: instanceOf(Date).isRequired,
lastTransitionedAt: instanceOf(Date).isRequired,
lastTransition: oneOf(TX_TRANSITIONS).isRequired,
state: oneOf(TX_STATES).isRequired,
payinTotal: money.isRequired,
payoutTotal: money.isRequired,
lineItems: arrayOf(

View file

@ -89,7 +89,6 @@ export const createListing = (id, attributes = {}, includes = {}) => ({
export const createTransaction = options => {
const {
id,
state = propTypes.TX_STATE_PREAUTHORIZED,
lastTransition = propTypes.TX_TRANSITION_PREAUTHORIZE,
total = new Money(1000, 'USD'),
commission = new Money(100, 'USD'),
@ -106,7 +105,6 @@ export const createTransaction = options => {
attributes: {
createdAt: new Date(Date.UTC(2017, 4, 1)),
lastTransitionedAt,
state,
lastTransition,
payinTotal: total,
payoutTotal: new Money(total.amount - commission.amount, total.currency),