mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 12:43:11 +10:00
Move breakdown estimation to a separate file
This commit is contained in:
parent
1fc23dac36
commit
322e65ef41
2 changed files with 119 additions and 120 deletions
|
|
@ -6,130 +6,14 @@ import { reduxForm, formValueSelector, propTypes as formPropTypes } from 'redux-
|
|||
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import moment from 'moment';
|
||||
import Decimal from 'decimal.js';
|
||||
import { types as sdkTypes } from '../../util/sdkLoader';
|
||||
import { required, bookingDatesRequired } from '../../util/validators';
|
||||
import {
|
||||
dateFromLocalToAPI,
|
||||
nightsBetween,
|
||||
daysBetween,
|
||||
START_DATE,
|
||||
END_DATE,
|
||||
} from '../../util/dates';
|
||||
import { unitDivisor, convertMoneyToNumber, convertUnitToSubUnit } from '../../util/currency';
|
||||
import {
|
||||
LINE_ITEM_DAY,
|
||||
LINE_ITEM_NIGHT,
|
||||
LINE_ITEM_UNITS,
|
||||
TRANSITION_REQUEST,
|
||||
TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
propTypes,
|
||||
} from '../../util/types';
|
||||
import { START_DATE, END_DATE } from '../../util/dates';
|
||||
import { propTypes } from '../../util/types';
|
||||
import config from '../../config';
|
||||
import { Form, PrimaryButton, BookingBreakdown, FieldDateRangeInput } from '../../components';
|
||||
import { Form, PrimaryButton, FieldDateRangeInput } from '../../components';
|
||||
|
||||
import css from './BookingDatesForm.css';
|
||||
|
||||
const { Money, UUID } = sdkTypes;
|
||||
|
||||
const estimatedTotalPrice = (unitPrice, unitCount) => {
|
||||
const numericPrice = convertMoneyToNumber(unitPrice);
|
||||
const numericTotalPrice = new Decimal(numericPrice).times(unitCount).toNumber();
|
||||
return new Money(
|
||||
convertUnitToSubUnit(numericTotalPrice, unitDivisor(unitPrice.currency)),
|
||||
unitPrice.currency
|
||||
);
|
||||
};
|
||||
|
||||
// When we cannot speculatively initiate a transaction (i.e. logged
|
||||
// out), we must estimate the booking breakdown. This function creates
|
||||
// an estimated transaction object for that use case.
|
||||
const estimatedTransaction = (unitType, bookingStart, bookingEnd, unitPrice, quantity) => {
|
||||
const now = new Date();
|
||||
const isNightly = unitType === LINE_ITEM_NIGHT;
|
||||
const isDaily = unitType === LINE_ITEM_DAY;
|
||||
|
||||
const unitCount = isNightly
|
||||
? nightsBetween(bookingStart, bookingEnd)
|
||||
: isDaily ? daysBetween(bookingStart, bookingEnd) : quantity;
|
||||
|
||||
const totalPrice = estimatedTotalPrice(unitPrice, unitCount);
|
||||
|
||||
// bookingStart: "Fri Mar 30 2018 12:00:00 GMT-1100 (SST)" aka "Fri Mar 30 2018 23:00:00 GMT+0000 (UTC)"
|
||||
// Server normalizes night/day bookings to start from 00:00 UTC aka "Thu Mar 29 2018 13:00:00 GMT-1100 (SST)"
|
||||
// The result is: local timestamp.subtract(12h).add(timezoneoffset) (in eg. -23 h)
|
||||
|
||||
// local noon -> startOf('day') => 00:00 local => remove timezoneoffset => 00:00 API (UTC)
|
||||
const serverDayStart = dateFromLocalToAPI(
|
||||
moment(bookingStart)
|
||||
.startOf('day')
|
||||
.toDate()
|
||||
);
|
||||
const serverDayEnd = dateFromLocalToAPI(
|
||||
moment(bookingEnd)
|
||||
.startOf('day')
|
||||
.toDate()
|
||||
);
|
||||
|
||||
return {
|
||||
id: new UUID('estimated-transaction'),
|
||||
type: 'transaction',
|
||||
attributes: {
|
||||
createdAt: now,
|
||||
lastTransitionedAt: now,
|
||||
lastTransition: TRANSITION_REQUEST,
|
||||
payinTotal: totalPrice,
|
||||
payoutTotal: totalPrice,
|
||||
lineItems: [
|
||||
{
|
||||
code: unitType,
|
||||
includeFor: ['customer', 'provider'],
|
||||
unitPrice: unitPrice,
|
||||
quantity: new Decimal(unitCount),
|
||||
lineTotal: totalPrice,
|
||||
reversal: false,
|
||||
},
|
||||
],
|
||||
transitions: [
|
||||
{
|
||||
at: now,
|
||||
by: TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
transition: TRANSITION_REQUEST,
|
||||
},
|
||||
],
|
||||
},
|
||||
booking: {
|
||||
id: new UUID('estimated-booking'),
|
||||
type: 'booking',
|
||||
attributes: {
|
||||
start: serverDayStart,
|
||||
end: serverDayEnd,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const estimatedBreakdown = (unitType, bookingStart, bookingEnd, unitPrice, quantity) => {
|
||||
const isUnits = unitType === LINE_ITEM_UNITS;
|
||||
const quantityIfUsingUnits = !isUnits || Number.isInteger(quantity);
|
||||
const canEstimatePrice = bookingStart && bookingEnd && unitPrice && quantityIfUsingUnits;
|
||||
if (!canEstimatePrice) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tx = estimatedTransaction(unitType, bookingStart, bookingEnd, unitPrice, quantity);
|
||||
|
||||
return (
|
||||
<BookingBreakdown
|
||||
className={css.receipt}
|
||||
userRole="customer"
|
||||
unitType={unitType}
|
||||
transaction={tx}
|
||||
booking={tx.booking}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export class BookingDatesFormComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
@ -213,7 +97,7 @@ export class BookingDatesFormComponent extends Component {
|
|||
<h3 className={css.priceBreakdownTitle}>
|
||||
<FormattedMessage id="BookingDatesForm.priceBreakdownTitle" />
|
||||
</h3>
|
||||
{estimatedBreakdown(unitType, startDate, endDate, unitPrice)}
|
||||
{/*estimatedBreakdown(unitType, startDate, endDate, unitPrice)*/}
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
|
|
|
|||
115
src/containers/BookingDatesForm/EstimatedBreakdownMaybe.js
Normal file
115
src/containers/BookingDatesForm/EstimatedBreakdownMaybe.js
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import moment from 'moment';
|
||||
import Decimal from 'decimal.js';
|
||||
import { types as sdkTypes } from '../../util/sdkLoader';
|
||||
import { dateFromLocalToAPI, nightsBetween, daysBetween } from '../../util/dates';
|
||||
import {
|
||||
LINE_ITEM_DAY,
|
||||
LINE_ITEM_NIGHT,
|
||||
LINE_ITEM_UNITS,
|
||||
TRANSITION_REQUEST,
|
||||
TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
} from '../../util/types';
|
||||
import { unitDivisor, convertMoneyToNumber, convertUnitToSubUnit } from '../../util/currency';
|
||||
import { BookingBreakdown } from '../../components';
|
||||
|
||||
import css from './BookingDatesForm.css';
|
||||
|
||||
const { Money, UUID } = sdkTypes;
|
||||
|
||||
const estimatedTotalPrice = (unitPrice, unitCount) => {
|
||||
const numericPrice = convertMoneyToNumber(unitPrice);
|
||||
const numericTotalPrice = new Decimal(numericPrice).times(unitCount).toNumber();
|
||||
return new Money(
|
||||
convertUnitToSubUnit(numericTotalPrice, unitDivisor(unitPrice.currency)),
|
||||
unitPrice.currency
|
||||
);
|
||||
};
|
||||
|
||||
// When we cannot speculatively initiate a transaction (i.e. logged
|
||||
// out), we must estimate the booking breakdown. This function creates
|
||||
// an estimated transaction object for that use case.
|
||||
const estimatedTransaction = (unitType, bookingStart, bookingEnd, unitPrice, quantity) => {
|
||||
const now = new Date();
|
||||
const isNightly = unitType === LINE_ITEM_NIGHT;
|
||||
const isDaily = unitType === LINE_ITEM_DAY;
|
||||
|
||||
const unitCount = isNightly
|
||||
? nightsBetween(bookingStart, bookingEnd)
|
||||
: isDaily ? daysBetween(bookingStart, bookingEnd) : quantity;
|
||||
|
||||
const totalPrice = estimatedTotalPrice(unitPrice, unitCount);
|
||||
|
||||
// bookingStart: "Fri Mar 30 2018 12:00:00 GMT-1100 (SST)" aka "Fri Mar 30 2018 23:00:00 GMT+0000 (UTC)"
|
||||
// Server normalizes night/day bookings to start from 00:00 UTC aka "Thu Mar 29 2018 13:00:00 GMT-1100 (SST)"
|
||||
// The result is: local timestamp.subtract(12h).add(timezoneoffset) (in eg. -23 h)
|
||||
|
||||
// local noon -> startOf('day') => 00:00 local => remove timezoneoffset => 00:00 API (UTC)
|
||||
const serverDayStart = dateFromLocalToAPI(
|
||||
moment(bookingStart)
|
||||
.startOf('day')
|
||||
.toDate()
|
||||
);
|
||||
const serverDayEnd = dateFromLocalToAPI(
|
||||
moment(bookingEnd)
|
||||
.startOf('day')
|
||||
.toDate()
|
||||
);
|
||||
|
||||
return {
|
||||
id: new UUID('estimated-transaction'),
|
||||
type: 'transaction',
|
||||
attributes: {
|
||||
createdAt: now,
|
||||
lastTransitionedAt: now,
|
||||
lastTransition: TRANSITION_REQUEST,
|
||||
payinTotal: totalPrice,
|
||||
payoutTotal: totalPrice,
|
||||
lineItems: [
|
||||
{
|
||||
code: unitType,
|
||||
includeFor: ['customer', 'provider'],
|
||||
unitPrice: unitPrice,
|
||||
quantity: new Decimal(unitCount),
|
||||
lineTotal: totalPrice,
|
||||
reversal: false,
|
||||
},
|
||||
],
|
||||
transitions: [
|
||||
{
|
||||
at: now,
|
||||
by: TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
transition: TRANSITION_REQUEST,
|
||||
},
|
||||
],
|
||||
},
|
||||
booking: {
|
||||
id: new UUID('estimated-booking'),
|
||||
type: 'booking',
|
||||
attributes: {
|
||||
start: serverDayStart,
|
||||
end: serverDayEnd,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const estimatedBreakdown = (unitType, bookingStart, bookingEnd, unitPrice, quantity) => {
|
||||
const isUnits = unitType === LINE_ITEM_UNITS;
|
||||
const quantityIfUsingUnits = !isUnits || Number.isInteger(quantity);
|
||||
const canEstimatePrice = bookingStart && bookingEnd && unitPrice && quantityIfUsingUnits;
|
||||
if (!canEstimatePrice) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tx = estimatedTransaction(unitType, bookingStart, bookingEnd, unitPrice, quantity);
|
||||
|
||||
return (
|
||||
<BookingBreakdown
|
||||
className={css.receipt}
|
||||
userRole="customer"
|
||||
unitType={unitType}
|
||||
transaction={tx}
|
||||
booking={tx.booking}
|
||||
/>
|
||||
);
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue