_form.html.erb 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <!-- BEGIN FORM-->
  2. <%= form_for(@product, html: { class: "form-horizontal" }) do |f| %>
  3. <div class="portlet-body form" id="products_form">
  4. <% if @product.errors.any? %>
  5. <div class="alert alert-danger">
  6. <strong>Tiene <%= pluralize(@product.errors.count, "error") %> no se puede guardar el producto</strong><br>
  7. </div>
  8. <% end %>
  9. <div class="form-body">
  10. <input type="text" class="hidden" value="<%= @product.id %>" id="idproduct">
  11. <h4 class="form-section">Información general</h4>
  12. <div class="row">
  13. <div class="col-md-7">
  14. <%= hidden_field_tag :gain_margin, @pos_config.gain_margin %>
  15. <%= hidden_field_tag :tax_percent, @pos_config.tax_percent %>
  16. <div class="form-group">
  17. <%= f.label :sku, { class: "col-md-3 col-sm-2 control-label" } do %>SKU <span class="required">*</span>
  18. <% end %>
  19. <div class="col-md-9 col-sm-4">
  20. <div class="input-icon">
  21. <i class="fa fa-tag"></i>
  22. <%= f.text_field :sku, { class: "form-control input-medium", readonly: true } %>
  23. </div>
  24. <span class="help-block">El SKU se genera automáticamente en base a la línea y sublínea seleccionadas. </span>
  25. </div>
  26. </div>
  27. <div class="form-group">
  28. <%= f.label :barcode, { class: "col-md-3 col-sm-2 control-label" } do %> Código de barras <span class="required">*</span> <% end %>
  29. <div class="col-md-9 col-sm-4">
  30. <div class="input-icon">
  31. <i class="fa fa-barcode"></i>
  32. <%= f.text_field :barcode, { class: "form-control input-medium", readonly: true } %>
  33. </div>
  34. <span class="help-block">Para indicar el código de barras, debe escanearlo. </span>
  35. </div>
  36. </div>
  37. <div class="form-group">
  38. <%= f.label :name, "Producto", { class: "col-md-3 col-sm-2 control-label" } do %>Nombre <span class="required">*</span> <% end %>
  39. <div class="col-md-9 col-sm-4">
  40. <%= f.text_field :name, { class: "form-control input-large" } %>
  41. </div>
  42. </div>
  43. <div class="form-group">
  44. <%= f.label :description, "Descripción", { class: "col-md-3 col-sm-2 control-label" } %>
  45. <div class="col-md-9 col-sm-4">
  46. <%= f.text_area :description, { class: "form-control input-large" } %>
  47. </div>
  48. </div>
  49. <div class="form-group">
  50. <%= f.label :unit_id, "Unidad de medida", { class: "col-md-3 col-sm-2 control-label" } do %>Unidad de medida <span class="required">*</span> <% end %>
  51. <div class="col-md-9 col-sm-4">
  52. <%= f.collection_select :unit_id, Unit.vigentes, :id, :unit, { prompt: "Seleccione" }, { class: "form-control input-medium" } %>
  53. </div>
  54. </div>
  55. </div>
  56. <div class="col-md-5">
  57. <div class="form-group">
  58. <%= f.label :img_product, "Imagen producto", { class: "col-md-5 col-sm-2 control-label" } %>
  59. <div class="col-md-7 col-sm-4">
  60. <div class="fileinput fileinput-new" data-provides="fileinput">
  61. <div class="fileinput-new thumbnail" style="width: 200px; height: 150px;">
  62. <% if @product.img_product? %>
  63. <%= image_tag @product.img_product %>
  64. <% else %>
  65. <%= image_tag "no-image.png" %>
  66. <% end %>
  67. </div>
  68. <div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 200px; max-height: 150px;"> </div>
  69. <div>
  70. <span class="btn default btn-file">
  71. <span class="fileinput-new"> Seleccione imagen </span>
  72. <span class="fileinput-exists"> Cambiar </span>
  73. <%= f.file_field :img_product, { class: "default" } %>
  74. <%= f.hidden_field :img_product_cache %>
  75. </span>
  76. <a href="javascript:;" class="btn red fileinput-exists" data-dismiss="fileinput"> Borrar </a>
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. </div>
  82. </div>
  83. <h4 class="form-section">Información del producto</h4>
  84. <div class="row">
  85. <div class="form-group ">
  86. <%= f.label :inventory, "¿Se maneja inventario de este producto?", { class: "col-md-3 col-sm-3 control-label" } do %>¿Este producto tendrá inventario? <span class="required">*</span> <% end %>
  87. <div class="col-md-9 col-sm-2">
  88. <%= f.check_box(:inventory,
  89. {
  90. class: "make-switch",
  91. data: {
  92. on_color: "success",
  93. off_color: "danger",
  94. on_text: "Si",
  95. off_text: "No"
  96. }
  97. }, "true","false"
  98. ) %>
  99. </div>
  100. </div>
  101. <div class="form-group">
  102. <%
  103. @category = nil
  104. @subcategory = nil;
  105. @prompt = 'Seleccione'
  106. @disabled = true
  107. if @product.categories[0].present? && @product.categories[0].parent_id == 0
  108. @category = @product.categories[0]
  109. @prompt = ''
  110. elsif @product.categories[0].present?
  111. @category = Category.find(@product.categories[0].parent_id)
  112. @subcategory = @product.categories[0]
  113. @disabled = false
  114. end
  115. %>
  116. <%= label_tag :categorias, "Líneas de producto", { class: "col-md-3 col-sm-3 control-label" } do %>Líneas de producto <span class="required">*</span> <% end %>
  117. <div class="col-md-4 col-sm-4">
  118. <%= select_tag 'categorias', options_from_collection_for_select(Category.activos_padre, 'id', 'category', :selected => (@category.id unless @category.nil?)), { :include_blank => "Seleccione", :class => 'form-control' } %>
  119. </div>
  120. </div>
  121. <div class="form-group">
  122. <%= f.label :category_ids, "Sublinea del producto", { class: "col-md-3 col-sm-3 control-label" } %>
  123. <div class="col-md-4 col-sm-4">
  124. <%= f.collection_select(:category_ids, @category.nil? ? {} : Category.where(:parent_id => @category.id), :id, :category , options = { :include_blank => @prompt, :selected => (@subcategory.id unless @subcategory.nil?) }, :class => "form-control", :disabled => @disabled) %>
  125. <%= f.hidden_field :category_ids, { :id => 'subcategory_hidden' } %>
  126. </div>
  127. </div>
  128. <div class="form-group">
  129. <%= f.label :include_purchase_tax, "¿Incluir IVA en compra?", { class: "col-md-3 col-sm-3 control-label" } do %> ¿Incluir IVA en compra? <span class="required">*</span> <% end %>
  130. <div class="col-md-9 col-sm-2">
  131. <%= f.check_box(:include_purchase_tax,
  132. {
  133. class: "make-switch",
  134. data: {
  135. on_color: "success",
  136. off_color: "danger",
  137. on_text: "Si",
  138. off_text: "No"
  139. }
  140. }, "1","0"
  141. ) %>
  142. </div>
  143. </div>
  144. <div class="form-group">
  145. <%= f.label :include_sale_tax, "¿Incluir IVA en venta?", { class: "col-md-3 col-sm-3 control-label" } do %> ¿Incluir IVA en venta? <span class="required">*</span> <% end %>
  146. <div class="col-md-9 col-sm-2">
  147. <%= f.check_box(:include_sale_tax,
  148. {
  149. class: "make-switch",
  150. data: {
  151. on_color: "success",
  152. off_color: "danger",
  153. on_text: "Si",
  154. off_text: "No"
  155. }
  156. }, "1","0"
  157. ) %>
  158. </div>
  159. </div>
  160. <div class="form-group">
  161. <%= f.label :is_in_dollars, "¿Se compra en dólares?", { class: "col-md-3 col-sm-3 control-label" } do %> ¿Se compra en dólares? <span class="required">*</span> <% end %>
  162. <div class="col-md-9 col-sm-2">
  163. <%= f.check_box(:is_in_dollars,
  164. {
  165. class: "make-switch",
  166. data: {
  167. on_color: "success",
  168. off_color: "danger",
  169. on_text: "Si",
  170. off_text: "No"
  171. }
  172. }, "true","false"
  173. ) %>
  174. </div>
  175. </div>
  176. <div class="form-group inventory">
  177. <%= f.label :price_base_dollars, "Precio de compra neto", { class: "col-md-3 col-sm-3 control-label" } %>
  178. <div class="col-md-3 col-sm-3">
  179. <div class="input-group <%= (@product.persisted? && @product.is_in_dollars?) ? '' : 'hidden' %>" id="price_base_usd_div">
  180. <span class="input-group-addon"> $ </span>
  181. <%= f.text_field :price_base_dollars, { class: "form-control mask_decimal" } %>
  182. <span class="input-group-addon"> USD </span>
  183. </div>
  184. <div class="input-group <%= (@product.persisted? && !@product.is_in_dollars?) ? '' : 'hidden' %>" id="price_base_mxn_div">
  185. <span class="input-group-addon"> $ </span>
  186. <%= f.text_field :price_base, { class: "form-control mask_decimal" } %>
  187. <span class="input-group-addon"> MXN </span>
  188. </div>
  189. </div>
  190. </div>
  191. <div class="form-group inventory">
  192. <%= f.label :price_sale, "Precio de venta base", { class: "col-md-3 col-sm-3 control-label" } do %> Precio de venta base
  193. <span class="required">*</span>
  194. <% end %>
  195. <div class="col-md-3 col-sm-3">
  196. <div class="input-group">
  197. <span class="input-group-addon"> $ </span>
  198. <%= f.text_field :price_sale, { class: "form-control mask_decimal" } %>
  199. <span class="input-group-addon"> MXN </span>
  200. </div>
  201. </div>
  202. <div class="col-md-6 col-sm-6">
  203. <span class="help-block">El precio de venta base será calculado de acuerdo al porcentaje de utilidad especificado, sólo en caso de especificar el precio de compra neto.</span>
  204. </div>
  205. </div>
  206. <div class="form-group">
  207. <%= f.label :presentation, "¿El producto tiene variantes?", { class: "col-md-3 col-sm-3 control-label" } do %>¿El producto tiene variantes?
  208. <span class="required">*</span>
  209. <% end %>
  210. <div class="col-md-9 col-sm-2">
  211. <%= f.check_box(:presentation,
  212. {
  213. class: "make-switch",
  214. data: {
  215. on_color: "success",
  216. off_color: "danger",
  217. on_text: "Si",
  218. off_text: "No"
  219. },
  220. readonly: @with_presentation
  221. }, "true", "false"
  222. ) %>
  223. </div>
  224. </div>
  225. </div>
  226. <h4 class="form-section presentaciones">Variantes</h4>
  227. <div class="row presentaciones">
  228. <% if @product.persisted? %>
  229. <div class="col-md-offset-2 col-md-9 col-sm-offset-2 col-sm-9">
  230. <%= render 'products_children' %>
  231. </div>
  232. <% else %>
  233. <div class="col-md-9 col-md-offset-3">
  234. <div class="alert alert-warning hidden">
  235. Son <strong id="variantes"></strong> variantes del producto.
  236. </div>
  237. </div>
  238. <div class="form-group ">
  239. <%= f.label :size_list, "Tallas", { class: "col-md-3 control-label" } %>
  240. <div class="col-md-9">
  241. <%= f.collection_select(:size_list, @product.size_list, :to_s, :to_s, { include_blank: false }, { class: "form-control input-medium", 'data-role'=>'tagsinput', multiple: true }) %>
  242. <span class="help-block">Ingrese las diferentes tallas, separándolas con coma (,) </span>
  243. </div>
  244. </div>
  245. <div class="form-group ">
  246. <%= f.label :color_list, "Colores", { class: "col-md-3 control-label" } %>
  247. <div class="col-md-9">
  248. <%= f.collection_select(:color_list, @product.color_list, :to_s, :to_s, { include_blank: false }, { class: "form-control input-medium", 'data-role'=>'tagsinput', multiple: true }) %>
  249. <span class="help-block">Ingrese los diferentes colores, separándolos con coma (,) </span>
  250. </div>
  251. </div>
  252. <div class="form-group ">
  253. <%= f.label :style_list, "Estilos", { class: "col-md-3 control-label" } %>
  254. <div class="col-md-9">
  255. <%= f.collection_select(:style_list, @product.style_list, :to_s, :to_s, { include_blank: false }, { class: "form-control input-medium", 'data-role'=>'tagsinput', multiple: true }) %>
  256. <span class="help-block">Ingrese los diferentes estilos, separándolos con coma (,) </span>
  257. </div>
  258. </div>
  259. <%= hidden_field_tag :variants %>
  260. <% end %>
  261. </div>
  262. </div>
  263. <div class="form-actions">
  264. <div class="row">
  265. <div class="col-md-offset-3 col-md-9">
  266. <%= f.submit 'Guardar', { class: "btn green" } %>
  267. <%= link_to 'Cancelar', products_path(filter: @filter, current_page: @current_page), { class: "btn default" } %>
  268. </div>
  269. </div>
  270. </div>
  271. </div>
  272. <% end %>
  273. <script type="text/javascript">
  274. var timeout = null;
  275. var regex = /[a,e,i,o,u]/gi;
  276. var skuEdit = "";
  277. $(document).on('page:change', function() {
  278. App.init();
  279. $('.fileinput').fileinput();
  280. <% if @product.barcode.blank? %>
  281. $('body').barcodeListener().on('barcode.valid', function(e, code) {
  282. if($('#product_barcode').length > 0) {
  283. $('#product_barcode').val(code);
  284. validateBarcode(code);
  285. }
  286. });
  287. <% end %>
  288. presentaciones();
  289. // < % if @product.children.present? %>
  290. getVariants();
  291. // < % end %>
  292. showPriceBaseInput(<%= @product.is_in_dollars? %>);
  293. $(document).on("cut copy paste",'form#new_product .presentaciones input[type=text]', function(e) {
  294. // evitar que se pueda copiar y pegar en los inputs de los tags de variantes
  295. e.preventDefault();
  296. });
  297. });
  298. $('#product_size_list').on('change', function(event) { getVariants(); });
  299. $('#product_color_list').on('change', function(event) { getVariants(); });
  300. $('#product_style_list').on('change', function(event) { getVariants(); });
  301. function presentaciones(){
  302. if ($('#product_presentation').is(':checked')){
  303. $('.presentaciones').removeClass('hidden');
  304. } else {
  305. $('.presentaciones').addClass('hidden');
  306. }
  307. }
  308. $('#product_presentation').on('switchChange.bootstrapSwitch', function(event, state) {
  309. presentaciones();
  310. });
  311. function getVariants(){
  312. sizes = $('#product_size_list').tagsinput('items');
  313. colors = $('#product_color_list').tagsinput('items');
  314. styles = $('#product_style_list').tagsinput('items');
  315. variantes = (sizes.length > 0 ? sizes.length : 1)
  316. * (colors.length > 0 ? colors.length : 1 )
  317. * (styles.length > 0 ? styles.length : 1);
  318. $('#variants').html(variantes);
  319. $('.alert-warning').removeClass('hidden');
  320. $('#variantes').html(variantes);
  321. }
  322. $('#categorias').on('change', function() {
  323. $('#product_sku').val('');
  324. if($('#categorias').val()) {
  325. $.ajax({
  326. type: "get",
  327. url: '/getcategories/' + $(this).val(),
  328. dataType: 'json',
  329. success: function(data) {
  330. $('#product_category_ids').empty();
  331. if(data.length > 0) {
  332. $('#product_category_ids').attr('disabled', false);
  333. $('#product_category_ids').append("<option selected value='0'>Seleccione</option>")
  334. } else {
  335. $('#product_category_ids').attr('disabled', true);
  336. $('#subcategory_hidden').val($('#categorias').val());
  337. $('#product_category_ids').append("<option selected value='" + $('#categorias').val() +"'></option>")
  338. }
  339. for(i in data){
  340. $('#product_category_ids').append("<option value='" + data[i].id +"'>" + data[i].category+ "</option>")
  341. }
  342. fillSKU();
  343. }
  344. });
  345. }
  346. });
  347. $('#product_category_ids').on('change', function() {
  348. $('#subcategory_hidden').val($(this).val());
  349. fillSKU();
  350. });
  351. $('#product_price_base').on('input', function() {
  352. getSalePrice($(this));
  353. });
  354. $('#product_is_in_dollars').on('switchChange.bootstrapSwitch', function(event, state) {
  355. showPriceBaseInput(state);
  356. });
  357. function getSalePrice(input){
  358. clearTimeout(timeout);
  359. timeout = setTimeout(function () {
  360. var gainMargin = parseFloat($('#gain_margin').val());
  361. var purchasePrice = parseFloat(input.val());
  362. var gain = (gainMargin / 100) * purchasePrice
  363. $('#product_price_sale').val( (purchasePrice + gain).toFixed(2) );
  364. }, 500);
  365. }
  366. function getProductId() {
  367. $('#categorias').attr('disabled', true);
  368. $.ajax({
  369. type: "get",
  370. url: '/get_max_product_id',
  371. dataType: 'json',
  372. success: function(data) {
  373. $('#categorias').attr('disabled', false);
  374. var sku = $('#product_sku').val();
  375. if(sku.length && !$('#idproduct').val()) {
  376. $('#product_sku').val(sku + "-" + data);
  377. } else {
  378. $('#product_sku').val(sku + "-" + $('#idproduct').val());
  379. }
  380. },
  381. });
  382. }
  383. function fillSKU() {
  384. var sku = $('#product_sku').val();
  385. if(sku.length <= 3) {
  386. $('#product_sku').val($('#categorias option:selected').text().substring(0,3).toUpperCase());
  387. getProductId();
  388. }
  389. sku = $('#product_sku').val();
  390. if(sku.length >= 3 && $('#product_category_ids').val() != "0") {
  391. var subcategory = $('#product_category_ids option:selected').text();
  392. if(subcategory){
  393. $('#product_sku').val(sku.substring(0,3) + '-' + subcategory.replace(regex, '').substring(0,3).toUpperCase());
  394. getProductId();
  395. }
  396. }
  397. }
  398. function validateBarcode(barcode) {
  399. $.ajax({
  400. type: "get",
  401. url: '/validate_unique_barcode/' + barcode,
  402. dataType: 'script',
  403. success: function(data) {
  404. }
  405. });
  406. }
  407. function showPriceBaseInput(state) {
  408. //true es en dolares, false en pesos
  409. if (state) {
  410. $('#price_base_usd_div').removeClass('hidden');
  411. $('#price_base_mxn_div').addClass('hidden');
  412. $('#product_price_base').val('');
  413. <% unless @product.persisted? %>
  414. $('#product_price_sale').val('');
  415. <% end %>
  416. } else {
  417. $('#price_base_mxn_div').removeClass('hidden');
  418. $('#price_base_usd_div').addClass('hidden');
  419. $('#product_price_base_dollars').val('');
  420. }
  421. }
  422. </script>