Skip to content

Instantly share code, notes, and snippets.

@kidap
Created August 14, 2018 13:00
Show Gist options
  • Save kidap/26247bb7aaf0a41c104e160bd56e05c5 to your computer and use it in GitHub Desktop.
Save kidap/26247bb7aaf0a41c104e160bd56e05c5 to your computer and use it in GitHub Desktop.
Cleanup Protocols/Objects that display or calculate totals
// MARK: Refundable
protocol Refundable {
var canBeRefunded: Bool { get }
var isRefunded: Bool { get }
var isARefund: Bool { get }
}
extension Bill: Refundable {
var canBeRefunded: Bool {
return isClosed && !isRefunded && !isARefund
}
}
// MARK: OrderTotals
protocol OrderTotals {
/// Amount the customer has to pay
func totalAmountDue(whenPayingBy paymentType: PaymentType?) -> Int64
/**
Remaining amount the customer has to pay
Calculation:
```
totalOutstandingBalance = totalAmountPaid - totalAmountDue
````
*/
func totalOutstandingBalance(whenPayingBy paymentType: PaymentType?) -> Int64
/// Tips received
var totalTips: Int64 { get }
/// Total rounding adjustments made to the BillEngineBillRepresentable.total
var totalRoundingAdjustments: Int64 { get }
/// Total amount tendered in cash, credit/debit, or non-integrated payment
var totalAmountTendered: Int64 { get }
/// The excess amount that is returned to the customer
var totalChange: Int64 { get }
/**
Total amount paid by the customer. It excludes the change returned to the customer.
Calculation:
```
totalAmountPaid = totalAmountTendered - totalChange
````
*/
var totalAmountPaid: Int64 { get }
}
extension OrderTotals where Self: BillEngineBillRepresentable & NSManagedObject {
func calculateTotal(whenPayingBy paymentType: PaymentType?) -> ZeroDecimalAmount {
guard let managedObjectContext = managedObjectContext,
let paymentType = paymentType else {
return total
}
switch paymentType {
case .cash: return PennyRoundingCalculator.round(total, in: managedObjectContext)
case .card: return total
case .nonIntegrated: return total
}
}
}
// MARK: Bill extension
extension Bill: OrderTotals {
func totalAmountDue(whenPayingBy paymentType: PaymentType? = nil) -> Int64 {
if isClosed {
return total + totalRoundingAdjustments
} else {
return calculateTotal(whenPayingBy: paymentType)
}
}
func totalOutstandingBalance(whenPayingBy paymentType: PaymentType? = nil) -> Int64 {
return totalAmountPaid - totalAmountDue(whenPayingBy: paymentType)
}
var totalTips: Int64 {
return payments?.reduce(ZeroDecimalAmount.zero) { $0 + $1.tip } ?? ZeroDecimalAmount.zero
}
var totalRoundingAdjustments: Int64 {
if isClosed {
return payments?.reduce(ZeroDecimalAmount.zero) { $0 + $1.roundingDifference } ?? ZeroDecimalAmount.zero
} else {
return calculateTotal(whenPayingBy: .cash) - total
}
}
var totalAmountTendered: Int64 {
return totalAmountPaid + totalTips + totalChange
}
var totalChange: Int64 {
return payments?.reduce(ZeroDecimalAmount.zero) {
return $0 + ($1.cashPayments?.reduce(ZeroDecimalAmount.zero) { $0 + $1.change } ?? ZeroDecimalAmount.zero)
} ?? ZeroDecimalAmount.zero
}
var totalAmountPaid: Int64 {
return payments?.reduce(ZeroDecimalAmount.zero) { $0 + $1.amount } ?? ZeroDecimalAmount.zero
}
}
// MARK: Order extension
extension Order: OrderTotals {
func totalAmountDue(whenPayingBy paymentType: PaymentType? = nil) -> Int64 {
return calculateTotal(whenPayingBy: paymentType)
}
func totalOutstandingBalance(whenPayingBy paymentType: PaymentType? = nil) -> Int64 {
return totalAmountDue(whenPayingBy: paymentType)
}
var totalTips: Int64 {
return ZeroDecimalAmount.zero
}
var totalRoundingAdjustments: Int64 {
return calculateTotal(whenPayingBy: .cash) - total
}
var totalAmountTendered: Int64 {
return totalAmountPaid + totalTips + totalChange
}
var totalChange: Int64 {
return ZeroDecimalAmount.zero
}
var totalAmountPaid: Int64 {
return ZeroDecimalAmount.zero
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment