cloudcommerce 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/ecomplus-stores/monocard/functions/ssr/package.json +0 -2
- package/ecomplus-stores/tia-sonia/functions/ssr/package.json +0 -2
- package/package.json +6 -6
- package/packages/api/package.json +1 -1
- package/packages/apps/correios/package.json +2 -2
- package/packages/apps/custom-payment/package.json +1 -1
- package/packages/apps/custom-shipping/package.json +1 -1
- package/packages/apps/datafrete/package.json +2 -2
- package/packages/apps/discounts/package.json +1 -1
- package/packages/apps/emails/package.json +1 -1
- package/packages/apps/fb-conversions/package.json +1 -1
- package/packages/apps/frenet/package.json +2 -2
- package/packages/apps/galaxpay/package.json +2 -2
- package/packages/apps/google-analytics/package.json +2 -2
- package/packages/apps/infinitepay/package.json +2 -2
- package/packages/apps/jadlog/package.json +2 -2
- package/packages/apps/loyalty-points/package.json +1 -1
- package/packages/apps/melhor-envio/CHANGELOG.md +1 -0
- package/packages/apps/melhor-envio/README.md +1 -0
- package/packages/apps/melhor-envio/events.js +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/database.d.ts +18 -0
- package/packages/apps/melhor-envio/lib/functions-lib/database.js +115 -0
- package/packages/apps/melhor-envio/lib/functions-lib/database.js.map +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/events-to-melhor-envio.d.ts +7 -0
- package/packages/apps/melhor-envio/lib/functions-lib/events-to-melhor-envio.js +112 -0
- package/packages/apps/melhor-envio/lib/functions-lib/events-to-melhor-envio.js.map +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/new-label.d.ts +42 -0
- package/packages/apps/melhor-envio/lib/functions-lib/new-label.js +185 -0
- package/packages/apps/melhor-envio/lib/functions-lib/new-label.js.map +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/order-is-valid.d.ts +5 -0
- package/packages/apps/melhor-envio/lib/functions-lib/order-is-valid.js +40 -0
- package/packages/apps/melhor-envio/lib/functions-lib/order-is-valid.js.map +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/tracking-codes.d.ts +2 -0
- package/packages/apps/melhor-envio/lib/functions-lib/tracking-codes.js +164 -0
- package/packages/apps/melhor-envio/lib/functions-lib/tracking-codes.js.map +1 -0
- package/packages/apps/melhor-envio/lib/index.d.ts +1 -0
- package/packages/apps/melhor-envio/lib/index.js +2 -0
- package/packages/apps/melhor-envio/lib/index.js.map +1 -0
- package/packages/apps/melhor-envio/lib/melhor-envio-events.d.ts +6 -0
- package/packages/apps/melhor-envio/lib/melhor-envio-events.js +17 -0
- package/packages/apps/melhor-envio/lib/melhor-envio-events.js.map +1 -0
- package/packages/apps/melhor-envio/lib/melhor-envio.d.ts +2 -0
- package/packages/apps/melhor-envio/lib/melhor-envio.js +6 -0
- package/packages/apps/melhor-envio/lib/melhor-envio.js.map +1 -0
- package/packages/apps/melhor-envio/lib-mjs/calculate-melhor-envio.mjs +341 -0
- package/packages/apps/melhor-envio/lib-mjs/functions/client-melhor-envio.mjs +14 -0
- package/packages/apps/melhor-envio/lib-mjs/functions/error-handling.mjs +62 -0
- package/packages/apps/melhor-envio/lib-mjs/functions/new-shipment.mjs +119 -0
- package/packages/apps/melhor-envio/package.json +36 -0
- package/packages/apps/melhor-envio/src/functions-lib/database.ts +140 -0
- package/packages/apps/melhor-envio/src/functions-lib/events-to-melhor-envio.ts +137 -0
- package/packages/apps/melhor-envio/src/functions-lib/new-label.ts +214 -0
- package/packages/apps/melhor-envio/src/functions-lib/order-is-valid.ts +51 -0
- package/packages/apps/melhor-envio/src/functions-lib/tracking-codes.ts +191 -0
- package/packages/apps/melhor-envio/src/index.ts +1 -0
- package/packages/apps/melhor-envio/src/melhor-envio-events.ts +24 -0
- package/packages/apps/melhor-envio/src/melhor-envio.ts +7 -0
- package/packages/apps/melhor-envio/tsconfig.json +6 -0
- package/packages/apps/mercadopago/package.json +2 -2
- package/packages/apps/pagarme/package.json +2 -2
- package/packages/apps/paghiper/package.json +3 -3
- package/packages/apps/pix/package.json +2 -2
- package/packages/apps/tiny-erp/package.json +2 -2
- package/packages/cli/package.json +1 -1
- package/packages/config/package.json +1 -1
- package/packages/emails/package.json +3 -3
- package/packages/events/lib/firebase.js +2 -0
- package/packages/events/lib/firebase.js.map +1 -1
- package/packages/events/package.json +2 -1
- package/packages/events/src/firebase.ts +2 -0
- package/packages/firebase/lib/config.d.ts +4 -0
- package/packages/firebase/lib/config.js +7 -0
- package/packages/firebase/lib/config.js.map +1 -1
- package/packages/firebase/package.json +2 -2
- package/packages/firebase/src/config.ts +8 -0
- package/packages/i18n/lib/en_us/i19buyTogether.txt +1 -0
- package/packages/i18n/lib/en_us/i19buyTogetherWith.txt +1 -0
- package/packages/i18n/lib/en_us/i19report.txt +1 -0
- package/packages/i18n/lib/en_us/i19toggleMenu.txt +1 -0
- package/packages/i18n/lib/en_us/i19uponRequest.txt +1 -0
- package/packages/i18n/lib/en_us/i19usedPoints.txt +1 -0
- package/packages/i18n/lib/en_us.d.ts +6 -0
- package/packages/i18n/lib/en_us.js +6 -0
- package/packages/i18n/lib/en_us.js.map +1 -1
- package/packages/i18n/lib/pt_br/i19buyTogether.txt +1 -0
- package/packages/i18n/lib/pt_br/i19buyTogetherWith.txt +1 -0
- package/packages/i18n/lib/pt_br/i19report.txt +1 -0
- package/packages/i18n/lib/pt_br/i19toggleMenu.txt +1 -0
- package/packages/i18n/lib/pt_br/i19uponRequest.txt +1 -0
- package/packages/i18n/lib/pt_br/i19usedPoints.txt +1 -0
- package/packages/i18n/lib/pt_br.d.ts +6 -0
- package/packages/i18n/lib/pt_br.js +6 -0
- package/packages/i18n/lib/pt_br.js.map +1 -1
- package/packages/i18n/package.json +1 -1
- package/packages/i18n/src/en_us.ts +6 -0
- package/packages/i18n/src/pt_br.ts +6 -0
- package/packages/modules/lib/firebase/call-app-module.js +5 -0
- package/packages/modules/lib/firebase/call-app-module.js.map +1 -1
- package/packages/modules/package.json +3 -2
- package/packages/modules/src/firebase/call-app-module.ts +5 -0
- package/packages/passport/package.json +1 -1
- package/packages/ssr/package.json +3 -4
- package/packages/storefront/.eslintrc.cjs +1 -1
- package/packages/storefront/astro.config.mjs +8 -1
- package/packages/storefront/dist/client/_astro/PitchBar.103168e6.js +1 -0
- package/packages/storefront/dist/client/_astro/Prices.b75d44d6.js +1 -0
- package/packages/storefront/dist/client/_astro/Prices.vue_vue_type_script_setup_true_lang.054033ef.js +1 -0
- package/packages/storefront/dist/client/_astro/{ProductCard.6d8b6d86.js → ProductCard.9138ec25.js} +1 -1
- package/packages/storefront/dist/client/_astro/ShopHeader.65213f83.js +1 -0
- package/packages/storefront/dist/client/_astro/_...slug_.39c46f54.css +1 -0
- package/packages/storefront/dist/client/_astro/client.eba0daa7.js +1 -0
- package/packages/storefront/dist/client/_astro/index.0c833781.css +1 -0
- package/packages/storefront/dist/client/_astro/index.7577af70.js +1 -0
- package/packages/storefront/dist/client/_astro/{modules-info.dde776b4.js → modules-info.0c999f60.js} +1 -1
- package/packages/storefront/dist/client/_astro/runtime-core.esm-bundler.4da3640b.js +1 -0
- package/packages/storefront/dist/client/_astro/runtime-dom.esm-bundler.0869e112.js +1 -0
- package/packages/storefront/dist/client/_astro/server.60de185d.css +1 -0
- package/packages/storefront/dist/client/fallback/index.html +12 -7
- package/packages/storefront/dist/client/sw.js +1 -1
- package/packages/storefront/dist/server/chunks/pages/{all.c27193d6.mjs → all.6379e666.mjs} +494 -373
- package/packages/storefront/dist/server/chunks/{prerender.89f63027.mjs → prerender.a1ec39e0.mjs} +0 -0
- package/packages/storefront/dist/server/entry.mjs +39 -4452
- package/packages/storefront/package.json +4 -5
- package/packages/storefront/src/lib/assets/base.css +16 -11
- package/packages/storefront/src/lib/components/Carousel.vue +52 -82
- package/packages/storefront/src/lib/components/Drawer.vue +97 -0
- package/packages/storefront/src/lib/components/ProductCard.vue +1 -1
- package/packages/storefront/src/lib/components/ShopHeader.vue +110 -0
- package/packages/storefront/src/lib/components/ShopSidenav.vue +26 -0
- package/packages/storefront/src/lib/components/globals/Fade.vue +10 -14
- package/packages/storefront/src/lib/composables/use-pitch-bar.ts +27 -0
- package/packages/storefront/src/lib/composables/use-prices.ts +4 -2
- package/packages/storefront/src/lib/composables/use-sticky-header.ts +111 -0
- package/packages/storefront/src/lib/layouts/BaseBody.astro +2 -0
- package/packages/storefront/src/lib/layouts/PagesHeader.astro +23 -17
- package/packages/storefront/tailwind.config.cjs +4 -0
- package/packages/storefront/uno.config.cjs +1 -1
- package/packages/types/package.json +1 -1
- package/packages/storefront/dist/client/_astro/PitchBar.f3579a5b.js +0 -1
- package/packages/storefront/dist/client/_astro/Prices.8e5cead5.js +0 -1
- package/packages/storefront/dist/client/_astro/Prices.vue_vue_type_script_setup_true_lang.b8cbeb54.js +0 -1
- package/packages/storefront/dist/client/_astro/StickyHeader.7b0f3963.js +0 -1
- package/packages/storefront/dist/client/_astro/_...slug_.97285eba.css +0 -1
- package/packages/storefront/dist/client/_astro/client.3e777d4c.js +0 -1
- package/packages/storefront/dist/client/_astro/index.90df622b.css +0 -1
- package/packages/storefront/dist/client/_astro/runtime-core.esm-bundler.7cf33881.js +0 -1
- package/packages/storefront/dist/client/_astro/runtime-dom.esm-bundler.1a4c7407.js +0 -1
- package/packages/storefront/dist/client/_astro/server.4d9646d8.css +0 -1
- package/packages/storefront/src/lib/components/PitchBar.vue +0 -61
- package/packages/storefront/src/lib/components/Prices.vue +0 -176
- package/packages/storefront/src/lib/components/StickyHeader.vue +0 -56
- package/packages/storefront/src/lib/composables/use-component-variant.ts +0 -13
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import logger from 'firebase-functions/logger';
|
|
2
|
+
import api from '@cloudcommerce/api';
|
|
3
|
+
import { newShipment, matchService, sortServicesBy } from './functions/new-shipment.mjs';
|
|
4
|
+
import meClient from './functions/client-melhor-envio.mjs';
|
|
5
|
+
import errorHandling from './functions/error-handling.mjs';
|
|
6
|
+
|
|
7
|
+
export default async ({ params, application }) => {
|
|
8
|
+
const appData = {
|
|
9
|
+
...application.data,
|
|
10
|
+
...application.hidden_data,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
if (!appData.access_token) {
|
|
14
|
+
// no Melhor Envio access_token
|
|
15
|
+
return {
|
|
16
|
+
status: 409,
|
|
17
|
+
error: 'CALCULATE_SHIPPING_DISABLED',
|
|
18
|
+
message: 'Melhor Envio Token is unset on app hidden data',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (
|
|
22
|
+
appData.skip_no_weight_item
|
|
23
|
+
&& params.items && params.items.find(({ weight }) => weight && !weight.value)
|
|
24
|
+
) {
|
|
25
|
+
return {
|
|
26
|
+
status: 409,
|
|
27
|
+
error: 'CALCULATE_SHIPPING_SKIPPED',
|
|
28
|
+
message: 'Melhor Envio configured to skip no weight items',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// start mounting response body
|
|
32
|
+
// https://apx-mods.e-com.plus/api/v1/calculate_shipping/response_schema.json?store_id=100
|
|
33
|
+
const response = {
|
|
34
|
+
shipping_services: [],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
let shippingRules;
|
|
38
|
+
if (Array.isArray(appData.shipping_rules) && appData.shipping_rules.length) {
|
|
39
|
+
shippingRules = appData.shipping_rules;
|
|
40
|
+
} else {
|
|
41
|
+
shippingRules = [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const destinationZip = params.to ? params.to.zip.replace(/\D/g, '') : '';
|
|
45
|
+
|
|
46
|
+
const checkZipCode = (rule) => {
|
|
47
|
+
// validate rule zip range
|
|
48
|
+
if (destinationZip && rule.zip_range) {
|
|
49
|
+
const { min, max } = rule.zip_range;
|
|
50
|
+
return Boolean((!min || destinationZip >= min) && (!max || destinationZip <= max));
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// search for configured free shipping rule
|
|
56
|
+
if (Array.isArray(shippingRules)) {
|
|
57
|
+
for (let i = 0; i < shippingRules.length; i++) {
|
|
58
|
+
const rule = shippingRules[i];
|
|
59
|
+
if (rule.free_shipping && checkZipCode(rule)) {
|
|
60
|
+
if (!rule.min_amount) {
|
|
61
|
+
response.free_shipping_from_value = 0;
|
|
62
|
+
break;
|
|
63
|
+
} else if (!(response.free_shipping_from_value <= rule.min_amount)) {
|
|
64
|
+
response.free_shipping_from_value = rule.min_amount;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// params object follows calculate shipping request schema:
|
|
71
|
+
// https://apx-mods.e-com.plus/api/v1/calculate_shipping/schema.json?store_id=100
|
|
72
|
+
if (!params.to) {
|
|
73
|
+
// respond only with free shipping option
|
|
74
|
+
return response;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (params.items) {
|
|
78
|
+
const intZipCode = parseInt(params.to.zip.replace(/\D/g, ''), 10);
|
|
79
|
+
const token = appData.access_token;
|
|
80
|
+
const { sandbox } = appData;
|
|
81
|
+
|
|
82
|
+
if (!appData.merchant_address) {
|
|
83
|
+
// get merchant_address
|
|
84
|
+
const { data } = await meClient(token, sandbox).get('/');
|
|
85
|
+
const merchantAddress = data.address;
|
|
86
|
+
|
|
87
|
+
// update config.merchant_address
|
|
88
|
+
appData.merchant_address = merchantAddress;
|
|
89
|
+
// save merchant_address in hidden_data
|
|
90
|
+
|
|
91
|
+
const bodyUpdate = {
|
|
92
|
+
merchant_address: merchantAddress,
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
await api.patch(`applications/${application._id}/hidden_data`, bodyUpdate);
|
|
96
|
+
} catch (err) {
|
|
97
|
+
logger.error('>>(App Melhor Envio): !<> Update merchant_address failed', err.message);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let schema;
|
|
102
|
+
try {
|
|
103
|
+
schema = newShipment(appData, params);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
logger.error('>>(App Melhor Envio): NEW_SHIPMENT_PARSE_ERR', e);
|
|
106
|
+
return {
|
|
107
|
+
status: 400,
|
|
108
|
+
error: 'CALCULATE_ERR',
|
|
109
|
+
message: 'Unexpected Error Try Later',
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// calculate the shipment
|
|
114
|
+
try {
|
|
115
|
+
const data = await meClient(token, sandbox).post('/shipment/calculate', schema);
|
|
116
|
+
|
|
117
|
+
let errorMsg;
|
|
118
|
+
data.forEach((service) => {
|
|
119
|
+
let isAvailable = true;
|
|
120
|
+
// check if service is not disabled
|
|
121
|
+
if (Array.isArray(appData.unavailable_for)) {
|
|
122
|
+
for (let i = 0; i < appData.unavailable_for.length; i++) {
|
|
123
|
+
if (appData.unavailable_for[i] && appData.unavailable_for[i].zip_range
|
|
124
|
+
&& appData.unavailable_for[i].service_name
|
|
125
|
+
) {
|
|
126
|
+
const unavailable = appData.unavailable_for[i];
|
|
127
|
+
if (intZipCode >= unavailable.zip_range.min
|
|
128
|
+
&& intZipCode <= unavailable.zip_range.max
|
|
129
|
+
&& matchService(unavailable, service.name)
|
|
130
|
+
) {
|
|
131
|
+
isAvailable = false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!service.error && isAvailable) {
|
|
138
|
+
// mounte response body
|
|
139
|
+
const { to } = params;
|
|
140
|
+
const from = {
|
|
141
|
+
zip: appData.merchant_address.postal_code,
|
|
142
|
+
street: appData.merchant_address.address,
|
|
143
|
+
number: parseInt(appData.merchant_address.number, 10),
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const shippingLine = {
|
|
147
|
+
to,
|
|
148
|
+
from,
|
|
149
|
+
own_hand: service.additional_services.own_hand,
|
|
150
|
+
receipt: service.additional_services.receipt,
|
|
151
|
+
discount: 0,
|
|
152
|
+
total_price: parseFloat(service.price),
|
|
153
|
+
delivery_time: {
|
|
154
|
+
days: parseInt(service.delivery_time, 10),
|
|
155
|
+
working_days: true,
|
|
156
|
+
},
|
|
157
|
+
posting_deadline: {
|
|
158
|
+
days: 3,
|
|
159
|
+
...appData.posting_deadline,
|
|
160
|
+
},
|
|
161
|
+
custom_fields: [
|
|
162
|
+
{
|
|
163
|
+
field: 'by_melhor_envio',
|
|
164
|
+
value: 'true',
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const servicePkg = (service.packages && service.packages[0])
|
|
170
|
+
|| (service.volumes && service.volumes[0]);
|
|
171
|
+
|
|
172
|
+
if (servicePkg) {
|
|
173
|
+
shippingLine.package = {};
|
|
174
|
+
if (servicePkg.dimensions) {
|
|
175
|
+
shippingLine.package.dimensions = {
|
|
176
|
+
width: {
|
|
177
|
+
value: servicePkg.dimensions.width,
|
|
178
|
+
},
|
|
179
|
+
height: {
|
|
180
|
+
value: servicePkg.dimensions.height,
|
|
181
|
+
},
|
|
182
|
+
length: {
|
|
183
|
+
value: servicePkg.dimensions.length,
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (servicePkg.weight) {
|
|
188
|
+
shippingLine.package.weight = {
|
|
189
|
+
value: parseFloat(servicePkg.weight),
|
|
190
|
+
unit: 'kg',
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (appData.jadlog_agency) {
|
|
196
|
+
shippingLine.custom_fields.push({
|
|
197
|
+
field: 'jadlog_agency',
|
|
198
|
+
value: String(appData.jadlog_agency),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// check for default configured additional/discount price
|
|
203
|
+
if (appData.additional_price) {
|
|
204
|
+
if (appData.additional_price > 0) {
|
|
205
|
+
shippingLine.other_additionals = [{
|
|
206
|
+
tag: 'additional_price',
|
|
207
|
+
label: 'Adicional padrão',
|
|
208
|
+
price: appData.additional_price,
|
|
209
|
+
}];
|
|
210
|
+
} else {
|
|
211
|
+
// negative additional price to apply discount
|
|
212
|
+
shippingLine.discount -= appData.additional_price;
|
|
213
|
+
}
|
|
214
|
+
// update total price
|
|
215
|
+
shippingLine.total_price += appData.additional_price;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// search for discount by shipping rule
|
|
219
|
+
if (Array.isArray(shippingRules)) {
|
|
220
|
+
for (let i = 0; i < shippingRules.length; i++) {
|
|
221
|
+
const rule = shippingRules[i];
|
|
222
|
+
if (rule && matchService(rule, service.name)
|
|
223
|
+
&& checkZipCode(rule) && !(rule.min_amount > params.subtotal)
|
|
224
|
+
) {
|
|
225
|
+
// valid shipping rule
|
|
226
|
+
if (rule.free_shipping) {
|
|
227
|
+
shippingLine.discount += shippingLine.total_price;
|
|
228
|
+
shippingLine.total_price = 0;
|
|
229
|
+
break;
|
|
230
|
+
} else if (rule.discount && rule.service_name) {
|
|
231
|
+
let discountValue = rule.discount.value;
|
|
232
|
+
if (rule.discount.percentage) {
|
|
233
|
+
discountValue *= (shippingLine.total_price / 100);
|
|
234
|
+
}
|
|
235
|
+
shippingLine.discount += discountValue;
|
|
236
|
+
shippingLine.total_price -= discountValue;
|
|
237
|
+
if (shippingLine.total_price < 0) {
|
|
238
|
+
shippingLine.total_price = 0;
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
let label = service.name;
|
|
247
|
+
if (appData.services && Array.isArray(appData.services) && appData.services.length) {
|
|
248
|
+
const serviceFound = appData.services.find((lookForService) => {
|
|
249
|
+
return lookForService && matchService(lookForService, label);
|
|
250
|
+
});
|
|
251
|
+
if (serviceFound && serviceFound.label) {
|
|
252
|
+
label = serviceFound.label;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
response.shipping_services.push({
|
|
257
|
+
label,
|
|
258
|
+
carrier: service.company.name,
|
|
259
|
+
service_name: service.name,
|
|
260
|
+
service_code: `ME ${service.id}`,
|
|
261
|
+
icon: service.company.picture,
|
|
262
|
+
shipping_line: shippingLine,
|
|
263
|
+
});
|
|
264
|
+
} else {
|
|
265
|
+
errorMsg += `${service.name}, ${service.error} \n`;
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// sort services?
|
|
270
|
+
if (appData.sort_services && Array.isArray(response.shipping_services)
|
|
271
|
+
&& response.shipping_services.length) {
|
|
272
|
+
response.shipping_services.sort(sortServicesBy(appData.sort_services));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return (!Array.isArray(response.shipping_services) || !response.shipping_services.length)
|
|
276
|
+
&& errorMsg ? {
|
|
277
|
+
status: 400,
|
|
278
|
+
error: 'CALCULATE_ERR_MSG',
|
|
279
|
+
message: errorMsg,
|
|
280
|
+
}
|
|
281
|
+
// success response with available shipping services
|
|
282
|
+
: response;
|
|
283
|
+
} catch (err) {
|
|
284
|
+
//
|
|
285
|
+
let message = 'Unexpected Error Try Later';
|
|
286
|
+
if (err.response && err.isAxiosError) {
|
|
287
|
+
const { data, status, config } = err.response;
|
|
288
|
+
let isAppError = true;
|
|
289
|
+
if (status >= 500) {
|
|
290
|
+
message = 'Melhor Envio offline no momento';
|
|
291
|
+
isAppError = false;
|
|
292
|
+
} else if (data) {
|
|
293
|
+
if (data.errors && typeof data.errors === 'object' && Object.keys(data.errors).length) {
|
|
294
|
+
const errorKeys = Object.keys(data.errors);
|
|
295
|
+
for (let i = 0; i < errorKeys.length; i++) {
|
|
296
|
+
const meError = data.errors[errorKeys[i]];
|
|
297
|
+
if (meError && meError.length) {
|
|
298
|
+
message = Array.isArray(meError) ? meError[0] : meError;
|
|
299
|
+
if (errorKeys[i].startsWith('to.')) {
|
|
300
|
+
// invalid merchant config on ME
|
|
301
|
+
// eg.: 'O campo to.postal code deve ter pelo menos 5 caracteres.'
|
|
302
|
+
isAppError = false;
|
|
303
|
+
break;
|
|
304
|
+
} else {
|
|
305
|
+
message += errorKeys[i];
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} else if (data.error) {
|
|
310
|
+
message = `ME: ${data.error}`;
|
|
311
|
+
} else if (data.message) {
|
|
312
|
+
message = `ME: ${data.message}`;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (isAppError) {
|
|
317
|
+
// debug unexpected error
|
|
318
|
+
logger.error('>>(App Melhor Envio): CalculateShippingErr:', JSON.stringify({
|
|
319
|
+
status,
|
|
320
|
+
data,
|
|
321
|
+
config,
|
|
322
|
+
}, null, 4));
|
|
323
|
+
}
|
|
324
|
+
} else {
|
|
325
|
+
errorHandling(err);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return {
|
|
329
|
+
status: 409,
|
|
330
|
+
error: 'CALCULATE_ERR',
|
|
331
|
+
message,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
return {
|
|
336
|
+
status: 400,
|
|
337
|
+
error: 'CALCULATE_EMPTY_CART',
|
|
338
|
+
message: 'Cannot calculate shipping without cart items',
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
|
|
3
|
+
export default (accessToken, isSandbox) => {
|
|
4
|
+
const headers = {
|
|
5
|
+
Accept: 'application/json',
|
|
6
|
+
'Content-Type': 'application/json',
|
|
7
|
+
Authorization: `Bearer ${accessToken}`,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
return axios.create({
|
|
11
|
+
baseURL: `https://${isSandbox ? 'sandbox.' : ''}melhorenvio.com.br/api/v2/me`,
|
|
12
|
+
headers,
|
|
13
|
+
});
|
|
14
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import logger from 'firebase-functions/logger';
|
|
2
|
+
|
|
3
|
+
const ignoreError = (response) => {
|
|
4
|
+
// check response status code
|
|
5
|
+
// should ignore some error responses
|
|
6
|
+
const { status, data } = response;
|
|
7
|
+
if (status >= 400 && status < 500) {
|
|
8
|
+
switch (status) {
|
|
9
|
+
case 403:
|
|
10
|
+
// ignore resource limits errors
|
|
11
|
+
return true;
|
|
12
|
+
|
|
13
|
+
case 404:
|
|
14
|
+
if (data && data.error_code !== 20) {
|
|
15
|
+
// resource ID not found ?
|
|
16
|
+
// ignore
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
break;
|
|
20
|
+
default:
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// must debug
|
|
25
|
+
return false;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default (err) => {
|
|
29
|
+
// axios error object
|
|
30
|
+
// https://github.com/axios/axios#handling-errors
|
|
31
|
+
if (!err.appAuthRemoved && !err.appErrorLog) {
|
|
32
|
+
// error not treated by App SDK
|
|
33
|
+
if (err.response) {
|
|
34
|
+
if (ignoreError(err.response)) {
|
|
35
|
+
// ignore client error
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
err.responseJSON = JSON.stringify(err.response.data);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// debug unexpected response
|
|
42
|
+
logger.error('>>(App Melhor Envio) =>', err);
|
|
43
|
+
} else if (err.appErrorLog && !err.appErrorLogged) {
|
|
44
|
+
// cannot log to app hidden data
|
|
45
|
+
// debug app log error
|
|
46
|
+
const error = err.appErrorLog;
|
|
47
|
+
const { response, config } = error;
|
|
48
|
+
|
|
49
|
+
// handle error response
|
|
50
|
+
if (response) {
|
|
51
|
+
if (ignoreError(response)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// debug unexpected response
|
|
55
|
+
error.configJSON = {
|
|
56
|
+
originalRequest: JSON.stringify(err.config),
|
|
57
|
+
logRequest: JSON.stringify(config),
|
|
58
|
+
};
|
|
59
|
+
logger.error('>>(App Melhor Envio) => ', error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const convertDimensions = (dimension) => {
|
|
2
|
+
let dimensionValue = 0;
|
|
3
|
+
if (dimension && dimension.unit) {
|
|
4
|
+
switch (dimension.unit) {
|
|
5
|
+
case 'cm':
|
|
6
|
+
dimensionValue = dimension.value;
|
|
7
|
+
break;
|
|
8
|
+
case 'm':
|
|
9
|
+
dimensionValue = dimension.value * 100;
|
|
10
|
+
break;
|
|
11
|
+
case 'mm':
|
|
12
|
+
dimensionValue = dimension.value / 10;
|
|
13
|
+
break;
|
|
14
|
+
default:
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return dimensionValue;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const newShipment = (appConfig, params) => {
|
|
22
|
+
const calculate = {};
|
|
23
|
+
const { to, items } = params;
|
|
24
|
+
|
|
25
|
+
// https://docs.menv.io/?version=latest#9bbc2460-7786-4871-a0cc-2ae3cd54333e
|
|
26
|
+
// creates a new model for calculating freight in the Melhor Envio API.
|
|
27
|
+
calculate.from = appConfig.merchant_address;
|
|
28
|
+
|
|
29
|
+
calculate.to = {
|
|
30
|
+
postal_code: to.zip,
|
|
31
|
+
address: to.street,
|
|
32
|
+
number: to.number,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
calculate.options = {
|
|
36
|
+
receipt: appConfig.receipt || false,
|
|
37
|
+
own_hand: appConfig.own_hand || false,
|
|
38
|
+
collect: false,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
calculate.products = [];
|
|
42
|
+
|
|
43
|
+
items.forEach((item) => {
|
|
44
|
+
const { dimensions, weight, quantity } = item;
|
|
45
|
+
// sum physical weight
|
|
46
|
+
let physicalWeight = 0;
|
|
47
|
+
if (weight && weight.value) {
|
|
48
|
+
switch (weight.unit) {
|
|
49
|
+
case 'kg':
|
|
50
|
+
physicalWeight = weight.value;
|
|
51
|
+
break;
|
|
52
|
+
case 'g':
|
|
53
|
+
physicalWeight = weight.value / 1000;
|
|
54
|
+
break;
|
|
55
|
+
case 'mg':
|
|
56
|
+
physicalWeight = weight.value / 1000000;
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
calculate.products.push({
|
|
64
|
+
id: item.product_id,
|
|
65
|
+
weight: physicalWeight,
|
|
66
|
+
width: convertDimensions(dimensions && dimensions.width),
|
|
67
|
+
height: convertDimensions(dimensions && dimensions.height),
|
|
68
|
+
length: convertDimensions(dimensions && dimensions.length),
|
|
69
|
+
quantity: quantity || 1,
|
|
70
|
+
insurance_value: item.final_price || item.price,
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return calculate;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const matchService = (service, name) => {
|
|
78
|
+
const fields = ['service_name', 'service_code'];
|
|
79
|
+
for (let i = 0; i < fields.length; i++) {
|
|
80
|
+
if (service[fields[i]]) {
|
|
81
|
+
return service[fields[i]].trim().toUpperCase() === name.toUpperCase();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const sortServicesBy = (by) => {
|
|
88
|
+
switch (by) {
|
|
89
|
+
case 'Maior preço':
|
|
90
|
+
return function sort(a, b) {
|
|
91
|
+
return a.shipping_line.total_price < b.shipping_line.total_price;
|
|
92
|
+
};
|
|
93
|
+
case 'Menor preço':
|
|
94
|
+
return function sort(a, b) {
|
|
95
|
+
return a.shipping_line.total_price > b.shipping_line.total_price;
|
|
96
|
+
};
|
|
97
|
+
case 'Maior prazo de entrega':
|
|
98
|
+
return function sort(a, b) {
|
|
99
|
+
return a.shipping_line.delivery_time.days < b.shipping_line.delivery_time.days;
|
|
100
|
+
};
|
|
101
|
+
case 'Menor prazo de entrega':
|
|
102
|
+
return function sort(a, b) {
|
|
103
|
+
return a.shipping_line.delivery_time.days > b.shipping_line.delivery_time.days;
|
|
104
|
+
};
|
|
105
|
+
default:
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// default
|
|
110
|
+
return function sort(a, b) {
|
|
111
|
+
return a.shipping_line.total_price > b.shipping_line.total_price;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export {
|
|
116
|
+
newShipment,
|
|
117
|
+
matchService,
|
|
118
|
+
sortServicesBy,
|
|
119
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cloudcommerce/app-melhor-envio",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.4.0",
|
|
5
|
+
"description": "E-Com Plus Cloud Commerce app to integrate Melhor Envio",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./lib/index.js",
|
|
9
|
+
"./events": "./lib/melhor-envio-events.js"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/ecomplus/cloud-commerce.git",
|
|
14
|
+
"directory": "packages/apps/melhor-envio"
|
|
15
|
+
},
|
|
16
|
+
"author": "E-Com Club Softwares para E-commerce <ti@e-com.club>",
|
|
17
|
+
"license": "Apache 2.0 with Commons Clause",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/ecomplus/cloud-commerce/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/ecomplus/cloud-commerce/tree/main/packages/apps/melhor-envio#readme",
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "sh ../../../scripts/build-lib.sh"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@cloudcommerce/api": "workspace:*",
|
|
27
|
+
"@cloudcommerce/firebase": "workspace:*",
|
|
28
|
+
"axios": "^1.2.5",
|
|
29
|
+
"firebase-admin": "^11.5.0",
|
|
30
|
+
"firebase-functions": "^4.2.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@cloudcommerce/types": "workspace:*",
|
|
34
|
+
"@firebase/app-types": "^0.9.0"
|
|
35
|
+
}
|
|
36
|
+
}
|