-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
[Marketplace] Orders line items refund #2590
Changes from 145 commits
b9a5237
6917f5c
cca678a
433bef6
5b64575
564dfdf
7f7a02a
9a56646
28db441
f5c7c9e
c5c79a4
540c24e
9393e16
9218f31
4ac11b2
9f8da99
3d972d0
5ce8394
de48f0b
7e330d9
4729320
31c0349
62b9c45
1de63a3
e263769
239680d
c72247a
0d069d7
c1c4b3f
df6739d
5b446c7
eef7f18
9cfe6e8
6d88f3c
133e764
ea5aa34
278756a
bcd7d1d
f3ca0d4
1e4d7fc
6e45ad6
a0b44da
d202a0a
18d45a2
42ffc56
73274c9
da41bc0
754e66b
c8409ff
9858361
4512d75
352c98d
43e0a60
b2b8e7f
5d0fc79
9a623be
e4bade3
6d50cea
c5ee98a
f7aa04b
4efb14e
dd0a77b
b64ee84
72d1ad3
18778df
25e8942
cea9557
1d0fd64
1a6a8f3
d3e7da5
b59263b
c9a0b28
670ee6b
e87ea72
c737ac9
c27f70e
0b97a00
3144dc3
3f252fe
543ddc0
6c60ea1
1e11e68
bef35d9
a6c941b
50c75f1
9ba4187
8555f11
62b040c
5b5b38a
a69f152
58fee6d
3ad51f4
9d68fe6
eef7b45
8dd458b
1df9c09
aa97091
b1daa00
bcccf44
9b0f9d9
fcbafdd
f36edc8
c097696
e5e69fa
c2af01f
b86d9c8
9a13ffb
02ae4f4
4511fe7
e92bcc9
4f3ffdf
ff74ac9
0ccc35a
11f6a8a
7daaa98
035d268
4b49dfe
321591e
b039f87
b9b125c
4ef6aa5
9c0e11d
e2af30a
e42637e
6871a61
cf8bf8c
3a6acea
5c365c0
fd0ab82
3e38ac9
5f9207e
e409f40
d282b4a
b7c27d5
0c16338
2c1bdf5
463531f
bc1f6bb
f4abdde
cb7d31c
2ce6218
5f4f063
a037809
9caee44
adcfcd0
b95b7c3
64f2db4
58c1079
753fd6d
a86de17
ab1038d
7ce7322
7f1cf7d
df312d3
8619af4
194a7a8
182d896
86fa03b
744d2bc
94457d8
6911414
e40afb0
90aa8a4
296d218
c887b7d
f2d60c9
ab007ef
835ecc2
6a01e84
229f82d
bb9cacb
272c70b
89fa5b1
6494f1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,41 @@ | ||
import React, { Component } from "react"; | ||
import PropTypes from "prop-types"; | ||
import moment from "moment"; | ||
import { formatPriceString } from "/client/api"; | ||
import { Translation } from "/imports/plugins/core/ui/client/components"; | ||
import DiscountList from "/imports/plugins/core/discounts/client/components/list"; | ||
import { Translation, CardGroup, Card, CardBody, CardHeader, DiscountList } from "@reactioncommerce/reaction-ui"; | ||
import LineItems from "./lineItems"; | ||
import InvoiceActions from "./invoiceActions"; | ||
|
||
class Invoice extends Component { | ||
static propTypes = { | ||
canMakeAdjustments: PropTypes.bool, | ||
collection: PropTypes.string, | ||
dateFormat: PropTypes.func, | ||
discounts: PropTypes.bool, | ||
handleClick: PropTypes.func, | ||
hasRefundingEnabled: PropTypes.bool, | ||
invoice: PropTypes.object, | ||
isFetching: PropTypes.bool, | ||
isOpen: PropTypes.bool, | ||
orderId: PropTypes.string, | ||
order: PropTypes.object, | ||
paymentCaptured: PropTypes.bool, | ||
refunds: PropTypes.array | ||
} | ||
|
||
dateFormat(context, block) { | ||
const f = block || "MMM DD, YYYY hh:mm:ss A"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's not use single letter variables ever |
||
return moment(context).format(f); | ||
} | ||
|
||
renderDiscountForm() { | ||
const { isOpen, orderId, collection } = this.props; | ||
const { isOpen, order } = this.props; | ||
|
||
return ( | ||
<div> | ||
{isOpen && | ||
<div> | ||
<hr/> | ||
<DiscountList | ||
id={orderId} | ||
collection={collection} | ||
id={order._id} | ||
collection="Orders" | ||
validatedInput={true} | ||
/> | ||
<hr/> | ||
|
@@ -41,7 +46,7 @@ class Invoice extends Component { | |
} | ||
|
||
renderRefundsInfo() { | ||
const { hasRefundingEnabled, isFetching, refunds, dateFormat } = this.props; | ||
const { hasRefundingEnabled, isFetching, refunds } = this.props; | ||
|
||
return ( | ||
<div> | ||
|
@@ -56,7 +61,7 @@ class Invoice extends Component { | |
|
||
{refunds && refunds.map((refund) => ( | ||
<div className="order-summary-form-group text-danger" key={refund.created} style={{ marginBottom: 15 }}> | ||
<strong>Refunded on: {dateFormat(refund.created, "MM/D/YYYY")}</strong> | ||
<strong>Refunded on: {this.dateFormat(refund.created, "MM/D/YYYY")}</strong> | ||
<div className="invoice-details"><strong>{formatPriceString(refund.amount)}</strong></div> | ||
</div> | ||
))} | ||
|
@@ -80,7 +85,6 @@ class Invoice extends Component { | |
|
||
renderConditionalDisplay() { | ||
const { canMakeAdjustments, paymentCaptured } = this.props; | ||
|
||
return ( | ||
<div> | ||
{canMakeAdjustments ? | ||
|
@@ -99,7 +103,7 @@ class Invoice extends Component { | |
); | ||
} | ||
|
||
render() { | ||
renderInvoice() { | ||
const { invoice, discounts, handleClick } = this.props; | ||
|
||
return ( | ||
|
@@ -148,6 +152,31 @@ class Invoice extends Component { | |
</div> | ||
); | ||
} | ||
|
||
render() { | ||
return ( | ||
<CardGroup> | ||
<Card | ||
expanded={true} | ||
> | ||
<CardHeader | ||
actAsExpander={false} | ||
i18nKeyTitle="admin.orderWorkflow.invoice.cardTitle" | ||
title="Invoice" | ||
/> | ||
<CardBody expandable={false}> | ||
<LineItems {...this.props} /> | ||
|
||
<div className="invoice-container"> | ||
{this.renderInvoice()} | ||
</div> | ||
|
||
<InvoiceActions {...this.props}/> | ||
</CardBody> | ||
</Card> | ||
</CardGroup> | ||
); | ||
} | ||
} | ||
|
||
export default Invoice; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,28 @@ | ||
import React, { Component } from "react"; | ||
import PropTypes from "prop-types"; | ||
import { formatPriceString } from "/client/api"; | ||
import { IconButton, NumericInput, Translation } from "/imports/plugins/core/ui/client/components"; | ||
import { Button, NumericInput, Translation, ButtonSelect } from "@reactioncommerce/reaction-ui"; | ||
|
||
class InvoiceActions extends Component { | ||
static propTypes = { | ||
adjustedTotal: PropTypes.number, | ||
handleActionViewBack: PropTypes.func, | ||
currency: PropTypes.object, | ||
handleApprove: PropTypes.func, | ||
handleCapturePayment: PropTypes.func, | ||
handleRefund: PropTypes.func, | ||
hasRefundingEnabled: PropTypes.bool, | ||
invoice: PropTypes.object, | ||
isAdjusted: PropTypes.func | ||
isCapturing: PropTypes.bool, | ||
isRefunding: PropTypes.bool, | ||
paymentApproved: PropTypes.bool, | ||
paymentCaptured: PropTypes.bool, | ||
paymentPendingApproval: PropTypes.bool, | ||
printOrder: PropTypes.string, | ||
showAfterPaymentCaptured: PropTypes.bool | ||
} | ||
|
||
state = { | ||
value: 0 | ||
} | ||
|
||
renderCapturedTotal() { | ||
|
@@ -42,46 +56,161 @@ class InvoiceActions extends Component { | |
</div> | ||
); | ||
} | ||
|
||
renderRefundForm() { | ||
const { adjustedTotal } = this.props; | ||
|
||
return ( | ||
<div className="invoice-summary"> | ||
<span className="invoice-label refund"> | ||
<strong><Translation defaultValue="Refund" i18nKey="admin.invoice.refund"/></strong> | ||
</span> | ||
<div> | ||
{this.props.hasRefundingEnabled && | ||
<div className="flex refund-container"> | ||
<div className="form-group order-summary-form-group"> | ||
<div className="invoice-details"> | ||
<NumericInput | ||
numericType="currency" | ||
value={this.state.value} | ||
maxValue={adjustedTotal} | ||
format={this.props.currency} | ||
classNames={{ | ||
input: { | ||
amount: true | ||
} | ||
}} | ||
onChange={(event, data)=>{ | ||
this.setState({ | ||
value: data.numberValue | ||
}); | ||
}} | ||
/> | ||
</div> | ||
|
||
<div className="invoice-details"> | ||
<span className="refundAmount"> | ||
<NumericInput | ||
numericType="currency" | ||
value="0" | ||
maxValue={adjustedTotal} | ||
classNames="amount" | ||
/> | ||
</span> | ||
<span className="refundSubmit"> | ||
<IconButton | ||
bezelStyle={"flat"} | ||
icon="fa fa-arrow-circle-o-right" | ||
onClick={this.props.handleActionViewBack} | ||
/> | ||
<span id="btn-refund-payment">-></span> | ||
</span> | ||
</div> | ||
</div> | ||
|
||
<Button | ||
className="flex-item-fill refund-button" | ||
type="button" | ||
status="primary" | ||
bezelStyle="solid" | ||
disabled={this.props.isRefunding || this.state.value === 0} | ||
onClick={(event) => { | ||
this.props.handleRefund(event, this.state.value); | ||
this.setState({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason to do this here rather than in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, coz the value on the refund input box is being set by the onChange function on this component instead of having the value change propagated from the parent component I have the value set in the same component. In short yes there is a reason. |
||
value: 0 | ||
}); | ||
}} | ||
> | ||
{this.props.isRefunding ? | ||
<span id="btn-refund-payment" data-i18n="order.applyRefund">Refunding <i className="fa fa-spinner fa-spin" /></span> : | ||
<span id="btn-refund-payment" data-i18n="order.applyRefund">Apply Refund</span> | ||
} | ||
</Button> | ||
</div> | ||
} | ||
|
||
{this.props.showAfterPaymentCaptured && | ||
<Button | ||
className="btn btn-danger" | ||
bezelStyle="solid" | ||
type="button" | ||
data-event-action="cancelOrder" | ||
style={{ marginBottom: 10 }} | ||
data-i18n="order.cancelOrderLabel" | ||
> | ||
Cancel Order | ||
</Button> | ||
} | ||
|
||
<a | ||
className="btn btn-default btn-block" | ||
href={this.props.printOrder} | ||
target="_blank" | ||
data-i18n="app.printInvoice" | ||
> | ||
Print Invoice | ||
</a> | ||
</div> | ||
); | ||
} | ||
|
||
render() { | ||
const { isAdjusted } = this.props; | ||
renderApproval() { | ||
if (this.props.paymentPendingApproval) { | ||
return ( | ||
<div className="btn-block"> | ||
<div> | ||
<ButtonSelect | ||
buttons= {[ | ||
{ | ||
name: "Approve", | ||
i18nKeyLabel: "order.approveInvoice", | ||
active: true, | ||
status: "success", | ||
eventAction: "approveInvoice", | ||
bgColor: "bg-success", | ||
buttonType: "submit" | ||
}, { | ||
name: "Cancel", | ||
i18nKeyLabel: "order.cancelInvoice", | ||
active: false, | ||
status: "danger", | ||
eventAction: "cancelOrder", | ||
bgColor: "bg-danger", | ||
buttonType: "button" | ||
} | ||
]} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
if (this.props.paymentApproved) { | ||
return ( | ||
<div className="flex"> | ||
<a | ||
className="btn btn-link" | ||
href={this.props.printOrder} | ||
target="_blank" | ||
data-i18n="app.print" | ||
> | ||
</a> | ||
|
||
<button | ||
className="btn btn-success flex-item-fill" | ||
type="button" | ||
data-event-action="capturePayment" | ||
disabled={this.props.isCapturing} | ||
onClick = {this.props.handleCapturePayment} | ||
> | ||
|
||
{this.props.isCapturing ? | ||
<span id="btn-capture-payment"> | ||
Capturing <i className="fa fa-spinner fa-spin" id="btn-processing" /> | ||
</span> : | ||
<span id="btn-capture-payment" data-i18n="order.capturePayment">Capture Payment</span> | ||
} | ||
</button> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
render() { | ||
return ( | ||
<div> | ||
{this.renderCapturedTotal()} | ||
{isAdjusted() && this.renderAdjustedTotal()} | ||
{/* {this.renderRefundForm()} */} | ||
</div> | ||
<form onSubmit={this.props.handleApprove}> | ||
|
||
<div style={{ marginBottom: 15, marginTop: 15 }}> | ||
{this.renderApproval()} | ||
{this.props.paymentCaptured && | ||
<div className="total-container"> | ||
{this.renderCapturedTotal()} | ||
{this.props.invoice.total !== this.props.adjustedTotal && this.renderAdjustedTotal()} | ||
{this.renderRefundForm()} | ||
</div> | ||
} | ||
</div> | ||
</form> | ||
|
||
); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While were here let's add docs: https://github.com/reactioncommerce/reaction-jsdoc#documenting-react-components