_form.html.erb 17 KB

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