Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store Orders: Update status labels for "cash on delivery" orders #18983

Merged
merged 7 commits into from
Oct 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class OrderDetails extends Component {
return isEditing ? (
<OrderStatusSelect value={ order.status } onChange={ this.updateStatus } />
) : (
<OrderStatus status={ order.status } showShipping={ false } />
<OrderStatus order={ order } showShipping={ false } />
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ class OrderPaymentCard extends Component {
refund: formatCurrency( refund, order.currency ),
},
} );
} else if ( 'cod' === order.payment_method && 'processing' === order.status ) {
paymentStatus = translate( 'Payment of %(total)s on delivery', {
args: {
total: formatCurrency( order.total, order.currency ),
},
} );
} else {
paymentStatus = translate( 'Payment of %(total)s received via %(method)s', {
args: {
Expand All @@ -76,7 +82,8 @@ class OrderPaymentCard extends Component {

getPaymentAction = () => {
const { order, translate } = this.props;
if ( 'refunded' === order.status ) {
const codProcessing = 'cod' === order.payment_method && 'processing' === order.status;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate logic from line 86, maybe we should extract it out - or just leave it - 6 one way, half dozen the other 😆

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had the same thought, but then I'd have to write tests for another status function 😆

if ( 'refunded' === order.status || codProcessing ) {
return null;
} else if ( isOrderWaitingPayment( order.status ) ) {
return <Button onClick={ this.markAsPaid }>{ translate( 'Mark as Paid' ) }</Button>;
Expand Down
2 changes: 1 addition & 1 deletion client/extensions/woocommerce/app/orders/orders-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class Orders extends Component {
{ humanDate( order.date_created_gmt + 'Z' ) }
</TableItem>
<TableItem className="orders__table-status">
<OrderStatus status={ order.status } />
<OrderStatus order={ order } />
</TableItem>
<TableItem className="orders__table-total">
{ formatCurrency( order.total, order.currency ) || order.total }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Some statuses don't have a shipping status: `cancelled`, `refunded`, and `failed
render: function() {
return (
<SectionHeader label="Order Details">
<OrderStatus status={ 'pending' } />
<OrderStatus order={ { status: 'pending' } } />
</SectionHeader>
);
}
Expand Down
114 changes: 71 additions & 43 deletions client/extensions/woocommerce/components/order-status/index.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,80 @@
/** @format */
/**
* External dependencies
*
* @format
*/

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { localize } from 'i18n-calypso';
import React from 'react';

function OrderStatus( { showPayment = true, showShipping = true, status, translate } ) {
const classes = `order-status__item is-${ status }`;
let paymentLabel;
let shippingLabel;
switch ( status ) {
case 'pending':
shippingLabel = translate( 'New order' );
paymentLabel = translate( 'Payment pending' );
break;
case 'processing':
shippingLabel = translate( 'New order' );
paymentLabel = translate( 'Paid in full' );
break;
case 'on-hold':
shippingLabel = translate( 'On hold' );
paymentLabel = translate( 'Payment pending' );
break;
case 'completed':
shippingLabel = translate( 'Fulfilled' );
paymentLabel = translate( 'Paid in full' );
break;
case 'cancelled':
paymentLabel = translate( 'Cancelled' );
break;
case 'refunded':
paymentLabel = translate( 'Refunded' );
break;
case 'failed':
paymentLabel = translate( 'Payment failed' );
break;
}
export class OrderStatus extends Component {
static propTypes = {
order: PropTypes.shape( {
payment_method: PropTypes.string,
status: PropTypes.string.isRequired,
} ),
showPayment: PropTypes.bool,
showShipping: PropTypes.bool,
translate: PropTypes.func.isRequired,
};

getPaymentLabel = () => {
const { order, translate } = this.props;
const { status, payment_method } = order;
switch ( status ) {
case 'pending':
case 'on-hold':
return translate( 'Payment pending' );
case 'processing':
if ( 'cod' === payment_method ) {
return translate( 'Paid on delivery' );
}
return translate( 'Paid in full' );
case 'completed':
return translate( 'Paid in full' );
case 'cancelled':
return translate( 'Cancelled' );
case 'refunded':
return translate( 'Refunded' );
case 'failed':
return translate( 'Payment failed' );
}
return false;
};

getShippingLabel = () => {
const { order, translate } = this.props;
switch ( order.status ) {
case 'pending':
case 'processing':
return translate( 'New order' );
case 'on-hold':
return translate( 'On hold' );
case 'completed':
return translate( 'Fulfilled' );
}
return false;
};

return (
<span className={ classes }>
{ shippingLabel && showShipping ? (
<span className="order-status__shipping">{ shippingLabel }</span>
) : null }
{ showPayment ? <span className="order-status__payment">{ paymentLabel }</span> : null }
</span>
);
render() {
const { order: { status }, showPayment = true, showShipping = true } = this.props;
const classes = `order-status__item is-${ status }`;
const paymentLabel = this.getPaymentLabel();
const shippingLabel = this.getShippingLabel();

// Status was unrecognized, there is no label content to display
if ( ! shippingLabel && ! paymentLabel ) {
return null;
}

return (
<span className={ classes }>
{ shippingLabel && showShipping ? (
<span className="order-status__shipping">{ shippingLabel }</span>
) : null }
{ showPayment ? <span className="order-status__payment">{ paymentLabel }</span> : null }
</span>
);
}
}

export default localize( OrderStatus );
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!

* External dependencies
*
* @format
*/

import React from 'react';
import { expect } from 'chai';
import { identity } from 'lodash';
import { shallow } from 'enzyme';

/**
* Internal dependencies
*/
import { OrderStatus } from '../';

describe( 'OrderStatus', () => {
test( 'should render a label with shipping and payment content', () => {
const order = {
status: 'pending',
payment_method: 'paypal',
};
const wrapper = shallow( <OrderStatus order={ order } translate={ identity } /> );
expect( wrapper.find( '.order-status__item' ) ).to.have.length( 1 );
expect( wrapper.find( '.order-status__item' ).hasClass( 'is-pending' ) ).to.equal( true );
expect( wrapper.find( '.order-status__shipping' ) ).to.have.length( 1 );
expect( wrapper.find( '.order-status__payment' ) ).to.have.length( 1 );
} );

test( 'should render only payment label when showShipping is false', () => {
const order = { status: 'pending' };
const wrapper = shallow(
<OrderStatus order={ order } showShipping={ false } translate={ identity } />
);
expect( wrapper.find( '.order-status__item' ) ).to.have.length( 1 );
expect( wrapper.find( '.order-status__shipping' ) ).to.have.length( 0 );
expect( wrapper.find( '.order-status__payment' ) ).to.have.length( 1 );
} );

test( 'should render only payment label when shipping does not apply to this status', () => {
const order = { status: 'refunded' };
const wrapper = shallow(
<OrderStatus order={ order } showShipping={ false } translate={ identity } />
);
expect( wrapper.find( '.order-status__item' ) ).to.have.length( 1 );
expect( wrapper.find( '.order-status__item' ).hasClass( 'is-refunded' ) ).to.equal( true );
expect( wrapper.find( '.order-status__shipping' ) ).to.have.length( 0 );
expect( wrapper.find( '.order-status__payment' ) ).to.have.length( 1 );
} );

test( 'should render only shipping label when showPayment is false', () => {
const order = { status: 'completed' };
const wrapper = shallow(
<OrderStatus order={ order } showPayment={ false } translate={ identity } />
);
expect( wrapper.find( '.order-status__item' ) ).to.have.length( 1 );
expect( wrapper.find( '.order-status__item' ).hasClass( 'is-completed' ) ).to.equal( true );
expect( wrapper.find( '.order-status__shipping' ) ).to.have.length( 1 );
expect( wrapper.find( '.order-status__payment' ) ).to.have.length( 0 );
} );

test( 'should render correct labels for a processing cash-on-delivery order', () => {
const order = {
status: 'processing',
payment_method: 'cod',
};
const wrapper = shallow( <OrderStatus order={ order } translate={ identity } /> );
expect( wrapper.find( '.order-status__item' ) ).to.have.length( 1 );
expect( wrapper.find( '.order-status__item' ).hasClass( 'is-processing' ) ).to.equal( true );
expect( wrapper.find( '.order-status__shipping' ).text() ).to.eql( 'New order' );
expect( wrapper.find( '.order-status__payment' ).text() ).to.eql( 'Paid on delivery' );
} );

test( 'should not render anything if the status is not recognized', () => {
const order = { status: 'fake-status' };
const wrapper = shallow( <OrderStatus order={ order } translate={ identity } /> );
expect( wrapper.getNode() ).to.be.null;
} );
} );