Last active
March 1, 2019 02:37
-
-
Save gmmoreira/5b8fbcb2b52c689c4f63f48bcc90e531 to your computer and use it in GitHub Desktop.
Revisions
-
gmmoreira revised this gist
Mar 1, 2019 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -113,7 +113,7 @@ class Membership # now, how to deal with shipping rules then? ProcessPaidOrder.new(payment).call class ProcessPaidOrder attr_reader :payment def initialize(payment) @@ -130,7 +130,7 @@ def call def item_processor_for(item) case item.product.type when :physical then PhysicalProductProcessor.new(item, shipping_label_printer_class: ShippingLabelPrinter) when :book then BookProductProcessor.new(item, shipping_label_printer_class: BookShippingLabelPrinter) when :membership then MembershipProductProcessor.new(item) when :digital then DigitalProductProcessor.new(item) -
gmmoreira created this gist
Mar 1, 2019 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,278 @@ class Payment attr_reader :authorization_number, :amount, :invoice, :order, :payment_method, :paid_at def initialize(attributes = {}) @authorization_number, @amount = attributes.values_at(:authorization_number, :amount) @invoice, @order = attributes.values_at(:invoice, :order) @payment_method = attributes.values_at(:payment_method) end def pay(paid_at = Time.now) @amount = order.total_amount @authorization_number = Time.now.to_i @invoice = Invoice.new(billing_address: order.address, shipping_address: order.address, order: order) @paid_at = paid_at order.close(@paid_at) end def paid? !paid_at.nil? end end class Invoice attr_reader :billing_address, :shipping_address, :order def initialize(attributes = {}) @billing_address = attributes.values_at(:billing_address) @shipping_address = attributes.values_at(:shipping_address) @order = attributes.values_at(:order) end end class Order attr_reader :customer, :items, :address, :closed_at attr_accessor :payment def initialize(customer, overrides = {}) @customer = customer @items = [] @order_item_class = overrides.fetch(:item_class) { OrderItem } @address = overrides.fetch(:address) { Address.new(zipcode: '45678-979') } end def add_product(product) @items << @order_item_class.new(order: self, product: product) end def total_amount @items.map(&:total).inject(:+) end def close(closed_at = Time.now) @closed_at = closed_at end end class OrderItem attr_reader :order, :product def initialize(order:, product:) @order = order @product = product end def total 10 end end class Product # use type to distinguish each kind of product: physical, book, digital, membership, etc. attr_reader :name, :type def initialize(name:, type:) @name, @type = name, type end end class Address attr_reader :zipcode def initialize(zipcode:) @zipcode = zipcode end end class CreditCard def self.fetch_by_hashed(code) CreditCard.new end end class Customer # you can customize this class by yourself end class Membership # you can customize this class by yourself end # Book Example (build new payments if you need to properly test it) foolano = Customer.new book = Product.new(name: 'Awesome book', type: :book) book_order = Order.new(foolano) book_order.add_product(book) payment_book = Payment.new(order: book_order, payment_method: CreditCard.fetch_by_hashed('43567890-987654367')) order.payment = payment_book payment_book.pay p payment_book.paid? # < true p payment_book.order.items.first.product.type # now, how to deal with shipping rules then? ProcessPaidOrder.new(payment).call class ProcessPaidorder attr_reader :payment def initialize(payment) @payment = payment end def call payment.order.items.each do |item| item_processor_for(item.product).call end end private def item_processor_for(item) case item.product.type when :physical then PhysicalProductProcessor.new(itemm shipping_label_printer_class: ShippingLabelPrinter) when :book then BookProductProcessor.new(item, shipping_label_printer_class: BookShippingLabelPrinter) when :membership then MembershipProductProcessor.new(item) when :digital then DigitalProductProcessor.new(item) else raise ArgumentError, "Unsupported type #{item.product.type}" end end end class PhysicalProductProcessor attr_reader :order_item def initialize(order_item, shipping_label_printer_class: ShippingLabelPrinter) @order_item end def call puts shipping_label_printer.call end def shipping_label_printer shipping_label_printer_class.new(order_item) end end class ShippingLabelPrinter attr_reader :order_item def initialize(order_item) @order_item end def call "Envio do produto #{product.name}\n" + "Endereço: #{order_item.order.address}" end end class BookShippingLabelPrinter < ShippingLabelPrinter def call "#{super}\n" + "Produto isento de imposto conforme disposto na Constituição Art 150, Vl, d." end end class MembershipProductProcessor attr_reader :order_item def initialize(order_item) @order_item end def call membership_activator.call email_sender.call end private def membership_activator MembershipActivator.new(order_item).call end def email_sender MembershipEmailSender.new(order_item).call end end class MembershipActivator attr_reader :order_item def initialize(order_item) @order_item end def call puts "Ativando a assinatura de #{order_item.product.name}..." end end class MembershipEmailSender attr_reader :order_item def initialize(order_item) @order_item end def call puts "Sua assinatura de #{order_item.product.name} foi ativada com sucesso!" end end class DigitalProductProcessor attr_reader :order_item def initialize(order_item) @order_item end def call email_sender.call voucher_creator.call end def email_sender DigitalEmailSender.new(order_item).call end def voucher_creator VoucherCreator.new(amount: BigDecimal(10), customer: order_item.order.customer) end end class DigitalEmailSender attr_reader :order_item def initialize(order_item) @order_item end def call puts "Parabéns, você adquiriu um #{order_item.product.name}!" end end class VoucherCreator attr_reader :amount, :customer def initialize(amount:, customer:) @amount = amount @customer = customer end def call customer.vouchers << Voucher.new(amount) end end class Voucher attr_reader :amount def initialize(amount) @amount = amount end end