spree_br_common 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +14 -0
- data/Gemfile +20 -0
- data/LICENSE +26 -0
- data/README.md +55 -0
- data/Rakefile +21 -0
- data/app/assets/javascripts/spree/backend/spree_br_common.js +2 -0
- data/app/assets/javascripts/spree/frontend/address.js +119 -0
- data/app/assets/javascripts/spree/frontend/mask.js +21 -0
- data/app/assets/javascripts/spree/frontend/plugins/jquery.mask.extension.js +4 -0
- data/app/assets/javascripts/spree/frontend/plugins/jquery.mask.js +395 -0
- data/app/assets/javascripts/spree/frontend/routes.js.erb +4 -0
- data/app/assets/javascripts/spree/frontend/spree_br_common.js +1 -0
- data/app/assets/stylesheets/spree/backend/spree_br_common.css +4 -0
- data/app/assets/stylesheets/spree/frontend/spree_br_common.css +4 -0
- data/app/controllers/spree/addresses_controller.rb +24 -0
- data/app/controllers/spree/api/cities_controller.rb +38 -0
- data/app/controllers/spree/user_registrations_controller_decorator.rb +13 -0
- data/app/helpers/spree/api/api_helpers_decorator.rb +13 -0
- data/app/helpers/spree/base_helper_decorator.rb +5 -0
- data/app/models/spree/ability_decorator.rb +21 -0
- data/app/models/spree/address_decorator.rb +6 -0
- data/app/models/spree/city.rb +7 -0
- data/app/models/spree/permitted_attributes_decorator.rb +8 -0
- data/app/models/spree/state_decorator.rb +3 -0
- data/app/models/spree/user_decorator.rb +52 -0
- data/app/overrides/spree/address/_form/add_district.html.erb.deface +5 -0
- data/app/overrides/spree/address/_form/add_number.html.erb.deface +5 -0
- data/app/overrides/spree/address/_form/hide_country.html.erb.deface +4 -0
- data/app/overrides/spree/address/_form/move_city_to_after_state.deface +2 -0
- data/app/overrides/spree/address/_form/move_zipcode_after_last_name.deface +2 -0
- data/app/overrides/spree/address/_form/replace_city_input_text_by_select.html.erb.deface +18 -0
- data/app/overrides/spree/address/_form/set_data_uf_to_state.html.erb.deface +15 -0
- data/app/overrides/spree/admin/users/_form/add_extras_fields.html.erb.deface +39 -0
- data/app/overrides/spree/shared/_user_form/add_extra_fields.html.erb.deface +19 -0
- data/app/overrides/spree/users/show/add_details.html.erb.deface +13 -0
- data/app/views/spree/api/cities/index.v1.rabl +11 -0
- data/app/views/spree/api/cities/show.v1.rabl +2 -0
- data/bin/rails +7 -0
- data/config/locales/en.yml +11 -0
- data/config/locales/pt-BR.yml +14 -0
- data/config/routes.rb +7 -0
- data/db/default/country.rb +3 -0
- data/db/default/shipping_categories.rb +1 -0
- data/db/default/shipping_zones.rb +3 -0
- data/db/default/states.rb +31 -0
- data/db/default/states_cities_of_acre.rb +26 -0
- data/db/default/states_cities_of_alagoas.rb +107 -0
- data/db/default/states_cities_of_amapa.rb +20 -0
- data/db/default/states_cities_of_amazonas.rb +67 -0
- data/db/default/states_cities_of_bahia.rb +421 -0
- data/db/default/states_cities_of_ceara.rb +188 -0
- data/db/default/states_cities_of_distrito_federal.rb +5 -0
- data/db/default/states_cities_of_espirito_santo.rb +82 -0
- data/db/default/states_cities_of_goias.rb +250 -0
- data/db/default/states_cities_of_maranhao.rb +221 -0
- data/db/default/states_cities_of_mato_grosso.rb +145 -0
- data/db/default/states_cities_of_mato_grosso_do_sul.rb +82 -0
- data/db/default/states_cities_of_minas_gerais.rb +857 -0
- data/db/default/states_cities_of_para.rb +147 -0
- data/db/default/states_cities_of_paraiba.rb +227 -0
- data/db/default/states_cities_of_parana.rb +403 -0
- data/db/default/states_cities_of_pernambuco.rb +189 -0
- data/db/default/states_cities_of_piaui.rb +227 -0
- data/db/default/states_cities_of_rio_de_janeiro.rb +96 -0
- data/db/default/states_cities_of_rio_grande_do_norte.rb +171 -0
- data/db/default/states_cities_of_rio_grande_do_sul.rb +500 -0
- data/db/default/states_cities_of_rondonia.rb +56 -0
- data/db/default/states_cities_of_roraima.rb +19 -0
- data/db/default/states_cities_of_santa_catarina.rb +297 -0
- data/db/default/states_cities_of_sao_paulo.rb +649 -0
- data/db/default/states_cities_of_sergipe.rb +79 -0
- data/db/default/states_cities_of_tocantins.rb +144 -0
- data/db/default/stock.rb +1 -0
- data/db/default/tax_categories.rb +1 -0
- data/db/default/user.rb +100 -0
- data/db/migrate/20150503011715_create_spree_cities.rb +13 -0
- data/db/migrate/20150504004509_remove_city_from_spree_address.rb +5 -0
- data/db/migrate/20150504004648_add_city_to_spree_address.rb +5 -0
- data/db/migrate/20150505020218_add_number_and_district_to_spree_address.rb +6 -0
- data/db/migrate/20150505031019_add_details_to_spree_user.rb +10 -0
- data/db/seeds.rb +5 -0
- data/lib/generators/spree_br_common/install/install_generator.rb +31 -0
- data/lib/spree_br_common/engine.rb +20 -0
- data/lib/spree_br_common/factories/address_factory.rb +7 -0
- data/lib/spree_br_common/factories/city_factory.rb +8 -0
- data/lib/spree_br_common/factories/user_factory.rb +12 -0
- data/lib/spree_br_common/factories.rb +3 -0
- data/lib/spree_br_common.rb +2 -0
- data/spec/controllers/features/address_checkout_spec.rb +89 -0
- data/spec/controllers/features/user_account_spec.rb +46 -0
- data/spec/controllers/features/user_signup_spec.rb +24 -0
- data/spec/controllers/spree/addresses_controller_spec.rb +27 -0
- data/spec/controllers/spree/api/cities_controller_spec.rb +86 -0
- data/spec/fixtures/vcr_cassettes/Checkout/visitor_makes_checkout_as_guest_without_registration/full_checkout/does_not_break_the_per-item_shipping_method_calculator.yml +49 -0
- data/spec/fixtures/vcr_cassettes/Checkout/visitor_makes_checkout_as_guest_without_registration/full_checkout/in_Brazil/should_autocomplete_zipcode.yml +46 -0
- data/spec/fixtures/vcr_cassettes/Spree_AddressesController/_show/does_not_find_an_incorrect_cep.yml +38 -0
- data/spec/fixtures/vcr_cassettes/Spree_AddressesController/_show/shows_the_correct_address.yml +46 -0
- data/spec/models/spree/address_spec.rb +32 -0
- data/spec/models/spree/city_spec.rb +7 -0
- data/spec/models/spree/user_spec.rb +88 -0
- data/spec/spec_helper.rb +94 -0
- data/spec/support/controller_hacks.rb +33 -0
- data/spec/support/shared_context/checkout_setup.rb +9 -0
- data/spec/support/vcr.rb +8 -0
- data/spree_br_common.gemspec +33 -0
- metadata +351 -0
@@ -0,0 +1,395 @@
|
|
1
|
+
/**
|
2
|
+
* jquery.mask.js
|
3
|
+
* @version: v1.6.5
|
4
|
+
* @author: Igor Escobar
|
5
|
+
*
|
6
|
+
* Created by Igor Escobar on 2012-03-10. Please report any bug at http://blog.igorescobar.com
|
7
|
+
*
|
8
|
+
* Copyright (c) 2012 Igor Escobar http://blog.igorescobar.com
|
9
|
+
*
|
10
|
+
* The MIT License (http://www.opensource.org/licenses/mit-license.php)
|
11
|
+
*
|
12
|
+
* Permission is hereby granted, free of charge, to any person
|
13
|
+
* obtaining a copy of this software and associated documentation
|
14
|
+
* files (the "Software"), to deal in the Software without
|
15
|
+
* restriction, including without limitation the rights to use,
|
16
|
+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
17
|
+
* copies of the Software, and to permit persons to whom the
|
18
|
+
* Software is furnished to do so, subject to the following
|
19
|
+
* conditions:
|
20
|
+
*
|
21
|
+
* The above copyright notice and this permission notice shall be
|
22
|
+
* included in all copies or substantial portions of the Software.
|
23
|
+
*
|
24
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
25
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
26
|
+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
27
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
28
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
29
|
+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
30
|
+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
31
|
+
* OTHER DEALINGS IN THE SOFTWARE.
|
32
|
+
*/
|
33
|
+
/*jshint laxbreak: true */
|
34
|
+
/* global define */
|
35
|
+
|
36
|
+
// UMD (Universal Module Definition) patterns for JavaScript modules that work everywhere.
|
37
|
+
// https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
|
38
|
+
(function (factory) {
|
39
|
+
if (typeof define === "function" && define.amd) {
|
40
|
+
// AMD. Register as an anonymous module.
|
41
|
+
define(["jquery"], factory);
|
42
|
+
} else {
|
43
|
+
// Browser globals
|
44
|
+
factory(window.jQuery || window.Zepto);
|
45
|
+
}
|
46
|
+
}(function ($) {
|
47
|
+
"use strict";
|
48
|
+
var Mask = function (el, mask, options) {
|
49
|
+
var jMask = this, old_value, regexMask;
|
50
|
+
el = $(el);
|
51
|
+
|
52
|
+
mask = typeof mask === "function" ? mask(el.val(), undefined, el, options) : mask;
|
53
|
+
|
54
|
+
jMask.init = function() {
|
55
|
+
options = options || {};
|
56
|
+
|
57
|
+
jMask.byPassKeys = [9, 16, 17, 18, 36, 37, 38, 39, 40, 91];
|
58
|
+
jMask.translation = {
|
59
|
+
'0': {pattern: /\d/},
|
60
|
+
'9': {pattern: /\d/, optional: true},
|
61
|
+
'#': {pattern: /\d/, recursive: true},
|
62
|
+
'A': {pattern: /[a-zA-Z0-9]/},
|
63
|
+
'S': {pattern: /[a-zA-Z]/}
|
64
|
+
};
|
65
|
+
|
66
|
+
jMask.translation = $.extend({}, jMask.translation, options.translation);
|
67
|
+
jMask = $.extend(true, {}, jMask, options);
|
68
|
+
|
69
|
+
regexMask = p.getRegexMask();
|
70
|
+
|
71
|
+
el.each(function() {
|
72
|
+
if (options.maxlength !== false) {
|
73
|
+
el.attr('maxlength', mask.length);
|
74
|
+
}
|
75
|
+
|
76
|
+
if (options.placeholder) {
|
77
|
+
el.attr('placeholder' , options.placeholder);
|
78
|
+
}
|
79
|
+
|
80
|
+
el.attr('autocomplete', 'off');
|
81
|
+
p.destroyEvents();
|
82
|
+
p.events();
|
83
|
+
|
84
|
+
var caret = p.getCaret();
|
85
|
+
|
86
|
+
p.val(p.getMasked());
|
87
|
+
p.setCaret(caret + p.getMaskCharactersBeforeCount(caret, true));
|
88
|
+
});
|
89
|
+
|
90
|
+
|
91
|
+
};
|
92
|
+
|
93
|
+
var p = {
|
94
|
+
getCaret: function () {
|
95
|
+
var sel,
|
96
|
+
pos = 0,
|
97
|
+
ctrl = el.get(0),
|
98
|
+
dSel = document.selection,
|
99
|
+
cSelStart = ctrl.selectionStart;
|
100
|
+
|
101
|
+
// IE Support
|
102
|
+
if (dSel && !~navigator.appVersion.indexOf("MSIE 10")) {
|
103
|
+
sel = dSel.createRange();
|
104
|
+
sel.moveStart('character', el.is("input") ? -el.val().length : -el.text().length);
|
105
|
+
pos = sel.text.length;
|
106
|
+
}
|
107
|
+
// Firefox support
|
108
|
+
else if (cSelStart || cSelStart === '0') {
|
109
|
+
pos = cSelStart;
|
110
|
+
}
|
111
|
+
|
112
|
+
return pos;
|
113
|
+
},
|
114
|
+
setCaret: function(pos) {
|
115
|
+
if (el.is(":focus")) {
|
116
|
+
var range, ctrl = el.get(0);
|
117
|
+
|
118
|
+
if (ctrl.setSelectionRange) {
|
119
|
+
ctrl.setSelectionRange(pos,pos);
|
120
|
+
} else if (ctrl.createTextRange) {
|
121
|
+
range = ctrl.createTextRange();
|
122
|
+
range.collapse(true);
|
123
|
+
range.moveEnd('character', pos);
|
124
|
+
range.moveStart('character', pos);
|
125
|
+
range.select();
|
126
|
+
}
|
127
|
+
}
|
128
|
+
},
|
129
|
+
events: function() {
|
130
|
+
el.on('keydown.mask', function() {
|
131
|
+
old_value = p.val();
|
132
|
+
});
|
133
|
+
el.on('keyup.mask', p.behaviour);
|
134
|
+
el.on("paste.mask drop.mask", function() {
|
135
|
+
setTimeout(function() {
|
136
|
+
el.keydown().keyup();
|
137
|
+
}, 100);
|
138
|
+
});
|
139
|
+
el.on("change.mask", function() {
|
140
|
+
el.data("changeCalled", true);
|
141
|
+
});
|
142
|
+
el.on("blur.mask", function(e){
|
143
|
+
var el = $(e.target);
|
144
|
+
if (el.prop("defaultValue") !== el.val()) {
|
145
|
+
el.prop("defaultValue", el.val());
|
146
|
+
if (!el.data("changeCalled")) {
|
147
|
+
el.trigger("change");
|
148
|
+
}
|
149
|
+
}
|
150
|
+
el.data("changeCalled", false);
|
151
|
+
});
|
152
|
+
|
153
|
+
// clear the value if it not complete the mask
|
154
|
+
el.on("focusout.mask", function() {
|
155
|
+
if (options.clearIfNotMatch && !regexMask.test(p.val())) {
|
156
|
+
p.val('');
|
157
|
+
}
|
158
|
+
});
|
159
|
+
},
|
160
|
+
getRegexMask: function() {
|
161
|
+
var maskChunks = [], translation, pattern, optional, recursive, oRecursive, r;
|
162
|
+
|
163
|
+
for (var i = 0; i < mask.length; i++) {
|
164
|
+
translation = jMask.translation[mask[i]];
|
165
|
+
|
166
|
+
if (translation) {
|
167
|
+
|
168
|
+
pattern = translation.pattern.toString().replace(/.{1}$|^.{1}/g, "");
|
169
|
+
optional = translation.optional;
|
170
|
+
recursive = translation.recursive;
|
171
|
+
|
172
|
+
if (recursive) {
|
173
|
+
maskChunks.push(mask[i]);
|
174
|
+
oRecursive = {digit: mask[i], pattern: pattern};
|
175
|
+
} else {
|
176
|
+
maskChunks.push((!optional && !recursive) ? pattern : (pattern + "?"));
|
177
|
+
}
|
178
|
+
|
179
|
+
} else {
|
180
|
+
maskChunks.push("\\" + mask[i]);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
r = maskChunks.join("");
|
185
|
+
|
186
|
+
if (oRecursive) {
|
187
|
+
r = r.replace(new RegExp("(" + oRecursive.digit + "(.*" + oRecursive.digit + ")?)"), "($1)?")
|
188
|
+
.replace(new RegExp(oRecursive.digit, "g"), oRecursive.pattern);
|
189
|
+
}
|
190
|
+
|
191
|
+
return new RegExp(r);
|
192
|
+
},
|
193
|
+
destroyEvents: function() {
|
194
|
+
el.off('keydown.mask keyup.mask paste.mask drop.mask change.mask blur.mask focusout.mask').removeData("changeCalled");
|
195
|
+
},
|
196
|
+
val: function(v) {
|
197
|
+
var isInput = el.is('input');
|
198
|
+
return arguments.length > 0
|
199
|
+
? (isInput ? el.val(v) : el.text(v))
|
200
|
+
: (isInput ? el.val() : el.text());
|
201
|
+
},
|
202
|
+
getMaskCharactersBeforeCount: function(index, onCleanVal) {
|
203
|
+
for (var count = 0, i = 0, maskL = mask.length; i < maskL && i < index; i++) {
|
204
|
+
if (!jMask.translation[mask.charAt(i)]) {
|
205
|
+
index = onCleanVal ? index + 1 : index;
|
206
|
+
count++;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
return count;
|
210
|
+
},
|
211
|
+
determineCaretPos: function (originalCaretPos, oldLength, newLength, maskDif) {
|
212
|
+
var translation = jMask.translation[mask.charAt(Math.min(originalCaretPos - 1, mask.length - 1))];
|
213
|
+
|
214
|
+
return !translation ? p.determineCaretPos(originalCaretPos + 1, oldLength, newLength, maskDif)
|
215
|
+
: Math.min(originalCaretPos + newLength - oldLength - maskDif, newLength);
|
216
|
+
},
|
217
|
+
behaviour: function(e) {
|
218
|
+
e = e || window.event;
|
219
|
+
var keyCode = e.keyCode || e.which;
|
220
|
+
|
221
|
+
if ($.inArray(keyCode, jMask.byPassKeys) === -1) {
|
222
|
+
|
223
|
+
var caretPos = p.getCaret(),
|
224
|
+
currVal = p.val(),
|
225
|
+
currValL = currVal.length,
|
226
|
+
changeCaret = caretPos < currValL,
|
227
|
+
newVal = p.getMasked(),
|
228
|
+
newValL = newVal.length,
|
229
|
+
maskDif = p.getMaskCharactersBeforeCount(newValL - 1) - p.getMaskCharactersBeforeCount(currValL - 1);
|
230
|
+
|
231
|
+
if (newVal !== currVal) {
|
232
|
+
p.val(newVal);
|
233
|
+
}
|
234
|
+
|
235
|
+
// change caret but avoid CTRL+A
|
236
|
+
if (changeCaret && !(keyCode === 65 && e.ctrlKey)) {
|
237
|
+
// Avoid adjusting caret on backspace or delete
|
238
|
+
if (!(keyCode === 8 || keyCode === 46)) {
|
239
|
+
caretPos = p.determineCaretPos(caretPos, currValL, newValL, maskDif);
|
240
|
+
}
|
241
|
+
p.setCaret(caretPos);
|
242
|
+
}
|
243
|
+
|
244
|
+
return p.callbacks(e);
|
245
|
+
}
|
246
|
+
},
|
247
|
+
getMasked: function (skipMaskChars) {
|
248
|
+
var buf = [],
|
249
|
+
value = p.val(),
|
250
|
+
m = 0, maskLen = mask.length,
|
251
|
+
v = 0, valLen = value.length,
|
252
|
+
offset = 1, addMethod = "push",
|
253
|
+
resetPos = -1,
|
254
|
+
lastMaskChar,
|
255
|
+
check;
|
256
|
+
|
257
|
+
if (options.reverse) {
|
258
|
+
addMethod = "unshift";
|
259
|
+
offset = -1;
|
260
|
+
lastMaskChar = 0;
|
261
|
+
m = maskLen - 1;
|
262
|
+
v = valLen - 1;
|
263
|
+
check = function () {
|
264
|
+
return m > -1 && v > -1;
|
265
|
+
};
|
266
|
+
} else {
|
267
|
+
lastMaskChar = maskLen - 1;
|
268
|
+
check = function () {
|
269
|
+
return m < maskLen && v < valLen;
|
270
|
+
};
|
271
|
+
}
|
272
|
+
|
273
|
+
while (check()) {
|
274
|
+
var maskDigit = mask.charAt(m),
|
275
|
+
valDigit = value.charAt(v),
|
276
|
+
translation = jMask.translation[maskDigit];
|
277
|
+
|
278
|
+
if (translation) {
|
279
|
+
if (valDigit.match(translation.pattern)) {
|
280
|
+
buf[addMethod](valDigit);
|
281
|
+
if (translation.recursive) {
|
282
|
+
if (resetPos === -1) {
|
283
|
+
resetPos = m;
|
284
|
+
} else if (m === lastMaskChar) {
|
285
|
+
m = resetPos - offset;
|
286
|
+
}
|
287
|
+
|
288
|
+
if (lastMaskChar === resetPos) {
|
289
|
+
m -= offset;
|
290
|
+
}
|
291
|
+
}
|
292
|
+
m += offset;
|
293
|
+
} else if (translation.optional) {
|
294
|
+
m += offset;
|
295
|
+
v -= offset;
|
296
|
+
}
|
297
|
+
v += offset;
|
298
|
+
} else {
|
299
|
+
if (!skipMaskChars) {
|
300
|
+
buf[addMethod](maskDigit);
|
301
|
+
}
|
302
|
+
|
303
|
+
if (valDigit === maskDigit) {
|
304
|
+
v += offset;
|
305
|
+
}
|
306
|
+
|
307
|
+
m += offset;
|
308
|
+
}
|
309
|
+
}
|
310
|
+
|
311
|
+
var lastMaskCharDigit = mask.charAt(lastMaskChar);
|
312
|
+
if (maskLen === valLen + 1 && !jMask.translation[lastMaskCharDigit]) {
|
313
|
+
buf.push(lastMaskCharDigit);
|
314
|
+
}
|
315
|
+
|
316
|
+
return buf.join("");
|
317
|
+
},
|
318
|
+
callbacks: function (e) {
|
319
|
+
var val = p.val(),
|
320
|
+
changed = p.val() !== old_value;
|
321
|
+
if (changed === true) {
|
322
|
+
if (typeof options.onChange === "function") {
|
323
|
+
options.onChange(val, e, el, options);
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
if (changed === true && typeof options.onKeyPress === "function") {
|
328
|
+
options.onKeyPress(val, e, el, options);
|
329
|
+
}
|
330
|
+
|
331
|
+
if (typeof options.onComplete === "function" && val.length === mask.length) {
|
332
|
+
options.onComplete(val, e, el, options);
|
333
|
+
}
|
334
|
+
}
|
335
|
+
};
|
336
|
+
|
337
|
+
// public methods
|
338
|
+
jMask.remove = function() {
|
339
|
+
var caret = p.getCaret(),
|
340
|
+
maskedCharacterCountBefore = p.getMaskCharactersBeforeCount(caret);
|
341
|
+
|
342
|
+
p.destroyEvents();
|
343
|
+
p.val(jMask.getCleanVal()).removeAttr('maxlength');
|
344
|
+
p.setCaret(caret - maskedCharacterCountBefore);
|
345
|
+
};
|
346
|
+
|
347
|
+
// get value without mask
|
348
|
+
jMask.getCleanVal = function() {
|
349
|
+
return p.getMasked(true);
|
350
|
+
};
|
351
|
+
|
352
|
+
jMask.init();
|
353
|
+
};
|
354
|
+
|
355
|
+
$.fn.mask = function(mask, options) {
|
356
|
+
this.unmask();
|
357
|
+
return this.each(function() {
|
358
|
+
$(this).data('mask', new Mask(this, mask, options));
|
359
|
+
});
|
360
|
+
};
|
361
|
+
|
362
|
+
$.fn.unmask = function() {
|
363
|
+
return this.each(function() {
|
364
|
+
try {
|
365
|
+
$(this).data('mask').remove();
|
366
|
+
} catch (e) {}
|
367
|
+
});
|
368
|
+
};
|
369
|
+
|
370
|
+
$.fn.cleanVal = function() {
|
371
|
+
return $(this).data('mask').getCleanVal();
|
372
|
+
};
|
373
|
+
|
374
|
+
// looking for inputs with data-mask attribute
|
375
|
+
$('*[data-mask]').each(function() {
|
376
|
+
var input = $(this),
|
377
|
+
options = {},
|
378
|
+
prefix = "data-mask-";
|
379
|
+
|
380
|
+
if (input.attr(prefix + 'reverse') === 'true') {
|
381
|
+
options.reverse = true;
|
382
|
+
}
|
383
|
+
|
384
|
+
if (input.attr(prefix + 'maxlength') === 'false') {
|
385
|
+
options.maxlength = false;
|
386
|
+
}
|
387
|
+
|
388
|
+
if (input.attr(prefix + 'clearifnotmatch') === 'true') {
|
389
|
+
options.clearIfNotMatch = true;
|
390
|
+
}
|
391
|
+
|
392
|
+
input.mask(input.attr('data-mask'), options);
|
393
|
+
});
|
394
|
+
|
395
|
+
}));
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require_tree .
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class AddressesController < Spree::BaseController
|
5
|
+
def show
|
6
|
+
respond_to do |format|
|
7
|
+
format.json { render json: JSON.parse(find_address) }
|
8
|
+
end
|
9
|
+
rescue ::RestClient::ResourceNotFound
|
10
|
+
respond_to do |format|
|
11
|
+
format.json { render json: nil, status: :not_found }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def find_address
|
17
|
+
::RestClient.get "http://api.postmon.com.br/v1/cep/#{permitted_params}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def permitted_params
|
21
|
+
params.require(:cep)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
class CitiesController < Spree::Api::BaseController
|
4
|
+
skip_before_filter :set_expiry
|
5
|
+
skip_before_filter :check_for_user_or_api_key
|
6
|
+
skip_before_filter :authenticate_user
|
7
|
+
|
8
|
+
def index
|
9
|
+
@cities = scope.ransack(params[:q]).result.
|
10
|
+
includes(:state).order('name ASC')
|
11
|
+
|
12
|
+
if params[:page] || params[:per_page]
|
13
|
+
@cities = @cities.page(params[:page]).per(params[:per_page])
|
14
|
+
end
|
15
|
+
|
16
|
+
city = @cities.last
|
17
|
+
if stale?(city)
|
18
|
+
respond_with(@cities)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def show
|
23
|
+
@city = scope.find(params[:id])
|
24
|
+
respond_with(@city)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def scope
|
29
|
+
if params[:state_id]
|
30
|
+
@state = State.accessible_by(current_ability, :read).find(params[:state_id])
|
31
|
+
return @state.cities.accessible_by(current_ability, :read)
|
32
|
+
else
|
33
|
+
return City.accessible_by(current_ability, :read)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Spree::UserRegistrationsController.class_eval do
|
2
|
+
include Spree::BaseHelper
|
3
|
+
before_action :parse_date_of_birth, :only => [:create, :update]
|
4
|
+
|
5
|
+
protected
|
6
|
+
|
7
|
+
def parse_date_of_birth
|
8
|
+
params[:spree_user][:date_of_birth] = DateTime.strptime(
|
9
|
+
params[:spree_user][:date_of_birth],
|
10
|
+
Spree.t('date_picker.format', default: '%Y/%m/%d')
|
11
|
+
) rescue ''
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'cancan'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class AbilityDecorator
|
5
|
+
include CanCan::Ability
|
6
|
+
|
7
|
+
def initialize(user)
|
8
|
+
user ||= Spree.user_class.new
|
9
|
+
|
10
|
+
if user.respond_to?(:has_spree_role?) && user.has_spree_role?('admin')
|
11
|
+
can :manage, :all
|
12
|
+
else
|
13
|
+
can [:index, :read], City
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Spree::Ability.register_ability(Spree::AbilityDecorator)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'cpf_cnpj'
|
2
|
+
require 'validates_timeliness'
|
3
|
+
|
4
|
+
Spree::User.class_eval do
|
5
|
+
|
6
|
+
validates_presence_of :phone
|
7
|
+
validates :date_of_birth,
|
8
|
+
presence: true,
|
9
|
+
timeliness: {
|
10
|
+
on_or_before: lambda { 18.years.ago.at_end_of_day },
|
11
|
+
on_or_after: lambda { 100.years.ago.at_midnight },
|
12
|
+
type: :datetime
|
13
|
+
}
|
14
|
+
validates :cpf, presence: true
|
15
|
+
validates :first_name, :last_name, presence: true, length: {maximum: 100}
|
16
|
+
validates :phone, :alternative_phone, length: {maximum: 11}
|
17
|
+
validate :valid_cpf
|
18
|
+
|
19
|
+
before_validation :sanitize_fields
|
20
|
+
|
21
|
+
def full_name
|
22
|
+
"#{first_name} #{last_name}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def cpf_formatted
|
26
|
+
CPF::Formatter.format(cpf)
|
27
|
+
end
|
28
|
+
|
29
|
+
def phone_area_code
|
30
|
+
phone[0..1] if phone
|
31
|
+
end
|
32
|
+
|
33
|
+
def phone_number
|
34
|
+
phone[2..-1] if phone
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def sanitize(*fields)
|
40
|
+
fields.each do |field|
|
41
|
+
self[field] = self[field].to_s.gsub(/[^\d]/, '') if self.respond_to?(field)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def sanitize_fields
|
46
|
+
sanitize(:cpf, :phone, :alternative_phone)
|
47
|
+
end
|
48
|
+
|
49
|
+
def valid_cpf
|
50
|
+
errors.add(:cpf, Spree.t(:invalid)) unless CPF.valid?(cpf)
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<!-- insert_after '[data-erb-id*="address2"]' -->
|
2
|
+
<p class="form-group" id=<%="#{address_id}district" %>>
|
3
|
+
<%= form.label :district, Spree.t(:district) %><span class="required">*</span><br />
|
4
|
+
<%= form.text_field :district, class: 'form-control required ajax-loading' %>
|
5
|
+
</p>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<!-- insert_before '[data-erb-id*="address2"]' -->
|
2
|
+
<p class="form-group" id=<%="#{address_id}number" %>>
|
3
|
+
<%= form.label :number, Spree.t(:number) %><span class="required">*</span><br />
|
4
|
+
<%= form.number_field :number, class: 'form-control required ajax-loading' %>
|
5
|
+
</p>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!-- replace 'p[data-erb-id*="city"]' -->
|
2
|
+
<p class="form-group" id=<%="#{address_id}city" %>>
|
3
|
+
<%= form.label :city, Spree.t(:city) %><span class="required">*</span><br />
|
4
|
+
<%= form.collection_select(
|
5
|
+
:city_id, address.state ? address.state.cities : [],
|
6
|
+
:id, :name,
|
7
|
+
{:include_blank => false},
|
8
|
+
{:class => 'form-control required'}
|
9
|
+
) %>
|
10
|
+
|
11
|
+
<% unless address.state %>
|
12
|
+
<script>
|
13
|
+
$(function() {
|
14
|
+
Spree.updateCity('b');
|
15
|
+
});
|
16
|
+
</script>
|
17
|
+
<% end %>
|
18
|
+
</p>
|