diff --git a/_includes/donacion.html b/_includes/donacion.html new file mode 100644 index 0000000..5164821 --- /dev/null +++ b/_includes/donacion.html @@ -0,0 +1,125 @@ +{% comment %} +Traer la donación pasada como parámetro o la que se haya establecido por +defecto para el layout correspondiente. + +product = producto +page = post que incluye esta donación +icon = ícono del botón +class = clases extra para el botón +boton = texto opcional para el botón +{% endcomment %} +{%- assign product = include.product | default: include.page -%} +{%- assign donacion = include.page.donacion | default: product.donacion -%} + + + + +
+ + + + +
+
+
+ {{ donacion.content | markdownify }} +
+ +
+ {% if include.page.image.path %} + + + + + {% else %} + {% include_cached logo_horizontal.svg %} + {% endif %} +
+ +
+

{{ site.i18n.donacion.monto }}

+ + + +
+ +
+
+
+ + +
+ +
+ + +
+ +
+ {% comment %} + Este input invisible es para que Bootstrap pueda mostrar el + error si querés mandar el formulario sin elegir una moneda. + {% endcomment %} + +
+ {{ site.i18n.donacion.currency }} +
+ +

+
+
+
+ +
+ + + {% if include.page.pdf.path %} + + {% endif %} +
+ +
+ +
+ {{ site.i18n.donacion.medios | markdownify | replace: '

', '

' | replace: '

', '

' }} +
+
+
+
diff --git a/_includes/pay_what_you_can_controller.html b/_includes/pay_what_you_can_controller.html new file mode 100644 index 0000000..eabed0f --- /dev/null +++ b/_includes/pay_what_you_can_controller.html @@ -0,0 +1,13 @@ +data-controller="pay-what-you-can" +data-pay-what-you-can-download-value="{{ include.product.url | present }}" +data-pay-what-you-can-url-value="{{ include.url | default: include.product.url }}" +data-pay-what-you-can-variant-id-value="{{ include.product.variant_id }}" +data-pay-what-you-can-firstname-value="{{ include.product.title }}" +data-pay-what-you-can-currency-value="ARS" +data-pay-what-you-can-price-value="1" +data-image="{{ include.product.image.path | thumbnail: 300 }}" +data-title="{{ include.product.title }}" +data-price="{{ include.product.price }}" +data-in-stock="{{ include.product.in_stock }}" +data-stock="{{ include.product.stock }}" +data-extra="{{ include.extra | join: '|' }}" diff --git a/_packs/controllers/pay_what_you_can_controller.js b/_packs/controllers/pay_what_you_can_controller.js new file mode 100644 index 0000000..9602774 --- /dev/null +++ b/_packs/controllers/pay_what_you_can_controller.js @@ -0,0 +1,206 @@ +import { CartBaseController } from './cart_base_controller' + +/* + * Al pagar lo que podamos, primero hay que crear una orden y luego + * contactarse con la APIv2 para generar la variante con el precio que + * queramos agregar. Agregamos la variante al carrito y lanzamos el + * proceso de pago. + */ +export default class extends CartBaseController { + static targets = [ 'form' ] + static values = { + variantId: Number, + currency: String, + price: Number, + firstname: String + } + + connect () { + this.paymentMethodByCurrency = { + ARS: 'Spree::PaymentMethod::MercadoPago', + USD: 'Spree::PaymentMethod::Paypal' + } + } + + store (event) { + const target = event.currentTarget || event.target + + this[`${target.dataset.name}Value`] = target.value + } + + set formDisable (disable) { + this.formTarget.elements.forEach(x => x.disabled = disable) + } + + /* + * Realiza todos los pasos: + * + * * Crear pedido + * * Crear variante con el monto y moneda + * * Agregar al pedido + * * Agregar dirección al pedido + * * Obtener métodos de envío + * * Obtener métodos de pago + * * Pagar + * * Reenviar a confirmación + * * Ejecutar el pago (si aplica) + */ + async pay (event = undefined) { + if (event) { + event.preventDefault() + event.stopPropagation() + } + + if (!this.formTarget.checkValidity()) { + this.formTarget.classList.add('was-validated') + return + } + + this.formDisable = true + + // Crear pedido. Todos los pedidos van a ser hechos desde + // Argentina, no hay forma de cambiar esto. + const orderToken = await this.tempCartCreate() + const quantity = 1 + const include = 'line_items' + const currency = this.currencyValue + const price = this.priceValue + const email = 'noreply@sutty.nl' + const firstname = this.firstnameValue + const lastname = '-' + const address1 = '-' + const country_id = 250 // XXX: Internet + const city = '-' + const phone = '11111111' + const zipcode = '1111' + const ship_address_attributes = { firstname, lastname, address1, city, country_id, zipcode, phone } + const bill_address_attributes = ship_address_attributes + const confirmation_delivered = true + const custom_return_url = this.customReturnUrl() + + let variant_id = this.variantIdValue + + // Crear la variante + const payWhatYouCanResponse = await this.spree.sutty.payWhatYouCan({ orderToken }, { variant_id, price, currency, quantity }) + + variant_id = payWhatYouCanResponse.data.id + + if (!variant_id) { + this.formDisable = false + console.error('No se pudo generar la variante', { variant_id, price, currency, quantity }) + return + } + + // Configurar la moneda del pedido + let response = await this.spree.sutty.updateOrder({ orderToken }, { currency, confirmation_delivered, custom_return_url }) + + if (response.status > 299) { + console.error(response) + this.formDisable = false + return + } + + // Agregar al carrito + response = await this.spree.cart.addItem({ orderToken }, { variant_id, quantity, include }) + + if (response.isFail()) { + this.handleFailure(response) + this.formDisable = false + return + } + + // Actualizar la dirección + response = await this.spree.checkout.orderUpdate({ orderToken }, { order: { email, ship_address_attributes, bill_address_attributes }}) + + if (response.isFail()) { + this.handleFailure(response) + this.formDisable = false + return + } + + // Obtener los medios de envío + response = await this.spree.checkout.shippingMethods({ orderToken }, { include: 'shipping_rates' }) + + if (response.isFail()) { + this.handleFailure(response) + this.formDisable = false + return + } + + // Elegir medio de envío + response = await this.spree.checkout.orderUpdate({ orderToken }, { + order: { + shipments_attributes: [{ + id: response.success().data[0].id, + selected_shipping_rate_id: response.success().included.filter(x => x.type == 'shipping_rate')[0].id + }] + } + }) + + // Elegir medio de pago + response = await this.spree.checkout.paymentMethods({ orderToken }) + + if (response.isFail()) { + this.handleFailure(response) + this.formDisable = false + return + } + + const payment_method_id = response.success().data.find(x => this.paymentMethodByCurrency[this.currencyValue] == x.attributes.type).id + + response = await this.spree.checkout.orderUpdate({ orderToken }, + { + order: { payments_attributes: [{ payment_method_id }] }, + payment_source: { + [payment_method_id]: { + name: 'Pepitx', + month: 12, + year: 2021 + } + } + }) + + if (response.isFail()) { + this.handleFailure(response) + this.formDisable = false + return + } + + response = await this.spree.checkout.complete({ orderToken }) + + if (response.isFail()) { + this.handleFailure(response) + this.formDisable = false + return + } + + // Reenviar al medio de pago + const checkoutUrls = await this.spree.sutty.getCheckoutURL({ orderToken }) + const redirectUrl = checkoutUrls.data[0] + + Turbolinks.visit(redirectUrl) + + // Volver + } + + async tempCartCreate () { + const response = await this.spree.cart.create() + + // If we fail here it's probably a server error, so we inform the + // user. + if (response.isFail()) { + this.handleFailure(response) + return + } + + return response.success().data.attributes.token + } + + // @return [String] + customReturnUrl () { + const url = new URL(window.location.href) + url.searchParams.set('open', '') + + return url.toString() + } +}