Last active
August 29, 2015 13:57
-
-
Save simmsy/9684227 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# The fundamantal design opinion is that a Stock Return has many Returned Items | |
# Each Returned Item effectively has one of 3 actions associated with it return, exchange OR replace | |
# Any of these action can involve a refund, although the most common is that a return involves a refund | |
# You may wish to refund a replacement Or exchange to maintain customer relations | |
# | |
# Once all Returned Items and their actions have been set then you can commence to attempt to process the Stock Return | |
# Processing the Stock Return will automate the Order Adjustments, Addiitonal Shipments and any Refunds / Payments | |
# It should be exstensible so that developers can easily implement their own behaviour here | |
# | |
# It could be that a developer can extend this to Create New Orders instead of Additional Shipments under certain scenarios: | |
# When the total of the exchanged items exceed the balance on the Order, it might be preferable to require a new payment, hence new Order | |
class StockReturn | |
# return_cost | |
# handling_cost | |
# timestamps | |
has_many :returned_items | |
has_many :exchange_items | |
before_transistion_to :complete, :handle_return | |
# Validate processable? | |
def processable? | |
Spree::StockReturnHandler.factory(self).processable? | |
end | |
def handle_return | |
Spree::StockReturnHandler.factory(self).process! | |
end | |
end | |
# A Returned Item has 3 actions: return, replace or exchange | |
# You can refund (using refund_amount not null and > 0) with ANY of the actions above | |
# | |
# Attributes: | |
# - reason: provided by customer (wrong_size, not_suitable, not_as_described, arrived_late, other, etc) | |
# - reason_other : string | |
# - refund_amount: allow null, null is unknown and therefore unprocessable, must be set to 0 if no refund provided | |
# NOTE: No qty for line item, each one has a separate record | |
# | |
# Potentially: | |
# - condition: provided by receiver (faulty, damaged, good) | |
# - restock: boolean (null is unknown and therefore unprocessable) | |
class ReturnedItem | |
enum action: [:return, :replace, :exchange] | |
enum reason: REASON_CODES | |
belongs_to :stock_return | |
belongs_to :line_item | |
# If certain Reason Codes provided then we can auto set refund amount | |
before_create :auto_set_refund_amount | |
def refund? | |
refund_amount.present? && refund_amount > 0 | |
end | |
end | |
class ExchangeItem | |
# price (defaults to line_item current price but if set here is overriden) | |
belongs_to :stock_return | |
belongs_to :line_item | |
end | |
class StockReturnHandler | |
def initialize(stock_return) | |
@stock_return | |
end | |
def processable? | |
# These methods add errors to the Stock Return object | |
refund_due_within_processable_boundary? | |
exchange_items_shipable? | |
replacement_items_shipable? | |
@stock_return.valid? | |
end | |
def perform | |
return false unless processable? | |
adjust_order_for_return_cost | |
adjust_order_for_handling_fee | |
create_shipments_for_exchanged_and_replacement_items | |
process_balance #(refund or charge additional) | |
true | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You said you would like the ReturnedItems to not have a quantity, and be a single record per unit quantity. That is what InventoryUnits are used for in terms of mapping LineItems to a Shipment. Following that naming convention it would make sense it using the naming as ReturnedInventoryUnit and ExchangedInventoryUnit as the way to track that your shipped InventoryUnit came back.