spree_pluggto 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/spree/admin/pluggto_fields_controller.rb +27 -0
- data/app/controllers/spree/admin/pluggto_settings_controller.rb +2 -1
- data/app/controllers/spree/api/v1/pluggto_controller.rb +30 -0
- data/app/jobs/spree_pluggto/order_created_job.rb +23 -0
- data/app/jobs/spree_pluggto/order_updated_job.rb +7 -0
- data/app/jobs/spree_pluggto/product_updated_job.rb +7 -0
- data/app/jobs/spree_pluggto/sku_deleted_job.rb +7 -0
- data/app/jobs/spree_pluggto/update_pluggto_order_job.rb +8 -0
- data/app/jobs/spree_pluggto/upsert_all_products_job.rb +1 -1
- data/app/jobs/spree_pluggto/upsert_product_job.rb +3 -3
- data/app/models/spree_pluggto/spree/product_decorator.rb +6 -3
- data/app/models/spree_pluggto/spree/shipment_decorator.rb +24 -0
- data/app/overrides/add_pluggto_id_to_order_summary.rb +14 -0
- data/app/overrides/add_pluggto_tab_to_order_sidebar.rb +11 -0
- data/app/services/spree_pluggto/{oauth.rb → api/oauth.rb} +1 -1
- data/app/services/spree_pluggto/api/order.rb +112 -0
- data/app/services/spree_pluggto/{product.rb → api/product.rb} +20 -16
- data/app/services/spree_pluggto/{request.rb → api/request.rb} +2 -2
- data/app/services/spree_pluggto/create_spree_order.rb +122 -0
- data/app/services/spree_pluggto/delete_spree_product_reference.rb +15 -0
- data/app/services/spree_pluggto/send_integration_errors.rb +24 -0
- data/app/services/spree_pluggto/update_spree_order.rb +50 -0
- data/app/services/spree_pluggto/update_spree_product.rb +17 -0
- data/app/views/spree/admin/pluggto_fields/index.html.erb +33 -0
- data/config/locales/pt-BR.yml +1 -0
- data/config/routes.rb +13 -0
- data/db/migrate/20210713194303_add_pluggto_id_to_spree_products.rb +5 -0
- data/db/migrate/20210805194730_add_pluggto_name_to_spree_products.rb +5 -0
- data/db/migrate/20210812182652_add_pluggto_id_to_spree_shipments.rb +5 -0
- data/db/migrate/20210812190431_add_sync_with_pluggto_to_products.rb +5 -0
- data/lib/spree_pluggto/version.rb +2 -2
- metadata +26 -6
- data/app/services/spree_pluggto/api.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fe48703fbef832cd6c4fcf7336be85d018b872b44e6f299575ae2a24d04ee92
|
4
|
+
data.tar.gz: bc238a43d02ead868d093f66acec13b970f246cf04a24c66d4566382cd6abf6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c1838f27d41d18720aec4a75c0de557f864f354bc87e16ee484d2e6627b34d61114ebafb11407b9f8ac42741499d3de33c5aa558a6e4220ae5639d753e50ecb
|
7
|
+
data.tar.gz: d831df2e340db48a77c3b3660bdc92449c87ee88ebadc2df4fdbb311943fb0d26fd0b80344280c76d63f1f43d60d112f1bf512de2f1545b6e368a830a8db0940
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Spree
|
2
|
+
module Admin
|
3
|
+
class PluggtoFieldsController < ResourceController
|
4
|
+
before_action :load_product
|
5
|
+
|
6
|
+
def index
|
7
|
+
end
|
8
|
+
|
9
|
+
def update
|
10
|
+
end
|
11
|
+
|
12
|
+
def location_after_save
|
13
|
+
admin_product_pluggto_fields_url(@product)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def load_product
|
19
|
+
@product = Spree::Product.friendly.find(params[:product_id])
|
20
|
+
end
|
21
|
+
|
22
|
+
def model_class
|
23
|
+
@model_class ||= Spree::Product
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -12,12 +12,13 @@ module Spree
|
|
12
12
|
|
13
13
|
def update
|
14
14
|
@pluggto_settings.update(pluggto_settings_params)
|
15
|
+
flash[:success] = Spree.t(:pluggto_settings_updated)
|
15
16
|
redirect_to edit_admin_pluggto_settings_path
|
16
17
|
end
|
17
18
|
|
18
19
|
def upload_all_products
|
19
|
-
flash[:success] = Spree.t(:pluggto_products_being_uploaded)
|
20
20
|
::SpreePluggto::UpsertAllProductsJob.perform_later
|
21
|
+
flash[:success] = Spree.t(:pluggto_products_being_uploaded)
|
21
22
|
redirect_to edit_admin_pluggto_settings_path
|
22
23
|
end
|
23
24
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
class PluggtoController < Spree::Api::BaseController
|
5
|
+
skip_before_action :authenticate_user
|
6
|
+
|
7
|
+
# The post will be send in the following format:
|
8
|
+
# {"type":"PRODUCTS/SKUS/ORDERS","id":"PLUGGTO_ID","action":"UPDATEORCREATE","user":1120, "changes" : {"status" : false,"stock" : false,"price":false }}
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
# { "user" : 129, "id" : "5b9169c309eacd415056aa3a", "changes" : { "status" : false, "stock" : false, "price" : false }, "type" : "products", "action" : "updated" }
|
12
|
+
|
13
|
+
def notifications
|
14
|
+
puts "Notification received from PluggTo: #{notification_params}"
|
15
|
+
service_class = "spree_pluggto/#{notification_params[:type].singularize}_#{notification_params[:action]}_job".camelize
|
16
|
+
puts "Service: #{service_class}"
|
17
|
+
service_class.constantize.perform_later(notification_params[:id])
|
18
|
+
head :ok
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def notification_params
|
24
|
+
params.require(:pluggto).permit!
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SpreePluggto
|
2
|
+
class OrderCreatedJob < ActiveJob::Base
|
3
|
+
|
4
|
+
|
5
|
+
# sidekiq_retries_exhausted do |msg, ex|
|
6
|
+
# message = "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
|
7
|
+
# ::SpreePluggto::SendIntegrationErrors.new(msg['args']).call(message)
|
8
|
+
# end
|
9
|
+
# https://edgeguides.rubyonrails.org/active_job_basics.html#exceptions
|
10
|
+
# https://stackoverflow.com/questions/32193144/in-activejob-how-to-catch-any-exception
|
11
|
+
# https://github.com/mperham/sidekiq/issues/4496#issuecomment-600714253
|
12
|
+
# https://stackoverflow.com/questions/29085458/how-to-access-perform-parameters-in-activejob-rescue
|
13
|
+
rescue_from(StandardError) do |exception|
|
14
|
+
puts "--- Problem creating plugg_to order #{arguments} ---"
|
15
|
+
puts exception
|
16
|
+
::SpreePluggto::SendIntegrationErrors.new(arguments.first).call(exception)
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform(pluggto_id)
|
20
|
+
::SpreePluggto::CreateSpreeOrder.new(pluggto_id).call
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module SpreePluggto
|
2
|
-
class UpsertProductJob <
|
2
|
+
class UpsertProductJob < ActiveJob::Base
|
3
3
|
# UPSERT => Updates the record if it exists, inserts if it is new
|
4
4
|
def perform(product_id)
|
5
|
-
product = Spree::Product.find
|
6
|
-
SpreePluggto::Product.upsert(product)
|
5
|
+
product = ::Spree::Product.find(product_id)
|
6
|
+
::SpreePluggto::Api::Product.upsert(product)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -1,15 +1,18 @@
|
|
1
1
|
module SpreePluggto
|
2
2
|
module Spree
|
3
3
|
module ProductDecorator
|
4
|
+
|
5
|
+
# https://guides.spreecommerce.org/developer/customization/logic.html
|
6
|
+
# self.prepended is needed to access class-level methods, like has_many, scopes and callbacks
|
4
7
|
def self.prepended(base)
|
5
|
-
base.after_create :upsert_pluggto_product
|
6
|
-
base.after_update :upsert_pluggto_product
|
8
|
+
base.after_create :upsert_pluggto_product, if: :sync_with_pluggto?
|
9
|
+
base.after_update :upsert_pluggto_product, if: :sync_with_pluggto?
|
7
10
|
end
|
8
11
|
|
9
12
|
private
|
10
13
|
|
11
14
|
def upsert_pluggto_product
|
12
|
-
::SpreePluggto::UpsertProductJob.perform_later(
|
15
|
+
::SpreePluggto::UpsertProductJob.perform_later(self.id)
|
13
16
|
end
|
14
17
|
|
15
18
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SpreePluggto
|
2
|
+
module Spree
|
3
|
+
module ShipmentDecorator
|
4
|
+
|
5
|
+
# https://guides.spreecommerce.org/developer/customization/logic.html
|
6
|
+
# self.prepended is needed to access class-level methods, like has_many, scopes and callbacks
|
7
|
+
def self.prepended(base)
|
8
|
+
base.state_machine.after_transition to: :shipped, do: :update_pluggto_order, if: :pluggto_order?
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def update_pluggto_order
|
14
|
+
::SpreePluggto::UpdatePluggtoOrderJob.perform_later(order.number)
|
15
|
+
end
|
16
|
+
|
17
|
+
def pluggto_order?
|
18
|
+
order.channel == "pluggto"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Spree::Shipment.prepend(SpreePluggto::Spree::ShipmentDecorator)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Deface::Override.new(
|
2
|
+
virtual_path: 'spree/admin/shared/_order_summary',
|
3
|
+
name: 'add_pluggto_id_to_order_summary',
|
4
|
+
insert_bottom: '[id="order_tab_summary"]'
|
5
|
+
) do
|
6
|
+
<<-HTML
|
7
|
+
<% if @order.pluggto_id %>
|
8
|
+
<tr>
|
9
|
+
<td><strong>Plugg.to id</strong></td>
|
10
|
+
<td><%= @order.pluggto_id %></td>
|
11
|
+
</tr>
|
12
|
+
<% end %>
|
13
|
+
HTML
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Deface::Override.new(
|
2
|
+
virtual_path: 'spree/admin/shared/_product_tabs',
|
3
|
+
name: 'add_pluggto_tab_to_order_sidebar',
|
4
|
+
insert_bottom: '[data-hook="admin_product_tabs"]'
|
5
|
+
) do
|
6
|
+
<<-HTML
|
7
|
+
<%= content_tag :li, class: ('active' if current == :pluggto_fields) do %>
|
8
|
+
<%= link_to_with_icon "transfer", "Plugg.to", spree.admin_product_pluggto_fields_url(@product) %>
|
9
|
+
<% end %>
|
10
|
+
HTML
|
11
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module SpreePluggto::Api
|
2
|
+
class Order
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def find(pluggto_id)
|
6
|
+
response = ::SpreePluggto::Api::Request.new.get("/orders/#{pluggto_id}")
|
7
|
+
response["Order"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def update(spree_order)
|
11
|
+
response = ::SpreePluggto::Api::Request.new.put("/orders/#{spree_order.pluggto_id}", params(spree_order).to_json)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def pluggto_status(spree_order)
|
17
|
+
return 'canceled' if spree_order.canceled?
|
18
|
+
return 'shipping_informed' if spree_order.shipped?
|
19
|
+
return 'approved' if spree_order.shipment_state == 'ready'
|
20
|
+
return 'partial_payment' if spree_order.payment_state == 'credit_owed'
|
21
|
+
return 'pending'
|
22
|
+
end
|
23
|
+
|
24
|
+
def phone_area(number)
|
25
|
+
ddd_regex = /\((?<DDD>\d\d)\)/
|
26
|
+
ddd_regex.match(number)["DDD"]
|
27
|
+
end
|
28
|
+
|
29
|
+
def phone_without_area(number)
|
30
|
+
number.sub(/\(..\)/, '').strip
|
31
|
+
end
|
32
|
+
|
33
|
+
def params(spree_order)
|
34
|
+
{
|
35
|
+
"status": pluggto_status(spree_order),
|
36
|
+
"subtotal": spree_order.amount,
|
37
|
+
"total": spree_order.total,
|
38
|
+
"total_paid": spree_order.payment_total.to_s,
|
39
|
+
"shipping": spree_order.shipment_total,
|
40
|
+
"discount": spree_order.adjustment_total,
|
41
|
+
"external": spree_order.number,
|
42
|
+
|
43
|
+
"receiver_email": spree_order.email,
|
44
|
+
"receiver_name": spree_order.ship_address.firstname,
|
45
|
+
"receiver_lastname": spree_order.ship_address.lastname,
|
46
|
+
"receiver_address": spree_order.ship_address.address1,
|
47
|
+
"receiver_address_number": spree_order.ship_address.street_number,
|
48
|
+
"receiver_address_complement": spree_order.ship_address.address2,
|
49
|
+
"receiver_city": spree_order.ship_address.city,
|
50
|
+
"receiver_neighborhood": spree_order.ship_address.neighborhood,
|
51
|
+
"receiver_state": spree_order.ship_address.state.abbr,
|
52
|
+
"receiver_zipcode": spree_order.ship_address.zipcode,
|
53
|
+
"receiver_phone": phone_without_area(spree_order.ship_address.phone),
|
54
|
+
"receiver_phone_area": phone_area(spree_order.ship_address.phone),
|
55
|
+
|
56
|
+
"payer_email": spree_order.email,
|
57
|
+
"payer_name": spree_order.bill_address.firstname,
|
58
|
+
"payer_lastname": spree_order.bill_address.lastname,
|
59
|
+
"payer_address": spree_order.bill_address.address1,
|
60
|
+
"payer_address_number": spree_order.bill_address.street_number,
|
61
|
+
"payer_address_complement": spree_order.bill_address.address2,
|
62
|
+
"payer_city": spree_order.bill_address.city,
|
63
|
+
"payer_neighborhood": spree_order.bill_address.neighborhood,
|
64
|
+
"payer_state": spree_order.bill_address.state.abbr,
|
65
|
+
"payer_zipcode": spree_order.bill_address.zipcode,
|
66
|
+
"payer_phone": phone_without_area(spree_order.bill_address.phone),
|
67
|
+
"payer_phone_area": phone_area(spree_order.bill_address.phone),
|
68
|
+
"payer_cpf": spree_order.cpf,
|
69
|
+
|
70
|
+
"shipments": spree_order.shipments.map { |shipment|
|
71
|
+
{
|
72
|
+
"id": shipment.pluggto_id,
|
73
|
+
"estimate_delivery_date": (shipment.expected_delivery_date if shipment.shipped?),
|
74
|
+
"nfe_date": (shipment.shipped_at.to_date if shipment.shipped?),
|
75
|
+
"nfe_key": (shipment.get_invoice_key if shipment.shipped?),
|
76
|
+
"track_url": (shipment.tracking_url_with_code if shipment.shipped?),
|
77
|
+
"nfe_link": (shipment.get_invoice_pdf if shipment.shipped?),
|
78
|
+
"external": shipment.number,
|
79
|
+
"shipping_company": shipment.shipping_method.name,
|
80
|
+
"shipping_method": shipment.shipping_method.name,
|
81
|
+
"track_code": shipment.tracking,
|
82
|
+
"date_shipped": shipment.shipped_at&.to_date,
|
83
|
+
"nfe_number": shipment.nf_number&.split("/")&.first,
|
84
|
+
"nfe_serie": shipment.nf_number&.split("/")&.last,
|
85
|
+
"shipping_items": shipment.line_items.map { |line_item|
|
86
|
+
{
|
87
|
+
"sku": line_item.sku,
|
88
|
+
"quantity": line_item.quantity
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
},
|
93
|
+
|
94
|
+
"items": spree_order.line_items.map { |line_item|
|
95
|
+
{
|
96
|
+
"quantity": line_item.quantity,
|
97
|
+
"sku": line_item.sku,
|
98
|
+
"price": line_item.price,
|
99
|
+
"total": line_item.total,
|
100
|
+
"name": line_item.name,
|
101
|
+
"variation": {
|
102
|
+
"sku": line_item.sku
|
103
|
+
},
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
}.compact
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -1,31 +1,34 @@
|
|
1
|
-
module SpreePluggto
|
1
|
+
module SpreePluggto::Api
|
2
2
|
class Product
|
3
3
|
class << self
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
def find(pluggto_id)
|
6
|
+
response = ::SpreePluggto::Api::Request.new.get("/products/#{pluggto_id}")
|
7
|
+
response["Product"]
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
# UPSERT => Updates the record if it exists, inserts if it is a new record
|
11
|
+
def upsert(spree_product)
|
12
|
+
response = ::SpreePluggto::Api::Request.new.put("/skus/#{spree_product.sku}", params(spree_product).to_json)
|
13
|
+
spree_product.update_columns(pluggto_id: response.dig("Product","id"))
|
12
14
|
end
|
13
|
-
|
15
|
+
|
14
16
|
private
|
15
17
|
|
16
18
|
def params(product)
|
19
|
+
description = ::ActionView::Helpers::TextHelper.simple_format(product.description) + "<br/><u>MAIS INFORMAÇÕES:</u><br/>".html_safe + product.info.html_safe
|
17
20
|
{
|
18
21
|
"sku": product.sku,
|
19
|
-
"name": product.name,
|
20
|
-
"special_price": product.on_sale? ? product.sale_price :
|
22
|
+
"name": product.pluggto_name.present? ? product.pluggto_name : product.name,
|
23
|
+
"special_price": product.on_sale? ? product.sale_price : product.price,
|
21
24
|
"price": product.price,
|
22
|
-
"description":
|
23
|
-
"brand":
|
25
|
+
"description": description,
|
26
|
+
"brand": "Nordweg",
|
24
27
|
"warranty_time": product.try(:months_of_warranty),
|
25
28
|
"warranty_message": product.lifetime_warranty? ? "Garantia vitalícia" : "",
|
26
29
|
"link": "#{::Rails.application.routes.url_helpers.spree_url}products/#{product.slug}",
|
27
30
|
"categories": product.taxons.map { |taxon| {"name": taxon.name } },
|
28
|
-
"handling_time": Spree::Config.try(:handling_time),
|
31
|
+
"handling_time": ::Spree::Config.try(:handling_time),
|
29
32
|
"ean_not_mandatory": true,
|
30
33
|
"dimension": {
|
31
34
|
"length": product.depth,
|
@@ -36,8 +39,8 @@ module SpreePluggto
|
|
36
39
|
"photos": product.images.map { |image|
|
37
40
|
{
|
38
41
|
"url": image.attachment.url(:big),
|
39
|
-
"name": name,
|
40
|
-
"title": name,
|
42
|
+
"name": product.name,
|
43
|
+
"title": product.name,
|
41
44
|
"order": image.position,
|
42
45
|
"external": image.attachment.url(:big)
|
43
46
|
}
|
@@ -47,8 +50,9 @@ module SpreePluggto
|
|
47
50
|
"sku": variant.sku,
|
48
51
|
"name": variant.name,
|
49
52
|
"quantity": variant.total_on_hand.finite? ? variant.total_on_hand : 99,
|
50
|
-
"special_price": variant.product.on_sale? ? variant.product.sale_price :
|
53
|
+
"special_price": variant.product.on_sale? ? variant.product.sale_price : variant.price,
|
51
54
|
"price": variant.price,
|
55
|
+
"ean_not_mandatory": true,
|
52
56
|
"attributes": variant.option_values.map { |option_value|
|
53
57
|
{
|
54
58
|
"code": option_value.option_type.name,
|
@@ -56,7 +60,7 @@ module SpreePluggto
|
|
56
60
|
"value": { "code": option_value.name, "label": option_value.name }
|
57
61
|
}
|
58
62
|
},
|
59
|
-
"photos":
|
63
|
+
"photos": variant.images.map { |image|
|
60
64
|
{
|
61
65
|
"url": image.attachment.url(:big),
|
62
66
|
"name": variant.name,
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# Creates on Spree e new order after it was created on Pluggto
|
2
|
+
module SpreePluggto
|
3
|
+
class CreateSpreeOrder
|
4
|
+
attr_reader :pluggto_id
|
5
|
+
|
6
|
+
def initialize(pluggto_id)
|
7
|
+
@pluggto_id = pluggto_id
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
# Skip creation if the order was already created on Spree
|
12
|
+
return if ::Spree::Order.find_by(pluggto_id: pluggto_id)
|
13
|
+
|
14
|
+
# Get info Plugg
|
15
|
+
pluggto_order = ::SpreePluggto::Api::Order.find(pluggto_id)
|
16
|
+
|
17
|
+
# Create the order on Spree
|
18
|
+
spree_order = ::Spree::Order.create(
|
19
|
+
channel: "pluggto",
|
20
|
+
pluggto_id: pluggto_order["id"],
|
21
|
+
user: ::Spree::User.find_by(email: pluggto_order["receiver_email"]),
|
22
|
+
email: pluggto_order["receiver_email"],
|
23
|
+
cpf: pluggto_order["receiver_cpf"] || pluggto_order["payer_cpf"],
|
24
|
+
)
|
25
|
+
|
26
|
+
# Add line items
|
27
|
+
pluggto_order["items"].each do |pluggto_item|
|
28
|
+
spree_order.line_items.new(
|
29
|
+
variant: ::Spree::Variant.find_by!(sku: pluggto_item["sku"]),
|
30
|
+
quantity: pluggto_item["quantity"],
|
31
|
+
price: pluggto_item["price"]
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Go to Addres
|
36
|
+
spree_order.next
|
37
|
+
|
38
|
+
# Add ship_address
|
39
|
+
spree_order.ship_address = ::Spree::Address.new(
|
40
|
+
firstname: pluggto_order["receiver_name"],
|
41
|
+
lastname: pluggto_order["receiver_lastname"],
|
42
|
+
address1: pluggto_order["receiver_address"],
|
43
|
+
address2: "#{pluggto_order["receiver_address_complement"]} - #{pluggto_order["receiver_address_reference"]}",
|
44
|
+
neighborhood: pluggto_order["receiver_neighborhood"],
|
45
|
+
street_number: pluggto_order["receiver_address_number"],
|
46
|
+
city: pluggto_order["receiver_city"],
|
47
|
+
zipcode: pluggto_order["receiver_zipcode"],
|
48
|
+
phone: "(#{pluggto_order['receiver_phone_area']}) #{pluggto_order['receiver_phone']}",
|
49
|
+
state_name: pluggto_order["receiver_state"],
|
50
|
+
state: ::Spree::State.find_by(abbr: pluggto_order["receiver_state"]),
|
51
|
+
alternative_phone: "(#{pluggto_order['receiver_phone2_area']}) #{pluggto_order['receiver_phone2']}",
|
52
|
+
country: ::Spree::Country.find_by(iso: "BR")
|
53
|
+
)
|
54
|
+
|
55
|
+
# Add bill_address
|
56
|
+
spree_order.bill_address = ::Spree::Address.new(
|
57
|
+
firstname: pluggto_order["payer_name"],
|
58
|
+
lastname: pluggto_order["payer_lastname"],
|
59
|
+
address1: pluggto_order["payer_address"],
|
60
|
+
address2: "#{pluggto_order["payer_address_complement"]} - #{pluggto_order["payer_address_reference"]}",
|
61
|
+
neighborhood: pluggto_order["payer_neighborhood"],
|
62
|
+
street_number: pluggto_order["payer_address_number"],
|
63
|
+
city: pluggto_order["payer_city"],
|
64
|
+
zipcode: pluggto_order["payer_zipcode"],
|
65
|
+
phone: "(#{pluggto_order['payer_phone_area']}) #{pluggto_order['payer_phone']}",
|
66
|
+
state_name: pluggto_order["payer_state"],
|
67
|
+
state: ::Spree::State.find_by(abbr: pluggto_order["payer_state"]),
|
68
|
+
alternative_phone: "(#{pluggto_order['payer_phone2_area']}) #{pluggto_order['payer_phone2']}",
|
69
|
+
country: ::Spree::Country.find_by(iso: "BR")
|
70
|
+
)
|
71
|
+
|
72
|
+
# Go to delivery
|
73
|
+
spree_order.next!
|
74
|
+
|
75
|
+
# Go to payment
|
76
|
+
spree_order.next!
|
77
|
+
|
78
|
+
# By calling 'next' the first shipping option was selected,
|
79
|
+
# we need to set it up according to what we received from Pluggto
|
80
|
+
spree_order.shipments.first.update_columns(
|
81
|
+
cost: pluggto_order["shipping"],
|
82
|
+
pluggto_id: pluggto_order.dig("shipments",0,"id")
|
83
|
+
)
|
84
|
+
spree_order.update_columns(
|
85
|
+
shipment_total: pluggto_order["shipping"]
|
86
|
+
)
|
87
|
+
|
88
|
+
# Add discounts
|
89
|
+
if pluggto_order["discount"].present? && pluggto_order["discount"] > 0
|
90
|
+
spree_order.adjustments.create(
|
91
|
+
order: spree_order,
|
92
|
+
label: "Desconto via Plugg.to",
|
93
|
+
amount: pluggto_order["discount"] * -1,
|
94
|
+
eligible: true
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Update the total after discounts
|
99
|
+
spree_order.update_totals
|
100
|
+
|
101
|
+
# Add payments
|
102
|
+
pluggto_order["payments"].each do |pluggto_payment|
|
103
|
+
spree_order.payments.create(
|
104
|
+
payment_method: ::Spree::PaymentMethod.find_by(type:"Spree::PaymentMethod::StoreCredit"), # Not ideal - we should define a specific payment method referring to PluggTo
|
105
|
+
installments: pluggto_payment["payment_installments"],
|
106
|
+
amount: pluggto_payment["payment_total"],
|
107
|
+
state: "completed"
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Completes the order
|
112
|
+
# The "Pending" on Pluggto is NOT "Paid", even if it has payments
|
113
|
+
# We should force the payments status according to the plugg_order status
|
114
|
+
spree_order.update_columns(
|
115
|
+
state: 'complete',
|
116
|
+
completed_at: DateTime.now,
|
117
|
+
payment_state: pluggto_order["status"] == 'approved' ? 'paid' : 'balance_due'
|
118
|
+
)
|
119
|
+
spree_order.fulfill! if spree_order.paid?
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# When a product is deleted on Plugg, we remove the pluggto_id reference on Spree
|
2
|
+
module SpreePluggto
|
3
|
+
class DeleteSpreeProductReference
|
4
|
+
attr_accessor :spree_product
|
5
|
+
|
6
|
+
def initialize(sku)
|
7
|
+
variant = ::Spree::Variant.find_by!(sku: sku)
|
8
|
+
@spree_product = variant.product
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
spree_product.update_columns(pluggto_id: nil)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SpreePluggto
|
2
|
+
class SendIntegrationErrors
|
3
|
+
attr_reader :pluggto_id
|
4
|
+
|
5
|
+
def initialize(pluggto_id)
|
6
|
+
@pluggto_id = pluggto_id
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(error)
|
10
|
+
::SpreePluggto::Api::Request.new.put("/orders/#{pluggto_id}", params(error).to_json)
|
11
|
+
end
|
12
|
+
|
13
|
+
def params(error)
|
14
|
+
{
|
15
|
+
"log_history": [
|
16
|
+
{
|
17
|
+
"message": "#{error}",
|
18
|
+
"date": "#{DateTime.now}"
|
19
|
+
}
|
20
|
+
]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Gets updates from an order on Pluggto and updates the order on Spree
|
2
|
+
module SpreePluggto
|
3
|
+
class UpdateSpreeOrder
|
4
|
+
attr_reader :pluggto_order
|
5
|
+
attr_accessor :spree_order
|
6
|
+
|
7
|
+
def initialize(pluggto_id)
|
8
|
+
@pluggto_order = ::SpreePluggto::Api::Order.find(pluggto_id)
|
9
|
+
@spree_order = ::Spree::Order.find_by!(pluggto_id: pluggto_id)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
case pluggto_order["status"]
|
14
|
+
when 'pending'
|
15
|
+
update_payments
|
16
|
+
when 'approved'
|
17
|
+
update_payments
|
18
|
+
set_as_paid
|
19
|
+
if !spree_order.shipped?
|
20
|
+
set_as_ready
|
21
|
+
spree_order.fulfill!
|
22
|
+
end
|
23
|
+
when 'canceled'
|
24
|
+
spree_order.update_columns(state: 'canceled')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def update_payments
|
31
|
+
pluggto_order["payments"].each do |pluggto_payment|
|
32
|
+
spree_order.payments.find_or_create_by(
|
33
|
+
payment_method: ::Spree::PaymentMethod.find_by(type:"Spree::PaymentMethod::StoreCredit"), # Not ideal - we should define a specific payment method referring to PluggTo
|
34
|
+
amount: pluggto_payment["payment_total"],
|
35
|
+
installments: pluggto_payment["payment_installments"],
|
36
|
+
state: "completed"
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_as_ready
|
42
|
+
spree_order.update_columns(shipment_state: 'ready')
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_as_paid
|
46
|
+
spree_order.update_columns(payment_state: 'paid')
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Gets updates from a product on Pluggto and updates the product on Spree
|
2
|
+
module SpreePluggto
|
3
|
+
class UpdateSpreeProduct
|
4
|
+
attr_reader :pluggto_product
|
5
|
+
attr_accessor :spree_product
|
6
|
+
|
7
|
+
def initialize(pluggto_id)
|
8
|
+
@pluggto_product = SpreePluggto::Api::Product.find(pluggto_id)
|
9
|
+
@spree_product = ::Spree::Product.find_by!(pluggto_id: pluggto_id)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
# Logic here to define what we want to update on Spree when PluggTo say a product was updated
|
14
|
+
# Only stock?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<%= render partial: 'spree/admin/shared/product_tabs', locals: { current: :pluggto_fields } %>
|
2
|
+
|
3
|
+
<%= form_for [:admin, @product], method: :put do |f| %>
|
4
|
+
|
5
|
+
<fieldset>
|
6
|
+
<div class="row">
|
7
|
+
<div class="col-xs-12 col-md-8" data-hook="admin_product_pluggto_fields">
|
8
|
+
<%= f.field_container :pluggto_id, class: ['form-group'] do %>
|
9
|
+
<%= f.label :sync_with_pluggto, "Sincronizar com Plugg.to" %>
|
10
|
+
<%= f.check_box :sync_with_pluggto %>
|
11
|
+
<%= f.error_message_on :sync_with_pluggto %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<%= f.field_container :pluggto_name, class: ['form-group'] do %>
|
15
|
+
<%= f.label :pluggto_name, "Nome no Plugg.to" %>
|
16
|
+
<%= f.text_field :pluggto_name, class: 'form-control', placeholder: "Deixe em branco para usar o nome original do produto" %>
|
17
|
+
<%= f.error_message_on :pluggto_name %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<%= f.field_container :pluggto_id, class: ['form-group'] do %>
|
21
|
+
<%= f.label :pluggto_id, "ID no Plugg.to" %>
|
22
|
+
<%= f.text_field :pluggto_id, class: 'form-control', readonly: true %>
|
23
|
+
<%= f.error_message_on :pluggto_id %>
|
24
|
+
<% end %>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
|
29
|
+
<%= render partial: 'spree/admin/shared/edit_resource_links' %>
|
30
|
+
|
31
|
+
</fieldset>
|
32
|
+
|
33
|
+
<% end %>
|
data/config/locales/pt-BR.yml
CHANGED
data/config/routes.rb
CHANGED
@@ -3,5 +3,18 @@ Spree::Core::Engine.routes.draw do
|
|
3
3
|
resource :pluggto_settings do
|
4
4
|
get :upload_all_products
|
5
5
|
end
|
6
|
+
resources :products do
|
7
|
+
resources :pluggto_fields, except: [:destroy]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :api do
|
12
|
+
namespace :v1 do
|
13
|
+
namespace :pluggto, defaults: {format: :json} do
|
14
|
+
post :notifications
|
15
|
+
end
|
16
|
+
end
|
6
17
|
end
|
18
|
+
|
19
|
+
# post "/pluggto/api/pluggto/notifications", to: 'api/v1/pluggto#notifications'
|
7
20
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_pluggto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lucas Kuhn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spree_core
|
@@ -280,22 +280,42 @@ files:
|
|
280
280
|
- app/assets/javascripts/spree/frontend/spree_pluggto.js
|
281
281
|
- app/assets/stylesheets/spree/backend/spree_pluggto.css
|
282
282
|
- app/assets/stylesheets/spree/frontend/spree_pluggto.css
|
283
|
+
- app/controllers/spree/admin/pluggto_fields_controller.rb
|
283
284
|
- app/controllers/spree/admin/pluggto_settings_controller.rb
|
285
|
+
- app/controllers/spree/api/v1/pluggto_controller.rb
|
286
|
+
- app/jobs/spree_pluggto/order_created_job.rb
|
287
|
+
- app/jobs/spree_pluggto/order_updated_job.rb
|
288
|
+
- app/jobs/spree_pluggto/product_updated_job.rb
|
289
|
+
- app/jobs/spree_pluggto/sku_deleted_job.rb
|
290
|
+
- app/jobs/spree_pluggto/update_pluggto_order_job.rb
|
284
291
|
- app/jobs/spree_pluggto/upsert_all_products_job.rb
|
285
292
|
- app/jobs/spree_pluggto/upsert_product_job.rb
|
286
293
|
- app/models/pluggto_settings.rb
|
287
294
|
- app/models/spree_pluggto/spree/product_decorator.rb
|
295
|
+
- app/models/spree_pluggto/spree/shipment_decorator.rb
|
296
|
+
- app/overrides/add_pluggto_id_to_order_summary.rb
|
297
|
+
- app/overrides/add_pluggto_tab_to_order_sidebar.rb
|
288
298
|
- app/overrides/add_settings_to_admin_configurations.rb
|
289
|
-
- app/services/spree_pluggto/api.rb
|
290
|
-
- app/services/spree_pluggto/
|
291
|
-
- app/services/spree_pluggto/product.rb
|
292
|
-
- app/services/spree_pluggto/request.rb
|
299
|
+
- app/services/spree_pluggto/api/oauth.rb
|
300
|
+
- app/services/spree_pluggto/api/order.rb
|
301
|
+
- app/services/spree_pluggto/api/product.rb
|
302
|
+
- app/services/spree_pluggto/api/request.rb
|
303
|
+
- app/services/spree_pluggto/create_spree_order.rb
|
304
|
+
- app/services/spree_pluggto/delete_spree_product_reference.rb
|
305
|
+
- app/services/spree_pluggto/send_integration_errors.rb
|
306
|
+
- app/services/spree_pluggto/update_spree_order.rb
|
307
|
+
- app/services/spree_pluggto/update_spree_product.rb
|
308
|
+
- app/views/spree/admin/pluggto_fields/index.html.erb
|
293
309
|
- app/views/spree/admin/pluggto_settings/edit.html.erb
|
294
310
|
- bin/rails
|
295
311
|
- config/locales/en.yml
|
296
312
|
- config/locales/pt-BR.yml
|
297
313
|
- config/routes.rb
|
298
314
|
- db/migrate/20210706173803_create_pluggto_settings.rb
|
315
|
+
- db/migrate/20210713194303_add_pluggto_id_to_spree_products.rb
|
316
|
+
- db/migrate/20210805194730_add_pluggto_name_to_spree_products.rb
|
317
|
+
- db/migrate/20210812182652_add_pluggto_id_to_spree_shipments.rb
|
318
|
+
- db/migrate/20210812190431_add_sync_with_pluggto_to_products.rb
|
299
319
|
- lib/generators/spree_pluggto/install/install_generator.rb
|
300
320
|
- lib/spree_pluggto.rb
|
301
321
|
- lib/spree_pluggto/engine.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module SpreePluggto
|
2
|
-
class Api
|
3
|
-
def find_product(spree_product)
|
4
|
-
SpreePluggto::Request.new.get("/products/{pluggto_product_id}")
|
5
|
-
end
|
6
|
-
|
7
|
-
def upset_product(spree_product)
|
8
|
-
SpreePluggto::Request.new.put("/skus/#{product.sku}", product.pluggto_product.to_json)
|
9
|
-
end
|
10
|
-
|
11
|
-
def upsert_variant(spree_variant)
|
12
|
-
SpreePluggto::Request.new.put("/skus/#{spree_variant.sku}", body)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|